-Copyright (c) 1992-1996 Regents of the University of Michigan.
+Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+All rights reserved.
+
+Redistribution and use in source and binary forms are permitted only
+as authorized by the OpenLDAP Public License. A copy of this
+license is available at http://www.OpenLDAP.org/license.html or
+in file LICENSE in the top-level directory of the distribution.
+
+Individual files and/or contributed packages may be copyright by
+other parties and use subject to additional restrictions.
+
+This work is derived from the University of Michigan LDAP v3.3
+distribution. Information concerning is available at
+ http://www.umich.edu/~dirsvcs/ldap/ldap.html.
+
+This work also contains materials derived from public sources.
+
+Additional Information about OpenLDAP can be obtained at:
+ http://www.openldap.org/
+
+or by sending e-mail to:
+ info@OpenLDAP.org
+
+---
+
+Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
All rights reserved.
Redistribution and use in source and binary forms are permitted
-Making and Installing the U-M LDAP Distribution
+Making and Installing the OpenLDAP Distribution
+**
** It is recommended that you read or at least skim through ALL of the
** instructions in this file before attempting to build the software.
+**
+** A Quick Start Guide, which may be used in conjunction with this
+** document, is available at:
+** http://www.openldap.org/faq/index.cgi?file=172
+**
+** The OpenLDAP Installation FAQ is available at:
+** http://www.openldap.org/faq/index.cgi?file=8
+**
+** You should also check for platform specific hints located on
+** on our web site.
+** http://www.openldap.org/faq/index.cgi?file=9
+**
If you want to build binaries for more than one platform from a single
source tree, skip ahead to the "Building LDAP For More Than One Platform"
-section near the end of this file. If you are planning to run slapd,
-you should read the "SLAPD and SLURPD Administrator's Guide", found in
-the doc/guides/ directory within the distribution.
+section near the end of this file.
If you simply want to build LDAP for a single machine platform, follow
these steps:
1. untar the distribution and cd to the top:
- % zcat ldap-3.3.tar.Z | tar xf -
- % cd ldap-3.3
+ % tar xfz openldap-VERSION.tgz
+ % cd openldap-VERSION
- If you are reading this file, you probably have already done this!
+ replacing VERSION to match the version you downloaded. If you are
+ reading this file, you probably have already done this!
+ 2. Type:
+ % ./configure --help
- 2. edit the files Make-common and include/ldapconfig.h.edit to configure
- the software for your site (the files are well-commented):
+ to list available configuration options. A description of
+ these options is provided in the 'CONFIGURE OPTIONS' section
+ below.
- % vi Make-common
- % vi include/ldapconfig.h.edit
+ The configure script uses environmental variables for
+ determining compiler/linker options. See the HINTS
+ section for commonly used settings.
- Note that you should NOT need to edit the Makefile located at the
- top of the distribution.
+ These environment variables are used:
+ CC C Compiler (cc, ecgs)
+ CFLAGS C Flags (-ansi)
+ CPPFLAGS CPP Flags (-I/path/include -Ddef)
+ LDFLAGS LDFLAGS (-L/path/lib)
+ LIBS LIBS (-llib)
- If you just want to see if things will build, you can leave the
- configuration alone and change it later.
+ See the 'USING ENVIRONMENT VARIABLES' section for information
+ on how to use the variables.
- If you have the ISODE package built and want to build the
- LDAP-to-X.500 server (ldapd), be sure to uncomment the appropriate
- lines near the end of the Make-common file. By default only the
- stand-alone server, LDAP libraries and client software are built.
+ 3. Configure the build system
- 3. make the software:
+ % [env settings] ./configure [options]
- % make
+ If all goes well, the configure script with auto-detect the
+ appropriate settings. Use configure enable/with options and/or
+ environment variables to obtain desired results.
- If all goes well, then make will figure out what platform you are on,
- pick a compiler to use, construct Makefiles, and build everything.
- If you see a message like "unknown platform..." LDAP has probably not
- been set up to build on your machine. See the file build/PORTS for
- hints on what to do in that case.
-
- Note that if your make does not use the Bourne (sh) shell by
- default when executing internal scripts (reportedly the case on SGI
- machines at least), you will need to run the make explicitly from
- within a Bourne shell. If you a syntax error such as "Missing ]"
- when you do the make under your usual shell, try this:
-
- % sh
- $ make
-
- If you don't like the some of the platform-specific options chosen
- by the automatic build process (such as the compiler to use, etc),
- you can intervene and edit them before anything is actually compiled
- by explicitly doing a "make platform" step, editing the .make-platform
- file (actually a link to the file to be edited), and then doing a
- regular make:
-
- % make platform
- % vi .make-platform
- % make
+ 4. Build dependencies
+
+ % make depend
- If you want to choose the build platform yourself from among those that
- the distribution supports, cd to the appropriate directory underneath
- build/platforms and make from there. For example, if you are on a
- machine running SunOS 4.1.4 and you want to force the use of the cc
- compiler, you would do this:
+ 5. Build the system
- % cd build/platforms/sunos4-cc
% make
- If you want to run some simple tests after the build is complete, you
- can do this:
+ If all goes well, the system will build as configured. If not,
+ return to step 4 after reviewing the configuration settings.
+
+ You may want to consult the doc/install/hints file for your
+ platform.
+
+ 6. Test the standalone system
+ This step requires the standalone LDAP server (slapd) with
+ LDBM support.
+
+ % cd tests
% make test
- 4. install the binaries and man pages. You may need to be superuser to
+ If all goes well, the system has been built as configured. If not,
+ return to step 4 after reviewing your configuration settings.
+
+ You may want to consult the doc/install/hints file for your
+ platform.
+
+ 7. install the binaries and man pages. You may need to be superuser to
do this (depending on where you are installing things):
% su
# make install
- That's it! See the man pages for the individual clients for information
- on configuring and using them. Eventually you will probably want to
- edit the configuration files used by the various clients (installed in
- the LDAP etc directory). The files are:
+ That's it!
+
+ See the man pages for the individual applications for
+ information on configuring and using them. You may also want
+ to edit the configuration files used by the various clients.
+ These configuration files are located in the OpenLDAP
+ configuration directory (normally /usr/local/etc/openldap).
+
+ Client configuration files:
+ ldap.conf - client defaults
+ ldapfilter.conf - search filter configuration
+ ldapsearchprefs.conf - search object definitions
+ ldaptemplates.conf - display template definitions
- ldapfilter.conf - search filter configuration
- ldapfriendly - mapping of X.500 names to human-friendly names
- ldapsearchprefs.conf - search object definitions
- ldaptemplates.conf - display template definitions
+ Server configuration files:
+ ldapd.conf - LDAP - X.500 daemon
+ slapd.conf - Standalone LDAP daemon
There are section 5 man pages for all of these files.
Building LDAP For More Than One Platform
It is now possible to build LDAP for more than one platform from the same
-source tree. This is accomplished by some rules in the Makefiles that
-create a shadow (linked) directory tree where the binaries are placed.
+source tree. This is accomplished by using make(1) VPATH support. If
+your make(1) program is old and doesn't have VPATH support, install GNU
+Make.
Follow these steps for each different platform:
- 1. move to the directory that matches the platform and compiler you
- want to build for and type make. The directories are all located
- underneath the build/platforms directory. If your platform is not
- there, you may need to do a port - see the build/PORTS file for
- more information. For a Sun running SunOS 4.1.4, you might do
- this:
+ 1. Create a directory for the platform object files.
- % cd build/platforms/sunos4-cc
- % make links
+ % mkdir obj-platform
- This will create a linked source area.
+ 2. Change your working directory to the platform object directory.
+ % cd obj-platform
- 2. move to the new directory and make as for a single platform. Follow steps
- 1-4 above to accomplish this. For example:
+ 3. Configure the build system
- % cd obj-sunos4-cc
- % make
+ % [env settings] ../configure --src-dir=.. [options]
+
+ ( replace ".." with the appropriate path )
+
+ 4. Continue as above (starting at step 6).
+
+ Note: make depend in VPATH environment is not yet supported.
+
+
+CONFIGURE OPTIONS
+
+Regrettably, this section has not been written (yet). See
+"./configure --help" for current list of options. For general
+information about how to use "configure", please read:
+ doc/install/configure
+
+
+USING ENVIRONMENT VARIABLES
+
+The configure script will also use your environmental
+variables for determining compiler/linker options. This can
+be used to manual specify features and compilation options.
+
+NOTE: If you change environment setting, be sure to remove
+ any config.cache before running ./configure.
+
+Supported Environmental Variables
+ CC C compiler (cc, egcc)
+ CFLAGS C flags (-ansi)
+ CPPFLAGS cpp flags (-I/path/include -Ddef)
+ LDFLAGS ld flags (-L/usr/local/lib)
+ LIBS libraries (-llib)
+ PATH command path /usr/local/bin:/usr/bin:/bin
+
+* Including alternative compilers
+ Use the CC environment variable to tell configure to
+ use a specific compiler. For example, to use GNU
+ C Compiler instead of the compiler configure choose,
+ use:
+
+ [env] CC=gcc ./configure
+
+ You can also use CC use specific flags with the
+ specified compiler. For example, to require strict
+ ANSI C using the GNU C Compiler, use:
+
+ [env] CC="gcc -ansi -pedantic" ./configure
+
+ (you can use CFLAGS to specify compiler flags)
+
+* Preprocessor Flags
+ You may specify additional preprocessor flags by setting
+ CPPFLAGS. For example, if you would like to use headers
+ installed in /usr/local/include, use:
+
+ [env] CPPFLAGS="-I/usr/local/include" ./configure
+
+ You can also use CPPFLAGS to specify preprocessor macros.
+
+ [env] CPPFLAGS="-D__SPECIAL_FLAG__" ./configure
+
+* Linker Flags
+ You may specify additional linker flags by setting LDFLAGS.
+ For example, if you would like to use libraries installed
+ in /usr/local/lib, use:
+
+ [env] LDFLAGS="-L/usr/local/lib" ./configure
+
+ You can also use CPPFLAGS to specify linker flags:
+
+ [env] LDFLAGS="-Bstatic" ./configure
+
+* Path
+ You may alter your path to affect configure ability to
+ find (or not find) commands. For example, to have configure
+ additionally look in /usr/css/bin for commands, use:
+
+ [env] PATH="/usr/css/bin:$PATH" ./configure
+
+
+HINTS
+
+* Platform specific hints are available in doc/install/hints.
- That's all there is to it. You can also create the linked source area(s)
- by just typing "make links" at the top of the distribution, in which case
- the Makefile will try to automatically determine the platform and
- compiler.
+* Use software under installed in /usr/local/{include,lib}
+ [env] \
+ CPPFLAGS="-I/usr/local/include" \
+ LDFLAGS="-L/usr/local/lib" \
+ ./configure
-End of LDAP INSTALL file.
+End of OpenLDAP INSTALL file.
--- /dev/null
+## Copyright 1998,1999 The OpenLDAP Foundation
+## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory
+## of this package for details.
+##---------------------------------------------------------------------------
+##
+## Makes subdirectories
+##
+
+
+all-common: FORCE
+ @echo "Making all in `$(PWD)`"
+ @for i in $(SUBDIRS) $(ALLDIRS); do \
+ echo " Entering subdirectory $$i"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) all ); \
+ echo " "; \
+ done
+
+install-common: FORCE
+ @echo "Making install in `$(PWD)`"
+ @for i in $(SUBDIRS) $(INSTALLDIRS); do \
+ echo " Entering subdirectory $$i"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) install ); \
+ echo " "; \
+ done
+
+clean-common: FORCE
+ @echo "Making clean in `$(PWD)`"
+ @for i in $(SUBDIRS) $(CLEANDIRS); do \
+ echo " Entering subdirectory $$i"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) clean ); \
+ echo " "; \
+ done
+
+veryclean-common: FORCE
+ @echo "Making veryclean in `$(PWD)`"
+ @for i in $(SUBDIRS) $(CLEANDIRS); do \
+ echo " Entering subdirectory $$i"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) veryclean ); \
+ echo " "; \
+ done
+
+depend-common: FORCE
+ @echo "Making depend in `$(PWD)`"
+ @for i in $(SUBDIRS) $(DEPENDDIRS); do \
+ echo " Entering subdirectory $$i"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) depend ); \
+ echo " "; \
+ done
+
+Makefile: $(top_srcdir)/build/dir.mk
--- /dev/null
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun ltconfig.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The name of this program.
+progname=`$echo "$0" | sed 's%^.*/%%'`
+modename="$progname"
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.3.3
+TIMESTAMP=" (1.385.2.181 1999/07/02 15:49:11)"
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+SP2NL='tr \040 \012'
+NL2SP='tr \015\012 \040\040'
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+if test "$LTCONFIG_VERSION" != "$VERSION"; then
+ echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ echo "$modename: not configured to build any kind of library" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+# Parse our command line options once, thoroughly.
+while test $# -gt 0
+do
+ arg="$1"
+ shift
+
+ case "$arg" in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ execute_dlfiles)
+ eval "$prev=\"\$$prev \$arg\""
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case "$arg" in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ exit 0
+ ;;
+
+ --config)
+ sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0
+ exit 0
+ ;;
+
+ --debug)
+ echo "$progname: enabling shell trace mode"
+ set -x
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ echo "enable shared libraries"
+ else
+ echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ echo "enable static libraries"
+ else
+ echo "disable static libraries"
+ fi
+ exit 0
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --only-shared)
+ build_libtool_libs=yes
+ build_old_libs=no
+ ;;
+
+ --only-static)
+ build_libtool_libs=no
+ build_old_libs=yes
+ ;;
+
+ --quiet | --silent)
+ show=:
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+fi
+
+case "$show $MFLAGS -$MAKEFLAGS" in
+ :\ *) : ;;
+ *\ -*s*)
+ # Be silent inside 'make -s'
+ expr " $MFLAGS -$MAKEFLAGS" : '.* -[a-zA-Z]*s' >/dev/null && show=: ;;
+esac
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ case "$nonopt" in
+ *cc | *++ | gcc* | *-gcc*)
+ mode=link
+ for arg
+ do
+ case "$arg" in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case "$mode" in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ lastarg=
+ srcfile="$nonopt"
+ suppress_output=
+
+ user_target=no
+ for arg
+ do
+ # Accept any command-line options.
+ case "$arg" in
+ -o)
+ if test "$user_target" != "no"; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit 1
+ fi
+ user_target=next
+ ;;
+
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+ esac
+
+ case "$user_target" in
+ next)
+ # The next one is the -o target name
+ user_target=yes
+ continue
+ ;;
+ yes)
+ # We got the output file
+ user_target=set
+ libobj="$arg"
+ continue
+ ;;
+ esac
+
+ # Accept the current argument as the source file.
+ lastarg="$srcfile"
+ srcfile="$arg"
+
+ # Aesthetically quote the previous argument.
+
+ # Backslashify any backslashes, double quotes, and dollar signs.
+ # These are the only characters that are still specially
+ # interpreted inside of double-quoted scrings.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly in scan
+ # sets, so we specify it separately.
+ case "$lastarg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ # Add the previous argument to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ done
+
+ case "$user_target" in
+ set)
+ ;;
+ no)
+ # Get the name of the library object.
+ libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ *)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSfmso]'
+ case "$libobj" in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case "$libobj" in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $libobj"
+ else
+ removelist="$libobj"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit 1" 1 2 15
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit 1" 1 2 15
+ else
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until ln "$0" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+ echo $srcfile > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ command="$base_compile $pic_flag -DPIC $srcfile"
+ if test "$build_old_libs" = yes; then
+ lo_libobj="$libobj"
+ dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$libobj"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+ libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+
+ if test -d "$dir"; then
+ $show "$rm $libobj"
+ $run $rm $libobj
+ else
+ $show "$mkdir $dir"
+ $run $mkdir $dir
+ status=$?
+ if test $status -ne 0 && test ! -d $dir; then
+ exit $status
+ fi
+ fi
+ fi
+ if test "$compiler_o_lo" = yes; then
+ output_obj="$libobj"
+ command="$command -o $output_obj"
+ elif test "$compiler_c_o" = yes; then
+ output_obj="$obj"
+ command="$command -o $output_obj"
+ fi
+
+ $run $rm "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test x"$output_obj" != x"$libobj"; then
+ $show "$mv $output_obj $libobj"
+ if $run $mv $output_obj $libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # If we have no pic_flag, then copy the object into place and finish.
+ if test -z "$pic_flag" && test "$build_old_libs" = yes; then
+ # Rename the .lo from within objdir to obj
+ if test -f $obj; then
+ $show $rm $obj
+ $run $rm $obj
+ fi
+
+ $show "$mv $libobj $obj"
+ if $run $mv $libobj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+
+ # Now arrange that obj and lo_libobj become the same file
+ $show "$LN_S $obj $lo_libobj"
+ if $run $LN_S $obj $lo_libobj; then
+ exit 0
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Allow error messages only from the first compilation.
+ suppress_output=' >/dev/null 2>&1'
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ command="$base_compile $srcfile"
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ output_obj="$obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed
+ if test x"$output_obj" != x"$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we do not
+ # accidentally link it into a program.
+ if test "$build_libtool_libs" != yes; then
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > \$libobj" || exit $?
+ else
+ # Move the .lo from within objdir
+ $show "$mv $libobj $lo_libobj"
+ if $run $mv $libobj $lo_libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+ fi
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $rm "$lockfile"
+ fi
+
+ exit 0
+ ;;
+
+ # libtool link mode
+ link)
+ modename="$modename: link"
+ C_compiler="$CC" # save it, to compile generated C sources
+ CC="$nonopt"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invokation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+
+ # This is a source program that is used to create dlls on Windows
+ # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# # ifdef __CYGWIN32__
+# # define __CYGWIN__ __CYGWIN32__
+# # endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+ # This is a source program that is used to create import libraries
+ # on Windows for dlls which lack them. Don't remove nor modify the
+ # starting and closing comments
+# /* impgen.c starts here */
+# /* Copyright (C) 1999 Free Software Foundation, Inc.
+#
+# This file is part of GNU libtool.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# */
+#
+# #include <stdio.h> /* for printf() */
+# #include <unistd.h> /* for open(), lseek(), read() */
+# #include <fcntl.h> /* for O_RDONLY, O_BINARY */
+# #include <string.h> /* for strdup() */
+#
+# static unsigned int
+# pe_get16 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[2];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 2);
+# return b[0] + (b[1]<<8);
+# }
+#
+# static unsigned int
+# pe_get32 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[4];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 4);
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# static unsigned int
+# pe_as32 (ptr)
+# void *ptr;
+# {
+# unsigned char *b = ptr;
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# int
+# main (argc, argv)
+# int argc;
+# char *argv[];
+# {
+# int dll;
+# unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+# unsigned long export_rva, export_size, nsections, secptr, expptr;
+# unsigned long name_rvas, nexp;
+# unsigned char *expdata, *erva;
+# char *filename, *dll_name;
+#
+# filename = argv[1];
+#
+# dll = open(filename, O_RDONLY|O_BINARY);
+# if (!dll)
+# return 1;
+#
+# dll_name = filename;
+#
+# for (i=0; filename[i]; i++)
+# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
+# dll_name = filename + i +1;
+#
+# pe_header_offset = pe_get32 (dll, 0x3c);
+# opthdr_ofs = pe_header_offset + 4 + 20;
+# num_entries = pe_get32 (dll, opthdr_ofs + 92);
+#
+# if (num_entries < 1) /* no exports */
+# return 1;
+#
+# export_rva = pe_get32 (dll, opthdr_ofs + 96);
+# export_size = pe_get32 (dll, opthdr_ofs + 100);
+# nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+# secptr = (pe_header_offset + 4 + 20 +
+# pe_get16 (dll, pe_header_offset + 4 + 16));
+#
+# expptr = 0;
+# for (i = 0; i < nsections; i++)
+# {
+# char sname[8];
+# unsigned long secptr1 = secptr + 40 * i;
+# unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+# unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+# unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+# lseek(dll, secptr1, SEEK_SET);
+# read(dll, sname, 8);
+# if (vaddr <= export_rva && vaddr+vsize > export_rva)
+# {
+# expptr = fptr + (export_rva - vaddr);
+# if (export_rva + export_size > vaddr + vsize)
+# export_size = vsize - (export_rva - vaddr);
+# break;
+# }
+# }
+#
+# expdata = (unsigned char*)malloc(export_size);
+# lseek (dll, expptr, SEEK_SET);
+# read (dll, expdata, export_size);
+# erva = expdata - export_rva;
+#
+# nexp = pe_as32 (expdata+24);
+# name_rvas = pe_as32 (expdata+32);
+#
+# printf ("EXPORTS\n");
+# for (i = 0; i<nexp; i++)
+# {
+# unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+# printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+# }
+#
+# return 0;
+# }
+# /* impgen.c ends here */
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ compile_command="$CC"
+ finalize_command="$CC"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ linkopts=
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval lib_search_path=\`\$echo \"X \${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ lib_search_path=
+ fi
+ # now prepend the system-specific ones
+ eval lib_search_path=\"$sys_lib_search_path_spec\$lib_search_path\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ link_against_libtool_libs=
+ ltlibs=
+ module=no
+ objs=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case "$arg" in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ prefer_static_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test $# -gt 0; do
+ arg="$1"
+ shift
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case "$prev" in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case "$arg" in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit 1
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case "$arg" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi
+
+ prevarg="$arg"
+
+ case "$arg" in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: not more than one -exported-symbols argument allowed"
+ exit 1
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ absdir="$dir"
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case " $deplibs " in
+ *" $arg "*) ;;
+ *) deplibs="$deplibs $arg";;
+ esac
+ case " $lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir";;
+ esac
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+ case ":$dllsearchpath:" in
+ ::) dllsearchpath="$dllsearchdir";;
+ *":$dllsearchdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dllsearchdir";;
+ esac
+ ;;
+ esac
+ ;;
+
+ -l*)
+ if test "$arg" = "-lc"; then
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+ # These systems don't actually have c library (as such)
+ continue
+ ;;
+ esac
+ elif test "$arg" = "-lm"; then
+ case "$host" in
+ *-*-cygwin* | *-*-beos*)
+ # These systems don't actually have math library (as such)
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static)
+ # If we have no pic_flag, then this is the same as -all-static.
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.o | *.obj | *.a | *.lib)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A library object.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
+ prev=
+ fi
+ libobjs="$libobjs $arg"
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ dlname=
+ libdir=
+ library_names=
+ old_library=
+
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variable installed.
+ installed=yes
+
+ # Read the .la file
+ # If there is no directory component, then add one.
+ case "$arg" in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Find the relevant object directory and library name.
+ name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
+
+ if test "X$installed" = Xyes; then
+ dir="$libdir"
+ else
+ dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$arg"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+ fi
+
+ if test -n "$dependency_libs"; then
+ # Extract -R and -L from dependency_libs
+ temp_deplibs=
+ for deplib in $dependency_libs; do
+ case "$deplib" in
+ -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ case " $rpath $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ -L*) case "$compile_command $temp_deplibs " in
+ *" $deplib "*) ;;
+ *) temp_deplibs="$temp_deplibs $deplib";;
+ esac
+ temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ case " $lib_search_path " in
+ *" $temp_dir "*) ;;
+ *) lib_search_path="$lib_search_path $temp_dir";;
+ esac
+ ;;
+ *) temp_deplibs="$temp_deplibs $deplib";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ if test -z "$libdir"; then
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $dir/$old_library"
+ old_convenience="$old_convenience $dir/$old_library"
+ deplibs="$deplibs$dependency_libs"
+ compile_command="$compile_command $dir/$old_library$dependency_libs"
+ finalize_command="$finalize_command $dir/$old_library$dependency_libs"
+ continue
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking statically,
+ # we need to preload.
+ prev=dlprefiles
+ else
+ # We should not create a dependency on this library, but we
+ # may need any libraries it requires.
+ compile_command="$compile_command$dependency_libs"
+ finalize_command="$finalize_command$dependency_libs"
+ prev=
+ continue
+ fi
+ fi
+
+ # The library was specified with -dlpreopen.
+ if test "$prev" = dlprefiles; then
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ dlprefiles="$dlprefiles $dir/$old_library"
+ else
+ dlprefiles="$dlprefiles $dir/$linklib"
+ fi
+ prev=
+ fi
+
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ link_against_libtool_libs="$link_against_libtool_libs $arg"
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+
+ # We need an absolute path.
+ case "$dir" in
+ [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+
+ # This is the magic to use -rpath.
+ # Skip directories that are in the system default run-time
+ # search path, unless they have been requested with -R.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+
+ lib_linked=yes
+ case "$hardcode_action" in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ compile_command="$compile_command $dir/$linklib"
+ deplibs="$deplibs $dir/$linklib"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+ if test -n "$dllsearchpath"; then
+ dllsearchpath="$dllsearchpath:$dllsearchdir"
+ else
+ dllsearchpath="$dllsearchdir"
+ fi
+ ;;
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case "$host" in
+ *-*-sunos*)
+ compile_shlibpath="$compile_shlibpath$dir:"
+ ;;
+ esac
+ case "$compile_command " in
+ *" -L$dir "*) ;;
+ *) compile_command="$compile_command -L$dir";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -L$dir -l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ case ":$compile_shlibpath:" in
+ *":$dir:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$dir:";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+
+ relink)
+ if test "$hardcode_direct" = yes; then
+ compile_command="$compile_command $absdir/$linklib"
+ deplibs="$deplibs $absdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ case "$compile_command " in
+ *" -L$absdir "*) ;;
+ *) compile_command="$compile_command -L$absdir";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -L$absdir -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case ":$compile_shlibpath:" in
+ *":$absdir:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$absdir:";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+
+ *)
+ lib_linked=no
+ ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit 1
+ fi
+
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ finalize_command="$finalize_command $libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ case "$finalize_command " in
+ *" -L$libdir "*) ;;
+ *) finalize_command="$finalize_command -L$libdir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case ":$finalize_shlibpath:" in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ case "$finalize_command " in
+ *" -L$dir "*) ;;
+ *) finalize_command="$finalize_command -L$libdir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ fi
+ else
+ # Transform directly to old archives if we don't build new libraries.
+ if test -n "$pic_flag" && test -z "$old_library"; then
+ $echo "$modename: cannot find static library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_command="$compile_command $dir/$linklib"
+ finalize_command="$finalize_command $dir/$linklib"
+ else
+ case "$compile_command " in
+ *" -L$dir "*) ;;
+ *) compile_command="$compile_command -L$dir";;
+ esac
+ compile_command="$compile_command -l$name"
+ case "$finalize_command " in
+ *" -L$dir "*) ;;
+ *) finalize_command="$finalize_command -L$dir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ fi
+ fi
+
+ # Add in any libraries that this one depends upon.
+ compile_command="$compile_command$dependency_libs"
+ finalize_command="$finalize_command$dependency_libs"
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ case "$output" in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *.a | *.lib)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link libtool libraries into archives" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ ;;
+
+ *.la)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case "$outputname" in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+
+ if test -n "$objs"; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
+ exit 1
+ fi
+
+ # How the heck are we supposed to write a wrapper for a shared library?
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2
+ exit 1
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test $# -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ libext=al
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+ dependency_libs="$deplibs"
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ current="$2"
+ revision="$3"
+ age="$4"
+
+ # Check that each of the things are valid numbers.
+ case "$current" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$revision" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$age" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test $age -gt $current; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case "$version_type" in
+ none) ;;
+
+ irix)
+ major=`expr $current - $age + 1`
+ versuffix="$major.$revision"
+ verstring="sgi$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test $loop != 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="sgi$major.$iface:$verstring"
+ done
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test $loop != 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ windows)
+ # Like Linux, but with '-' rather than '.', since we only
+ # want one extension on Windows 95.
+ major=`expr $current - $age`
+ versuffix="-$major-$age-$revision"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ verstring="0.0"
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+
+ dependency_libs="$deplibs"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *)
+ # Add libc to deplibs on all other systems.
+ deplibs="$deplibs -lc"
+ ;;
+ esac
+ fi
+
+ # Create the output directory, or remove our outputs if we need to.
+ if test -d $output_objdir; then
+ $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
+ $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
+ else
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ if test "$build_libtool_libs" = yes; then
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case "$deplibs_check_method" in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behaviour.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $C_compiler -o conftest conftest.c $deplibs
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occured in the first compile. Let's try to salvage the situation:
+ # Compile a seperate program for each library.
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ $rm conftest
+ $C_compiler -o conftest conftest.c $i
+ # Did it work?
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning! Library $i is needed by this library but I was not able to"
+ echo "*** make it link in! You will probably need to install it or some"
+ echo "*** library that it depends on before this library will be fully"
+ echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"$2 \(.*\)\"`"
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | sed 's/.* -> //'`
+ case "$potliblink" in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | sed 10q \
+ | egrep "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' |
+ grep . >/dev/null; then
+ echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ echo
+ echo "*** Warning: libtool could not satisfy all declared inter-library"
+ echo "*** dependencies of module $libname. Therefore, libtool will create"
+ echo "*** a static module, that should work as long as the dlopening"
+ echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ echo "*** The inter-library dependencies that have been dropped here will be"
+ echo "*** automatically added whenever a program is linked with this library"
+ echo "*** or is declared to -dlopen it."
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ # Get the real and link names of the library.
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ lib="$output_objdir/$realname"
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Ensure that we have .o objects for linkers which dislike .lo
+ # (e.g. aix) incase we are running --disable-static
+ for obj in $libobjs; do
+ oldobj=`$echo "X$obj" | $Xsed -e "$lo2o"`
+ if test ! -f $oldobj; then
+ $show "${LN_S} $obj $oldobj"
+ $run ${LN_S} $obj $oldobj || exit $?
+ fi
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ eval cmds=\"$export_symbols_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linkopts="$linkopts $flag"
+ fi
+
+ # Do each of the archive commands.
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval cmds=\"$archive_expsym_cmds\"
+ else
+ eval cmds=\"$archive_cmds\"
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ *.lo | *.o | *.obj)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link libtool libraries into objects" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case "$output" in
+ *.lo)
+ if test -n "$objs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit 1
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${obj}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs"
+
+ output="$obj"
+ eval cmds=\"$reload_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit 0
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > $libobj" || exit $?
+ exit 0
+ fi
+
+ if test -n "$pic_flag"; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ eval cmds=\"$reload_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ else
+ # Just create a symlink.
+ $show $rm $libobj
+ $run $rm $libobj
+ $show "$LN_S $obj $libobj"
+ $run $LN_S $obj $libobj || exit $?
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit 0
+ ;;
+
+ # Anything else should be a program.
+ *)
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$compile_rpath " in
+ *" $libdir "*) ;;
+ *) compile_rpath="$compile_rpath $libdir" ;;
+ esac
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+
+ # Create the binary in the object directory, then wrap it.
+ if test ! -d $output_objdir; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case "$dlsyms" in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$output.exp"
+ $run $rm $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/$output.exp"'
+ $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`echo "$arg" | sed -e 's%^.*/%%'`
+ $run eval 'echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \
+ -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \
+ < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr_t) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case "$host" in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit 1
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+
+ if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
+ case "$0" in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit 1" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ link_against_libtool_libs='$link_against_libtool_libs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ echo >> $output "\
+ program=lt-'$outputname'
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if (cd \"\$thisdir\" && eval \$relink_command); then :
+ else
+ $rm \"\$progdir/\$file\"
+ exit 1
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ echo >> $output "\
+ program='$outputname$exeext'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ *-*-cygwin* | *-*-mingw | *-*-os2*)
+ # win32 systems need to use the prog path for dll
+ # lookup to work
+ $echo >> $output "\
+ exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+ ;;
+ *)
+ $echo >> $output "\
+ # Export the path to the program.
+ PATH=\"\$progdir:\$PATH\"
+ export PATH
+
+ exec \$program \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ \$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 1
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit 0
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ # Add in members from convenience archives.
+ for xlib in $addlibs; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ eval cmds=\"$old_archive_from_new_cmds\"
+ else
+ # Ensure that we have .o objects in place incase we decided
+ # not to build a shared library, and have fallen back to building
+ # static libs even though --disable-static was passed!
+ for oldobj in $oldobjs; do
+ if test ! -f $oldobj; then
+ obj=`$echo "X$oldobj" | $Xsed -e "$o2lo"`
+ $show "${LN_S} $obj $oldobj"
+ $run ${LN_S} $obj $oldobj || exit $?
+ fi
+ done
+
+ eval cmds=\"$old_archive_cmds\"
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case "$output" in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ if test -n "$xrpath"; then
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ done
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ fi
+ $rm $output
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$dlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'\
+"
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $?
+ ;;
+ esac
+ exit 0
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ 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
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest="$arg"
+ continue
+ fi
+
+ case "$arg" in
+ -d) isdir=yes ;;
+ -f) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*) ;;
+
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest="$arg"
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test $# -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ fi
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case "$file" in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case "$file" in
+ *.a | *.lib)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ library_names=
+ old_library=
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/"
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$realname $destdir/$realname"
+ $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
+
+ if test $# -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ 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)"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ eval cmds=\"$postinstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case "$destfile" in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.o | *.obj)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit 0
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Do a test to see if this is really a libtool program.
+ if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ link_against_libtool_libs=
+ relink_command=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$link_against_libtool_libs"; then
+ $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
+ exit 1
+ fi
+
+ finalize=yes
+ for lib in $link_against_libtool_libs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case "$lib" in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`"
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir="/tmp"
+ test -n "$TMPDIR" && tmpdir="$TMPDIR"
+ tmpdir="$tmpdir/libtool-$$"
+ if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+ else
+ $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+ continue
+ fi
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ # Do each command in the postinstall commands.
+ eval cmds=\"$old_postinstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec $SHELL $0 --finish$current_libdirs
+ exit 1
+ fi
+
+ exit 0
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ eval cmds=\"$finish_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit 0
+
+ echo "----------------------------------------------------------------------"
+ echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ echo " $libdir"
+ done
+ echo
+ echo "If you ever happen to want to link against installed libraries"
+ echo "in a given directory, LIBDIR, you must either use libtool, and"
+ echo "specify the full pathname of the library, or use \`-LLIBDIR'"
+ echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ echo
+ echo "See any operating system documentation about shared libraries for"
+ echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ echo "----------------------------------------------------------------------"
+ exit 0
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit 1
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ dir=
+ case "$file" in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit 1
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case "$file" in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+
+ # Restore saved enviroment variables
+ if test "${save_LC_ALL+set}" = set; then
+ LC_ALL="$save_LC_ALL"; export LC_ALL
+ fi
+ if test "${save_LANG+set}" = set; then
+ LANG="$save_LANG"; export LANG
+ fi
+
+ # Now actually exec the command.
+ eval "exec \$cmd$args"
+
+ $echo "$modename: cannot exec \$cmd$args"
+ exit 1
+ else
+ # Display what would be done.
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ $echo "$cmd$args"
+ exit 0
+ fi
+ ;;
+
+ # libtool uninstall mode
+ uninstall)
+ modename="$modename: uninstall"
+ rm="$nonopt"
+ files=
+
+ for arg
+ do
+ case "$arg" in
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ rmfiles="$file"
+
+ case "$name" in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $dir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
+
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ eval cmds=\"$postuninstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ eval cmds=\"$old_postuninstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ fi
+
+ # FIXME: should reinstall the best remaining shared library.
+ fi
+ ;;
+
+ *.lo)
+ if test "$build_old_libs" = yes; then
+ oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
+ rmfiles="$rmfiles $dir/$oldobj"
+ fi
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ ;;
+
+ *)
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ ;;
+ esac
+ done
+ exit 0
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+fi # test -z "$show_help"
+
+# We need to display help for each of the modes.
+case "$mode" in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --version print version information
+
+MODE must be one of the following:
+
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE."
+ exit 0
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+esac
+
+echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
--- /dev/null
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "apitest"=..\libraries\libldap\apitest.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "apitest_r"=..\libraries\libldap_r\apitest_r.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "backldbm"="..\servers\slapd\back-ldbm\backldbm.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "build"=.\build.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name apitest
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name apitest_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name dtest
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name etest
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldapdelete
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldapmodify
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldapmodrdn
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldappasswd
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldapsearch
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldbmtest
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name testavl
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ud
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name slapcat
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name slapadd
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name slapindex
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name slapd
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldbmcat
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldif2ldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldbmindex
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldbmentry
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ltest
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ltest_r
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "dtest"=..\libraries\liblber\dtest.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "etest"=..\libraries\liblber\etest.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ldapdelete"=..\clients\tools\ldapdelete.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ldapmodify"=..\clients\tools\ldapmodify.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ldapmodrdn"=..\clients\tools\ldapmodrdn.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ldappasswd"=..\clients\tools\ldappasswd.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ldapsearch"=..\clients\tools\ldapsearch.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ldbmtest"=..\servers\slapd\tools\ldbmtest.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name backldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libslapd
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libavl
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ldif"=..\servers\slapd\tools\ldif.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libavl"=..\libraries\libavl\libavl.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "liblber"=..\libraries\liblber\liblber.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libldap"=..\libraries\libldap\libldap.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libldap_r"=..\libraries\libldap_r\libldap_r.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libldbm"=..\libraries\libldbm\libldbm.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libldif"=..\libraries\libldif\libldif.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "liblutil"=..\libraries\liblutil\liblutil.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libslapd"=..\servers\slapd\libslapd.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "ltest"=..\libraries\libldap\ltest.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ltest_r"=..\libraries\libldap_r\ltest_r.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "setup"=..\include\setup.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "slapadd"=..\servers\slapd\tools\slapadd.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name backldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libavl
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libslapd
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "slapcat"=..\servers\slapd\tools\slapcat.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libavl
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libslapd
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name backldbm
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "slapd"=..\servers\slapd\slapd.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name backldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libavl
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name setup
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libslapd
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "slapindex"=..\servers\slapd\tools\slapindex.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name backldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libavl
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libslapd
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "testavl"=..\libraries\libavl\testavl.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libavl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ud"=..\clients\ud\ud.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+## Copyright 1998,1999 The OpenLDAP Foundation
+## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory
+## of this package for details.
+##---------------------------------------------------------------------------
+##
+## Makefile Template for Manual Pages
+##
+
+MANDIR=$(mandir)/man$(MANSECT)
+TMP_SUFFIX=tmp
+
+all-common:
+ PAGES=`cd $(srcdir); echo *.$(MANSECT)`; \
+ for page in $$PAGES; do \
+ $(SED) -e "s%LDVERSION%$(VERSION)%" \
+ -e 's%ETCDIR%$(sysconfdir)%' \
+ -e 's%LOCALSTATEDIR%$(localstatedir)%' \
+ -e 's%SYSCONFDIR%$(sysconfdir)%' \
+ -e 's%DATADIR%$(datadir)%' \
+ -e 's%SBINDIR%$(sbindir)%' \
+ -e 's%BINDIR%$(bindir)%' \
+ -e 's%LIBDIR%$(libdir)%' \
+ -e 's%LIBEXECDIR%$(libexecdir)%' \
+ $(srcdir)/$$page > $$page.$(TMP_SUFFIX); \
+ done
+
+install-common:
+ -$(MKDIR) $(MANDIR)
+ PAGES=`cd $(srcdir); echo *.$(MANSECT)`; \
+ for page in $$PAGES; do \
+ echo "installing $(MANDIR)/$$page"; \
+ $(RM) $(MANDIR)/$$page; \
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $$page.$(TMP_SUFFIX) $(MANDIR)/$$page; \
+ if test -f "$(srcdir)/$$page.links" ; then \
+ for link in `$(CAT) $(srcdir)/$$page.links`; do \
+ echo "installing $(MANDIR)/$$link as link to $$page"; \
+ $(RM) $(MANDIR)/$$link ; \
+ $(LN_S) $$page $(MANDIR)/$$link; \
+ done; \
+ fi; \
+ done
+
+clean-common: FORCE
+ $(RM) *.tmp all-common
+
+Makefile: $(top_srcdir)/build/man.mk
--- /dev/null
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
exit 1
fi
-cvs export -r$CVSTAG -d $RELNAME $*
+echo Release: $RELNAME
+echo CVS Tag: $CVSTAG
+echo Modules: $*
+
+cvs -q export -r $CVSTAG -d $RELNAME $*
if test ! -d $RELNAME ; then
echo "error: $RELNAME doesn't exists"
--- /dev/null
+## Copyright 1998,1999 The OpenLDAP Foundation
+## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory
+## of this package for details.
+##---------------------------------------------------------------------------
+##
+## Makefile Template for Server Modules
+##
+
+LIBRARY = $(LIBBASE).la
+LIBSTAT = lib$(LIBBASE).a
+LTFLAGS = --only-$(LINKAGE)
+
+all-no lint-no 5lint-no depend-no install-no: FORCE
+ @echo "run configure with $(BUILD_OPT) to make $(LIBBASE)"
+
+all-common: all-$(BUILD_MOD)
+
+version.c: $(OBJS)
+ $(RM) $@
+ $(MKVERSION) $(LIBBASE) > $@
+
+$(LIBRARY): version.lo
+ $(LTLIBLINK) -module -rpath $(moduledir) -o $@ $(OBJS) version.lo
+
+$(LIBSTAT): version.lo
+ $(AR) ruv $@ `echo $(OBJS) | sed 's/\.lo/.o/g'` version.o
+ @$(RANLIB) $@
+
+clean-common: clean-lib FORCE
+veryclean-common: veryclean-lib FORCE
+
+
+lint-common: lint-$(BUILD_MOD)
+
+5lint-common: 5lint-$(BUILD_MOD)
+
+depend-common: depend-$(BUILD_MOD)
+
+install-common: install-$(BUILD_MOD)
+
+all-local-mod:
+all-mod: $(LIBRARY) all-local-mod FORCE
+
+all-local-lib:
+all-yes: $(LIBSTAT) all-local-lib FORCE
+
+install-mod: $(LIBRARY)
+ @-$(MKDIR) $(moduledir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 $(LIBRARY) $(moduledir)
+
+install-local-lib:
+install-yes: install-local-lib FORCE
+
+lint-local-lib:
+lint-yes lint-mod: lint-local-lib FORCE
+ $(LINT) $(DEFS) $(DEFINES) $(SRCS)
+
+5lint-local-lib:
+5lint-yes 5lint-mod: 5lint-local-lib FORCE
+ $(5LINT) $(DEFS) $(DEFINES) $(SRCS)
+
+clean-local-lib:
+clean-lib: clean-local-lib FORCE
+ $(RM) $(LIBRARY) $(LIBSTAT) version.c *.o *.lo a.out core .libs/*
+
+depend-local-lib:
+depend-yes depend-mod: depend-local-lib FORCE
+ $(MKDEP) $(DEFS) $(DEFINES) $(SRCS)
+
+veryclean-local-lib:
+veryclean-lib: clean-lib veryclean-local-lib
+
+COMPILE = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CFLAGS) -c
+MKDEPFLAG = -l
+
+.SUFFIXES: .c .o .lo
+
+.c.lo:
+ $(COMPILE) $<
+
+Makefile: $(top_srcdir)/build/mod.mk
--- /dev/null
+dnl Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+dnl COPYING RESTRICTIONS APPLY, See COPYRIGHT file
+dnl
+dnl OpenLDAP Autoconf Macros
+dnl
+dnl --------------------------------------------------------------------
+dnl Restricted form of AC_ARG_ENABLE that limits user options
+dnl
+dnl $1 = option name
+dnl $2 = help-string
+dnl $3 = default value (auto)
+dnl $4 = allowed values (auto yes no)
+AC_DEFUN([OL_ARG_ENABLE], [# OpenLDAP --enable-$1
+ AC_ARG_ENABLE($1,[$2 (]ifelse($3,,auto,$3)[)],[
+ ol_arg=invalid
+ for ol_val in ifelse($4,,[auto yes no],[$4]) ; do
+ if test "$enableval" = "$ol_val" ; then
+ ol_arg="$ol_val"
+ fi
+ done
+ if test "$ol_arg" = "invalid" ; then
+ AC_MSG_ERROR(bad value $enableval for --enable-$1)
+ fi
+ ol_enable_$1="$ol_arg"
+],
+[ ol_enable_$1=ifelse($3,,"auto","$3")])dnl
+dnl AC_VERBOSE(OpenLDAP -enable-$1 $ol_enable_$1)
+# end --enable-$1
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+dnl Restricted form of AC_ARG_WITH that limits user options
+dnl
+dnl $1 = option name
+dnl $2 = help-string
+dnl $3 = default value (no)
+dnl $4 = allowed values (yes or no)
+AC_DEFUN([OL_ARG_WITH], [# OpenLDAP --with-$1
+ AC_ARG_WITH($1,[$2 (]ifelse($3,,yes,$3)[)],[
+ ol_arg=invalid
+ for ol_val in ifelse($4,,[yes no],[$4]) ; do
+ if test "$withval" = "$ol_val" ; then
+ ol_arg="$ol_val"
+ fi
+ done
+ if test "$ol_arg" = "invalid" ; then
+ AC_MSG_ERROR(bad value $withval for --with-$1)
+ fi
+ ol_with_$1="$ol_arg"
+],
+[ ol_with_$1=ifelse($3,,"no","$3")])dnl
+dnl AC_VERBOSE(OpenLDAP --with-$1 $ol_with_$1)
+# end --with-$1
+])dnl
+dnl
+dnl ====================================================================
+dnl check if hard links are supported.
+dnl
+AC_DEFUN([OL_PROG_LN_H], [# test for ln hardlink support
+AC_MSG_CHECKING(whether ln works)
+AC_CACHE_VAL(ol_cv_prog_LN_H,
+[rm -f conftest.src conftest.dst
+echo "conftest" > conftest.src
+if ln conftest.src conftest.dst 2>/dev/null
+then
+ ol_cv_prog_LN_H="ln"
+else
+ ol_cv_prog_LN_H="cp"
+fi
+rm -f conftest.src conftest.dst
+])dnl
+LN_H="$ol_cv_prog_LN_H"
+if test "$ol_cv_prog_LN_H" = "ln"; then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST(LN_H)dnl
+])dnl
+dnl
+dnl ====================================================================
+dnl Check for dependency generation flag
+AC_DEFUN([OL_MKDEPEND], [# test for make depend flag
+OL_MKDEP=
+OL_MKDEP_FLAGS=
+if test -z "${MKDEP}"; then
+ OL_MKDEP="${CC-cc}"
+ if test -z "${MKDEP_FLAGS}"; then
+ AC_CACHE_CHECK([for ${OL_MKDEP} depend flag], ol_cv_mkdep, [
+ ol_cv_mkdep=no
+ for flag in "-M" "-xM"; do
+ cat > conftest.c <<EOF
+ noCode;
+EOF
+ if AC_TRY_COMMAND($OL_MKDEP $flag conftest.c) \
+ | egrep '^conftest\.'"${ac_objext}" >/dev/null 2>&1
+ then
+ if test ! -f conftest."${ac_object}" ; then
+ ol_cv_mkdep=$flag
+ OL_MKDEP_FLAGS="$flag"
+ break
+ fi
+ fi
+ done
+ rm -f conftest*
+ ])
+ else
+ cc_cv_mkdep=yes
+ OL_MKDEP_FLAGS="${MKDEP_FLAGS}"
+ fi
+else
+ cc_cv_mkdep=yes
+ OL_MKDEP="${MKDEP}"
+ OL_MKDEP_FLAGS="${MKDEP_FLAGS}"
+fi
+AC_SUBST(OL_MKDEP)
+AC_SUBST(OL_MKDEP_FLAGS)
+])
+dnl
+dnl ====================================================================
+dnl Check if system uses EBCDIC instead of ASCII
+AC_DEFUN([OL_CPP_EBCDIC], [# test for EBCDIC
+AC_CACHE_CHECK([for EBCDIC],ol_cv_cpp_ebcdic,[
+ AC_TRY_CPP([
+#if !('M' == 0xd4)
+#include <__ASCII__/generate_error.h>
+#endif
+],
+ [ol_cv_cpp_ebcdic=yes],
+ [ol_cv_cpp_ebcdic=no])])
+if test $ol_cv_cpp_ebcdic = yes ; then
+ AC_DEFINE(HAVE_EBCDIC,1, [define if system uses EBCDIC instead of ASCII])
+fi
+])
+dnl
+dnl --------------------------------------------------------------------
+dnl OpenLDAP version of STDC header check w/ EBCDIC support
+AC_DEFUN(OL_HEADER_STDC,
+[AC_REQUIRE_CPP()dnl
+AC_REQUIRE([OL_CPP_EBCDIC])dnl
+AC_CACHE_CHECK([for ANSI C header files], ol_cv_header_stdc,
+[AC_TRY_CPP([#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>], ol_cv_header_stdc=yes, ol_cv_header_stdc=no)
+
+if test $ol_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+AC_EGREP_HEADER(memchr, string.h, , ol_cv_header_stdc=no)
+fi
+
+if test $ol_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+AC_EGREP_HEADER(free, stdlib.h, , ol_cv_header_stdc=no)
+fi
+
+if test $ol_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+AC_TRY_RUN([#include <ctype.h>
+#ifndef HAVE_EBCDIC
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+], , ol_cv_header_stdc=no, :)
+fi])
+if test $ol_cv_header_stdc = yes; then
+ AC_DEFINE(STDC_HEADERS)
+fi
+ac_cv_header_stdc=disable
+])
+dnl
+dnl ====================================================================
+dnl Check if struct passwd has pw_gecos
+AC_DEFUN([OL_STRUCT_PASSWD_PW_GECOS], [# test for pw_gecos in struct passwd
+AC_CACHE_CHECK([struct passwd for pw_gecos],ol_cv_struct_passwd_pw_gecos,[
+ AC_TRY_COMPILE([#include <pwd.h>],[
+ struct passwd pwd;
+ pwd.pw_gecos = pwd.pw_name;
+],
+ [ol_cv_struct_passwd_pw_gecos=yes],
+ [ol_cv_struct_passwd_pw_gecos=no])])
+if test $ol_cv_struct_passwd_pw_gecos = yes ; then
+ AC_DEFINE(HAVE_PW_GECOS,1, [define if struct passwd has pw_gecos])
+fi
+])
+dnl
+dnl --------------------------------------------------------------------
+dnl Check if struct passwd has pw_passwd
+AC_DEFUN([OL_STRUCT_PASSWD_PW_PASSWD], [# test for pw_passwd in struct passwd
+AC_CACHE_CHECK([struct passwd for pw_passwd],ol_cv_struct_passwd_pw_passwd,[
+ AC_TRY_COMPILE([#include <pwd.h>],[
+ struct passwd pwd;
+ pwd.pw_passwd = pwd.pw_name;
+],
+ [ol_cv_struct_passwd_pw_passwd=yes],
+ [ol_cv_struct_passwd_pw_passwd=no])])
+if test $ol_cv_struct_passwd_pw_passwd = yes ; then
+ AC_DEFINE(HAVE_PW_PASSWD,1, [define if struct passwd has pw_passwd])
+fi
+])
+dnl
+dnl ====================================================================
+dnl Check if db.h is Berkeley DB2
+dnl
+dnl defines ol_cv_header_db2 to 'yes' or 'no'
+dnl
+dnl uses:
+dnl AC_CHECK_HEADERS(db.h)
+dnl
+AC_DEFUN([OL_HEADER_BERKELEY_DB2],
+[AC_CHECK_HEADERS(db.h)
+if test $ac_cv_header_db_h = yes ; then
+ AC_CACHE_CHECK([if db.h is DB2], [ol_cv_header_db2],[
+ AC_EGREP_CPP(__db_version_2,[
+# include <db.h>
+ /* this check could be improved */
+# ifdef DB_VERSION_MAJOR
+# if DB_VERSION_MAJOR == 2
+ __db_version_2
+# endif
+# endif
+ ], ol_cv_header_db2=yes, ol_cv_header_db2=no)])
+else
+ ol_cv_header_db2=no
+fi
+])dnl
+dnl --------------------------------------------------------------------
+dnl Check if Berkeley DB2 library exists
+dnl Check for dbopen in standard libraries or -ldb
+dnl
+dnl defines ol_cv_lib_db2 to '-ldb' or 'no'
+dnl
+dnl uses:
+dnl AC_CHECK_LIB(db,db_open)
+dnl
+AC_DEFUN([OL_LIB_BERKELEY_DB2],
+[AC_CACHE_CHECK([for DB2 library], [ol_cv_lib_db2],
+[ ol_LIBS="$LIBS"
+ AC_CHECK_LIB(db,db_open,[ol_cv_lib_db2=-ldb],[ol_cv_lib_db2=no])
+ LIBS="$ol_LIBS"
+])
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+dnl Check if Berkeley db2 exists
+dnl
+dnl defines ol_cv_berkeley_db2 to 'yes' or 'no'
+dnl
+dnl uses:
+dnl OL_LIB_BERKELEY_DB2
+dnl OL_HEADER_BERKELEY_DB2
+dnl
+AC_DEFUN([OL_BERKELEY_DB2],
+[AC_REQUIRE([OL_LIB_BERKELEY_DB2])
+ AC_REQUIRE([OL_HEADER_BERKELEY_DB2])
+ AC_CACHE_CHECK([for Berkeley DB2], [ol_cv_berkeley_db2], [
+ if test "$ol_cv_lib_db2" = no -o "$ol_cv_header_db2" = no ; then
+ ol_cv_berkeley_db2=no
+ else
+ ol_cv_berkeley_db2=yes
+ fi
+])
+ if test $ol_cv_berkeley_db2 = yes ; then
+ AC_DEFINE(HAVE_BERKELEY_DB2,1, [define if Berkeley DBv2 is available])
+ fi
+])dnl
+dnl
+dnl ====================================================================
+dnl Check for db.h/db_185.h is Berkeley DB
+dnl
+dnl defines ol_cv_header_db to 'yes' or 'no'
+dnl
+dnl uses:
+dnl OL_HEADER_BERKELEY_DB2
+dnl AC_CHECK_HEADERS(db_185.h)
+dnl
+AC_DEFUN([OL_HEADER_BERKELEY_DB],
+[AC_REQUIRE([OL_HEADER_BERKELEY_DB2])
+AC_CHECK_HEADERS(db_185.h)
+if test "$ol_cv_header_db2" = yes ; then
+ dnl db.h is db2!
+
+ ol_cv_header_db=$ac_cv_header_db_185_h
+else
+ ol_cv_header_db=$ac_cv_header_db_h
+fi
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+dnl Check if Berkeley DB library exists
+dnl Check for dbopen in standard libraries or -ldb
+dnl
+dnl defines ol_cv_lib_db to 'yes' or '-ldb' or 'no'
+dnl 'yes' implies dbopen is in $LIBS
+dnl
+dnl uses:
+dnl AC_CHECK_FUNC(dbopen)
+dnl AC_CHECK_LIB(db,dbopen)
+dnl
+AC_DEFUN([OL_LIB_BERKELEY_DB],
+[AC_CACHE_CHECK([for Berkeley DB library], [ol_cv_lib_db],
+[
+ AC_CHECK_HEADERS(db1/db.h)
+ ol_LIBS="$LIBS"
+ AC_CHECK_FUNC(dbopen,[ol_cv_lib_db=yes], [
+ AC_CHECK_LIB(db1,dbopen,[ol_cv_lib_db=-ldb1],[
+ AC_CHECK_LIB(db,dbopen,[ol_cv_lib_db=-ldb],
+ [ol_cv_lib_db=no])
+ ])
+ ])
+ LIBS="$ol_LIBS"
+])
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+dnl Check if Berkeley DB exists
+dnl
+dnl defines ol_cv_berkeley_db to 'yes' or 'no'
+dnl
+dnl uses:
+dnl OL_LIB_BERKELEY_DB
+dnl OL_HEADER_BERKELEY_DB
+dnl
+AC_DEFUN([OL_BERKELEY_DB],
+[AC_REQUIRE([OL_LIB_BERKELEY_DB])
+ AC_REQUIRE([OL_HEADER_BERKELEY_DB])
+ AC_CACHE_CHECK([for Berkeley DB], [ol_cv_berkeley_db], [
+ if test "$ol_cv_lib_db" = no -o "$ol_cv_header_db" = no ; then
+ ol_cv_berkeley_db=no
+ else
+ ol_cv_berkeley_db=yes
+ fi
+])
+ if test $ol_cv_berkeley_db = yes ; then
+ AC_DEFINE(HAVE_BERKELEY_DB,1, [define if Berkeley DB is available])
+ fi
+])dnl
+dnl
+dnl ====================================================================
+dnl Check if GDBM library exists
+dnl Check for gdbm_open in standard libraries or -lgdbm
+dnl
+dnl defines ol_cv_lib_gdbm to 'yes' or '-lgdbm' or 'no'
+dnl 'yes' implies gdbm_open is in $LIBS
+dnl
+dnl uses:
+dnl AC_CHECK_FUNC(gdbm_open)
+dnl AC_CHECK_LIB(gdbm,gdbm_open)
+dnl
+AC_DEFUN([OL_LIB_GDBM],
+[AC_CACHE_CHECK(for GDBM library, [ol_cv_lib_gdbm],
+[ ol_LIBS="$LIBS"
+ AC_CHECK_FUNC(gdbm_open,[ol_cv_lib_gdbm=yes], [
+ AC_CHECK_LIB(gdbm,gdbm_open,[ol_cv_lib_gdbm=-lgdbm],[ol_cv_lib_gdbm=no])
+ ])
+ LIBS="$ol_LIBS"
+])
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+dnl Check if GDBM exists
+dnl
+dnl defines ol_cv_gdbm to 'yes' or 'no'
+dnl
+dnl uses:
+dnl OL_LIB_GDBM
+dnl AC_CHECK_HEADERS(gdbm.h)
+dnl
+AC_DEFUN([OL_GDBM],
+[AC_REQUIRE([OL_LIB_GDBM])
+ AC_CHECK_HEADERS(gdbm.h)
+ AC_CACHE_CHECK(for db, [ol_cv_gdbm], [
+ if test $ol_cv_lib_gdbm = no -o $ac_cv_header_gdbm_h = no ; then
+ ol_cv_gdbm=no
+ else
+ ol_cv_gdbm=yes
+ fi
+])
+ if test $ol_cv_gdbm = yes ; then
+ AC_DEFINE(HAVE_GDBM,1, [define if GNU DBM is available])
+ fi
+])dnl
+dnl
+dnl ====================================================================
+dnl Check if MDBM library exists
+dnl Check for mdbm_open in standard libraries or -lmdbm
+dnl
+dnl defines ol_cv_lib_mdbm to 'yes' or '-lmdbm' or 'no'
+dnl 'yes' implies mdbm_open is in $LIBS
+dnl
+dnl uses:
+dnl AC_CHECK_FUNC(mdbm_set_chain)
+dnl AC_CHECK_LIB(mdbm,mdbm_set_chain)
+dnl
+AC_DEFUN([OL_LIB_MDBM],
+[AC_CACHE_CHECK(for MDBM library, [ol_cv_lib_mdbm],
+[ ol_LIBS="$LIBS"
+ AC_CHECK_FUNC(mdbm_set_chain,[ol_cv_lib_mdbm=yes], [
+ AC_CHECK_LIB(mdbm,mdbm_set_chain,[ol_cv_lib_mdbm=-lmdbm],[ol_cv_lib_mdbm=no])
+ ])
+ LIBS="$ol_LIBS"
+])
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+dnl Check if MDBM exists
+dnl
+dnl defines ol_cv_mdbm to 'yes' or 'no'
+dnl
+dnl uses:
+dnl OL_LIB_MDBM
+dnl AC_CHECK_HEADERS(mdbm.h)
+dnl
+AC_DEFUN([OL_MDBM],
+[AC_REQUIRE([OL_LIB_MDBM])
+ AC_CHECK_HEADERS(mdbm.h)
+ AC_CACHE_CHECK(for db, [ol_cv_mdbm], [
+ if test $ol_cv_lib_mdbm = no -o $ac_cv_header_mdbm_h = no ; then
+ ol_cv_mdbm=no
+ else
+ ol_cv_mdbm=yes
+ fi
+])
+ if test $ol_cv_mdbm = yes ; then
+ AC_DEFINE(HAVE_MDBM,1, [define if MDBM is available])
+ fi
+])dnl
+dnl
+dnl ====================================================================
+dnl Check if NDBM library exists
+dnl Check for dbm_open in standard libraries or -lndbm or -ldbm
+dnl
+dnl defines ol_cv_lib_ndbm to 'yes' or '-lndbm' or -ldbm or 'no'
+dnl 'yes' implies ndbm_open is in $LIBS
+dnl
+dnl uses:
+dnl AC_CHECK_FUNC(dbm_open)
+dnl AC_CHECK_LIB(ndbm,dbm_open)
+dnl AC_CHECK_LIB(dbm,dbm_open)
+dnl
+dnl restrictions:
+dnl should also check SVR4 case: dbm_open() in -lucb but that
+dnl would requiring dealing with -L/usr/ucblib
+dnl
+AC_DEFUN([OL_LIB_NDBM],
+[AC_CACHE_CHECK(for NDBM library, [ol_cv_lib_ndbm],
+[ ol_LIBS="$LIBS"
+ AC_CHECK_FUNC(dbm_open,[ol_cv_lib_ndbm=yes], [
+ AC_CHECK_LIB(ndbm,dbm_open,[ol_cv_lib_ndbm=-lndbm], [
+ AC_CHECK_LIB(dbm,dbm_open,[ol_cv_lib_ndbm=-ldbm],
+ [ol_cv_lib_ndbm=no])dnl
+ ])
+ ])
+ LIBS="$ol_LIBS"
+])
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+dnl Check if NDBM exists
+dnl
+dnl defines ol_cv_ndbm to 'yes' or 'no'
+dnl
+dnl uses:
+dnl OL_LIB_NDBM
+dnl AC_CHECK_HEADERS(ndbm.h)
+dnl
+dnl restrictions:
+dnl Doesn't handle SVR4 case (see above)
+dnl
+AC_DEFUN([OL_NDBM],
+[AC_REQUIRE([OL_LIB_NDBM])
+ AC_CHECK_HEADERS(ndbm.h)
+ AC_CACHE_CHECK(for db, [ol_cv_ndbm], [
+ if test $ol_cv_lib_ndbm = no -o $ac_cv_header_ndbm_h = no ; then
+ ol_cv_ndbm=no
+ else
+ ol_cv_ndbm=yes
+ fi
+])
+ if test $ol_cv_ndbm = yes ; then
+ AC_DEFINE(HAVE_NDBM,1, [define if NDBM is available])
+ fi
+])dnl
+dnl
+dnl ====================================================================
+dnl Check POSIX Thread version
+dnl
+dnl defines ol_cv_posix_version to 'final' or 'draft' or 'unknown'
+dnl 'unknown' implies that the version could not be detected
+dnl or that pthreads.h does exist. Existance of pthreads.h
+dnl should be tested separately.
+dnl
+AC_DEFUN([OL_POSIX_THREAD_VERSION],
+[AC_CACHE_CHECK([POSIX thread version],[ol_cv_pthread_version],[
+ AC_EGREP_CPP(pthread_version_final,[
+# include <pthread.h>
+ /* this check could be improved */
+# ifdef PTHREAD_ONCE_INIT
+ pthread_version_final
+# endif
+ ], ol_pthread_final=yes, ol_pthread_final=no)
+
+ AC_EGREP_CPP(pthread_version_draft4,[
+# include <pthread.h>
+ /* this check could be improved */
+# ifdef pthread_once_init
+ pthread_version_draft4
+# endif
+ ], ol_pthread_draft4=yes, ol_pthread_draft4=no)
+
+ if test $ol_pthread_final = yes -a $ol_pthread_draft4 = no; then
+ ol_cv_pthread_version=final
+ elif test $ol_pthread_final = no -a $ol_pthread_draft4 = yes; then
+ ol_cv_pthread_version=draft4
+ else
+ ol_cv_pthread_version=unknown
+ fi
+])
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+AC_DEFUN([OL_PTHREAD_TEST_INCLUDES],
+[/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+])
+AC_DEFUN([OL_PTHREAD_TEST_FUNCTION],[
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+])
+
+AC_DEFUN([OL_PTHREAD_TEST_PROGRAM],
+[OL_PTHREAD_TEST_INCLUDES
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+OL_PTHREAD_TEST_FUNCTION
+}
+])
+dnl --------------------------------------------------------------------
+AC_DEFUN([OL_PTHREAD_TRY], [# Pthread try link: $1 ($2)
+if test "$ol_link_threads" = no ; then
+ # try $1
+ AC_CACHE_CHECK([for pthread link with $1], [$2], [
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="$1 $LIBS"
+
+ AC_TRY_RUN(OL_PTHREAD_TEST_PROGRAM,
+ [$2=yes], [$2=no],
+ [AC_TRY_LINK(OL_PTHREAD_TEST_INCLUDES,OL_PTHREAD_TEST_FUNCTION,
+ [$2=yes], [$2=no])])
+
+ # restore the LIBS
+ LIBS="$ol_LIBS"
+ ])
+
+ if test $$2 = yes ; then
+ ol_link_pthreads="$1"
+ ol_link_threads=posix
+ fi
+fi
+])
+dnl
+dnl ====================================================================
+dnl Check LinuxThreads Header
+dnl
+dnl defines ol_cv_header linux_threads to 'yes' or 'no'
+dnl 'no' implies pthreads.h is not LinuxThreads or pthreads.h
+dnl doesn't exists. Existance of pthread.h should separately
+dnl checked.
+dnl
+AC_DEFUN([OL_HEADER_LINUX_THREADS], [
+ AC_CACHE_CHECK([for LinuxThreads pthread.h],
+ [ol_cv_header_linux_threads],
+ [AC_EGREP_CPP(pthread_kill_other_threads_np,
+ [#include <pthread.h>],
+ [ol_cv_header_linux_threads=yes],
+ [ol_cv_header_linux_threads=no])
+ ])
+ if test $ol_cv_header_linux_threads = yes; then
+ AC_DEFINE(HAVE_LINUX_THREADS,1,[if you have LinuxThreads])
+ fi
+])dnl
+dnl --------------------------------------------------------------------
+dnl Check LinuxThreads Implementation
+dnl
+dnl defines ol_cv_sys_linux_threads to 'yes' or 'no'
+dnl 'no' implies pthreads implementation is not LinuxThreads.
+dnl
+AC_DEFUN([OL_SYS_LINUX_THREADS], [
+ AC_CHECK_FUNC(pthread_kill_other_threads_np)
+ AC_CACHE_CHECK([for LinuxThreads implementation],
+ [ol_cv_sys_linux_threads],
+ [ol_cv_sys_linux_threads=$ac_cv_func_pthread_kill_other_threads_np])
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+dnl Check LinuxThreads consistency
+AC_DEFUN([OL_LINUX_THREADS], [
+ AC_REQUIRE([OL_HEADER_LINUX_THREADS])
+ AC_REQUIRE([OL_SYS_LINUX_THREADS])
+ AC_CACHE_CHECK([for LinuxThreads consistency], [ol_cv_linux_threads], [
+ if test $ol_cv_header_linux_threads = yes -a \
+ $ol_cv_sys_linux_threads = yes; then
+ ol_cv_linux_threads=yes
+ elif test $ol_cv_header_linux_threads = no -a \
+ $ol_cv_sys_linux_threads = no; then
+ ol_cv_linux_threads=no
+ else
+ ol_cv_linux_threads=error
+ fi
+ ])
+])dnl
+dnl
+dnl ====================================================================
+dnl Check for POSIX Regex
+AC_DEFUN([OL_POSIX_REGEX], [
+AC_CACHE_CHECK([for compatible POSIX regex],ol_cv_c_posix_regex,[
+ AC_TRY_RUN([
+#include <sys/types.h>
+#include <regex.h>
+static char *pattern, *string;
+main()
+{
+ int rc;
+ regex_t re;
+
+ pattern = "^A";
+
+ if(regcomp(&re, pattern, 0)) {
+ return -1;
+ }
+
+ string = "ALL MATCH";
+
+ rc = regexec(&re, string, 0, (void*)0, 0);
+
+ regfree(&re);
+
+ return rc;
+}],
+ [ol_cv_c_posix_regex=yes],
+ [ol_cv_c_posix_regex=no],
+ [ol_cv_c_posix_regex=cross])])
+])
+dnl
+dnl ====================================================================
+dnl Check if toupper() requires islower() to be called first
+AC_DEFUN([OL_C_UPPER_LOWER],
+[AC_CACHE_CHECK([if toupper() requires islower()],ol_cv_c_upper_lower,[
+ AC_TRY_RUN([
+#include <ctype.h>
+main()
+{
+ if ('C' == toupper('C'))
+ exit(0);
+ else
+ exit(1);
+}],
+ [ol_cv_c_upper_lower=no],
+ [ol_cv_c_upper_lower=yes],
+ [ol_cv_c_upper_lower=safe])])
+if test $ol_cv_c_upper_lower != no ; then
+ AC_DEFINE(C_UPPER_LOWER,1, [define if toupper() requires islower()])
+fi
+])
+dnl
+dnl ====================================================================
+dnl Check for declaration of sys_errlist in one of stdio.h and errno.h.
+dnl Declaration of sys_errlist on BSD4.4 interferes with our declaration.
+dnl Reported by Keith Bostic.
+AC_DEFUN([OL_SYS_ERRLIST],
+[AC_CACHE_CHECK([declaration of sys_errlist],ol_cv_dcl_sys_errlist,[
+ AC_TRY_COMPILE([
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h> ],
+ [char *c = (char *) *sys_errlist],
+ [ol_cv_dcl_sys_errlist=yes
+ ol_cv_have_sys_errlist=yes],
+ [ol_cv_dcl_sys_errlist=no])])
+#
+# It's possible (for near-UNIX clones) that sys_errlist doesn't exist
+if test $ol_cv_dcl_sys_errlist = no ; then
+ AC_DEFINE(DECL_SYS_ERRLIST,1,
+ [define if sys_errlist is not declared in stdio.h or errno.h])
+
+ AC_CACHE_CHECK([existence of sys_errlist],ol_cv_have_sys_errlist,[
+ AC_TRY_LINK([#include <errno.h>],
+ [char *c = (char *) *sys_errlist],
+ [ol_cv_have_sys_errlist=yes],
+ [ol_cv_have_sys_errlist=no])])
+fi
+if test $ol_cv_have_sys_errlist = yes ; then
+ AC_DEFINE(HAVE_SYS_ERRLIST,1,
+ [define if you actually have sys_errlist in your libs])
+fi
+])dnl
+dnl
+dnl ====================================================================
+dnl Early MIPS compilers (used in Ultrix 4.2) don't like
+dnl "int x; int *volatile a = &x; *a = 0;"
+dnl -- borrowed from PDKSH
+AC_DEFUN(OL_C_VOLATILE,
+ [AC_CACHE_CHECK(if compiler understands volatile, ol_cv_c_volatile,
+ [AC_TRY_COMPILE([int x, y, z;],
+ [volatile int a; int * volatile b = x ? &y : &z;
+ /* Older MIPS compilers (eg., in Ultrix 4.2) don't like *b = 0 */
+ *b = 0;], ol_cv_c_volatile=yes, ol_cv_c_volatile=no)])
+ if test $ol_cv_c_volatile = yes; then
+ :
+ else
+ AC_DEFINE(volatile,,[define as empty if volatile is not supported])
+ fi
+ ])dnl
+dnl
+dnl ====================================================================
+dnl Look for fetch(3)
+AC_DEFUN([OL_LIB_FETCH],
+[ol=$LIBS
+LIBS="-lfetch -lcom_err $LIBS"
+AC_CACHE_CHECK([fetch(3) library],ol_cv_lib_fetch,[
+ AC_TRY_LINK([
+#include <sys/param.h>
+#include <stdio.h>
+#include <fetch.h>],
+ [struct url *u = fetchParseURL("file:///"); ],
+ [ol_cv_lib_fetch=yes],
+ [ol_cv_lib_fetch=no])])
+LIBS=$ol_LIBS
+if test $ol_cv_lib_fetch != no ; then
+ ol_link_fetch="-lfetch -lcom_err"
+ AC_DEFINE(HAVE_FETCH,1,
+ [define if you actually have FreeBSD fetch(3)])
+fi
+])dnl
+dnl
+dnl ====================================================================
+dnl Define sig_atomic_t if not defined in signal.h
+AC_DEFUN(OL_TYPE_SIG_ATOMIC_T,
+ [AC_CACHE_CHECK(for sig_atomic_t, ol_cv_type_sig_atomic_t,
+ [AC_TRY_COMPILE([#include <signal.h>], [sig_atomic_t atomic;],
+ ol_cv_type_sig_atomic_t=yes, ol_cv_type_sig_atomic_t=no)])
+ if test $ol_cv_type_sig_atomic_t = no; then
+ AC_DEFINE(sig_atomic_t,int,
+ [define to atomic type if sig_atomic_t is not available])
+ fi
+ ])dnl
+dnl
+dnl ====================================================================
+dnl Define socklen_t if not defined in sys/types.h or sys/socket.h
+AC_DEFUN(OL_TYPE_SOCKLEN_T,
+ [AC_CACHE_CHECK(for socklen_t, ol_cv_type_socklen_t,
+ [AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+], [socklen_t len;],
+ ol_cv_type_socklen_t=yes, ol_cv_type_socklen_t=no)])
+ if test $ol_cv_type_socklen_t = no; then
+ AC_DEFINE(socklen_t, int,
+ [define to int if socklen_t is not available])
+ fi
+ ])dnl
+dnl
+dnl ====================================================================
+dnl Define inet_aton is available
+AC_DEFUN(OL_FUNC_INET_ATON,
+ [AC_CACHE_CHECK([for inet_aton()], ol_cv_func_inet_aton,
+ [AC_TRY_LINK([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# endif
+# include <netinet/in.h>
+# ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+# endif
+#endif
+], [struct in_addr in;
+int rc = inet_aton( "255.255.255.255", &in );],
+ ol_cv_func_inet_aton=yes, ol_cv_func_inet_aton=no)])
+ if test $ol_cv_func_inet_aton != no; then
+ AC_DEFINE(HAVE_INET_ATON, 1,
+ [define to you inet_aton(3) is available])
+ fi
+ ])dnl
+dnl
+dnl ====================================================================
+dnl check no of arguments for ctime_r
+AC_DEFUN(OL_FUNC_CTIME_R_NARGS,
+ [AC_CACHE_CHECK(number of arguments of ctime_r, ol_cv_func_ctime_r_nargs,
+ [AC_TRY_COMPILE([#include <time.h>],
+ [time_t ti; char *buffer; ctime_r(&ti,buffer,32);],
+ ol_cv_func_ctime_r_nargs=3,
+ [AC_TRY_COMPILE([#include <time.h>],
+ [time_t ti; char *buffer; ctime_r(&ti,buffer);],
+ ol_cv_func_ctime_r_nargs=2,
+ ol_cv_func_ctime_r_nargs=0)])])
+ if test $ol_cv_func_ctime_r_nargs -gt 1 ; then
+ AC_DEFINE_UNQUOTED(CTIME_R_NARGS, $ol_cv_func_ctime_r_nargs,
+ [set to the number of arguments ctime_r() expects])
+ fi
+])dnl
+dnl
+dnl --------------------------------------------------------------------
+dnl check return type of ctime_r()
+AC_DEFUN(OL_FUNC_CTIME_R_TYPE,
+ [AC_CACHE_CHECK(return type of ctime_r, ol_cv_func_ctime_r_type,
+ [AC_TRY_COMPILE([#include <time.h>],
+ [extern int (ctime_r)();],
+ ol_cv_func_ctime_r_type="int", ol_cv_func_ctime_r_type="charp")
+ ])
+ if test $ol_cv_func_ctime_r_type = "int" ; then
+ AC_DEFINE(CTIME_R_RETURNS_INT,1, [define if ctime_r() returns int])
+ fi
+])dnl
+dnl ====================================================================
+dnl check no of arguments for gethostbyname_r
+AC_DEFUN(OL_FUNC_GETHOSTBYNAME_R_NARGS,
+ [AC_CACHE_CHECK(number of arguments of gethostbyname_r,
+ ol_cv_func_gethostbyname_r_nargs,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#define BUFSIZE (sizeof(struct hostent)+10)],
+ [struct hostent hent; char buffer[BUFSIZE];
+ int bufsize=BUFSIZE;int h_errno;
+ (void)gethostbyname_r("segovia.cs.purdue.edu", &hent,
+ buffer, bufsize, &h_errno);],
+ ol_cv_func_gethostbyname_r_nargs=5,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#define BUFSIZE (sizeof(struct hostent)+10)],
+ [struct hostent hent;struct hostent *rhent;
+ char buffer[BUFSIZE];
+ int bufsize=BUFSIZE;int h_errno;
+ (void)gethostbyname_r("localhost", &hent, buffer, bufsize,
+ &rhent, &h_errno);],
+ ol_cv_func_gethostbyname_r_nargs=6,
+ ol_cv_func_gethostbyname_r_nargs=0)])])
+ if test $ol_cv_func_gethostbyname_r_nargs -gt 1 ; then
+ AC_DEFINE_UNQUOTED(GETHOSTBYNAME_R_NARGS,
+ $ol_cv_func_gethostbyname_r_nargs,
+ [set to the number of arguments gethostbyname_r() expects])
+ fi
+])dnl
+dnl
+dnl check no of arguments for gethostbyaddr_r
+AC_DEFUN(OL_FUNC_GETHOSTBYADDR_R_NARGS,
+ [AC_CACHE_CHECK(number of arguments of gethostbyaddr_r,
+ [ol_cv_func_gethostbyaddr_r_nargs],
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#define BUFSIZE (sizeof(struct hostent)+10)],
+ [struct hostent hent; char buffer[BUFSIZE];
+ struct in_addr add;
+ size_t alen=sizeof(struct in_addr);
+ int bufsize=BUFSIZE;int h_errno;
+ (void)gethostbyaddr_r( (void *)&(add.s_addr),
+ alen, AF_INET, &hent, buffer, bufsize, &h_errno);],
+ ol_cv_func_gethostbyaddr_r_nargs=7,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#define BUFSIZE (sizeof(struct hostent)+10)],
+ [struct hostent hent;
+ struct hostent *rhent; char buffer[BUFSIZE];
+ struct in_addr add;
+ size_t alen=sizeof(struct in_addr);
+ int bufsize=BUFSIZE;int h_errno;
+ (void)gethostbyaddr_r( (void *)&(add.s_addr),
+ alen, AF_INET, &hent, buffer, bufsize,
+ &rhent, &h_errno);],
+ ol_cv_func_gethostbyaddr_r_nargs=8,
+ ol_cv_func_gethostbyaddr_r_nargs=0)])])
+ if test $ol_cv_func_gethostbyaddr_r_nargs -gt 1 ; then
+ AC_DEFINE_UNQUOTED(GETHOSTBYADDR_R_NARGS,
+ $ol_cv_func_gethostbyaddr_r_nargs,
+ [set to the number of arguments gethostbyaddr_r() expects])
+ fi
+])dnl
+dnl
--- /dev/null
+## Copyright 1998,1999 The OpenLDAP Foundation
+## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory
+## of this package for details.
+##---------------------------------------------------------------------------
+##
+## Makefile Template for Programs
+##
+
+all-common: $(PROGRAMS) FORCE
+
+clean-common: FORCE
+ $(RM) $(PROGRAMS) $(XPROGRAMS) $(XSRCS) *.o *.lo a.out core *.core .libs/*
+
+depend-common: FORCE
+ $(MKDEP) $(DEFS) $(DEFINES) $(SRCS)
+
+lint: FORCE
+ $(LINT) $(DEFS) $(DEFINES) $(SRCS)
+
+lint5: FORCE
+ $(5LINT) $(DEFS) $(DEFINES) $(SRCS)
+
+Makefile: $(top_srcdir)/build/rules.mk
+
--- /dev/null
+## Copyright 1998,1999 The OpenLDAP Foundation
+## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory
+## of this package for details.
+##---------------------------------------------------------------------------
+##
+## Makefile Template for Servers
+##
+
+all-common: all-$(BUILD_SRV)
+all-no lint-no 5lint-no depend-no install-no:
+ @echo "run configure with $(BUILD_OPT) to make $(PROGRAMS)"
+
+clean-common: clean-srv FORCE
+veryclean-common: veryclean-srv FORCE
+
+lint-common: lint-$(BUILD_SRV)
+
+5lint-common: 5lint-$(BUILD_SRV)
+
+depend-common: depend-$(BUILD_SRV)
+
+install-common: install-$(BUILD_SRV)
+
+all-local-srv:
+all-yes: all-local-srv FORCE
+
+install-local-srv:
+install-yes: install-local-srv FORCE
+
+lint-local-srv:
+lint-yes: lint-local-srv FORCE
+ $(LINT) $(DEFS) $(DEFINES) $(SRCS)
+
+5lint-local-srv:
+5lint-yes: 5lint-local-srv FORCE
+ $(5LINT) $(DEFS) $(DEFINES) $(SRCS)
+
+clean-local-srv:
+clean-srv: clean-local-srv FORCE
+ $(RM) $(PROGRAMS) $(XPROGRAMS) $(XSRCS) *.o a.out core .libs/*
+
+depend-local-srv:
+depend-yes: depend-local-srv FORCE
+ $(MKDEP) $(DEFS) $(DEFINES) $(SRCS)
+
+veryclean-local-srv:
+veryclean-srv: clean-srv veryclean-local-srv
+
+Makefile: $(top_srcdir)/build/srv.mk
ldap_subdir = @ldap_subdir@
bindir = $(TMPROOT)@bindir@
-datadir = $(TMPROOT)@datadir@/$(ldap_subdir)
+datadir = $(TMPROOT)@datadir@$(ldap_subdir)
includedir = $(TMPROOT)@includedir@
infodir = $(TMPROOT)@infodir@
libdir = $(TMPROOT)@libdir@
libexecdir = $(TMPROOT)@libexecdir@
localstatedir = $(TMPROOT)@localstatedir@
mandir = $(TMPROOT)@mandir@
+moduledir = $(TMPROOT)@libexecdir@$(ldap_subdir)
sbindir = $(TMPROOT)@sbindir@
sharedstatedir = $(TMPROOT)@sharedstatedir@
-sysconfdir = $(TMPROOT)@sysconfdir@/$(ldap_subdir)
+sysconfdir = $(TMPROOT)@sysconfdir@$(ldap_subdir)
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
LDAP_LIBPATH= -L$(LDAP_LIBADIR)
LUTIL_LIBS = @LUTIL_LIBS@
+LDIF_LIBS = @LDIF_LIBS@
LDBM_LIBS = @LDBM_LIBS@
LTHREAD_LIBS = @LTHREAD_LIBS@
AC_LIBS = @LIBS@
KRB_LIBS = @KRB_LIBS@
+SASL_LIBS = @SASL_LIBS@
TLS_LIBS = @TLS_LIBS@
+SECURITY_LIBS = @SASL_LIBS@ @KRB_LIBS@ @TLS_LIBS@
+
MODULES_CPPFLAGS = @SLAPD_MODULES_CPPFLAGS@
MODULES_LDFLAGS = @SLAPD_MODULES_LDFLAGS@
+MODULES_LIBS = @MODULES_LIBS@
PERL_CPPFLAGS = @SLAPD_PERL_CPPFLAGS@
PERL_LDFLAGS = @SLAPD_PERL_LDFLAGS@
TERMCAP_LIBS = @TERMCAP_LIBS@
--- /dev/null
+PROGRAMS= rp500 fax500 xrpcomp.tmp
+
+SRCS= main.c faxtotpc.c rp500.c
+XSRCS=fax5version.c rpversion.c
+
+FAX5OBJS = main.o faxtotpc.o
+RPOBJS = rp500.o faxtotpc.o
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldap -llber -llutil
+XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
+
+rp500 : rpversion.o
+ $(LTLINK) -o $@ $(RPOBJS) rpversion.o $(LIBS)
+
+fax500 : fax5version.o
+ $(LTLINK) -o $@ $(RPOBJS) fax5version.o $(LIBS)
+
+rpversion.c: ${RPOBJS} $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) rp500 > $@
+
+fax5version.c: ${FAX5OBJS} $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) fax500 > $@
+
+xrpcomp.tmp: xrpcomp
+ $(SED) -e 's|%LIBEXECDIR%|$(libexecdir)|' $(srcdir)/xrpcomp > xrpcomp.tmp
+
+install-local: $(PROGRAMS) FORCE
+ -$(MKDIR) $(libexecdir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 rp500 $(libexecdir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 fax500 $(libexecdir)
+ $(INSTALL) $(INSTALLFLAGS) -m 755 xrpcomp.tmp $(libexecdir)/xrpcomp
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <memory.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <syslog.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/sysexits.h>
+#include <ac/syslog.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sysexits.h>
-#include <ldapconfig.h>
-#include "portable.h"
+#endif
-#include "lber.h"
-#include "ldap.h"
+#include <ldap.h>
+
+#include "fax500.h"
+#include "ldap_defaults.h"
#define USER 0
#define GROUP_ERRORS 1
char *mailfrom = NULL;
char *host = NULL;
int hostlen = 0;
-char *faxtotpc();
int identity;
#define MAIL500 1
"rfc822RequestsTo", "joinable", "cn", "member",
"facsimileTelephoneNumber", NULL };
-static do_address();
-static do_group();
-static do_group_members();
-static send_message();
-static send_errors();
-static do_noemailorfax();
-static do_ambiguous();
-static add_to();
-static isgroup();
-static add_error();
-static add_group();
-static unbind_and_exit();
-static group_loop();
-static send_group();
-static has_attributes();
-static char **get_attributes_mail_dn();
-static char *canonical();
-
-main (argc, argv)
-int argc;
-char **argv;
+
+static void do_address(char *name, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr, int type);
+static int do_group(LDAPMessage *e, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr);
+static void do_group_members(LDAPMessage *e, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr);
+static void send_message(char **to);
+static void send_errors(Error *err, int nerr);
+static void do_noemailorfax(FILE *fp, Error *err, int namelen, int errtype);
+static void do_ambiguous(FILE *fp, Error *err, int namelen);
+static int count_values(char **list);
+static void add_to(char ***list, int *nlist, char **new);
+static int isgroup(LDAPMessage *e);
+static void add_error(Error **err, int *nerr, int code, char *addr, LDAPMessage *msg);
+static void add_group(char *dn, Group **list, int *nlist);
+static void unbind_and_exit(int rc);
+static int group_loop(char *dn);
+static void send_group(Group *group, int ngroup);
+static int has_attributes(LDAPMessage *e, char *attr1, char *attr2);
+static char **get_attributes_mail_dn(LDAPMessage *e, char *attr1, char *attr2);
+static char *canonical(char *s);
+static int connect_to_x500 (void);
+static void do_group_errors (LDAPMessage *e, char *dn, char ***to, int *nto, Error **err, int *nerr);
+static void do_group_request (LDAPMessage *e, char *dn, char ***to, int *nto, Error **err, int *nerr);
+static void add_member (char *gdn, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr);
+
+
+int
+main ( int argc, char **argv )
{
char *myname;
char **tolist;
Group *togroups;
int numto, ngroups, numerr, nargs;
int i, j;
- FILE *fp;
- extern int optind, errno;
- extern char *optarg;
while ( (i = getopt( argc, argv, "f:h:m:" )) != EOF ) {
switch( i ) {
identity = MAIL500;
}
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+
#ifdef LOG_MAIL
openlog( myname, OPENLOG_OPTIONS, LOG_MAIL );
#else
*/
if ( numerr > 0 && numto > nargs || ngroups > 0 ) {
- int fd;
+ FILE *fp;
char buf[BUFSIZ];
umask( 077 );
return( EX_OK );
}
-connect_to_x500()
+static int
+connect_to_x500( void )
{
- if ( (ld = ldap_open( LDAPHOST, LDAP_PORT )) == NULL ) {
- syslog( LOG_ALERT, "ldap_open failed" );
+ int sizelimit = FAX_MAXAMBIGUOUS;
+ int deref = LDAP_DEREF_ALWAYS;
+
+ if ( (ld = ldap_init( NULL, 0 )) == NULL ) {
+ syslog( LOG_ALERT, "ldap_init failed" );
return( -1 );
}
- ld->ld_sizelimit = FAX_MAXAMBIGUOUS;
- ld->ld_deref = LDAP_DEREF_ALWAYS;
- if ( ldap_simple_bind_s( ld, FAX_BINDDN, NULL ) != LDAP_SUCCESS ) {
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
+
+ if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
syslog( LOG_ALERT, "ldap_simple_bind_s failed" );
return( -1 );
}
}
-static
-do_address( name, to, nto, togroups, ngroups, err, nerr, type )
- char *name;
- char ***to;
- int *nto;
- Group **togroups;
- int *ngroups;
- Error **err;
- int *nerr;
- int type;
+static void
+do_address(
+ char *name,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr,
+ int type
+)
{
int rc, b, f, match;
LDAPMessage *e, *res;
/* no matches - bounce with user unknown */
if ( match == 0 ) {
- add_error( err, nerr, E_USERUNKNOWN, name, NULLMSG );
+ add_error( err, nerr, E_USERUNKNOWN, name, NULL );
return;
}
return;
}
-static
-do_group( e, dn, to, nto, togroups, ngroups, err, nerr )
- LDAPMessage *e;
- char *dn;
- char ***to;
- int *nto;
- Group **togroups;
- int *ngroups;
- Error **err;
- int *nerr;
+static int
+do_group(
+ LDAPMessage *e,
+ char *dn,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr
+)
{
/*
* If this group has an rfc822ErrorsTo attribute, we need to
}
/* ARGSUSED */
-static
-do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr )
- LDAPMessage *e;
- char *dn;
- char ***to;
- int *nto;
- Group **togroups;
- int *ngroups;
- Error **err;
- int *nerr;
+static void
+do_group_members(
+ LDAPMessage *e,
+ char *dn,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr
+)
{
int i, rc;
char *ndn;
timeout.tv_usec = 0;
/* for each subtree to look in... */
- ld->ld_sizelimit = FAX_MAXMEMBERS;
+ {
+ int sizelimit = FAX_MAXMEMBERS;
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
+ }
for ( i = 0; base[i].b_dn != NULL; i++ ) {
/* find entries that have joined this group... */
rc = ldap_search_st( ld, base[i].b_dn,
add_error( err, nerr,
E_JOINMEMBERNOFAXNUM, ndn,
- NULLMSG );
+ NULL );
free( ndn );
}
add_error( err, nerr,
E_JOINMEMBERNOEMAIL, ndn,
- NULLMSG );
+ NULL );
free( ndn );
}
ldap_msgfree( res );
}
- ld->ld_sizelimit = FAX_MAXAMBIGUOUS;
+ {
+ int sizelimit = FAX_MAXAMBIGUOUS;
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
+ }
}
return;
}
-add_member( gdn, dn, to, nto, togroups, ngroups, err, nerr )
- char *gdn;
- char *dn;
- char ***to;
- int *nto;
- Group **togroups;
- int *ngroups;
- Error **err;
- int *nerr;
+static void
+add_member(
+ char *gdn,
+ char *dn,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr
+)
{
char *ndn;
char **mail;
if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "(objectclass=*)",
attrs, 0, &timeout, &res )) != LDAP_SUCCESS ) {
if ( rc == LDAP_NO_SUCH_OBJECT ) {
- add_error( err, nerr, E_BADMEMBER, dn, NULLMSG );
+ add_error( err, nerr, E_BADMEMBER, dn, NULL );
return;
} else {
ldap_value_free( mail );
ldap_msgfree( res );
} else {
- add_error( err, nerr, E_MEMBERNOFAXNUM, ndn, NULLMSG );
+ add_error( err, nerr, E_MEMBERNOFAXNUM, ndn, NULL );
}
break;
case MAIL500 :
/* else generate a bounce */
} else {
- add_error( err, nerr, E_MEMBERNOEMAIL, ndn, NULLMSG );
+ add_error( err, nerr, E_MEMBERNOEMAIL, ndn, NULL );
}
free( ndn );
return;
}
-do_group_request( e, dn, to, nto, err, nerr )
- LDAPMessage *e;
- char *dn;
- char ***to;
- int *nto;
- Error **err;
- int *nerr;
+static void
+do_group_request(
+ LDAPMessage *e,
+ char *dn,
+ char ***to,
+ int *nto,
+ Error **err,
+ int *nerr
+)
{
char **requeststo;
ldap_value_free( requeststo );
} else {
- add_error( err, nerr, E_NOREQUEST, dn, NULLMSG );
+ add_error( err, nerr, E_NOREQUEST, dn, NULL );
}
-
- return;
}
-do_group_errors( e, dn, to, nto, err, nerr )
- LDAPMessage *e;
- char *dn;
- char ***to;
- int *nto;
- Error **err;
- int *nerr;
+static void
+do_group_errors(
+ LDAPMessage *e,
+ char *dn,
+ char ***to,
+ int *nto,
+ Error **err,
+ int *nerr
+)
{
char **errorsto;
ldap_value_free( errorsto );
} else {
- add_error( err, nerr, E_NOERRORS, dn, NULLMSG );
+ add_error( err, nerr, E_NOERRORS, dn, NULL );
}
-
- return;
}
-static
-send_message( to )
- char **to;
+static void
+send_message( char **to )
{
int pid;
-#ifndef USE_WAITPID
+#ifndef HAVE_WAITPID
WAITSTATUSTYPE status;
#endif
/* parent */
- if ( pid = fork() ) {
-#ifdef USE_WAITPID
+ if ( (pid = fork()) != 0 ) {
+#ifdef HAVE_WAITPID
waitpid( pid, (int *) NULL, 0 );
#else
wait4( pid, &status, WAIT_FLAGS, 0 );
}
}
-static
-send_group( group, ngroup )
- Group *group;
- int ngroup;
+static void
+send_group( Group *group, int ngroup )
{
int i, pid;
char **argv;
int argc;
char *iargv[7];
-#ifndef USE_WAITPID
+#ifndef HAVE_WAITPID
WAITSTATUSTYPE status;
#endif
/* parent */
- if ( pid = fork() ) {
-#ifdef USE_WAITPID
+ if ( (pid = fork()) != 0 ) {
+#ifdef HAVE_WAITPID
waitpid( pid, (int *) NULL, 0 );
#else
wait4( pid, &status, WAIT_FLAGS, 0 );
return;
}
-static
-send_errors( err, nerr )
- Error *err;
- int nerr;
+static void
+send_errors( Error *err, int nerr )
{
int i, namelen;
FILE *fp;
}
-static
-do_noemailorfax( fp, err, namelen, errtype )
- FILE *fp;
- Error *err;
- int namelen;
- int errtype;
+static void
+do_noemailorfax( FILE *fp, Error *err, int namelen, int errtype )
{
int i, last;
char *dn, *rdn;
!= NULL ) {
for ( i = 0; vals[i]; i++ ) {
last = strlen( vals[i] ) - 1;
- if ( isdigit( vals[i][last] ) ) {
+ if ( isdigit((unsigned char) vals[i][last]) ) {
rdn = strdup( vals[i] );
break;
}
for ( i = 0; vals[0][i] != '\0'; i++ ) {
if ( vals[0][i] == '$' ) {
fprintf( fp, "\n%*s ", namelen, " " );
- while ( isspace( vals[0][i+1] ) )
+ while ( isspace((unsigned char) vals[0][i+1]) )
i++;
} else {
fprintf( fp, "%c", vals[0][i] );
}
/* ARGSUSED */
-static
-do_ambiguous( fp, err, namelen )
- FILE *fp;
- Error *err;
- int namelen;
+static void
+do_ambiguous( FILE *fp, Error *err, int namelen )
{
int i, last;
char *dn, *rdn;
if ( (vals = ldap_get_values( ld, e, "cn" )) != NULL ) {
for ( i = 0; vals[i]; i++ ) {
last = strlen( vals[i] ) - 1;
- if ( isdigit( vals[i][last] ) ) {
+ if ( isdigit((unsigned char) vals[i][last]) ) {
rdn = strdup( vals[i] );
break;
}
}
}
-static
-count_values( list )
- char **list;
+static int
+count_values( char **list )
{
int i;
return( i );
}
-static
-add_to( list, nlist, new )
- char ***list;
- int *nlist;
- char **new;
+static void
+add_to( char ***list, int *nlist, char **new )
{
int i, nnew, oldnlist;
return;
}
-static
-isgroup( e )
- LDAPMessage *e;
+static int
+isgroup( LDAPMessage *e )
{
int i;
char **oclist;
return( 0 );
}
-static
-add_error( err, nerr, code, addr, msg )
- Error **err;
- int *nerr;
- int code;
- char *addr;
- LDAPMessage *msg;
+static void
+add_error( Error **err, int *nerr, int code, char *addr, LDAPMessage *msg )
{
if ( *nerr == 0 ) {
*err = (Error *) malloc( sizeof(Error) );
return;
}
-static
-add_group( dn, list, nlist )
- char *dn;
- Group **list;
- int *nlist;
+static void
+add_group( char *dn, Group **list, int *nlist )
{
int i, namelen;
char **ufn;
return;
}
-static
-unbind_and_exit( rc )
- int rc;
+static void
+unbind_and_exit( int rc )
{
int i;
}
static char *
-canonical( s )
- char *s;
+canonical( char *s )
{
char *saves = s;
return( saves );
}
-static
-group_loop( dn )
- char *dn;
+static int
+group_loop( char *dn )
{
int i;
static char **groups;
return( 0 );
}
-static
-has_attributes( e, attr1, attr2 )
- LDAPMessage *e;
- char *attr1;
- char *attr2;
+static int
+has_attributes( LDAPMessage *e, char *attr1, char *attr2 )
{
char **attr;
}
static char **
-get_attributes_mail_dn( e, attr1, attr2 )
- LDAPMessage *e;
- char *attr1;
- char *attr2; /* this one is dn-valued */
+get_attributes_mail_dn( LDAPMessage *e, char *attr1, char *attr2 )
{
LDAPMessage *ee, *res;
char **vals, **dnlist, **mail;
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <syslog.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/syslog.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <ldapconfig.h>
-#include "lber.h"
-#include "ldap.h"
+#endif
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "fax500.h"
+#include "ldap_defaults.h"
#define DEFAULT_PORT 79
#define DEFAULT_SIZELIMIT 50
int debug;
-char *ldaphost = LDAPHOST;
-char *base = DEFAULT_BASE;
-int deref;
-int sizelimit;
+char *ldaphost = NULL;
+char *base = NULL;
+int deref = LDAP_DEREF_ALWAYS;
+int sizelimit = DEFAULT_SIZELIMIT;
LDAPFiltDesc *filtd;
-static print_entry();
+static void print_entry(LDAP *ld, LDAPMessage *e);
-static
-usage( name )
- char *name;
+static void
+usage( char *name )
{
fprintf( stderr, "usage: %s [-d debuglevel] [-x ldaphost] [-b searchbase] [-a] [-z sizelimit] [-f filterfile] searchstring\r\n", name );
exit( -1 );
}
-main (argc, argv)
- int argc;
- char **argv;
+int
+main( int argc, char **argv )
{
int i, rc, matches;
char *filterfile = FILTERFILE;
- struct timeval timeout;
char buf[10];
char *key;
LDAP *ld;
static char *attrs[] = { "title", "o", "ou", "postalAddress",
"telephoneNumber", "mail",
"facsimileTelephoneNumber", NULL };
- extern char *optarg;
- extern int optind;
- deref = LDAP_DEREF_ALWAYS;
while ( (i = getopt( argc, argv, "ab:d:f:x:z:" )) != EOF ) {
switch( i ) {
case 'a': /* do not deref aliases when searching */
exit( -1 );
}
- if ( (ld = ldap_open( ldaphost, LDAP_PORT )) == NULL ) {
- perror( "ldap_open" );
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+
+ if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) {
+ perror( "ldap_init" );
exit( -1 );
}
- ld->ld_sizelimit = sizelimit ? sizelimit : DEFAULT_SIZELIMIT;
- ld->ld_deref = deref;
- if ( ldap_simple_bind_s( ld, RP_BINDDN, NULL ) != LDAP_SUCCESS ) {
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
+
+ if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
fprintf( stderr, "X.500 is temporarily unavailable.\n" );
ldap_perror( ld, "ldap_simple_bind_s" );
exit( -1 );
result = NULL;
if ( strchr( key, ',' ) != NULL ) {
- ld->ld_deref = LDAP_DEREF_FINDING;
+ int ld_deref = LDAP_DEREF_FINDING;
+ ldap_set_option(ld, LDAP_OPT_DEREF, &ld_deref);
if ( (rc = ldap_ufn_search_s( ld, key, attrs, 0, &result ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED &&
rc != LDAP_TIMELIMIT_EXCEEDED )
rdn++;
if ( strcasecmp( rdn, buf ) == 0 ) {
char **cn;
- char *s;
int i, last;
cn = ldap_get_values( ld, e, "cn" );
for ( i = 0; cn[i] != NULL; i++ ) {
last = strlen( cn[i] ) - 1;
- if ( isdigit( cn[i][last] ) ) {
+ if ( isdigit((unsigned char) cn[i][last]) ) {
rdn = strdup( cn[i] );
break;
}
if ( fgets( buf, sizeof(buf), stdin ) == NULL
|| buf[0] == '\n' ) {
- exit( 1 );
+ exit( EXIT_FAILURE );
}
i = atoi( buf ) - 1;
e = ldap_first_entry( ld, result );
}
if ( e == NULL ) {
fprintf( stderr, "Invalid choice!\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
print_entry( ld, e );
} else if ( matches == 0 ) {
fprintf( stderr, "No matches found for \"%s\"\n", key );
- exit( 1 );
+ exit( EXIT_FAILURE );
} else {
fprintf( stderr, "Error return from ldap_count_entries\n" );
exit( -1 );
return( 0 );
}
-static
-print_entry( ld, e )
- LDAP *ld;
- LDAPMessage *e;
+static void
+print_entry( LDAP *ld, LDAPMessage *e )
{
int i;
char *dn, *rdn;
char **ufn;
char **title, **dept, **addr, **phone, **fax, **mail;
- char *faxmail, *org, *faxtotpc();
+ char *faxmail, *org;
dn = ldap_get_dn( ld, e );
ufn = ldap_explode_dn( dn, 0 );
if ( (fax = ldap_get_values( ld, e, "facsimileTelephoneNumber" ))
== NULL ) {
fprintf( stderr, "Entry \"%s\" has no fax number.\n", dn );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
- faxmail = faxtotpc( fax[0] );
+ faxmail = faxtotpc( fax[0], NULL );
title = ldap_get_values( ld, e, "title" );
phone = ldap_get_values( ld, e, "telephoneNumber" );
mail = ldap_get_values( ld, e, "mail" );
--- /dev/null
+SRCS= main.c
+XSRCS= version.c
+OBJS= main.o
+PROGRAMS= in.xfingerd
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldap -llber -llutil
+XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
+
+in.xfingerd : version.o
+ $(LTLINK) -o $@ version.o $(OBJS) $(LIBS)
+
+version.c: ${OBJS} ${LDAP_LIBDEPEND}
+ @-$(RM) $@
+ $(MKVERSION) in.xfingerd > $@
+
+install-local: $(PROGRAMS) FORCE
+ -$(MKDIR) $(libexecdir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 in.xfingerd $(libexecdir)
* is provided ``as is'' without express or implied warranty.
*/
-#include "lber.h"
-#include "ldap.h"
-#include "disptmpl.h"
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <syslog.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/syslog.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
-#include <sys/wait.h>
-#ifdef aix
-#include <sys/select.h>
-#endif /* aix */
-#include <signal.h>
-#include "portable.h"
-#include "ldapconfig.h"
+#endif
+
+#include <ldap.h>
+#include <disptmpl.h>
+
+#include "ldap_defaults.h"
-#ifdef USE_SYSCONF
-#include <unistd.h>
-#endif /* USE_SYSCONF */
int dosyslog = 1;
-char *ldaphost = LDAPHOST;
-int ldapport = LDAP_PORT;
-char *base = FINGER_BASE;
+char *ldaphost = NULL;
+int ldapport = 0;
+char *base = NULL;
int deref;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
int rdncount = FINGER_RDNCOUNT;
-static do_query();
-static do_search();
-static do_read();
-static print_attr();
+static void do_query(void);
+static void do_search(LDAP *ld, char *buf);
+static void do_read(LDAP *ld, LDAPMessage *e);
-static usage( name )
-char *name;
+static void
+usage( char *name )
{
fprintf( stderr, "usage: %s [-l] [-x ldaphost] [-p ldapport] [-f filterfile] [-t templatefile] [-c rdncount]\r\n", name );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
-main (argc, argv)
-int argc;
-char **argv;
+int
+main( int argc, char **argv )
{
int i;
char *myname;
- unsigned long mypeer = -1;
struct hostent *hp;
struct sockaddr_in peername;
- int peernamelen;
+ socklen_t peernamelen;
int interactive = 0;
- extern char *optarg;
deref = FINGER_DEREF;
while ( (i = getopt( argc, argv, "f:ilp:t:x:p:c:" )) != EOF ) {
if ( getpeername( 0, (struct sockaddr *)&peername,
&peernamelen ) != 0 ) {
perror( "getpeername" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
- mypeer = (unsigned long) peername.sin_addr.s_addr;
}
#ifdef FINGER_BANNER
else
myname = strdup( myname + 1 );
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+
if ( dosyslog ) {
#ifdef LOG_LOCAL4
openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
#endif
}
- if ( dosyslog && mypeer != -1 ) {
- struct in_addr addr;
-
- hp = gethostbyaddr( (char *) &mypeer, sizeof(mypeer), AF_INET );
- addr.s_addr = mypeer;
- syslog( LOG_INFO, "connection from %s (%s)", (hp == NULL) ?
- "unknown" : hp->h_name, inet_ntoa( addr ) );
+ if ( dosyslog && !interactive ) {
+ hp = gethostbyaddr( (char *) &peername.sin_addr.s_addr,
+ sizeof(peername.sin_addr.s_addr), AF_INET );
+ syslog( LOG_INFO, "connection from %s (%s)",
+ (hp == NULL) ? "unknown" : hp->h_name,
+ inet_ntoa( peername.sin_addr ) );
}
do_query();
return( 0 );
}
-static do_query()
+static void
+do_query( void )
{
char buf[256];
int len, rc, tblsize;
fd_set readfds;
LDAP *ld;
- if ( (ld = ldap_open( ldaphost, ldapport )) == NULL ) {
+ if ( (ld = ldap_init( ldaphost, ldapport )) == NULL ) {
fprintf( stderr, FINGER_UNAVAILABLE );
- perror( "ldap_open" );
- exit( 1 );
+ perror( "ldap_init" );
+ exit( EXIT_FAILURE );
}
- ld->ld_sizelimit = FINGER_SIZELIMIT;
- ld->ld_deref = deref;
- if ( ldap_simple_bind_s( ld, FINGER_BINDDN, NULL ) != LDAP_SUCCESS ) {
+ {
+ int limit = FINGER_SIZELIMIT;
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &limit);
+ }
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
+
+ if ( ldap_simple_bind_s( ld, NULL, NULL )
+ != LDAP_SUCCESS )
+ {
fprintf( stderr, FINGER_UNAVAILABLE );
ldap_perror( ld, "ldap_simple_bind_s" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
-#ifdef USE_SYSCONF
+#ifdef HAVE_SYSCONF
tblsize = sysconf( _SC_OPEN_MAX );
-#else /* USE_SYSCONF */
+#elif HAVE_GETDTABLESIZE
tblsize = getdtablesize();
-#endif /* USE_SYSCONF */
+#else
+ tblsize = FD_SETSIZE;
+#endif
+
+#ifdef FD_SETSIZE
+ if (tblsize > FD_SETSIZE) {
+ tblsize = FD_SETSIZE;
+ }
+#endif /* FD_SETSIZE*/
timeout.tv_sec = FINGER_TIMEOUT;
timeout.tv_usec = 0;
perror( "select" );
else
fprintf( stderr, "connection timed out on input\r\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( fgets( buf, sizeof(buf), stdin ) == NULL )
- exit( 1 );
+ exit( EXIT_FAILURE );
len = strlen( buf );
p = buf;
}
- for ( ; *p && isspace( *p ); p++ )
+ for ( ; *p && isspace( (unsigned char) *p ); p++ )
; /* NULL */
do_search( ld, p );
}
static void
-spaces2dots( s )
- char *s;
+spaces2dots( char *s )
{
for ( ; *s; s++ ) {
if ( *s == ' ' ) {
}
}
-static do_search( ld, buf )
-LDAP *ld;
-char *buf;
+static void
+do_search( LDAP *ld, char *buf )
{
char *dn, *rdn;
char **title;
int rc, matches, i, ufn;
struct timeval tv;
+ LDAPFiltDesc *fd;
LDAPFiltInfo *fi;
LDAPMessage *result, *e;
static char *attrs[] = { "cn", "title", "objectClass", "joinable",
FINGER_SORT_ATTR,
#endif
0 };
- extern int strcasecmp();
ufn = 0;
#ifdef FINGER_UFN
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
fprintf( stderr, FINGER_UNAVAILABLE );
ldap_perror( ld, "ldap_search_st" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
matches = ldap_count_entries( ld, result );
ufn = 1;
} else {
#endif
- if ( (ld->ld_filtd = ldap_init_getfilter( filterfile ))
+ if ( (fd = ldap_init_getfilter( filterfile ))
== NULL ) {
fprintf( stderr, "Cannot open filter file (%s)\n",
filterfile );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
- for ( fi = ldap_getfirstfilter( ld->ld_filtd, "finger", buf );
+ for ( fi = ldap_getfirstfilter( fd, "finger", buf );
fi != NULL;
- fi = ldap_getnextfilter( ld->ld_filtd ) )
+ fi = ldap_getnextfilter( fd ) )
{
tv.tv_sec = FINGER_TIMEOUT;
tv.tv_usec = 0;
{
fprintf( stderr, FINGER_UNAVAILABLE );
ldap_perror( ld, "ldap_search_st" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( (matches = ldap_count_entries( ld, result )) != 0 )
fflush( stdout );
} else if ( matches < 0 ) {
fprintf( stderr, "error return from ldap_count_entries\r\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
} else if ( matches <= FINGER_LISTLIMIT ) {
printf( "%d %s match%s found for \"%s\":\r\n", matches,
ufn ? "UFN" : fi->lfi_desc, matches > 1 ? "es" : "", buf );
cn = ldap_get_values( ld, e, "cn" );
for ( i = 0; cn[i] != NULL; i++ ) {
last = strlen( cn[i] ) - 1;
- if ( isdigit( cn[i][last] ) ) {
+ if (isdigit((unsigned char) cn[i][last])) {
rdn = strdup( cn[i] );
break;
}
static int
-entry2textwrite( void *fp, char *buf, int len )
+entry2textwrite( void *fp, char *buf, ber_len_t len )
{
return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
}
-static do_read( ld, e )
-LDAP *ld;
-LDAPMessage *e;
+static void
+do_read( LDAP *ld, LDAPMessage *e )
{
static struct ldap_disptmpl *tmpllist;
static char *defattrs[] = { "mail", NULL };
defvals, entry2textwrite, (void *)stdout, "\r\n", rdncount,
LDAP_DISP_OPT_DOSEARCHACTIONS ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_entry2text_search" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( tmpllist != NULL ) {
--- /dev/null
+##
+## Makefile for gopher clients
+##
+PROGRAMS= go500gw go500
+
+SRCS= go500.c go500gw.c
+XSRCS= gwversion.c goversion.c
+GOOBJS = go500.o
+GWOBJS = go500gw.o
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldap -llber -llutil
+XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
+
+go500 : goversion.o
+ $(LTLINK) -o $@ $(GOOBJS) goversion.o $(LIBS)
+
+go500gw : gwversion.o
+ $(LTLINK) -o $@ $(GWOBJS) gwversion.o $(LIBS)
+
+goversion.c: ${GOOBJS} $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) go500 > $@
+
+gwversion.c: ${GWOBJS} $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) go500gw > $@
+
+install-local: $(PROGRAMS) go500gw.help FORCE
+ -$(MKDIR) $(libexecdir) $(datadir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 go500 $(libexecdir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 go500gw $(libexecdir)
+ -$(MV) $(datadir)/go500gw.help $(datadir)/go500gw.help-
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/go500gw.help $(datadir)
go500gw A more general gopher to X.500 gateway
-Both programs use the LDAP protocol to talk to X.500. If you did not
-get this software with the U-M LDAP software distribution, you will
-need to have the LDAP libraries on hand to be able to make this software.
-The LDAP distribution is available for anonymous ftp from the host
-terminator.rs.itd.umich.edu in the x500/ directory.
+Both programs use the LDAP protocol to talk to X.500.
What you are trying to set up looks like this:
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/syslog.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#include <ac/setproctitle.h>
+
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <syslog.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
-#include <sys/wait.h>
-#ifdef aix
-#include <sys/select.h>
-#endif /* aix */
-#include <signal.h>
-#include "portable.h"
-#include "ldapconfig.h"
-#include "lber.h"
-#include "ldap.h"
-#include "disptmpl.h"
+#endif
+
+#include <ldap.h>
+#include <disptmpl.h>
+
+#include "ldap_defaults.h"
+
+#define ldap_debug debug
+#include "ldap_log.h"
+
+#include "lutil.h"
-#ifdef USE_SYSCONF
-#include <unistd.h>
-#endif /* USE_SYSCONF */
int debug;
int dosyslog;
+int ldap_syslog;
+int ldap_syslog_level;
int inetd;
int dtblsize;
-char *ldaphost = LDAPHOST;
-char *base = GO500_BASE;
+char *ldaphost = NULL;
+char *base = NULL;
int rdncount = GO500_RDNCOUNT;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
char myhost[MAXHOSTNAMELEN];
int myport;
-static set_socket();
-static SIG_FN wait4child();
-static do_queries();
-static do_error();
-static do_search();
-static do_read();
-extern int strcasecmp();
+static void usage ( char *name );
+static int set_socket (int port);
+static RETSIGTYPE wait4child(int sig);
+static void do_queries (int s);
+static void do_error (FILE *fp, char *s);
+static void do_search (LDAP *ld, FILE *fp, char *buf);
+static void do_read (LDAP *ld, FILE *fp, char *dn);
-static usage( name )
-char *name;
+static void
+usage( char *name )
{
fprintf( stderr, "usage: %s [-d debuglevel] [-f filterfile] [-t templatefile]\r\n\t[-a] [-l] [-p port] [-x ldaphost] [-b searchbase] [-c rdncount]\r\n", name );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
-main (argc, argv)
-int argc;
-char **argv;
+int
+main( int argc, char **argv )
{
int s, ns, rc;
int port = -1;
fd_set readfds;
struct hostent *hp;
struct sockaddr_in from;
- int fromlen;
- SIG_FN wait4child();
- extern char *optarg;
- extern char **Argv;
- extern int Argc;
+ socklen_t fromlen;
+#if defined( LDAP_PROCTITLE ) && !defined( HAVE_SETPROCTITLE )
/* for setproctitle */
- Argv = argv;
- Argc = argc;
+ Argv = argv;
+ Argc = argc;
+#endif
while ( (i = getopt( argc, argv, "b:d:f:lp:c:t:x:I" )) != EOF ) {
switch( i ) {
break;
case 'd': /* debug level */
- debug = atoi( optarg );
+ debug |= atoi( optarg );
break;
case 'f': /* ldap filter file */
if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost) )
== -1 ) {
perror( "gethostname" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
#endif
-#ifdef USE_SYSCONF
+#ifdef HAVE_SYSCONF
dtblsize = sysconf( _SC_OPEN_MAX );
-#else /* USE_SYSCONF */
+#elif HAVE_GETDTABLESIZE
dtblsize = getdtablesize();
-#endif /* USE_SYSCONF */
+#else
+ dtblsize = FD_SETSIZE;
+#endif
+
+#ifdef FD_SETSIZE
+ if (dtblsize > FD_SETSIZE) {
+ dtblsize = FD_SETSIZE;
+ }
+#endif /* FD_SETSIZE*/
/* detach if stderr is redirected or no debugging */
if ( inetd == 0 )
- (void) detach( debug );
+ lutil_detach( debug && !isatty( 1 ), 1 );
if ( (myname = strrchr( argv[0], '/' )) == NULL )
myname = strdup( argv[0] );
else
myname = strdup( myname + 1 );
+ if ( debug ) {
+ ber_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
+ ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
+ }
+
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+
if ( dosyslog ) {
#ifdef LOG_LOCAL3
openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 );
s = set_socket( port );
/* arrange to reap children */
- (void) signal( SIGCHLD, (void *) wait4child );
+ (void) SIGNAL( SIGCHLD, wait4child );
} else {
myport = GO500_PORT;
inet_ntoa( from.sin_addr ) );
}
+#ifdef LDAP_PROCTITLE
setproctitle( hp == NULL ? inet_ntoa( from.sin_addr ) :
hp->h_name );
+#endif
}
do_queries( 0 );
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
for ( ;; ) {
if ( (ns = accept( s, (struct sockaddr *) &from, &fromlen ))
== -1 ) {
if ( debug ) perror( "accept" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
switch( pid = fork() ) {
case 0: /* child */
- close( s );
+ tcp_close( s );
do_queries( ns );
break;
break;
default: /* parent */
- close( ns );
+ tcp_close( ns );
if ( debug )
fprintf( stderr, "forked child %d\n", pid );
break;
/* NOT REACHED */
}
-static
-set_socket( port )
-int port;
+static int
+set_socket( int port )
{
int s, one;
struct sockaddr_in addr;
if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
perror( "socket" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
+#ifdef SO_REUSEADDR
/* set option so clients can't keep us from coming back up */
- one = 1;
+ one = 1;
if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
sizeof(one) ) < 0 ) {
perror( "setsockopt" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
+#endif
+#ifdef SO_KEEPALIVE
+ /* enable keep alives */
+ one = 1;
+ if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
+ sizeof(one) ) < 0 ) {
+ perror( "setsockopt" );
+ exit( EXIT_FAILURE );
+ }
+#endif
/* bind to a name */
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons( port );
if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
perror( "bind" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/* listen for connections */
if ( listen( s, 5 ) == -1 ) {
perror( "listen" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( debug ) printf("tcp socket allocated, bound, and listening\n");
return( s );
}
-static SIG_FN
-wait4child()
+static RETSIGTYPE
+wait4child( int sig )
{
+#ifndef HAVE_WAITPID
WAITSTATUSTYPE status;
+#endif
if ( debug ) printf( "parent: catching child status\n" );
-#ifdef USE_WAITPID
- while (waitpid ((pid_t) -1, 0, WAIT_FLAGS) > 0)
-#else /* USE_WAITPID */
- while ( wait3( &status, WAIT_FLAGS, 0 ) > 0 )
-#endif /* USE_WAITPID */
- ; /* NULL */
-
- (void) signal( SIGCHLD, (void *) wait4child );
+
+#ifdef HAVE_WAITPID
+ while (waitpid ((pid_t) -1, (int *) NULL, WAIT_FLAGS) > 0)
+ ; /* NULL */
+#else
+ while ( wait4((pid_t) -1, &status, WAIT_FLAGS, 0 ) > 0 )
+ ; /* NULL */
+#endif
+
+ (void) SIGNAL( SIGCHLD, wait4child );
}
-static
-do_queries( s )
-int s;
+static void
+do_queries( int s )
{
char buf[1024], *query;
int len;
LDAP *ld;
if ( (fp = fdopen( s, "a+")) == NULL ) {
- exit( 1 );
+ exit( EXIT_FAILURE );
}
timeout.tv_sec = GO500_TIMEOUT;
FD_SET( fileno( fp ), &readfds );
if ( (rc = select( dtblsize, &readfds, 0, 0, &timeout )) <= 0 )
- exit( 1 );
+ exit( EXIT_FAILURE );
if ( fgets( buf, sizeof(buf), fp ) == NULL )
- exit( 1 );
+ exit( EXIT_FAILURE );
len = strlen( buf );
if ( debug ) {
fprintf( stderr, "got %d bytes\n", len );
#ifdef LDAP_DEBUG
- lber_bprint( buf, len );
+ ber_bprint( buf, len );
#endif
}
query = buf;
/* strip off leading white space */
- while ( isspace( *query )) {
+ while ( isspace( (unsigned char) *query )) {
++query;
--len;
}
rewind(fp);
- if ( *query != '~' && *query != '@' ) {
- if ( (ld = ldap_open( ldaphost, LDAP_PORT )) == NULL ) {
- fprintf(fp,
- "0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
- LDAP_SERVER_DOWN, myhost, myport );
- fprintf( fp, ".\r\n" );
- rewind(fp);
- exit( 1 );
- }
+ if ( *query == '~' || *query == '@' ) {
+ ld = NULL;
+ } else if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) {
+ fprintf(fp,
+ "0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
+ LDAP_SERVER_DOWN, myhost, myport );
+ fprintf( fp, ".\r\n" );
+ rewind(fp);
+ exit( EXIT_FAILURE );
+ } else {
+ int deref = GO500_DEREF;
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
- ld->ld_deref = GO500_DEREF;
- if ( (rc = ldap_simple_bind_s( ld, GO500_BINDDN, NULL ))
- != LDAP_SUCCESS ) {
+ rc = ldap_simple_bind_s( ld, NULL, NULL );
+ if ( rc != LDAP_SUCCESS ) {
fprintf(fp,
"0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
rc, myhost, myport );
fprintf( fp, ".\r\n" );
rewind(fp);
- exit( 1 );
+ exit( EXIT_FAILURE );
}
}
fprintf( fp, ".\r\n" );
rewind(fp);
- ldap_unbind( ld );
- exit( 1 );
+ if ( ld != NULL) {
+ ldap_unbind( ld );
+ }
+
+ exit( EXIT_FAILURE );
/* NOT REACHED */
}
-static
-do_error( fp, s )
-FILE *fp;
-char *s;
+static void
+do_error( FILE *fp, char *s )
{
int code;
fprintf( fp, ".\r\n" );
}
-static
-do_search( ld, fp, buf )
-LDAP *ld;
-FILE *fp;
-char *buf;
+static void
+do_search( LDAP *ld, FILE *fp, char *buf )
{
char *dn, *rdn;
char **title;
if ( (filtd = ldap_init_getfilter( filterfile )) == NULL ) {
fprintf( stderr, "Cannot open filter file (%s)\n",
filterfile );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
tv.tv_sec = GO500_TIMEOUT;
}
static int
-entry2textwrite( void *fp, char *buf, int len )
+entry2textwrite( void *fp, char *buf, ber_len_t len )
{
- return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
+ return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
}
-static
-do_read( ld, fp, dn )
-LDAP *ld;
-FILE *fp;
-char *dn;
+static void
+do_read( LDAP *ld, FILE *fp, char *dn )
{
static struct ldap_disptmpl *tmpllist;
entry2textwrite, (void *) fp, "\r\n", rdncount,
LDAP_DISP_OPT_DOSEARCHACTIONS ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_entry2text_search" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( tmpllist != NULL ) {
* is provided ``as is'' without express or implied warranty.
*/
-#include "lber.h"
-#include "ldap.h"
-#include "disptmpl.h"
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/syslog.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#include <ac/setproctitle.h>
+
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <syslog.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
-#include <sys/wait.h>
-#include <signal.h>
-#ifdef aix
-#include <sys/select.h>
-#endif /* aix */
-#include "portable.h"
-#include "ldapconfig.h"
+#endif
+
+
+#include <ldap.h>
+#include <disptmpl.h>
+
+#define ldap_debug debug
+#include "ldap_log.h"
+
+#include "lutil.h"
-#ifdef USE_SYSCONF
-#include <unistd.h>
-#endif /* USE_SYSCONF */
+
+#include "ldap_defaults.h"
int debug;
+int ldap_syslog;
+int ldap_syslog_level;
int dosyslog;
int inetd;
int dtblsize;
-char *ldaphost = LDAPHOST;
-int ldapport = LDAP_PORT;
+char *ldaphost = NULL;
+int ldapport = 0;
int searchaliases = 1;
char *helpfile = GO500GW_HELPFILE;
char *filterfile = FILTERFILE;
char *friendlyfile = FRIENDLYFILE;
int rdncount = GO500GW_RDNCOUNT;
-static set_socket();
-static SIG_FN wait4child();
-static do_queries();
-static do_menu();
-static do_list();
-static do_search();
-static do_read();
-static do_help();
-static do_sizelimit();
-static do_error();
-extern int strcasecmp();
+static void usage ( char *name );
+static int set_socket (int port);
+static RETSIGTYPE wait4child(int sig);
+static void do_queries (int s);
+static char *pick_oc ( char **oclist );
+static int isnonleaf ( LDAP *ld, char **oclist, char *dn );
+static void do_menu (LDAP *ld, FILE *fp, char *dn);
+static void do_list (LDAP *ld, FILE *fp, char *dn);
+static int isoc ( char **ocl, char *oc );
+static int make_scope ( LDAP *ld, char *dn );
+static void do_search (LDAP *ld, FILE *fp, char *query);
+static int entry2textwrite( void *fp, char *buf, ber_len_t len );
+static void do_read (LDAP *ld, FILE *fp, char *dn);
+static void do_help (FILE *op);
+static void do_sizelimit(FILE *fp, char type);
+static void do_error (FILE *fp, char *s);
char myhost[MAXHOSTNAMELEN];
int myport = GO500GW_PORT;
-static usage( name )
-char *name;
+static void
+usage( char *name )
{
fprintf( stderr, "usage: %s [-d debuglevel] [-I] [-p port] [-P ldapport] [-l]\r\n\t[-x ldaphost] [-a] [-h helpfile] [-f filterfile] [-t templatefile] [-c rdncount]\r\n", name );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
-main (argc, argv)
-int argc;
-char **argv;
+int
+main (int argc, char **argv )
{
int s, ns, rc;
int port = -1;
fd_set readfds;
struct hostent *hp;
struct sockaddr_in from;
- int fromlen;
- SIG_FN wait4child();
- extern char *optarg;
- extern char **Argv;
- extern int Argc;
+ socklen_t fromlen;
+#if defined( LDAP_PROCTITLE ) && !defined( HAVE_SETPROCTITLE )
/* for setproctitle */
- Argv = argv;
- Argc = argc;
+ Argv = argv;
+ Argc = argc;
+#endif
while ( (i = getopt( argc, argv, "P:ad:f:h:lp:t:x:Ic:" )) != EOF ) {
switch( i ) {
break;
case 'd': /* debugging level */
- debug = atoi( optarg );
-#ifdef LDAP_DEBUG
- ldap_debug = debug;
-#else
- fprintf( stderr, "warning: ldap debugging requires LDAP_DEBUG\n" );
-#endif
+ debug |= atoi( optarg );
break;
case 'f': /* ldap filter file */
}
}
-#ifdef USE_SYSCONF
+#ifdef HAVE_SYSCONF
dtblsize = sysconf( _SC_OPEN_MAX );
-#else /* USE_SYSCONF */
+#elif HAVE_GETDTABLESIZE
dtblsize = getdtablesize();
-#endif /* USE_SYSCONF */
+#else
+ dtblsize = FD_SETSIZE;
+#endif
+
+#ifdef FD_SETSIZE
+ if ( dtblsize > FD_SETSIZE ) {
+ dtblsize = FD_SETSIZE;
+ }
+#endif /* FD_SETSIZE*/
+
+
#ifdef GO500GW_HOSTNAME
strcpy( myhost, GO500GW_HOSTNAME );
if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost) )
== -1 ) {
perror( "gethostname" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
#endif
/* detach if stderr is redirected or no debugging */
if ( inetd == 0 )
- (void) detach( debug );
+ lutil_detach( debug && !isatty( 1 ), 1 );
if ( (myname = strrchr( argv[0], '/' )) == NULL )
myname = strdup( argv[0] );
else
myname = strdup( myname + 1 );
+ if ( debug ) {
+ ber_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
+ ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
+ }
+
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+
if ( dosyslog ) {
#ifdef LOG_LOCAL3
openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 );
s = set_socket( port );
/* arrange to reap children */
- (void) signal( SIGCHLD, (void *) wait4child );
+ (void) SIGNAL( SIGCHLD, wait4child );
}
if ( inetd ) {
inet_ntoa( from.sin_addr ) );
}
+#ifdef LDAP_PROCTITLE
setproctitle( hp == NULL ? inet_ntoa( from.sin_addr ) :
hp->h_name );
+#endif
}
do_queries( 0 );
- close( 0 );
+ tcp_close( 0 );
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
for ( ;; ) {
if ( (ns = accept( s, (struct sockaddr *) &from, &fromlen ))
== -1 ) {
if ( debug ) perror( "accept" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
switch( pid = fork() ) {
case 0: /* child */
- close( s );
+ tcp_close( s );
do_queries( ns );
break;
break;
default: /* parent */
- close( ns );
+ tcp_close( ns );
if ( debug )
fprintf( stderr, "forked child %d\n", pid );
break;
/* NOT REACHED */
}
-static set_socket( port )
-int port;
+static int
+set_socket( int port )
{
int s, one;
struct sockaddr_in addr;
if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
perror( "socket" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
+#ifdef SO_REUSEADDR
/* set option so clients can't keep us from coming back up */
- one = 1;
+ one = 1;
if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
sizeof(one) ) < 0 ) {
perror( "setsockopt" );
- exit( 1 );
+ exit( EXIT_FAILURE );
+ }
+#endif
+#ifdef SO_KEEPALIVE
+ /* enable keep alives */
+ one = 1;
+ if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
+ sizeof(one) ) < 0 ) {
+ perror( "setsockopt" );
+ exit( EXIT_FAILURE );
}
+#endif
/* bind to a name */
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons( port );
if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
perror( "bind" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/* listen for connections */
if ( listen( s, 5 ) == -1 ) {
perror( "listen" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( debug )
return( s );
}
-static SIG_FN
-wait4child()
+static RETSIGTYPE
+wait4child( int sig )
{
- WAITSTATUSTYPE status;
+#ifndef HAVE_WAITPID
+ WAITSTATUSTYPE status;
+#endif
- if ( debug ) printf( "parent: catching child status\n" );
-#ifdef USE_WAITPID
- while (waitpid ((pid_t) -1, 0, WAIT_FLAGS) > 0)
-#else /* USE_WAITPID */
- while ( wait3( &status, WAIT_FLAGS, 0 ) > 0 )
-#endif /* USE_WAITPID */
- ; /* NULL */
+ if ( debug ) printf( "parent: catching child status\n" );
+
+#ifdef HAVE_WAITPID
+ while (waitpid ((pid_t) -1, (int *) NULL, WAIT_FLAGS) > 0)
+ ; /* NULL */
+#else
+ while (wait4( (pid_t) -1, &status, WAIT_FLAGS, 0 ) > 0 )
+ ; /* NULL */
+#endif
- (void) signal( SIGCHLD, (void *) wait4child );
+ (void) SIGNAL( SIGCHLD, wait4child );
}
-static do_queries( s )
-int s;
+static void
+do_queries( int s )
{
char buf[1024], *query;
int len;
FILE *fp;
int rc;
+ int deref;
struct timeval timeout;
fd_set readfds;
LDAP *ld;
if ( (fp = fdopen( s, "a+")) == NULL ) {
perror( "fdopen" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
timeout.tv_sec = GO500GW_TIMEOUT;
FD_SET( fileno( fp ), &readfds );
if ( (rc = select( dtblsize, &readfds, 0, 0, &timeout )) <= 0 )
- exit( 1 );
+ exit( EXIT_FAILURE );
if ( fgets( buf, sizeof(buf), fp ) == NULL )
- exit( 1 );
+ exit( EXIT_FAILURE );
len = strlen( buf );
if ( debug ) {
fprintf( stderr, "got %d bytes\n", len );
#ifdef LDAP_DEBUG
- lber_bprint( buf, len );
+ ber_bprint( buf, len );
#endif
}
query = buf;
/* strip off leading white space */
- while ( isspace( *query )) {
+ while ( isspace( (unsigned char) *query )) {
++query;
--len;
}
fprintf( fp, ".\r\n" );
rewind(fp);
- exit( 0 );
+ exit( EXIT_SUCCESS );
/* NOT REACHED */
}
- if ( (ld = ldap_open( ldaphost, ldapport )) == NULL ) {
- if ( debug ) perror( "ldap_open" );
+ if ( (ld = ldap_init( ldaphost, ldapport )) == NULL ) {
+ if ( debug ) perror( "ldap_init" );
fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
LDAP_SERVER_DOWN, myhost, myport );
fprintf( fp, ".\r\n" );
rewind(fp);
- exit( 1 );
+ exit( EXIT_FAILURE );
}
- ld->ld_deref = LDAP_DEREF_ALWAYS;
+ deref = LDAP_DEREF_ALWAYS;
if ( !searchaliases )
- ld->ld_deref = LDAP_DEREF_FINDING;
+ deref = LDAP_DEREF_FINDING;
- if ( (rc = ldap_simple_bind_s( ld, GO500GW_BINDDN, NULL ))
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
+
+ if ( (rc = ldap_simple_bind_s( ld, NULL, NULL ))
!= LDAP_SUCCESS ) {
if ( debug ) ldap_perror( ld, "ldap_simple_bind_s" );
fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
rc, myhost, myport );
fprintf( fp, ".\r\n" );
rewind(fp);
- exit( 1 );
+ exit( EXIT_FAILURE );
}
switch ( *query++ ) {
break;
case 'S': /* search */
- do_search( ld, fp, query, 1 );
+ do_search( ld, fp, query );
break;
case 'M': /* X.500 menu */
fprintf( fp, ".\r\n" );
rewind(fp);
- exit( 0 );
+ exit( EXIT_SUCCESS );
/* NOT REACHED */
}
-static char *pick_oc( oclist )
-char **oclist;
+static char *
+pick_oc( char **oclist )
{
int i;
return( "unknown" );
}
-static isnonleaf( ld, oclist, dn )
-LDAP *ld;
-char **oclist;
-char *dn;
+static int
+isnonleaf( LDAP *ld, char **oclist, char *dn )
{
int i, quipuobject = 0;
struct timeval timeout;
LDAPMessage *res = NULL;
static char *attrs[] = { "objectClass", 0 };
+ int sizelimit = 1;
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
- ld->ld_sizelimit = 1;
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_ONELEVEL,
"(objectClass=*)", attrs, 0, &timeout, &res ))
== LDAP_SUCCESS || rc == LDAP_SIZELIMIT_EXCEEDED ) {
- ld->ld_sizelimit = LDAP_NO_LIMIT;
+ sizelimit = LDAP_NO_LIMIT;
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
numentries = ldap_count_entries( ld, res );
if ( res != NULL )
#endif
}
-static do_menu( ld, fp, dn )
-LDAP *ld;
-FILE *fp;
-char *dn;
+static void
+do_menu( LDAP *ld, FILE *fp, char *dn )
{
char **s;
char *rdn = NULL;
- FriendlyMap *fm = NULL;
+ LDAPFriendlyMap *fm = NULL;
if ( strcmp( dn, "" ) != 0 ) {
s = ldap_explode_dn( dn, 1 );
ldap_free_friendlymap( &fm );
}
-static do_list( ld, fp, dn )
-LDAP *ld;
-FILE *fp;
-char *dn;
+static void
+do_list( LDAP *ld, FILE *fp, char *dn )
{
int rc;
LDAPMessage *e, *res;
struct timeval timeout;
- FriendlyMap *fm = NULL;
+ LDAPFriendlyMap *fm = NULL;
static char *attrs[] = { "objectClass", 0 };
+ int deref = LDAP_DEREF_FINDING;
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
- ld->ld_deref = LDAP_DEREF_FINDING;
+
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
+
if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_ONELEVEL,
"(!(objectClass=dSA))", attrs, 0, &timeout, &res )) != LDAP_SUCCESS
&& rc != LDAP_SIZELIMIT_EXCEEDED ) {
rc, myhost, myport );
return;
}
- ld->ld_deref = LDAP_DEREF_ALWAYS;
+
+ deref = LDAP_DEREF_ALWAYS;
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
if ( ldap_count_entries( ld, res ) < 1 ) {
return;
}
}
-static isoc( ocl, oc )
-char **ocl;
-char *oc;
+static int
+isoc( char **ocl, char *oc )
{
int i;
return( 0 );
}
-static int make_scope( ld, dn )
-LDAP *ld;
-char *dn;
+static int
+make_scope( LDAP *ld, char *dn )
{
int scope;
char **oc;
return( scope );
}
-static do_search( ld, fp, query )
-LDAP *ld;
-FILE *fp;
-char *query;
+static void
+do_search( LDAP *ld, FILE *fp, char *query )
{
+ int deref;
int scope;
char *base, *filter;
char *filtertype;
if ( (filter = strchr( query, '\t' )) == NULL ) {
fprintf( fp, "3Missing filter!\r\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
*filter++ = '\0';
base = query;
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
ldap_ufn_timeout( (void *) &timeout );
- ld->ld_deref = LDAP_DEREF_FINDING;
+
+ deref = LDAP_DEREF_FINDING;
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
if ( (rc = ldap_ufn_search_s( ld, filter, attrs, 0, &res ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
#endif
if ( (scope = make_scope( ld, base )) == -1 ) {
fprintf( fp, "3Bad scope\r\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
filtertype = (scope == LDAP_SCOPE_ONELEVEL ?
"go500gw onelevel" : "go500gw subtree");
- ld->ld_deref = (scope == LDAP_SCOPE_ONELEVEL ?
+ deref = (scope == LDAP_SCOPE_ONELEVEL ?
LDAP_DEREF_FINDING : LDAP_DEREF_ALWAYS);
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
if ( (filtd = ldap_init_getfilter( filterfile )) == NULL ) {
fprintf( stderr, "Cannot open filter file (%s)\n",
filterfile );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
count = 0;
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
rc, myhost, myport );
- return( 1 );
+ return;
}
if ( (count = ldap_count_entries( ld, res )) != 0 )
break;
}
- ld->ld_deref = LDAP_DEREF_ALWAYS;
+ deref = LDAP_DEREF_ALWAYS;
+ ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
ldap_getfilter_free( filtd );
#ifdef GO500GW_UFN
}
#endif
if ( count == 0 ) {
- return( 0 );
+ return;
}
if ( count == 1 ) {
- char *dn, **s, **oc;
- int rc;
+ char *dn, **oc;
e = ldap_first_entry( ld, res );
oc = ldap_get_values( ld, e, "objectClass" );
- if ( isnonleaf( ld, oc, dn ) ) {
- dn = ldap_get_dn( ld, e );
+ dn = ldap_get_dn( ld, e );
- rc = do_menu( ld, fp, dn );
+ if ( isnonleaf( ld, oc, dn ) ) {
+ do_menu( ld, fp, dn );
free( dn );
- return( rc );
+ return;
}
+ free( dn );
ldap_value_free( oc );
}
static int
-entry2textwrite( void *fp, char *buf, int len )
+entry2textwrite( void *fp, char *buf, ber_len_t len )
{
return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
}
-static do_read( ld, fp, dn )
-LDAP *ld;
-FILE *fp;
-char *dn;
+static void
+do_read( LDAP *ld, FILE *fp, char *dn )
{
static struct ldap_disptmpl *tmpllist;
if ( ldap_entry2text_search( ld, dn, NULL, NULL, tmpllist, NULL, NULL,
entry2textwrite,(void *) fp, "\r\n", rdncount, 0 )
!= LDAP_SUCCESS ) {
+ int ld_errno = 0;
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
fprintf(fp,
- "0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
- ld->ld_errno, myhost, myport );
+ "0An error occurred (explanation)\t@%s\t%s\t%d\r\n",
+ ldap_err2string( ld_errno ), myhost, myport );
}
if ( tmpllist != NULL ) {
}
}
-static do_help( op )
-FILE *op;
+static void
+do_help( FILE *op )
{
FILE *fp;
char line[BUFSIZ];
fclose( fp );
}
-static do_sizelimit( fp, type )
-FILE *fp;
-char type;
+static void
+do_sizelimit( FILE *fp, char type )
{
if ( type == 'S' ) {
fprintf( fp, "The query you specified was not specific enough, causing a size limit\r\n" );
fprintf( fp, ".\r\n" );
}
-static do_error( fp, s )
-FILE *fp;
-char *s;
+static void
+do_error( FILE *fp, char *s )
{
int code;
be for people and are subtree in scope. What sort of search is done
depends on what you type, but a variety of things are tried.
-If you have comments, suggestions or questions about this service,
-please send mail to x500@umich.edu. -- Tim Howes 8/25/93
+We would appreciate any feedback you can provide. If you have
+problems, report them using our Issue Tracking System:
+ http://www.OpenLDAP.com/its/
+or by sending e-mail to:
+ OpenLDAP-its@OpenLDAP.org
+Additional mailing lists are available. Please see:
+ http://www.OpenLDAP.com/lists/
--- /dev/null
+PROGRAMS= mail500
+
+SRCS= main.c
+XSRCS= version.c
+OBJS= main.o
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldap -llber -llutil
+XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
+
+mail500 : version.o
+ $(LTLINK) -o $@ version.o $(OBJS) $(LIBS)
+
+version.c: ${OBJS} $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) mail500 > $@
+
+install-local: $(PROGRAMS) FORCE
+ -$(MKDIR) $(libexecdir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 mail500 $(libexecdir)
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
+ *
+ * Copyright 1998,1999 The OpenLDAP Foundation
+ * COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory
+ * of this package for details.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <memory.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <syslog.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/sysexits.h>
+#include <ac/syslog.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
-#include <sys/wait.h>
-#include <sysexits.h>
-#include "portable.h"
+#endif
+
+#include <ldap.h>
-#include "lber.h"
-#include "ldap.h"
-#include "ldapconfig.h"
+#include "ldap_defaults.h"
+
+#ifndef MAIL500_BOUNCEFROM
+#define MAIL500_BOUNCEFROM "<>"
+#endif
#define USER 0x01
#define GROUP_ERRORS 0x02
LDAP *ld;
char *vacationhost = NULL;
-char *errorsfrom = NULL;
+char *errorsfrom = MAIL500_BOUNCEFROM;
char *mailfrom = NULL;
char *host = NULL;
-char *ldaphost = LDAPHOST;
+char *ldaphost = NULL;
int hostlen = 0;
int debug;
#define E_NOOWNER 11
#define E_GROUPUNKNOWN 12
char *e_addr;
- union {
+ union e_union_u {
char *e_u_loop;
LDAPMessage *e_u_msg;
} e_union;
char *g_dn;
char *g_errorsto;
char **g_members;
+ int g_nmembers;
} Group;
typedef struct baseinfo {
- char *b_dn; /* dn to start searching at */
+ char *b_url;
+ int b_m_entries;
char b_rdnpref; /* give rdn's preference when searching? */
int b_search; /* ORed with the type of thing the address */
/* looks like (USER, GROUP_ERRORS, etc.) */
/* to see if this should be searched */
- char *b_filter[3]; /* filter to apply - name substituted for %s */
- /* (up to three of them) */
} Base;
-Base base[] =
- { "ou=People, o=University of Michigan, c=US",
- 0, USER,
- "uid=%s", "cn=%s", NULL,
- "ou=System Groups, ou=Groups, o=University of Michigan, c=US",
- 1, 0xff,
- "(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
- "ou=User Groups, ou=Groups, o=University of Michigan, c=US",
- 1, 0xff,
- "(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
- NULL
- };
-
-char *sendmailargs[] = { MAIL500_SENDMAIL, "-oMrX.500", "-odi", "-oi", "-f", NULL, NULL };
-
-static char *attrs[] = { "objectClass", "title", "postaladdress",
- "telephoneNumber", "mail", "description", "owner",
- "errorsTo", "rfc822ErrorsTo", "requestsTo",
- "rfc822RequestsTo", "joinable", "cn", "member",
- "moderator", "onVacation", "uid",
- "suppressNoEmailError", NULL };
-
-static do_address();
-static do_group();
-static do_group_members();
-static send_message();
-static send_errors();
-static do_noemail();
-static do_ambiguous();
-static add_to();
-static isgroup();
-static add_error();
-static add_group();
-static unbind_and_exit();
-static group_loop();
-static send_group();
-static has_attributes();
-static char **get_attributes_mail_dn();
-static char *canonical();
-
-main (argc, argv)
-int argc;
-char **argv;
+/*
+ * We should limit the search to objectclass=mailRecipient or
+ * objectclass=mailGroup.
+ */
+
+/*
+Base base[] = {
+ {"dc=StlInter, dc=Net",
+ 0, 0xff,
+ {"mail=%s", "mailAlternateAddress=%s", NULL}},
+ {NULL}
+};
+*/
+
+Base **base = NULL;
+
+char *sendmailargs[] = { MAIL500_SENDMAIL, "-oMrLDAP", "-odi", "-oi", "-f", NULL, NULL };
+
+typedef struct attr_semantics {
+ char *as_name;
+ int as_m_valued; /* Is multivalued? */
+ int as_final; /* If true, no further expansion is tried. */
+ int as_syntax; /* How to interpret values */
+ int as_m_entries; /* Can resolve to several entries? */
+ int as_kind; /* Recipient, sender, etc. */
+ char *as_param; /* Extra info for filters and things alike */
+} AttrSemantics;
+
+#define AS_SYNTAX_UNKNOWN 0 /* Unqualified mailbox name */
+#define AS_SYNTAX_NATIVE_MB 1 /* Unqualified mailbox name */
+#define AS_SYNTAX_RFC822 2 /* RFC822 mail address */
+#define AS_SYNTAX_HOST 3
+#define AS_SYNTAX_DN 4 /* A directory entry */
+#define AS_SYNTAX_RFC822_EXT 5
+#define AS_SYNTAX_URL 6 /* mailto: or ldap: URL */
+#define AS_SYNTAX_BOOL_FILTER 7 /* For joinable, filter in as_param */
+
+#define AS_KIND_UNKNOWN 0
+#define AS_KIND_RECIPIENT 1
+#define AS_KIND_ERRORS 2 /* For ErrorsTo and similar */
+#define AS_KIND_REQUEST 3
+#define AS_KIND_OWNER 4
+#define AS_KIND_FORWARD_TO_HOST 5 /* Expand at some other host */
+#define AS_KIND_ALLOWED_SENDER 6 /* Can send to group */
+#define AS_KIND_MODERATOR 7
+
+AttrSemantics **attr_semantics = NULL;
+
+typedef struct subst {
+ char sub_char;
+ char *sub_value;
+} Subst;
+
+char **groupclasses = NULL;
+char **def_attr = NULL;
+
+static void load_config( char *filespec );
+static void split_address( char *address, char **localpart, char **domainpart);
+static int entry_engine( LDAPMessage *e, char *dn, char *address, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr, int type );
+static void do_address( char *name, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr, int type );
+static void send_message( char **to );
+static void send_errors( Error *err, int nerr );
+static void do_noemail( FILE *fp, Error *err, int namelen );
+static void do_ambiguous( FILE *fp, Error *err, int namelen );
+static int count_values( char **list );
+static void add_to( char ***list, int *nlist, char **new );
+static void add_single_to( char ***list, char *new );
+static int isgroup( LDAPMessage *e );
+static void add_error( Error **err, int *nerr, int code, char *addr, LDAPMessage *msg );
+static void unbind_and_exit( int rc );
+static void send_group( Group *group, int ngroup );
+
+static int connect_to_x500( void );
+
+
+int
+main ( int argc, char **argv )
{
char *myname;
char **tolist;
Group *togroups;
int numto, ngroups, numerr, nargs;
int i, j;
- FILE *fp;
- extern int optind, errno;
- extern char *optarg;
+ char *conffile = NULL;
if ( (myname = strrchr( argv[0], '/' )) == NULL )
myname = strdup( argv[0] );
else
myname = strdup( myname + 1 );
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+
#ifdef LOG_MAIL
openlog( myname, OPENLOG_OPTIONS, LOG_MAIL );
#else
openlog( myname, OPENLOG_OPTIONS );
#endif
- while ( (i = getopt( argc, argv, "d:f:h:l:m:v:" )) != EOF ) {
+ while ( (i = getopt( argc, argv, "d:C:f:h:l:m:v:" )) != EOF ) {
switch( i ) {
case 'd': /* turn on debugging */
debug = atoi( optarg );
break;
+ case 'C': /* path to configuration file */
+ conffile = strdup( optarg );
+ break;
+
case 'f': /* who it's from & where errors should go */
mailfrom = strdup( optarg );
for ( j = 0; sendmailargs[j] != NULL; j++ ) {
syslog( LOG_ALERT, "required argument -m not present" );
exit( EX_TEMPFAIL );
}
- if ( host == NULL ) {
- syslog( LOG_ALERT, "required argument -h not present" );
+/* if ( host == NULL ) { */
+/* syslog( LOG_ALERT, "required argument -h not present" ); */
+/* exit( EX_TEMPFAIL ); */
+/* } */
+ if ( conffile == NULL ) {
+ syslog( LOG_ALERT, "required argument -C not present" );
exit( EX_TEMPFAIL );
}
+ load_config( conffile );
+
if ( connect_to_x500() != 0 )
exit( EX_TEMPFAIL );
for ( i = optind; i < argc; i++ ) {
char *s;
int type;
+ char *localpart, *domainpart;
+ char address[1024];
- for ( j = 0; argv[i][j] != '\0'; j++ ) {
- if ( argv[i][j] == '.' || argv[i][j] == '_' )
- argv[i][j] = ' ';
- }
+/* TBC: Make this processing optional */
+/* for ( j = 0; argv[i][j] != '\0'; j++ ) { */
+/* if ( argv[i][j] == '.' || argv[i][j] == '_' ) */
+/* argv[i][j] = ' '; */
+/* } */
type = USER;
- if ( (s = strrchr( argv[i], '-' )) != NULL ) {
+ split_address( argv[i], &localpart, &domainpart );
+ if ( (s = strrchr( localpart, '-' )) != NULL ) {
s++;
if ((strcasecmp(s, ERROR) == 0) ||
}
}
- do_address( argv[i], &tolist, &numto, &togroups, &ngroups,
+ if ( domainpart ) {
+ sprintf( address, "%s@%s", localpart, domainpart );
+ free( localpart );
+ free( domainpart );
+ } else {
+ sprintf( address, "%s@%s", localpart, domainpart );
+ free( localpart );
+ }
+ do_address( address, &tolist, &numto, &togroups, &ngroups,
&errlist, &numerr, type );
}
*/
if ( numerr > 0 && numto > nargs || ngroups > 0 ) {
- int fd;
+ FILE *fp;
char buf[BUFSIZ];
umask( 077 );
return( EX_OK );
}
-connect_to_x500()
+static char *
+get_config_line( FILE *cf, int *lineno)
+{
+ static char buf[2048];
+ int len;
+ int pos;
+ int room;
+
+ pos = 0;
+ room = sizeof( buf );
+ while ( fgets( &buf[pos], room, cf ) ) {
+ (*lineno)++;
+ if ( pos > 0 ) {
+ /* Delete whitespace at the beginning of new data */
+ if ( isspace( buf[pos] ) ) {
+ char *s, *d;
+ for ( s = buf+pos; isspace(*s); s++ )
+ ;
+ for ( d = buf+pos; *s; s++, d++ ) {
+ *d = *s;
+ }
+ *d = *s;
+ }
+ }
+ len = strlen( buf );
+ if ( buf[len-1] != '\n' ) {
+ syslog( LOG_ALERT, "Definition too long at line %d",
+ *lineno );
+ exit( EX_TEMPFAIL );
+ }
+ if ( buf[0] == '#' )
+ continue;
+ if ( strspn( buf, " \t\n" ) == len )
+ continue;
+ if ( buf[len-2] == '\\' ) {
+ pos = len - 2;
+ room = sizeof(buf) - pos;
+ continue;
+ }
+ /* We have a real line, we will exit the loop */
+ buf[len-1] = '\0';
+ return( buf );
+ }
+ return( NULL );
+}
+
+static void
+add_url ( char *url, int rdnpref, int typemask )
+{
+ Base **list_temp;
+ int size;
+ Base *b;
+
+ b = calloc(1, sizeof(Base));
+ if ( !b ) {
+ syslog( LOG_ALERT, "Out of memory" );
+ exit( EX_TEMPFAIL );
+ }
+ b->b_url = strdup( url );
+ b->b_rdnpref = rdnpref;
+ b->b_search = typemask;
+
+ if ( base == NULL ) {
+ base = calloc(2, sizeof(LDAPURLDesc *));
+ if ( !base ) {
+ syslog( LOG_ALERT, "Out of memory" );
+ exit( EX_TEMPFAIL );
+ }
+ base[0] = b;
+ } else {
+ for ( size = 0; base[size]; size++ )
+ ;
+ size += 2;
+ list_temp = realloc( base, size*sizeof(LDAPURLDesc *) );
+ if ( !list_temp ) {
+ syslog( LOG_ALERT, "Out of memory" );
+ exit( EX_TEMPFAIL );
+ }
+ base = list_temp;
+ base[size-2] = b;
+ base[size-1] = NULL;
+ }
+}
+
+static void
+add_def_attr( char *s )
+{
+ char *p, *q;
+
+ p = s;
+ while ( *p ) {
+ p += strspn( p, "\t," );
+ q = strpbrk( p, " \t," );
+ if ( q ) {
+ *q = '\0';
+ add_single_to( &def_attr, p );
+ } else {
+ add_single_to( &def_attr, p );
+ break;
+ }
+ p = q + 1;
+ }
+}
+
+static void
+add_attr_semantics( char *s )
+{
+ char *p, *q;
+ AttrSemantics *as;
+
+ as = calloc( 1, sizeof( AttrSemantics ) );
+ p = s;
+ while ( isspace ( *p ) )
+ p++;
+ q = p;
+ while ( !isspace ( *q ) && *q != '\0' )
+ q++;
+ *q = '\0';
+ as->as_name = strdup( p );
+ p = q + 1;
+
+ while ( *p ) {
+ while ( isspace ( *p ) )
+ p++;
+ q = p;
+ while ( !isspace ( *q ) && *q != '\0' )
+ q++;
+ *q = '\0';
+ if ( !strcasecmp( p, "multivalued" ) ) {
+ as->as_m_valued = 1;
+ } else if ( !strcasecmp( p, "multiple-entries" ) ) {
+ as->as_m_entries = 1;
+ } else if ( !strcasecmp( p, "final" ) ) {
+ as->as_final = 1;
+ } else if ( !strcasecmp( p, "local-native-mailbox" ) ) {
+ as->as_syntax = AS_SYNTAX_NATIVE_MB;
+ } else if ( !strcasecmp( p, "rfc822" ) ) {
+ as->as_syntax = AS_SYNTAX_RFC822;
+ } else if ( !strcasecmp( p, "rfc822-extended" ) ) {
+ as->as_syntax = AS_SYNTAX_RFC822_EXT;
+ } else if ( !strcasecmp( p, "dn" ) ) {
+ as->as_syntax = AS_SYNTAX_DN;
+ } else if ( !strcasecmp( p, "url" ) ) {
+ as->as_syntax = AS_SYNTAX_URL;
+ } else if ( !strncasecmp( p, "search-with-filter=", 19 ) ) {
+ as->as_syntax = AS_SYNTAX_BOOL_FILTER;
+ q = strchr( p, '=' );
+ if ( q ) {
+ p = q + 1;
+ while ( *q && !isspace( *q ) ) {
+ q++;
+ }
+ if ( *q ) {
+ *q = '\0';
+ as->as_param = strdup( p );
+ p = q + 1;
+ } else {
+ as->as_param = strdup( p );
+ p = q;
+ }
+ } else {
+ syslog( LOG_ALERT,
+ "Missing filter in %s", s );
+ exit( EX_TEMPFAIL );
+ }
+ } else if ( !strcasecmp( p, "host" ) ) {
+ as->as_kind = AS_SYNTAX_HOST;
+ } else if ( !strcasecmp( p, "forward-to-host" ) ) {
+ as->as_kind = AS_KIND_FORWARD_TO_HOST;
+ } else if ( !strcasecmp( p, "recipient" ) ) {
+ as->as_kind = AS_KIND_RECIPIENT;
+ } else if ( !strcasecmp( p, "errors" ) ) {
+ as->as_kind = AS_KIND_ERRORS;
+ } else if ( !strcasecmp( p, "request" ) ) {
+ as->as_kind = AS_KIND_REQUEST;
+ } else if ( !strcasecmp( p, "owner" ) ) {
+ as->as_kind = AS_KIND_OWNER;
+ } else {
+ syslog( LOG_ALERT,
+ "Unknown semantics word %s", p );
+ exit( EX_TEMPFAIL );
+ }
+ p = q + 1;
+ }
+ if ( attr_semantics == NULL ) {
+ attr_semantics = calloc(2, sizeof(AttrSemantics *));
+ if ( !attr_semantics ) {
+ syslog( LOG_ALERT, "Out of memory" );
+ exit( EX_TEMPFAIL );
+ }
+ attr_semantics[0] = as;
+ } else {
+ int size;
+ AttrSemantics **list_temp;
+ for ( size = 0; attr_semantics[size]; size++ )
+ ;
+ size += 2;
+ list_temp = realloc( attr_semantics,
+ size*sizeof(AttrSemantics *) );
+ if ( !list_temp ) {
+ syslog( LOG_ALERT, "Out of memory" );
+ exit( EX_TEMPFAIL );
+ }
+ attr_semantics = list_temp;
+ attr_semantics[size-2] = as;
+ attr_semantics[size-1] = NULL;
+ }
+}
+
+static void
+load_config( char *filespec )
{
- if ( (ld = ldap_open( ldaphost, LDAP_PORT )) == NULL ) {
- syslog( LOG_ALERT, "ldap_open failed" );
+ FILE *cf;
+ char *line;
+ int lineno = 0;
+ char *p;
+ int rdnpref;
+ int typemask;
+
+ cf = fopen( filespec, "r" );
+ if ( !cf ) {
+ perror( "Opening config file" );
+ exit( EX_TEMPFAIL );
+ }
+
+ while ( ( line = get_config_line( cf,&lineno ) ) ) {
+ p = strpbrk( line, " \t" );
+ if ( !p ) {
+ syslog( LOG_ALERT,
+ "Missing space at line %d", lineno );
+ exit( EX_TEMPFAIL );
+ }
+ if ( !strncmp( line, "search", p-line ) ) {
+ p += strspn( p, " \t" );
+ /* TBC, get these */
+ rdnpref = 0;
+ typemask = 0xFF;
+ add_url( p, rdnpref, typemask );
+ } else if ( !strncmp(line, "attribute", p-line) ) {
+ p += strspn(p, " \t");
+ add_attr_semantics( p );
+ } else if ( !strncmp(line, "default-attributes", p-line) ) {
+ p += strspn(p, " \t");
+ add_def_attr( p );
+ } else if ( !strncmp(line, "group-classes", p-line) ) {
+ p += strspn(p, " \t");
+ add_single_to( &groupclasses, p );
+ } else {
+ syslog( LOG_ALERT,
+ "Unparseable config definition at line %d",
+ lineno );
+ exit( EX_TEMPFAIL );
+ }
+ }
+ fclose( cf );
+}
+
+static int
+connect_to_x500( void )
+{
+ int opt;
+
+ if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) {
+ syslog( LOG_ALERT, "ldap_init failed" );
return( -1 );
}
- ld->ld_sizelimit = MAIL500_MAXAMBIGUOUS;
- ld->ld_deref = LDAP_DEREF_ALWAYS;
- if ( ldap_simple_bind_s( ld, MAIL500_BINDDN, NULL ) != LDAP_SUCCESS ) {
+ /* TBC: Set this only when it makes sense
+ opt = MAIL500_MAXAMBIGUOUS;
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &opt);
+ */
+ opt = LDAP_DEREF_ALWAYS;
+ ldap_set_option(ld, LDAP_OPT_DEREF, &opt);
+
+ if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
syslog( LOG_ALERT, "ldap_simple_bind_s failed" );
return( -1 );
}
return( 0 );
}
-static
-mailcmp( a, b )
- char *a;
- char *b;
+static Group *
+new_group( char *dn, Group **list, int *nlist )
{
int i;
+ Group *this_group;
- for ( i = 0; a[i] != '\0'; i++ ) {
- if ( a[i] != b[i] ) {
- switch ( a[i] ) {
- case ' ':
- case '.':
- case '_':
- if ( b[i] == ' ' || b[i] == '.' || b[i] == '_' )
- break;
- return( 1 );
-
- default:
- return( 1 );
- }
+ for ( i = 0; i < *nlist; i++ ) {
+ if ( strcmp( dn, (*list)[i].g_dn ) == 0 ) {
+ syslog( LOG_ALERT, "group loop 2 detected (%s)", dn );
+ return NULL;
}
}
- return( 0 );
+ if ( *nlist == 0 ) {
+ *list = (Group *) malloc( sizeof(Group) );
+ } else {
+ *list = (Group *) realloc( *list, (*nlist + 1) *
+ sizeof(Group) );
+ }
+
+ this_group = *list;
+
+ (*list)[*nlist].g_errorsto = NULL;
+ (*list)[*nlist].g_members = NULL;
+ (*list)[*nlist].g_nmembers = 0;
+ /* save the group's dn so we can check for loops above */
+ (*list)[*nlist].g_dn = strdup( dn );
+
+ (*nlist)++;
+
+ return( this_group );
}
-static
-do_address( name, to, nto, togroups, ngroups, err, nerr, type )
- char *name;
- char ***to;
- int *nto;
- Group **togroups;
- int *ngroups;
- Error **err;
- int *nerr;
- int type;
+static void
+split_address(
+ char *address,
+ char **localpart,
+ char **domainpart
+)
{
- int rc, b, f, match;
- LDAPMessage *e, *res;
- struct timeval timeout;
- char *dn;
- char filter[1024];
- char realfilter[1024];
- char **mail, **onvacation = NULL, **uid = NULL;
+ char *p;
- /*
- * Look up the name in X.500, add the appropriate addresses found
- * to the to list, or to the err list in case of error. Groups are
- * handled by the do_group routine, individuals are handled here.
- * When looking up name, we follow the bases hierarchy, looking
- * in base[0] first, then base[1], etc. For each base, there is
- * a set of search filters to try, in order. If something goes
- * wrong here trying to contact X.500, we exit with EX_TEMPFAIL.
- * If the b_rdnpref flag is set, then we give preference to entries
- * that matched name because it's their rdn, otherwise not.
- */
+ if ( ( p = strrchr( address, '@' ) ) == NULL ) {
+ *localpart = strdup( address );
+ *domainpart = NULL;
+ } else {
+ *localpart = malloc( p - address + 1 );
+ strncpy( *localpart, address, p - address );
+ (*localpart)[p - address] = '\0';
+ p++;
+ *domainpart = strdup( p );
+ }
+}
+
+static int
+dn_search(
+ char **dnlist,
+ char *address,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr
+)
+{
+ int rc;
+ int i;
+ int resolved = 0;
+ LDAPMessage *res, *e;
+ struct timeval timeout;
timeout.tv_sec = MAIL500_TIMEOUT;
timeout.tv_usec = 0;
- for ( b = 0, match = 0; !match && base[b].b_dn != NULL; b++ ) {
- if ( ! (base[b].b_search & type) ) {
- continue;
- }
- for ( f = 0; base[b].b_filter[f] != NULL; f++ ) {
- char *format, *p, *s, *d;
- char *argv[3];
- int argc;
+ for ( i = 0; dnlist[i]; i++ ) {
+ if ( (rc = ldap_search_st( ld, dnlist[i], LDAP_SCOPE_BASE,
+ "(objectclass=*)", def_attr, 0,
+ &timeout, &res )) != LDAP_SUCCESS ) {
+ if ( rc == LDAP_NO_SUCH_OBJECT ) {
+ add_error( err, nerr, E_BADMEMBER, dnlist[i], NULL );
+ continue;
+ } else {
+ syslog( LOG_ALERT, "member search return 0x%x", rc );
- for ( argc = 0; argc < 3; argc++ ) {
- argv[argc] = NULL;
+ unbind_and_exit( EX_TEMPFAIL );
+ }
+ } else {
+ if ( (e = ldap_first_entry( ld, res )) == NULL ) {
+ syslog( LOG_ALERT, "member search error parsing entry" );
+ unbind_and_exit( EX_TEMPFAIL );
}
+ if ( entry_engine( e, dnlist[i], address, to, nto,
+ togroups, ngroups, err, nerr,
+ USER | GROUP_MEMBERS ) ) {
+ resolved = 1;
+ }
+ }
+ }
+ return( resolved );
+}
- format = strdup( base[b].b_filter[f] );
- for ( argc = 0, p = format; *p; p++ ) {
- if ( *p == '%' ) {
- switch ( *++p ) {
- case 's': /* %s is the name */
- argv[argc] = name;
- break;
+static int
+search_ldap_url(
+ char *url,
+ Subst *substs,
+ char *address,
+ int rdnpref,
+ int multi_entry,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr,
+ int type
+)
+{
+ LDAPURLDesc *ludp;
+ char *p, *s, *d;
+ int i;
+ char filter[1024];
+ char realfilter[1024];
+ LDAPMessage *e, *res;
+ int rc;
+ char **attrlist;
+ struct timeval timeout;
+ int match;
+ int resolved = 0;
+ char *dn;
- case 'h': /* %h is the host */
- *p = 's';
- argv[argc] = host;
- break;
+ timeout.tv_sec = MAIL500_TIMEOUT;
+ timeout.tv_usec = 0;
- default:
- syslog( LOG_ALERT,
- "unknown format %c", *p );
+ rc = ldap_url_parse( url, &ludp );
+ if ( rc ) {
+ switch ( rc ) {
+ case LDAP_URL_ERR_NOTLDAP:
+ syslog( LOG_ALERT,
+ "Not an LDAP URL: %s", url );
+ break;
+ case LDAP_URL_ERR_BADENCLOSURE:
+ syslog( LOG_ALERT,
+ "Bad Enclosure in URL: %s", url );
+ break;
+ case LDAP_URL_ERR_BADURL:
+ syslog( LOG_ALERT,
+ "Bad URL: %s", url );
+ break;
+ case LDAP_URL_ERR_BADHOST:
+ syslog( LOG_ALERT,
+ "Host is invalid in URL: %s", url );
+ break;
+ case LDAP_URL_ERR_BADATTRS:
+ syslog( LOG_ALERT,
+ "Attributes are invalid in URL: %s", url );
+ break;
+ case LDAP_URL_ERR_BADSCOPE:
+ syslog( LOG_ALERT,
+ "Scope is invalid in URL: %s", url );
+ break;
+ case LDAP_URL_ERR_BADFILTER:
+ syslog( LOG_ALERT,
+ "Filter is invalid in URL: %s", url );
+ break;
+ case LDAP_URL_ERR_BADEXTS:
+ syslog( LOG_ALERT,
+ "Extensions are invalid in URL: %s", url );
+ break;
+ case LDAP_URL_ERR_MEM:
+ syslog( LOG_ALERT,
+ "Out of memory parsing URL: %s", url );
+ break;
+ case LDAP_URL_ERR_PARAM:
+ syslog( LOG_ALERT,
+ "bad parameter parsing URL: %s", url );
+ break;
+ default:
+ syslog( LOG_ALERT,
+ "Unknown error %d parsing URL: %s",
+ rc, url );
+ break;
+ }
+ add_error( err, nerr, E_BADMEMBER,
+ url, NULL );
+ return 0;
+ }
+
+ if ( substs ) {
+ for ( s = ludp->lud_filter, d = filter; *s; s++,d++ ) {
+ if ( *s == '%' ) {
+ s++;
+ if ( *s == '%' ) {
+ *d = '%';
+ continue;
+ }
+ for ( i = 0; substs[i].sub_char != '\0';
+ i++ ) {
+ if ( *s == substs[i].sub_char ) {
+ for ( p = substs[i].sub_value;
+ *p; p++,d++ ) {
+ *d = *p;
+ }
+ d--;
break;
}
-
- argc++;
}
- }
-
- /* three names ought to do... */
- sprintf( filter, format, argv[0], argv[1], argv[2] );
- free( format );
- for ( s = filter, d = realfilter; *s; s++, d++ ) {
- if ( *s == '*' ) {
- *d++ = '\\';
+ if ( substs[i].sub_char == '\0' ) {
+ syslog( LOG_ALERT,
+ "unknown format %c", *s );
}
+ } else {
*d = *s;
}
- *d = '\0';
-
- res = NULL;
- rc = ldap_search_st( ld, base[b].b_dn,
- LDAP_SCOPE_SUBTREE, realfilter, attrs, 0, &timeout,
- &res );
-
- /* some other trouble - try again later */
- if ( rc != LDAP_SUCCESS &&
- rc != LDAP_SIZELIMIT_EXCEEDED ) {
- syslog( LOG_ALERT, "return 0x%x from X.500",
- rc );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- if ( (match = ldap_count_entries( ld, res )) != 0 )
- break;
+ }
+ *d = *s;
+ } else {
+ strncpy( filter, ludp->lud_filter, sizeof( filter ) - 1 );
+ filter[ sizeof( filter ) - 1 ] = '\0';
+ }
- ldap_msgfree( res );
+ for ( s = filter, d = realfilter; *s; s++, d++ ) {
+ if ( *s == '*' ) {
+ *d++ = '\\';
}
+ *d = *s;
+ }
+ *d = '\0';
- if ( match )
- break;
+ if ( ludp->lud_attrs ) {
+ attrlist = ludp->lud_attrs;
+ } else {
+ attrlist = def_attr;
+ }
+ res = NULL;
+ /* TBC: we don't read the host, dammit */
+ rc = ldap_search_st( ld, ludp->lud_dn, ludp->lud_scope,
+ realfilter, attrlist, 0,
+ &timeout, &res );
+
+ /* some other trouble - try again later */
+ if ( rc != LDAP_SUCCESS &&
+ rc != LDAP_SIZELIMIT_EXCEEDED ) {
+ syslog( LOG_ALERT, "return 0x%x from X.500",
+ rc );
+ unbind_and_exit( EX_TEMPFAIL );
}
+ match = ldap_count_entries( ld, res );
+
/* trouble - try again later */
if ( match == -1 ) {
syslog( LOG_ALERT, "error parsing result from X.500" );
unbind_and_exit( EX_TEMPFAIL );
}
- /* no matches - bounce with user unknown */
- if ( match == 0 ) {
- if ( type == USER ) {
- add_error( err, nerr, E_USERUNKNOWN, name, NULLMSG );
- } else {
- add_error( err, nerr, E_GROUPUNKNOWN, name, NULLMSG );
+ if ( match == 1 || multi_entry ) {
+ for ( e = ldap_first_entry( ld, res ); e != NULL;
+ e = ldap_next_entry( ld, e ) ) {
+ dn = ldap_get_dn( ld, e );
+ resolved = entry_engine( e, dn, address, to, nto,
+ togroups, ngroups,
+ err, nerr, type );
+ if ( !resolved ) {
+ add_error( err, nerr, E_NOEMAIL, address, res );
+ }
}
- return;
+ return ( resolved );
}
/* more than one match - bounce with ambiguous user? */
char **xdn;
/* not giving rdn preference - bounce with ambiguous user */
- if ( base[b].b_rdnpref == 0 ) {
- add_error( err, nerr, E_AMBIGUOUS, name, res );
- return;
+ if ( rdnpref == 0 ) {
+ add_error( err, nerr, E_AMBIGUOUS, address, res );
+ return 0;
}
/*
xdn = ldap_explode_dn( dn, 1 );
/* XXX bad, but how else can we do it? XXX */
- if ( strcasecmp( xdn[0], name ) == 0 ) {
+ if ( strcasecmp( xdn[0], address ) == 0 ) {
ldap_delete_result_entry( &res, e );
ldap_add_result_entry( &tmpres, e );
}
/* nothing matched by rdn - go ahead and bounce */
if ( tmpres == NULL ) {
- add_error( err, nerr, E_AMBIGUOUS, name, res );
- return;
+ add_error( err, nerr, E_AMBIGUOUS, address, res );
+ return 0;
/* more than one matched by rdn - bounce with rdn matches */
} else if ( (match = ldap_count_entries( ld, tmpres )) > 1 ) {
- add_error( err, nerr, E_AMBIGUOUS, name, tmpres );
- return;
+ add_error( err, nerr, E_AMBIGUOUS, address, tmpres );
+ return 0;
/* trouble... */
} else if ( match < 0 ) {
/* otherwise one matched by rdn - send to it */
ldap_msgfree( res );
res = tmpres;
- }
-
- /*
- * if we get this far, it means that we found a single match for
- * name. for a user, we deliver to the mail attribute or bounce
- * with address and phone if no mail attr. for a group, we
- * deliver to all members or bounce to rfc822ErrorsTo if no members.
- */
-
- /* trouble */
- if ( (e = ldap_first_entry( ld, res )) == NULL ) {
- syslog( LOG_ALERT, "error parsing entry from X.500" );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- dn = ldap_get_dn( ld, e );
-
- if ( type == GROUP_ERRORS ) {
- /* sent to group-errors - resend to [rfc822]ErrorsTo attr */
- do_group_errors( e, dn, to, nto, err, nerr );
-
- } else if ( type == GROUP_REQUEST ) {
- /* sent to group-request - resend to [rfc822]RequestsTo attr */
- do_group_request( e, dn, to, nto, err, nerr );
-
- } else if ( type == GROUP_MEMBERS ) {
- /* sent to group-members - expand */
- do_group_members( e, dn, to, nto, togroups, ngroups, err,
- nerr );
-
- } else if ( type == GROUP_OWNER ) {
- /* sent to group-owner - resend to owner attr */
- do_group_owner( e, dn, to, nto, err, nerr );
-
- } else if ( isgroup( e ) ) {
- /*
- * sent to group - resend from [rfc822]ErrorsTo if it's there,
- * otherwise, expand the group
- */
-
- do_group( e, dn, to, nto, togroups, ngroups, err, nerr );
-
- ldap_msgfree( res );
-
- } else {
- /*
- * sent to user - mail attribute => add it to the to list,
- * otherwise bounce
- */
- if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) {
- char buf[1024];
- char *h;
- int i, j;
-
- /* try to detect simple mail loops */
- sprintf( buf, "%s@%s", name, host );
- for ( i = 0; mail[i] != NULL; i++ ) {
- /*
- * address is the same as the one we're
- * sending to - mail loop. syslog the
- * problem, bounce a message back to the
- * sender (who else?), and delete the bogus
- * addr from the list.
- */
-
- if ( (h = strchr( mail[i], '@' )) != NULL ) {
- h++;
- if ( strcasecmp( h, host ) == 0 ) {
- syslog( LOG_ALERT,
- "potential loop detected (%s)",
- mail[i] );
- }
- }
- if ( mailcmp( buf, mail[i] ) == 0 ) {
- syslog( LOG_ALERT,
- "loop detected (%s)", mail[i] );
-
- /* remove the bogus address */
- for ( j = i; mail[j] != NULL; j++ ) {
- mail[j] = mail[j+1];
- }
- }
- }
- if ( mail[0] != NULL ) {
- add_to( to, nto, mail );
- } else {
- add_error( err, nerr, E_NOEMAIL, name, res );
- }
-
- ldap_value_free( mail );
- } else {
- add_error( err, nerr, E_NOEMAIL, name, res );
+ /* trouble */
+ if ( (e = ldap_first_entry( ld, res )) == NULL ) {
+ syslog( LOG_ALERT, "error parsing entry from X.500" );
+ unbind_and_exit( EX_TEMPFAIL );
}
- /*
- * If the user is on vacation, send a copy of the mail to
- * the vacation server. The address is constructed from
- * the vacationhost (set in a command line argument) and
- * the uid (XXX this should be more general XXX).
- */
-
- if ( vacationhost != NULL && (onvacation = ldap_get_values( ld,
- e, "onVacation" )) != NULL && strcasecmp( onvacation[0],
- "TRUE" ) == 0 ) {
- char buf[1024];
- char *vaddr[2];
-
- if ( (uid = ldap_get_values( ld, e, "uid" )) != NULL ) {
- sprintf( buf, "%s@%s", uid[0], vacationhost );
-
- vaddr[0] = buf;
- vaddr[1] = NULL;
+ dn = ldap_get_dn( ld, e );
- add_to( to, nto, vaddr );
- } else {
- syslog( LOG_ALERT,
- "user without a uid on vacation (%s)",
- name );
- }
+ resolved = entry_engine( e, dn, address, to, nto,
+ togroups, ngroups,
+ err, nerr, type );
+ if ( !resolved ) {
+ add_error( err, nerr, E_NOEMAIL, address, res );
+ /* Don't free res if we passed it to add_error */
+ } else {
+ ldap_msgfree( res );
}
}
-
- if ( onvacation != NULL ) {
- ldap_value_free( onvacation );
- }
- if ( uid != NULL ) {
- ldap_value_free( uid );
- }
- free( dn );
-
- return;
+ return( resolved );
}
-static
-do_group( e, dn, to, nto, togroups, ngroups, err, nerr )
- LDAPMessage *e;
- char *dn;
- char ***to;
- int *nto;
- Group **togroups;
- int *ngroups;
- Error **err;
- int *nerr;
+static int
+url_list_search(
+ char **urllist,
+ char *address,
+ int multi_entry,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr,
+ int type
+)
{
- int i;
- char **moderator;
-
- /*
- * If this group has an rfc822ErrorsTo attribute, we need to
- * arrange for errors involving this group to go there, not
- * to the sender. Since sendmail only has the concept of a
- * single sender, we arrange for errors to go to groupname-errors,
- * which we then handle specially when (if) it comes back to us
- * by expanding to all the rfc822ErrorsTo addresses. If it has no
- * rfc822ErrorsTo attribute, we call do_group_members() to expand
- * the group.
- */
+ int i;
+ int resolved = 0;
- if ( group_loop( dn ) ) {
- return( -1 );
- }
+ for ( i = 0; urllist[i]; i++ ) {
- /*
- * check for moderated groups - if the group has a moderator
- * attribute, we check to see if the from address is one of
- * the moderator values. if so, continue on. if not, arrange
- * to send the mail to the moderator(s). need to do this before
- * we change the from below.
- */
+ if ( !strncasecmp( urllist[i], "mail:", 5 ) ) {
+ char *vals[2];
- if ( (moderator = ldap_get_values( ld, e, "moderator" )) != NULL ) {
- /* check if it came from any of the group's moderators */
- for ( i = 0; moderator[i] != NULL; i++ ) {
- if ( strcasecmp( moderator[i], mailfrom ) == 0 )
- break;
- }
+ vals[0] = urllist[i] + 5;
+ vals[1] = NULL;
+ add_to( to, nto, vals );
+ resolved = 1;
- /* not from the moderator? */
- if ( moderator[i] == NULL ) {
- add_to( to, nto, moderator );
- ldap_value_free( moderator );
+ } else if ( ldap_is_ldap_url( urllist[i] ) ) {
- return( 0 );
+ resolved = search_ldap_url( urllist[i], NULL,
+ address, 0, multi_entry,
+ to, nto, togroups, ngroups,
+ err, nerr, type );
+ } else {
+ /* Produce some sensible error here */
+ resolved = 0;
}
- /* else from the moderator - fall through and deliver it */
- }
-
- if ( has_attributes( e, "rfc822ErrorsTo", "errorsTo" ) ) {
- add_group( dn, togroups, ngroups );
-
- return( 0 );
}
-
- do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr );
-
- return( 0 );
+ return( resolved );
}
-/* ARGSUSED */
-static
-do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr )
- LDAPMessage *e;
- char *dn;
- char ***to;
- int *nto;
- Group **togroups;
- int *ngroups;
- Error **err;
- int *nerr;
-{
- int i, rc, anymembers;
- char *ndn;
- char **mail, **member, **joinable, **suppress;
- char filter[1024];
- LDAPMessage *ee, *res;
- struct timeval timeout;
-
- /*
- * if all has gone according to plan, we've already arranged for
- * errors to go to the [rfc822]ErrorsTo attributes (if they exist),
- * so all we have to do here is arrange to send to the
- * rfc822Mailbox attribute, the member attribute, and anyone who
- * has joined the group by setting memberOfGroup equal to the
- * group dn.
- */
-
- /* add members in the group itself - mail attribute */
- anymembers = 0;
- if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) {
- anymembers = 1;
- add_to( to, nto, mail );
+/*
+ * The entry engine processes an entry. Normally, each entry will resolve
+ * to one or more values that will be added to the 'to' argument. This
+ * argument needs not be the global 'to' list, it may be the g_to field
+ * in a group. Groups have no special treatment, unless they require
+ * a special sender.
+ */
- ldap_value_free( mail );
- }
+static int
+entry_engine(
+ LDAPMessage *e,
+ char *dn,
+ char *address,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr,
+ int type
+)
+{
+ char **vals;
+ int i;
+ int resolved = 0;
+ char ***current_to = to;
+ int *current_nto = nto;
+ Group *current_group = NULL;
+ char buf[1024];
+ char *localpart, *domainpart;
+ Subst substs[2];
- /* add members in the group itself - member attribute */
- if ( (member = ldap_get_values( ld, e, "member" )) != NULL ) {
- suppress = ldap_get_values( ld, e, "suppressNoEmailError" );
- anymembers = 1;
- for ( i = 0; member[i] != NULL; i++ ) {
- if ( strcasecmp( dn, member[i] ) == 0 ) {
- syslog( LOG_ALERT, "group (%s) contains itself",
- dn );
- continue;
- }
- add_member( dn, member[i], to, nto, togroups,
- ngroups, err, nerr, suppress );
- }
+ for ( i=0; attr_semantics[i] != NULL; i++ ) {
+ AttrSemantics *as = attr_semantics[i];
+ int nent;
- if ( suppress ) {
- ldap_value_free( suppress );
+ vals = ldap_get_values( ld, e, as->as_name );
+ if ( !vals || vals[0] == NULL ) {
+ continue;
}
- ldap_value_free( member );
- }
-
- /* add members who have joined by setting memberOfGroup */
- if ( (joinable = ldap_get_values( ld, e, "joinable" )) != NULL ) {
- if ( strcasecmp( joinable[0], "FALSE" ) == 0 ) {
- if ( ! anymembers ) {
- add_error( err, nerr, E_NOMEMBERS, dn,
- NULLMSG );
- }
-
- ldap_value_free( joinable );
- return;
+ nent = count_values( vals );
+ if ( nent > 1 && !as->as_m_valued ) {
+ add_error( err, nerr, E_AMBIGUOUS, address, e );
+ return( 0 );
}
- ldap_value_free( joinable );
+ switch ( as->as_kind ) {
+ case AS_KIND_RECIPIENT:
+ if ( ! ( type & ( USER | GROUP_MEMBERS ) ) )
+ break;
+ switch ( as->as_syntax ) {
+ case AS_SYNTAX_RFC822:
+ add_to( current_to, current_nto, vals );
+ resolved = 1;
+ break;
+ case AS_SYNTAX_RFC822_EXT:
+ add_to( current_to, current_nto, vals );
+ resolved = 1;
+ break;
+ case AS_SYNTAX_NATIVE_MB:
+ /* We used to concatenate mailHost if set here */
+ /*
+ * We used to send a copy to the vacation host
+ * if onVacation to uid@vacationhost
+ */
+ add_to( current_to, current_nto, vals );
+ resolved = 1;
+ break;
- sprintf( filter, "(memberOfGroup=%s)", dn );
+ case AS_SYNTAX_DN:
+ if ( dn_search( vals, address,
+ current_to, current_nto,
+ togroups, ngroups,
+ err, nerr ) ) {
+ resolved = 1;
+ }
+ break;
- timeout.tv_sec = MAIL500_TIMEOUT;
- timeout.tv_usec = 0;
+ case AS_SYNTAX_URL:
+ if ( url_list_search( vals, address,
+ as->as_m_entries,
+ current_to, current_nto,
+ togroups, ngroups,
+ err, nerr, type ) ) {
+ resolved = 1;
+ }
+ break;
- /* for each subtree to look in... */
- ld->ld_sizelimit = MAIL500_MAXGROUPMEMBERS;
- for ( i = 0; base[i].b_dn != NULL; i++ ) {
- /* find entries that have joined this group... */
- rc = ldap_search_st( ld, base[i].b_dn,
- LDAP_SCOPE_SUBTREE, filter, attrs, 0, &timeout,
- &res );
+ case AS_SYNTAX_BOOL_FILTER:
+ if ( strcasecmp( vals[0], "true" ) ) {
+ break;
+ }
+ substs[0].sub_char = 'D';
+ substs[0].sub_value = dn;
+ substs[1].sub_char = '\0';
+ substs[1].sub_value = NULL;
+ if ( url_list_search( vals, address,
+ as->as_m_entries,
+ current_to, current_nto,
+ togroups, ngroups,
+ err, nerr, type ) ) {
+ resolved = 1;
+ }
+ break;
- if ( rc == LDAP_SIZELIMIT_EXCEEDED ||
- rc == LDAP_TIMELIMIT_EXCEEDED ) {
+ default:
syslog( LOG_ALERT,
- "group search limit exceeded %d", rc );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- if ( rc != LDAP_SUCCESS ) {
- syslog( LOG_ALERT, "group search return 0x%x",
- rc );
- unbind_and_exit( EX_TEMPFAIL );
+ "Invalid syntax %d for kind %d",
+ as->as_syntax, as->as_kind );
+ break;
}
+ break;
- /* for each entry that has joined... */
- for ( ee = ldap_first_entry( ld, res ); ee != NULL;
- ee = ldap_next_entry( ld, ee ) ) {
- anymembers = 1;
- if ( isgroup( ee ) ) {
- ndn = ldap_get_dn( ld, ee );
-
- if ( do_group( e, ndn, to, nto,
- togroups, ngroups, err, nerr )
- == -1 ) {
- syslog( LOG_ALERT,
- "group loop (%s) (%s)",
- dn, ndn );
- }
-
- free( ndn );
-
- continue;
+ case AS_KIND_ERRORS:
+ /* This is a group with special processing */
+ if ( type & GROUP_ERRORS ) {
+ switch (as->as_kind) {
+ case AS_SYNTAX_RFC822:
+ add_to( current_to, current_nto, vals );
+ resolved = 1;
+ break;
+ case AS_SYNTAX_URL:
+ default:
+ syslog( LOG_ALERT,
+ "Invalid syntax %d for kind %d",
+ as->as_syntax, as->as_kind );
}
-
- /* add them to the to list */
- if ( (mail = ldap_get_values( ld, ee, "mail" ))
- != NULL ) {
- add_to( to, nto, mail );
-
- ldap_value_free( mail );
-
- /* else generate a bounce */
+ } else {
+ current_group = new_group( dn, togroups,
+ ngroups );
+ current_to = ¤t_group->g_members;
+ current_nto = ¤t_group->g_nmembers;
+ split_address( address,
+ &localpart, &domainpart );
+ if ( domainpart ) {
+ sprintf( buf, "%s-%s@%s",
+ localpart, ERRORS,
+ domainpart );
+ free( localpart );
+ free( domainpart );
} else {
- ndn = ldap_get_dn( ld, ee );
-
- add_error( err, nerr,
- E_JOINMEMBERNOEMAIL, ndn, NULLMSG );
-
- free( ndn );
+ sprintf( buf, "%s-%s@%s",
+ localpart, ERRORS,
+ host );
+ free( localpart );
}
+ current_group->g_errorsto = strdup( buf );
}
+ break;
- ldap_msgfree( res );
- }
- ld->ld_sizelimit = MAIL500_MAXAMBIGUOUS;
- }
-
- if ( ! anymembers ) {
- add_error( err, nerr, E_NOMEMBERS, dn, NULLMSG );
- }
-
- return;
-}
-
-add_member( gdn, dn, to, nto, togroups, ngroups, err, nerr, suppress )
- char *gdn;
- char *dn;
- char ***to;
- int *nto;
- Group **togroups;
- int *ngroups;
- Error **err;
- int *nerr;
- char **suppress;
-{
- char *ndn;
- char **mail;
- int i, rc;
- LDAPMessage *res, *e;
- struct timeval timeout;
-
- timeout.tv_sec = MAIL500_TIMEOUT;
- timeout.tv_usec = 0;
- if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "(objectclass=*)",
- attrs, 0, &timeout, &res )) != LDAP_SUCCESS ) {
- if ( rc == LDAP_NO_SUCH_OBJECT ) {
- add_error( err, nerr, E_BADMEMBER, dn, NULLMSG );
-
- return;
- } else {
- syslog( LOG_ALERT, "member search return 0x%x", rc );
-
- unbind_and_exit( EX_TEMPFAIL );
- }
- }
-
- if ( (e = ldap_first_entry( ld, res )) == NULL ) {
- syslog( LOG_ALERT, "member search error parsing entry" );
+ case AS_KIND_REQUEST:
+ /* This is a group with special processing */
+ if ( type & GROUP_REQUEST ) {
+ add_to( current_to, current_nto, vals );
+ resolved = 1;
+ }
+ break;
- unbind_and_exit( EX_TEMPFAIL );
- }
- ndn = ldap_get_dn( ld, e );
+ case AS_KIND_OWNER:
+ /* This is a group with special processing */
+ if ( type & GROUP_REQUEST ) {
+ add_to( current_to, current_nto, vals );
+ resolved = 1;
+ }
+ break;
- /* allow groups within groups */
- if ( isgroup( e ) ) {
- if ( do_group( e, ndn, to, nto, togroups, ngroups, err, nerr )
- == -1 ) {
- syslog( LOG_ALERT, "group loop (%s) (%s)", gdn, ndn );
+ default:
+ syslog( LOG_ALERT,
+ "Invalid kind %d", as->as_kind );
+ /* Error, TBC */
}
-
- free( ndn );
-
- return;
- }
-
- /* send to the member's mail attribute */
- if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) {
- add_to( to, nto, mail );
-
- ldap_value_free( mail );
-
- /* else generate a bounce */
- } else {
- if ( suppress == NULL || strcasecmp( suppress[0], "FALSE" )
- == 0 ) {
- add_error( err, nerr, E_MEMBERNOEMAIL, ndn, NULLMSG );
+ ldap_value_free( vals );
+ if ( as->as_final ) {
+ return( resolved );
}
}
-
- free( ndn );
-
- return;
+ return( resolved );
}
-do_group_request( e, dn, to, nto, err, nerr )
- LDAPMessage *e;
- char *dn;
- char ***to;
- int *nto;
- Error **err;
- int *nerr;
+static int
+search_bases(
+ char *filter,
+ Subst *substs,
+ char *name,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr,
+ int type
+)
{
- char **requeststo;
+ int b, resolved = 0;
- if ( (requeststo = get_attributes_mail_dn( e, "rfc822RequestsTo",
- "requestsTo" )) != NULL ) {
- add_to( to, nto, requeststo );
-
- ldap_value_free( requeststo );
- } else {
- add_error( err, nerr, E_NOREQUEST, dn, NULLMSG );
- }
+ for ( b = 0; base[b] != NULL; b++ ) {
- return;
-}
-
-do_group_errors( e, dn, to, nto, err, nerr )
- LDAPMessage *e;
- char *dn;
- char ***to;
- int *nto;
- Error **err;
- int *nerr;
-{
- char **errorsto;
-
- if ( (errorsto = get_attributes_mail_dn( e, "rfc822ErrorsTo",
- "errorsTo" )) != NULL ) {
- add_to( to, nto, errorsto );
+ if ( ! (base[b]->b_search & type) ) {
+ continue;
+ }
- ldap_value_free( errorsto );
- } else {
- add_error( err, nerr, E_NOERRORS, dn, NULLMSG );
+ resolved = search_ldap_url( base[b]->b_url, substs, name,
+ base[b]->b_rdnpref,
+ base[b]->b_m_entries,
+ to, nto, togroups, ngroups,
+ err, nerr, type );
+ if ( resolved )
+ break;
}
-
- return;
+ return( resolved );
}
-do_group_owner( e, dn, to, nto, err, nerr )
- LDAPMessage *e;
- char *dn;
- char ***to;
- int *nto;
- Error **err;
- int *nerr;
+static void
+do_address(
+ char *name,
+ char ***to,
+ int *nto,
+ Group **togroups,
+ int *ngroups,
+ Error **err,
+ int *nerr,
+ int type
+)
{
- char **owner;
+ struct timeval timeout;
+ char *localpart, *domainpart;
+ int resolved;
+ Subst substs[5];
- if ( (owner = get_attributes_mail_dn( e, "", "owner" )) != NULL ) {
- add_to( to, nto, owner );
- ldap_value_free( owner );
- } else {
- add_error( err, nerr, E_NOOWNER, dn, NULLMSG );
+ /*
+ * Look up the name in X.500, add the appropriate addresses found
+ * to the to list, or to the err list in case of error. Groups are
+ * handled by the do_group routine, individuals are handled here.
+ * When looking up name, we follow the bases hierarchy, looking
+ * in base[0] first, then base[1], etc. For each base, there is
+ * a set of search filters to try, in order. If something goes
+ * wrong here trying to contact X.500, we exit with EX_TEMPFAIL.
+ * If the b_rdnpref flag is set, then we give preference to entries
+ * that matched name because it's their rdn, otherwise not.
+ */
+
+ split_address( name, &localpart, &domainpart );
+ timeout.tv_sec = MAIL500_TIMEOUT;
+ timeout.tv_usec = 0;
+ substs[0].sub_char = 'm';
+ substs[0].sub_value = name;
+ substs[1].sub_char = 'h';
+ substs[1].sub_value = host;
+ substs[2].sub_char = 'l';
+ substs[2].sub_value = localpart;
+ substs[3].sub_char = 'd';
+ substs[3].sub_value = domainpart;
+ substs[4].sub_char = '\0';
+ substs[4].sub_value = NULL;
+
+ resolved = search_bases( NULL, substs, name,
+ to, nto, togroups, ngroups,
+ err, nerr, type );
+
+ if ( !resolved ) {
+ /* not resolved - bounce with user unknown */
+ if ( type == USER ) {
+ add_error( err, nerr, E_USERUNKNOWN, name, NULL );
+ } else {
+ add_error( err, nerr, E_GROUPUNKNOWN, name, NULL );
+ }
}
- return;
}
-static
-send_message( to )
- char **to;
+static void
+send_message( char **to )
{
int pid;
-#ifndef USE_WAITPID
+#ifndef HAVE_WAITPID
WAITSTATUSTYPE status;
#endif
}
/* parent */
- if ( pid = fork() ) {
-#ifdef USE_WAITPID
+ if ( (pid = fork()) != 0 ) {
+#ifdef HAVE_WAITPID
waitpid( pid, (int *) NULL, 0 );
#else
wait4( pid, &status, WAIT_FLAGS, 0 );
}
}
-static
-send_group( group, ngroup )
- Group *group;
- int ngroup;
+static void
+send_group( Group *group, int ngroup )
{
int i, pid;
char **argv;
int argc;
char *iargv[7];
-#ifndef USE_WAITPID
+#ifndef HAVE_WAITPID
WAITSTATUSTYPE status;
#endif
}
/* parent */
- if ( pid = fork() ) {
-#ifdef USE_WAITPID
+ if ( (pid = fork()) != 0 ) {
+#ifdef HAVE_WAITPID
waitpid( pid, (int *) NULL, 0 );
#else
wait4( pid, &status, WAIT_FLAGS, 0 );
exit( EX_TEMPFAIL );
}
}
-
- return;
}
-static
-send_errors( err, nerr )
- Error *err;
- int nerr;
+static void
+send_errors( Error *err, int nerr )
{
int pid, i, namelen;
FILE *fp;
int fd[2];
char *argv[8];
char buf[1024];
-#ifndef USE_WAITPID
+#ifndef HAVE_WAITPID
WAITSTATUSTYPE status;
#endif
+ if ( strcmp( MAIL500_BOUNCEFROM, mailfrom ) == 0 ) {
+ mailfrom = errorsfrom;
+ }
+
argv[0] = MAIL500_SENDMAIL;
argv[1] = "-oMrX.500";
argv[2] = "-odi";
argv[3] = "-oi";
argv[4] = "-f";
- argv[5] = errorsfrom;
+ argv[5] = MAIL500_BOUNCEFROM;
argv[6] = mailfrom;
argv[7] = NULL;
exit( EX_TEMPFAIL );
}
- if ( pid = fork() ) {
+ if ( (pid = fork()) != 0 ) {
if ( (fp = fdopen( fd[1], "w" )) == NULL ) {
syslog( LOG_ALERT, "cannot fdopen pipe" );
exit( EX_TEMPFAIL );
}
fclose( fp );
-#ifdef USE_WAITPID
+#ifdef HAVE_WAITPID
waitpid( pid, (int *) NULL, 0 );
#else
wait4( pid, &status, WAIT_FLAGS, 0 );
exit( EX_TEMPFAIL );
}
-
- return;
}
-static
-do_noemail( fp, err, namelen )
- FILE *fp;
- Error *err;
- int namelen;
+static void
+do_noemail( FILE *fp, Error *err, int namelen )
{
int i, last;
char *dn, *rdn;
!= NULL ) {
for ( i = 0; vals[i]; i++ ) {
last = strlen( vals[i] ) - 1;
- if ( isdigit( vals[i][last] ) ) {
+ if ( isdigit((unsigned char) vals[i][last]) ) {
rdn = strdup( vals[i] );
break;
}
for ( i = 0; vals[0][i] != '\0'; i++ ) {
if ( vals[0][i] == '$' ) {
fprintf( fp, "\n%*s ", namelen, " " );
- while ( isspace( vals[0][i+1] ) )
+ while ( isspace((unsigned char) vals[0][i+1]) )
i++;
} else {
fprintf( fp, "%c", vals[0][i] );
}
/* ARGSUSED */
-static
-do_ambiguous( fp, err, namelen )
- FILE *fp;
- Error *err;
- int namelen;
+static void
+do_ambiguous( FILE *fp, Error *err, int namelen )
{
int i, last;
char *dn, *rdn;
if ( (vals = ldap_get_values( ld, e, "cn" )) != NULL ) {
for ( i = 0; vals[i]; i++ ) {
last = strlen( vals[i] ) - 1;
- if ( isdigit( vals[i][last] ) ) {
+ if (isdigit((unsigned char) vals[i][last])) {
rdn = strdup( vals[i] );
break;
}
}
}
+ /*
if ( isgroup( e ) ) {
vals = ldap_get_values( ld, e, "description" );
} else {
vals = ldap_get_values( ld, e, "title" );
}
+ */
+ vals = ldap_get_values( ld, e, "description" );
fprintf( fp, " %-20s %s\n", rdn, vals ? vals[0] : "" );
for ( i = 1; vals && vals[i] != NULL; i++ ) {
}
}
-static
-count_values( list )
- char **list;
+static int
+count_values( char **list )
{
int i;
return( i );
}
-static
-add_to( list, nlist, new )
- char ***list;
- int *nlist;
- char **new;
+static void
+add_to( char ***list, int *nlist, char **new )
{
int i, nnew, oldnlist;
for ( i = 0; i < nnew; i++ )
(*list)[i + oldnlist] = strdup( new[i] );
(*list)[*nlist] = NULL;
+}
+
+static void
+add_single_to( char ***list, char *new )
+{
+ int nlist;
- return;
+ if ( *list == NULL ) {
+ nlist = 0;
+ *list = (char **) malloc( 2 * sizeof(char *) );
+ } else {
+ nlist = count_values( *list );
+ *list = (char **) realloc( *list,
+ ( nlist + 2 ) * sizeof(char *) );
+ }
+
+ (*list)[nlist] = strdup( new );
+ (*list)[nlist+1] = NULL;
}
-static
-isgroup( e )
- LDAPMessage *e;
+static int
+isgroup( LDAPMessage *e )
{
- int i;
+ int i, j;
char **oclist;
+ if ( !groupclasses ) {
+ return( 0 );
+ }
+
oclist = ldap_get_values( ld, e, "objectClass" );
for ( i = 0; oclist[i] != NULL; i++ ) {
- if ( strcasecmp( oclist[i], "rfc822MailGroup" ) == 0 ) {
- ldap_value_free( oclist );
- return( 1 );
+ for ( j = 0; groupclasses[j] != NULL; j++ ) {
+ if ( strcasecmp( oclist[i], groupclasses[j] ) == 0 ) {
+ ldap_value_free( oclist );
+ return( 1 );
+ }
}
}
ldap_value_free( oclist );
return( 0 );
}
-static
-add_error( err, nerr, code, addr, msg )
- Error **err;
- int *nerr;
- int code;
- char *addr;
- LDAPMessage *msg;
+static void
+add_error( Error **err, int *nerr, int code, char *addr, LDAPMessage *msg )
{
if ( *nerr == 0 ) {
*err = (Error *) malloc( sizeof(Error) );
(*err)[*nerr].e_addr = strdup( addr );
(*err)[*nerr].e_msg = msg;
(*nerr)++;
-
- return;
}
-static
-add_group( dn, list, nlist )
- char *dn;
- Group **list;
- int *nlist;
-{
- int i, namelen;
- char **ufn;
-
- for ( i = 0; i < *nlist; i++ ) {
- if ( strcmp( dn, (*list)[i].g_dn ) == 0 ) {
- syslog( LOG_ALERT, "group loop 2 detected (%s)", dn );
- return;
- }
- }
-
- ufn = ldap_explode_dn( dn, 1 );
- namelen = strlen( ufn[0] );
-
- if ( *nlist == 0 ) {
- *list = (Group *) malloc( sizeof(Group) );
- } else {
- *list = (Group *) realloc( *list, (*nlist + 1) *
- sizeof(Group) );
- }
-
- /* send errors to groupname-errors@host */
- (*list)[*nlist].g_errorsto = (char *) malloc( namelen + sizeof(ERRORS)
- + hostlen + 2 );
- sprintf( (*list)[*nlist].g_errorsto, "%s-%s@%s", ufn[0], ERRORS, host );
- (void) canonical( (*list)[*nlist].g_errorsto );
-
- /* send to groupname-members@host - make it a list for send_group */
- (*list)[*nlist].g_members = (char **) malloc( 2 * sizeof(char *) );
- (*list)[*nlist].g_members[0] = (char *) malloc( namelen +
- sizeof(MEMBERS) + hostlen + 2 );
- sprintf( (*list)[*nlist].g_members[0], "%s-%s@%s", ufn[0], MEMBERS,
- host );
- (void) canonical( (*list)[*nlist].g_members[0] );
- (*list)[*nlist].g_members[1] = NULL;
-
- /* save the group's dn so we can check for loops above */
- (*list)[*nlist].g_dn = strdup( dn );
-
- (*nlist)++;
-
- ldap_value_free( ufn );
-
- return;
-}
-
-static
-unbind_and_exit( rc )
- int rc;
+static void
+unbind_and_exit( int rc )
{
int i;
exit( rc );
}
-static char *
-canonical( s )
- char *s;
-{
- char *saves = s;
-
- for ( ; *s != '\0'; s++ ) {
- if ( *s == ' ' )
- *s = '.';
- }
-
- return( saves );
-}
-
-static
-group_loop( dn )
- char *dn;
-{
- int i;
- static char **groups;
- static int ngroups;
-
- for ( i = 0; i < ngroups; i++ ) {
- if ( strcmp( dn, groups[i] ) == 0 )
- return( 1 );
- }
-
- if ( ngroups == 0 )
- groups = (char **) malloc( sizeof(char *) );
- else
- groups = (char **) realloc( groups,
- (ngroups + 1) * sizeof(char *) );
-
- groups[ngroups++] = strdup( dn );
-
- return( 0 );
-}
-
-static
-has_attributes( e, attr1, attr2 )
- LDAPMessage *e;
- char *attr1;
- char *attr2;
-{
- char **attr;
-
- if ( (attr = ldap_get_values( ld, e, attr1 )) != NULL ) {
- ldap_value_free( attr );
- return( 1 );
- }
-
- if ( (attr = ldap_get_values( ld, e, attr2 )) != NULL ) {
- ldap_value_free( attr );
- return( 1 );
- }
-
- return( 0 );
-}
-
-static char **
-get_attributes_mail_dn( e, attr1, attr2 )
- LDAPMessage *e;
- char *attr1;
- char *attr2; /* this one is dn-valued */
-{
- LDAPMessage *ee, *res;
- char **vals, **dnlist, **mail, **grname, **graddr;
- char *dn;
- int nto = 0, i, rc;
- struct timeval timeout;
-
- dn = ldap_get_dn( ld, e );
-
- vals = ldap_get_values( ld, e, attr1 );
- for ( nto = 0; vals != NULL && vals[nto] != NULL; nto++ )
- ; /* NULL */
-
- if ( (dnlist = ldap_get_values( ld, e, attr2 )) != NULL ) {
- timeout.tv_sec = MAIL500_TIMEOUT;
- timeout.tv_usec = 0;
- for ( i = 0; dnlist[i] != NULL; i++ ) {
- if ( (rc = ldap_search_st( ld, dnlist[i],
- LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0,
- &timeout, &res )) != LDAP_SUCCESS ) {
- if ( rc != LDAP_NO_SUCH_OBJECT ) {
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- syslog( LOG_ALERT, "bad (%s) dn (%s)", attr2,
- dnlist[i] );
- continue;
- }
- if ( (ee = ldap_first_entry( ld, res )) == NULL ) {
- syslog( LOG_ALERT, "error parsing x500 entry" );
- continue;
- }
-
- if ( isgroup(ee) ) {
- char *graddr[2];
-
- grname = ldap_explode_dn( dnlist[i], 1 );
-
- /* groupname + host + @ + null */
- graddr[0] = (char *) malloc( strlen( grname[0] )
- + strlen( host ) + 2 );
- graddr[1] = NULL;
- sprintf( graddr[0], "%s@%s", grname[0], host);
- (void) canonical( graddr[0] );
-
- add_to( &vals, &nto, graddr );
-
- free( graddr[0] );
- ldap_value_free( grname );
- } else if ( (mail = ldap_get_values( ld, ee, "mail" ))
- != NULL ) {
- add_to( &vals, &nto, mail );
-
- ldap_value_free( mail );
- }
-
- ldap_msgfree( res );
- }
- }
-
- return( vals );
-}
--- /dev/null
+PROGRAMS= rcpt500
+SRCS= main.c cmds.c help.c query.c
+XSRCS= version.c
+OBJS= main.o cmds.o help.o query.o
+HDRS= rcpt500.h
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldap -llber -llutil
+XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
+
+rcpt500 : version.o
+ $(LTLINK) -o $@ version.o $(OBJS) $(LIBS)
+
+version.c: ${OBJS} $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) rcpt500 > $@
+
+install-local: $(PROGRAMS) rcpt500.help FORCE
+ -$(MKDIR) $(libexecdir) $(datadir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 rcpt500 $(libexecdir)
+ -$(MV) $(datadir)/rcpt500.help $(datadir)/rcpt500.help-
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/rcpt500.help $(datadir)
.
Reply from rcpt500:
- Received: from totalrecall.rs.itd.umich.edu by terminator.cc.umich.edu
- id AA26151; Wed, 16 Sep 92 11:26:18 -0400
- Received: by umich.edu (5.65/2.2)
- id AA12041; Wed, 16 Sep 92 11:26:17 -0400
- Message-Id: <9209161526.AA12041@umich.edu>
- Date: Wed, 16 Sep 92 11:26:17 -0400
+ Message-Id: <199209161526.AA12041@umich.edu>
+ Date: Wed, 16 Sep 1992 11:26:17 -0400
From: "X.500 Query Program" <X500-Query@umich.edu>
Subject: Re: find tim howes
- In-Reply-To: Your message of "Wed, 16 Sep 92 11:26:12 -0400"
- <9209161526.AA26144@terminator.cc.umich.edu>
+ In-Reply-To: Your message of "Wed, 16 Sep 1992 11:26:12 -0400"
+ <199209161526.AA26144@terminator.cc.umich.edu>
To: "Mark Smith" <mcs@terminator.cc.umich.edu>
One exact match was found for 'tim howes':
ldaptemplates.conf files.
-SUPPORT
+FEEDBACK / PROBLEM REPORTS / DISCUSSIONS
The software is provided as is without any express or implied
- warranty, but there is a bug reporting mail address which is
- responded to on a best-effort basis:
+ warranty, but you can report problems using our Issue Tracking
+ System:
- ldap-support@terminator.cc.umich.edu
+ http://www.OpenLDAP.com/its/
+ or by sending e-mail to:
-BUG REPORTING
+ OpenLDAP-its@OpenLDAP.org
- Bug reports should be sent to bug-ldap@terminator.cc.umich.edu.
+ Additional mailing lists are available. Please see:
-
-README Last updated 10 November 1994 Mark Smith
+ http://www.OpenLDAP.com/lists/
* All Rights Reserved
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <string.h>
-#include <ctype.h>
-#include "portable.h"
-#include "ldapconfig.h"
-#include "rcpt500.h"
+#include <ac/stdlib.h>
-#ifdef ultrix
-extern char *strdup();
-#endif
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/syslog.h>
+#include <ac/unistd.h>
+
+#include "ldap_defaults.h"
+#include "rcpt500.h"
int dosyslog = 0;
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
int do_cldap = 0;
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
+
int derefaliases = 1;
int sizelimit = RCPT500_SIZELIMIT;
int rdncount = RCPT500_RDNCOUNT;
int ldapport = 0;
-char *ldaphost = LDAPHOST;
-char *searchbase = RCPT500_BASE;
-char *dapuser = RCPT500_BINDDN;
+char *ldaphost = NULL;
+char *searchbase = NULL;
+char *dapuser = NULL;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
-char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
-
+static char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
/*
* functions
*/
-int read_msg();
-char *read_hdr();
-int send_reply();
+static int read_msg(FILE *fp, struct msginfo *msgp);
+static char *read_hdr(FILE *fp, int off, char *buf, int MAXSIZEe, char **ln_p);
+static int send_reply(struct msginfo *msgp, char *body);
+static int find_command(char *text, char **argp);
/*
* main is invoked by sendmail via the alias file
* the entire incoming message gets piped to our standard input
*/
-main( argc, argv )
- int argc;
- char **argv;
+int
+main( int argc, char **argv )
{
char *prog, *usage = "%s [-l] [-U] [-h ldaphost] [-p ldapport] [-b searchbase] [-a] [-z sizelimit] [-u dapuser] [-f filterfile] [-t templatefile] [-c rdncount]\n";
struct msginfo msg;
int c, errflg;
- char *replytext;
-
- extern int optind;
- extern char *optarg;
*reply = '\0';
dosyslog = 1;
break;
case 'U':
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
do_cldap = 1;
-#else /* CLDAP */
- fprintf( stderr, "Compile with -DCLDAP for -U support\n" );
-#endif /* CLDAP */
+#else /* LDAP_CONNECTIONLESS */
+ fprintf( stderr,
+ "Compile with -DLDAP_CONNECTIONLESS for -U support\n" );
+#endif /* LDAP_CONNECTIONLESS */
break;
case 'b':
searchbase = optarg;
}
if ( errflg || optind < argc ) {
fprintf( stderr, usage, prog );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+
if ( dosyslog ) {
/*
* if syslogging requested, initialize
}
-int
-read_msg( fp, msgp )
- FILE *fp;
- struct msginfo *msgp;
+static int
+read_msg( FILE *fp, struct msginfo *msgp )
{
char buf[ MAXSIZE ], *line;
int command = -1;
}
-char *
-read_hdr( fp, offset, buf, MAXSIZEe, linep )
- FILE *fp;
- int offset;
- char *buf;
- int MAXSIZEe;
- char **linep;
+static char *
+read_hdr( FILE *fp, int offset, char *buf, int MAXSIZEe, char **linep )
{
char *hdr;
- for ( hdr = buf + offset; isspace( *hdr ); ++hdr ) {
+ for ( hdr = buf + offset; isspace( (unsigned char) *hdr ); ++hdr ) {
;
}
if (( hdr = strdup( hdr )) == NULL ) {
if ( dosyslog ) {
syslog( LOG_ERR, "strdup: %m" );
}
- exit( 1 );
+ exit( EXIT_FAILURE );
}
while ( 1 ) {
*linep = fgets( buf, MAXSIZE, fp );
buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
- if ( *linep == NULL || !isspace( **linep )) {
+ if ( *linep == NULL || !isspace( (unsigned char) **linep )) {
break;
}
if (( hdr = realloc( hdr, strlen( hdr ) +
if ( dosyslog ) {
syslog( LOG_ERR, "realloc: %m" );
}
- exit( 1 );
+ exit( EXIT_FAILURE );
}
strcat( hdr, "\n" );
strcat( hdr, *linep );
}
-int
-send_reply( msgp, body )
- struct msginfo *msgp;
- char *body;
+static int
+send_reply( struct msginfo *msgp, char *body )
{
char buf[ MAXSIZE ];
FILE *cmdpipe;
}
-int
-find_command( text, argp )
- char *text;
- char **argp;
+static int
+find_command( char *text, char **argp )
{
int i;
char *s, *p;
p = text;
for ( s = argbuf; *p != '\0'; ++p ) {
- *s++ = tolower( *p );
+ *s++ = TOLOWER( (unsigned char) *p );
}
*s = '\0';
for ( i = 0; cmds[ i ].cmd_text != NULL; ++i ) {
if (( s = strstr( argbuf, cmds[ i ].cmd_text )) != NULL
- && isspace( *(s + strlen( cmds[ i ].cmd_text )))) {
+ && isspace( (unsigned char) s[ strlen( cmds[ i ].cmd_text ) ] )) {
strcpy( argbuf, text + (s - argbuf) + strlen( cmds[ i ].cmd_text ));
*argp = argbuf;
- while ( isspace( **argp )) {
+ while ( isspace( (unsigned char) **argp )) {
++(*argp);
}
return( i );
* All Rights Reserved
*/
+#include "portable.h"
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/syslog.h>
+#include <ac/time.h>
+
#include <stdio.h>
-#include <syslog.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include "lber.h"
-#include "ldap.h"
-#include "portable.h"
-#include "ldapconfig.h"
-#include "disptmpl.h"
-#include "rcpt500.h"
+#include <ldap.h>
+#include <disptmpl.h>
-extern int dosyslog;
-extern int do_cldap;
-extern int rdncount;
-extern int derefaliases;
-extern int sizelimit;
-extern int ldapport;
-extern char *ldaphost;
-extern char *searchbase;
-extern char *dapuser;
-extern char *filterfile;
-extern char *templatefile;
+#include "rcpt500.h"
+#include "ldap_defaults.h"
static char buf[ MAXSIZE ];
static char *errpreface = "Your query failed: ";
-extern int strcasecmp();
-
-void close_ldap();
+static void close_ldap(LDAP *ld);
+static void append_entry_list(char *rep, char *qu, LDAP *ld, LDAPMessage *msg);
+static int append_text(void *reply, char *text, ber_len_t len);
+static int do_read (LDAP *ld, char *dn, char *rep, struct ldap_disptmpl *tmp);
+static void report_ldap_err (LDAP *ldp, char *reply);
+static void remove_trailing_space (char *s);
int
-query_cmd( msgp, reply )
- struct msginfo *msgp;
- char *reply;
+query_cmd( struct msginfo *msgp, char *reply )
{
LDAP *ldp;
LDAPMessage *ldmsgp, *entry;
- char *s, *dn;
- int matches, rc, ufn;
+ char *dn;
+ int matches, rc, ld_errno, ufn;
LDAPFiltDesc *lfdp;
LDAPFiltInfo *lfi;
struct ldap_disptmpl *tmpllist = NULL;
/*
* open connection to LDAP server and bind as dapuser
*/
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
if ( do_cldap )
ldp = cldap_open( ldaphost, ldapport );
else
-#endif /* CLDAP */
- ldp = ldap_open( ldaphost, ldapport );
+#endif /* LDAP_CONNECTIONLESS */
+ ldp = ldap_init( ldaphost, ldapport );
if ( ldp == NULL ) {
strcat( reply, errpreface );
return( 0 );
}
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
if ( !do_cldap )
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
if ( ldap_simple_bind_s( ldp, dapuser, NULL ) != LDAP_SUCCESS ) {
report_ldap_err( ldp, reply );
close_ldap( ldp );
/*
* set options for search and build filter
*/
- ldp->ld_deref = derefaliases;
- ldp->ld_sizelimit = sizelimit;
+ ldap_set_option(ldp, LDAP_OPT_DEREF, &derefaliases);
+ ldap_set_option(ldp, LDAP_OPT_SIZELIMIT, &sizelimit);
matches = 0;
#ifdef RCPT500_UFN
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
if ( !do_cldap && strchr( msgp->msg_arg, ',' ) != NULL ) {
-#else /* CLDAP */
+#else /* LDAP_CONNECTIONLESS */
if ( strchr( msgp->msg_arg, ',' ) != NULL ) {
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
struct timeval tv;
ldap_ufn_setprefix( ldp, searchbase );
for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
if ( do_cldap )
rc = cldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
lfi->lfi_filter, attrs, 0, &ldmsgp, dapuser );
else
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
rc = ldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
lfi->lfi_filter, attrs, 0, &ldmsgp );
return( 0 );
}
- if ( ldp->ld_errno == LDAP_TIMELIMIT_EXCEEDED
- || ldp->ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
+ ld_errno = 0;
+ ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
+ if ( ld_errno == LDAP_TIMELIMIT_EXCEEDED
+ || ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
strcat( reply, "(Partial results only - a limit was exceeded)\n" );
}
}
-void
+static void
close_ldap( LDAP *ld )
{
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
if ( do_cldap )
cldap_close( ld );
else
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
ldap_unbind( ld );
}
-append_entry_list( reply, query, ldp, ldmsgp )
- char *reply;
- char *query;
- LDAP *ldp;
- LDAPMessage *ldmsgp;
+static void
+append_entry_list( char *reply, char *query, LDAP *ldp, LDAPMessage *ldmsgp )
{
LDAPMessage *e;
char *dn, *rdn, *s, **title;
if (( cn = ldap_get_values( ldp, e, "cn" )) != NULL ) {
for ( i = 0; cn[i] != NULL; i++ ) {
- if ( isdigit( *( cn[i] + strlen( cn[i] ) - 1 ))) {
+ if ( isdigit((unsigned char) cn[i][strlen( cn[i] ) - 1])) {
rdn = strdup( cn[i] );
free_rdn = 1;
break;
}
-int
-append_text( reply, text, len )
- char *reply;
- char *text;
- int len;
+static int
+append_text( void *reply, char *text, ber_len_t len )
{
- strcat( reply, text );
+ strcat( (char *) reply, text );
return( len );
}
-int
-do_read( ldp, dn, reply, tmpll )
- LDAP *ldp;
- char *dn;
- char *reply;
- struct ldap_disptmpl *tmpll;
+static int
+do_read( LDAP *ldp, char *dn, char *reply, struct ldap_disptmpl *tmpll )
{
int rc;
static char *maildefvals[] = { "None registered in this service", NULL };
static char **defvals[] = { maildefvals, NULL };
- rc = ldap_entry2text_search( ldp, dn, searchbase, NULLMSG, tmpll,
- defattrs, defvals, (void *)append_text, (void *)reply, "\n",
+ rc = ldap_entry2text_search( ldp, dn, searchbase, NULL, tmpll,
+ defattrs, defvals, append_text, (void *)reply, "\n",
rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
return( rc );
}
-report_ldap_err( ldp, reply )
- LDAP *ldp;
- char *reply;
+static void
+report_ldap_err( LDAP *ldp, char *reply )
{
+ int ld_errno = 0;
+ ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
strcat( reply, errpreface );
- strcat( reply, ldap_err2string( ldp->ld_errno ));
+ strcat( reply, ldap_err2string( ld_errno ));
strcat( reply, "\n" );
}
-remove_trailing_space( s )
- char *s;
+static void
+remove_trailing_space( char *s )
{
char *p = s + strlen( s ) - 1;
- while ( isspace( *p ) && p > s ) {
+ while ( isspace( (unsigned char) *p ) && p > s ) {
--p;
}
*(++p) = '\0';
a message with the word "help" in it to get this text returned to you.
Note that this service is entirely automated -- no humans will respond
-to requests or other email sent here. If you have questions or
-comments on the X.500 Directory service in general, or about this
-service in particular, please send electronic mail to:
-
- x500@umich.edu
+to requests or other email sent here.
+
+We would appreciate any feedback you can provide.
+If you have problems, report them using our Issue Tracking System:
+ http://www.OpenLDAP.com/its/
+or by sending e-mail to:
+ OpenLDAP-its@OpenLDAP.org
+Additional mailing lists are available. Please see:
+ http://www.OpenLDAP.com/lists/
This is the end of the help text.
--- /dev/null
+##
+## Makefile for LDAP tools
+##
+SRCS = ldapsearch.c ldapmodify.c ldapdelete.c ldapmodrdn.c ldappasswd.c
+OBJS = ldapsearch.o ldapmodify.o ldapdelete.o ldapmodrdn.o ldappasswd.o
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldif -lldap -llber -llutil
+XXLIBS = $(SECURITY_LIBS) $(LDIF_LIBS) $(LUTIL_LIBS)
+
+XSRCS = ldsversion.c ldmversion.c lddversion.c ldrversion.c ldpversion.c
+
+PROGRAMS = ldapsearch ldapmodify ldapdelete ldapmodrdn ldapadd ldappasswd
+
+ldapsearch: ldsversion.o
+ $(LTLINK) -o $@ ldapsearch.o ldsversion.o $(LIBS)
+
+ldapmodify: ldmversion.o
+ $(LTLINK) -o $@ ldapmodify.o ldmversion.o $(LIBS)
+
+ldapdelete: lddversion.o
+ $(LTLINK) -o $@ ldapdelete.o lddversion.o $(LIBS)
+
+ldapmodrdn: ldrversion.o
+ $(LTLINK) -o $@ ldapmodrdn.o ldrversion.o $(LIBS)
+
+ldappasswd: ldpversion.o
+ $(LTLINK) -o $@ ldappasswd.o ldpversion.o $(LIBS)
+
+ldapadd: ldapmodify
+ @-$(RM) $@$(EXEEXT)
+ $(LN_H) ldapmodify$(EXEEXT) ldapadd$(EXEEXT)
+
+ldsversion.c: ldapsearch.o $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) ldapsearch > $@
+
+ldmversion.c: ldapmodify.o $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) ldapmodify > $@
+
+lddversion.c: ldapdelete.o $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) ldapdelete > $@
+
+ldpversion.c: ldappasswd.o $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) ldappasswd > $@
+
+ldrversion.c: ldapmodrdn.o $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) ldapmodrdn > $@
+
+install-local: FORCE
+ -$(MKDIR) $(bindir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldapsearch $(bindir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldapmodify $(bindir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldapdelete $(bindir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldapmodrdn $(bindir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldappasswd $(bindir)
+ $(RM) $(bindir)/ldapadd$(EXEEXT)
+ $(LN) $(bindir)/ldapmodify$(EXEEXT) $(bindir)/ldapadd$(EXEEXT)
/* ldapdelete.c - simple program to delete an entry using LDAP */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
+
+#include <ac/stdlib.h>
+#include <ac/ctype.h>
+
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
#include <lber.h>
#include <ldap.h>
-#include "ldapconfig.h"
-
-static char *binddn = LDAPDELETE_BINDDN;
-static char *base = LDAPDELETE_BASE;
+static char *binddn = NULL;
static char *passwd = NULL;
-static char *ldaphost = LDAPHOST;
-static int ldapport = LDAP_PORT;
+static char *base = NULL;
+static char *ldaphost = NULL;
+static int ldapport = 0;
static int not, verbose, contoper;
static LDAP *ld;
-#ifdef LDAP_DEBUG
-extern int ldap_debug, lber_debug;
-#endif /* LDAP_DEBUG */
+static int dodelete LDAP_P((
+ LDAP *ld,
+ char *dn));
-#define safe_realloc( ptr, size ) ( ptr == NULL ? malloc( size ) : \
- realloc( ptr, size ))
-
-
-main( argc, argv )
- int argc;
- char **argv;
+int
+main( int argc, char **argv )
{
- char *usage = "usage: %s [-n] [-v] [-k] [-d debug-level] [-f file] [-h ldaphost] [-p ldapport] [-D binddn] [-w passwd] [dn]...\n";
- char *p, buf[ 4096 ];
+ char *usage = "usage: %s [-n] [-v] [-k] [-W] [-M[M]] [-d debug-level] [-f file] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [dn]...\n";
+ char buf[ 4096 ];
FILE *fp;
- int i, rc, kerberos, linenum, authmethod;
-
- extern char *optarg;
- extern int optind;
+ int i, rc, authmethod, want_bindpw, version, debug, manageDSAit;
- kerberos = not = verbose = contoper = 0;
+ not = verbose = contoper = want_bindpw = debug = manageDSAit = 0;
fp = NULL;
+ authmethod = LDAP_AUTH_SIMPLE;
+ version = -1;
- while (( i = getopt( argc, argv, "nvkKch:p:D:w:d:f:" )) != EOF ) {
+ while (( i = getopt( argc, argv, "WMnvkKch:P:p:D:w:d:f:" )) != EOF ) {
switch( i ) {
case 'k': /* kerberos bind */
- kerberos = 2;
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV4;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
+ fprintf( stderr, usage, argv[0] );
+ return( EXIT_FAILURE );
+#endif
break;
case 'K': /* kerberos bind, part one only */
- kerberos = 1;
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV41;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
+ fprintf( stderr, usage, argv[0] );
+ return( EXIT_FAILURE );
+#endif
break;
case 'c': /* continuous operation mode */
++contoper;
break;
case 'w': /* password */
passwd = strdup( optarg );
+ {
+ char* p;
+
+ for( p = optarg; *p == '\0'; p++ ) {
+ *p = '*';
+ }
+ }
break;
case 'f': /* read DNs from a file */
if (( fp = fopen( optarg, "r" )) == NULL ) {
perror( optarg );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
break;
case 'd':
-#ifdef LDAP_DEBUG
- ldap_debug = lber_debug = atoi( optarg ); /* */
-#else /* LDAP_DEBUG */
- fprintf( stderr, "compile with -DLDAP_DEBUG for debugging\n" );
-#endif /* LDAP_DEBUG */
+ debug |= atoi( optarg );
break;
case 'p':
ldapport = atoi( optarg );
case 'v': /* verbose mode */
verbose++;
break;
+ case 'M':
+ /* enable Manage DSA IT */
+ manageDSAit++;
+ break;
+ case 'W':
+ want_bindpw++;
+ break;
+ case 'P':
+ switch( atoi(optarg) )
+ {
+ case 2:
+ version = LDAP_VERSION2;
+ break;
+ case 3:
+ version = LDAP_VERSION3;
+ break;
+ default:
+ fprintf( stderr, "protocol version should be 2 or 3\n" );
+ fprintf( stderr, usage, argv[0] );
+ return( EXIT_FAILURE );
+ }
+ break;
default:
fprintf( stderr, usage, argv[0] );
- exit( 1 );
+ return( EXIT_FAILURE );
}
}
}
}
- if (( ld = ldap_open( ldaphost, ldapport )) == NULL ) {
- perror( "ldap_open" );
- exit( 1 );
- }
+ if ( debug ) {
+ if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ }
- ld->ld_deref = LDAP_DEREF_NEVER; /* prudent, but probably unnecessary */
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
- if ( !kerberos ) {
- authmethod = LDAP_AUTH_SIMPLE;
- } else if ( kerberos == 1 ) {
- authmethod = LDAP_AUTH_KRBV41;
- } else {
- authmethod = LDAP_AUTH_KRBV4;
+ if (( ld = ldap_init( ldaphost, ldapport )) == NULL ) {
+ perror( "ldap_init" );
+ return( EXIT_FAILURE );
}
+
+ {
+ /* this seems prudent */
+ int deref = LDAP_DEREF_NEVER;
+ ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
+ }
+
+ if (want_bindpw)
+ passwd = getpass("Enter LDAP Password: ");
+
+ if (version != -1 &&
+ ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS)
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
+ }
+
if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_bind" );
- exit( 1 );
+ return( EXIT_FAILURE );
}
+ if ( manageDSAit ) {
+ int err;
+ LDAPControl c;
+ LDAPControl *ctrls[2];
+ ctrls[0] = &c;
+ ctrls[1] = NULL;
+
+ c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+ c.ldctl_value.bv_val = NULL;
+ c.ldctl_value.bv_len = 0;
+ c.ldctl_iscritical = manageDSAit > 1;
+
+ err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+ if( err != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+ if( c.ldctl_iscritical ) {
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
+
if ( fp == NULL ) {
for ( ; optind < argc; ++optind ) {
rc = dodelete( ld, argv[ optind ] );
ldap_unbind( ld );
- exit( rc );
+ return( rc );
}
-dodelete( ld, dn )
- LDAP *ld;
- char *dn;
+static int dodelete(
+ LDAP *ld,
+ char *dn)
{
int rc;
if ( verbose ) {
- printf( "%sdeleting entry %s\n", not ? "!" : "", dn );
+ printf( "%sdeleting entry \"%s\"\n",
+ (not ? "!" : ""), dn );
}
if ( not ) {
rc = LDAP_SUCCESS;
if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_delete" );
} else if ( verbose ) {
- printf( "entry removed\n" );
+ printf( "\tremoved\n" );
}
}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/* ldapmodify.c - generic program to modify or add entries using LDAP */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <sys/types.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
#include <sys/stat.h>
+
+#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
+#endif
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#ifndef VMS
-#include <unistd.h>
-#endif /* VMS */
+#endif
+
#include <lber.h>
#include <ldap.h>
-#include <ldif.h>
-#include "ldapconfig.h"
+#include "ldif.h"
+#include "ldap_defaults.h"
static char *prog;
-static char *binddn = LDAPMODIFY_BINDDN;
+static char *binddn = NULL;
static char *passwd = NULL;
-static char *ldaphost = LDAPHOST;
-static int ldapport = LDAP_PORT;
+static char *ldaphost = NULL;
+static int ldapport = 0;
static int new, replace, not, verbose, contoper, force, valsfromfiles;
static LDAP *ld;
-#ifdef LDAP_DEBUG
-extern int ldap_debug, lber_debug;
-#endif /* LDAP_DEBUG */
-
-#define safe_realloc( ptr, size ) ( ptr == NULL ? malloc( size ) : \
- realloc( ptr, size ))
-
#define LDAPMOD_MAXLINE 4096
/* strings found in replog/LDIF entries (mostly lifted from slurpd/slurp.h) */
+#define T_VERSION_STR "version"
#define T_REPLICA_STR "replica"
#define T_DN_STR "dn"
#define T_CHANGETYPESTR "changetype"
#define T_MODIFYCTSTR "modify"
#define T_DELETECTSTR "delete"
#define T_MODRDNCTSTR "modrdn"
+#define T_MODDNCTSTR "moddn"
+#define T_RENAMECTSTR "rename"
#define T_MODOPADDSTR "add"
#define T_MODOPREPLACESTR "replace"
#define T_MODOPDELETESTR "delete"
#define T_MODSEPSTR "-"
#define T_NEWRDNSTR "newrdn"
#define T_DELETEOLDRDNSTR "deleteoldrdn"
+#define T_NEWSUPSTR "newsuperior"
-#ifdef NEEDPROTOS
-static int process_ldapmod_rec( char *rbuf );
-static int process_ldif_rec( char *rbuf );
-static void addmodifyop( LDAPMod ***pmodsp, int modop, char *attr,
- char *value, int vlen );
-static int domodify( char *dn, LDAPMod **pmods, int newentry );
-static int dodelete( char *dn );
-static int domodrdn( char *dn, char *newrdn, int deleteoldrdn );
-static void freepmods( LDAPMod **pmods );
-static int fromfile( char *path, struct berval *bv );
-static char *read_one_record( FILE *fp );
-#else /* NEEDPROTOS */
-static int process_ldapmod_rec();
-static int process_ldif_rec();
-static void addmodifyop();
-static int domodify();
-static int dodelete();
-static int domodrdn();
-static void freepmods();
-static int fromfile();
-static char *read_one_record();
-#endif /* NEEDPROTOS */
-
-
-main( argc, argv )
- int argc;
- char **argv;
+static void usage LDAP_P(( const char *prog ));
+static int process_ldapmod_rec LDAP_P(( char *rbuf ));
+static int process_ldif_rec LDAP_P(( char *rbuf, int count ));
+static void addmodifyop LDAP_P(( LDAPMod ***pmodsp, int modop, char *attr,
+ char *value, int vlen ));
+static int domodify LDAP_P(( char *dn, LDAPMod **pmods, int newentry ));
+static int dodelete LDAP_P(( char *dn ));
+static int domodrdn LDAP_P(( char *dn, char *newrdn, int deleteoldrdn ));
+static int fromfile LDAP_P(( char *path, struct berval *bv ));
+static char *read_one_record LDAP_P(( FILE *fp ));
+
+static void
+usage( const char *prog )
+{
+ fprintf( stderr,
+ "Add or modify entries from an LDAP server\n\n"
+ "usage: %s [-abcknrvF] [-M[M]] [-d debug-level] [-P version] [-h ldaphost]\n"
+ " [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile ]\n"
+ " a - add values (default%s)\n"
+ " b - read values from files (for binary attributes)\n"
+ " c - continuous operation\n"
+ " D - bind DN\n"
+ " M - enable Manage DSA IT control (-MM for critical)\n"
+ " d - debug level\n"
+ " f - read from file\n"
+ " F - force all changes records to be used\n"
+ " h - ldap host\n"
+ " n - print adds, don't actually do them\n"
+ " p - LDAP port\n"
+ " r - replace values\n"
+ " v - verbose mode\n"
+ " w - password\n"
+ , prog, (strcmp( prog, "ldapadd" ) ? " is to replace" : "") );
+ exit( EXIT_FAILURE );
+}
+
+
+int
+main( int argc, char **argv )
{
char *infile, *rbuf, *start, *p, *q;
FILE *fp;
- int rc, i, kerberos, use_ldif, authmethod;
- char *usage = "usage: %s [-abcknrvF] [-d debug-level] [-h ldaphost] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile ]\n";
-
- extern char *optarg;
- extern int optind;
+ int rc, i, use_ldif, authmethod, version, want_bindpw, debug, manageDSAit;
+ int count;
- if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) {
+ if (( prog = strrchr( argv[ 0 ], *LDAP_DIRSEP )) == NULL ) {
prog = argv[ 0 ];
} else {
++prog;
}
+
+ /* Print usage when no parameters */
+ if( argc < 2 )
+ usage( prog );
+
new = ( strcmp( prog, "ldapadd" ) == 0 );
infile = NULL;
- kerberos = not = verbose = valsfromfiles = 0;
+ not = verbose = valsfromfiles = want_bindpw = debug = manageDSAit = 0;
+ authmethod = LDAP_AUTH_SIMPLE;
+ version = -1;
- while (( i = getopt( argc, argv, "FabckKnrtvh:p:D:w:d:f:" )) != EOF ) {
+ while (( i = getopt( argc, argv, "WFMabckKnrtvh:p:D:w:d:f:P:" )) != EOF ) {
switch( i ) {
case 'a': /* add */
new = 1;
replace = 1;
break;
case 'k': /* kerberos bind */
- kerberos = 2;
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV4;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
+ usage( argv[0] );
+ return( EXIT_FAILURE );
+#endif
break;
case 'K': /* kerberos bind, part 1 only */
- kerberos = 1;
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV41;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
+ usage( argv[0] );
+ return( EXIT_FAILURE );
+#endif
break;
case 'F': /* force all changes records to be used */
force = 1;
break;
case 'w': /* password */
passwd = strdup( optarg );
+ {
+ char* p;
+
+ for( p = optarg; *p == '\0'; p++ ) {
+ *p = '*';
+ }
+ }
break;
case 'd':
-#ifdef LDAP_DEBUG
- ldap_debug = lber_debug = atoi( optarg ); /* */
-#else /* LDAP_DEBUG */
- fprintf( stderr, "%s: compile with -DLDAP_DEBUG for debugging\n",
- prog );
-#endif /* LDAP_DEBUG */
+ debug |= atoi( optarg );
break;
case 'f': /* read from file */
infile = strdup( optarg );
case 'v': /* verbose mode */
verbose++;
break;
+ case 'M':
+ /* enable Manage DSA IT */
+ manageDSAit++;
+ break;
+ case 'W':
+ want_bindpw++;
+ break;
+ case 'P':
+ switch( atoi(optarg) )
+ {
+ case 2:
+ version = LDAP_VERSION2;
+ break;
+ case 3:
+ version = LDAP_VERSION3;
+ break;
+ default:
+ fprintf( stderr, "protocol version should be 2 or 3\n" );
+ usage( argv[0] );
+ }
+ break;
default:
- fprintf( stderr, usage, prog );
- exit( 1 );
+ usage( prog );
}
}
- if ( argc - optind != 0 ) {
- fprintf( stderr, usage, prog );
- exit( 1 );
- }
+ if ( argc != optind )
+ usage( prog );
if ( infile != NULL ) {
if (( fp = fopen( infile, "r" )) == NULL ) {
perror( infile );
- exit( 1 );
+ return( EXIT_FAILURE );
}
} else {
fp = stdin;
}
+ if ( debug ) {
+ if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ ldif_debug = debug;
+ }
+
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
if ( !not ) {
- if (( ld = ldap_open( ldaphost, ldapport )) == NULL ) {
- perror( "ldap_open" );
- exit( 1 );
+ if (( ld = ldap_init( ldaphost, ldapport )) == NULL ) {
+ perror( "ldap_init" );
+ return( EXIT_FAILURE );
}
- ld->ld_deref = LDAP_DEREF_NEVER; /* this seems prudent */
+ /* this seems prudent */
+ {
+ int deref = LDAP_DEREF_NEVER;
+ ldap_set_option( ld, LDAP_OPT_DEREF, &deref);
+ }
- if ( !kerberos ) {
- authmethod = LDAP_AUTH_SIMPLE;
- } else if ( kerberos == 1 ) {
- authmethod = LDAP_AUTH_KRBV41;
- } else {
- authmethod = LDAP_AUTH_KRBV4;
+ if (want_bindpw)
+ passwd = getpass("Enter LDAP Password: ");
+
+ if (version != -1 &&
+ ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS)
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION to %d\n", version );
}
+
if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_bind" );
- exit( 1 );
+ return( EXIT_FAILURE );
}
}
rc = 0;
+ if ( manageDSAit ) {
+ int err;
+ LDAPControl c;
+ LDAPControl *ctrls[2];
+ ctrls[0] = &c;
+ ctrls[1] = NULL;
+
+ c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+ c.ldctl_value.bv_val = NULL;
+ c.ldctl_value.bv_len = 0;
+ c.ldctl_iscritical = manageDSAit > 1;
+
+ err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+ if( err != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+ if( c.ldctl_iscritical ) {
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
+
+ count = 0;
while (( rc == 0 || contoper ) &&
( rbuf = read_one_record( fp )) != NULL ) {
+ count++;
/*
* we assume record is ldif/slapd.replog if the first line
* has a colon that appears to the left of any equal signs, OR
* if the first line consists entirely of digits (an entry id)
*/
- use_ldif = ( p = strchr( rbuf, ':' )) != NULL &&
- ( q = strchr( rbuf, '\n' )) != NULL && p < q &&
- (( q = strchr( rbuf, '=' )) == NULL || p < q );
+ use_ldif = ( *rbuf == '#' ) ||
+ (( p = strchr( rbuf, ':' )) != NULL &&
+ ( q = strchr( rbuf, '\n' )) != NULL && p < q &&
+ (( q = strchr( rbuf, '=' )) == NULL || p < q ));
start = rbuf;
if ( !use_ldif && ( q = strchr( rbuf, '\n' )) != NULL ) {
for ( p = rbuf; p < q; ++p ) {
- if ( !isdigit( *p )) {
+ if ( !isdigit( (unsigned char) *p )) {
break;
}
}
}
if ( use_ldif ) {
- rc = process_ldif_rec( start );
+ rc = process_ldif_rec( start, count );
} else {
rc = process_ldapmod_rec( start );
}
+ if( rc )
+ fprintf( stderr, "%s() = %d\n",
+ use_ldif ? "ldif_rec" : "ldapmod_rec" , rc );
+
free( rbuf );
}
ldap_unbind( ld );
}
- exit( rc );
+ return( rc );
}
static int
-process_ldif_rec( char *rbuf )
+process_ldif_rec( char *rbuf, int count )
{
- char *line, *dn, *type, *value, *newrdn, *p;
- int rc, linenum, vlen, modop, replicaport;
- int expect_modop, expect_sep, expect_ct, expect_newrdn;
+ char *line, *dn, *type, *value, *newrdn, *newsup, *p;
+ int rc, linenum, modop, replicaport;
+ ber_len_t vlen;
+ int expect_modop, expect_sep, expect_ct, expect_newrdn, expect_newsup;
int expect_deleteoldrdn, deleteoldrdn;
int saw_replica, use_record, new_entry, delete_entry, got_all;
LDAPMod **pmods;
+ int version;
new_entry = new;
rc = got_all = saw_replica = delete_entry = expect_modop = 0;
- expect_deleteoldrdn = expect_newrdn = expect_sep = expect_ct = 0;
+ expect_deleteoldrdn = expect_newrdn = expect_newsup = 0;
+ expect_sep = expect_ct = 0;
linenum = 0;
+ version = 0;
deleteoldrdn = 1;
use_record = force;
pmods = NULL;
- dn = newrdn = NULL;
+ dn = newrdn = newsup = NULL;
- while ( rc == 0 && ( line = str_getline( &rbuf )) != NULL ) {
+ while ( rc == 0 && ( line = ldif_getline( &rbuf )) != NULL ) {
++linenum;
+
if ( expect_sep && strcasecmp( line, T_MODSEPSTR ) == 0 ) {
expect_sep = 0;
expect_ct = 1;
continue;
}
- if ( str_parse_line( line, &type, &value, &vlen ) < 0 ) {
- fprintf( stderr, "%s: invalid format (line %d of entry: %s\n",
+ if ( ldif_parse_line( line, &type, &value, &vlen ) < 0 ) {
+ fprintf( stderr, "%s: invalid format (line %d) entry: \"%s\"\n",
prog, linenum, dn == NULL ? "" : dn );
rc = LDAP_PARAM_ERROR;
break;
if ( !use_record && strcasecmp( type, T_REPLICA_STR ) == 0 ) {
++saw_replica;
if (( p = strchr( value, ':' )) == NULL ) {
- replicaport = LDAP_PORT;
+ replicaport = 0;
} else {
*p++ = '\0';
replicaport = atoi( p );
replicaport == ldapport ) {
use_record = 1;
}
+ } else if ( count == 1 && linenum == 1 &&
+ strcasecmp( type, T_VERSION_STR ) == 0 )
+ {
+ if( vlen == 0 || atoi(value) != 1 ) {
+ fprintf( stderr, "%s: invalid version %s, line %d (ignored)\n",
+ prog, value == NULL ? "(null)" : value, linenum );
+ }
+ version++;
+
} else if ( strcasecmp( type, T_DN_STR ) == 0 ) {
- if (( dn = strdup( value )) == NULL ) {
+ if (( dn = strdup( value ? value : "" )) == NULL ) {
perror( "strdup" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
expect_ct = 1;
}
if ( expect_ct ) {
expect_ct = 0;
if ( !use_record && saw_replica ) {
- printf( "%s: skipping change record for entry: %s\n\t(LDAP host/port does not match replica: lines)\n",
+ printf( "%s: skipping change record for entry: %s\n"
+ "\t(LDAP host/port does not match replica: lines)\n",
prog, dn );
free( dn );
return( 0 );
expect_modop = 1;
} else if ( strcasecmp( value, T_ADDCTSTR ) == 0 ) {
new_entry = 1;
- } else if ( strcasecmp( value, T_MODRDNCTSTR ) == 0 ) {
+ } else if ( strcasecmp( value, T_MODRDNCTSTR ) == 0
+ || strcasecmp( value, T_MODDNCTSTR ) == 0
+ || strcasecmp( value, T_RENAMECTSTR ) == 0)
+ {
expect_newrdn = 1;
} else if ( strcasecmp( value, T_DELETECTSTR ) == 0 ) {
got_all = delete_entry = 1;
} else {
fprintf( stderr,
- "%s: unknown %s \"%s\" (line %d of entry: %s)\n",
+ "%s: unknown %s \"%s\" (line %d of entry \"%s\")\n",
prog, T_CHANGETYPESTR, value, linenum, dn );
rc = LDAP_PARAM_ERROR;
}
if ( strcasecmp( type, T_NEWRDNSTR ) == 0 ) {
if (( newrdn = strdup( value )) == NULL ) {
perror( "strdup" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
expect_deleteoldrdn = 1;
expect_newrdn = 0;
} else {
- fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n",
+ fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry \"%s\")\n",
prog, T_NEWRDNSTR, type, linenum, dn );
rc = LDAP_PARAM_ERROR;
}
} else if ( expect_deleteoldrdn ) {
if ( strcasecmp( type, T_DELETEOLDRDNSTR ) == 0 ) {
deleteoldrdn = ( *value == '0' ) ? 0 : 1;
+ expect_deleteoldrdn = 0;
+ expect_newsup = 1;
got_all = 1;
} else {
- fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n",
+ fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry \"%s\")\n",
prog, T_DELETEOLDRDNSTR, type, linenum, dn );
rc = LDAP_PARAM_ERROR;
}
+ } else if ( expect_newsup ) {
+ if ( strcasecmp( type, T_NEWSUPSTR ) == 0 ) {
+ if (( newsup = strdup( value )) == NULL ) {
+ perror( "strdup" );
+ exit( EXIT_FAILURE );
+ }
+ expect_newsup = 0;
+ } else {
+ fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry \"%s\")\n",
+ prog, T_NEWSUPSTR, type, linenum, dn );
+ rc = LDAP_PARAM_ERROR;
+ }
} else if ( got_all ) {
fprintf( stderr,
- "%s: extra lines at end (line %d of entry %s)\n",
+ "%s: extra lines at end (line %d of entry \"%s\")\n",
prog, linenum, dn );
rc = LDAP_PARAM_ERROR;
} else {
}
}
+ if( linenum == 0 ) {
+ return 0;
+ }
+
+ if( version && linenum == 1 ) {
+ return 0;
+ }
+
if ( rc == 0 ) {
if ( delete_entry ) {
rc = dodelete( dn );
free( newrdn );
}
if ( pmods != NULL ) {
- freepmods( pmods );
+ ldap_mods_free( pmods, 1 );
}
return( rc );
rbuf = NULL;
} else {
if ( *(p-1) == '\\' ) { /* lines ending in '\' are continued */
- strcpy( p - 1, p );
+ SAFEMEMCPY( p - 1, p, strlen( p ) + 1 );
rbuf = p;
continue;
}
if ( dn == NULL ) { /* first line contains DN */
if (( dn = strdup( line )) == NULL ) {
perror( "strdup" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
} else {
if (( p = strchr( line, '=' )) == NULL ) {
value = p;
}
- for ( attr = line; *attr != '\0' && isspace( *attr ); ++attr ) {
+ for ( attr = line;
+ *attr != '\0' && isspace( (unsigned char) *attr ); ++attr ) {
; /* skip attribute leading white space */
}
- for ( q = p - 1; q > attr && isspace( *q ); --q ) {
+ for ( q = p - 1; q > attr && isspace( (unsigned char) *q ); --q ) {
*q = '\0'; /* remove attribute trailing white space */
}
if ( value != NULL ) {
- while ( isspace( *value )) {
+ while ( isspace( (unsigned char) *value )) {
++value; /* skip value leading white space */
}
for ( q = value + strlen( value ) - 1; q > value &&
- isspace( *q ); --q ) {
+ isspace( (unsigned char) *q ); --q ) {
*q = '\0'; /* remove value trailing white space */
}
if ( *value == '\0' ) {
}
if ( value == NULL && new ) {
- fprintf( stderr, "%s: missing value on line %d (attr is %s)\n",
+ fprintf( stderr, "%s: missing value on line %d (attr=\"%s\")\n",
prog, linenum, attr );
rc = LDAP_PARAM_ERROR;
} else {
}
if ( pmods != NULL ) {
- freepmods( pmods );
+ ldap_mods_free( pmods, 1 );
}
if ( dn != NULL ) {
free( dn );
}
if ( pmods == NULL || pmods[ i ] == NULL ) {
- if (( pmods = (LDAPMod **)safe_realloc( pmods, (i + 2) *
+ if (( pmods = (LDAPMod **)ber_memrealloc( pmods, (i + 2) *
sizeof( LDAPMod * ))) == NULL ) {
- perror( "safe_realloc" );
- exit( 1 );
+ perror( "realloc" );
+ exit( EXIT_FAILURE );
}
*pmodsp = pmods;
pmods[ i + 1 ] = NULL;
- if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
+ if (( pmods[ i ] = (LDAPMod *)ber_memcalloc( 1, sizeof( LDAPMod )))
== NULL ) {
perror( "calloc" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
pmods[ i ]->mod_op = modop;
- if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
+ if (( pmods[ i ]->mod_type = ber_strdup( attr )) == NULL ) {
perror( "strdup" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
}
}
}
if (( pmods[ i ]->mod_bvalues =
- (struct berval **)safe_realloc( pmods[ i ]->mod_bvalues,
+ (struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
(j + 2) * sizeof( struct berval * ))) == NULL ) {
- perror( "safe_realloc" );
- exit( 1 );
+ perror( "ber_realloc" );
+ exit( EXIT_FAILURE );
}
pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
- if (( bvp = (struct berval *)malloc( sizeof( struct berval )))
+ if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
== NULL ) {
- perror( "malloc" );
- exit( 1 );
+ perror( "ber_memalloc" );
+ exit( EXIT_FAILURE );
}
pmods[ i ]->mod_bvalues[ j ] = bvp;
if ( valsfromfiles && *value == '/' ) { /* get value from file */
if ( fromfile( value, bvp ) < 0 ) {
- exit( 1 );
+ exit( EXIT_FAILURE );
}
} else {
bvp->bv_len = vlen;
- if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
+ if (( bvp->bv_val = (char *)ber_memalloc( vlen + 1 )) == NULL ) {
perror( "malloc" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
SAFEMEMCPY( bvp->bv_val, value, vlen );
bvp->bv_val[ vlen ] = '\0';
struct berval *bvp;
if ( pmods == NULL ) {
- fprintf( stderr, "%s: no attributes to change or add (entry %s)\n",
+ fprintf( stderr, "%s: no attributes to change or add (entry=\"%s\")\n",
prog, dn );
return( LDAP_PARAM_ERROR );
}
for ( j = 0; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
bvp = pmods[ i ]->mod_bvalues[ j ];
notascii = 0;
- for ( k = 0; k < bvp->bv_len; ++k ) {
+ for ( k = 0; (unsigned long) k < bvp->bv_len; ++k ) {
if ( !isascii( bvp->bv_val[ k ] )) {
notascii = 1;
break;
}
if ( newentry ) {
- printf( "%sadding new entry %s\n", not ? "!" : "", dn );
+ printf( "%sadding new entry \"%s\"\n", not ? "!" : "", dn );
} else {
- printf( "%smodifying entry %s\n", not ? "!" : "", dn );
+ printf( "%smodifying entry \"%s\"\n", not ? "!" : "", dn );
}
if ( !not ) {
{
int rc;
- printf( "%sdeleting entry %s\n", not ? "!" : "", dn );
+ printf( "%sdeleting entry \"%s\"\n", not ? "!" : "", dn );
if ( !not ) {
if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_delete" );
{
int rc;
+
+ printf( "%smodifying rdn of entry \"%s\"\n", not ? "!" : "", dn );
if ( verbose ) {
- printf( "new RDN: %s (%skeep existing values)\n",
+ printf( "\tnew RDN: \"%s\" (%skeep existing values)\n",
newrdn, deleteoldrdn ? "do not " : "" );
}
-
- printf( "%smodifying rdn of entry %s\n", not ? "!" : "", dn );
if ( !not ) {
if (( rc = ldap_modrdn2_s( ld, dn, newrdn, deleteoldrdn ))
!= LDAP_SUCCESS ) {
}
-
-static void
-freepmods( LDAPMod **pmods )
-{
- int i;
-
- for ( i = 0; pmods[ i ] != NULL; ++i ) {
- if ( pmods[ i ]->mod_bvalues != NULL ) {
- ber_bvecfree( pmods[ i ]->mod_bvalues );
- }
- if ( pmods[ i ]->mod_type != NULL ) {
- free( pmods[ i ]->mod_type );
- }
- free( pmods[ i ] );
- }
- free( pmods );
-}
-
-
static int
fromfile( char *path, struct berval *bv )
{
bv->bv_len = ftell( fp );
- if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) {
+ if (( bv->bv_val = (char *)ber_memalloc( bv->bv_len )) == NULL ) {
perror( "malloc" );
fclose( fp );
return( -1 );
if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {
perror( path );
fclose( fp );
+ ber_memfree( bv->bv_val );
+ bv->bv_val = NULL;
return( -1 );
}
eof = feof( fp );
fclose( fp );
- if ( rlen != bv->bv_len ) {
+ if ( (unsigned long) rlen != bv->bv_len ) {
perror( path );
- free( bv->bv_val );
+ ber_memfree( bv->bv_val );
+ bv->bv_val = NULL;
return( -1 );
}
static char *
read_one_record( FILE *fp )
{
- int len;
char *buf, line[ LDAPMOD_MAXLINE ];
int lcur, lmax;
lcur = lmax = 0;
buf = NULL;
- while (( fgets( line, sizeof(line), fp ) != NULL ) &&
- (( len = strlen( line )) > 1 )) {
- if ( lcur + len + 1 > lmax ) {
- lmax = LDAPMOD_MAXLINE
- * (( lcur + len + 1 ) / LDAPMOD_MAXLINE + 1 );
- if (( buf = (char *)safe_realloc( buf, lmax )) == NULL ) {
- perror( "safe_realloc" );
- exit( 1 );
- }
- }
- strcpy( buf + lcur, line );
- lcur += len;
+ while ( fgets( line, sizeof(line), fp ) != NULL ) {
+ int len = strlen( line );
+
+ if( len < 2 ) {
+ if( buf == NULL ) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if ( lcur + len + 1 > lmax ) {
+ lmax = LDAPMOD_MAXLINE
+ * (( lcur + len + 1 ) / LDAPMOD_MAXLINE + 1 );
+
+ if (( buf = (char *)realloc( buf, lmax )) == NULL ) {
+ perror( "realloc" );
+ exit( EXIT_FAILURE );
+ }
+ }
+
+ strcpy( buf + lcur, line );
+ lcur += len;
}
return( buf );
--- /dev/null
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ldapmodify"=.\ldapmodify.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "liblber"=..\..\libraries\liblber\liblber.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libldap"=..\..\libraries\libldap\libldap.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libldif"=..\..\libraries\libldif\libldif.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "liblutil"=..\..\libraries\liblutil\liblutil.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "setup"=..\..\include\setup.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
-/* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP.
+ *
+ * Support for MODIFYDN REQUEST V3 (newSuperior) by:
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
#include <lber.h>
#include <ldap.h>
-#include "ldapconfig.h"
-
-static char *binddn = LDAPMODRDN_BINDDN;
-static char *base = LDAPMODRDN_BASE;
+static char *binddn = NULL;
static char *passwd = NULL;
-static char *ldaphost = LDAPHOST;
-static int ldapport = LDAP_PORT;
+static char *base = NULL;
+static char *ldaphost = NULL;
+static int ldapport = 0;
static int not, verbose, contoper;
static LDAP *ld;
-#ifdef LDAP_DEBUG
-extern int ldap_debug, lber_debug;
-#endif /* LDAP_DEBUG */
+static int domodrdn LDAP_P((
+ LDAP *ld,
+ char *dn,
+ char *rdn,
+ int remove, /* flag: remove old RDN */
+ char *newSuperior));
-#define safe_realloc( ptr, size ) ( ptr == NULL ? malloc( size ) : \
- realloc( ptr, size ))
-
-
-main( argc, argv )
- int argc;
- char **argv;
+int
+main(int argc, char **argv)
{
- char *usage = "usage: %s [-nvkc] [-d debug-level] [-h ldaphost] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile | dn newrdn ]\n";
- char *myname,*infile, *p, *entrydn, *rdn, buf[ 4096 ];
+ char *usage = "usage: %s [-nvkWc] [-M[M]] [-d debug-level] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile | dn newrdn ] [-s newSuperior]\n";
+ char *myname,*infile, *entrydn, *rdn, buf[ 4096 ];
FILE *fp;
- int rc, i, kerberos, remove, havedn, authmethod;
- LDAPMod **pmods;
-
- extern char *optarg;
- extern int optind;
+ int rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit;
+ char *newSuperior=NULL;
infile = NULL;
- kerberos = not = contoper = verbose = remove = 0;
+ not = contoper = verbose = remove = want_bindpw = debug = manageDSAit = 0;
+ authmethod = LDAP_AUTH_SIMPLE;
+ version = -1;
myname = (myname = strrchr(argv[0], '/')) == NULL ? argv[0] : ++myname;
- while (( i = getopt( argc, argv, "kKcnvrh:p:D:w:d:f:" )) != EOF ) {
+ while (( i = getopt( argc, argv, "WkKMcnvrh:P:p:D:w:d:f:s:" )) != EOF ) {
switch( i ) {
case 'k': /* kerberos bind */
- kerberos = 2;
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV4;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
+ return( EXIT_FAILURE );
+#endif
break;
case 'K': /* kerberos bind, part one only */
- kerberos = 1;
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV41;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
+ return( EXIT_FAILURE );
+#endif
break;
case 'c': /* continuous operation mode */
++contoper;
case 'D': /* bind DN */
binddn = strdup( optarg );
break;
+ case 's': /* newSuperior */
+ newSuperior = strdup( optarg );
+ version = LDAP_VERSION3; /* This option => force V3 */
+ break;
case 'w': /* password */
passwd = strdup( optarg );
+ {
+ char* p;
+
+ for( p = optarg; *p == '\0'; p++ ) {
+ *p = '*';
+ }
+ }
break;
case 'd':
-#ifdef LDAP_DEBUG
- ldap_debug = lber_debug = atoi( optarg ); /* */
-#else /* LDAP_DEBUG */
- fprintf( stderr, "compile with -DLDAP_DEBUG for debugging\n" );
-#endif /* LDAP_DEBUG */
+ debug |= atoi( optarg );
break;
case 'f': /* read from file */
infile = strdup( optarg );
case 'r': /* remove old RDN */
remove++;
break;
+ case 'M':
+ /* enable Manage DSA IT */
+ manageDSAit++;
+ break;
+ case 'W':
+ want_bindpw++;
+ break;
+ case 'P':
+ switch( atoi(optarg) )
+ {
+ case 2:
+ version = LDAP_VERSION2;
+ break;
+ case 3:
+ version = LDAP_VERSION3;
+ break;
+ default:
+ fprintf( stderr, "protocol version should be 2 or 3\n" );
+ fprintf( stderr, usage, argv[0] );
+ return( EXIT_FAILURE );
+ }
+ break;
default:
fprintf( stderr, usage, argv[0] );
- exit( 1 );
+ return( EXIT_FAILURE );
}
}
+ if (newSuperior != NULL) {
+ if (version == LDAP_VERSION2) {
+ fprintf( stderr,
+ "%s: version conflict!, -s newSuperior requires LDAPv3\n",
+ myname);
+ fprintf( stderr, usage, argv[0] );
+ return( EXIT_FAILURE );
+ }
+
+ /* promote to LDAPv3 */
+ version = LDAP_VERSION3;
+ }
+
havedn = 0;
if (argc - optind == 2) {
if (( rdn = strdup( argv[argc - 1] )) == NULL ) {
perror( "strdup" );
- exit( 1 );
+ return( EXIT_FAILURE );
}
if (( entrydn = strdup( argv[argc - 2] )) == NULL ) {
perror( "strdup" );
- exit( 1 );
+ return( EXIT_FAILURE );
}
++havedn;
} else if ( argc - optind != 0 ) {
fprintf( stderr, "%s: invalid number of arguments, only two allowed\n", myname);
fprintf( stderr, usage, argv[0] );
- exit( 1 );
+ return( EXIT_FAILURE );
}
if ( infile != NULL ) {
if (( fp = fopen( infile, "r" )) == NULL ) {
perror( infile );
- exit( 1 );
+ return( EXIT_FAILURE );
}
} else {
fp = stdin;
}
- if (( ld = ldap_open( ldaphost, ldapport )) == NULL ) {
- perror( "ldap_open" );
- exit( 1 );
- }
+ if ( debug ) {
+ if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ }
- ld->ld_deref = LDAP_DEREF_NEVER; /* this seems prudent */
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
- if ( !kerberos ) {
- authmethod = LDAP_AUTH_SIMPLE;
- } else if ( kerberos == 1 ) {
- authmethod = LDAP_AUTH_KRBV41;
- } else {
- authmethod = LDAP_AUTH_KRBV4;
+ if (( ld = ldap_init( ldaphost, ldapport )) == NULL ) {
+ perror( "ldap_init" );
+ return( EXIT_FAILURE );
}
+
+ /* this seems prudent */
+ {
+ int deref = LDAP_DEREF_NEVER;
+ ldap_set_option( ld, LDAP_OPT_DEREF, &deref);
+ }
+
+ if (want_bindpw)
+ passwd = getpass("Enter LDAP Password: ");
+
+ if (version != -1 &&
+ ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS)
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
+ }
+
if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_bind" );
- exit( 1 );
+ return( EXIT_FAILURE );
}
+ if ( manageDSAit ) {
+ int err;
+ LDAPControl c;
+ LDAPControl *ctrls[2];
+ ctrls[0] = &c;
+ ctrls[1] = NULL;
+
+ c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+ c.ldctl_value.bv_val = NULL;
+ c.ldctl_value.bv_len = 0;
+ c.ldctl_iscritical = manageDSAit > 1;
+
+ err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+ if( err != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+ if( c.ldctl_iscritical ) {
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
+
rc = 0;
if (havedn)
- rc = domodrdn(ld, entrydn, rdn, remove);
+ rc = domodrdn(ld, entrydn, rdn, remove, newSuperior);
else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) {
if ( *buf != '\0' ) { /* blank lines optional, skip */
buf[ strlen( buf ) - 1 ] = '\0'; /* remove nl */
if ( havedn ) { /* have DN, get RDN */
if (( rdn = strdup( buf )) == NULL ) {
perror( "strdup" );
- exit( 1 );
+ return( EXIT_FAILURE );
}
- rc = domodrdn(ld, entrydn, rdn, remove);
+ rc = domodrdn(ld, entrydn, rdn, remove, newSuperior);
havedn = 0;
} else if ( !havedn ) { /* don't have DN yet */
if (( entrydn = strdup( buf )) == NULL ) {
perror( "strdup" );
- exit( 1 );
+ return( EXIT_FAILURE );
}
++havedn;
}
ldap_unbind( ld );
- exit( rc );
+ /* UNREACHABLE */
+ return( rc );
}
-domodrdn( ld, dn, rdn, remove )
- LDAP *ld;
- char *dn;
- char *rdn;
- int remove; /* flag: remove old RDN */
+static int domodrdn(
+ LDAP *ld,
+ char *dn,
+ char *rdn,
+ int remove, /* flag: remove old RDN */
+ char *newSuperior)
{
int i;
if ( verbose ) {
- printf( "modrdn %s:\n\t%s\n", dn, rdn );
- if (remove)
- printf("removing old RDN\n");
- else
- printf("keeping old RDN\n");
- }
+ printf( "Renaming \"%s\"\n", dn );
+ printf( "\tnew rdn=\"%s\" (%s old rdn)\n",
+ rdn, remove ? "delete" : "keep" );
+ if( newSuperior != NULL ) {
+ printf("\tnew parent=\"%s\"\n", newSuperior);
+ }
+ }
if ( !not ) {
- i = ldap_modrdn2_s( ld, dn, rdn, remove );
+ i = ldap_rename2_s( ld, dn, rdn, remove, newSuperior );
if ( i != LDAP_SUCCESS ) {
- ldap_perror( ld, "ldap_modrdn2_s" );
+ ldap_perror( ld, "ldap_rename2_s" );
} else if ( verbose ) {
printf( "modrdn complete\n" );
}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * Copyright 1998, David E. Storey, All rights reserved.
+ * This software is not subject to any license of The Murphy Group, Inc.
+ * or George Mason University.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ *
+ * ldappasswd.c - program to modify passwords in an LDAP tree
+ *
+ * Author: David E. Storey <dave@tamos.net>
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#include <lber.h>
+#include <ldap.h>
+#include <lutil.h>
+#include <lutil_md5.h>
+#include <lutil_sha1.h>
+
+#include "ldap_defaults.h"
+
+/* local macros */
+#define CEILING(x) ((double)(x) > (int)(x) ? (int)(x) + 1 : (int)(x))
+
+#define LDAP_PASSWD_ATTRIB "userPassword"
+#define LDAP_PASSWD_CONF LDAP_SYSCONFDIR LDAP_DIRSEP "passwd.conf"
+
+#define HS_NONE 0
+#define HS_PLAIN 1
+#define HS_CONV 2
+
+typedef enum
+{
+ HASHTYPE_NONE,
+ HASHTYPE_CRYPT,
+ HASHTYPE_MD5,
+ HASHTYPE_SMD5,
+ HASHTYPE_SHA1,
+ HASHTYPE_SSHA1
+}
+HashTypes;
+
+typedef struct salt_t
+{
+ unsigned char *salt;
+ unsigned int len;
+}
+Salt;
+
+typedef struct hash_t
+{
+ char *name;
+ unsigned int namesz;
+ char *(*func) (const char *, Salt *);
+ unsigned char takes_salt;
+ HashTypes type;
+ HashTypes type_salted;
+ unsigned int default_salt_len;
+}
+Hash;
+
+static int noupdates = 0;
+static int verbose = 0;
+static int want_entryhash = 0;
+static int auto_gen_pw = 0;
+
+/*** functions ***/
+
+/*
+ * pw_encode() essentially base64 encodes a password and its salt
+ */
+
+char *
+pw_encode (unsigned char *passwd, Salt * salt, unsigned int len)
+{
+ int salted = salt && salt->salt && salt->len;
+ int b64_len = 0;
+ char *base64digest = NULL;
+ unsigned char *npasswd = passwd;
+
+ if (salted)
+ {
+ npasswd = (unsigned char *)malloc (len + salt->len);
+ memcpy (npasswd, passwd, len);
+ memcpy (&npasswd[len], salt->salt, salt->len);
+ len += salt->len;
+ }
+
+ b64_len = CEILING (len / 3) * 4 + 1;
+ base64digest = (char *)malloc (b64_len);
+ if (lutil_b64_ntop (npasswd, len, base64digest, b64_len) < 0)
+ {
+ free (base64digest);
+ base64digest = NULL;
+ }
+
+ if (salted)
+ free (npasswd);
+
+ return (base64digest);
+}
+
+/*
+ * if you'd like to write a better salt generator, please, be my guest.
+ */
+
+void
+make_salt (Salt * salt, unsigned int len)
+{
+
+ if (!salt)
+ return;
+
+ salt->len = len;
+ salt->salt = (unsigned char *)malloc (len);
+
+ for (len = 0; len < salt->len; len++)
+ salt->salt[len] = rand () & 0xff;
+}
+
+/*
+ * password generator
+ */
+
+char *
+gen_pass (unsigned int len)
+{
+ static const unsigned char autogen[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.,";
+ unsigned int i;
+ Salt salt;
+
+ salt.salt = NULL;
+ salt.len = 0;
+
+ make_salt (&salt, len);
+ for (i = 0; i < len; i++)
+ salt.salt[i] = autogen[salt.salt[i] % (sizeof (autogen) - 1)];
+
+ return ((char *)salt.salt);
+}
+
+#ifdef SLAPD_CLEARTEXT
+char *
+hash_none (const char *pw_in, Salt * salt)
+{
+ return (strdup (pw_in));
+}
+#endif
+
+#ifdef SLAPD_CRYPT
+char *
+hash_crypt (const char *pw_in, Salt * salt)
+{
+ static const unsigned char crypt64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
+ char *crypted_pw = NULL;
+ Salt lsalt;
+
+ if (salt && salt->salt && strlen ((char *)salt->salt) >= 2)
+ {
+ /* sanity check */
+ if (!(isalnum(salt->salt[0]) || salt->salt[0] == '.' || salt->salt[0] == '/'))
+ salt->salt[0] = crypt64[salt->salt[0] % (sizeof (crypt64) - 1)];
+ if (!(isalnum(salt->salt[1]) || salt->salt[1] == '.' || salt->salt[1] == '/'))
+ salt->salt[1] = crypt64[salt->salt[1] % (sizeof (crypt64) - 1)];
+
+ crypted_pw = crypt (pw_in, (char *)salt->salt);
+ }
+ else
+ {
+ make_salt (&lsalt, 2);
+ lsalt.salt[0] = crypt64[lsalt.salt[0] % (sizeof (crypt64) - 1)];
+ lsalt.salt[1] = crypt64[lsalt.salt[1] % (sizeof (crypt64) - 1)];
+ crypted_pw = crypt (pw_in, (char *)lsalt.salt);
+ free (lsalt.salt);
+ }
+ return (strdup (crypted_pw));
+}
+#endif
+
+char *
+hash_md5 (const char *pw_in, Salt * salt)
+{
+ lutil_MD5_CTX MD5context;
+ unsigned char MD5digest[16];
+
+ lutil_MD5Init (&MD5context);
+ lutil_MD5Update (&MD5context,
+ (const unsigned char *)pw_in, strlen(pw_in));
+ if (salt && salt->salt && salt->len)
+ lutil_MD5Update (&MD5context, salt->salt, salt->len);
+ lutil_MD5Final (MD5digest, &MD5context);
+
+ return (pw_encode (MD5digest, salt, sizeof (MD5digest)));
+}
+
+char *
+hash_sha1 (const char *pw_in, Salt * salt)
+{
+ lutil_SHA1_CTX SHA1context;
+ unsigned char SHA1digest[20];
+
+ lutil_SHA1Init (&SHA1context);
+ lutil_SHA1Update (&SHA1context,
+ (const unsigned char *)pw_in, strlen(pw_in));
+ if (salt && salt->salt && salt->len)
+ lutil_SHA1Update (&SHA1context, salt->salt, salt->len);
+ lutil_SHA1Final (SHA1digest, &SHA1context);
+
+ return (pw_encode (SHA1digest, salt, sizeof (SHA1digest)));
+}
+
+static Hash hashes[] =
+{
+#ifdef SLAPD_CLEARTEXT
+ {"none", 4, hash_none, 0, HASHTYPE_NONE, HASHTYPE_NONE, 0},
+#endif
+#ifdef SLAPD_CRYPT
+ {"crypt", 5, hash_crypt, 1, HASHTYPE_CRYPT, HASHTYPE_CRYPT, 2},
+#endif
+ {"md5", 3, hash_md5, 0, HASHTYPE_MD5, HASHTYPE_SMD5, 0},
+ {"smd5", 4, hash_md5, 1, HASHTYPE_SMD5, HASHTYPE_SMD5, 4},
+ {"sha", 3, hash_sha1, 0, HASHTYPE_SHA1, HASHTYPE_SSHA1, 0},
+ {"ssha", 4, hash_sha1, 1, HASHTYPE_SSHA1, HASHTYPE_SSHA1, 4},
+ {NULL, 0, NULL, 0, HASHTYPE_NONE, HASHTYPE_NONE, 0}
+};
+
+int
+modify_dn (LDAP * ld, char *targetdn, char *pwattr, char *oldpw,
+ char *newpw, HashTypes htype, Salt * salt)
+{
+ int ret = 0;
+ int salted = salt->salt ? 1 : 0;
+ int want_salt = salt->len && !salted;
+ char *buf = NULL;
+ char *hashed_pw = NULL;
+ char *strvals[2];
+ LDAPMod mod, *mods[2];
+
+ if (!ld || !targetdn || !newpw)
+ return (1);
+
+ /* auto-generate password */
+ if (auto_gen_pw)
+ newpw = gen_pass (auto_gen_pw);
+
+ /* handle salt */
+ if (want_salt)
+ {
+ make_salt (salt, salt->len);
+ htype = hashes[htype].type_salted;
+ }
+ else if (hashes[htype].default_salt_len)
+ {
+ /* user chose a salted hash and needs a salt */
+ if (!salted)
+ {
+ want_salt++;
+ salt->len = hashes[htype].default_salt_len;
+ make_salt (salt, salt->len);
+ }
+ }
+
+ /* hash password */
+ hashed_pw = hashes[htype].func (newpw, salt->len ? salt : NULL);
+
+ /* return salt back to its original state */
+ if (want_salt)
+ {
+ free (salt->salt);
+ salt->salt = NULL;
+ }
+
+ buf = (char *)malloc (hashes[htype].namesz + 3 + strlen (hashed_pw));
+ if (htype)
+ sprintf (buf, "{%s}%s", hashes[htype].name, hashed_pw);
+ else
+ sprintf (buf, "%s", hashed_pw);
+
+ if (verbose > 0)
+ {
+ printf ("%s", targetdn);
+ if (verbose > 1)
+ {
+ printf (":%s", buf);
+ if (verbose > 2)
+ printf (":%s", newpw);
+ }
+ printf ("\n");
+ }
+
+ strvals[0] = buf;
+ strvals[1] = NULL;
+ mod.mod_values = strvals;
+ mod.mod_type = pwattr;
+ mod.mod_op = LDAP_MOD_REPLACE;
+ mods[0] = &mod;
+ mods[1] =NULL;
+
+ if (!noupdates && (ret = ldap_modify_s (ld, targetdn, mods)) != LDAP_SUCCESS)
+ ldap_perror (ld, "ldap_modify");
+
+ free (hashed_pw);
+ free (buf);
+ return (ret);
+}
+
+void
+usage (char *s)
+{
+ fprintf (stderr, "Usage: %s [options] [filter]\n", s);
+ fprintf (stderr, " -a attrib\tpassword attribute (default: " LDAP_PASSWD_ATTRIB ")\n");
+ fprintf (stderr, " -b basedn\tbasedn to perform searches\n");
+/* fprintf (stderr, " -C\t\tuse entry's current hash mechanism\n"); */
+ fprintf (stderr, " -D binddn\tbind dn\n");
+ fprintf (stderr, " -d level\tdebugging level\n");
+ fprintf (stderr, " -E\t\tprompt for new password\n");
+ fprintf (stderr, " -e passwd\tnew password\n");
+ fprintf (stderr, " -g passlen\tauto-generate passwords with length pwlen\n");
+ fprintf (stderr, " -H hash\thash type (default: crypt)\n");
+ fprintf (stderr, " -h host\tldap server (default: localhost)\n");
+#ifdef HAVE_KERBEROS
+ fprintf (stderr, " -K\t\tuse Kerberos step 1\n");
+ fprintf (stderr, " -k\t\tuse Kerberos\n");
+#endif
+ fprintf (stderr, " -l time\ttime limit\n");
+ fprintf (stderr, " -n\t\tmake no modifications\n");
+ fprintf (stderr, " -P version\tprotocol version (2 or 3)\n");
+ fprintf (stderr, " -p port\tldap port\n");
+ fprintf (stderr, " -s scope\tsearch scope: base, one, sub (default: sub)\n");
+ fprintf (stderr, " -t targetdn\tdn to change password\n");
+ fprintf (stderr, " -v\t\tverbose (more v's, more verbose)\n");
+ fprintf (stderr, " -W\t\tprompt for bind password\n");
+ fprintf (stderr, " -w passwd\tbind password (for simple authentication)\n");
+ fprintf (stderr, " -Y saltlen\tsalt length to use\n");
+/* fprintf (stderr, " -y salt\tsalt to use\n"); */
+ fprintf (stderr, " -z size\tsize limit\n");
+ exit( EXIT_FAILURE );
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *base = NULL;
+ char *binddn = NULL;
+ char *bindpw = NULL;
+ char *filtpattern = NULL;
+ char *ldaphost = NULL;
+ char *targetdn = NULL;
+ char *pwattr = LDAP_PASSWD_ATTRIB;
+ char *newpw = NULL;
+ int authmethod = LDAP_AUTH_SIMPLE;
+ int hashtype = HASHTYPE_CRYPT;
+ int i, j;
+ int ldapport = 0;
+ int debug = 0;
+ int scope = LDAP_SCOPE_SUBTREE;
+ int sizelimit = -1;
+ int timelimit = -1;
+ int version = -1;
+ int want_bindpw = 0;
+ int want_newpw = 0;
+ LDAP *ld;
+ Salt salt;
+
+ salt.salt = NULL;
+ salt.len = 0;
+
+ if (argc == 1)
+ usage (argv[0]);
+
+ while ((i = getopt (argc, argv, "a:b:C:D:d:Ee:g:H:h:Kkl:nP:p:s:t:vWw:Y:y:z:")) != EOF)
+ {
+ switch (i)
+ {
+ case 'a': /* password attribute */
+ pwattr = strdup (optarg);
+ break;
+
+ case 'b': /* base search dn */
+ base = strdup (optarg);
+ break;
+
+ case 'C':
+ want_entryhash++;
+ break;
+
+ case 'D': /* bind distinguished name */
+ binddn = strdup (optarg);
+ break;
+
+ case 'd': /* debugging option */
+ debug |= atoi (optarg);
+ break;
+
+ case 'E': /* prompt for new password */
+ want_newpw++;
+ break;
+
+ case 'e': /* new password */
+ newpw = strdup (optarg);
+ break;
+
+ case 'g':
+ auto_gen_pw = strtol (optarg, NULL, 10);
+ break;
+
+ case 'H': /* hashes */
+ for (j = 0; hashes[j].name; j++)
+ {
+ if (!strncasecmp (optarg, hashes[j].name, hashes[j].namesz))
+ {
+ hashtype = hashes[j].type;
+ break;
+ }
+ }
+
+ if (!hashes[j].name)
+ {
+ fprintf (stderr, "hash type: %s is unknown\n", optarg);
+ usage (argv[0]);
+ }
+ break;
+
+ case 'h': /* ldap host */
+ ldaphost = strdup (optarg);
+ break;
+
+ case 'K': /* use kerberos bind, 1st part only */
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV41;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
+ usage (argv[0]);
+#endif
+ break;
+
+ case 'k': /* use kerberos bind */
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV4;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
+ usage (argv[0]);
+#endif
+ break;
+
+ case 'l': /* time limit */
+ timelimit = strtol (optarg, NULL, 10);
+ break;
+
+ case 'n': /* don't update entry(s) */
+ noupdates++;
+ break;
+
+ case 'P':
+ switch( atoi( optarg ) ) {
+ case 2:
+ version = LDAP_VERSION2;
+ break;
+ case 3:
+ version = LDAP_VERSION3;
+ break;
+ default:
+ fprintf( stderr, "protocol version should be 2 or 3\n" );
+ usage( argv[0] );
+ }
+ break;
+
+ case 'p': /* ldap port */
+ ldapport = strtol (optarg, NULL, 10);
+ break;
+
+ case 's': /* scope */
+ if (strcasecmp (optarg, "base") == 0)
+ scope = LDAP_SCOPE_BASE;
+ else if (strcasecmp (optarg, "one") == 0)
+ scope = LDAP_SCOPE_ONELEVEL;
+ else if (strcasecmp (optarg, "sub") == 0)
+ scope = LDAP_SCOPE_SUBTREE;
+ else
+ {
+ fprintf (stderr, "scope should be base, one, or sub\n");
+ usage (argv[0]);
+ }
+ break;
+
+ case 't': /* target dn */
+ targetdn = strdup (optarg);
+ break;
+
+ case 'v': /* verbose */
+ verbose++;
+ break;
+
+ case 'W': /* promt for bind password */
+ want_bindpw++;
+ break;
+
+ case 'w': /* bind password */
+ bindpw = strdup (optarg);
+ {
+ char* p;
+
+ for( p = optarg; *p == '\0'; p++ ) {
+ *p = '*';
+ }
+ }
+ break;
+
+ case 'Y': /* salt length */
+ salt.len = strtol (optarg, NULL, 10);
+ break;
+
+ case 'y': /* user specified salt */
+ salt.len = strlen (optarg);
+ salt.salt = (unsigned char *)strdup (optarg);
+ break;
+
+ case 'z': /* time limit */
+ sizelimit = strtol (optarg, NULL, 10);
+ break;
+
+ default:
+ usage (argv[0]);
+ }
+ }
+
+ /* grab filter */
+ if (!(argc - optind < 1))
+ filtpattern = strdup (argv[optind]);
+
+ /* check for target(s) */
+ if (!filtpattern && !targetdn)
+ targetdn = binddn;
+
+ /* handle bind password */
+ if (want_bindpw)
+ bindpw = strdup (getpass ("Enter LDAP password: "));
+
+ /* handle new password */
+ if (!newpw)
+ {
+ char *cknewpw;
+ newpw = strdup (getpass ("New password: "));
+ cknewpw = getpass ("Re-enter new password: ");
+
+ if (strncmp (newpw, cknewpw, strlen (newpw)))
+ {
+ fprintf (stderr, "passwords do not match\n");
+ return ( EXIT_FAILURE );
+ }
+ }
+
+ if ( debug ) {
+ if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ }
+
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+ /* seed random number generator */
+
+#ifdef HAVE_GETTIMEOFDAY
+ /* this is of questionable value
+ * gettimeofday may not provide much usec
+ */
+ {
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ srand(tv.tv_sec * (tv.tv_usec + 1));
+ }
+#else
+ /* The traditional seed */
+ srand((unsigned)time( NULL ));
+#endif
+
+ /* connect to server */
+ if ((ld = ldap_init (ldaphost, ldapport)) == NULL)
+ {
+ perror ("ldap_init");
+ return ( EXIT_FAILURE );
+ }
+
+ /* set options */
+ if (timelimit != -1 &&
+ ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS )
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_TIMELIMIT %d\n", timelimit );
+ }
+ if (sizelimit != -1 &&
+ ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) != LDAP_OPT_SUCCESS )
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_SIZELIMIT %d\n", sizelimit );
+ }
+
+ /* this seems prudent */
+ {
+ int deref = LDAP_DEREF_NEVER;
+ ldap_set_option( ld, LDAP_OPT_DEREF, &deref);
+ }
+
+ if (version != -1 &&
+ ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS )
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
+ }
+
+ /* authenticate to server */
+ if (ldap_bind_s (ld, binddn, bindpw, authmethod) != LDAP_SUCCESS)
+ {
+ ldap_perror (ld, "ldap_bind");
+ return ( EXIT_FAILURE );
+ }
+
+ if (targetdn)
+ {
+ if (want_entryhash)
+ {
+ /* insert code here =) */
+ }
+ else
+ modify_dn (ld, targetdn, pwattr, NULL, newpw, hashtype, &salt);
+ }
+
+ if (filtpattern)
+ {
+ char filter[BUFSIZ];
+ LDAPMessage *result = NULL, *e;
+ char *attrs[2];
+ attrs[0] = pwattr;
+ attrs[1] = NULL;
+
+ /* search */
+ sprintf (filter, "%s", filtpattern);
+ i = ldap_search_s (ld, base, scope, filter, attrs, 0, &result);
+ if (i != LDAP_SUCCESS &&
+ i != LDAP_TIMELIMIT_EXCEEDED &&
+ i != LDAP_SIZELIMIT_EXCEEDED)
+ {
+ ldap_perror (ld, "ldap_search");
+ return ( EXIT_FAILURE );
+ }
+
+ for (e = ldap_first_entry (ld, result); e; e = ldap_next_entry (ld, e))
+ {
+ char *dn = ldap_get_dn (ld, e);
+ if (dn)
+ {
+ struct berval **pw_vals = ldap_get_values_len (ld, e, pwattr);
+ modify_dn (ld, dn, pwattr, pw_vals ? pw_vals[0]->bv_val : NULL, newpw, hashtype, &salt);
+ if (pw_vals)
+ ldap_value_free_len (pw_vals);
+ free (dn);
+ }
+ }
+ }
+
+ /* disconnect from server */
+ ldap_unbind (ld);
+
+ return ( EXIT_SUCCESS );
+}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <lber.h>
-#include <ldap.h>
-#include <ldif.h>
-#include "ldapconfig.h"
+#include <ac/stdlib.h>
-#define DEFSEP "="
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include <ldap.h>
-#ifdef LDAP_DEBUG
-extern int ldap_debug, lber_debug;
-#endif /* LDAP_DEBUG */
+#include "ldif.h"
+#include "ldap_defaults.h"
+#define DEFSEP "="
-usage( s )
-char *s;
+static void
+usage( char *s )
{
- fprintf( stderr, "usage: %s [options] filter [attributes...]\nwhere:\n", s );
- fprintf( stderr, " filter\tRFC-1558 compliant LDAP search filter\n" );
- fprintf( stderr, " attributes\twhitespace-separated list of attributes to retrieve\n" );
- fprintf( stderr, "\t\t(if no attribute list is given, all are retrieved)\n" );
- fprintf( stderr, "options:\n" );
- fprintf( stderr, " -n\t\tshow what would be done but don't actually search\n" );
- fprintf( stderr, " -v\t\trun in verbose mode (diagnostics to standard output)\n" );
- fprintf( stderr, " -t\t\twrite values to files in /tmp\n" );
- fprintf( stderr, " -u\t\tinclude User Friendly entry names in the output\n" );
- fprintf( stderr, " -A\t\tretrieve attribute names only (no values)\n" );
- fprintf( stderr, " -B\t\tdo not suppress printing of non-ASCII values\n" );
- fprintf( stderr, " -L\t\tprint entries in LDIF format (-B is implied)\n" );
-#ifdef LDAP_REFERRALS
- fprintf( stderr, " -R\t\tdo not automatically follow referrals\n" );
-#endif /* LDAP_REFERRALS */
- fprintf( stderr, " -d level\tset LDAP debugging level to `level'\n" );
- fprintf( stderr, " -F sep\tprint `sep' instead of `=' between attribute names and values\n" );
- fprintf( stderr, " -S attr\tsort the results by attribute `attr'\n" );
- fprintf( stderr, " -f file\tperform sequence of searches listed in `file'\n" );
- fprintf( stderr, " -b basedn\tbase dn for search\n" );
- fprintf( stderr, " -s scope\tone of base, one, or sub (search scope)\n" );
- fprintf( stderr, " -a deref\tone of never, always, search, or find (alias dereferencing)\n" );
- fprintf( stderr, " -l time lim\ttime limit (in seconds) for search\n" );
- fprintf( stderr, " -z size lim\tsize limit (in entries) for search\n" );
- fprintf( stderr, " -D binddn\tbind dn\n" );
- fprintf( stderr, " -w passwd\tbind passwd (for simple authentication)\n" );
-#ifdef KERBEROS
- fprintf( stderr, " -k\t\tuse Kerberos instead of Simple Password authentication\n" );
+ fprintf( stderr,
+"usage: %s [options] filter [attributes...]\nwhere:\n"
+" filter\tRFC-1558 compliant LDAP search filter\n"
+" attributes\twhitespace-separated list of attributes to retrieve\n"
+"\t\t1.1 -- no attributes\n"
+"\t\t* -- all user attributes\n"
+"\t\t+ -- all operational attributes\n"
+"\t\tempty list -- all non-operational attributes\n"
+"options:\n"
+" -n\t\tshow what would be done but don't actually search\n"
+" -v\t\trun in verbose mode (diagnostics to standard output)\n"
+" -t\t\twrite binary values to files in TMPDIR\n"
+" -tt\t\twrite all values to files in TMPDIR\n"
+" -T path\twrite files to directory specified by path (default: \"/tmp\")\n"
+" -V prefix\tURL prefix for files (default: \"file://tmp/\"\n"
+" -u\t\tinclude User Friendly entry names in the output\n"
+" -A\t\tretrieve attribute names only (no values)\n"
+" -B\t\tdo not suppress printing of binary values\n"
+" -F sep\tprint `sep' instead of `=' between attribute names and values\n"
+" -L\t\tprint entries in LDIF format (implies -B)\n"
+" -LL\t\tprint entries in LDIF format without comments\n"
+" -LLL\t\tprint entries in LDIF format without comments and version\n"
+" -M\t\tenable Manage DSA IT control (-MM to make critical)\n"
+" -R\t\tdo not automatically follow referrals\n"
+" -S attr\tsort the results by attribute `attr'\n"
+" -d level\tset LDAP debugging level to `level'\n"
+" -f file\tperform sequence of searches listed in `file'\n"
+" -b basedn\tbase dn for search\n"
+" -s scope\tone of base, one, or sub (search scope)\n"
+" -a deref\tone of never, always, search, or find (alias dereferencing)\n"
+" -l limit\ttime limit (in seconds) for search\n"
+" -z limit\tsize limit (in entries) for search\n"
+" -D binddn\tbind dn\n"
+" -w passwd\tbind passwd (for simple authentication)\n"
+" -W\t\tprompt for bind passwd\n"
+#ifdef HAVE_KERBEROS
+" -k\t\tuse Kerberos instead of Simple Password authentication\n"
#endif
- fprintf( stderr, " -h host\tldap server\n" );
- fprintf( stderr, " -p port\tport on ldap server\n" );
- exit( 1 );
+" -h host\tldap server\n"
+" -p port\tport on ldap server\n"
+" -P version\tprocotol version (2 or 3)\n"
+, s );
+
+ exit( EXIT_FAILURE );
}
-static char *binddn = LDAPSEARCH_BINDDN;
+static void print_entry LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ int attrsonly));
+
+static int write_ldif LDAP_P((
+ int type,
+ char *name,
+ char *value,
+ ber_len_t vallen ));
+
+static int dosearch LDAP_P((
+ LDAP *ld,
+ char *base,
+ int scope,
+ char **attrs,
+ int attrsonly,
+ char *filtpatt,
+ char *value));
+
+#define TMPDIR "/tmp"
+#define URLPRE "file:/tmp/"
+
+static char *tmpdir = NULL;
+static char *urlpre = NULL;
+
+static char *binddn = NULL;
static char *passwd = NULL;
-static char *base = LDAPSEARCH_BASE;
-static char *ldaphost = LDAPHOST;
-static int ldapport = LDAP_PORT;
+static char *base = NULL;
+static char *ldaphost = NULL;
+static int ldapport = 0;
static char *sep = DEFSEP;
static char *sortattr = NULL;
static int skipsortattr = 0;
-static int verbose, not, includeufn, allow_binary, vals2tmp, ldif;
+static int verbose, not, includeufn, binary, vals2tmp, ldif;
-main( argc, argv )
-int argc;
-char **argv;
+int
+main( int argc, char **argv )
{
- char *infile, *filtpattern, **attrs, line[ BUFSIZ ];
- FILE *fp;
- int rc, i, first, scope, kerberos, deref, attrsonly;
- int ldap_options, timelimit, sizelimit, authmethod;
- LDAP *ld;
- extern char *optarg;
- extern int optind;
-
- infile = NULL;
- deref = verbose = allow_binary = not = kerberos = vals2tmp =
- attrsonly = ldif = 0;
-#ifdef LDAP_REFERRALS
- ldap_options = LDAP_OPT_REFERRALS;
-#else /* LDAP_REFERRALS */
- ldap_options = 0;
-#endif /* LDAP_REFERRALS */
- sizelimit = timelimit = 0;
- scope = LDAP_SCOPE_SUBTREE;
-
- while (( i = getopt( argc, argv,
-#ifdef KERBEROS
- "KknuvtRABLD:s:f:h:b:d:p:F:a:w:l:z:S:"
-#else
- "nuvtRABLD:s:f:h:b:d:p:F:a:w:l:z:S:"
-#endif
- )) != EOF ) {
+ char *infile, *filtpattern, **attrs, line[ BUFSIZ ];
+ FILE *fp;
+ int rc, i, first, scope, deref, attrsonly, manageDSAit;
+ int referrals, timelimit, sizelimit, debug;
+ int authmethod, version, want_bindpw;
+ LDAP *ld;
+
+ infile = NULL;
+ debug = verbose = binary = not = vals2tmp =
+ attrsonly = manageDSAit = ldif = want_bindpw = 0;
+
+ deref = referrals = sizelimit = timelimit = version = -1;
+
+ scope = LDAP_SCOPE_SUBTREE;
+ authmethod = LDAP_AUTH_SIMPLE;
+
+ while (( i = getopt( argc, argv,
+ "WKknuvtMRABLD:s:f:h:b:d:P:p:F:a:w:l:z:S:T:V:")) != EOF )
+ {
switch( i ) {
case 'n': /* do Not do any searches */
- ++not;
- break;
+ ++not;
+ break;
case 'v': /* verbose mode */
- ++verbose;
- break;
+ ++verbose;
+ break;
case 'd':
-#ifdef LDAP_DEBUG
- ldap_debug = lber_debug = atoi( optarg ); /* */
-#else /* LDAP_DEBUG */
- fprintf( stderr, "compile with -DLDAP_DEBUG for debugging\n" );
-#endif /* LDAP_DEBUG */
- break;
-#ifdef KERBEROS
+ debug |= atoi( optarg );
+ break;
case 'k': /* use kerberos bind */
- kerberos = 2;
- break;
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV4;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
+#endif
+ break;
case 'K': /* use kerberos bind, 1st part only */
- kerberos = 1;
- break;
+#ifdef HAVE_KERBEROS
+ authmethod = LDAP_AUTH_KRBV41;
+#else
+ fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]);
#endif
+ break;
case 'u': /* include UFN */
- ++includeufn;
- break;
+ ++includeufn;
+ break;
case 't': /* write attribute values to /tmp files */
- ++vals2tmp;
- break;
+ ++vals2tmp;
+ break;
+ case 'M':
+ /* enable Manage DSA IT */
+ manageDSAit++;
+ break;
case 'R': /* don't automatically chase referrals */
-#ifdef LDAP_REFERRALS
- ldap_options &= ~LDAP_OPT_REFERRALS;
-#else /* LDAP_REFERRALS */
- fprintf( stderr,
- "compile with -DLDAP_REFERRALS for referral support\n" );
-#endif /* LDAP_REFERRALS */
- break;
+ referrals = (int) LDAP_OPT_OFF;
+ break;
case 'A': /* retrieve attribute names only -- no values */
- ++attrsonly;
- break;
+ ++attrsonly;
+ break;
case 'L': /* print entries in LDIF format */
- ++ldif;
- /* fall through -- always allow binary when outputting LDIF */
+ ++ldif;
+ /* fall through -- always allow binary when outputting LDIF */
case 'B': /* allow binary values to be printed */
- ++allow_binary;
- break;
+ ++binary;
+ break;
case 's': /* search scope */
- if ( strncasecmp( optarg, "base", 4 ) == 0 ) {
+ if ( strcasecmp( optarg, "base" ) == 0 ) {
scope = LDAP_SCOPE_BASE;
- } else if ( strncasecmp( optarg, "one", 3 ) == 0 ) {
+ } else if ( strcasecmp( optarg, "one" ) == 0 ) {
scope = LDAP_SCOPE_ONELEVEL;
- } else if ( strncasecmp( optarg, "sub", 3 ) == 0 ) {
+ } else if ( strcasecmp( optarg, "sub" ) == 0 ) {
scope = LDAP_SCOPE_SUBTREE;
- } else {
+ } else {
fprintf( stderr, "scope should be base, one, or sub\n" );
usage( argv[ 0 ] );
- }
- break;
+ }
+ break;
case 'a': /* set alias deref option */
- if ( strncasecmp( optarg, "never", 5 ) == 0 ) {
+ if ( strcasecmp( optarg, "never" ) == 0 ) {
deref = LDAP_DEREF_NEVER;
- } else if ( strncasecmp( optarg, "search", 5 ) == 0 ) {
+ } else if ( strcasecmp( optarg, "search" ) == 0 ) {
deref = LDAP_DEREF_SEARCHING;
- } else if ( strncasecmp( optarg, "find", 4 ) == 0 ) {
+ } else if ( strcasecmp( optarg, "find" ) == 0 ) {
deref = LDAP_DEREF_FINDING;
- } else if ( strncasecmp( optarg, "always", 6 ) == 0 ) {
+ } else if ( strcasecmp( optarg, "always" ) == 0 ) {
deref = LDAP_DEREF_ALWAYS;
- } else {
+ } else {
fprintf( stderr, "alias deref should be never, search, find, or always\n" );
usage( argv[ 0 ] );
- }
- break;
-
+ }
+ break;
+
+ case 'T': /* field separator */
+ if( tmpdir ) free( tmpdir );
+ tmpdir = strdup( optarg );
+ break;
+ case 'V': /* field separator */
+ if( urlpre ) free( urlpre );
+ urlpre = strdup( optarg );
+ break;
case 'F': /* field separator */
- sep = strdup( optarg );
- break;
+ sep = strdup( optarg );
+ break;
case 'f': /* input file */
- infile = strdup( optarg );
- break;
+ infile = strdup( optarg );
+ break;
case 'h': /* ldap host */
- ldaphost = strdup( optarg );
- break;
+ ldaphost = strdup( optarg );
+ break;
case 'b': /* searchbase */
- base = strdup( optarg );
- break;
+ base = strdup( optarg );
+ break;
case 'D': /* bind DN */
- binddn = strdup( optarg );
- break;
+ binddn = strdup( optarg );
+ break;
case 'p': /* ldap port */
- ldapport = atoi( optarg );
- break;
+ ldapport = atoi( optarg );
+ break;
case 'w': /* bind password */
- passwd = strdup( optarg );
- break;
+ passwd = strdup( optarg );
+ {
+ char* p;
+
+ for( p = optarg; *p == '\0'; p++ ) {
+ *p = '*';
+ }
+ }
+ break;
case 'l': /* time limit */
- timelimit = atoi( optarg );
- break;
+ timelimit = atoi( optarg );
+ break;
case 'z': /* size limit */
- sizelimit = atoi( optarg );
- break;
+ sizelimit = atoi( optarg );
+ break;
case 'S': /* sort attribute */
- sortattr = strdup( optarg );
- break;
- default:
- usage( argv[0] );
- }
- }
-
- if ( argc - optind < 1 ) {
- usage( argv[ 0 ] );
- }
- filtpattern = strdup( argv[ optind ] );
- if ( argv[ optind + 1 ] == NULL ) {
- attrs = NULL;
- } else if ( sortattr == NULL || *sortattr == '\0' ) {
- attrs = &argv[ optind + 1 ];
- } else {
- for ( i = optind + 1; i < argc; i++ ) {
- if ( strcasecmp( argv[ i ], sortattr ) == 0 ) {
+ sortattr = strdup( optarg );
+ break;
+ case 'W':
+ want_bindpw++;
break;
- }
+ case 'P':
+ switch( atoi( optarg ) )
+ {
+ case 2:
+ version = LDAP_VERSION2;
+ break;
+ case 3:
+ version = LDAP_VERSION3;
+ break;
+ default:
+ fprintf( stderr, "protocol version should be 2 or 3\n" );
+ usage( argv[0] );
+ }
+ break;
+ default:
+ usage( argv[0] );
}
- if ( i == argc ) {
- skipsortattr = 1;
- argv[ optind ] = sortattr;
+ }
+
+ if ( argc - optind < 1 ) {
+ usage( argv[ 0 ] );
+ }
+
+ filtpattern = strdup( argv[ optind ] );
+
+ if ( argv[ optind + 1 ] == NULL ) {
+ attrs = NULL;
+ } else if ( sortattr == NULL || *sortattr == '\0' ) {
+ attrs = &argv[ optind + 1 ];
} else {
- optind++;
+ for ( i = optind + 1; i < argc; i++ ) {
+ if ( strcasecmp( argv[ i ], sortattr ) == 0 ) {
+ break;
+ }
+ }
+ if ( i == argc ) {
+ skipsortattr = 1;
+ argv[ optind ] = sortattr;
+ } else {
+ optind++;
+ }
+ attrs = &argv[ optind ];
}
- attrs = &argv[ optind ];
- }
- if ( infile != NULL ) {
- if ( infile[0] == '-' && infile[1] == '\0' ) {
- fp = stdin;
- } else if (( fp = fopen( infile, "r" )) == NULL ) {
- perror( infile );
- exit( 1 );
+ if ( infile != NULL ) {
+ if ( infile[0] == '-' && infile[1] == '\0' ) {
+ fp = stdin;
+ } else if (( fp = fopen( infile, "r" )) == NULL ) {
+ perror( infile );
+ return EXIT_FAILURE;
+ }
}
- }
- if ( verbose ) {
- printf( "ldap_open( %s, %d )\n", ldaphost, ldapport );
- }
+ if( tmpdir == NULL
+ && (tmpdir = getenv("TMPDIR")) == NULL
+ && (tmpdir = getenv("TMP")) == NULL
+ && (tmpdir = getenv("TEMP")) == NULL )
+ {
+ tmpdir = "/tmp";
+ }
- if (( ld = ldap_open( ldaphost, ldapport )) == NULL ) {
- perror( ldaphost );
- exit( 1 );
- }
+ if( urlpre == NULL ) {
+ urlpre = malloc( sizeof("file:///") + strlen(tmpdir) );
- ld->ld_deref = deref;
- ld->ld_timelimit = timelimit;
- ld->ld_sizelimit = sizelimit;
- ld->ld_options = ldap_options;
+ if( urlpre == NULL ) {
+ perror( "malloc" );
+ return EXIT_FAILURE;
+ }
- if ( !kerberos ) {
- authmethod = LDAP_AUTH_SIMPLE;
- } else if ( kerberos == 1 ) {
- authmethod = LDAP_AUTH_KRBV41;
- } else {
- authmethod = LDAP_AUTH_KRBV4;
- }
- if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) {
- ldap_perror( ld, "ldap_bind" );
- exit( 1 );
- }
-
- if ( verbose ) {
- printf( "filter pattern: %s\nreturning: ", filtpattern );
- if ( attrs == NULL ) {
- printf( "ALL" );
- } else {
- for ( i = 0; attrs[ i ] != NULL; ++i ) {
- printf( "%s ", attrs[ i ] );
- }
+ sprintf( urlpre, "file:///%s/",
+ tmpdir[0] == '/' ? &tmpdir[1] : tmpdir );
+
+ /* urlpre should be URLized.... */
}
- putchar( '\n' );
- }
- if ( infile == NULL ) {
- rc = dosearch( ld, base, scope, attrs, attrsonly, filtpattern, "" );
- } else {
- rc = 0;
- first = 1;
- while ( rc == 0 && fgets( line, sizeof( line ), fp ) != NULL ) {
- line[ strlen( line ) - 1 ] = '\0';
- if ( !first ) {
- putchar( '\n' );
- } else {
- first = 0;
- }
- rc = dosearch( ld, base, scope, attrs, attrsonly, filtpattern,
- line );
+ if ( debug ) {
+ if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
+ }
+ ldif_debug = debug;
+ }
+
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+
+ if ( verbose ) {
+ fprintf( stderr,
+ (ldapport ? "ldap_init( %s, %d )\n" : "ldap_init( %s, <DEFAULT> )\n"),
+ (ldaphost != NULL) ? ldaphost : "<DEFAULT>",
+ ldapport );
+ }
+
+ if (( ld = ldap_init( ldaphost, ldapport )) == NULL ) {
+ perror( "ldap_init" );
+ return( EXIT_FAILURE );
+ }
+
+ if (deref != -1 &&
+ ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref ) != LDAP_OPT_SUCCESS )
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_DEREF %d\n", deref );
+ }
+ if (timelimit != -1 &&
+ ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS )
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_TIMELIMIT %d\n", timelimit );
+ }
+ if (sizelimit != -1 &&
+ ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) != LDAP_OPT_SUCCESS )
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_SIZELIMIT %d\n", sizelimit );
+ }
+ if (referrals != -1 &&
+ ldap_set_option( ld, LDAP_OPT_REFERRALS,
+ (referrals ? LDAP_OPT_ON : LDAP_OPT_OFF) ) != LDAP_OPT_SUCCESS )
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
+ referrals ? "on" : "off" );
+ }
+
+ if (version != -1 &&
+ ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS )
+ {
+ fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
+ }
+
+ if (want_bindpw) {
+ passwd = getpass("Enter LDAP Password: ");
+ }
+
+ if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_bind" );
+ return( EXIT_FAILURE );
}
- if ( fp != stdin ) {
- fclose( fp );
+
+ if ( manageDSAit ) {
+ int err;
+ LDAPControl c;
+ LDAPControl *ctrls[2];
+ ctrls[0] = &c;
+ ctrls[1] = NULL;
+
+ c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+ c.ldctl_value.bv_val = NULL;
+ c.ldctl_value.bv_len = 0;
+ c.ldctl_iscritical = manageDSAit > 1;
+
+ err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+ if( err != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+ if( c.ldctl_iscritical ) {
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
+
+ if ( verbose ) {
+ fprintf( stderr, "filter%s: %s\nreturning: ",
+ infile != NULL ? " pattern" : "",
+ filtpattern );
+
+ if ( attrs == NULL ) {
+ fprintf( stderr, "ALL" );
+ } else {
+ for ( i = 0; attrs[ i ] != NULL; ++i ) {
+ fprintf( stderr, "%s ", attrs[ i ] );
+ }
+ }
+ fprintf( stderr, "\n" );
+ }
+
+ if ( ldif ) {
+ if (ldif < 3 ) {
+ printf( "version: 1\n\n");
+ }
+
+ if (ldif < 2 ) {
+ printf( "#\n# filter%s: %s\n# returning: ",
+ infile != NULL ? " pattern" : "",
+ filtpattern );
+
+ if ( attrs == NULL ) {
+ printf( "ALL" );
+ } else {
+ for ( i = 0; attrs[ i ] != NULL; ++i ) {
+ printf( "%s ", attrs[ i ] );
+ }
+ }
+ printf( "\n#\n\n" );
+ }
+ }
+
+ if ( infile == NULL ) {
+ rc = dosearch( ld, base, scope, attrs, attrsonly, NULL, filtpattern );
+
+ } else {
+ rc = 0;
+ first = 1;
+ while ( rc == 0 && fgets( line, sizeof( line ), fp ) != NULL ) {
+ line[ strlen( line ) - 1 ] = '\0';
+ if ( !first ) {
+ putchar( '\n' );
+ } else {
+ first = 0;
+ }
+ rc = dosearch( ld, base, scope, attrs, attrsonly,
+ filtpattern, line );
+ }
+ if ( fp != stdin ) {
+ fclose( fp );
+ }
}
- }
- ldap_unbind( ld );
- exit( rc );
+ ldap_unbind( ld );
+ return( rc );
}
-dosearch( ld, base, scope, attrs, attrsonly, filtpatt, value )
- LDAP *ld;
- char *base;
- int scope;
- char **attrs;
- int attrsonly;
- char *filtpatt;
- char *value;
+static int dosearch(
+ LDAP *ld,
+ char *base,
+ int scope,
+ char **attrs,
+ int attrsonly,
+ char *filtpatt,
+ char *value)
{
- char filter[ BUFSIZ ], **val;
- int rc, first, matches;
- LDAPMessage *res, *e;
+ char filter[ BUFSIZ ];
+ int rc, first, matches;
+ LDAPMessage *res, *e;
+
+ if( filtpatt != NULL ) {
+ sprintf( filter, filtpatt, value );
+
+ if ( verbose ) {
+ fprintf( stderr, "filter is: (%s)\n", filter );
+ }
+
+ if( ldif == 1 ) {
+ printf( "#\n# filter: %s\n#\n", filter );
+ }
- sprintf( filter, filtpatt, value );
+ } else {
+ sprintf( filter, "%s", value );
+ }
- if ( verbose ) {
- printf( "filter is: (%s)\n", filter );
- }
+ if ( not ) {
+ return( LDAP_SUCCESS );
+ }
- if ( not ) {
- return( LDAP_SUCCESS );
- }
+ if ( ldap_search( ld, base, scope, filter, attrs, attrsonly ) == -1 ) {
+ int ld_errno;
+ ldap_perror( ld, "ldap_search" );
- if ( ldap_search( ld, base, scope, filter, attrs, attrsonly ) == -1 ) {
- ldap_perror( ld, "ldap_search" );
- return( ld->ld_errno );
- }
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+ return( ld_errno );
+ }
- matches = 0;
- first = 1;
- while ( (rc = ldap_result( ld, LDAP_RES_ANY, sortattr ? 1 : 0, NULL, &res ))
- == LDAP_RES_SEARCH_ENTRY ) {
+ matches = 0;
+ first = 1;
+ res = NULL;
+ while ( (rc = ldap_result( ld, LDAP_RES_ANY, sortattr ? 1 : 0, NULL, &res ))
+ == LDAP_RES_SEARCH_ENTRY ) {
matches++;
e = ldap_first_entry( ld, res );
if ( !first ) {
- putchar( '\n' );
+ putchar( '\n' );
} else {
- first = 0;
+ first = 0;
}
print_entry( ld, e, attrsonly );
ldap_msgfree( res );
- }
- if ( rc == -1 ) {
+ res = NULL;
+ }
+ if ( rc == -1 ) {
ldap_perror( ld, "ldap_result" );
return( rc );
- }
- if (( rc = ldap_result2error( ld, res, 0 )) != LDAP_SUCCESS ) {
- ldap_perror( ld, "ldap_search" );
- }
- if ( sortattr != NULL ) {
- extern int strcasecmp();
-
- (void) ldap_sort_entries( ld, &res,
- ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp );
- matches = 0;
- first = 1;
- for ( e = ldap_first_entry( ld, res ); e != NULLMSG;
- e = ldap_next_entry( ld, e ) ) {
+ }
+ if (( rc = ldap_result2error( ld, res, 0 )) != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_search" );
+ }
+ if ( sortattr != NULL ) {
+ (void) ldap_sort_entries( ld, &res,
+ ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp );
+ matches = 0;
+ first = 1;
+ for ( e = ldap_first_entry( ld, res ); e != NULL;
+ e = ldap_next_entry( ld, e ) ) {
matches++;
if ( !first ) {
- putchar( '\n' );
+ putchar( '\n' );
} else {
- first = 0;
+ first = 0;
}
print_entry( ld, e, attrsonly );
- }
- }
+ }
+ }
- if ( verbose ) {
- printf( "%d matches\n", matches );
- }
+ if ( verbose ) {
+ printf( "%d matches\n", matches );
+ }
- ldap_msgfree( res );
- return( rc );
+ ldap_msgfree( res );
+ return( rc );
}
-print_entry( ld, entry, attrsonly )
- LDAP *ld;
- LDAPMessage *entry;
- int attrsonly;
+void print_entry(
+ LDAP *ld,
+ LDAPMessage *entry,
+ int attrsonly)
{
- char *a, *dn, *ufn, tmpfname[ 64 ];
- int i, j, notascii;
- BerElement *ber;
- struct berval **bvals;
- FILE *tmpfp;
- extern char *mktemp();
-
- dn = ldap_get_dn( ld, entry );
- if ( ldif ) {
- write_ldif_value( "dn", dn, strlen( dn ));
- } else {
- printf( "%s\n", dn );
- }
- if ( includeufn ) {
- ufn = ldap_dn2ufn( dn );
+ char *a, *dn, *ufn;
+ char tmpfname[ 256 ];
+ char url[ 256 ];
+ int i;
+ BerElement *ber = NULL;
+ struct berval **bvals;
+ FILE *tmpfp;
+
+ dn = ldap_get_dn( ld, entry );
+ ufn = NULL;
+
+ if ( ldif == 1 ) {
+ ufn = ldap_dn2ufn( dn );
+ write_ldif( LDIF_PUT_COMMENT, NULL, ufn, strlen( ufn ));
+ }
if ( ldif ) {
- write_ldif_value( "ufn", ufn, strlen( ufn ));
+ write_ldif( LDIF_PUT_VALUE, "dn", dn, strlen( dn ));
} else {
- printf( "%s\n", ufn );
- }
- free( ufn );
- }
- free( dn );
-
- for ( a = ldap_first_attribute( ld, entry, &ber ); a != NULL;
- a = ldap_next_attribute( ld, entry, ber ) ) {
- if ( skipsortattr && strcasecmp( a, sortattr ) == 0 ) {
- continue;
- }
- if ( attrsonly ) {
- if ( ldif ) {
- write_ldif_value( a, "", 0 );
- } else {
- printf( "%s\n", a );
- }
- } else if (( bvals = ldap_get_values_len( ld, entry, a )) != NULL ) {
- for ( i = 0; bvals[i] != NULL; i++ ) {
- if ( vals2tmp ) {
- sprintf( tmpfname, "/tmp/ldapsearch-%s-XXXXXX", a );
- tmpfp = NULL;
-
- if ( mktemp( tmpfname ) == NULL ) {
- perror( tmpfname );
- } else if (( tmpfp = fopen( tmpfname, "w")) == NULL ) {
- perror( tmpfname );
- } else if ( fwrite( bvals[ i ]->bv_val,
- bvals[ i ]->bv_len, 1, tmpfp ) == 0 ) {
- perror( tmpfname );
- } else if ( ldif ) {
- write_ldif_value( a, tmpfname, strlen( tmpfname ));
- } else {
- printf( "%s%s%s\n", a, sep, tmpfname );
- }
-
- if ( tmpfp != NULL ) {
- fclose( tmpfp );
- }
+ printf( "%s\n", dn );
+ }
+
+ if ( includeufn ) {
+ if( ufn == NULL ) {
+ ufn = ldap_dn2ufn( dn );
+ }
+ if ( ldif ) {
+ write_ldif( LDIF_PUT_VALUE, "ufn", ufn, strlen( ufn ));
} else {
- notascii = 0;
- if ( !allow_binary ) {
- for ( j = 0; j < bvals[ i ]->bv_len; ++j ) {
- if ( !isascii( bvals[ i ]->bv_val[ j ] )) {
- notascii = 1;
- break;
- }
+ printf( "%s\n", ufn );
+ }
+ }
+
+ if( ufn != NULL ) ldap_memfree( ufn );
+ ldap_memfree( dn );
+
+ for ( a = ldap_first_attribute( ld, entry, &ber ); a != NULL;
+ a = ldap_next_attribute( ld, entry, ber ) )
+ {
+ if ( skipsortattr && strcasecmp( a, sortattr ) == 0 ) {
+ continue;
+ }
+
+ if ( attrsonly ) {
+ if ( ldif ) {
+ write_ldif( LDIF_PUT_NOVALUE, a, NULL, 0 );
+ } else {
+ printf( "%s\n", a );
}
- }
-
- if ( ldif ) {
- write_ldif_value( a, bvals[ i ]->bv_val,
- bvals[ i ]->bv_len );
- } else {
- printf( "%s%s%s\n", a, sep,
- notascii ? "NOT ASCII" : bvals[ i ]->bv_val );
- }
+
+ } else if (( bvals = ldap_get_values_len( ld, entry, a )) != NULL ) {
+ for ( i = 0; bvals[i] != NULL; i++ ) {
+ if ( vals2tmp > 1 || ( vals2tmp
+ && ldif_is_not_printable( bvals[i]->bv_val, bvals[i]->bv_len ) ))
+ {
+ /* write value to file */
+ sprintf( tmpfname, "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX",
+ tmpdir, a );
+ tmpfp = NULL;
+
+ if ( mktemp( tmpfname ) == NULL ) {
+ perror( tmpfname );
+ continue;
+ }
+
+ if (( tmpfp = fopen( tmpfname, "w")) == NULL ) {
+ perror( tmpfname );
+ continue;
+ }
+
+ if ( fwrite( bvals[ i ]->bv_val,
+ bvals[ i ]->bv_len, 1, tmpfp ) == 0 )
+ {
+ perror( tmpfname );
+ fclose( tmpfp );
+ continue;
+ }
+
+ fclose( tmpfp );
+
+ sprintf( url, "%s%s", urlpre,
+ &tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] );
+
+ if ( ldif ) {
+ write_ldif( LDIF_PUT_URL, a, url, strlen( url ));
+ } else {
+ printf( "%s%s%s\n", a, sep, url );
+ }
+
+
+ } else {
+ if ( ldif ) {
+ write_ldif( LDIF_PUT_VALUE, a,
+ bvals[ i ]->bv_val, bvals[ i ]->bv_len );
+
+ } else {
+ int notprint = !binary && !vals2tmp
+ && ldif_is_not_printable( bvals[i]->bv_val,
+ bvals[i]->bv_len );
+ printf( "%s%s", a, sep );
+ puts( notprint ? "NOT PRINTABLE" : bvals[ i ]->bv_val );
+ }
+ }
+ }
+ ber_bvecfree( bvals );
}
- }
- ber_bvecfree( bvals );
}
- }
+
+ if( ber != NULL ) {
+ ber_free( ber, 0 );
+ }
}
int
-write_ldif_value( char *type, char *value, unsigned long vallen )
+write_ldif( int type, char *name, char *value, ber_len_t vallen )
{
- char *ldif;
+ char *ldif;
- if (( ldif = ldif_type_and_value( type, value, (int)vallen )) == NULL ) {
- return( -1 );
- }
+ if (( ldif = ldif_put( type, name, value, vallen )) == NULL ) {
+ return( -1 );
+ }
- fputs( ldif, stdout );
- free( ldif );
+ fputs( ldif, stdout );
+ ber_memfree( ldif );
- return( 0 );
+ return( 0 );
}
--- /dev/null
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ldapsearch"=.\ldapsearch.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "liblber"=..\..\libraries\liblber\liblber.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libldap"=..\..\libraries\libldap\libldap.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libldif"=..\..\libraries\libldif\libldif.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "liblutil"=..\..\libraries\liblutil\liblutil.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "setup"=..\..\include\setup.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+SRCS= main.c find.c mod.c print.c auth.c util.c help.c \
+ string_to_key.c group.c edit.c globals.c
+XSRCS= version.c
+OBJS= main.o find.o mod.o print.o auth.o util.o help.o \
+ string_to_key.o group.o globals.o edit.o
+HDRS= ud.h
+PROGRAMS= ud
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldif -lldap -llber -llutil
+XXLIBS = $(TERMCAP_LIBS) $(SECURITY_LIBS) $(LUTIL_LIBS)
+
+ud : version.o
+ $(LTLINK) -o $@ version.o $(OBJS) $(LIBS)
+
+version.c: ${OBJS} $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) -s -c -n Version UserDirectory > $@
+
+install-local: FORCE
+ -$(MKDIR) $(bindir)
+ -mv -f $(bindir)/ud $(bindir)/ud-
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 ud $(bindir)
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/krb.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_PWD_H
#include <pwd.h>
-#include <string.h>
-#include <ctype.h>
-#include <lber.h>
-#include <ldap.h>
-#include <ldapconfig.h>
-#include "ud.h"
-#ifdef KERBEROS
-#include <sys/types.h>
-#include <krb.h>
#endif
-extern LDAP *ld; /* our LDAP descriptor */
-extern int verbose; /* verbosity indicator */
-extern char *mygetpass(); /* getpass() passwds are too short */
+#include <lber.h>
+#include <ldap.h>
-#ifdef DEBUG
-extern int debug; /* debug flag */
-#endif
+#include "ldap_defaults.h"
+#include "ud.h"
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
static char tktpath[20]; /* ticket file path */
static int kinit();
static int valid_tgt();
#endif
-auth(who, implicit)
-char *who;
-int implicit;
+static void set_bound_dn(char *s);
+
+
+int
+auth( char *who, int implicit )
{
int rc; /* return code from ldap_bind() */
- char *passwd = NULL; /* returned by mygetpass() */
+ char *passwd = NULL; /* returned by getpass() */
char **rdns; /* for fiddling with the DN */
int authmethod;
int name_provided; /* was a name passed in? */
+#ifdef HAVE_GETPWUID
struct passwd *pw; /* for getting user id */
+#else
+ char *user;
+#endif
char uidname[20];
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
char **krbnames; /* for kerberos names */
int kinited, ikrb;
char buf[5];
static char prompt[MED_BUF_SIZE]; /* place for us to sprintf the prompt */
static char name[MED_BUF_SIZE]; /* place to store the user's name */
static char password[MED_BUF_SIZE]; /* password entered by user */
- extern struct entry Entry; /* look here for a name if needed */
- extern LDAPMessage *find(); /* for looking up 'name' */
- extern char *search_base; /* for printing later */
- extern char *default_bind_object; /* bind as this on failure */
- extern void printbase(); /* used to pretty-print a base */
- extern int bind_status;
- extern void Free();
- static void set_bound_dn();
#ifdef DEBUG
if (debug & D_TRACE)
* The user needs to bind. If <who> is not specified, we
* assume that authenticating as user id is what user wants.
*/
- if (who == NULL && implicit && (pw = getpwuid((uid_t)geteuid()))
- != (struct passwd *) NULL) {
- sprintf(uidname, "uid=%s", pw->pw_name);
- /* who = pw->pw_name; /* */
- who = uidname;
+ if (who == NULL && implicit) {
+ uidname[0] = '\0';
+
+#ifdef HAVE_GETPWUID
+ if ((pw = getpwuid((uid_t)geteuid())) != (struct passwd *) NULL) {
+ sprintf(uidname, "uid=%s", pw->pw_name);
+ }
+#else
+ user = getenv("USER");
+ if(user == NULL) user = getenv("USERNAME");
+ if(user == NULL) user = getenv("LOGNAME");
+
+ if(user != NULL) {
+ sprintf(uidname, "uid=%s", user);
+ }
+#endif
+
+ if(uidname[0] != '\0') {
+ who = uidname;
+ }
}
if ( who == NULL ) {
* from the user. Then perform the ldap_bind().
*/
if ((mp = find(who, TRUE)) == NULL) {
- (void) ldap_msgfree(mp);
printf(" I could not find \"%s\" in the Directory.\n", who);
printf(" I used a search base of ");
printbase("", search_base);
rdns = ldap_explode_dn(Entry.DN, TRUE);
printf(" Authenticating to the directory as \"%s\"...\n", *rdns );
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
/*
* First, if the user has a choice of auth methods, ask which
* one they want to use. if they want kerberos, ask which
if ( hassimple && !kinited ) {
printf(" Which password would you like to use?\n");
- printf(" 1 -> X.500 password\n");
+ printf(" 1 -> LDAP password\n");
#ifdef UOFM
printf(" 2 -> UMICH password (aka Uniqname or Kerberos password)\n");
#else
} else {
#endif
authmethod = LDAP_AUTH_SIMPLE;
- sprintf(prompt, " Enter your X.500 password: ");
+ sprintf(prompt, " Enter your LDAP password: ");
do {
- passwd = mygetpass(prompt);
+ passwd = getpass(prompt);
} while (passwd != NULL && *passwd == '\0');
if (passwd == NULL) {
(void) ldap_value_free(rdns);
return(0);
}
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
}
(void) ldap_value_free(krbnames);
#endif
ldap_flush_cache( ld );
rc = ldap_bind_s(ld, Entry.DN, passwd, authmethod);
if (rc != LDAP_SUCCESS) {
- if (ld->ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
+ int ld_errno;
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+ if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
fprintf(stderr, " Entry has no password\n");
- else if (ld->ld_errno == LDAP_INVALID_CREDENTIALS)
-#ifdef KERBEROS
+ else if (ld_errno == LDAP_INVALID_CREDENTIALS)
+#ifdef HAVE_KERBEROS
if ( authmethod == LDAP_AUTH_KRBV4 ) {
fprintf(stderr, " The Kerberos credentials are invalid.\n");
} else {
#endif
fprintf(stderr, " The password you provided is incorrect.\n");
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
}
#endif
else
ldap_perror(ld, "ldap_bind_s" );
(void) ldap_bind_s(ld, default_bind_object,
- (char *) UD_PASSWD, LDAP_AUTH_SIMPLE);
+ (char *) NULL, LDAP_AUTH_SIMPLE);
if (default_bind_object == NULL)
set_bound_dn(NULL);
else
return(0);
}
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
#define FIVEMINS ( 5 * 60 )
#define TGT "krbtgt"
-str2upper( s )
- char *s;
+static void
+str2upper( char *s )
{
char *p;
for ( p = s; *p != '\0'; ++p ) {
- if ( islower( *p )) {
- *p = toupper( *p );
- }
+ *p = TOUPPER( (unsigned char) *p );
}
}
-static valid_tgt( names )
- char **names;
+static int
+valid_tgt( char **names )
{
int i;
char name[ ANAME_SZ ], inst[ INST_SZ ], realm[ REALM_SZ ];
return( 0 );
}
-#ifdef AFSKERBEROS
+#ifdef HAVE_AFS_KERBEROS
/*
* realm must be uppercase for krb_ routines
*/
str2upper( realm );
-#endif /* AFSKERBEROS */
+#endif /* HAVE_AFS_KERBEROS */
/*
* check ticket file for a valid ticket granting ticket
/*ARGSUSED*/
int
-krbgetpass( user, inst, realm, pw, key )
- char *user, *inst, *realm, *pw;
- C_Block key;
+krbgetpass( char *user, char *inst, char *realm, char *pw, C_Block key )
{
char *p, lcrealm[ REALM_SZ ], prompt[256], *passwd;
sprintf(prompt, " Enter Kerberos password for %s: ", kauth_name );
#endif
do {
- passwd = mygetpass(prompt);
+ passwd = getpass(prompt);
} while (passwd != NULL && *passwd == '\0');
if (passwd == NULL) {
return(-1);
}
-#ifdef AFSKERBEROS
+#ifdef HAVE_AFS_KERBEROS
strcpy( lcrealm, realm );
for ( p = lcrealm; *p != '\0'; ++p ) {
- if ( isupper( *p )) {
- *p = tolower( *p );
- }
+ *p = TOLOWER( (unsigned char) *p );
}
ka_StringToKey( passwd, lcrealm, key );
-#else /* AFSKERBEROS */
+#else /* HAVE_AFS_KERBEROS */
string_to_key( passwd, key );
-#endif /* AFSKERBEROS */
+#endif /* HAVE_AFS_KERBEROS */
return( 0 );
}
-static kinit( kname )
- char *kname;
+static int
+kinit( char *kname )
{
int rc;
char name[ ANAME_SZ ], inst[ INST_SZ ], realm[ REALM_SZ ];
return( -1 );
}
-#ifdef AFSKERBEROS
+#ifdef HAVE_AFS_KERBEROS
/*
* realm must be uppercase for krb_ routines
*/
str2upper( realm );
-#endif /* AFSKERBEROS */
+#endif /* HAVE_AFS_KERBEROS */
rc = krb_get_in_tkt( name, inst, realm, TGT, realm,
DEFAULT_TKT_LIFE, krbgetpass, NULL, NULL );
return( 0 );
}
-destroy_tickets()
+void
+destroy_tickets( void )
{
if ( *tktpath != '\0' ) {
unlink( tktpath );
}
#endif
-static void set_bound_dn(s)
-char *s;
+static void
+set_bound_dn( char *s )
{
- extern void Free();
- extern char *bound_dn;
-
if (bound_dn != NULL)
Free(bound_dn);
- bound_dn = strdup(s);
+ bound_dn = (s == NULL) ? NULL : strdup(s);
}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/time.h>
+#include <ac/wait.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
-#include <sys/wait.h>
-#include <signal.h>
+#endif
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
#include <lber.h>
#include <ldap.h>
-#include <ldapconfig.h>
-#include "ud.h"
-extern struct entry Entry;
-extern int verbose;
-extern LDAP *ld;
+#include "ldap_defaults.h"
+#include "ud.h"
-extern LDAPMessage *find();
+static int load_editor( void );
+static int modifiable( char *s, short flag );
+static int print_attrs_and_values( FILE *fp, struct attribute *attrs, short flag );
+static int ovalues( char *attr );
+static void write_entry( void );
static char *entry_temp_file;
-#ifdef DEBUG
-extern int debug;
-#endif
-edit(who)
-char *who;
+void
+edit( char *who )
{
LDAPMessage *mp; /* returned from find() */
char *dn, **rdns; /* distinguished name */
char name[MED_BUF_SIZE]; /* entry to modify */
- extern int bind_status;
- static int load_editor();
- static int write_entry();
#ifdef DEBUG
if (debug & D_TRACE)
}
dn = ldap_get_dn(ld, ldap_first_entry(ld, mp));
rdns = ldap_explode_dn(dn, TRUE);
- Free(dn);
+ ldap_memfree(dn);
if (verbose) {
printf("\n Editing directory entry \"%s\"...\n", *rdns);
}
(void) ldap_value_free(rdns);
if (load_editor() < 0)
return;
- (void) write_entry();
+ write_entry();
(void) unlink(entry_temp_file);
ldap_uncache_entry(ld, Entry.DN);
return;
}
-static load_editor()
+static int
+load_editor( void )
{
FILE *fp;
char *cp, *editor = UD_DEFAULT_EDITOR;
static char template[MED_BUF_SIZE];
- extern char * mktemp();
- extern int isgroup(), fatal();
- static int print_attrs_and_values();
+#ifndef HAVE_SPAWNLP
int pid;
int status;
+#endif
int rc;
- void (*handler)();
#ifdef DEBUG
if (debug & D_TRACE)
++p;
}
printf(" Using %s as the editor...\n", p );
+#ifndef HAVE_SPAWNLP
sleep(2);
+#endif
+ }
+#ifdef HAVE_SPAWNLP
+ rc = _spawnlp( _P_WAIT, editor, editor, entry_temp_file, NULL );
+ if(rc != 0) {
+ fatal("spawnlp");
}
+#else
if ((pid = fork()) == 0) {
/* child - edit the Directory entry */
- (void) signal(SIGINT, SIG_IGN);
+ (void) SIGNAL(SIGINT, SIG_IGN);
(void) execlp(editor, editor, entry_temp_file, NULL);
/*NOTREACHED*/
(void) fatal(editor);
}
else if (pid > 0) {
/* parent - wait until the child proc is done editing */
- handler = signal(SIGINT, SIG_IGN);
+ RETSIGTYPE (*handler)();
+ handler = SIGNAL(SIGINT, SIG_IGN);
(void) wait(&status);
- (void) signal(SIGINT, handler);
+ (void) SIGNAL(SIGINT, handler);
}
else {
fatal("fork");
/*NOTREACHED*/
}
+#endif
return(0);
}
-static int print_attrs_and_values(fp, attrs, flag)
-FILE *fp;
-struct attribute attrs[];
-short flag;
+static int
+print_attrs_and_values( FILE *fp, struct attribute *attrs, short int flag )
{
- static int modifiable();
register int i, j;
for (i = 0; attrs[i].quipu_name != NULL; i++) {
- if (!modifiable(attrs[i].quipu_name, flag|ATTR_FLAG_MAY_EDIT))
+ if (!modifiable(attrs[i].quipu_name,
+ (short) (flag|ATTR_FLAG_MAY_EDIT)))
+ {
continue;
+ }
+
fprintf(fp, "%s\n", attrs[i].quipu_name);
if ( attrs[i].number_of_values > MAX_VALUES ) {
printf(" The %s attribute has more than %d values.\n",
return( 0 );
}
-static modifiable(s, flag)
-char *s;
-short flag;
+static int
+modifiable( char *s, short int flag )
{
register int i;
- extern struct attribute attrlist[];
for (i = 0; attrlist[i].quipu_name != NULL; i++) {
if (strcasecmp(s, attrlist[i].quipu_name))
return(FALSE);
}
-static write_entry()
+static void
+write_entry( void )
{
int i = 0, j, number_of_values = -1;
LDAPMod *mods[MAX_ATTRS + 1];
LDAPMod *modp = NULL;
- static int ovalues();
- extern char * code_to_str();
- extern void free_mod_struct();
-
/* parse the file and write the values to the Directory */
if ((fp = fopen(entry_temp_file, "r")) == NULL) {
perror("fopen");
cp = line;
if (*cp == '#')
continue;
- if (isspace(*cp)) { /* value */
- while (isspace(*cp))
+ if (isspace((unsigned char)*cp)) { /* value */
+ while (isspace((unsigned char)*cp))
cp++;
values[number_of_values++] = strdup(cp);
if ( number_of_values >= MAX_VALUES ) {
continue;
}
/* attribute */
- while (isspace(*cp))
+ while (isspace((unsigned char)*cp))
cp++;
/*
* If the number of values is greater than zero, then we
return;
}
-static ovalues(attr)
-char *attr;
+static int
+ovalues( char *attr )
{
struct attribute *ap;
*
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <lber.h>
-#include <ldap.h>
-#include <ldapconfig.h>
-#include "ud.h"
-extern LDAPMessage * find();
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
-#ifdef DEBUG
-extern int debug;
+#ifdef HAVE_IO_H
+#include <io.h>
#endif
-extern char *bound_dn, *group_base;
-extern int verbose, bind_status;
-extern struct entry Entry;
-extern LDAP *ld;
+#include <lber.h>
+#include <ldap.h>
+
+#include "ldap_defaults.h"
+#include "ud.h"
+
+static char * bind_and_fetch(char *name);
-extern void Free();
-void add_group(name)
-char *name;
+void
+add_group( char *name )
{
- register int i, idx = 0, prompt = 0;
+ int idx = 0, prompt = 0;
char tmp[BUFSIZ], dn[BUFSIZ];
static LDAPMod *attrs[9];
LDAPMod init_rdn, init_owner, init_domain,
char *init_rdn_value[2], *init_owner_value[2], *init_domain_value[2],
*init_errors_value[MAX_VALUES], *init_joinable_value[2],
*init_request_value[MAX_VALUES];
- extern void ldap_flush_cache();
- extern char * strip_ignore_chars();
#ifdef DEBUG
if (debug & D_TRACE) {
#ifdef DEBUG
if (debug & D_GROUPS) {
- register LDAPMod **lpp;
- register char **cpp;
- register int j;
- extern char * code_to_str();
+ LDAPMod **lpp;
+ char **cpp;
+ int i, j;
printf(" About to call ldap_add()\n");
printf(" ld = 0x%x\n", ld);
printf(" dn = [%s]\n", dn);
#endif
/*
- * Now add this to the X.500 Directory.
+ * Now add this to the LDAP Directory.
*/
if (ldap_add_s(ld, dn, attrs) != 0) {
ldap_perror(ld, " ldap_add_s");
return;
}
-void remove_group(name)
-char *name;
+void
+remove_group( char *name )
{
char *dn, tmp[BUFSIZ];
- static char * bind_and_fetch();
#ifdef DEBUG
if (debug & D_TRACE) {
return;
/*
- * Now remove this from the X.500 Directory.
+ * Now remove this from the LDAP Directory.
*/
if (ldap_delete_s(ld, dn) != 0) {
- if (ld->ld_errno == LDAP_INSUFFICIENT_ACCESS)
+ int ld_errno = 0;
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+ if (ld_errno == LDAP_INSUFFICIENT_ACCESS)
printf(" You do not own the group \"%s\".\n", name);
else
ldap_perror(ld, " ldap_delete_s");
return;
}
-void x_group(action, name)
-int action;
-char *name;
+void
+x_group( int action, char *name )
{
char **vp;
char *values[2], *group_name;
LDAPMod mod, *mods[2];
static char *actions[] = { "join", "resign from", NULL };
- static char * bind_and_fetch();
#ifdef DEBUG
if (debug & D_TRACE) {
#endif
if (ldap_modify_s(ld, bound_dn, mods)) {
- if ((action == G_JOIN) && (ld->ld_errno == LDAP_TYPE_OR_VALUE_EXISTS))
+ int ld_errno = 0;
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+ if ((action == G_JOIN) && (ld_errno == LDAP_TYPE_OR_VALUE_EXISTS))
printf(" You are already subscribed to \"%s\"\n", group_name);
- else if ((action == G_RESIGN) && (ld->ld_errno == LDAP_NO_SUCH_ATTRIBUTE))
+ else if ((action == G_RESIGN) && (ld_errno == LDAP_NO_SUCH_ATTRIBUTE))
printf(" You are not subscribed to \"%s\"\n", group_name);
else
mod_perror(ld);
return;
}
-void bulk_load(group)
-char *group;
+void
+bulk_load( char *group )
{
register int idx_mail, idx_x500;
register int count_mail, count_x500;
}
/*
- * Add the X.500 style names.
+ * Add the LDAP style names.
*/
if (count_x500 > 0) {
mods[0] = &mod;
return;
}
-void purge_group(group)
-char *group;
+void
+purge_group( char *group )
{
int isclean = TRUE;
LDAPMessage *lm;
LDAPMod mod, *mods[2];
char dn[BUFSIZ], tmp[BUFSIZ], *values[2], **vp, **rdns;
- extern char * my_ldap_dn2ufn();
- extern int col_size;
#ifdef DEBUG
if (debug & D_TRACE) {
vp = Entry.attrs[attr_to_index("member")].values;
if (vp == NULL) {
if (verbose)
- printf(" \"%s\" has no X.500 members. There is nothing to purge.\n", group);
+ printf(" \"%s\" has no LDAP members. There is nothing to purge.\n", group);
return;
}
for (; *vp != NULL; vp++) {
return;
}
-void tidy_up()
+void
+tidy_up( void )
{
register int i = 0;
int found_one = 0;
* Names or e-mail addresses. This includes things like group members,
* the errors-to field in groups, and so on.
*/
-void mod_addrDN(group, offset)
-char *group;
-int offset;
+void
+mod_addrDN( char *group, int offset )
{
- extern struct attribute attrlist[];
char s[BUFSIZ], *new_value /* was member */, *values[2];
char attrtype[ 64 ];
- int i;
LDAPMod mod, *mods[2];
LDAPMessage *mp;
}
if (verbose) {
printf("\n");
- format("Values may be specified as a name (which is then looked up in the X.500 Directory) or as a domain-style (i.e., user@domain) e-mail address. Simply hit the RETURN key at the prompt when finished.\n", 75, 2);
+ format("Values may be specified as a name (which is then looked up in the LDAP Directory) or as a domain-style (i.e., user@domain) e-mail address. Simply hit the RETURN key at the prompt when finished.\n", 75, 2);
printf("\n");
}
* "Bryan Beecher" <bryan@umich.edu>
* Bryan Beecher <bryan@umich.edu>
*/
- register char *cp;
+ char *cp;
if (strchr(s, '<') == NULL) {
for (cp = s; *cp != '@'; cp++)
- if (isspace(*cp))
+ if (isspace((unsigned char)*cp))
*cp = '.';
}
new_value = s;
#ifdef DEBUG
if (debug & D_GROUPS) {
- register LDAPMod **lpp;
- register char **cp;
- register int i, j;
+ LDAPMod **lpp;
+ char **cp;
+ int i, j;
printf(" About to call ldap_modify_s()\n");
printf(" ld = 0x%x\n", ld);
printf(" dn = [%s]\n", group);
#endif
if (my_ldap_modify_s(ld, group, mods)) {
- if (ld->ld_errno == LDAP_NO_SUCH_ATTRIBUTE) {
+ int ld_errno = 0;
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+ if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE) {
printf(" Could not locate value \"%s\"\n",
new_value);
continue;
mod.mod_op = LDAP_MOD_DELETE;
#ifdef DEBUG
if (debug & D_GROUPS) {
- register LDAPMod **lpp;
- register char **cp;
- register int i, j;
+ LDAPMod **lpp;
+ char **cp;
+ int i, j;
printf(" About to call ldap_modify_s()\n");
printf(" ld = 0x%x\n", ld);
printf(" dn = [%s]\n", group);
* A "No such attribute" error is no big deal.
* We only wanted to clear the attribute anyhow.
*/
- if (ld->ld_errno != LDAP_NO_SUCH_ATTRIBUTE) {
+ int ld_errno = 0;
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+ if (ld_errno != LDAP_NO_SUCH_ATTRIBUTE) {
mod_perror(ld);
return;
}
}
}
-my_ldap_modify_s(ldap, group, mods)
-LDAP *ldap;
-char *group;
-LDAPMod *mods[];
+int
+my_ldap_modify_s( LDAP *ldap, char *group, LDAPMod **mods )
{
int was_rfc822member, rc;
return(rc);
}
-void list_groups(who)
-char *who;
+void
+list_groups( char *who )
{
LDAPMessage *mp;
char name[BUFSIZ], filter[BUFSIZ], *search_attrs[2];
/* lookup the groups belonging to this person */
sprintf(filter, "owner=%s", dn);
- Free(dn);
+ ldap_memfree(dn);
search_attrs[0] = "cn";
search_attrs[1] = NULL;
if ((rc = ldap_search_s(ld, UD_WHERE_ALL_GROUPS_LIVE, LDAP_SCOPE_SUBTREE,
return;
}
-static char * bind_and_fetch(name)
-char *name;
+static char *
+bind_and_fetch( char *name )
{
LDAPMessage *lm;
char tmp[MED_BUF_SIZE];
- extern char * strip_ignore_chars();
#ifdef DEBUG
if (debug & D_TRACE) {
return(strdup(Entry.DN));
}
-void list_memberships(who)
-char *who;
+void
+list_memberships( char *who )
{
LDAPMessage *mp;
char name[BUFSIZ], filter[BUFSIZ], *search_attrs[2];
/* lookup the groups belonging to this person */
sprintf(filter, "member=%s", dn);
- Free(dn);
+ ldap_memfree(dn);
search_attrs[0] = "cn";
search_attrs[1] = NULL;
ldap_msgfree(mp);
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include <lber.h>
#include <ldap.h>
+
#include "ud.h"
-#ifdef DEBUG
-extern int debug;
-#endif
-print_help(s)
-char *s;
+void
+print_help( char *s )
{
int len; /* command length */
printf("\n Type \"help <command-name>\" to get help about a particular command.");
printf("\n Type \"help options\" to get help about options in brackets above.\n");
#ifdef UOFM
- printf("\n Bugs in ud should be reported via e-mail to: ud-bugs@umich.edu\n" );
+ printf("\n Bugs in ud should be reported via e-mail to: OpenLDAP-its@OpenLDAP.org\n" );
printf("\n For more assistance with ud, contact the ITD Consultants by phoning\n" );
printf(" 764-HELP or by sending e-mail to: consulting.help@umich.edu\n" );
#endif /* UOFM */
format("should be specified as a ordinary name (e.g., 'Friends of maX500').", 75, 15);
printf("\n");
printf(" [where] A place in the Directory needs to be specified. This name\n");
- format("should be specified as an X.500-style name (e.g., 'ou=people, o=University of Michigan, c=United States of America'). In most cases, it is easier to omit the [where] and allow the program to guide you.", 75, 15);
+ format("should be specified as an LDAP-style name (e.g., 'ou=people, o=University of Michigan, c=United States of America'). In most cases, it is easier to omit the [where] and allow the program to guide you.", 75, 15);
printf("\n");
printf(" [who] A person in the Directory needs to be specified. This name\n");
format("can be specified as either a ordinary name (e.g., 'Jane Doe'), or as some other identifying characteristic (e.g., 'uid=babs').", 75, 15);
}
else if (!strncasecmp("groupbase", s, len)) {
printf(" groupbase [where]\n\n");
- format("The syntax and use of this command is identical to the more commonly used 'cb' command. This command sets the base which is used to create groups in the X.500 Directory. Setting the base to a certain value does not necessarily grant the person write-access to that part of the Directory in order to successfully create a group.", 75, 2);
+ format("The syntax and use of this command is identical to the more commonly used 'cb' command. This command sets the base which is used to create groups in the LDAP Directory. Setting the base to a certain value does not necessarily grant the person write-access to that part of the Directory in order to successfully create a group.", 75, 2);
}
else if (!strncasecmp("cd", s, len) || !strncasecmp("cb", s,len)) {
printf(" cb [where]\n");
printf("\n * cb default\n\n");
format("sets the search base to its original default value.", 75, 2);
printf("\n * cb o=Merit Computer Network, c=US\n\n");
- format("sets the search base to organization given, the Merit Computer Network in this case. This comamnd checks the validity of the specified search base, and rejects it if it is not a valid Distinguished Name (DN). A DN uniquely identifies a portion of the global X.500 namespace.", 75, 2);
+ format("sets the search base to organization given, the Merit Computer Network in this case. This comamnd checks the validity of the specified search base, and rejects it if it is not a valid Distinguished Name (DN). A DN uniquely identifies a portion of the global LDAP namespace.", 75, 2);
}
else if (!strncasecmp("quit", s, len) || !strncasecmp("stop",s, len)) {
printf(" quit\n");
else if (!strncasecmp("modify", s, len) || !strncasecmp("change", s, len)) {
printf(" modify [entry]\n");
printf(" change [entry]\n\n");
- format("Changes information associated with an entry in the X.500 Directory. 'change' is an alias for 'modify'.", 75, 2);
+ format("Changes information associated with an entry in the LDAP Directory. 'change' is an alias for 'modify'.", 75, 2);
}
else if (!strncasecmp("verbose", s, len)) {
printf(" verbose\n\n");
}
else if (!strncasecmp("tidy", s, len)) {
printf(" tidy\n\n");
- format("Unsubscribes you from non-existent groups. Useful when you cannot resign from a group because, while your X.500 entry still contains a pointer to it, someone has removed a group of which you were a subscriber.", 75, 2);
+ format("Unsubscribes you from non-existent groups. Useful when you cannot resign from a group because, while your LDAP entry still contains a pointer to it, someone has removed a group of which you were a subscriber.", 75, 2);
}
else if (*s == '?') {
format("Prints out a brief description of each command. Same as typing 'help help'.", 75, 2);
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1991, 1992, 1993
* Regents of the University of Michigan. All rights reserved.
* Simon Fraser University, Academic Computing Services
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <sys/types.h>
-#if defined(NeXT)
-#include <stdlib.h>
-#include <sys/file.h>
-#else NeXT
-#include <unistd.h>
-#endif NeXT
-#include <pwd.h>
-#include <string.h>
-#ifndef DOS
-#if defined( NeXT ) || defined( ultrix ) || defined( osf1 ) || (defined(SunOS) && SunOS < 40)
-#include <sgtty.h>
-#else /* defined( NeXT ) || defined( ultrix ) etc. */
-#include <termios.h>
-#endif /* defined( NeXT ) || defined( ultrix ) etc. */
-#endif /* !DOS */
-#if defined( aix ) || defined( __NetBSD__ )
-#include <sys/ioctl.h>
-#endif /* aix || __NetBSD__ */
-#include <ctype.h>
-#include <signal.h>
+
+#include <ac/stdlib.h>
+
#include <setjmp.h>
-#include <memory.h>
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/termios.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
#include <lber.h>
#include <ldap.h>
-#include <ldapconfig.h>
-#include "portable.h"
-#include "ud.h"
-#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1991, 1992, 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+#include "ldap_defaults.h"
+#include "ud.h"
/*
* Used with change_base() to indicate which base we are changing.
#define BASE_SEARCH 0
#define BASE_GROUPS 1
-#define iscom(x) (!strncasecmp(x, cmd, strlen(cmd)))
+#define iscom(x) (!strncasecmp((x), cmd, strlen(cmd)))
static char *server = NULL;
static char *config_file = UD_CONFIG_FILE;
static char *filter_file = FILTERFILE;
-static int ldap_port = LDAP_PORT;
+static int ldap_port = 0;
static int dereference = TRUE;
-char *default_bind_object = UD_BINDDN;
+char *default_bind_object = NULL;
char *bound_dn; /* bound user's Distinguished Name */
-char *group_base; /* place in X.500 tree where groups are */
-char *search_base; /* place in X.500 tree where searches start */
+char *group_base; /* place in LDAP tree where groups are */
+char *search_base; /* place in LDAP tree where searches start */
static jmp_buf env; /* spot to jump to on an interrupt */
#ifdef DEBUG
int debug; /* debug flag */
#endif
+int ldebug; /* library debug flag */
+
+#ifndef HAVE_MKVERSION
+char Version[] = OPENLDAP_PACKAGE " " OPENLDAP_VERSION " UserDirectory (ud)";
+#endif
-main(argc, argv)
-int argc;
-char *argv[];
+int
+main( int argc, char **argv )
{
- extern char Version[]; /* version number */
- extern char *optarg; /* for parsing argv */
register int c; /* for parsing argv */
register char *cp; /* for parsing Version */
- extern void initialize_attribute_strings();
verbose = 1;
while ((c = getopt(argc, argv, "c:d:Df:l:p:s:u:vV")) != -1) {
switch (c) {
case 'l' :
-#ifdef LDAP_DEBUG
- ldap_debug = (int) strtol(optarg, (char **) NULL, 0);
- lber_debug = ldap_debug;
-#endif
+ ldebug |= (int) strtol(optarg, (char **) NULL, 0);
break;
case 'd' :
#ifdef DEBUG
- debug = (int) strtol(optarg, (char **) NULL, 0);
+ debug |= (int) strtol(optarg, (char **) NULL, 0);
#endif
break;
case 's' :
printf(" 64 authentication information\n");
printf(" 128 initialization information\n\n");
format("These are masks, and may be added to form multiple debug levels. For example, '-d 35' would perform a function trace, print out information about the find() function, and would print out information about the output routines too.", 75, 2);
- exit(0);
+ exit( EXIT_SUCCESS );
default:
fprintf(stderr, "Usage: %s [-c filter-config-file] [-d debug-level] [-l ldap-debug-level] [-s server] [-p port] [-V]\n", argv[0]);
- exit(-1);
+ exit( EXIT_FAILURE);
/* NOTREACHED */
}
}
printf(Version);
fflush( stdout );
+#ifdef SIGPIPE
+ (void) SIGNAL (SIGPIPE, SIG_IGN);
+#endif
+
initialize_client();
initialize_attribute_strings();
/* now tackle the user's commands */
do_commands();
/* NOTREACHED */
+
+ return 0;
}
-do_commands()
+void
+do_commands( void )
{
LDAPMessage *mp; /* returned by find() */
register char *cp; /* misc char pointer */
register char *ap; /* misc char pointer */
- static char buf[MED_BUF_SIZE]; /* for prompting */
static char cmd[MED_BUF_SIZE]; /* holds the command */
static char input[MED_BUF_SIZE]; /* buffer for input */
- extern LDAPMessage *find();
- extern void purge_group(), add_group(), remove_group(), x_group(),
- tidy_up(), list_groups(), list_memberships(), edit();
- extern char *nextstr();
#ifdef DEBUG
if (debug & D_TRACE)
putchar('\n');
continue;
}
- while (isspace(*cp))
+ while (isspace((unsigned char)*cp))
cp++;
ap = cmd;
if (memset(cmd, '\0', sizeof(cmd)) == NULL)
fatal("memset");
- while (!isspace(*cp) && (*cp != '\0'))
+ while (!isspace((unsigned char)*cp) && (*cp != '\0'))
*ap++ = *cp++;
if (iscom("status"))
status();
else if (iscom("stop") || iscom("quit"))
break;
else if (iscom("cb") || iscom("cd") || iscom("moveto")) {
- while (isspace(*cp) && (*cp != '\0'))
+ while (isspace((unsigned char)*cp) && (*cp != '\0'))
cp++;
if (!strncasecmp(cp, "base", 4))
cp += 4;
printf(" Verbose mode has been turned on.\n");
}
else if (!strncasecmp("dereference", cmd, strlen(cmd))) {
+ int deref;
dereference = 1 - dereference;
- if (dereference == 1)
- ld->ld_deref = LDAP_DEREF_ALWAYS;
- else
- ld->ld_deref = LDAP_DEREF_NEVER;
+ if (dereference == 1) {
+ deref = LDAP_DEREF_ALWAYS;
+ } else {
+ deref = LDAP_DEREF_NEVER;
+ }
+ ldap_set_option(ld, LDAP_OPT_DEREF, (void *) &deref);
}
else if (!strncasecmp("tidy", cmd, strlen(cmd)))
tidy_up();
printf(" Thank you!\n");
ldap_unbind(ld);
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
destroy_tickets();
#endif
- exit(0);
+ exit( EXIT_SUCCESS );
/* NOTREACHED */
}
-status()
+void
+status( void )
{
- void printbase();
register char **rdns;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->status()\n");
#endif
- printf(" Current server is %s", server);
- if ( ld != NULL && ld->ld_host != NULL && strcasecmp( ld->ld_host,
- server ) != 0 )
- printf( " (%s)", ld->ld_host );
+ printf(" Current server is %s", server != NULL ? server : "<default>" );
+ if ( ld != NULL ) {
+ char *host = NULL;
+
+ ldap_get_option(ld, LDAP_OPT_HOST_NAME, &host);
+
+ if ( host != NULL &&
+ ( server == NULL || strcasecmp( host, server ) != 0 ) )
+ {
+ printf( " (%s)", host );
+ }
+ }
putchar( '\n' );
printbase(" Search base is ", search_base);
printbase(" Group base is ", group_base);
}
printf( " Verbose mode is %sabled\n", ( verbose ? "en" : "dis" ));
if ( ld != NULL ) {
- printf( " Aliases are %sbeing dereferenced\n", ( ld->ld_deref == LDAP_DEREF_ALWAYS ) ? "" : "not" );
+ int deref = LDAP_DEREF_NEVER;
+ ldap_get_option(ld, LDAP_OPT_DEREF, &deref);
+ printf( " Aliases are %sbeing dereferenced\n",
+ ( deref == LDAP_DEREF_ALWAYS ) ? "" : "not" );
}
}
-change_base(type, base, s)
-int type;
-char **base, *s;
+void
+change_base( int type, char **base, char *s )
{
register char *cp; /* utility pointers */
char **rdns; /* for parsing */
static char *choices[MED_BUF_SIZE]; /* bases from which to choose */
static char resp[SMALL_BUF_SIZE]; /* for prompting user */
static char buf[MED_BUF_SIZE];
- void printbase();
static char *attrs[] = { "objectClass", NULL };
LDAPMessage *mp; /* results from a search */
LDAPMessage *ep; /* for going thru bases */
- extern char * friendly_name();
- extern void StrFreeDup();
- extern void Free();
#ifdef DEBUG
if (debug & D_TRACE)
}
/*
- * User wants to ascend one level in the X.500 tree.
+ * User wants to ascend one level in the LDAP tree.
* Easy: Just strip off the first element of the
* current search base, unless it's the root, in
* which case we just do nothing.
*
* sequence now that 'cp' is pointing to the '='.
*/
- while(!isspace(*cp))
+ while(!isspace((unsigned char)*cp))
cp--;
cp++;
/*
* type a number at that point too.
*/
if (ldap_search_s(ld, *base, LDAP_SCOPE_ONELEVEL, "(|(objectClass=quipuNonLeafObject)(objectClass=externalNonLeafObject))", attrs, FALSE, &mp) != LDAP_SUCCESS) {
- if ((ld->ld_errno == LDAP_TIMELIMIT_EXCEEDED) ||
- (ld->ld_errno == LDAP_SIZELIMIT_EXCEEDED)) {
+ int ld_errno = 0;
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+ if ((ld_errno == LDAP_TIMELIMIT_EXCEEDED) ||
+ (ld_errno == LDAP_SIZELIMIT_EXCEEDED)) {
if (verbose) {
printf(" Your query was too general and a limit was exceeded. The results listed\n");
printf(" are not complete. You may want to try again with a more refined query.\n\n");
if (j == 0) {
(void) ldap_msgfree(mp);
for (i = 0; i < matches; i++)
- Free(choices[i]);
+ ldap_memfree(choices[i]);
return;
}
if ((j < 1) || (j >= i))
printbase(output_string, *base);
(void) ldap_msgfree(mp);
for (i = 0; choices[i] != NULL; i++)
- Free(choices[i]);
+ ldap_memfree(choices[i]);
return;
}
}
/* set the search base back to the original default value */
else if (!strcasecmp(s, "default")) {
if (type == BASE_SEARCH)
- StrFreeDup(base, UD_BASE);
+ StrFreeDup(base, NULL);
else if (type == BASE_GROUPS)
StrFreeDup(base, UD_WHERE_GROUPS_ARE_CREATED);
printbase(output_string, *base);
}
}
-initialize_client()
+void
+initialize_client( void )
{
FILE *fp; /* for config file */
static char buffer[MED_BUF_SIZE]; /* for input */
+#ifdef HAVE_GETPWUID
struct passwd *pw; /* for getting the home dir */
+#endif
register char *cp; /* for fiddling with buffer */
- char *term; /* for tty set-up */
char *config; /* config file to use */
static char bp[1024]; /* for tty set-up */
- extern SIG_FN attn(); /* ^C signal handler */
- extern char *getenv();
- extern void Free();
#ifdef DEBUG
if (debug & D_TRACE)
printf("->initialize_client()\n");
#endif
+
+ if (ldebug) {
+ ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldebug );
+ ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &ldebug );
+ }
+
/*
* A per-user config file has precedence over any system-wide
* config file, if one exists.
*/
+#ifdef HAVE_GETPWUID
if ((pw = getpwuid((uid_t) geteuid())) == (struct passwd *) NULL)
config = config_file;
else {
config = config_file;
}
}
+#else
+ config = config_file;
+#endif /* getpwduid() */
#ifdef DEBUG
if (debug & D_INITIALIZE)
printf("Using config file %s\n", config);
if (server != NULL)
continue;
cp = buffer + 6;
- while (isspace(*cp))
+ while (isspace((unsigned char)*cp))
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ server = strdup(cp);
+ }
+ else if (!strncasecmp(buffer, "host", 4)) {
+ if (server != NULL)
+ continue;
+ cp = buffer + 4;
+ while (isspace((unsigned char)*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
}
else if (!strncasecmp(buffer, "base", 4)) {
cp = buffer + 4;
- while (isspace(*cp))
+ while (isspace((unsigned char)*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
}
else if (!strncasecmp(buffer, "groupbase", 9)) {
cp = buffer + 9;
- while (isspace(*cp))
+ while (isspace((unsigned char)*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
}
if (group_base == NULL)
group_base = strdup(UD_WHERE_GROUPS_ARE_CREATED);
- if (search_base == NULL)
- search_base = strdup(UD_BASE);
- if (server == NULL)
- server = strdup(LDAPHOST);
/*
* Set up our LDAP connection. The values of retry and timeout
* are meaningless since we will immediately be doing a null bind
* because we want to be sure to use TCP, not UDP.
*/
- if ((ld = ldap_open(server, ldap_port)) == NULL) {
- fprintf(stderr, " The X.500 Directory is temporarily unavailable. Please try again later.\n");
- exit(0);
+ if ((ld = ldap_init(server, ldap_port)) == NULL) {
+ fprintf(stderr, " Initialization of LDAP session failed.\n");
+ exit( EXIT_FAILURE );
/* NOTREACHED */
}
- if (ldap_bind_s(ld, (char *) default_bind_object, (char *) UD_PASSWD,
+ if (ldap_bind_s(ld, (char *) default_bind_object, NULL,
LDAP_AUTH_SIMPLE) != LDAP_SUCCESS) {
- fprintf(stderr, " The X.500 Directory is temporarily unavailable. Please try again later.\n");
- if (ld->ld_errno != LDAP_UNAVAILABLE)
+ int ld_errno = 0;
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
+ fprintf(stderr, " The LDAP Directory is temporarily unavailable. Please try again later.\n");
+ if (ld_errno != LDAP_UNAVAILABLE)
ldap_perror(ld, " ldap_bind_s");
- exit(0);
+ exit( EXIT_FAILURE );
/* NOTREACHED */
}
- ld->ld_deref = LDAP_DEREF_ALWAYS;
+ {
+ int deref = LDAP_DEREF_ALWAYS;
+ ldap_set_option(ld, LDAP_OPT_DEREF, (void *) &deref);
+ }
bind_status = UD_NOT_BOUND;
if ( default_bind_object != NULL ) {
bound_dn = strdup(default_bind_object);
}
/* enabled local caching of ldap results, 15 minute lifetime */
-#ifdef DOS
- ldap_enable_cache( ld, 60 * 15, 100 * 1024 ); /* 100k max memory */
-#else /* DOS */
ldap_enable_cache( ld, 60 * 15, 0 ); /* no memory limit */
-#endif /* DOS */
/* initialize the search filters */
if ((lfdp = ldap_init_getfilter(filter_file)) == NULL) {
lpp = DEFAULT_TTY_HEIGHT;
col_size = DEFAULT_TTY_WIDTH;
- (void) signal(SIGINT, attn);
+ (void) SIGNAL (SIGINT, attn);
-#if !defined(DOS) && !defined(NOTERMCAP)
+#ifndef NO_TERMCAP
{
- struct winsize win; /* for tty set-up */
- extern SIG_FN chwinsz(); /* WINSZ signal handler */
+ char *term;
if (((term = getenv("TERM")) == NULL) || (tgetent(bp, term) <= 0))
return;
else {
- if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {
- lpp = tgetnum("li");
- col_size = tgetnum("co");
- }
- else {
+#ifdef TIOCGWINSZ
+ struct winsize win; /* for tty set-up */
+ if (ioctl(fileno(stdout), TIOCGWINSZ, &win) >= 0) {
if ((lpp = win.ws_row) == 0)
lpp = tgetnum("li");
if ((col_size = win.ws_col) == 0)
lpp = DEFAULT_TTY_HEIGHT;
if ((col_size <= 0) || tgetflag("hc"))
col_size = DEFAULT_TTY_WIDTH;
+ (void) SIGNAL (SIGWINCH, chwinsz);
+ } else
+#endif
+ {
+ lpp = tgetnum("li");
+ col_size = tgetnum("co");
}
}
- (void) signal(SIGWINCH, chwinsz);
-
}
#endif
}
-SIG_FN attn()
+RETSIGTYPE
+attn( int sig )
{
fflush(stderr);
fflush(stdout);
printf("\n\n INTERRUPTED!\n");
-#if defined(DOS) || defined(SYSV)
- (void) signal(SIGINT, attn);
-#endif
+
+ (void) SIGNAL (SIGINT, attn);
+
longjmp(env, 1);
}
-#if !defined(DOS) && !defined(NOTERMCAP)
-SIG_FN chwinsz()
+#if !defined(NO_TERMCAP) && defined(TIOCGWINSZ)
+RETSIGTYPE
+chwinsz( int sig )
{
struct winsize win;
- (void) signal(SIGWINCH, SIG_IGN);
+ (void) SIGNAL (SIGWINCH, SIG_IGN);
if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
if (win.ws_row != 0)
lpp = win.ws_row;
if (win.ws_col != 0)
col_size = win.ws_col;
}
- (void) signal(SIGWINCH, chwinsz);
+
+ (void) SIGNAL (SIGWINCH, chwinsz);
}
#endif
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include <lber.h>
#include <ldap.h>
-#ifndef __STDC__
-#include <memory.h>
-#endif
-#include <sys/types.h>
#include "ud.h"
-extern struct entry Entry;
-extern int verbose;
-extern LDAP *ld;
+static char *get_URL( void );
+static int check_URL( char *url );
-extern LDAPMessage *find();
-#ifdef DEBUG
-extern int debug;
-#endif
-
-modify(who)
-char *who;
+void
+modify( char *who )
{
-#ifdef UOFM
- void set_updates(); /* routine to modify noBatchUpdates */
-#endif
LDAPMessage *mp; /* returned from find() */
char *dn; /* distinguished name */
char **rdns; /* for fiddling with the DN */
#ifdef UOFM
static char printed_warning = 0; /* for use with the */
struct attribute no_batch_update_attr;
- extern char * fetch_boolean_value();
+ int ld_errno;
#endif
int is_a_group; /* TRUE if it is; FALSE otherwise */
- extern void Free();
- extern int bind_status;
#ifdef DEBUG
if (debug & D_TRACE)
*/
no_batch_update_attr.quipu_name = "noBatchUpdates";
(void) fetch_boolean_value(dn, no_batch_update_attr);
- if (verbose && !printed_warning && (ld->ld_errno == LDAP_NO_SUCH_ATTRIBUTE)) {
+
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
+ if (verbose && !printed_warning && (ld_errno == LDAP_NO_SUCH_ATTRIBUTE)) {
printed_warning = 1;
printf("\n WARNING!\n");
- printf(" You are about to make a modification to an X.500 entry\n");
+ printf(" You are about to make a modification to an LDAP entry\n");
printf(" that has its \"automatic updates\" field set to ON.\n");
printf(" This means that the entry will be automatically updated\n");
printf(" each month from official University sources like the\n");
parse_answer(mp);
(void) ldap_msgfree(mp);
}
- (void) Free(dn);
+ ldap_memfree(dn);
ldap_value_free(rdns);
return;
}
/* generic routine for changing any field */
-void change_field(who, attr)
-char *who; /* DN of entry we are changing */
-struct attribute attr; /* attribute to change */
+void
+change_field(
+ char *who, /* DN of entry we are changing */
+ int attr_idx /* attribute to change */
+)
{
+ struct attribute attr = Entry.attrs[attr_to_index(attrlist[attr_idx].quipu_name)];
#define IS_MOD(x) (!strncasecmp(resp, (x), strlen(resp)))
- char *get_value(); /* routine to extract values */
static char buf[MED_BUF_SIZE]; /* for printing things */
static char resp[SMALL_BUF_SIZE]; /* for user input */
char *prompt, *prompt2, *more;
static LDAPMod mod;
static LDAPMod *mods[2] = { &mod }; /* passed to ldap_modify */
static char *values[MAX_VALUES]; /* passed to ldap_modify */
- extern void Free();
#ifdef DEBUG
if (debug & D_TRACE)
#define MAX_DESC_LINES 24
#define INTL_ADDR_LIMIT 30
-char *get_value(id, prompt)
-char *id, *prompt;
+char *
+get_value( char *id, char *prompt )
{
char *cp; /* for the Malloc() */
int count; /* line # of new value -- if multiline */
int multiline = 0; /* 1 if this value is multiline */
static char line[LINE_SIZE]; /* raw line from user */
- static char buffer[MAX_DESC_LINES * LINE_SIZE]; /* holds ALL of the
+ static char buffer[MAX_DESC_LINES * (LINE_SIZE+2)]; /* holds ALL of the
lines we get */
- extern void * Malloc();
- static char * get_URL();
-
#ifdef DEBUG
if (debug & D_TRACE)
printf("->get_value(%s, %s)\n", id, prompt);
if (lmp == (LDAPMessage *) NULL) {
printf(" Could not find \"%s\" in the Directory\n", line);
if (verbose)
- format("Owners of groups must be valid entries in the X.500 Directory. The name you have typed above could not be found in the X.500 Directory.", 72, 2);
+ format("Owners of groups must be valid entries in the LDAP Directory. The name you have typed above could not be found in the LDAP Directory.", 72, 2);
return(NULL);
}
elmp = ldap_first_entry(ld, lmp);
}
tmp = ldap_get_dn(ld, elmp);
strcpy(buffer, tmp);
+ ldap_memfree(tmp);
(void) ldap_msgfree(lmp);
break;
}
* are done.
*/
if (count++ > 1)
- (void) strcat(buffer, "$");
+ (void) strcat(buffer, " $ ");
(void) strcat(buffer, line);
if (!multiline)
break;
return(cp);
}
-void set_boolean(who, attr)
-char *who; /* DN of entry we are changing */
-struct attribute attr; /* boolean attribute to change */
+void
+set_boolean(
+ char *who, /* DN of entry we are changing */
+ int attr_idx /* boolean attribute to change */
+)
{
+ struct attribute attr = Entry.attrs[attr_to_index(attrlist[attr_idx].quipu_name)];
+
char *cp, *s;
- extern char * fetch_boolean_value();
static char response[16];
static char *newsetting[2] = { NULL, NULL };
LDAPMod mod, *mods[2];
printf(" Please enter Y for yes, N for no, or RETURN to cancel: ");
fflush(stdout);
(void) fetch_buffer(response, sizeof(response), stdin);
- for (s = response; isspace(*s); s++)
+ for (s = response; isspace((unsigned char)*s); s++)
;
if ((*s == 'y') || (*s == 'Y')) {
if (ldap_modify_s(ld, who, mods)) {
#ifdef UOFM
-void set_updates(who)
-char *who;
+void
+set_updates( char *who, int dummy )
{
char *cp, *s;
- extern char * fetch_boolean_value();
static char response[16];
static char value[6];
static char *newsetting[2] = { value, NULL };
if (verbose) {
printf("\n By default, updates that are received from the Personnel\n");
printf(" Office and the Office of the Registrar are applied to all\n");
- printf(" entries in the X.500 database each month. Sometimes this\n");
+ printf(" entries in the LDAP database each month. Sometimes this\n");
printf(" feature is undesirable. For example, if you maintain your\n");
- printf(" entry in the X.500 database manually, you may not want to\n");
+ printf(" entry in the LDAP database manually, you may not want to\n");
printf(" have these updates applied to your entry, possibly overwriting\n");
printf(" correct information with out-dated information.\n\n");
}
printf("\n Change this setting [no]? ");
fflush(stdout);
(void) fetch_buffer(response, sizeof(response), stdin);
- for (s = response; isspace(*s); s++)
+ for (s = response; isspace((unsigned char)*s); s++)
;
if ((*s == 'y') || (*s == 'Y')) {
if (!strcmp(cp, "TRUE"))
#endif
-print_mod_list(group)
-int group;
+void
+print_mod_list( int group )
{
register int i, j = 1;
- extern struct attribute attrlist[];
if (group == TRUE) {
for (i = 0; attrlist[i].quipu_name != NULL; i++) {
#endif
}
-perform_action(choice, dn, group)
-char choice[];
-char *dn;
-int group;
+int
+perform_action( char *choice, char *dn, int group )
{
int selection;
register int i, j = 1;
- extern struct attribute attrlist[];
- extern void mod_addrDN(), change_field(), set_boolean();
selection = atoi(choice);
if (selection < 1) {
return(1);
/* NOTREACHED */
}
- if (attrlist[i].mod_func == change_field)
- (*attrlist[i].mod_func)(dn, Entry.attrs[attr_to_index(attrlist[i].quipu_name)]);
- else if (attrlist[i].mod_func == mod_addrDN)
- (*attrlist[i].mod_func)(dn, i);
- else if (attrlist[i].mod_func == set_boolean)
- (*attrlist[i].mod_func)(dn, Entry.attrs[attr_to_index(attrlist[i].quipu_name)]);
- else
- (*attrlist[i].mod_func)(dn);
+ (*attrlist[i].mod_func)(dn, i);
return(0);
}
-static char * get_URL()
+static char *
+get_URL( void )
{
char *rvalue, label[MED_BUF_SIZE], url[MED_BUF_SIZE];
- static int check_URL();
- extern void * Malloc();
if (verbose) {
printf(" First, enter the URL. (Example: http://www.us.itd.umich.edu/users/).\n");
return((char *) rvalue);
}
-static check_URL(url)
-char *url;
+static int
+check_URL( char *url )
{
register char *cp;
for (cp = url; *cp != '\n' && *cp != '\0'; cp++) {
- if (isspace(*cp))
+ if (isspace((unsigned char)*cp))
return(-1);
/*NOTREACHED*/
}
}
+void
mod_perror( LDAP *ld )
{
- if ( ld == NULL || ( ld->ld_errno != LDAP_UNAVAILABLE &&
- ld->ld_errno != LDAP_UNWILLING_TO_PERFORM )) {
+ int ld_errno = 0;
+
+ if(ld != NULL) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
+ }
+
+ if (( ld == NULL ) || ( ld_errno != LDAP_UNAVAILABLE &&
+ ld_errno != LDAP_UNWILLING_TO_PERFORM ))
+ {
ldap_perror( ld, "modify" );
return;
}
fprintf( stderr, "\n modify: failed because part of the online directory is not able\n" );
fprintf( stderr, " to be modified right now" );
- if ( ld->ld_errno == LDAP_UNAVAILABLE ) {
+ if ( ld_errno == LDAP_UNAVAILABLE ) {
fprintf( stderr, " or is temporarily unavailable" );
}
fprintf( stderr, ".\n Please try again later.\n" );
-#ifdef KERBEROS
+#include "portable.h"
+
+#if defined(HAVE_KERBEROS) && !defined(openbsd)
/*
- * $Source: /usr/local/src/ldap/clients/ud/RCS/string_to_key.c,v $
- * $Author: lsloan $
+ * $Source: /repo/OpenLDAP/pkg/ldap/clients/ud/string_to_key.c,v $
+ * $Author: hallvard $
*
* Copyright 1985, 1986, 1987, 1988, 1989 by the Massachusetts Institute
* of Technology.
* spm 8/85 MIT project athena
*/
-#ifndef lint
-static char rcsid_string_to_key_c[] =
-"$Id: string_to_key.c,v 1.5 1995/11/09 20:29:55 lsloan Exp $";
-#endif
-
-#include <mit-copyright.h>
#include <stdio.h>
-#include <des.h>
-/* #include "des_internal.h" */
-#if 1
-#include <krb.h>
-#endif
+#include <ac/krb.h>
+#if defined( DEBUG ) && defined( HAVE_DES_DEBUG )
+#define USE_DES_DEBUG
extern int des_debug;
-extern int des_debug_print();
+#endif
+
extern void des_fixup_key_parity();
-#ifndef AFSKERBEROS
+#ifndef HAVE_AFS_KERBEROS
#define WORLDPEACEINOURTIME
#endif
#if defined(WORLDPEACEINOURTIME) /* Use original, not ifs version */
+#ifndef HAVE_KERBEROS_V
/*
* convert an arbitrary length string to a DES key
*/
-int
-des_string_to_key(str,key)
- char *str;
- register des_cblock *key;
+void
+des_string_to_key( char *str, register des_cblock *key )
{
register char *in_str;
register unsigned temp,i;
/* init key array for bits */
memset(k_char, 0, sizeof(k_char));
-#ifdef DEBUG
+#ifdef USE_DES_DEBUG
if (des_debug)
fprintf(stdout,
"\n\ninput str length = %d string = %s\nstring = 0x ",
for (i = 1; i <= length; i++) {
/* get next input key byte */
temp = (unsigned int) *str++;
-#ifdef DEBUG
+#ifdef USE_DES_DEBUG
if (des_debug)
fprintf(stdout,"%02x ",temp & 0xff);
#endif
/* now fix up key parity again */
des_fixup_key_parity(key);
+#ifdef USE_DES_DEBUG
if (des_debug)
fprintf(stdout,
- "\nResulting string_to_key = 0x%x 0x%x\n",
+ "\nResulting string_to_key = 0x%lx 0x%lx\n",
*((unsigned long *) key),
*((unsigned long *) key+1));
+#endif
}
+#endif /* HAVE_KERBEROS_V */
#else /* Use ifs version */
#if 0
encryption key. It is compatible with the original Andrew authentication
service password database. */
-static void Andrew_StringToKey (str, cell, key)
- char *str;
- char *cell; /* cell for password */
- des_cblock *key;
+static void
+Andrew_StringToKey(
+ char *str,
+ char *cell, /* cell for password */
+ des_cblock *key
+)
{ char password[8+1]; /* crypt is limited to 8 chars anyway */
int i;
int passlen;
des_fixup_key_parity (key);
}
-static void StringToKey (str, cell, key)
- char *str;
- char *cell; /* cell for password */
- des_cblock *key;
+static void
+StringToKey(
+ char *str,
+ char *cell, /* cell for password */
+ des_cblock *key
+)
{ des_key_schedule schedule;
char temp_key[8];
char ivec[8];
des_fixup_key_parity (key);
}
-/* static */ void
-ka_StringToKey (str, cell, key)
- char *str;
- char *cell; /* cell for password */
- des_cblock *key;
+void
+ka_StringToKey (
+ char *str,
+ char *cell, /* cell for password */
+ des_cblock *key
+)
{ char realm[REALM_SZ];
#if NOWAYOUTTODAY
long code;
- /* code = ka_CellToRealm (cell, realm, 0/*local*/); */
+#if 0
+ code = ka_CellToRealm (cell, realm, 0/*local*/);
+#endif
if (code) strcpy (realm, "");
else lcstring (realm, realm, sizeof(realm)); /* for backward compatibility */
#else
* convert an arbitrary length string to a DES key
*/
int
-des_string_to_key(str,key)
- char *str;
- register des_cblock *key;
+des_string_to_key( char *str, register des_cblock *key )
{
/* NB: i should probably call routine to get local cell here */
ka_StringToKey(str, "umich.edu", key);
* is provided ``as is'' without express or implied warranty.
*/
-#include <stdio.h>
-#include <signal.h>
-#include <string.h>
-#ifdef DOS
-#include <malloc.h>
-#endif
-#include <memory.h>
-#if defined( NeXT )
-#include <stdlib.h>
-#endif
-#include <ctype.h>
-#include <errno.h>
-#include <lber.h>
-#include <ldap.h>
-#include <ldapconfig.h>
-#if !defined(DOS) && !defined( VMS)
-#include <sys/types.h>
-#endif
#include "portable.h"
-#ifdef USE_TERMIOS
-#include <termios.h>
-#else /* USE_TERMIOS */
-#include <sgtty.h>
-#endif /* USE_TERMIOS */
-#include "ud.h"
-
-#if defined(VMS)
-#define getch getchar
-#endif
-
-#ifdef DEBUG
-extern int debug;
-#endif
-char * mygetpass(prompt)
-char *prompt;
-{
-#if defined(DOS) || defined(VMS)
- static char buf[256];
- int i, c;
-
-#ifdef DEBUG
- if (debug & D_TRACE)
- printf("->mygetpass(%s)\n", prompt);
-#endif
- printf("%s", prompt);
- i = 0;
- while ( (c = getch()) != EOF && c != '\n' && c != '\r' )
- buf[i++] = c;
- if ( c == EOF )
- return( NULL );
- buf[i] = '\0';
- return (buf);
-#else
- int no_pass = 0;
- char i, j, k;
- TERMIO_TYPE ttyb;
- TERMFLAG_TYPE flags;
- static char pbuf[513];
- register char *p;
- register int c;
- FILE *fi;
- SIG_FN (*sig)();
-
-#ifdef DEBUG
- if (debug & D_TRACE)
- printf("->mygetpass(%s)\n", prompt);
-#endif
- /*
- * Stolen from the getpass() routine. Can't use the plain
- * getpass() for two reasons. One is that X.500 passwords
- * can be really, really long - much longer than 8 chars.
- * The second is that we like to make this client available
- * out of inetd via a Merit asynch port, and we need to be
- * able to do telnet control codes to turn on and off line
- * blanking.
- */
- if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
- fi = stdin;
- else
- setbuf(fi, (char *)NULL);
- sig = signal(SIGINT, SIG_IGN);
- if (fi != stdin) {
- if (GETATTR(fileno(fi), &ttyb) < 0)
- perror("GETATTR");
- }
- flags = GETFLAGS( ttyb );
- SETFLAGS( ttyb, flags & ~ECHO );
- if (fi != stdin) {
- if (SETATTR(fileno(fi), &ttyb) < 0)
- perror("SETATTR");
- }
+#include <stdio.h>
- /* blank the line if through Merit */
- if (fi == stdin) {
- printf("%c%c%c", 255, 251, 1);
- fflush(stdout);
- (void) scanf("%c%c%c", &i, &j, &k);
- fflush(stdin);
- }
+#include <ac/stdlib.h>
- /* fetch the password */
- fprintf(stdout, "%s", prompt);
- fflush(stdout);
- for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) {
- if (c == '\r')
- break;
- if (p < &pbuf[512])
- *p++ = c;
- }
- if (c == EOF)
- no_pass = 1;
- else {
- *p = '\0';
- if (*(p - 1) == '\r')
- *(p - 1) = '\0';
- }
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/termios.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
- /* unblank the line if through Merit */
- if (fi == stdin) {
- printf("%c%c%c", 255, 252, 1);
- fflush(stdout);
- (void) scanf("%c%c%c", &i, &j, &k);
- fflush(stdin);
- printf("\n"); fflush(stdout);
- }
- fprintf(stdout, "\n");
- fflush(stdout);
+#include <lber.h>
+#include <ldap.h>
- /* tidy up */
- SETFLAGS( ttyb, flags );
- if (fi != stdin) {
- if (SETATTR(fileno(fi), &ttyb) < 0)
- perror("SETATTR");
- }
- (void) signal(SIGINT, sig);
- if (fi != stdin)
- (void) fclose(fi);
- else
- i = getchar();
- if (no_pass)
- return(NULL);
- return(pbuf);
-#endif /* DOS */
-}
+#include "ldap_defaults.h"
+#include "ud.h"
-void printbase(lead, s)
-char *lead, *s;
+void
+printbase( char *lead, char *s )
{
register char **cp;
char **rdns;
- char * friendly_name();
#ifdef DEBUG
if (debug & D_TRACE)
return;
}
-fetch_buffer(buffer, length, where)
-char *buffer;
-int length;
-FILE *where;
+void
+fetch_buffer( char *buffer, int length, FILE *where )
{
- extern LDAP *ld;
register int i;
char *p;
errno = 0; /* so fatal() doesn't bitch */
fatal("fgets");
}
- for (i = strlen(buffer) - 1; i >= 0 && !isprint(buffer[i]); i--)
+ for (i = strlen(buffer) - 1;
+ i >= 0 && !isprint((unsigned char) buffer[i]); i--)
buffer[i] = '\0';
p = buffer;
while ( *p != '\0' ) {
- if ( isprint( *p )) {
+ if ( isprint( (unsigned char) *p )) {
++p;
} else {
- strcpy( p, p + 1 );
+ SAFEMEMCPY( p, p + 1, strlen( p + 1 ) + 1 );
}
}
}
-fatal(s)
-char *s;
+void
+fatal( char *s )
{
- void exit();
-
if (errno != 0)
perror(s);
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
destroy_tickets();
#endif
- exit(-1);
+ exit( EXIT_FAILURE );
}
-isgroup()
+int
+isgroup( void )
{
- extern struct entry Entry;
char **vp;
register int i;
int group = FALSE;
* Print out the string 's' on a field of 'width' chracters. Each line
* should be indented 'lead' characters.
*/
-format(str, width, lead)
-char *str;
-int width, lead;
+void
+format( char *str, int width, int lead )
{
char *s, *original, *leader = "";
register char *cp;
- void * Malloc();
- void Free();
#ifdef DEBUG
if (debug & D_TRACE)
*/
s = original = strdup(str);
for (;;) {
- if ((strlen(s) + lead) < width) {
+ if (((int) strlen(s) + lead) < width) {
printf("%s%s\n", leader, s);
Free(leader);
Free(original);
/*NOTREACHED*/
}
cp = s + width - lead;
- while (!isspace(*cp) && (cp != s))
+ while (!isspace((unsigned char)*cp) && (cp != s))
cp--;
*cp = '\0';
- while (isspace(*s))
+ while (isspace((unsigned char)*s))
s++;
printf("%s%s\n", leader, s);
s = cp + 1;
* indented 'indent' spaces, then followed by 'tag', and then followed by
* subsequent lines of 's'.
*/
-format2(s, first_tag, tag, first_indent, indent, width)
-char *s, *first_tag, *tag;
-int first_indent, indent, width;
+void
+format2(
+ char *s,
+ char *first_tag,
+ char *tag,
+ int first_indent,
+ int indent,
+ int width
+)
{
char c, *fi, *i;
register char *cp;
- void * Malloc();
- void Free();
if (first_tag == NULL)
first_tag = "";
i = "";
/* now do the first line */
- if ((strlen(s) + strlen(first_tag) + first_indent) < width) {
+ if (((int) strlen(s) + (int) strlen(first_tag) + first_indent) < width) {
printf("%s%s%s\n", fi, first_tag, s);
Free(fi);
Free(i);
* back it up to the first space character.
*/
cp = s + width - first_indent - strlen(first_tag);
- while (!isspace(*cp) && (cp != s))
+ while (!isspace((unsigned char)*cp) && (cp != s))
cp--;
/*
* as well. We should gobble up all of these since we don't want
* unexpected leading blanks.
*/
- for (s = cp + 1; isspace(*s); s++)
+ for (s = cp + 1; isspace((unsigned char)*s); s++)
;
/* now do all of the other lines */
for (;;) {
- if ((strlen(s) + strlen(tag) + indent) < width) {
+ if (((int) strlen(s) + (int) strlen(tag) + indent) < width) {
printf("%s%s%s\n", i, tag, s);
Free(fi);
Free(i);
/*NOTREACHED*/
}
cp = s + width - indent - strlen(tag);
- while (!isspace(*cp) && (cp != s))
+ while (!isspace((unsigned char)*cp) && (cp != s))
cp--;
c = *cp;
*cp = '\0';
#define IN_A_QUOTE 0
#define OUT_OF_QUOTE 1
-char * strip_ignore_chars(cp)
-char *cp;
+char *
+strip_ignore_chars( char *cp )
{
int had_a_comma = FALSE;
int flag = OUT_OF_QUOTE;
register char *rcp, *cp1;
char *tmp;
- void * Malloc();
- void Free();
#ifdef DEBUG
if (debug & D_TRACE)
return(tmp);
}
-char * code_to_str(i)
+char *
+code_to_str( int i )
{
switch(i) {
case LDAP_MOD_ADD : return("ADD");
}
}
-char * friendly_name(s)
-char *s;
+char *
+friendly_name( char *s )
{
- static FriendlyMap *map = NULL;
+ static LDAPFriendlyMap *map = NULL;
static char *cp;
cp = ldap_friendly_name(FRIENDLYFILE, s, &map);
#ifdef UOFM
/* return TRUE if s has the syntax of a uniqname */
-isauniqname(s)
-char *s;
+int
+isauniqname( char *s )
{
int i = strlen(s);
if ((i < 3) || (i > 8)) /* uniqnames are 3-8 chars */
return(FALSE);
- if (!isalpha(*s)) /* uniqnames begin with a letter */
+ if (!isalpha((unsigned char)*s)) /* uniqnames begin with a letter */
return(FALSE);
for ( ; *s != '\0'; s++) /* uniqnames are alphanumeric */
- if (!isalnum(*s))
+ if (!isalnum((unsigned char)*s))
return(FALSE);
return(TRUE);
}
#endif
/* return TRUE if this attribute should be printed as a DN */
-isadn(s)
-char *s;
+int
+isadn( char *s )
{
register int i;
- extern struct attribute attrlist[];
for (i = 0; attrlist[i].quipu_name != NULL; i++)
if (!strcasecmp(s, attrlist[i].quipu_name))
return(FALSE);
}
-char * my_ldap_dn2ufn(s)
-char *s;
+char *
+my_ldap_dn2ufn( char *s )
{
register char **cpp;
static char short_DN[BUFSIZ];
- if (strstr(s, UD_BASE) == NULL)
+ if (strstr(s, NULL) == NULL)
return(ldap_dn2ufn(s));
cpp = ldap_explode_dn(s, TRUE);
sprintf(short_DN, "%s, %s", *cpp, *(cpp + 1));
}
/* return TRUE if this attribute should be printed as a URL */
-isaurl(s)
-char *s;
+int
+isaurl( char *s )
{
register int i;
- extern struct attribute attrlist[];
for (i = 0; attrlist[i].quipu_name != NULL; i++)
if (!strcasecmp(s, attrlist[i].quipu_name))
}
/* return TRUE if this attribute should be printed as a date and time */
-isadate(s)
-char *s;
+int
+isadate( char *s )
{
register int i;
- extern struct attribute attrlist[];
for (i = 0; attrlist[i].quipu_name != NULL; i++)
if (!strcasecmp(s, attrlist[i].quipu_name))
return(FALSE);
}
-void * Malloc(size)
-unsigned int size;
+void *
+Malloc( unsigned int size )
{
void *void_ptr;
void_ptr = (void *) malloc(size);
if (void_ptr == NULL) {
perror("malloc");
- exit(-1);
+ exit( EXIT_FAILURE );
/*NOTREACHED*/
}
return(void_ptr);
}
-void Free(ptr)
-char *ptr;
+void
+Free( void *ptr )
{
- extern int free();
-
- if (free(ptr) < 0) {
- perror("free");
- exit(-1);
- /*NOTREACHED*/
- }
- return;
+ free(ptr);
}
-char * nextstr(s)
-char *s;
+char *
+nextstr( char *s )
{
- while (isspace(*s) && (*s != '\0'))
+ while (isspace((unsigned char) *s) && (*s != '\0'))
s++;
if (s == NULL)
return(NULL);
return(s);
}
-void free_mod_struct(modp)
-LDAPMod *modp;
+void
+free_mod_struct( LDAPMod *modp )
{
- void Free();
-
if (modp->mod_values != NULL)
(void) ldap_value_free(modp->mod_values);
Free(modp->mod_type);
Free(modp);
}
-void StrFreeDup(ptr, new_value)
-char **ptr, *new_value;
+void
+StrFreeDup( char **ptr, char *new_value )
{
- void Free();
-
if (*ptr != NULL)
Free(*ptr);
if (new_value == NULL)
}
-confirm_action( msg )
- char *msg;
+int
+confirm_action( char *msg )
{
char tmp[SMALL_BUF_SIZE];
int i;
--enable-x-compile enable cross compiling (no)"
ac_help="$ac_help
--enable-dmalloc enable debug malloc support (no)"
+ac_help="$ac_help
+ --with-cyrus-sasl with Cyrus SASL support (auto)"
+ac_help="$ac_help
+ --with-fetch with fetch URL support (auto)"
ac_help="$ac_help
--with-kerberos with Kerberos support (auto)"
ac_help="$ac_help
--enable-crypt enable crypt(3) passwords (auto)"
ac_help="$ac_help
--enable-modules enable dynamic module support (no)"
+ac_help="$ac_help
+ --enable-multimaster enable multimaster replication (no)"
ac_help="$ac_help
--enable-phonetic enable phonetic/soundex (no)"
+ac_help="$ac_help
+ --enable-quipu build quipu migration tools (no)"
ac_help="$ac_help
--enable-rlookups enable reverse lookups (auto)"
ac_help="$ac_help
echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:638: checking host system type" >&5
+echo "configure:646: checking host system type" >&5
if test "x$ac_cv_host" = "x" || (test "x$host" != "xNONE" && test "x$host" != "x$ac_cv_host_alias"); then
# Make sure we can run config.sub.
echo $ac_n "checking target system type""... $ac_c" 1>&6
-echo "configure:679: checking target system type" >&5
+echo "configure:687: checking target system type" >&5
if test "x$ac_cv_target" = "x" || (test "x$target" != "xNONE" && test "x$target" != "x$ac_cv_target_alias"); then
# Make sure we can run config.sub.
echo $ac_n "checking build system type""... $ac_c" 1>&6
-echo "configure:719: checking build system type" >&5
+echo "configure:727: checking build system type" >&5
if test "x$ac_cv_build" = "x" || (test "x$build" != "xNONE" && test "x$build" != "x$ac_cv_build_alias"); then
# Make sure we can run config.sub.
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:796: checking for a BSD compatible install" >&5
+echo "configure:804: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"\${ac_cv_path_install+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
-echo "configure:853: checking whether build environment is sane" >&5
+echo "configure:861: checking whether build environment is sane" >&5
# Just in case
sleep 1
echo timestamp > conftestfile
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:914: checking for $ac_word" >&5
+echo "configure:922: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_AWK+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
done
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:944: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:952: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
missing_dir=`cd $ac_aux_dir && pwd`
echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
-echo "configure:984: checking for working aclocal" >&5
+echo "configure:992: checking for working aclocal" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
fi
echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
-echo "configure:997: checking for working autoconf" >&5
+echo "configure:1005: checking for working autoconf" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
fi
echo $ac_n "checking for working automake""... $ac_c" 1>&6
-echo "configure:1010: checking for working automake" >&5
+echo "configure:1018: checking for working automake" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
fi
echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
-echo "configure:1023: checking for working autoheader" >&5
+echo "configure:1031: checking for working autoheader" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
fi
echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
-echo "configure:1036: checking for working makeinfo" >&5
+echo "configure:1044: checking for working makeinfo" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1056: checking for $ac_word" >&5
+echo "configure:1064: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_AMTAR+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking configure arguments""... $ac_c" 1>&6
-echo "configure:1107: checking configure arguments" >&5
+echo "configure:1115: checking configure arguments" >&5
top_builddir=`pwd`
-ldap_subdir="openldap"
+ldap_subdir="/openldap"
# Check whether --with-subdir or --without-subdir was given.
if test "${with_subdir+set}" = set; then
withval="$with_subdir"
-
- if test "$withval" = "no"; then
- ldap_subdir=""
- elif test "$withval" != "yes"; then
+ case "$withval" in
+ no) ldap_subdir=""
+ ;;
+ yes)
+ ;;
+ /*|\\*)
ldap_subdir="$withval"
- fi
+ ;;
+ *)
+ ldap_subdir="/$withval"
+ ;;
+esac
fi
fi
# end --enable-dmalloc
+# OpenLDAP --with-cyrus_sasl
+ # Check whether --with-cyrus_sasl or --without-cyrus_sasl was given.
+if test "${with_cyrus_sasl+set}" = set; then
+ withval="$with_cyrus_sasl"
+
+ ol_arg=invalid
+ for ol_val in auto yes no ; do
+ if test "$withval" = "$ol_val" ; then
+ ol_arg="$ol_val"
+ fi
+ done
+ if test "$ol_arg" = "invalid" ; then
+ { echo "configure: error: bad value $withval for --with-cyrus_sasl" 1>&2; exit 1; }
+ fi
+ ol_with_cyrus_sasl="$ol_arg"
+
+else
+ ol_with_cyrus_sasl="auto"
+fi
+# end --with-cyrus_sasl
+
+# OpenLDAP --with-fetch
+ # Check whether --with-fetch or --without-fetch was given.
+if test "${with_fetch+set}" = set; then
+ withval="$with_fetch"
+
+ ol_arg=invalid
+ for ol_val in auto yes no ; do
+ if test "$withval" = "$ol_val" ; then
+ ol_arg="$ol_val"
+ fi
+ done
+ if test "$ol_arg" = "invalid" ; then
+ { echo "configure: error: bad value $withval for --with-fetch" 1>&2; exit 1; }
+ fi
+ ol_with_fetch="$ol_arg"
+
+else
+ ol_with_fetch="auto"
+fi
+# end --with-fetch
+
# OpenLDAP --with-kerberos
# Check whether --with-kerberos or --without-kerberos was given.
if test "${with_kerberos+set}" = set; then
ol_enable_modules="no"
fi
# end --enable-modules
+# OpenLDAP --enable-multimaster
+ # Check whether --enable-multimaster or --disable-multimaster was given.
+if test "${enable_multimaster+set}" = set; then
+ enableval="$enable_multimaster"
+
+ ol_arg=invalid
+ for ol_val in auto yes no ; do
+ if test "$enableval" = "$ol_val" ; then
+ ol_arg="$ol_val"
+ fi
+ done
+ if test "$ol_arg" = "invalid" ; then
+ { echo "configure: error: bad value $enableval for --enable-multimaster" 1>&2; exit 1; }
+ fi
+ ol_enable_multimaster="$ol_arg"
+
+else
+ ol_enable_multimaster="no"
+fi
+# end --enable-multimaster
# OpenLDAP --enable-phonetic
# Check whether --enable-phonetic or --disable-phonetic was given.
if test "${enable_phonetic+set}" = set; then
ol_enable_phonetic="no"
fi
# end --enable-phonetic
+# OpenLDAP --enable-quipu
+ # Check whether --enable-quipu or --disable-quipu was given.
+if test "${enable_quipu+set}" = set; then
+ enableval="$enable_quipu"
+
+ ol_arg=invalid
+ for ol_val in auto yes no ; do
+ if test "$enableval" = "$ol_val" ; then
+ ol_arg="$ol_val"
+ fi
+ done
+ if test "$ol_arg" = "invalid" ; then
+ { echo "configure: error: bad value $enableval for --enable-quipu" 1>&2; exit 1; }
+ fi
+ ol_enable_quipu="$ol_arg"
+
+else
+ ol_enable_quipu="no"
+fi
+# end --enable-quipu
# OpenLDAP --enable-rlookups
# Check whether --enable-rlookups or --disable-rlookups was given.
if test "${enable_rlookups+set}" = set; then
if test $ol_enable_modules = yes ; then
echo "configure: warning: slapd disabled, ignoring --enable-modules argument" 1>&2
fi
+ if test $ol_enable_multimaster = yes ; then
+ echo "configure: warning: slapd disabled, ignoring --enable-multimaster argument" 1>&2
+ fi
if test $ol_enable_wrappers = yes ; then
echo "configure: warning: slapd disabled, ignoring --enable-wrappers argument" 1>&2
fi
if test $ol_enable_phonetic = yes ; then
echo "configure: warning: slapd disabled, ignoring --enable-phonetic argument" 1>&2
fi
+ if test $ol_enable_quipu = yes ; then
+ echo "configure: warning: slapd disabled, ignoring --enable-quipu argument" 1>&2
+ fi
if test $ol_enable_rlookups = yes ; then
echo "configure: warning: slapd disabled, ignoring --enable-rlookups argument" 1>&2
fi
ol_enable_tcl=no
ol_enable_modules=no
+ ol_enable_multimaster=no
ol_enable_phonetic=no
+ ol_enable_quipu=no
ol_enable_rlookups=no
ol_enable_wrappers=no
## Initialize vars
LDAP_LIBS=
+LDIF_LIBS=
LDBM_LIBS=
LTHREAD_LIBS=
LUTIL_LIBS=
BUILD_LDBM=no
BUILD_PASSWD=no
BUILD_PERL=no
+BUILD_QUIPU=no
BUILD_SHELL=no
BUILD_TCL=no
BUILD_THREAD=no
-BUILD_BDB2_DYNAMIC=no
-BUILD_LDAP_DYNAMIC=no
-BUILD_LDBM_DYNAMIC=no
-BUILD_PASSWD_DYNAMIC=no
-BUILD_PERL_DYNAMIC=no
-BUILD_SHELL_DYNAMIC=no
-BUILD_TCL_DYNAMIC=no
+BUILD_BDB2_DYNAMIC=static
+BUILD_LDAP_DYNAMIC=static
+BUILD_LDBM_DYNAMIC=static
+BUILD_PASSWD_DYNAMIC=static
+BUILD_PERL_DYNAMIC=static
+BUILD_SHELL_DYNAMIC=static
+BUILD_TCL_DYNAMIC=static
SLAPD_MODULES_LDFLAGS=
SLAPD_MODULES_CPPFLAGS=
+SLAPD_MODULES_LIST=
SLAPD_PERL_LDFLAGS=
SLAPD_PERL_CPPFLAGS=
KRB_LIBS=
READLINE_LIBS=
+SASL_LIBS=
TERMCAP_LIBS=
TLS_LIBS=
+MODULES_LIBS=
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2216: checking for $ac_word" >&5
+echo "configure:2325: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2268: checking for $ac_word" >&5
+echo "configure:2377: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
fi
+
# Check whether --enable-fast-install or --disable-fast-install was given.
if test "${enable_fast_install+set}" = set; then
enableval="$enable_fast_install"
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2326: checking for $ac_word" >&5
+echo "configure:2436: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_RANLIB+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2356: checking for $ac_word" >&5
+echo "configure:2466: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2386: checking for $ac_word" >&5
+echo "configure:2496: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2437: checking for $ac_word" >&5
+echo "configure:2547: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:2469: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works" >&5
+echo "configure:2579: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
cat > conftest.$ac_ext << EOF
-#line 2480 "configure"
+#line 2590 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-if { (eval echo configure:2485: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2595: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:2511: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:2621: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:2516: checking whether we are using GNU C" >&5
+echo "configure:2626: checking whether we are using GNU C" >&5
if eval "test \"\${ac_cv_prog_gcc+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2525: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2635: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:2544: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:2654: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"\${ac_cv_prog_cc_g+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "$ac_cv_prog_gcc" = yes; then
# Check if gcc -print-prog-name=ld gives a path.
echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
-echo "configure:2587: checking for ld used by GCC" >&5
+echo "configure:2697: checking for ld used by GCC" >&5
ac_prog=`($CC -print-prog-name=ld) 2>&5`
case "$ac_prog" in
# Accept absolute paths.
esac
elif test "$with_gnu_ld" = yes; then
echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
-echo "configure:2611: checking for GNU ld" >&5
+echo "configure:2721: checking for GNU ld" >&5
else
echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
-echo "configure:2614: checking for non-GNU ld" >&5
+echo "configure:2724: checking for non-GNU ld" >&5
fi
if eval "test \"\${ac_cv_path_LD+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
-echo "configure:2650: checking if the linker ($LD) is GNU ld" >&5
+echo "configure:2760: checking if the linker ($LD) is GNU ld" >&5
if eval "test \"\${ac_cv_prog_gnu_ld+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
-echo "configure:2666: checking for BSD-compatible nm" >&5
+echo "configure:2776: checking for BSD-compatible nm" >&5
if eval "test \"\${ac_cv_path_NM+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:2703: checking whether ln -s works" >&5
+echo "configure:2813: checking whether ln -s works" >&5
if eval "test \"\${ac_cv_prog_LN_S+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
-
+libtool_flags="$libtool_flags --enable-dlopen"
# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
if test "${enable_libtool_lock+set}" = set; then
case "$host" in
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 2747 "configure"' > conftest.$ac_ext
- if { (eval echo configure:2748: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ echo '#line 2857 "configure"' > conftest.$ac_ext
+ if { (eval echo configure:2858: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
case "`/usr/bin/file conftest.o`" in
*32-bit*)
LD="${LD-ld} -32"
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -belf"
echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
-echo "configure:2769: checking whether the C compiler needs -belf" >&5
+echo "configure:2879: checking whether the C compiler needs -belf" >&5
if eval "test \"\${lt_cv_cc_needs_belf+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2774 "configure"
+#line 2884 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:2781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2891: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
lt_cv_cc_needs_belf=yes
else
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2835: checking for $ac_word" >&5
+echo "configure:2945: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_AWK+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# test for ln hardlink support
echo $ac_n "checking whether ln works""... $ac_c" 1>&6
-echo "configure:2866: checking whether ln works" >&5
+echo "configure:2976: checking whether ln works" >&5
if eval "test \"\${ol_cv_prog_LN_H+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
fi
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:2889: checking whether ln -s works" >&5
+echo "configure:2999: checking whether ln -s works" >&5
if eval "test \"\${ac_cv_prog_LN_S+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "sendmail", so it can be a program name with args.
set dummy sendmail; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2917: checking for $ac_word" >&5
+echo "configure:3027: checking for $ac_word" >&5
if eval "test \"\${ac_cv_path_SENDMAIL+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "vi", so it can be a program name with args.
set dummy vi; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2953: checking for $ac_word" >&5
+echo "configure:3063: checking for $ac_word" >&5
if eval "test \"\${ac_cv_path_EDITOR+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "finger", so it can be a program name with args.
set dummy finger; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2989: checking for $ac_word" >&5
+echo "configure:3099: checking for $ac_word" >&5
if eval "test \"\${ac_cv_path_FINGER+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "perl", so it can be a program name with args.
set dummy perl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3028: checking for $ac_word" >&5
+echo "configure:3138: checking for $ac_word" >&5
if eval "test \"\${ac_cv_path_PERLBIN+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:3076: checking how to run the C preprocessor" >&5
+echo "configure:3186: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 3091 "configure"
+#line 3201 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3097: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3207: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 3108 "configure"
+#line 3218 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3114: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3224: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
-#line 3125 "configure"
+#line 3235 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3131: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3241: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
fi
echo $ac_n "checking for AIX""... $ac_c" 1>&6
-echo "configure:3169: checking for AIX" >&5
+echo "configure:3279: checking for AIX" >&5
cat > conftest.$ac_ext <<EOF
-#line 3171 "configure"
+#line 3281 "configure"
#include "confdefs.h"
#ifdef _AIX
yes
echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
-echo "configure:3193: checking for POSIXized ISC" >&5
+echo "configure:3303: checking for POSIXized ISC" >&5
if test -d /etc/conf/kconfig.d &&
grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
then
ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
-echo "configure:3215: checking for minix/config.h" >&5
+echo "configure:3325: checking for minix/config.h" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3220 "configure"
+#line 3330 "configure"
#include "confdefs.h"
#include <minix/config.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3225: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3335: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
-echo "configure:3264: checking for Cygwin environment" >&5
+echo "configure:3374: checking for Cygwin environment" >&5
if eval "test \"\${ac_cv_cygwin+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3269 "configure"
+#line 3379 "configure"
#include "confdefs.h"
int main() {
return __CYGWIN__;
; return 0; }
EOF
-if { (eval echo configure:3280: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3390: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_cygwin=yes
else
CYGWIN=
test "$ac_cv_cygwin" = yes && CYGWIN=yes
echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
-echo "configure:3296: checking for mingw32 environment" >&5
+echo "configure:3406: checking for mingw32 environment" >&5
if eval "test \"\${ac_cv_mingw32+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3301 "configure"
+#line 3411 "configure"
#include "confdefs.h"
int main() {
return __MINGW32__;
; return 0; }
EOF
-if { (eval echo configure:3308: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3418: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_mingw32=yes
else
MINGW32=
test "$ac_cv_mingw32" = yes && MINGW32=yes
echo $ac_n "checking for EMX OS/2 environment""... $ac_c" 1>&6
-echo "configure:3324: checking for EMX OS/2 environment" >&5
+echo "configure:3434: checking for EMX OS/2 environment" >&5
if eval "test \"\${ac_cv_emxos2+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3329 "configure"
+#line 3439 "configure"
#include "confdefs.h"
int main() {
return __EMX__;
; return 0; }
EOF
-if { (eval echo configure:3336: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3446: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_emxos2=yes
else
echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
-echo "configure:3355: checking for executable suffix" >&5
+echo "configure:3465: checking for executable suffix" >&5
if eval "test \"\${ac_cv_exeext+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
rm -f conftest*
echo 'int main () { return 0; }' > conftest.$ac_ext
ac_cv_exeext=
- if { (eval echo configure:3365: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ if { (eval echo configure:3475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
for file in conftest.*; do
case $file in
*.c | *.C | *.o | *.obj | *.xcoff) ;;
ac_exeext=$EXEEXT
echo $ac_n "checking for object suffix""... $ac_c" 1>&6
-echo "configure:3386: checking for object suffix" >&5
+echo "configure:3496: checking for object suffix" >&5
if eval "test \"\${ac_cv_objext+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
rm -f conftest*
echo 'int i = 1;' > conftest.$ac_ext
-if { (eval echo configure:3392: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3502: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
for ac_file in conftest.*; do
case $ac_file in
*.c) ;;
echo $ac_n "checking for be_app in -lbe""... $ac_c" 1>&6
-echo "configure:3416: checking for be_app in -lbe" >&5
+echo "configure:3526: checking for be_app in -lbe" >&5
ac_lib_var=`echo be'_'be_app | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lbe -lroot -lnet $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3424 "configure"
+#line 3534 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
be_app()
; return 0; }
EOF
-if { (eval echo configure:3435: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3545: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6
-echo "configure:3461: checking for ${CC-cc} option to accept ANSI C" >&5
+echo "configure:3571: checking for ${CC-cc} option to accept ANSI C" >&5
if eval "test \"\${am_cv_prog_cc_stdc+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
do
CC="$ac_save_CC $ac_arg"
cat > conftest.$ac_ext <<EOF
-#line 3478 "configure"
+#line 3588 "configure"
#include "confdefs.h"
#include <stdarg.h>
#include <stdio.h>
; return 0; }
EOF
-if { (eval echo configure:3515: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3625: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
am_cv_prog_cc_stdc="$ac_arg"; break
else
OL_MKDEP="${CC-cc}"
if test -z "${MKDEP_FLAGS}"; then
echo $ac_n "checking for ${OL_MKDEP} depend flag""... $ac_c" 1>&6
-echo "configure:3549: checking for ${OL_MKDEP} depend flag" >&5
+echo "configure:3659: checking for ${OL_MKDEP} depend flag" >&5
if eval "test \"\${ol_cv_mkdep+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.c <<EOF
noCode;
EOF
- if { ac_try='$OL_MKDEP $flag conftest.c'; { (eval echo configure:3559: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } \
+ if { ac_try='$OL_MKDEP $flag conftest.c'; { (eval echo configure:3669: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } \
| egrep '^conftest\.'"${ac_objext}" >/dev/null 2>&1
then
if test ! -f conftest."${ac_object}" ; then
ol_link_modules=no
if test $ol_enable_modules != no ; then
- # Extract the first word of "glib-config", so it can be a program name with args.
-set dummy glib-config; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3596: checking for $ac_word" >&5
-if eval "test \"\${ac_cv_path_GLIBCONFIG+set}\" = set"; then
+ for ac_hdr in ltdl.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:3707: checking for $ac_hdr" >&5
+if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- case "$GLIBCONFIG" in
- /*)
- ac_cv_path_GLIBCONFIG="$GLIBCONFIG" # Let the user override the test with a path.
- ;;
- ?:/*)
- ac_cv_path_GLIBCONFIG="$GLIBCONFIG" # Let the user override the test with a dos path.
- ;;
- *)
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_path_GLIBCONFIG="$ac_dir/$ac_word"
- break
- fi
- done
- IFS="$ac_save_ifs"
- ;;
-esac
+ cat > conftest.$ac_ext <<EOF
+#line 3712 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3717: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
fi
-GLIBCONFIG="$ac_cv_path_GLIBCONFIG"
-if test -n "$GLIBCONFIG"; then
- echo "$ac_t""$GLIBCONFIG" 1>&6
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
else
echo "$ac_t""no" 1>&6
fi
+done
- if test "no$GLIBCONFIG" = "no" ; then
- if test $ol_enable_modules = yes ; then
- { echo "configure: error: could not locate glib-config" 1>&2; exit 1; }
- fi
+ if test $ac_cv_header_ltdl_h = no ; then
+ { echo "configure: error: could not locate libtool ltdl.h" 1>&2; exit 1; }
- else
- SLAPD_MODULES_VERSION="`$GLIBCONFIG --version gmodule`"
- SLAPD_MODULES_CPPFLAGS="`$GLIBCONFIG --cflags gmodule`"
- SLAPD_MODULES_LDFLAGS="`$GLIBCONFIG --libs gmodule`"
+ fi
+
+ echo $ac_n "checking for lt_dlinit in -lltdl""... $ac_c" 1>&6
+echo "configure:3750: checking for lt_dlinit in -lltdl" >&5
+ac_lib_var=`echo ltdl'_'lt_dlinit | sed 'y%./+-:%__p__%'`
+if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lltdl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3758 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char lt_dlinit();
+
+int main() {
+lt_dlinit()
+; return 0; }
+EOF
+if { (eval echo configure:3769: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo ltdl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lltdl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
- ol_link_modules=yes
+ if test "$ac_cv_lib_ltdl_lt_dlinit" = no ; then
+ { echo "configure: error: could not locate libtool -lltdl" 1>&2; exit 1; }
fi
+ ol_link_modules=yes
else
ol_with_bdb2_module=static
ol_with_ldap_module=static
# test for EBCDIC
echo $ac_n "checking for EBCDIC""... $ac_c" 1>&6
-echo "configure:3653: checking for EBCDIC" >&5
+echo "configure:3812: checking for EBCDIC" >&5
if eval "test \"\${ol_cv_cpp_ebcdic+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3659 "configure"
+#line 3818 "configure"
#include "confdefs.h"
#if !('M' == 0xd4)
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3668: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3827: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
fi
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:3692: checking for ANSI C header files" >&5
+echo "configure:3851: checking for ANSI C header files" >&5
if eval "test \"\${ol_cv_header_stdc+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3697 "configure"
+#line 3856 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3705: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3864: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ol_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 3722 "configure"
+#line 3881 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if test $ol_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 3740 "configure"
+#line 3899 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
:
else
cat > conftest.$ac_ext <<EOF
-#line 3761 "configure"
+#line 3920 "configure"
#include "confdefs.h"
#include <ctype.h>
#ifndef HAVE_EBCDIC
exit (0); }
EOF
-if { (eval echo configure:3779: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3938: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
-echo "configure:3813: checking for $ac_hdr that defines DIR" >&5
+echo "configure:3972: checking for $ac_hdr that defines DIR" >&5
if eval "test \"\${ac_cv_header_dirent_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3818 "configure"
+#line 3977 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
DIR *dirp = 0;
; return 0; }
EOF
-if { (eval echo configure:3826: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3985: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_header_dirent_$ac_safe=yes"
else
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:3851: checking for opendir in -ldir" >&5
+echo "configure:4010: checking for opendir in -ldir" >&5
ac_lib_var=`echo dir'_'opendir | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ldir $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3859 "configure"
+#line 4018 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
opendir()
; return 0; }
EOF
-if { (eval echo configure:3870: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4029: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
else
echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:3892: checking for opendir in -lx" >&5
+echo "configure:4051: checking for opendir in -lx" >&5
ac_lib_var=`echo x'_'opendir | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lx $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3900 "configure"
+#line 4059 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
opendir()
; return 0; }
EOF
-if { (eval echo configure:3911: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4070: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
-echo "configure:3934: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo "configure:4093: checking for sys/wait.h that is POSIX.1 compatible" >&5
if eval "test \"\${ac_cv_header_sys_wait_h+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3939 "configure"
+#line 4098 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/wait.h>
s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
; return 0; }
EOF
-if { (eval echo configure:3955: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4114: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_sys_wait_h=yes
else
fi
echo $ac_n "checking POSIX termios""... $ac_c" 1>&6
-echo "configure:3976: checking POSIX termios" >&5
+echo "configure:4135: checking POSIX termios" >&5
if eval "test \"\${am_cv_sys_posix_termios+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3981 "configure"
+#line 4140 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <unistd.h>
tcgetattr(0, 0);
; return 0; }
EOF
-if { (eval echo configure:3991: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4150: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
am_cv_sys_posix_termios=yes
else
echo $ac_n "checking whether use of TIOCGWINSZ requires sys/ioctl.h""... $ac_c" 1>&6
-echo "configure:4007: checking whether use of TIOCGWINSZ requires sys/ioctl.h" >&5
+echo "configure:4166: checking whether use of TIOCGWINSZ requires sys/ioctl.h" >&5
if eval "test \"\${am_cv_sys_tiocgwinsz_needs_sys_ioctl_h+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
gwinsz_in_termios_h=no
if test $am_cv_sys_posix_termios = yes; then
cat > conftest.$ac_ext <<EOF
-#line 4016 "configure"
+#line 4175 "configure"
#include "confdefs.h"
#include <sys/types.h>
# include <termios.h>
if test $gwinsz_in_termios_h = no; then
cat > conftest.$ac_ext <<EOF
-#line 4036 "configure"
+#line 4195 "configure"
#include "confdefs.h"
#include <sys/types.h>
# include <sys/ioctl.h>
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4115: checking for $ac_hdr" >&5
+echo "configure:4274: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4120 "configure"
+#line 4279 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4125: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4284: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
echo $ac_n "checking for socket""... $ac_c" 1>&6
-echo "configure:4155: checking for socket" >&5
+echo "configure:4314: checking for socket" >&5
if eval "test \"\${ac_cv_func_socket+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4160 "configure"
+#line 4319 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char socket(); below. */
; return 0; }
EOF
-if { (eval echo configure:4184: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4343: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_socket=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for main in -lsocket""... $ac_c" 1>&6
-echo "configure:4203: checking for main in -lsocket" >&5
+echo "configure:4362: checking for main in -lsocket" >&5
ac_lib_var=`echo socket'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lsocket $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4211 "configure"
+#line 4370 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:4218: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4377: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for main in -lnet""... $ac_c" 1>&6
-echo "configure:4246: checking for main in -lnet" >&5
+echo "configure:4405: checking for main in -lnet" >&5
ac_lib_var=`echo net'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lnet $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4254 "configure"
+#line 4413 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:4261: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4420: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for socket in -lnet""... $ac_c" 1>&6
-echo "configure:4289: checking for socket in -lnet" >&5
+echo "configure:4448: checking for socket in -lnet" >&5
ac_lib_var=`echo net'_'socket | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lnet $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4297 "configure"
+#line 4456 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
socket()
; return 0; }
EOF
-if { (eval echo configure:4308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4467: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for main in -lnsl_s""... $ac_c" 1>&6
-echo "configure:4336: checking for main in -lnsl_s" >&5
+echo "configure:4495: checking for main in -lnsl_s" >&5
ac_lib_var=`echo nsl_s'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lnsl_s $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4344 "configure"
+#line 4503 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:4351: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4510: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6
-echo "configure:4379: checking for main in -lnsl" >&5
+echo "configure:4538: checking for main in -lnsl" >&5
ac_lib_var=`echo nsl'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lnsl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4387 "configure"
+#line 4546 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:4394: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4553: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6
-echo "configure:4422: checking for socket in -linet" >&5
+echo "configure:4581: checking for socket in -linet" >&5
ac_lib_var=`echo inet'_'socket | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-linet $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4430 "configure"
+#line 4589 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
socket()
; return 0; }
EOF
-if { (eval echo configure:4441: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for main in -lgen""... $ac_c" 1>&6
-echo "configure:4469: checking for main in -lgen" >&5
+echo "configure:4628: checking for main in -lgen" >&5
ac_lib_var=`echo gen'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lgen $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4477 "configure"
+#line 4636 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:4484: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4643: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo $ac_n "checking for select""... $ac_c" 1>&6
-echo "configure:4516: checking for select" >&5
+echo "configure:4675: checking for select" >&5
if eval "test \"\${ac_cv_func_select+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4521 "configure"
+#line 4680 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char select(); below. */
; return 0; }
EOF
-if { (eval echo configure:4545: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4704: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_select=yes"
else
echo $ac_n "checking types of arguments for select()""... $ac_c" 1>&6
-echo "configure:4567: checking types of arguments for select()" >&5
+echo "configure:4726: checking types of arguments for select()" >&5
if eval "test \"\${ac_cv_func_select_arg234+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_cv_func_select_arg1 in 'int' 'size_t' 'unsigned long' 'unsigned'; do
for ac_cv_func_select_arg5 in 'struct timeval *' 'const struct timeval *'; do
cat > conftest.$ac_ext <<EOF
-#line 4581 "configure"
+#line 4740 "configure"
#include "confdefs.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
; return 0; }
EOF
-if { (eval echo configure:4600: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4759: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_not_found=no ; break 3
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4644: checking for $ac_hdr" >&5
+echo "configure:4803: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4649 "configure"
+#line 4808 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4654: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4813: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
{ echo "configure: error: POSIX regex.h required." 1>&2; exit 1; }
fi
echo $ac_n "checking for regfree""... $ac_c" 1>&6
-echo "configure:4684: checking for regfree" >&5
+echo "configure:4843: checking for regfree" >&5
if eval "test \"\${ac_cv_func_regfree+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4689 "configure"
+#line 4848 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char regfree(); below. */
; return 0; }
EOF
-if { (eval echo configure:4713: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4872: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_regfree=yes"
else
echo $ac_n "checking for compatible POSIX regex""... $ac_c" 1>&6
-echo "configure:4736: checking for compatible POSIX regex" >&5
+echo "configure:4895: checking for compatible POSIX regex" >&5
if eval "test \"\${ol_cv_c_posix_regex+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ol_cv_c_posix_regex=cross
else
cat > conftest.$ac_ext <<EOF
-#line 4745 "configure"
+#line 4904 "configure"
#include "confdefs.h"
#include <sys/types.h>
return rc;
}
EOF
-if { (eval echo configure:4771: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4930: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ol_cv_c_posix_regex=yes
else
echo $ac_n "checking for sigset in -lV3""... $ac_c" 1>&6
-echo "configure:4793: checking for sigset in -lV3" >&5
+echo "configure:4952: checking for sigset in -lV3" >&5
ac_lib_var=`echo V3'_'sigset | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lV3 $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4801 "configure"
+#line 4960 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
sigset()
; return 0; }
EOF
-if { (eval echo configure:4812: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4971: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
-
-# find res_search
-if test $ol_enable_dns != no ; then
- echo $ac_n "checking for res_search""... $ac_c" 1>&6
-echo "configure:4844: checking for res_search" >&5
+echo $ac_n "checking for res_search""... $ac_c" 1>&6
+echo "configure:5000: checking for res_search" >&5
if eval "test \"\${ac_cv_func_res_search+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4849 "configure"
+#line 5005 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char res_search(); below. */
; return 0; }
EOF
-if { (eval echo configure:4873: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5029: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_res_search=yes"
else
echo "$ac_t""no" 1>&6
fi
- if test $ac_cv_func_res_search = no ; then
- echo $ac_n "checking for res_search in -lbind""... $ac_c" 1>&6
-echo "configure:4894: checking for res_search in -lbind" >&5
+if test $ac_cv_func_res_search = no ; then
+ echo $ac_n "checking for res_search in -lbind""... $ac_c" 1>&6
+echo "configure:5050: checking for res_search in -lbind" >&5
ac_lib_var=`echo bind'_'res_search | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lbind $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4902 "configure"
+#line 5058 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
res_search()
; return 0; }
EOF
-if { (eval echo configure:4913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5069: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo "$ac_t""no" 1>&6
fi
- ac_cv_func_res_search=$ac_cv_lib_bind_res_search
- fi
- if test $ac_cv_func_res_search = no ; then
- echo $ac_n "checking for res_search in -lresolv""... $ac_c" 1>&6
-echo "configure:4944: checking for res_search in -lresolv" >&5
+ ac_cv_func_res_search=$ac_cv_lib_bind_res_search
+fi
+
+if test $ac_cv_func_res_search = no ; then
+ echo $ac_n "checking for __res_search in -lbind""... $ac_c" 1>&6
+echo "configure:5101: checking for __res_search in -lbind" >&5
+ac_lib_var=`echo bind'_'__res_search | sed 'y%./+-:%__p__%'`
+if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lbind $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5109 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char __res_search();
+
+int main() {
+__res_search()
+; return 0; }
+EOF
+if { (eval echo configure:5120: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo bind | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lbind $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ac_cv_func_res_search=$ac_cv_lib_bind___res_search
+fi
+
+if test $ac_cv_func_res_search = no ; then
+ echo $ac_n "checking for res_search in -lresolv""... $ac_c" 1>&6
+echo "configure:5152: checking for res_search in -lresolv" >&5
ac_lib_var=`echo resolv'_'res_search | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lresolv $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4952 "configure"
+#line 5160 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
res_search()
; return 0; }
EOF
-if { (eval echo configure:4963: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5171: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo "$ac_t""no" 1>&6
fi
- ac_cv_func_res_search=$ac_cv_lib_resolv_res_search
- fi
+ ac_cv_func_res_search=$ac_cv_lib_resolv_res_search
+fi
- if test "$ac_cv_func_res_search" = yes ; then
- cat >> confdefs.h <<\EOF
+if test "$ac_cv_func_res_search" = yes ; then
+ cat >> confdefs.h <<\EOF
#define HAVE_RES_SEARCH 1
EOF
- elif test $ol_enable_dns = yes ; then
- { echo "configure: error: --enable-dns requires res_search" 1>&2; exit 1; }
+elif test $ol_enable_dns = yes ; then
+ { echo "configure: error: --enable-dns requires res_search" 1>&2; exit 1; }
+elif test $ol_enable_dns != no ; then
+ echo "configure: warning: no res_search, disabling DNS support" 1>&2
+fi
+
+
+# QUIPU
+if test $ol_enable_quipu != no ; then
+ for ac_hdr in quipu/commonarg.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:5219: checking for $ac_hdr" >&5
+if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5224 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5229: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+ if test $ac_cv_header_quipu_commonarg_h = yes ; then
+ BUILD_QUIPU=yes
+ elif test $ol_enable_quipu = auto ; then
+ echo "configure: warning: no quipu for --enable-quipu=auto, disabling" 1>&2
else
- echo "configure: warning: no res_search, disabling DNS support" 1>&2
+ { echo "configure: error: no quipu for --enable-quipu=$ol_enable_quipu" 1>&2; exit 1; }
fi
fi
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:5012: checking for $ac_hdr" >&5
+echo "configure:5272: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5017 "configure"
+#line 5277 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:5022: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:5282: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_kerberosIV_krb_h = yes ; then
echo $ac_n "checking for main in -lkrb4""... $ac_c" 1>&6
-echo "configure:5051: checking for main in -lkrb4" >&5
+echo "configure:5311: checking for main in -lkrb4" >&5
ac_lib_var=`echo krb4'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lkrb4 -lkrb5 -ldes425 $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 5059 "configure"
+#line 5319 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:5066: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
LIBS="$KRB_LIBS $LIBS"
echo $ac_n "checking for des_debug in Kerberos libraries""... $ac_c" 1>&6
-echo "configure:5097: checking for des_debug in Kerberos libraries" >&5
+echo "configure:5357: checking for des_debug in Kerberos libraries" >&5
if eval "test \"\${ol_cv_var_des_debug+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
save_LIBS="$LIBS"
LIBS="$KRB_LIBS $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 5105 "configure"
+#line 5365 "configure"
#include "confdefs.h"
#include <kerberosIV/krb.h>
; return 0; }
EOF
-if { (eval echo configure:5118: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5378: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ol_cv_var_des_debug=yes
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:5151: checking for $ac_hdr" >&5
+echo "configure:5411: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5156 "configure"
+#line 5416 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:5161: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:5421: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_krb_h = yes ; then
echo $ac_n "checking for main in -lkrb""... $ac_c" 1>&6
-echo "configure:5190: checking for main in -lkrb" >&5
+echo "configure:5450: checking for main in -lkrb" >&5
ac_lib_var=`echo krb'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lkrb -ldes $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 5198 "configure"
+#line 5458 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:5205: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5465: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:5250: checking for $ac_hdr" >&5
+echo "configure:5510: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5255 "configure"
+#line 5515 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:5260: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:5520: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_openssl_ssl_h = yes -o $ac_cv_header_ssl_h = yes ; then
echo $ac_n "checking for SSLeay_add_ssl_algorithms in -lssl""... $ac_c" 1>&6
-echo "configure:5289: checking for SSLeay_add_ssl_algorithms in -lssl" >&5
+echo "configure:5549: checking for SSLeay_add_ssl_algorithms in -lssl" >&5
ac_lib_var=`echo ssl'_'SSLeay_add_ssl_algorithms | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lssl -lcrypto $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 5297 "configure"
+#line 5557 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
SSLeay_add_ssl_algorithms()
; return 0; }
EOF
-if { (eval echo configure:5308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5568: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if test $have_ssleay = no ; then
echo $ac_n "checking for SSL_library_init in -lssl""... $ac_c" 1>&6
-echo "configure:5333: checking for SSL_library_init in -lssl" >&5
+echo "configure:5593: checking for SSL_library_init in -lssl" >&5
ac_lib_var=`echo ssl'_'SSL_library_init | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lssl -lcrypto $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 5341 "configure"
+#line 5601 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
SSL_library_init()
; return 0; }
EOF
-if { (eval echo configure:5352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5612: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if test $have_ssleay = no ; then
echo $ac_n "checking for ssl3_accept in -lssl""... $ac_c" 1>&6
-echo "configure:5378: checking for ssl3_accept in -lssl" >&5
+echo "configure:5638: checking for ssl3_accept in -lssl" >&5
ac_lib_var=`echo ssl'_'ssl3_accept | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lssl -lcrypto -lRSAglue -lrsaref $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 5386 "configure"
+#line 5646 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
ssl3_accept()
; return 0; }
EOF
-if { (eval echo configure:5397: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5657: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5457: checking for $ac_func" >&5
+echo "configure:5717: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5462 "configure"
+#line 5722 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:5486: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5746: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
ol_cv_func_ctime_r_nargs=0
else
echo $ac_n "checking number of arguments of ctime_r""... $ac_c" 1>&6
-echo "configure:5515: checking number of arguments of ctime_r" >&5
+echo "configure:5775: checking number of arguments of ctime_r" >&5
if eval "test \"\${ol_cv_func_ctime_r_nargs+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5520 "configure"
+#line 5780 "configure"
#include "confdefs.h"
#include <time.h>
int main() {
time_t ti; char *buffer; ctime_r(&ti,buffer,32);
; return 0; }
EOF
-if { (eval echo configure:5527: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5787: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_func_ctime_r_nargs=3
else
cat conftest.$ac_ext >&5
rm -rf conftest*
cat > conftest.$ac_ext <<EOF
-#line 5535 "configure"
+#line 5795 "configure"
#include "confdefs.h"
#include <time.h>
int main() {
time_t ti; char *buffer; ctime_r(&ti,buffer);
; return 0; }
EOF
-if { (eval echo configure:5542: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5802: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_func_ctime_r_nargs=2
else
if test "$ac_cv_func_gethostbyname_r" = yes ; then
echo $ac_n "checking number of arguments of gethostbyname_r""... $ac_c" 1>&6
-echo "configure:5568: checking number of arguments of gethostbyname_r" >&5
+echo "configure:5828: checking number of arguments of gethostbyname_r" >&5
if eval "test \"\${ol_cv_func_gethostbyname_r_nargs+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5573 "configure"
+#line 5833 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
buffer, bufsize, &h_errno);
; return 0; }
EOF
-if { (eval echo configure:5587: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5847: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_func_gethostbyname_r_nargs=5
else
cat conftest.$ac_ext >&5
rm -rf conftest*
cat > conftest.$ac_ext <<EOF
-#line 5595 "configure"
+#line 5855 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
&rhent, &h_errno);
; return 0; }
EOF
-if { (eval echo configure:5610: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5870: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_func_gethostbyname_r_nargs=6
else
if test "$ac_cv_func_gethostbyaddr_r" = yes ; then
echo $ac_n "checking number of arguments of gethostbyaddr_r""... $ac_c" 1>&6
-echo "configure:5638: checking number of arguments of gethostbyaddr_r" >&5
+echo "configure:5898: checking number of arguments of gethostbyaddr_r" >&5
if eval "test \"\${ol_cv_func_gethostbyaddr_r_nargs+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5643 "configure"
+#line 5903 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
alen, AF_INET, &hent, buffer, bufsize, &h_errno);
; return 0; }
EOF
-if { (eval echo configure:5659: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5919: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_func_gethostbyaddr_r_nargs=7
else
cat conftest.$ac_ext >&5
rm -rf conftest*
cat > conftest.$ac_ext <<EOF
-#line 5667 "configure"
+#line 5927 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
&rhent, &h_errno);
; return 0; }
EOF
-if { (eval echo configure:5685: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5945: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_func_gethostbyaddr_r_nargs=8
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:5736: checking for $ac_hdr" >&5
+echo "configure:5996: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5741 "configure"
+#line 6001 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:5746: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6006: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_pthread_h = yes ; then
echo $ac_n "checking POSIX thread version""... $ac_c" 1>&6
-echo "configure:5775: checking POSIX thread version" >&5
+echo "configure:6035: checking POSIX thread version" >&5
if eval "test \"\${ol_cv_pthread_version+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5781 "configure"
+#line 6041 "configure"
#include "confdefs.h"
# include <pthread.h>
cat > conftest.$ac_ext <<EOF
-#line 5803 "configure"
+#line 6063 "configure"
#include "confdefs.h"
# include <pthread.h>
echo $ac_n "checking for LinuxThreads pthread.h""... $ac_c" 1>&6
-echo "configure:5856: checking for LinuxThreads pthread.h" >&5
+echo "configure:6116: checking for LinuxThreads pthread.h" >&5
if eval "test \"\${ol_cv_header_linux_threads+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5861 "configure"
+#line 6121 "configure"
#include "confdefs.h"
#include <pthread.h>
EOF
echo $ac_n "checking for pthread_create in default libraries""... $ac_c" 1>&6
-echo "configure:5889: checking for pthread_create in default libraries" >&5
+echo "configure:6149: checking for pthread_create in default libraries" >&5
if eval "test \"\${ol_cv_pthread_create+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "$cross_compiling" = yes; then
- ol_cv_pthread_create=yes
-else
cat > conftest.$ac_ext <<EOF
-#line 5898 "configure"
+#line 6156 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
return (void *) (p == NULL);
}
-int main(argc, argv)
- int argc;
- char **argv;
-{
+int main() {
+
+ /* pthread test function */
pthread_t t;
int status;
status = pthread_create(&t, NULL, task, NULL);
#endif
- if( status ) return status;
+ if( status ) exit( status );
/* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
status = pthread_detach( t );
#endif
- return status;
-}
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+; return 0; }
EOF
-if { (eval echo configure:5939: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+if { (eval echo configure:6200: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
ol_cv_pthread_create=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -fr conftest*
+ rm -rf conftest*
+ ol_cv_pthread_create=no
+fi
+rm -f conftest*
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6212 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+}
+
+EOF
+if { (eval echo configure:6261: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_create=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
ol_cv_pthread_create=no
fi
rm -fr conftest*
ol_link_pthreads=""
fi
- # Pthread try link: -mt (ol_cv_pthread_mt)
- if test "$ol_link_threads" = no ; then
- # try -mt
- echo $ac_n "checking for pthread link with -mt""... $ac_c" 1>&6
-echo "configure:5964: checking for pthread link with -mt" >&5
-if eval "test \"\${ol_cv_pthread_mt+set}\" = set"; then
+ # Pthread try link: -kthread (ol_cv_pthread_kthread)
+if test "$ol_link_threads" = no ; then
+ # try -kthread
+ echo $ac_n "checking for pthread link with -kthread""... $ac_c" 1>&6
+echo "configure:6286: checking for pthread link with -kthread" >&5
+if eval "test \"\${ol_cv_pthread_kthread+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-mt $LIBS"
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-kthread $LIBS"
- cat > conftest.$ac_ext <<EOF
-#line 5974 "configure"
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 6297 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
int main() {
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
+ exit( status );
+
; return 0; }
EOF
-if { (eval echo configure:5999: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6341: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
- ol_cv_pthread_mt=yes
+ ol_cv_pthread_kthread=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
- ol_cv_pthread_mt=no
+ ol_cv_pthread_kthread=no
fi
rm -f conftest*
-
- # restore the LIBS
- LIBS="$ol_LIBS"
-
-fi
-
-echo "$ac_t""$ol_cv_pthread_mt" 1>&6
-
- if test $ol_cv_pthread_mt = yes ; then
- ol_link_pthreads="-mt"
- ol_link_threads=posix
- fi
- fi
-
- # Pthread try link: -kthread (ol_cv_pthread_kthread)
- if test "$ol_link_threads" = no ; then
- # try -kthread
- echo $ac_n "checking for pthread link with -kthread""... $ac_c" 1>&6
-echo "configure:6027: checking for pthread link with -kthread" >&5
-if eval "test \"\${ol_cv_pthread_kthread+set}\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
else
-
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-kthread $LIBS"
-
- cat > conftest.$ac_ext <<EOF
-#line 6037 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 6353 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
-int main() {
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
-; return 0; }
+ exit( status );
+
+}
+
EOF
-if { (eval echo configure:6062: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+if { (eval echo configure:6402: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
ol_cv_pthread_kthread=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
+ rm -fr conftest*
ol_cv_pthread_kthread=no
fi
-rm -f conftest*
+rm -fr conftest*
+fi
+
# restore the LIBS
LIBS="$ol_LIBS"
-
+
fi
echo "$ac_t""$ol_cv_pthread_kthread" 1>&6
- if test $ol_cv_pthread_kthread = yes ; then
- ol_link_pthreads="-kthread"
- ol_link_threads=posix
- fi
+ if test $ol_cv_pthread_kthread = yes ; then
+ ol_link_pthreads="-kthread"
+ ol_link_threads=posix
fi
+fi
# Pthread try link: -pthread (ol_cv_pthread_pthread)
- if test "$ol_link_threads" = no ; then
- # try -pthread
- echo $ac_n "checking for pthread link with -pthread""... $ac_c" 1>&6
-echo "configure:6090: checking for pthread link with -pthread" >&5
+if test "$ol_link_threads" = no ; then
+ # try -pthread
+ echo $ac_n "checking for pthread link with -pthread""... $ac_c" 1>&6
+echo "configure:6432: checking for pthread link with -pthread" >&5
if eval "test \"\${ol_cv_pthread_pthread+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-pthread $LIBS"
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-pthread $LIBS"
- cat > conftest.$ac_ext <<EOF
-#line 6100 "configure"
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 6443 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
int main() {
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
+ exit( status );
+
; return 0; }
EOF
-if { (eval echo configure:6125: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ol_cv_pthread_pthread=yes
else
ol_cv_pthread_pthread=no
fi
rm -f conftest*
-
- # restore the LIBS
- LIBS="$ol_LIBS"
-
-fi
-
-echo "$ac_t""$ol_cv_pthread_pthread" 1>&6
-
- if test $ol_cv_pthread_pthread = yes ; then
- ol_link_pthreads="-pthread"
- ol_link_threads=posix
- fi
- fi
-
- # Pthread try link: -pthreads (ol_cv_pthread_pthreads)
- if test "$ol_link_threads" = no ; then
- # try -pthreads
- echo $ac_n "checking for pthread link with -pthreads""... $ac_c" 1>&6
-echo "configure:6153: checking for pthread link with -pthreads" >&5
-if eval "test \"\${ol_cv_pthread_pthreads+set}\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
else
-
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-pthreads $LIBS"
-
- cat > conftest.$ac_ext <<EOF
-#line 6163 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 6499 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
-int main() {
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
-; return 0; }
+ exit( status );
+
+}
+
EOF
-if { (eval echo configure:6188: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- ol_cv_pthread_pthreads=yes
+if { (eval echo configure:6548: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_pthread=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- ol_cv_pthread_pthreads=no
+ rm -fr conftest*
+ ol_cv_pthread_pthread=no
+fi
+rm -fr conftest*
fi
-rm -f conftest*
+
# restore the LIBS
LIBS="$ol_LIBS"
-
+
fi
-echo "$ac_t""$ol_cv_pthread_pthreads" 1>&6
+echo "$ac_t""$ol_cv_pthread_pthread" 1>&6
- if test $ol_cv_pthread_pthreads = yes ; then
- ol_link_pthreads="-pthreads"
- ol_link_threads=posix
- fi
+ if test $ol_cv_pthread_pthread = yes ; then
+ ol_link_pthreads="-pthread"
+ ol_link_threads=posix
fi
+fi
- # Pthread try link: -mthreads (ol_cv_pthread_mthreads)
- if test "$ol_link_threads" = no ; then
- # try -mthreads
- echo $ac_n "checking for pthread link with -mthreads""... $ac_c" 1>&6
-echo "configure:6216: checking for pthread link with -mthreads" >&5
-if eval "test \"\${ol_cv_pthread_mthreads+set}\" = set"; then
+ # Pthread try link: -pthreads (ol_cv_pthread_pthreads)
+if test "$ol_link_threads" = no ; then
+ # try -pthreads
+ echo $ac_n "checking for pthread link with -pthreads""... $ac_c" 1>&6
+echo "configure:6578: checking for pthread link with -pthreads" >&5
+if eval "test \"\${ol_cv_pthread_pthreads+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-mthreads $LIBS"
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-pthreads $LIBS"
- cat > conftest.$ac_ext <<EOF
-#line 6226 "configure"
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 6589 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
int main() {
+ /* pthread test function */
pthread_t t;
+ int status;
+ /* make sure pthread_create() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
-#endif
-#ifdef HAVE_LINUX_THREADS
- pthread_kill_other_threads_np();
+ status = pthread_create(&t, NULL, task, NULL);
#endif
-; return 0; }
-EOF
-if { (eval echo configure:6251: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+; return 0; }
+EOF
+if { (eval echo configure:6633: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ol_cv_pthread_pthreads=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ol_cv_pthread_pthreads=no
+fi
+rm -f conftest*
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6645 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+}
+
+EOF
+if { (eval echo configure:6694: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_pthreads=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ol_cv_pthread_pthreads=no
+fi
+rm -fr conftest*
+fi
+
+
+ # restore the LIBS
+ LIBS="$ol_LIBS"
+
+fi
+
+echo "$ac_t""$ol_cv_pthread_pthreads" 1>&6
+
+ if test $ol_cv_pthread_pthreads = yes ; then
+ ol_link_pthreads="-pthreads"
+ ol_link_threads=posix
+ fi
+fi
+
+ # Pthread try link: -mthreads (ol_cv_pthread_mthreads)
+if test "$ol_link_threads" = no ; then
+ # try -mthreads
+ echo $ac_n "checking for pthread link with -mthreads""... $ac_c" 1>&6
+echo "configure:6724: checking for pthread link with -mthreads" >&5
+if eval "test \"\${ol_cv_pthread_mthreads+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-mthreads $LIBS"
+
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 6735 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main() {
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+; return 0; }
+EOF
+if { (eval echo configure:6779: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ol_cv_pthread_mthreads=yes
else
rm -rf conftest*
ol_cv_pthread_mthreads=no
fi
-rm -f conftest*
+rm -f conftest*
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6791 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+}
+
+EOF
+if { (eval echo configure:6840: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_mthreads=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ol_cv_pthread_mthreads=no
+fi
+rm -fr conftest*
+fi
+
+
+ # restore the LIBS
+ LIBS="$ol_LIBS"
+
+fi
+
+echo "$ac_t""$ol_cv_pthread_mthreads" 1>&6
+
+ if test $ol_cv_pthread_mthreads = yes ; then
+ ol_link_pthreads="-mthreads"
+ ol_link_threads=posix
+ fi
+fi
+
+ # Pthread try link: -thread (ol_cv_pthread_thread)
+if test "$ol_link_threads" = no ; then
+ # try -thread
+ echo $ac_n "checking for pthread link with -thread""... $ac_c" 1>&6
+echo "configure:6870: checking for pthread link with -thread" >&5
+if eval "test \"\${ol_cv_pthread_thread+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-thread $LIBS"
+
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 6881 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main() {
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+; return 0; }
+EOF
+if { (eval echo configure:6925: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ol_cv_pthread_thread=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ol_cv_pthread_thread=no
+fi
+rm -f conftest*
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6937 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+}
+
+EOF
+if { (eval echo configure:6986: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_thread=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ol_cv_pthread_thread=no
+fi
+rm -fr conftest*
+fi
+
+
+ # restore the LIBS
+ LIBS="$ol_LIBS"
+
+fi
+
+echo "$ac_t""$ol_cv_pthread_thread" 1>&6
+
+ if test $ol_cv_pthread_thread = yes ; then
+ ol_link_pthreads="-thread"
+ ol_link_threads=posix
+ fi
+fi
+
+
+ # Pthread try link: -lpthread -lmach -lexc -lc_r (ol_cv_pthread_lpthread_lmach_lexc_lc_r)
+if test "$ol_link_threads" = no ; then
+ # try -lpthread -lmach -lexc -lc_r
+ echo $ac_n "checking for pthread link with -lpthread -lmach -lexc -lc_r""... $ac_c" 1>&6
+echo "configure:7017: checking for pthread link with -lpthread -lmach -lexc -lc_r" >&5
+if eval "test \"\${ol_cv_pthread_lpthread_lmach_lexc_lc_r+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-lpthread -lmach -lexc -lc_r $LIBS"
+
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 7028 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main() {
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+; return 0; }
+EOF
+if { (eval echo configure:7072: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ol_cv_pthread_lpthread_lmach_lexc_lc_r=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ol_cv_pthread_lpthread_lmach_lexc_lc_r=no
+fi
+rm -f conftest*
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7084 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+}
+
+EOF
+if { (eval echo configure:7133: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_lpthread_lmach_lexc_lc_r=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ol_cv_pthread_lpthread_lmach_lexc_lc_r=no
+fi
+rm -fr conftest*
+fi
+
+
+ # restore the LIBS
+ LIBS="$ol_LIBS"
+
+fi
+
+echo "$ac_t""$ol_cv_pthread_lpthread_lmach_lexc_lc_r" 1>&6
+
+ if test $ol_cv_pthread_lpthread_lmach_lexc_lc_r = yes ; then
+ ol_link_pthreads="-lpthread -lmach -lexc -lc_r"
+ ol_link_threads=posix
+ fi
+fi
+
+ # Pthread try link: -lpthread -lmach -lexc (ol_cv_pthread_lpthread_lmach_lexc)
+if test "$ol_link_threads" = no ; then
+ # try -lpthread -lmach -lexc
+ echo $ac_n "checking for pthread link with -lpthread -lmach -lexc""... $ac_c" 1>&6
+echo "configure:7163: checking for pthread link with -lpthread -lmach -lexc" >&5
+if eval "test \"\${ol_cv_pthread_lpthread_lmach_lexc+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-lpthread -lmach -lexc $LIBS"
+
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 7174 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main() {
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+; return 0; }
+EOF
+if { (eval echo configure:7218: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ol_cv_pthread_lpthread_lmach_lexc=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ol_cv_pthread_lpthread_lmach_lexc=no
+fi
+rm -f conftest*
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7230 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+}
+
+EOF
+if { (eval echo configure:7279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_lpthread_lmach_lexc=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ol_cv_pthread_lpthread_lmach_lexc=no
+fi
+rm -fr conftest*
+fi
+
+
+ # restore the LIBS
+ LIBS="$ol_LIBS"
+
+fi
+
+echo "$ac_t""$ol_cv_pthread_lpthread_lmach_lexc" 1>&6
+
+ if test $ol_cv_pthread_lpthread_lmach_lexc = yes ; then
+ ol_link_pthreads="-lpthread -lmach -lexc"
+ ol_link_threads=posix
+ fi
+fi
+
+
+ # Pthread try link: -lpthread -Wl,-woff,85 (ol_cv_pthread_lib_lpthread_woff)
+if test "$ol_link_threads" = no ; then
+ # try -lpthread -Wl,-woff,85
+ echo $ac_n "checking for pthread link with -lpthread -Wl,-woff,85""... $ac_c" 1>&6
+echo "configure:7310: checking for pthread link with -lpthread -Wl,-woff,85" >&5
+if eval "test \"\${ol_cv_pthread_lib_lpthread_woff+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-lpthread -Wl,-woff,85 $LIBS"
+
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 7321 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main() {
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+; return 0; }
+EOF
+if { (eval echo configure:7365: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ol_cv_pthread_lib_lpthread_woff=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ol_cv_pthread_lib_lpthread_woff=no
+fi
+rm -f conftest*
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7377 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+}
+
+EOF
+if { (eval echo configure:7426: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_lib_lpthread_woff=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ol_cv_pthread_lib_lpthread_woff=no
+fi
+rm -fr conftest*
+fi
+
+
+ # restore the LIBS
+ LIBS="$ol_LIBS"
+
+fi
+
+echo "$ac_t""$ol_cv_pthread_lib_lpthread_woff" 1>&6
+
+ if test $ol_cv_pthread_lib_lpthread_woff = yes ; then
+ ol_link_pthreads="-lpthread -Wl,-woff,85"
+ ol_link_threads=posix
+ fi
+fi
+
+
+ # Pthread try link: -lpthread (ol_cv_pthread_lpthread)
+if test "$ol_link_threads" = no ; then
+ # try -lpthread
+ echo $ac_n "checking for pthread link with -lpthread""... $ac_c" 1>&6
+echo "configure:7457: checking for pthread link with -lpthread" >&5
+if eval "test \"\${ol_cv_pthread_lpthread+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 7468 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main() {
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+; return 0; }
+EOF
+if { (eval echo configure:7512: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ol_cv_pthread_lpthread=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ol_cv_pthread_lpthread=no
+fi
+rm -f conftest*
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7524 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
+
+}
+
+EOF
+if { (eval echo configure:7573: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_lpthread=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ol_cv_pthread_lpthread=no
+fi
+rm -fr conftest*
+fi
+
# restore the LIBS
LIBS="$ol_LIBS"
-
+
fi
-echo "$ac_t""$ol_cv_pthread_mthreads" 1>&6
+echo "$ac_t""$ol_cv_pthread_lpthread" 1>&6
- if test $ol_cv_pthread_mthreads = yes ; then
- ol_link_pthreads="-mthreads"
- ol_link_threads=posix
- fi
+ if test $ol_cv_pthread_lpthread = yes ; then
+ ol_link_pthreads="-lpthread"
+ ol_link_threads=posix
fi
+fi
- # Pthread try link: -thread (ol_cv_pthread_thread)
- if test "$ol_link_threads" = no ; then
- # try -thread
- echo $ac_n "checking for pthread link with -thread""... $ac_c" 1>&6
-echo "configure:6279: checking for pthread link with -thread" >&5
-if eval "test \"\${ol_cv_pthread_thread+set}\" = set"; then
+ # Pthread try link: -lc_r (ol_cv_pthread_lc_r)
+if test "$ol_link_threads" = no ; then
+ # try -lc_r
+ echo $ac_n "checking for pthread link with -lc_r""... $ac_c" 1>&6
+echo "configure:7603: checking for pthread link with -lc_r" >&5
+if eval "test \"\${ol_cv_pthread_lc_r+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-thread $LIBS"
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-lc_r $LIBS"
- cat > conftest.$ac_ext <<EOF
-#line 6289 "configure"
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 7614 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
int main() {
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
+ exit( status );
+
; return 0; }
EOF
-if { (eval echo configure:6314: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
- ol_cv_pthread_thread=yes
+ ol_cv_pthread_lc_r=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
- ol_cv_pthread_thread=no
+ ol_cv_pthread_lc_r=no
fi
rm -f conftest*
-
- # restore the LIBS
- LIBS="$ol_LIBS"
-
-fi
-
-echo "$ac_t""$ol_cv_pthread_thread" 1>&6
-
- if test $ol_cv_pthread_thread = yes ; then
- ol_link_pthreads="-thread"
- ol_link_threads=posix
- fi
- fi
-
-
- # Pthread try link: -lpthread -lmach -lexc -lc_r (ol_cv_pthread_lpthread_lmach_lexc_lc_r)
- if test "$ol_link_threads" = no ; then
- # try -lpthread -lmach -lexc -lc_r
- echo $ac_n "checking for pthread link with -lpthread -lmach -lexc -lc_r""... $ac_c" 1>&6
-echo "configure:6343: checking for pthread link with -lpthread -lmach -lexc -lc_r" >&5
-if eval "test \"\${ol_cv_pthread_lpthread_lmach_lexc_lc_r+set}\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
else
-
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-lpthread -lmach -lexc -lc_r $LIBS"
-
- cat > conftest.$ac_ext <<EOF
-#line 6353 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 7670 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
-int main() {
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
-; return 0; }
+ exit( status );
+
+}
+
EOF
-if { (eval echo configure:6378: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- ol_cv_pthread_lpthread_lmach_lexc_lc_r=yes
+if { (eval echo configure:7719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_lc_r=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- ol_cv_pthread_lpthread_lmach_lexc_lc_r=no
+ rm -fr conftest*
+ ol_cv_pthread_lc_r=no
fi
-rm -f conftest*
+rm -fr conftest*
+fi
+
# restore the LIBS
LIBS="$ol_LIBS"
-
+
fi
-echo "$ac_t""$ol_cv_pthread_lpthread_lmach_lexc_lc_r" 1>&6
+echo "$ac_t""$ol_cv_pthread_lc_r" 1>&6
- if test $ol_cv_pthread_lpthread_lmach_lexc_lc_r = yes ; then
- ol_link_pthreads="-lpthread -lmach -lexc -lc_r"
- ol_link_threads=posix
- fi
+ if test $ol_cv_pthread_lc_r = yes ; then
+ ol_link_pthreads="-lc_r"
+ ol_link_threads=posix
fi
+fi
- # Pthread try link: -lpthread -lmach -lexc (ol_cv_pthread_lpthread_lmach_lexc)
- if test "$ol_link_threads" = no ; then
- # try -lpthread -lmach -lexc
- echo $ac_n "checking for pthread link with -lpthread -lmach -lexc""... $ac_c" 1>&6
-echo "configure:6406: checking for pthread link with -lpthread -lmach -lexc" >&5
-if eval "test \"\${ol_cv_pthread_lpthread_lmach_lexc+set}\" = set"; then
+
+ # Pthread try link: -threads (ol_cv_pthread_threads)
+if test "$ol_link_threads" = no ; then
+ # try -threads
+ echo $ac_n "checking for pthread link with -threads""... $ac_c" 1>&6
+echo "configure:7750: checking for pthread link with -threads" >&5
+if eval "test \"\${ol_cv_pthread_threads+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-lpthread -lmach -lexc $LIBS"
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-threads $LIBS"
- cat > conftest.$ac_ext <<EOF
-#line 6416 "configure"
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 7761 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
int main() {
+ /* pthread test function */
pthread_t t;
+ int status;
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
+ exit( status );
+
; return 0; }
EOF
-if { (eval echo configure:6441: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7805: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
- ol_cv_pthread_lpthread_lmach_lexc=yes
+ ol_cv_pthread_threads=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
- ol_cv_pthread_lpthread_lmach_lexc=no
+ ol_cv_pthread_threads=no
fi
rm -f conftest*
-
- # restore the LIBS
- LIBS="$ol_LIBS"
-
-fi
-
-echo "$ac_t""$ol_cv_pthread_lpthread_lmach_lexc" 1>&6
-
- if test $ol_cv_pthread_lpthread_lmach_lexc = yes ; then
- ol_link_pthreads="-lpthread -lmach -lexc"
- ol_link_threads=posix
- fi
- fi
-
-
- # Pthread try link: -lpthread -Wl,-woff,85 (ol_cv_pthread_lib_lpthread_woff)
- if test "$ol_link_threads" = no ; then
- # try -lpthread -Wl,-woff,85
- echo $ac_n "checking for pthread link with -lpthread -Wl,-woff,85""... $ac_c" 1>&6
-echo "configure:6470: checking for pthread link with -lpthread -Wl,-woff,85" >&5
-if eval "test \"\${ol_cv_pthread_lib_lpthread_woff+set}\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
else
-
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-lpthread -Wl,-woff,85 $LIBS"
-
- cat > conftest.$ac_ext <<EOF
-#line 6480 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 7817 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
-int main() {
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
-; return 0; }
+ exit( status );
+
+}
+
EOF
-if { (eval echo configure:6505: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- ol_cv_pthread_lib_lpthread_woff=yes
+if { (eval echo configure:7866: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_threads=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- ol_cv_pthread_lib_lpthread_woff=no
+ rm -fr conftest*
+ ol_cv_pthread_threads=no
fi
-rm -f conftest*
+rm -fr conftest*
+fi
+
# restore the LIBS
LIBS="$ol_LIBS"
-
+
fi
-echo "$ac_t""$ol_cv_pthread_lib_lpthread_woff" 1>&6
+echo "$ac_t""$ol_cv_pthread_threads" 1>&6
- if test $ol_cv_pthread_lib_lpthread_woff = yes ; then
- ol_link_pthreads="-lpthread -Wl,-woff,85"
- ol_link_threads=posix
- fi
+ if test $ol_cv_pthread_threads = yes ; then
+ ol_link_pthreads="-threads"
+ ol_link_threads=posix
fi
+fi
- # Pthread try link: -lpthread (ol_cv_pthread_lpthread)
- if test "$ol_link_threads" = no ; then
- # try -lpthread
- echo $ac_n "checking for pthread link with -lpthread""... $ac_c" 1>&6
-echo "configure:6534: checking for pthread link with -lpthread" >&5
-if eval "test \"\${ol_cv_pthread_lpthread+set}\" = set"; then
+ # Pthread try link: -lpthreads -lmach -lexc -lc_r (ol_cv_pthread_lpthreads_lmach_lexc_lc_r)
+if test "$ol_link_threads" = no ; then
+ # try -lpthreads -lmach -lexc -lc_r
+ echo $ac_n "checking for pthread link with -lpthreads -lmach -lexc -lc_r""... $ac_c" 1>&6
+echo "configure:7897: checking for pthread link with -lpthreads -lmach -lexc -lc_r" >&5
+if eval "test \"\${ol_cv_pthread_lpthreads_lmach_lexc_lc_r+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-lpthread $LIBS"
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-lpthreads -lmach -lexc -lc_r $LIBS"
+
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 7908 "configure"
+#include "confdefs.h"
+/* pthread test headers */
+#include <pthread.h>
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main() {
+
+ /* pthread test function */
+ pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_detach( &t );
+#else
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
+#endif
+
+ exit( status );
- cat > conftest.$ac_ext <<EOF
-#line 6544 "configure"
+; return 0; }
+EOF
+if { (eval echo configure:7952: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ol_cv_pthread_lpthreads_lmach_lexc_lc_r=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ol_cv_pthread_lpthreads_lmach_lexc_lc_r=no
+fi
+rm -f conftest*
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7964 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
-int main() {
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
-; return 0; }
+ exit( status );
+
+}
+
EOF
-if { (eval echo configure:6569: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- ol_cv_pthread_lpthread=yes
+if { (eval echo configure:8013: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_lpthreads_lmach_lexc_lc_r=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- ol_cv_pthread_lpthread=no
+ rm -fr conftest*
+ ol_cv_pthread_lpthreads_lmach_lexc_lc_r=no
+fi
+rm -fr conftest*
fi
-rm -f conftest*
+
# restore the LIBS
LIBS="$ol_LIBS"
-
+
fi
-echo "$ac_t""$ol_cv_pthread_lpthread" 1>&6
+echo "$ac_t""$ol_cv_pthread_lpthreads_lmach_lexc_lc_r" 1>&6
- if test $ol_cv_pthread_lpthread = yes ; then
- ol_link_pthreads="-lpthread"
- ol_link_threads=posix
- fi
+ if test $ol_cv_pthread_lpthreads_lmach_lexc_lc_r = yes ; then
+ ol_link_pthreads="-lpthreads -lmach -lexc -lc_r"
+ ol_link_threads=posix
fi
+fi
- # Pthread try link: -lc_r (ol_cv_pthread_lc_r)
- if test "$ol_link_threads" = no ; then
- # try -lc_r
- echo $ac_n "checking for pthread link with -lc_r""... $ac_c" 1>&6
-echo "configure:6597: checking for pthread link with -lc_r" >&5
-if eval "test \"\${ol_cv_pthread_lc_r+set}\" = set"; then
+ # Pthread try link: -lpthreads -lmach -lexc (ol_cv_pthread_lpthreads_lmach_lexc)
+if test "$ol_link_threads" = no ; then
+ # try -lpthreads -lmach -lexc
+ echo $ac_n "checking for pthread link with -lpthreads -lmach -lexc""... $ac_c" 1>&6
+echo "configure:8043: checking for pthread link with -lpthreads -lmach -lexc" >&5
+if eval "test \"\${ol_cv_pthread_lpthreads_lmach_lexc+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-lc_r $LIBS"
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-lpthreads -lmach -lexc $LIBS"
- cat > conftest.$ac_ext <<EOF
-#line 6607 "configure"
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 8054 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
int main() {
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
+ exit( status );
+
; return 0; }
EOF
-if { (eval echo configure:6632: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8098: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
- ol_cv_pthread_lc_r=yes
+ ol_cv_pthread_lpthreads_lmach_lexc=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
- ol_cv_pthread_lc_r=no
+ ol_cv_pthread_lpthreads_lmach_lexc=no
fi
rm -f conftest*
-
- # restore the LIBS
- LIBS="$ol_LIBS"
-
-fi
-
-echo "$ac_t""$ol_cv_pthread_lc_r" 1>&6
-
- if test $ol_cv_pthread_lc_r = yes ; then
- ol_link_pthreads="-lc_r"
- ol_link_threads=posix
- fi
- fi
-
-
- # Pthread try link: -threads (ol_cv_pthread_threads)
- if test "$ol_link_threads" = no ; then
- # try -threads
- echo $ac_n "checking for pthread link with -threads""... $ac_c" 1>&6
-echo "configure:6661: checking for pthread link with -threads" >&5
-if eval "test \"\${ol_cv_pthread_threads+set}\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
else
-
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-threads $LIBS"
-
- cat > conftest.$ac_ext <<EOF
-#line 6671 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 8110 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
-int main() {
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
-; return 0; }
+ exit( status );
+
+}
+
EOF
-if { (eval echo configure:6696: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- ol_cv_pthread_threads=yes
+if { (eval echo configure:8159: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_lpthreads_lmach_lexc=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- ol_cv_pthread_threads=no
+ rm -fr conftest*
+ ol_cv_pthread_lpthreads_lmach_lexc=no
fi
-rm -f conftest*
+rm -fr conftest*
+fi
+
# restore the LIBS
LIBS="$ol_LIBS"
-
+
fi
-echo "$ac_t""$ol_cv_pthread_threads" 1>&6
+echo "$ac_t""$ol_cv_pthread_lpthreads_lmach_lexc" 1>&6
- if test $ol_cv_pthread_threads = yes ; then
- ol_link_pthreads="-threads"
- ol_link_threads=posix
- fi
+ if test $ol_cv_pthread_lpthreads_lmach_lexc = yes ; then
+ ol_link_pthreads="-lpthreads -lmach -lexc"
+ ol_link_threads=posix
fi
+fi
-
- # Pthread try link: -lpthreads -lmach -lexc -lc_r (ol_cv_pthread_lpthreads_lmach_lexc_lc_r)
- if test "$ol_link_threads" = no ; then
- # try -lpthreads -lmach -lexc -lc_r
- echo $ac_n "checking for pthread link with -lpthreads -lmach -lexc -lc_r""... $ac_c" 1>&6
-echo "configure:6725: checking for pthread link with -lpthreads -lmach -lexc -lc_r" >&5
-if eval "test \"\${ol_cv_pthread_lpthreads_lmach_lexc_lc_r+set}\" = set"; then
+ # Pthread try link: -lpthreads -lexc (ol_cv_pthread_lpthreads_lexc)
+if test "$ol_link_threads" = no ; then
+ # try -lpthreads -lexc
+ echo $ac_n "checking for pthread link with -lpthreads -lexc""... $ac_c" 1>&6
+echo "configure:8189: checking for pthread link with -lpthreads -lexc" >&5
+if eval "test \"\${ol_cv_pthread_lpthreads_lexc+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-lpthreads -lmach -lexc -lc_r $LIBS"
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-lpthreads -lexc $LIBS"
- cat > conftest.$ac_ext <<EOF
-#line 6735 "configure"
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 8200 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
int main() {
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
+ exit( status );
+
; return 0; }
EOF
-if { (eval echo configure:6760: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8244: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
- ol_cv_pthread_lpthreads_lmach_lexc_lc_r=yes
+ ol_cv_pthread_lpthreads_lexc=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
- ol_cv_pthread_lpthreads_lmach_lexc_lc_r=no
+ ol_cv_pthread_lpthreads_lexc=no
fi
rm -f conftest*
-
- # restore the LIBS
- LIBS="$ol_LIBS"
-
-fi
-
-echo "$ac_t""$ol_cv_pthread_lpthreads_lmach_lexc_lc_r" 1>&6
-
- if test $ol_cv_pthread_lpthreads_lmach_lexc_lc_r = yes ; then
- ol_link_pthreads="-lpthreads -lmach -lexc -lc_r"
- ol_link_threads=posix
- fi
- fi
-
- # Pthread try link: -lpthreads -lmach -lexc (ol_cv_pthread_lpthreads_lmach_lexc)
- if test "$ol_link_threads" = no ; then
- # try -lpthreads -lmach -lexc
- echo $ac_n "checking for pthread link with -lpthreads -lmach -lexc""... $ac_c" 1>&6
-echo "configure:6788: checking for pthread link with -lpthreads -lmach -lexc" >&5
-if eval "test \"\${ol_cv_pthread_lpthreads_lmach_lexc+set}\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
else
-
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-lpthreads -lmach -lexc $LIBS"
-
- cat > conftest.$ac_ext <<EOF
-#line 6798 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 8256 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
-int main() {
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
-; return 0; }
+ exit( status );
+
+}
+
EOF
-if { (eval echo configure:6823: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- ol_cv_pthread_lpthreads_lmach_lexc=yes
+if { (eval echo configure:8305: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ol_cv_pthread_lpthreads_lexc=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- ol_cv_pthread_lpthreads_lmach_lexc=no
+ rm -fr conftest*
+ ol_cv_pthread_lpthreads_lexc=no
fi
-rm -f conftest*
+rm -fr conftest*
+fi
+
# restore the LIBS
LIBS="$ol_LIBS"
-
+
fi
-echo "$ac_t""$ol_cv_pthread_lpthreads_lmach_lexc" 1>&6
+echo "$ac_t""$ol_cv_pthread_lpthreads_lexc" 1>&6
- if test $ol_cv_pthread_lpthreads_lmach_lexc = yes ; then
- ol_link_pthreads="-lpthreads -lmach -lexc"
- ol_link_threads=posix
- fi
+ if test $ol_cv_pthread_lpthreads_lexc = yes ; then
+ ol_link_pthreads="-lpthreads -lexc"
+ ol_link_threads=posix
fi
+fi
- # Pthread try link: -lpthreads -lexc (ol_cv_pthread_lpthreads_lexc)
- if test "$ol_link_threads" = no ; then
- # try -lpthreads -lexc
- echo $ac_n "checking for pthread link with -lpthreads -lexc""... $ac_c" 1>&6
-echo "configure:6851: checking for pthread link with -lpthreads -lexc" >&5
-if eval "test \"\${ol_cv_pthread_lpthreads_lexc+set}\" = set"; then
+
+ # Pthread try link: -lpthreads (ol_cv_pthread_lib_lpthreads)
+if test "$ol_link_threads" = no ; then
+ # try -lpthreads
+ echo $ac_n "checking for pthread link with -lpthreads""... $ac_c" 1>&6
+echo "configure:8336: checking for pthread link with -lpthreads" >&5
+if eval "test \"\${ol_cv_pthread_lib_lpthreads+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-lpthreads -lexc $LIBS"
+ # save the flags
+ ol_LIBS="$LIBS"
+ LIBS="-lpthreads $LIBS"
- cat > conftest.$ac_ext <<EOF
-#line 6861 "configure"
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 8347 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
int main() {
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
+ exit( status );
+
; return 0; }
EOF
-if { (eval echo configure:6886: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8391: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
- ol_cv_pthread_lpthreads_lexc=yes
+ ol_cv_pthread_lib_lpthreads=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
- ol_cv_pthread_lpthreads_lexc=no
+ ol_cv_pthread_lib_lpthreads=no
fi
rm -f conftest*
-
- # restore the LIBS
- LIBS="$ol_LIBS"
-
-fi
-
-echo "$ac_t""$ol_cv_pthread_lpthreads_lexc" 1>&6
-
- if test $ol_cv_pthread_lpthreads_lexc = yes ; then
- ol_link_pthreads="-lpthreads -lexc"
- ol_link_threads=posix
- fi
- fi
-
-
- # Pthread try link: -lpthreads (ol_cv_pthread_lib_lpthreads)
- if test "$ol_link_threads" = no ; then
- # try -lpthreads
- echo $ac_n "checking for pthread link with -lpthreads""... $ac_c" 1>&6
-echo "configure:6915: checking for pthread link with -lpthreads" >&5
-if eval "test \"\${ol_cv_pthread_lib_lpthreads+set}\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
else
-
- # save the flags
- ol_LIBS="$LIBS"
- LIBS="-lpthreads $LIBS"
-
- cat > conftest.$ac_ext <<EOF
-#line 6925 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 8403 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
#endif
-int main() {
+static void *task(p)
+ void *p;
+{
+ return (void *) (p == NULL);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- pthread_create(&t, pthread_attr_default, NULL, NULL);
- pthread_detach( &t );
+ status = pthread_detach( &t );
#else
- pthread_create(&t, NULL, NULL, NULL);
- pthread_detach( t );
+ status = pthread_detach( t );
#endif
+
#ifdef HAVE_LINUX_THREADS
pthread_kill_other_threads_np();
#endif
-; return 0; }
+ exit( status );
+
+}
+
EOF
-if { (eval echo configure:6950: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+if { (eval echo configure:8452: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
ol_cv_pthread_lib_lpthreads=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
+ rm -fr conftest*
ol_cv_pthread_lib_lpthreads=no
fi
-rm -f conftest*
+rm -fr conftest*
+fi
+
# restore the LIBS
LIBS="$ol_LIBS"
-
+
fi
echo "$ac_t""$ol_cv_pthread_lib_lpthreads" 1>&6
- if test $ol_cv_pthread_lib_lpthreads = yes ; then
- ol_link_pthreads="-lpthreads"
- ol_link_threads=posix
- fi
+ if test $ol_cv_pthread_lib_lpthreads = yes ; then
+ ol_link_pthreads="-lpthreads"
+ ol_link_threads=posix
fi
+fi
if test $ol_link_threads != no ; then
for ac_func in sched_yield pthread_yield
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6990: checking for $ac_func" >&5
+echo "configure:8494: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6995 "configure"
+#line 8499 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7019: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8523: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
if test $ac_cv_func_sched_yield = no -a \
$ac_cv_func_pthread_yield = no ; then
echo $ac_n "checking for sched_yield in -lrt""... $ac_c" 1>&6
-echo "configure:7047: checking for sched_yield in -lrt" >&5
+echo "configure:8551: checking for sched_yield in -lrt" >&5
ac_lib_var=`echo rt'_'sched_yield | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lrt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7055 "configure"
+#line 8559 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
sched_yield()
; return 0; }
EOF
-if { (eval echo configure:7066: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8570: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
for ac_func in thr_yield
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7098: checking for $ac_func" >&5
+echo "configure:8602: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7103 "configure"
+#line 8607 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7127: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8631: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
for ac_func in pthread_kill
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7161: checking for $ac_func" >&5
+echo "configure:8665: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7166 "configure"
+#line 8670 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7190: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8694: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
echo $ac_n "checking for pthread_detach with <pthread.h>""... $ac_c" 1>&6
-echo "configure:7216: checking for pthread_detach with <pthread.h>" >&5
+echo "configure:8720: checking for pthread_detach with <pthread.h>" >&5
if eval "test \"\${ol_cv_func_pthread_detach+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7222 "configure"
+#line 8726 "configure"
#include "confdefs.h"
#include <pthread.h>
pthread_detach(NULL);
; return 0; }
EOF
-if { (eval echo configure:7234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8738: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ol_cv_func_pthread_detach=yes
else
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7266: checking for $ac_func" >&5
+echo "configure:8770: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7271 "configure"
+#line 8775 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7295: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8799: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
echo $ac_n "checking for pthread_kill_other_threads_np""... $ac_c" 1>&6
-echo "configure:7322: checking for pthread_kill_other_threads_np" >&5
+echo "configure:8826: checking for pthread_kill_other_threads_np" >&5
if eval "test \"\${ac_cv_func_pthread_kill_other_threads_np+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7327 "configure"
+#line 8831 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char pthread_kill_other_threads_np(); below. */
; return 0; }
EOF
-if { (eval echo configure:7351: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8855: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_pthread_kill_other_threads_np=yes"
else
fi
echo $ac_n "checking for LinuxThreads implementation""... $ac_c" 1>&6
-echo "configure:7371: checking for LinuxThreads implementation" >&5
+echo "configure:8875: checking for LinuxThreads implementation" >&5
if eval "test \"\${ol_cv_sys_linux_threads+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking for LinuxThreads consistency""... $ac_c" 1>&6
-echo "configure:7384: checking for LinuxThreads consistency" >&5
+echo "configure:8888: checking for LinuxThreads consistency" >&5
if eval "test \"\${ol_cv_linux_threads+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
fi
echo $ac_n "checking if pthread_create() works""... $ac_c" 1>&6
-echo "configure:7409: checking if pthread_create() works" >&5
+echo "configure:8913: checking if pthread_create() works" >&5
if eval "test \"\${ol_cv_pthread_create_works+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ol_cv_pthread_create_works=yes
else
cat > conftest.$ac_ext <<EOF
-#line 7418 "configure"
+#line 8922 "configure"
#include "confdefs.h"
-
+/* pthread test headers */
#include <pthread.h>
#ifndef NULL
#define NULL (void*)0
return (void *) (p == NULL);
}
+
int main(argc, argv)
int argc;
char **argv;
{
+
+ /* pthread test function */
pthread_t t;
+ int status;
+
+ /* make sure pthread_create() isn't just a stub */
+#if HAVE_PTHREADS_D4
+ status = pthread_create(&t, pthread_attr_default, task, NULL);
+#else
+ status = pthread_create(&t, NULL, task, NULL);
+#endif
+
+ if( status ) exit( status );
+
+ /* make sure pthread_detach() isn't just a stub */
#if HAVE_PTHREADS_D4
- exit(pthread_create(&t, pthread_attr_default, task, NULL));
+ status = pthread_detach( &t );
#else
- exit(pthread_create(&t, NULL, task, NULL));
+ status = pthread_detach( t );
+#endif
+
+#ifdef HAVE_LINUX_THREADS
+ pthread_kill_other_threads_np();
#endif
+
+ exit( status );
+
}
EOF
-if { (eval echo configure:7445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8971: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ol_cv_pthread_create_works=yes
else
if test $ol_with_yielding_select = auto ; then
echo $ac_n "checking if select yields when using pthreads""... $ac_c" 1>&6
-echo "configure:7467: checking if select yields when using pthreads" >&5
+echo "configure:8993: checking if select yields when using pthreads" >&5
if eval "test \"\${ol_cv_pthread_select_yields+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ol_cv_pthread_select_yields=cross
else
cat > conftest.$ac_ext <<EOF
-#line 7476 "configure"
+#line 9002 "configure"
#include "confdefs.h"
#include <sys/types.h>
exit(2);
}
EOF
-if { (eval echo configure:7552: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9078: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ol_cv_pthread_select_yields=no
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7596: checking for $ac_hdr" >&5
+echo "configure:9122: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7601 "configure"
+#line 9127 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7606: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:9132: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
ol_with_threads=found
echo $ac_n "checking for cthread_fork""... $ac_c" 1>&6
-echo "configure:7636: checking for cthread_fork" >&5
+echo "configure:9162: checking for cthread_fork" >&5
if eval "test \"\${ac_cv_func_cthread_fork+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7641 "configure"
+#line 9167 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char cthread_fork(); below. */
; return 0; }
EOF
-if { (eval echo configure:7665: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_cthread_fork=yes"
else
if test $ol_link_threads = no ; then
echo $ac_n "checking for cthread_fork with -all_load""... $ac_c" 1>&6
-echo "configure:7687: checking for cthread_fork with -all_load" >&5
+echo "configure:9213: checking for cthread_fork with -all_load" >&5
if eval "test \"\${ol_cv_cthread_all_load+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
save_LIBS="$LIBS"
LIBS="-all_load $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7695 "configure"
+#line 9221 "configure"
#include "confdefs.h"
#include <mach/cthreads.h>
int main() {
; return 0; }
EOF
-if { (eval echo configure:7704: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9230: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ol_cv_cthread_all_load=yes
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7749: checking for $ac_hdr" >&5
+echo "configure:9275: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7754 "configure"
+#line 9280 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7759: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:9285: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_thread_h = yes -a $ac_cv_header_synch_h = yes ; then
echo $ac_n "checking for thr_create in -lthread""... $ac_c" 1>&6
-echo "configure:7787: checking for thr_create in -lthread" >&5
+echo "configure:9313: checking for thr_create in -lthread" >&5
ac_lib_var=`echo thread'_'thr_create | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lthread $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7795 "configure"
+#line 9321 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
thr_create()
; return 0; }
EOF
-if { (eval echo configure:7806: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9332: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7846: checking for $ac_func" >&5
+echo "configure:9372: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7851 "configure"
+#line 9377 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7875: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9401: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7906: checking for $ac_hdr" >&5
+echo "configure:9432: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7911 "configure"
+#line 9437 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7916: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:9442: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_lwp_lwp_h = yes ; then
echo $ac_n "checking for lwp_create in -llwp""... $ac_c" 1>&6
-echo "configure:7944: checking for lwp_create in -llwp" >&5
+echo "configure:9470: checking for lwp_create in -llwp" >&5
ac_lib_var=`echo lwp'_'lwp_create | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-llwp $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7952 "configure"
+#line 9478 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
lwp_create()
; return 0; }
EOF
-if { (eval echo configure:7963: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9489: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8016: checking for $ac_hdr" >&5
+echo "configure:9542: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8021 "configure"
+#line 9547 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8026: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:9552: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
for ac_func in sched_yield pthread_yield
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8055: checking for $ac_func" >&5
+echo "configure:9581: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8060 "configure"
+#line 9586 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:8084: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9610: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
echo $ac_n "checking for LinuxThreads pthread.h""... $ac_c" 1>&6
-echo "configure:8110: checking for LinuxThreads pthread.h" >&5
+echo "configure:9636: checking for LinuxThreads pthread.h" >&5
if eval "test \"\${ol_cv_header_linux_threads+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8115 "configure"
+#line 9641 "configure"
#include "confdefs.h"
#include <pthread.h>
EOF
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8145: checking for $ac_hdr" >&5
+echo "configure:9671: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8150 "configure"
+#line 9676 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8155: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:9681: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8185: checking for $ac_hdr" >&5
+echo "configure:9711: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8190 "configure"
+#line 9716 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8195: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:9721: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8225: checking for $ac_hdr" >&5
+echo "configure:9751: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8230 "configure"
+#line 9756 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8235: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:9761: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
echo $ac_n "checking for thread specific errno""... $ac_c" 1>&6
-echo "configure:8294: checking for thread specific errno" >&5
+echo "configure:9820: checking for thread specific errno" >&5
if eval "test \"\${ol_cv_errno_thread_specific+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8300 "configure"
+#line 9826 "configure"
#include "confdefs.h"
#include <errno.h>
int main() {
errno = 0;
; return 0; }
EOF
-if { (eval echo configure:8307: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9833: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ol_cv_errno_thread_specific=yes
else
echo "$ac_t""$ol_cv_errno_thread_specific" 1>&6
echo $ac_n "checking for thread specific h_errno""... $ac_c" 1>&6
-echo "configure:8323: checking for thread specific h_errno" >&5
+echo "configure:9849: checking for thread specific h_errno" >&5
if eval "test \"\${ol_cv_h_errno_thread_specific+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8329 "configure"
+#line 9855 "configure"
#include "confdefs.h"
#include <netdb.h>
int main() {
h_errno = 0;
; return 0; }
EOF
-if { (eval echo configure:8336: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9862: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ol_cv_h_errno_thread_specific=yes
else
ol_link_ldbm=no
if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = db2 ; then
echo $ac_n "checking for DB2 library""... $ac_c" 1>&6
-echo "configure:8387: checking for DB2 library" >&5
+echo "configure:9913: checking for DB2 library" >&5
if eval "test \"\${ol_cv_lib_db2+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ol_LIBS="$LIBS"
echo $ac_n "checking for db_open in -ldb""... $ac_c" 1>&6
-echo "configure:8393: checking for db_open in -ldb" >&5
+echo "configure:9919: checking for db_open in -ldb" >&5
ac_lib_var=`echo db'_'db_open | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ldb $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8401 "configure"
+#line 9927 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
db_open()
; return 0; }
EOF
-if { (eval echo configure:8412: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9938: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8443: checking for $ac_hdr" >&5
+echo "configure:9969: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8448 "configure"
+#line 9974 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8453: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:9979: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_db_h = yes ; then
echo $ac_n "checking if db.h is DB2""... $ac_c" 1>&6
-echo "configure:8481: checking if db.h is DB2" >&5
+echo "configure:10007: checking if db.h is DB2" >&5
if eval "test \"\${ol_cv_header_db2+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8487 "configure"
+#line 10013 "configure"
#include "confdefs.h"
# include <db.h>
echo $ac_n "checking for Berkeley DB2""... $ac_c" 1>&6
-echo "configure:8519: checking for Berkeley DB2" >&5
+echo "configure:10045: checking for Berkeley DB2" >&5
if eval "test \"\${ol_cv_berkeley_db2+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = db ; then
echo $ac_n "checking for Berkeley DB library""... $ac_c" 1>&6
-echo "configure:8570: checking for Berkeley DB library" >&5
+echo "configure:10096: checking for Berkeley DB library" >&5
if eval "test \"\${ol_cv_lib_db+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8579: checking for $ac_hdr" >&5
+echo "configure:10105: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8584 "configure"
+#line 10110 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10115: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
ol_LIBS="$LIBS"
echo $ac_n "checking for dbopen""... $ac_c" 1>&6
-echo "configure:8617: checking for dbopen" >&5
+echo "configure:10143: checking for dbopen" >&5
if eval "test \"\${ac_cv_func_dbopen+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8622 "configure"
+#line 10148 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char dbopen(); below. */
; return 0; }
EOF
-if { (eval echo configure:8646: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10172: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_dbopen=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for dbopen in -ldb1""... $ac_c" 1>&6
-echo "configure:8665: checking for dbopen in -ldb1" >&5
+echo "configure:10191: checking for dbopen in -ldb1" >&5
ac_lib_var=`echo db1'_'dbopen | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ldb1 $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8673 "configure"
+#line 10199 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
dbopen()
; return 0; }
EOF
-if { (eval echo configure:8684: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10210: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for dbopen in -ldb""... $ac_c" 1>&6
-echo "configure:8704: checking for dbopen in -ldb" >&5
+echo "configure:10230: checking for dbopen in -ldb" >&5
ac_lib_var=`echo db'_'dbopen | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ldb $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8712 "configure"
+#line 10238 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
dbopen()
; return 0; }
EOF
-if { (eval echo configure:8723: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10249: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8761: checking for $ac_hdr" >&5
+echo "configure:10287: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8766 "configure"
+#line 10292 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8771: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10297: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
echo $ac_n "checking for Berkeley DB""... $ac_c" 1>&6
-echo "configure:8807: checking for Berkeley DB" >&5
+echo "configure:10333: checking for Berkeley DB" >&5
if eval "test \"\${ol_cv_berkeley_db+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8860: checking for $ac_hdr" >&5
+echo "configure:10386: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8865 "configure"
+#line 10391 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8870: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10396: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = mdbm ; then
echo $ac_n "checking for MDBM library""... $ac_c" 1>&6
-echo "configure:8905: checking for MDBM library" >&5
+echo "configure:10431: checking for MDBM library" >&5
if eval "test \"\${ol_cv_lib_mdbm+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ol_LIBS="$LIBS"
echo $ac_n "checking for mdbm_set_chain""... $ac_c" 1>&6
-echo "configure:8911: checking for mdbm_set_chain" >&5
+echo "configure:10437: checking for mdbm_set_chain" >&5
if eval "test \"\${ac_cv_func_mdbm_set_chain+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8916 "configure"
+#line 10442 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char mdbm_set_chain(); below. */
; return 0; }
EOF
-if { (eval echo configure:8940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_mdbm_set_chain=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for mdbm_set_chain in -lmdbm""... $ac_c" 1>&6
-echo "configure:8959: checking for mdbm_set_chain in -lmdbm" >&5
+echo "configure:10485: checking for mdbm_set_chain in -lmdbm" >&5
ac_lib_var=`echo mdbm'_'mdbm_set_chain | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lmdbm $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8967 "configure"
+#line 10493 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
mdbm_set_chain()
; return 0; }
EOF
-if { (eval echo configure:8978: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10504: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:9013: checking for $ac_hdr" >&5
+echo "configure:10539: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9018 "configure"
+#line 10544 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:9023: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10549: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
done
echo $ac_n "checking for db""... $ac_c" 1>&6
-echo "configure:9050: checking for db" >&5
+echo "configure:10576: checking for db" >&5
if eval "test \"\${ol_cv_mdbm+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = gdbm ; then
echo $ac_n "checking for GDBM library""... $ac_c" 1>&6
-echo "configure:9083: checking for GDBM library" >&5
+echo "configure:10609: checking for GDBM library" >&5
if eval "test \"\${ol_cv_lib_gdbm+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ol_LIBS="$LIBS"
echo $ac_n "checking for gdbm_open""... $ac_c" 1>&6
-echo "configure:9089: checking for gdbm_open" >&5
+echo "configure:10615: checking for gdbm_open" >&5
if eval "test \"\${ac_cv_func_gdbm_open+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9094 "configure"
+#line 10620 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char gdbm_open(); below. */
; return 0; }
EOF
-if { (eval echo configure:9118: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_gdbm_open=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for gdbm_open in -lgdbm""... $ac_c" 1>&6
-echo "configure:9137: checking for gdbm_open in -lgdbm" >&5
+echo "configure:10663: checking for gdbm_open in -lgdbm" >&5
ac_lib_var=`echo gdbm'_'gdbm_open | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lgdbm $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9145 "configure"
+#line 10671 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
gdbm_open()
; return 0; }
EOF
-if { (eval echo configure:9156: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:9191: checking for $ac_hdr" >&5
+echo "configure:10717: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9196 "configure"
+#line 10722 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:9201: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10727: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
done
echo $ac_n "checking for db""... $ac_c" 1>&6
-echo "configure:9228: checking for db" >&5
+echo "configure:10754: checking for db" >&5
if eval "test \"\${ol_cv_gdbm+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo "configure: warning: skipping automatic checking for NDBM, must be manually enabled." 1>&2
elif test $ol_with_ldbm_api = ndbm ; then
echo $ac_n "checking for NDBM library""... $ac_c" 1>&6
-echo "configure:9264: checking for NDBM library" >&5
+echo "configure:10790: checking for NDBM library" >&5
if eval "test \"\${ol_cv_lib_ndbm+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ol_LIBS="$LIBS"
echo $ac_n "checking for dbm_open""... $ac_c" 1>&6
-echo "configure:9270: checking for dbm_open" >&5
+echo "configure:10796: checking for dbm_open" >&5
if eval "test \"\${ac_cv_func_dbm_open+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9275 "configure"
+#line 10801 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char dbm_open(); below. */
; return 0; }
EOF
-if { (eval echo configure:9299: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_dbm_open=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for dbm_open in -lndbm""... $ac_c" 1>&6
-echo "configure:9318: checking for dbm_open in -lndbm" >&5
+echo "configure:10844: checking for dbm_open in -lndbm" >&5
ac_lib_var=`echo ndbm'_'dbm_open | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lndbm $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9326 "configure"
+#line 10852 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
dbm_open()
; return 0; }
EOF
-if { (eval echo configure:9337: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10863: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for dbm_open in -ldbm""... $ac_c" 1>&6
-echo "configure:9357: checking for dbm_open in -ldbm" >&5
+echo "configure:10883: checking for dbm_open in -ldbm" >&5
ac_lib_var=`echo dbm'_'dbm_open | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ldbm $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9365 "configure"
+#line 10891 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
dbm_open()
; return 0; }
EOF
-if { (eval echo configure:9376: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10902: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:9413: checking for $ac_hdr" >&5
+echo "configure:10939: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9418 "configure"
+#line 10944 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:9423: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:10949: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
done
echo $ac_n "checking for db""... $ac_c" 1>&6
-echo "configure:9450: checking for db" >&5
+echo "configure:10976: checking for db" >&5
if eval "test \"\${ol_cv_ndbm+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:9497: checking for $ac_hdr" >&5
+echo "configure:11023: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9502 "configure"
+#line 11028 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:9507: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11033: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
have_wrappers=no
else
echo $ac_n "checking for main in -lwrap""... $ac_c" 1>&6
-echo "configure:9538: checking for main in -lwrap" >&5
+echo "configure:11064: checking for main in -lwrap" >&5
ac_lib_var=`echo wrap'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lwrap $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9546 "configure"
+#line 11072 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:9553: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11079: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
SLAPD_LIBS="$SLAPD_LIBS -lwrap"
echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6
-echo "configure:9584: checking for main in -lnsl" >&5
+echo "configure:11110: checking for main in -lnsl" >&5
ac_lib_var=`echo nsl'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lnsl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9592 "configure"
+#line 11118 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:9599: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11125: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if test $ol_enable_syslog != no ; then
echo $ac_n "checking for openlog""... $ac_c" 1>&6
-echo "configure:9639: checking for openlog" >&5
+echo "configure:11165: checking for openlog" >&5
if eval "test \"\${ac_cv_func_openlog+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9644 "configure"
+#line 11170 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char openlog(); below. */
; return 0; }
EOF
-if { (eval echo configure:9668: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11194: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_openlog=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:9698: checking for $ac_hdr" >&5
+echo "configure:11224: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9703 "configure"
+#line 11229 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:9708: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11234: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
done
echo $ac_n "checking for dmalloc_shutdown in -ldmalloc""... $ac_c" 1>&6
-echo "configure:9735: checking for dmalloc_shutdown in -ldmalloc" >&5
+echo "configure:11261: checking for dmalloc_shutdown in -ldmalloc" >&5
ac_lib_var=`echo dmalloc'_'dmalloc_shutdown | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ldmalloc $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9743 "configure"
+#line 11269 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
dmalloc_shutdown()
; return 0; }
EOF
-if { (eval echo configure:9754: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11280: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:9788: checking for $ac_hdr" >&5
+echo "configure:11314: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9793 "configure"
+#line 11319 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:9798: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11324: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
have_tcl=no
else
echo $ac_n "checking for main in -ltcl""... $ac_c" 1>&6
-echo "configure:9829: checking for main in -ltcl" >&5
+echo "configure:11355: checking for main in -ltcl" >&5
ac_lib_var=`echo tcl'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ltcl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9837 "configure"
+#line 11363 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:9844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11370: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if test $have_tcl != yes; then
echo $ac_n "checking for main in -ltcl7.6""... $ac_c" 1>&6
-echo "configure:9868: checking for main in -ltcl7.6" >&5
+echo "configure:11394: checking for main in -ltcl7.6" >&5
ac_lib_var=`echo tcl7.6'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ltcl7.6 $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9876 "configure"
+#line 11402 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:9883: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11409: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if test $have_tcl != yes; then
echo $ac_n "checking for main in -ltcl8.0""... $ac_c" 1>&6
-echo "configure:9908: checking for main in -ltcl8.0" >&5
+echo "configure:11434: checking for main in -ltcl8.0" >&5
ac_lib_var=`echo tcl8.0'_'main | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ltcl8.0 $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9916 "configure"
+#line 11442 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:9923: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11449: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:9963: checking for $ac_hdr" >&5
+echo "configure:11489: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 9968 "configure"
+#line 11494 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:9973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11499: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ol_link_termcap = no ; then
echo $ac_n "checking for tputs in -ltermcap""... $ac_c" 1>&6
-echo "configure:10002: checking for tputs in -ltermcap" >&5
+echo "configure:11528: checking for tputs in -ltermcap" >&5
ac_lib_var=`echo termcap'_'tputs | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ltermcap $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 10010 "configure"
+#line 11536 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
tputs()
; return 0; }
EOF
-if { (eval echo configure:10021: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if test $ol_link_termcap = no ; then
echo $ac_n "checking for initscr in -lncurses""... $ac_c" 1>&6
-echo "configure:10054: checking for initscr in -lncurses" >&5
+echo "configure:11580: checking for initscr in -lncurses" >&5
ac_lib_var=`echo ncurses'_'initscr | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lncurses $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 10062 "configure"
+#line 11588 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
initscr()
; return 0; }
EOF
-if { (eval echo configure:10073: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11599: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
TERMCAP_LIBS=
fi
+ol_link_sasl=no
+if test $ol_with_cyrus_sasl != no ; then
+ ac_safe=`echo "sasl.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for sasl.h""... $ac_c" 1>&6
+echo "configure:11642: checking for sasl.h" >&5
+if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 11647 "configure"
+#include "confdefs.h"
+#include <sasl.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:11652: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ if test $ac_cv_header_sasl_h = yes ; then
+ echo $ac_n "checking for sasl_client_init in -lsasl""... $ac_c" 1>&6
+echo "configure:11676: checking for sasl_client_init in -lsasl" >&5
+ac_lib_var=`echo sasl'_'sasl_client_init | sed 'y%./+-:%__p__%'`
+if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsasl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 11684 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sasl_client_init();
+
+int main() {
+sasl_client_init()
+; return 0; }
+EOF
+if { (eval echo configure:11695: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ have_cyrus_sasl=yes
+else
+ echo "$ac_t""no" 1>&6
+have_cyrus_sasl=no
+fi
+
+
+ if test $have_cyrus_sasl != no ; then
+ SASL_LIBS="-lsasl"
+ cat >> confdefs.h <<\EOF
+#define HAVE_CYRUS_SASL 1
+EOF
+
+ ol_link_sasl=yes
+ fi
+ fi
+
+ if test $ol_link_sasl = no -a $ol_with_cyrus_sasl = yes ; then
+ { echo "configure: error: no suitable API for --with-cyrus-sasl=$ol_with_cyrus_sasl" 1>&2; exit 1; }
+ fi
+fi
+
+ol_link_fetch=no
+if test $ol_with_fetch != no ; then
+ ol=$LIBS
+LIBS="-lfetch -lcom_err $LIBS"
+echo $ac_n "checking fetch(3) library""... $ac_c" 1>&6
+echo "configure:11737: checking fetch(3) library" >&5
+if eval "test \"\${ol_cv_lib_fetch+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 11743 "configure"
+#include "confdefs.h"
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <fetch.h>
+int main() {
+struct url *u = fetchParseURL("file:///");
+; return 0; }
+EOF
+if { (eval echo configure:11753: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ol_cv_lib_fetch=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ol_cv_lib_fetch=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ol_cv_lib_fetch" 1>&6
+LIBS=$ol_LIBS
+if test $ol_cv_lib_fetch != no ; then
+ ol_link_fetch="-lfetch -lcom_err"
+ cat >> confdefs.h <<\EOF
+#define HAVE_FETCH 1
+EOF
+
+fi
+
+
+ if test $ol_cv_lib_fetch != no ; then
+ LDIF_LIBS="$LDIF_LIBS $ol_link_fetch"
+ ol_link_fetch=freebsd
+
+ elif test $ol_with_fetch != auto ; then
+ { echo "configure: error: no suitable API for --with-fetch=$ol_with_fetch" 1>&2; exit 1; }
+ fi
+fi
+
ol_link_readline=no
if test $ol_with_readline != no ; then
for ac_hdr in readline/readline.h readline/history.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:10118: checking for $ac_hdr" >&5
+echo "configure:11791: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10123 "configure"
+#line 11796 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:10128: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:11801: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
save_LIBS="$LIBS"
LIBS="$TERMCAP_LIBS $LIBS"
echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6
-echo "configure:10159: checking for readline in -lreadline" >&5
+echo "configure:11832: checking for readline in -lreadline" >&5
ac_lib_var=`echo readline'_'readline | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lreadline $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 10167 "configure"
+#line 11840 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
readline()
; return 0; }
EOF
-if { (eval echo configure:10178: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
# FreeBSD (and others) have crypt(3) in -lcrypt
if test $ol_enable_crypt != no ; then
echo $ac_n "checking for crypt""... $ac_c" 1>&6
-echo "configure:10221: checking for crypt" >&5
+echo "configure:11894: checking for crypt" >&5
if eval "test \"\${ac_cv_func_crypt+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10226 "configure"
+#line 11899 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char crypt(); below. */
; return 0; }
EOF
-if { (eval echo configure:10250: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11923: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_crypt=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
-echo "configure:10269: checking for crypt in -lcrypt" >&5
+echo "configure:11942: checking for crypt in -lcrypt" >&5
ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lcrypt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 10277 "configure"
+#line 11950 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
crypt()
; return 0; }
EOF
-if { (eval echo configure:10288: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:11961: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
# FreeBSD (and others) have setproctitle(3) in -lutil
if test $ol_enable_proctitle != no ; then
echo $ac_n "checking for setproctitle""... $ac_c" 1>&6
-echo "configure:10332: checking for setproctitle" >&5
+echo "configure:12005: checking for setproctitle" >&5
if eval "test \"\${ac_cv_func_setproctitle+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10337 "configure"
+#line 12010 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char setproctitle(); below. */
; return 0; }
EOF
-if { (eval echo configure:10361: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12034: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_setproctitle=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for setproctitle in -lutil""... $ac_c" 1>&6
-echo "configure:10380: checking for setproctitle in -lutil" >&5
+echo "configure:12053: checking for setproctitle in -lutil" >&5
ac_lib_var=`echo util'_'setproctitle | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lutil $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 10388 "configure"
+#line 12061 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
setproctitle()
; return 0; }
EOF
-if { (eval echo configure:10399: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12072: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:10434: checking for uid_t in sys/types.h" >&5
+echo "configure:12107: checking for uid_t in sys/types.h" >&5
if eval "test \"\${ac_cv_type_uid_t+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10439 "configure"
+#line 12112 "configure"
#include "confdefs.h"
#include <sys/types.h>
EOF
fi
echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6
-echo "configure:10468: checking type of array argument to getgroups" >&5
+echo "configure:12141: checking type of array argument to getgroups" >&5
if eval "test \"\${ac_cv_type_getgroups+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_type_getgroups=cross
else
cat > conftest.$ac_ext <<EOF
-#line 10476 "configure"
+#line 12149 "configure"
#include "confdefs.h"
/* Thanks to Mike Rendell for this test. */
}
EOF
-if { (eval echo configure:10501: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:12174: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_type_getgroups=gid_t
else
if test $ac_cv_type_getgroups = cross; then
cat > conftest.$ac_ext <<EOF
-#line 10515 "configure"
+#line 12188 "configure"
#include "confdefs.h"
#include <unistd.h>
EOF
EOF
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:10538: checking for ANSI C header files" >&5
+echo "configure:12211: checking for ANSI C header files" >&5
if eval "test \"\${ac_cv_header_stdc+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10543 "configure"
+#line 12216 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:10551: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:12224: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 10568 "configure"
+#line 12241 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 10586 "configure"
+#line 12259 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
:
else
cat > conftest.$ac_ext <<EOF
-#line 10607 "configure"
+#line 12280 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
exit (0); }
EOF
-if { (eval echo configure:10618: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:12291: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
fi
echo $ac_n "checking for mode_t""... $ac_c" 1>&6
-echo "configure:10642: checking for mode_t" >&5
+echo "configure:12315: checking for mode_t" >&5
if eval "test \"\${ac_cv_type_mode_t+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10647 "configure"
+#line 12320 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
fi
echo $ac_n "checking for off_t""... $ac_c" 1>&6
-echo "configure:10677: checking for off_t" >&5
+echo "configure:12350: checking for off_t" >&5
if eval "test \"\${ac_cv_type_off_t+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10682 "configure"
+#line 12355 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
fi
echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:10712: checking for pid_t" >&5
+echo "configure:12385: checking for pid_t" >&5
if eval "test \"\${ac_cv_type_pid_t+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10717 "configure"
+#line 12390 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
fi
echo $ac_n "checking for ptrdiff_t""... $ac_c" 1>&6
-echo "configure:10747: checking for ptrdiff_t" >&5
+echo "configure:12420: checking for ptrdiff_t" >&5
if eval "test \"\${am_cv_type_ptrdiff_t+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10752 "configure"
+#line 12425 "configure"
#include "confdefs.h"
#include <stddef.h>
int main() {
ptrdiff_t p
; return 0; }
EOF
-if { (eval echo configure:10759: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12432: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
am_cv_type_ptrdiff_t=yes
else
fi
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:10780: checking return type of signal handlers" >&5
+echo "configure:12453: checking return type of signal handlers" >&5
if eval "test \"\${ac_cv_type_signal+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10785 "configure"
+#line 12458 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
int i;
; return 0; }
EOF
-if { (eval echo configure:10802: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12475: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
echo $ac_n "checking for sig_atomic_t""... $ac_c" 1>&6
-echo "configure:10821: checking for sig_atomic_t" >&5
+echo "configure:12494: checking for sig_atomic_t" >&5
if eval "test \"\${ol_cv_type_sig_atomic_t+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10826 "configure"
+#line 12499 "configure"
#include "confdefs.h"
#include <signal.h>
int main() {
sig_atomic_t atomic;
; return 0; }
EOF
-if { (eval echo configure:10833: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12506: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_type_sig_atomic_t=yes
else
fi
echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:10854: checking for size_t" >&5
+echo "configure:12527: checking for size_t" >&5
if eval "test \"\${ac_cv_type_size_t+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10859 "configure"
+#line 12532 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
fi
echo $ac_n "checking for socklen_t""... $ac_c" 1>&6
-echo "configure:10889: checking for socklen_t" >&5
+echo "configure:12562: checking for socklen_t" >&5
if eval "test \"\${ol_cv_type_socklen_t+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10894 "configure"
+#line 12567 "configure"
#include "confdefs.h"
#ifdef HAVE_SYS_TYPES_H
socklen_t len;
; return 0; }
EOF
-if { (eval echo configure:10908: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12581: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_type_socklen_t=yes
else
fi
echo $ac_n "checking for member st_blksize in aggregate type struct stat""... $ac_c" 1>&6
-echo "configure:10929: checking for member st_blksize in aggregate type struct stat" >&5
+echo "configure:12602: checking for member st_blksize in aggregate type struct stat" >&5
if eval "test \"\${ac_cv_c_struct_member_st_blksize+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10934 "configure"
+#line 12607 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
struct stat foo; foo.st_blksize;
; return 0; }
EOF
-if { (eval echo configure:10942: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12615: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_struct_member_st_blksize=yes
else
fi
echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:10964: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:12637: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"\${ac_cv_header_time+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 10969 "configure"
+#line 12642 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
struct tm *tp;
; return 0; }
EOF
-if { (eval echo configure:10978: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12651: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_time=yes
else
fi
echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
-echo "configure:10999: checking whether struct tm is in sys/time.h or time.h" >&5
+echo "configure:12672: checking whether struct tm is in sys/time.h or time.h" >&5
if eval "test \"\${ac_cv_struct_tm+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11004 "configure"
+#line 12677 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <time.h>
struct tm *tp; tp->tm_sec;
; return 0; }
EOF
-if { (eval echo configure:11012: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12685: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_tm=time.h
else
# test for pw_gecos in struct passwd
echo $ac_n "checking struct passwd for pw_gecos""... $ac_c" 1>&6
-echo "configure:11034: checking struct passwd for pw_gecos" >&5
+echo "configure:12707: checking struct passwd for pw_gecos" >&5
if eval "test \"\${ol_cv_struct_passwd_pw_gecos+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11040 "configure"
+#line 12713 "configure"
#include "confdefs.h"
#include <pwd.h>
int main() {
; return 0; }
EOF
-if { (eval echo configure:11050: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12723: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_struct_passwd_pw_gecos=yes
else
# test for pw_passwd in struct passwd
echo $ac_n "checking struct passwd for pw_passwd""... $ac_c" 1>&6
-echo "configure:11072: checking struct passwd for pw_passwd" >&5
+echo "configure:12745: checking struct passwd for pw_passwd" >&5
if eval "test \"\${ol_cv_struct_passwd_pw_passwd+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11078 "configure"
+#line 12751 "configure"
#include "confdefs.h"
#include <pwd.h>
int main() {
; return 0; }
EOF
-if { (eval echo configure:11088: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12761: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_struct_passwd_pw_passwd=yes
else
echo $ac_n "checking if toupper() requires islower()""... $ac_c" 1>&6
-echo "configure:11110: checking if toupper() requires islower()" >&5
+echo "configure:12783: checking if toupper() requires islower()" >&5
if eval "test \"\${ol_cv_c_upper_lower+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ol_cv_c_upper_lower=safe
else
cat > conftest.$ac_ext <<EOF
-#line 11119 "configure"
+#line 12792 "configure"
#include "confdefs.h"
#include <ctype.h>
exit(1);
}
EOF
-if { (eval echo configure:11131: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:12804: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ol_cv_c_upper_lower=no
else
fi
echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:11154: checking for working const" >&5
+echo "configure:12827: checking for working const" >&5
if eval "test \"\${ac_cv_c_const+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11159 "configure"
+#line 12832 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:11208: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12881: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
fi
echo $ac_n "checking if compiler understands volatile""... $ac_c" 1>&6
-echo "configure:11229: checking if compiler understands volatile" >&5
+echo "configure:12902: checking if compiler understands volatile" >&5
if eval "test \"\${ol_cv_c_volatile+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11234 "configure"
+#line 12907 "configure"
#include "confdefs.h"
int x, y, z;
int main() {
*b = 0;
; return 0; }
EOF
-if { (eval echo configure:11243: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12916: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_c_volatile=yes
else
else
echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:11287: checking whether byte ordering is bigendian" >&5
+echo "configure:12960: checking whether byte ordering is bigendian" >&5
if eval "test \"\${ac_cv_c_bigendian+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_bigendian=unknown
# See if sys/param.h defines the BYTE_ORDER macro.
cat > conftest.$ac_ext <<EOF
-#line 11294 "configure"
+#line 12967 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
#endif
; return 0; }
EOF
-if { (eval echo configure:11305: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12978: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
# It does; now see whether it defined to BIG_ENDIAN or not.
cat > conftest.$ac_ext <<EOF
-#line 11309 "configure"
+#line 12982 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
#endif
; return 0; }
EOF
-if { (eval echo configure:11320: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12993: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_bigendian=yes
else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 11340 "configure"
+#line 13013 "configure"
#include "confdefs.h"
main () {
/* Are we little or big endian? From Harbison&Steele. */
exit (u.c[sizeof (long) - 1] == 1);
}
EOF
-if { (eval echo configure:11353: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13026: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_bigendian=no
else
fi
echo $ac_n "checking size of short""... $ac_c" 1>&6
-echo "configure:11377: checking size of short" >&5
+echo "configure:13050: checking size of short" >&5
if eval "test \"\${ac_cv_sizeof_short+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 11385 "configure"
+#line 13058 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
exit(0);
}
EOF
-if { (eval echo configure:11396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13069: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_sizeof_short=`cat conftestval`
else
echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:11416: checking size of int" >&5
+echo "configure:13089: checking size of int" >&5
if eval "test \"\${ac_cv_sizeof_int+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 11424 "configure"
+#line 13097 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
exit(0);
}
EOF
-if { (eval echo configure:11435: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13108: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_sizeof_int=`cat conftestval`
else
echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:11455: checking size of long" >&5
+echo "configure:13128: checking size of long" >&5
if eval "test \"\${ac_cv_sizeof_long+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 11463 "configure"
+#line 13136 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
exit(0);
}
EOF
-if { (eval echo configure:11474: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13147: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_sizeof_long=`cat conftestval`
else
echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:11531: checking for 8-bit clean memcmp" >&5
+echo "configure:13204: checking for 8-bit clean memcmp" >&5
if eval "test \"\${ac_cv_func_memcmp_clean+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_func_memcmp_clean=no
else
cat > conftest.$ac_ext <<EOF
-#line 11539 "configure"
+#line 13212 "configure"
#include "confdefs.h"
main()
}
EOF
-if { (eval echo configure:11549: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13222: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_func_memcmp_clean=yes
else
test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
echo $ac_n "checking for strftime""... $ac_c" 1>&6
-echo "configure:11567: checking for strftime" >&5
+echo "configure:13240: checking for strftime" >&5
if eval "test \"\${ac_cv_func_strftime+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11572 "configure"
+#line 13245 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char strftime(); below. */
; return 0; }
EOF
-if { (eval echo configure:11596: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_strftime=yes"
else
echo "$ac_t""no" 1>&6
# strftime is in -lintl on SCO UNIX.
echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6
-echo "configure:11618: checking for strftime in -lintl" >&5
+echo "configure:13291: checking for strftime in -lintl" >&5
ac_lib_var=`echo intl'_'strftime | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lintl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 11626 "configure"
+#line 13299 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
strftime()
; return 0; }
EOF
-if { (eval echo configure:11637: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13310: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
+echo $ac_n "checking for inet_aton()""... $ac_c" 1>&6
+echo "configure:13338: checking for inet_aton()" >&5
+if eval "test \"\${ol_cv_func_inet_aton+set}\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 13343 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# endif
+# include <netinet/in.h>
+# ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+# endif
+#endif
+
+int main() {
+struct in_addr in;
+int rc = inet_aton( "255.255.255.255", &in );
+; return 0; }
+EOF
+if { (eval echo configure:13365: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ol_cv_func_inet_aton=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ol_cv_func_inet_aton=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ol_cv_func_inet_aton" 1>&6
+ if test $ol_cv_func_inet_aton != no; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_INET_ATON 1
+EOF
+
+ fi
+
+
echo $ac_n "checking for vprintf""... $ac_c" 1>&6
-echo "configure:11665: checking for vprintf" >&5
+echo "configure:13387: checking for vprintf" >&5
if eval "test \"\${ac_cv_func_vprintf+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11670 "configure"
+#line 13392 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vprintf(); below. */
; return 0; }
EOF
-if { (eval echo configure:11694: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13416: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_vprintf=yes"
else
if test "$ac_cv_func_vprintf" != yes; then
echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
-echo "configure:11718: checking for _doprnt" >&5
+echo "configure:13440: checking for _doprnt" >&5
if eval "test \"\${ac_cv_func__doprnt+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11723 "configure"
+#line 13445 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char _doprnt(); below. */
; return 0; }
EOF
-if { (eval echo configure:11747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13469: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func__doprnt=yes"
else
for ac_func in vsnprintf vsprintf
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:11776: checking for $ac_func" >&5
+echo "configure:13498: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11781 "configure"
+#line 13503 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:11805: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:11880: checking for $ac_func" >&5
+echo "configure:13602: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11885 "configure"
+#line 13607 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:11909: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13631: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
for ac_func in getopt tempnam
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:11937: checking for $ac_func" >&5
+echo "configure:13659: checking for $ac_func" >&5
if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 11942 "configure"
+#line 13664 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:11966: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13688: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
# Check Configuration
echo $ac_n "checking declaration of sys_errlist""... $ac_c" 1>&6
-echo "configure:11995: checking declaration of sys_errlist" >&5
+echo "configure:13717: checking declaration of sys_errlist" >&5
if eval "test \"\${ol_cv_dcl_sys_errlist+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 12001 "configure"
+#line 13723 "configure"
#include "confdefs.h"
#include <stdio.h>
char *c = (char *) *sys_errlist
; return 0; }
EOF
-if { (eval echo configure:12011: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:13733: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ol_cv_dcl_sys_errlist=yes
ol_cv_have_sys_errlist=yes
echo $ac_n "checking existence of sys_errlist""... $ac_c" 1>&6
-echo "configure:12034: checking existence of sys_errlist" >&5
+echo "configure:13756: checking existence of sys_errlist" >&5
if eval "test \"\${ol_cv_have_sys_errlist+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 12040 "configure"
+#line 13762 "configure"
#include "confdefs.h"
#include <errno.h>
int main() {
char *c = (char *) *sys_errlist
; return 0; }
EOF
-if { (eval echo configure:12047: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13769: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ol_cv_have_sys_errlist=yes
else
#define SLAPD_CLEARTEXT 1
EOF
+fi
+if test "$ol_enable_multimaster" != no ; then
+ cat >> confdefs.h <<\EOF
+#define SLAPD_MULTIMASTER 1
+EOF
+
fi
if test "$ol_enable_phonetic" != no ; then
cat >> confdefs.h <<\EOF
EOF
BUILD_SLAPD=yes
+ MODULES_LIBS=-lltdl
+ SLAPD_MODULES_LDFLAGS="-dlopen self"
fi
if test "$ol_link_bdb2" != no ; then
#define SLAPD_BDB2_DYNAMIC 1
EOF
- BUILD_BDB2_DYNAMIC=yes
+ BUILD_BDB2=mod
+ BUILD_BDB2_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-bdb2/back_bdb2.la"
fi
fi
#define SLAPD_LDAP_DYNAMIC 1
EOF
- BUILD_LDAP_DYNAMIC=yes
+ BUILD_LDAP=mod
+ BUILD_LDAP_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-ldap/back_ldap.la"
fi
fi
#define SLAPD_LDBM_DYNAMIC 1
EOF
- BUILD_LDBM_DYNAMIC=yes
+ BUILD_LDBM=mod
+ BUILD_LDBM_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-ldbm/back_ldbm.la"
fi
fi
#define SLAPD_PASSWD_DYNAMIC 1
EOF
- BUILD_PASSWD_DYNAMIC=yes
+ BUILD_PASSWD=mod
+ BUILD_PASSWD_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-passwd/back_passwd.la"
fi
fi
#define SLAPD_PERL_DYNAMIC 1
EOF
- BUILD_PERL_DYNAMIC=yes
+ BUILD_PERL=mod
+ BUILD_PERL_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-perl/back_perl.la"
fi
fi
#define SLAPD_SHELL_DYNAMIC 1
EOF
- BUILD_SHELL_DYNAMIC=yes
+ BUILD_SHELL=mod
+ BUILD_SHELL_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-shell/back_shell.la"
fi
fi
#define SLAPD_TCL_DYNAMIC 1
EOF
- BUILD_TCL_DYNAMIC=yes
+ BUILD_TCL=mod
+ BUILD_TCL_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-tcl/back_tcl.la"
fi
fi
+
+
+
+
+
libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk \
servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk \
servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk \
-servers/slapd/back-bdb2/Makefile:build/top.mk:servers/slapd/back-bdb2/Makefile.in:build/srv.mk \
-servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/srv.mk \
-servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/srv.mk \
-servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/srv.mk \
-servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/srv.mk \
-servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/srv.mk \
-servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/srv.mk \
+servers/slapd/back-bdb2/Makefile:build/top.mk:servers/slapd/back-bdb2/Makefile.in:build/mod.mk \
+servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk \
+servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/mod.mk \
+servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk \
+servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk \
+servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk \
+servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/mod.mk \
servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk \
servers/slapd/tools/Makefile:build/top.mk:servers/slapd/tools/Makefile.in \
servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk \
s%@OBJEXT@%$OBJEXT%g
s%@OL_MKDEP@%$OL_MKDEP%g
s%@OL_MKDEP_FLAGS@%$OL_MKDEP_FLAGS%g
-s%@GLIBCONFIG@%$GLIBCONFIG%g
s%@LIBOBJS@%$LIBOBJS%g
s%@BUILD_SLAPD@%$BUILD_SLAPD%g
s%@BUILD_BDB2@%$BUILD_BDB2%g
s%@BUILD_LDBM@%$BUILD_LDBM%g
s%@BUILD_PASSWD@%$BUILD_PASSWD%g
s%@BUILD_PERL@%$BUILD_PERL%g
+s%@BUILD_QUIPU@%$BUILD_QUIPU%g
s%@BUILD_SHELL@%$BUILD_SHELL%g
s%@BUILD_TCL@%$BUILD_TCL%g
s%@BUILD_BDB2_DYNAMIC@%$BUILD_BDB2_DYNAMIC%g
s%@BUILD_TCL_DYNAMIC@%$BUILD_TCL_DYNAMIC%g
s%@BUILD_SLURPD@%$BUILD_SLURPD%g
s%@LDAP_LIBS@%$LDAP_LIBS%g
+s%@LDIF_LIBS@%$LDIF_LIBS%g
s%@SLAPD_LIBS@%$SLAPD_LIBS%g
s%@SLURPD_LIBS@%$SLURPD_LIBS%g
s%@LDBM_LIBS@%$LDBM_LIBS%g
s%@LUTIL_LIBS@%$LUTIL_LIBS%g
s%@SLAPD_MODULES_CPPFLAGS@%$SLAPD_MODULES_CPPFLAGS%g
s%@SLAPD_MODULES_LDFLAGS@%$SLAPD_MODULES_LDFLAGS%g
+s%@SLAPD_MODULES_LIST@%$SLAPD_MODULES_LIST%g
s%@SLAPD_PERL_CPPFLAGS@%$SLAPD_PERL_CPPFLAGS%g
s%@SLAPD_PERL_LDFLAGS@%$SLAPD_PERL_LDFLAGS%g
s%@KRB_LIBS@%$KRB_LIBS%g
s%@READLINE_LIBS@%$READLINE_LIBS%g
+s%@SASL_LIBS@%$SASL_LIBS%g
s%@TERMCAP_LIBS@%$TERMCAP_LIBS%g
s%@TLS_LIBS@%$TLS_LIBS%g
+s%@MODULES_LIBS@%$MODULES_LIBS%g
CEOF
EOF
libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk \
servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk \
servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk \
-servers/slapd/back-bdb2/Makefile:build/top.mk:servers/slapd/back-bdb2/Makefile.in:build/srv.mk \
-servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/srv.mk \
-servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/srv.mk \
-servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/srv.mk \
-servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/srv.mk \
-servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/srv.mk \
-servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/srv.mk \
+servers/slapd/back-bdb2/Makefile:build/top.mk:servers/slapd/back-bdb2/Makefile.in:build/mod.mk \
+servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk \
+servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/mod.mk \
+servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk \
+servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk \
+servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk \
+servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/mod.mk \
servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk \
servers/slapd/tools/Makefile:build/top.mk:servers/slapd/tools/Makefile.in \
servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk \
top_builddir=`pwd`
AC_SUBST(top_builddir)dnl
-ldap_subdir="openldap"
-
-AC_ARG_WITH(subdir, [ --with-subdir=DIR change default subdirectory used for installs], [
- if test "$withval" = "no"; then
- ldap_subdir=""
- elif test "$withval" != "yes"; then
+ldap_subdir="/openldap"
+
+AC_ARG_WITH(subdir,
+[ --with-subdir=DIR change default subdirectory used for installs],
+[case "$withval" in
+ no) ldap_subdir=""
+ ;;
+ yes)
+ ;;
+ /*|\\*)
ldap_subdir="$withval"
- fi
+ ;;
+ *)
+ ldap_subdir="/$withval"
+ ;;
+esac
])dnl
AC_SUBST(ldap_subdir)dnl
dnl General "with" options
OL_ARG_ENABLE(dmalloc,[ --enable-dmalloc enable debug malloc support], no)dnl
+OL_ARG_WITH(cyrus_sasl,[ --with-cyrus-sasl with Cyrus SASL support],
+ auto, [auto yes no] )
+OL_ARG_WITH(fetch,[ --with-fetch with fetch URL support],
+ auto, [auto yes no] )
OL_ARG_WITH(kerberos,[ --with-kerberos with Kerberos support],
auto, [auto k5 k4 afs yes no])
OL_ARG_WITH(readline,[ --with-readline with readline support],
OL_ARG_ENABLE(cleartext,[ --enable-cleartext enable cleartext passwords], yes)dnl
OL_ARG_ENABLE(crypt,[ --enable-crypt enable crypt(3) passwords], auto)dnl
OL_ARG_ENABLE(modules,[ --enable-modules enable dynamic module support], no)dnl
+OL_ARG_ENABLE(multimaster,[ --enable-multimaster enable multimaster replication], no)dnl
OL_ARG_ENABLE(phonetic,[ --enable-phonetic enable phonetic/soundex], no)dnl
+OL_ARG_ENABLE(quipu,[ --enable-quipu build quipu migration tools], no)dnl
OL_ARG_ENABLE(rlookups,[ --enable-rlookups enable reverse lookups], auto)dnl
OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)dnl
if test $ol_enable_modules = yes ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-modules argument])
fi
+ if test $ol_enable_multimaster = yes ; then
+ AC_MSG_WARN([slapd disabled, ignoring --enable-multimaster argument])
+ fi
if test $ol_enable_wrappers = yes ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-wrappers argument])
fi
if test $ol_enable_phonetic = yes ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-phonetic argument])
fi
+ if test $ol_enable_quipu = yes ; then
+ AC_MSG_WARN([slapd disabled, ignoring --enable-quipu argument])
+ fi
if test $ol_enable_rlookups = yes ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-rlookups argument])
fi
ol_enable_tcl=no
ol_enable_modules=no
+ ol_enable_multimaster=no
ol_enable_phonetic=no
+ ol_enable_quipu=no
ol_enable_rlookups=no
ol_enable_wrappers=no
## Initialize vars
LDAP_LIBS=
+LDIF_LIBS=
LDBM_LIBS=
LTHREAD_LIBS=
LUTIL_LIBS=
BUILD_LDBM=no
BUILD_PASSWD=no
BUILD_PERL=no
+BUILD_QUIPU=no
BUILD_SHELL=no
BUILD_TCL=no
BUILD_THREAD=no
-BUILD_BDB2_DYNAMIC=no
-BUILD_LDAP_DYNAMIC=no
-BUILD_LDBM_DYNAMIC=no
-BUILD_PASSWD_DYNAMIC=no
-BUILD_PERL_DYNAMIC=no
-BUILD_SHELL_DYNAMIC=no
-BUILD_TCL_DYNAMIC=no
+BUILD_BDB2_DYNAMIC=static
+BUILD_LDAP_DYNAMIC=static
+BUILD_LDBM_DYNAMIC=static
+BUILD_PASSWD_DYNAMIC=static
+BUILD_PERL_DYNAMIC=static
+BUILD_SHELL_DYNAMIC=static
+BUILD_TCL_DYNAMIC=static
SLAPD_MODULES_LDFLAGS=
SLAPD_MODULES_CPPFLAGS=
+SLAPD_MODULES_LIST=
SLAPD_PERL_LDFLAGS=
SLAPD_PERL_CPPFLAGS=
KRB_LIBS=
READLINE_LIBS=
+SASL_LIBS=
TERMCAP_LIBS=
TLS_LIBS=
+MODULES_LIBS=
dnl ----------------------------------------------------------------
dnl Checks for programs
dnl (for now, let autoconf sort this out)
dnl CFLAGS=${CFLAGS-""}
+AC_LIBTOOL_DLOPEN
AC_PROG_LIBTOOL
dnl AC_PROG_MAKE_SET
dnl
ol_link_modules=no
if test $ol_enable_modules != no ; then
- AC_PATH_PROG(GLIBCONFIG, glib-config)
+ AC_CHECK_HEADERS(ltdl.h)
- if test "no$GLIBCONFIG" = "no" ; then
- if test $ol_enable_modules = yes ; then
- AC_MSG_ERROR([could not locate glib-config])
- fi
+ if test $ac_cv_header_ltdl_h = no ; then
+ AC_MSG_ERROR([could not locate libtool ltdl.h])
- else
- SLAPD_MODULES_VERSION="`$GLIBCONFIG --version gmodule`"
- SLAPD_MODULES_CPPFLAGS="`$GLIBCONFIG --cflags gmodule`"
- SLAPD_MODULES_LDFLAGS="`$GLIBCONFIG --libs gmodule`"
+ fi
- dnl should check glib version
- ol_link_modules=yes
+ AC_CHECK_LIB(ltdl, lt_dlinit)
+ if test "$ac_cv_lib_ltdl_lt_dlinit" = no ; then
+ AC_MSG_ERROR([could not locate libtool -lltdl])
fi
+ ol_link_modules=yes
else
ol_with_bdb2_module=static
ol_with_ldap_module=static
dnl HP-UX requires -lV3
AC_CHECK_LIB(V3, sigset)
+dnl Check for resolver routines
+AC_CHECK_FUNC(res_search,:)
+if test $ac_cv_func_res_search = no ; then
+ AC_CHECK_LIB(bind, res_search)
+ ac_cv_func_res_search=$ac_cv_lib_bind_res_search
+fi
-# find res_search
-if test $ol_enable_dns != no ; then
- dnl Check for resolver routines
- AC_CHECK_FUNC(res_search,:)
- if test $ac_cv_func_res_search = no ; then
- AC_CHECK_LIB(bind, res_search)
- ac_cv_func_res_search=$ac_cv_lib_bind_res_search
- fi
- if test $ac_cv_func_res_search = no ; then
- AC_CHECK_LIB(resolv, res_search)
- ac_cv_func_res_search=$ac_cv_lib_resolv_res_search
- fi
+if test $ac_cv_func_res_search = no ; then
+ AC_CHECK_LIB(bind, __res_search)
+ ac_cv_func_res_search=$ac_cv_lib_bind___res_search
+fi
+
+if test $ac_cv_func_res_search = no ; then
+ AC_CHECK_LIB(resolv, res_search)
+ ac_cv_func_res_search=$ac_cv_lib_resolv_res_search
+fi
- if test "$ac_cv_func_res_search" = yes ; then
- AC_DEFINE(HAVE_RES_SEARCH,1,
- [define if you have res_search()])
- elif test $ol_enable_dns = yes ; then
- AC_MSG_ERROR([--enable-dns requires res_search])
+if test "$ac_cv_func_res_search" = yes ; then
+ AC_DEFINE(HAVE_RES_SEARCH,1,
+ [define if you have res_search()])
+elif test $ol_enable_dns = yes ; then
+ AC_MSG_ERROR([--enable-dns requires res_search])
+elif test $ol_enable_dns != no ; then
+ AC_MSG_WARN([no res_search, disabling DNS support])
+fi
+
+
+# QUIPU
+if test $ol_enable_quipu != no ; then
+ AC_CHECK_HEADERS(quipu/commonarg.h)
+
+ if test $ac_cv_header_quipu_commonarg_h = yes ; then
+ BUILD_QUIPU=yes
+ elif test $ol_enable_quipu = auto ; then
+ AC_MSG_WARN([no quipu for --enable-quipu=auto, disabling])
else
- AC_MSG_WARN([no res_search, disabling DNS support])
+ AC_MSG_ERROR(no quipu for --enable-quipu=$ol_enable_quipu)
fi
fi
dnl pthread_create() in $LIBS
dnl
dnl Check special pthread (final) flags
- dnl pthread_create() with -mt (Solaris)
+ dnl [skipped] pthread_create() with -mt (Solaris) [disabled]
dnl pthread_create() with -kthread (FreeBSD)
dnl pthread_create() with -pthread (FreeBSD/Digital Unix)
dnl pthread_create() with -pthreads (?)
dnl Check pthread (final) libraries
dnl pthread_mutex_unlock() in -lpthread -lmach -lexc -lc_r (OSF/1)
dnl pthread_mutex_lock() in -lpthread -lmach -lexc (OSF/1)
- dnl (skipped) pthread_mutex_trylock() in -lpthread -lexc (OSF/1)
+ dnl [skipped] pthread_mutex_trylock() in -lpthread -lexc (OSF/1)
dnl pthread_join() -Wl,-woff,85 -lpthread (IRIX)
dnl pthread_create() in -lpthread (many)
dnl pthread_create() in -lc_r (FreeBSD)
dnl pthread_create in $LIBS
AC_CACHE_CHECK([for pthread_create in default libraries],
ol_cv_pthread_create,[
- AC_TRY_RUN([
-#include <pthread.h>
-#ifndef NULL
-#define NULL (void*)0
-#endif
-
-static void *task(p)
- void *p;
-{
- return (void *) (p == NULL);
-}
-
-int main(argc, argv)
- int argc;
- char **argv;
-{
- pthread_t t;
- int status;
-
- /* make sure pthread_create() isn't just a stub */
-#if HAVE_PTHREADS_D4
- status = pthread_create(&t, pthread_attr_default, task, NULL);
-#else
- status = pthread_create(&t, NULL, task, NULL);
-#endif
-
- if( status ) return status;
-
- /* make sure pthread_detach() isn't just a stub */
-#if HAVE_PTHREADS_D4
- status = pthread_detach( &t );
-#else
- status = pthread_detach( t );
-#endif
-
- return status;
-}
-],
+ AC_TRY_RUN(OL_PTHREAD_TEST_PROGRAM,
[ol_cv_pthread_create=yes],
[ol_cv_pthread_create=no],
- [dnl assume yes
- ol_cv_pthread_create=yes])])
+ [AC_TRY_LINK(OL_PTHREAD_TEST_INCLUDES,OL_PTHREAD_TEST_FUNCTION,
+ [ol_cv_pthread_create=yes],
+ [ol_cv_pthread_create=no])])])
if test $ol_cv_pthread_create != no ; then
ol_link_threads=posix
ol_link_pthreads=""
fi
- OL_PTHREAD_TRY_LINK([-mt], [ol_cv_pthread_mt])
- OL_PTHREAD_TRY_LINK([-kthread], [ol_cv_pthread_kthread])
- OL_PTHREAD_TRY_LINK([-pthread], [ol_cv_pthread_pthread])
- OL_PTHREAD_TRY_LINK([-pthreads],[ol_cv_pthread_pthreads])
- OL_PTHREAD_TRY_LINK([-mthreads],[ol_cv_pthread_mthreads])
- OL_PTHREAD_TRY_LINK([-thread], [ol_cv_pthread_thread])
-
- OL_PTHREAD_TRY_LINK([-lpthread -lmach -lexc -lc_r],
+dnl OL_PTHREAD_TRY([-mt], [ol_cv_pthread_mt])
+ OL_PTHREAD_TRY([-kthread], [ol_cv_pthread_kthread])
+ OL_PTHREAD_TRY([-pthread], [ol_cv_pthread_pthread])
+ OL_PTHREAD_TRY([-pthreads], [ol_cv_pthread_pthreads])
+ OL_PTHREAD_TRY([-mthreads], [ol_cv_pthread_mthreads])
+ OL_PTHREAD_TRY([-thread], [ol_cv_pthread_thread])
+
+ OL_PTHREAD_TRY([-lpthread -lmach -lexc -lc_r],
[ol_cv_pthread_lpthread_lmach_lexc_lc_r])
- OL_PTHREAD_TRY_LINK([-lpthread -lmach -lexc],
+ OL_PTHREAD_TRY([-lpthread -lmach -lexc],
[ol_cv_pthread_lpthread_lmach_lexc])
-dnl OL_PTHREAD_TRY_LINK([-lpthread -lexc],
+dnl OL_PTHREAD_TRY([-lpthread -lexc],
dnl [ol_cv_pthread_lpthread_lexc])
- OL_PTHREAD_TRY_LINK([-lpthread -Wl,-woff,85],
+ OL_PTHREAD_TRY([-lpthread -Wl,-woff,85],
[ol_cv_pthread_lib_lpthread_woff])
- OL_PTHREAD_TRY_LINK([-lpthread],[ol_cv_pthread_lpthread])
- OL_PTHREAD_TRY_LINK([-lc_r], [ol_cv_pthread_lc_r])
+ OL_PTHREAD_TRY([-lpthread], [ol_cv_pthread_lpthread])
+ OL_PTHREAD_TRY([-lc_r], [ol_cv_pthread_lc_r])
- OL_PTHREAD_TRY_LINK([-threads], [ol_cv_pthread_threads])
+ OL_PTHREAD_TRY([-threads], [ol_cv_pthread_threads])
- OL_PTHREAD_TRY_LINK([-lpthreads -lmach -lexc -lc_r],
+ OL_PTHREAD_TRY([-lpthreads -lmach -lexc -lc_r],
[ol_cv_pthread_lpthreads_lmach_lexc_lc_r])
- OL_PTHREAD_TRY_LINK([-lpthreads -lmach -lexc],
+ OL_PTHREAD_TRY([-lpthreads -lmach -lexc],
[ol_cv_pthread_lpthreads_lmach_lexc])
- OL_PTHREAD_TRY_LINK([-lpthreads -lexc],
+ OL_PTHREAD_TRY([-lpthreads -lexc],
[ol_cv_pthread_lpthreads_lexc])
- OL_PTHREAD_TRY_LINK([-lpthreads], [ol_cv_pthread_lib_lpthreads])
+ OL_PTHREAD_TRY([-lpthreads],[ol_cv_pthread_lib_lpthreads])
if test $ol_link_threads != no ; then
AC_DEFINE(HAVE_PTHREADS,1,
AC_CACHE_CHECK([if pthread_create() works],
ol_cv_pthread_create_works,[
- AC_TRY_RUN([
-#include <pthread.h>
-#ifndef NULL
-#define NULL (void*)0
-#endif
-
-static void *task(p)
- void *p;
-{
- return (void *) (p == NULL);
-}
-
-int main(argc, argv)
- int argc;
- char **argv;
-{
- pthread_t t;
-#if HAVE_PTHREADS_D4
- exit(pthread_create(&t, pthread_attr_default, task, NULL));
-#else
- exit(pthread_create(&t, NULL, task, NULL));
-#endif
-}
-],
+ AC_TRY_RUN(OL_PTHREAD_TEST_PROGRAM,
[ol_cv_pthread_create_works=yes],
[ol_cv_pthread_create_works=no],
[dnl assume yes
TERMCAP_LIBS=
fi
+dnl
+dnl Check for fetch URL support
+dnl should be extended to support other fetch URL APIs
+dnl
+ol_link_sasl=no
+if test $ol_with_cyrus_sasl != no ; then
+ AC_CHECK_HEADER(sasl.h)
+
+ if test $ac_cv_header_sasl_h = yes ; then
+ AC_CHECK_LIB(sasl, sasl_client_init,
+ [have_cyrus_sasl=yes], [have_cyrus_sasl=no])
+
+ if test $have_cyrus_sasl != no ; then
+ SASL_LIBS="-lsasl"
+ AC_DEFINE(HAVE_CYRUS_SASL,1,[define if you have Cyrus SASL])
+ ol_link_sasl=yes
+ fi
+ fi
+
+ if test $ol_link_sasl = no -a $ol_with_cyrus_sasl = yes ; then
+ AC_MSG_ERROR(no suitable API for --with-cyrus-sasl=$ol_with_cyrus_sasl)
+ fi
+fi
+
+dnl
+dnl Check for fetch URL support
+dnl should be extended to support other fetch URL APIs
+dnl
+ol_link_fetch=no
+if test $ol_with_fetch != no ; then
+ OL_LIB_FETCH
+
+ if test $ol_cv_lib_fetch != no ; then
+ LDIF_LIBS="$LDIF_LIBS $ol_link_fetch"
+ ol_link_fetch=freebsd
+
+ elif test $ol_with_fetch != auto ; then
+ AC_MSG_ERROR(no suitable API for --with-fetch=$ol_with_fetch)
+ fi
+fi
+
dnl
dnl Check for GNU readline
dnl
AC_FUNC_STRFTIME
dnl AM_FUNC_STRTOD
+OL_FUNC_INET_ATON
+
dnl we should use vfork instead of fork in a number of places...
dnl AC_FUNC_VFORK
AC_FUNC_VPRINTF
if test "$ol_enable_cleartext" != no ; then
AC_DEFINE(SLAPD_CLEARTEXT,1,[define to support cleartext passwords])
fi
+if test "$ol_enable_multimaster" != no ; then
+ AC_DEFINE(SLAPD_MULTIMASTER,1,[define to support multimaster replication])
+fi
if test "$ol_enable_phonetic" != no ; then
AC_DEFINE(SLAPD_PHONETIC,1,[define to support phonetic])
fi
if test "$ol_link_modules" != no ; then
AC_DEFINE(SLAPD_MODULES,1,[define to support modules])
BUILD_SLAPD=yes
+ MODULES_LIBS=-lltdl
+ SLAPD_MODULES_LDFLAGS="-dlopen self"
fi
if test "$ol_link_bdb2" != no ; then
if test "$ol_with_bdb2_module" != static ; then
AC_DEFINE(SLAPD_BDB2_DYNAMIC,1,
[define to support dynamic BDB2 backend])
- BUILD_BDB2_DYNAMIC=yes
+ BUILD_BDB2=mod
+ BUILD_BDB2_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-bdb2/back_bdb2.la"
fi
fi
if test "$ol_with_ldap_module" != static ; then
AC_DEFINE(SLAPD_LDAP_DYNAMIC,1,
[define to support dynamic LDAP backend])
- BUILD_LDAP_DYNAMIC=yes
+ BUILD_LDAP=mod
+ BUILD_LDAP_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-ldap/back_ldap.la"
fi
fi
if test "$ol_with_ldbm_module" != static ; then
AC_DEFINE(SLAPD_LDBM_DYNAMIC,1,
[define to support dynamic LDBM backend])
- BUILD_LDBM_DYNAMIC=yes
+ BUILD_LDBM=mod
+ BUILD_LDBM_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-ldbm/back_ldbm.la"
fi
fi
if test "$ol_with_passwd_module" != static ; then
AC_DEFINE(SLAPD_PASSWD_DYNAMIC,1,
[define to support dynamic PASSWD backend])
- BUILD_PASSWD_DYNAMIC=yes
+ BUILD_PASSWD=mod
+ BUILD_PASSWD_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-passwd/back_passwd.la"
fi
fi
if test "$ol_with_perl_module" != static ; then
AC_DEFINE(SLAPD_PERL_DYNAMIC,1,
[define to support dynamic PERL backend])
- BUILD_PERL_DYNAMIC=yes
+ BUILD_PERL=mod
+ BUILD_PERL_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-perl/back_perl.la"
fi
fi
if test "$ol_with_shell_module" != static ; then
AC_DEFINE(SLAPD_SHELL_DYNAMIC,1,
[define to support dynamic SHELL backend])
- BUILD_SHELL_DYNAMIC=yes
+ BUILD_SHELL=mod
+ BUILD_SHELL_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-shell/back_shell.la"
fi
fi
if test "$ol_with_tcl_module" != static; then
AC_DEFINE(SLAPD_TCL_DYNAMIC,1,
[define to support dynamic TCL backend])
- BUILD_TCL_DYNAMIC=yes
+ BUILD_TCL=mod
+ BUILD_TCL_DYNAMIC=shared
+ SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-tcl/back_tcl.la"
fi
fi
AC_SUBST(BUILD_LDBM)
AC_SUBST(BUILD_PASSWD)
AC_SUBST(BUILD_PERL)
+ AC_SUBST(BUILD_QUIPU)
AC_SUBST(BUILD_SHELL)
AC_SUBST(BUILD_TCL)
AC_SUBST(BUILD_BDB2_DYNAMIC)
AC_SUBST(BUILD_SLURPD)
AC_SUBST(LDAP_LIBS)
+AC_SUBST(LDIF_LIBS)
AC_SUBST(SLAPD_LIBS)
AC_SUBST(SLURPD_LIBS)
AC_SUBST(LDBM_LIBS)
AC_SUBST(SLAPD_MODULES_CPPFLAGS)
AC_SUBST(SLAPD_MODULES_LDFLAGS)
+AC_SUBST(SLAPD_MODULES_LIST)
AC_SUBST(SLAPD_PERL_CPPFLAGS)
AC_SUBST(SLAPD_PERL_LDFLAGS)
AC_SUBST(KRB_LIBS)
AC_SUBST(READLINE_LIBS)
+AC_SUBST(SASL_LIBS)
AC_SUBST(TERMCAP_LIBS)
AC_SUBST(TLS_LIBS)
+AC_SUBST(MODULES_LIBS)
dnl ----------------------------------------------------------------
dnl final output
libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk \
servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk \
servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk \
-servers/slapd/back-bdb2/Makefile:build/top.mk:servers/slapd/back-bdb2/Makefile.in:build/srv.mk \
-servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/srv.mk \
-servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/srv.mk \
-servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/srv.mk \
-servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/srv.mk \
-servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/srv.mk \
-servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/srv.mk \
+servers/slapd/back-bdb2/Makefile:build/top.mk:servers/slapd/back-bdb2/Makefile.in:build/mod.mk \
+servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk \
+servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/mod.mk \
+servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk \
+servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk \
+servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk \
+servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/mod.mk \
servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk \
servers/slapd/tools/Makefile:build/top.mk:servers/slapd/tools/Makefile.in \
servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk \
--- /dev/null
+## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, See COPYRIGHT file
+##
+## contrib Makefile.in for OpenLDAP
+
+SUBDIRS= saucer web_ldap
--- /dev/null
+Package version 1.2:
+
+- Filter no longer a required controlArray member, defaults to objectclass=*.
+- Sets errorCode with LDAP macro string value (better to test than the more
+ human readable values).
+- Shorten minimum required characters for search scope definitions: now allows
+ "base", "one", and "sub". For the latter two, additional characters are
+ ignored.
+- Now compiles successfully with -devel branch.
+- Client cache management code enabled for OpenLDAP versions <= 1.2.4. (This
+ code is relatively untested and feedback is welcome.)
--- /dev/null
+#
+# This file is a Makefile for Neo, the NeoSoft extensions to Tcl.
+# If it has the name "Makefile.in" then it is a template for a
+# Makefile; to generate the actual Makefile, run "./configure",
+# which is a configuration script generated by the "autoconf" program
+# (constructs like "@foo@" will get replaced in the actual Makefile.
+#
+
+VERSION = @NEO_VERSION@
+LIBNAME = @NEO_SHARED_LIB_FILE@
+
+# Default top-level directories in which to install architecture-
+# specific files (exec_prefix) and machine-independent files such
+# as scripts (prefix). The values specified here may be overridden
+# at configure-time with the --exec-prefix and --prefix options
+# to the "configure" script.
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+# The following definition can be set to non-null for special systems
+# like AFS with replication. It allows the pathnames used for installation
+# to be different than those used for actually reference files at
+# run-time. INSTALL_ROOT is prepended to $prefix and $exec_prefix
+# when installing files.
+INSTALL_ROOT =
+
+# Directory in which to search for tcl libraries
+NEO_LIBRARY = $(exec_prefix)/lib/ldaptcl$(VERSION)
+
+# Directory in which to install the ldaptcl binary:
+BIN_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/bin
+
+# Directory in which to install the .a or .so binary for the Neo library:
+LIB_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/lib
+
+# Path to use at runtime to refer to LIB_INSTALL_DIR:
+LIB_RUNTIME_DIR = $(exec_prefix)/lib
+
+# Top-level directory for man entries:
+MANN_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/man/mann
+
+
+# The symbols below provide support for dynamic loading and shared
+# libraries. The values of the symbols are normally set by the
+# configure script. You shouldn't normally need to modify any of
+# these definitions by hand.
+
+SHLIB_CFLAGS = @NEO_SHLIB_CFLAGS@
+
+NEO_LIB_FILE = @NEO_LIB_FILE@
+
+NEO_SHARED_LIB_FILE = @NEO_SHARED_LIB_FILE@
+
+# The directory containing the Tcl sources and headers appropriate
+# for this version of Neo ("srcdir" will be replaced or has already
+# been replaced by the configure script):
+TCL_GENERIC_DIR = @TCL_SRC_DIR@/generic
+
+# The top of the TclX directory tree
+TCLX_TOP_DIR = @TCLX_TOP_DIR@
+
+# The directory where tclExtend.h will be:
+TCLX_TCL_GEN_DIR = ${TCLX_TOP_DIR}/tcl/generic
+
+# The directory where tclXunixPort.h will be:
+TCLX_TCL_UNIX_DIR = ${TCLX_TOP_DIR}/tcl/unix
+
+# The path to tclX the runtcl script:
+TCLX_RUNTCL = ${TCLX_TOP_DIR}/unix/runtcl
+
+# The directory containing the Tcl library archive file appropriate
+# for this version of Neo:
+TCL_BIN_DIR = @TCL_BIN_DIR@
+
+
+# The symbol below provides support for dynamic loading and shared
+# libraries. See configure.in for a description of what it means.
+# The values of the symbolis normally set by the configure script.
+
+SHLIB_LD = @SHLIB_LD@
+
+# Set to the options to include libldap.a and liblber.a
+# (eg. -L../tools/blah -lldap -llber)
+
+LDAP_LIBFLAGS = @ldaplibflags@
+LDAP_CFLAGS = @ldapinclude@
+LDAP_INCDIR = @ldapincdir@
+LDAP_BUILD = @ldapbuild@
+LDAP_DIR = @ldapdir@
+
+
+#----------------------------------------------------------------
+# The information below is modified by the configure script when
+# Makefile is generated from Makefile.in. You shouldn't normally
+# modify any of this stuff by hand.
+#----------------------------------------------------------------
+
+AC_FLAGS = @DEFS@
+INSTALL= @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+RANLIB = @RANLIB@
+SRC_DIR = @srcdir@/..
+TOP_DIR = @srcdir@/..
+GENERIC_DIR = $(TOP_DIR)/generic
+
+#----------------------------------------------------------------
+# The information below should be usable as is. The configure
+# script won't modify it and you shouldn't need to modify it
+# either.
+#----------------------------------------------------------------
+
+
+OBJS= neoXldap.o
+
+LIBDIR=$(exec_prefix)/lib
+INCDIR=$(prefix)/include
+
+LIBS= @LIBS@ @TCLX_LIB_SPEC@ @TCL_LIB_SPEC@ @TCL_LIBS@ $(LDAP_LIBFLAGS) -lc
+TK_LIBS=@TKX_LIB_SPEC@ @TK_LIB_SPEC@ @TK_LIBS@
+TK_VERSION=@TK_VERSION@
+
+CC = @CC@
+CC_SWITCHES = ${CFLAGS} @NEO_SHLIB_CFLAGS@ -I. \
+-I@prefix@/include ${AC_FLAGS} ${PROTO_FLAGS} \
+${SECURITY_FLAGS} ${MEM_DEBUG_FLAGS} ${KEYSYM_FLAGS} \
+-DNEO_LIBRARY=\"${NEO_LIBRARY}\" -DVERSION=\"${VERSION}\"
+
+TK_SWITCHES = ${CC_SWITCHES} @TK_XINCLUDES@
+
+.c.o:
+ $(CC) -c $(CC_SWITCHES) $<
+
+all: @NEO_LIB_FILE@ ldaptclsh @LDAPWISH@
+
+@NEO_LIB_FILE@: $(OBJS)
+ rm -f @NEO_LIB_FILE@
+ @MAKE_LIB@
+ $(RANLIB) @NEO_LIB_FILE@
+
+neoXldap.o: neoXldap.c ldaptclerr.h
+ $(CC) -c $(LDAP_CFLAGS) $(CC_SWITCHES) $<
+
+ldaptclerr.h: ldaperr.tcl
+ tcl ldaperr.tcl $(LDAP_INCDIR)/ldap.h > ldaptclerr.h
+
+
+clean:
+ -rm -f ldaptclsh ldapwish
+ -rm -f *.o *.a *.so*
+
+distclean: clean
+ rm -f Makefile pkgIndex.tcl config.cache config.log config.status \
+ ldaptclerr.h
+
+install: install-binaries install-man
+
+install-binaries: @NEO_LIB_FILE@ ldaptclsh @LDAPWISH@
+ @-mkdir -p $(BIN_INSTALL_DIR)
+ $(INSTALL_PROGRAM) ldaptclsh $(BIN_INSTALL_DIR)/ldaptclsh
+ @if [ -n "@LDAPWISH@" ] ; then \
+ echo $(INSTALL_PROGRAM) ldapwish $(BIN_INSTALL_DIR)/ldapwish; \
+ $(INSTALL_PROGRAM) ldapwish $(BIN_INSTALL_DIR)/ldapwish; \
+ fi
+ $(INSTALL_DATA) @NEO_LIB_FILE@ $(LIB_INSTALL_DIR)
+ @if [ "$(NEO_LIB_FILE)" = "$(NEO_SHARED_LIB_FILE)" ] ; then \
+ echo Installing pkgIndex.tcl in $(NEO_LIBRARY); \
+ mkdir -p $(NEO_LIBRARY); \
+ $(INSTALL_DATA) pkgIndex.tcl $(NEO_LIBRARY); \
+ fi
+
+
+install-man:
+ @for i in ldap.n; \
+ do \
+ echo "Installing $$i"; \
+ rm -f $(MANN_INSTALL_DIR)/$$i; \
+ sed -e '/man\.macros/r man.macros' -e '/man\.macros/d' \
+ $$i > $(MANN_INSTALL_DIR)/$$i; \
+ chmod 444 $(MANN_INSTALL_DIR)/$$i; \
+ done;
+
+
+TCLOFILES= tclAppInit.o
+
+ldaptclsh:$(TCLOFILES) @NEO_LIB_FILE@
+ $(CC) @LD_FLAGS@ $(TCLOFILES) @NEO_BUILD_LIB_SPEC@ $(LIBS) \
+ @TCL_LD_SEARCH_FLAGS@ -o ldaptclsh
+
+tkAppInit.o: tkAppInit.c
+ $(CC) -c ${TK_SWITCHES} tkAppInit.c
+
+ldapwish:tkAppInit.o @NEO_LIB_FILE@
+ $(CC) @LD_FLAGS@ tkAppInit.o @NEO_BUILD_LIB_SPEC@ $(TK_LIBS) $(LIBS) \
+ @TCL_LD_SEARCH_FLAGS@ -o ldapwish
--- /dev/null
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-gcc allow use of gcc if available"
+ac_help="$ac_help
+ --enable-gcc allow use of gcc if available"
+ac_help="$ac_help
+ --with-tk=DIR use Tk 8.0 binaries from DIR"
+ac_help="$ac_help
+ --without-x do not build/install ldapwish"
+ac_help="$ac_help
+ --enable-shared build libldaptcl as a shared library"
+ac_help="$ac_help
+ --with-ldap=<dir> common parent of ldap include and lib dirs"
+ac_help="$ac_help
+ --with-ldap-incdir=<dir> path to ldap.h"
+ac_help="$ac_help
+ --with-ldap-libdir=<dir> path to ldap and lber libs"
+ac_help="$ac_help
+ --with-ldap-libflags=<libnames> -l flags for ldap libraries"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=neoXldap.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+# $Id: configure,v 1.3 1999/08/03 05:23:03 kunkee Exp $
+
+NEO_VERSION=1.2
+NEO_MAJOR_VERSION=1
+NEO_MINOR_VERSION=2
+VERSION=${NEO_VERSION}
+
+if test "${prefix}" = "NONE"; then
+ prefix=/usr/local
+fi
+if test "${exec_prefix}" = "NONE"; then
+ exec_prefix=$prefix
+fi
+
+# Check whether --enable-gcc or --disable-gcc was given.
+if test "${enable_gcc+set}" = set; then
+ enableval="$enable_gcc"
+ neo_ok=$enableval
+else
+ neo_ok=no
+fi
+
+if test "$neo_ok" = "yes"; then
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:569: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:599: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:650: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:682: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 693 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:698: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:724: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:729: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:738: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:757: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+else
+ CC=${CC-cc}
+
+fi
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:793: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 808 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:814: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 825 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:831: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 842 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:848: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+
+# Check whether --enable-gcc or --disable-gcc was given.
+if test "${enable_gcc+set}" = set; then
+ enableval="$enable_gcc"
+ neo_ok=$enableval
+else
+ neo_ok=no
+fi
+
+if test "$neo_ok" = "yes"; then
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:885: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:915: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:966: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:998: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1009 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:1014: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1040: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:1045: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1054: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1073: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+else
+ CC=${CC-cc}
+
+fi
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1140: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1195: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test ! -f $exec_prefix/lib/tclConfig.sh
+then
+ { echo "configure: error: Tcl must be installed first" 1>&2; exit 1; }
+fi
+
+. $exec_prefix/lib/tclConfig.sh
+
+if test ! -f $exec_prefix/lib/tclxConfig.sh
+then
+ { echo "configure: error: Extended Tcl must be installed first" 1>&2; exit 1; }
+fi
+. $exec_prefix/lib/tclxConfig.sh
+
+
+#--------------------------------------------------------------------
+# See if there was a command-line option for where Tk is; if
+# not, assume that its top-level directory is a sibling of ours.
+#--------------------------------------------------------------------
+
+# Check whether --with-tk or --without-tk was given.
+if test "${with_tk+set}" = set; then
+ withval="$with_tk"
+ :
+else
+ with_tk=yes
+fi
+
+
+case "$with_tk" in
+ yes)
+ if test -f $exec_prefix/lib/tkConfig.sh -a $exec_prefix/lib/tkxConfig.sh
+ then
+ :
+ else
+ { echo "configure: error: Tk does not appear to be installed at $exec_prefix" 1>&2; exit 1; }
+ fi
+ ;;
+ no) ;;
+ *) { echo "configure: error: Tk cannot be specified and must be in $exec_prefix" 1>&2; exit 1; }
+ ;;
+esac
+
+# Check whether --with-x or --without-x was given.
+if test "${with_x+set}" = set; then
+ withval="$with_x"
+ :
+fi
+
+if test "$with_x" = "no"
+then
+ with_tk=no
+fi
+
+if test "$with_tk" != "no"
+then
+ LDAPWISH=ldapwish
+ . $exec_prefix/lib/tkConfig.sh
+ . $exec_prefix/lib/tkxConfig.sh
+fi
+
+
+
+
+
+
+
+#--------------------------------------------------------------------
+# Read in configuration information generated by Tcl for shared
+# libraries, and arrange for it to be substituted into our
+# Makefile.
+#--------------------------------------------------------------------
+
+CC=$TCL_CC
+SHLIB_CFLAGS=$TCL_SHLIB_CFLAGS
+SHLIB_LD=$TCL_SHLIB_LD
+SHLIB_LD_LIBS=$TCL_SHLIB_LD_LIBS
+SHLIB_SUFFIX=$TCL_SHLIB_SUFFIX
+SHLIB_VERSION=$TCL_SHLIB_VERSION
+DL_LIBS=$TCL_DL_LIBS
+LD_FLAGS=$TCL_LD_FLAGS
+NEO_LD_SEARCH_FLAGS=$TCL_LD_SEARCH_FLAGS
+
+eval "NEO_SHARED_LIB_FILE=libldaptcl${TCL_SHARED_LIB_SUFFIX}"
+eval "NEO_UNSHARED_LIB_FILE=libldaptcl${TCL_UNSHARED_LIB_SUFFIX}"
+
+#--------------------------------------------------------------------
+# The statements below define a collection of symbols related to
+# building libldap as a shared library instead of a static library.
+#--------------------------------------------------------------------
+
+# Warning: in order to use the following code for libldap and libdb versions,
+# the VERSION shell variable is modified, and then is restored after.
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ ok=$enableval
+else
+ ok=no
+fi
+
+if test "$ok" = "yes" -a "${SHLIB_SUFFIX}" != ""; then
+ NEO_SHLIB_CFLAGS="${SHLIB_CFLAGS}"
+ eval "NEO_LIB_FILE=libldaptcl${TCL_SHARED_LIB_SUFFIX}"
+ MAKE_LIB="\${SHLIB_LD} $TCL_LIB_HNAME -o ${NEO_LIB_FILE} \${OBJS} \${LDAP_LIBFLAGS}"
+ RANLIB=":"
+else
+ NEO_SHLIB_CFLAGS=""
+ eval "NEO_LIB_FILE=libldaptcl${TCL_UNSHARED_LIB_SUFFIX}"
+ MAKE_LIB="ar cr ${NEO_LIB_FILE} \${OBJS}"
+fi
+
+# Check whether --with-ldap or --without-ldap was given.
+if test "${with_ldap+set}" = set; then
+ withval="$with_ldap"
+ neo_ldap=$withval
+ case $withval in
+ yes) ldapdir=/usr/local
+ ;;
+ no) ;;
+ *) ldapdir=$withval
+ neo_ldap=yes
+ ;;
+ esac
+
+else
+
+ neo_ldap=yes
+ ldapdir=/usr/local
+
+fi
+
+
+ldapincdir=$ldapdir/include
+# Check whether --with-ldap-incdir or --without-ldap-incdir was given.
+if test "${with_ldap_incdir+set}" = set; then
+ withval="$with_ldap_incdir"
+ ldapincdir=$withval
+fi
+
+
+ldaplibdir=$ldapdir/lib
+# Check whether --with-ldap-libdir or --without-ldap-libdir was given.
+if test "${with_ldap_libdir+set}" = set; then
+ withval="$with_ldap_libdir"
+ ldapincdir=$withval
+fi
+
+
+# Check whether --with-ldap-libraries or --without-ldap-libraries was given.
+if test "${with_ldap_libraries+set}" = set; then
+ withval="$with_ldap_libraries"
+ ldaplibflags="-L$ldaplibdir $withval"
+else
+ ldaplibflags="-L$ldaplibdir -lldap -llber"
+fi
+
+
+ldapinclude="-I$ldapincdir"
+
+ldapbuild=yes
+
+
+
+
+
+
+
+
+VERSION=${NEO_VERSION}
+# Note: in the following variable, it's important to use the absolute
+# path name of the Tcl directory rather than "..": this is because
+# AIX remembers this path and will attempt to use it at run-time to look
+# up the Tcl library.
+
+if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
+ NEO_BUILD_LIB_SPEC="-L`pwd` -lldaptcl${VERSION}"
+ NEO_LIB_SPEC="-L${exec_prefix}/lib -lldaptcl${VERSION}"
+else
+ NEO_BUILD_LIB_SPEC="-L`pwd` -lldaptcl`echo ${VERSION} | tr -d .`"
+ NEO_LIB_SPEC="-L${exec_prefix}/lib -lldaptcl`echo ${VERSION} | tr -d .`"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile pkgIndex.tcl" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@RANLIB@%$RANLIB%g
+s%@TK_LIBS@%$TK_LIBS%g
+s%@TK_LIB_SPEC@%$TK_LIB_SPEC%g
+s%@TK_XINCLUDES@%$TK_XINCLUDES%g
+s%@TK_VERSION@%$TK_VERSION%g
+s%@TKX_LIB_SPEC@%$TKX_LIB_SPEC%g
+s%@LDAPWISH@%$LDAPWISH%g
+s%@ldaplibflags@%$ldaplibflags%g
+s%@ldapinclude@%$ldapinclude%g
+s%@ldapbuild@%$ldapbuild%g
+s%@ldapdir@%$ldapdir%g
+s%@ldapincdir@%$ldapincdir%g
+s%@DL_LIBS@%$DL_LIBS%g
+s%@LD_FLAGS@%$LD_FLAGS%g
+s%@MATH_LIBS@%$MATH_LIBS%g
+s%@MAKE_LIB@%$MAKE_LIB%g
+s%@SHLIB_CFLAGS@%$SHLIB_CFLAGS%g
+s%@SHLIB_LD@%$SHLIB_LD%g
+s%@SHLIB_LD_LIBS@%$SHLIB_LD_LIBS%g
+s%@SHLIB_SUFFIX@%$SHLIB_SUFFIX%g
+s%@SHLIB_VERSION@%$SHLIB_VERSION%g
+s%@TCLX_TOP_DIR@%$TCLX_TOP_DIR%g
+s%@TCLX_TCL_DIR@%$TCLX_TCL_DIR%g
+s%@TCLX_LIB_SPEC@%$TCLX_LIB_SPEC%g
+s%@ITCL_LIB_SPEC@%$ITCL_LIB_SPEC%g
+s%@TCL_LIBS@%$TCL_LIBS%g
+s%@TCL_SRC_DIR@%$TCL_SRC_DIR%g
+s%@TCL_BIN_DIR@%$TCL_BIN_DIR%g
+s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g
+s%@TCL_LD_SEARCH_FLAGS@%$TCL_LD_SEARCH_FLAGS%g
+s%@TCL_LIB_HNAME@%$TCL_LIB_HNAME%g
+s%@TCL_VERSION@%$TCL_VERSION%g
+s%@NEO_BUILD_LIB_SPEC@%$NEO_BUILD_LIB_SPEC%g
+s%@NEO_LD_SEARCH_FLAGS@%$NEO_LD_SEARCH_FLAGS%g
+s%@NEO_SHARED_LIB_FILE@%$NEO_SHARED_LIB_FILE%g
+s%@NEO_UNSHARED_LIB_FILE@%$NEO_UNSHARED_LIB_FILE%g
+s%@NEO_LIB_FILE@%$NEO_LIB_FILE%g
+s%@NEO_LIB_SPEC@%$NEO_LIB_SPEC%g
+s%@NEO_MAJOR_VERSION@%$NEO_MAJOR_VERSION%g
+s%@NEO_MINOR_VERSION@%$NEO_MINOR_VERSION%g
+s%@NEO_SHLIB_CFLAGS@%$NEO_SHLIB_CFLAGS%g
+s%@NEO_VERSION@%$NEO_VERSION%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile pkgIndex.tcl"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
--- /dev/null
+dnl This file is an input file used by the GNU "autoconf" program to
+dnl generate the file "configure", which is run during Tk installation
+dnl to configure the system for the local environment.
+AC_INIT(neoXldap.c)
+# $Id: configure.in,v 1.3 1999/08/03 05:23:03 kunkee Exp $
+
+NEO_VERSION=1.2
+NEO_MAJOR_VERSION=1
+NEO_MINOR_VERSION=2
+VERSION=${NEO_VERSION}
+
+if test "${prefix}" = "NONE"; then
+ prefix=/usr/local
+fi
+if test "${exec_prefix}" = "NONE"; then
+ exec_prefix=$prefix
+fi
+
+AC_ARG_ENABLE(gcc, [ --enable-gcc allow use of gcc if available],
+ [neo_ok=$enableval], [neo_ok=no])
+if test "$neo_ok" = "yes"; then
+ AC_PROG_CC
+else
+ CC=${CC-cc}
+ AC_SUBST(CC)
+fi
+AC_PROG_CPP
+
+AC_ARG_ENABLE(gcc, [ --enable-gcc allow use of gcc if available],
+ [neo_ok=$enableval], [neo_ok=no])
+if test "$neo_ok" = "yes"; then
+ AC_PROG_CC
+else
+ CC=${CC-cc}
+AC_SUBST(CC)
+fi
+
+AC_PROG_INSTALL(install-sh)
+AC_PROG_RANLIB
+
+if test ! -f $exec_prefix/lib/tclConfig.sh
+then
+ AC_MSG_ERROR(Tcl must be installed first)
+fi
+
+. $exec_prefix/lib/tclConfig.sh
+
+if test ! -f $exec_prefix/lib/tclxConfig.sh
+then
+ AC_MSG_ERROR(Extended Tcl must be installed first)
+fi
+. $exec_prefix/lib/tclxConfig.sh
+
+
+#--------------------------------------------------------------------
+# See if there was a command-line option for where Tk is; if
+# not, assume that its top-level directory is a sibling of ours.
+#--------------------------------------------------------------------
+
+AC_ARG_WITH(tk, [ --with-tk=DIR use Tk 8.0 binaries from DIR],
+ , with_tk=yes)
+
+case "$with_tk" in
+ yes)
+ if test -f $exec_prefix/lib/tkConfig.sh -a $exec_prefix/lib/tkxConfig.sh
+ then
+ :
+ else
+ AC_MSG_ERROR(Tk does not appear to be installed at $exec_prefix)
+ fi
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR(Tk cannot be specified and must be in $exec_prefix)
+ ;;
+esac
+
+AC_ARG_WITH(x, [ --without-x do not build/install ldapwish])
+if test "$with_x" = "no"
+then
+ with_tk=no
+fi
+
+if test "$with_tk" != "no"
+then
+ LDAPWISH=ldapwish
+ . $exec_prefix/lib/tkConfig.sh
+ . $exec_prefix/lib/tkxConfig.sh
+fi
+AC_SUBST(TK_LIBS)
+AC_SUBST(TK_LIB_SPEC)
+AC_SUBST(TK_XINCLUDES)
+AC_SUBST(TK_VERSION)
+AC_SUBST(TKX_LIB_SPEC)
+AC_SUBST(LDAPWISH)
+
+#--------------------------------------------------------------------
+# Read in configuration information generated by Tcl for shared
+# libraries, and arrange for it to be substituted into our
+# Makefile.
+#--------------------------------------------------------------------
+
+CC=$TCL_CC
+SHLIB_CFLAGS=$TCL_SHLIB_CFLAGS
+SHLIB_LD=$TCL_SHLIB_LD
+SHLIB_LD_LIBS=$TCL_SHLIB_LD_LIBS
+SHLIB_SUFFIX=$TCL_SHLIB_SUFFIX
+SHLIB_VERSION=$TCL_SHLIB_VERSION
+DL_LIBS=$TCL_DL_LIBS
+LD_FLAGS=$TCL_LD_FLAGS
+NEO_LD_SEARCH_FLAGS=$TCL_LD_SEARCH_FLAGS
+
+eval "NEO_SHARED_LIB_FILE=libldaptcl${TCL_SHARED_LIB_SUFFIX}"
+eval "NEO_UNSHARED_LIB_FILE=libldaptcl${TCL_UNSHARED_LIB_SUFFIX}"
+
+#--------------------------------------------------------------------
+# The statements below define a collection of symbols related to
+# building libldap as a shared library instead of a static library.
+#--------------------------------------------------------------------
+
+# Warning: in order to use the following code for libldap and libdb versions,
+# the VERSION shell variable is modified, and then is restored after.
+
+AC_ARG_ENABLE(shared,
+ [ --enable-shared build libldaptcl as a shared library],
+ [ok=$enableval], [ok=no])
+if test "$ok" = "yes" -a "${SHLIB_SUFFIX}" != ""; then
+ NEO_SHLIB_CFLAGS="${SHLIB_CFLAGS}"
+ eval "NEO_LIB_FILE=libldaptcl${TCL_SHARED_LIB_SUFFIX}"
+ MAKE_LIB="\${SHLIB_LD} $TCL_LIB_HNAME -o ${NEO_LIB_FILE} \${OBJS} \${LDAP_LIBFLAGS}"
+ RANLIB=":"
+else
+ NEO_SHLIB_CFLAGS=""
+ eval "NEO_LIB_FILE=libldaptcl${TCL_UNSHARED_LIB_SUFFIX}"
+ MAKE_LIB="ar cr ${NEO_LIB_FILE} \${OBJS}"
+fi
+
+AC_ARG_WITH(ldap, [ --with-ldap=<dir> common parent of ldap include and lib dirs],
+ [neo_ldap=$withval
+ case $withval in
+ yes) ldapdir=/usr/local
+ ;;
+ no) ;;
+ *) ldapdir=$withval
+ neo_ldap=yes
+ ;;
+ esac
+ ], [
+ neo_ldap=yes
+ ldapdir=/usr/local
+ ])
+
+ldapincdir=$ldapdir/include
+AC_ARG_WITH(ldap-incdir, [ --with-ldap-incdir=<dir> path to ldap.h],
+ [ldapincdir=$withval])
+
+ldaplibdir=$ldapdir/lib
+AC_ARG_WITH(ldap-libdir, [ --with-ldap-libdir=<dir> path to ldap and lber libs],
+ [ldapincdir=$withval])
+
+AC_ARG_WITH(ldap-libraries, [ --with-ldap-libflags=<libnames> -l flags for ldap libraries],
+ [ldaplibflags="-L$ldaplibdir $withval"],
+ [ldaplibflags="-L$ldaplibdir -lldap -llber"])
+
+ldapinclude="-I$ldapincdir"
+
+ldapbuild=yes
+
+AC_SUBST(ldaplibflags)
+AC_SUBST(ldapinclude)
+AC_SUBST(ldapbuild)
+AC_SUBST(ldapdir)
+AC_SUBST(ldapincdir)
+
+
+VERSION=${NEO_VERSION}
+# Note: in the following variable, it's important to use the absolute
+# path name of the Tcl directory rather than "..": this is because
+# AIX remembers this path and will attempt to use it at run-time to look
+# up the Tcl library.
+
+if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
+ NEO_BUILD_LIB_SPEC="-L`pwd` -lldaptcl${VERSION}"
+ NEO_LIB_SPEC="-L${exec_prefix}/lib -lldaptcl${VERSION}"
+else
+ NEO_BUILD_LIB_SPEC="-L`pwd` -lldaptcl`echo ${VERSION} | tr -d .`"
+ NEO_LIB_SPEC="-L${exec_prefix}/lib -lldaptcl`echo ${VERSION} | tr -d .`"
+fi
+
+AC_SUBST(CC)
+AC_SUBST(LIBS)
+AC_SUBST(DL_LIBS)
+AC_SUBST(LD_FLAGS)
+AC_SUBST(MATH_LIBS)
+AC_SUBST(MAKE_LIB)
+AC_SUBST(SHLIB_CFLAGS)
+AC_SUBST(SHLIB_LD)
+AC_SUBST(SHLIB_LD_LIBS)
+AC_SUBST(SHLIB_SUFFIX)
+AC_SUBST(SHLIB_VERSION)
+AC_SUBST(TCLX_TOP_DIR)
+AC_SUBST(TCLX_TCL_DIR)
+AC_SUBST(TCLX_LIB_SPEC)
+AC_SUBST(ITCL_LIB_SPEC)
+AC_SUBST(TCL_LIBS)
+AC_SUBST(TCL_SRC_DIR)
+AC_SUBST(TCL_BIN_DIR)
+AC_SUBST(TCL_LIB_SPEC)
+AC_SUBST(TCL_LD_SEARCH_FLAGS)
+AC_SUBST(TCL_LIB_HNAME)
+AC_SUBST(TCL_SRC_DIR)
+AC_SUBST(TCL_VERSION)
+AC_SUBST(NEO_BUILD_LIB_SPEC)
+AC_SUBST(NEO_LD_SEARCH_FLAGS)
+AC_SUBST(NEO_SHARED_LIB_FILE)
+AC_SUBST(NEO_UNSHARED_LIB_FILE)
+AC_SUBST(NEO_LIB_FILE)
+AC_SUBST(NEO_LIB_SPEC)
+AC_SUBST(NEO_MAJOR_VERSION)
+AC_SUBST(NEO_MINOR_VERSION)
+AC_SUBST(NEO_SHLIB_CFLAGS)
+AC_SUBST(NEO_VERSION)
+dnl AC_SUBST(XINCLUDES)
+dnl AC_SUBST(XLIBSW)
+
+AC_OUTPUT(Makefile pkgIndex.tcl)
--- /dev/null
+#
+# ldaperr.tcl: scan ldap.h for error return codes for initializing
+# errorCode table.
+#
+
+proc genstrings {path} {
+ set fp [open $path]
+ while {[gets $fp line] != -1 &&
+ ![string match "#define LDAP_SUCCESS*" $line]} { }
+ puts "/* This file automatically generated, hand edit at your own risk! */"
+ puts -nonewline "char *ldaptclerrorcode\[\] = {
+ NULL"
+ set lasterr 0
+ while {[gets $fp line] != -1} {
+ if {[clength $line] == 0 || [ctype space $line]} continue
+ if {![string match #define* $line]} break
+ if {![string match "#define LDAP_*" $line]} continue
+ lassign $line define macro value
+ incr lasterr
+ while {$lasterr < $value} {
+ puts -nonewline ",\n\tNULL"
+ incr lasterr
+ }
+ puts -nonewline ",\n\t\"$macro\""
+ }
+ puts "\n};"
+ puts "#define LDAPTCL_MAXERR\t$value"
+}
+
+#cmdtrace on
+if !$tcl_interactive {
+ genstrings [lindex $argv 0]
+}
--- /dev/null
+/*
+ * NeoSoft Tcl client extensions to Lightweight Directory Access Protocol.
+ *
+ * Copyright (c) 1998-1999 NeoSoft, Inc.
+ * All Rights Reserved.
+ *
+ * This software may be used, modified, copied, distributed, and sold,
+ * in both source and binary form provided that these copyrights are
+ * retained and their terms are followed.
+ *
+ * Under no circumstances are the authors or NeoSoft Inc. responsible
+ * for the proper functioning of this software, nor do the authors
+ * assume any liability for damages incurred with its use.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to NeoSoft, Inc.
+ *
+ * NeoSoft, Inc. may not be used to endorse or promote products derived
+ * from this software without specific prior written permission. This
+ * software is provided ``as is'' without express or implied warranty.
+ *
+ * Requests for permission may be sent to NeoSoft Inc, 1770 St. James Place,
+ * Suite 500, Houston, TX, 77056.
+ *
+ * $Id: neoXldap.c,v 1.5 1999/08/03 05:23:03 kunkee Exp $
+ *
+ */
+
+/*
+ * This code was originally developed by Karl Lehenbauer to work with
+ * Umich-3.3 LDAP. It was debugged against the Netscape LDAP server
+ * and their much more reliable SDK, and again backported to the
+ * Umich-3.3 client code. The UMICH_LDAP define is used to include
+ * code that will work with the Umich-3.3 LDAP, but not with Netscape's
+ * SDK. OpenLDAP may support some of these, but they have not been tested.
+ * Currently supported by Randy Kunkee (kunkee@OpenLDAP.org).
+ */
+
+/*
+ * Add timeout to controlArray to set timeout for ldap_result.
+ * 4/14/99 - Randy
+ */
+
+#include "tclExtend.h"
+
+#include <lber.h>
+#include <ldap.h>
+#include <string.h>
+#include <sys/time.h>
+#include <math.h>
+
+/*
+ * Macros to do string compares. They pre-check the first character before
+ * checking of the strings are equal.
+ */
+
+#define STREQU(str1, str2) \
+ (((str1) [0] == (str2) [0]) && (strcmp (str1, str2) == 0))
+#define STRNEQU(str1, str2, n) \
+ (((str1) [0] == (str2) [0]) && (strncmp (str1, str2, n) == 0))
+
+/*
+ * The following section defines some common macros used by the rest
+ * of the code. It's ugly, and can use some work. This code was
+ * originally developed to work with Umich-3.3 LDAP. It was debugged
+ * against the Netscape LDAP server and the much more reliable SDK,
+ * and then again backported to the Umich-3.3 client code.
+ */
+#define OPEN_LDAP 1
+#if defined(OPEN_LDAP)
+ /* LDAP_API_VERSION must be defined per the current draft spec
+ ** it's value will be assigned RFC number. However, as
+ ** no RFC is defined, it's value is currently implementation
+ ** specific (though I would hope it's value is greater than 1823).
+ ** In OpenLDAP 2.x-devel, its 2000 + the draft number, ie 2002.
+ ** This section is for OPENLDAP.
+ */
+#define ldap_attributefree(p) ldap_memfree(p)
+#define ldap_memfree(p) free(p)
+#ifdef LDAP_OPT_ERROR_NUMBER
+#define ldap_get_lderrno(ld) (ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &lderrno), lderrno)
+#else
+#define ldap_get_lderrno(ld) (ld->ld_errno)
+#endif
+#define LDAP_ERR_STRING(ld) \
+ ldap_err2string(ldap_get_lderrno(ld))
+#elif defined( LDAP_OPT_SIZELIMIT )
+ /*
+ ** Netscape SDK w/ ldap_set_option, ldap_get_option
+ */
+#define ldap_attributefree(p) ldap_memfree(p)
+#define LDAP_ERR_STRING(ld) \
+ ldap_err2string(ldap_get_lderrno(ldap))
+#else
+ /* U-Mich/OpenLDAP 1.x API */
+ /* RFC-1823 w/ changes */
+#define UMICH_LDAP 1
+#define ldap_memfree(p) free(p)
+#define ldap_ber_free(p, n) ber_free(p, n)
+#define ldap_value_free_len(bvals) ber_bvecfree(bvals)
+#define ldap_attributefree(p)
+#define ldap_get_lderrno(ld) (ld->ld_errno)
+#define LDAP_ERR_STRING(ld) \
+ ldap_err2string(ld->ld_errno)
+#endif
+
+typedef struct ldaptclobj {
+ LDAP *ldap;
+ int flags
+} LDAPTCL;
+
+#define LDAPTCL_INTERRCODES 0x001
+
+#include "ldaptclerr.h"
+
+static
+LDAP_SetErrorCode(LDAPTCL *ldaptcl, int code, Tcl_Interp *interp)
+{
+ char shortbuf[6];
+ char *errp;
+ int lderrno;
+
+ if (code == -1)
+ code = ldap_get_lderrno(ldaptcl->ldap);
+ if ((ldaptcl->flags & LDAPTCL_INTERRCODES) || code > LDAPTCL_MAXERR ||
+ ldaptclerrorcode[code] == NULL) {
+ sprintf(shortbuf, "0x%03x", code);
+ errp = shortbuf;
+ } else
+ errp = ldaptclerrorcode[code];
+
+ Tcl_SetErrorCode(interp, errp, NULL);
+}
+
+/*-----------------------------------------------------------------------------
+ * LDAP_ProcessOneSearchResult --
+ *
+ * Process one result return from an LDAP search.
+ *
+ * Paramaters:
+ * o interp - Tcl interpreter; Errors are returned in result.
+ * o ldap - LDAP structure pointer.
+ * o entry - LDAP message pointer.
+ * o destArrayNameObj - Name of Tcl array in which to store attributes.
+ * o evalCodeObj - Tcl_Obj pointer to code to eval against this result.
+ * Returns:
+ * o TCL_OK if processing succeeded..
+ * o TCL_ERROR if an error occured, with error message in interp.
+ *-----------------------------------------------------------------------------
+ */
+static int
+LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj)
+ Tcl_Interp *interp;
+ LDAP *ldap;
+ LDAPMessage *entry;
+ Tcl_Obj *destArrayNameObj;
+ Tcl_Obj *evalCodeObj;
+{
+ char *attributeName;
+ Tcl_Obj *attributeNameObj;
+ Tcl_Obj *attributeDataObj;
+ int i;
+ BerElement *ber;
+ struct berval **bvals;
+ char *dn;
+ int lderrno;
+
+ Tcl_UnsetVar (interp, Tcl_GetStringFromObj (destArrayNameObj, NULL), 0);
+
+ dn = ldap_get_dn(ldap, entry);
+ if (dn != NULL) {
+ if (Tcl_SetVar2(interp, /* set dn */
+ Tcl_GetStringFromObj(destArrayNameObj, NULL),
+ "dn",
+ dn,
+ TCL_LEAVE_ERR_MSG) == NULL)
+ return TCL_ERROR;
+ ldap_memfree(dn);
+ }
+ for (attributeName = ldap_first_attribute (ldap, entry, &ber);
+ attributeName != NULL;
+ attributeName = ldap_next_attribute(ldap, entry, ber)) {
+
+ bvals = ldap_get_values_len(ldap, entry, attributeName);
+
+ if (bvals != NULL) {
+ /* Note here that the U.of.M. ldap will return a null bvals
+ when the last attribute value has been deleted, but still
+ retains the attributeName. Even though this is documented
+ as an error, we ignore it to present a consistent interface
+ with Netscape's server
+ */
+ attributeNameObj = Tcl_NewStringObj (attributeName, -1);
+ Tcl_IncrRefCount (attributeNameObj);
+ attributeDataObj = Tcl_NewObj();
+ for (i = 0; bvals[i] != NULL; i++) {
+ Tcl_Obj *singleAttributeValueObj;
+
+ singleAttributeValueObj = Tcl_NewStringObj (bvals[i]->bv_val, -1);
+ if (Tcl_ListObjAppendElement (interp,
+ attributeDataObj,
+ singleAttributeValueObj)
+ == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ }
+
+ ldap_value_free_len(bvals);
+
+ if (Tcl_ObjSetVar2 (interp,
+ destArrayNameObj,
+ attributeNameObj,
+ attributeDataObj,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount (attributeNameObj);
+ }
+ ldap_attributefree(attributeName);
+ }
+ return Tcl_EvalObj (interp, evalCodeObj);
+}
+
+/*-----------------------------------------------------------------------------
+ * LDAP_PerformSearch --
+ *
+ * Perform an LDAP search.
+ *
+ * Paramaters:
+ * o interp - Tcl interpreter; Errors are returned in result.
+ * o ldap - LDAP structure pointer.
+ * o base - Base DN from which to perform search.
+ * o scope - LDAP search scope, must be one of LDAP_SCOPE_BASE,
+ * LDAP_SCOPE_ONELEVEL, or LDAP_SCOPE_SUBTREE.
+ * o attrs - Pointer to array of char * pointers of desired
+ * attribute names, or NULL for all attributes.
+ * o filtpatt LDAP filter pattern.
+ * o value Value to get sprintf'ed into filter pattern.
+ * o destArrayNameObj - Name of Tcl array in which to store attributes.
+ * o evalCodeObj - Tcl_Obj pointer to code to eval against this result.
+ * Returns:
+ * o TCL_OK if processing succeeded..
+ * o TCL_ERROR if an error occured, with error message in interp.
+ *-----------------------------------------------------------------------------
+ */
+static int
+LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destArrayNameObj, evalCodeObj, timeout_p)
+ Tcl_Interp *interp;
+ LDAPTCL *ldaptcl;
+ char *base;
+ int scope;
+ char **attrs;
+ char *filtpatt;
+ char *value;
+ Tcl_Obj *destArrayNameObj;
+ Tcl_Obj *evalCodeObj;
+ struct timeval *timeout_p;
+{
+ LDAP *ldap = ldaptcl->ldap;
+ char filter[BUFSIZ];
+ int resultCode;
+ int errorCode;
+ int abandon;
+ int tclResult = TCL_OK;
+ int msgid;
+ LDAPMessage *resultMessage;
+ LDAPMessage *entryMessage;
+
+ Tcl_Obj *resultObj;
+ int lderrno;
+
+ resultObj = Tcl_GetObjResult (interp);
+
+ sprintf(filter, filtpatt, value);
+
+ if ((msgid = ldap_search (ldap, base, scope, filter, attrs, 0)) == -1) {
+ Tcl_AppendStringsToObj (resultObj,
+ "LDAP start search error: ",
+ LDAP_ERR_STRING(ldap),
+ (char *)NULL);
+ LDAP_SetErrorCode(ldaptcl, -1, interp);
+ return TCL_ERROR;
+ }
+
+ abandon = 0;
+ while ((resultCode = ldap_result (ldap,
+ msgid,
+ 0,
+ timeout_p,
+ &resultMessage)) == LDAP_RES_SEARCH_ENTRY) {
+
+ entryMessage = ldap_first_entry(ldap, resultMessage);
+
+ tclResult = LDAP_ProcessOneSearchResult (interp,
+ ldap,
+ entryMessage,
+ destArrayNameObj,
+ evalCodeObj);
+ ldap_msgfree(resultMessage);
+ if (tclResult != TCL_OK) {
+ if (tclResult == TCL_CONTINUE) {
+ tclResult = TCL_OK;
+ } else if (tclResult == TCL_BREAK) {
+ tclResult = TCL_OK;
+ abandon = 1;
+ break;
+ } else if (tclResult == TCL_ERROR) {
+ char msg[100];
+ sprintf(msg, "\n (\"search\" body line %d)",
+ interp->errorLine);
+ Tcl_AddObjErrorInfo(interp, msg, -1);
+ abandon = 1;
+ break;
+ } else {
+ abandon = 1;
+ break;
+ }
+ }
+ }
+ if (abandon || resultCode == 0) {
+ ldap_abandon(ldap, msgid);
+ if (resultCode == 0) {
+ Tcl_SetErrorCode (interp, "TIMEOUT", (char*) NULL);
+ Tcl_SetStringObj (resultObj, "LDAP timeout retrieving results", -1);
+ return TCL_ERROR;
+ }
+ } else {
+ if (resultCode == LDAP_RES_SEARCH_RESULT) {
+ if ((errorCode = ldap_result2error (ldap, resultMessage, 0))
+ != LDAP_SUCCESS) {
+ Tcl_AppendStringsToObj (resultObj,
+ "LDAP search error: ",
+ ldap_err2string(errorCode),
+ (char *)NULL);
+ ldap_msgfree(resultMessage);
+ LDAP_SetErrorCode(ldaptcl, errorCode, interp);
+ return TCL_ERROR;
+ }
+ }
+
+
+ if (resultCode == -1) {
+ Tcl_AppendStringsToObj (resultObj,
+ "LDAP result search error: ",
+ LDAP_ERR_STRING(ldap),
+ (char *)NULL);
+ LDAP_SetErrorCode(ldaptcl, -1, interp);
+ return TCL_ERROR;
+ } else
+ ldap_msgfree(resultMessage);
+ }
+
+ return tclResult;
+}
+
+/*-----------------------------------------------------------------------------
+ * NeoX_LdapTargetObjCmd --
+ *
+ * Implements the body of commands created by Neo_LdapObjCmd.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *-----------------------------------------------------------------------------
+ */
+static int
+NeoX_LdapTargetObjCmd (clientData, interp, objc, objv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ char *command;
+ char *subCommand;
+ LDAPTCL *ldaptcl = (LDAPTCL *)clientData;
+ LDAP *ldap = ldaptcl->ldap;
+ char *dn;
+ int is_add = 0;
+ int is_add_or_modify = 0;
+ int mod_op = 0;
+ char *m, *s, *errmsg;
+ int errcode;
+
+ Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
+
+ if (objc < 2)
+ return TclX_WrongArgs (interp,
+ objv [0],
+ "subcommand [args...]");
+
+ command = Tcl_GetStringFromObj (objv[0], NULL);
+ subCommand = Tcl_GetStringFromObj (objv[1], NULL);
+
+ /* object bind authtype name password */
+ if (STREQU (subCommand, "bind")) {
+ char *binddn;
+ char *passwd;
+ int stringLength;
+ char *ldap_authString;
+ int ldap_authInt;
+
+ if (objc != 5)
+ return TclX_WrongArgs (interp, objv [0], "bind authtype dn passwd");
+
+ ldap_authString = Tcl_GetStringFromObj (objv[2], NULL);
+
+ if (STREQU (ldap_authString, "simple")) {
+ ldap_authInt = LDAP_AUTH_SIMPLE;
+ }
+#ifdef UMICH_LDAP
+ else if (STREQU (ldap_authString, "kerberos_ldap")) {
+ ldap_authInt = LDAP_AUTH_KRBV41;
+ } else if (STREQU (ldap_authString, "kerberos_dsa")) {
+ ldap_authInt = LDAP_AUTH_KRBV42;
+ } else if (STREQU (ldap_authString, "kerberos_both")) {
+ ldap_authInt = LDAP_AUTH_KRBV4;
+ }
+#endif
+ else {
+ Tcl_AppendStringsToObj (resultObj,
+ "\"",
+ command,
+ " ",
+ subCommand,
+#ifdef UMICH_LDAP
+ "\" authtype must be one of \"simple\", ",
+ "\"kerberos_ldap\", \"kerberos_dsa\" ",
+ "or \"kerberos_both\"",
+#else
+ "\" authtype must be \"simple\", ",
+#endif
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ binddn = Tcl_GetStringFromObj (objv[3], &stringLength);
+ if (stringLength == 0)
+ binddn = NULL;
+
+ passwd = Tcl_GetStringFromObj (objv[4], &stringLength);
+ if (stringLength == 0)
+ passwd = NULL;
+
+/* ldap_bind_s(ldap, dn, pw, method) */
+
+#ifdef UMICH_LDAP
+#define LDAP_BIND(ldap, dn, pw, method) \
+ ldap_bind_s(ldap, dn, pw, method)
+#else
+#define LDAP_BIND(ldap, dn, pw, method) \
+ ldap_simple_bind_s(ldap, dn, pw)
+#endif
+ if ((errcode = LDAP_BIND (ldap,
+ binddn,
+ passwd,
+ ldap_authInt)) != LDAP_SUCCESS) {
+
+ Tcl_AppendStringsToObj (resultObj,
+ "LDAP bind error: ",
+ ldap_err2string(errcode),
+ (char *)NULL);
+ LDAP_SetErrorCode(ldaptcl, errcode, interp);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+ }
+
+ if (STREQU (subCommand, "unbind")) {
+ if (objc != 2)
+ return TclX_WrongArgs (interp, objv [0], "unbind");
+
+ return Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], NULL));
+ }
+
+ /* object delete dn */
+ if (STREQU (subCommand, "delete")) {
+ if (objc != 3)
+ return TclX_WrongArgs (interp, objv [0], "delete dn");
+
+ dn = Tcl_GetStringFromObj (objv [2], NULL);
+ if ((errcode = ldap_delete_s(ldap, dn)) != LDAP_SUCCESS) {
+ Tcl_AppendStringsToObj (resultObj,
+ "LDAP delete error: ",
+ ldap_err2string(errcode),
+ (char *)NULL);
+ LDAP_SetErrorCode(ldaptcl, errcode, interp);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+ }
+
+ /* object rename_rdn dn rdn */
+ /* object modify_rdn dn rdn */
+ if (STREQU (subCommand, "rename_rdn") || STREQU (subCommand, "modify_rdn")) {
+ char *rdn;
+ int deleteOldRdn;
+
+ if (objc != 4)
+ return TclX_WrongArgs (interp,
+ objv [0],
+ "delete_rdn|modify_rdn dn rdn");
+
+ dn = Tcl_GetStringFromObj (objv [2], NULL);
+ rdn = Tcl_GetStringFromObj (objv [3], NULL);
+
+ deleteOldRdn = (*subCommand == 'r');
+
+ if ((errcode = ldap_modrdn2_s (ldap, dn, rdn, deleteOldRdn)) != LDAP_SUCCESS) {
+ Tcl_AppendStringsToObj (resultObj,
+ "LDAP ",
+ subCommand,
+ " error: ",
+ ldap_err2string(errcode),
+ (char *)NULL);
+ LDAP_SetErrorCode(ldaptcl, errcode, interp);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+ }
+
+ /* object add dn attributePairList */
+ /* object add_attributes dn attributePairList */
+ /* object replace_attributes dn attributePairList */
+ /* object delete_attributes dn attributePairList */
+
+ if (STREQU (subCommand, "add")) {
+ is_add = 1;
+ is_add_or_modify = 1;
+ } else {
+ is_add = 0;
+ if (STREQU (subCommand, "add_attributes")) {
+ is_add_or_modify = 1;
+ mod_op = LDAP_MOD_ADD;
+ } else if (STREQU (subCommand, "replace_attributes")) {
+ is_add_or_modify = 1;
+ mod_op = LDAP_MOD_REPLACE;
+ } else if (STREQU (subCommand, "delete_attributes")) {
+ is_add_or_modify = 1;
+ mod_op = LDAP_MOD_DELETE;
+ }
+ }
+
+ if (is_add_or_modify) {
+ int result;
+ LDAPMod **modArray;
+ LDAPMod *mod;
+ char **valPtrs = NULL;
+ int attribObjc;
+ Tcl_Obj **attribObjv;
+ int valuesObjc;
+ Tcl_Obj **valuesObjv;
+ int nPairs;
+ int i;
+ int j;
+
+ Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
+
+ if (objc != 4) {
+ Tcl_AppendStringsToObj (resultObj,
+ "wrong # args: ",
+ Tcl_GetStringFromObj (objv [0], NULL),
+ " ",
+ subCommand,
+ " dn attributePairList",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ dn = Tcl_GetStringFromObj (objv [2], NULL);
+
+ if (Tcl_ListObjGetElements (interp, objv [3], &attribObjc, &attribObjv)
+ == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ if (attribObjc & 1) {
+ Tcl_AppendStringsToObj (resultObj,
+ "attribute list does not contain an ",
+ "even number of key-value elements",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ nPairs = attribObjc / 2;
+
+ modArray = (LDAPMod **)ckalloc (sizeof(LDAPMod *) * (nPairs + 1));
+ modArray[nPairs] = (LDAPMod *) NULL;
+
+ for (i = 0; i < nPairs; i++) {
+ mod = modArray[i] = (LDAPMod *) ckalloc (sizeof(LDAPMod));
+ mod->mod_op = mod_op;
+ mod->mod_type = Tcl_GetStringFromObj (attribObjv [i * 2], NULL);
+
+ if (Tcl_ListObjGetElements (interp, attribObjv [i * 2 + 1], &valuesObjc, &valuesObjv) == TCL_ERROR) {
+ /* FIX: cleanup memory here */
+ return TCL_ERROR;
+ }
+
+ valPtrs = mod->mod_vals.modv_strvals = \
+ (char **)ckalloc (sizeof (char *) * (valuesObjc + 1));
+ valPtrs[valuesObjc] = (char *)NULL;
+
+ for (j = 0; j < valuesObjc; j++) {
+ valPtrs [j] = Tcl_GetStringFromObj (valuesObjv[j], NULL);
+
+ /* If it's "delete" and value is an empty string, make
+ * value be NULL to indicate entire attribute is to be
+ * deleted */
+ if ((*valPtrs [j] == '\0')
+ && (mod->mod_op == LDAP_MOD_DELETE)) {
+ valPtrs [j] = NULL;
+ }
+ }
+ }
+
+ if (is_add) {
+ result = ldap_add_s (ldap, dn, modArray);
+ } else {
+ result = ldap_modify_s (ldap, dn, modArray);
+ }
+
+ /* free the modArray elements, then the modArray itself. */
+ for (i = 0; i < nPairs; i++) {
+ ckfree ((char *) modArray[i]->mod_vals.modv_strvals);
+ ckfree ((char *) modArray[i]);
+ }
+ ckfree ((char *) modArray);
+
+ /* FIX: memory cleanup required all over the place here */
+ if (result != LDAP_SUCCESS) {
+ Tcl_AppendStringsToObj (resultObj,
+ "LDAP ",
+ subCommand,
+ " error: ",
+ ldap_err2string(result),
+ (char *)NULL);
+ LDAP_SetErrorCode(ldaptcl, result, interp);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+ }
+
+ /* object search controlArray dn pattern */
+ if (STREQU (subCommand, "search")) {
+ char *controlArrayName;
+ Tcl_Obj *controlArrayNameObj;
+
+ char *scopeString;
+ int scope;
+
+ char *derefString;
+ int deref;
+
+ char *baseString;
+
+ char **attributesArray;
+ char *attributesString;
+ int attributesArgc;
+
+ char *filterPatternString;
+
+ char *timeoutString;
+ double timeoutTime;
+ struct timeval timeout, *timeout_p;
+
+ Tcl_Obj *destArrayNameObj;
+ Tcl_Obj *evalCodeObj;
+
+ if (objc != 5)
+ return TclX_WrongArgs (interp,
+ objv [0],
+ "search controlArray destArray code");
+
+ controlArrayNameObj = objv [2];
+ controlArrayName = Tcl_GetStringFromObj (controlArrayNameObj, NULL);
+
+ destArrayNameObj = objv [3];
+
+ evalCodeObj = objv [4];
+
+ baseString = Tcl_GetVar2 (interp,
+ controlArrayName,
+ "base",
+ 0);
+
+ if (baseString == (char *)NULL) {
+ Tcl_AppendStringsToObj (resultObj,
+ "required element \"base\" ",
+ "is missing from ldap control array \"",
+ controlArrayName,
+ "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ filterPatternString = Tcl_GetVar2 (interp,
+ controlArrayName,
+ "filter",
+ 0);
+ if (filterPatternString == (char *)NULL) {
+ filterPatternString = "objectclass=*";
+ }
+
+ /* Fetch scope setting from control array.
+ * If it doesn't exist, default to subtree scoping.
+ */
+ scopeString = Tcl_GetVar2 (interp, controlArrayName, "scope", 0);
+ if (scopeString == NULL) {
+ scope = LDAP_SCOPE_SUBTREE;
+ } else {
+ if (STREQU(scopeString, "base"))
+ scope = LDAP_SCOPE_BASE;
+ else if (STRNEQU(scopeString, "one", 3))
+ scope = LDAP_SCOPE_ONELEVEL;
+ else if (STRNEQU(scopeString, "sub", 3))
+ scope = LDAP_SCOPE_SUBTREE;
+ else {
+ Tcl_AppendStringsToObj (resultObj,
+ "\"scope\" element of \"",
+ controlArrayName,
+ "\" array is not one of ",
+ "\"base\", \"onelevel\", ",
+ "or \"subtree\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /* Fetch dereference control setting from control array.
+ * If it doesn't exist, default to never dereference. */
+ derefString = Tcl_GetVar2 (interp,
+ controlArrayName,
+ "deref",
+ 0);
+
+ if (derefString == (char *)NULL) {
+ deref = LDAP_DEREF_NEVER;
+ } else {
+ if (STREQU(derefString, "never"))
+ deref = LDAP_DEREF_NEVER;
+ else if (STREQU(derefString, "search"))
+ deref = LDAP_DEREF_SEARCHING;
+ else if (STREQU(derefString, "find") == 0)
+ deref = LDAP_DEREF_FINDING;
+ else if (STREQU(derefString, "always"))
+ deref = LDAP_DEREF_ALWAYS;
+ else {
+ Tcl_AppendStringsToObj (resultObj,
+ "\"deref\" element of \"",
+ controlArrayName,
+ "\" array is not one of ",
+ "\"never\", \"search\", \"find\", ",
+ "or \"always\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /* Fetch list of attribute names from control array.
+ * If entry doesn't exist, default to NULL (all).
+ */
+ attributesString = Tcl_GetVar2 (interp,
+ controlArrayName,
+ "attributes",
+ 0);
+ if (attributesString == (char *)NULL) {
+ attributesArray = NULL;
+ } else {
+ if ((Tcl_SplitList (interp,
+ attributesString,
+ &attributesArgc,
+ &attributesArray)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ /* Fetch timeout value if there is one
+ */
+ timeoutString = Tcl_GetVar2 (interp,
+ controlArrayName,
+ "timeout",
+ 0);
+ timeout.tv_usec = 0;
+ if (timeoutString == (char *)NULL) {
+ timeout_p = NULL;
+ timeout.tv_sec = 0;
+ } else {
+ if (Tcl_GetDouble(interp, timeoutString, &timeoutTime) != TCL_OK)
+ return TCL_ERROR;
+ timeout.tv_sec = floor(timeoutTime);
+ timeout.tv_usec = (timeoutTime-timeout.tv_sec) * 1000000;
+ timeout_p = &timeout;
+ }
+
+#ifdef UMICH_LDAP
+ ldap->ld_deref = deref;
+ ldap->ld_timelimit = 0;
+ ldap->ld_sizelimit = 0;
+ ldap->ld_options = 0;
+#endif
+
+ return LDAP_PerformSearch (interp,
+ ldaptcl,
+ baseString,
+ scope,
+ attributesArray,
+ filterPatternString,
+ "",
+ destArrayNameObj,
+ evalCodeObj,
+ timeout_p);
+ }
+
+#if defined(UMICH_LDAP) || (defined(OPEN_LDAP) && !defined(LDAP_API_VERSION))
+ if (STREQU (subCommand, "cache")) {
+ char *cacheCommand;
+
+ if (objc < 3)
+ badargs:
+ return TclX_WrongArgs (interp,
+ objv [0],
+ "cache command [args...]");
+
+ cacheCommand = Tcl_GetStringFromObj (objv [2], NULL);
+
+ if (STREQU (cacheCommand, "uncache")) {
+ char *dn;
+
+ if (objc != 4)
+ return TclX_WrongArgs (interp,
+ objv [0],
+ "cache uncache dn");
+
+ dn = Tcl_GetStringFromObj (objv [3], NULL);
+ ldap_uncache_entry (ldap, dn);
+ return TCL_OK;
+ }
+
+ if (STREQU (cacheCommand, "enable")) {
+ long timeout;
+ long maxmem;
+
+ if (objc != 5)
+ return TclX_WrongArgs (interp,
+ objv [0],
+ "cache enable timeout maxmem");
+
+ if (Tcl_GetLongFromObj (interp, objv [3], &timeout) == TCL_ERROR)
+ return TCL_ERROR;
+
+ if (Tcl_GetLongFromObj (interp, objv [4], &maxmem) == TCL_ERROR)
+ return TCL_ERROR;
+
+ if (ldap_enable_cache (ldap, timeout, maxmem) == -1) {
+ Tcl_AppendStringsToObj (resultObj,
+ "LDAP cache enable error: ",
+ LDAP_ERR_STRING(ldap),
+ (char *)NULL);
+ LDAP_SetErrorCode(ldaptcl, -1, interp);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+ }
+
+ if (objc != 3) goto badargs;
+
+ if (STREQU (cacheCommand, "disable")) {
+ ldap_disable_cache (ldap);
+ return TCL_OK;
+ }
+
+ if (STREQU (cacheCommand, "destroy")) {
+ ldap_destroy_cache (ldap);
+ return TCL_OK;
+ }
+
+ if (STREQU (cacheCommand, "flush")) {
+ ldap_flush_cache (ldap);
+ return TCL_OK;
+ }
+
+ if (STREQU (cacheCommand, "no_errors")) {
+ ldap_set_cache_options (ldap, LDAP_CACHE_OPT_CACHENOERRS);
+ return TCL_OK;
+ }
+
+ if (STREQU (cacheCommand, "all_errors")) {
+ ldap_set_cache_options (ldap, LDAP_CACHE_OPT_CACHEALLERRS);
+ return TCL_OK;
+ }
+
+ if (STREQU (cacheCommand, "size_errors")) {
+ ldap_set_cache_options (ldap, 0);
+ return TCL_OK;
+ }
+ Tcl_AppendStringsToObj (resultObj,
+ "\"",
+ command,
+ " ",
+ subCommand,
+ "\" subcommand",
+ " must be one of \"enable\", ",
+ "\"disable\", ",
+ "\"destroy\", \"flush\", \"uncache\", ",
+ "\"no_errors\", \"size_errors\",",
+ " or \"all_errors\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+#endif
+#ifdef LDAP_DEBUG
+ if (STREQU (subCommand, "debug")) {
+ if (objc != 3) {
+ Tcl_AppendStringsToObj(resultObj, "Wrong # of arguments",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ return Tcl_GetIntFromObj(interp, objv[2], &ldap_debug);
+ }
+#endif
+
+ /* FIX: this needs to enumerate all the possibilities */
+ Tcl_AppendStringsToObj (resultObj,
+ "subcommand \"",
+ subCommand,
+ "\" must be one of \"add\", ",
+ "\"add_attributes\", ",
+ "\"bind\", \"cache\", \"delete\", ",
+ "\"delete_attributes\", \"modify\", ",
+ "\"modify_rdn\", \"rename_rdn\", ",
+ "\"replace_attributes\", ",
+ "\"search\" or \"unbind\".",
+ (char *)NULL);
+ return TCL_ERROR;
+}
+
+/*
+ * Delete and LDAP command object
+ *
+ */
+static void
+NeoX_LdapObjDeleteCmd(clientData)
+ ClientData clientData;
+{
+ LDAPTCL *ldaptcl = (LDAPTCL *)clientData;
+ LDAP *ldap = ldaptcl->ldap;
+
+ ldap_unbind(ldap);
+ ckfree((char*) ldaptcl);
+}
+
+/*-----------------------------------------------------------------------------
+ * NeoX_LdapObjCmd --
+ *
+ * Implements the `ldap' command:
+ * ldap open newObjName host [port]
+ * ldap init newObjName host [port]
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *-----------------------------------------------------------------------------
+ */
+static int
+NeoX_LdapObjCmd (clientData, interp, objc, objv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ extern int errno;
+ char *subCommand;
+ char *newCommand;
+ char *ldapHost;
+ int ldapPort = 389;
+ LDAP *ldap;
+ LDAPTCL *ldaptcl;
+
+ Tcl_Obj *resultObj = Tcl_GetObjResult (interp);
+
+ if (objc < 3 || objc > 5)
+ return TclX_WrongArgs (interp, objv [0],
+ "(open|init) new_command host [port]|explode dn");
+
+ subCommand = Tcl_GetStringFromObj (objv[1], NULL);
+
+ if (STREQU(subCommand, "explode")) {
+ char *param;
+ int nonames = 0;
+ int list = 0;
+ char **exploded, **p;
+
+ param = Tcl_GetStringFromObj (objv[2], NULL);
+ if (param[0] == '-') {
+ if (STREQU(param, "-nonames")) {
+ nonames = 1;
+ } else if (STREQU(param, "-list")) {
+ list = 1;
+ } else {
+ return TclX_WrongArgs (interp, objv [0], "explode ?-nonames|-list? dn");
+ }
+ }
+ if (nonames || list)
+ param = Tcl_GetStringFromObj (objv[3], NULL);
+ exploded = ldap_explode_dn(param, nonames);
+ for (p = exploded; *p; p++) {
+ if (list) {
+ char *q = strchr(*p, '=');
+ if (!q) {
+ Tcl_SetObjLength(resultObj, 0);
+ Tcl_AppendStringsToObj(resultObj, "rdn ", *p,
+ " missing '='", NULL);
+ ldap_value_free(exploded);
+ return TCL_ERROR;
+ }
+ *q = '\0';
+ if (Tcl_ListObjAppendElement(interp, resultObj,
+ Tcl_NewStringObj(*p, -1)) != TCL_OK ||
+ Tcl_ListObjAppendElement(interp, resultObj,
+ Tcl_NewStringObj(q+1, -1)) != TCL_OK) {
+ ldap_value_free(exploded);
+ return TCL_ERROR;
+ }
+ } else {
+ if (Tcl_ListObjAppendElement(interp, resultObj,
+ Tcl_NewStringObj(*p, -1))) {
+ ldap_value_free(exploded);
+ return TCL_ERROR;
+ }
+ }
+ }
+ ldap_value_free(exploded);
+ return TCL_OK;
+ }
+
+#ifdef UMICH_LDAP
+ if (STREQU(subCommand, "friendly")) {
+ char *friendly = ldap_dn2ufn(Tcl_GetStringFromObj(objv[2], NULL));
+ Tcl_SetStringObj(resultObj, friendly, -1);
+ free(friendly);
+ return TCL_OK;
+ }
+#endif
+
+ newCommand = Tcl_GetStringFromObj (objv[2], NULL);
+ ldapHost = Tcl_GetStringFromObj (objv[3], NULL);
+
+ if (objc == 5) {
+ if (Tcl_GetIntFromObj (interp, objv [4], &ldapPort) == TCL_ERROR) {
+ Tcl_AppendStringsToObj (resultObj,
+ "LDAP port number is non-numeric",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (STREQU (subCommand, "open")) {
+ ldap = ldap_open (ldapHost, ldapPort);
+ } else if (STREQU (subCommand, "init")) {
+ ldap = ldap_init (ldapHost, ldapPort);
+ } else {
+ Tcl_AppendStringsToObj (resultObj,
+ "option was not \"open\" or \"init\"");
+ return TCL_ERROR;
+ }
+
+ if (ldap == (LDAP *)NULL) {
+ Tcl_SetErrno(errno);
+ Tcl_AppendStringsToObj (resultObj,
+ Tcl_PosixError (interp),
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+#if UMICH_LDAP
+ ldap->ld_deref = LDAP_DEREF_NEVER; /* Turn off alias dereferencing */
+#endif
+
+ ldaptcl = (LDAPTCL *) ckalloc(sizeof(LDAPTCL));
+ ldaptcl->ldap = ldap;
+ ldaptcl->flags = 0;
+
+ Tcl_CreateObjCommand (interp,
+ newCommand,
+ NeoX_LdapTargetObjCmd,
+ (ClientData) ldaptcl,
+ NeoX_LdapObjDeleteCmd);
+ return TCL_OK;
+}
+
+/*-----------------------------------------------------------------------------
+ * Neo_initLDAP --
+ * Initialize the LDAP interface.
+ *-----------------------------------------------------------------------------
+ */
+int
+Ldaptcl_Init (interp)
+Tcl_Interp *interp;
+{
+ Tcl_CreateObjCommand (interp,
+ "ldap",
+ NeoX_LdapObjCmd,
+ (ClientData) NULL,
+ (Tcl_CmdDeleteProc*) NULL);
+ Tcl_PkgProvide(interp, "Ldaptcl", VERSION);
+ return TCL_OK;
+}
--- /dev/null
+PROGRAMS= saucer
+
+SRCS= main.c
+OBJS= main.o
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+READLINE_LIBS = @READLINE_LIBS@
+
+XLIBS = -lldap -llber -llutil
+XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS) $(READLINE_LIBS) $(TERMCAP_LIBS)
+
+MANDIR=$(mandir)/man1
+
+saucer: ${OBJS} $(LDAP_LIBDEPEND)
+ $(LTLINK) -o $@ $(OBJS) $(LIBS)
+
+install-local: $(PROGRAMS) FORCE
+ -$(MKDIR) $(bindir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 saucer $(bindir)
+ -test -d $(MANDIR) || $(MKDIR) $(mandir) $(MANDIR)
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/saucer.1 $(MANDIR)/saucer.1
* 'saucer' LDAP command-line client source code.
*
* Author: Eric Rosenquist, 1994.
+ *
+ * 07-Mar-1999 readline support added: O. Steffensen (oddbjorn@tricknology.org)
*/
-#include <ctype.h>
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
+
+#include <ac/stdlib.h>
+
+#ifdef HAVE_READLINE
+# include <readline/readline.h>
+# ifdef HAVE_READLINE_HISTORY_H
+# include <readline/history.h>
+# endif
+#endif
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
#include <lber.h>
#include <ldap.h>
+#include <ldap_log.h>
#define DN_MAXLEN 4096
typedef struct {
- char *cmd;
- int (*func)();
- char *help_msg;
+ const char *cmd;
+ int (*func) (char **, int);
+ const char *help_msg;
} CMDTABLE;
typedef enum {
int cmd_search(char **cmdargv, int cmdargc);
int cmd_set(char **cmdargv, int cmdargc);
int cmd_show(char **cmdargv, int cmdargc);
+
+int bind_user(void);
+void display_search_results(LDAPMessage *result);
+int do_command(char *cmd);
+void do_commands(FILE *file);
+int is_whitespace(register char *s);
char *make_dn(char *dn, int relative);
+void show_syntax(unsigned int cmdnum);
char *skip_to_char(register char *s, register int c);
char *skip_to_whitespace(register char *s);
char *skip_whitespace(register char *s);
+int table_lookup(const char *, const char *const *, int);
FILE *user_tailor(void);
-static char *binary_attrs[] = { "audio", "jpegPhoto", "personalSignature", "photo" };
+static const char *const binary_attrs[] = {
+ "audio", "jpegPhoto", "personalSignature", "photo"
+};
-CMDTABLE cmdtable[] = {
+const CMDTABLE cmdtable[] = {
"help" , cmd_help , "[command]",
"list" , cmd_list , "[RDN-or-DN] [-absolute]",
"moveto", cmd_moveto, "[RDN-or-DN] [-absolute]",
int cmd_help(char **cmdargv, int cmdargc)
{
- int i;
+ unsigned int i;
if (cmdargc == 2) {
for (i = 0; i < sizeof(cmdtable) / sizeof(cmdtable[0]); i++)
char *dn = NULL;
int errflag = 0;
int i;
- static char *opts[] = { "absolute" };
+ static const char *const opts[] = { "absolute" };
int relative = 1;
LDAPMessage *result;
int errflag = 0;
char **exploded_dn;
int i;
- static char *opts[] = { "absolute" };
+ static const char *const opts[] = { "absolute" };
int relative = 1;
for (i = 1; i < cmdargc; i++) {
int errflag = 0;
char *filter = NULL;
int i, j;
- static char *opts[] = { "absolute", "object", "scope" };
+ static const char *const opts[] = { "absolute", "object", "scope" };
int relative = 1;
LDAPMessage *result;
- static char *scope_opts[] = { "base", "onelevel", "subtree" };
- static int scope_vals[] = { LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE };
+ static const char *const scope_opts[]= { "base","onelevel","subtree" };
+ static const int scope_vals[] = { LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE };
static int search_scope = LDAP_SCOPE_ONELEVEL;
for (i = 1; i < cmdargc; i++) {
int cmd_set(char **cmdargv, int cmdargc)
{
- static char *alias_opts[] = { "never", "search", "find", "always" };
+ static const char *const alias_opts[] = {
+ "never", "search", "find", "always"
+ };
int errflag = 0;
int i, j;
- static char *opts[] = { "aliasderef", "sizelimit", "timelimit" };
+ static const char *const opts[] = {
+ "aliasderef", "sizelimit", "timelimit"
+ };
for (i = 1; i < cmdargc; i++) {
if (cmdargv[i][0] == '-') {
case 0:
if ((++i < cmdargc) &&
(j = table_lookup(cmdargv[i], alias_opts, sizeof(alias_opts) / sizeof(alias_opts[0]))) >= 0)
- ld->ld_deref = j;
+ ldap_set_option(ld, LDAP_OPT_DEREF, &j);
else
errflag = 1;
break;
case 1:
- if (++i < cmdargc)
- ld->ld_sizelimit = atoi(cmdargv[i]);
- else
+ if (++i < cmdargc) {
+ j = atoi(cmdargv[i]);
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &j);
+ } else
errflag = 1;
break;
case 2:
- if (++i < cmdargc)
- ld->ld_timelimit = atoi(cmdargv[i]);
- else
+ if (++i < cmdargc) {
+ j = atoi(cmdargv[i]);
+ ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &j);
+ } else
errflag = 1;
break;
default:
if (errflag)
show_syntax(CMD_SET);
- else
+ else {
+ int opt_a, opt_s, opt_t;
+ ldap_get_option(ld, LDAP_OPT_DEREF, &opt_a);
+ ldap_get_option(ld, LDAP_OPT_SIZELIMIT, &opt_s);
+ ldap_get_option(ld, LDAP_OPT_TIMELIMIT, &opt_t);
printf("Alias dereferencing is %s, Sizelimit is %d entr%s, Timelimit is %d second%s.\n",
- alias_opts[ld->ld_deref],
- ld->ld_sizelimit, ld->ld_sizelimit == 1 ? "y" : "ies",
- ld->ld_timelimit, ld->ld_timelimit == 1 ? "" : "s");
+ alias_opts[opt_a],
+ opt_s, opt_s == 1 ? "y" : "ies",
+ opt_t, opt_t == 1 ? "" : "s");
+ }
return 0;
}
int cmd_show(char **cmdargv, int cmdargc)
{
char *dn = NULL;
- LDAPMessage *entry;
int errflag = 0;
int i;
- static char *opts[] = { "absolute" };
+ static const char *const opts[] = { "absolute" };
int relative = 1;
LDAPMessage *result;
return 0;
}
-display_search_results(LDAPMessage *result)
+void display_search_results(LDAPMessage *result)
{
BerElement *cookie;
int i;
for (entry = ldap_first_entry(ld, result); entry; entry = ldap_next_entry(ld, entry)) {
if (s = ldap_get_dn(ld, entry)) {
printf(" %s\n", s);
- free(s);
+ ldap_memfree(s);
}
/* Make one pass to calculate the length of the longest attribute name */
{
char cmd_buf[BUFSIZ];
int tty = isatty(fileno(file));
+ char *buf = cmd_buf;
+ int status;
for (;;) {
if (tty)
- printf("Cmd? ");
- if (!fgets(cmd_buf, sizeof(cmd_buf), file))
- break;
- if (do_command(cmd_buf))
+ {
+ char prompt[40];
+ sprintf(prompt, (strlen(default_dn) < 18
+ ? "saucer dn=%s> "
+ : "saucer dn=%.15s..> "), default_dn);
+#ifndef HAVE_READLINE
+ fputs (prompt, stdout);
+#else
+ buf = readline (prompt);
+ if (!buf)
+ break;
+ add_history (buf);
+#endif
+ }
+#ifdef HAVE_READLINE
+ else
+#endif
+ {
+ if (!fgets(cmd_buf, sizeof(cmd_buf), file))
+ break;
+ }
+
+ status = do_command(buf);
+#ifdef HAVE_READLINE
+ if (tty)
+ free(buf);
+#endif
+ if (status)
break;
}
}
if (!s)
return 1;
- while (*s && isspace(*s))
+ while (*s && isspace((unsigned char) *s))
++s;
return !*s;
int main(int argc, char **argv)
{
int error_flag = 0;
+ int tmp;
FILE *rc;
progname = argv[0];
break;
case 'd':
#ifdef LDAP_DEBUG
- lber_debug = atoi(optarg);
- ldap_debug = atoi(optarg);
+ tmp = atoi(optarg);
+ ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &tmp);
+ ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &tmp);
#endif
break;
case 'h':
if (error_flag) {
fprintf(stderr, "usage: %s [-h host] [-p portnumber] [-u X500UserName]\n\t[-c credentials] [-d debug-level]\n",
progname);
- exit(2);
+ exit( EXIT_FAILURE );
}
rc = user_tailor();
- if (!(ld = ldap_open(hostname, portnum))) {
- fprintf(stderr, "%s: unable to connect to server at host `%s' on port %d\n",
+ if (!(ld = ldap_init(hostname, portnum))) {
+ fprintf(stderr, "%s: unable to initialize LDAP session (%s:%d)\n",
progname, hostname, portnum);
- exit(2);
+ exit( EXIT_FAILURE );
}
if (!bind_user())
char *make_dn(char *dn, int relative)
{
static char dn_buf[DN_MAXLEN];
- char *s;
if (!dn)
dn = "";
return strcat(strcat(strcpy(dn_buf, dn), ", "), default_dn);
}
-show_syntax(int cmdnum)
+void show_syntax(unsigned int cmdnum)
{
printf("Syntax: %s %s\n", cmdtable[cmdnum].cmd, cmdtable[cmdnum].help_msg);
}
if (!s)
return s;
- while (*s && !isspace(*s))
+ while (*s && !isspace((unsigned char) *s))
++s;
return s;
if (!s)
return s;
- while (*s && isspace(*s))
+ while (*s && isspace((unsigned char) *s))
++s;
return s;
}
-int table_lookup(char *word, char **table, int table_count)
+int table_lookup(const char *word, const char *const *table, int table_count)
{
register int i;
int wordlen;
--- /dev/null
+PROGRAMS= web_ldap
+
+SRCS= web_ldap.c util.c
+OBJS= web_ldap.o util.o
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldap -llber -llutil
+XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
+
+web_ldap: ${OBJS} $(LDAP_LIBDEPEND)
+ $(LTLINK) -o $@ $(OBJS) $(LIBS)
+
+install-local: $(PROGRAMS) FORCE
+ -test -d $(libexecdir) || $(MKDIR) $(libexecdir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 web_ldap $(libexecdir)
+ @echo ">> You must copy and edit web_ldap.cfg and web_ldap.html as needed. <<"
--- /dev/null
+/* web_ldap.c
+ * Form Processing Web application that returns html based
+ * LDAP data with definitions from a configuration file.
+ *
+ * Jens Moller - Dec 11, 1998
+ */
+
+#include "portable.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#include <lber.h>
+#include <ldap.h>
+#include "ldif.h"
+#include "maint_form.h" /* for HTML Form manipulations */
+
+/* default values */
+#ifndef LDAP_PORT
+#define LDAP_PORT 389
+#endif
+#ifndef SERVER
+#define SERVER "ldap.bigfoot.com"
+#endif
+#ifndef CONFIG
+#define CONFIG "web_ldap.cfg"
+#endif
+
+#define MAX_ATTRIB 100
+#define MAX_CHARS 256
+#define version "v 1.1"
+
+entry entries[MAX_ENTRIES];
+
+typedef struct {
+ char servername[MAX_CHARS];
+ char query[MAX_CHARS];
+ char searchbase[MAX_CHARS];
+ char htmlfile[MAX_CHARS];
+ int ldap_port_num;
+ int num_of_attrib;
+ int debug; /* if zero, no debug text displayed */
+} LDAP_INFO;
+
+typedef struct {
+ char title[40];
+} ATTRIB_TITLE;
+
+/* function Prototypes */
+void process_cfg(char *config,
+ LDAP_INFO *ldap_data,
+ char *attribute_array[],
+ ATTRIB_TITLE *disp_attrib);
+
+int strscn(char *istring,
+ char *tstring);
+
+void upcase_string(char *array,
+ char *uparray);
+
+int find_comma(char *array);
+
+int find_colon(char *array);
+
+void squeeze_blanks(char *array);
+
+/* Pass in nothing and use the default config file, or
+ * pass in the config file to use */
+
+main(int argc, char ** argv) {
+ LDAP *ld;
+ LDAPMessage *res, *e;
+ int i, j, cl, x, how_many;
+ char *a, *dn, *value;
+ BerElement *ptr;
+ char **vals;
+ char *read_attrs[MAX_ATTRIB]; /* up to MAX_ATTRIB attribs returned */
+ struct berval **bvals;
+ char attrs_name[MAX_CHARS];
+ char config_file[MAX_CHARS];
+ char temp[MAX_CHARS];
+ char passed_in[MAX_CHARS];
+ LDAP_INFO ldap_data;
+ ATTRIB_TITLE attribute[MAX_ATTRIB];
+ time_t now;
+ FILE *logfp;
+
+
+ /* html initialization */
+ printf("Content-type: text/html\n\n");
+ printf("<html>\n<head>\n<title>Web Ldap Results</title>\n");
+ printf("</head>\n");
+ printf("<body text=\"#000000\" bgcolor=\"#FFFFFF\">\n");
+ printf("<h2>Web LDAP Results</h2>\n");
+
+ /* initialize ldap_data structure */
+ memset(ldap_data.servername,0,MAX_CHARS);
+ memset(ldap_data.query,0,MAX_CHARS);
+ memset(ldap_data.searchbase,0,MAX_CHARS);
+ memset(ldap_data.htmlfile,0,MAX_CHARS);
+ ldap_data.ldap_port_num = 0;
+ ldap_data.num_of_attrib = 0;
+ ldap_data.debug = 0;
+
+ memset(passed_in,0,MAX_CHARS);
+
+ if (argc > 1) { /* interactive mode */
+
+ /* To use in this fashion when run from a Unix command line:
+ *
+ * > web_ldap DEF "cn=j*moller"
+ * > web_ldap DEF cn=jens moller
+ *
+ * NOTE: The quotes are required if a special
+ * character is a part of the LDAP request such
+ * as the asterix (*) in the above example.
+ */
+
+ /* Parameters passed in are
+ *
+ * argv[0] = Program Name (argc = 1)
+ * argv[1] = Config File Name (argc = 2)
+ * argv[2] = Ldap Request (argc => 3)
+ */
+
+ /* do we use a different config file ? */
+ strcpy(config_file, CONFIG);
+
+ if (argc == 2){
+ if ((strcmp(argv[1],"DEF")) == 0) {
+ strcpy(config_file, CONFIG);
+ }
+ else {
+ strcpy(config_file, argv[1]);
+ }
+ }
+
+ /* is there an LDAP request?
+ * if so, it may take up to 3 argv[x] values */
+
+ if (argc >= 3) {
+ if (argc == 3) {
+ strcpy(temp, argv[2]);
+ }
+
+ if (argc == 4) {
+ strcpy(temp, argv[2]);
+ strcat(temp, " ");
+ strcat(temp, argv[3]);
+ }
+
+ if (argc == 5) {
+ strcpy(temp, argv[2]);
+ strcat(temp, " ");
+ strcat(temp, argv[3]);
+ strcat(temp, " ");
+ strcat(temp, argv[4]);
+ }
+
+ j = 0;
+ for (i=0; i<strlen(temp);i++) {
+ if ((temp[i] != '"') &&
+ (temp[i] != '\\')){
+ passed_in[j] = temp[i];
+ j++;
+ }
+ }
+ }
+ }
+ else { /* Non Interactive Mode - read from a form */
+ if (strcompare(getenv("REQUEST_METHOD"),"POST"))
+ {
+ printf("<p>++ Error - This script should be referenced with a METHOD of POST.\n");
+ exit( EXIT_FAILURE );
+ }
+ if (strcompare(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded"))
+ {
+ printf("<p>++ Error - This script can only be used to decode form results. \n");
+ exit( EXIT_FAILURE );
+ }
+ cl = atoi(getenv("CONTENT_LENGTH"));
+
+ for(x=0; cl && (!feof(stdin));x++)
+ {
+ entries[x].val = fmakeword(stdin,'&',&cl);
+ plustospace(entries[x].val);
+ unescape_url(entries[x].val);
+ entries[x].name = makeword(entries[x].val,'=');
+ how_many = x; /* keep track of how many we got */
+
+#ifdef DEBUG_TEXT
+ printf("entries[%d].name=%s - ",x,entries[x].name);
+ printf("entries[%d].val =%s<br>\n",x,entries[x].val);
+#endif
+ }
+
+ entries[x].name = NULL; /* entry after last valid one */
+ entries[x].val = NULL; /* is set to NULL */
+
+ if(!getvalue(entries, "FORM", &value))
+ {
+ printf("%s%s%s", "This script expected a 'FORM' value returned ",
+ "and did not get one. Make sure the HTML used for this ",
+ "script is correct.");
+ exit( EXIT_FAILURE );
+ }
+
+ /* Looking for:
+ * LDAP_REQUEST - actual LDAP request, ie 'cn=j*moller'
+ * CONFIG = Configuration file
+ */
+
+ strcpy(config_file, CONFIG);
+
+ if(getvalue(entries, "LDAP_REQUEST", &value)) {
+ strcpy(passed_in,value);
+ }
+
+ if(getvalue(entries, "CONFIG", &value)) {
+ if ((strcmp("DEF",value)) == 0) {
+ strcpy(config_file, CONFIG);
+ }
+ else {
+ strcpy(config_file, value);
+ }
+ }
+
+ }
+
+ /* zero out the attribute pointers/data area */
+ for (i = 0; i < MAX_ATTRIB; i++) {
+ read_attrs[i] = NULL;
+ memset(attribute[i].title,0,40);
+ }
+
+ /* read in the config file */
+ process_cfg(config_file, &ldap_data, read_attrs, attribute);
+
+ if (passed_in[0] != 0) {
+ strcpy(ldap_data.query,passed_in);
+ }
+
+ if (ldap_data.debug != 0) {
+ if ((logfp = fopen("web_ldap.log","w")) == 0) {
+ printf("<font color=red size=5>\n");
+ printf("<p>Unable to open requested log file: web_ldap.log<p>\n");
+ printf("</font>\n");
+ }
+ else {
+ time(&now);
+ sprintf(temp,"==> web_ldap request made at: %s\n",ctime(&now));
+ fputs(temp,logfp);
+ if (argc > 1) {
+ sprintf(temp," Interactive Unix Command Line Request:\n\n");
+ }
+ else {
+ sprintf(temp," Browser/Form Request:\n\n");
+ }
+ fputs(temp,logfp);
+ sprintf(temp," Server Name: %s\n", ldap_data.servername);
+ fputs(temp,logfp);
+ sprintf(temp," Query: %s\n", ldap_data.query);
+ fputs(temp,logfp);
+ sprintf(temp," Passed In: %s\n", passed_in);
+ fputs(temp,logfp);
+ sprintf(temp," Searchbase: %s\n",ldap_data.searchbase);
+ fputs(temp,logfp);
+ if (ldap_data.htmlfile[0] != 0) {
+ sprintf(temp," HTML File: %s\n",ldap_data.htmlfile);
+ }
+ else {
+ sprintf(temp," HTML File: Non Provided - Use Default Processing\n");
+ }
+ fputs(temp,logfp);
+ sprintf(temp," LDAP Port: %d\n",ldap_data.ldap_port_num);
+ fputs(temp,logfp);
+ sprintf(temp," Number of Attributes: %d\n",ldap_data.num_of_attrib);
+ fputs(temp,logfp);
+ if (ldap_data.num_of_attrib > 0) {
+ for (i = 0; i < ldap_data.num_of_attrib; i++) {
+ sprintf(temp," - %s\n",read_attrs[i]);
+ fputs(temp,logfp);
+ }
+ }
+
+ sprintf(temp,"\n==< Process Arguments: %d >==\n\n argv[0]: %s\n",
+ argc, argv[0]);
+ fputs(temp,logfp);
+ if (argc >= 2) {
+ sprintf(temp," argv[1]: %s\n",argv[1]);
+ fputs(temp,logfp);
+ }
+ if (argc >= 3) {
+ sprintf(temp," argv[2]: %s\n",argv[2]);
+ fputs(temp,logfp);
+ }
+ if (argc >= 4) {
+ sprintf(temp," argv[3]: %s\n",argv[3]);
+ fputs(temp,logfp);
+ }
+ if (argc >= 5) {
+ sprintf(temp," argv[4]: %s\n",argv[4]);
+ fputs(temp,logfp);
+ }
+ fflush(logfp);
+ fclose(logfp);
+ }
+ }
+
+ if (ldap_data.debug != 0) {
+ if ((logfp = fopen("web_ldap.log","a")) == 0) {
+ }
+ else {
+ time(&now);
+ sprintf(temp,"\n==< Results >==\n\n");
+ fputs(temp,logfp);
+ sprintf(temp,"** performing ldap_init at %s\n", ctime(&now));
+ fputs(temp,logfp);
+ fflush(logfp);
+ fclose(logfp);
+ }
+ }
+ if ( (ld = ldap_init(ldap_data.servername, ldap_data.ldap_port_num) ) == NULL)
+ {
+ printf("<font color=red><b>ldap_init error</b></font>\n");
+ if (ldap_data.debug != 0) {
+ if ((logfp = fopen("web_ldap.log","a")) == 0) {
+ }
+ else {
+ sprintf(temp,"++ ldap_init error\n");
+ fputs(temp,logfp);
+ fflush(logfp);
+ fclose(logfp);
+ }
+ }
+ printf("</body>\n</html>\n");
+ exit( EXIT_FAILURE );
+ }
+
+ /*authenticate as nobody */
+ if (ldap_data.debug != 0) {
+ if ((logfp = fopen("web_ldap.log","a")) == 0) {
+ }
+ else {
+ time(&now);
+ sprintf(temp,"** performing ldap_bind_s at %s\n",ctime(&now));
+ fputs(temp,logfp);
+ fflush(logfp);
+ fclose(logfp);
+ }
+ }
+ if(ldap_bind_s(ld, "", "", LDAP_AUTH_SIMPLE) != 0)
+ {
+ printf("<font color=red><b>");
+ ldap_perror (ld, "ldap_simple_bind_s");
+ printf("</b></font>\n");
+
+ if (ldap_data.debug != 0) {
+ if ((logfp = fopen("web_ldap.log","a")) == 0) {
+ }
+ else {
+ sprintf(temp,"++ ldap_bind_s error\n");
+ fputs(temp,logfp);
+ fflush(logfp);
+ fclose(logfp);
+ }
+ }
+ printf("</body>\n</html>\n");
+ exit( EXIT_FAILURE );
+ }
+
+ printf("<b>Directory Lookup Results</b>\n<pre>\n");
+ printf("<hr><p>\n<pre>\n");
+
+ /* Get data */
+ if (ldap_data.debug != 0) {
+ if ((logfp = fopen("web_ldap.log","a")) == 0) {
+ }
+ else {
+ time(&now);
+ sprintf(temp,"** performing ldap_search_s at %s\n",ctime(&now));
+ fputs(temp,logfp);
+ fflush(logfp);
+ fclose(logfp);
+ }
+ }
+ if(ldap_search_s(ld, ldap_data.searchbase, LDAP_SCOPE_SUBTREE,
+ ldap_data.query, read_attrs, 0, &res)
+ != LDAP_SUCCESS)
+ {
+ ldap_perror(ld, "ldap_search_s");
+ }
+
+ for (e=ldap_first_entry(ld, res); e != NULL; e=ldap_next_entry(ld, e))
+ {
+ dn = ldap_get_dn(ld, e);
+
+ if (ldap_data.debug != 0) {
+ if ((logfp = fopen("web_ldap.log","a")) == 0) {
+ }
+ else {
+ sprintf(temp," dn=%s\n", dn);
+ fputs(temp,logfp);
+ fflush(logfp);
+ fclose(logfp);
+ }
+ }
+
+ /*print each attribute */
+ for (a = ldap_first_attribute(ld, e, &ptr);
+ a != NULL;
+ a = ldap_next_attribute(ld, e, ptr) )
+ {
+ strcpy(attrs_name, a);
+ /* print attribute name */
+ printf("%s: ", attrs_name);
+
+ /*print each value */
+
+ vals = ldap_get_values(ld, e, a);
+
+ for(i=0; vals[i] != NULL; i++)
+ /* print value of attribute */
+ printf("%s\n", vals[i],strlen(vals[i]));
+
+ ldap_value_free(vals);
+ } /*end for*/
+ free(a);
+ free(dn);
+ printf("<p>\n");
+ }
+ /*free the search results */
+ ldap_msgfree (res);
+
+ printf("</pre>\n");
+
+ ldap_unbind(ld);
+
+ if (ldap_data.debug != 0) {
+ if ((logfp = fopen("web_ldap.log","a")) == 0) {
+ }
+ else {
+ time(&now);
+ sprintf(temp,"\nFinished gathering results at %s\n",ctime(&now));
+ fputs(temp,logfp);
+ sprintf(temp,"==< Done >==\n");
+ fputs(temp,logfp);
+ fflush(logfp);
+ fclose(logfp);
+ }
+ }
+ printf("</body>\n</html>\n");
+}
+
+/* Process the user passed in configuration file */
+void process_cfg(char *config,
+ LDAP_INFO *ldap_data,
+ char *attribute_array[],
+ ATTRIB_TITLE *disp_attrib) {
+
+ char file_data[1024];
+ char upfile_data[1024];
+ char temp[1024];
+ int lcomma, lcolon, attrib_pos;
+ FILE * fp;
+
+ strcpy(ldap_data->servername,SERVER);
+ ldap_data->ldap_port_num = LDAP_PORT;
+ strcpy(ldap_data->query,"cn=jens*moller");
+
+ /* config file needs to be in the cgi-bin directory */
+ if ((fp = fopen(config,"r")) == 0) {
+ return;
+ }
+
+ attrib_pos = 0;
+
+ for (;;) { /* read until eof */
+ fgets (file_data,1024,fp);
+ if (feof(fp)) break;
+ if (file_data[0] != '#') { /* skip commented lines */
+ upcase_string(file_data,upfile_data);
+
+ /* get the server specific data */
+ if (strscn(upfile_data,"SERVER:") == 0) {
+ lcolon = find_colon(file_data) + 1;
+ lcomma = find_comma(file_data);
+ if (lcomma > 0) {
+ memset(ldap_data->servername,0,MAX_CHARS);
+ strncpy(ldap_data->servername,&file_data[lcolon],
+ lcomma - lcolon);
+ ldap_data->ldap_port_num = atoi(&file_data[lcomma + 1]);
+ }
+ else {
+ strcpy(ldap_data->servername,&file_data[lcolon]);
+ }
+ squeeze_blanks(ldap_data->servername);
+ }
+ else if (strscn(upfile_data,"SEARCHBASE:") == 0) {
+ lcolon = find_colon(file_data) + 1;
+ strcpy(ldap_data->searchbase,&file_data[lcolon]);
+ squeeze_blanks(ldap_data->searchbase);
+ }
+ else if (strscn(upfile_data,"HTMLFILE:") == 0) {
+ lcolon = find_colon(file_data) + 1;
+ strcpy(ldap_data->htmlfile,&file_data[lcolon]);
+ }
+ else if (strscn(upfile_data,"DEBUG:") == 0) {
+ lcolon = find_colon(file_data) + 1;
+ ldap_data->debug = atoi(&file_data[lcolon]);
+ }
+
+ /* get the attribute list */
+ else if ((file_data[0] != ' ') && (file_data[0] != 0)) {
+ memset(temp,0,1024);
+ /* data appears as a comma delimited list, where:
+ *
+ * attrib_name (char),display_length (int)
+ *
+ * (default length = 20 if display_length undefined)
+ *
+ * is how each record is defined */
+ lcomma = find_comma(file_data);
+ if (lcomma < 0) {
+ strcpy(temp,file_data);
+ squeeze_blanks(temp);
+ }
+ else {
+ strncpy(temp,file_data,lcomma);
+ squeeze_blanks(temp);
+ }
+ attribute_array[attrib_pos] = malloc(strlen(temp));
+ strcpy(attribute_array[attrib_pos],temp);
+ attrib_pos++;
+ ldap_data->num_of_attrib = attrib_pos;
+ }
+ }
+ }
+}
+
+/* find character substring matches */
+int strscn(char * istring,
+ char * tstring) {
+ int i, status, icmp, len;
+ status = -1;
+ len = (strlen(istring) + 1) - strlen(tstring);
+ if (len < 1) len = 1;
+ for (i=0;i<len ;i++) {
+ icmp = memcmp(&istring[i],tstring,strlen(tstring));
+ if (icmp == 0) {
+ status = i;
+ break;
+ }
+ }
+ return status;
+}
+
+/* convert the array to uparray, where uparray contains upper
+ * case characters */
+void upcase_string(char *array,
+ char *uparray) {
+ int i;
+ for (i=0; i < strlen(array); i++) {
+ uparray[i] = toupper((unsigned char) array[i]);
+ uparray[i + 1] = 0;
+ }
+ return;
+}
+
+/* return the position of the first comma - ',' - from within a string */
+int find_comma(char *array){
+ int i;
+ for (i = 0; i < strlen(array); i++) {
+ if (array[i] == ',') return(i);
+ }
+ return -1;
+}
+
+/* return the position of the first colon - '.' - from within a string */
+int find_colon(char *array){
+ int i;
+ for (i = 0; i < strlen(array); i++) {
+ if (array[i] == ':') return(i);
+ }
+ return -1;
+}
+
+/* Remove unneeded blanks from a character array. Don't leave
+ * any at the end & throw away any newline characters */
+void squeeze_blanks(char *array){
+ int i, pos, blank;
+ char temp[1024];
+ memset(temp,0,1024);
+
+ pos = 0; /* location within temp array */
+ blank = 0; /* # of blanks written in a row */
+
+ for (i = 0; i < strlen(array); i++) {
+ if (array[i] != ' ') {
+ temp[pos] = array[i];
+ blank = 0;
+ pos++;
+ }
+ else if ((blank == 0) &&
+ (array[i] == ' ') &&
+ (pos != 0)) {
+ temp[pos] = array[i];
+ blank += 1;
+ pos++;
+ }
+ }
+ strcpy(array,temp);
+ if (array[strlen(array) - 1] <= ' ')
+ array[strlen(array) - 1] = 0;
+}
--- /dev/null
+<html>
+<title>web_ldap_usage</title>
+<body text="#000000"
+bgcolor="#FFFFFF">
+
+<h2>web_ldap version 1.1, OpenLDAP variant</h2>
+
+This is an OpenLDAP port of the web_ldap program.
+<p>
+<i>
+The files provided in the file set for 'web_ldap'
+were developed under the GNU General Public License (GPL).
+Under the GPL, the source code is freely-distributed and available
+to the general public. There is no warranty on the software,
+and it does not come with support, however, I would appreciate
+it if you emailed any bug-fixes you create to me
+(<a href="mailto:jens@colomar.com">jens@colomar.com</a>) and
+<a href="mailto:OpenLDAP-its@OpenLDAP.org">OpenLDAP-its@OpenLDAP.org</a>.
+<p>
+All code here is generic ISO C, allowing most Unix compilers
+to generate the required object files and executable images.
+It was tested against an Apache HTTPD server and uses no
+special HTML functionality that does not appear within V 3.x
+versions of Netscapes or Microsofts Web Browsers. The goal was
+to create a starting point example to help people build
+effective interactive HTML based LDAP clients.
+</i>
+<h3>Introduction:</h3>
+
+The 'web_ldap' package is a complete LDAP application that
+provides a functional Web Server Based client. The intent
+is to give you a working example that you can expand upon
+for your own needs. It does not solve a specific problem
+for you, rather it solves a general problem by giving
+you a functional starting point from where to begin your
+development efforts. It runs under Unix.
+<p>
+The application consists of a number of C programs, header
+files, an HTML file with form entry, a configuration file
+and a sample makefile. You will need the LDAP SDK for your
+specific Unix System (both the UofM libraries and Netscape
+libraries - which are also free - have been tested).
+<p>
+The tool allows you to specify that actions taken
+be logged to a file. This provides you a method by which
+you can build out larger applications and see what is happening.
+<p>
+The application can be run interactively (without use of
+a Web Browser) but was intended for use as an HTML LDAP Web
+page application.
+<p>
+One thing to consider when running a program of this nature
+is that there are 2 totally different sets of environments
+involved. The program is written assuming very little in
+the way of file/directory organization. As such it looks for
+files either in the directory it was run from, or where ever
+you have configured your Web Server to look for things.
+<p>
+The C CGI program will attempt to open a default configuration
+file called 'web_ldap.cfg'. If you set the debug mode on
+in the configuration file, it will also attempt to create
+a log file called 'web_ldap.log' in the same directory as
+the 'web_ldap.cfg' files appears in.
+<p>
+The 2 environments are 'Interactive' and 'Web Server'.
+<p>
+When you execute the application from a command line such as:
+<pre>
+ > web_ldap DEF cn=jens moller
+</pre>
+All actions take place in the same directory that the web_ldap
+program resides in. Most people would typically build an
+application of this nature in one of their own directories and
+this would give them Read/Write access to all of the files
+associated with the program. Any file restrictions or capabilities
+that you have will be enabled as part of your session.
+<p>
+This is quite different than when you ask a Web Server to
+execute the program for you. The Web Server is typically
+using the user 'nobody'. This is not you, its a separate
+application user and it may not have access to the same
+files that you have nor the same process capabilities.
+<p>
+When your program executes from a Web Browser, you will
+see something like:
+<pre>
+ http://my.system.com/cgi-bin/web_ldap
+
+</pre>
+displayed by the Web Browser as the URL that its executing.
+The Web Server is executing the program on your behalf.
+File protections normally cause initial problems, possibly
+because the Web Browser doesn't own the files or doesn't
+have execute access. For your initial testing, please set these
+files to full access - ie. 'chmod 777 web_ldap*' - You can
+adjust the file protections once you get everything working.
+If you get errors - start with this simple change.
+
+<h3>Building the application:</h3>
+
+Requires ISO C (your standard OS compiler or GCC should
+work fine).
+<p>
+Under OpenLDAP, you should build with the following commands after
+having configured and built OpenLDAP itself:
+<pre>
+ cd contrib/web_ldap
+ make depend
+ make
+</pre>
+
+<h3>Configuration:</h3>
+
+Its a very simple tool that allows you to make LDAP requests
+to any existing LDAP Directory Server. By default, it
+attempts to connect to 'ldap.bigfoot.com', which is a
+commercial LDAP server on the Internet - usually available
+from anywhere.
+<p>
+To specify a different LDAP server, you could either modify
+the program to default elsewhere, or you could modify the
+existing 'web_ldap.cfg' file, or create another one with
+a different name.
+<p><i>
+NOTE: A '#' in the first column of any line
+in the configuration file is considered a comment.
+</i>
+<p>
+The configuration file allows you specify:
+<pre>
+ server:
+</pre>
+This is the servername. For example:
+<pre>
+ server:ldap.bigfoot.com,389
+</pre>
+connects you up to port 389 on the ldap server 'ldap.bigfoot.com'.
+You can specify one of your own servers here if you desire.
+<p>
+Next you will see:
+<pre>
+ searchbase:
+</pre>
+This is where within a tree you want to start looking. For
+'ldap.bigfoot.com', you would leave this blank and it will
+look in all the trees. For many companies a specific tree
+structure will be defined, and you will want to specify the
+highest point in the tree structure that defines the area that
+you are interested in. For example, if you have a tree that
+starts at 'c=US', and branches at 'o=ABC, c=US' and
+'o=XYZ, c=US', you could specify:
+<pre>
+ searchbase:c=US
+</pre>
+and search both 'o=ABC, c=US' and 'o=XYZ, c=US', or
+if you only wanted to search against 'o=ABC, c=US',
+you could specify:
+<pre>
+ searchbase:o=ABC, c=US
+</pre>
+If you want to turn on a simple Debug mode, you can specify any number
+other than zero for 'debug:'. For example:
+<pre>
+ debug:1
+</pre>
+turns on the Debug logging mode, and
+<pre>
+ debug:0
+</pre>
+turns it off. Debug logging simply creates a file called
+'web_ldap.log' in the same directory that the web_ldap
+executable is located. It flushes everything after each
+event, so if it gets stuck anywhere, you will be able
+to see it. It also time-stamps most of the results, so you
+can get an idea where things are running faster and/or
+slower for different queries.
+<p>
+The remainder of the configuration file is where you list
+the attributes that you are interested in displaying.
+<p>
+You could list parameters (up to 100) like:
+<pre>
+ cn
+ givenname
+ sn
+</pre>
+and that is all it will return. If you don't specify
+anything, it returns everything it finds. if you
+specify an attribute that the directory has never
+heard of (ie. its not a member of any object class
+anyone has defined), that attribute will simply be
+ignored. If you misspell an attribute name and wonder
+why it never gets listed in the results - this might be
+why. If you specify an attribute that some users have and
+others don't, only ones with that attribute will list
+a value for it.
+<p>
+Directory data can be multi-valued. This means that any
+attribute could have multiple values. This application will
+list all the values it finds for any given attribute.
+
+
+<h3>Where to put the files:</h3>
+
+If running this interactively (from a Unix shell prompt),
+all the files can reside in any of your home directories.
+I suggest that you test the application in your home
+directory first.
+<p>
+If running this application from a Web Server, you need
+to find out where the Web Server keeps its cgi applications
+and where it keeps its html applications. This varies
+from operating system to operating system and Web Server
+to Web Server.
+<p>
+Once you have located the cgi-bin (or equivalent) directory,
+put these 2 files there:
+<pre>
+ web_ldap
+ web_ldap.cfg
+</pre>
+then make sure that these files are accessible to the Web
+Server by executing the Unix shell command:
+<pre>
+ > chmod 777 web_ldap*
+</pre>
+Now find the HTML source directory. Copy
+<pre>
+ web_ldap.html
+</pre>
+to this directory. Make sure that this file is accessible to the Web
+Server by executing the Unix shell command:
+<pre>
+ > chmod 777 web_ldap*
+</pre>
+
+<h3>Running the application:</h3>
+
+Test it in your own directory by entering:
+<pre>
+ > web_ldap DEF
+</pre>
+This should connect to 'ldap.bigfoot.com' and try to find a number
+of entries (it does when I try it). You will notice that it
+outputs results in the form of an HTML file - this is what it
+is supposed to do. If you leave out the 'DEF', you will get the
+error:
+<pre>
+<p>++ Error - This script should be referenced with a METHOD of POST.
+</pre>
+as a part of your result with no LDAP data returned.
+<p>
+Interactively, the program assumes that you will always pass it at least
+the name of the Configuration file ('DEF' tells it to use the default
+configuration file). If there is no configuration file, it still will
+find 'ldap.bigfoot.com'.
+<p>
+Once you have it working there, try the version in the HTML directory.
+To do so, enter your WEB Servers URL, the cgi-bin directory reference
+and then the application name, all separated by slashes. For example,
+if your Web Server URL is 'http://my.server.com', then you will want
+to specify the URL:
+<pre>
+ http://my.server.com/cgi-bin/web_ldap
+</pre>
+NOTE: You can only run cgi scripts out of a directory that the Web Server
+allows. It is unlikely that you can execute Web Server CGI applications
+from your own directory.
+<p>
+This will provide a simple Web Based form. It will have 2 user entry
+fields. The first allows you to enter an LDAP request. The second
+allows you to specify a configuration file (it defaults to 'DEF').
+<p>
+Enter a simple LDAP request, such as the ones shown and see if you
+get back a response. You should if connected to 'ldap.bigfoot.com'.
+
+
+<h3>Now that you have it working:</h3>
+
+Feel free to adapt this program to fit your needs. You will need
+to have the 'dn' in order to do updates. It is recovered within
+the program, so you can save it for use once you retrieve it
+(it is listed in the web_ldap.log file of you enable debug mode).
+<p>
+This program does not update anything. The goal was to create a very
+simple and expandable LDAP client and provide the complete source
+code for doing it. To this goal, it is successful. From here
+you should be able to experiment with the interfaces and create
+new functionality to suit your given needs.
+<p>
+This was tested against the UofM V 3.3 LDAP Libraries and the Netscape
+V 1.x and V 3.x SDK under both Irix 6.2 (Silicon Graphics) and
+Solaris 2.6 (Sun). I don't have other hardware or OS's to test
+against here.
+
+
+<h3>Usage Information:</h3>
+
+If you want to find out what attributes are being used, you can enable
+the application to tell you all that it finds. Do this by simply
+not defining any attributes within the configuration file. It will
+list all the attributes it finds. You could create a special configuration
+file specifically for this purpose.
+<p>
+If you are getting fatal errors from your Web Server when you attempt to
+execute a command, please try the same command using interactive mode. Look
+to see if the HTML being generated makes sense or not. If the HTML
+looks good, run it again interactively and pipe the results to a file, then
+attempt to submit the resulting file as the URL. If it works, it is
+likely that the environment you run is different than the one the Web
+server is using - Unix file protections frequently are a cause of these
+problems. If you can't determine what is different, discuss the problem
+with your Unix system administrator - is is likely a resource problem.
+If you add code that causes problems, but you still get a result, try the
+application in interactive mode and verify the HTML being generated. Any
+additional HTML code you add may need to to have proper termination syntax
+(tables are very touchy about this), and you may need to further enhance
+your changes to compensate.
+<p>
+When creating new applications, please test your
+results on both Netscape's Web Browser and Internet
+Explorer. Nothing is more irritating to end users than getting different
+results based on their Web Browser selection.
+<p>
+The Unix Command line will not allow you to pass some characters into
+an application unless you surround the characters or command with quotes.
+Some common examples of executing web_ldap interactively are:
+<pre>
+ > web_ldap DEF "cn=j*moller"
+
+ > web_ldap DEF cn=jens moller
+</pre>
+The command with the '*' in it requires quotes around it. Also note
+that the application only allows the LDAP command to use up to 3 argv
+values. This is as a limitation of the current parsing within the program
+of argc/argv parameters. You could alter the program, or simply put
+quotes around the LDAP request. Enable the debug mode within the
+configuration file if you feel that the application is losing
+arguments to see what its operating against. When operated by the Web Server,
+and passing in FORM data - you won't have this limitation, and you don't
+need quotes.
+<p>
+You can pass hidden fields from the Web Form into the web_ldap program.
+An example is shown with the name of 'FORM' having a value of '300'.
+You can create additional hidden fields, named anything you want them
+to be, with any value you want. These can be used to define existing
+options (such as which configuration file to use), or other options
+that your modified web_ldap.c program may want to have passed to it.
+<p>
+<hr>
+Jens Moller - Jens@colomar.com -
+<a href="http://www.colomar.com">COLOMAR Group</a>.<br>
+
+<a href="http://www.OpenLDAP.org/">OpenLDAP</a> - OpenLDAP-devel@OpenLDAP.org.
--- /dev/null
+web_ldap Version 1.1, OpenLDAP variant
+
+This is an OpenLDAP port of the web_ldap program.
+
+The files provided in the file set for 'web_ldap'
+were developed under the GNU General Public License (GPL).
+Under the GPL, the source code is freely-distributed and available
+to the general public. There is no warranty on the software,
+and it does not come with support, however, I would appreciate
+it if you emailed any bug-fixes you create to me (jens@colomar.com)
+and OpenLDAP-its@OpenLDAP.org.
+
+All code here is generic ISO C, allowing most Unix compilers
+to generate the required object files and executable images.
+It was tested against an Apache HTTPD server and uses no
+special HTML functionality that does not appear within V 3.x
+versions of Netscapes or Microsofts Web Browsers. The goal was
+to create a starting point example to help people build
+effective interactive HTML based LDAP clients.
+
+Introduction:
+
+The 'web_ldap' package is a complete LDAP application that
+provides a functional Web Server Based client. The intent
+is to give you a working example that you can expand upon
+for your own needs. It does not solve a specific problem
+for you, rather it solves a general problem by giving
+you a functional starting point from where to begin your
+development efforts. It runs under Unix.
+
+The application consists of a number of C programs, header
+files, an HTML file with form entry, a configuration file
+and a sample makefile. You will need the LDAP SDK for your
+specific Unix System (both the UofM libraries and Netscape
+libraries - which are also free - have been tested).
+
+The tool allows You to specify that actions taken
+be logged to a file. This provides you a method by which
+you can build out larger applications and see what is happening.
+
+The application can be run interactively (without use of
+a Web Browser) but was intended for use as an HTML LDAP Web
+page application.
+
+One thing to consider when running a program of this nature
+is that there are 2 totally different sets of environments
+involved. The program is written assuming very little in
+the way of file/directory organization. As such it looks for
+files either in the directory it was run from, or where ever
+you have configured your Web Server to look for things.
+
+The C CGI program will attempt to open a default configuration
+file called 'web_ldap.cfg'. If you set the debug mode on
+in the configuration file, it will also attempt to create
+a log file called 'web_ldap.log' in the same directory as
+the 'web_ldap.cfg' files appears in.
+
+The 2 environments are 'Interactive' and 'Web Server'.
+
+When you execute the application from a command line such as:
+
+ > web_ldap DEF cn=jens moller
+
+All actions take place in the same directory that the web_ldap
+program resides in. Most people would typically build an
+application of this nature in one of their own directories and
+this would give them Read/Write access to all of the files
+associated with the program. Any file restrictions or capabilities
+that you have will be enabled as part of your session.
+
+This is quite different than when you ask a Web Server to
+execute the program for you. The Web Server is typically
+using the user 'nobody'. This is not you, its a separate
+application user and it may not have access to the same
+files that you have nor the same process capabilities.
+
+When your program executes from a Web Browser, you will
+see something like:
+
+ http://my.system.com/cgi-bin/web_ldap
+
+displayed by the Web Browser as the URL that its executing.
+The Web Server is executing the program on your behalf.
+File protections normally cause initial problems, possibly
+because the Web Browser doesn't own the files or doesn't
+have execute access. For your initial testing, please set these
+files to full access - ie. 'chmod 777 web_ldap*' - You can
+adjust the file protections once you get everything working.
+If you get errors - start with this simple change.
+
+
+Building the application:
+
+Requires ISO C (your standard OS compiler or GCC should
+work fine).
+
+Under OpenLDAP, you should build with the following commands after having
+configured and built OpenLDAP itself:
+
+ cd contrib/web_ldap
+ make depend
+ make
+
+
+Configuration:
+
+Its a very simple tool that allows you to make LDAP requests
+to any existing LDAP Directory Server. By default, it
+attempts to connect to 'ldap.bigfoot.com', which is a
+commercial LDAP server on the Internet - usually available
+from anywhere.
+
+To specify a different LDAP server, you could either modify
+the program to default elsewhere, or you could modify the
+existing 'web_ldap.cfg' file, or create another one with
+a different name.
+
+NOTE: A '#' in the first column of any line
+in the configuration file is considered a comment.
+
+The configuration file allows you specify:
+
+ server:
+
+This is the servername. For example:
+
+ server:ldap.bigfoot.com,389
+
+connects you up to port 389 on the ldap server 'ldap.bigfoot.com'.
+You can specify one of your own servers here if you desire.
+
+Next you will see:
+
+ searchbase:
+
+This is where within a tree you want to start looking. For
+'ldap.bigfoot.com', you would leave this blank and it will
+look in all the trees. For many companies a specific tree
+structure will be defined, and you will want to specify the
+highest point in the tree structure that defines the area that
+you are interested in. For example, if you have a tree that
+starts at 'c=US', and branches at 'o=ABC, c=US' and
+'o=XYZ, c=US', you could specify:
+
+ searchbase:c=US
+
+and search both 'o=ABC, c=US' and 'o=XYZ, c=US', or
+if you only wanted to search against 'o=ABC, c=US',
+you could specify:
+
+ searchbase:o=ABC, c=US
+
+If you want to turn on a simple Debug mode, you can specify any number
+other than zero for 'debug:'. For example:
+
+ debug:1
+
+turns on the Debug logging mode, and
+
+ debug:0
+
+turns it off. Debug logging simply creates a file called
+'web_ldap.log' in the same directory that the web_ldap
+executable is located. It flushes everything after each
+event, so if it gets stuck anywhere, you will be able
+to see it. It also time-stamps most of the results, so you
+can get an idea where things are running faster and/or
+slower for different queries.
+
+The remainder of the configuration file is where you list
+the attributes that you are interested in displaying.
+
+You could list parameters (up to 100) like:
+
+ cn
+ givenname
+ sn
+
+and that is all it will return. If you don't specify
+anything, it returns everything it finds. if you
+specify an attribute that the directory has never
+heard of (ie. its not a member of any object class
+anyone has defined), that attribute will simply be
+ignored. If you misspell an attribute name and wonder
+why it never gets listed in the results - this might be
+why. If you specify an attribute that some users have and
+others don't, only ones with that attribute will list
+a value for it.
+
+Directory data can be multi-valued. This means that any
+attribute could have multiple values. This application will
+list all the values it finds for any given attribute.
+
+
+Where to put the files:
+
+If running this interactively (from a Unix shell prompt),
+all the files can reside in any of your home directories.
+I suggest that you test the application in your home
+directory first.
+
+If running this application from a Web Server, you need
+to find out where the Web Server keeps its cgi applications
+and where it keeps its html applications. This varies
+from operating system to operating system and Web Server
+to Web Server.
+
+Once you have located the cgi-bin (or equivalent) directory,
+put these 2 files there:
+
+ web_ldap
+ web_ldap.cfg
+
+then make sure that these files are accessible to the Web
+Server by executing the Unix shell command:
+
+ > chmod 777 web_ldap*
+
+Now find the HTML source directory. Copy
+
+ web_ldap.html
+
+to this directory. Make sure that this file is accessible to the Web
+Server by executing the Unix shell command:
+
+ > chmod 777 web_ldap*
+
+
+Running the application:
+
+Test it in your own directory by entering:
+
+ > web_ldap DEF
+
+This should connect to 'ldap.bigfoot.com' and try to find a number
+of entries (it does when I try it). You will notice that it
+outputs results in the form of an HTML file - this is what it
+is supposed to do. If you leave out the 'DEF', you will get the
+error:
+
+<p>++ Error - This script should be referenced with a METHOD of POST.
+
+as a part of your result with no LDAP data returned.
+
+Interactively, the program assumes that you will always pass it at least
+the name of the Configuration file ('DEF' tells it to use the default
+configuration file). If there is no configuration file, it still will
+find 'ldap.bigfoot.com'.
+
+Once you have it working there, try the version in the HTML directory.
+To do so, enter your WEB Servers URL, the cgi-bin directory reference
+and then the application name, all separated by slashes. For example,
+if your Web Server URL is 'http://my.server.com', then you will want
+to specify the URL:
+
+ http://my.server.com/cgi-bin/web_ldap
+
+NOTE: You can only run cgi scripts out of a directory that the Web Server
+allows. It is unlikely that you can execute Web Server CGI applications
+from your own directory.
+
+This will provide a simple Web Based form. It will have 2 user entry
+fields. The first allows you to enter an LDAP request. The second
+allows you to specify a configuration file (it defaults to 'DEF').
+
+Enter a simple LDAP request, such as the ones shown and see if you
+get back a response. You should if connected to 'ldap.bigfoot.com'.
+
+
+Now that you have it working:
+
+Feel free to adapt this program to fit your needs. You will need
+to have the 'dn' in order to do updates. It is recovered within
+the program, so you can save it for use once you retrieve it
+(it is listed in the web_ldap.log file of you enable debug mode).
+
+This program does not update anything. The goal was to create a very
+simple and expandable LDAP client and provide the complete source
+code for doing it. To this goal, it is successful. From here
+you should be able to experiment with the interfaces and create
+new functionality to suit your given needs.
+
+This was tested against the UofM V 3.3 LDAP Libraries and the Netscape
+V 1.x and V 3.x SDK under both Irix 6.2 (Silicon Graphics) and
+Solaris 2.6 (Sun). I don't have other hardware or OS's to test
+against here.
+
+
+Usage Information:
+
+If you want to find out what attributes are being used, you can enable
+the application to tell you all that it finds. Do this by simply
+not defining any attributes within the configuration file. It will
+list all the attributes it finds. You could create a special configuration
+file specifically for this purpose.
+
+If you are getting fatal errors from your Web Server when you attempt to
+execute a command, please try the same command using interactive mode. Look
+to see if the HTML being generated makes sense or not. If the HTML
+looks good, run it again interactively and pipe the results to a file, then
+attempt to submit the resulting file as the URL. If it works, it is
+likely that the environment you run is different than the one the Web
+server is using - Unix file protections frequently are a cause of these
+problems. If you can't determine what is different, discuss the problem
+with your Unix system administrator - is is likely a resource problem.
+If you add code that causes problems, but you still get a result, try the
+application in interactive mode and verify the HTML being generated. Any
+additional HTML code you add may need to to have proper termination syntax
+(tables are very touchy about this), and you may need to further enhance
+your changes to compensate.
+
+When creating new applications, please test your results on both
+Netscape's Web Browser and Internet Explorer. Nothing is more
+irritating to end users than getting different results based on their
+Web Browser selection.
+
+The Unix Command line will not allow you to pass some characters into
+an application unless you surround the characters or command with quotes.
+Some common examples of executing web_ldap interactively are:
+
+ > web_ldap DEF "cn=j*moller"
+
+ > web_ldap DEF cn=jens moller
+
+The command with the '*' in it requires quotes around it. Also note
+that the application only allows the LDAP command to use up to 3 argv
+values. This is as a limitation of the current parsing within the program
+of argc/argv parameters. You could alter the program, or simply put
+quotes around the LDAP request. Enable the debug mode within the
+configuration file if you feel that the application is losing
+arguments to see what its operating against. When operated by the Web Server,
+and passing in FORM data - you won't have this limitation, and you don't
+need quotes.
+
+You can pass hidden fields from the Web Form into the web_ldap program.
+An example is shown with the name of 'FORM' having a value of '300'.
+You can create additional hidden fields, named anything you want them
+to be, with any value you want. These can be used to define existing
+options (such as which configuration file to use), or other options
+that your modified web_ldap.c program may want to have passed to it.
+
+
+Jens Moller - Jens@colomar.com - COLOMAR Group.
+OpenLDAP - OpenLDAP-devel@OpenLDAP.org.
#include <sys/time.h>
#include <netinet/in.h>
#include "syslog.h"
-#include "lber.h"
-#include "ldap.h"
+#include <ldap.h>
#define EQ(x,y) (strcasecmp(x,y) == 0)
EXTERN char **category;
EXTERN table *templateTranslationTable;
-extern int displayDescribe(), parseCommand();
-extern void needHelp();
-extern void showTemplate(), listTemplates();
-extern char **specifyAttributes();
-extern char *lowerCase(), *version(), *attributeLabel();
+extern int displayDescribe(), parseCommand(char *query);
+extern void needHelp(char *reason);
+extern void showTemplate(char *template), listTemplates(char *query);
+extern char **specifyAttributes(char *objectClass);
+extern char *lowerCase(char *string), *version(void), *attributeLabel();
extern char *rfc931_name();
+extern char *templateToObjectClass(char *template);
--- /dev/null
+Internet-Drafts are working documents of the Internet Engineering Task
+Force (IETF), its areas, and its working groups. Note that other groups
+may also distribute working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time. It is inappropriate to use Internet-Drafts as reference material
+or to cite them other than as "work in progress."
--- /dev/null
+
+ Internet-Draft D. Byrne, IBM
+ LDAP Extensions WG L. Poitou, Sun
+ Intended Category: Standards Track E. Stokes, IBM
+ Expires: 20 October 1998
+
+ 20 April 1998
+
+ Use of Aliases within LDAP
+ <draft-byrne-ldap-alias-00.txt>
+
+ STATUS OF THIS MEMO
+
+ This document is an Internet Draft. Internet Drafts are
+ working documents of the Internet Engineering Task Force
+ (IETF), its Areas, and its Working Groups. Note that other
+ groups may also distribute working documents as Internet
+ Drafts.
+
+ Internet Drafts are draft documents valid for a maximum of six
+ months. Internet Drafts may be updated, replaced, or obsoleted
+ by other documents at any time. It is not appropriate to use
+ Internet Drafts as reference material or to cite them other
+ than as a "working draft" or "work in progress."
+
+ To view the entire list of current Internet-Drafts, please
+ check the "1id-abstracts.txt" listing contained in the
+ Internet-Drafts Shadow Directories on ftp.is.co.za (Africa),
+ ftp.nordu.net (Northern Europe), ftp.nis.garr.it (Southern
+ Europe), munnari.oz.au (Pacific Rim), ftp.ietf.org (US East
+ Coast), or ftp.isi.edu (US West Coast).
+
+ Comments and suggestions on this document are encouraged.
+ Comments on this document should be sent to the LDAPEXT
+ working group discussion list:
+
+ ietf-ldapext@netscape.com
+
+ ABSTRACT
+
+ This document describes the suggested behavior for aliases for
+ LDAPv3 and above to improve LDAP server interoperability .
+
+ The key words "MUST", "SHOULD", and "MAY" used in this
+ document are to be interpreted as described in [Bradner97].
+
+
+ 1. Objectives
+
+
+ Aliases may be used within LDAP to reference entries anywhere
+ within the directory tree. Conceptually, an alias is simply a
+ pointer to the DIT entry it represents. It does not contain
+ additional information about that entry; only the location of
+ the entry.
+
+ The behavior of the alias object within LDAP is not well-
+ defined, both in creation of the alias object and the behavior
+ when dereferencing the alias.
+
+ For successful interoperability, the expected behavior of
+ servers when encountering alias objects SHOULD be consistent.
+
+ Additionally, it MUST be possible to use aliases without
+ changing the LDAPv3 schema as defined in [Wahl] and without
+ adding server-dependent data.
+
+
+ 2. Schema Definition
+
+
+ 2.1 Schema Expansion
+
+ The alias objectclass definitions presented in the LDAPv3
+ Schema [Wahl] are the basis for aliasing within ldap. The
+ alias objectclass is a Structural objectclass with a single
+ required attribute; the single valued aliasObjectName.
+
+ This definition of the alias objectclass does not allow for
+ any attribute other than 'aliasedObjectName' to be used as the
+ naming attribute within the RDN. The resulting dn for the
+ alias object must therefore be of the form
+ "aliasedObjectName=<dn>, <rdn>, <rdn>..." This is not a
+ user-friendly name for a directory entry, and quite possibly
+ corrupts the naming hierarchy within the directory tree.
+
+ In order to remain true the concept of an alias; that it is
+ merely a pointer to another entry, an entry of objectclass
+ alias SHOULD NOT be combined with any other objectclass. If
+ multiple objectclasses are combined, it becomes possible to
+ add information to the alias entry without violating the
+ schema rules.
+
+ While not explicitly specified as either a 'required' or
+ 'may', any naming attribute MUST be allowed to form the RDN of
+ the alias. Restricting the possible naming attributes would
+ potentially corrupt the hierarchy. For example, it would be
+ impossible to distinguish between a person alias and an
+ organisation alias.
+
+ 2.2 AliasObject Objectclass
+
+ In order to create an alias object which can be appropriately
+ named to that which it represents, the definition of the alias
+ object MUST be expanded. A new objectclass must be defined
+ which inherits from the current definition of alias but
+ extends the attributes allowed within the RDN.
+
+ ( 1.3.6.1.4.1.42.2.27.1.2.1
+ NAME 'aliasObject'
+ DESC objectclass for all alias objects
+ SUP 'ALIAS'
+ MAY *
+ )
+
+ The '*' allows any naming attribute to be used in forming the
+ RDN of the object.
+
+ For example, the following is a correct LDIF:
+ dn: cn=John Doe, ou=myOrg, c=US
+ objectclass: alias
+ objectclass: aliasObject
+ aliasedObjectName: cn=President, ou=myOrg, c=US
+ cn: John Doe
+
+ To prevent the alias from containing extra information about
+ the object, the naming attribute SHOULD contain only a single
+ value.
+
+ For example, the following is not a correct LDIF:
+ dn: cn=John Doe, ou=myOrg, c=US
+ objectclass: alias
+ objectclass: aliasObject
+ aliasedObjectName: cn=President, ou=myOrg, c=US
+ cn: John Doe
+ cn: Doe
+
+ Similarly, the following would not be a correct LDIF file
+ because it adds extra information to the alias object.
+
+ dn: cn=John Doe, ou=myOrg, c=US
+ objectclass: alias
+ objectclass: aliasObject
+ aliasedObjectName: cn=President, ou=myOrg, c=US
+ cn: John Doe
+ title: President
+
+ The naming attribute used to form the RDN of the object SHOULD
+ reflect the naming attribute of the referenced object.
+ However, there are some cases where the naming attribute MAY
+ be different.
+
+ Within the X.501 [ITU-T], the attribute used to described the
+ aliased object is 'aliasedEntryName'. Since the OID for
+ 'aliasedEntryName' and 'aliasedObjectName' are the same for
+ both X.500 and LDAP, LDAP servers SHOULD treat the
+ 'aliasedEntryName' as a synonym for 'aliasedObjectName'.
+
+
+ 3. Alias Behavior
+
+ In general alias objects SHOULD NOT be dereferenced during any
+ operation other than search unless requested to do so by the
+ client.
+
+ Since an alias points to another section of the tree, it MUST
+ NOT be possible to add an object under an alias object; alias
+ objects MUST always be leaf nodes.
+
+ During the dereferencing of aliases, a loop is detected if the
+ server visits the same alias entry more than once. In this
+ case a data integrity error has occurred and the server MUST
+ return an error of 'aliasProblem'
+
+ If an alias is dereferenced, and the resulting directory entry
+ does not exists, a data integrity problem has occurred, and
+ the server MUST return an error code of
+ 'aliasDereferencingProblem'
+
+ If the base entry for an ldapsearch is an alias, and alias
+ dereferencing is set to either derefFindBaseObj, or
+ derefAlways, the base entry MUST be dereferenced before the
+ search is performed. The new base for the search will become
+ the entry to which the alias resolves. The search is then
+ performed.
+
+ If multiple aliases are chained, the alias for the first
+ object MUST resolve to the last entry in the chain. For
+ example, A, B, and C are alias objects. If A points to B which
+ points to C which points to D, A resolves to D when
+ dereferencing the alias.
+
+ If an alias is dereferenced as part of a search, the alias
+ entry itself SHOULD NOT be returned as part of the search.
+
+ If an alias matches the search filter, and dereferencing is
+ set to 'searching' or 'always', the dereferenced object SHOULD
+ be returned, even if it does not match the filter.
+
+ If the alias is not dereferenced during the search, and it
+ matches the filter, then it SHOULD be returned within the
+ search result.
+
+ Each directory object matching a filter SHOULD be returned
+ only once during a search. If an entry is found twice because
+ of aliases pointing to a part of the tree already searched,
+ the entry SHOULD NOT be returned to the client a second time.
+
+ 4. Scenarios
+
+ Using the following LDIF, the scenarios would return the
+ expected information as follows:
+
+ dn: c=myCountry
+ c: myCountry
+ objectclass: country
+
+ dn: ou=Area1, c=myCountry
+ ou: Area1
+ aliasedObjectName: o=myCorporation, c=myCountry
+ objectclass: alias
+ objectclass:aliasObject
+
+ dn: o=myCorporation, c=myCountry
+ ou: myCorporation
+ objectclass:organization
+
+ dn: cn=President, o=myCorporation, c=myCountry
+ cn: President
+ aliasObjectName: cn=John Doe, o=myCorporation, c=myCountry
+ objectclass: alias
+ objectclass: aliasObject
+
+ dn: cn=John Doe, o=myCorporation, c=myCountry
+ cn: John Doe
+ objectclass: person
+
+
+ c = myCountry
+ / |
+ ou = Area1 -----> o = myCorporation
+ | \
+ cn=President ---> cn = John Doe
+
+ Performing a base search of 'ou = Area1, c=myCountry' with a
+ filter of 'objectclass=aliasObject'
+ NeverDerefAlias would return 'ou=Area1, c=myCountry'
+ DerefFinding would return 'cn=President, o=myCorporation,
+ c=myCountry'
+ DerefSearching would return 'o=myCorporation,
+ c=myCountry'
+ DerefAlways would return 'cn=John Doe, o=myCorporation,
+ c=myCountry'
+
+ Performing a one level search of 'c=myCountry' with a filter
+ of 'ou = * '
+ NeverDerefAlias would return 'ou=Area1, c=myCountry'
+ DerefFinding would return 'ou=Area1, c=myCountry'
+ DerefSearching would return 'o=myCorporation,
+ c=myCountry'
+ DerefAlways would return ' o=myCorporation, c=myCountry'
+
+ Performing a full tree search of 'c=myCountry' with a filter
+ of ' cn = President '
+ NeverDerefAlias would return 'cn=President, o=myCorporation,
+ c=myCountry'
+ DerefFinding would return 'cn=President, o=myCorporation,
+ c=myCountry'
+ DerefSearching would return 'cn=John Doe, o=myCorporation,
+ c=myCountry'
+ DerefAlways would return 'cn=John Doe, o=myCorporation,
+ c=myCountry'
+
+
+ 6. Security Considerations
+
+ Permissions to dereferencing an alias, adding, deleting or
+ returning alias entries are decided by the directory server's
+ ACL administration policy.
+
+
+ 7. References
+
+ [LDAPv3] M. Wahl, T. Howes, S. Kille, "Lightweight Directory
+ Access Protocol (v3)", RFC 2251, December 1997.
+
+ [Whal] M.Wahl, A, Coulbeck, T. Howes, S. Kille, "Lightweight
+ Directory Access Protocol (v3)": Attribute Syntax Definitions,
+ RFC 2252, December 1997.
+
+ [Bradner97] Bradner, Scott, "Key Words for use in RFCs to
+ Indicate Requirement Levels", RFC 2119.
+
+ [ITU-T] ITU-T Rec. X.501, "The Directory: Models", 1993
+
+
+ AUTHOR(S) ADDRESS
+
+
+ Debbie Byrne
+ IBM
+ 11400 Burnet Rd
+ Austin, TX 78758
+ USA
+ mail-to: djbyrne@us.ibm.com
+ phone: +1 512 838 1930
+
+ Ludovic Poitou
+ Sun Microsystems
+ 32, Chemin du vieux Chene
+ 38240 Meylan
+ France
+ Phone: +33.(0)4.76.41.42.12
+ email: ludovic.poitou@france.sun.com
+
+ Ellen Stokes
+ IBM
+ 11400 Burnet Rd
+ Austin, TX 78758
+ USA
+ mail-to: stokes@austin.ibm.com
+ phone: +1 512 838 3725
+
+
--- /dev/null
+
+
+
+
+Change Record Object Class Definition Gordon Good
+INTERNET-DRAFT Netscape Communications
+ 11 March 1998
+
+ Definition of an Object Class to Hold LDAP Change Records
+ Filename: draft-good-ldap-changelog-00.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft. Internet-Drafts are working
+ documents of the Internet Engineering Task Force (IETF), its
+ areas, and its working groups. Note that other groups may also
+ distribute working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six
+ months and may be updated, replaced, or obsoleted by other
+ documents at any time. It is inappropriate to use Internet-
+ Drafts as reference material or to cite them other than as
+ ``work in progress.''
+
+ To learn the current status of any Internet-Draft, please check
+ the ``1id-abstracts.txt'' listing contained in the Internet-
+ Drafts Shadow Directories on ds.internic.net (US East Coast),
+ nic.nordu.net (Europe), ftp.isi.edu (US West Coast), or
+ munnari.oz.au (Pacific Rim).
+
+ This Internet Draft expires October 1st, 1998.
+
+
+
+Abstract
+
+ In order to support more flexible replication methods, it is
+ desirable to specify some manner in which an LDAP client may retrieve
+ a set of changes which have been applied to an LDAP server's
+ database. The client, which may be another LDAP server, may then
+ choose to update its own replicated copy of the data. This document
+ specifies an object class which may be used to represent changes
+ applied to an LDAP server. It also specifies a method for
+ discovering the location of the container object which holds these
+ change records, so that clients and servers have a common rendezvous
+ point for this information.
+
+
+
+Background and Intended Usage
+
+ This document describes an objectclass which can be used to represent
+
+
+
+Good March 11, 1998 [Page 1]
+\f
+INTERNET-DRAFT Change Record Object Class 11 March 1998
+
+
+ changes which have been applied to a directory server. It also
+ suggests a common location for a container which holds these objects.
+ A client may update its local copy of directory information by
+ reading the entries within this container, and applying the changes
+ to its local database.
+
+ The key words "MUST", "MAY", and "SHOULD" used in this document are
+ to be interpreted as described in [3].
+
+New Attribute Types Used in the changeLogEntry Object Class
+
+ ( 2.16.840.1.113730.3.1.5
+ NAME 'changeNumber'
+ DESC 'a number which uniquely identifies a change made to a
+ directory entry'
+ SYNTAX 'INTEGER'
+ EQUALITY 'integerMatch'
+ ORDERING 'integerOrderingMatch' )
+
+ ( 2.16.840.1.113730.3.1.6
+ NAME 'targetDN'
+ DESC 'the DN of the entry which was modified'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 'DN' )
+
+ ( 2.16.840.1.113730.3.1.7
+ NAME 'changeType'
+ DESC 'the type of change made to an entry'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 'DirectoryString' )
+
+ ( 2.16.840.1.113730.3.1.8
+ NAME 'changes'
+ DESC 'a set of changes to apply to an entry'
+ SYNTAX 'OctetString' )
+
+ ( 2.16.840.1.113730.3.1.9
+ NAME 'newRDN'
+ DESC 'the new RDN of an entry which is the target of a
+ modrdn operation'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 'DN' )
+
+ ( 2.16.840.1.113730.3.1.10
+ NAME 'deleteOldRDN'
+ DESC 'a flag which indicates if the old RDN should be retained
+ as an attribute of the entry'
+ EQUALITY booleanMatch
+
+
+
+Good March 11, 1998 [Page 2]
+\f
+INTERNET-DRAFT Change Record Object Class 11 March 1998
+
+
+ SYNTAX 'BOOLEAN' )
+
+ ( 2.16.840.1.113730.3.1.11
+ NAME 'newSuperior'
+ DESC 'the new parent of an entry which is the target of a
+ moddn operation'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 'DN' )
+
+
+Schema Definition of the changeLogEntry Object Class
+
+ ( 2.16.840.1.113730.3.2.1
+ NAME 'changeLogEntry'
+ SUP top
+ STRUCTURAL
+ MUST (
+ changeNumber $ targetDN $ changeType
+ )
+ MAY (
+ changes $ newRDN $ deleteOldRDN $ newSuperior
+ )
+ )
+
+
+
+Discussion of changeLogEntry Attributes:
+
+ changeNumber: the change number, as assigned by the supplier. This
+ integer MUST strictly increase as new entries are added, and must
+ always be unique within a given server. Syntax: INTEGER
+
+ targetdn: the distinguished name of the entry which was added,
+ modified or deleted. In the case of a modrdn operation, the targetdn
+ gives the DN of the entry before it was modified. Syntax: DN
+
+ changeType: the type of change. One of: "add", "delete", "modify",
+ "modrdn". Later RFCs may define additional values for changeType.
+ Syntax: DirectoryString
+
+ changes: the changes which were made to the directory server. These
+ changes are in LDIF format, which is described in [1].
+ Syntax: OctetString
+
+ newRDN: the new RDN (Relative Distinguished Name) of the entry, if the
+ changeType is "modrdn". If the changeType attribute does not have the
+ value "modrdn", then there should be no values contained in the newRDN
+ attribute.
+
+
+
+Good March 11, 1998 [Page 3]
+\f
+INTERNET-DRAFT Change Record Object Class 11 March 1998
+
+
+ Syntax: DN
+
+ deleteOldRDN: a flag which tells whether the old RDN of the entry
+ should be retained as a distinguished attribute of the entry, or
+ should be deleted. A value of "FALSE" indicates that the RDN should be
+ retained as a distinguished attribute, and a value of "TRUE" indicates
+ that it should not be retained as a distinguished attribute of the
+ entry. If any value other than "TRUE" or "FALSE" is contained in the
+ deleteOldRDN attribute, or if the deleteOldRDN contains multiple
+ values, the RDN should be retained as a distinguished attribute (that
+ is, "FALSE" is the default if no values are present, or if illegal
+ values are present).
+ Syntax: BOOLEAN
+
+ newSuperior: if present, gives the name of the entry which
+ becomes the immediate superior of the existing entry. This optional
+ attribute reflects LDAPv3 functionality, and MUST NOT be generated
+ by LDAPv2 servers [2].
+ Syntax: DN
+
+
+
+Discussion of the changeLogEntry object class
+
+ The changeLogEntry object class is used to represent changes made to a
+ directory server. The set of changes made to a directory server, then,
+ is given by the ordered set of all entries within the changelog
+ container, ordered by changeNumber.
+
+ A client may synchronize its local copy of a remote directory server's
+ contents by searching the remote server's changelog container for any
+ entries where the changenumber is greater than or equal to the last
+ change previously retrieved from that server. If the entry with the
+ changenumber matching the last change retrieved is not returned in the
+ search results, then the server's changelog has been trimmed. The
+ client must then fall back to reading the entire directory to bring its
+ copy in sync with the server's.
+
+ Assuming that the client has successfully retrieved one or more changelog
+ entries from the server, it can then use the information contained in each
+ entry to update the corresponding entry (named by the targetDN attribute)
+ in its local copy of the database.
+
+ Note that, due to access control restrictions, the client is not guaranteed
+ read access to the "changes" attribute. If the client discovers that the
+ "changes" attribute has no values, then it must read the entry given by
+ the targetDN attribute, possibly only retrieving attributes it deems
+ "interesting". However, in the case of delete and modrdn operations, there
+
+
+
+Good March 11, 1998 [Page 4]
+\f
+INTERNET-DRAFT Change Record Object Class 11 March 1998
+
+
+ is never a "changes" attribute, so it is never necessary to read the target
+ entry in these cases.
+
+
+
+Examples of the changeLogEntry object class
+
+ In each example below, the "changes" attribute is shown in plain text,
+ with embedded newlines. This is done for clarity. It is intended that
+ newlines be stored in the entry literally, not encoded in any way.
+ If a "changes" attribute value is stored in an LDIF file, it must
+ base-64 encoded.
+
+ Example 1: A changeLogEntry representing the addition of a
+ new entry to the directory
+
+ dn: changenumber=1923, cn=changelog
+ changenumber: 1923
+ targetdn: cn=Barbara Jensen, ou=Accounting, o=Ace Industry, c=US
+ changetype: add
+ changes: cn: Barbara Jensen\ncn: Babs Jensen\nsn: Jensen\n
+ givenname: Barbara\ntelephonenumber: +1 212 555-1212\nmail: babs@ace.com\n
+ objectclass: top\nobjectclass: person\nobjectclass: organizationalPerson\n
+ objectclass: inetOrgPerson
+
+ Example 2: A changeLogEntry representing the deletion of an entry
+ from the directory
+
+ dn: changenumber=2933, cn=changelog
+ changenumber: 2933
+ targetdn: cn=Gern Jensen, ou=Product Testing, o=Ace Industry, c=US
+ changetype: delete
+
+ Example 3: A changeLogEntry representing the modification of an entry
+ in the directory
+
+ dn: changenumber=5883, cn=changelog
+ changenumber: 5883
+ targetdn: cn=Bjorn Jensen, ou=Product Development, o=Ace Industry, c=US
+ changetype: modify
+ changes: delete: telephonenumber\ntelephonenumber: 1212\n-\n
+ add: telephonenumber\ntelephonenumber: +1 212 555 1212\n-
+
+ Example 4: A changeLogEntry representing a modrdn operation performed
+ on an entry in the directory
+
+ dn: changenumber=10042, cn=changelog
+ changenumber: 10042
+
+
+
+Good March 11, 1998 [Page 5]
+\f
+INTERNET-DRAFT Change Record Object Class 11 March 1998
+
+
+ targetdn: cn=Bjorn Jensen, ou=Product Development, o=Ace Industry, c=US
+ changetype: modrdn
+ newrdn: cn=Bjorn J Jensen
+ deleteoldrdn: FALSE
+
+
+Location of the container containing changeLogEntry objects
+
+ For LDAPv3 servers, the location of the container which holds
+ changeLogEntry objects is obtained by reading the "changeLog" attribute
+ of a server's root DSE. For example, if the container's root is
+ "cn=changelog", then the root DSE must have an attribute named
+ "changeLog" with the value "cn=changelog".
+
+ The "changelog" attribute is defined as follows:
+
+ ( 2.16.840.1.113730.3.1.35
+ NAME 'changelog'
+ DESC 'the distinguished name of the entry which contains
+ the set of entries comprising this server's changelog'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 'DN'
+ )
+
+ For LDAPv2 servers, the name of the changelog container must be
+ "cn=changelog".
+
+
+Differences from previous versions of this document
+
+ Differences between draft-ietf-asid-changelog-00.txt and
+ draft-ietf-asid-changelog-01.txt
+
+ 1) Fixed a deficiency in the syntax of the changeNumber attribute. The
+ attribute now has INTEGER syntax, with appropriate matching and
+ ordering rules defined.
+
+ 2) Removed unneeded substring matching rules from the changeType and
+ deleteOldRDN attribute definitions.
+
+ 3) Made use of MAY, SHOULD, etc. consistent with RFC 2119.
+
+ 4) Renamed document (now an individual submission).
+
+ 5) Changed syntax of "changes" attribute from "Binary" to "OctetString".
+
+ 6) Removed references to X.500 supplier and consumer-initiated
+ replication.
+
+
+
+Good March 11, 1998 [Page 6]
+\f
+INTERNET-DRAFT Change Record Object Class 11 March 1998
+
+
+ 7) Updated references to current drafts/proposed standards documents.
+
+Security Considerations
+
+ Servers implementing this scheme MUST NOT allow the "changes"
+ attribute to be generally readable. The "changes" attribute contains
+ all modifications made to an entry, and some changes may contain
+ sensitive data, e.g. passwords.
+
+ If a server does allow read access on the "changes: attribute to a
+ particular bound DN, then that DN should be trusted. For example, two
+ cooperating servers may exchange the password for some DN which is
+ granted read access to the "changes" attribute of the changeLog. This
+ would allow one server to retrieve changes and apply them directly to
+ its database.
+
+ In situations where the "changes" attribute is not readable by a client,
+ that client may still use the entries in the changeLog to construct a
+ list of entry DNs which are known to have changed since the last time
+ the client synchronized. The client may then read each of those entries,
+ subject to whatever access control is in effect on the server,
+ and update its local copy of each entry.
+
+ Servers implementing this scheme should disallow write access to the
+ changelog container object and all entries contained within.
+
+
+
+Acknowledgements
+
+ This material is based in part upon work supported by the National
+ Science Foundation under Grant No. NCR-9416667.
+
+
+
+References
+
+ [1] Good, G., "The LDAP Data Interchange Format", INTERNET-DRAFT
+ draft-good-ldap-ldif-03.txt, Netscape Communications Corp., March 1997,
+ <URL:ftp://ftp.ietf.org/internet-drafts/draft-good-ldap-ldif-03.txt>
+
+ [2] Wahl, M., Howes, T., Kille, S., "Lightweight Directory Access
+ Protocol (v3)", RFC 2251 Critical Angle, Inc., Netscape Communications Corp.,
+ ISODE Consortium, July, 1997,
+ <URL:ftp://ftp.isi.edu/in-notes/rfc2251.txt>
+
+ [3] S. Bradner, "Key Words for use in RFCs to Indicate Requirement
+ Levels", Harvard University, RFC 2119, March 1997,
+
+
+
+Good March 11, 1998 [Page 7]
+\f
+INTERNET-DRAFT Change Record Object Class 11 March 1998
+
+
+ <URL:http://ds.internic.net/rfc/rfc2119.txt>
+
+
+Author's Address
+
+ Gordon Good
+ Netscape Communications Corp.
+ 501 E. Middlefield Rd.
+ Mailstop MV068
+ Mountain View, CA 94043, USA
+ Phone: +1 415 937-3825
+ EMail: ggood@netscape.com
+
+ This Internet Draft expires October 1st, 1998.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Good March 11, 1998 [Page 8]
+\f
--- /dev/null
+
+
+
+LDAP Data Interchange Format (LDIF) Gordon Good
+INTERNET-DRAFT Netscape Communications
+ 22 February 1999
+
+ The LDAP Data Interchange Format (LDIF) - Technical Specification
+ Filename: draft-good-ldap-ldif-03.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance
+ with all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six
+ months and may be updated, replaced, or obsoleted by other
+ documents at any time. It is inappropriate to use Internet-
+ Drafts as reference material or to cite them other than as
+ "work in progress."
+
+ To view the list Internet-Draft Shadow Directories, see
+ http://www.ietf.org/shadow.html.
+
+ This Internet Draft expires August 22nd, 1999.
+
+
+Abstract
+
+ This document describes a file format suitable for describing
+ directory information or modifications made to directory information.
+ The file format, known as LDIF, for LDAP Data Interchange Format, is
+ typically used to import and export directory information between
+ LDAP-based directory servers, or to describe a set of changes which
+ are to be applied to a directory.
+
+
+Background and Intended Usage
+
+ There are a number of situations where a common interchange format is
+ desirable. For example, one might wish to export a copy of the
+ contents of a directory server to a file, move that file to a
+ different machine, and import the contents into a second directory
+ server.
+
+ Additionally, by using a well-defined interchange format, development
+
+
+
+Good February 22, 1999 [Page 1]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ of data import tools from legacy systems is facilitated. A fairly
+ simple set of tools written in awk or perl can, for example, convert
+ a database of personnel information into an LDIF file. Thie file can
+ then be imported into a directory server, regardless of the internal
+ database representation the target directory server uses.
+
+ The LDIF format was originally developed and used in the University
+ of Michigan LDAP implementation. The first use of LDIF was in
+ describing directory entries. Later, the format was expanded to
+ allow representation of changes to directory entries.
+
+ Relationship to the application/directory MIME content-type:
+
+ The application/directory MIME content-type [1] is a general
+ framework and format for conveying directory information, and is
+ independent of any particular directory service. The LDIF format is
+ a simpler format which is perhaps easier to create, and also may also
+ be used, as noted, to describe a set of changes to be applied to a
+ directory.
+
+ The key words "MUST", "MAY", and "SHOULD" used in this document are
+ to be interpreted as described in [7].
+
+
+Definition of the LDAP Data Interchange Format
+
+
+ The LDIF format is used to convey directory information, or a
+ description of a set of changes made to directory entries. An LDIF
+ file consists of a series of records separated by line separators. A
+ record consists of a sequence of lines describing a directory entry,
+ or a sequence of lines describing a set of changes to a directory
+ entry. An LDIF file specifies a set of directory entries, or a set
+ of changes to be applied to directory entries, but not both.
+
+ There is a one-to-one correlation between LDAP operations which
+ modify the directory (add, delete, modify, and modrdn), and the types
+ of changerecords described below ("add", "delete", "modify", and
+ "modrdn" or "moddn"). This correspondence is intentional, and
+ permits a straightforward translation from LDIF changerecords to
+ protocol operations.
+
+Formal Syntax Definition of LDIF
+
+ The following definition uses the augmented Backus-Naur Form
+ specified in RFC 822 [2].
+
+ ldif-file = ldif-content / ldif-changes
+
+
+
+Good February 22, 1999 [Page 2]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ ldif-content = version-spec 1*SEP
+ ldif-attrval-record *(1*SEP ldif-attrval-record)
+ ldif-changes = version-spec 1*SEP
+ ldif-change-record *(1*SEP ldif-change-record)
+ ldif-attrval-record = dn-spec SEP 1*(attrval-spec SEP)
+ ldif-change-record = dn-spec SEP 1*(changerecord SEP)
+
+ version-spec = "version:" *SPACE version-number
+ version-number = 1*DIGIT ; version-number MUST be "1" for the
+ ; LDIF format described in this document.
+
+ dn-spec = ("dn:" *SPACE dn) / ("dn::" *SPACE base64-dn)
+ dn = <a distinguished name, as defined in RFC 2253 [3]>
+ base64-dn = <a dn which has been base-64 encoded, as
+ defined in RFC 1521 [5]>
+ rdn = <a relative distinguished name, as defined in RFC
+ 2253 [3]>
+ base64-rdn = <an rdn which has been base-64 encoded, as
+ defined in RFC 1521 [5]>
+
+ attrval-spec = attribute-description ((":") / (":" *SPACE value) /
+ ("::" *SPACE base64-value) /
+ (":<" *SPACE url))
+ url = <a Uniform Resource Locator, as defined in [6]>
+ ; (See Note 6, below)
+ attribute-description = <an attribute description, as defined in [4].
+ An attribute description MAY NOT contain a
+ colon ":">
+ value = 1*safe-initval *safe
+ ; (See Note 9, below)
+ safe = <any value except CR or LF>
+ safe-initval = <any value except CR, LF, colon (":", ASCII 58
+ decimal), SPACE, and less-than ("<" , ASCII 60
+ decimal)>
+ base64-value = <base-64-encoded value, as defined in RFC 1521 [5]>
+
+ changerecord = change-add / change-delete / change-modify /
+ change-moddn
+ change-add = "changetype:" *SPACE "add" 1*(SEP attrval-spec)
+ change-delete = "changetype:" *SPACE "delete"
+ change-moddn = "changetype:" *SPACE ("modrdn" / "moddn") SEP
+ ("newrdn:" *SPACE rdn /
+ "newrdn::" *SPACE base-64-rdn) SEP
+ "deleteoldrdn:" *SPACE ("0" / "1")
+ 0,1*(SEP (("newsuperior:" *SPACE dn) /
+ ("newsuperior::" *SPACE base-64-dn)))
+ change-modify = "changetype:" *SPACE "modify" 1*(SEP mod-spec)
+ mod-spec = mod-add-spec / mod-delete-spec / mod-replace-spec
+
+
+
+Good February 22, 1999 [Page 3]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ mod-add-spec = "add:" *SPACE attribute-description
+ 1*(SEP attrval-spec) SEP "-"
+ mod-delete-spec = "delete:" *SPACE attribute-description
+ *(SEP attrval-spec) SEP "-"
+ mod-replace-spec = "replace:" *SPACE attribute-description
+ *(SEP attrval-spec) SEP "-"
+ SPACE = <ASCII SP, space>
+ SEP = (CR LF / LF)
+ CR = <ASCII CR, carriage return>
+ LF = <ASCII LF, line feed>
+ DIGIT = <any ASCII decimal digit (60 - 71 decimal) >
+
+
+ Notes on LDIF Syntax
+
+ 1) For the LDIF format described in this document, the version number
+ MUST be "1". If the version number is absent, implementations MAY
+ choose to interpret the contents as an older LDIF file format,
+ supported by the University of Michigan ldap-3.3 implementation [8].
+
+ 2) Any line, including comment lines, in an LDIF file MAY be wrapped
+ by inserting a line separator (SEP) and a SPACE. Any line which
+ begins with a single space MUST be treated as a continuation of the
+ previous line. When joining folded lines, exactly one space character
+ at the beginning of each continued line must be discarded.
+
+ 3) Any line which begins with a pound-sign ("#", ASCII 35) is a
+ comment line, and MUST be ignored when parsing an LDIF file.
+
+ 4) Any dn or value which contains characters other than those defined
+ as "safe", or begins with a character other than those defined as
+ "safe-initval", above, MUST be base-64 encoded. Other values MAY be
+ base-64 encoded.
+
+ 5) To represent a zero-length attribute value, use an attrval-spec of
+ "attribute-description:". For example, "seeAlso:" represents a
+ zero-length "seeAlso" attribute value.
+
+ 6) When a URL is specified in an attrval-spec, the following
+ conventions apply:
+ a) Implementations SHOULD support the file:// URL format. The
+ contents of the referenced file are to be included verbatim
+ in the interpreted output of the LDIF file.
+ b) Implementations MAY support other URL formats. The semantics
+ associated with each supported URL will be documented in
+ an associated Applicability Statement.
+
+ 7) While it is permissible for character values larger than 126 to be
+
+
+
+Good February 22, 1999 [Page 4]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ contained in an attribute value, implementations SHOULD base-64
+ encode any value which contains such characters when generating LDIF.
+ However, implementations MAY leave the values unencoded. This
+ relaxation is designed to allow editing of LDIF files containing
+ UTF-8 data.
+
+ 8) Attribute values contained in LDIF files represent directory data,
+ and therefore MUST be valid UTF-8 strings. Implementations which read
+ LDIF MAY interpret files in which the values are stored in some other
+ character set encoding, but implementations MUST NOT generate LDIF
+ content which does not contain valid UTF-8 data.
+
+ 9) Values that end with SPACE SHOULD be base-64 encoded.
+
+Examples of LDAP Data Interchange Format
+
+
+ Example 1: An simple LDAP file with two entries
+
+ version: 1
+ dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+ objectclass: top
+ objectclass: person
+ objectclass: organizationalPerson
+ cn: Barbara Jensen
+ cn: Barbara J Jensen
+ cn: Babs Jensen
+ sn: Jensen
+ uid: bjensen
+ telephonenumber: +1 408 555 1212
+ description: A big sailing fan.
+
+ dn: cn=Bjorn Jensen, ou=Accounting, dc=airius, dc=com
+ objectclass: top
+ objectclass: person
+ objectclass: organizationalPerson
+ cn: Bjorn Jensen
+ sn: Jensen
+ telephonenumber: +1 408 555 1212
+
+ Example 2: A file containing an entry with a folded attribute value
+
+ version: 1
+ dn:cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+ objectclass:top
+ objectclass:person
+ objectclass:organizationalPerson
+ cn:Barbara Jensen
+
+
+
+Good February 22, 1999 [Page 5]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ cn:Barbara J Jensen
+ cn:Babs Jensen
+ sn:Jensen
+ uid:bjensen
+ telephonenumber:+1 408 555 1212
+ description:Babs is a big sailing fan, and travels extensively in search of
+ perfect sailing conditions.
+ title:Product Manager, Rod and Reel Division
+
+ Example 3: A file containing a base-64-encoded value
+
+ version: 1
+ dn: cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com
+ objectclass: top
+ objectclass: person
+ objectclass: organizationalPerson
+ cn: Gern Jensen
+ cn: Gern O Jensen
+ sn: Jensen
+ uid: gernj
+ telephonenumber: +1 408 555 1212
+ description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVlIGlzIGJ
+ hc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdGVyIGluIGl0ICh
+ hIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQgb3V0IG1vcmUu
+
+ Example 4: A file containing an entries with UTF-8-encoded attribute
+ values, including language tags. Comments indicate the contents
+ of UTF-8-encoded attributes and distinguished names.
+
+ version: 1
+ dn:: b3U95Za25qWt6YOoLG89QWlyaXVz
+ # dn:: ou=<JapaneseOU>,o=Airius
+ objectclass: top
+ objectclass: organizationalUnit
+ ou:: 5Za25qWt6YOo
+ # ou:: <JapaneseOU>
+ ou;lang-ja:: 5Za25qWt6YOo
+ # ou;lang-ja:: <JapaneseOU>
+ ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2
+ # ou;lang-ja:: <JapaneseOU_in_phonetic_representation>
+ ou;lang-en: Sales
+ description: Japanese office
+
+ dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
+ # dn:: uid=<uid>,ou=<JapaneseOU>,o=Airius
+ userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
+ objectclass: top
+ objectclass: person
+
+
+
+Good February 22, 1999 [Page 6]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ objectclass: organizationalPerson
+ objectclass: inetOrgPerson
+ uid: rogasawara
+ mail: rogasawara@airius.co.jp
+ givenname;lang-ja:: 44Ot44OJ44OL44O8
+ # givenname;lang-ja:: <JapaneseGivenname>
+ sn;lang-ja:: 5bCP56yg5Y6f
+ # sn;lang-ja:: <JapaneseSn>
+ cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+ # cn;lang-ja:: <JapaneseCn>
+ title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
+ # title;lang-ja:: <JapaneseTitle>
+ preferredlanguage: ja
+ givenname:: 44Ot44OJ44OL44O8
+ # givenname:: <JapaneseGivenname>
+ sn:: 5bCP56yg5Y6f
+ # sn:: <JapaneseSn>
+ cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+ # cn:: <JapaneseCn>
+ title:: 5Za25qWt6YOoIOmDqOmVtw==
+ # title:: <JapaneseTitle>
+ givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
+ # givenname;lang-ja;phonetic::
+ <JapaneseGivenname_in_phonetic_representation_kana>
+ sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
+ # sn;lang-ja;phonetic:: <JapaneseSn_in_phonetic_representation_kana>
+ cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
+ # cn;lang-ja;phonetic:: <JapaneseCn_in_phonetic_representation_kana>
+ title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
+ # title;lang-ja;phonetic:: <JapaneseTitle_in_phonetic_representation_kana>
+ givenname;lang-en: Rodney
+ sn;lang-en: Ogasawara
+ cn;lang-en: Rodney Ogasawara
+ title;lang-en: Sales, Director
+
+ Example 5: A file containing a reference to an external file
+
+ version: 1
+ dn: cn=Horatio Jensen, ou=Product Testing, dc=airius, dc=com
+ objectclass: top
+ objectclass: person
+ objectclass: organizationalPerson
+ cn: Horatio Jensen
+ cn: Horatio N Jensen
+ sn: Jensen
+ uid: hjensen
+ telephonenumber: +1 408 555 1212
+ jpegphoto:< file:///usr/local/directory/photos/hjensen.jpg
+
+
+
+Good February 22, 1999 [Page 7]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ Example 6: A file containing a series of change records and comments
+
+ version: 1
+ # Add a new entry
+ dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
+ changetype: add
+ objectclass: top
+ objectclass: person
+ objectclass: organizationalPerson
+ cn: Fiona Jensen
+ sn: Jensen
+ uid: fiona
+ telephonenumber: +1 408 555 1212
+ jpegphoto:< file:///usr/local/directory/photos/fiona.jpg
+
+ # Delete an existing entry
+ dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
+ changetype: delete
+
+ # Modify an entry's relative distinguished name
+ dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
+ changetype: modrdn
+ newrdn: cn=Paula Jensen
+ deleteoldrdn: 1
+
+ # Rename an entry and move all of its children to a new location in
+ # the directory tree (only implemented by LDAPv3 servers).
+ dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
+ changetype: modrdn
+ newrdn: ou=Product Development Accountants
+ deleteoldrdn: 0
+ newsuperior: ou=Accounting, dc=airius, dc=com
+
+ # Modify an entry: add an additional value to the postaladdress attribute,
+ # completely delete the description attribute, replace the telephonenumber
+ # attribute with two values, and delete a specific value from the
+ # facsimiletelephonenumber attribute
+ dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
+ changetype: modify
+ add: postaladdress
+ postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
+ -
+ delete: description
+ -
+ replace: telephonenumber
+ telephonenumber: +1 408 555 1234
+ telephonenumber: +1 408 555 5678
+ -
+
+
+
+Good February 22, 1999 [Page 8]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ delete: facsimiletelephonenumber
+ facsimiletelephonenumber: +1 408 555 9876
+ -
+
+
+Security Considerations
+
+ Given typical directory applications, an LDIF file is likely to
+ contain sensitive personal data. Appropriate measures should be
+ taken to protect the privacy of those persons whose data is contained
+ in an LDIF file.
+
+ Since ":<" directives can cause external content to be included when
+ processing an LDIF file, one should be cautious of accepting LDIF
+ files from external sources. A "trojan" LDIF file could name a file
+ with sensitive contents and cause it to be included in a directory
+ entry, which a hostile entity could read via LDAP.
+
+ LDIF does not provide any method for carrying authentication
+ information with an LDIF file. Users of LDIF files must take care to
+ verify the integrity of an LDIF file received from an external
+ source.
+
+Appendix A: Differences from previous versions of this document
+
+ This section summarizes the differences between previous revisions of
+ this draft, as an aid to document reviewers. This section will be
+ deleted prior to publication as an RFC.
+
+ Differences between draft-ietf-asid-ldif-00.txt and draft-ietf-asid-
+ ldif-01.txt
+
+ 1) The BNF has been modified to explicitly disallow ldif content and
+ change records in the same file. In other words, a given LDIF file
+ is either a series of directory entries, or a series of
+ modifications. An LDIF file MUST NOT contain both types of records.
+
+ 2) External references are now URLs, instead of simple filenames.
+
+ 3) The BNF has been modified to allow base-64-encoded distinguished
+ names.
+
+ 4) Multiple separators are now permitted between records.
+
+ Differences between draft-ietf-asid-ldif-01.txt and draft-ietf-asid-
+ ldif-02.txt
+
+ 1) The BNF has been modified such that a simple attribute name
+
+
+
+Good February 22, 1999 [Page 9]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ ("attrname") has been replaced with an "attribute-description" as
+ defined in the LDAPv3 protocol document [4]. This permits language
+ codes and other attribute options to be carried in an LDIF file.
+
+ 2) A new option, "charset", may be used in attribute descriptions.
+ This facilitates multi-lingual character set conversion.
+
+ 3) The definition of the "safe" and "safe-initval" productions has
+ been relaxed to allow non-ASCII characters with values greater than
+ 126. This permits more natural expression of character sets such as
+ Latin-1 in LDIF files.
+
+ Differences between draft-ietf-asid-ldif-02.txt and draft-good-ldap-
+ ldif-00.txt
+
+ 1) The "charset-option" and "charset-name" productions were removed
+ from the BNF, due to objections within the working group. UTF-8 is
+ the only character set which may be used in LDIF.
+
+ 2) Examples were reworked to reflect the above change, and to include
+ an example of a non-western language represented in UTF-8.
+
+ Differences between draft-ietf-good-ldif-00.txt and draft-good-ldap-
+ ldif-01.txt
+
+ 1) Added version identifiers to the examples - they were missing.
+
+ 2) Clarified that LDIF file must use UTF-8.
+
+ Differences between draft-ietf-good-ldif-01.txt and draft-good-ldap-
+ ldif-02.txt
+
+ 1) Added a recommendation that values ending in SPACE should be
+ base-64 encoded.
+
+ 2) Clarified the procedure for joining folded lines.
+
+ 3) Updated header to reflect new IETF I-D guidelines.
+
+ Differences between draft-ietf-good-ldif-02.txt and draft-good-ldap-
+ ldif-03.txt
+
+ 1) Fixed reference from RFC 1779 to RFC 2253.
+
+ 2) Version string is now required.
+
+ 3) Comment lines may be folded (this is now explicitly mentioned in
+ note 2).
+
+
+
+Good February 22, 1999 [Page 10]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ 4) Moved this section (differences between draft versions) to an
+ appendix.
+
+ 5) Updated examples to use "dc=airius, dc=com" instead of "o=Ace
+ Industry, c=US"
+
+ 6) Cleaned up references section.
+
+
+Acknowledgments
+
+ The LDAP Interchange Format was developed as part of the University
+ of Michigan LDAP reference implementation, and was developed by Tim
+ Howes, Mark Smith, and Gordon Good. It is based in part upon work
+ supported by the National Science Foundation under Grant No. NCR-
+ 9416667.
+
+
+References
+
+
+ [1] Howes, T., Smith, M., "A MIME Content-Type for Directory Infor-
+ mation", RFC 2425, September 1998,
+ <URL:http://www.ietf.org/rfc/rfc2245.txt>
+
+ [2] Crocker, D.H., "Standard for the Format of ARPA Internet Text
+ Messages", RFC 822, August 1982,
+ <URL:http://ds.internic.net/rfc/rfc822.txt>
+
+ [3] Wahl, M., Kille, S., Howes, T., "A String Representation of Dis-
+ tinguished Names", RFC 2253,
+ <URL:http://www.ietf.org/rfc/rfc2253.txt>
+
+ [4] Wahl, M., Howes, T., Kille, S., "Lightweight Directory Access
+ Protocol (v3)", RFC 2251, July, 1997,
+ <URL:ftp://www.ietf.org/rfc/rfc2251.txt>
+
+ [5] Borenstein, N., Freed, N., "MIME (Multipurpose Internet Mail
+ Extensions) Part One: Mechanisms for Specifying and Describing
+ the Format of Internet Message Bodies", section 5.2, "Base64
+ Content-Transfer-Encoding", RFC 1521, December 1993,
+ <URL:http://ds.internic.net/rfc/rfc1521.txt>
+
+ [6] T. Berners-Lee, L. Masinter, M. McCahill, "Uniform Resource
+ Locators (URL)", RFC 1738, December 1994,
+ <URL:http://ds.internic.net/rfc/rfc1738.txt>
+
+ [7] S. Bradner, "Key Words for use in RFCs to Indicate Requirement
+
+
+
+Good February 22, 1999 [Page 11]
+\f
+INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999
+
+
+ Levels", Harvard University, RFC 2119, March 1997,
+ <URL:http://ds.internic.net/rfc/rfc2119.txt>
+
+ [8] The SLAPD and SLURPD Administrators Guide. University of Michi-
+ gan, April 1996. <URL:
+ http://www.umich.edu/~dirsvcs/ldap/doc/guides/slapd/toc.html>
+
+
+
+Author's Address
+
+ Gordon Good
+ Netscape Communications Corp.
+ 501 E. Middlefield Rd.
+ Mailstop MV068
+ Mountain View, CA 94043, USA
+ Phone: +1 650 937-3825
+ EMail: ggood@netscape.com
+
+ This Internet Draft expires August 22nd, 1999.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Good February 22, 1999 [Page 12]
+\f
--- /dev/null
+ Internet-Draft E. Stokes
+ LDAP Extensions WG D. Byrne
+ Intended Category: Standards Track B. Blakley
+ Expires: 25 December 1999 IBM
+ 25 June 1999
+
+ Access Control Model for LDAP
+ <draft-ietf-ldapext-acl-model-03.txt>
+
+ STATUS OF THIS MEMO
+
+ This document is an Internet-Draft and is in full
+ conformance with all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet
+ Engineering Task Force (IETF), its areas, and its working
+ groups. Note that other groups may also distribute
+ working documents as Internet-Drafts. Internet-Drafts are
+ draft documents valid for a maximum of six months and may
+ be updated, replaced, or obsoleted by other documents at
+ any time. It is inappropriate to use Internet- Drafts as
+ reference material or to cite them other than as "work in
+ progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+
+ The list of Internet-Draft Shadow Directories can be
+ accessed at http://www.ietf.org/shadow.html.
+
+ Comments and suggestions on this document are encouraged.
+ Comments on this document should be sent to the LDAPEXT
+ working group discussion list:
+
+ ietf-ldapext@netscape.com
+
+ COPYRIGHT NOTICE
+ Copyright (C) The Internet Society (1997). All Rights
+ Reserved.
+
+ ABSTRACT
+
+ This document describes the access control model for the
+ Lightweight Directory Application Protocol (LDAP)
+ directory service. It includes a description of the
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 1]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ model, the LDAP controls, and the extended operations to
+ the LDAP protocol. A separate document defines the
+ corresponding application programming interfaces (APIs).
+ RFC2219 [Bradner97] terminology is used.
+
+
+
+ 1. Introduction
+
+ The ability to securely access (replicate and distribute)
+ directory information throughout the network is necessary
+ for successful deployment. LDAP's acceptance as an
+ access protocol for directory information is driving the
+ need to provide an access control model definition for
+ LDAP directory content among servers within an enterprise
+ and the Internet. Currently LDAP does not define an
+ access control model, but is needed to ensure consistent
+ secure access across heterogeneous LDAP implementations.
+ The major objective is to provide a simple, but secure,
+ highly efficient access control model for LDAP while also
+ providing the appropriate flexibility to meet the needs
+ of both the Internet and enterprise environments and
+ policies. This document defines the model and the
+ protocol extensions (controls and extended operations).
+ A separate document defines the corresponding application
+ programming interfaces (APIs).
+
+
+ 2. Overview
+
+ Access Control mechanisms evaluate requests for access to
+ protected resources and make decisions about whether
+ those requests should be granted or denied. In order to
+ make a grant/deny decision about a request for access to
+ a protected resource, an access control mechanism needs
+ to evaluate policy data. This policy data describes
+ security-relevant characteristics of the requesting
+ subject and the rules which govern the use of the target
+ object.
+
+ This proposal defines the protocol elements for
+ transmission of this access control policy data in an
+ LDAP environment and an attribute that defines the access
+ control mechanism in effect for a given part of the LDAP
+ namespace. The instantiation of an access control model
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 2]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ at the directory server is not defined in this document.
+ By defining only what flows on the wire allows existing
+ access control mechanisms to be used at the directory
+ server.
+
+ No mechanisms are defined in this document to control
+ access to access control information or for storage of
+ access control information at the server; this is vendor
+ dependent.
+
+ A separate requirements document for access control
+ exists. The access control model used the requirements
+ documents as a guideline for the development of this
+ specification and are reflected in this specification to
+ the extent that the working group could agree on an
+ access control model.
+
+ The access control model defines
+
+ - A wire protocol for interoperability: The existing
+ LDAP protocol flows for add, delete, modify, etc are
+ used to manipulate access control information.
+ There are additional LDAP controls and extended
+ protocol operations defined to further help
+ management of access control information:
+ getEffectiveRights and specifyCredentials.
+
+ - A set of access control information (ACI) attributes
+ for application portability: These attributes are
+ used as input to the LDAP APIs so access control
+ information can be addressed uniformly independent
+ of how that information is addressed and stored at
+ the server. These same attributes appear in LDIF
+ output for interchange of access control
+ information.
+
+ - A set of attributes to identity the access control
+ mechanisms supported by a server.
+
+ Encoding of access control information on the wire is per
+ the LDAPv3 specifications.
+
+
+
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 3]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ 3. Terminology
+
+ An "access control list" contains the access control
+ policy information controlling access to an object or
+ collection of objects. An access control list consists
+ of a set of access control list entries.
+
+ An "access control list entry" defines a single subject
+ security attribute's granted rights for the objects
+ governed by the access control list to which it belongs.
+
+ The "access control policy information" (acpi) for an
+ object or a collection of objects defines which subject
+ security attributes entitle a subject to which granted
+ rights. The access control policy information for an
+ object is stored in an access control list.
+
+ An "access decision" is a boolean-valued function which
+ answers the question: "can the subject with these subject
+ security attributes perform this operation on this
+ object?"
+
+ An "access decision function" is an algorithm which makes
+ an access decision based on subject security attributes,
+ access control policy information, an object identifier,
+ and an operation name (possibly augmented by additional
+ contextual information).
+
+ An "access decision function interface" is a programmatic
+ interface through which applications can request an
+ access decision.
+
+ An "access identity" is an identity which is used by an
+ access decision function to make an access decision.
+
+ An "audit identity" is an identity which does not, in the
+ absence of additional information, enable a party
+ receiving and examining it to determine which subject it
+ belongs to.
+
+ A "credential" is a collection of subject security
+ attributes.
+
+ "effective rights" are the complete set of rights a
+ subject is entitled to based on all access control lists
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 4]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ which apply to a specific object and based on all of the
+ subject's security attributes.
+
+ "granted rights" are the complete set of rights an access
+ control list entitles a subject to based on a specific
+ subject security attribute.
+
+ A "group" is a privilege attribute asserting a subject's
+ membership in the collection of subjects whose name is
+ that of the group.
+
+ An "identity" is a subject security attribute which is
+ unique to a single subject.
+
+ An "object" is the target of operations in an information
+ system.
+
+ An "operation" is the result of executing the code
+ accessed through a named entry point in an information
+ system.
+
+ An "operation name" is the name of the entry point
+ through which an operation is invoked in an information
+ system.
+
+ A "privilege attribute" is a subject security attribute
+ which may be shared by several subjects.
+
+ "required rights" are the complete set of rights needed
+ to authorize a requester to perform a specific operation
+ on an object of a specific type.
+
+ A "right" is the basic unit of access control policy
+ administration. For each object type in an information
+ system, a security administrator defines a set of
+ required rights for each operation. For each object in
+ the system, a security administrator defines a set of
+ granted rights for each subject security attribute. When
+ an access decision is required, an access decision
+ function checks to make sure that the requester's subject
+ security attributes have been granted all required rights
+ needed to perform the requested operation on the
+ specified target object.
+
+ A "role" is a privilege attribute asserting a subject's
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 5]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ organizational position and entitlement to perform the
+ operations appropriate to that organizational position.
+
+ A "subject" is an entity which intiates actions in an
+ information system.
+
+ A "subject security attribute" is a defined property
+ which is used by a security policy evaluation system to
+ make policy decisions.
+
+
+ 4. The Model
+
+
+ 4.1 Access Control Activity Lifecycle
+
+ The access control proposal described in this draft
+ addresses four activities:
+
+ - Creation of subject security attribute information
+ and access control policy information
+
+ - Retrieval of subject security attribute information
+ at the time an access request is made
+
+ - Evaluation of access requests against policy,
+ resulting in an access decision
+
+ - Replication of access control policy information
+ from one server to another
+
+ 4.2 Access Control Information Model
+
+ This document does not define formats for storage of
+ access control information; it does define the
+ operational semantics of access control operations.
+
+
+
+
+
+
+
+
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 6]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ The diagram below illustrates the componentry of an LDAP
+ system and the placement of the function specified in
+ this draft.
+
+ +-------------+
+ | Application |
+ +-------------+
+ +--------+
+ | LDAP |
+ | Client |
+ +--------+
+ |
+ |
+ | <-- LDAP Extended Access Control
+ Controls
+ | or Extended Access Control
+ Operations
+ v
+ +-----------------------------+
+ | LDAP Server (e.g. SLAPD) |
+ +-----------------------------+
+ . |
+ . |
+ . |
+ . |
+ v v
+ +----------+ +-----------+
+ | Access | | |
+ | Control |<.....| Datastore |
+ | Manager | | |
+ +----------+ +-----------+
+
+ LDAP clients use the controls and extended operations
+ specified in this document to administer access control
+ policy enforced by LDAP servers. Servers may store
+ access control information in any way they choose. In
+ particular, servers may use the access control mechanisms
+ of their datastores to store and enforce LDAP access
+ control, or they may implement access control managers
+ external to their datastores. Datastores and external
+ access control managers may implement any access control
+ rule syntax and semantics they choose, as long as the
+ semantics is compatible with that defined in the section
+ titled "Operational Semantics of Access Control
+ Operations" (found after the control and extended
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 7]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ operation definition).
+
+ The access control administration mechanisms specified in
+ this document are neutral with respect to policy
+ inheritance mechanisms, explicit vs. implicit denial,
+ and group nesting.
+
+ 4.3 Bind and Credentials
+
+ A bind authenticates a principal to the directory. A
+ principal is represented by a DN. A principal has a set
+ of credentials that are used for determining whether
+ access to resources specified in ldap operations. These
+ credentials may be pushed to the server by the client or
+ may be pulled by the server from the directory data.
+ Credentials may be local with respect to the server. If
+ not local (owned by another server or administrative
+ scope), then the server may decide to define a trust
+ model that states how to evaluate the trust of a
+ credential at bind time. The definition of such a trust
+ model is outside the scope of this document.
+
+
+ 5. Access Control Information Schema
+
+
+ 5.1 Attributes
+
+
+ 5.1.1 Root DSE Attribute for Access Control Mechanism
+
+ The following attribute may be included in the Root DSE.
+
+ (<OID to be assigned>
+ NAME 'supportedACIMechanisms'
+ DESC list of access control mechanisms supported
+ by this directory server
+ SYNTAX LDAPOID
+ )
+
+ Two access control mechanisms are defined by this
+ document:
+ LDAPv3 <OID to be assigned>
+ X500 <OID to be assigned>
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 8]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ Other vendor access control mechanisms can be defined (by
+ OID) and are the responsibility of those vendors to
+ provide the definition and OID.
+
+ 5.1.2 Subschema Attribute for Access Control Mechanism
+
+ A given naming context must provide information about
+ which access control mechanism is in effect for that
+ portion of the namespace. The following attribute must
+ be in each subschema entry associated with a naming
+ context whose access control mechanism is different from
+ adjacent naming contexts supported by that directory
+ server.
+
+ - aCIMechanism lists the value (an OID) that defines
+ the access control mechanism in effect for the scope
+ of that subschema entry
+
+ 5.2 Other Defined Parameters/OIDs
+
+
+ 5.2.1 Rights Families and Rights
+
+ The following rights families are defined:
+ LDAPv3 <OID to be assigned>
+ X500 <OID to be assigned>
+
+ Other parties can (and will) define other rights
+ families. It is the responsibility of those parties to
+ provide the definition and OID.
+
+ 5.2.1.1 LDAPv3 Rights Family
+
+ Access rights can apply to an entire object or to
+ attributes of the object. Each of the LDAP access rights
+ are discrete. One permission does not imply another
+ permission. The rights may be ORed together to provide
+ the desired rights list.
+
+ Rights which apply to attributes are:
+
+ 1 Read Read attribute values
+ 2 Write Write attribute values
+ 4 Search Search entries with specified attributes
+ 8 Compare Compare attributes
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 9]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ Rights that apply to an entire object are:
+
+ 16 Add Add an object below this object
+ 32 Delete Delete this object
+ 64 EditDN Edit an object's DN
+
+ Rights that apply to the object to which the directory
+ object points are:
+
+ 128 Manage Perform a privileged operation; used to
+ restrict access to operations which
+ read or write especially sensitive data
+ 256 Use Execute; useful in controlling access to
+ the objects referred to by directory
+ entries than in controlling access to
+ the directory entries themselves
+ 512 Get Get retrieves the attribute values
+ 1024 Set Set writes the attribute values
+
+ 5.2.1.2 The X.500 Rights Family
+
+ <define the rights for X.500>
+
+ 5.2.2 DN Types
+
+ The following DN Types are defined:
+
+ - access-id, OID=<OID to be assigned>
+
+ - group, OID=<OID to be assigned>
+
+ - role, OID=<OID to be assigned>
+
+ access-id, group, and role MUST be supported. An acess-
+ id is a non-collection (non-group and non-role objects)
+ DN that can be authenticated.
+
+ Other parties can (and will) define other DN Types. It
+ is the responsibility of those parties to provide the
+ definition and OID.
+
+
+
+
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 10]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ 6. Access Control Parameters for LDAP Controls & Extended
+ Operations
+
+ This section defines the parameters used in the access
+ control LDAP controls and extended operations in this
+ document.
+
+ targetDN specifies the initial directory entry in DN
+ syntax on which the control or extended operation is
+ performed.
+
+ whichObject specifies whether the access control
+ information which is get/set is for the target directory
+ entry (ENTRY) or the target directory entry and its
+ subtree (SUBTREE).
+
+ rightsFamily specifies the family of rights that will be
+ get/set for the control or extended operation performed.
+ A rights family has a defined set of rights.
+
+ rightsList in the SearchResultEntry is of the form
+ specified in the LDIF BNF for <right>.
+
+ dnType speficies the type of subject security attribute.
+ Defined types are access-id, group, and role.
+
+ subjectDN is a LDAP string that defines the subject or
+ value of the dnType. The subjectDN may be a DN or
+ another string such as IPAddress (dotted-decimal string
+ representation) on which access control is get/set. If
+ the subject is an entry in the directory, then the syntax
+ of the LDAP string is DN. We define two well-known
+ subjectDNs, the strings
+
+ - public - meaning public access for all users
+
+ - this - meaning the user whose name matches the entry
+ being accessed
+
+ Four operations are defined:
+
+ - ACI_GRANT grants the rights specified in the
+ rightsList for the given subject. If an access
+ control list does not exist for the specified
+ entry/attribute, then the access control list is
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 11]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ created with the granted rights for the given
+ subject. If the access control list already exists
+ for the specified entry/attribute, then the access
+ control list is modified to grant the rights for the
+ given subject.
+
+ - ACI_DENY denies the rights specified in the
+ rightsList for the given subject. No implementation
+ is implied for this operation. For example, denial
+ of rights may be implemented as explicit denial
+ (negative rights) on the access control list or
+ removal of rights from the access control list.
+
+ - ACI_REPLACE replaces the entire access control list
+ for the specified entry/attribute. If an access
+ control list does not exist for the specified
+ entry/attribute, then the access control list is
+ created with the granted rights for the given
+ subject.
+
+ - ACI_DELETE deletes the entire access control list
+ for the specified entry/attribute.
+
+ attrs specifies the list of attributes against which the
+ operation is performed. attrs can be defined using a
+ LDAP filter expression.
+
+
+ 7. Access Control Information (ACI) Controls
+
+ The access control information controls provide a way to
+ manipulate access control information in conjunction with
+ an LDAP operation such as ldap_add, ldap_modify, or
+ ldap_search. Three LDAP controls are defined for
+ transmission of access control information. These
+ controls allow access control information to be get/set
+ while manipulating other directory information. The
+ controls are:
+
+ - getEffectiveRights to obtain the effective rights
+ for a given directory entry(s) for a given subject
+ during a ldap_search operation
+
+ - specifyCredentials to specify a set of credentials
+ for the bind identity (DN) during a ldap_bind
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 12]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ operation
+
+ 7.1 getEffectiveRights Control
+
+
+ 7.1.1 Request Control
+
+ This control is included in the ldap_search message as
+ part of the controls field of the LDAPMessage, as
+ defined in Section 4.1.12 of [LDAPv3].
+
+ The controlType is set to <OID to be assigned>. The
+ criticality MAY be either TRUE or FALSE (where absent is
+ also equivalent to FALSE) at the client's option. The
+ controlValue is an OCTET STRING, whose value is the BER
+ encoding of a value of the following SEQUENCE:
+
+ getEffectiveRightsRequest ::= SEQUENCE {
+ targetDN LDAPDN,
+ effectiveRightsRequest SEQUENCE OF SEQUENCE {
+ rightsFamily LDAPOID | "*",
+ whichObject ENUMERATED {
+ LDAP_ENTRY (1),
+ LDAP_SUBTREE (2)
+ },
+ dnType LDAPOID | "*",
+ subjectDN LDAPString,
+ }
+ }
+
+ The targetDN specifies the initial directory entry in DN
+ syntax on which the getEffectiveRights control is
+ performed. request is a set of sequences that state the
+ whichObject (entry or entry plus subtree) and specifics
+ of the control request to be performed. One or more
+ rightsFamily can be be obtained for a given subjectDN ad
+ dnType. A "*" in the rightsFamily field indicates that
+ the rights for all rights families defined for the
+ subjectDN / dnType are to be returned. This control is
+ applied to the scope set by the ldap_search operation,
+ i.e. base, one-level, subtree.
+
+ 7.1.2 Response Control
+
+ This control is included in the ldap_search_response
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 13]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ message as part of the controls field of the LDAPMessage,
+ as defined in Section 4.1.12 of [LDAPv3].
+
+ The controlType is set to <OID to be assigned>. The
+ criticality MAY be either TRUE or FALSE (where absent is
+ also equivalent to FALSE). The controlValue is an OCTET
+ STRING, whose value is the BER encoding of a value of the
+ following SEQUENCE:
+
+ getEffectiveRightsResponse ::= {
+ result ENUMERATED {
+ success (0),
+ operationsError (1),
+ unavailableCriticalExtension (12),
+ noSuchAttribute (16),
+ undefinedAttributeType (17),
+ invalidAttributeSyntax (21),
+ unavailable (52),
+ unwillingToPerform (53),
+ other (80)
+ }
+ }
+
+ The effective rights returned are returned with each
+ entry returned by the search result. The control
+ response for ldap_search is:
+
+ PartialEffectiveRightsList ::= SEQUENCE OF SEQUENCE {
+ rightFamily LDAPOID,
+ rightsList ENUMERATED,
+ whichObject ENUMERATED {
+ LDAP_ENTRY (1),
+ LDAP_SUBTREE (2)
+ }
+ }
+
+ Although this extends the search operation, there are no
+ incompatibilities between versions. LDAPv2 cannot send a
+ control, hence the above structure cannot be returned to
+ a LDAPv2 client. A LDAPv3 client cannot send this
+ request to a LDAPv2 server. A LDAPv3 server not
+ supporting this control cannot return the additional
+ data.
+
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 14]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ 7.1.3 Client-Server Interaction
+
+ The getEffectiveRightsRequest control requests the rights
+ that MUST be in effect for requested directory
+ entry/attribute based on the subject DN. The server that
+ consumes the search operation looks up the rights for the
+ returned directory information based on the subject DN
+ and returns that rights information.
+
+ There are six possible scenarios that may occur as a
+ result of the getEffectiveRights control being included
+ on the search request:
+
+
+ 1. If the server does not support this control and the
+ client specified TRUE for the control's criticality
+ field, then the server MUST return
+ unavailableCriticalExtension as a return code in
+ the searchResponse message and not send back any
+ other results. This behavior is specified in
+ section 4.1.12 of [LDAPv3].
+
+ 2. If the server does not support this control and the
+ client specified FALSE for the control's
+ criticality field, then the server MUST ignore the
+ control and process the request as if it were not
+ present. This behavior is specified in section
+ 4.1.12 of [LDAPv3].
+
+ 3. If the server supports this control but for some
+ reason such as cannot process specified
+ rightsFamily and the client specified TRUE for the
+ control's criticality field, then the server SHOULD
+ do the following: return
+ unavailableCriticalExtension as a return code in
+ the searchResult message.
+
+ 4. If the server supports this control but for some
+ reason such as cannot process specified
+ rightsFamily and the client specified FALSE for the
+ control's criticality field, then the server should
+ process as 'no rights returned for that family' and
+ include the result Unavailable in the
+ getEffectiveRightsResponse control in the
+ searchResult message.
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 15]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ 5. If the server supports this control and can return
+ the rights per the rightsFamily information, then
+ it should include the getEffectiveRightsResponse
+ control in the searchResult message with a result
+ of success.
+
+ 6. If the search request failed for any other reason,
+ then the server SHOULD omit the
+ getEffectiveRightsResponse control from the
+ searchResult message.
+
+ The client application is assured that the correct rights
+ are returned for scope of the search operation if and
+ only if the getEffectiveRightsResponse control returns
+ the rights. If the server omits the
+ getEffectiveRightsResponse control from the searchResult
+ message, the client SHOULD assume that the control was
+ ignored by the server.
+
+ The getEffectiveRightsResponse control, if included by
+ the server in the searchResponse message, should have the
+ getEffectiveRightsResult set to either success if the
+ rights are returned or set to the appropriate error code
+ as to why the rights could not be returned.
+
+ The server may not be able to return a right because it
+ may not exist in that directory object's attribute; in
+ this case, the rights request is ignored with success.
+
+ 7.2 specifyCredentials Control
+
+
+ 7.2.1 Request Control
+
+ This control is included in the ldap_bind message as
+ part of the controls field of the LDAPMessage, as
+ defined in Section 4.1.12 of [LDAPv3].
+
+ The controlType is set to <OID to be assigned>. The
+ criticality MAY be either TRUE or FALSE (where absent is
+ also equivalent to FALSE) at the client's option. The
+ controlValue is an OCTET STRING, whose value is the BER
+ encoding of a value of the following SEQUENCE:
+
+ specifyCredentialRequest ::= SEQUENCE {
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 16]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ credential LDAPString
+ }
+ }
+
+ The credential specifies the credential (e.g. groups,
+ roles, etc) that the client is requesting be associated
+ with the bind DN for access control determination in
+ subsequent ldap operations. This provides a 'push' model
+ for credentials where the client attempts to 'push' the
+ credential to the server. The server may process at bind
+ time as follows:
+
+ - server may unconditionally ignore
+
+ - server may unconditionally accept
+
+ - server may define trust model and evaluate of the
+ trust of each credential
+
+ If this control is not used, it is assumed that the
+ server determines (pulls) the credentials associated with
+ the bind DN when needed in subsequent ldap operations to
+ provide access control.
+
+ 7.2.2 Response Control
+
+ This control is included in the ldap_bind message as part
+ of the controls field of the LDAPMessage, as defined in
+ Section 4.1.12 of [LDAPv3].
+
+ The controlType is set to <OID to be assigned>. The
+ criticality MAY be either TRUE or FALSE (where absent is
+ also equivalent to FALSE). The controlValue is an OCTET
+ STRING, whose value is the BER encoding of a value of the
+ following SEQUENCE:
+
+ specifyCredentialsResponse ::= {
+ result ENUMERATED {
+ success (0),
+ operationsError (1),
+ unavailableCriticalExtension (12),
+ unavailable (52),
+ unwillingToPerform (53),
+ other (80)
+ }
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 17]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ }
+
+ No data is returned; just the result is returned.
+
+ Although this extends the bind operation, there are no
+ incompatibilities between versions. LDAPv2 cannot send a
+ control. A LDAPv3 client cannot send this request to a
+ LDAPv2 server. A LDAPv3 server not supporting this
+ control cannot return the additional data.
+
+ 7.2.3 Client-Server Interaction
+
+ The specifyCredentialsRequest control specifies the
+ credentials that the client wants the server to use for
+ access control in subsequent ldap operations. The server
+ that consumes the bind operation may unconditionally
+ accept, ignore, or evaluate the trust of the specified
+ credentials at bind time and returns only a success or
+ failure response (no data returned).
+
+ There are six possible scenarios that may occur as a
+ result of the specifyCredential control being included on
+ the bind request:
+
+
+ 1. If the server does not support this control and the
+ client specified TRUE for the control's criticality
+ field, then the server MUST return
+ unavailableCriticalExtension as a return code in
+ the bindResponse message. This behavior is
+ specified in section 4.1.12 of [LDAPv3].
+
+ 2. If the server does not support this control and the
+ client specified FALSE for the control's
+ criticality field, then the server MUST ignore the
+ control and process the request as if it were not
+ present. This behavior is specified in section
+ 4.1.12 of [LDAPv3].
+
+ 3. If the server supports this control but for some
+ reason such as cannot process specified credential
+ (e.g. server decided to evaluate the trust of that
+ credential and the result is the server not
+ trusting all the credentials or unconditionally
+ ignores the credential) and the client specified
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 18]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ TRUE for the control's criticality field, then the
+ server SHOULD do the following: return
+ unavailableCriticalExtension as a return code in
+ the bindResult message and omit the
+ specifyCredentialResponse control in the bindResult
+ message.
+
+ 4. If the server supports this control but for some
+ reason such as cannot process specified credential
+ (e.g. server decided to evaluate the trust of that
+ credential and the result is the server not
+ trusting all the credentials or unconditionally
+ ignores the credential) and the client specified
+ FALSE for the control's criticality field, then the
+ server should process as 'credential ignored' and
+ include the result Unavailable in the
+ specifyCredentialResponse control in the bindResult
+ message.
+
+ 5. If the server supports this control and evaulates
+ the trust of that credential and the result is the
+ server trusting all the credentials, then it should
+ include the specifyCredentialResponse control in
+ the bindResult message with a result of success.
+
+ 6. If the bind request failed for any other reason,
+ then the server SHOULD omit the
+ specifyCredentialResponse control from the
+ bindResult message.
+
+ The client application is assured that the correct
+ credentials are used by the server when specified by the
+ client for subsequent ldap operations if and only if the
+ specifyCredentialResponse is successful. If the server
+ omits the specifyCredentialResponse control from the
+ bindResponse message, the client SHOULD assume that the
+ control was ignored by the server.
+
+ The specifyCredentialResponse control, if included by the
+ server in the bindResponse message, should have the
+ bindResult set to either success if the credentials were
+ accepted by the server or set to the appropriate error
+ code as to why the credentials were not accepted.
+
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 19]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ 8. Access Control Extended Operations
+
+ Two extended operations (analogous to the controls) are
+ defined for transmission of access control information.
+ These operations help with the management of access
+ control information independent of manipulating other
+ directory information. The extended operations are:
+
+ - LDAP Get Effective Rights to obtain the effective
+ rights for a given directory entry for a given
+ subject
+
+ 8.1 LDAP Get Effective Rights Operation
+
+ ldapGetEffectiveRightsRequest ::= [APPLICATION 23]
+ SEQUENCE {
+ requestName [0] <OID to be assigned>,
+ requestValue [1] OCTET STRING OPTIONAL }
+
+ where
+
+ requestValue ::= SEQUENCE {
+ targetDN LDAPDN,
+ updates SEQUENCE OF SEQUENCE {
+ rightsFamily LDAPOID | "*",
+ whichObject ENUMERATED {
+ LDAP_ENTRY (1),
+ LDAP_SUBTREE (2)
+ },
+ dnType LDAPOID | "*",
+ subjectDN LDAPString,
+ }
+ }
+
+
+ The requestName is a dotted-decimal representation of the
+ OBJECT IDENTIFIER corresponding to the request. The
+ requestValue is information in a form defined by that
+ request, encapsulated inside an OCTET STRING.
+
+ The server will respond to this with an LDAPMessage
+ containing the ExtendedResponse which is a rights list.
+
+ ldpGetEffectiveRightsResponse ::= [APPLICATION 24]
+ SEQUENCE {
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 20]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ COMPONENTS OF LDAPResult,
+ responseName [10] <OID to be assigned> OPTIONAL,
+ effectiveRights [11] OCTET STRING OPTIONAL }
+
+ where
+
+ effectiveRights ::= SEQUENCE OF SEQUENCE {
+ rightFamily LDAPOID,
+ rightsList ENUMERATED,
+ whichObject ENUMERATED {
+ LDAP_ENTRY (1),
+ LDAP_SUBTREE (2)
+ },
+ subjectDnType LDAPOID,
+ subjectDN LDAPSTRING
+ }
+
+ If the server does not recognize the request name, it
+ MUST return only the response fields from LDAPResult,
+ containing the protocolError result code.
+
+
+
+ 9. Access Control Information Attributes/LDIF
+
+ The intent of the following attribute definitions is to
+ design a common interchange format. Any given LDAP server
+ should be able to translate the below defined attributes
+ into a meaningful operation requests. Each server should be
+ able to understand the attributes; there should not be any
+ ambiguity into what any part of the syntax means.
+
+ While the end goal is to have a common behavior model
+ between different LDAP server implementations, the attribute
+ definition alone will not ensure identical ACL processing
+ behavior between servers. The semantics of how a server
+ interprets the ACI syntax are not defined here. What 'deny'
+ means on server1 might be different than on server2.
+ Additionally, while the server must recognize and act on the
+ attribute when received over the wire, there are no
+ requirements for the server to actually implement this
+ attribute.
+
+ The attribute definition maintains an assumption that the
+ receiving server supports inheritance within the security
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 21]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ model. If the server does not support inheritance, the
+ receiving server must expand any inherited information based
+ on the scope flag.
+
+
+ 9.1 ACI Attributes
+
+ There are three attributes which may be queried or set on
+ all directory objects: aci, vendorAci and policyOwner. The
+ syntax of these attributes is defined below.
+
+
+ 9.1.1 The BNF
+
+ < aci > ::= < acl syntax >
+
+ < vendorAci > ::= <oid> + '#' + < printable string >
+
+ < acl syntax > ::= <familyOID> + '#' + <scope > + '#'
+ + < rights > + '#' + < dnType >
+ + '#' + < subjectDn >
+
+ < policyOwner > ::= < familyOid > + '#' + <scope >
+ + '#' +< dnType > + '#' + < subjectDn >
+
+ < subjectDn > ::= < printable string >
+
+ < familyOid > ::= < oid >
+
+ <scope > ::= "entry" | "subtree" | <level>
+
+ < level > ::= numericstring
+
+ < dnType > ::= "access-id" | "role" | "group"
+
+ < rights > ::= [ ] | [ < right > + [ '$'
+ + <right> ] * ]
+
+ < right > ::= <action > + ';' + <permissions>
+ + ';' + <attrs>
+
+ < action > ::= "grant" | "deny"
+
+ < permissions > ::= [ ] | [ < permission >
+ + [ ',' + <permission> ] * ]
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 22]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ < attrs > ::= [ < attributeString>
+ + [ ',' + < attributeString > ] * ]
+
+ < attributeString > ::= "[all]" | "[entry]"
+ | <printableString >
+
+ < permission > ::= "a" | "d" | "r" | "s" | "w" |
+ "c" | "g" | "s" | "m" | "u" | "e"
+
+ These are the permissions defined for the IETF family OID.
+ "a" corresponds to add
+ "d" corresponds to delete
+ "r" corresponds to read
+ "w" corresponds to write
+ "c" corresponds to compare
+ "g" corresponds to get
+ "s" corresponds to set
+ "m" corresponds to manage
+ "u" corresponds to use
+ "e" corresponds to editDn
+
+
+ 9.1.2 VendorACI
+
+ ( vendorAciOID NAME 'vendorACI' DESC 'Vendor specific
+ Access control information' EQUALITY caseIgnoreMatch SYNTAX
+ directoryString )
+
+ The Vendor specific ACI information is listed in its own
+ attribute. This may be used by vendors to provide vendor
+ specific access control related information which can not be
+ expressed in defined ACISyntax. Within the vendorACI, the
+ oid determines the format or the printable string to follow.
+
+
+ 9.1.3 Policy Owner
+
+ ( policySyntaxOID DESC 'PolicyOwner Syntax' ) (
+ policyOwnerOID NAME 'policyOwner' DESC 'Policy Owner Access
+ Control Information' EQUALITY caseIgnoreMatch SYNTAX
+ policySyntaxOID )
+
+ Policy ownership controls administrative subdomains. It can
+ also control who has permission to set / change acls for
+ implementations that do not have ACI controlling access to
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 23]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ itself. If there are multiple policy owners it is
+ implementation specific as to the behavior of whether policy
+ owner #1 can override policy owner # 2.
+
+ The syntax for policyOwner includes the 'scope' flag.
+ Servers which do not support inheritance must expand the
+ policyOwner inheritance similar to the expansion of the ACI.
+ The scope and any inheritance hierarchy for policy ownership
+ is distinct from any inheritance hierarchy defined for ACI
+ values.
+
+ If the policy owner is not specified for any object in the
+ tree, behavior is implementation defined. For instance, if
+ no object anywhere in the tree has a policy owner, then the
+ server could simply assert that the 'root DN' is considered
+ the policy owner for all objects. An alternate approach
+ might be that the implementation defines the entryDN to be
+ the policy owner.
+
+
+ 9.1.4 ACI
+
+ ( aciSyntaxOID DESC 'ACI Syntax' )
+ ( aciOID NAME 'aci' DESC 'Access control information'
+ EQUALITY caseIgnoreMatch SYNTAX aciSyntaxOID )
+
+ Within the access control syntax, the family OID describes
+ the permissions, dnType, subjectDn and scope that will be
+ found in the following string. If the OID within the ACI
+ attribute is listed as other than the IETF family oid, the
+ syntax is the same as listed below, but one or more of the
+ scope, dnType, subjectDn or permissions may vary from the
+ IETF defined syntax.
+
+ Within the access control syntax, there is a string which
+ describes the rights. This is a composite of the permissions
+ and resources to which the user is being granted or denied
+ access. The set of permissions is fixed. Either of the
+ actions "grant" | "deny" may be used when creating or
+ updating ACI.
+
+ The attributeString is an attribute Name (defined to be a
+ printable string). If the string refers to an attribute not
+ defined in the given server's schema, the server SHOULD
+ report an error. Another option for the attributeString is
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 24]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ "[entry]". This is provided to describe permissions which
+ apply to an entire object. This could mean actions such as
+ delete the object, or add a child object. The third option
+ for attributeString is "[all]" which means the permission
+ set should apply to all attributes.
+
+ If the keyword "[all]" and another attribute are both
+ specified within an aci, the more specific permission set
+ for the attribute overrides the less specific permission set
+ for "[all]".
+
+ If two ACIs contain identical familyOID, scope, DnTypes and
+ DNs, the permission given DN is specified in two distinct
+ acis on any given entry, the rights lists can be combined
+ into one list. For example,
+
+ aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ
+ aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ
+
+ is the equivalent of
+
+ aci: 1.2.3.4#subtree#grant;r,w;[all];
+ r,attribute1#group#cn=Dept XYZ
+
+ Using the defined BNF it is possible for the permission
+ string to be empty. The ACI
+
+ aci: 1.2.3.4#subtree#grant;;attribute1$grant;r,s;
+ [all]#group#cn=Dept XYZ,c=US
+
+ means that this group is granted permission to read and
+ search all attributes except attribute1.
+
+ Similarly, the ACI
+
+ aci: 1.2.3.4#subtree##group#cn=Dept XYZ, c=US
+
+ simply means that no permissions have been defined for this
+ group. It is up to the server implementation as to whether
+ the group does or does not receive permission to attributes
+ on an entry with an empty rights list.
+
+ Multiple attributeStrings can be listed after any given
+ permission set; for instance, "r,w ; attribute1,
+ attribute2". This means that if the server supports a
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 25]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ attribute aggregation mechanism, attribute1 and attribute2
+ should be considered to be part of the same group. If the
+ server does not support a grouping mechanism, the permission
+ set applies independently to attribute1 and attribute2. For
+ servers that do not support attribute grouping, "grant ; r,w
+ ; attribute1, attribute2" results in the same operations as
+ "grant ; r,w; attribute1$grant; r,w; attribute2"
+
+
+ 9.1.5 LDAP Operations
+
+ The attributes which are defined for access control
+ interchange may be used in all LDAP operations.
+
+ Within the ldapmodify-delete operation, the entire acl may
+ be deleted by specifying
+
+ dn: cn = some Entry
+ changetype: modify
+ delete: aci
+
+ In this case, the entry would then inherit its ACI from some
+ other node in the tree depending on the server inheritance
+ model.
+
+ Deleting the last ACI value from an entry is not the same as
+ deleting the ACI from the entry. It is possible for an entry
+ to contain an ACI with no values. In this case, nothing is
+ returned to the client when querying the aci. It is server
+ dependent whether access is granted or denied in the absence
+ of any ACI information. Deleting an ACI value which does
+ not exist will result in an unchanged ACI and a return code
+ specifying that the attribute value does not exist.
+
+
+ 9.2 Examples
+
+
+ 9.2.1 Attribute Definition
+
+ Pretend IETFFamilyOID = 1.2.3.4
+
+ The following two examples show an administrative
+ subdomain being established. The first example shows a
+ single user being assigned the policyOwner for the entire
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 26]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ domain. The second example shows a group of ids assigned
+ to the policy Owner.
+
+ policyOwner: 1.2.3.4#subtree#access-id#cn=Hoyt
+
+ policyOwner: 1.2.3.4#subtree#group#cn=System Owners,
+ o=Company
+
+ The next example shows an aci attribute where a group
+ "cn=Dept XYZ, c=US" is being given permissions to read,
+ search and compare attribute1. The permission should
+ apply to the entire subtree below the node containing
+ this ACI.
+
+ aci:1.2.3.4#subtree#grant;r,s,c;
+ attribute1#group#cn=Dept XYZ,c=US
+
+ The next example shows an ACI attribute where a role
+ "cn=SysAdmins,o=Company" is being given permissions to
+ add objects below this node, and read, search and compare
+ attributes 2 and 3. The permission should apply to the
+ entire subtree below the node containing this ACI.
+
+ aci: 1.2.3.4#subtree#grant;a;[entry]$grant;
+ r,s,c;attribute2, attribute3#role#
+ cn=SysAdmins,o=Company
+
+
+ 9.2.2 Modifying the ACI Values
+
+ Replace works similarly to all other attributes. If the
+ attribute value does not exist, create the value. If the
+ attribute does exist, replace the value. If the ACI value
+ is replaced, all ACI values are replaced.
+
+ A given aci for an entry:
+
+ aci: 1.2.3.4#subtree#deny;r,w;[all]$grant;r,s,c;
+ attribute2#group#cn=Dept ABC
+
+ aci: 1.2.3.4#subtree#grant;r;[all]$grant;r,s,c;
+ attribute1#group#cn=Dept XYZ
+
+ perform the following change:
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 27]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ dn: cn=someEntry
+ changetype: modify
+ replace: aci
+ aci: 1.2.3.4#subtree#grant;r,w;[all];#group#cn=Dept LMN
+
+ The resulting acl is:
+
+ aci: 1.2.3.4#subtree#grant;r,w;[all];#group#cn=Dept LMN
+
+ ( aci values for Dept XYZ and ABC are lost through the
+ replace )
+
+ During an ldapmodify-add, if the ACI does not exist, the
+ create the ACI with the specific aci value(s). If the ACI
+ does exist, then add the specified values to the given ACI.
+ For example a given ACI:
+
+ aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ
+
+ with a modification:
+
+ dn: cn=someEntry
+ changetype: modify
+ add: aci
+ aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ
+
+ would yield an multi-valued aci of:
+
+ aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ
+ aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ
+ To delete a particular aci value, use the regular ldapmodify
+ - delete syntax
+
+ Given an ACI of:
+
+ aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ
+ aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ
+
+ dn: cn = some Entry
+ changetype: modify
+ delete: aci
+ aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ
+
+ would yield a remaining ACI on the server of
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 28]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ
+
+
+
+ 10. Security Considerations
+
+ This draft proposes protocol elements for transmission of
+ security policy information. Security considerations are
+ discussed throughout this draft. Because subject
+ security attribute information is used to evaluate
+ decision requests, it is security-sensitive information
+ and must be protected against unauthorized modification
+ whenever it is stored or transmitted.
+
+
+
+ 11. References
+
+ [LDAPv3] M. Wahl, T. Howes, S. Kille, "Lightweight
+ Directory Access Protocol (v3)", RFC 2251, December 1997.
+
+ [ECMA] ECMA, "Security in Open Systems: A Security
+ Framework" ECMA TR/46, July 1988
+
+ [REQTS] Stokes, Byrne, Blakley, "Access Control
+ Requirements for LDAP, INTERNET-DRAFT <draft-ietf-
+ ldapext-acl-reqts-01.txt>, August 1998.
+
+ [ATTR] M.Wahl, A, Coulbeck, T. Howes, S. Kille,
+ "Lightweight Directory Access Protocol (v3)": Attribute
+ Syntax Definitions, RFC 2252, December 1997.
+
+ [UTF] M. Wahl, S. Kille, "Lightweight Directory Access
+ Protocol (v3)": A UTF-8 String Representation of
+ Distinguished Names", RFC 2253, December 1997.
+
+ [Bradner97] Bradner, Scott, "Key Words for use in RFCs to
+ Indicate Requirement Levels", RFC 2119.
+
+
+ AUTHOR(S) ADDRESS
+
+ Ellen Stokes Bob Blakley
+ IBM Dascom
+ 11400 Burnet Rd 5515 Balcones Drive
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 29]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+ Austin, TX 78758 Austin, TX 78731
+ USA USA
+ mail-to: stokes@austin.ibm.com mail-to: blakley@dascom.com
+ phone: +1 512 838 3725 phone: +1 512 458 4037 ext 5012
+ fax: +1 512 838 8597 fax: +1 512 458 237
+
+
+ Debbie Byrne
+ IBM
+ 11400 Burnet Rd
+ Austin, TX 78758
+ USA
+ mail-to: djbyrne@us.ibm.com
+ phone: +1 512 838 1960
+ fax: +1 512 838 8597
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 30]
+
+
+
+
+
+
+ Internet-Draft Access Control Model 25 June 1999
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Stokes, Byrne, Blakley Expires 25 December 1999 [Page 31]
+
+
+
+
+
+
+
+
+
+
+ CONTENTS
+
+
+ 1. Introduction....................................... 2
+
+ 2. Overview........................................... 2
+
+ 3. Terminology........................................ 4
+
+ 4. The Model.......................................... 6
+ 4.1 Access Control Activity Lifecycle............. 6
+ 4.2 Access Control Information Model.............. 6
+ 4.3 Bind and Credentials.......................... 8
+
+ 5. Access Control Information Schema.................. 8
+ 5.1 Attributes.................................... 8
+ 5.1.1 Root DSE Attribute for Access Control
+ Mechanism 8
+ 5.1.2 Subschema Attribute for Access Control
+ Mechanism 9
+ 5.2 Other Defined Parameters/OIDs................. 9
+ 5.2.1 Rights Families and Rights 9
+ 5.2.2 DN Types 10
+
+ 6. Access Control Parameters for LDAP Controls &
+ Extended Operations................................ 11
+
+ 7. Access Control Information (ACI) Controls.......... 12
+ 7.1 getEffectiveRights Control.................... 13
+ 7.1.1 Request Control 13
+ 7.1.2 Response Control 13
+ 7.1.3 Client-Server Interaction 15
+ 7.2 specifyCredentials Control.................... 16
+ 7.2.1 Request Control 16
+ 7.2.2 Response Control 17
+ 7.2.3 Client-Server Interaction 18
+
+ 8. Access Control Extended Operations................. 20
+ 8.1 LDAP Get Effective Rights Operation........... 20
+
+ 10. Security Considerations............................ 29
+
+ 11. References......................................... 29
+
+
+
+
+
+ - i -
+
+
+
+
+
+
+
+
+
+
+
+ Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999).á All Rights
+ Reserved.
+
+ This document and translations of it may be copied and
+ furnished to others, and derivative works that comment on or
+ otherwise explain it or assist in its implementation may be
+ prepared, copied, published and distributed, in whole or in
+ part, without restriction of any kind, provided that the
+ above copyright notice and this paragraph are included on
+ all such copies and derivative works.á However, this
+ document itself may not be modified in any way, such as by
+ removing the copyright notice or references to the Internet
+ Society or other Internet organizations, except as needed
+ for the purpose of developing Internet standards in which
+ case the procedures for copyrights defined in the Internet
+ Standards process must be followed, or as required to
+ translate it into languages other than English.
+
+ The limited permissions granted above are perpetual and will
+ not be revoked by the Internet Society or its successors or
+ assigns.
+
+ This document and the information contained herein is
+ provided on an "AS IS" basis and THE INTERNET SOCIETY AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+ ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
+ INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - ii -
+
+
+
+
--- /dev/null
+
+ Internet-Draft E. Stokes
+ LDAP Extensions WG D. Byrne
+ Intended Category: Informational IBM
+ Expires: 25 December 1999 B. Blakley
+ Dascom
+ P. Behera
+ Netscape
+ 25 June 1999
+
+ Access Control Requirements for LDAP
+ <draft-ietf-ldapext-acl-reqts-02.txt>
+
+ STATUS OF THIS MEMO
+
+ This document is an Internet-Draft and is in full
+ conformance with all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet
+ Engineering Task Force (IETF), its areas, and its working
+ groups. Note that other groups may also distribute
+ working documents as Internet-Drafts. Internet-Drafts are
+ draft documents valid for a maximum of six months and may
+ be updated, replaced, or obsoleted by other documents at
+ any time. It is inappropriate to use Internet- Drafts as
+ reference material or to cite them other than as "work in
+ progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+
+ The list of Internet-Draft Shadow Directories can be
+ accessed at http://www.ietf.org/shadow.html.
+
+ Comments and suggestions on this document are encouraged.
+ Comments on this document should be sent to the LDAPEXT
+ working group discussion list:
+
+ ietf-ldapext@netscape.com
+
+ COPYRIGHT NOTICE
+ Copyright (C) The Internet Society (1997). All Rights
+ Reserved.
+
+
+
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 1]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ ABSTRACT
+
+ This document describes the fundamental requirements of
+ an access control list (ACL) model for the Lightweight
+ Directory Application Protocol (LDAP) directory service.
+ It is intended to be a gathering place for access control
+ requirements needed to provide authorized access to and
+ interoperability between directories. The RFC 2119
+ terminology is used in this document.
+
+
+
+ 1. Introduction
+
+ The ability to securely access (replicate and distribute)
+ directory information throughout the network is necessary
+ for successful deployment. LDAP's acceptance as an
+ access protocol for directory information is driving the
+ need to provide an access control model definition for
+ LDAP directory content among servers within an enterprise
+ and the Internet. Currently LDAP does not define an
+ access control model, but is needed to ensure consistent
+ secure access across heterogeneous LDAP implementations.
+ The requirements for access control are critical to the
+ successful deployment and acceptance of LDAP in the
+ market place.
+
+ The RFC 2119 terminology is used in this document.
+
+
+ 2. Objectives
+
+ The major objective is to provide a simple, but secure,
+ highly efficient access control model for LDAP while also
+ providing the appropriate flexibility to meet the needs
+ of both the Internet and enterprise environments and
+ policies.
+
+ This generally leads to several general requirements that
+ are discussed below.
+
+
+ 3. Requirements
+
+ This section is divided into several areas of
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 2]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ requirements: general, semantics/policy, usability, and
+ nested groups (an unresolved issue). The requirements
+ are not in any priority order. Examples and explanatory
+ text is provided where deemed necessary. Usability is
+ perhaps the one set of requirements that is generally
+ overlooked, but must be addressed to provide a secure
+ system. Usability is a security issue, not just a nice
+ design goal and requirement. If it is impossible to set
+ and manage a policy for a secure situation that a human
+ can understand, then what was set up will probably be
+ non-secure. We all need to think of usability as a
+ functional security requirement.
+
+ 3.1 General
+
+ G1. Model SHOULD be general enough to support
+ extensibility to add desirable features in the future.
+
+ G2. When in doubt, safer is better, especially when
+ establishing defaults.
+
+ G3. ACL administration SHOULD be part of the LDAP
+ protocol. Access control information MUST be an LDAP
+ attribute.
+
+ G4. Object reuse protection SHOULD be provided and MUST
+ NOT inhibit implementation of object reuse. The directory
+ SHOULD support policy controlling the re-creation of
+ deleted DNs, particularly in cases where they are re-
+ created for the purpose of assigning them to a subject
+ other than the owner of the deleted DN.
+
+ 3.2 Semantics / Policy
+
+ S1. Omitted as redundant; see U8.
+
+ S2. More specific policies must override less specific
+ ones (e.g. individual user entry in ACL SHOULD take
+ precedence over group entry) for the evaluation of an
+ ACL.
+
+ S3. Multiple policies of equal specificity SHOULD be
+ combined in some easily-understood way (e.g. union or
+ intersection). This is best understood by example.
+ Suppose user A belongs to 3 groups and those 3 groups are
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 3]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ listed on the ACL. Also suppose that the permissions for
+ each of those groups are not identical. Each group is of
+ equal specificity (e.g. each group is listed on the ACL)
+ and the policy for granting user A access (given the
+ example) SHOULD be combined in some easily understood
+ way, such as by intersection or union. For example, an
+ intersection policy here may yield a more limited access
+ for user A than a union policy.
+
+ S4. Newly created directory entries SHOULD be subject to
+ a secure default policy.
+
+ S5. Access policy SHOULD NOT be expressed in terms of
+ attributes which the directory administrator or his
+ organization cannot administer (e.g. groups whose
+ membership is administered by another organization).
+
+ S6. Access policy SHOULD NOT be expressed in terms of
+ attributes which are easily forged (e.g. IP addresses).
+ There may be valid reasons for enabling access based on
+ attributes that are easily forged and the
+ behavior/implications of doing that should be documented.
+
+ S7. Humans (including administrators) SHOULD NOT be
+ required to manage access policy on the basis of
+ attributes which are not "human-readable" (e.g. IP
+ addresses).
+
+ S8. It MUST be possible to deny a subject the right to
+ invoke a directory operation. The system SHOULD NOT
+ require a specific implementation of denial (e.g.
+ explicit denial, implicit denial).
+
+ S9. The system MUST be able (semantically) to support
+ either default-grant or default-deny semantics (not
+ simultaneously).
+
+ S10. The system MUST be able to support either union
+ semantics or intersection semantics for aggregate
+ subjects (not simultaneously).
+
+ S11. Absence of policy SHOULD be interpretable as grant
+ or deny. Deny takes precedence over grant among entries
+ of equal specificity.
+
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 4]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ S12. ACL policy resolution MUST NOT depend on the order
+ of entries in the ACL.
+
+ S13. Rights management MUST have no side effects.
+ Granting a subject one right to an object MUST NOT
+ implicitly grant the same or any other subject a
+ different right to the same object. Granting a privilege
+ attribute to one subject MUST NOT implicitly grant the
+ same privilege attribute to any other subject. Granting
+ a privilege attribute to one subject MUST NOT implicitly
+ grant a different privilege attribute to the same or any
+ other subject. Definition: An ACL's "scope" is defined
+ as the set of directory objects governed by the policy it
+ defines; this set of objects is a sub-tree of the
+ directory. Changing the policy asserted by an ACL (by
+ changing one or more of its entries) MUST NOT implicitly
+ change the policy governed by an ACL in a different
+ scope.
+
+ S14. It SHOULD be possible to apply a single policy to
+ multiple directory entries, even if those entries are in
+ different subtrees. Applying a single policy to multiple
+ directory entries SHOULD NOT require creation and storage
+ of multiple copies of the policy data. The system SHOULD
+ NOT require a specific implementation (e.g. nested
+ groups, named ACLs) of support for policy sharing.
+
+ 3.3 Usability (Manageability)
+
+ U1. When in doubt, simpler is better, both at the
+ interface and in the implementation.
+
+ U2. Subjects MUST be drawn from the "natural" LDAP
+ namespace; they should be DNs.
+
+ U3. It SHOULD NOT be possible via ACL administration to
+ lock all users, including all administrators, out of the
+ directory.
+
+ U4. Administrators SHOULD NOT be required to evaluate
+ arbitrary Boolean predicates in order to create or
+ understand policy.
+
+ U5. Administrators SHOULD be able to administer access
+ to directories and their attributes based on their
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 5]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ sensitivity, without having to understand the semantics
+ of individual schema elements and their attributes (see
+ U9).
+
+ U6. Management of access to resources in an entire
+ subtree SHOULD require only one ACL (at the subtree
+ root). Note that this makes access control based
+ explicitly on attribute types very hard, unless you
+ constrain the types of entries in subtrees. For example,
+ another attribute is added to an entry. That attribute
+ may fall outside the grouping covered by the ACL and
+ hence require additional administration where the desired
+ affect is indeed a different ACL. Access control
+ information specified in one administrative area MUST NOT
+ have jurisdiction in another area. You SHOULD NOT be
+ able to control access to the aliased entry in the alias.
+ You SHOULD be able to control access to the alias name.
+
+ U7. Override of subtree policy MUST be supported on a
+ per-directory-entry basis.
+
+ U8. Control of access to individual directory entry
+ attributes (not just the whole directory entry) MUST be
+ supported.
+
+ U9. Administrator MUST be able to coarsen access policy
+ granularity by grouping attributes with similar access
+ sensitivities.
+
+ U10. Control of access on a per-user granularity MUST be
+ supported.
+
+ U11. Administrator MUST be able to aggregate users (for
+ example, by assigning them to groups or roles) to
+ simplify administration.
+
+ U12. It MUST be possible to review "effective access" of
+ any user, group, or role to any entry's attributes. This
+ aids the administrator in setting the correct policy.
+
+ U13. A single administrator SHOULD be able to define
+ policy for the entire directory tree. An administrator
+ MUST be able to delegate policy administration for
+ specific subtrees to other users. This allows for the
+ partitioning of the entire directory tree for policy
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 6]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ administration, but still allows a single policy to be
+ defined for the entire tree independent of partitioning.
+ (Partition in this context means scope of
+ administration). An administrator MUST be able to create
+ new partitions at any point in the directory tree, and
+ MUST be able to merge a superior and subordinate
+ partition. An administrator MUST be able to configure
+ whether delegated access control information from
+ superior partitions is to be accepted or not.
+
+ U14. It MUST be possible to authorize users to traverse
+ directory structure even if they are not authorized to
+ examine or modify some traversed entries; it MUST also be
+ possible to prohibit this. The tree structure MUST be
+ able to be protected from view if so desired by the
+ administrator.
+
+ U15. It MUST be possible to create publicly readable
+ entries, which may be read even by unauthenticated
+ clients.
+
+ U16. The model for combining multiple access control
+ list entries referring to a single individual MUST be
+ easy to understand.
+
+ U17. Administrator MUST be able to determine where
+ inherited policy information comes from, that is, where
+ ACLs are located and which ACLs were applied. Where
+ inheritance of ACLs is applied, it must be able to be
+ shown how/where that new ACL is derived from.
+
+ U18. It SHOULD be possible for the administrator to
+ configure the access control system to permit users to
+ grant additional access control rights for entries which
+ they create.
+
+
+ 4. Security Considerations
+
+ Access control is a security consideration. This
+ documents addresses the requirements.
+
+
+
+
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 7]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ 5. Glossary
+
+ This glossary is intended to aid the novice not versed in
+ depth about access control. It contains a list [2] of
+ terms and their definitions that are commonly used in
+ discussing access control.
+
+ Access control - The prevention of use of a resource by
+ unidentified and/or unauthorized entities in any other
+ that an authorized manner.
+
+ Access control list - A set of control attributes. It is
+ a list, associated with a security object or a group of
+ security objects. The list contains the names of
+ security subjects and the type of access that may be
+ granted.
+
+ Access control policy - A set of rules, part of a
+ security policy, by which human users, or their
+ representatives, are authenticated and by which access by
+ these users to applications and other services and
+ security objects is granted or denied.
+
+ Access context - The context, in terms of such variables
+ as location, time of day, level of security of the
+ underlying associations, etc., in which an access to a
+ security object is made.
+
+ Authorization - The granting of access to a security
+ object.
+
+ Authorization policy - A set of rules, part of an access
+ control policy, by which access by security subjects to
+ security objects is granted or denied. An authorization
+ policy may be defined in terms of access control lists,
+ capabilities, or attributes assigned to security
+ subjects, security objects, or both.
+
+ Control attributes - Attributes, associated with a
+ security object that, when matched against the privilege
+ attributes of a security subject, are used to grant or
+ deny access to the security object. An access control
+ list or list of rights or time of day range are examples
+ of control attributes.
+
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 8]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ Credentials - Data that serve to establish the claimed
+ identity of a security subject relative to a given
+ security domain.
+
+ Privilege attributes - Attributes, associated with a
+ security subject that, when matched against control
+ attributes of a security object, are used to grant or
+ deny access to that subject. Group and role memberships
+ are examples of privilege attributes.
+
+ Security attributes - A general term covering both
+ privilege attributes and control attributes. The use of
+ security attributes is defined by a security policy.
+
+ Security object - An entity in a passive role to which a
+ security policy applies.
+
+ Security policy - A general term covering both access
+ control policies and authorization policies.
+
+ Security subject - An entity in an active role to which a
+ security policy applies.
+
+
+ 6. References
+
+ [1] Steve Kille, Tim Howes, M. Wahl, "Lightweight
+ Directory Access Protocol (v3)", RFC 2251, August 1997.
+
+ [2] ECMA, "Security in Open Systems: A Security
+ Framework" ECMA TR/46, July 1988
+
+
+ AUTHOR(S) ADDRESS
+
+ Bob Blakley Ellen Stokes
+ Dascom IBM
+ 5515 Balcones Drive 11400 Burnet Rd
+ Austin, TX 78731 Austin, TX 78758
+ USA USA
+ mail-to: blakley@dascom.com mail-to: stokes@austin.ibm.com
+ phone: +1 512 458 4037 ext 5012 phone: +1 512 838 3725
+ fax: +1 512 458 2377 fax: +1 512 838 0156
+
+
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 9]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ Debbie Byrne Prasanta Behera
+ IBM Netscape
+ 11400 Burnet Rd 501 Ellis Street
+ Austin, TX 78758 Mountain View, CA 94043
+ USA USA
+ mail-to: djbyrne@us.ibm.com mail-to: prasanta@netscape.com
+ phone: +1 512 838 1930 phone: +1 650 937 4948
+ fax: +1 512 838 8597 fax: +1 650 528-4164
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 10]
+\f
+
+
+
+
+ Internet-Draft ACI Requirements 25 June 1999
+
+
+
+ 7. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999).á All Rights
+ Reserved.
+
+ This document and translations of it may be copied and
+ furnished to others, and derivative works that comment on or
+ otherwise explain it or assist in its implementation may be
+ prepared, copied, published and distributed, in whole or in
+ part, without restriction of any kind, provided that the
+ above copyright notice and this paragraph are included on
+ all such copies and derivative works.á However, this
+ document itself may not be modified in any way, such as by
+ removing the copyright notice or references to the Internet
+ Society or other Internet organizations, except as needed
+ for the purpose of developing Internet standards in which
+ case the procedures for copyrights defined in the Internet
+ Standards process must be followed, or as required to
+ translate it into languages other than English.
+
+ The limited permissions granted above are perpetual and will
+ not be revoked by the Internet Society or its successors or
+ assigns.
+
+ This document and the information contained herein is
+ provided on an "AS IS" basis and THE INTERNET SOCIETY AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+ ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
+ INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Stokes, etal Expires 25 December 1999 [Page 11]
+\f
+
--- /dev/null
+
+Network Working Group M. Wahl
+INTERNET-DRAFT Innosoft International, Inc.
+ H. Alvestrand
+ MaXware AS
+ J. Hodges
+ Stanford University
+ RL "Bob" Morgan
+ Stanford University
+Expires in six months from June 21, 1999
+
+
+ Authentication Methods for LDAP
+ <draft-ietf-ldapext-authmeth-04.txt>
+
+1. Status of this Memo
+
+ This document is an Internet-Draft. Internet-Drafts are working
+ documents of the Internet Engineering Task Force (IETF), its
+ areas, and its working groups. Note that other groups may also
+ distribute working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six
+ months and may be updated, replaced, or obsoleted by other
+ documents at any time. It is inappropriate to use Internet-Drafts
+ as reference material or to cite them other than as "work in
+ progress."
+
+ To view the entire list of current Internet-Drafts, please check
+ the "1id-abstracts.txt" listing contained in the Internet-Drafts
+ Shadow Directories on ftp.is.co.za (Africa), ftp.nordu.net
+ (Northern Europe), ftp.nis.garr.it (Southern Europe), munnari.oz.au
+ (Pacific Rim), ftp.ietf.org (US East Coast), or ftp.isi.edu
+ (US West Coast).
+
+2. Abstract
+
+ This document specifies particular combinations of security
+ mechanisms which are required and recommended in LDAP [1]
+ implementations.
+
+3. Introduction
+
+ LDAP version 3 is a powerful access protocol for directories.
+
+ It offers means of searching, fetching and manipulating directory
+ content, and ways to access a rich set of security functions.
+
+ In order to function for the best of the Internet, it is vital
+ that these security functions be interoperable; therefore there
+ has to be a minimum subset of security functions that is common to
+ all implementations that claim LDAPv3 conformance.
+
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 1
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+ Basic threats to an LDAP directory service include:
+
+ (1) Unauthorized access to data via data-fetching operations,
+
+ (2) Unauthorized access to reusable client authentication
+ information by monitoring others' access,
+
+ (3) Unauthorized access to data by monitoring others' access,
+
+ (4) Unauthorized modification of data,
+
+ (5) Unauthorized modification of configuration,
+
+ (6) Unauthorized or excessive use of resources (denial of
+ service), and
+
+ (7) Spoofing of directory: Tricking a client into believing
+ that information came from the directory when in fact it
+ did not, either by modifying data in transit or misdirecting
+ the client's connection.
+
+ Threats (1), (4), (5) and (6) are due to hostile clients. Threats
+ (2), (3) and (7) are due to hostile agents on the path between client
+ and server, or posing as a server.
+
+ The LDAP protocol suite can be protected with the following
+ security mechanisms:
+
+ (1) Client authentication by means of the SASL [2] mechanism set,
+ possibly backed by the TLS credentials exchange mechanism,
+
+ (2) Client authorization by means of access control based on
+ the requestor's authenticated identity,
+
+ (3) Data integrity protection by means of the TLS protocol or
+ data-integrity SASL mechanisms,
+
+ (4) Protection against snooping by means of the TLS protocol
+ or data-encrypting SASL mechanisms,
+
+ (5) Resource limitation by means of administrative limits on
+ service controls, and
+
+ (6) Server authentication by means of the TLS protocol or SASL
+ mechanism.
+
+ At the moment, imposition of access controls is done by means
+ outside the scope of the LDAP protocol.
+
+ In this document, the term "user" represents any application which
+ is an LDAP client using the directory to retrieve or store information.
+
+Wahl, Alvestrand, Hodges, Morgan Page 2
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in
+ this document are to be interpreted as described in RFC 2119 [3].
+
+4. Example deployment scenarios
+
+ The following scenarios are typical for LDAP directories on the
+ Internet, and have different security requirements. (In the
+ following, "sensitive" means data that will cause real damage to
+ the owner if revealed; there may be data that is protected but
+ not sensitive). This is not intended to be a comprehensive list,
+ other scenarios are possible, especially on physically protected
+ networks.
+
+ (1) A read-only directory, containing no sensitive data,
+ accessible to "anyone", and TCP connection hijacking
+ or IP spoofing is not a problem. This directory requires
+ no security functions except administrative service limits.
+
+ (2) A read-only directory containing no sensitive data; read
+ access is granted based on identity. TCP connection
+ hijacking is not currently a problem. This scenario requires
+ a secure authentication function.
+
+ (3) A read-only directory containing no sensitive data; and
+ the client needs to ensure that the directory data is
+ authenticated by the server and not modified while being
+ returned from the server.
+
+ (4) A read-write directory, containing no sensitive data; read
+ access is available to "anyone", update access to properly
+ authorized persons. TCP connection hijacking is not
+ currently a problem. This scenario requires a secure
+ authentication function.
+
+ (5) A directory containing sensitive data. This scenario
+ requires session confidentiality protection AND secure
+ authentication.
+
+5. Authentication and Authorization: Definitions and Concepts
+
+ This section defines basic terms, concepts, and interrelationships
+ regarding authentication, authorization, credentials, and identity.
+ These concepts are used in describing how various security
+ approaches are utilized in client authentication and authorization.
+
+
+
+
+
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 3
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+5.1. Access Control Policy
+
+ An access control policy is a set of rules defining the protection
+ of resources, generally in terms of the capabilities of persons or
+ other entities accessing those resources. A common expression of an
+ access control policy is an access control list. Security objects
+ and mechanisms, such as those described here, enable the expression of
+ access control policies and their enforcement. Access control
+ policies are typically expressed in terms of access control attributes
+ as described below.
+
+5.2. Access Control Factors
+
+ A request, when it is being processed by a server, may be associated
+ with a wide variety of security-related factors (section 4.2 of [1]).
+ The server uses these factors to determine whether and how to process
+ the request. These are called access control factors (ACFs). They
+ might include source IP address, encryption strength, the type of
+ operation being requested, time of day, etc. Some factors may be
+ specific to the request itself, others may be associated with the
+ connection via which the request is transmitted, others (e.g. time of
+ day) may be "environmental".
+
+ Access control policies are expressed in terms of access control
+ factors. E.g., a request having ACFs i,j,k can perform operation Y
+ on resource Z. The set of ACFs that a server makes available for such
+ expressions is implementation-specific.
+
+5.3. Authentication, Credentials, Identity
+
+ Authentication credentials are the evidence supplied by one party to
+ another, asserting the identity of the supplying party (e.g. a user)
+ who is attempting to establish an association with the other party
+ (typically a server). Authentication is the process of generating,
+ transmitting, and verifying these credentials and thus the identity
+ they assert. An authentication identity is the name presented in a
+ credential.
+
+ There are many forms of authentication credentials -- the form used
+ depends upon the particular authentication mechanism negotiated by the
+ parties. For example: X.509 certificates, Kerberos tickets, simple
+ identity and password pairs. Note that an authentication mechanism may
+ constrain the form of authentication identities used with it.
+
+5.4. Authorization Identity
+
+ An authorization identity is one kind of access control factor. It is
+ the name of the user or other entity that requests that operations be
+ performed. Access control policies are often expressed in terms of
+ authorization identities; e.g., entity X can perform operation Y on
+ resource Z.
+
+Wahl, Alvestrand, Hodges, Morgan Page 4
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+ The authorization identity bound to an association is often exactly the
+ same as the authentication identity presented by the client, but it may
+ be different. SASL allows clients to specify an authorization identity
+ distinct from the authentication identity asserted by the client's
+ credentials. This permits agents such as proxy servers to authenticate
+ using their own credentials, yet request the access privileges of the
+ identity for which they are proxying [2]. Also, the form of
+ authentication identity supplied by a service like TLS may not
+ correspond to the authorization identities used to express a server's
+ access control policy, requiring a server-specific mapping to be done.
+ The method by which a server composes and validates an authorization
+ identity from the authentication credentials supplied by a client is
+ implementation-specific.
+
+6. Required security mechanisms
+
+ It is clear that allowing any implementation, faced with the above
+ requirements, to pick and choose among the possible alternatives
+ is not a strategy that is likely to lead to interoperability. In
+ the absence of mandates, clients will be written that do not
+ support any security function supported by the server, or worse,
+ support only mechanisms like cleartext passwords that provide
+ clearly inadequate security.
+
+ Active intermediary attacks are the most difficult for an attacker
+ to perform, and for an implementation to protect against. Methods
+ that protect only against hostile client and passive eavesdropping
+ attacks are useful in situations where the cost of protection
+ against active intermediary attacks is not justified based on the
+ perceived risk of active intermediary attacks.
+
+ Given the presence of the Directory, there is a strong desire to
+ see mechanisms where identities take the form of a Distinguished
+ Name and authentication data can be stored in the directory; this
+ means that either this data is useless for faking authentication
+ (like the Unix "/etc/passwd" file format used to be), or its
+ content is never passed across the wire unprotected - that is,
+ it's either updated outside the protocol or it is only updated in
+ sessions well protected against snooping. It is also desirable
+ to allow authentication methods to carry authorization identities
+ based on existing forms of user identities for backwards compatibility
+ with non-LDAP-based authentication services.
+
+ Therefore, the following implementation conformance requirements
+ are in place:
+
+ (1) For a read-only, public directory, anonymous authentication,
+ described in section 7, can be used.
+
+
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 5
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+ (2) Implementations providing password-based authenticated access
+ MUST support authentication using Digest, as described in
+ section 8.1. This provides client authentication with
+ protection against passive eavesdropping attacks, but does
+ not provide protection against active intermediary attacks.
+
+ (3) For a directory needing session protection and
+ authentication, the Start TLS extended operation, and either
+ the simple authentication choice or the SASL EXTERNAL
+ mechanism, are to be used together. Implementations SHOULD
+ support authentication with a password as described in
+ section 8.2, and SHOULD support authentication with a
+ certificate as described in section 9.1. Together, these
+ can provide integrity and disclosure protection of
+ transmitted data, and authentication of client and server,
+ including protection against active intermediary attacks.
+
+ If TLS is negotated, the client MUST discard all information about
+ the server fetched prior to the TLS negotiation. In particular, the
+ value of supportedSASLMechanisms MAY be different after TLS has been
+ negotiated (specifically, the EXTERNAL mechanism or the proposed
+ PLAIN mechanism are likely to only be listed after a TLS negotiation
+ has been performed).
+
+ If a SASL security layer is negotiated, the client MUST discard all
+ information about the server fetched prior to SASL. In particular, if
+ the client is configured to support multiple SASL mechanisms, it SHOULD
+ fetch supportedSASLMechanisms both before and after the SASL security
+ layer is negotiated and verify that the value has not changed after the
+ SASL security layer was negotiated. This detects active attacks which
+ remove supported SASL mechanisms from the supportedSASLMechanisms list.
+
+7. Anonymous authentication
+
+ Directory operations which modify entries or access protected
+ attributes or entries generally require client authentication.
+ Clients which do not intend to perform any of these operations
+ typically use anonymous authentication.
+
+ LDAP implementations MUST support anonymous authentication, as
+ defined in section 7.1.
+
+ LDAP implementations MAY support anonymous authentication with TLS,
+ as defined in section 7.2.
+
+ While there MAY be access control restrictions to prevent access to
+ directory entries, an LDAP server SHOULD allow an anonymously-bound
+ client to retrieve the supportedSASLMechanisms attribute of the root
+ DSE.
+
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 6
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+ An LDAP server MAY use other information about the client provided
+ by the lower layers or external means to grant or deny access even
+ to anonymously authenticated clients.
+
+7.1. Anonymous authentication procedure
+
+ An LDAP client which has not successfully completed a bind operation
+ on a connection is anonymously authenticated.
+
+ An LDAP client MAY also specify anonymous authentication in a bind
+ request by using a zero-length OCTET STRING with the simple
+ authentication choice.
+
+7.2. Anonymous authentication and TLS
+
+ An LDAP client MAY use the Start TLS operation [5] to negotiate the
+ use of TLS security [6]. If the client has not bound beforehand,
+ then until the client uses the EXTERNAL SASL mechanism to negotiate
+ the recognition of the client's certificate, the client is
+ anonymously authenticated.
+
+ Recommendations on TLS ciphersuites are given in section 12.
+
+ An LDAP server which requests that clients provide their certificate
+ during TLS negotiation MAY use a local security policy to determine
+ whether to successfully complete TLS negotiation if the client did not
+ present a certificate which could be validated.
+
+8. Password-based authentication
+
+ LDAP implementations MUST support authentication with a password using
+ the DIGEST-MD5 mechanism for password protection, as defined in section
+ 8.1.
+
+ LDAP implementations SHOULD support authentication with the "simple"
+ password choice when the connection is protected against eavesdropping
+ using TLS, as defined in section 8.2.
+
+8.1. Digest authentication
+
+ An LDAP client MAY determine whether the server supports this
+ mechanism by performing a search request on the root DSE, requesting
+ the supportedSASLMechanisms attribute, and checking whether the
+ string "DIGEST-MD5" is present as a value of this attribute.
+
+ In the first stage of authentication, when the client is performing
+ an "initial authentication" as defined in section 2.1 of [4], the
+ client sends a bind request in which the version number is 3, the
+ authentication choice is sasl, the sasl mechanism name is "DIGEST-MD5",
+ and the credentials are absent. The client then waits for a response
+ from the server to this request.
+
+Wahl, Alvestrand, Hodges, Morgan Page 7
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+ The server will respond with a bind response in which the resultCode
+ is saslBindInProgress, and the serverSaslCreds field is present. The
+ contents of this field is a string defined by "digest-challenge" in
+ section 2.1.1 of [4]. The server SHOULD include a realm indication and
+ MUST indicate support for UTF-8.
+
+ The client will send a bind request with a distinct mesage id, in which
+ the version number is 3, the authentication choice is sasl, the sasl
+ mechanism name is "DIGEST-MD5", and the credentials contain the string
+ defined by "digest-response" in section 2.1.2 of [4]. The serv-type
+ is "ldap".
+
+ The server will respond with a bind response in which the resultCode
+ is either success, or an error indication. If the authentication is
+ successful and the server does not support subsequent authentication,
+ then the credentials field is absent. If the authentication is
+ successful and the server supports subsequent authentication, then
+ the crendentials field contains the string defined by "response-auth"
+ in section 2.1.3 of [4]. Support for subsequent authentication is
+ OPTIONAL in clients and servers.
+
+8.2. "simple" authentication choice under TLS encryption
+
+ A user who has a directory entry containing a userPassword attribute
+ MAY authenticate to the directory by performing a simple password
+ bind sequence following the negotiation of a TLS ciphersuite
+ providing connection confidentiality [6].
+
+ The client will use the Start TLS operation [5] to negotiate the
+ use of TLS security [6] on the connection to the LDAP server. The
+ client need not have bound to the directory beforehand.
+
+ For this authentication procedure to be successful, the client and
+ server MUST negotiate a ciphersuite which contains a bulk encryption
+ algorithm of appropriate strength. Recommendations on cipher
+ suites are given in section 12.
+
+ Following the successful completion of TLS negotiation, the client
+ MUST send an LDAP bind request with the version number of 3, the
+ name field containing the name of the user's entry, and the "simple"
+ authentication choice, containing a password.
+
+ The server will, for each value of the userPassword attribute in
+ the named user's entry, compare these for case-sensitive equality
+ with the client's presented password. If there is a match, then the
+ server will respond with resultCode success, otherwise the server will
+ respond with resultCode invalidCredentials.
+
+
+
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 8
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+8.3. Other authentication choices with TLS
+
+ It is also possible to perform a SASL authentication exchange of
+ passwords following the negotiation of TLS. In this case the
+ client and server need not negotiate a ciphersuite which provides
+ confidentiality if the only service required is data integrity.
+
+9. Certificate-based authentication
+
+ LDAP implementations SHOULD support authentication via a client
+ certificate in TLS, as defined in section 9.1.
+
+9.1. Certificate-based authentication with TLS
+
+ A user who has a public/private key pair in which the public key has
+ been signed by a Certification Authority may use this key pair to
+ authenticate to the directory server if the user's certificate is
+ requested by the server. The user's certificate subject field
+ SHOULD be the name of the user's directory entry, and the
+ Certification Authority must be sufficiently trusted by the
+ directory server to have issued the certificate in order that the
+ server can process the certificate. The means by which servers
+ validate certificate paths is outside the scope of this document.
+
+ A server MAY support mappings for certificates in which the subject
+ field name is different from the name of the user's directory entry.
+ A server which supports mappings of names MUST be capable of being
+ configured to support certificates for which no mapping is required.
+
+ The client will use the Start TLS operation [5] to negotiate the
+ use of TLS security [6] on the connection to the LDAP server. The
+ client need not have bound to the directory beforehand.
+
+ In the TLS negotiation, the server MUST request a certificate. The
+ client will provide its certificate to the server, and MUST perform
+ a private key-based encryption, proving it has it private key
+ associated with the certificate.
+
+ As deployments will require protection of sensitive data in transit,
+ the client and server MUST negotiate a ciphersuite which contains a
+ bulk encryption algorithm of appropriate strength. Recommendations
+ of cipher suites are given in section 12.
+
+ The server MUST verify that the client's certificate is valid.
+ The server will normally check that the certificate is issued by a
+ known CA, and that none of the certificates on the client's
+ certificate chain are invalid or revoked. There are several
+ procedures by which the server can perform these checks.
+
+ Following the successful completion of TLS negotiation, the client
+ will send an LDAP bind request with the SASL "EXTERNAL" mechanism.
+
+Wahl, Alvestrand, Hodges, Morgan Page 9
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+10. Other mechanisms
+
+ The LDAP "simple" authentication choice is not suitable for
+ authentication on the Internet where there is no network or transport
+ layer confidentiality.
+
+ As LDAP includes a native anonymous and plaintext authentication
+ methods, the "ANONYMOUS" and "PLAIN" SASL mechanisms are not used
+ with LDAP. If an authorization identity of a form different from
+ a DN is requested by the client, a mechanism that protects the
+ password in transit SHOULD be used.
+
+ The following SASL-based mechanisms are not considered in this
+ document: KERBEROS_V4, GSSAPI and SKEY.
+
+ The "EXTERNAL" SASL mechanism can be used to request the LDAP server
+ make use of security credentials exchanged by a lower layer. If a
+ TLS session has not been established between the client and server
+ prior to making the SASL EXTERNAL Bind request and there is no other
+ external source of authentication credentials (e.g. IP-level
+ security [8]), or if, during the process of establishing the
+ TLS session, the server did not request the client's authentication
+ credentials, the SASL EXTERNAL bind MUST fail with a result code of
+ inappropriateAuthentication. Any authentication identity and
+ authorization identity, as well as TLS connection, which were in
+ effect prior to making the Bind request, MUST remain in force.
+
+11. Authorization Identity
+
+ The authorization identity is carried as part of the SASL credentials
+ field in the LDAP Bind request and response.
+
+ When the "EXTERNAL" mechanism is being negotiated, if the
+ credentials field is present, it contains an authorization identity
+ of the authzId form described below.
+
+ Other mechanisms define the location of the authorization
+ identity in the credentials field.
+
+ The authorization identity is a string in the UTF-8 character set,
+ corresponding to the following ABNF [7]:
+
+ ; Specific predefined authorization (authz) id schemes are
+ ; defined below -- new schemes may be defined in the future.
+
+ authzId = dnAuthzId / uAuthzId
+
+ ; distinguished-name-based authz id.
+ dnAuthzId = "dn:" dn
+ dn = utf8string ; with syntax defined in RFC 2253
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 10
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+ ; unspecified userid, UTF-8 encoded.
+ uAuthzId = "u:" userid
+ userid = utf8string ; syntax unspecified
+
+ A utf8string is defined to be the UTF-8 encoding of one or more
+ ISO 10646 characters.
+
+ All servers which support the storage of authentication credentials,
+ such as passwords or certificates, in the directory MUST support the
+ dnAuthzId choice.
+
+ The uAuthzId choice allows for compatibility with client applications
+ which wish to authenticate to a local directory but do not know their
+ own Distinguished Name or have a directory entry. The format of the
+ string is defined as only a sequence of UTF-8 encoded ISO 10646
+ characters, and further interpretation is subject to prior agreement
+ between the client and server.
+
+ For example, the userid could identify a user of a specific directory
+ service, or be a login name or the local-part of an RFC 822 email
+ address. In general a uAuthzId MUST NOT be assumed to be globally
+ unique.
+
+ Additional authorization identity schemes MAY be defined in future
+ versions of this document.
+
+12. TLS Ciphersuites
+
+ The following ciphersuites defined in [6] MUST NOT be used for
+ confidentiality protection of passwords or data:
+
+ TLS_NULL_WITH_NULL_NULL
+ TLS_RSA_WITH_NULL_MD5
+ TLS_RSA_WITH_NULL_SHA
+
+ The following ciphersuites defined in [6] can be cracked easily
+ (less than a week of CPU time on a standard CPU in 1997). The
+ client and server SHOULD carefully consider the value of the
+ password or data being protected before using these ciphersuites:
+
+ TLS_RSA_EXPORT_WITH_RC4_40_MD5
+ TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
+ TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
+ TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
+ TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
+ TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
+ TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
+ TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
+ TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
+
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 11
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+ The following ciphersuites are vulnerable to man-in-the-middle
+ attacks, and SHOULD NOT be used to protect passwords or sensitive
+ data, unless the network configuration is such that the danger of
+ a man-in-the-middle attack is tolerable:
+
+ TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
+ TLS_DH_anon_WITH_RC4_128_MD5
+ TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
+ TLS_DH_anon_WITH_DES_CBC_SHA
+ TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
+
+ A client or server that supports TLS MUST support at least
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA.
+
+13. SASL service name for LDAP
+
+ For use with SASL [2], a protocol must specify a service name to be
+ used with various SASL mechanisms, such as GSSAPI. For LDAP, the
+ service name is "ldap", which has been registered with the IANA
+ as a GSSAPI service name.
+
+14. Security Considerations
+
+ Security issues are discussed throughout this memo; the
+ (unsurprising) conclusion is that mandatory security is important,
+ and that session encryption is required when snooping is a
+ problem.
+
+ Servers are encouraged to prevent modifications by anonymous
+ users. Servers may also wish to minimize denial of service attacks
+ by timing out idle connections, and returning the unwillingToPerform
+ result code rather than performing computationally expensive
+ operations requested by unauthorized clients.
+
+ A connection on which the client has not performed the Start TLS
+ operation or negotiated a suitable SASL mechanism for connection
+ integrity and encryption services is subject to man-in-the-middle
+ attacks to view and modify information in transit.
+
+ Additional security considerations relating to the EXTERNAL
+ EXTERNAL mechanism to negotiate TLS can be found in [2], [5]
+ and [6].
+
+15. Acknowledgements
+
+ This document is a product of the LDAPEXT Working Group of the
+ IETF. The contributions of its members is greatly appreciated.
+
+
+
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 12
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+16. Bibliography
+
+ [1] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access
+ Protocol (v3)", Dec. 1997, RFC 2251.
+
+ [2] J. Myers, "Simple Authentication and Security Layer (SASL)",
+ Oct. 1997, RFC 2222.
+
+ [3] S. Bradner, "Key words for use in RFCs to Indicate Requirement
+ Levels", RFC 2119.
+
+ [4] P. Leach, C. Newman, "Using Digest Authentication as a SASL
+ Mechanism", INTERNET DRAFT <draft-leach-digest-sasl-00.txt>.
+
+ [5] J. Hodges, RL Morgan, M. Wahl, "LDAPv3 Extension for Transport
+ Layer Security", Oct. 1998, INTERNET DRAFT
+ <draft-ietf-ldapext-ldapv3-tls-03.txt>.
+
+ [6] T. Diers, C. Allen, "The TLS Protocol Version 1.0", Jan. 1999,
+ RFC 2246.
+
+ [7] D. Crocker, Ed., P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234.
+
+ [8] S. Kent, R. Atkinson, "Security Architecture for the Internet
+ Protocol", Nov. 1998, RFC 2401.
+
+17. Authors Address
+
+ Mark Wahl
+ Innosoft International, Inc.
+ 8911 Capital of Texas Hwy, Suite 4140
+ Austin, TX 78759
+ USA
+ Phone: +1 512 231 1600
+ EMail: Mark.Wahl@innosoft.com
+
+ Harald Tveit Alvestrand
+ EMail: Harald.Alvestrand@maxware.no
+
+ Jeff Hodges
+ Computing & Communication Services
+ Stanford University
+ Pine Hall
+ 241 Panama Street
+ Stanford, CA 94305-4122
+ USA
+ Phone: +1-650-723-2452
+ EMail: Jeff.Hodges@Stanford.edu
+
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 13
+\f
+INTERNET-DRAFT Authentication Methods for LDAP June 1999
+
+ RL "Bob" Morgan
+ Computing & Communication Services
+ Stanford University
+ Pine Hall
+ 241 Panama Street
+ Stanford, CA 94305-4122
+ USA
+ Phone: +1-650-723-9711
+ EMail: Bob.Morgan@Stanford.edu
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl, Alvestrand, Hodges, Morgan Page 14
+
--- /dev/null
+Network Working Group M. Smith, Editor
+INTERNET-DRAFT Netscape Communications Corp.
+Intended Category: Standards Track T. Howes
+Obsoletes: RFC 1823 Netscape Communications Corp.
+Expires: 2 December 1999 A. Herron
+ Microsoft Corp.
+ M. Wahl
+ Innosoft International, Inc.
+ A. Anantha
+ Microsoft Corp.
+
+
+ 2 June 1999
+
+ The C LDAP Application Program Interface
+ <draft-ietf-ldapext-ldap-c-api-03.txt>
+
+
+1. Status of this Memo
+
+This document is an Internet-Draft and is in full conformance with all
+provisions of Section 10 of RFC2026. Internet-Drafts are working docu-
+ments of the Internet Engineering Task Force (IETF), its areas, and its
+working groups. Note that other groups may also distribute working
+documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time. It is inappropriate to use Internet-Drafts as reference material
+or to cite them other than as "work in progress."
+
+The list of current Internet-Drafts can be accessed at
+http://www.ietf.org/ietf/1id-abstracts.txt.
+
+The list of Internet-Draft Shadow Directories can be accessed at
+http://www.ietf.org/shadow.html.
+
+This draft document will be submitted to the RFC Editor as a Standards
+Track document. Distribution of this memo is unlimited. Technical dis-
+cussion of this document will take place on the IETF LDAP Extension
+Working Group mailing list <ietf-ldapext@netscape.com>. Please send
+editorial comments directly to the authors.
+
+Copyright (C) The Internet Society (1997-1999). All Rights Reserved.
+
+Please see the Copyright section near the end of this document for more
+information.
+
+
+
+
+Expires: 2 December 1999 [Page 1]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+2. Introduction
+
+This document defines a C language application program interface (API)
+to the Lightweight Directory Access Protocol (LDAP). This document
+replaces the previous definition of this API, defined in RFC 1823,
+updating it to include support for features found in version 3 of the
+LDAP protocol. New extended operation functions were added to support
+LDAPv3 features such as controls. In addition, other LDAP API changes
+were made to support information hiding and thread safety.
+
+The C LDAP API is designed to be powerful, yet simple to use. It defines
+compatible synchronous and asynchronous interfaces to LDAP to suit a
+wide variety of applications. This document gives a brief overview of
+the LDAP model, then an overview of how the API is used by an applica-
+tion program to obtain LDAP information. The API calls are described in
+detail, followed by appendices that provide example code demonstrating
+use of the API, the namespace consumed by the API, a summary of require-
+ments for API extensions, known incompatibilities with RFC 1823, and a
+list of changes made since the last revision of this document.
+
+
+3. Table of Contents
+
+1. Status of this Memo............................................1
+2. Introduction...................................................2
+3. Table of Contents..............................................2
+4. Overview of the LDAP Model.....................................4
+5. Overview of LDAP API Use.......................................4
+6. Header File Requirements.......................................6
+7. Common Data Structures.........................................7
+8. Retrieving Information About the API Implementation............8
+8.1. Retrieving Information at Compile Time......................9
+8.2. Retrieving Information During Execution.....................10
+9. LDAP Error Codes...............................................13
+10. Performing LDAP Operations.....................................14
+10.1. Initializing an LDAP Session................................14
+10.2. LDAP Session Handle Options.................................15
+10.3. Working With Controls.......................................20
+10.3.1. A Client Control That Governs Referral Processing........22
+10.4. Authenticating to the directory.............................22
+10.5. Closing the session.........................................25
+10.6. Searching...................................................26
+10.7. Reading an Entry............................................29
+10.8. Listing the Children of an Entry............................30
+10.9. Comparing a Value Against an Entry..........................30
+10.10. Modifying an entry..........................................32
+10.11. Modifying the Name of an Entry..............................34
+10.12. Adding an entry.............................................36
+
+
+
+Expires: 2 December 1999 [Page 2]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+10.13. Deleting an entry...........................................38
+10.14. Extended Operations.........................................39
+11. Abandoning An Operation........................................41
+12. Obtaining Results and Peeking Inside LDAP Messages.............42
+13. Handling Errors and Parsing Results............................44
+14. Stepping Through a List of Results.............................46
+15. Parsing Search Results.........................................47
+15.1. Stepping Through a List of Entries or References............48
+15.2. Stepping Through the Attributes of an Entry.................49
+15.3. Retrieving the Values of an Attribute.......................50
+15.4. Retrieving the name of an entry.............................51
+15.5. Retrieving controls from an entry...........................52
+15.6. Parsing References..........................................53
+16. Encoded ASN.1 Value Manipulation...............................54
+16.1. General.....................................................54
+16.2. Encoding....................................................55
+16.3. Encoding Example............................................58
+16.4. Decoding....................................................59
+16.5. Decoding Example............................................61
+17. Security Considerations........................................64
+18. Acknowledgements...............................................64
+19. Copyright......................................................64
+20. Bibliography...................................................65
+21. Authors' Addresses.............................................66
+22. Appendix A - Sample C LDAP API Code............................66
+23. Appendix B - Namespace Consumed By This Specification..........68
+24. Appendix C - Summary of Requirements for API Extensions........68
+24.1. Compatibility...............................................69
+24.2. Style.......................................................69
+24.3. Dependence on Externally Defined Types......................69
+24.4. Compile Time Information....................................69
+24.5. Runtime Information.........................................69
+24.6. Values Used for Session Handle Options......................70
+25. Appendix D - Known Incompatibilities with RFC 1823.............70
+25.1. Opaque LDAP Structure.......................................70
+25.2. Additional Error Codes......................................70
+25.3. Freeing of String Data with ldap_memfree()..................71
+25.4. Changes to ldap_result()....................................71
+25.5. Changes to ldap_first_attribute() and ldap_next_attribute...71
+25.6. Changes to ldap_modrdn() and ldap_modrdn_s() Functions......71
+25.7. Changes to the berval structure.............................71
+25.8. API Specification Clarified.................................72
+25.9. Deprecated Functions........................................72
+26. Appendix E - Data Types and Legacy Implementations.............72
+27. Appendix F - Changes Made Since Last Document Revision.........73
+27.1. API Changes.................................................73
+27.2. Editorial Changes...........................................74
+28. Appendix G - Changes Made Since draft-ietf-ldapext-ldap-c-api-.74
+28.1. API Changes.................................................74
+28.2. Editorial changes...........................................75
+
+Expires: 2 December 1999 [Page 3]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+4. Overview of the LDAP Model
+
+LDAP is the lightweight directory access protocol, described in [2] and
+[6]. It can provide a lightweight frontend to the X.500 directory [1],
+or a stand-alone service. In either mode, LDAP is based on a client-
+server model in which a client makes a TCP connection to an LDAP server,
+over which it sends requests and receives responses.
+
+The LDAP information model is based on the entry, which contains infor-
+mation about some object (e.g., a person). Entries are composed of
+attributes, which have a type and one or more values. Each attribute has
+a syntax that determines what kinds of values are allowed in the attri-
+bute (e.g., ASCII characters, a jpeg photograph, etc.) and how those
+values behave during directory operations (e.g., is case significant
+during comparisons).
+
+Entries may be organized in a tree structure, usually based on politi-
+cal, geographical, and organizational boundaries. Each entry is uniquely
+named relative to its sibling entries by its relative distinguished name
+(RDN) consisting of one or more distinguished attribute values from the
+entry. At most one value from each attribute may be used in the RDN.
+For example, the entry for the person Babs Jensen might be named with
+the "Barbara Jensen" value from the commonName attribute.
+
+A globally unique name for an entry, called a distinguished name or DN,
+is constructed by concatenating the sequence of RDNs from the entry up
+to the root of the tree. For example, if Babs worked for the University
+of Michigan, the DN of her U-M entry might be "cn=Barbara Jensen,
+o=University of Michigan, c=US". The DN format used by LDAP is defined
+in [4].
+
+Operations are provided to authenticate, search for and retrieve infor-
+mation, modify information, and add and delete entries from the tree.
+The next sections give an overview of how the API is used and detailed
+descriptions of the LDAP API calls that implement all of these func-
+tions.
+
+
+5. Overview of LDAP API Use
+
+An application generally uses the C LDAP API in four simple steps.
+
+ 1. Initialize an LDAP session with a primary LDAP server. The
+ ldap_init() function returns a handle to the session, allowing
+ multiple connections to be open at once.
+
+ 2. Authenticate to the LDAP server. The ldap_sasl_bind() function
+ and friends support a variety of authentication methods.
+
+
+
+Expires: 2 December 1999 [Page 4]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ 3. Perform some LDAP operations and obtain some results.
+ ldap_search() and friends return results which can be parsed by
+ ldap_parse_result(), ldap_first_entry(), ldap_next_entry(), etc.
+
+ 4. Close the session. The ldap_unbind() function closes the connec-
+ tion.
+
+Operations can be performed either synchronously or asynchronously. The
+names of the synchronous functions end in _s. For example, a synchronous
+search can be completed by calling ldap_search_s(). An asynchronous
+search can be initiated by calling ldap_search(). All synchronous rou-
+tines return an indication of the outcome of the operation (e.g, the
+constant LDAP_SUCCESS or some other error code). The asynchronous rou-
+tines make available to the caller the message id of the operation ini-
+tiated. This id can be used in subsequent calls to ldap_result() to
+obtain the result(s) of the operation. An asynchronous operation can be
+abandoned by calling ldap_abandon() or ldap_abandon_ext().
+
+Results and errors are returned in an opaque structure called LDAPMes-
+sage. Routines are provided to parse this structure, step through
+entries and attributes returned, etc. Routines are also provided to
+interpret errors. Later sections of this document describe these rou-
+tines in more detail.
+
+LDAP version 3 servers may return referrals and references to other
+servers. By default, implementations of this API will attempt to follow
+referrals automatically for the application. This behavior can be dis-
+abled globally (using the ldap_set_option() call) or on a per-request
+basis through the use of a client control.
+
+All DN and string attribute values passed into or produced by this C
+LDAP API are represented using the character set of the underlying LDAP
+protocol version in use. When this API is used with LDAPv3, DN and
+string values are represented as UTF-8[10] characters. When this API is
+used with LDAPv2, the US-ASCII[12] or T.61[12] character set are used.
+Future documents may specific additional APIs supporting other character
+sets.
+
+For compatibility with existing applications, implementations of this
+API will by default use version 2 of the LDAP protocol. Applications
+that intend to take advantage of LDAP version 3 features will need to
+use the ldap_set_option() call with a LDAP_OPT_PROTOCOL_VERSION to
+switch to version 3.
+
+Note that this API is designed for use in environments where the 'int'
+type is at least 32 bits in size.
+
+
+
+
+
+Expires: 2 December 1999 [Page 5]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+6. Header File Requirements
+
+To promote portability of applications, implementations of this C LDAP
+API must conform to the following requirements of the header files used
+by applications to access the services of this API:
+
+Name and Inclusion
+ Applications are only required to include a single header file
+ named ldap.h to access all of the API services described in this
+ document. Therefore, the following C source program must com-
+ pile without errors:
+
+ #include <ldap.h>
+
+ int
+ main()
+ {
+ return 0;
+ }
+
+ Note that it is permissible for the ldap.h header file to
+ include other implementation-specific header files.
+
+Implementations SHOULD also provide a header file named lber.h to faci-
+late development of applications desiring compatibility with older LDAP
+implementations. The lber.h header file may be empty.
+
+
+Idempotence
+ All header files should be idempotent; that is, if they are
+ included more than once the effect is as if they had only been
+ included once.
+
+Must Be Included Before API Is Used
+ An application must include the ldap.h header file before
+ referencing any of the function or type definitions described in
+ this API specification.
+
+Mutual Independence
+ If possible, header files should be mutually independent with
+ minimal dependence on system or any other header files.
+
+Use of the 'const' Keyword
+ This API specification is defined in terms of ISO C[13]. It
+ makes use of function prototypes and the 'const' keyword. The
+ use of 'const' in this specification is limited to simple, non-
+ array function parameters to avoid forcing applications to
+ declare parameters and variables that accept return values from
+
+
+
+Expires: 2 December 1999 [Page 6]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ LDAP API functions as 'const.' Implementations specifically
+ designed to be used with non-ISO C translators may provide func-
+ tion declarations without prototypes or function prototypes
+ without specification of 'const' arguments.
+
+Definition of 'struct timeval'
+ This API specification uses the 'struct timeval' type. Imple-
+ mentations of this API should ensure that the struct timeval
+ type is by default defined as a consequence of including the
+ ldap.h header file. Because struct timeval is usually defined
+ in one or more system header files, it is possible for header
+ file conflicts to occur if ldap.h also defines it or arranges
+ for it to be defined by including another header file. There-
+ fore, applications may want to arrange for struct timeval to be
+ defined before they include ldap.h. To support this, the ldap.h
+ header file must not itself define struct timeval if the prepro-
+ cessor symbol LDAP_TYPE_TIMEVAL_DEFINED is defined before ldap.h
+ is included.
+
+
+7. Common Data Structures
+
+Some data structures that are common to several LDAP API functions are
+defined here:
+
+ typedef struct ldap LDAP;
+
+ typedef struct ldapmsg LDAPMessage;
+
+ typedef struct berelement BerElement;
+
+ typedef ber_len_t; /* actual definition is implementation-specific */
+
+ typedef ber_tag_t; /* actual definition is implementation-specific */
+
+ struct berval {
+ ber_len_t bv_len;
+ char *bv_val;
+ };
+
+ struct timeval {
+ long tv_sec;
+ long tv_usec;
+ };
+
+The LDAP structure is an opaque data type that represents an LDAP ses-
+sion Typically this corresponds to a connection to a single server, but
+it may encompass several server connections in the face of LDAPv3
+
+
+
+Expires: 2 December 1999 [Page 7]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+referrals.
+
+The LDAPMessage structure is an opaque data type that is used to return
+entry, reference, result, and error information. An LDAPMessage struc-
+ture may represent the beginning of a list, or chain of messages that
+consists of a series of entries, references, and result messages as
+returned by LDAP operations such as search. LDAP API functions such as
+ldap_parse_result() that operate on message chains that may contain more
+than one result message always operate on the first result message in
+the chain. See the "Obtaining Results and Peeking Inside LDAP Messages"
+section of this document for more information.
+
+The BerElement structure is an opaque data type that is used to hold
+data and state information about encoded data. It is described in more
+detail in the section "Encoded ASN.1 Value Manipulation" later in this
+document.
+
+The ber_len_t type is an unsigned integral data type that is large
+enough to contain the length of the largest piece of data supported by
+the API implementation. Similarly, the ber_tag_t type is an unsigned
+integral data type that is large enough to hold the largest BER tag sup-
+ported by the API implementation. Both of these types should be at
+least 32 bits in size. See the appendix "Data Types and Legacy Imple-
+mentations" for additional considerations.
+
+The berval structure is used to represent arbitrary binary data and its
+fields have the following meanings:
+
+bv_len Length of data in bytes.
+
+bv_val A pointer to the data itself.
+
+
+The timeval structure is used to represent an interval of time and its
+fields have the following meanings:
+
+tv_sec Seconds component of time interval.
+
+tv_usec Microseconds component of time interval.
+
+See the earlier section "Header File Requirements" for more information
+on struct timeval.
+
+
+8. Retrieving Information About the API Implementation
+
+Applications developed to this specification need to be able to deter-
+mine information about the particular API implementation they are using
+
+
+
+Expires: 2 December 1999 [Page 8]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+both at compile time and during execution.
+
+
+8.1. Retrieving Information at Compile Time
+
+All conformant implementations MUST include the following five defini-
+tions in a header file so compile time tests can be done by LDAP
+software developers:
+
+ #define LDAP_API_VERSION level
+ #define LDAP_VERSION_MIN min-version
+ #define LDAP_VERSION_MAX max-version
+ #define LDAP_VENDOR_NAME "vend-name"
+ #define LDAP_VENDOR_VERSION vend-version
+
+where:
+
+ "level" is replaced with the RFC number given to this C LDAP API
+ specification when it is published as a standards track RFC.
+
+ min-version is replaced with the lowest LDAP protocol version sup-
+ ported by the implementation.
+
+ max-version is replaced with the highest LDAP protocol version sup-
+ ported by the implementation. This should be 3.
+
+ "vend-name" is replaced with a text string that identifies the
+ party that supplies the API implementation.
+
+ "vend-version" is a supplier-specific version number multiplied
+ times 100.
+
+Note that the LDAP_VENDOR_NAME macro may be defined as "" if no vendor
+name is available and the LDAP_VENDOR_VERSION macro may be defined as 0
+if no vendor-specific version information is available.
+
+For example, if this specification is published as RFC 88888, Netscape
+Communication's version 4.0 implementation that supports LDAPv2 and v3
+might include macro definitions like these:
+
+ #define LDAP_API_VERSION 88888 /* RFC 88888 compliant */
+ #define LDAP_VERSION_MIN 2
+ #define LDAP_VERSION_MAX 3
+ #define LDAP_VENDOR_NAME "Netscape Communications Corp."
+ #define LDAP_VENDOR_VERSION 400 /* version 4.0 */
+
+and application code can test the C LDAP API version level using a
+construct such as this one:
+
+
+
+Expires: 2 December 1999 [Page 9]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ #if (LDAP_API_VERSION >= 88888)
+ /* use features supported in RFC 88888 or later */
+ #endif
+
+Until such time as this document is published as an RFC, implementations
+should use the value 2000 plus the revision number of this draft for
+LDAP_API_VERSION. For example, the correct value for LDAP_API_VERSION
+for revision 03 of this draft is 2003.
+
+Documents that extend this specification SHOULD define a macro of the
+form:
+
+ #define LDAP_API_FEATURE_x level
+
+where "x" is replaced with a name (textual identifier) for the feature
+and "level" is replaced with the number of the RFC that specifies the
+API extension. The name SHOULD NOT begin with the string "X_".
+
+For example, if C LDAP API extensions for Transport Layer Security [9]
+were published in RFC 99999, that RFC might require conformant implemen-
+tations to define a macro like this:
+
+ #define LDAP_API_FEATURE_TLS 99999
+
+
+Private or experimental API extensions may be indicated by defining a
+macro of this same form where "x" (the extension's name) begins with the
+string "X_" and "level" is replaced with a integer number that is
+specific to the extension.
+
+
+8.2. Retrieving Information During Execution
+
+The ldap_get_option() call (described in greater detail later in this
+document) can be used during execution in conjunction with an option
+parameter value of LDAP_OPT_API_INFO (0x00) to retrieve some basic
+information about the API and about the specific implementation being
+used. The ld parameter to ldap_get_option() can be either NULL or a
+valid LDAP session handle which was obtained by calling ldap_init().
+The optdata parameter to ldap_get_option() MUST be the address of an
+LDAPAPIInfo structure which is defined as follows:
+
+ typedef struct ldapapiinfo {
+ int ldapai_info_version; /* version of this struct (1) */
+ int ldapai_api_version; /* revision of API supported */
+ int ldapai_protocol_version; /* highest LDAP version supported */
+ char **ldapai_extensions; /* names of API extensions */
+ char *ldapai_vendor_name; /* name of supplier */
+
+
+
+Expires: 2 December 1999 [Page 10]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ int ldapai_vendor_version; /* supplier-specific version times 100 */
+ } LDAPAPIInfo;
+
+In addition, API implementations MUST include the following macro defin-
+ition:
+
+ #define LDAP_API_INFO_VERSION 1
+
+Note that the ldapai_info_version field of the LDAPAPIInfo structure
+should be set to the value LDAP_API_INFO_VERSION (1) before calling
+ldap_get_option() so that it can be checked for consistency. All other
+fields are set by the ldap_get_option() function.
+
+The members of the LDAPAPIInfo structure are:
+
+ldapai_info_version
+ A number that identifies the version of the LDAPAPIInfo struc-
+ ture. This should be set to the value LDAP_API_INFO_VERSION
+ (1) before calling ldap_get_option(). If the value received
+ is not recognized by the API implementation, the
+ ldap_get_option() function sets ldapai_info_version to a valid
+ value that would be recognized, sets the ldapai_api_version to
+ the correct value, and returns an error without filling in any
+ of the other fields in the LDAPAPIInfo structure.
+
+ldapai_api_version
+ A number that matches that assigned to the C LDAP API RFC sup-
+ ported by the API implementation. This should match the value
+ of the LDAP_API_VERSION macro defined earlier.
+
+ldapai_protocol_version
+ The highest LDAP protocol version supported by the implementa-
+ tion. For example, if LDAPv3 is the highest version supported
+ then this field will be set to 3.
+
+ldapai_extensions
+ A NULL-terminated array of character strings that lists the
+ names of the API extensions supported by the LDAP API imple-
+ mentation. These names will typically match the textual iden-
+ tifiers that appear in the "x" portion of the
+ LDAP_API_FEATURE_x macros described above, although the pre-
+ cise value MUST be defined by documents that specify C LDAP
+ API extensions. If no API extensions are supported, this
+ field will be set to NULL. The caller is responsible for
+ disposing of the memory occupied by this array by passing it
+ to ldap_value_free() which is described later in this docu-
+ ment. To retrieve more information about a particular exten-
+ sion, the ldap_get_option() call can be used with an option
+
+
+
+Expires: 2 December 1999 [Page 11]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ parameter value of LDAP_OPT_API_FEATURE_INFO (0x15). The opt-
+ data parameter to the ldap_get_option() MUST be the address of
+ an LDAPAPIFeatureInfo structure which is defined as follows:
+
+ typedef struct ldap_apifeature_info {
+ int ldapaif_info_version; /* version of this struct (1) */
+ char *ldapaif_name; /* name of supported feature */
+ int ldapaif_version; /* revision of supported feature */
+ } LDAPAPIFeatureInfo;
+
+ In addition, API implementations MUST include the following
+ macro definition:
+
+ #define LDAP_FEATURE_INFO_VERSION 1
+
+ Note that the ldapaif_info_version field of the LDAPAPI-
+ FeatureInfo structure should be set to the value
+ LDAP_FEATURE_INFO_VERSION (1) and the ldapaif_name field
+ should be set to the extension name string as described below
+ before ldap_get_option() is called. The call will fill in the
+ ldapaif_version field of the LDAPAPIFeatureInfo structure.
+
+ The members of the LDAPAPIFeatureInfo structure are:
+
+ ldapaif_info_version
+ A number that identifies the version of the LDAPAPI-
+ FeatureInfo structure. This should be set to the value
+ LDAP_FEATURE_INFO_VERSION (1) before calling
+ ldap_get_option(). If the value received is not recognized
+ by the API implementation, the ldap_get_option() function
+ sets ldapaif_info_version to a valid value that would be
+ recognized and returns an error without filling in the
+ ldapaif_version field in the LDAPAPIFeatureInfo structure.
+
+ ldapaif_name
+ The name of an extension, as returned in the
+ ldapai_extensions array of the LDAPAPIInfo structure and as
+ specified in the document that describes the extension.
+
+ ldapaif_version
+ This field will be set as a result of calling
+ ldap_get_option(). It is a number that matches that
+ assigned to the C LDAP API extension RFC supported for this
+ extension. For private or experimental API extensions, the
+ value is extension-specific. In either case, the value of
+ ldapaxi_ext_version should be identical to the value of the
+ LDAP_API_FEATURE_x macro defined for the extension
+ (described above).
+
+
+
+Expires: 2 December 1999 [Page 12]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+9. LDAP Error Codes
+
+Many of the LDAP API routines return LDAP error codes, some of which
+indicate local errors and some of which may be returned by servers. All
+of the LDAP error codes returned will be positive integers. Supported
+error codes are (hexadecimal values are given in parentheses after the
+constant):
+
+ LDAP_SUCCESS (0x00)
+ LDAP_OPERATIONS_ERROR (0x01)
+ LDAP_PROTOCOL_ERROR (0x02)
+ LDAP_TIMELIMIT_EXCEEDED (0x03)
+ LDAP_SIZELIMIT_EXCEEDED (0x04)
+ LDAP_COMPARE_FALSE (0x05)
+ LDAP_COMPARE_TRUE (0x06)
+ LDAP_STRONG_AUTH_NOT_SUPPORTED (0x07)
+ LDAP_STRONG_AUTH_REQUIRED (0x08)
+ LDAP_REFERRAL (0x0a) -- new in LDAPv3
+ LDAP_ADMINLIMIT_EXCEEDED (0x0b) -- new in LDAPv3
+ LDAP_UNAVAILABLE_CRITICAL_EXTENSION (0x0c) -- new in LDAPv3
+ LDAP_CONFIDENTIALITY_REQUIRED (0x0d) -- new in LDAPv3
+ LDAP_SASL_BIND_IN_PROGRESS (0x0e) -- new in LDAPv3
+ LDAP_NO_SUCH_ATTRIBUTE (0x10)
+ LDAP_UNDEFINED_TYPE (0x11)
+ LDAP_INAPPROPRIATE_MATCHING (0x12)
+ LDAP_CONSTRAINT_VIOLATION (0x13)
+ LDAP_TYPE_OR_VALUE_EXISTS (0x14)
+ LDAP_INVALID_SYNTAX (0x15)
+ LDAP_NO_SUCH_OBJECT (0x20)
+ LDAP_ALIAS_PROBLEM (0x21)
+ LDAP_INVALID_DN_SYNTAX (0x22)
+ LDAP_IS_LEAF (0x23) -- not used in LDAPv3
+ LDAP_ALIAS_DEREF_PROBLEM (0x24)
+ LDAP_INAPPROPRIATE_AUTH (0x30)
+ LDAP_INVALID_CREDENTIALS (0x31)
+ LDAP_INSUFFICIENT_ACCESS (0x32)
+ LDAP_BUSY (0x33)
+ LDAP_UNAVAILABLE (0x34)
+ LDAP_UNWILLING_TO_PERFORM (0x35)
+ LDAP_LOOP_DETECT (0x36)
+ LDAP_NAMING_VIOLATION (0x40)
+ LDAP_OBJECT_CLASS_VIOLATION (0x41)
+ LDAP_NOT_ALLOWED_ON_NONLEAF (0x42)
+ LDAP_NOT_ALLOWED_ON_RDN (0x43)
+ LDAP_ALREADY_EXISTS (0x44)
+ LDAP_NO_OBJECT_CLASS_MODS (0x45)
+ LDAP_RESULTS_TOO_LARGE (0x46) -- reserved for CLDAP
+ LDAP_AFFECTS_MULTIPLE_DSAS (0x47) -- new in LDAPv3
+
+
+
+Expires: 2 December 1999 [Page 13]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ LDAP_OTHER (0x50)
+ LDAP_SERVER_DOWN (0x51)
+ LDAP_LOCAL_ERROR (0x52)
+ LDAP_ENCODING_ERROR (0x53)
+ LDAP_DECODING_ERROR (0x54)
+ LDAP_TIMEOUT (0x55)
+ LDAP_AUTH_UNKNOWN (0x56)
+ LDAP_FILTER_ERROR (0x57)
+ LDAP_USER_CANCELLED (0x58)
+ LDAP_PARAM_ERROR (0x59)
+ LDAP_NO_MEMORY (0x5a)
+ LDAP_CONNECT_ERROR (0x5b)
+ LDAP_NOT_SUPPORTED (0x5c)
+ LDAP_CONTROL_NOT_FOUND (0x5d)
+ LDAP_NO_RESULTS_RETURNED (0x5e)
+ LDAP_MORE_RESULTS_TO_RETURN (0x5f)
+ LDAP_CLIENT_LOOP (0x60)
+ LDAP_REFERRAL_LIMIT_EXCEEDED (0x61)
+
+
+10. Performing LDAP Operations
+
+This section describes each LDAP operation API call in detail. All func-
+tions take a "session handle," a pointer to an LDAP structure containing
+per-connection information. Many routines return results in an LDAPMes-
+sage structure. These structures and others are described as needed
+below.
+
+
+10.1. Initializing an LDAP Session
+
+ldap_init() initializes a session with an LDAP server. The server is not
+actually contacted until an operation is performed that requires it,
+allowing various options to be set after initialization.
+
+ LDAP *ldap_init(
+ const char *hostname,
+ int portno
+ );
+
+Use of the following routine is deprecated:
+
+ LDAP *ldap_open(
+ const char *hostname,
+ int portno
+ );
+Unlike ldap_init(), ldap_open() attempts to make a server connection
+before returning to the caller.
+
+
+
+Expires: 2 December 1999 [Page 14]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+Parameters are:
+
+hostname Contains a space-separated list of hostnames or dotted strings
+ representing the IP address of hosts running an LDAP server to
+ connect to. Each hostname in the list can include an optional
+ port number which is separated from the host itself with a
+ colon (:) character. The hosts will be tried in the order
+ listed, stopping with the first one to which a successful con-
+ nection is made.
+
+ Note: A suitable representation for including a literal IPv6[11]
+ address in the hostname parameter is desired, but has not yet been
+ determined or implemented in practice.
+
+portno Contains the TCP port number to connect to. The default LDAP
+ port of 389 can be obtained by supplying the constant
+ LDAP_PORT. If a host includes a port number then this parame-
+ ter is ignored.
+
+ldap_init() and ldap_open() both return a "session handle," a pointer to
+an opaque structure that should be passed to subsequent calls pertaining
+to the session. These routines return NULL if the session cannot be ini-
+tialized in which case the operating system error reporting mechanism
+can be checked to see why the call failed.
+
+Note that if you connect to an LDAPv2 server, one of the LDAP bind calls
+described below must be completed before other operations can be per-
+formed on the session. LDAPv3 does not require that a bind operation be
+completed before other operations can be performed.
+
+The calling program can set various attributes of the session by calling
+the routines described in the next section.
+
+
+10.2. LDAP Session Handle Options
+
+The LDAP session handle returned by ldap_init() is a pointer to an
+opaque data type representing an LDAP session. In RFC 1823 this data
+type was a structure exposed to the caller, and various fields in the
+structure could be set to control aspects of the session, such as size
+and time limits on searches.
+
+In the interest of insulating callers from inevitable changes to this
+structure, these aspects of the session are now accessed through a pair
+of accessor functions, described below.
+
+ldap_get_option() is used to access the current value of various
+session-wide parameters. ldap_set_option() is used to set the value of
+
+
+
+Expires: 2 December 1999 [Page 15]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+these parameters. Note that some options are READ-ONLY and cannot be
+set; it is an error to call ldap_set_option() and attempt to set a
+READ-ONLY option.
+
+Note that if automatic referral following is enabled (the default), any
+connections created during the course of following referrals will
+inherit the options associated with the session that sent the original
+request that caused the referrals to be returned.
+
+ int ldap_get_option(
+ LDAP *ld,
+ int option,
+ void *outvalue
+ );
+
+ int ldap_set_option(
+ LDAP *ld,
+ int option,
+ const void *invalue
+ );
+
+ #define LDAP_OPT_ON ((void *)1)
+ #define LDAP_OPT_OFF ((void *)0)
+
+
+Parameters are:
+
+ld The session handle. If this is NULL, a set of global defaults is
+ accessed. New LDAP session handles created with ldap_init() or
+ ldap_open() inherit their characteristics from these global
+ defaults.
+
+option The name of the option being accessed or set. This parameter
+ should be one of the following constants, which have the indi-
+ cated meanings. After the constant the actual hexadecimal value
+ of the constant is listed in parentheses.
+
+
+ LDAP_OPT_API_INFO (0x00)
+ Type for invalue parameter: not applicable (option is READ-ONLY)
+
+ Type for outvalue parameter: LDAPAPIInfo *
+
+ Description:
+ Used to retrieve some basic information about the LDAP API
+ implementation at execution time. See the section "Retriev-
+ ing Information About the API Implementation" above for more
+ information. This option is READ-ONLY and cannot be set.
+
+
+
+Expires: 2 December 1999 [Page 16]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ LDAP_OPT_DESC (0x01)
+ Type for invalue parameter: not applicable (option is READ-
+ ONLY)
+
+ Type for outvalue parameter: int *
+
+ Description:
+ The underlying socket descriptor corresponding to the pri-
+ mary LDAP connection. This option is READ-ONLY and cannot
+ be set.
+
+ LDAP_OPT_DEREF (0x02)
+ Type for invalue parameter: int *
+
+ Type for outvalue parameter: int *
+
+ Description:
+ Determines how aliases are handled during search. It can
+ have one of the following values: LDAP_DEREF_NEVER (0x00),
+ LDAP_DEREF_SEARCHING (0x01), LDAP_DEREF_FINDING (0x02), or
+ LDAP_DEREF_ALWAYS (0x03). The LDAP_DEREF_SEARCHING value
+ means aliases should be dereferenced during the search but
+ not when locating the base object of the search. The
+ LDAP_DEREF_FINDING value means aliases should be derefer-
+ enced when locating the base object but not during the
+ search.
+
+ LDAP_OPT_SIZELIMIT (0x03)
+ Type for invalue parameter: int *
+
+ Type for outvalue parameter: int *
+
+ Description:
+ A limit on the number of entries to return from a search.
+ A value of LDAP_NO_LIMIT (0) means no limit.
+
+ LDAP_OPT_TIMELIMIT (0x04)
+ Type for invalue parameter: int *
+
+ Type for outvalue parameter: int *
+
+ Description:
+ A limit on the number of seconds to spend on a search. A
+ value of LDAP_NO_LIMIT (0) means no limit. This value is
+ passed to the server in the search request only; it does
+ not affect how long the C LDAP API implementation itself
+ will wait locally for search results. The timeout parame-
+ ter passed to ldap_search_ext_s() or ldap_result() -- both
+
+
+
+Expires: 2 December 1999 [Page 17]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ of which are described later in this document -- can be
+ used to specify both a local and server side time limit.
+
+ LDAP_OPT_REFERRALS (0x08)
+ Type for invalue parameter: void * (LDAP_OPT_ON or
+ LDAP_OPT_OFF)
+
+ Type for outvalue parameter: int *
+
+ Description:
+ Determines whether the LDAP library automatically follows
+ referrals returned by LDAP servers or not. It can be set
+ to one of the constants LDAP_OPT_ON or LDAP_OPT_OFF; any
+ non-NULL pointer value passed to ldap_set_option() enables
+ this option. When reading the current setting using
+ ldap_get_option(), a zero value means off and any non-zero
+ value means on.
+
+ LDAP_OPT_RESTART (0x09)
+ Type for invalue parameter: void * (LDAP_OPT_ON or
+ LDAP_OPT_OFF)
+
+ Type for outvalue parameter: int *
+
+ Description:
+ Determines whether LDAP I/O operations should automati-
+ cally be restarted if they abort prematurely. It should be
+ set to one of the constants LDAP_OPT_ON or LDAP_OPT_OFF;
+ any non-NULL pointer value passed to ldap_set_option()
+ enables this option. When reading the current setting
+ using ldap_get_option(), a zero value means off and any
+ non-zero value means on. This option is useful if an LDAP
+ I/O operation may be interrupted prematurely, for example
+ by a timer going off, or other interrupt.
+
+ LDAP_OPT_PROTOCOL_VERSION (0x11)
+ Type for invalue parameter: int *
+
+ Type for outvalue parameter: int *
+
+ Description:
+ This option indicates the version of the LDAP protocol
+ used when communicating with the primary LDAP server. It
+ must be one of the constants LDAP_VERSION2 (2) or
+ LDAP_VERSION3 (3). If no version is set the default is
+ LDAP_VERSION2 (2).
+
+ LDAP_OPT_SERVER_CONTROLS (0x12)
+
+
+
+Expires: 2 December 1999 [Page 18]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ Type for invalue parameter: LDAPControl **
+
+ Type for outvalue parameter: LDAPControl ***
+
+ Description:
+ A default list of LDAP server controls to be sent with
+ each request. See the Working With Controls section
+ below.
+
+ LDAP_OPT_CLIENT_CONTROLS (0x13)
+ Type for invalue parameter: LDAPControl **
+
+ Type for outvalue parameter: LDAPControl ***
+
+ Description:
+ A default list of client controls that affect the LDAP
+ session. See the Working With Controls section below.
+
+ LDAP_OPT_API_FEATURE_INFO (0x15)
+ Type for invalue parameter: not applicable (option is READ-
+ ONLY)
+
+ Type for outvalue parameter: LDAPAPIFeatureInfo *
+
+ Description:
+ Used to retrieve version information about LDAP API
+ extended features at execution time. See the section
+ "Retrieving Information About the API Implementation"
+ above for more information. This option is READ-ONLY and
+ cannot be set.
+
+ LDAP_OPT_HOST_NAME (0x30)
+ Type for invalue parameter: char *
+
+ Type for outvalue parameter: char **
+
+ Description:
+ The host name (or list of hosts) for the primary LDAP
+ server. See the definition of the hostname parameter to
+ ldap_init() for the allowed syntax.
+
+ LDAP_OPT_ERROR_NUMBER (0x31)
+ Type for invalue parameter: int *
+
+ Type for outvalue parameter: int *
+
+ Description:
+ The code of the most recent LDAP error that occurred for
+
+
+
+Expires: 2 December 1999 [Page 19]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ this session.
+
+ LDAP_OPT_ERROR_STRING (0x32)
+ Type for invalue parameter: char *
+
+ Type for outvalue parameter: char **
+
+ Description:
+ The message returned with the most recent LDAP error that
+ occurred for this session.
+
+
+ outvalue The address of a place to put the value of the option. The
+ actual type of this parameter depends on the setting of the
+ option parameter. For outvalues of type char ** and LDAP-
+ Control **, a copy of the data that is associated with the
+ LDAP session ld is returned; callers should dispose of the
+ memory by calling ldap_memfree() or ldap_controls_free().
+
+ invalue A pointer to the value the option is to be given. The actual
+ type of this parameter depends on the setting of the option
+ parameter. The data associated with invalue is copied by the
+ API implementation to allow callers of the API to dispose of
+ or otherwise change their copy of the data after a success-
+ ful call to ldap_set_option(). If a value passed for
+ invalue is invalid or cannot be accepted by the implementa-
+ tion, ldap_set_option() should return -1 to indicate an
+ error.
+
+Both ldap_get_option() and ldap_set_option() return 0 if successful and
+-1 if an error occurs.
+
+Standards track documents that extend this specification and specify new
+options MUST use values for option macros that are between 0x1000 and
+0x3FFF inclusive. Private and experimental extensions MUST use values
+for the option macros that are between 0x4000 and 0x7FFF inclusive. All
+values below 0x1000 and above 0x7FFF that are not defined in this docu-
+ment are reserved and MUST NOT be used.
+
+
+10.3. Working With Controls
+
+LDAPv3 operations can be extended through the use of controls. Controls
+may be sent to a server or returned to the client with any LDAP message.
+These controls are referred to as server controls.
+
+The LDAP API also supports a client-side extension mechanism through the
+use of client controls. These controls affect the behavior of the LDAP
+
+
+
+Expires: 2 December 1999 [Page 20]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+API only and are never sent to a server. A common data structure is
+used to represent both types of controls:
+
+ typedef struct ldapcontrol {
+ char *ldctl_oid;
+ struct berval ldctl_value;
+ char ldctl_iscritical;
+ } LDAPControl, *PLDAPControl;
+
+The fields in the ldapcontrol structure have the following meanings:
+
+ldctl_oid The control type, represented as a string.
+
+ldctl_value The data associated with the control (if any). To
+ specify a zero-length value, set ldctl_value.bv_len to
+ zero and ldctl_value.bv_val to a zero-length string.
+ To indicate that no data is associated with the con-
+ trol, set ldctl_value.bv_val to NULL.
+
+ldctl_iscritical Indicates whether the control is critical of not. If
+ this field is non-zero, the operation will only be car-
+ ried out if the control is recognized by the server
+ and/or client. Note that the LDAP unbind and abandon
+ operations have no server response, so clients SHOULD
+ NOT mark server controls critical when used with these
+ two operations.
+
+Some LDAP API calls allocate an ldapcontrol structure or a NULL-
+terminated array of ldapcontrol structures. The following routines can
+be used to dispose of a single control or an array of controls:
+
+ void ldap_control_free( LDAPControl *ctrl );
+ void ldap_controls_free( LDAPControl **ctrls );
+
+A set of controls that affect the entire session can be set using the
+ldap_set_option() function (see above). A list of controls can also be
+passed directly to some LDAP API calls such as ldap_search_ext(), in
+which case any controls set for the session through the use of
+ldap_set_option() are ignored. Control lists are represented as a NULL-
+terminated array of pointers to ldapcontrol structures.
+
+Server controls are defined by LDAPv3 protocol extension documents; for
+example, a control has been proposed to support server-side sorting of
+search results [7].
+
+One client control is defined in this document (described in the follow-
+ing section). Other client controls may be defined in future revisions
+of this document or in documents that extend this API.
+
+
+
+Expires: 2 December 1999 [Page 21]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+10.3.1. A Client Control That Governs Referral Processing
+
+As described previously in the section "LDAP Session Handle Options,"
+applications can enable and disable automatic chasing of referrals on a
+session-wide basic by using the ldap_set_option() function with the
+LDAP_OPT_REFERRALS option. It is also useful to govern automatic refer-
+ral chasing on per-request basis. A client control with an OID of
+1.2.840.113556.1.4.616 exists to provide this functionality.
+
+ /* OID for referrals client control */
+ #define LDAP_CONTROL_REFERRALS "1.2.840.113556.1.4.616"
+
+ /* Flags for referrals client control value */
+ #define LDAP_CHASE_SUBORDINATE_REFERRALS 0x00000020
+ #define LDAP_CHASE_EXTERNAL_REFERRALS 0x00000040
+
+To create a referrals client control, the ldctl_oid field of an LDAPCon-
+trol structure should be set to LDAP_CONTROL_REFERRALS
+("1.2.840.113556.1.4.616") and the ldctl_value field should be set to a
+4-octet value that contains a set of flags. The ldctl_value.bv_len
+field should always be set to 4. The ldctl_value.bv_val field should
+point to a 4-octet integer flags value. This flags value can be set to
+zero to disable automatic chasing of referrals and LDAPv3 references
+altogether. Alternatively, the flags value can be set to the value
+LDAP_CHASE_SUBORDINATE_REFERRALS (0x00000020) to indicate that only
+LDAPv3 search continuation references should be automatically chased by
+the API implementation, to the value LDAP_CHASE_EXTERNAL_REFERRALS
+(0x00000040) to indicate that only LDAPv3 referrals should be automati-
+cally chased, or the logical OR of the two flag values (0x00000060) to
+indicate that both referrals and references should be automatically
+chased.
+
+
+10.4. Authenticating to the directory
+
+The following functions are used to authenticate an LDAP client to an
+LDAP directory server.
+
+The ldap_sasl_bind() and ldap_sasl_bind_s() functions can be used to do
+general and extensible authentication over LDAP through the use of the
+Simple Authentication Security Layer [8]. The routines both take the dn
+to bind as, the method to use, as a dotted-string representation of an
+OID identifying the method, and a struct berval holding the credentials.
+The special constant value LDAP_SASL_SIMPLE (NULL) can be passed to
+request simple authentication, or the simplified routines
+ldap_simple_bind() or ldap_simple_bind_s() can be used.
+
+ int ldap_sasl_bind(
+
+
+
+Expires: 2 December 1999 [Page 22]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ LDAP *ld,
+ const char *dn,
+ const char *mechanism,
+ const struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp
+ );
+
+ int ldap_sasl_bind_s(
+ LDAP *ld,
+ const char *dn,
+ const char *mechanism,
+ const struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct berval **servercredp
+ );
+
+ int ldap_simple_bind(
+ LDAP *ld,
+ const char *dn,
+ const char *passwd
+ );
+
+ int ldap_simple_bind_s(
+ LDAP *ld,
+ const char *dn,
+ const char *passwd
+ );
+
+ The use of the following routines is deprecated:
+
+ int ldap_bind( LDAP *ld, const char *dn, const char *cred,
+ int method );
+
+ int ldap_bind_s( LDAP *ld, const char *dn, const char *cred,
+ int method );
+
+ int ldap_kerberos_bind( LDAP *ld, const char *dn );
+
+ int ldap_kerberos_bind_s( LDAP *ld, const char *dn );
+
+Parameters are:
+
+ld The session handle.
+
+dn The name of the entry to bind as.
+
+
+
+Expires: 2 December 1999 [Page 23]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+mechanism Either LDAP_SASL_SIMPLE (NULL) to get simple authentica-
+ tion, or a text string identifying the SASL method.
+
+cred The credentials with which to authenticate. Arbitrary
+ credentials can be passed using this parameter. The format
+ and content of the credentials depends on the setting of
+ the mechanism parameter.
+
+passwd For ldap_simple_bind(), the password to compare to the
+ entry's userPassword attribute.
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+msgidp This result parameter will be set to the message id of the
+ request if the ldap_sasl_bind() call succeeds.
+
+servercredp This result parameter will be filled in with the creden-
+ tials passed back by the server for mutual authentication,
+ if given. An allocated berval structure is returned that
+ should be disposed of by calling ber_bvfree(). NULL may be
+ passed to ignore this field.
+
+Additional parameters for the deprecated routines are not described.
+Interested readers are referred to RFC 1823.
+
+The ldap_sasl_bind() function initiates an asynchronous bind operation
+and returns the constant LDAP_SUCCESS if the request was successfully
+sent, or another LDAP error code if not. See the section below on error
+handling for more information about possible errors and how to interpret
+them. If successful, ldap_sasl_bind() places the message id of the
+request in *msgidp. A subsequent call to ldap_result(), described below,
+can be used to obtain the result of the bind.
+
+The ldap_simple_bind() function initiates a simple asynchronous bind
+operation and returns the message id of the operation initiated. A sub-
+sequent call to ldap_result(), described below, can be used to obtain
+the result of the bind. In case of error, ldap_simple_bind() will return
+-1, setting the session error parameters in the LDAP structure appropri-
+ately.
+
+The synchronous ldap_sasl_bind_s() and ldap_simple_bind_s() functions
+both return the result of the operation, either the constant
+LDAP_SUCCESS if the operation was successful, or another LDAP error code
+if it was not. See the section below on error handling for more informa-
+tion about possible errors and how to interpret them.
+
+
+
+
+Expires: 2 December 1999 [Page 24]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+Note that if an LDAPv2 server is contacted, no other operations over the
+connection should be attempted before a bind call has successfully com-
+pleted.
+
+Subsequent bind calls can be used to re-authenticate over the same con-
+nection, and multistep SASL sequences can be accomplished through a
+sequence of calls to ldap_sasl_bind() or ldap_sasl_bind_s().
+
+
+10.5. Closing the session
+
+The following functions are used to unbind from the directory, close
+open connections, and dispose of the session handle.
+
+ int ldap_unbind_ext( LDAP *ld, LDAPControl **serverctrls,
+ LDAPControl **clientctrls );
+
+ int ldap_unbind( LDAP *ld );
+
+ int ldap_unbind_s( LDAP *ld );
+
+Parameters are:
+
+ld The session handle.
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+The ldap_unbind_ext(), ldap_unbind() and ldap_unbind_s() all work syn-
+chronously in the sense that they send an unbind request to the server,
+close all open connections associated with the LDAP session handle, and
+dispose of all resources associated with the session handle before
+returning. Note, however, that there is no server response to an LDAP
+unbind operation. All three of the unbind functions return LDAP_SUCCESS
+(or another LDAP error code if the request cannot be sent to the LDAP
+server). After a call to one of the unbind functions, the session han-
+dle ld is invalid and it is illegal to make any further LDAP API calls
+using ld.
+
+The ldap_unbind() and ldap_unbind_s() functions behave identically. The
+ldap_unbind_ext() function allows server and client controls to be
+included explicitly, but note that since there is no server response to
+an unbind request there is no way to receive a response to a server con-
+trol sent with an unbind request.
+
+
+
+
+
+
+Expires: 2 December 1999 [Page 25]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+10.6. Searching
+
+The following functions are used to search the LDAP directory, returning
+a requested set of attributes for each entry matched. There are five
+variations.
+
+ int ldap_search_ext(
+ LDAP *ld,
+ const char *base,
+ int scope,
+ const char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct timeval *timeout,
+ int sizelimit,
+ int *msgidp
+ );
+
+ int ldap_search_ext_s(
+ LDAP *ld,
+ const char *base,
+ int scope,
+ const char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct timeval *timeout,
+ int sizelimit,
+ LDAPMessage **res
+ );
+
+ int ldap_search(
+ LDAP *ld,
+ const char *base,
+ int scope,
+ const char *filter,
+ char **attrs,
+ int attrsonly
+ );
+
+ int ldap_search_s(
+ LDAP *ld,
+ const char *base,
+ int scope,
+ const char *filter,
+
+
+
+Expires: 2 December 1999 [Page 26]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res
+ );
+
+ int ldap_search_st(
+ LDAP *ld,
+ const char *base,
+ int scope,
+ const char *filter,
+ char **attrs,
+ int attrsonly,
+ struct timeval *timeout,
+ LDAPMessage **res
+ );
+
+Parameters are:
+
+ld The session handle.
+
+base The dn of the entry at which to start the search.
+
+scope One of LDAP_SCOPE_BASE (0x00), LDAP_SCOPE_ONELEVEL (0x01),
+ or LDAP_SCOPE_SUBTREE (0x02), indicating the scope of the
+ search.
+
+filter A character string as described in [3], representing the
+ search filter. The value NULL can be passed to indicate
+ that the filter "(objectclass=*)" which matches all entries
+ should be used. Note that if the caller of the API is
+ using LDAPv2, only a subset of the filter functionality
+ described in [3] can be successfully used.
+
+attrs A NULL-terminated array of strings indicating which attri-
+ butes to return for each matching entry. Passing NULL for
+ this parameter causes all available user attributes to be
+ retrieved. The special constant string LDAP_NO_ATTRS
+ ("1.1") can be used as the only string in the array to
+ indicate that no attribute types should be returned by the
+ server. The special constant string LDAP_ALL_USER_ATTRS
+ ("*") can be used in the attrs array along with the names
+ of some operational attributes to indicate that all user
+ attributes plus the listed operational attributes should be
+ returned.
+
+attrsonly A boolean value that should be zero if both attribute types
+ and values are to be returned, non-zero if only types are
+ wanted.
+
+
+
+Expires: 2 December 1999 [Page 27]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+timeout For the ldap_search_st() function, this specifies the local
+ search timeout value (if it is NULL, the timeout is infin-
+ ite). For the ldap_search_ext() and ldap_search_ext_s()
+ functions, this specifies both the local search timeout
+ value and the operation time limit that is sent to the
+ server within the search request. For the
+ ldap_search_ext() and ldap_search_ext_s() functions, pass-
+ ing a NULL value for timeout causes the global default
+ timeout stored in the LDAP session handle (set by using
+ ldap_set_option() with the LDAP_OPT_TIMELIMIT parameter) to
+ be sent to the server with the request but an infinite
+ local search timeout to be used.
+
+sizelimit For the ldap_search_ext() and ldap_search_ext_s() calls,
+ this is a limit on the number of entries to return from the
+ search. A value of LDAP_NO_LIMIT (0) means no limit.
+
+res For the synchronous calls, this is a result parameter which
+ will contain the results of the search upon completion of
+ the call. If no results are returned, *res is set to NULL.
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+msgidp This result parameter will be set to the message id of the
+ request if the ldap_search_ext() call succeeds.
+
+There are three options in the session handle ld which potentially
+affect how the search is performed. They are:
+
+LDAP_OPT_SIZELIMIT
+ A limit on the number of entries to return from the search.
+ A value of LDAP_NO_LIMIT (0) means no limit. Note that the
+ value from the session handle is ignored when using the
+ ldap_search_ext() or ldap_search_ext_s() functions.
+
+LDAP_OPT_TIMELIMIT
+ A limit on the number of seconds to spend on the search. A
+ value of LDAP_NO_LIMIT (0) means no limit. Note that the
+ value from the session handle is ignored when using the
+ ldap_search_ext() or ldap_search_ext_s() functions.
+
+LDAP_OPT_DEREF
+ One of LDAP_DEREF_NEVER (0x00), LDAP_DEREF_SEARCHING
+ (0x01), LDAP_DEREF_FINDING (0x02), or LDAP_DEREF_ALWAYS
+ (0x03), specifying how aliases should be handled during the
+ search. The LDAP_DEREF_SEARCHING value means aliases should
+
+
+
+Expires: 2 December 1999 [Page 28]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ be dereferenced during the search but not when locating the
+ base object of the search. The LDAP_DEREF_FINDING value
+ means aliases should be dereferenced when locating the base
+ object but not during the search.
+
+The ldap_search_ext() function initiates an asynchronous search opera-
+tion and returns the constant LDAP_SUCCESS if the request was success-
+fully sent, or another LDAP error code if not. See the section below on
+error handling for more information about possible errors and how to
+interpret them. If successful, ldap_search_ext() places the message id
+of the request in *msgidp. A subsequent call to ldap_result(), described
+below, can be used to obtain the results from the search. These results
+can be parsed using the result parsing routines described in detail
+later.
+
+Similar to ldap_search_ext(), the ldap_search() function initiates an
+asynchronous search operation and returns the message id of the opera-
+tion initiated. As for ldap_search_ext(), a subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+bind. In case of error, ldap_search() will return -1, setting the ses-
+sion error parameters in the LDAP structure appropriately.
+
+The synchronous ldap_search_ext_s(), ldap_search_s(), and
+ldap_search_st() functions all return the result of the operation,
+either the constant LDAP_SUCCESS if the operation was successful, or
+another LDAP error code if it was not. See the section below on error
+handling for more information about possible errors and how to interpret
+them. Entries returned from the search (if any) are contained in the
+res parameter. This parameter is opaque to the caller. Entries, attri-
+butes, values, etc., should be extracted by calling the parsing routines
+described below. The results contained in res should be freed when no
+longer in use by calling ldap_msgfree(), described later.
+
+The ldap_search_ext() and ldap_search_ext_s() functions support LDAPv3
+server controls, client controls, and allow varying size and time limits
+to be easily specified for each search operation. The ldap_search_st()
+function is identical to ldap_search_s() except that it takes an addi-
+tional parameter specifying a local timeout for the search. The local
+search timeout is used to limit the amount of time the API implementa-
+tion will wait for a search to complete. After the local search timeout
+expires, the API implementation will send an abandon operation to abort
+the search operation.
+
+10.7. Reading an Entry
+
+LDAP does not support a read operation directly. Instead, this operation
+is emulated by a search with base set to the DN of the entry to read,
+scope set to LDAP_SCOPE_BASE, and filter set to "(objectclass=*)" or
+
+
+
+Expires: 2 December 1999 [Page 29]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+NULL. attrs contains the list of attributes to return.
+
+
+10.8. Listing the Children of an Entry
+
+LDAP does not support a list operation directly. Instead, this operation
+is emulated by a search with base set to the DN of the entry to list,
+scope set to LDAP_SCOPE_ONELEVEL, and filter set to "(objectclass=*)" or
+NULL. attrs contains the list of attributes to return for each child
+entry.
+
+10.9. Comparing a Value Against an Entry
+
+The following routines are used to compare a given attribute value
+assertion against an LDAP entry. There are four variations:
+
+ int ldap_compare_ext(
+ LDAP *ld,
+ const char *dn,
+ const char *attr,
+ struct berval *bvalue
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp
+ );
+
+ int ldap_compare_ext_s(
+ LDAP *ld,
+ const char *dn,
+ const char *attr,
+ struct berval *bvalue,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls
+ );
+
+ int ldap_compare(
+ LDAP *ld,
+ const char *dn,
+ const char *attr,
+ const char *value
+ );
+
+ int ldap_compare_s(
+ LDAP *ld,
+ const char *dn,
+ const char *attr,
+ const char *value
+ );
+
+
+
+Expires: 2 December 1999 [Page 30]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+Parameters are:
+
+ld The session handle.
+
+dn The name of the entry to compare against.
+
+attr The attribute to compare against.
+
+bvalue The attribute value to compare against those found in the
+ given entry. This parameter is used in the extended rou-
+ tines and is a pointer to a struct berval so it is possible
+ to compare binary values.
+
+value A string attribute value to compare against, used by the
+ ldap_compare() and ldap_compare_s() functions. Use
+ ldap_compare_ext() or ldap_compare_ext_s() if you need to
+ compare binary values.
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+msgidp This result parameter will be set to the message id of the
+ request if the ldap_compare_ext() call succeeds.
+
+The ldap_compare_ext() function initiates an asynchronous compare opera-
+tion and returns the constant LDAP_SUCCESS if the request was success-
+fully sent, or another LDAP error code if not. See the section below on
+error handling for more information about possible errors and how to
+interpret them. If successful, ldap_compare_ext() places the message id
+of the request in *msgidp. A subsequent call to ldap_result(), described
+below, can be used to obtain the result of the compare.
+
+Similar to ldap_compare_ext(), the ldap_compare() function initiates an
+asynchronous compare operation and returns the message id of the opera-
+tion initiated. As for ldap_compare_ext(), a subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+bind. In case of error, ldap_compare() will return -1, setting the ses-
+sion error parameters in the LDAP structure appropriately.
+
+The synchronous ldap_compare_ext_s() and ldap_compare_s() functions both
+return the result of the operation, either the constant LDAP_SUCCESS if
+the operation was successful, or another LDAP error code if it was not.
+See the section below on error handling for more information about pos-
+sible errors and how to interpret them.
+
+The ldap_compare_ext() and ldap_compare_ext_s() functions support LDAPv3
+server controls and client controls.
+
+
+
+Expires: 2 December 1999 [Page 31]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+10.10. Modifying an entry
+
+The following routines are used to modify an existing LDAP entry. There
+are four variations:
+
+ typedef struct ldapmod {
+ int mod_op;
+ char *mod_type;
+ union {
+ char **modv_strvals;
+ struct berval **modv_bvals;
+ } mod_vals;
+ } LDAPMod;
+ #define mod_values mod_vals.modv_strvals
+ #define mod_bvalues mod_vals.modv_bvals
+
+ int ldap_modify_ext(
+ LDAP *ld,
+ const char *dn,
+ LDAPMod **mods,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp
+ );
+
+ int ldap_modify_ext_s(
+ LDAP *ld,
+ const char *dn,
+ LDAPMod **mods,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls
+ );
+
+ int ldap_modify(
+ LDAP *ld,
+ const char *dn,
+ LDAPMod **mods
+ );
+
+ int ldap_modify_s(
+ LDAP *ld,
+ const char *dn,
+ LDAPMod **mods
+ );
+
+Parameters are:
+
+ld The session handle.
+
+
+
+Expires: 2 December 1999 [Page 32]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+dn The name of the entry to modify.
+
+mods A NULL-terminated array of modifications to make to the
+ entry.
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+msgidp This result parameter will be set to the message id of the
+ request if the ldap_modify_ext() call succeeds.
+
+The fields in the LDAPMod structure have the following meanings:
+
+mod_op The modification operation to perform. It should be one of
+ LDAP_MOD_ADD (0x00), LDAP_MOD_DELETE (0x01), or
+ LDAP_MOD_REPLACE (0x02). This field also indicates the
+ type of values included in the mod_vals union. It is logi-
+ cally ORed with LDAP_MOD_BVALUES (0x80) to select the
+ mod_bvalues form. Otherwise, the mod_values form is used.
+
+mod_type The type of the attribute to modify.
+
+mod_vals The values (if any) to add, delete, or replace. Only one of
+ the mod_values or mod_bvalues variants should be used,
+ selected by ORing the mod_op field with the constant
+ LDAP_MOD_BVALUES. mod_values is a NULL-terminated array of
+ zero-terminated strings and mod_bvalues is a NULL-
+ terminated array of berval structures that can be used to
+ pass binary values such as images.
+
+For LDAP_MOD_ADD modifications, the given values are added to the
+entry, creating the attribute if necessary.
+
+For LDAP_MOD_DELETE modifications, the given values are deleted from the
+entry, removing the attribute if no values remain. If the entire attri-
+bute is to be deleted, the mod_vals field should be set to NULL.
+
+For LDAP_MOD_REPLACE modifications, the attribute will have the listed
+values after the modification, having been created if necessary, or
+removed if the mod_vals field is NULL. All modifications are performed
+in the order in which they are listed.
+
+The ldap_modify_ext() function initiates an asynchronous modify opera-
+tion and returns the constant LDAP_SUCCESS if the request was success-
+fully sent, or another LDAP error code if not. See the section below on
+error handling for more information about possible errors and how to
+interpret them. If successful, ldap_modify_ext() places the message id
+
+
+
+Expires: 2 December 1999 [Page 33]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+of the request in *msgidp. A subsequent call to ldap_result(), described
+below, can be used to obtain the result of the modify.
+
+Similar to ldap_modify_ext(), the ldap_modify() function initiates an
+asynchronous modify operation and returns the message id of the opera-
+tion initiated. As for ldap_modify_ext(), a subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+modify. In case of error, ldap_modify() will return -1, setting the ses-
+sion error parameters in the LDAP structure appropriately.
+
+The synchronous ldap_modify_ext_s() and ldap_modify_s() functions both
+return the result of the operation, either the constant LDAP_SUCCESS if
+the operation was successful, or another LDAP error code if it was not.
+See the section below on error handling for more information about pos-
+sible errors and how to interpret them.
+
+The ldap_modify_ext() and ldap_modify_ext_s() functions support LDAPv3
+server controls and client controls.
+
+
+10.11. Modifying the Name of an Entry
+
+In LDAPv2, the ldap_modrdn(), ldap_modrdn_s(), ldap_modrdn2(), and
+ldap_modrdn2_s() routines were used to change the name of an LDAP entry.
+They could only be used to change the least significant component of a
+name (the RDN or relative distinguished name). LDAPv3 provides the
+Modify DN protocol operation that allows more general name change
+access. The ldap_rename() and ldap_rename_s() routines are used to
+change the name of an entry, and the use of the ldap_modrdn(),
+ldap_modrdn_s(), ldap_modrdn2(), and ldap_modrdn2_s() routines is depre-
+cated.
+
+ int ldap_rename(
+ LDAP *ld,
+ const char *dn,
+ const char *newrdn,
+ const char *newparent,
+ int deleteoldrdn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp
+
+ );
+ int ldap_rename_s(
+ LDAP *ld,
+ const char *dn,
+ const char *newrdn,
+ const char *newparent,
+
+
+
+Expires: 2 December 1999 [Page 34]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ int deleteoldrdn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls
+ );
+
+ Use of the following routines is deprecated.
+
+ int ldap_modrdn(
+ LDAP *ld,
+ const char *dn,
+ const char *newrdn
+ );
+ int ldap_modrdn_s(
+ LDAP *ld,
+ const char *dn,
+ const char *newrdn
+ );
+ int ldap_modrdn2(
+ LDAP *ld,
+ const char *dn,
+ const char *newrdn,
+ int deleteoldrdn
+ );
+ int ldap_modrdn2_s(
+ LDAP *ld,
+ const char *dn,
+ const char *newrdn,
+ int deleteoldrdn
+ );
+
+Parameters are:
+
+ld The session handle.
+
+dn The name of the entry whose DN is to be changed.
+
+newrdn The new RDN to give the entry.
+
+newparent The new parent, or superior entry. If this parameter is
+ NULL, only the RDN of the entry is changed. The root DN
+ may be specified by passing a zero length string, "". The
+ newparent parameter should always be NULL when using ver-
+ sion 2 of the LDAP protocol; otherwise the server's
+ behavior is undefined.
+
+deleteoldrdn This parameter only has meaning on the rename routines if
+ newrdn is different than the old RDN. It is a boolean
+ value, if non-zero indicating that the old RDN value(s)
+
+
+
+Expires: 2 December 1999 [Page 35]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ should be removed, if zero indicating that the old RDN
+ value(s) should be retained as non-distinguished values of
+ the entry.
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+msgidp This result parameter will be set to the message id of the
+ request if the ldap_rename() call succeeds.
+
+The ldap_rename() function initiates an asynchronous modify DN operation
+and returns the constant LDAP_SUCCESS if the request was successfully
+sent, or another LDAP error code if not. See the section below on error
+handling for more information about possible errors and how to interpret
+them. If successful, ldap_rename() places the DN message id of the
+request in *msgidp. A subsequent call to ldap_result(), described below,
+can be used to obtain the result of the rename.
+
+The synchronous ldap_rename_s() returns the result of the operation,
+either the constant LDAP_SUCCESS if the operation was successful, or
+another LDAP error code if it was not. See the section below on error
+handling for more information about possible errors and how to interpret
+them.
+
+The ldap_rename() and ldap_rename_s() functions both support LDAPv3
+server controls and client controls.
+
+
+10.12. Adding an entry
+
+The following functions are used to add entries to the LDAP directory.
+There are four variations:
+
+ int ldap_add_ext(
+ LDAP *ld,
+ const char *dn,
+ LDAPMod **attrs,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp
+ );
+
+ int ldap_add_ext_s(
+ LDAP *ld,
+ const char *dn,
+ LDAPMod **attrs,
+ LDAPControl **serverctrls,
+
+
+
+Expires: 2 December 1999 [Page 36]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ LDAPControl **clientctrls
+ );
+
+ int ldap_add(
+ LDAP *ld,
+ const char *dn,
+ LDAPMod **attrs
+ );
+
+ int ldap_add_s(
+ LDAP *ld,
+ const char *dn,
+ LDAPMod **attrs
+ );
+
+Parameters are:
+
+ld The session handle.
+
+dn The name of the entry to add.
+
+attrs The entry's attributes, specified using the LDAPMod struc-
+ ture defined for ldap_modify(). The mod_type and mod_vals
+ fields should be filled in. The mod_op field is ignored
+ unless ORed with the constant LDAP_MOD_BVALUES, used to
+ select the mod_bvalues case of the mod_vals union.
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+msgidp This result parameter will be set to the message id of the
+ request if the ldap_add_ext() call succeeds.
+
+Note that the parent of the entry being added must already exist or the
+parent must be empty (i.e., equal to the root DN) for an add to succeed.
+
+The ldap_add_ext() function initiates an asynchronous add operation and
+returns the constant LDAP_SUCCESS if the request was successfully sent,
+or another LDAP error code if not. See the section below on error han-
+dling for more information about possible errors and how to interpret
+them. If successful, ldap_add_ext() places the message id of the
+request in *msgidp. A subsequent call to ldap_result(), described below,
+can be used to obtain the result of the add.
+
+Similar to ldap_add_ext(), the ldap_add() function initiates an asyn-
+chronous add operation and returns the message id of the operation ini-
+tiated. As for ldap_add_ext(), a subsequent call to ldap_result(),
+
+
+
+Expires: 2 December 1999 [Page 37]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+described below, can be used to obtain the result of the add. In case of
+error, ldap_add() will return -1, setting the session error parameters
+in the LDAP structure appropriately.
+
+The synchronous ldap_add_ext_s() and ldap_add_s() functions both return
+the result of the operation, either the constant LDAP_SUCCESS if the
+operation was successful, or another LDAP error code if it was not. See
+the section below on error handling for more information about possible
+errors and how to interpret them.
+
+The ldap_add_ext() and ldap_add_ext_s() functions support LDAPv3 server
+controls and client controls.
+
+
+
+10.13. Deleting an entry
+
+The following functions are used to delete a leaf entry from the LDAP
+directory. There are four variations:
+
+ int ldap_delete_ext(
+ LDAP *ld,
+ const char *dn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp
+ );
+
+ int ldap_delete_ext_s(
+ LDAP *ld,
+ const char *dn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls
+ );
+
+ int ldap_delete(
+ LDAP *ld,
+ const char *dn
+ );
+
+ int ldap_delete_s(
+ LDAP *ld,
+ const char *dn
+ );
+
+Parameters are:
+
+ld The session handle.
+
+
+
+Expires: 2 December 1999 [Page 38]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+dn The name of the entry to delete.
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+msgidp This result parameter will be set to the message id of the
+ request if the ldap_delete_ext() call succeeds.
+
+Note that the entry to delete must be a leaf entry (i.e., it must have
+no children). Deletion of entire subtrees in a single operation is not
+supported by LDAP.
+
+The ldap_delete_ext() function initiates an asynchronous delete opera-
+tion and returns the constant LDAP_SUCCESS if the request was success-
+fully sent, or another LDAP error code if not. See the section below on
+error handling for more information about possible errors and how to
+interpret them. If successful, ldap_delete_ext() places the message id
+of the request in *msgidp. A subsequent call to ldap_result(), described
+below, can be used to obtain the result of the delete.
+
+Similar to ldap_delete_ext(), the ldap_delete() function initiates an
+asynchronous delete operation and returns the message id of the opera-
+tion initiated. As for ldap_delete_ext(), a subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+delete. In case of error, ldap_delete() will return -1, setting the ses-
+sion error parameters in the LDAP structure appropriately.
+
+The synchronous ldap_delete_ext_s() and ldap_delete_s() functions both
+return the result of the operation, either the constant LDAP_SUCCESS if
+the operation was successful, or another LDAP error code if it was not.
+See the section below on error handling for more information about pos-
+sible errors and how to interpret them.
+
+The ldap_delete_ext() and ldap_delete_ext_s() functions support LDAPv3
+server controls and client controls.
+
+
+10.14. Extended Operations
+
+The ldap_extended_operation() and ldap_extended_operation_s() routines
+allow extended LDAP operations to be passed to the server, providing a
+general protocol extensibility mechanism.
+
+ int ldap_extended_operation(
+ LDAP *ld,
+ const char *requestoid,
+ struct berval *requestdata,
+
+
+
+Expires: 2 December 1999 [Page 39]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp
+ );
+
+ int ldap_extended_operation_s(
+ LDAP *ld,
+ const char *requestoid,
+ struct berval *requestdata,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ char **retoidp,
+ struct berval **retdatap
+ );
+
+Parameters are:
+
+ld The session handle.
+
+requestoid The dotted-OID text string naming the request.
+
+requestdata The arbitrary data required by the operation (if NULL, no
+ data is sent to the server).
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+msgidp This result parameter will be set to the message id of the
+ request if the ldap_extended_operation() call succeeds.
+
+retoidp Pointer to a character string that will be set to an allo-
+ cated, dotted-OID text string returned by the server. This
+ string should be disposed of using the ldap_memfree() func-
+ tion. If no OID was returned, *retoidp is set to NULL.
+
+retdatap Pointer to a berval structure pointer that will be set an
+ allocated copy of the data returned by the server. This
+ struct berval should be disposed of using ber_bvfree(). If
+ no data is returned, *retdatap is set to NULL.
+
+The ldap_extended_operation() function initiates an asynchronous
+extended operation and returns the constant LDAP_SUCCESS if the request
+was successfully sent, or another LDAP error code if not. See the sec-
+tion below on error handling for more information about possible errors
+and how to interpret them. If successful, ldap_extended_operation()
+places the message id of the request in *msgidp. A subsequent call to
+ldap_result(), described below, can be used to obtain the result of the
+
+
+
+Expires: 2 December 1999 [Page 40]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+extended operation which can be passed to ldap_parse_extended_result()
+to obtain the OID and data contained in the response.
+
+The synchronous ldap_extended_operation_s() function returns the result
+of the operation, either the constant LDAP_SUCCESS if the operation was
+successful, or another LDAP error code if it was not. See the section
+below on error handling for more information about possible errors and
+how to interpret them. The retoid and retdata parameters are filled in
+with the OID and data from the response. If no OID or data was
+returned, these parameters are set to NULL.
+
+The ldap_extended_operation() and ldap_extended_operation_s() functions
+both support LDAPv3 server controls and client controls.
+
+
+11. Abandoning An Operation
+
+The following calls are used to abandon an operation in progress:
+
+ int ldap_abandon_ext(
+ LDAP *ld,
+ int msgid,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls
+ );
+
+ int ldap_abandon(
+ LDAP *ld,
+ int msgid
+ );
+
+
+ld The session handle.
+
+msgid The message id of the request to be abandoned.
+
+serverctrls List of LDAP server controls.
+
+clientctrls List of client controls.
+
+ldap_abandon_ext() abandons the operation with message id msgid and
+returns the constant LDAP_SUCCESS if the abandon was successful or
+another LDAP error code if not. See the section below on error handling
+for more information about possible errors and how to interpret them.
+
+ldap_abandon() is identical to ldap_abandon_ext() except that it does
+not accept client or server controls and it returns zero if the abandon
+was successful, -1 otherwise.
+
+
+
+Expires: 2 December 1999 [Page 41]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+After a successful call to ldap_abandon() or ldap_abandon_ext(), results
+with the given message id are never returned from a subsequent call to
+ldap_result(). There is no server response to LDAP abandon operations.
+
+
+12. Obtaining Results and Peeking Inside LDAP Messages
+
+ldap_result() is used to obtain the result of a previous asynchronously
+initiated operation. Note that depending on how it is called,
+ldap_result() may actually return a list or "chain" of result messages.
+The ldap_result() function only returns messages for a single request,
+so for all LDAP operations other than search only one result message is
+expected; that is, the only time the "result chain" may contain more
+than one message is if results from a search operation are returned.
+Once a chain of messages has been returned to the caller, it is no
+longer tied in any caller-visible way to the LDAP request that produced
+it. Therefore, a chain of messages returned by calling ldap_result() or
+by calling a synchronous search routine will never be affected by subse-
+quent LDAP API calls (except for ldap_msgfree() which is used to dispose
+of a chain of messages).
+
+ldap_msgfree() frees the result messages (possibly an entire chain of
+messages) obtained from a previous call to ldap_result() or from a call
+to a synchronous search routine.
+
+ldap_msgtype() returns the type of an LDAP message. ldap_msgid()
+returns the message ID of an LDAP message.
+
+ int ldap_result(
+ LDAP *ld,
+ int msgid,
+ int all,
+ struct timeval *timeout,
+ LDAPMessage **res
+ );
+
+ int ldap_msgfree( LDAPMessage *res );
+
+ int ldap_msgtype( LDAPMessage *res );
+
+ int ldap_msgid( LDAPMessage *res );
+
+Parameters are:
+
+ld The session handle.
+
+msgid The message id of the operation whose results are to be
+ returned, or the constant LDAP_RES_ANY (-1) if any result is
+
+
+
+Expires: 2 December 1999 [Page 42]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ desired.
+
+all Specifies how many messages will be retrieved in a single call
+ to ldap_result(). This parameter only has meaning for search
+ results. Pass the constant LDAP_MSG_ONE (0x00) to retrieve one
+ message at a time. Pass LDAP_MSG_ALL (0x01) to request that
+ all results of a search be received before returning all
+ results in a single chain. Pass LDAP_MSG_RECEIVED (0x02) to
+ indicate that all messages retrieved so far should be returned
+ in the result chain.
+
+timeout A timeout specifying how long to wait for results to be
+ returned. A NULL value causes ldap_result() to block until
+ results are available. A timeout value of zero seconds speci-
+ fies a polling behavior.
+
+res For ldap_result(), a result parameter that will contain the
+ result(s) of the operation. If no results are returned, *res is
+ set to NULL. For ldap_msgfree(), the result chain to be freed,
+ obtained from a previous call to ldap_result(),
+ ldap_search_s(), or ldap_search_st(). If res is NULL, nothing
+ is done and ldap_msgfree() returns zero.
+
+Upon successful completion, ldap_result() returns the type of the first
+result returned in the res parameter. This will be one of the following
+constants.
+
+ LDAP_RES_BIND (0x61)
+ LDAP_RES_SEARCH_ENTRY (0x64)
+ LDAP_RES_SEARCH_REFERENCE (0x73) -- new in LDAPv3
+ LDAP_RES_SEARCH_RESULT (0x65)
+ LDAP_RES_MODIFY (0x67)
+ LDAP_RES_ADD (0x69)
+ LDAP_RES_DELETE (0x6B)
+ LDAP_RES_MODDN (0x6D)
+ LDAP_RES_COMPARE (0x6F)
+ LDAP_RES_EXTENDED (0x78) -- new in LDAPv3
+
+ldap_result() returns 0 if the timeout expired and -1 if an error
+occurs, in which case the error parameters of the LDAP session handle
+will be set accordingly.
+
+ldap_msgfree() frees the result structure pointed to by res and returns
+the type of the message it freed. If res is NULL, nothing is done and
+the value zero is returned.
+
+ldap_msgtype() returns the type of the LDAP message it is passed as a
+parameter. The type will be one of the types listed above, or -1 on
+
+
+
+Expires: 2 December 1999 [Page 43]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+error.
+
+ldap_msgid() returns the message ID associated with the LDAP message
+passed as a parameter.
+
+
+13. Handling Errors and Parsing Results
+
+The following calls are used to extract information from results and
+handle errors returned by other LDAP API routines. Note that
+ldap_parse_sasl_bind_result() and ldap_parse_extended_result() must typ-
+ically be used in addition to ldap_parse_result() to retrieve all the
+result information from SASL Bind and Extended Operations respectively.
+
+ int ldap_parse_result(
+ LDAP *ld,
+ LDAPMessage *res,
+ int *errcodep,
+ char **matcheddnp,
+ char **errmsgp,
+ char ***referralsp,
+ LDAPControl ***serverctrlsp,
+ int freeit
+ );
+
+ int ldap_parse_sasl_bind_result(
+ LDAP *ld,
+ LDAPMessage *res,
+ struct berval **servercredp,
+ int freeit
+ );
+
+ int ldap_parse_extended_result(
+ LDAP *ld,
+ LDAPMessage *res,
+ char **retoidp,
+ struct berval **retdatap,
+ int freeit
+ );
+
+ char *ldap_err2string( int err );
+
+ The use of the following routines is deprecated.
+
+ int ldap_result2error(
+ LDAP *ld,
+ LDAPMessage *res,
+ int freeit
+
+
+
+Expires: 2 December 1999 [Page 44]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ );
+
+ void ldap_perror( LDAP *ld, const char *msg );
+
+Parameters are:
+
+ld The session handle.
+
+res The result of an LDAP operation as returned by
+ ldap_result() or one of the synchronous API operation
+ calls.
+
+errcodep This result parameter will be filled in with the LDAP error
+ code field from the LDAPMessage message. This is the indi-
+ cation from the server of the outcome of the operation.
+ NULL may be passed to ignore this field.
+
+matcheddnp In the case of a return of LDAP_NO_SUCH_OBJECT, this result
+ parameter will be filled in with a DN indicating how much
+ of the name in the request was recognized. NULL may be
+ passed to ignore this field. The matched DN string should
+ be freed by calling ldap_memfree() which is described later
+ in this document.
+
+errmsgp This result parameter will be filled in with the contents
+ of the error message field from the LDAPMessage message.
+ The error message string should be freed by calling
+ ldap_memfree() which is described later in this document.
+ NULL may be passed to ignore this field.
+
+referralsp This result parameter will be filled in with the contents
+ of the referrals field from the LDAPMessage message, indi-
+ cating zero or more alternate LDAP servers where the
+ request should be retried. The referrals array should be
+ freed by calling ldap_value_free() which is described later
+ in this document. NULL may be passed to ignore this field.
+
+serverctrlsp This result parameter will be filled in with an allocated
+ array of controls copied out of the LDAPMessage message.
+ The control array should be freed by calling
+ ldap_controls_free() which was described earlier.
+
+freeit A boolean that determines whether the res parameter is
+ disposed of or not. Pass any non-zero value to have these
+ routines free res after extracting the requested informa-
+ tion. This is provided as a convenience; you can also use
+ ldap_msgfree() to free the result later. If freeit is
+ non-zero, the entire chain of messages represented by res
+
+
+
+Expires: 2 December 1999 [Page 45]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ is disposed of.
+
+servercredp For SASL bind results, this result parameter will be filled
+ in with the credentials passed back by the server for
+ mutual authentication, if given. An allocated berval struc-
+ ture is returned that should be disposed of by calling
+ ber_bvfree(). NULL may be passed to ignore this field.
+
+retoidp For extended results, this result parameter will be filled
+ in with the dotted-OID text representation of the name of
+ the extended operation response. This string should be
+ disposed of by calling ldap_memfree(). NULL may be passed
+ to ignore this field.
+
+retdatap For extended results, this result parameter will be filled
+ in with a pointer to a struct berval containing the data in
+ the extended operation response. It should be disposed of
+ by calling ber_bvfree(). NULL may be passed to ignore this
+ field.
+
+err For ldap_err2string(), an LDAP error code, as returned by
+ ldap_parse_result() or another LDAP API call.
+
+Additional parameters for the deprecated routines are not described.
+Interested readers are referred to RFC 1823.
+
+All three of the ldap_parse_*_result() routines skip over messages of
+type LDAP_RES_SEARCH_ENTRY and LDAP_RES_SEARCH_REFERENCE when looking
+for a result message to parse. They return the constant LDAP_SUCCESS if
+the result was successfully parsed and another LDAP error code if not.
+Note that the LDAP error code that indicates the outcome of the opera-
+tion performed by the server is placed in the errcodep
+ldap_parse_result() parameter. If a chain of messages that contains
+more than one result message is passed to these routines they always
+operate on the first result in the chain.
+
+ldap_err2string() is used to convert a numeric LDAP error code, as
+returned by one of the three ldap_parse_*_result() routines, or one of
+the synchronous API operation calls, into an informative zero-terminated
+character string message describing the error. It returns a pointer to
+static data.
+
+
+14. Stepping Through a List of Results
+
+The ldap_first_message() and ldap_next_message() routines are used to
+step through the list of messages in a result chain returned by
+ldap_result(). For search operations, the result chain may actually
+
+
+
+Expires: 2 December 1999 [Page 46]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+include referral messages, entry messages, and result messages.
+ldap_count_messages() is used to count the number of messages returned.
+The ldap_msgtype() function, described above, can be used to distinguish
+between the different message types.
+
+ LDAPMessage *ldap_first_message( LDAP *ld, LDAPMessage *res );
+
+ LDAPMessage *ldap_next_message( LDAP *ld, LDAPMessage *msg );
+
+ int ldap_count_messages( LDAP *ld, LDAPMessage *res );
+
+Parameters are:
+
+ld The session handle.
+
+res The result chain, as obtained by a call to one of the synchronous
+ search routines or ldap_result().
+
+msg The message returned by a previous call to ldap_first_message()
+ or ldap_next_message().
+
+ldap_first_message() and ldap_next_message() will return NULL when no
+more messages exist in the result set to be returned. NULL is also
+returned if an error occurs while stepping through the entries, in which
+case the error parameters in the session handle ld will be set to indi-
+cate the error.
+
+ldap_count_messages() returns the number of messages contained in a
+chain of results. It can also be used to count the number of messages
+that remain in a chain if called with a message, entry, or reference
+returned by ldap_first_message(), ldap_next_message(),
+ldap_first_entry(), ldap_next_entry(), ldap_first_reference(),
+ldap_next_reference().
+
+
+15. Parsing Search Results
+
+The following calls are used to parse the entries and references
+returned by ldap_search() and friends. These results are returned in an
+opaque structure that should only be accessed by calling the routines
+described below. Routines are provided to step through the entries and
+references returned, step through the attributes of an entry, retrieve
+the name of an entry, and retrieve the values associated with a given
+attribute in an entry.
+
+
+
+
+
+
+
+Expires: 2 December 1999 [Page 47]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+15.1. Stepping Through a List of Entries or References
+
+The ldap_first_entry() and ldap_next_entry() routines are used to step
+through and retrieve the list of entries from a search result chain.
+The ldap_first_reference() and ldap_next_reference() routines are used
+to step through and retrieve the list of continuation references from a
+search result chain. ldap_count_entries() is used to count the number
+of entries returned. ldap_count_references() is used to count the number
+of references returned.
+
+ LDAPMessage *ldap_first_entry( LDAP *ld, LDAPMessage *res );
+
+ LDAPMessage *ldap_next_entry( LDAP *ld, LDAPMessage *entry );
+
+ LDAPMessage *ldap_first_reference( LDAP *ld, LDAPMessage *res );
+
+ LDAPMessage *ldap_next_reference( LDAP *ld, LDAPMessage *ref );
+
+ int ldap_count_entries( LDAP *ld, LDAPMessage *res );
+
+ int ldap_count_references( LDAP *ld, LDAPMessage *res );
+
+Parameters are:
+
+ld The session handle.
+
+res The search result, as obtained by a call to one of the synchro-
+ nous search routines or ldap_result().
+
+entry The entry returned by a previous call to ldap_first_entry() or
+ ldap_next_entry().
+
+ref The reference returned by a previous call to
+ ldap_first_reference() or ldap_next_reference().
+
+ldap_first_entry(), ldap_next_entry(), ldap_first_reference() and
+ldap_next_reference() all return NULL when no more entries or references
+exist in the result set to be returned. NULL is also returned if an
+error occurs while stepping through the entries or references, in which
+case the error parameters in the session handle ld will be set to indi-
+cate the error.
+
+ldap_count_entries() returns the number of entries contained in a chain
+of entries. It can also be used to count the number of entries that
+remain in a chain if called with a message, entry or reference returned
+by ldap_first_message(), ldap_next_message(), ldap_first_entry(),
+ldap_next_entry(), ldap_first_reference(), ldap_next_reference().
+
+
+
+
+Expires: 2 December 1999 [Page 48]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ldap_count_references() returns the number of references contained in a
+chain of search results. It can also be used to count the number of
+references that remain in a chain.
+
+
+15.2. Stepping Through the Attributes of an Entry
+
+The ldap_first_attribute() and ldap_next_attribute() calls are used to
+step through the list of attribute types returned with an entry.
+
+ char *ldap_first_attribute(
+ LDAP *ld,
+ LDAPMessage *entry,
+ BerElement **ptr
+ );
+
+ char *ldap_next_attribute(
+ LDAP *ld,
+ LDAPMessage *entry,
+ BerElement *ptr
+ );
+
+ void ldap_memfree( char *mem );
+
+Parameters are:
+
+ld The session handle.
+
+entry The entry whose attributes are to be stepped through, as returned
+ by ldap_first_entry() or ldap_next_entry().
+
+ptr In ldap_first_attribute(), the address of a pointer used inter-
+ nally to keep track of the current position in the entry. In
+ ldap_next_attribute(), the pointer returned by a previous call to
+ ldap_first_attribute(). The BerElement type itself is an opaque
+ structure that is described in more detail later in this document
+ in the section "Encoded ASN.1 Value Manipulation".
+
+mem A pointer to memory allocated by the LDAP library, such as the
+ attribute type names returned by ldap_first_attribute() and
+ ldap_next_attribute, or the DN returned by ldap_get_dn(). If mem
+ is NULL, nothing is done.
+
+ldap_first_attribute() and ldap_next_attribute() will return NULL when
+the end of the attributes is reached, or if there is an error, in which
+case the error parameters in the session handle ld will be set to indi-
+cate the error.
+
+
+
+
+Expires: 2 December 1999 [Page 49]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+Both routines return a pointer to an allocated buffer containing the
+current attribute name. This should be freed when no longer in use by
+calling ldap_memfree().
+
+ldap_first_attribute() will allocate and return in ptr a pointer to a
+BerElement used to keep track of the current position. This pointer
+should be passed in subsequent calls to ldap_next_attribute() to step
+through the entry's attributes. After a set of calls to
+ldap_first_attribute() and ldap_next_attribute(), if ptr is non-NULL, it
+should be freed by calling ber_free( ptr, 0 ). Note that it is very
+important to pass the second parameter as 0 (zero) in this call, since
+the buffer associated with the BerElement does not point to separately
+allocated memory.
+
+The attribute type names returned are suitable for passing in a call to
+ldap_get_values() and friends to retrieve the associated values.
+
+
+15.3. Retrieving the Values of an Attribute
+
+ldap_get_values() and ldap_get_values_len() are used to retrieve the
+values of a given attribute from an entry. ldap_count_values() and
+ldap_count_values_len() are used to count the returned values.
+ldap_value_free() and ldap_value_free_len() are used to free the values.
+
+ char **ldap_get_values(
+ LDAP *ld,
+ LDAPMessage *entry,
+ const char *attr
+ );
+
+ struct berval **ldap_get_values_len(
+ LDAP *ld,
+ LDAPMessage *entry,
+ const char *attr
+ );
+
+ int ldap_count_values( char **vals );
+
+ int ldap_count_values_len( struct berval **vals );
+
+ void ldap_value_free( char **vals );
+
+ void ldap_value_free_len( struct berval **vals );
+
+Parameters are:
+
+ld The session handle.
+
+
+
+Expires: 2 December 1999 [Page 50]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+entry The entry from which to retrieve values, as returned by
+ ldap_first_entry() or ldap_next_entry().
+
+attr The attribute whose values are to be retrieved, as returned by
+ ldap_first_attribute() or ldap_next_attribute(), or a caller-
+ supplied string (e.g., "mail").
+
+vals The values returned by a previous call to ldap_get_values() or
+ ldap_get_values_len().
+
+Two forms of the various calls are provided. The first form is only
+suitable for use with non-binary character string data. The second _len
+form is used with any kind of data.
+
+ldap_get_values() and ldap_get_values_len() return NULL if no values are
+found for attr or if an error occurs.
+
+ldap_count_values() and ldap_count_values_len() return -1 if an error
+occurs such as the vals parameter being invalid.
+
+Note that the values returned are dynamically allocated and should be
+freed by calling either ldap_value_free() or ldap_value_free_len() when
+no longer in use.
+
+
+15.4. Retrieving the name of an entry
+
+ldap_get_dn() is used to retrieve the name of an entry.
+ldap_explode_dn() and ldap_explode_rdn() are used to break up a name
+into its component parts. ldap_dn2ufn() is used to convert the name into
+a more "user friendly" format.
+
+ char *ldap_get_dn( LDAP *ld, LDAPMessage *entry );
+
+ char **ldap_explode_dn( const char *dn, int notypes );
+
+ char **ldap_explode_rdn( const char *rdn, int notypes );
+
+ char *ldap_dn2ufn( const char *dn );
+
+Parameters are:
+
+ld The session handle.
+
+entry The entry whose name is to be retrieved, as returned by
+ ldap_first_entry() or ldap_next_entry().
+
+dn The dn to explode, such as returned by ldap_get_dn().
+
+
+
+Expires: 2 December 1999 [Page 51]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+rdn The rdn to explode, such as returned in the components of the
+ array returned by ldap_explode_dn().
+
+notypes A boolean parameter, if non-zero indicating that the dn or rdn
+ components should have their type information stripped off
+ (i.e., "cn=Babs" would become "Babs").
+
+ldap_get_dn() will return NULL if there is some error parsing the dn,
+setting error parameters in the session handle ld to indicate the error.
+It returns a pointer to newly allocated space that the caller should
+free by calling ldap_memfree() when it is no longer in use. Note the
+format of the DNs returned is given by [4].
+
+ldap_explode_dn() returns a NULL-terminated char * array containing the
+RDN components of the DN supplied, with or without types as indicated by
+the notypes parameter. The components are returned in the order they
+appear in the dn. The array returned should be freed when it is no
+longer in use by calling ldap_value_free().
+
+ldap_explode_rdn() returns a NULL-terminated char * array containing the
+components of the RDN supplied, with or without types as indicated by
+the notypes parameter. The components are returned in the order they
+appear in the rdn. The array returned should be freed when it is no
+longer in use by calling ldap_value_free().
+
+ldap_dn2ufn() converts the DN into the user friendly format described in
+[5]. The UFN returned is newly allocated space that should be freed by a
+call to ldap_memfree() when no longer in use.
+
+
+15.5. Retrieving controls from an entry
+
+ldap_get_entry_controls() is used to extract LDAP controls from an
+entry.
+
+
+ int ldap_get_entry_controls(
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAPControl ***serverctrlsp
+ );
+
+Parameters are:
+
+ld The session handle.
+
+entry The entry to extract controls from, as returned by
+ ldap_first_entry() or ldap_next_entry().
+
+
+
+Expires: 2 December 1999 [Page 52]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+serverctrlsp This result parameter will be filled in with an allocated
+ array of controls copied out of entry. The control array
+ should be freed by calling ldap_controls_free(). If ser-
+ verctrlsp is NULL, no controls are returned.
+
+ldap_get_entry_controls() returns an LDAP error code that indicates
+whether the reference could be successfully parsed (LDAP_SUCCESS if all
+goes well).
+
+
+
+15.6. Parsing References
+
+ldap_parse_reference() is used to extract referrals and controls from a
+SearchResultReference message.
+
+
+ int ldap_parse_reference(
+ LDAP *ld,
+ LDAPMessage *ref,
+ char ***referralsp,
+ LDAPControl ***serverctrlsp,
+ int freeit
+ );
+
+Parameters are:
+
+ld The session handle.
+
+ref The reference to parse, as returned by ldap_result(),
+ ldap_first_reference(), or ldap_next_reference().
+
+referralsp This result parameter will be filled in with an allocated
+ array of character strings. The elements of the array are
+ the referrals (typically LDAP URLs) contained in ref. The
+ array should be freed when no longer in used by calling
+ ldap_value_free(). If referralsp is NULL, the referral
+ URLs are not returned.
+
+serverctrlsp This result parameter will be filled in with an allocated
+ array of controls copied out of ref. The control array
+ should be freed by calling ldap_controls_free(). If ser-
+ verctrlsp is NULL, no controls are returned.
+
+freeit A boolean that determines whether the ref parameter is
+ disposed of or not. Pass any non-zero value to have this
+ routine free ref after extracting the requested informa-
+ tion. This is provided as a convenience; you can also use
+
+
+
+Expires: 2 December 1999 [Page 53]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ ldap_msgfree() to free the result later.
+
+ldap_parse_reference() returns an LDAP error code that indicates whether
+the reference could be successfully parsed (LDAP_SUCCESS if all goes
+well).
+
+
+16. Encoded ASN.1 Value Manipulation
+
+This section describes routines which may be used to encode and decode
+BER-encoded ASN.1 values, which are often used inside of control and
+extension values.
+
+With the exceptions of two new functions ber_flatten() and ber_init(),
+these functions are compatible with the University of Michigan LDAP 3.3
+implementation of BER.
+
+
+16.1. General
+
+ struct berval {
+ ber_len_t bv_len;
+ char *bv_val;
+ };
+
+As defined earlier in the section "Common Data Structures", a struct
+berval contains an arbitrary sequence of bytes and an indication of its
+length. The bv_len element is an unsigned integer. The bv_val is not
+necessarily zero-terminated. Applications may allocate their own berval
+structures.
+
+As defined earlier in the section "Common Data Structures", the BerEle-
+ment structure is an opaque structure:
+
+ typedef struct berelement BerElement;
+
+It contains not only a copy of the encoded value, but also state infor-
+mation used in encoding or decoding. Applications cannot allocate their
+own BerElement structures. The internal state is neither thread-
+specific nor locked, so two threads should not manipulate the same
+BerElement value simultaneously.
+
+A single BerElement value cannot be used for both encoding and decoding.
+
+ void ber_bvfree( struct berval *bv );
+
+ber_bvfree() frees a berval returned from this API. Both the bv->bv_val
+string and the berval itself are freed. Applications should not use
+
+
+
+Expires: 2 December 1999 [Page 54]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ber_bvfree() with bervals which the application has allocated.
+
+ void ber_bvecfree( struct berval **bv );
+
+ber_bvecfree() frees an array of bervals returned from this API. Each
+of the bervals in the array are freed using ber_bvfree(), then the array
+itself is freed.
+
+ struct berval *ber_bvdup( const struct berval *bv );
+
+ber_bvdup() returns a copy of a berval. The bv_val field in the
+returned berval points to a different area of memory than the bv_val
+field in the argument berval. The NULL pointer is returned on error
+(e.g. out of memory).
+
+ void ber_free( BerElement *ber, int fbuf );
+
+ber_free() frees a BerElement which is returned from the API calls
+ber_alloc_t() or ber_init(). Each BerElement must be freed by the
+caller. The second argument fbuf should always be set to 1 to ensure
+that the internal buffer used by the BER functions is freed as well as
+the BerElement container itself.
+
+
+16.2. Encoding
+
+ BerElement *ber_alloc_t( int options );
+
+ber_alloc_t() constructs and returns BerElement. The NULL pointer is
+returned on error. The options field contains a bitwise-or of options
+which are to be used when generating the encoding of this BerElement.
+One option is defined and must always be supplied:
+
+ #define LBER_USE_DER 0x01
+
+When this option is present, lengths will always be encoded in the
+minimum number of octets. Note that this option does not cause values
+of sets to be rearranged in tag and byte order or default values to be
+removed, so these functions are not sufficient for generating DER output
+as defined in X.509 and X.680. If the caller takes responsibility for
+ordering values of sets correctly and removing default values, DER out-
+put as defined in X.509 and X.680 can be produced.
+
+Unrecognized option bits are ignored.
+
+The BerElement returned by ber_alloc_t() is initially empty. Calls to
+ber_printf() will append bytes to the end of the ber_alloc_t().
+
+
+
+
+Expires: 2 December 1999 [Page 55]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ int ber_printf( BerElement *ber, const char *fmt, ... )
+
+The ber_printf() routine is used to encode a BER element in much the
+same way that sprintf() works. One important difference, though, is
+that state information is kept in the ber argument so that multiple
+calls can be made to ber_printf() to append to the end of the BER ele-
+ment. ber must be a pointer to a BerElement returned by ber_alloc_t().
+ber_printf() interprets and formats its arguments according to the for-
+mat string fmt. ber_printf() returns -1 if there is an error during
+encoding and a positive number if successful. As with sprintf(), each
+character in fmt refers to an argument to ber_printf().
+
+The format string can contain the following format characters:
+
+'t' Tag. The next argument is a ber_tag_t specifying the tag to
+ override the next element to be written to the ber. This works
+ across calls. The integer tag value must contain the tag class,
+ constructed bit, and tag value. For example, a tag of "[3]" for
+ a constructed type is 0xA3. All implementations must support
+ tags that fit in a single octet (i.e., where the tag value is
+ less than 32) and they may support larger tags.
+
+'b' Boolean. The next argument is an int, containing either 0 for
+ FALSE or 0xff for TRUE. A boolean element is output. If this
+ format character is not preceded by the 't' format modifier, the
+ tag 0x01 is used for the element.
+
+'i' Integer. The next argument is an int, containing the integer in
+ the host's byte order. An integer element is output. If this
+ format character is not preceded by the 't' format modifier, the
+ tag 0x02 is used for the element.
+
+'X' Bitstring. The next two arguments are a char * pointer to the
+ start of the bitstring, followed by an int containing the number
+ of bits in the bitstring. A bitstring element is output, in
+ primitive form. If this format character is not preceded by the
+ 't' format modifier, the tag 0x03 is used for the element.
+
+'n' Null. No argument is required. An ASN.1 NULL element is out-
+ put. If this format character is not preceded by the 't' format
+ modifier, the tag 0x05 is used for the element.
+
+'o' Octet string. The next two arguments are a char *, followed by
+ an int with the length of the string. The string may contain
+ null bytes and need not be zero-terminated. An octet string
+ element is output, in primitive form. If this format character
+ is not preceded by the 't' format modifier, the tag 0x04 is used
+ for the element.
+
+
+
+Expires: 2 December 1999 [Page 56]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+'s' Octet string. The next argument is a char * pointing to a
+ zero-terminated string. An octet string element in primitive
+ form is output, which does not include the trailing '\0' (null)
+ byte. If this format character is not preceded by the 't' format
+ modifier, the tag 0x04 is used for the element.
+
+'v' Several octet strings. The next argument is a char **, an array
+ of char * pointers to zero-terminated strings. The last element
+ in the array must be a NULL pointer. The octet strings do not
+ include the trailing '\0' (null) byte. Note that a construct
+ like '{v}' is required to get an actual SEQUENCE OF octet
+ strings. The 't' format modifier cannot be used with this for-
+ mat character.
+
+'V' Several octet strings. A NULL-terminated array of berval *'s is
+ supplied. Note that a construct like '{V}' is required to get an
+ actual SEQUENCE OF octet strings. The 't' format modifier cannot
+ be used with this format character.
+
+'{' Begin sequence. No argument is required. If this format char-
+ acter is not preceded by the 't' format modifier, the tag 0x30
+ is used.
+
+'}' End sequence. No argument is required. The 't' format modifier
+ cannot be used with this format character.
+
+'[' Begin set. No argument is required. If this format character
+ is not preceded by the 't' format modifier, the tag 0x31 is
+ used.
+
+']' End set. No argument is required. The 't' format modifier can-
+ not be used with this format character.
+
+Each use of a '{' format character must be matched by a '}' character,
+either later in the format string, or in the format string of a subse-
+quent call to ber_printf() for that BerElement. The same applies to the
+'[' and ']' format characters.
+
+Sequences and sets nest, and implementations of this API must maintain
+internal state to be able to properly calculate the lengths.
+
+ int ber_flatten( const BerElement *ber, struct berval **bvPtr );
+
+The ber_flatten routine allocates a struct berval whose contents are a
+BER encoding taken from the ber argument. The bvPtr pointer points to
+the returned berval, which must be freed using ber_bvfree(). This rou-
+tine returns 0 on success and -1 on error.
+
+
+
+
+Expires: 2 December 1999 [Page 57]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+The ber_flatten API call is not present in U-M LDAP 3.3.
+
+The use of ber_flatten on a BerElement in which all '{' and '}' format
+modifiers have not been properly matched is an error (i.e., -1 will be
+returned by ber_flatten() if this situation is exists).
+
+
+16.3. Encoding Example
+
+The following is an example of encoding the following ASN.1 data type:
+
+ Example1Request ::= SEQUENCE {
+ s OCTET STRING, -- must be printable
+ val1 INTEGER,
+ val2 [0] INTEGER DEFAULT 0
+ }
+
+
+ int encode_example1(const char *s,int val1,int val2,struct berval **bvPtr)
+ {
+ BerElement *ber;
+ int rc = -1;
+
+ ber = ber_alloc_t(LBER_USE_DER);
+
+ if (ber == NULL) return -1;
+
+ if (ber_printf(ber,"{si",s,val1) == -1) {
+ goto done;
+ }
+
+ if (val2 != 0) {
+ if (ber_printf(ber,"ti",0x80,val2) == -1) {
+ goto done;
+ }
+ }
+
+ if (ber_printf(ber,"}") == -1) {
+ goto done;
+ }
+
+ rc = ber_flatten(ber,bvPtr);
+
+ done:
+ ber_free(ber,1);
+ return rc;
+ }
+
+
+
+
+Expires: 2 December 1999 [Page 58]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+16.4. Decoding
+
+The following two symbols are available to applications.
+
+ #define LBER_ERROR (ber_tag_t)0xffffffff
+ #define LBER_DEFAULT (ber_tag_t)0xffffffff
+
+ BerElement *ber_init( const struct berval *bv );
+
+The ber_init function constructs a BerElement and returns a new BerEle-
+ment containing a copy of the data in the bv argument. ber_init returns
+the NULL pointer on error.
+
+ ber_tag_t ber_scanf( BerElement *ber, const char *fmt, ... );
+
+The ber_scanf() routine is used to decode a BER element in much the same
+way that sscanf() works. One important difference, though, is that some
+state information is kept with the ber argument so that multiple calls
+can be made to ber_scanf() to sequentially read from the BER element.
+The ber argument must be a pointer to a BerElement returned by
+ber_init(). ber_scanf interprets the bytes according to the format
+string fmt, and stores the results in its additional arguments.
+ber_scanf() returns LBER_ERROR on error, and a different value on suc-
+cess.
+
+The format string contains conversion specifications which are used to
+direct the interpretation of the BER element. The format string can
+contain the following characters:
+
+'a' Octet string. A char ** argument should be supplied. Memory is
+ allocated, filled with the contents of the octet string, zero-
+ terminated, and the pointer to the string is stored in the argu-
+ ment. The returned value must be freed using ldap_memfree. The
+ tag of the element must indicate the primitive form (constructed
+ strings are not supported) but is otherwise ignored and dis-
+ carded during the decoding. This format cannot be used with
+ octet strings which could contain null bytes.
+
+'O' Octet string. A struct berval ** argument should be supplied,
+ which upon return points to an allocated struct berval contain-
+ ing the octet string and its length. ber_bvfree() must be
+ called to free the allocated memory. The tag of the element
+ must indicate the primitive form (constructed strings are not
+ supported) but is otherwise ignored during the decoding.
+
+'b' Boolean. A pointer to an int should be supplied. The int value
+ stored will be 0 for FALSE or nonzero for TRUE. The tag of the
+ element must indicate the primitive form but is otherwise
+
+
+
+Expires: 2 December 1999 [Page 59]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ ignored during the decoding.
+
+'i' Integer. A pointer to an int should be supplied. The int value
+ stored will be in host byte order. The tag of the element must
+ indicate the primitive form but is otherwise ignored during the
+ decoding. ber_scanf() will return an error if the integer can-
+ not be stored in an int.
+
+'B' Bitstring. A char ** argument should be supplied which will
+ point to the allocated bits, followed by a ber_len_t * argument,
+ which will point to the length (in bits) of the bitstring
+ returned. ldap_memfree must be called to free the bitstring.
+ The tag of the element must indicate the primitive form (con-
+ structed bitstrings are not supported) but is otherwise ignored
+ during the decoding.
+
+'n' Null. No argument is required. The element is verified to have
+ a zero-length value and is skipped. The tag is ignored.
+
+'v' Several octet strings. A char *** argument should be supplied,
+ which upon return points to an allocated NULL-terminated array
+ of char *'s containing the octet strings. NULL is stored if the
+ sequence is empty. ldap_memfree must be called to free each
+ element of the array and the array itself. The tag of the
+ sequence and of the octet strings are ignored.
+
+'V' Several octet strings (which could contain null bytes). A
+ struct berval *** should be supplied, which upon return points
+ to a allocated NULL-terminated array of struct berval *'s con-
+ taining the octet strings and their lengths. NULL is stored if
+ the sequence is empty. ber_bvecfree() can be called to free the
+ allocated memory. The tag of the sequence and of the octet
+ strings are ignored.
+
+'x' Skip element. The next element is skipped. No argument is
+ required.
+
+'{' Begin sequence. No argument is required. The initial sequence
+ tag and length are skipped.
+
+'}' End sequence. No argument is required.
+
+'[' Begin set. No argument is required. The initial set tag and
+ length are skipped.
+
+']' End set. No argument is required.
+
+ ber_tag_t ber_peek_tag( const BerElement *ber,
+
+
+
+Expires: 2 December 1999 [Page 60]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ ber_len_t *lenPtr );
+
+ber_peek_tag() returns the tag of the next element to be parsed in the
+BerElement argument. The length of this element is stored in the
+*lenPtr argument. LBER_DEFAULT is returned if there is no further data
+to be read. The ber argument is not modified.
+
+ ber_tag_t ber_skip_tag( BerElement *ber, ber_len_t *lenPtr );
+
+ber_skip_tag() is similar to ber_peek_tag(), except that the state
+pointer in the BerElement argument is advanced past the first tag and
+length, and is pointed to the value part of the next element. This rou-
+tine should only be used with constructed types and situations when a
+BER encoding is used as the value of an OCTET STRING. The length of the
+value is stored in *lenPtr.
+
+ ber_tag_t ber_first_element( BerElement *ber,
+ ber_len_t *lenPtr, char **opaquePtr );
+
+ ber_tag_t ber_next_element( BerElement *ber,
+ ber_len_t *lenPtr, char *opaque );
+
+ber_first_element() and ber_next_element() are used to traverse a SET,
+SET OF, SEQUENCE or SEQUENCE OF data value. ber_first_element() calls
+ber_skip_tag(), stores internal information in *lenPtr and *opaquePtr,
+and calls ber_peek_tag() for the first element inside the constructed
+value. LBER_DEFAULT is returned if the constructed value is empty.
+ber_next_element() positions the state at the start of the next element
+in the constructed type. LBER_DEFAULT is returned if there are no
+further values.
+
+The len and opaque values should not be used by applications other than
+as arguments to ber_next_element(), as shown in the example below.
+
+
+16.5. Decoding Example
+
+The following is an example of decoding an ASN.1 data type:
+
+ Example2Request ::= SEQUENCE {
+ dn OCTET STRING, -- must be printable
+ scope ENUMERATED { b (0), s (1), w (2) },
+ ali ENUMERATED { n (0), s (1), f (2), a (3) },
+ size INTEGER,
+ time INTEGER,
+ tonly BOOLEAN,
+ attrs SEQUENCE OF OCTET STRING, -- must be printable
+ [0] SEQUENCE OF SEQUENCE {
+
+
+
+Expires: 2 December 1999 [Page 61]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ type OCTET STRING -- must be printable,
+ crit BOOLEAN DEFAULT FALSE,
+ value OCTET STRING
+ } OPTIONAL }
+
+ #define TAG_CONTROL_LIST 0xA0L /* context specific cons 0 */
+
+ int decode_example2(struct berval *bv)
+ {
+ BerElement *ber;
+ ber_len_t len;
+ ber_tag_t res;
+ int scope, ali, size, time, tonly;
+ char *dn = NULL, **attrs = NULL;
+ int i,rc = 0;
+
+ ber = ber_init(bv);
+ if (ber == NULL) {
+ fputs("ERROR ber_init failed\n", stderr);
+ return -1;
+ }
+
+ res = ber_scanf(ber,"{aiiiib{v}",&dn,&scope,&ali,
+ &size,&time,&tonly,&attrs);
+
+ if (res == LBER_ERROR) {
+ fputs("ERROR ber_scanf failed\n", stderr);
+ ber_free(ber,1);
+ return -1;
+ }
+
+ /* *** use dn */
+ ldap_memfree(dn);
+
+ for (i = 0; attrs != NULL && attrs[i] != NULL; i++) {
+ /* *** use attrs[i] */
+ ldap_memfree(attrs[i]);
+ }
+ ldap_memfree(attrs);
+
+ if (ber_peek_tag(ber,&len) == TAG_CONTROL_LIST) {
+ char *opaque;
+ ber_tag_t tag;
+
+ for (tag = ber_first_element(ber,&len,&opaque);
+ tag != LBER_DEFAULT;
+ tag = ber_next_element (ber,&len,opaque)) {
+
+
+
+
+Expires: 2 December 1999 [Page 62]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ ber_len_t tlen;
+ ber_tag_t ttag;
+ char *type;
+ int crit;
+ struct berval *value;
+
+ if (ber_scanf(ber,"{a",&type) == LBER_ERROR) {
+ fputs("ERROR cannot parse type\n", stderr);
+ break;
+ }
+ /* *** use type */
+ ldap_memfree(type);
+
+ ttag = ber_peek_tag(ber,&tlen);
+ if (ttag == 0x01) { /* boolean */
+ if (ber_scanf(ber,"b",
+ &crit) == LBER_ERROR) {
+ fputs("ERROR cannot parse crit\n",
+ stderr);
+ rc = -1;
+ break;
+ }
+ } else if (ttag == 0x04) { /* octet string */
+ crit = 0;
+ } else {
+ fputs("ERROR extra field in controls\n",
+ stderr );
+ break;
+ }
+
+ if (ber_scanf(ber,"O}",&value) == LBER_ERROR) {
+ fputs("ERROR cannot parse value\n", stderr);
+ rc = -1;
+ break;
+ }
+ /* *** use value */
+ ber_bvfree(value);
+ }
+ }
+
+ ber_scanf(ber,"}");
+
+ ber_free(ber,1);
+
+ return rc;
+ }
+
+
+
+
+
+Expires: 2 December 1999 [Page 63]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+17. Security Considerations
+
+LDAPv2 supports security through protocol-level authentication using
+clear-text passwords. LDAPv3 adds support for SASL [8] (Simple Authen-
+tication Security Layer) methods. LDAPv3 also supports operation over a
+secure transport layer using Transport Layer Security TLS [9]. Readers
+are referred to the protocol documents for discussion of related secu-
+rity considerations.
+
+Implementations of this API should be cautious when handling authentica-
+tion credentials. In particular, keeping long-lived copies of creden-
+tials without the application's knowledge is discouraged.
+
+
+18. Acknowledgements
+
+Many members of the IETF ASID and LDAPEXT working groups as well as
+members of the Internet at large have provided useful comments and
+suggestions that have been incorporated into this document. Chris
+Weider deserves special mention for his contributions as co-author of
+earlier revisions of this document.
+
+The original material upon which this specification is based was sup-
+ported by the National Science Foundation under Grant No. NCR-9416667.
+
+
+19. Copyright
+
+Copyright (C) The Internet Society (1997-1999). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to oth-
+ers, and derivative works that comment on or otherwise explain it or
+assist in its implementation may be prepared, copied, published and dis-
+tributed, in whole or in part, without restriction of any kind, provided
+that the above copyright notice and this paragraph are included on all
+such copies and derivative works. However, this document itself may not
+be modified in any way, such as by removing the copyright notice or
+references to the Internet Society or other Internet organizations,
+except as needed for the purpose of developing Internet standards in
+which case the procedures for copyrights defined in the Internet Stan-
+dards process must be followed, or as required to translate it into
+languages other than English.
+
+The limited permissions granted above are perpetual and will not be
+revoked by the Internet Society or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS
+IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK
+
+
+
+Expires: 2 December 1999 [Page 64]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
+INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FIT-
+NESS FOR A PARTICULAR PURPOSE.
+
+
+20. Bibliography
+
+[1] The Directory: Selected Attribute Syntaxes. CCITT, Recommendation
+ X.520.
+
+[2] M. Wahl, A. Coulbeck, T. Howes, S. Kille, W. Yeong, C. Robbins,
+ "Lightweight Directory Access Protocol (v3): Attribute Syntax
+ Definitions", RFC 2252, December 1997.
+
+[3] T. Howes, "The String Representation of LDAP Search Filters," RFC
+ 2254, December 1997.
+
+[4] M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access Protocol
+ (v3): A UTF-8 String Representation of Distinguished Names", RFC
+ 2253, December 1997.
+
+[5] S. Kille, "Using the OSI Directory to Achieve User Friendly Nam-
+ ing," RFC 1781, March 1995.
+
+[6] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol
+ (v3)", RFC 2251, December 1997.
+
+[7] A. Herron, T. Howes, M. Wahl, C. Weider, A. Anantha, "LDAP Control
+ Extension for Server Side Sorting of Search Results", INTERNET-
+ DRAFT <draft-ietf-ldapext-sorting-01.txt>, 7 August 1998.
+
+[8] J. Meyers, "Simple Authentication and Security Layer (SASL)", RFC
+ 2222, October 1997.
+
+[9] "Lightweight Directory Access Protocol (v3): Extension for Tran-
+ sport Layer Security", INTERNET-DRAFT <draft-ietf-ldapext-ldapv3-
+ tls-04.txt>, November 1998.
+
+[10] "UTF-8, a transformation format of Unicode and ISO 10646", RFC
+ 2044, October 1996.
+
+[11] "IP Version 6 Addressing Architecture,", RFC 1884, December 1995.
+
+[12] "Character Mnemonics and Character Sets," RFC 1345, June 1992.
+
+[13] "Programming Languages - C", ANSI/ISO Standard 9899, revised 1997.
+
+
+
+
+Expires: 2 December 1999 [Page 65]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+21. Authors' Addresses
+
+ Mark Smith (document editor)
+ Netscape Communications Corp.
+ 501 E. Middlefield Rd., Mailstop MV068
+ Mountain View, CA 94043
+ USA
+ +1 650 937-3477
+ mcs@netscape.com
+
+ Tim Howes
+ Netscape Communications Corp.
+ 501 E. Middlefield Rd., Mailstop MV068
+ Mountain View, CA 94043
+ USA
+ +1 650 937-3419
+ howes@netscape.com
+
+ Andy Herron
+ Microsoft Corp.
+ 1 Microsoft Way
+ Redmond, WA 98052
+ USA
+ +1 425 882-8080
+ andyhe@microsoft.com
+
+ Mark Wahl
+ Innosoft International, Inc.
+ 8911 Capital of Texas Hwy, Suite 4140
+ Austin, TX 78759
+ USA
+ +1 626 919 3600
+ Mark.Wahl@innosoft.com
+
+ Anoop Anantha
+ Microsoft Corp.
+ 1 Microsoft Way
+ Redmond, WA 98052
+ USA
+ +1 425 882-8080
+ anoopa@microsoft.com
+
+
+22. Appendix A - Sample C LDAP API Code
+
+ #include <stdio.h>
+ #include <ldap.h>
+
+
+
+
+Expires: 2 December 1999 [Page 66]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ main()
+ {
+ LDAP *ld;
+ LDAPMessage *res, *e;
+ int i, rc;
+ char *a, *dn;
+ BerElement *ptr;
+ char **vals;
+
+ /* open an LDAP session */
+ if ( (ld = ldap_init( "dotted.host.name", LDAP_PORT )) == NULL )
+ return 1;
+
+ /* authenticate as nobody */
+ if (( rc = ldap_simple_bind_s( ld, NULL, NULL )) != LDAP_SUCCESS ) {
+ fprintf( stderr, "ldap_simple_bind_s: %s\n",
+ ldap_err2string( rc ));
+ ldap_unbind( ld );
+ return 1;
+ }
+
+ /* search for entries with cn of "Babs Jensen", return all attrs */
+ if (( rc = ldap_search_s( ld, "o=University of Michigan, c=US",
+ LDAP_SCOPE_SUBTREE, "(cn=Babs Jensen)", NULL, 0, &res ))
+ != LDAP_SUCCESS ) {
+ fprintf( stderr, "ldap_search_s: %s\n",
+ ldap_err2string( rc ));
+ if ( res == NULL ) {
+ ldap_unbind( ld );
+ return 1;
+ }
+ }
+
+ /* step through each entry returned */
+ for ( e = ldap_first_entry( ld, res ); e != NULL;
+ e = ldap_next_entry( ld, e ) ) {
+ /* print its name */
+ dn = ldap_get_dn( ld, e );
+ printf( "dn: %s\n", dn );
+ ldap_memfree( dn );
+
+ /* print each attribute */
+ for ( a = ldap_first_attribute( ld, e, &ptr ); a != NULL;
+ a = ldap_next_attribute( ld, e, ptr ) ) {
+ printf( "\tattribute: %s\n", a );
+
+ /* print each value */
+ vals = ldap_get_values( ld, e, a );
+
+
+
+Expires: 2 December 1999 [Page 67]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ for ( i = 0; vals[i] != NULL; i++ ) {
+ printf( "\t\tvalue: %s\n", vals[i] );
+ }
+ ldap_value_free( vals );
+ ldap_memfree( a );
+ }
+ if ( ptr != NULL ) {
+ ber_free( ptr, 0 );
+ }
+ }
+ /* free the search results */
+ ldap_msgfree( res );
+
+ /* close and free connection resources */
+ ldap_unbind( ld );
+
+ return 0;
+ }
+
+
+23. Appendix B - Namespace Consumed By This Specification
+
+The following 2 prefixes are used in this specification to name func-
+tions:
+ ldap_
+ ber_
+
+The following 6 prefixes are used in this specification to name struc-
+tures, unions, and typedefs:
+ ldap
+ LDAP
+ PLDAP
+ ber
+ Ber
+ timeval
+
+The following 3 prefixes are used in this specification to name #defined
+macros:
+ LDAP
+ LBER_
+ mod_
+
+
+24. Appendix C - Summary of Requirements for API Extensions
+
+As the LDAP protocol is extended, this C LDAP API will need to be
+extended as well. For example, an LDAPv3 control extension has already
+been defined for server-side sorting of search results [7]. This
+
+
+
+Expires: 2 December 1999 [Page 68]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+appendix summarizes the requirements for extending this API.
+
+24.1. Compatibility
+
+Extensions to this document should not, by default, alter the behavior
+of any of the APIs specified in this document. If an extension option-
+ally changes the behavior of any existing C LDAP API function calls, the
+behavior change must be well documented.
+
+24.2. Style
+
+Extensions to this API should follow the general style and naming con-
+ventions used in this document. For example, function names should
+start with "ldap_" or "ber_" and consist entirely of lowercase letters,
+digits, and underscore ('_') characters. More information can be found
+in the preceding appendix called "Namespace Consumed By This Specifica-
+tion."
+
+24.3. Dependence on Externally Defined Types
+
+Extensions to this API should minimize dependencies on types and macros
+that are defined in system header files and generally use only intrinsic
+types that are part of the C language, types defined in this specifica-
+tion, or types defined in the extension document itself.
+
+24.4. Compile Time Information
+
+Extensions to this API should conform to the requirements contained in
+the "Retrieving Information at Compile Time" section of this document.
+That is, extensions should define a macro of the form:
+
+ #define LDAP_API_FEATURE_x level
+
+so that applications can detect the presence or absence of the extension
+at compile time and also test the version or level of the extension pro-
+vided by an API implementation.
+
+24.5. Runtime Information
+
+Extensions to this API should conform to the requirements contained in
+the "Retrieving Information During Execution" section of this document.
+That is, each extension should be given a character string name and that
+name should appear in the ldapai_extensions array field of the LDAPAPI-
+Info structure following a successful call to ldap_get_option() with an
+option parameter value of LDAP_OPT_API_INFO. In addition, information
+about the extension should be available via a call to ldap_get_option()
+with an option parameter value of LDAP_OPT_API_FEATURE_INFO.
+
+
+
+
+Expires: 2 December 1999 [Page 69]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+24.6. Values Used for Session Handle Options
+
+Extensions to this API that add new session options (for use with the
+ldap_get_option() and ldap_set_option() functions) should meet the
+requirements contained in the last paragraph of the "LDAP Session Handle
+Options" section of this document. Specifically, standards track docu-
+ments MUST use values for option macros that are between 0x1000 and
+0x3FFF inclusive and private and experimental extensions MUST use values
+for the option macros that are between 0x4000 and 0x7FFF inclusive.
+
+
+25. Appendix D - Known Incompatibilities with RFC 1823
+
+This appendix lists known incompatibilities between this API specifica-
+tion and the one contained in RFC 1823, beyond the additional API func-
+tions added in support of LDAPv3.
+
+
+25.1. Opaque LDAP Structure
+
+In RFC 1823, some fields in the LDAP structure were exposed to applica-
+tion programmers. To provide a cleaner interface and to make it easier
+for implementations to evolve over time without sacrificing binary com-
+patibility with older applications, the LDAP structure is now entirely
+opaque. The new ldap_set_option() and ldap_get_option() calls can be
+used to manipulate per-session and global options.
+
+
+25.2. Additional Error Codes
+
+The following new error code macros were introduced to support LDAPv3:
+ LDAP_REFERRAL
+ LDAP_ADMINLIMIT_EXCEEDED
+ LDAP_UNAVAILABLE_CRITICAL_EXTENSION
+ LDAP_CONFIDENTIALITY_REQUIRED
+ LDAP_SASL_BIND_IN_PROGRESS
+ LDAP_AFFECTS_MULTIPLE_DSAS
+ LDAP_CONNECT_ERROR
+ LDAP_NOT_SUPPORTED
+ LDAP_CONTROL_NOT_FOUND
+ LDAP_NO_RESULTS_RETURNED
+ LDAP_MORE_RESULTS_TO_RETURN
+ LDAP_CLIENT_LOOP
+ LDAP_REFERRAL_LIMIT_EXCEEDED
+
+
+
+
+
+
+
+Expires: 2 December 1999 [Page 70]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+25.3. Freeing of String Data with ldap_memfree()
+
+All strings received from the API (e.g., those returned by the
+ldap_get_dn() or ldap_dn2ufn() functions) should be freed by calling
+ldap_memfree() not free(). RFC 1823 did not define an ldap_memfree()
+function.
+
+
+25.4. Changes to ldap_result()
+
+The meaning of the all parameter to ldap_result has changed slightly.
+Nonzero values from RFC 1823 correspond to LDAP_MSG_ALL (0x01). There
+is also a new possible value, LDAP_MSG_RECEIVED (0x02).
+
+The result type LDAP_RES_MODDN is now returned where RFC 1823 returned
+LDAP_RES_MODRDN. The actual value for these two macros is the same
+(0x6D).
+
+
+25.5. Changes to ldap_first_attribute() and ldap_next_attribute
+
+Each non-NULL return value should be freed by calling ldap_memfree()
+after use. In RFC 1823, these two functions returned a pointer to a
+per-session buffer, which was not very thread-friendly.
+
+After the last call to ldap_first_attribute() or ldap_next_attribute(),
+the value set in the ptr parameter should be freed by calling ber_free(
+ptr, 0 ). RFC 1823 did not mention that the ptr value should be freed.
+
+The type of the ptr parameter was changed from void * to BerElement *.
+
+
+25.6. Changes to ldap_modrdn() and ldap_modrdn_s() Functions
+
+In RFC 1823, the ldap_modrdn() and ldap_modrdn_s() functions include a
+parameter called deleteoldrdn. This does not match the great majority
+of implementations, so in this specification the deleteoldrdn parameter
+was removed from ldap_modrdn() and ldap_modrdn_s(). Two additional
+functions that support deleteoldrdn and are widely implemented as well
+were added to this specification: ldap_modrdn2() and ldap_modrdn2_s().
+
+
+25.7. Changes to the berval structure
+
+In RFC 1823, the bv_len element of the berval structure was defined as
+an unsigned long. In this specification, the type is implementation-
+specific, although it must be an unsigned integral type that is at least
+32 bits in size. See the appendix "Data Types and Legacy
+
+
+
+Expires: 2 December 1999 [Page 71]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+Implementations" for additional considerations.
+
+
+25.8. API Specification Clarified
+
+RFC 1823 left many things unspecified, including behavior of various
+memory disposal functions when a NULL pointer is presented, requirements
+for header files, values of many macros, and so on. This specification
+is more complete and generally tighter than the one in RFC 1823.
+
+
+25.9. Deprecated Functions
+
+A number of functions that are in RFC 1823 are labeled as "deprecated"
+in this specification. In most cases, a replacement that provides
+equivalent functionality has been defined. The deprecated functions
+are:
+
+ ldap_bind()
+ Use ldap_simple_bind() or ldap_sasl_bind() instead.
+
+ ldap_bind_s()
+ Use ldap_simple_bind_s() or ldap_sasl_bind_s() instead.
+
+ ldap_kerberos_bind() and ldap_kerberos_bind_s()
+ No equivalent functions are provided.
+
+ ldap_modrdn() and ldap_modrdn2()
+ Use ldap_rename() instead.
+
+ ldap_modrdn_s() and ldap_modrdn2_s()
+ Use ldap_rename_s() instead.
+
+ ldap_open()
+ Use ldap_init() instead.
+
+ ldap_perror()
+ Use ldap_err2string() instead.
+
+ ldap_result2error()
+ Use ldap_parse_result() instead.
+
+
+26. Appendix E - Data Types and Legacy Implementations
+
+The data types associated with the length of a ber value (ber_len_t) and
+the tag (ber_tag_t) have been defined in this specification as unsigned
+integral types of implementation-specific size. This was done so that
+
+
+
+Expires: 2 December 1999 [Page 72]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+source and binary compatibility of the C LDAP API can be maintained
+across ILP32 environments (where int, long, and pointers are all 32 bits
+in size) and LP64 environments (where ints remain 32 bits but longs and
+pointers grow to 64 bits).
+
+In older implementations of the C LDAP API, such as those based on RFC
+1823, implementors may have chosen to use an unsigned long for these
+types. If a long data type was used, a port of an application to a 64-
+bit operating system using the LP64 data model would find the size of
+the BER length and tag types used by the C LDAP API to increase. Also,
+if the legacy implementation had chosen to implement the types as an
+unsigned int, adoption of a specification that mandated use of unsigned
+longs would cause a source incompatibility in an LP64 application. By
+using an implementation-specific data type, the C LDAP API implementa-
+tion is free to choose the correct data type and the ability to maintain
+source compatibility.
+
+For example, suppose a legacy implementation chose to define the return
+value of ber_skip_tag() as an unsigned long but wishes to have the
+library return a 32-bit quantity in both ILP32 and LP64 data models.
+The following typedefs for ber_tag_t will provide a fixed sized data
+structure while preserving existing ILP32 source -- all without generat-
+ing compiler warnings:
+ #if defined(_LP64)
+ typedef unsigned int ber_tag_t;
+ #else
+ typedef unsigned long ber_tag_t;
+ #endif
+The above assumes that the the preprocessor symbol _LP64 is defined if
+and only if the code is being compiled in an LP64 environment. Similar
+code can be used to define an appropriate ber_len_t type.
+
+
+27. Appendix F - Changes Made Since Last Document Revision
+
+The previous version of this document was draft-ietf-ldapext-ldap-c-
+api-02.txt, dated 23 February, 1999. This appendix lists all of the
+changes made to that document to produce this one.
+
+27.1. API Changes
+
+ Types: added the ber_len_t and ber_tag_t implementation-specific
+ unsigned integral data types to support source and binary compatibil-
+ ity between ILP32 and LP64 environments. Changes were made to the
+ "Common Data Structures" and "Encoded ASN.1 Value Manipulation" sec-
+ tions of this document.
+
+
+
+
+
+Expires: 2 December 1999 [Page 73]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+27.2. Editorial Changes
+
+ General: Added Appendix E - Data Types and Legacy Implementations;
+ moved list of recent document changes to Appendices F and G.
+
+ "Retrieving Information During Execution" section: removed misplaced
+ ldapai_vendor_name and ldapai_vendor_version from the LDAPAPI-
+ FeatureInfo structure description.
+
+ "Extended Operations" section: changed the names of the "requestoid"
+ and "requestdata" parameters in the function prototypes to match the
+ parameter descriptions. The old names were "exoid" and "exdata."
+
+ Appendix D - "Appendix D - Known Incompatibilities with RFC 1823 ":
+ Added note about changes to the berval structure.
+
+
+28. Appendix G - Changes Made Since draft-ietf-ldapext-ldap-c-api-
+01.txt
+
+The version of this document that preceded draft-ietf-ldapext-ldap-c-
+api-02.txt was draft-ietf-ldapext-ldap-c-api-01.txt, dated 7 August
+1998. This appendix lists all of the changes made to that document to
+produce draft-ietf-ldapext-ldap-c-api-02.txt.
+
+
+28.1. API Changes
+
+ General: added the 'const' keyword to function prototypes where
+ appropriate.
+
+ Added two new sections that specify additional features and require-
+ ments for API implementors:
+ "Header File Requirements"
+ "A Client Control That Governs Referral Processing"
+
+
+ LDAP_VERSION_MAX, LDAP_VENDOR_NAME, and LDAP_VENDOR_VERSION macros.
+ Corrected LDAP_API_VERSION example code to use >= instead of >.
+ Added note about what value to use for LDAP_API_VERSION prior to pub-
+ lication of this draft as an RFC (2000 + draft revision number).
+
+ "Retrieving Information During Execution" section: added
+ LDAP_API_INFO_VERSION macro and clarified the text to explain the
+ behavior when there is a mismatch between LDAPAPIInfo structure ver-
+ sions. Added LDAP_OPT_API_FEATURE_INFO to allow applications to
+ retrieve version information about API extended features.
+
+
+
+
+Expires: 2 December 1999 [Page 74]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ "LDAP Session Handle Options" section: Added macro definitions for
+ LDAP_OPT_ON and LDAP_OPT_OFF and changed the "invalue" type for
+ Boolean options from "int" to "void *". For consistency, we now
+ require that applications dispose of "char *" and "LDAPControl *"
+ values that are returned. Added note about which option value ranges
+ are to be used for various purposes.
+
+ "Closing the session" section: added new function ldap_unbind_ext()
+ to allow controls to be used with unbind operations.
+
+ "Searching" section: added requirement that *res be set to NULL by
+ synchronous calls that fail to return any results.
+
+ "Modifying the Name of an Entry" section: added function prototypes
+ for ldap_modrdn2() and ldap_modrdn2_s() and corrected the ones for
+ ldap_modrdn() and ldap_modrdn_s() to match the most widely imple-
+ mented APIs.
+
+ "Obtaining Results and Peeking Inside LDAP Messages" section: added
+ requirement that "*res" be set to NULL when ldap_result() fails to
+ return any results. Added requirement that ldap_msgfree() accept a
+ NULL "res" parameter.
+
+ "Stepping Through the Attributes of an Entry" section: added
+ requirement that ldap_memfree() accept a NULL "mem" parameter.
+
+ "Encoded ASN.1 Value Manipulation - Encoding" section: added note
+ that implementations may support tags with a value larger than 32
+ (but this is not required).
+
+ "Encoded ASN.1 Value Manipulation - Decoding" section: changed the
+ LBER_ERROR and LBER_DEFAULT macros to end in "UL" instead of "L"
+ since all the functions that return these two values return an
+ "unsigned long" value.
+
+
+28.2. Editorial changes
+
+
+ Removed section: "Appendix - Outstanding Issues."
+
+ Added two new editorial sections:
+ "Appendix - Summary of Requirements for API Extensions"
+ "Appendix - Known Incompatibilities with RFC 1823".
+
+ General: replaced all occurrences of "LDAP C API" with "C LDAP API"
+ for consistency.
+
+
+
+
+Expires: 2 December 1999 [Page 75]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ "Status of Memo" section: added a statement that this document is in
+ full conformance with all provisions of Section 10 of RFC2026. Also
+ revised the text about the Internet Draft current and shadow direc-
+ tories to match the latest I-D guidelines.
+
+ Document authors: removed Chris Weider from the list of authors (at
+ his own request) and added an explicit mention of him in the "Ack-
+ nowledgements" section. Updated Mark Wahl's company affiliation in
+ document preface. Added "(document editor)" after Mark Smith's name
+ in the "Authors' Addresses" section.
+
+ Copyright: updated the year to 1999.
+
+ "Introduction" section: expanded the sentence that mentioned the sam-
+ ple code appendix to mention all of the appendices.
+
+ "Overview of LDAP API Use" section: numbered the four simple steps
+ for using the API. Added mention of the referrals client control.
+ Clarified the text on character sets. Replaced mention of
+ ldap_bind() with ldap_sasl_bind() because the former is deprecated.
+ Added note that this API is designed for use in environments where
+ the 'int' type is at least 32 bits in size.
+
+ "Common Data Structures" section: added definition of BerElement so
+ it is defined before it is used. Added reference back to "Header
+ File Requirements" for "struct timeval" related considerations.
+
+ "Initializing an LDAP Session" section: moved note about ldap_open()
+ attempting to make a server connection closer to the ldap_open()
+ function prototype. Added note that using literal IPv6 addresses in
+ the "hostname" parameter is not yet supported.
+
+ "LDAP Session Handle Options" section: replaced one instance of
+ "Formerly" with "In RFC 1823." Added note about inheritance of
+ options when automatic referral following is enabled. Added
+ LDAP_OPT_API_INFO and LDAP_OPT_API_FEATURE_INFO for completeness (not
+ previously included in this section). Replaced erroneous references
+ to the "Using Controls" section with references to the "Working With
+ Controls" section. In the text describing the LDAP_OPT_HOST_NAME
+ option, added a reference to the "hostname" parameter of ldap_init()
+ for the syntax of the option value. Clarified that ldap_set_option()
+ makes a copy of the "invalue" data.
+
+ "Working With Controls" section: added a note to remind the reader
+ that server controls that are marked critical should not be used with
+ unbind and abandon operations since those two operations have no
+ server response.
+
+
+
+
+Expires: 2 December 1999 [Page 76]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ "Closing the session" section: made it clear that all open connec-
+ tions associated with a session handle are closed when any of the
+ unbind API functions are called.
+
+ "Searching" section: added note that only a subset of the filter
+ functionality is available when communicating with an LDAPv2 server.
+ Clarified text to explain when a local timeout is used and when it is
+ not.
+
+ "Abandoning An Operation" section: removed some redundant text from
+ the paragraph that explains the differences between ldap_abandon()
+ and ldap_abandon_ext().
+
+ "Obtaining Results and Peeking Inside LDAP Messages" section: clari-
+ fied that ldap_result() only returns messages for one request at a
+ time.
+
+ "Handling Errors and Parsing Results" section: replace a few
+ occurrences of LDAPResult with LDAPMessage (there is no type called
+ LDAPResult). Changed the names of the "resultoidp" and "resultdatap"
+ parameters to "retoidp" and "retdatap" to avoid confusion with LDAP
+ result messages.
+
+ "Stepping Through a List of Entries or References" section: added "or
+ References" to the section name to better reflect its contents.
+ Added missing description of "ref" parameter. Added mention of
+ ldap_first_reference() and ldap_next_reference() in sentence about
+ function return values.
+
+ "Stepping Through the Attributes of an Entry" section: added forward
+ reference for BerElement type.
+
+ "Parsing References" section: in the description of the "ref" parame-
+ ter, changed the phrase "these routines" to the more accurate "this
+ routine."
+
+ "Encoded ASN.1 Value Manipulation - General" section: changed text to
+ make sense given that the definition of BerElement now appears first
+ in the "Common Data Structures" section.
+
+ "Encoded ASN.1 Value Manipulation - Encoding" section: Changed the
+ style of function prototypes to better match the rest of the docu-
+ ment. Corrected a typo in the ber_bvdup() description ("as the"
+ replaced with "than the"). Changed "null" to "NULL" where appropri-
+ ate to be consistent with use elsewhere in the document. Removed
+ mention of sequences from the discussion of the LBER_USE_DER option.
+ Fixed some truncated sentences (by adding some missing '\' characters
+ to the nroff document source).
+
+
+
+Expires: 2 December 1999 [Page 77]
+
+
+C LDAP API C LDAP Application Program Interface 2 June 1999
+
+
+ "Encoded ASN.1 Value Manipulation - Encoding Example" section: sim-
+ plified the error handling in the example code through the use of a
+ 'goto' statement.
+
+ "Encoded ASN.1 Value Manipulation - Decoding" section: Changed the
+ style of function prototypes to better match the rest of the docu-
+ ment. Changed "null" to "NULL" and "null-terminated" to "zero-
+ terminated" where appropriate to be consistent with use elsewhere in
+ the document. Fixed a typo (the text now says "an allocated" instead
+ of "a allocated."). Clarified the description of the 'n' format
+ character for ber_scanf().
+
+ "Encoded ASN.1 Value Manipulation - Decoding Example" section:
+ changed code to not define a macro that begins with "LDAP" since that
+ prefix is reserved for the API. Removed an extra 'i' from the format
+ string used in the first call to ber_scanf(). Changed error report-
+ ing code to send messages to stderr instead of stdout. Changed
+ declaration of "res" local variable from "int" to "unsigned long" and
+ corrected one test of the ber_scanf() return value to test against
+ LBER_ERROR instead of -1. Fixed improperly rendered strings (by
+ adding '\' characters to the nroff source for this document so that
+ '\t' and '\n' are correctly rendered).
+
+ "Acknowledgements" section: added the mention of Chris Weider.
+ Rephrased the text that gives credit to the National Science Founda-
+ tion (it now says "The original material upon which this specifica-
+ tion is based was supported by ..." instead of "This original
+ material upon which this revision is based was based upon work sup-
+ ported by ..."
+
+ In the "Bibliography" section: Added a reference to RFC 1345 and
+ ANSI/ISO C. Updated the LDAPv3 TLS and Sorting references to point
+ to the latest revisions of those documents.
+
+ "Appendix - Sample C LDAP API Code": added #include <stdio.h> to the
+ sample code. Changed the code to demonstrate good error handling by
+ freeing all memory and calling ldap_unbind() before returning.
+ Replaced calls to exit() with return statements. Fixed improperly
+ rendered strings (by adding '\' characters to the nroff source for
+ this document so that '\t' and '\n' are correctly rendered).
+
+
+
+
+
+
+
+
+
+
+
+Expires: 2 December 1999 [Page 78]
+
+
--- /dev/null
+IETF LDAPEXT Working Group Christopher Lukas [Editor]
+INTERNET-DRAFT Internet Scout Project
+ Tim Howes
+ Netscape Communications Corp.
+ Michael Roszkowski
+ Internet Scout Project
+ Mark C. Smith
+ Netscape Communications Corp.
+ Mark Wahl
+ Critial Angle, Inc.
+ June 1999
+
+
+ Named Referrals in LDAP Directories
+ <draft-ietf-ldapext-namedref-00.txt>
+
+
+
+1. Status of this Memo
+
+This document is an Internet-Draft and is in full conformance with all
+provisions of Section 10 of RFC2026.
+
+Internet-Drafts are working documents of the Internet Engineering Task
+Force (IETF), its areas, and its working groups. Note that other groups
+may also distribute working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time. It is inappropriate to use Internet- Drafts as reference material
+or to cite them other than as "work in progress."
+
+The list of current Internet-Drafts can be accessed at
+http://www.ietf.org/ietf/1id-abstracts.txt
+
+The list of Internet-Draft Shadow Directories can be accessed at
+http://www.ietf.org/shadow.html.
+
+Distribution of this document is unlimited. Please send comments to the
+authors or the LDAPEXT mailing list, ietf-ldapext@netscape.com.
+
+Copyright Notice: Copyright (C) The Internet Society (1999). All Rights
+Reserved.
+
+This draft is a revision of a draft formerly published as draft-ietf-
+ldapext-referral-00.txt.
+
+This draft expires December 6, 1999.
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 1]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+2. Abstract
+
+This document defines a "ref" attribute and associated "referral" object
+class for representing generic knowledge information in LDAP directories
+[RFC2251]. The attribute uses URIs [RFC1738] to represent knowledge,
+enabling LDAP and non-LDAP services alike to be referenced. The object
+class can be used to construct entries in an LDAP directory containing
+references to other directories or services. This document also defines
+procedures directory servers should follow when supporting these schema
+elements and when responding to requests for which the directory server
+does not contain the requested object but may contain some knowledge of
+the location of the requested object.
+
+3. Background and intended usage
+
+The broadening of interest in LDAP directories beyond their use as front
+ends to X.500 directories has created a need to represent knowledge
+information in a more general way. Knowledge information is information
+about one or more servers maintained in another server, used to link
+servers and services together.
+
+This document defines a general method of representing knowledge infor-
+mation in LDAP directories, based on URIs.
+
+The key words "MUST", "SHOULD", and "MAY" used in this document are to
+be interpreted as described in [RFC2119].
+
+4. The ref attribute type
+
+This section defines the ref attribute type for holding general
+knowledge reference information.
+
+( 2.16.840.1.113730.3.1.34 NAME 'ref' DESC 'URL reference'
+ EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ USAGE distributedOperation )
+
+The ref attribute type has IA5 syntax and is case sensitive. The ref
+attribute is multivalued. Values placed in the attribute MUST conform to
+the specification given for the labeledURI attribute defined in
+[RFC2079]. The labeledURI specification defines a format that is a URI,
+optionally followed by whitespace and a label. This document does not
+make use of the label portion of the syntax. Future documents MAY enable
+new functionality by imposing additional structure on the label portion
+of the syntax as it appears in the ref attribute.
+
+If the URI contained in the ref attribute refers to an LDAPv3 server, it
+must be in the LDAP URI format described in [RFC2255].
+
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 2]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+When returning a referral result, the server must not return the label
+portion of the labeledURI as part of the referral. Only the URI portion
+of the ref attribute should be returned.
+
+5. Use of the ref attribute
+
+One usage of the ref attribute is defined in this document. Other uses
+of the ref attribute MAY be defined in subsequent documents, or by bila-
+teral agreement between cooperating clients and servers.
+
+Except when the manageDsaIT control (documented in section 8 of this
+document) is present in the operation request, the ref attribute is not
+visible to clients, except as its value is returned in referrals or con-
+tinuation references.
+
+If the manageDsaIT control is not set, and the entry named in a request
+contains the ref attribute, and the entry is not the root DSE, the
+server returns an LDAPResult with the resultCode field set to "referral"
+and the referral field set to contain the value(s) of the ref attribute
+minus any optional trailing whitespace and labels that might be present.
+
+If the manageDsaIT control is not set, and an entry containing the ref
+attribute is in the scope of a one level or subtree search request, the
+server returns a SearchResultReference for each such entry containing
+the value(s) of the entry's ref attribute.
+
+When the manageDsaIT control is present in a request, the server will
+treat an entry containing the ref attribute as an ordinary entry, and
+the ref attribute as an ordinary attribute, and the server will not
+return referrals or continuation references corresponding to ref attri-
+butes.
+
+The following sections detail these usages of the ref attribute.
+
+5.1. Named reference
+
+This use of the ref attribute is to facilitate distributed name resolu-
+tion or search across multiple servers. The ref attribute appears in an
+entry named in the referencing server. The value of the ref attribute
+points to the corresponding entry maintained in the referenced server.
+
+While the distinguished name in a value of the ref attribute is typi-
+cally that of an entry in a naming context below the naming context held
+by the referencing server, it is permitted to be the distinguished name
+of any entry. If the ref attribute is multi-valued all the DNs in the
+values of the ref attribute SHOULD have the same value. It is the
+responsibility of clients to not loop repeatedly if a naming loop is
+present in the directory. Administrators SHOULD avoid configuring
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 3]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+naming loops using referrals.
+
+Clients SHOULD perform at least simple "depth-of-referral count" loop
+detection by incrementing a counter each time a new set of referrals is
+received. Clients MAY perform more sophisticated loop detection, for
+example not chasing the same URI twice.
+
+If an entry containing the ref attribute is immediately subordinate to
+the base object named in a one level search request, then the referring
+server MUST include a scope of "base" in any LDAP URIs returned in the
+corresponding SearchResultReference.
+
+5.1.1. Scenarios
+
+The following sections contain specifications of how the ref attribute
+should be used in different scenarios followed by examples that illus-
+trate that usage. The scenarios described consist of referral operation
+when finding a base or target object, referral operation when performing
+a one level search, and referral operation when performing a subtree
+search.
+
+It is to be noted that, in this document, a search operation is concep-
+tually divided into two distinct, sequential phases: (1) finding the
+base object where the search is to begin, and (2) performing the search
+itself. The operation of the server with respect to referrals in phase
+(1) is almost identical to the operation of the server while finding the
+target object for a non-search operation.
+
+It is to also be noted that multiple ref attributes are allowed in any
+entry and, where these sections refer to a single ref attribute, multi-
+ple ref attributes may be substituted and should be processed and
+returned as a group in an LDAPResult or search result in the same way as
+described for a single attribute. The order of the returned continuation
+references within a result is not defined.
+
+
+5.1.1.1. Example configuration
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 4]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+ |------------------------------------------------------------|
+ | Server A |
+ | dn: o=abc,c=us dn: o=xyz,c=us |
+ | o: abc o: xyz |
+ | ref: ldap://hostB/o=abc,c=us ref: ldap://hostD/o=xyz,c=us |
+ | ref: ldap://hostC/o=abc,c=us objectclass: referral |
+ | objectclass: referral objectclass: extensibleObject|
+ | objectclass: extensibleObject |
+ |____________________________________________________________|
+
+ |---------------------| |---------------------| |---------------------|
+ | Server B | | Server D | | Server C |
+ | dn: o=abc,c=us | | dn: o=xyz,c=us | | dn: o=abc,c=us |
+ | o: abc | | o: xyz | | o: abc |
+ | other attributes... | | other attributes... | | other attributes... |
+ |_____________________| |_____________________| |_____________________|
+
+In this example, Server A holds references for two entries: "o=abc,c=us"
+and "o=xyz,c=us". For the "o=abc,c=us" entry, Server A holds two refer-
+ences, one to Server B and one to Server C. The entries referenced are
+replicas of each other. For the "o=xyz,c=us" entry, Server A holds a
+single reference to the entry contained in Server D.
+
+In the following protocol interaction examples, the client has contacted
+Server A. Server A holds the naming context "c=us".
+
+5.1.1.2. Base or target object considerations
+
+As previously described, the process of generating referrals for a
+search can be described in two phases. The first, which is described in
+this section, is generating referrals based on the base object specified
+in the search. This process is identical to the process of generating
+referrals based on the target object while processing other operations
+(modify, add, delete, modify DN, and compare) with the sole exception
+that for these other operations, the DN in the referral must be modified
+in some cases.
+
+If a client requests any of these operations, there are four cases that
+the server must handle with respect to the base or target object speci-
+fied in the request.
+
+Case 1: The base or target object is not held by the server and is not
+subordinate to any object held by the server with a ref attribute.
+
+The handling of this case is described in section 6.
+
+Case 2: The base or target object is held by the server and contains a
+ref attribute
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 5]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+In this case, if the type of operation requested is a search or the URI
+contained in the ref attribute of the requested base object is NOT an
+LDAP URI as defined in [RFC2255], the server should return the URI value
+contained in the ref attribute of the base object whose DN is the DN
+requested by the client as the base for the operation.
+
+Example:
+
+If the client issues a search in which the base object is "o=xyz,c=us",
+server A will return
+
+ SearchResultDone "referral" {
+ ldap://hostD/o=xyz,c=us
+ }
+
+If the type of operation requested is not a search and the URI contained
+in the ref attribute of the requested target object is an LDAP URI
+[RFC2255], the server should return a modified form of this URL. The
+returned URL must have only the protocol, host, port, and trailing "/"
+portion of the URL contained in the ref attribute. The server should
+strip any dn, attributes, scope, and filter parts of the URL.
+
+Example:
+
+If the client issues a modify request for the target object of
+"o=abc,c=us", server A will return
+
+ ModifyResponse "referral" {
+ ldap://hostB/
+ ldap://hostC/
+ }
+
+Case 3: The base or target object is not held by the server, but is
+subordinate to an object with a ref attribute held by the server.
+
+
+If a client requests an operation for which the base or target object is
+not held by the server, but is subordinate to one or more objects with a
+ref attribute held by the server, the server must return the referral
+from the superior held object nearest to the requested base or target
+object. Nearest superior object with a referral, in this document, means
+an object superior to the base or target object with the DN that has the
+most attribute values in common with the DN of the base or target object
+and contains a ref attribute.
+
+The process of finding the nearest superior object can be envisioned as
+walking up the locally held part of the DIT from the requested base or
+target object checking each superior object until either an object with
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 6]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+a ref attribute is found or the top-most locally held object is reached.
+Once possible implementation of this algorithm is as follows:
+
+ 1. Remove the leftmost attribute/value pair from the DN of the
+ requested base or target object.
+ 2. If the remaining DN represents a locally held object that contains
+ a ref attribute, that object is the nearest superior object with a
+ referral. Stop and process the referral as described below.
+ 3. If the remaining DN is the root of the locally held part of the
+ DIT, stop and proceed as described in section 6.
+ 4. Continue with step 1.
+
+Once the nearest superior object has been identified, if the referral
+contained in that object is not an LDAP URI [RFC2255], it should be
+returned as-is. If the referral is an LDAP URI, the referral must be
+modified, regardless of the type of operation, as case 2 describes for a
+non-search requuest. That is, the dn, attributes, scope, and filter
+parts of the URL must be stripped from the referral and the referral
+returned.
+
+Example:
+
+If the client issues an add request where the target object has a DN of
+"cn=Chris Lukas,o=abc,c=us", server A will return
+
+ AddResponse "referral" {
+ ldap://hostB/
+ ldap://hostC/
+ }
+
+
+
+
+5.1.1.3. Search with one level scope
+
+For search operations, once the base object has been found and deter-
+mined not to contain a ref attribute, the search may progress. Any
+entries matching the filter and scope of the search that do NOT contain
+a ref attribute are returned to the client normally as described in
+[RFC2251]. Any entries matching the filter and one level scope that do
+contain a ref attribute must be returned as referrals as described here.
+
+If a matching entry contains a ref attribute and the URI contained in
+the ref attribute is NOT an LDAP URI [RFC2255], the server should return
+the URI value contained in the ref attribute of that entry in a Sear-
+chResultReference.
+
+If a matching entry contains a ref attribute in the LDAP URI syntax
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 7]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+[RFC2255], the URL from the ref attribute must be modified before it is
+returned by adding or substituting a "base" scope into the URL. If the
+URL does not contain a scope specifier, the "base" scope specifier must
+be added. If the URL does contain a scope specifier, the existing scope
+specifier must be replaced by the "base" scope.
+
+Example:
+
+If a client requests a one level search of "c=US" then, in addition to
+any entries one level below the "c=US" naming context matching the
+filter (shown below as "... SearchResultEntry responses ..."), the
+server will also return referrals modified to include the "base" scope
+to maintain the one level search semantics.
+
+The order of the SearchResultEntry responses and the SearchResultRefer-
+ence responses is undefined. One possible sequence is shown.
+
+ ... SearchResultEntry responses ...
+
+ SearchResultReference {
+ ldap://hostB/o=abc,c=us??base
+ ldap://hostC/o=abc,c=us??base
+ }
+
+ SearchResultReference {
+ ldap://hostD/o=xyz,c=us??base
+ }
+
+ SearchResultDone "success"
+
+
+5.1.1.4. Search with subtree scope
+
+For a search operation with a subtree scope, once the base object has
+been found, the search progresses. As with the one level search, any
+entries matching the filter and scope of the search that do NOT contain
+a ref attribute are returned to the client normally as described in
+[RFC2251].
+
+If an entry matching the requested scope and filter contains a ref
+attribute, the server should return the URI value in a SearchResul-
+tReference.
+
+Example:
+
+If a client requests a subtree search of "c=us", then in addition to any
+entries in the "c=us" naming context which match the filter, Server A
+will also return two continuation references. As described in the
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 8]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+preceding section, the order of the responses is not defined.
+
+One possible response might be:
+
+ ... SearchResultEntry responses ...
+
+ SearchResultReference {
+ ldap://hostB/o=abc,c=us
+ ldap://hostC/o=abc,c=us
+ }
+
+ SearchResultReference {
+ ldap://hostD/o=xyz,c=us
+ }
+
+ SearchResultDone "success"
+
+
+6. Superior Reference
+
+An LDAP server may be configured to return a superior reference in the
+case where the server does not hold either the requested base object or
+an object containing a ref attribute that is superior to that base
+object.
+
+An LDAP server's root DSE MAY contain a ref attribute. The values of the
+ref attribute in the root DSE that are LDAP URIs SHOULD NOT contain any
+dn part, just the host name and optional port number.
+
+If the LDAP server's root DSE contains a ref attribute and a client
+requests an object not held by the server and not subordinate to any
+held object, the server must return the URI component of the values in
+the ref attribute of the root DSE as illustrated in the example.
+
+If the LDAP server's root DSE does not contain a ref attribute, the
+server may return one or more references that the server determines via
+a method not defined in this document to be appropriate.
+
+The default reference may be to any server that might contain more
+knowledge of the namespace than the responding server. In particular,
+the client must not expect the superior reference to be identical from
+session to session as the reference may be dynamically created by the
+server based on the details of the query submitted by the client.
+
+When the server receives an operation for which the base or target entry
+of the request is not contained in or subordinate to any naming context
+held by the server or a referral entry, the server will return an
+LDAPResult with the resultCode set to "referral", and with the referral
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 9]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+field filled with a referral that the server has determined to be
+appropriate.
+
+Example:
+
+If a client requests a subtree search of "c=de" from server A in the
+example configuration, and server A has the following ref attribute
+defined in it's root DSE:
+
+ ref: ldap://hostG/
+
+then server A will return
+
+ SearchResultDone "referral" {
+ ldap://hostG/
+ }
+
+
+7. The referral object class
+
+The referral object class is defined as follows.
+
+( 2.16.840.1.113730.3.2.6 NAME 'referral' SUP top STRUCTURAL
+ MAY ( ref ) )
+
+The referral object class is a subclass of top and may contain the
+referral attribute. The referral object class should, in general, be
+used in conjunction with the extensibleObject object class to support
+the naming attributes used in the entry's distinguished name.
+
+Servers must support the ref attribute through use of the referral
+object class. Any named reference must be of the referral object class
+and will likely also be of the extensibleObject object class to support
+naming and use of other attributes.
+
+8. The manageDsaIT control
+
+A client MAY specify the following control when issuing a search, com-
+pare, add, delete, modify, or modifyDN request or an extended operation
+for which the control is defined.
+
+The control type is 2.16.840.1.113730.3.4.2. The control SHOULD be
+marked as critical. There is no value; the controlValue field is
+absent.
+
+This control causes entries with the "ref" attribute to be treated as
+normal entries, allowing clients to read and modify these entries.
+
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 10]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+This control is not needed if the entry containing the referral attri-
+bute is one used for directory administrative purposes, such as the root
+DSE, or the server change log entries. Operations on these entries
+never cause referrals or continuation references to be returned.
+
+9. Relationship to X.500 Knowledge References
+
+The X.500 standard defines several types of knowledge references, used
+to bind together different parts of the X.500 namespace. In X.500,
+knowledge references can be associated with a set of unnamed entries
+(e.g., a reference, associated with an entry, to a server containing the
+descendants of that entry).
+
+This creates a potential problem for LDAP clients resolving an LDAPv3
+URL referral referring to an LDAP directory back-ended by X.500. Sup-
+pose the search is a subtree search, and that server A holds the base
+object of the search, and server B holds the descendants of the base
+object. The behavior of X.500(1993) subordinate references is that the
+base object on server A is searched, and a single continuation reference
+is returned pointing to all of the descendants held on server B.
+
+An LDAP URI only allows the base object to be specified. It is not pos-
+sible using standard LDAP URIs to indicate a search of several entries
+whose names are not known to the server holding the superior entry.
+
+X.500 solves this problem by having two fields, one indicating the pro-
+gress of name resolution and the other indicating the target of the
+search. In the above example, name resolution would be complete by the
+time the query reached server B, indicating that it should not refer the
+request.
+
+This document does not address this problem. This problem will be
+addressed in separate documents which define the changes to the X.500
+distribution model and LDAPv3 extensions to indicate the progress of
+name resolution.
+
+10. Security Considerations
+
+This document defines mechanisms that can be used to "glue" LDAP (and
+other) servers together. The information used to specify this glue
+information should be protected from unauthorized modification. If the
+server topology information itself is not public information, the infor-
+mation should be protected from unauthorized access as well.
+
+Clients should use caution when re-using credentials while following
+referrals as the client may be directed to any server which may or may
+not respect or use those credentials appropriately.
+
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 11]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+11. References
+
+[RFC1738]
+ Berners-Lee, T., Masinter, L., and McCahill, M., "Uniform Resource
+ Locators (URL)", RFC 1738, CERN, Xerox Corporation, University of
+ Minnesota, December 1994.
+
+[RFC2079]
+ M. Smith, "Definition of an X.500 Attribute Type and an Object Class
+ to Hold Uniform Resource Identifiers (URIs)", RFC 2079, January
+ 1997.
+
+[RFC2119]
+ S. Bradner, "Key Words for use in RFCs to Indicate Requirement Lev-
+ els", RFC 2119, March 1997. (Format: TXT=4723 bytes) (Also BCP0014)
+ (Status: BEST CURRENT PRACTICE)
+
+[RFC2251]
+ M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol
+ (v3)", RFC 2251, December 1997.
+
+[RFC2255]
+ T. Howes, M. Smith, "The LDAP URL Format", RFC 2255, December, 1997.
+ (Format: TXT=20685 bytes) (Status: PROPOSED STANDARD)
+
+[X500]
+ ITU-T Rec. X.501, "The Directory: Models", 1993.
+
+12. Author's Address
+
+Tim Howes
+Netscape Communications Corp.
+501 E. Middlefield Rd.
+Mailstop MV068
+Mountain View, CA 94043
+USA
++1 650 937-3419
+EMail: howes@netscape.com
+
+Christopher E. Lukas
+Internet Scout Project
+Computer Sciences Dept.
+University of Wisconsin-Madison
+1210 W. Dayton St.
+Madison, WI 53706
+USA
+EMail: lukas@cs.wisc.edu
+
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 12]
+
+
+
+
+
+INTERNET-DRAFT LDAPv3 Named Referrals March 1999
+
+
+Michael Roszkowski
+Internet Scout Project
+Computer Sciences Dept.
+University of Wisconsin-Madison
+1210 W. Dayton St.
+Madison, WI 53706
+USA
+EMail: mfr@cs.wisc.edu
+
+Mark C. Smith
+Netscape Communications Corp.
+501 E. Middlefield Rd.
+Mailstop MV068
+Mountain View, CA 94043
+USA
+EMail: mcs@netscape.com
+
+Mark Wahl
+Innosoft International, Inc.
+8911 Capital of Texas Hwy #4140
+Austin TX 78759
+EMail: M.Wahl@innosoft.com
+
+
+This draft expires December 6, 1999.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Howes, et al. IETF LDAPEXT Working Group [Page 13]
+
+
--- /dev/null
+INTERNET-DRAFT
+draft-ietf-ldup-subentry-00.txt
+ Ed Reed
+ Novell, Inc.
+ August 15, 1999
+
+ LDAP Subentry Schema
+
+
+1. Status of this Memo
+
+This document is an Internet-Draft and is in full conformance with all
+provisions of Section 10 of RFC2026.
+
+Internet-Drafts are working documents of the Internet Engineering Task
+Force (IETF), its areas, and its working groups. Note that other
+groups may also distribute working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time. It is inappropriate to use Internet-Drafts as reference material
+or to cite them other than as "work in progress."
+
+The list of current Internet-Drafts can be accessed at
+http://www.ietf.org/ietf/1id-abstracts.txt.
+
+The list of Internet-Draft Shadow Directories can be accessed at
+http://www.ietf.org/shadow.html.
+
+This Internet-Draft expires on January 9, 1999.
+
+
+2. Abstract
+
+This document describes an object class called lDAPsubEntry which MAY
+be used to indicate operations and management related entries in the
+directory, called LDAP Subentries.
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+document are to be interpreted as described in RFC 2119 [RFC2119]. The
+sections below reiterate these definitions and include some additional
+ones.
+
+
+
+
+
+
+
+Reed [Page 1]
+ Expires January 15, 2000\f
+
+
+INTERNET-DRAFT 15 August 1999
+ LDAP Subentry Schema
+
+3. Definition
+
+
+3.1 LDAPsubEntry Class
+
+( 1.3.6.1.4.1.1466.115.121.1.?? NAME 'LDAPsubEntry'
+ DESC 'LDAP Subentry class, named by cn'
+ SUP top STRUCTURAL
+ MUST ( cn ) )
+
+The class lDAPsubEntry is intended to be used as a super class when
+defining other structural classes to be used as LDAP Subentries. The
+presence of lDAPsubEntry in the list of super-classes of an entry in
+the directory makes that entry an LDAP Subentry. Object classes
+derived from lDAPsubEntry are themselves considered lDAPsubEntry
+classes, for the purpose of this discussion.
+
+LDAP Subentries MAY be named by their commonName attribute [LDAPv3].
+Other naming attributes are also permitted.
+
+LDAP Subentries MAY be containers, unlike their [X.500] counterparts.
+
+LDAP Subentries MAY be contained by, and will usually be located in
+the directory information tree immediately subordinate to,
+administrative points and/or naming contexts [LDUPINFO]. Further
+(unlike X.500 subentries), LDAP Subentries MAY be contained by other
+LDAP Subentries (the way organizational units may be contained by
+other organizational units). Deep nestings of LDAP Subentries are
+discouraged, but not prohibited.
+
+LDAP Subentries SHOULD be treated as "operational objects" in much the
+same way that "operational attributes" are not regularly provided in
+search results and read operations when only user attributes are
+requested).
+
+NOTE: No special treatment of LDAP Subentries by applications is
+required, but it might be worth considering creating an LDAPv3 control
+to indicate when LDAP Subentries are desired to be returned (subject
+to access controls and search filters, of course) for LDAP search
+operations.
+
+
+
+4. Security Considerations
+
+LDAP Subentries will frequently be used to hold data which reflects
+either the actual or intended behavior of the directory service. As
+such, permission to read such entries MAY need to be restricted to
+
+Reed [Page 2]
+ Expires January 15, 2000\f
+
+
+INTERNET-DRAFT 15 August 1999
+ LDAP Subentry Schema
+
+authorized users. More importantly, IF a directory service treats the
+information in an LDAP Subentry as the authoritative source of policy
+to be used to control the behavior of the directory, then permission
+to create, modify, or delete such entries MUST be carefully restricted
+to authorized administrators.
+
+
+
+5. References
+
+[LDUPINFO] _ E. Reed, "LDUP Replication Information Model", draft-
+ietf-ldup-infomod-01.txt
+
+[LDAPv3] Kille, S., Wahl, M., and T. Howes, "Lightweight Directory
+Access Protocol (v3)", RFC 2251, December 1997
+
+[X.500] ITU-T Rec. X.501, "The Directory: Models", 1993
+
+
+
+6. Copyright Notice
+
+Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to
+others, and derivative works that comment on or otherwise explain it
+or assist in its implementation may be prepared, copied, published and
+distributed, in whole or in part, without restriction of any kind,
+provided that the above copyright notice and this paragraph are
+included on all such copies and derivative works. However, this
+document itself may not be modified in any way, such as by removing
+the copyright notice or references to the Internet Society or other
+Internet organizations, except as needed for the purpose of developing
+Internet standards in which case the procedures for copyrights defined
+in the Internet Standards process must be followed, or as required to
+translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be
+revoked by the Internet Society or its successors or assigns.
+
+This document and the information contained herein is provided on an
+"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN
+WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE."
+
+
+
+Reed [Page 3]
+ Expires January 15, 2000\f
+
+
+INTERNET-DRAFT 15 August 1999
+ LDAP Subentry Schema
+
+7. Acknowledgements
+
+The use of subEntry object class to store Replica and Replication
+Agreement information is due primarily to the lucid explanation by
+Mark Wahl, Innosoft, of how they could be used and extended.
+
+The IETF takes no position regarding the validity or scope of any
+intellectual property or other rights that might be claimed to pertain
+to the implementation or use of the technology described in this
+document or the extent to which any license under such rights might or
+might not be available; neither does it represent that it has made any
+effort to identify any such rights. Information on the IETF's
+procedures with respect to rights in standards-track and standards-
+related documentation can be found in BCP-11. Copies of claims of
+rights made available for publication and any assurances of licenses
+to be made available, or the result of an attempt made to obtain a
+general license or permission for the use of such proprietary rights
+by implementors or users of this specification can be obtained from
+the IETF Secretariat.
+
+The IETF invites any interested party to bring to its attention any
+copyrights, patents or patent applications, or other proprietary
+rights which may cover technology that may be required to practice
+this standard. Please address the information to the IETF Executive
+Director.
+
+
+8. Author's Address
+
+ Edwards E. Reed
+ Novell, Inc.
+ 122 E 1700 S
+ Provo, UT 84606
+ USA
+ E-mail: Ed_Reed@Novell.com
+
+ LDUP Mailing List: ietf-ldup@imc.org
+
+
+
+
+
+
+
+
+
+
+
+
+Reed [Page 4]
+ Expires January 15, 2000\f
-.TH LDAPDELETE 1 "13 November 1995" "U-M LDAP LDVERSION"
+.TH LDAPDELETE 1 "17 August 1999" "OpenLDAP LDVERSION"
.SH NAME
-ldapdelete \- ldap delete entry tool
+ldapdelete \- LDAP delete entry tool
.SH SYNOPSIS
.B ldapdelete
-.B [\-n]
-.B [\-v]
-.B [\-k]
-.B [\-K]
-.B [\-c]
-.B [\-d debuglevel]
-.B [\-f file]
-.B [\-D binddn]
-.B [\-w passwd]
-.B [\-h ldaphost]
-.B [\-p ldapport]
-.B [dn]...
+[\c
+.BR \-n ]
+[\c
+.BR \-v ]
+[\c
+.BR \-k ]
+[\c
+.BR \-K ]
+[\c
+.BR \-c ]
+[\c
+.BR \-M[M] ]
+[\c
+.BI \-d \ debuglevel\fR]
+[\c
+.BI \-f \ file\fR]
+[\c
+.BI \-D \ binddn\fR]
+[\c
+.BR \-W ]
+[\c
+.BI \-w \ passwd\fR]
+[\c
+.BI \-h \ ldaphost\fR]
+[\c
+.BI \-P \ 2\fR\||\|\fI3\fR]
+[\c
+.BI \-p \ ldapport\fR]
+[\c
+.IR dn ]...
.SH DESCRIPTION
.I ldapdelete
is a shell-accessible interface to the
will continue with deletions. The default is to exit after
reporting an error.
.TP
-.B \-d debuglevel
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
+.BI \-d \ debuglevel
Set the LDAP debugging level to \fIdebuglevel\fP.
.B ldapdelete
must be compiled with LDAP_DEBUG defined for this option to have any effect.
.TP
-.B \-f file
+.BI \-f \ file
Read a series of lines from \fIfile\fP, performing one LDAP search for
each line. In this case, the \fIfilter\fP given on the command line
is treated as a pattern where the first occurrence of \fB%s\fP is
replaced with a line from \fIfile\fP.
.TP
-.B \-D binddn
-Use \fIbinddn\fP to bind to the X.500 directory. \fIbinddn\fP should be
+.BI \-D \ binddn
+Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should be
a string-represented DN as defined in RFC 1779.
.TP
-.B \-w passwd
+.B \-W
+Prompt for simple authentication.
+This is used instead of specifying the password on the command line.
+.TP
+.BI \-w \ passwd
Use \fIpasswd\fP as the password for simple authentication.
.TP
-.B \-h ldaphost
+.BI \-h \ ldaphost
Specify an alternate host on which the ldap server is running.
.TP
-.B \-p ldapport
+.BI \-p \ ldapport
Specify an alternate TCP port where the ldap server is listening.
+.TP
+.BI \-P \ 2\fR\||\|\fI3
+Specify the LDAP protocol version to use.
.SH EXAMPLE
The following command:
.LP
.nf
- ldapdelete "cn=Delete Me, o=University of Michigan, c=US"
+ ldapdelete "cn=Delete Me, dc=OpenLDAP, dc=org"
.fi
.LP
will attempt to delete the entry named with commonName "Delete Me"
-directly below the University of Michigan organizational entry. Of
+directly below the "dc=OpenLDAP, dc=org" entry. Of
course it would probably be necessary to supply a \fIbinddn\fP and
\fIpasswd\fP for deletion to be allowed (see the -D and -w options).
.SH DIAGNOSTICS
Exit status is 0 if no errors occur. Errors result in a non-zero exit
status and a diagnostic message being written to standard error.
.SH "SEE ALSO"
+.BR ldap.conf (5),
.BR ldapadd (1),
.BR ldapmodify (1),
.BR ldapmodrdn (1),
ISODE Consortium, March 1995.
.SH BUGS
There is no interactive mode, but there probably should be.
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
-.TH LDAPMODIFY 1 "13 November 1995" "U-M LDAP LDVERSION"
+.TH LDAPMODIFY 1 "17 August 1999" "OpenLDAP LDVERSION"
.SH NAME
-ldapmodify, ldapadd \- ldap modify entry and ldap add entry tools
+ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools
.SH SYNOPSIS
.B ldapmodify
-.B [\-a]
-.B [\-b]
-.B [\-c]
-.B [\-r]
-.B [\-n]
-.B [\-v]
-.B [\-k]
-.B [\-d debuglevel]
-.B [\-D binddn]
-.B [\-w passwd]
-.B [\-h ldaphost]
-.B [\-p ldapport]
-.B [\-f file]
+[\c
+.BR \-a ]
+[\c
+.BR \-b ]
+[\c
+.BR \-c ]
+[\c
+.BR \-r ]
+[\c
+.BR \-n ]
+[\c
+.BR \-v ]
+[\c
+.BR \-k ]
+[\c
+.BR \-M[M] ]
+[\c
+.BI \-d \ debuglevel\fR]
+[\c
+.BI \-D \ binddn\fR]
+[\c
+.BR \-W ]
+[\c
+.BI \-w \ passwd\fR]
+[\c
+.BI \-h \ ldaphost\fR]
+[\c
+.BI \-p \ ldapport\fR]
+[\c
+.BI \-P \ 2\fR\||\|\fI3\fR]
+[\c
+.BI \-f \ file\fR]
.LP
.B ldapadd
-.B [\-b]
-.B [\-c]
-.B [\-r]
-.B [\-n]
-.B [\-v]
-.B [\-k]
-.B [\-K]
-.B [\-d debuglevel]
-.B [\-D binddn]
-.B [\-w passwd]
-.B [\-h ldaphost]
-.B [\-p ldapport]
-.B [\-f file]
+[\c
+.BR \-b ]
+[\c
+.BR \-c ]
+[\c
+.BR \-r ]
+[\c
+.BR \-n ]
+[\c
+.BR \-v ]
+[\c
+.BR \-k ]
+[\c
+.BR \-K ]
+[\c
+.BI \-d \ debuglevel\fR]
+[\c
+.BI \-D \ binddn\fR]
+[\c
+.BI \-w \ passwd\fR]
+[\c
+.BI \-h \ ldaphost\fR]
+[\c
+.BI \-p \ ldapport\fR]
+[\c
+.BI \-f \ file\fR]
.SH DESCRIPTION
.B ldapmodify
is a shell-accessible interface to the
(by default, replica: lines are compared against the LDAP server host
and port in use to decide if a replog record should actually be applied).
.TP
-.B \-d debuglevel
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
+.BI \-d \ debuglevel
Set the LDAP debugging level to \fIdebuglevel\fP.
.B ldapmodify
must be compiled with LDAP_DEBUG defined for this option to have any effect.
.TP
-.B \-f file
+.BI \-f \ file
Read the entry modification information from \fIfile\fP instead of from
standard input.
.TP
-.B \-D binddn
-Use \fIbinddn\fP to bind to the X.500 directory. \fIbinddn\fP should be
+.BI \-D \ binddn
+Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should be
a string-represented DN as defined in RFC 1779.
.TP
-.B \-w passwd
+.B \-W
+Prompt for simple authentication.
+This is used instead of specifying the password on the command line.
+.TP
+.BI \-w \ passwd
Use \fIpasswd\fP as the password for simple authentication.
.TP
-.B \-h ldaphost
+.BI \-h \ ldaphost
Specify an alternate host on which the ldap server is running.
.TP
-.B \-p ldapport
+.BI \-p \ ldapport
Specify an alternate TCP port where the ldap server is listening.
+.TP
+.BI \-P \ 2\fR\||\|\fI3
+Specify the LDAP protocol version to use.
.SH INPUT FORMAT
The contents of \fIfile\fP (or standard input if no \-f flag is given on
the command line) should conform to the format defined in
exists and has the contents:
.LP
.nf
- dn: cn=Modify Me, o=University of Michigan, c=US
+ dn: cn=Modify Me, dc=OpenLDAP, dc=Org
changetype: modify
replace: mail
- mail: modme@terminator.rs.itd.umich.edu
+ mail: modme@OpenLDAP.org
-
add: title
title: Grand Poobah
-
add: jpegPhoto
- jpegPhoto: /tmp/modme.jpeg
+ jpegPhoto:< file://tmp/modme.jpeg
-
delete: description
-
.LP
will replace the contents of the "Modify Me" entry's
.I mail
-attribute with the value "modme@terminator.rs.itd.umich.edu", add a
+attribute with the value "modme@OpenLDAP.org", add a
.I title
of "Grand Poobah", and the contents of the file "/tmp/modme.jpeg"
as a
inout format:
.LP
.nf
- cn=Modify Me, o=University of Michigan, c=US
- mail=modme@terminator.rs.itd.umich.edu
+ cn=Modify Me, dc=OpenLDAP, dc=org
+ mail=modme@OpenLDAP.org
+title=Grand Poobah
+jpegPhoto=/tmp/modme.jpeg
-description
exists and has the contents:
.LP
.nf
- dn: cn=Barbara Jensen, o=University of Michigan, c=US
+ dn: cn=Barbara Jensen, dc=OpenLDAP, dc=org
objectClass: person
cn: Barbara Jensen
cn: Babs Jensen
sn: Jensen
title: the world's most famous mythical manager
- mail: bjensen@terminator.rs.itd.umich.edu
+ mail: bjensen@OpenLDAP.org
uid: bjensen
.LP
the command:
exists and has the contents:
.LP
.nf
- dn: cn=Barbara Jensen, o=University of Michigan, c=US
+ dn: cn=Barbara Jensen, dc=OpenLDAP, dc=org
changetype: delete
.LP
the command:
.BR ldapdelete (1),
.BR ldapmodrdn (1),
.BR ldapsearch (1),
+.BR ldap.conf (5),
.BR ldap (3),
.BR ldap_add (3),
.BR ldap_delete (3),
ISODE Consortium, March 1995.
.SH BUGS
There is no interactive mode, but there probably should be.
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
-.TH LDAPMODRDN 1 "13 November 1995" "U-M LDAP LDVERSION"
+.TH LDAPMODRDN 1 "17 August 1999" "OpenLDAP LDVERSION"
.SH NAME
-ldapmodrdn \- ldap modify entry RDN tool
+ldapmodrdn \- LDAP rename entry tool
.SH SYNOPSIS
.B ldapmodrdn
-.B [\-r]
-.B [\-n]
-.B [\-v]
-.B [\-k]
-.B [\-K]
-.B [\-c]
-.B [\-d debuglevel]
-.B [\-D binddn]
-.B [\-w passwd]
-.B [\-h ldaphost]
-.B [\-p ldapport]
-.B [\-f file] [dn rdn]
+[\c
+.BR \-r ]
+[\c
+.BR \-n ]
+[\c
+.BR \-v ]
+[\c
+.BR \-k ]
+[\c
+.BR \-K ]
+[\c
+.BR \-c ]
+[\c
+.BR \-M[M] ]
+[\c
+.BI \-d \ debuglevel\fR]
+[\c
+.BI \-D \ binddn\fR]
+[\c
+.BR \-W ]
+[\c
+.BI \-w \ passwd\fR]
+[\c
+.BI \-h \ ldaphost\fR]
+[\c
+.BI \-p \ ldapport\fR]
+[\c
+.BI \-P \ 2\fR\||\|\fI3\fR]
+[\c
+.BI \-f \ file\fR]
+[\c
+.I dn rdn\fR]
.SH DESCRIPTION
.B ldapmodrdn
is a shell-accessible interface to the
will continue with modifications. The default is to exit after
reporting an error.
.TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
.B \-d debuglevel
Set the LDAP debugging level to \fIdebuglevel\fP.
.B ldapmodrdn
standard input or the command-line.
.TP
.B \-D binddn
-Use \fIbinddn\fP to bind to the X.500 directory. \fIbinddn\fP should be
+Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should be
a string-represented DN as defined in RFC 1779.
.TP
+.B \-W
+Prompt for simple authentication.
+This is used instead of specifying the password on the command line.
+.TP
.B \-w passwd
Use \fIpasswd\fP as the password for simple authentication.
.TP
.TP
.B \-p ldapport
Specify an alternate TCP port where the ldap server is listening.
+.TP
+.BI \-P \ 2\fR\||\|\fI3
+Specify the LDAP protocol version to use.
.SH INPUT FORMAT
If the command-line arguments \fIdn\fP and \fIrdn\fP are given, \fIrdn\fP
will replace the RDN of the entry specified by the DN, \fIdn\fP.
exists and has the contents:
.LP
.nf
- cn=Modify Me, o=University of Michigan, c=US
+ cn=Modify Me, dc=OpenLDAP, dc=org
cn=The New Me
.fi
.LP
.BR ldapdelete (1),
.BR ldapmodify (1),
.BR ldapsearch (1),
+.BR ldap.conf (5),
.BR ldap (3),
.BR ldap_modrdn2 (3)
.LP
ISODE Consortium, March 1995.
.SH BUGS
There is no interactive mode, but there probably should be.
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
-.TH LDAPSEARCH 1 "29 March 1996" "U-M LDAP LDVERSION"
+.TH LDAPSEARCH 1 "17 August 1999" "OpenLDAP LDVERSION"
.SH NAME
-ldapsearch \- ldap search tool
+ldapsearch \- LDAP search tool
.SH SYNOPSIS
.B ldapsearch
-.B [\-n]
-.B [\-u]
-.B [\-v]
-.B [\-k]
-.B [\-K]
-.B [\-t]
-.B [\-A]
-.B [\-B]
-.B [\-L]
-.B [\-R]
-.B [\-d debuglevel]
-.B [\-F sep]
-.B [\-f file]
-.B [\-D binddn]
-.B [\-w bindpasswd]
-.B [\-h ldaphost]
-.B [\-p ldapport]
-.B [\-b searchbase]
-.B [\-s scope ]
-.B [\-a deref]
-.B [\-l time limit]
-.B [\-z size limit]
-.B filter
-.B [attrs....]
+[\c
+.BR \-n ]
+[\c
+.BR \-u ]
+[\c
+.BR \-v ]
+[\c
+.BR \-k ]
+[\c
+.BR \-K ]
+[\c
+.BR \-t ]
+[\c
+.BR \-A ]
+[\c
+.BR \-B ]
+[\c
+.BR \-L ]
+[\c
+.BR \-M[M] ]
+[\c
+.BR \-R ]
+[\c
+.BI \-d \ debuglevel\fR]
+[\c
+.BI \-F \ sep\fR]
+[\c
+.BI \-f \ file\fR]
+[\c
+.BI \-D \ binddn\fR]
+[\c
+.BR \-W ]
+[\c
+.BI \-w \ bindpasswd\fR]
+[\c
+.BI \-h \ ldaphost\fR]
+[\c
+.BI \-p \ ldapport\fR]
+[\c
+.BI \-P \ 2\fR\||\|\fI3\fR]
+[\c
+.BI \-b \ searchbase\fR]
+[\c
+.BI \-s \ base\fR\||\|\fIone\fR\||\|\fIsub\fR]
+[\c
+.BI \-a \ never\fR\||\|\fIalways\fR\||\|\fIsearch\fR\||\|\fIfind\fR]
+[\c
+.BI \-l \ timelimit\fR]
+[\c
+.BI \-z \ sizelimit\fR]
+.I filter
+[\c
+.IR attrs... ]
.SH DESCRIPTION
.I ldapsearch
is a shell-accessible interface to the
finds one or more entries, the attributes specified by
\fIattrs\fP are retrieved and the entries and values are printed to
standard output. If no \fIattrs\fP are listed, all attributes are
-returned.
+returned. If * is listed, all user attributes are returned.
+If + is listed, all operational attributes are returned.
+If only 1.1 is listed, no attributes are listed.
.SH OPTIONS
.TP
.B \-n
format. This option also turns on the -B option, and causes the -F option
to be ignored.
.TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
.B \-R
Do not automatically follow referrals returned while searching.
.B ldapsearch
must be compiled with LDAP_REFERRALS defined for referrals to be
automatically followed by default, and for this option to have any effect.
.TP
-.B \-F sep
+.BI \-F \ sep
Use \fIsep\fP as the field separator between attribute names and values.
The default separator is `=', unless the -L flag has been specified, in
which case this option is ignored.
.TP
-.B \-S attribute
+.BI \-S \ attribute
Sort the entries returned based on \fIattribute\fP. The default is not
to sort entries returned. If \fIattribute\fP is a zero-length string (""),
the entries are sorted by the components of their Distingished Name. See
option defeats this behavior, causing all entries to be retrieved,
then sorted, then printed.
.TP
-.B \-d debuglevel
+.BI \-d \ debuglevel
Set the LDAP debugging level to \fIdebuglevel\fP.
.B ldapsearch
must be compiled with LDAP_DEBUG defined for this option to have any effect.
.TP
-.B \-f file
+.BI \-f \ file
Read a series of lines from \fIfile\fP, performing one LDAP search for
each line. In this case, the \fIfilter\fP given on the command line
is treated as a pattern where the first occurrence of \fB%s\fP is
replaced with a line from \fIfile\fP. If \fIfile\fP is a single \fI-\fP
character, then the lines are read from standard input.
.TP
-.B \-D binddn
-Use \fIbinddn\fP to bind to the X.500 directory. \fIbinddn\fP should be
+.BI \-D \ binddn
+Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should be
a string-represented DN as defined in RFC 1779.
.TP
-.B \-w bindpasswd
+.B \-W
+Prompt for simple authentication.
+This is used instead of specifying the password on the command line.
+.TP
+.BI \-w \ bindpasswd
Use \fIbindpasswd\fP as the password for simple authentication.
.TP
-.B \-h ldaphost
+.BI \-h \ ldaphost
Specify an alternate host on which the ldap server is running.
.TP
-.B \-p ldapport
+.BI \-p \ ldapport
Specify an alternate TCP port where the ldap server is listening.
.TP
-.B \-b searchbase
+.BI \-b \ searchbase
Use \fIsearchbase\fP as the starting point for the search instead of
the default.
.TP
-.B \-s scope
-Specify the scope of the search. \fIscope\fP should be one of
-.B base,
-.B one,
+.BI \-s \ base\fR\||\|\fIone\fR\||\|\fIsub
+Specify the scope of the search to be one of
+.IR base ,
+.IR one ,
or
-.B sub
+.I sub
to specify a base object, one-level, or subtree search. The default
is
-.BR sub .
+.IR sub .
.TP
-.B \-a deref
-Specify how aliases dereferencing is done. \fIderef\fP should be one of
-.B never,
-.B always,
-.B search,
+.BI \-a \ never\fR\||\|\fIalways\fR\||\|\fIsearch\fR\||\|\fIfind
+Specify how aliases dereferencing is done. Should be one of
+.IR never ,
+.IR always ,
+.IR search ,
or
-.B find
+.I find
to specify that aliases are never dereferenced, always dereferenced,
dereferenced when searching, or dereferenced only when locating the
base object for the search. The default is to never dereference aliases.
.TP
-.B \-l timelimit
-wait at most \fItimelimit\fP seconds for a search to complete.
+.BI \-P \ 2\fR\||\|\fI3
+Specify the LDAP protocol version to use.
+.TP
+.BI \-l \ timelimit
+wait at most \fItimelimit\fP seconds for a search to complete. A
+timelimit of
+.I 0
+(zero) removes the
+.B ldap.conf
+limit.
+A server may impose a maximal timelimit which only
+the root user may override.
.TP
-.B \-z sizelimit
-retrieve at most \fIsizelimit\fP seconds for a search to complete.
+.BI \-z \ sizelimit
+retrieve at most \fIsizelimit\fP entries for a search. A sizelimit
+of
+.I 0
+(zero) removes the
+.B ldap.conf
+limit.
+A server may impose a maximal sizelimit which only
+the root user may override.
.SH OUTPUT FORMAT
If one or more entries are found, each entry is written to standard output
in the form:
The following command:
.LP
.nf
- ldapsearch "cn=mark smith" cn telephoneNumber
+ ldapsearch "(sn=smith)" cn sn telephoneNumber
.fi
.LP
-will perform a subtree search (using the default search base) for entries
-with a commonName of "mark smith". The commonName and telephoneNumber
-values will be retrieved and printed to standard output.
+will perform a subtree search (using the default search base) for
+entries with a surname (sn) of smith. The common name (cn), surname
+(sn) and telephoneNumber values will be retrieved and printed to
+standard output.
The output might look something like this if two entries are found:
.LP
.nf
-cn=Mark D Smith, ou="College of Literature, Science, and the Arts", ou=Students, ou=People, o=University of Michigan, c=US
-cn=Mark Smith
-cn=Mark David Smith
-cn=Mark D Smith 1
-cn=Mark D Smith
-telephoneNumber=+1 313 930-9489
+uid=jts, ou=Volunteers, ou=People, dc=OpenLDAP, dc=org
+cn=John Smith
+cn=John T. Smith
+sn=Smith
+telephoneNumber=+1 555 123-4567
-cn=Mark C Smith, ou=Information Technology Division, ou=Faculty and Staff, ou=People, o=University of Michigan, c=US
-cn=Mark Smith
-cn=Mark C Smith 1
-cn=Mark C Smith
-telephoneNumber=+1 313 764-2277
+uid=sss, ou=Staff, ou=People, dc=OpenLDAP, dc=org
+cn=Steve Smith
+cn=Steve S. Smith
+sn=Smith
+telephoneNumber=+1 555 765-4321
.fi
.LP
The command:
.LP
.nf
- ldapsearch -u -t "uid=mcs" jpegPhoto audio
+ ldapsearch -u -t "uid=xyz" jpegPhoto audio
.fi
.LP
will perform a subtree search using the default search base for entries
-with user id of "mcs". The user friendly form of the entry's DN will be
+with user id of "xyz". The user friendly form of the entry's DN will be
output after the line that contains the DN itself, and the jpegPhoto
and audio values will be retrieved and written to temporary files. The
output might look like this if one entry with one value for each of the
requested attributes is found:
.LP
.nf
-cn=Mark C Smith, ou=Information Technology Division, ou=Faculty and Staff, ou=People, o=University of Michigan, c=US
-Mark C Smith, Information Technology Division, Faculty and Staff, People, University of Michigan, US
+uid=xyz, ou=Staff, ou=People, dc=OpenLDAP, dc=org
+xyz, Staff, People, OpenLDAP, org
audio=/tmp/ldapsearch-audio-a19924
jpegPhoto=/tmp/ldapsearch-jpegPhoto-a19924
.fi
This command:
.LP
.nf
- ldapsearch -L -s one -b "c=US" "o=university*" o description
+ ldapsearch -L -s one -b "c=US" "o=University*" o description
.fi
.LP
-will perform a one-level search at the c=US level for all organizations
-whose organizationName begins with \fBuniversity\fP. Search results
-will be displayed in the LDIF format.
+will perform a one-level search at the c=US level for all entries
+whose organizationName (o) begins begins with \fBUniversity\fP.
+Search results will be displayed in the LDIF format.
The organizationName and description attribute values will be retrieved
and printed to standard output, resulting in output similar to this:
.LP
.BR ldapdelete (1),
.BR ldapmodify (1),
.BR ldapmodrdn (1),
+.BR ldap.conf (5),
.BR ldap (3),
.BR ldap_search (3)
.LP
.SM RFC
1558,
University of Michigan, December 1993.
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
-.TH LDAPTEMPLATES.CONF 5 "13 December 1994" "U-M LDAP LDVERSION"
+.TH LDAPTEMPLATES.CONF 5 "22 September 1998" "OpenLDAP LDVERSION"
.SH NAME
ldaptemplates.conf \- configuration file for LDAP display template routines
.SH SYNOPSIS
It should be a string-represented Distringuished Name. E.g.,
.nf
.ft B
- "o=University of Michigan, c=US"
+ "dc=OpenLDAP, dc=org"
.ft
.fi
.LP
#
# default location when adding new entries (DN; "" means no default)
- "o=University of Michigan, c=US"
+ "dc=OpenLDAP, dc=Org"
#
# rules used to define default values for new entries
.SH SEE ALSO
.BR ldap (3),
.BR ldap_disptmpl (3)
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
-.TH LDIF 5 "13 November 1995" "U-M LDAP LDVERSION"
+.TH LDIF 5 "22 September 1998" "OpenLDAP LDVERSION"
.SH NAME
ldif \- LDAP Data Interchange Format
.SH DESCRIPTION
The LDAP Data Interchange Format (LDIF) is used to represent LDAP
-entries in text form. The
-.BR ldif2ldbm (8)
-tools can be used to convert from LDIF format to the LDBM format
-used by
-.BR slapd (8).
-The
-.BR ldbmcat (8)
-tool can be used to do the reverse conversion. See "The SLAPD and
-SLURPD Administrator's Guide" for more information on this format and
-the conversion tools.
+entries in text form. LDAP tools, such as
+.BR ldapadd (1)
+and
+.BR ldapsearch (1),
+read and write LDIF.
.LP
The basic form of an LDIF entry is:
.LP
.nf
.ft tt
- [<id>]
dn: <distinguished name>
<attrtype>: <attrvalue>
<attrtype>: <attrvalue>
+ <attrtype>:: <base64-encoded-value>
+ <attrtype>:< <URL>
...
.ft
.fi
.LP
-where <id> is the optional entry ID (a positive decimal number).
-Normally, you would not supply the <id>, allowing the database creation
-tools to do that for you. The
-.BR ldbmcat (8)
-program, however, produces an LDIF format that includes <id> so that
-new indexes created will be consistent with the existing database. A
-line may be continued by starting the next line with a single space or
-tab character, e.g.,
+The value may be specified as ASCII text or as base64 encoded data,
+or a URL may be provided to the location of the attribute value.
+.LP
+A line may be continued by starting the next line with a single space
+or tab, e.g.,
.LP
.nf
.ft tt
- dn: cn=Barbara J Jensen, o=University of Michi
- gan, c=US
+ dn: cn=Barbara J Jensen, dc=Open
+ LDAP, dc=org
.ft
.fi
.LP
.ft
.fi
.LP
-If an <attrvalue> contains a non-printing character, or begins with a
-space or a colon ':', the <attrtype> is followed by a double colon and
-the value is encoded in base 64 notation. e.g., the value " begins with
-a space" would be encoded like this:
+If an value contains a non-printing character, or begins
+with a space or a colon ':', the <attrtype> is followed by a
+double colon and the value is encoded in base 64 notation. e.g.,
+the value " begins with a space" would be encoded like this:
.LP
.nf
.ft tt
.ft
.fi
.LP
+If the attribute value is located in a file, the <attrtype> is
+followed by a ':<' and a file:// URL. e.g., the value contained
+in the file /tmp/value would be listed like this:
+.LP
+.nf
+.ft tt
+ cn:< file://tmp/value
+.ft
+.fi
+.LP
Multiple entries within the same LDIF file are separated by blank
lines.
.SH EXAMPLE
.LP
.nf
.ft tt
- dn: cn=Barbara J Jensen, o=University of Michi
- gan, c=US
+ dn: cn=Barbara J Jensen, dc=OpenLDAP, dc=Org
cn: Barbara J Jensen
cn: Babs Jensen
objectclass: person
+ description:< file://tmp/barbara
sn: Jensen
- dn: cn=Bjorn J Jensen, o=University of Michi
- gan, c=US
+ dn: cn=Bjorn J Jensen, dc=OpenLDAP, dc=Org
cn: Bjorn J Jensen
cn: Bjorn Jensen
objectclass: person
sn: Jensen
- dn: cn=Jennifer J Jensen, o=University of Michi
- gan, c=US
+ dn: cn=Jennifer J Jensen, dc=OpenLDAP, dc=Org
cn: Jennifer J Jensen
cn: Jennifer Jensen
objectclass: person
base 64.
.SH SEE ALSO
.BR ldap (3),
-.BR slapd (8),
-.BR ldif2ldbm (8),
-.BR ldbmcat (8)
+.BR ldapsearch (1),
+.BR ldapadd (1)
.LP
"The SLAPD and SLURPD Administrator's Guide"
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
-.TH SLAPD.CONF 5 "13 November 1995" "U-M LDAP LDVERSION"
+.TH SLAPD.CONF 5 "5 August 1999" "OpenLDAP LDVERSION"
.SH NAME
slapd.conf \- configuration file for slapd, the stand-alone LDAP daemon
.SH SYNOPSIS
.BR slapd (8)
daemon. This configuration file is also used by the
.BR slurpd (8)
-replication daemon and by the LDBM indexing utilities
-.BR ldif2ldbm (8),
-.BR ldif2index (8),
-.BR ldif2id2entry (8),
+replication daemon and by the SLAPD tools
+.BR slapadd (8),
+.BR slapcat (8),
and
-.BR ldif2id2children (8).
+.BR slapindex (8).
.LP
The
.B slapd.conf
.RE
.TP
.B
-defaultaccess { none | compare | search | read | write | delete }
+defaultaccess [self]{ none | compare | search | read | write }
Specify the default access to grant requestors not matched by
any other access line. The default behavior is to grant read access.
.TP
+.B idletimeout <integer>
+Specify the number of seconds to wait before forcibly closing
+an idle client connections. A idletimeout of 0 disables this
+feature. The default is 0.
+.TP
.B include <filename>
Read additional configuration information from the given file before
continuing with the next line of the current file.
.TP
+.B pidfile <filename>
+The ( absolute ) name of a file that will hold the
+.B slapd
+server's process ID ( see
+.BR getpid (2)
+) if started without the debugging command line option.
+.TP
+.B argsfile <filename>
+The ( absolute ) name of a file that will hold the
+.B slapd
+server's command line options
+if started without the debugging command line option.
+.TP
+.B
+locale { <locale-name> | on | off }
+Obey <locale-name>'s character classification and case conversion; i.e. the
+.BR locale (5)
+LC_CTYPE category. See
+.BR locale (5)
+for details about locales. "on" takes the locale from the environment,
+typically $LANG or $LC_CTYPE, and will only work properly if slapd will
+run with the same environment variables as when the database was
+generated. "off" (the default setting) resets to the initial "C" locale.
+.TP
.B loglevel <integer>
Specify the level at which debugging statements and operation
statistics should be syslogged (currently logged to the
Specify the referral to pass back when
.BR slapd (8)
cannot find a local database to handle a request.
+If specified multiple times, each url is provided.
.TP
.B schemacheck { on | off }
-Turn schema checking on or off. The default is off.
+Turn schema checking on or off. The default is on.
.TP
.B sizelimit <integer>
Specify the maximum number of entries to return from a search operation.
Specify the maximum number of seconds (in real time)
.B slapd
will spend answering a search request. The default time limit is 3600.
+.SH TLS OPTIONS
+If
+.B slapd
+is build with support for Transport Layer Security, there are more options
+you can specify.
+.TP
+.B TLSCipherSuite <cipher-suite-spec>
+Permits configuring what ciphers will be accepted and the preference order.
+<cipher-suite-spec> should be a cipher specification for OpenSSL. Example:
+
+TLSCipherSuite HIGH:MEDIUM:+SSLv2
+
+To check what ciphers a given spec selects, use:
+
+openssl ciphers -v <cipher-suite-spec>
+.TP
+.B TLSCertificateFile <filename>
+Specifies the file that contains the
+.B slapd
+server certificate.
+.TP
+.B TLSCertificateKeyFile <filename>
+Specifies the file that contains the
+.B slapd
+server private key that matches the certificate stored in the
+.B TLSCertificateFile
+file. Currently, the private key must not be protected with a password, so
+it is of critical importance that it is protected carefully.
.SH GENERAL BACKEND OPTIONS
Options in this section only apply to the configuration file section
for the backend in which they are defined. They are supported by every
.B slapd
will automatically maintain the
modifiersName, modifyTimestamp, creatorsName, and
-createTimestamp attributes for entries. By default, lastmod is off.
+createTimestamp attributes for entries. By default, lastmod is on.
.TP
.B readonly on | off
This option puts the database into "read-only" mode. Any attempts to
or administrative limit restrictions for operations on this database.
.TP
.B rootpw <password>
-Specify a password for the rootdn.
+Specify a password (or hash of the password) for the rootdn.
+This option accepts all password formats known to the server
+including \fB{SHA}\fP, \fB{MD5}\fP, \fB{CRYPT}\fP, and cleartext.
+Cleartext passwords are not recommended.
.TP
.B suffix <dn suffix>
Specify the DN suffix of queries that will be passed to this
this is the DN
.BR slurpd (8)
binds as when making changes to the replica).
+.TP
+.B updateref <url>
+Specify the referral to pass back when
+.BR slapd (8)
+is asked to modify a replicated local database.
+If specified multiple times, each url is provided.
.SH LDBM BACKEND-SPECIFIC OPTIONS
Options in this category only apply to the LDBM backend database. That is,
they must follow a "database ldbm" line and come before any subsequent
with each open index file. If not supported by the underlying database
method, this option is ignored without comment. The default is 100000 bytes.
.TP
+.B dbcachenowsync
+Specify that database writes should not be immediately synchronized
+with in memory changes. Enabling this option may improve performance
+at the expense of data security.
+.TP
.B directory <directory>
Specify the directory where the LDBM files containing the database and
associated indexes live. The default is
.SH SEE ALSO
.BR ldap (3),
.BR slapd.replog (5),
+.BR locale (5),
.BR passwd (5),
.BR slapd (8),
+.BR slapadd (8),
+.BR slapcat (8),
+.BR slapindex (8),
.BR slurpd (8),
.LP
"The SLAPD and SLURPD Administrator's Guide"
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
-.TH EDB2LDIF 8C "12 November 1995" "U-M LDAP LDVERSION"
+.TH EDB2LDIF 8C "22 September 1998" "OpenLDAP LDVERSION"
.SH NAME
edb2ldif \- QUIPU EDB file to LDIF conversion tool
.SH SYNOPSIS
-.B ETCDIR/edb2ldif
+.B SBINDIR/edb2ldif
.B [\-d] [\-v] [\-r] [\-o] [\-b basedn]
.B [\-a addvalsfile] [\-f fileattrdir]
.B [\-i ignoreattr...] [edbfile...]
LDAP Directory Interchange Format (LDIF) used by
.BR slapd (8)
and associated utilities. The
-.BR ldif2ldbm (8)
+.BR slapadd (8)
program can be used to convert the resulting LDIF data into a database
that is compatible with
.BR slapd (8).
.BR ldap (3),
.BR ldif (5),
.BR slapd (8),
-.BR ldif2ldbm (8)
+.BR slapadd (8)
.LP
"The SLAPD and SLURPD Administrator's Guide"
.LP
Volume 5 of The ISODE Manual
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
+++ /dev/null
-.TH LDBMCAT 8C "13 November 1995" "U-M LDAP LDVERSION"
-.SH NAME
-ldbmcat \- LDBM to LDIF database format conversion utility
-.SH SYNOPSIS
-.B ETCDIR/ldbmcat [\-n] id2entry\-file
-.LP
-.SH DESCRIPTION
-.LP
-This program is used to convert a
-.BR slapd (8)
-LDBM database to the text LDAP Directory Interchange Format (LDIF).
-It opens the given
-.I id2entry\-file
-and writes the corresponding LDIF output to standard output.
-.LP
-See "The SLAPD and SLURPD Administrator's Guide" for more details on
-using this program.
-.SH OPTIONS
-.TP
-.B \-n
-This option specifies that
-.B ldbmcat
-should not print entry IDs when it dumps out the database. Note
-that the printing of entry IDs is essential if you are going to
-use the LDIF format produced as input to
-.B ldif2index,
-for example, to create a new index file for use with an existing
-database.
-.SH EXAMPLES
-To make a text backup of your LDBM database and put it in a file called
-.BR ldif ,
-give the command:
-.LP
-.nf
-.ft tt
- ETCDIR/ldbmcat -n id2entry.dbb > ldif
-.ft
-.fi
-.LP
-To create a new index for the
-.B mail
-attribute, give these commands:
-.LP
-.nf
-.ft tt
- ETCDIR/ldbmcat id2entry.dbb > ldif
- ETCDIR/ldif2index -i ldif -f slapd-config-file mail
-.ft
-.fi
-.LP
-Note that your
-.B slapd (8)
-should not be running (at least, not in read-write
-mode) when you do this to ensure consistency of the database.
-.SH "SEE ALSO"
-.BR ldap (3),
-.BR ldif (5),
-.BR ldif2ldbm (8),
-.BR slapd (8)
-.LP
-"The SLAPD and SLURPD Administrator's Guide"
-.TH LDIF 8C "15 November 1995" "U-M LDAP LDVERSION"
+.TH LDIF 8C "22 September 1998" "OpenLDAP LDVERSION"
.SH NAME
ldif \- convert arbitrary data to LDIF format
.SH SYNOPSIS
-.B ETCDIR/ldif [\-b] attr\-name
+.B SBINDIR/ldif [\-b] attr\-name
.LP
.SH DESCRIPTION
.LP
.SH "SEE ALSO"
.BR ldap (3),
.BR ldif (5),
-.BR ldif2ldbm (8),
+.BR slapadd (8),
.BR slapd (8)
.LP
"The SLAPD and SLURPD Administrator's Guide"
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
+++ /dev/null
-.TH LDIF2LDBM 8C "13 November 1995" "U-M LDAP LDVERSION"
-.SH NAME
-ldif2ldbm, ldif2index, ldif2id2entry, ldif2id2children \- LDIF to LDBM database format conversion utilities
-.SH SYNOPSIS
-.B ETCDIR/ldif2ldbm
-.B \-i ldif\-input\-file
-.B [\-d debug\-level] [\-f slapd\-config\-file]
-.B [\-j number\-of\-jobs]
-.LP
-.B ETCDIR/ldif2index
-.B \-i ldif\-input\-file
-.B [\-d debug\-level] [\-f slapd\-config\-file]
-.B attribute\-name
-.LP
-.B ETCDIR/ldif2id2entry
-.B \-i ldif\-input\-file
-.B [\-d debug\-level] [\-f slapd\-config\-file]
-.LP
-.B ETCDIR/ldif2id2children
-.B \-i ldif\-input\-file
-.B [\-d debug\-level] [\-f slapd\-config\-file]
-.LP
-.SH DESCRIPTION
-.LP
-These programs are used to convert a database in text LDIF LDAP
-Directory Interchange Format (LDIF) to an LDBM database suitable
-for use by
-.BR slapd (8).
-Normally, only
-.B ldif2ldbm
-is invoked by you. It will invoke the other programs as necessary.
-Occasionally, it may be necessary to invoke them by hand. For
-example, to create a new index file for an existing database, the
-.B ldif2index
-program can be invoked. The
-.BR ldbmcat (8)
-program is used to do the reverse conversion.
-.LP
-See "The SLAPD and SLURPD Administrator's Guide" for more details on
-using these programs.
-.SH OPTIONS
-The first three options apply to all four programs. The -j option is
-only for the
-.B ldif2ldbm
-program.
-.TP
-.BI \-i " ldif\-input\-file"
-This option specifies the location of the LDIF input file containing
-the database to convert. It is required.
-.TP
-.BI \-d " debug\-level"
-Turn on debugging as defined by
-.B debug\-level.
-Some general operation and status messages are printed for any value of
-\fIdebug\-level\fP. \fIdebug\-level\fP is taken as a bit string, with
-each bit corresponding to a different kind of debugging information.
-See <ldap.h> for details.
-.TP
-.BI \-f " slapd\-config\-file"
-This option
-Specifies the
-.B slapd
-configuration file. The default is
-.BR ETCDIR/slapd.conf .
-.TP
-.BI \-j " number\-of\-jobs"
-This option only applies to the
-.B ldif2ldbm
-program. It specifies the level of parallelism to use when doing the
-conversion.
-.B ldif2ldbm
-invokes several other programs during the conversion process,
-most notably one invocation of
-.B ldif2index
-for each indexed attribute that appears in the LDIF input file. The -j
-option tells
-.B ldif2ldbm
-how many of these other programs it should run in parallel. This can
-speed up the conversion, but beware of starting too many processes
-in parallel, all competing for disk, memory, and cpu resources. The
-default is one.
-.SH EXAMPLES
-To convert the file
-.BR ldif.input
-into an LDBM database with indexes as described in the
-.I slapd
-config file
-.BR /usr/local/etc/slapd.conf ,
-give the command:
-.LP
-.nf
-.ft tt
- ETCDIR/ldif2index -i ldif.input -f /usr/local/etc/slapd.conf
-.ft
-.fi
-.LP
-To do the same, but running two conversion sub-processes at a time,
-give this command:
-.LP
-.nf
-.ft tt
- ETCDIR/ldif2index -i ldif.input -f /usr/local/etc/slapd.conf -j 2
-.ft
-.fi
-.LP
-.SH "SEE ALSO"
-.BR ldap (3),
-.BR ldif (5),
-.BR slapd.conf (5),
-.BR ldbmcat (8),
-.BR edb2ldif (8)
-.LP
-"The SLAPD and SLURPD Administrator's Guide"
+++ /dev/null
-ldif2index.8
-ldif2id2entry.8
-ldif2id2children.8
--- /dev/null
+.TH SLAPADD 8C "17 August 1999" "OpenLDAP LDVERSION"
+.SH NAME
+slapadd \- Add entries to a SLAPD database
+.SH SYNOPSIS
+.B SBINDIR/slapadd
+.B [\-v]
+.B [\-c]
+.B [\-s]
+.B [\-d level]
+.B [\-b suffix]
+.B [\-n dbnum]
+.B [\-f slapd.conf]
+.B [\-l ldif-file]
+.B
+.LP
+.SH DESCRIPTION
+.LP
+.B Slapadd
+is used to add entries specified in LDAP Directory Interchange Format
+(LDIF) to a
+.BR slapd (8)
+database.
+It opens the given database determined by the database number or
+suffix and adds entries corresponding to the provided LDIF to
+the database. The LDIF input is read from standard input or
+the specified file.
+.LP
+The LDIF generated by this tool is suitable for use with
+.BR slapcat (8).
+.SH OPTIONS
+.TP
+.B \-v
+enable verbose mode.
+.TP
+.B \-c
+enable continue (ignore errors) mode.
+.TP
+.B \-s
+disable schema and other checks.
+.TP
+.BI \-d " level"
+enable debugging messages as defined by the specified
+.IR level .
+.TP
+.BI \-b " suffix"
+Use the specified \fIsuffix\fR to determine which database to
+add entries to. The \-b cannot be used in conjunction
+with the
+.B \-n
+option.
+.TP
+.BI \-n " dbnum"
+Add entries to the \fIdbnum\fR\-th database listed in the
+configuration file. The
+.B \-n
+cannot be used in conjunction with the
+.B \-b
+option.
+.TP
+.BI \-f " slapd.conf"
+specify an alternative
+.BR slapd.conf (5)
+file.
+.TP
+.BI \-l " ldif-file"
+Read LDIF from the specified file instead of standard input.
+.SH LIMITATIONS
+Your
+.BR slapd (8)
+should not be running
+when you do this to ensure consistency of the database.
+.LP
+.B slapadd
+may not provide naming or schema checks. It is advisable to
+use
+.BR ldapadd (1)
+when adding new entries into an existing directory.
+.SH EXAMPLES
+To import a entries specified in file
+.B ldif
+into your
+.BR slapd (8)
+database give the command:
+.LP
+.nf
+.ft tt
+ SBINDIR/slapadd -l ldif
+.ft
+.fi
+.SH "SEE ALSO"
+.BR ldap (3),
+.BR ldif (5),
+.BR slapcat (8),
+.BR ldapadd (1),
+.BR slapd (8)
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
--- /dev/null
+.TH SLAPCAT 8C "17 August 1999" "OpenLDAP LDVERSION"
+.SH NAME
+slapcat \- SLAPD database to LDIF utility
+.SH SYNOPSIS
+.B SBINDIR/slapcat
+.B [\-v]
+.B [\-c]
+.B [\-d level]
+.B [\-b suffix]
+.B [\-n dbnum]
+.B [\-f slapd.conf]
+.B [\-l ldif-file]
+.B
+.LP
+.SH DESCRIPTION
+.LP
+.B Slapcat
+is used to generate an LDAP Directory Interchange Format
+(LDIF) output based upon the contents of a
+.BR slapd (8)
+database.
+It opens the given database determined by the database number or
+suffix and and writes the corresponding LDIF to standard output or
+the specified file.
+.LP
+The LDIF generated by this tool is suitable for use with
+.BR ldapadd (1)
+or
+.BR slapadd (8).
+.SH OPTIONS
+.TP
+.B \-v
+enable verbose mode.
+.TP
+.B \-c
+enable continue (ignore errors) mode.
+.TP
+.BI \-d " level"
+enable debugging messages as defined by the specified
+.IR level .
+.TP
+.BI \-b " suffix"
+Use the specified \fIsuffix\fR to determine which database to
+generate output for. The \-b cannot be used in conjunction
+with the
+.B \-n
+option.
+.TP
+.BI \-n " dbnum"
+Generate output for the \fIdbnum\fR\-th database listed in the
+configuration file. The
+.B \-n
+cannot be used in conjunction with the
+.B \-b
+option.
+.TP
+.BI \-f " slapd.conf"
+specify an alternative
+.BR slapd.conf (5)
+file.
+.TP
+.BI \-l " ldif-file"
+Write LDIF to specified file instead of standard output.
+.SH Limitations
+Your
+.BR slapd (8)
+should not be running (at least, not in read-write
+mode) when you do this to ensure consistency of the database.
+.SH EXAMPLES
+To make a text backup of your SLAPD database and put it in a file called
+.BR ldif ,
+give the command:
+.LP
+.nf
+.ft tt
+ SBINDIR/slapcat -l ldif
+.ft
+.fi
+.SH "SEE ALSO"
+.BR ldap (3),
+.BR ldif (5),
+.BR slapadd (8),
+.BR ldapadd (1),
+.BR slapd (8)
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
--- /dev/null
+
+
+
+
+
+
+Network Working Group T. Howes
+Request for Comments: 1488 University of Michigan
+ S. Kille
+ ISODE Consortium
+ W. Yeong
+ Performance Systems International
+ C. Robbins
+ NeXor Ltd.
+ July 1993
+
+
+ The X.500 String Representation of Standard Attribute Syntaxes
+
+Status of this Memo
+
+ This RFC specifies an IAB standards track protocol for the Internet
+ community, and requests discussion and suggestions for improvements.
+ Please refer to the current edition of the "IAB Official Protocol
+ Standards" for the standardization state and status of this protocol.
+ Distribution of this memo is unlimited.
+
+Abstract
+
+ The Lightweight Directory Access Protocol (LDAP) [9] requires that
+ the contents of AttributeValue fields in protocol elements be octet
+ strings. This document defines the requirements that must be
+ satisfied by encoding rules used to render Directory attribute
+ syntaxes into a form suitable for use in the LDAP, then goes on to
+ define the encoding rules for the standard set of attribute syntaxes
+ defined in [1,2] and [3].
+
+1. Attribute Syntax Encoding Requirements
+
+ This section defines general requirements for lightweight directory
+ protocol attribute syntax encodings. All documents defining attribute
+ syntax encodings for use by the lightweight directory protocols are
+ expected to conform to these requirements.
+
+ The encoding rules defined for a given attribute syntax must produce
+ octet strings. To the greatest extent possible, encoded octet
+ strings should be usable in their native encoded form for display
+ purposes. In particular, encoding rules for attribute syntaxes
+ defining non-binary values should produce strings that can be
+ displayed with little or no translation by clients implementing the
+ lightweight directory protocols.
+
+
+
+
+
+
+Howes, Kille, Yeong & Robbins [Page 1]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+2. Standard Attribute Syntax Encodings
+
+ For the purposes of defining the encoding rules for the standard
+ attribute syntaxes, the following auxiliary BNF definitions will be
+ used:
+
+ <a> ::= 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' |
+ 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' |
+ 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | 'A' |
+ 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' |
+ 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'
+
+ <d> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
+
+ <hex-digit> ::= <d> | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
+ 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
+
+ <k> ::= <a> | <d> | '-'
+
+ <p> ::= <a> | <d> | ''' | '(' | ')' | '+' | ',' | '-' | '.' |
+ '/' | ':' | '?' | ' '
+
+ <CRLF> ::= The ASCII newline character with hexadecimal value 0x0A
+
+ <letterstring> ::= <a> | <a> <letterstring>
+
+ <numericstring> ::= <d> | <d> <numericstring>
+
+ <keystring> ::= <a> | <a> <anhstring>
+
+ <anhstring> ::= <k> | <k> <anhstring>
+
+ <printablestring> ::= <p> | <p> <printablestring>
+
+ <space> ::= ' ' | ' ' <space>
+
+2.1. Undefined
+
+ Values of type Undefined are encoded as if they were values of type
+ Octet String.
+
+2.2. Case Ignore String
+
+ A string of type caseIgnoreStringSyntax is encoded as the string
+ value itself.
+
+
+
+
+
+Howes, Kille, Yeong & Robbins [Page 2]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+2.3. Case Exact String
+
+ The encoding of a string of type caseExactStringSyntax is the string
+ value itself.
+
+2.4. Printable String
+
+ The encoding of a string of type printableStringSyntax is the string
+ value itself.
+
+2.5. Numeric String
+
+ The encoding of a string of type numericStringSyntax is the string
+ value itself.
+
+2.6. Octet String
+
+ The encoding of a string of type octetStringSyntax is the string
+ value itself.
+
+2.7. Case Ignore IA5 String
+
+ The encoding of a string of type caseIgnoreIA5String is the string
+ value itself.
+
+2.8. IA5 String
+
+ The encoding of a string of type iA5StringSyntax is the string value
+ itself.
+
+2.9. T61 String
+
+ The encoding of a string of type t61StringSyntax is the string value
+ itself.
+
+2.10. Case Ignore List
+
+ Values of type caseIgnoreListSyntax are encoded according to the
+ following BNF:
+
+ <caseignorelist> ::= <caseignorestring> |
+ <caseignorestring> '$' <caseignorelist>
+
+ <caseignorestring> ::= a string encoded according to the rules
+ for Case Ignore String as above.
+
+
+
+
+
+
+Howes, Kille, Yeong & Robbins [Page 3]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+2.11. Case Exact List
+
+ Values of type caseExactListSyntax are encoded according to the
+ following BNF:
+
+ <caseexactlist> ::= <caseexactstring> |
+ <caseexactstring> '$' <caseexactlist>
+
+ <caseexactstring> ::= a string encoded according to the rules for
+ Case Exact String as above.
+
+2.12. Distinguished Name
+
+ Values of type distinguishedNameSyntax are encoded to have the
+ representation defined in [5].
+
+2.13. Boolean
+
+ Values of type booleanSyntax are encoded according to the following
+ BNF:
+
+ <boolean> ::= "TRUE" | "FALSE"
+
+ Boolean values have an encoding of "TRUE" if they are logically true,
+ and have an encoding of "FALSE" otherwise.
+
+2.14. Integer
+
+ Values of type integerSyntax are encoded as the decimal
+ representation of their values, with each decimal digit represented
+ by the its character equivalent. So the digit 1 is represented by the
+ character
+
+2.15. Object Identifier
+
+ Values of type objectIdentifierSyntax are encoded according to the
+ following BNF:
+
+ <oid> ::= <descr> | <descr> '.' <numericoid> | <numericoid>
+
+ <descr> ::= <keystring>
+
+ <numericoid> ::= <numericstring> | <numericstring> '.' <numericoid>
+
+ In the above BNF, <descr> is the syntactic representation of an
+ object descriptor. When encoding values of type
+ objectIdentifierSyntax, the first encoding option should be used in
+ preference to the second, which should be used in preference to the
+
+
+
+Howes, Kille, Yeong & Robbins [Page 4]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+ third wherever possible. That is, in encoding object identifiers,
+ object descriptors (where assigned and known by the implementation)
+ should be used in preference to numeric oids to the greatest extent
+ possible. For example, in encoding the object identifier representing
+ an organizationName, the descriptor "organizationName" is preferable
+ to "ds.4.10", which is in turn preferable to the string "2.5.4.10".
+
+2.16. Telephone Number
+
+ Values of type telephoneNumberSyntax are encoded as if they were
+ Printable String types.
+
+2.17. Telex Number
+
+ Values of type telexNumberSyntax are encoded according to the
+ following BNF:
+
+ <telex-number> ::= <actual-number> '$' <country> '$' <answerback>
+
+ <actual-number> ::= <printablestring>
+
+ <country> ::= <printablestring>
+
+ <answerback> ::= <printablestring>
+
+ In the above, <actual-number> is the syntactic representation of the
+ number portion of the TELEX number being encoded, <country> is the
+ TELEX country code, and <answerback> is the answerback code of a
+ TELEX terminal.
+
+2.18. Teletex Terminal Identifier
+
+ Values of type teletexTerminalIdentifier are encoded according to the
+ following BNF:
+
+ <teletex-id> ::= <printablestring> 0*( '$' <printablestring>)
+
+ In the above, the first <printablestring> is the encoding of the
+ first portion of the teletex terminal identifier to be encoded, and
+ the subsequent 0 or more <printablestrings> are subsequent portions
+ of the teletex terminal identifier.
+
+2.19. Facsimile Telephone Number
+
+ Values of type FacsimileTelephoneNumber are encoded according to the
+ following BNF:
+
+ <fax-number> ::= <printablestring> [ '$' <faxparameters> ]
+
+
+
+Howes, Kille, Yeong & Robbins [Page 5]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+ <faxparameters> ::= <faxparm> | <faxparm> '$' <faxparameters>
+
+ <faxparm> ::= 'twoDimensional' | 'fineResolution' | 'unlimitedLength' |
+ 'b4Length' | 'a3Width' | 'b4Width' | 'uncompressed'
+
+ In the above, the first <printablestring> is the actual fax number,
+ and the <faxparm> tokens represent fax parameters.
+
+2.20. Presentation Address
+
+ Values of type PresentationAddress are encoded to have the
+ representation described in [6].
+
+2.21. UTC Time
+
+ Values of type uTCTimeSyntax are encoded as if they were Printable
+ Strings with the strings containing a UTCTime value.
+
+2.22. Guide (search guide)
+
+ Values of type Guide, such as values of the searchGuide attribute,
+ are encoded according to the following BNF:
+
+ <guide-value> ::= [ <object-class> '#' ] <criteria>
+
+ <object-class> ::= an encoded value of type objectIdentifierSyntax
+
+ <criteria> ::= <criteria-item> | <criteria-set> | '!' <criteria>
+
+ <criteria-set> ::= [ '(' ] <criteria> '&' <criteria-set> [ ')' ] |
+ [ '(' ] <criteria> '|' <criteria-set> [ ')' ]
+
+ <criteria-item> ::= [ '(' ] <attributetype> '$' <match-type> [ ')' ]
+
+ <match-type> ::= "EQ" | "SUBSTR" | "GE" | "LE" | "APPROX"
+
+2.23. Postal Address
+
+Values of type PostalAddress are encoded according to the following BNF:
+
+ <postal-address> ::= <t61string> | <t61string> '$' <postal-address>
+
+ In the above, each <t61string> component of a postal address value is
+ encoded as a value of type t61StringSyntax.
+
+
+
+
+
+
+
+Howes, Kille, Yeong & Robbins [Page 6]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+2.24. User Password
+
+ Values of type userPasswordSyntax are encoded as if they were of type
+ octetStringSyntax.
+
+2.25. User Certificate
+
+ Values of type userCertificate are encoded according to the following
+ BNF:
+
+ <certificate> ::= <signature> '#' <issuer> '#' <validity> '#' <subject>
+ '#' <public-key-info>
+
+ <signature> ::= <algorithm-id>
+
+ <issuer> ::= an encoded Distinguished Name
+
+ <validity> ::= <not-before-time> '#' <not-after-time>
+
+ <not-before-time> ::= <utc-time>
+
+ <not-after-time> ::= <utc-time>
+
+ <algorithm-parameters> ::= <null> | <integervalue> |
+ '{ASN}' <hex-string>
+
+ <subject> ::= an encoded Distinguished Name
+
+ <public-key-info> ::= <algorithm-id> '#' <encrypted-value>
+
+ <encrypted-value> ::= <hex-string> | <hex-string> '-' <d>
+
+ <algorithm-id> ::= <oid> '#' <algorithm-parameters>
+
+ <utc-time> ::= an encoded UTCTime value
+
+ <hex-string> ::= <hex-digit> | <hex-digit> <hex-string>
+
+2.26. CA Certificate
+
+ Values of type cACertificate are encoded as if the values were of
+ type userCertificate.
+
+2.27. Authority Revocation List
+
+ Values of type authorityRevocationList are encoded according to the
+ following BNF:
+
+
+
+
+Howes, Kille, Yeong & Robbins [Page 7]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+ <certificate-list> ::= <signature> '#' <issuer> '#'
+ <utc-time> [ '#' <revoked-certificates> ]
+
+ <revoked-certificates> ::= <algorithm> '#' <encrypted-value>
+ [ '#' 0*(<revoked-certificate>) '#']
+
+ <revoked-certificates> ::= <subject> '#' <algorithm> '#'
+ <serial> '#' <utc-time>
+
+ The syntactic components <algorithm>, <issuer>, <encrypted-value>,
+ <utc-time>, <subject> and <serial> have the same definitions as in
+ the BNF for the userCertificate attribute syntax.
+
+2.28. Certificate Revocation List
+
+ Values of type certificateRevocationList are encoded as if the values
+ were of type authorityRevocationList.
+
+2.29. Cross Certificate Pair
+
+ Values of type crossCertificatePair are encoded according to the
+ following BNF:
+
+ <certificate-pair> ::= <certificate> '|' <certificate>
+
+ The syntactic component <certificate> has the same definition as in
+ the BNF for the userCertificate attribute syntax.
+
+2.30. Delivery Method
+
+ Values of type deliveryMethod are encoded according to the following
+ BNF:
+
+ <delivery-value> ::= <pdm> | <pdm> '$' <delivery-value>
+
+ <pdm> ::= 'any' | 'mhs' | 'physical' | 'telex' | 'teletex' |
+ 'g3fax' | 'g4fax' | 'ia5' | 'videotex' | 'telephone'
+
+2.31. Other Mailbox
+
+ Values of the type otherMailboxSyntax are encoded according to the
+ following BNF:
+
+ <otherMailbox> ::= <mailbox-type> '$' <mailbox>
+
+ <mailbox-type> ::= an encoded Printable String
+
+ <mailbox> ::= an encoded IA5 String
+
+
+
+Howes, Kille, Yeong & Robbins [Page 8]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+ In the above, <mailbox-type> represents the type of mail system in
+ which the mailbox resides, for example "Internet" or "MCIMail"; and
+ <mailbox> is the actual mailbox in the mail system defined by
+ <mailbox-type>.
+
+2.32. Mail Preference
+
+ Values of type mailPreferenceOption are encoded according to the
+ following BNF:
+
+ <mail-preference> ::= "NO-LISTS" | "ANY-LIST" | "PROFESSIONAL-LISTS"
+
+2.33. MHS OR Address
+
+ Values of type MHS OR Address are encoded as strings, according to
+ the format defined in [10].
+
+2.34. Photo
+
+ Values of type Photo are encoded as if they were octet strings
+ containing JPEG images in the JPEG File Interchange Format (JFIF), as
+ described in [8].
+
+2.35. Fax
+
+ Values of type Fax are encoded as if they were octet strings
+ containing Group 3 Fax images as defined in [7].
+
+3. Acknowledgements
+
+ Many of the attribute syntax encodings defined in this document are
+ adapted from those used in the QUIPU X.500 implementation. The
+ contribu- tions of the authors of the QUIPU implementation in the
+ specification of the QUIPU syntaxes [4] are gratefully acknowledged.
+
+4. Bibliography
+
+ [1] The Directory: Selected Attribute Syntaxes. CCITT,
+ Recommendation X.520.
+
+ [2] Information Processing Systems -- Open Systems Interconnection --
+ The Directory: Selected Attribute Syntaxes.
+
+ [3] Barker, P., and S. Kille, "The COSINE and Internet X.500 Schema",
+ RFC 1274, University College London, November 1991.
+
+ [4] The ISO Development Environment: User's Manual -- Volume 5:
+ QUIPU. Colin Robbins, Stephen E. Kille.
+
+
+
+Howes, Kille, Yeong & Robbins [Page 9]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+ [5] Kille, S., "A String Representation of Distinguished Names", RFC
+ 1485, July 1993.
+
+ [6] Kille, S., "A String Representation for Presentation Addresses",
+ RFC 1278, University College London, November 1991.
+
+ [7] Terminal Equipment and Protocols for Telematic Services -
+ Standardization of Group 3 facsimile apparatus for document
+ transmission. CCITT, Recommendation T.4.
+
+ [8] JPEG File Interchange Format (Version 1.02). Eric Hamilton, C-
+ Cube Microsystems, Milpitas, CA, September 1, 1992.
+
+ [9] Yeong, W., Howes, T., and S. Kille, "Lightweight Directory Access
+ Protocol", RFC 1487, Performance Systems International,
+ University of Michigan, ISODE Consortium, July 1993.
+
+ [10] Kille, S., "Mapping between X.400(1988)/ISO 10021 and RFC 822",
+ RFC 1327, University College London, May 1992.
+
+5. Security Considerations
+
+ Security issues are not discussed in this memo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Howes, Kille, Yeong & Robbins [Page 10]
+\f
+RFC 1488 X.500 Syntax Encoding July 1993
+
+
+6. Authors' Addresses
+
+ Tim Howes
+ University of Michigan
+ ITD Research Systems
+ 535 W William St.
+ Ann Arbor, MI 48103-4943
+ USA
+
+ Phone: +1 313 747-4454
+ EMail: tim@umich.edu
+
+
+ Steve Kille
+ ISODE Consortium
+ PO Box 505
+ London
+ SW11 1DX
+ UK
+
+ Phone: +44-71-223-4062
+ EMail: S.Kille@isode.com
+
+
+ Wengyik Yeong
+ PSI, Inc.
+ 510 Huntmar Park Drive
+ Herndon, VA 22070
+ USA
+
+ Phone: +1 703-450-8001
+ EMail: yeongw@psilink.com
+
+
+ Colin Robbins
+ NeXor Ltd
+ University Park
+ Nottingham
+ NG7 2RD
+ UK
+
+
+
+
+
+
+
+
+
+
+
+Howes, Kille, Yeong & Robbins [Page 11]
+\f
\ No newline at end of file
--- /dev/null
+
+
+
+
+
+
+Network Working Group M. Smith
+Request for Comments: 2079 Netscape Communications
+Category: Standards Track January 1997
+
+
+ Definition of an X.500 Attribute Type and an Object Class to Hold
+ Uniform Resource Identifiers (URIs)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Abstract
+
+ Uniform Resource Locators (URLs) are being widely used to specify the
+ location of Internet resources. There is an urgent need to be able
+ to include URLs in directories that conform to the LDAP and X.500
+ information models, and a desire to include other types of Uniform
+ Resource Identifiers (URIs) as they are defined. A number of
+ independent groups are already experimenting with the inclusion of
+ URLs in LDAP and X.500 directories. This document builds on the
+ experimentation to date and defines a new attribute type and an
+ auxiliary object class to allow URIs, including URLs, to be stored in
+ directory entries in a standard way.
+
+Background and Intended Usage
+
+ Uniform Resource Locators (URLs) as defined by [1] are the first of
+ several types of Uniform Resource Identifiers (URIs) being defined by
+ the IETF. URIs are widely used on the Internet, most notably within
+ Hypertext Markup Language [2] documents. This document defines an
+ X.500 [3,4] attribute type called labeledURI and an auxiliary object
+ class called labeledURIObject to hold all types of URIs, including
+ URLs. These definitions are designed for use in LDAP and X.500
+ directories, and may be used in other contexts as well.
+
+
+
+
+
+
+
+
+
+
+
+
+Smith Standards Track [Page 1]
+\f
+RFC 2079 URI Attribute Type and Object Class January 1997
+
+
+Schema Definition of the labeledURI Attribute Type
+
+ Name: labeledURI
+ ShortName: None
+ Description: Uniform Resource Identifier with optional label
+ OID: umichAttributeType.57 (1.3.6.1.4.1.250.1.57)
+ Syntax: caseExactString
+ SizeRestriction: None
+ SingleValued: False
+
+Discussion of the labeledURI Attribute Type
+
+ The labeledURI attribute type has the caseExactString syntax (since
+ URIs are case-sensitive) and it is multivalued. Values placed in the
+ attribute should consist of a URI (at the present time, a URL)
+ optionally followed by one or more space characters and a label.
+ Since space characters are not allowed to appear un-encoded in URIs,
+ there is no ambiguity about where the label begins. At the present
+ time, the URI portion must comply with the URL specification [1].
+ Multiple labeledURI values will generally indicate different
+ resources that are all related to the X.500 object, but may indicate
+ different locations for the same resource.
+
+ The label is used to describe the resource to which the URI points,
+ and is intended as a friendly name fit for human consumption. This
+ document does not propose any specific syntax for the label part. In
+ some cases it may be helpful to include in the label some indication
+ of the kind and/or size of the resource referenced by the URI.
+
+ Note that the label may include any characters allowed by the
+ caseExactString syntax, but that the use of non-IA5 (non-ASCII)
+ characters is discouraged as not all directory clients may handle
+ them in the same manner. If non-IA5 characters are included, they
+ should be represented using the X.500 conventions, not the HTML
+ conventions (e.g., the character that is an "a" with a ring above it
+ should be encoded using the T.61 sequence 0xCA followed by an "a"
+ character; do not use the HTML escape sequence "å").
+
+Examples of labeledURI Attribute Values
+
+ An example of a labeledURI attribute value that does not include a
+ label:
+
+ ftp://ds.internic.net/rfc/rfc822.txt
+
+
+
+
+
+
+
+Smith Standards Track [Page 2]
+\f
+RFC 2079 URI Attribute Type and Object Class January 1997
+
+
+ An example of a labeledURI attribute value that contains a tilde
+ character in the URL (special characters in a URL must be encoded as
+ specified by the URL document [1]). The label is "LDAP Home Page":
+
+ http://www.umich.edu/%7Ersug/ldap/ LDAP Home Page
+
+ Another example. This one includes a hint in the label to help the
+ user realize that the URL points to a photo image.
+
+ http://champagne.inria.fr/Unites/rennes.gif Rennes [photo]
+
+Schema Definition of the labeledURIObject Object Class
+
+ Name: labeledURIObject
+ Description: object that contains the URI attribute type
+ OID: umichObjectClass.15 (1.3.6.1.4.1.250.3.15)
+ SubclassOf: top
+ MustContain:
+ MayContain: labeledURI
+
+Discussion of the labeledURIObject Object Class
+
+ The labeledURIObject class is a subclass of top and may contain the
+ labeledURI attribute. The intent is that this object class can be
+ added to existing directory objects to allow for inclusion of URI
+ values. This approach does not preclude including the labeledURI
+ attribute type directly in other object classes as appropriate.
+
+Security Considerations
+
+ Security considerations are not discussed in this memo, except to
+ note that blindly inserting the label portion of a labeledURI
+ attribute value into an HTML document is not recommended, as this may
+ allow a malicious individual to include HTML tags in the label that
+ mislead viewers of the entire document in which the labeledURI value
+ was inserted.
+
+Acknowledgments
+
+ Paul-Andre Pays, Martijn Koster, Tim Howes, Rakesh Patel, Russ
+ Wright, and Hallvard Furuseth provided invaluable assistance in the
+ creation of this document.
+
+ This material is based in part upon work supported by the National
+ Science Foundation under Grant No. NCR-9416667.
+
+
+
+
+
+
+Smith Standards Track [Page 3]
+\f
+RFC 2079 URI Attribute Type and Object Class January 1997
+
+
+Appendix: The labeledURL Attribute Type (Deprecated)
+
+ An earlier draft of this document defined an additional attribute
+ type called labeledURL. This attribute type is deprecated, and
+ should not be used when adding new values to directory entries. The
+ original motivation for including a separate attribute type to hold
+ URLs was that this would better enable efficient progammatic access
+ to specific types of URIs. After some deliberation, the IETF-ASID
+ working group concluded that it was better to simply have one
+ attribute than two.
+
+ The schema definition for labeledURL is included here for historical
+ reference only. Directory client software may want to support this
+ schema definition (in addition to labeledURI) to ease the transition
+ away from labeledURL for those sites that are using it.
+
+ Name: labeledURL
+ ShortName: None
+ Description: Uniform Resource Locator with optional label
+ OID: umichAttributeType.41 (1.3.6.1.4.1.250.1.41)
+ Syntax: caseExactString
+ SizeRestriction: None
+ SingleValued: False
+ OID: umichAttributeType.41 (1.3.6.1.4.1.250.1.41)
+
+References
+
+ [1] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform
+ Resource Locators (URL)", RFC 1738, CERN, Xerox Corporation,
+ University of Minnesota, December 1994.
+ <URL:ftp://ds.internic.net/rfc/rfc1738.txt>
+
+ [2] Berners-Lee, T., and D. Connolly, "Hypertext Markup Language -
+ 2.0", RFC 1866, <URL:ftp://ds.internic.net/rfc/rfc1866.txt>
+
+ [3] The Directory: Overview of Concepts, Models and Service. CCITT
+ Recommendation X.500, 1988.
+
+ [4] Information Processing Systems -- Open Systems Interconnection --
+ The Directory: Overview of Concepts, Models and Service. ISO/IEC JTC
+ 1/SC21; International Standard 9594-1, 1988.
+
+
+
+
+
+
+
+
+
+
+Smith Standards Track [Page 4]
+\f
+RFC 2079 URI Attribute Type and Object Class January 1997
+
+
+Author's Address
+
+ Mark Smith
+ Netscape Communications Corp.
+ 501 E. Middlefield Rd.
+ Mountain View, CA 94043, USA
+
+ Phone: +1 415 937-3477
+ EMail: mcs@netscape.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Smith Standards Track [Page 5]
+\f
--- /dev/null
+
+
+
+
+
+
+Network Working Group S. Boeyen
+Request for Comments: 2559 Entrust
+Updates: 1778 T. Howes
+Category: Standards Track Netscape
+ P. Richard
+ Xcert
+ April 1999
+
+
+ Internet X.509 Public Key Infrastructure
+ Operational Protocols - LDAPv2
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+1. Abstract
+
+ The protocol described in this document is designed to satisfy some
+ of the operational requirements within the Internet X.509 Public Key
+ Infrastructure (IPKI). Specifically, this document addresses
+ requirements to provide access to Public Key Infrastructure (PKI)
+ repositories for the purposes of retrieving PKI information and
+ managing that same information. The mechanism described in this
+ document is based on the Lightweight Directory Access Protocol (LDAP)
+ v2, defined in RFC 1777, defining a profile of that protocol for use
+ within the IPKI and updates encodings for certificates and revocation
+ lists from RFC 1778. Additional mechanisms addressing PKIX
+ operational requirements are specified in separate documents.
+
+ The key words 'MUST', 'REQUIRED', 'SHOULD', 'RECOMMENDED', and 'MAY'
+ in this document are to be interpreted as described in RFC 2119.
+
+2. Introduction
+
+ This specification is part of a multi-part standard for development
+ of a Public Key Infrastructure (PKI) for the Internet. This
+ specification addresses requirements to provide retrieval of X.509
+ PKI information, including certificates and CRLs from a repository.
+ This specification also addresses requirements to add, delete and
+
+
+
+Boeyen, et al. Standards Track [Page 1]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+ modify PKI information in a repository. A profile based on the LDAP
+ version 2 protocol is provided to satisfy these requirements.
+
+3. Model
+
+ The PKI components, as defined in PKIX Part 1, which are involved in
+ PKIX operational protocol interactions include:
+
+ - End Entities
+ - Certification Authorities (CA)
+ - Repository
+
+ End entities and CAs using LDAPv2, retrieve PKI information from the
+ repository using a subset of the LDAPv2 protocol.
+
+ CAs populate the repository with PKI information using a subset of
+ the LDAPv2 protocol.
+
+4. Lightweight Directory Access Protocol (LDAP)
+
+ The following sections examine the retrieval of PKI information from
+ a repository and management of PKI information in a repository. A
+ profile of the LDAPv2 protocol is defined for providing these
+ services.
+
+ Section 5 satisfies the requirement to retrieve PKI information (a
+ certificate, CRL, or other information of interest) from an entry in
+ the repository, where the retrieving entity (either an end entity or
+ a CA) has knowledge of the name of the entry. This is termed
+ "repository read".
+
+ Section 6 satisfies the same requirement as 5 for the situation where
+ the name of the entry is not known, but some other related
+ information which may optionally be used as a filter against
+ candidate entries in the repository, is known. This is termed
+ "repository search".
+
+ Section 7 satisfies the requirement of CAs to add, delete and modify
+ PKI information information (a certificate, CRL, or other information
+ of interest)in the repository. This is termed "repository modify".
+
+ The subset of LDAPv2 needed to support each of these functions is
+ described below. Note that the repository search service is a
+ superset of the repository read service in terms of the LDAPv2
+ functionality needed.
+
+ Note that all tags are implicit by default in the ASN.1 definitions
+ that follow.
+
+
+
+Boeyen, et al. Standards Track [Page 2]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+5. LDAP Repository Read
+
+ To retrieve information from an entry corresponding to the subject or
+ issuer name of a certificate, requires a subset of the following
+ three LDAP operations:
+
+ BindRequest (and BindResponse)
+ SearchRequest (and SearchResponse)
+ UnbindRequest
+
+ The subset of each REQUIRED operation is given below.
+
+5.1. Bind
+
+5.1.1. Bind Request
+
+ The full LDAP v2 Bind Request is defined in RFC 1777.
+
+ An application providing a LDAP repository read service MUST
+ implement the following subset of this operation:
+
+ BindRequest ::=
+ [APPLICATION 0] SEQUENCE {
+ version INTEGER (2),
+ name LDAPDN, -- MUST accept NULL LDAPDN
+ simpleauth [0] OCTET STRING -- MUST accept NULL simple
+ }
+
+ An application providing a LDAP repository read service MAY implement
+ other aspects of the BindRequest as well.
+
+ Different services may have different security requirements. Some
+ services may allow anonymous search, others may require
+ authentication. Those services allowing anonymous search may choose
+ only to allow search based on certain criteria and not others.
+
+ A LDAP repository read service SHOULD implement some level of
+ anonymous search access. A LDAP repository read service MAY implement
+ authenticated search access.
+
+5.1.2. Bind Response
+
+ The full LDAPv2 BindResponse is described in RFC 1777.
+
+ An application providing a LDAP repository read service MUST
+ implement this entire protocol element, though only the following
+ error codes may be returned from a Bind operation:
+
+
+
+
+Boeyen, et al. Standards Track [Page 3]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+ success (0),
+ operationsError (1),
+ protocolError (2),
+ authMethodNotSupported (7),
+ noSuchObject (32),
+ invalidDNSyntax (34),
+ inappropriateAuthentication (48),
+ invalidCredentials (49),
+ busy (51),
+ unavailable (52),
+ unwillingToPerform (53),
+ other (80)
+
+5.2. Search
+
+5.2.1. Search Request
+
+ The full LDAPv2 SearchRequest is defined in RFC 1777.
+
+ An application providing a LDAP repository read service MUST
+ implement the following subset of the SearchRequest.
+
+ SearchRequest ::=
+ [APPLICATION 3] SEQUENCE {
+ baseObject LDAPDN,
+ scope ENUMERATED {
+ baseObject (0),
+ },
+ derefAliases ENUMERATED {
+ neverDerefAliases (0),
+ },
+ sizeLimit INTEGER (0),
+ timeLimit INTEGER (0),
+ attrsOnly BOOLEAN, -- FALSE only
+ filter Filter,
+ attributes SEQUENCE OF AttributeType
+ }
+
+ Filter ::=
+ CHOICE {
+ present [7] AttributeType, -- "objectclass" only
+ }
+
+ This subset of the LDAPv2 SearchRequest allows the LDAPv2 "read"
+ operation: a base object search with a filter testing for the
+ existence of the objectClass attribute.
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 4]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+ An application providing a LDAP repository read service MAY implement
+ other aspects of the SearchRequest as well.
+
+5.2.2.
+
+ The full LDAPv2 SearchResponse is defined in RFC 1777.
+
+ An application providing a LDAP repository read service over LDAPv2
+ MUST implement the full SearchResponse.
+
+ Note that in the case of multivalued attributes such as
+ userCertificate a SearchResponse containing this attribute will
+ include all values, assuming the requester has sufficient access
+ permissions. The application/relying party may need to select an
+ appropriate value to be used. Also note that retrieval of a
+ certificate from a named entry does not guarantee that the
+ certificate will include that same Distinguished Name (DN) and in
+ some cases the subject DN in the certificate may be NULL.
+
+5.3. Unbind
+
+ The full LDAPv2 UnbindRequest is defined in RFC 1777.
+
+ An application providing a LDAP repository read service MUST
+ implement the full UnbindRequest.
+
+6. LDAP Repository Search
+
+ To search, using arbitrary criteria, for an entry in a repository
+ containing a certificate, CRL, or other information of interest,
+ requires a subset of the following three LDAP operations:
+
+ BindRequest (and BindResponse)
+ SearchRequest (and SearchResponse)
+ UnbindRequest
+
+ The subset of each operation REQUIRED is given below.
+
+6.1. Bind
+
+ The BindRequest and BindResponse subsets needed are the same as those
+ described in Section 5.1.
+
+ The full LDAP v2 Bind Request is defined in RFC 1777.
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 5]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+6.2. Search
+
+6.2.1. Search Request
+
+ The full LDAPv2 SearchRequest is defined in RFC 1777.
+
+ An application providing a LDAP repository search service MUST
+ implement the following subset of the SearchRequest protocol unit.
+
+ SearchRequest ::=
+ [APPLICATION 3] SEQUENCE {
+ baseObject LDAPDN,
+ scope ENUMERATED {
+ baseObject (0),
+ singleLevel (1),
+ wholeSubtree (2)
+ },
+ derefAliases ENUMERATED {
+ neverDerefAliases (0),
+ },
+ sizeLimit INTEGER (0 .. maxInt),
+ timeLimit INTEGER (0 .. maxInt),
+ attrsOnly BOOLEAN, -- FALSE only
+ filter Filter,
+ attributes SEQUENCE OF AttributeType
+ }
+
+ All aspects of the SearchRequest MUST be supported, except for the
+ following:
+
+ - Only the neverDerefAliases value of derefAliases needs to be
+ supported
+
+ - Only the FALSE value for attrsOnly needs to be supported
+
+ This subset provides a more general search capability. It is a
+ superset of the SearchRequest subset defined in Section 5.2.1. The
+ elements added to this service are:
+
+ - singleLevel and wholeSubtree scope needs to be supported
+
+ - sizeLimit is included
+
+ - timeLimit is included
+
+ - Enhanced filter capability
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 6]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+ An application providing a LDAP repository search service MAY
+ implement other aspects of the SearchRequest as well.
+
+6.2.2. Search Response
+
+ The full LDAPv2 SearchResponse is defined in RFC 1777.
+
+ An application providing a LDAP repository search service over LDAPv2
+ MUST implement the full SearchResponse.
+
+6.3. Unbind
+
+ An application providing a LDAP repository search service MUST
+ implement the full UnbindRequest.
+
+7. LDAP Repository Modify
+
+ To add, delete and modify PKI information in a repository requires a
+ subset of the following LDAP operations:
+
+ BindRequest (and BindResponse)
+ ModifyRequest (and ModifyResponse)
+ AddRequest (and AddResponse)
+ DelRequest (and DelResponse
+ UnbindRequest
+
+ The subset of each operation REQUIRED is given below.
+
+7.1. Bind
+
+ The full LDAP v2 Bind Request is defined in RFC 1777.
+
+ An application providing a LDAP repository modify service MUST
+ implement the following subset of this operation:
+
+ BindRequest ::=
+ [APPLICATION 0] SEQUENCE {
+ version INTEGER (2),
+ name LDAPDN,
+ simpleauth [0] OCTET STRING
+ }
+
+ A LDAP repository modify service MUST implement authenticated access.
+
+ The BindResponse subsets needed are the same as those described in
+ Section 5.1.2.
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 7]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+7.2. Modify
+
+7.2.1. Modify Request
+
+ The full LDAPv2 ModifyRequest is defined in RFC 1777.
+
+ An application providing a LDAP repository modify service MUST
+ implement the following subset of the ModifyRequest protocol unit.
+
+ ModifyRequest ::=
+ [APPLICATION 6] SEQUENCE {
+ object LDAPDN,
+ modification SEQUENCE OF SEQUENCE {
+ operation ENUMERATED {
+ add (0),
+ delete (1)
+ },
+ modification SEQUENCE {
+ type AttributeType,
+ values SET OF
+ AttributeValue
+ }
+ }
+ }
+
+ All aspects of the ModifyRequest MUST be supported, except for the
+ following:
+
+ - Only the add and delete values of operation need to be supported
+
+7.2.2. Modify Response
+
+ The full LDAPv2 ModifyResponse is defined in RFC 1777.
+
+ An application providing a LDAP repository modify service MUST
+ implement the full ModifyResponse.
+
+7.3. Add
+
+7.3.1. Add Request
+
+ The full LDAPv2 AddRequest is defined in RFC 1777.
+
+ An application providing a LDAP repository modify service MUST
+ implement the full AddRequest.
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 8]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+7.3.2. Add Response
+
+ The full LDAPv2 AddResponse is defined in RFC 1777.
+
+ An application providing a LDAP repository modify service MUST
+ implement the full AddResponse.
+
+7.4. Delete
+
+7.4.1. Delete Request
+
+ The full LDAPv2 DelRequest is defined in RFC 1777.
+
+ An application providing a LDAP repository modify service MUST
+ implement the full DelRequest.
+
+7.4.2. Delete Response
+
+ The full LDAPv2 DelResponse is defined in RFC 1777.
+
+ An application providing a LDAP repository modify service MUST
+ implement the full DelResponse.
+
+7.5. Unbind
+
+ An application providing a LDAP repository modify service MUST
+ implement the full UnbindRequest.
+
+8. Non-standard attribute value encodings
+
+ When conveyed in LDAP requests and results, attributes defined in
+ X.500 are to be encoded using string representations defined in RFC
+ 1778, The String Representation of Standard Attribute Syntaxes.
+ These string encodings were based on the attribute definitions from
+ X.500(1988). Thus, the string representations of the PKI information
+ elements are for version 1 certificates and version 1 revocation
+ lists. Since this specification uses version 3 certificates and
+ version 2 revocation lists, as defined in X.509(1997), the RFC 1778
+ string encoding of these attributes is inappropriate.
+
+ For this reason, these attributes MUST be encoded using a syntax
+ similar to the syntax "Undefined" from section 2.1 of RFC 1778:
+ values of these attributes are encoded as if they were values of type
+ "OCTET STRING", with the string value of the encoding being the DER-
+ encoding of the value itself. For example, when writing a
+ userCertificate to the repository, the CA generates a DER-encoding of
+ the certificate and uses that encoding as the value of the
+ userCertificate attribute in the LDAP Modify request.This encoding
+
+
+
+Boeyen, et al. Standards Track [Page 9]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+ style is consistent with the encoding scheme proposed for LDAPv3,
+ which is now being defined within the IETF.
+
+ Note that certificates and revocation lists will be transferred using
+ this mechanism rather than the string encodings in RFC 1778 and
+ client systems which do not understand this encoding may experience
+ problems with these attributes.
+
+9. Transport
+
+ An application providing a LDAP repository read service, LDAP
+ repository search service, or LDAP repository modify service MUST
+ support LDAPv2 transport over TCP, as defined in Section 3.1 of RFC
+ 1777.
+
+ An application providing a LDAP repository read service, LDAP
+ repository search service, or LDAP repository modify service MAY
+ support LDAPv2 transport over other reliable transports as well.
+
+10. Security Considerations
+
+ Since the elements of information which are key to the PKI service
+ (certificates and CRLs) are both digitally signed pieces of
+ information, additional integrity service is NOT REQUIRED. As
+ neither information element need be kept secret and anonymous access
+ to such information, for retrieval purposes is generally acceptable,
+ privacy service is NOT REQUIRED for information retrieval requests.
+
+ CAs have additional requirements, including modification of PKI
+ information. Simple authentication alone is not sufficient for these
+ purposes. It is RECOMMENDED that some stronger means of
+ authentication and/or (if simple authentication is used) some means
+ of protecting the privacy of the password is used, (e.g. accept
+ modifications only via physically secure networks, use IPsec, use SSH
+ or TLS or SSL tunnel). Without such authentication, it is possible
+ that a denial-of-service attack could occur where the attacker
+ replaces valid certificates with bogus ones.
+
+ For the LDAP repository modify service, profiled in section 7, there
+ are some specific security considerations with respect to access
+ control. These controls apply to a repository which is under the same
+ management control as the CA. Organizations operating directories are
+ NOT REQUIRED to provide external CAs access permission to their
+ directories.
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 10]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+ The CA MUST have access control permissions allowing it to:
+
+ For CA entries:
+ - add, modify and delete all PKI attributes for its own
+ directory entry;
+ - add, modify and delete all values of these attributes.
+
+ For CRL distribution point entries (if used):
+ - create, modify and delete entries of object class
+ cRLDistributionPoint immediately subordinate to its own
+ entry;
+ - add, modify and delete all attributes, and all values of
+ these attributes for these entries.
+
+ For subscriber (end-entity) entries:
+ - add, modify and delete the attribute userCertificate and all
+ values of that attribute, issued by this CA to/from these
+ entries.
+
+ The CA is the ONLY entity with these permissions.
+
+ An application providing LDAP repository read, LDAP repository
+ search, or LDAP repository modify service as defined in this
+ specification is NOT REQUIRED to implement any additional security
+ features other than those described herein, however an implementation
+ SHOULD do so.
+
+11. References
+
+ [1] Yeong, Y., Howes, T. and S. Kille, "Lightweight Directory Access
+ Protocol", RFC 1777, March 1995.
+
+ [2] Howes, T., Kille, S., Yeong, W. and C. Robbins, "The String
+ Representation of Standard Attribute Syntaxes", RFC 1778, March
+ 1995.
+
+ [3] Bradner, S., "Key Words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 11]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+12. Authors' Addresses
+
+ Sharon Boeyen
+ Entrust Technologies Limited
+ 750 Heron Road
+ Ottawa, Ontario
+ Canada K1V 1A7
+
+ EMail: sharon.boeyen@entrust.com
+
+
+ Tim Howes
+ Netscape Communications Corp.
+ 501 E. Middlefield Rd.
+ Mountain View, CA 94043
+ USA
+
+ EMail: howes@netscape.com
+
+
+ Patrick Richard
+ Xcert Software Inc.
+ Suite 1001, 701 W. Georgia Street
+ P.O. Box 10145
+ Pacific Centre
+ Vancouver, B.C.
+ Canada V7Y 1C6
+
+ EMail: patr@xcert.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 12]
+\f
+RFC 2559 PKIX Operational Protocols - LDAPv2 April 1999
+
+
+13. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 13]
+\f
--- /dev/null
+
+
+
+
+
+
+Network Working Group S. Boeyen
+Request for Comments: 2587 Entrust
+Category: Standards Track T. Howes
+ Netscape
+ P. Richard
+ Xcert
+ June 1999
+
+
+
+ Internet X.509 Public Key Infrastructure
+ LDAPv2 Schema
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+1. Abstract
+
+ The schema defined in this document is a minimal schema to support
+ PKIX in an LDAPv2 environment, as defined in RFC 2559. Only PKIX-
+ specific components are specified here. LDAP servers, acting as PKIX
+ repositories should support the auxiliary object classes defined in
+ this specification and integrate this schema specification with the
+ generic and other application-specific schemas as appropriate,
+ depending on the services to be supplied by that server.
+
+ The key words 'MUST', 'SHALL', 'REQUIRED', 'SHOULD', 'RECOMMENDED',
+ and 'MAY' in this document are to be interpreted as described in RFC
+ 2119.
+
+2. Introduction
+
+ This specification is part of a multi-part standard for development
+ of a Public Key Infrastructure (PKI) for the Internet. LDAPv2 is one
+ mechanism defined for access to a PKI repository. Other mechanisms,
+ such as http, are also defined. If an LDAP server, accessed by LDAPv2
+ is used to provide a repository, the minimum requirement is that the
+ repository support the addition of X.509 certificates to directory
+
+
+
+
+Boeyen, et al. Standards Track [Page 1]
+\f
+RFC 2587 PKIX LDAPv2 Schema June 1999
+
+
+ entries. Certificate Revocation List (CRL)is one mechanism for
+ publishing revocation information in a repository. Other mechanisms,
+ such as http, are also defined.
+
+ This specification defines the attributes and object classes to be
+ used by LDAP servers acting as PKIX repositories and to be understood
+ by LDAP clients communicating with such repositories to query, add,
+ modify and delete PKI information. Some object classes and attributes
+ defined in X.509 are duplicated here for completeness. For end
+ entities and Certification Authorities (CA), the earlier X.509
+ defined object classes mandated inclusion of attributes which are
+ optional for PKIX. Also, because of the mandatory attribute
+ specification, this would have required dynamic modification of the
+ object class attribute should the attributes not always be present in
+ entries. For these reasons, alternative object classes are defined in
+ this document for use by LDAP servers acting as PKIX repositories.
+
+3. PKIX Repository Objects
+
+ The primary PKIX objects to be represented in a repository are:
+
+ - End Entities
+ - Certification Authorities (CA)
+
+ These objects are defined in RFC 2459.
+
+3.1. End Entities
+
+ For purposes of PKIX schema definition, the role of end entities as
+ subjects of certificates is the major aspect relevant to this
+ specification. End entities may be human users, or other types of
+ entities to which certificates may be issued. In some cases, the
+ entry for the end entity may already exist and the PKI-specific
+ information is added to the existing entry. In other cases the entry
+ may not exist prior to the issuance of a certificate, in which case
+ the entity adding the certificate may also need to create the entry.
+ Schema elements used to represent the non PKIX aspects of an entry,
+ such as the structural object class used to represent organizational
+ persons, may vary, depending on the particular environment and set of
+ applications served and are outside the scope of this specification.
+
+ The following auxiliary object class MAY be used to represent
+ certificate subjects:
+
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 2]
+\f
+RFC 2587 PKIX LDAPv2 Schema June 1999
+
+
+pkiUser OBJECT-CLASS ::= {
+ SUBCLASS OF { top}
+ KIND auxiliary
+ MAY CONTAIN {userCertificate}
+ ID joint-iso-ccitt(2) ds(5) objectClass(6) pkiUser(21)}
+
+userCertificate ATTRIBUTE ::= {
+ WITH SYNTAX Certificate
+ EQUALITY MATCHING RULE certificateExactMatch
+ ID joint-iso-ccitt(2) ds(5) attributeType(4) userCertificate(36) }
+
+ An end entity may obtain one or more certificates from one or more
+ Certification Authorities. The userCertificate attribute MUST be
+ used to represent these certificates in the directory entry
+ representing that user.
+
+3.2. Certification Authorities
+
+ As with end entities, Certification Authorities are typically
+ represented in directories as auxiliary components of entries
+ representing a more generic object, such as organizations,
+ organizational units etc. The non PKIX-specific schema elements for
+ these entries, such as the structural object class of the object, are
+ outside the scope of this specification.
+
+ The following auxiliary object class MAY be used to represent
+ Certification Authorities:
+
+pkiCA OBJECT-CLASS ::= {
+ SUBCLASS OF { top}
+ KIND auxiliary
+ MAY CONTAIN {cACertificate |
+ certificateRevocationList |
+ authorityRevocationList |
+ crossCertificatePair }
+ ID joint-iso-ccitt(2) ds(5) objectClass(6) pkiCA(22)}
+
+cACertificate ATTRIBUTE ::= {
+ WITH SYNTAX Certificate
+ EQUALITY MATCHING RULE certificateExactMatch
+ ID joint-iso-ccitt(2) ds(5) attributeType(4) cACertificate(37) }
+
+crossCertificatePairATTRIBUTE::={
+ WITH SYNTAX CertificatePair
+ EQUALITY MATCHING RULE certificatePairExactMatch
+ ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 3]
+\f
+RFC 2587 PKIX LDAPv2 Schema June 1999
+
+
+ The cACertificate attribute of a CA's directory entry shall be used
+ to store self-issued certificates (if any) and certificates issued to
+ this CA by CAs in the same realm as this CA.
+
+ The forward elements of the crossCertificatePair attribute of a CA's
+ directory entry shall be used to store all, except self-issued
+ certificates issued to this CA. Optionally, the reverse elements of
+ the crossCertificatePair attribute, of a CA's directory entry may
+ contain a subset of certificates issued by this CA to other CAs.
+ When both the forward and the reverse elements are present in a
+ single attribute value, issuer name in one certificate shall match
+ the subject name in the other and vice versa, and the subject public
+ key in one certificate shall be capable of verifying the digital
+ signature on the other certificate and vice versa.
+
+ When a reverse element is present, the forward element value and the
+ reverse element value need not be stored in the same attribute value;
+ in other words, they can be stored in either a single attribute value
+ or two attribute values.
+
+ In the case of V3 certificates, none of the above CA certificates
+ shall include a basicConstraints extension with the cA value set to
+ FALSE.
+
+ The definition of realm is purely a matter of local policy.
+
+ certificateRevocationListATTRIBUTE::={
+ WITH SYNTAX CertificateList
+ EQUALITY MATCHING RULE certificateListExactMatch
+ ID joint-iso-ccitt(2) ds(5) attributeType(4)
+ certificateRevocationList(39)}
+
+ The certificateRevocationList attribute, if present in a particular
+ CA's entry, contains CRL(s) as defined in RFC 2459.
+
+ authorityRevocationListATTRIBUTE::={
+ WITH SYNTAX CertificateList
+ EQUALITY MATCHING RULE certificateListExactMatch
+ ID joint-iso-ccitt(2) ds(5) attributeType(4)
+ authorityRevocationList(38)}
+
+ The authorityRevocationList attribute, if present in a particular
+ CA's entry, includes revocation information regarding certificates
+ issued to other CAs.
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 4]
+\f
+RFC 2587 PKIX LDAPv2 Schema June 1999
+
+
+3.2.1. CRL distribution points
+
+ CRL distribution points are an optional mechanism, specified in RFC
+ 2459, which MAY be used to distribute revocation information.
+
+ A patent statement regarding CRL distribution points can be found at
+ the end of this document.
+
+ If a CA elects to use CRL distribution points, the following object
+ class is used to represent these.
+
+ cRLDistributionPoint OBJECT-CLASS::= {
+ SUBCLASS OF { top }
+ KIND structural
+ MUST CONTAIN { commonName }
+ MAY CONTAIN { certificateRevocationList |
+ authorityRevocationList |
+ deltaRevocationList }
+ ID joint-iso-ccitt(2) ds(5) objectClass(6) cRLDistributionPoint(19) }
+
+ The certificateRevocationList and authorityRevocationList attributes
+ are as defined above.
+
+ The commonName attribute and deltaRevocationList attributes, defined
+ in X.509, are duplicated below.
+
+ commonName ATTRIBUTE::={
+ SUBTYPE OF name
+ WITH SYNTAX DirectoryString
+ ID joint-iso-ccitt(2) ds(5) attributeType(4) commonName(3) }
+
+ deltaRevocationList ATTRIBUTE ::= {
+ WITH SYNTAX CertificateList
+ EQUALITY MATCHING RULE certificateListExactMatch
+ ID joint-iso-ccitt(2) ds(5) attributeType(4)
+ deltaRevocationList(53) }
+
+3.2.2. Delta CRLs
+
+ Delta CRLs are an optional mechanism, specified in RFC 2459, which
+ MAY be used to enhance the distribution of revocation information.
+
+ If a CA elects to use delta CRLs, the following object class is used
+ to represent these.
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 5]
+\f
+RFC 2587 PKIX LDAPv2 Schema June 1999
+
+
+ deltaCRL OBJECT-CLASS::= {
+ SUBCLASS OF { top }
+ KIND auxiliary
+ MAY CONTAIN { deltaRevocationList }
+ ID joint-iso-ccitt(2) ds(5) objectClass(6) deltaCRL(23) }
+
+4. Security Considerations
+
+ Since the elements of information which are key to the PKI service
+ (certificates and CRLs) are both digitally signed pieces of
+ information, no additional integrity service is REQUIRED.
+
+ Security considerations with respect to retrieval, addition,
+ deletion, and modification of the information supported by this
+ schema definition are addressed in RFC 2559.
+
+5. References
+
+ [1] Yeong, Y., Howes, T. and S. Kille, "Lightweight Directory Access
+ Protocol", RFC 1777, March 1995.
+
+ [2] Bradner, S., "Key Words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+6 Intellectual Property Rights
+
+ The IETF has been notified of intellectual property rights claimed in
+ regard to some or all of the specification contained in this
+ document. For more information consult the online list of claimed
+ rights.
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 6]
+\f
+RFC 2587 PKIX LDAPv2 Schema June 1999
+
+
+7. Authors' Addresses
+
+ Sharon Boeyen
+ Entrust Technologies Limited
+ 750 Heron Road
+ Ottawa, Ontario
+ Canada K1V 1A7
+
+ EMail: sharon.boeyen@entrust.com
+
+
+ Tim Howes
+ Netscape Communications Corp.
+ 501 E. Middlefield Rd.
+ Mountain View, CA 94043
+ USA
+
+ EMail: howes@netscape.com
+
+
+ Patrick Richard
+ Xcert Software Inc.
+ Suite 1001, 701 W. Georgia Street
+ P.O. Box 10145
+ Pacific Centre
+ Vancouver, B.C.
+ Canada V7Y 1C6
+
+ EMail: patr@xcert.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 7]
+\f
+RFC 2587 PKIX LDAPv2 Schema June 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Boeyen, et al. Standards Track [Page 8]
+\f
--- /dev/null
+
+
+
+
+
+
+Network Working Group Y. Yaacovi
+Request for Comments: 2589 Microsoft
+Category: Standards Track M. Wahl
+ Innosoft International, Inc.
+ T. Genovese
+ Microsoft
+ May 1999
+
+
+ Lightweight Directory Access Protocol (v3):
+ Extensions for Dynamic Directory Services
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+1. Abstract
+
+ This document defines the requirements for dynamic directory services
+ and specifies the format of request and response extended operations
+ for supporting client-server interoperation in a dynamic directories
+ environment.
+
+ The Lightweight Directory Access Protocol (LDAP) [1] supports
+ lightweight access to static directory services, allowing relatively
+ fast search and update access. Static directory services store
+ information about people that persists in its accuracy and value over
+ a long period of time.
+
+ Dynamic directory services are different in that they store
+ information that only persists in its accuracy and value when it is
+ being periodically refreshed. This information is stored as dynamic
+ entries in the directory. A typical use will be a client or a person
+ that is either online - in which case it has an entry in the
+ directory, or is offline - in which case its entry disappears from
+ the directory. Though the protocol operations and attributes used by
+ dynamic directory services are similar to the ones used for static
+ directory services, clients that store dynamic information in the
+ directory need to periodically refresh this information, in order to
+ prevent it from disappearing. If dynamic entries are not refreshed
+
+
+
+Yaacovi, et al. Standards Track [Page 1]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+ within a given timeout, they will be removed from the directory. For
+ example, this will happen if the client that set them goes offline.
+
+ A flow control mechanism from the server is also described that
+ allows a server to inform clients how often they should refresh their
+ presence.
+
+2. Requirements
+
+ The protocol extensions must allow accessing dynamic information in a
+ directory in a standard LDAP manner, to allow clients to access
+ static and dynamic information in the same way.
+
+ By definition, dynamic entries are not persistent and clients may go
+ away gracefully or not. The proposed extensions must offer a way for
+ a server to tell if entries are still valid, and to do this in a way
+ that is scalable. There also must be a mechanism for clients to
+ reestablish their entry with the server.
+
+ There must be a way for clients to find out, in a standard LDAP
+ manner, if servers support the dynamic extensions.
+
+ Finally, to allow clients to broadly use the dynamic extensions, the
+ extensions need to be registered as standard LDAP extended
+ operations.
+
+3. Description of Approach
+
+ The Lightweight Directory Access Protocol (LDAP) [1] permits
+ additional operation requests and responses to be added to the
+ protocol. This proposal takes advantage of these to support
+ directories which contain dynamic information in a manner which is
+ fully integrated with LDAP.
+
+ The approach described in this proposal defines dynamic entries in
+ order to allow implementing directories with dynamic information. An
+ implementation of dynamic directories, must be able to support
+ dynamic directory entries.
+
+3.1. Dynamic Entries and the dynamicObject object class
+
+ A dynamic entry is an object in the directory tree which has a time-
+ to-live associated with it. This time-to-live is set when the entry
+ is created. The time-to-live is automatically decremented, and when
+ it expires the dynamic entry disappears. By invoking the refresh
+ extended operation (defined below) to re-set the time-to-live, a
+ client can cause the entry to remain present a while longer.
+
+
+
+
+Yaacovi, et al. Standards Track [Page 2]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+ A dynamic entry is created by including the objectClass value given
+ in section 5 in the list of attributes when adding an entry. This
+ method is subject to standard access control restrictions.
+
+ The extended operation covered here, allows a client to refresh a
+ dynamic entry by invoking, at intervals, refresh operations
+ containing that entry's name. Dynamic entries will be treated the
+ same as non-dynamic entries when processing search, compare, add,
+ delete, modify and modifyDN operations. However if clients stop
+ sending refresh operations for an entry, then the server will
+ automatically and without notification remove that entry from the
+ directory. This removal will be treated the same as if the entry had
+ been deleted by an LDAP protocol operation.
+
+ There is no way to change a static entry into a dynamic one and
+ vice-versa. If the client is using Modify with an objectClass of
+ dynamicObject on a static entry, the server must return a service
+ error either "objectClassModsProhibited" (if the server does not
+ allow objectClass modifications at all) or "objectClassViolation" (if
+ the server does allow objectClass modifications in general).
+
+ A dynamic entry may be removed by the client using the delete
+ operation. This operation will be subject to access control
+ restrictions.
+
+ A non-dynamic entry cannot be added subordinate to a dynamic entry:
+ the server must return an appropriate update or service error if this
+ is attempted.
+
+ The support of dynamic attributes of an otherwise static object, are
+ outside the scope of this document.
+
+3.2 Dynamic meetings (conferences)
+
+ The way dynamicObject is defined, it has a time-to-live associated
+ with it, and that's about it. Though the most common dynamic object
+ is a person object, there is no specific type associated with the
+ dynamicObject as defined here. By the use of the dynamic object's
+ attributes, one can make this object represent practically anything.
+
+ Specifically, Meetings (conferences) can be represented by dynamic
+ objects. While full-featured meeting support requires special
+ semantics and handling by the server (and is not in the scope of this
+ document), the extensions described here, provide basic meetings
+ support. A meeting object can be refreshed by the meeting
+ participants, and when it is not, the meeting entry disappears. The
+ one meeting type that is naturally supported by the dynamic
+ extensions is creator-owned meeting.
+
+
+
+Yaacovi, et al. Standards Track [Page 3]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+3.2.1 Creator-owned meetings
+
+ Creator-owned meetings are created by a client that sets the time-
+ to-live attribute for the entry, and it is this client's
+ responsibility to refresh the meeting entry, so that it will not
+ disappear. Others might join the meeting, by modifying the
+ appropriate attribute, but they are not allowed to refresh the entry.
+ When the client that created the entry goes away, it can delete the
+ meeting entry, or it might disappear when its time-to-live expires.
+ This is consistent with the common model for dynamicObject as
+ described above.
+
+4. Protocol Additions
+
+4.1 Refresh Request
+
+ Refresh is a protocol operation sent by a client to tell the server
+ that the client is still alive and the dynamic directory entry is
+ still accurate and valuable. The client sends a Refresh request
+ periodically based on the value of the client refresh period (CRP).
+ The server can request that the client change this value. As long as
+ the server receives a Refresh request within the timeout period, the
+ directory entry is guaranteed to persist on the server. Client
+ implementers should be aware that since the intervening network
+ between the client and server is unreliable, a Refresh request packet
+ may be delayed or lost while in transit. If this occurs, the entry
+ may disappear, and the client will need to detect this and re-add the
+ entry.
+
+ A client may request this operation by transmitting an LDAP PDU
+ containing an ExtendedRequest. An LDAP ExtendedRequest is defined as
+ follows:
+
+ ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+ requestName [0] LDAPOID,
+ requestValue [1] OCTET STRING OPTIONAL }
+
+ The requestName field must be set to the string
+ "1.3.6.1.4.1.1466.101.119.1".
+
+ The requestValue field will contain as a value the DER-encoding of
+ the following ASN.1 data type:
+
+ SEQUENCE {
+ entryName [0] LDAPDN,
+ requestTtl [1] INTEGER
+ }
+
+
+
+
+Yaacovi, et al. Standards Track [Page 4]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+ The entryName field is the UTF-8 string representation of the name of
+ the dynamic entry [3]. This entry must already exist.
+
+ The requestTtl is a time in seconds (between 1 and 31557600) that the
+ client requests that the entry exists in the directory before being
+ automatically removed. Servers are not required to accept this value
+ and might return a different TTL value to the client. Clients must
+ be able to use this server-dictated value as their CRP.
+
+4.2 Refresh Response
+
+ If a server implements this extension, then when the request is made
+ it will return an LDAP PDU containing an ExtendedResponse. An LDAP
+ ExtendedResponse is defined as follows:
+
+ ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+ COMPONENTS OF LDAPResult,
+ responseName [10] LDAPOID OPTIONAL,
+ response [11] OCTET STRING OPTIONAL }
+
+ The responseName field contains the same string as that present in
+ the request.
+
+ The response field will contain as a value the DER-encoding of the
+ following ASN.1 data type:
+
+ SEQUENCE {
+ responseTtl [1] INTEGER
+ }
+
+ The responseTtl field is the time in seconds which the server chooses
+ to have as the time-to-live field for that entry. It must not be any
+ smaller than that which the client requested, and it may be larger.
+ However, to allow servers to maintain a relatively accurate
+ directory, and to prevent clients from abusing the dynamic
+ extensions, servers are permitted to shorten a client-requested
+ time-to-live value, down to a minimum of 86400 seconds (one day).
+
+ If the operation was successful, the errorCode field in the
+ standardResponse part of an ExtendedResponse will be set to success.
+
+ In case of an error, the responseTtl field will have the value 0, and
+ the errorCode field will contain an appropriate value, as follows: If
+ the entry named by entryName could not be located, the errorCode
+ field will contain "noSuchObject". If the entry is not dynamic, the
+ errorCode field will contain "objectClassViolation". If the
+ requester does not have permission to refresh the entry, the
+
+
+
+
+Yaacovi, et al. Standards Track [Page 5]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+ errorCode field will contain "insufficientAccessRights". If the
+ requestTtl field is too large, the errorCode field will contain
+ "sizeLimitExceeded".
+
+ If a server does not implement this extension, it will return an LDAP
+ PDU containing an ExtendedResponse, which contains only the
+ standardResponse element (the responseName and response elements will
+ be absent). The LDAPResult element will indicate the protocolError
+ result code.
+
+ This request is permitted to be invoked when LDAP is carried by a
+ connectionless transport.
+
+ When using a connection-oriented transport, there is no requirement
+ that this operation be on the same particular connection as any
+ other. A client may open multiple connections, or close and then
+ reopen a connection.
+
+4.3 X.500/DAP Modify(97)
+
+ X.500/DAP servers can map the Refresh request and response operations
+ into the X.500/DAP Modify(97) operation.
+
+5. Schema Additions
+
+ All dynamic entries must have the dynamicObject value in their
+ objectClass attribute. This object class is defined as follows
+ (using the ObjectClassDescription notation of [2]):
+
+ ( 1.3.6.1.4.1.1466.101.119.2 NAME 'dynamicObject'
+ DESC 'This class, if present in an entry, indicates that this entry
+ has a limited lifetime and may disappear automatically when
+ its time-to-live has reached 0. There are no mandatory
+ attributes of this class, however if the client has not
+ supplied a value for the entryTtl attribute, the server will
+ provide one.'
+ SUP top AUXILIARY )
+
+ Furthermore, the dynamic entry must have the following operational
+ attribute. It is described using the AttributeTypeDescription
+ notation of [2]:
+
+ ( 1.3.6.1.4.1.1466.101.119.3 NAME 'entryTtl'
+ DESC 'This operational attribute is maintained by the server and
+ appears to be present in every dynamic entry. The attribute
+ is not present when the entry does not contain the
+ dynamicObject object class. The value of this attribute is
+ the time in seconds that the entry will continue to exist
+
+
+
+Yaacovi, et al. Standards Track [Page 6]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+ before disappearing from the directory. In the absence of
+ intervening refresh operations, the values returned by
+ reading the attribute in two successive searches are
+ guaranteed to be nonincreasing. The smallest permissible
+ value is 0, indicating that the entry may disappear without
+ warning. The attribute is marked NO-USER-MODIFICATION since
+ it may only be changed using the refresh operation.'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE
+ NO-USER-MODIFICATION USAGE dSAOperation )
+
+ To allow servers to support dynamic entries in only a part of the
+ DIT, the following operational attribute is defined. It is
+ described using the AttributeTypeDescription notation of [2]:
+
+ ( 1.3.6.1.4.1.1466.101.119.4 NAME 'dynamicSubtrees'
+ DESC 'This operational attribute is maintained by the server and is
+ present in the Root DSE, if the server supports the dynamic
+ extensions described in this memo. The attribute contains a
+ list of all the subtrees in this directory for which the
+ server supports the dynamic extensions.'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION
+ USAGE dSAOperation )
+
+6. Client and Server Requirements
+
+6.1 Client Requirements
+
+ Clients can find out if a server supports the dynamic extensions by
+ checking the supportedExtension field in the root DSE, to see if the
+ OBJECT IDENTIFIER described in section 4 is present. Since servers
+ may select to support the dynamic extensions in only some of the
+ subtrees of the DIT, clients must check the dynamicSubtrees
+ operational attribute in the root DSE to find out if the dynamic
+ extensions are supported on a specific subtree.
+
+ Once a dynamic entry has been created, clients are responsible for
+ invoking the refresh extended operation, in order to keep that entry
+ present in the directory.
+
+ Clients must not expect that a dynamic entry will be present in the
+ DIT after it has timed out, however it must not require that the
+ server remove the entry immediately (some servers may only process
+ timing out entries at intervals). If the client wishes to ensure the
+ entry does not exist it should issue a RemoveRequest for that entry.
+
+ Initially, a client needs to know how often it should send refresh
+ requests to the server. This value is defined as the CRP (Client
+ Refresh Period) and is set by the server based on the entryTtl.
+
+
+
+Yaacovi, et al. Standards Track [Page 7]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+ Since the LDAP AddRequest operation is left unchanged and is not
+ modified in this proposal to return this value, a client must issue a
+ Refresh extended operation immediately after an Add that created a
+ dynamic entry. The Refresh Response will return the CRP (in
+ responseTtl) to the client.
+
+ Clients must not issue the refresh request for dynamic entries which
+ they have not created. If an anonymous client attempts to do so, a
+ server is permitted to return insufficientAccessRights (50) in the
+ RefreshResponse, enforcing the client to bind first. Please note that
+ servers which allow anonymous clients to create and refresh dynamic
+ entries will not be able to enforce the above.
+
+ Clients should always be ready to handle the case in which their
+ entry timed out. In such a case, the Refresh operation will fail
+ with an error code such as noSuchObject, and the client is expected
+ to re-create its entry.
+
+ Clients should be prepared to experience refresh operations failing
+ with protocolError, even though the add and any previous refresh
+ requests succeeded. This might happen if a proxy between the client
+ and the server goes down, and another proxy is used which does not
+ support the Refresh extended operation.
+
+6.2 Server Requirements
+
+ Servers are responsible for removing dynamic entries when they time
+ out. Servers are not required to do this immediately.
+
+ Servers must enforce the structural rules listed in above section 3.
+
+ Servers must ensure that the operational attribute described in
+ section 5 is present in dynamic entries
+
+ Servers may permit anonymous users to refresh entries. However, to
+ eliminate the possibility of a malicious use of the Refresh
+ operation, servers may require the refreshing client to bind first. A
+ server implementation can achieve this by presenting ACLs on the
+ entryTtl attribute, and returning insufficientAccessRights (50) in
+ the RefreshResponse, if the client is not allowed to refresh the
+ entry. Doing this, though, might have performance implications on the
+ server and might impact the server's scalability.
+
+ Servers may require that a client which attempts to create a dynamic
+ entry have a remove permission for that entry.
+
+ Servers which implement the dynamic extensions must have the OBJECT
+ IDENTIFIER, described above in section 4 for the request and
+
+
+
+Yaacovi, et al. Standards Track [Page 8]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+ response, present as a value of the supportedExtension field in the
+ root DSE. They must also have as values in the attributeTypes and
+ objectClasses attributes of their subschema subentries, the
+ AttributeTypeDescription and ObjectClassDescription from section 5.
+
+ Servers can limit the support of the dynamic extensions to only some
+ of the subtrees in the DIT. Servers indicate for which subtrees they
+ support the extensions, by specifying the OIDs for the supported
+ subtrees in the dynamicSubtrees attribute described in section 5. If
+ a server supports the dynamic extensions for all naming contexts it
+ holds, the dynamicSubtrees attribute may be absent.
+
+7. Implementation issues
+
+7.1 Storage of dynamic information
+
+ Dynamic information is expected to change very often. In addition,
+ Refresh requests are expected to arrive at the server very often.
+ Disk-based databases that static directory services often use are
+ likely inappropriate for storing dynamic information. We recommend
+ that server implementations store dynamic entries in memory
+ sufficient to avoid paging. This is not a requirement.
+
+ We expect LDAP servers to be able to store static and dynamic
+ entries. If an LDAP server does not support dynamic entries, it
+ should respond with an error code such as objectClassViolation.
+
+7.2 Client refresh behavior
+
+ In some cases, the client might not get a Refresh response. This may
+ happen as a result of a server crash after receiving the Refresh
+ request, the TCP/IP socket timing out in the connection case, or the
+ UDP packet getting lost in the connection-less case.
+
+ It is recommended that in such a case, the client will retry the
+ Refresh operation immediately, and if this Refresh request does not
+ get a response as well, it will resort to its original Refresh cycle,
+ i.e. send a Refresh request at its Client Refresh Period (CRP).
+
+7.3 Configuration of refresh times
+
+ We recommend that servers will provide administrators with the
+ ability to configure the default client refresh period (CRP), and
+ also a minimum and maximum CRP values. This, together with allowing
+ administrators to request that the server will not change the CRP
+ dynamically, will allow administrators to set CRP values which will
+ enforce a low refresh traffic, or - on the other extreme, an highly
+ up-to-date directory.
+
+
+
+Yaacovi, et al. Standards Track [Page 9]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+8. Replication
+
+ Replication is only partially addressed in this memo. There is a
+ separate effort in progress at the IETF on replication of static and
+ dynamic directories.
+
+ it is allowed to replicate a dynamic entry or a static entry with
+ dynamic attributes. Since the entryTtl is expressed as a relative
+ time (how many seconds till the entry will expire), replicating it
+ means that the replicated entry will be "off" by the replication
+ time.
+
+9. Localization
+
+ The are no localization issues for this extended operation.
+
+10. Security Considerations
+
+ Standard LDAP security rules and support apply for the extensions
+ described in this document, and there are no special security issues
+ for these extensions. Please note, though, that servers may permit
+ anonymous clients to refresh entries which they did not create.
+ Servers are also permitted to control a refresh access to an entry by
+ requiring clients to bind before issuing a RefreshRequest. This will
+ have implications on the server performance and scalability.
+
+ Also, Care should be taken in making use of information obtained from
+ directory servers that has been supplied by client, as it may now be
+ out of date. In many networks, for example, IP addresses are
+ automatically assigned when a host connects to the network, and may
+ be reassigned if that host later disconnects. An IP address obtained
+ from the directory may no longer be assigned to the host that placed
+ the address in the directory. This issue is not specific to LDAP or
+ dynamic directories.
+
+11. Acknowledgments
+
+ Design ideas included in this document are based on those discussed
+ in ASID and other IETF Working Groups.
+
+
+
+
+
+
+
+
+
+
+
+
+Yaacovi, et al. Standards Track [Page 10]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+12. Authors' Addresses
+
+ Yoram Yaacovi
+ Microsoft
+ One Microsoft way
+ Redmond, WA 98052
+ USA
+
+ Phone: +1 206-936-9629
+ EMail: yoramy@microsoft.com
+
+
+ Mark Wahl
+ Innosoft International, Inc.
+ 8911 Capital of Texas Hwy #4140
+ Austin, TX 78759
+ USA
+
+ Email: M.Wahl@innosoft.com
+
+
+ Tony Genovese
+ Microsoft
+ One Microsoft way
+ Redmond, WA 98052
+ USA
+
+ Phone: +1 206-703-0852
+ EMail: tonyg@microsoft.com
+
+13. Bibliography
+
+ [1] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory Access
+ Protocol (Version 3)", RFC 2251, December 1997.
+
+ [2] Wahl, M. Coulbeck, A., Howes, T. and S. Kille, "Lightweight
+ Directory Access Protocol (v3): Attribute Syntax Definitions",
+ RFC 2252, December 1997.
+
+ [3] Wahl, M. and S. Kille, "Lightweight Directory Access Protocol
+ (v3): UTF-8 String Representation of Distinguished Names", RFC
+ 2253, December 1997.
+
+
+
+
+
+
+
+
+
+Yaacovi, et al. Standards Track [Page 11]
+\f
+RFC 2589 LDAPv3 Extensions for Dynamic Directory Services May 1999
+
+
+14. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Yaacovi, et al. Standards Track [Page 12]
+\f
--- /dev/null
+
+
+
+
+
+
+Network Working Group M. Wahl
+Request for Comments: 2596 Innosoft International, Inc.
+Category: Standards Track T. Howes
+ Netscape Communications Corp.
+ May 1999
+
+
+ Use of Language Codes in LDAP
+
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+1. Abstract
+
+ The Lightweight Directory Access Protocol [1] provides a means for
+ clients to interrogate and modify information stored in a distributed
+ directory system. The information in the directory is maintained as
+ attributes [2] of entries. Most of these attributes have syntaxes
+ which are human-readable strings, and it is desirable to be able to
+ indicate the natural language associated with attribute values.
+
+ This document describes how language codes [3] are carried in LDAP
+ and are to be interpreted by LDAP servers. All implementations MUST
+ be prepared to accept language codes in the LDAP protocols. Servers
+ may or may not be capable of storing attributes with language codes
+ in the directory. This document does not specify how to determine
+ whether particular attributes can or cannot have language codes.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [4].
+
+2. Language Codes
+
+ Section 2 of RFC 1766 [3] describes the language code format which is
+ used in LDAP. Briefly, it is a string of ASCII alphabetic characters
+ and hyphens. Examples include "fr", "en-US" and "ja-JP".
+
+
+
+
+Wahl & Howes Standards Track [Page 1]
+\f
+RFC 2596 Use of Language Codes in LDAP May 1999
+
+
+ Language codes are case insensitive. For example, the language code
+ "en-us" is the same as "EN-US" and "en-US".
+
+ Implementations MUST NOT otherwise interpret the structure of the
+ code when comparing two codes, and MUST treat them as simply strings
+ of characters. Client and server implementations MUST allow any
+ arbitrary string which follows the patterns given in RFC 1766 to be
+ used as a language code.
+
+3. Use of Language Codes in LDAP
+
+ This section describes how LDAP implementations MUST interpret
+ language codes in performing operations.
+
+ In general, an attribute with a language code is to be treated as a
+ subtype of the attribute without a language code. If a server does
+ not support storing language codes with attribute values in the DIT,
+ then it MUST always treat an attribute with a language code as an
+ unrecognized attribute.
+
+3.1. Attribute Description
+
+ An attribute consists of a type, a list of options for that type, and
+ a set of one or more values. In LDAP, the type and the options are
+ combined into the AttributeDescription, defined in section 4.1.5 of
+ [1]. This is represented as an attribute type name and a possibly-
+ empty list of options. One of these options associates a natural
+ language with values for that attribute.
+
+ language-option = "lang-" lang-code
+
+ lang-code = printable-ascii ; a code as defined in RFC 1766
+
+ Multiple language options may be present on a particular value.
+
+ The language code has no effect on the character set encoding for
+ string representations of DirectoryString syntax values; the UTF-8
+ representation of UniversalString (ISO 10646) is always used.
+
+ Examples of valid AttributeDescription:
+ givenName;lang-en-US
+ CN;lang-ja
+
+ In LDAP and in examples in this document, a directory attribute is
+ represented as an AttributeDescription with a list of values. Note
+ that the data could be stored in the LDAP server in a different
+ representation.
+
+
+
+
+Wahl & Howes Standards Track [Page 2]
+\f
+RFC 2596 Use of Language Codes in LDAP May 1999
+
+
+3.2. Distinguished Names and Relative Distinguished Names
+
+ No attribute description options are permitted in Distinguished Names
+ or Relative Distinguished Names. Thus language codes MUST NOT be
+ used in forming DNs.
+
+3.3. Search Filter
+
+ If a language code is present in an AttributeDescription in a search
+ filter, then only attribute values in the directory which match the
+ base attribute type or its subtype, the language code and the
+ assertion value match this filter.
+
+ Thus for example a filter of an equality match of type "name;lang-
+ en-US" and assertion value "Billy Ray", against the following
+ directory entry
+
+ objectclass: top DOES NOT MATCH (wrong type)
+ objectclass: person DOES NOT MATCH (wrong type)
+ name;lang-EN-US: Billy Ray MATCHES
+ name;lang-EN-US: Billy Bob DOES NOT MATCH (wrong value)
+ CN;lang-en-us: Billy Ray MATCHES
+ CN;lang-EN-US;dynamic: Billy Ray MATCHES
+ CN;lang-en;dynamic: Billy Ray DOES NOT MATCH (differing lang-)
+ name: Billy Ray DOES NOT MATCH (no lang-)
+ SN: Ray DOES NOT MATCH (wrong value)
+
+ (Note that "CN" and "SN" are subtypes of "name".)
+
+ Client implementors should however note that providing a language
+ code in a search filter AttributeDescription will often filter out
+ desirable values where the language code does not match exactly. For
+ example, the filter (name;lang-en=Billy Ray) does NOT match the
+ attribute "name;lang-en-US: Billy Ray".
+
+ If the server does not support storing language codes with attribute
+ values in the DIT, then any filter which includes a language code
+ will always fail to match, as it is an unrecognized attribute type.
+ No error would be returned because of this; a presence filter would
+ evaluate to FALSE and all other forms to Undefined.
+
+ If no language code is specified in the search filter, then only the
+ base attribute type and the assertion value need match the value in
+ the directory.
+
+ Thus for example a filter of an equality match of type "name" and
+ assertion value "Billy Ray", against the following directory entry
+
+
+
+
+Wahl & Howes Standards Track [Page 3]
+\f
+RFC 2596 Use of Language Codes in LDAP May 1999
+
+
+ objectclass: top DOES NOT MATCH (wrong type)
+ objectclass: person DOES NOT MATCH (wrong type)
+ name;lang-EN-US: Billy Ray MATCHES
+ name;lang-EN-US: Billy Bob DOES NOT MATCH (wrong value)
+ CN;lang-EN-US;dynamic: Billy Ray MATCHES
+ CN;lang-en;dynamic: Billy Ray MATCHES
+ name: Billy Ray MATCHES
+ SN: Ray DOES NOT MATCH (wrong value)
+
+ Thus in general, clients SHOULD NOT use the language code option in
+ AttributeDescription fields in search filters.
+
+3.4. Compare
+
+ A language code can be present in an AttributeDescription used in a
+ compare request AttributeValueAssertion. This is to be treated by
+ servers the same as the use of language codes in a search filter with
+ an equality match, as described in the previous section. If there is
+ no attribute in the entry with the same subtype and language code,
+ the noSuchAttributeType error will be returned.
+
+ Thus for example a compare request of type "name" and assertion value
+ "Johann", against an entry with all the following directory entry
+
+ objectclass: top
+ objectclass: person
+ givenName;lang-de-DE: Johann
+ CN: Johann Sibelius
+ SN: Sibelius
+
+ will cause the server to return compareTrue.
+
+ However, if the client issued a compare request of type "name;lang-
+ de" and assertion value "Johann" against the above entry, the request
+ would fail with the noSuchAttributeType error.
+
+ If the server does not support storing language codes with attribute
+ values in the DIT, then any comparison which includes a language code
+ will always fail to locate an attribute type, and noSuchAttributeType
+ will be returned.
+
+ Thus in general, clients SHOULD NOT use the language code option in
+ AttributeDescription fields in the compare request.
+
+3.5. Requested Attributes in Search
+
+ Clients MAY provide language codes in AttributeDescription in the
+ requested attribute list in a search request.
+
+
+
+Wahl & Howes Standards Track [Page 4]
+\f
+RFC 2596 Use of Language Codes in LDAP May 1999
+
+
+ If a language code is provided in an attribute description, then only
+ attribute values in a directory entry which have the same language
+ code as that provided are to be returned. Thus if a client requests
+ an attribute "description;lang-en", the server MUST NOT return values
+ of an attribute "description" or "description;lang-fr".
+
+ Clients MAY provide in the attribute list multiple
+ AttributeDescription which have the same base attribute type but
+ different options. For example a client MAY provide both "name;lang-
+ en" and "name;lang-fr", and this would permit an attribute with
+ either language code to be returned. Note there would be no need to
+ provide both "name" and "name;lang-en" since all subtypes of name
+ would match "name".
+
+ If a server does not support storing language codes with attribute
+ values in the DIT, then any attribute descriptions in the list which
+ include language codes are to be ignored, just as if they were
+ unknown attribute types.
+
+ If a request is made specifying all attributes or an attribute is
+ requested without providing a language code, then all attribute
+ values regardless of their language code are returned.
+
+ For example, if the client requests a "description" attribute, and a
+ matching entry contains
+
+ objectclass: top
+ objectclass: organization
+ O: Software GmbH
+ description: software
+ description;lang-en: software products
+ description;lang-de: Softwareprodukte
+ postalAddress: Berlin 8001 Germany
+ postalAddress;lang-de: Berlin 8001 Deutschland
+
+ The server will return:
+
+ description: software
+ description;lang-en: software products
+ description;lang-de: Softwareprodukte
+
+3.6. Add Operation
+
+ Clients MAY provide language codes in AttributeDescription in
+ attributes of a new entry to be created, subject to the limitation
+ that the client MUST NOT use language codes in the attribute value or
+ values which form the RDN of the entry.
+
+
+
+
+Wahl & Howes Standards Track [Page 5]
+\f
+RFC 2596 Use of Language Codes in LDAP May 1999
+
+
+ A client MAY provide multiple attributes with the same attribute type
+ and value, so long as each attribute has a different language code,
+ and at most one attribute does not have a language code option.
+
+ Servers which support storing language codes in the DIT MUST allow
+ any attribute it recognizes that has the Directory String syntax to
+ have a language option associated with it. Servers SHOULD allow
+ language options to be associated with other attributes.
+
+ For example, the following is a legal request.
+
+ objectclass: top
+ objectclass: person
+ objectclass: residentialPerson
+ name: John Smith
+ CN: John Smith
+ CN;lang-en: John Smith
+ SN: Smith
+ streetAddress: 1 University Street
+ streetAddress;lang-en: 1 University Street
+ streetAddress;lang-fr: 1 rue Universite
+ houseIdentifier;lang-fr: 9e etage
+
+ If a server does not support storing language codes with attribute
+ values in the DIT, then it MUST treat an AttributeDescription with a
+ language code as an unrecognized attribute. If the server forbids the
+ addition of unrecognized attributes then it MUST fail the add request
+ with the appropriate result code.
+
+3.7. Modify Operation
+
+ A client MAY provide a language code in an AttributeDescription as
+ part of a modification element in the modify operation.
+
+ Attribute types and language codes MUST match exactly against values
+ stored in the directory. For example, if the modification is a
+ "delete", then if the stored values to be deleted have a language
+ code, the language code MUST be provided in the modify operation, and
+ if the stored values to be deleted do not have a language code, then
+ no language code is to be provided.
+
+ If the server does not support storing language codes with attribute
+ values in the DIT, then it MUST treat an AttributeDescription with a
+ language code as an unrecognized attribute, and MUST fail the request
+ with an appropriate result code.
+
+
+
+
+
+
+Wahl & Howes Standards Track [Page 6]
+\f
+RFC 2596 Use of Language Codes in LDAP May 1999
+
+
+3.8. Diagnostic Messages
+
+ Servers SHOULD use only printable ASCII characters in the
+ errorMessage field, as not all clients will be able to display the
+ full range of Unicode.
+
+4. Differences from X.500(1997)
+
+ X.500(1997) defines a different mechanism, contexts, as the means of
+ representing language tags. This section summarizes the major
+ differences in approach.
+
+ a) An X.500 operation which has specified a language code on a value
+ matches a value in the directory without a language code.
+ b) LDAP references RFC 1766, which allows for IANA registration of
+ new tags.
+ c) LDAP does not allow language codes in distinguished names.
+ d) X.500 describes subschema administration procedures to allow
+ language codes to be associated with particular attributes types.
+
+5. Security Considerations
+
+ There are no known security considerations for this document. See
+ the security considerations sections of [1] and [2] for security
+ considerations of LDAP in general.
+
+6. Acknowledgements
+
+ This document is a product of the IETF ASID and LDAPEXT working
+ groups. Martin Duerst provided many valuable comments on an earlier
+ version of this document.
+
+7. Bibliography
+
+ [1] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory Access
+ Protocol (v3)", RFC 2251, December 1997.
+
+ [2] Wahl, M., Coulbeck, A., Howes, T. and S. Kille, "Lightweight
+ X.500 Directory Access Protocol Attribute Syntax Definitions",
+ RFC 2252, December 1997.
+
+ [3] Alvestrand, H.,"Tags for the Identification of Languages", RFC
+ 1766, March 1995.
+
+ [4] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+
+
+Wahl & Howes Standards Track [Page 7]
+\f
+RFC 2596 Use of Language Codes in LDAP May 1999
+
+
+8. Authors' Addresses
+
+ Mark Wahl
+ Innosoft International, Inc.
+ 8911 Capital of Texas Hwy Suite 4140
+ Austin, TX 78759 USA
+
+ EMail: M.Wahl@innosoft.com
+
+
+ Tim Howes
+ Netscape Communications Corp.
+ 501 E. Middlefield Rd
+ Mountain View, CA 94043 USA
+
+ Phone: +1 650 937-3419
+ EMail: howes@netscape.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl & Howes Standards Track [Page 8]
+\f
+RFC 2596 Use of Language Codes in LDAP May 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wahl & Howes Standards Track [Page 9]
+\f
--- /dev/null
+## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, See COPYRIGHT file
+##
+## include Makefile.in for OpenLDAP
+
+all-local: ldap_config.h FORCE
+
+install-local: FORCE
+ -$(MKDIR) -p $(includedir)
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/lber.h $(includedir)
+ $(INSTALL) $(INSTALLFLAGS) -m 644 lber_types.h $(includedir)
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/ldap.h $(includedir)
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/ldap_cdefs.h $(includedir)
+ $(INSTALL) $(INSTALLFLAGS) -m 644 ldap_features.h $(includedir)
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/ldap_schema.h $(includedir)
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/disptmpl.h $(includedir)
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/srchpref.h $(includedir)
+
+clean-local: FORCE
+ $(RM) ldap_config.h
+
+veryclean-local: clean-local FORCE
+ $(RM) portable.h lber_types.h ldap_features.h
+
+depend-local: ldap_config.h FORCE
+
+LDAP_CONFIG=$(srcdir)/ldap_config.h.in
+
+ldap_config.h: $(LDAP_CONFIG) Makefile
+ @$(RM) $@
+ @echo "Making $@"
+ @echo "/* Generated from $(LDAP_CONFIG) on `date` */" > $@; \
+ $(SED) \
+ -e 's;%SYSCONFDIR%;$(sysconfdir);' \
+ -e 's;%DATADIR%;$(datadir);' \
+ -e 's;%BINDIR%;$(bindir);' \
+ -e 's;%SBINDIR%;$(sbindir);' \
+ -e 's;%LIBEXECDIR%;$(libexecdir);' \
+ -e 's;%RUNDIR%;$(localstatedir);' \
+ -e 's;%EDITOR%;$(EDITOR);' \
+ -e 's;%FINGER%;$(FINGER);' \
+ -e 's;%SENDMAIL%;$(SENDMAIL);' \
+ $(LDAP_CONFIG) >> $@; \
+ $(CHMOD) 444 $@
+
+all-common: all-local
+install-common: all-common install-local
+clean-common: clean-local
+veryclean-common: veryclean-local
+depend-common: depend-local
--- /dev/null
+/* Generic assert.h */
+/*
+ * Copyright 1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#ifndef _AC_ASSERT_H
+#define _AC_ASSERT_H
+
+#undef assert
+
+#ifdef LDAP_DEBUG
+
+#if defined( HAVE_ASSERT_H ) || defined( STDC_HEADERS )
+
+#undef NDEBUG
+#include <assert.h>
+
+#else /* !(HAVE_ASSERT_H || STDC_HEADERS) */
+
+#define LDAP_NEED_ASSERT 1
+
+/*
+ * no assert()... must be a very old compiler.
+ * create a replacement and hope it works
+ */
+
+LDAP_F(void) ber_pvt_assert LDAP_P((
+ const char *file, int line, const char *test ));
+
+/* Can't use LDAP_STRING(test), that'd expand to "test" */
+#if defined(__STDC__) || defined(__cplusplus)
+#define assert(test) \
+ ((test) ? (void)0 : ber_pvt_assert( __FILE__, __LINE__, #test ) )
+#else
+#define assert(test) \
+ ((test) ? (void)0 : ber_pvt_assert( __FILE__, __LINE__, "test" ) )
+#endif
+
+#endif /* (HAVE_ASSERT_H || STDC_HEADERS) */
+
+#else /* !LDAP_DEBUG */
+/* no asserts */
+#define assert(test) ((void)0)
+#endif /* LDAP_DEBUG */
+
+#endif /* _AC_ASSERT_H */
--- /dev/null
+/*
+ * Generic socket.h
+ */
+/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#ifndef _AC_SOCKET_H_
+#define _AC_SOCKET_H_
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include <netinet/in.h>
+
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+
+#include <netdb.h>
+
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+
+#endif /* HAVE_SYS_SOCKET_H */
+
+#ifdef HAVE_WINSOCK2
+#include <winsock2.h>
+#elif HAVE_WINSOCK
+#include <winsock.h>
+#else
+#define WSACleanup()
+#endif
+
+#ifdef HAVE_PCNFS
+#include <tklib.h>
+#endif /* HAVE_PCNFS */
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK (0x7f000001UL)
+#endif
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#ifdef HAVE_WINSOCK
+# define tcp_close( s ) closesocket( s );
+# define ioctl( s, c, a ) ioctlsocket( (s), (c), (a) )
+# define ioctl_t u_long
+# define AC_SOCKET_INVALID ((unsigned int) ~0)
+
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#define ETIMEDOUT WSAETIMEDOUT
+
+#elif MACOS
+# define tcp_close( s ) tcpclose( s )
+
+#elif DOS
+# ifdef PCNFS
+# define tcp_close( s ) close( s )
+# endif /* PCNFS */
+# ifdef NCSA
+# define tcp_close( s ) do { netclose( s ); netshut() } while(0)
+# endif /* NCSA */
+
+#elif HAVE_CLOSESOCKET
+# define tcp_close( s ) closesocket( s )
+
+#else
+# define tcp_close( s ) close( s )
+#endif /* MACOS */
+
+#ifndef ioctl_t
+# define ioctl_t int
+#endif
+
+#ifndef AC_SOCKET_INVALID
+# define AC_SOCKET_INVALID (-1)
+#endif
+
+#if !defined( HAVE_INET_ATON ) && !defined( inet_aton )
+#define inet_aton ldap_pvt_inet_aton
+struct in_addr;
+int ldap_pvt_inet_aton LDAP_P(( const char *, struct in_addr * ));
+#endif
+
+#if defined(__WIN32) && defined(_ALPHA)
+/* NT on Alpha is hosed. */
+#define AC_HTONL( l ) \
+ ((((l)&0xff)<<24) + (((l)&0xff00)<<8) + \
+ (((l)&0xff0000)>>8) + (((l)&0xff000000)>>24))
+#define AC_NTOHL(l) AC_HTONL(l)
+
+#elif defined(__alpha) && !defined(VMS)
+/*
+ * htonl and ntohl on the DEC Alpha under OSF 1 seem to only swap the
+ * lower-order 32-bits of a (64-bit) long, so we define correct versions
+ * here.
+ */
+#define AC_HTONL( l ) (((long)htonl( (l) & 0x00000000FFFFFFFF )) << 32 \
+ | htonl( ( (l) & 0xFFFFFFFF00000000 ) >> 32 ))
+
+#define AC_NTOHL( l ) (((long)ntohl( (l) & 0x00000000FFFFFFFF )) << 32 \
+ | ntohl( ( (l) & 0xFFFFFFFF00000000 ) >> 32 ))
+
+#else
+#define AC_HTONL( l ) htonl( l )
+#define AC_NTOHL( l ) ntohl( l )
+#endif
+
+/* htons()/ntohs() may be broken much like htonl()/ntohl() */
+#define AC_HTONS( s ) htons( s )
+#define AC_NTOHS( s ) ntohs( s )
+
+
+#endif /* _AC_SOCKET_H_ */
--- /dev/null
+/* Generic stdlib.h */
+/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#ifndef _AC_STDLIB_H
+#define _AC_STDLIB_H
+
+#if defined( HAVE_CSRIMALLOC )
+#include <stdio.h>
+#define MALLOC_TRACE
+#include <libmalloc.h>
+#endif
+
+#include <stdlib.h>
+
+/* Ignore malloc.h if we have STDC_HEADERS */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+# include <malloc.h>
+#endif
+
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# define EXIT_FAILURE 1
+#endif
+
+#endif /* _AC_STDLIB_H */
/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+/* Portions
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
#ifndef _LBER_H
#define _LBER_H
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <ldap_cdefs.h>
+#include <lber_types.h>
+
+LDAP_BEGIN_DECL
+
+/* boolean, enumerations, and integers */
+typedef LBER_INT_T ber_int_t;
+
+/* signed and unsigned versions */
+typedef signed LBER_INT_T ber_sint_t;
+typedef unsigned LBER_INT_T ber_uint_t;
+
+/* tags */
+typedef LBER_TAG_T ber_tag_t;
-#if !defined( NEEDPROTOS ) && defined(__STDC__)
-#define NEEDPROTOS 1
-#endif
+/* "socket" descriptors */
+typedef LBER_SOCKET_T ber_socket_t;
+
+/* lengths */
+typedef unsigned LBER_LEN_T ber_len_t;
+
+/* signed lengths */
+typedef LBER_LEN_T ber_slen_t;
+
+
+/* Overview of LBER tag construction
+ *
+ * Bits
+ * ______
+ * 8 7 | CLASS
+ * 0 0 = UNIVERSAL
+ * 0 1 = APPLICATION
+ * 1 0 = CONTEXT-SPECIFIC
+ * 1 1 = PRIVATE
+ * _____
+ * | 6 | DATA-TYPE
+ * 0 = PRIMITIVE
+ * 1 = CONSTRUCTED
+ * ___________
+ * | 5 ... 1 | TAG-NUMBER
+ */
/* BER classes and mask */
-#define LBER_CLASS_UNIVERSAL 0x00
-#define LBER_CLASS_APPLICATION 0x40
-#define LBER_CLASS_CONTEXT 0x80
-#define LBER_CLASS_PRIVATE 0xc0
-#define LBER_CLASS_MASK 0xc0
+#define LBER_CLASS_UNIVERSAL (ber_tag_t) 0x00U
+#define LBER_CLASS_APPLICATION (ber_tag_t) 0x40U
+#define LBER_CLASS_CONTEXT (ber_tag_t) 0x80U
+#define LBER_CLASS_PRIVATE (ber_tag_t) 0xc0U
+#define LBER_CLASS_MASK (ber_tag_t) 0xc0U
/* BER encoding type and mask */
-#define LBER_PRIMITIVE 0x00
-#define LBER_CONSTRUCTED 0x20
-#define LBER_ENCODING_MASK 0x20
+#define LBER_PRIMITIVE (ber_tag_t) 0x00U
+#define LBER_CONSTRUCTED (ber_tag_t) 0x20U
+#define LBER_ENCODING_MASK (ber_tag_t) 0x20U
-#define LBER_BIG_TAG_MASK 0x1f
-#define LBER_MORE_TAG_MASK 0x80
+#define LBER_BIG_TAG_MASK (ber_tag_t) 0x1fU
+#define LBER_MORE_TAG_MASK (ber_tag_t) 0x80U
/*
* Note that LBER_ERROR and LBER_DEFAULT are values that can never appear
* as valid BER tags, and so it is safe to use them to report errors. In
* fact, any tag for which the following is true is invalid:
- * (( tag & 0x00000080 ) != 0 ) && (( tag & 0xFFFFFF00 ) != 0 )
*/
-#define LBER_ERROR 0xffffffffL
-#define LBER_DEFAULT 0xffffffffL
+#define LBER_INVALID(t) (((t) & 0x080) && (((t) & (ber_tag_t) ~ 0x0FF))
+#define LBER_ERROR ((ber_tag_t) ~ 0x0)
+#define LBER_DEFAULT ((ber_tag_t) ~ 0x0)
/* general BER types we know about */
-#define LBER_BOOLEAN 0x01L
-#define LBER_INTEGER 0x02L
-#define LBER_BITSTRING 0x03L
-#define LBER_OCTETSTRING 0x04L
-#define LBER_NULL 0x05L
-#define LBER_ENUMERATED 0x0aL
-#define LBER_SEQUENCE 0x30L /* constructed */
-#define LBER_SET 0x31L /* constructed */
-
-#define OLD_LBER_SEQUENCE 0x10L /* w/o constructed bit - broken */
-#define OLD_LBER_SET 0x11L /* w/o constructed bit - broken */
-
-#ifdef NEEDPROTOS
-typedef int (*BERTranslateProc)( char **bufp, unsigned long *buflenp,
- int free_input );
-#else /* NEEDPROTOS */
-typedef int (*BERTranslateProc)();
-#endif /* NEEDPROTOS */
-
-typedef struct berelement {
- char *ber_buf;
- char *ber_ptr;
- char *ber_end;
- struct seqorset *ber_sos;
- unsigned long ber_tag;
- unsigned long ber_len;
- int ber_usertag;
- char ber_options;
+#define LBER_BOOLEAN (ber_tag_t) 0x01UL
+#define LBER_INTEGER (ber_tag_t) 0x02UL
+#define LBER_BITSTRING (ber_tag_t) 0x03UL
+#define LBER_OCTETSTRING (ber_tag_t) 0x04UL
+#define LBER_NULL (ber_tag_t) 0x05UL
+#define LBER_ENUMERATED (ber_tag_t) 0x0aUL
+#define LBER_SEQUENCE (ber_tag_t) 0x30UL /* constructed */
+#define LBER_SET (ber_tag_t) 0x31UL /* constructed */
+
+#define OLD_LBER_SEQUENCE (ber_tag_t) 0x10UL /* w/o constructed bit - broken */
+#define OLD_LBER_SET (ber_tag_t) 0x11UL /* w/o constructed bit - broken */
+
+typedef int (*BERTranslateProc) LDAP_P((
+ char **bufp,
+ ber_len_t *buflenp,
+ int free_input ));
+
+/* LBER BerElement options */
#define LBER_USE_DER 0x01
#define LBER_USE_INDEFINITE_LEN 0x02
#define LBER_TRANSLATE_STRINGS 0x04
- char *ber_rwptr;
- BERTranslateProc ber_encode_translate_proc;
- BERTranslateProc ber_decode_translate_proc;
-} BerElement;
-#define NULLBER ((BerElement *) 0)
-
-typedef struct sockbuf {
-#ifndef MACOS
- int sb_sd;
-#else /* MACOS */
- void *sb_sd;
-#endif /* MACOS */
- BerElement sb_ber;
-
- int sb_naddr; /* > 0 implies using CLDAP (UDP) */
- void *sb_useaddr; /* pointer to sockaddr to use next */
- void *sb_fromaddr; /* pointer to message source sockaddr */
- void **sb_addrs; /* actually an array of pointers to
- sockaddrs */
-
- int sb_options; /* to support copying ber elements */
-#define LBER_TO_FILE 0x01 /* to a file referenced by sb_fd */
-#define LBER_TO_FILE_ONLY 0x02 /* only write to file, not network */
-#define LBER_MAX_INCOMING_SIZE 0x04 /* impose limit on incoming stuff */
-#define LBER_NO_READ_AHEAD 0x08 /* read only as much as requested */
- int sb_fd;
- long sb_max_incoming;
-} Sockbuf;
-#define READBUFSIZ 8192
-
-typedef struct seqorset {
- BerElement *sos_ber;
- unsigned long sos_clen;
- unsigned long sos_tag;
- char *sos_first;
- char *sos_ptr;
- struct seqorset *sos_next;
-} Seqorset;
-#define NULLSEQORSET ((Seqorset *) 0)
+
+/* get/set options for BerElement */
+#define LBER_OPT_BER_OPTIONS 0x01
+#define LBER_OPT_BER_DEBUG 0x02
+
+#define LBER_OPT_DEBUG_LEVEL LBER_OPT_BER_DEBUG
+
+#define LBER_OPT_LOG_PRINT_FN 0x8001
+#define LBER_OPT_MEMORY_FNS 0x8002
+
+typedef void (*BER_LOG_PRINT_FN) LDAP_P(( char *buf ));
+
+typedef void* (*BER_MEMALLOC_FN) LDAP_P(( ber_len_t size ));
+typedef void* (*BER_MEMCALLOC_FN) LDAP_P(( ber_len_t n, ber_len_t size ));
+typedef void* (*BER_MEMREALLOC_FN) LDAP_P(( void *p, ber_len_t size ));
+typedef void (*BER_MEMFREE_FN) LDAP_P(( void *p ));
+
+typedef struct lber_memory_fns {
+ BER_MEMALLOC_FN bmf_malloc;
+ BER_MEMCALLOC_FN bmf_calloc;
+ BER_MEMREALLOC_FN bmf_realloc;
+ BER_MEMFREE_FN bmf_free;
+} BerMemoryFunctions;
+
+/* LBER Sockbuf options */
+#define LBER_TO_FILE 0x01 /* to a file referenced by sb_fd */
+#define LBER_TO_FILE_ONLY 0x02 /* only write to file, not network */
+#define LBER_MAX_INCOMING_SIZE 0x04 /* impose limit on incoming stuff */
+#define LBER_NO_READ_AHEAD 0x08 /* read only as much as requested */
+
+/* get/set options for Sockbuf */
+#define LBER_OPT_SOCKBUF_DESC 0x1000
+#define LBER_OPT_SOCKBUF_OPTIONS 0x1001
+#define LBER_OPT_SOCKBUF_DEBUG 0x1002
+
+/* on/off values */
+#define LBER_OPT_ON ((void *) 1)
+#define LBER_OPT_OFF ((void *) 0)
+
+#define LBER_OPT_SUCCESS 0
+#define LBER_OPT_ERROR (-1)
+
+typedef struct berelement BerElement;
+typedef struct sockbuf Sockbuf;
+typedef struct seqorset Seqorset;
/* structure for returning a sequence of octet strings + length */
-struct berval {
- unsigned long bv_len;
+typedef struct berval {
+ ber_len_t bv_len;
char *bv_val;
-};
-
-#ifndef NEEDPROTOS
-extern BerElement *ber_alloc();
-extern BerElement *der_alloc();
-extern BerElement *ber_alloc_t();
-extern BerElement *ber_dup();
-extern int lber_debug;
-extern void ber_bvfree();
-extern void ber_bvecfree();
-extern struct berval *ber_bvdup();
-extern void ber_dump();
-extern void ber_sos_dump();
-extern void lber_bprint();
-extern void ber_reset();
-extern void ber_init();
-#else /* NEEDPROTOS */
-#if defined(WINSOCK)
-#include "proto-lb.h"
-#else
-#include "proto-lber.h"
-#endif
-#endif /* NEEDPROTOS */
-
-#if !defined(__alpha) || defined(VMS)
-
-#define LBER_HTONL( l ) htonl( l )
-#define LBER_NTOHL( l ) ntohl( l )
-
-#else /* __alpha */
+} BerValue;
+
/*
- * htonl and ntohl on the DEC Alpha under OSF 1 seem to only swap the
- * lower-order 32-bits of a (64-bit) long, so we define correct versions
- * here.
+ * in bprint.c:
*/
-#define LBER_HTONL( l ) (((long)htonl( (l) & 0x00000000FFFFFFFF )) << 32 \
- | htonl( ( (l) & 0xFFFFFFFF00000000 ) >> 32 ))
+LDAP_F( void )
+ber_print_error LDAP_P((
+ LDAP_CONST char *data ));
+
+LDAP_F( void )
+ber_bprint LDAP_P((
+ LDAP_CONST char *data, ber_len_t len ));
+
+LDAP_F( void )
+ber_dump LDAP_P((
+ LDAP_CONST BerElement *ber, int inout ));
-#define LBER_NTOHL( l ) (((long)ntohl( (l) & 0x00000000FFFFFFFF )) << 32 \
- | ntohl( ( (l) & 0xFFFFFFFF00000000 ) >> 32 ))
-#endif /* __alpha */
+LDAP_F( void )
+ber_sos_dump LDAP_P((
+ LDAP_CONST Seqorset *sos ));
/*
- * SAFEMEMCPY is an overlap-safe copy from s to d of n bytes
+ * in decode.c:
*/
-#ifdef MACOS
-#define SAFEMEMCPY( d, s, n ) BlockMoveData( (Ptr)s, (Ptr)d, n )
-#else /* MACOS */
-#ifdef sunos4
-#define SAFEMEMCPY( d, s, n ) bcopy( s, d, n )
-#else /* sunos4 */
-#define SAFEMEMCPY( d, s, n ) memmove( d, s, n )
-#endif /* sunos4 */
-#endif /* MACOS */
-
-
-#ifdef __cplusplus
-}
-#endif
+typedef int (*BERDecodeCallback) LDAP_P((
+ BerElement *ber,
+ void *data,
+ int mode ));
+
+LDAP_F( ber_tag_t )
+ber_get_tag LDAP_P((
+ BerElement *ber ));
+
+LDAP_F( ber_tag_t )
+ber_skip_tag LDAP_P((
+ BerElement *ber,
+ ber_len_t *len ));
+
+LDAP_F( ber_tag_t )
+ber_peek_tag LDAP_P((
+ LDAP_CONST BerElement *ber,
+ ber_len_t *len ));
+
+LDAP_F( ber_tag_t )
+ber_get_int LDAP_P((
+ BerElement *ber,
+ ber_int_t *num ));
+
+LDAP_F( ber_tag_t )
+ber_get_stringb LDAP_P((
+ BerElement *ber,
+ char *buf,
+ ber_len_t *len ));
+
+LDAP_F( ber_tag_t )
+ber_get_stringa LDAP_P((
+ BerElement *ber,
+ char **buf ));
+
+LDAP_F( ber_tag_t )
+ber_get_stringal LDAP_P((
+ BerElement *ber,
+ struct berval **bv ));
+
+LDAP_F( ber_tag_t )
+ber_get_bitstringa LDAP_P((
+ BerElement *ber,
+ char **buf,
+ ber_len_t *len ));
+
+LDAP_F( ber_tag_t )
+ber_get_null LDAP_P((
+ BerElement *ber ));
+
+LDAP_F( ber_tag_t )
+ber_get_boolean LDAP_P((
+ BerElement *ber,
+ ber_int_t *boolval ));
+
+LDAP_F( ber_tag_t )
+ber_first_element LDAP_P((
+ BerElement *ber,
+ ber_len_t *len,
+ char **last ));
+
+LDAP_F( ber_tag_t )
+ber_next_element LDAP_P((
+ BerElement *ber,
+ ber_len_t *len,
+ char *last ));
+
+LDAP_F( ber_tag_t )
+ber_scanf LDAP_P((
+ BerElement *ber,
+ LDAP_CONST char *fmt,
+ ... ));
+
+LDAP_F( void )
+ber_set_string_translators LDAP_P((
+ BerElement *ber,
+ BERTranslateProc encode_proc,
+ BERTranslateProc decode_proc ));
+
+/*
+ * in encode.c
+ */
+typedef int (*BEREncodeCallback) LDAP_P((
+ BerElement *ber,
+ void *data ));
+
+LDAP_F( int )
+ber_put_enum LDAP_P((
+ BerElement *ber,
+ ber_int_t num,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_put_int LDAP_P((
+ BerElement *ber,
+ ber_int_t num,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_put_ostring LDAP_P((
+ BerElement *ber,
+ LDAP_CONST char *str,
+ ber_len_t len,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_put_berval LDAP_P((
+ BerElement *ber,
+ LDAP_CONST struct berval *bv,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_put_string LDAP_P((
+ BerElement *ber,
+ LDAP_CONST char *str,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_put_bitstring LDAP_P((
+ BerElement *ber,
+ LDAP_CONST char *str,
+ ber_len_t bitlen,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_put_null LDAP_P((
+ BerElement *ber,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_put_boolean LDAP_P((
+ BerElement *ber,
+ ber_int_t boolval,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_start_seq LDAP_P((
+ BerElement *ber,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_start_set LDAP_P((
+ BerElement *ber,
+ ber_tag_t tag ));
+
+LDAP_F( int )
+ber_put_seq LDAP_P((
+ BerElement *ber ));
+
+LDAP_F( int )
+ber_put_set LDAP_P((
+ BerElement *ber ));
+
+LDAP_F( int )
+ber_printf LDAP_P((
+ BerElement *ber,
+ LDAP_CONST char *fmt,
+ ... ));
+
+
+/*
+ * in io.c:
+ */
+
+LDAP_F( ber_slen_t )
+ber_read LDAP_P((
+ BerElement *ber,
+ char *buf,
+ ber_len_t len ));
+
+LDAP_F( ber_slen_t )
+ber_write LDAP_P((
+ BerElement *ber,
+ LDAP_CONST char *buf,
+ ber_len_t len,
+ int nosos ));
+
+LDAP_F( void )
+ber_free LDAP_P((
+ BerElement *ber,
+ int freebuf ));
+
+LDAP_F( int )
+ber_flush LDAP_P((
+ Sockbuf *sb,
+ BerElement *ber,
+ int freeit ));
+
+LDAP_F( BerElement * )
+ber_alloc LDAP_P(( void )); /* DEPRECATED */
+
+LDAP_F( BerElement * )
+der_alloc LDAP_P(( void )); /* DEPRECATED */
+
+LDAP_F( BerElement * )
+ber_alloc_t LDAP_P((
+ int beroptions ));
+
+LDAP_F( BerElement * )
+ber_dup LDAP_P((
+ LDAP_CONST BerElement *ber ));
+
+LDAP_F( ber_tag_t )
+ber_get_next LDAP_P((
+ Sockbuf *sb,
+ ber_len_t *len,
+ BerElement *ber ));
+
+LDAP_F( void )
+ber_init_w_nullc LDAP_P((
+ BerElement *ber,
+ int options ));
+
+LDAP_F( void )
+ber_reset LDAP_P((
+ BerElement *ber,
+ int was_writing ));
+
+LDAP_F( BerElement * )
+ber_init LDAP_P((
+ struct berval *bv ));
+
+LDAP_F( int )
+ber_flatten LDAP_P((
+ LDAP_CONST BerElement *ber,
+ struct berval **bvPtr ));
+
+/*
+ * LBER ber accessor functions
+ */
+
+LDAP_F( int )
+ber_get_option LDAP_P((
+ LDAP_CONST void *item,
+ int option,
+ void *outvalue));
+
+LDAP_F( int )
+ber_set_option LDAP_P((
+ void *item,
+ int option,
+ LDAP_CONST void *invalue));
+
+/*
+ * LBER sockbuf.c
+ */
+
+LDAP_F( Sockbuf * )
+ber_sockbuf_alloc( void );
+
+LDAP_F( Sockbuf * )
+ber_sockbuf_alloc_fd(
+ ber_socket_t fd );
+
+LDAP_F( void )
+ber_sockbuf_free(
+ Sockbuf *sb );
+
+/*
+ * LBER memory.c
+ */
+LDAP_F( void * )
+ber_memalloc LDAP_P((
+ ber_len_t s ));
+
+LDAP_F( void * )
+ber_memrealloc LDAP_P((
+ void* p,
+ ber_len_t s ));
+
+LDAP_F( void * )
+ber_memcalloc LDAP_P((
+ ber_len_t n,
+ ber_len_t s ));
+
+LDAP_F( void )
+ber_memfree LDAP_P((
+ void* p ));
+
+LDAP_F( void )
+ber_memvfree LDAP_P((
+ void** vector ));
+
+LDAP_F( void )
+ber_bvfree LDAP_P((
+ struct berval *bv ));
+
+LDAP_F( void )
+ber_bvecfree LDAP_P((
+ struct berval **bv ));
+
+LDAP_F( struct berval * )
+ber_bvdup LDAP_P((
+ LDAP_CONST struct berval *bv ));
+
+LDAP_F( char * )
+ber_strdup LDAP_P((
+ LDAP_CONST char * ));
+
+LDAP_END_DECL
+
#endif /* _LBER_H */
/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+/* Portions
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
#ifndef _LDAP_H
#define _LDAP_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
+#include <ldap_cdefs.h>
-#ifdef WINSOCK
-#include "msdos.h"
-#include <winsock.h>
-#endif
+/* draft spec requires ldap.h include lber declarations */
+#include <lber.h>
-#if !defined( NEEDPROTOS ) && defined(__STDC__)
-#define NEEDPROTOS 1
-#endif
+LDAP_BEGIN_DECL
-#define LDAP_PORT 389
#define LDAP_VERSION1 1
#define LDAP_VERSION2 2
-#define LDAP_VERSION LDAP_VERSION2
+#define LDAP_VERSION3 3
+
+#define LDAP_VERSION_MIN LDAP_VERSION2
+#define LDAP_VERSION LDAP_VERSION2
+#define LDAP_VERSION_MAX LDAP_VERSION3
-#define COMPAT20
-#define COMPAT30
-#if defined(COMPAT20) || defined(COMPAT30)
-#define COMPAT
+/*
+ * We'll use 2000+draft revision for our API version number
+ * As such, the number will be above the old RFC but below
+ * whatever number does finally get assigned
+ */
+#define LDAP_API_VERSION 2003
+#define LDAP_VENDOR_NAME "OpenLDAP"
+/* We'll eventually release as 200 */
+#define LDAP_VENDOR_VERSION 192
+
+/* OpenLDAP API Features */
+#define LDAP_API_FEATURE_X_OPENLDAP LDAP_VENDOR_VERSION
+
+/* include LDAP_API_FEATURE defines */
+#include <ldap_features.h>
+
+#if defined( LDAP_API_FEATURE_X_OPENLDAP_REENTRANT ) || \
+ ( defined( LDAP_THREAD_SAFE ) && \
+ defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) )
+ /* -lldap may or may not be thread safe */
+ /* -lldap_r, if available, is always thread safe */
+# define LDAP_API_FEATURE_THREAD_SAFE 1
+#endif
+#if defined( LDAP_THREAD_SAFE ) && \
+ defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE )
+/* #define LDAP_API_FEATURE_SESSION_SAFE 1 */
+/* #define LDAP_API_OPERATION_SESSION_SAFE 1 */
#endif
-#define LDAP_MAX_ATTR_LEN 100
+#define LDAP_PORT 389 /* ldap:/// default LDAP port */
+#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
+
+#define LDAP_ROOT_DSE ""
+#define LDAP_NO_ATTRS "1.1"
+#define LDAP_ALL_USER_ATTRIBUTES "*"
+#define LDAP_ALL_OPERATIONAL_ATTRIBUTES "+"
+
+/*
+ * LDAP_OPTions defined by draft-ldapext-ldap-c-api-02
+ * 0x0000 - 0x0fff reserved for api options
+ * 0x1000 - 0x3fff reserved for api extended options
+ * 0x4000 - 0x7fff reserved for private and experimental options
+ */
+#define LDAP_OPT_API_INFO 0x0000
+#define LDAP_OPT_DESC 0x0001
+#define LDAP_OPT_DEREF 0x0002
+#define LDAP_OPT_SIZELIMIT 0x0003
+#define LDAP_OPT_TIMELIMIT 0x0004
+/* 0x05 - 0x07 not defined by current draft */
+#define LDAP_OPT_REFERRALS 0x0008
+#define LDAP_OPT_RESTART 0x0009
+/* 0x0a - 0x10 not defined by current draft */
+#define LDAP_OPT_PROTOCOL_VERSION 0x0011
+#define LDAP_OPT_SERVER_CONTROLS 0x0012
+#define LDAP_OPT_CLIENT_CONTROLS 0x0013
+/* 0x14 not defined by current draft */
+#define LDAP_OPT_API_FEATURE_INFO 0x0015
+
+/* 0x16 - 0x2f not defined by current draft */
+#define LDAP_OPT_HOST_NAME 0x0030
+#define LDAP_OPT_ERROR_NUMBER 0x0031
+#define LDAP_OPT_ERROR_STRING 0x0032
+
+/* 0x33 - 0x0fff not defined by current draft */
+
+/* extended options - none */
+
+/* private and experimental options */
+#define LDAP_OPT_DNS 0x4001 /* use DN & DNS */
+
+/* OpenLDAP specific options */
+#define LDAP_OPT_DEBUG_LEVEL 0x5001 /* debug level */
+#define LDAP_OPT_TIMEOUT 0x5002 /* default timeout */
+#define LDAP_OPT_REFHOPLIMIT 0x5003 /* ref hop limit */
+#define LDAP_OPT_MATCHED_DN 0x5004 /* should have been in draft */
+#define LDAP_OPT_NETWORK_TIMEOUT 0x5005 /* socket level timeout */
+
+/* TLS options */
+#define LDAP_OPT_X_TLS_CACERTFILE 0x6001
+#define LDAP_OPT_X_TLS_CACERTDIR 0x6002
+#define LDAP_OPT_X_TLS_CERT 0x6003
+#define LDAP_OPT_X_TLS_CERTFILE 0x6004
+#define LDAP_OPT_X_TLS_KEYFILE 0x6005
+#define LDAP_OPT_X_TLS_REQUIRE_CERT 0x6006
+#define LDAP_OPT_X_TLS 0x6007
+#define LDAP_OPT_X_TLS_PROTOCOL 0x6008
+#define LDAP_OPT_X_TLS_CIPHER_SUITE 0x6009
+
+#define LDAP_OPT_X_TLS_NEVER 0
+#define LDAP_OPT_X_TLS_HARD 1
+#define LDAP_OPT_X_TLS_DEMAND 2
+#define LDAP_OPT_X_TLS_ALLOW 3
+#define LDAP_OPT_X_TLS_TRY 4
+
+/* on/off values */
+#define LDAP_OPT_ON ((void *) 1)
+#define LDAP_OPT_OFF ((void *) 0)
+
+#define LDAP_OPT_SUCCESS 0
+#define LDAP_OPT_ERROR (-1)
+
+#define LDAP_API_INFO_VERSION (1)
+typedef struct ldapapiinfo {
+ int ldapai_info_version; /* version of LDAPAPIInfo (1) */
+ int ldapai_api_version; /* revision of API supported */
+ int ldapai_protocol_version; /* highest LDAP version supported */
+ char **ldapai_extensions; /* names of API extensions */
+ char *ldapai_vendor_name; /* name of supplier */
+ int ldapai_vendor_version; /* supplier-specific version * 100 */
+} LDAPAPIInfo;
+
+#define LDAP_FEATURE_INFO_VERSION (1) /* version of api feature structure */
+typedef struct ldap_apifeature_info {
+ int ldapaif_info_version; /* version of this struct (1) */
+ char* ldapaif_name; /* matches LDAP_API_FEATURE_... less the prefix */
+ int ldapaif_version; /* matches the value LDAP_API_FEATURE_... */
+} LDAPAPIFeatureInfo;
+
+typedef struct ldapcontrol {
+ char * ldctl_oid;
+ struct berval ldctl_value;
+ char ldctl_iscritical;
+} LDAPControl;
+
+/* LDAP Controls */
+ /* chase referrals controls */
+#define LDAP_CONTROL_REFERRALS "1.2.840.113666.1.4.616"
+#define LDAP_CHASE_SUBORDINATE_REFERRALS 0x0020
+#define LDAP_CHASE_EXTERNAL_REFERRALS 0x0040
+
+#define LDAP_CONTROL_MANAGEDSAIT "2.16.16.840.1.113730.3.4.2"
+
+/* LDAP Unsolicited Notifications */
+#define LDAP_NOTICE_DISCONNECT "1.3.6.1.4.1.1466.20036"
+
+/* LDAP Extended Operations */
-/* debugging stuff */
-#ifdef LDAP_DEBUG
-extern int ldap_debug;
-#ifdef LDAP_SYSLOG
-extern int ldap_syslog;
-extern int ldap_syslog_level;
-#endif
-#define LDAP_DEBUG_TRACE 0x001
-#define LDAP_DEBUG_PACKETS 0x002
-#define LDAP_DEBUG_ARGS 0x004
-#define LDAP_DEBUG_CONNS 0x008
-#define LDAP_DEBUG_BER 0x010
-#define LDAP_DEBUG_FILTER 0x020
-#define LDAP_DEBUG_CONFIG 0x040
-#define LDAP_DEBUG_ACL 0x080
-#define LDAP_DEBUG_STATS 0x100
-#define LDAP_DEBUG_STATS2 0x200
-#define LDAP_DEBUG_SHELL 0x400
-#define LDAP_DEBUG_PARSE 0x800
-#define LDAP_DEBUG_ANY 0xffff
-
-#ifdef LDAP_SYSLOG
-#define Debug( level, fmt, arg1, arg2, arg3 ) \
- { \
- if ( ldap_debug & level ) \
- fprintf( stderr, fmt, arg1, arg2, arg3 ); \
- if ( ldap_syslog & level ) \
- syslog( ldap_syslog_level, fmt, arg1, arg2, arg3 ); \
- }
-#else /* LDAP_SYSLOG */
-#ifndef WINSOCK
-#define Debug( level, fmt, arg1, arg2, arg3 ) \
- if ( ldap_debug & level ) \
- fprintf( stderr, fmt, arg1, arg2, arg3 );
-#else /* !WINSOCK */
-extern void Debug( int level, char* fmt, ... );
-#endif /* !WINSOCK */
-#endif /* LDAP_SYSLOG */
-#else /* LDAP_DEBUG */
-#define Debug( level, fmt, arg1, arg2, arg3 )
-#endif /* LDAP_DEBUG */
/*
* specific LDAP instantiations of BER types we know about
*/
+/* Overview of LBER tag construction
+ *
+ * Bits
+ * ______
+ * 8 7 | CLASS
+ * 0 0 = UNIVERSAL
+ * 0 1 = APPLICATION
+ * 1 0 = CONTEXT-SPECIFIC
+ * 1 1 = PRIVATE
+ * _____
+ * | 6 | DATA-TYPE
+ * 0 = PRIMITIVE
+ * 1 = CONSTRUCTED
+ * ___________
+ * | 5 ... 1 | TAG-NUMBER
+ */
+
/* general stuff */
-#define LDAP_TAG_MESSAGE 0x30L /* tag is 16 + constructed bit */
-#define OLD_LDAP_TAG_MESSAGE 0x10L /* forgot the constructed bit */
-#define LDAP_TAG_MSGID 0x02L
+#define LDAP_TAG_MESSAGE (ber_tag_t) 0x30U /* constructed + 16 */
+#define LDAP_TAG_MSGID (ber_tag_t) 0x02U /* integer */
+#define LDAP_TAG_LDAPDN (ber_tag_t) 0x04U /* octect string */
+#define LDAP_TAG_LDAPCRED (ber_tag_t) 0x04U /* octect string */
+#define LDAP_TAG_CONTROLS (ber_tag_t) 0xa0U /* context specific + constructed + 0 */
+#define LDAP_TAG_REFERRAL (ber_tag_t) 0xa3U /* context specific + constructed + 3 */
-/* possible operations a client can invoke */
-#define LDAP_REQ_BIND 0x60L /* application + constructed */
-#define LDAP_REQ_UNBIND 0x42L /* application + primitive */
-#define LDAP_REQ_SEARCH 0x63L /* application + constructed */
-#define LDAP_REQ_MODIFY 0x66L /* application + constructed */
-#define LDAP_REQ_ADD 0x68L /* application + constructed */
-#define LDAP_REQ_DELETE 0x4aL /* application + primitive */
-#define LDAP_REQ_MODRDN 0x6cL /* application + constructed */
-#define LDAP_REQ_COMPARE 0x6eL /* application + constructed */
-#define LDAP_REQ_ABANDON 0x50L /* application + primitive */
-
-/* version 3.0 compatibility stuff */
-#define LDAP_REQ_UNBIND_30 0x62L
-#define LDAP_REQ_DELETE_30 0x6aL
-#define LDAP_REQ_ABANDON_30 0x70L
+#define LDAP_TAG_NEWSUPERIOR (ber_tag_t) 0x80U /* context-specific + primitive + 0 */
-/*
- * old broken stuff for backwards compatibility - forgot application tag
- * and constructed/primitive bit
- */
-#define OLD_LDAP_REQ_BIND 0x00L
-#define OLD_LDAP_REQ_UNBIND 0x02L
-#define OLD_LDAP_REQ_SEARCH 0x03L
-#define OLD_LDAP_REQ_MODIFY 0x06L
-#define OLD_LDAP_REQ_ADD 0x08L
-#define OLD_LDAP_REQ_DELETE 0x0aL
-#define OLD_LDAP_REQ_MODRDN 0x0cL
-#define OLD_LDAP_REQ_COMPARE 0x0eL
-#define OLD_LDAP_REQ_ABANDON 0x10L
+#define LDAP_TAG_EXOP_REQ_OID (ber_tag_t) 0x80U /* context specific + primitive */
+#define LDAP_TAG_EXOP_REQ_VALUE (ber_tag_t) 0x81U /* context specific + primitive */
+#define LDAP_TAG_EXOP_RES_OID (ber_tag_t) 0x8aU /* context specific + primitive */
+#define LDAP_TAG_EXOP_RES_VALUE (ber_tag_t) 0x8bU /* context specific + primitive */
+
+#define LDAP_TAG_SASL_RES_CREDS (ber_tag_t) 0x87U /* context specific + primitive */
+
+
+
+
+/* possible operations a client can invoke */
+#define LDAP_REQ_BIND (ber_tag_t) 0x60U /* application + constructed */
+#define LDAP_REQ_UNBIND (ber_tag_t) 0x42U /* application + primitive */
+#define LDAP_REQ_SEARCH (ber_tag_t) 0x63U /* application + constructed */
+#define LDAP_REQ_MODIFY (ber_tag_t) 0x66U /* application + constructed */
+#define LDAP_REQ_ADD (ber_tag_t) 0x68U /* application + constructed */
+#define LDAP_REQ_DELETE (ber_tag_t) 0x4aU /* application + primitive */
+#define LDAP_REQ_MODRDN (ber_tag_t) 0x6cU /* application + constructed */
+#define LDAP_REQ_MODDN LDAP_REQ_MODRDN
+#define LDAP_REQ_RENAME LDAP_REQ_MODRDN
+#define LDAP_REQ_COMPARE (ber_tag_t) 0x6eU /* application + constructed */
+#define LDAP_REQ_ABANDON (ber_tag_t) 0x50U /* application + primitive */
+#define LDAP_REQ_EXTENDED (ber_tag_t) 0x77U /* application + constructed */
/* possible result types a server can return */
-#define LDAP_RES_BIND 0x61L /* application + constructed */
-#define LDAP_RES_SEARCH_ENTRY 0x64L /* application + constructed */
-#define LDAP_RES_SEARCH_RESULT 0x65L /* application + constructed */
-#define LDAP_RES_MODIFY 0x67L /* application + constructed */
-#define LDAP_RES_ADD 0x69L /* application + constructed */
-#define LDAP_RES_DELETE 0x6bL /* application + constructed */
-#define LDAP_RES_MODRDN 0x6dL /* application + constructed */
-#define LDAP_RES_COMPARE 0x6fL /* application + constructed */
-#define LDAP_RES_ANY (-1L)
-
-/* old broken stuff for backwards compatibility */
-#define OLD_LDAP_RES_BIND 0x01L
-#define OLD_LDAP_RES_SEARCH_ENTRY 0x04L
-#define OLD_LDAP_RES_SEARCH_RESULT 0x05L
-#define OLD_LDAP_RES_MODIFY 0x07L
-#define OLD_LDAP_RES_ADD 0x09L
-#define OLD_LDAP_RES_DELETE 0x0bL
-#define OLD_LDAP_RES_MODRDN 0x0dL
-#define OLD_LDAP_RES_COMPARE 0x0fL
+#define LDAP_RES_BIND (ber_tag_t) 0x61U /* application + constructed */
+#define LDAP_RES_SEARCH_ENTRY (ber_tag_t) 0x64U /* application + constructed */
+#define LDAP_RES_SEARCH_REFERENCE (ber_tag_t) 0x73U /* V3: application + constructed */
+#define LDAP_RES_SEARCH_RESULT (ber_tag_t) 0x65U /* application + constructed */
+#define LDAP_RES_MODIFY (ber_tag_t) 0x67U /* application + constructed */
+#define LDAP_RES_ADD (ber_tag_t) 0x69U /* application + constructed */
+#define LDAP_RES_DELETE (ber_tag_t) 0x6bU /* application + constructed */
+#define LDAP_RES_MODRDN (ber_tag_t) 0x6dU /* application + constructed */
+#define LDAP_RES_MODDN LDAP_RES_MODRDN /* application + constructed */
+#define LDAP_RES_RENAME LDAP_RES_MODRDN /* application + constructed */
+#define LDAP_RES_COMPARE (ber_tag_t) 0x6fU /* application + constructed */
+#define LDAP_RES_EXTENDED (ber_tag_t) 0x78U /* V3: application + constructed */
+#define LDAP_RES_ANY ((ber_tag_t)(~0))
+
+
+/* sasl methods */
+#define LDAP_SASL_SIMPLE NULL
/* authentication methods available */
-#define LDAP_AUTH_NONE 0x00L /* no authentication */
-#define LDAP_AUTH_SIMPLE 0x80L /* context specific + primitive */
-#define LDAP_AUTH_KRBV4 0xffL /* means do both of the following */
-#define LDAP_AUTH_KRBV41 0x81L /* context specific + primitive */
-#define LDAP_AUTH_KRBV42 0x82L /* context specific + primitive */
-
-/* 3.0 compatibility auth methods */
-#define LDAP_AUTH_SIMPLE_30 0xa0L /* context specific + constructed */
-#define LDAP_AUTH_KRBV41_30 0xa1L /* context specific + constructed */
-#define LDAP_AUTH_KRBV42_30 0xa2L /* context specific + constructed */
-
-/* old broken stuff */
-#define OLD_LDAP_AUTH_SIMPLE 0x00L
-#define OLD_LDAP_AUTH_KRBV4 0x01L
-#define OLD_LDAP_AUTH_KRBV42 0x02L
+#define LDAP_AUTH_NONE (ber_tag_t) 0x00U /* no authentication */
+#define LDAP_AUTH_SIMPLE (ber_tag_t) 0x80U /* context specific + primitive */
+#define LDAP_AUTH_SASL (ber_tag_t) 0xa3U /* context specific + primitive */
+#define LDAP_AUTH_KRBV4 (ber_tag_t) 0xffU /* means do both of the following */
+#define LDAP_AUTH_KRBV41 (ber_tag_t) 0x81U /* context specific + primitive */
+#define LDAP_AUTH_KRBV42 (ber_tag_t) 0x82U /* context specific + primitive */
+
/* filter types */
-#define LDAP_FILTER_AND 0xa0L /* context specific + constructed */
-#define LDAP_FILTER_OR 0xa1L /* context specific + constructed */
-#define LDAP_FILTER_NOT 0xa2L /* context specific + constructed */
-#define LDAP_FILTER_EQUALITY 0xa3L /* context specific + constructed */
-#define LDAP_FILTER_SUBSTRINGS 0xa4L /* context specific + constructed */
-#define LDAP_FILTER_GE 0xa5L /* context specific + constructed */
-#define LDAP_FILTER_LE 0xa6L /* context specific + constructed */
-#define LDAP_FILTER_PRESENT 0x87L /* context specific + primitive */
-#define LDAP_FILTER_APPROX 0xa8L /* context specific + constructed */
-
-/* 3.0 compatibility filter types */
-#define LDAP_FILTER_PRESENT_30 0xa7L /* context specific + constructed */
-
-/* old broken stuff */
-#define OLD_LDAP_FILTER_AND 0x00L
-#define OLD_LDAP_FILTER_OR 0x01L
-#define OLD_LDAP_FILTER_NOT 0x02L
-#define OLD_LDAP_FILTER_EQUALITY 0x03L
-#define OLD_LDAP_FILTER_SUBSTRINGS 0x04L
-#define OLD_LDAP_FILTER_GE 0x05L
-#define OLD_LDAP_FILTER_LE 0x06L
-#define OLD_LDAP_FILTER_PRESENT 0x07L
-#define OLD_LDAP_FILTER_APPROX 0x08L
+#define LDAP_FILTER_AND (ber_tag_t) 0xa0U /* context specific + constructed */
+#define LDAP_FILTER_OR (ber_tag_t) 0xa1U /* context specific + constructed */
+#define LDAP_FILTER_NOT (ber_tag_t) 0xa2U /* context specific + constructed */
+#define LDAP_FILTER_EQUALITY (ber_tag_t) 0xa3U /* context specific + constructed */
+#define LDAP_FILTER_SUBSTRINGS (ber_tag_t) 0xa4U /* context specific + constructed */
+#define LDAP_FILTER_GE (ber_tag_t) 0xa5U /* context specific + constructed */
+#define LDAP_FILTER_LE (ber_tag_t) 0xa6U /* context specific + constructed */
+#define LDAP_FILTER_PRESENT (ber_tag_t) 0x87U /* context specific + primitive */
+#define LDAP_FILTER_APPROX (ber_tag_t) 0xa8U /* context specific + constructed */
+#define LDAP_FILTER_EXT (ber_tag_t) 0xa9U /* context specific + constructed */
+
+/* extended filter component types */
+#define LDAP_FILTER_EXT_OID (ber_tag_t) 0x81U /* context specific */
+#define LDAP_FILTER_EXT_TYPE (ber_tag_t) 0x82U /* context specific */
+#define LDAP_FILTER_EXT_VALUE (ber_tag_t) 0x83U /* context specific */
+#define LDAP_FILTER_EXT_DNATTRS (ber_tag_t) 0x84U /* context specific */
/* substring filter component types */
-#define LDAP_SUBSTRING_INITIAL 0x80L /* context specific */
-#define LDAP_SUBSTRING_ANY 0x81L /* context specific */
-#define LDAP_SUBSTRING_FINAL 0x82L /* context specific */
-
-/* 3.0 compatibility substring filter component types */
-#define LDAP_SUBSTRING_INITIAL_30 0xa0L /* context specific */
-#define LDAP_SUBSTRING_ANY_30 0xa1L /* context specific */
-#define LDAP_SUBSTRING_FINAL_30 0xa2L /* context specific */
-
-/* old broken stuff */
-#define OLD_LDAP_SUBSTRING_INITIAL 0x00L
-#define OLD_LDAP_SUBSTRING_ANY 0x01L
-#define OLD_LDAP_SUBSTRING_FINAL 0x02L
+#define LDAP_SUBSTRING_INITIAL (ber_tag_t) 0x80U /* context specific */
+#define LDAP_SUBSTRING_ANY (ber_tag_t) 0x81U /* context specific */
+#define LDAP_SUBSTRING_FINAL (ber_tag_t) 0x82U /* context specific */
/* search scopes */
-#define LDAP_SCOPE_BASE 0x00
-#define LDAP_SCOPE_ONELEVEL 0x01
-#define LDAP_SCOPE_SUBTREE 0x02
+#define LDAP_SCOPE_BASE (ber_int_t) 0x0000
+#define LDAP_SCOPE_ONELEVEL (ber_int_t) 0x0001
+#define LDAP_SCOPE_SUBTREE (ber_int_t) 0x0002
/* for modifications */
typedef struct ldapmod {
int mod_op;
-#define LDAP_MOD_ADD 0x00
-#define LDAP_MOD_DELETE 0x01
-#define LDAP_MOD_REPLACE 0x02
-#define LDAP_MOD_BVALUES 0x80
+#define LDAP_MOD_ADD (ber_int_t) 0x0000
+#define LDAP_MOD_DELETE (ber_int_t) 0x0001
+#define LDAP_MOD_REPLACE (ber_int_t) 0x0002
+#define LDAP_MOD_BVALUES (ber_int_t) 0x0080
+/* IMPORTANT: do not use code 0x1000 (or above),
+ * it is used internally by the backends!
+ * (see ldap/servers/slapd/slap.h)
+ * JCG 05/1999 (gomez@engr.sgi.com)
+ */
char *mod_type;
- union {
+ union mod_vals_u {
char **modv_strvals;
struct berval **modv_bvals;
} mod_vals;
#define mod_values mod_vals.modv_strvals
#define mod_bvalues mod_vals.modv_bvals
- struct ldapmod *mod_next;
} LDAPMod;
/*
* possible error codes we can return
*/
+#define LDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y)))
+
#define LDAP_SUCCESS 0x00
#define LDAP_OPERATIONS_ERROR 0x01
#define LDAP_PROTOCOL_ERROR 0x02
#define LDAP_SIZELIMIT_EXCEEDED 0x04
#define LDAP_COMPARE_FALSE 0x05
#define LDAP_COMPARE_TRUE 0x06
-#define LDAP_STRONG_AUTH_NOT_SUPPORTED 0x07
+#define LDAP_AUTH_METHOD_NOT_SUPPORTED 0x07
+#define LDAP_STRONG_AUTH_NOT_SUPPORTED LDAP_AUTH_METHOD_NOT_SUPPORTED
#define LDAP_STRONG_AUTH_REQUIRED 0x08
-#define LDAP_PARTIAL_RESULTS 0x09
+#define LDAP_PARTIAL_RESULTS 0x09 /* not listed in v3 */
+
+#define LDAP_REFERRAL 0x0a /* LDAPv3 */
+#define LDAP_ADMINLIMIT_EXCEEDED 0x0b /* LDAPv3 */
+#define LDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c /* LDAPv3 */
+#define LDAP_CONFIDENTIALITY_REQUIRED 0x0d /* LDAPv3 */
+#define LDAP_SASL_BIND_IN_PROGRESS 0x0e /* LDAPv3 */
+
+#define LDAP_ATTR_ERROR(n) LDAP_RANGE((n),0x10,0x15) /* 16-21 */
#define LDAP_NO_SUCH_ATTRIBUTE 0x10
#define LDAP_UNDEFINED_TYPE 0x11
#define LDAP_TYPE_OR_VALUE_EXISTS 0x14
#define LDAP_INVALID_SYNTAX 0x15
+#define LDAP_NAME_ERROR(n) LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */
+
#define LDAP_NO_SUCH_OBJECT 0x20
#define LDAP_ALIAS_PROBLEM 0x21
#define LDAP_INVALID_DN_SYNTAX 0x22
-#define LDAP_IS_LEAF 0x23
+#define LDAP_IS_LEAF 0x23 /* not LDAPv3 */
#define LDAP_ALIAS_DEREF_PROBLEM 0x24
-#define NAME_ERROR(n) ((n & 0xf0) == 0x20)
+#define LDAP_SECURITY_ERROR(n) LDAP_RANGE((n),0x30,0x32) /* 48-50 */
#define LDAP_INAPPROPRIATE_AUTH 0x30
#define LDAP_INVALID_CREDENTIALS 0x31
#define LDAP_INSUFFICIENT_ACCESS 0x32
+
+#define LDAP_SERVICE_ERROR(n) LDAP_RANGE((n),0x33,0x36) /* 51-54 */
+
#define LDAP_BUSY 0x33
#define LDAP_UNAVAILABLE 0x34
#define LDAP_UNWILLING_TO_PERFORM 0x35
#define LDAP_LOOP_DETECT 0x36
+#define LDAP_UPDATE_ERROR(n) LDAP_RANGE((n),0x40,0x47) /* 64-69,71 */
+
#define LDAP_NAMING_VIOLATION 0x40
#define LDAP_OBJECT_CLASS_VIOLATION 0x41
#define LDAP_NOT_ALLOWED_ON_NONLEAF 0x42
#define LDAP_NOT_ALLOWED_ON_RDN 0x43
#define LDAP_ALREADY_EXISTS 0x44
#define LDAP_NO_OBJECT_CLASS_MODS 0x45
-#define LDAP_RESULTS_TOO_LARGE 0x46
+#define LDAP_RESULTS_TOO_LARGE 0x46 /* CLDAP */
+#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 /* LDAPv3 */
#define LDAP_OTHER 0x50
+
+#define LDAP_API_ERROR(n) LDAP_RANGE((n),0x51,0xff) /* 81+ */
+
#define LDAP_SERVER_DOWN 0x51
#define LDAP_LOCAL_ERROR 0x52
#define LDAP_ENCODING_ERROR 0x53
#define LDAP_PARAM_ERROR 0x59
#define LDAP_NO_MEMORY 0x5a
-
-/* default limit on nesting of referrals */
-#define LDAP_DEFAULT_REFHOPLIMIT 5
+#define LDAP_CONNECT_ERROR 0x5b /* new */
+#define LDAP_NOT_SUPPORTED 0x5c /* new */
+#define LDAP_CONTROL_NOT_FOUND 0x5d /* new */
+#define LDAP_NO_RESULTS_RETURNED 0x5e /* new */
+#define LDAP_MORE_RESULTS_TO_RETURN 0x5f /* new */
+#define LDAP_CLIENT_LOOP 0x60 /* new */
+#define LDAP_REFERRAL_LIMIT_EXCEEDED 0x61 /* new */
/*
* This structure represents both ldap messages and ldap responses.
* where a response has multiple messages.
*/
-typedef struct ldapmsg {
- int lm_msgid; /* the message id */
- int lm_msgtype; /* the message type */
- BerElement *lm_ber; /* the ber encoded message contents */
- struct ldapmsg *lm_chain; /* for search - next msg in the resp */
- struct ldapmsg *lm_next; /* next response */
- unsigned long lm_time; /* used to maintain cache */
-} LDAPMessage;
-#define NULLMSG ((LDAPMessage *) NULL)
-
-
-#ifdef LDAP_REFERRALS
-/*
- * structure for tracking LDAP server host, ports, DNs, etc.
- */
-typedef struct ldap_server {
- char *lsrv_host;
- char *lsrv_dn; /* if NULL, use default */
- int lsrv_port;
- struct ldap_server *lsrv_next;
-} LDAPServer;
-
-
-/*
- * structure for representing an LDAP server connection
- */
-typedef struct ldap_conn {
- Sockbuf *lconn_sb;
- int lconn_refcnt;
- unsigned long lconn_lastused; /* time */
- int lconn_status;
-#define LDAP_CONNST_NEEDSOCKET 1
-#define LDAP_CONNST_CONNECTING 2
-#define LDAP_CONNST_CONNECTED 3
- LDAPServer *lconn_server;
- char *lconn_krbinstance;
- struct ldap_conn *lconn_next;
-} LDAPConn;
-
-
-/*
- * structure used to track outstanding requests
- */
-typedef struct ldapreq {
- int lr_msgid; /* the message id */
- int lr_status; /* status of request */
-#define LDAP_REQST_INPROGRESS 1
-#define LDAP_REQST_CHASINGREFS 2
-#define LDAP_REQST_NOTCONNECTED 3
-#define LDAP_REQST_WRITING 4
- int lr_outrefcnt; /* count of outstanding referrals */
- int lr_origid; /* original request's message id */
- int lr_parentcnt; /* count of parent requests */
- int lr_res_msgtype; /* result message type */
- int lr_res_errno; /* result LDAP errno */
- char *lr_res_error; /* result error string */
- char *lr_res_matched;/* result matched DN string */
- BerElement *lr_ber; /* ber encoded request contents */
- LDAPConn *lr_conn; /* connection used to send request */
- struct ldapreq *lr_parent; /* request that spawned this referral */
- struct ldapreq *lr_refnext; /* next referral spawned */
- struct ldapreq *lr_prev; /* previous request */
- struct ldapreq *lr_next; /* next request */
-} LDAPRequest;
-#endif /* LDAP_REFERRALS */
-
-
-/*
- * structure for client cache
- */
-#define LDAP_CACHE_BUCKETS 31 /* cache hash table size */
-typedef struct ldapcache {
- LDAPMessage *lc_buckets[LDAP_CACHE_BUCKETS];/* hash table */
- LDAPMessage *lc_requests; /* unfulfilled reqs */
- long lc_timeout; /* request timeout */
- long lc_maxmem; /* memory to use */
- long lc_memused; /* memory in use */
- int lc_enabled; /* enabled? */
- unsigned long lc_options; /* options */
-#define LDAP_CACHE_OPT_CACHENOERRS 0x00000001
-#define LDAP_CACHE_OPT_CACHEALLERRS 0x00000002
-} LDAPCache;
-#define NULLLDCACHE ((LDAPCache *)NULL)
+typedef struct ldapmsg LDAPMessage;
/*
* structures for ldap getfilter routines
* structure representing an ldap connection
*/
-typedef struct ldap {
- Sockbuf ld_sb; /* socket descriptor & buffer */
- char *ld_host;
- int ld_version;
- char ld_lberoptions;
- int ld_deref;
-#define LDAP_DEREF_NEVER 0
-#define LDAP_DEREF_SEARCHING 1
-#define LDAP_DEREF_FINDING 2
-#define LDAP_DEREF_ALWAYS 3
+typedef struct ldap LDAP;
- int ld_timelimit;
- int ld_sizelimit;
-#define LDAP_NO_LIMIT 0
+#define LDAP_DEREF_NEVER 0x00
+#define LDAP_DEREF_SEARCHING 0x01
+#define LDAP_DEREF_FINDING 0x02
+#define LDAP_DEREF_ALWAYS 0x03
- LDAPFiltDesc *ld_filtd; /* from getfilter for ufn searches */
- char *ld_ufnprefix; /* for incomplete ufn's */
-
- int ld_errno;
- char *ld_error;
- char *ld_matched;
- int ld_msgid;
-
- /* do not mess with these */
-#ifdef LDAP_REFERRALS
- LDAPRequest *ld_requests; /* list of outstanding requests */
-#else /* LDAP_REFERRALS */
- LDAPMessage *ld_requests; /* list of outstanding requests */
-#endif /* LDAP_REFERRALS */
- LDAPMessage *ld_responses; /* list of outstanding responses */
- int *ld_abandoned; /* array of abandoned requests */
- char ld_attrbuffer[LDAP_MAX_ATTR_LEN];
- LDAPCache *ld_cache; /* non-null if cache is initialized */
- char *ld_cldapdn; /* DN used in connectionless search */
-
- /* it is OK to change these next four values directly */
- int ld_cldaptries; /* connectionless search retry count */
- int ld_cldaptimeout;/* time between retries */
- int ld_refhoplimit; /* limit on referral nesting */
- unsigned long ld_options; /* boolean options */
-#ifdef LDAP_DNS
-#define LDAP_OPT_DNS 0x00000001 /* use DN & DNS */
-#endif /* LDAP_DNS */
-#ifdef LDAP_REFERRALS
-#define LDAP_OPT_REFERRALS 0x00000002 /* chase referrals */
-#endif /* LDAP_REFERRALS */
-#define LDAP_OPT_RESTART 0x00000004 /* restart if EINTR occurs */
-
- /* do not mess with the rest though */
- char *ld_defhost; /* full name of default server */
- int ld_defport; /* port of default server */
- BERTranslateProc ld_lber_encode_translate_proc;
- BERTranslateProc ld_lber_decode_translate_proc;
-#ifdef LDAP_REFERRALS
- LDAPConn *ld_defconn; /* default connection */
- LDAPConn *ld_conns; /* list of server connections */
- void *ld_selectinfo; /* platform specifics for select */
- int (*ld_rebindproc)( struct ldap *ld, char **dnp,
- char **passwdp, int *authmethodp, int freeit );
- /* routine to get info needed for re-bind */
-#endif /* LDAP_REFERRALS */
-} LDAP;
+#define LDAP_NO_LIMIT 0
+/* how many messages to retrieve results for */
+#define LDAP_MSG_ONE 0x00
+#define LDAP_MSG_ALL 0x01
+#define LDAP_MSG_RECEIVED 0x02
/*
* structure for ldap friendly mapping routines
*/
-typedef struct friendly {
- char *f_unfriendly;
- char *f_friendly;
-} FriendlyMap;
-
-
-/*
- * handy macro to check whether LDAP struct is set up for CLDAP or not
- */
-#define LDAP_IS_CLDAP( ld ) ( ld->ld_sb.sb_naddr > 0 )
-
+typedef struct ldap_friendly {
+ char *lf_unfriendly;
+ char *lf_friendly;
+} LDAPFriendlyMap;
/*
* types for ldap URL handling
*/
typedef struct ldap_url_desc {
+ int lud_ldaps;
char *lud_host;
int lud_port;
char *lud_dn;
char **lud_attrs;
int lud_scope;
char *lud_filter;
- char *lud_string; /* for internal use only */
+ char **lud_exts;
} LDAPURLDesc;
-#define NULLLDAPURLDESC ((LDAPURLDesc *)NULL)
-
-#define LDAP_URL_ERR_NOTLDAP 1 /* URL doesn't begin with "ldap://" */
-#define LDAP_URL_ERR_NODN 2 /* URL has no DN (required) */
-#define LDAP_URL_ERR_BADSCOPE 3 /* URL scope string is invalid */
-#define LDAP_URL_ERR_MEM 4 /* can't allocate memory space */
-
-
-#ifndef NEEDPROTOS
-extern LDAP *ldap_open();
-extern LDAP *ldap_init();
-#ifdef STR_TRANSLATION
-extern void ldap_set_string_translators();
-#ifdef LDAP_CHARSET_8859
-extern int ldap_t61_to_8859();
-extern int ldap_8859_to_t61();
-#endif /* LDAP_CHARSET_8859 */
-#endif /* STR_TRANSLATION */
-extern LDAPMessage *ldap_first_entry();
-extern LDAPMessage *ldap_next_entry();
-extern char *ldap_get_dn();
-extern char *ldap_dn2ufn();
-extern char **ldap_explode_dn();
-extern char *ldap_first_attribute();
-extern char *ldap_next_attribute();
-extern char **ldap_get_values();
-extern struct berval **ldap_get_values_len();
-extern void ldap_value_free();
-extern void ldap_value_free_len();
-extern int ldap_count_values();
-extern int ldap_count_values_len();
-extern char *ldap_err2string();
-extern void ldap_getfilter_free();
-extern LDAPFiltDesc *ldap_init_getfilter();
-extern LDAPFiltDesc *ldap_init_getfilter_buf();
-extern LDAPFiltInfo *ldap_getfirstfilter();
-extern LDAPFiltInfo *ldap_getnextfilter();
-extern void ldap_setfilteraffixes();
-extern void ldap_build_filter();
-extern void ldap_flush_cache();
-extern void ldap_set_cache_options();
-extern void ldap_uncache_entry();
-extern void ldap_uncache_request();
-extern char *ldap_friendly_name();
-extern void ldap_free_friendlymap();
-extern LDAP *cldap_open();
-extern void cldap_setretryinfo();
-extern void cldap_close();
-extern LDAPFiltDesc *ldap_ufn_setfilter();
-extern int ldap_ufn_timeout();
-extern int ldap_sort_entries();
-extern int ldap_sort_values();
-extern int ldap_sort_strcasecmp();
-void ldap_free_urldesc();
-void ldap_set_rebind_proc();
-void ldap_enable_translation();
-
-
-#if defined(ultrix) || defined(VMS) || defined( nextstep )
-extern char *strdup();
-#endif
-#else /* NEEDPROTOS */
-#if !defined(MACOS) && !defined(DOS) && !defined(_WIN32) && !defined(WINSOCK)
-#include <sys/time.h>
-#endif
-#if defined(WINSOCK)
-#include "proto-ld.h"
-#else
-#include "proto-ldap.h"
-#endif
+#define LDAP_URL_SUCCESS 0x00 /* Success */
+#define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */
+#define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */
-#ifdef VMS
-extern char *strdup( const char *s );
-#endif
-#if defined(ultrix) || defined( nextstep )
-extern char *strdup();
-#endif
+#define LDAP_URL_ERR_NOTLDAP 0x03 /* URL doesn't begin with "ldap[s]://" */
+#define LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */
+#define LDAP_URL_ERR_BADURL 0x05 /* URL is bad */
+#define LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */
+#define LDAP_URL_ERR_BADATTRS 0x07 /* bad (or missing) attributes */
+#define LDAP_URL_ERR_BADSCOPE 0x08 /* scope string is invalid (or missing) */
+#define LDAP_URL_ERR_BADFILTER 0x09 /* bad or missing filter */
+#define LDAP_URL_ERR_BADEXTS 0x0a /* bad or missing extensions */
-#endif /* NEEDPROTOS */
+/*
+ * The API draft spec says we should declare (or cause to be declared)
+ * 'struct timeval'. We don't. See LDAPext discussions.
+ */
+struct timeval;
+
+/*
+ * in options.c:
+ */
+LDAP_F( int )
+ldap_get_option LDAP_P((
+ LDAP_CONST LDAP *ld,
+ int option,
+ void *outvalue));
+
+LDAP_F( int )
+ldap_set_option LDAP_P((
+ LDAP *ld,
+ int option,
+ LDAP_CONST void *invalue));
+
+
+/*
+ * in controls.c:
+ */
+LDAP_F( void )
+ldap_control_free LDAP_P((
+ LDAPControl *ctrl ));
+
+LDAP_F( void )
+ldap_controls_free LDAP_P((
+ LDAPControl **ctrls ));
+
+
+/*
+ * in extended.c:
+ */
+LDAP_F( int )
+ldap_extended_operation LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *reqoid,
+ struct berval *reqdata,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_extended_operation_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *reqoid,
+ struct berval *reqdata,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ char **retoidp,
+ struct berval **retdatap ));
+
+LDAP_F( int )
+ldap_parse_extended_result LDAP_P((
+ LDAP *ld,
+ LDAPMessage *res,
+ char **retoidp,
+ struct berval **retdatap,
+ int freeit ));
+
+/*
+ * in abandon.c:
+ */
+LDAP_F( int )
+ldap_abandon LDAP_P((
+ LDAP *ld,
+ int msgid ));
+
+LDAP_F( int )
+ldap_abandon_ext LDAP_P((
+ LDAP *ld,
+ int msgid,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+
+/*
+ * in add.c:
+ */
+LDAP_F( int )
+ldap_add_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_add_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_add LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs ));
+
+LDAP_F( int )
+ldap_add_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs ));
+
+
+/*
+ * in sasl.c:
+ */
+LDAP_F( int )
+ldap_sasl_bind LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *mechanism,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_sasl_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *mechanism,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct berval **servercredp ));
+
+LDAP_F( int )
+ldap_parse_sasl_bind_result LDAP_P((
+ LDAP *ld,
+ LDAPMessage *res,
+ struct berval **servercredp,
+ int freeit ));
+
+/*
+ * in bind.c:
+ * (deprecated)
+ */
+LDAP_F( int )
+ldap_bind LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *passwd,
+ int authmethod ));
+
+LDAP_F( int )
+ldap_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *cred,
+ int authmethod ));
+
+LDAP_F( void )
+ldap_set_rebind_proc LDAP_P((
+ LDAP *ld,
+ int (*rebindproc) LDAP_P((
+ LDAP *ld,
+ char **dnp,
+ char **passwdp,
+ int *authmethodp,
+ int freeit ))));
+
+
+/*
+ * in sbind.c:
+ */
+LDAP_F( int )
+ldap_simple_bind LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *passwd ));
+
+LDAP_F( int )
+ldap_simple_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *passwd ));
+
+
+/*
+ * in kbind.c:
+ * (deprecated)
+ */
+LDAP_F( int )
+ldap_kerberos_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind1 LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind1_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind2 LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind2_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+/*
+ * in cache.c
+ * (deprecated)
+ */
+LDAP_F( int )
+ldap_enable_cache LDAP_P(( LDAP *ld, long timeout, ber_len_t maxmem ));
+
+LDAP_F( void )
+ldap_disable_cache LDAP_P(( LDAP *ld ));
+
+LDAP_F( void )
+ldap_set_cache_options LDAP_P(( LDAP *ld, unsigned long opts ));
+
+LDAP_F( void )
+ldap_destroy_cache LDAP_P(( LDAP *ld ));
+
+LDAP_F( void )
+ldap_flush_cache LDAP_P(( LDAP *ld ));
+
+LDAP_F( void )
+ldap_uncache_entry LDAP_P(( LDAP *ld, LDAP_CONST char *dn ));
+
+LDAP_F( void )
+ldap_uncache_request LDAP_P(( LDAP *ld, int msgid ));
+
+
+/*
+ * in compare.c:
+ */
+LDAP_F( int )
+ldap_compare_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *attr,
+ struct berval *bvalue,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_compare_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *attr,
+ struct berval *bvalue,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_compare LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *attr,
+ LDAP_CONST char *value ));
+
+LDAP_F( int )
+ldap_compare_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *attr,
+ LDAP_CONST char *value ));
+
+
+/*
+ * in delete.c:
+ */
+LDAP_F( int )
+ldap_delete_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_delete_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_delete LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn ));
+
+LDAP_F( int )
+ldap_delete_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn ));
+
+
+/*
+ * in error.c:
+ */
+LDAP_F( int )
+ldap_parse_result LDAP_P((
+ LDAP *ld,
+ LDAPMessage *res,
+ int *errcodep,
+ char **matcheddnp,
+ char **errmsgp,
+ char ***referralsp,
+ LDAPControl ***serverctrls,
+ int freeit ));
+
+LDAP_F( char *)
+ldap_err2string LDAP_P((
+ int err ));
+
+LDAP_F( int )
+ldap_result2error LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAPMessage *r,
+ int freeit ));
+
+LDAP_F( void )
+ldap_perror LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *s ));
+
+
+/*
+ * in modify.c:
+ */
+LDAP_F( int )
+ldap_modify_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_modify_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_modify LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods ));
+
+LDAP_F( int )
+ldap_modify_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods ));
+
+
+/*
+ * in modrdn.c:
+ */
+LDAP_F( int )
+ldap_rename_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ LDAP_CONST char *newparent,
+ int deleteoldrdn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_rename_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ LDAP_CONST char *newparent,
+ int deleteoldrdn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_rename2 LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn,
+ LDAP_CONST char *newSuperior ));
+
+LDAP_F( int )
+ldap_rename2_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn,
+ LDAP_CONST char *newSuperior));
+
+LDAP_F( int )
+ldap_modrdn LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn ));
+
+LDAP_F( int )
+ldap_modrdn_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn ));
+
+LDAP_F( int )
+ldap_modrdn2 LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn ));
+
+LDAP_F( int )
+ldap_modrdn2_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn));
+
+
+/*
+ * in open.c:
+ */
+LDAP_F( LDAP *)
+ldap_open LDAP_P((
+ LDAP_CONST char *host,
+ int port ));
+
+LDAP_F( LDAP *)
+ldap_init LDAP_P((
+ LDAP_CONST char *host,
+ int port ));
+
+
+/*
+ * in messages.c:
+ */
+LDAP_F( LDAPMessage *)
+ldap_first_message LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( LDAPMessage *)
+ldap_next_message LDAP_P((
+ LDAP *ld,
+ LDAPMessage *msg ));
+
+LDAP_F( int )
+ldap_count_messages LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+
+/*
+ * in references.c:
+ */
+LDAP_F( LDAPMessage *)
+ldap_first_reference LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( LDAPMessage *)
+ldap_next_reference LDAP_P((
+ LDAP *ld,
+ LDAPMessage *ref ));
+
+LDAP_F( int )
+ldap_count_references LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( int )
+ldap_parse_reference LDAP_P((
+ LDAP *ld,
+ LDAPMessage *ref,
+ char ***referralsp,
+ LDAPControl ***serverctrls,
+ int freeit));
+
+
+/*
+ * in getentry.c:
+ */
+LDAP_F( LDAPMessage *)
+ldap_first_entry LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( LDAPMessage *)
+ldap_next_entry LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry ));
+
+LDAP_F( int )
+ldap_count_entries LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( int )
+ldap_get_entry_controls LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAPControl ***serverctrls));
+
+
+/*
+ * in addentry.c
+ */
+LDAP_F( LDAPMessage *)
+ldap_delete_result_entry LDAP_P((
+ LDAPMessage **list,
+ LDAPMessage *e ));
+
+LDAP_F( void )
+ldap_add_result_entry LDAP_P((
+ LDAPMessage **list,
+ LDAPMessage *e ));
+
+
+/*
+ * in getdn.c
+ */
+LDAP_F( char *)
+ldap_get_dn LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry ));
+
+LDAP_F( char *)
+ldap_dn2ufn LDAP_P((
+ LDAP_CONST char *dn ));
+
+LDAP_F( char **)
+ldap_explode_dn LDAP_P((
+ LDAP_CONST char *dn,
+ int notypes ));
+
+LDAP_F( char **)
+ldap_explode_rdn LDAP_P((
+ LDAP_CONST char *rdn,
+ int notypes ));
+
+LDAP_F( char *)
+ldap_parent_dn LDAP_P(( /* new (from slapd) */
+ LDAP_CONST char *dn ));
+
+LDAP_F( char *)
+ldap_relative_dn LDAP_P(( /* new (from slapd) */
+ LDAP_CONST char *dn ));
+
+LDAP_F( char *)
+ldap_normalize_dn LDAP_P(( /* new (from slapd) */
+ LDAP_CONST char *dn ));
+
+LDAP_F( char **)
+ldap_explode_dns LDAP_P(( /* deprecated */
+ LDAP_CONST char *dn ));
+
+LDAP_F( int )
+ldap_is_dns_dn LDAP_P(( /* deprecated */
+ LDAP_CONST char *dn ));
+
+
+/*
+ * in getattr.c
+ */
+LDAP_F( char *)
+ldap_first_attribute LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ BerElement **ber ));
+
+LDAP_F( char *)
+ldap_next_attribute LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ BerElement *ber ));
+
+
+/*
+ * in getvalues.c
+ */
+LDAP_F( char **)
+ldap_get_values LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAP_CONST char *target ));
+
+LDAP_F( struct berval **)
+ldap_get_values_len LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAP_CONST char *target ));
+
+LDAP_F( int )
+ldap_count_values LDAP_P((
+ char **vals ));
+
+LDAP_F( int )
+ldap_count_values_len LDAP_P((
+ struct berval **vals ));
+
+LDAP_F( void )
+ldap_value_free LDAP_P((
+ char **vals ));
+
+LDAP_F( void )
+ldap_value_free_len LDAP_P((
+ struct berval **vals ));
+
+/*
+ * in result.c:
+ */
+LDAP_F( int )
+ldap_result LDAP_P((
+ LDAP *ld,
+ int msgid,
+ int all,
+ struct timeval *timeout,
+ LDAPMessage **result ));
+
+LDAP_F( int )
+ldap_msgtype LDAP_P((
+ LDAPMessage *lm ));
+
+LDAP_F( int )
+ldap_msgid LDAP_P((
+ LDAPMessage *lm ));
+
+LDAP_F( int )
+ldap_msgfree LDAP_P((
+ LDAPMessage *lm ));
+
+LDAP_F( int )
+ldap_msgdelete LDAP_P((
+ LDAP *ld,
+ int msgid ));
+
+
+/*
+ * in search.c:
+ */
+LDAP_F( int )
+ldap_search_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct timeval *timeout,
+ int sizelimit,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_search_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct timeval *timeout,
+ int sizelimit,
+ LDAPMessage **res ));
+
+LDAP_F( int )
+ldap_search LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly ));
+
+LDAP_F( int )
+ldap_search_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res ));
+
+LDAP_F( int )
+ldap_search_st LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ struct timeval *timeout,
+ LDAPMessage **res ));
+
+
+/*
+ * in ufn.c
+ */
+LDAP_F( int )
+ldap_ufn_search_c LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *ufn,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res,
+ int (*cancelproc)( void *cl ),
+ void *cancelparm ));
+
+LDAP_F( int )
+ldap_ufn_search_ct LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *ufn,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res,
+ int (*cancelproc)( void *cl ),
+ void *cancelparm,
+ char *tag1,
+ char *tag2,
+ char *tag3 ));
+
+LDAP_F( int )
+ldap_ufn_search_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *ufn,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res ));
+
+LDAP_F( LDAPFiltDesc *)
+ldap_ufn_setfilter LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *fname ));
+
+LDAP_F( void )
+ldap_ufn_setprefix LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *prefix ));
+
+LDAP_F( int )
+ldap_ufn_timeout LDAP_P((
+ void *tvparam ));
+
+
+/*
+ * in unbind.c
+ */
+LDAP_F( int )
+ldap_unbind LDAP_P((
+ LDAP *ld ));
+
+LDAP_F( int )
+ldap_unbind_s LDAP_P((
+ LDAP *ld ));
+
+LDAP_F( int )
+ldap_unbind_ext LDAP_P((
+ LDAP *ld,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls));
+
+LDAP_F( int )
+ldap_unbind_ext_s LDAP_P((
+ LDAP *ld,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls));
+
+/*
+ * in getfilter.c
+ */
+LDAP_F( LDAPFiltDesc *)
+ldap_init_getfilter LDAP_P((
+ LDAP_CONST char *fname ));
+
+LDAP_F( LDAPFiltDesc *)
+ldap_init_getfilter_buf LDAP_P((
+ /* LDAP_CONST */ char *buf,
+ ber_len_t buflen ));
+
+LDAP_F( LDAPFiltInfo *)
+ldap_getfirstfilter LDAP_P((
+ LDAPFiltDesc *lfdp,
+ /* LDAP_CONST */ char *tagpat,
+ /* LDAP_CONST */ char *value ));
+
+LDAP_F( LDAPFiltInfo *)
+ldap_getnextfilter LDAP_P((
+ LDAPFiltDesc *lfdp ));
+
+LDAP_F( void )
+ldap_setfilteraffixes LDAP_P((
+ LDAPFiltDesc *lfdp,
+ LDAP_CONST char *prefix,
+ LDAP_CONST char *suffix ));
+
+LDAP_F( void )
+ldap_build_filter LDAP_P((
+ char *buf,
+ ber_len_t buflen,
+ LDAP_CONST char *pattern,
+ LDAP_CONST char *prefix,
+ LDAP_CONST char *suffix,
+ LDAP_CONST char *attr,
+ LDAP_CONST char *value,
+ char **valwords ));
+
+
+/*
+ * in free.c
+ */
+
+LDAP_F( void * )
+ldap_memalloc LDAP_P((
+ ber_len_t s ));
+
+LDAP_F( void * )
+ldap_memrealloc LDAP_P((
+ void* p,
+ ber_len_t s ));
+
+LDAP_F( void * )
+ldap_memcalloc LDAP_P((
+ ber_len_t n,
+ ber_len_t s ));
+
+LDAP_F( void )
+ldap_memfree LDAP_P((
+ void* p ));
+
+LDAP_F( void )
+ldap_memvfree LDAP_P((
+ void** v ));
+
+LDAP_F( char * )
+ldap_strdup LDAP_P((
+ LDAP_CONST char * ));
+
+LDAP_F( void )
+ldap_getfilter_free LDAP_P((
+ LDAPFiltDesc *lfdp ));
+
+LDAP_F( void )
+ldap_mods_free LDAP_P((
+ LDAPMod **mods,
+ int freemods ));
+
+
+/*
+ * in friendly.c
+ */
+LDAP_F( char * )
+ldap_friendly_name LDAP_P((
+ LDAP_CONST char *filename,
+ /* LDAP_CONST */ char *uname,
+ LDAPFriendlyMap **map ));
+
+LDAP_F( void )
+ldap_free_friendlymap LDAP_P((
+ LDAPFriendlyMap **map ));
+
+
+/*
+ * in cldap.c
+ */
+LDAP_F( LDAP * )
+cldap_open LDAP_P((
+ LDAP_CONST char *host,
+ int port ));
+
+LDAP_F( void )
+cldap_close LDAP_P((
+ LDAP *ld ));
+
+LDAP_F( int )
+cldap_search_s LDAP_P(( LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res,
+ char *logdn ));
+
+LDAP_F( void )
+cldap_setretryinfo LDAP_P((
+ LDAP *ld,
+ int tries,
+ int timeout ));
+
+
+/*
+ * in sort.c
+ */
+LDAP_F( int )
+ldap_sort_entries LDAP_P(( LDAP *ld,
+ LDAPMessage **chain,
+ LDAP_CONST char *attr,
+ int (*cmp) (LDAP_CONST char *, LDAP_CONST char *) ));
+
+LDAP_F( int )
+ldap_sort_values LDAP_P((
+ LDAP *ld,
+ char **vals,
+ int (*cmp) (LDAP_CONST void *, LDAP_CONST void *) ));
+
+LDAP_F( int )
+ldap_sort_strcasecmp LDAP_P((
+ LDAP_CONST void *a,
+ LDAP_CONST void *b ));
+
+
+/*
+ * in url.c
+ *
+ * need _ext varients
+ */
+LDAP_F( int )
+ldap_is_ldap_url LDAP_P((
+ LDAP_CONST char *url ));
+
+LDAP_F( int )
+ldap_is_ldaps_url LDAP_P((
+ LDAP_CONST char *url ));
+
+LDAP_F( int )
+ldap_url_parse LDAP_P((
+ LDAP_CONST char *url,
+ LDAPURLDesc **ludpp ));
+
+LDAP_F( void )
+ldap_free_urldesc LDAP_P((
+ LDAPURLDesc *ludp ));
+
+LDAP_F( int )
+ldap_url_search LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *url,
+ int attrsonly ));
+
+LDAP_F( int )
+ldap_url_search_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *url,
+ int attrsonly,
+ LDAPMessage **res ));
+
+LDAP_F( int )
+ldap_url_search_st LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *url,
+ int attrsonly,
+ struct timeval *timeout,
+ LDAPMessage **res ));
+
+
+/*
+ * in charset.c
+ * DEPRECATED
+ */
+LDAP_F( void )
+ldap_set_string_translators LDAP_P((
+ LDAP *ld,
+ BERTranslateProc encode_proc,
+ BERTranslateProc decode_proc ));
+
+LDAP_F( int )
+ldap_translate_from_t61 LDAP_P((
+ LDAP *ld,
+ char **bufp,
+ ber_len_t *lenp,
+ int free_input ));
+
+LDAP_F( int )
+ldap_translate_to_t61 LDAP_P((
+ LDAP *ld,
+ char **bufp,
+ ber_len_t *lenp,
+ int free_input ));
+
+LDAP_F( void )
+ldap_enable_translation LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ int enable ));
+
+LDAP_F( int )
+ldap_t61_to_8859 LDAP_P((
+ char **bufp,
+ ber_len_t *buflenp,
+ int free_input ));
+
+LDAP_F( int )
+ldap_8859_to_t61 LDAP_P((
+ char **bufp,
+ ber_len_t *buflenp,
+ int free_input ));
+
+LDAP_END_DECL
-#ifdef __cplusplus
-}
-#endif
#endif /* _LDAP_H */
--- /dev/null
+/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+/*
+ * ldap-pvt.h - Header for ldap_pvt_ functions. These are meant to be used
+ * by the OpenLDAP distribution only.
+ */
+
+#ifndef _LDAP_PVT_H
+#define _LDAP_PVT_H 1
+
+#include <ldap_cdefs.h>
+
+LDAP_BEGIN_DECL
+
+struct hostent; /* avoid pulling in <netdb.h> */
+
+LDAP_F( char * )
+ldap_pvt_ctime LDAP_P((
+ const time_t *tp,
+ char *buf ));
+
+LDAP_F( int )
+ldap_pvt_gethostbyname_a LDAP_P((
+ const char *name,
+ struct hostent *resbuf,
+ char **buf,
+ struct hostent **result,
+ int *herrno_ptr ));
+
+LDAP_F( int )
+ldap_pvt_gethostbyaddr_a LDAP_P((
+ const char *addr,
+ int len,
+ int type,
+ struct hostent *resbuf,
+ char **buf,
+ struct hostent **result,
+ int *herrno_ptr ));
+
+
+/* charray.c */
+
+LDAP_F( int )
+ldap_charray_add LDAP_P((
+ char ***a,
+ char *s ));
+
+LDAP_F( int )
+ldap_charray_merge LDAP_P((
+ char ***a,
+ char **s ));
+
+LDAP_F( void )
+ldap_charray_free LDAP_P(( char **a ));
+
+LDAP_F( int )
+ldap_charray_inlist LDAP_P((
+ char **a,
+ char *s ));
+
+LDAP_F( char ** )
+ldap_charray_dup LDAP_P(( char **a ));
+
+LDAP_F( char ** )
+ldap_str2charray LDAP_P((
+ char *str,
+ char *brkstr ));
+
+/* url.c */
+void ldap_pvt_hex_unescape LDAP_P(( char *s ));
+int ldap_pvt_unhex( int c );
+
+LDAP_END_DECL
+
+#endif
+
--- /dev/null
+/*
+ * Copyright 1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+/*
+ * ldap-schema.h - Header for basic schema handling functions that can be
+ * used by both clients and servers.
+ */
+
+#ifndef _LDAP_SCHEMA_H
+#define _LDAP_SCHEMA_H 1
+
+#include <ldap_cdefs.h>
+
+LDAP_BEGIN_DECL
+
+/* Codes for parsing errors */
+
+#define LDAP_SCHERR_OUTOFMEM 1
+#define LDAP_SCHERR_UNEXPTOKEN 2
+#define LDAP_SCHERR_NOLEFTPAREN 3
+#define LDAP_SCHERR_NORIGHTPAREN 4
+#define LDAP_SCHERR_NODIGIT 5
+#define LDAP_SCHERR_BADNAME 6
+#define LDAP_SCHERR_BADDESC 7
+#define LDAP_SCHERR_BADSUP 8
+#define LDAP_SCHERR_DUPOPT 9
+#define LDAP_SCHERR_EMPTY 10
+
+typedef struct ldap_syntax {
+ char *syn_oid; /* REQUIRED */
+ char *syn_desc; /* OPTIONAL */
+} LDAP_SYNTAX;
+
+typedef struct ldap_matchingrule {
+ char *mr_oid; /* REQUIRED */
+ char **mr_names; /* OPTIONAL */
+ char *mr_desc; /* OPTIONAL */
+ int mr_obsolete; /* OPTIONAL */
+ char *mr_syntax_oid; /* REQUIRED */
+} LDAP_MATCHING_RULE;
+
+typedef struct ldap_attributetype {
+ char *at_oid; /* REQUIRED */
+ char **at_names; /* OPTIONAL */
+ char *at_desc; /* OPTIONAL */
+ int at_obsolete; /* 0=no, 1=yes */
+ char *at_sup_oid; /* OPTIONAL */
+ char *at_equality_oid; /* OPTIONAL */
+ char *at_ordering_oid; /* OPTIONAL */
+ char *at_substr_oid; /* OPTIONAL */
+ char *at_syntax_oid; /* OPTIONAL */
+ int at_syntax_len; /* OPTIONAL */
+ int at_single_value; /* 0=no, 1=yes */
+ int at_collective; /* 0=no, 1=yes */
+ int at_no_user_mod; /* 0=no, 1=yes */
+ int at_usage; /* 0=userApplications, 1=directoryOperation,
+ 2=distributedOperation, 3=dSAOperation */
+} LDAP_ATTRIBUTE_TYPE;
+
+typedef struct ldap_objectclass {
+ char *oc_oid; /* REQUIRED */
+ char **oc_names; /* OPTIONAL */
+ char *oc_desc; /* OPTIONAL */
+ int oc_obsolete; /* 0=no, 1=yes */
+ char **oc_sup_oids; /* OPTIONAL */
+ int oc_kind; /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */
+ char **oc_at_oids_must; /* OPTIONAL */
+ char **oc_at_oids_may; /* OPTIONAL */
+} LDAP_OBJECT_CLASS;
+
+#define LDAP_SCHEMA_NO 0
+#define LDAP_SCHEMA_YES 1
+
+#define LDAP_SCHEMA_USER_APPLICATIONS 0
+#define LDAP_SCHEMA_DIRECTORY_OPERATION 1
+#define LDAP_SCHEMA_DISTRIBUTED_OPERATION 2
+#define LDAP_SCHEMA_DSA_OPERATION 3
+
+#define LDAP_SCHEMA_ABSTRACT 0
+#define LDAP_SCHEMA_STRUCTURAL 1
+#define LDAP_SCHEMA_AUXILIARY 2
+
+LDAP_F( LDAP_CONST char * )
+ldap_syntax2name LDAP_P((
+ LDAP_SYNTAX * syn ));
+
+LDAP_F( LDAP_CONST char * )
+ldap_matchingrule2name LDAP_P((
+ LDAP_MATCHING_RULE * mr ));
+
+LDAP_F( LDAP_CONST char * )
+ldap_attributetype2name LDAP_P((
+ LDAP_ATTRIBUTE_TYPE * at ));
+
+LDAP_F( LDAP_CONST char * )
+ldap_objectclass2name LDAP_P((
+ LDAP_OBJECT_CLASS * oc ));
+
+LDAP_F( void )
+ldap_syntax_free LDAP_P((
+ LDAP_SYNTAX * syn ));
+
+LDAP_F( void )
+ldap_matchingrule_free LDAP_P((
+ LDAP_MATCHING_RULE * mr ));
+
+LDAP_F( void )
+ldap_attributetype_free LDAP_P((
+ LDAP_ATTRIBUTE_TYPE * at ));
+
+LDAP_F( void )
+ldap_objectclass_free LDAP_P((
+ LDAP_OBJECT_CLASS * oc ));
+
+LDAP_F( LDAP_OBJECT_CLASS * )
+ldap_str2objectclass LDAP_P((
+ LDAP_CONST char * s,
+ int * code,
+ LDAP_CONST char ** errp ));
+
+LDAP_F( LDAP_ATTRIBUTE_TYPE * )
+ldap_str2attributetype LDAP_P((
+ LDAP_CONST char * s,
+ int * code,
+ LDAP_CONST char ** errp ));
+
+LDAP_F( LDAP_SYNTAX * )
+ldap_str2syntax LDAP_P((
+ LDAP_CONST char * s,
+ int * code,
+ LDAP_CONST char ** errp ));
+
+LDAP_F( LDAP_MATCHING_RULE * )
+ldap_str2matchingrule LDAP_P((
+ LDAP_CONST char * s,
+ int * code,
+ LDAP_CONST char ** errp ));
+
+LDAP_F( char *)
+ldap_objectclass2str LDAP_P((
+ LDAP_CONST LDAP_OBJECT_CLASS * oc ));
+
+LDAP_F( char *)
+ldap_attributetype2str LDAP_P((
+ LDAP_CONST LDAP_ATTRIBUTE_TYPE * at ));
+
+LDAP_F( char *)
+ldap_syntax2str LDAP_P((
+ LDAP_CONST LDAP_SYNTAX * syn ));
+
+LDAP_F( char *)
+ldap_matchingrule2str LDAP_P((
+ LDAP_CONST LDAP_MATCHING_RULE * mr ));
+
+LDAP_F( char *)
+ldap_scherr2str LDAP_P((
+ int code ));
+
+LDAP_END_DECL
+
+#endif
+
+/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
/* ldbm.h - ldap dbm compatibility routine header file */
#ifndef _LDBM_H_
#define _LDBM_H_
-#ifdef LDBM_USE_GDBM
+#include <ldap_cdefs.h>
+
+#ifdef LDBM_USE_DBBTREE
/*****************************************************************
* *
- * use gdbm if possible *
+ * use berkeley db btree package *
* *
*****************************************************************/
-#include <gdbm.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <fcntl.h>
-typedef datum Datum;
+#ifdef HAVE_DB_185_H
+# include <db_185.h>
+#else
+# ifdef HAVE_DB1_DB_H
+# include <db1/db.h>
+# else
+# include <db.h>
+# endif
+# ifdef HAVE_BERKELEY_DB2
+# define R_NOOVERWRITE DB_NOOVERWRITE
+# define DEFAULT_DB_PAGE_SIZE 1024
+# endif
+#endif
-typedef GDBM_FILE LDBM;
-extern gdbm_error gdbm_errno;
+LDAP_BEGIN_DECL
+
+typedef DBT Datum;
+#define dsize size
+#define dptr data
+
+typedef DB *LDBM;
+
+
+#define DB_TYPE DB_BTREE
/* for ldbm_open */
-#define LDBM_READER GDBM_READER
-#define LDBM_WRITER GDBM_WRITER
-#define LDBM_WRCREAT GDBM_WRCREAT
-#define LDBM_NEWDB GDBM_NEWDB
-#define LDBM_FAST GDBM_FAST
+#ifdef HAVE_BERKELEY_DB2
+typedef DBC LDBMCursor;
+# define LDBM_READER DB_RDONLY
+# define LDBM_WRITER 0x00000 /* hopefully */
+# define LDBM_WRCREAT (DB_NOMMAP|DB_CREATE|DB_THREAD)
+# define LDBM_NEWDB (DB_TRUNCATE|DB_CREATE|DB_THREAD)
+#else
+typedef int LDBMCursor;
+# define LDBM_READER O_RDONLY
+# define LDBM_WRITER O_RDWR
+# define LDBM_WRCREAT (O_RDWR|O_CREAT)
+# define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT)
+#endif
-#define LDBM_SUFFIX ".gdbm"
+LDAP_END_DECL
+
+# define LDBM_FAST 0
+
+#define LDBM_SUFFIX ".dbb"
+#define LDBM_ORDERED 1
/* for ldbm_insert */
-#define LDBM_INSERT GDBM_INSERT
-#define LDBM_REPLACE GDBM_REPLACE
+#define LDBM_INSERT R_NOOVERWRITE
+#define LDBM_REPLACE 0
#define LDBM_SYNC 0x80000000
-#else /* end of gdbm */
-
-#ifdef LDBM_USE_DBHASH
+#elif defined( LDBM_USE_DBHASH )
/*****************************************************************
* *
#include <sys/types.h>
#include <limits.h>
#include <fcntl.h>
-#include <db.h>
+
+#ifdef HAVE_DB_185_H
+# include <db_185.h>
+#else
+# ifdef HAVE_DB1_DB_H
+# include <db1/db.h>
+# else
+# include <db.h>
+# endif
+# ifdef LDBM_USE_DB2
+# define R_NOOVERWRITE DB_NOOVERWRITE
+# define DEFAULT_DB_PAGE_SIZE 1024
+# endif
+#endif
+
+LDAP_BEGIN_DECL
typedef DBT Datum;
#define dsize size
#define DB_TYPE DB_HASH
/* for ldbm_open */
-#define LDBM_READER O_RDONLY
-#define LDBM_WRITER O_RDWR
-#define LDBM_WRCREAT (O_RDWR|O_CREAT)
-#define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT)
-#define LDBM_FAST 0
+#ifdef LDBM_USE_DB2
+typedef DBC LDBMCursor;
+# define LDBM_READER DB_RDONLY
+# define LDBM_WRITER 0x00000 /* hopefully */
+# define LDBM_WRCREAT (DB_NOMMAP|DB_CREATE|DB_THREAD)
+# define LDBM_NEWDB (DB_TRUNCATE|DB_CREATE|DB_THREAD)
+#else
+typedef int LDBMCursor;
+# define LDBM_READER O_RDONLY
+# define LDBM_WRITER O_RDWR
+# define LDBM_WRCREAT (O_RDWR|O_CREAT)
+# define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT)
+# define LDBM_FAST 0
+#endif
+
+LDAP_END_DECL
#define LDBM_SUFFIX ".dbh"
#define LDBM_REPLACE 0
#define LDBM_SYNC 0x80000000
-extern int errno;
+#elif defined( HAVE_GDBM )
-#else /* end of db hash */
+/*****************************************************************
+ * *
+ * use gdbm if possible *
+ * *
+ *****************************************************************/
-#ifdef LDBM_USE_DBBTREE
+#include <gdbm.h>
+
+LDAP_BEGIN_DECL
+
+typedef datum Datum;
+typedef int LDBMCursor;
+typedef GDBM_FILE LDBM;
+
+extern gdbm_error gdbm_errno;
+
+LDAP_END_DECL
+
+/* for ldbm_open */
+#define LDBM_READER GDBM_READER
+#define LDBM_WRITER GDBM_WRITER
+#define LDBM_WRCREAT GDBM_WRCREAT
+#define LDBM_NEWDB GDBM_NEWDB
+#define LDBM_FAST GDBM_FAST
+
+#define LDBM_SUFFIX ".gdbm"
+
+/* for ldbm_insert */
+#define LDBM_INSERT GDBM_INSERT
+#define LDBM_REPLACE GDBM_REPLACE
+#define LDBM_SYNC 0x80000000
+
+#elif defined( HAVE_MDBM )
/*****************************************************************
* *
- * use berkeley db btree package *
+ * use mdbm if possible *
* *
*****************************************************************/
-#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <db.h>
+#include <mdbm.h>
-typedef DBT Datum;
-#define dsize size
-#define dptr data
+LDAP_BEGIN_DECL
-typedef DB *LDBM;
+typedef datum Datum;
+typedef int LDBMCursor;
+typedef MDBM *LDBM;
-#define DB_TYPE DB_BTREE
+LDAP_END_DECL
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
/* for ldbm_open */
#define LDBM_READER O_RDONLY
#define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT)
#define LDBM_FAST 0
-#define LDBM_SUFFIX ".dbb"
-#define LDBM_ORDERED 1
+#define LDBM_SUFFIX ".mdbm"
/* for ldbm_insert */
-#define LDBM_INSERT R_NOOVERWRITE
-#define LDBM_REPLACE 0
+#define LDBM_INSERT MDBM_INSERT
+#define LDBM_REPLACE MDBM_REPLACE
#define LDBM_SYNC 0x80000000
-extern int errno;
-#else /* end of db btree */
-
-#ifdef LDBM_USE_NDBM
+#elif defined( HAVE_NDBM )
/*****************************************************************
* *
*****************************************************************/
#include <ndbm.h>
-#ifndef O_RDONLY
+
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-typedef datum Datum;
+LDAP_BEGIN_DECL
+typedef datum Datum;
+typedef int LDBMCursor;
typedef DBM *LDBM;
+LDAP_END_DECL
+
/* for ldbm_open */
#define LDBM_READER O_RDONLY
#define LDBM_WRITER O_WRONLY
#define LDBM_REPLACE DBM_REPLACE
#define LDBM_SYNC 0
-#endif /* ndbm */
-#endif /* db hash */
-#endif /* db btree */
-#endif /* gdbm */
+#endif
+
+LDAP_BEGIN_DECL
+int ldbm_initialize( void );
+int ldbm_shutdown( void );
+
+int ldbm_errno( LDBM ldbm );
LDBM ldbm_open( char *name, int rw, int mode, int dbcachesize );
void ldbm_close( LDBM ldbm );
void ldbm_sync( LDBM ldbm );
Datum ldbm_fetch( LDBM ldbm, Datum key );
int ldbm_store( LDBM ldbm, Datum key, Datum data, int flags );
int ldbm_delete( LDBM ldbm, Datum key );
-Datum ldbm_firstkey( LDBM ldbm );
-Datum ldbm_nextkey( LDBM ldbm, Datum key );
-int ldbm_errno( LDBM ldbm );
+
+Datum ldbm_firstkey( LDBM ldbm, LDBMCursor **cursor );
+Datum ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *cursor );
+
+/* initialization of Datum structures */
+#ifdef HAVE_BERKELEY_DB2
+ void *ldbm_malloc( size_t size );
+# define ldbm_datum_init(d) ((void)memset(&(d), 0, sizeof(Datum)))
+#else
+# define ldbm_datum_init(d) ((void)0)
+#endif /* HAVE_BERKELEY_DB2 */
+
+LDAP_END_DECL
#endif /* _ldbm_h_ */
/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+/* Portions
* Copyright (c) 1996 Regents of the University of Michigan.
* All rights reserved.
*
#ifndef _LDIF_H
#define _LDIF_H
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <ldap_cdefs.h>
+
+LDAP_BEGIN_DECL
-#define LINE_WIDTH 76 /* maximum length of LDIF lines */
+extern int ldif_debug;
+
+#define LDIF_LINE_WIDTH 76 /* maximum length of LDIF lines */
/*
* Macro to calculate maximum number of bytes that the base64 equivalent
- * of an item that is "vlen" bytes long will take up. Base64 encoding
+ * of an item that is "len" bytes long will take up. Base64 encoding
* uses one byte for every six bits in the value plus up to two pad bytes.
*/
-#define LDIF_BASE64_LEN(vlen) (((vlen) * 4 / 3 ) + 3)
+#define LDIF_BASE64_LEN(len) (((len) * 4 / 3 ) + 3)
/*
* Macro to calculate maximum size that an LDIF-encoded type (length
* first newline + base64 value + continued lines. Each continued line
* needs room for a newline and a leading space character.
*/
-#define LDIF_SIZE_NEEDED(tlen,vlen) \
- ((tlen) + 4 + LDIF_BASE64_LEN(vlen) \
- + ((LDIF_BASE64_LEN(vlen) + tlen + 3) / LINE_WIDTH * 2 ))
-
-
-#ifdef NEEDPROTOS
-int str_parse_line( char *line, char **type, char **value, int *vlen);
-char * str_getline( char **next );
-void put_type_and_value( char **out, char *t, char *val, int vlen );
-char *ldif_type_and_value( char *type, char *val, int vlen );
-#else /* NEEDPROTOS */
-int str_parse_line();
-char * str_getline();
-void put_type_and_value();
-char *ldif_type_and_value();
-#endif /* NEEDPROTOS */
-
-#ifdef __cplusplus
-}
-#endif
+#define LDIF_SIZE_NEEDED(nlen,vlen) \
+ ((nlen) + 4 + LDIF_BASE64_LEN(vlen) \
+ + ((LDIF_BASE64_LEN(vlen) + (nlen) + 3) / LDIF_LINE_WIDTH * 2 ))
+
+LDAP_F( int )
+ldif_parse_line LDAP_P((
+ LDAP_CONST char *line,
+ char **name,
+ char **value,
+ ber_len_t *vlen ));
+
+LDAP_F( int )
+ldif_fetch_url LDAP_P((
+ LDAP_CONST char *line,
+ char **value,
+ ber_len_t *vlen ));
+
+LDAP_F( char * )
+ldif_getline LDAP_P(( char **next ));
+
+LDAP_F( int )
+ldif_read_record LDAP_P((
+ FILE *fp,
+ int *lineno,
+ char **bufp,
+ int *buflen ));
+
+
+#define LDIF_PUT_NOVALUE 0x0000 /* no value */
+#define LDIF_PUT_VALUE 0x0001 /* value w/ auto detection */
+#define LDIF_PUT_TEXT 0x0002 /* assume text */
+#define LDIF_PUT_BINARY 0x0004 /* assume binary (convert to base64) */
+#define LDIF_PUT_B64 0x0008 /* pre-converted base64 value */
+
+#define LDIF_PUT_COMMENT 0x0010 /* comment */
+#define LDIF_PUT_URL 0x0020 /* url */
+#define LDIF_PUT_SEP 0x0040 /* separator */
+
+LDAP_F( void )
+ldif_sput LDAP_P((
+ char **out,
+ int type,
+ LDAP_CONST char *name,
+ LDAP_CONST char *val,
+ ber_len_t vlen ));
+
+LDAP_F( char * )
+ldif_put LDAP_P((
+ int type,
+ LDAP_CONST char *name,
+ LDAP_CONST char *val,
+ ber_len_t vlen ));
+
+LDAP_F( int )
+ldif_is_not_printable LDAP_P((
+ LDAP_CONST char *val,
+ ber_len_t vlen ));
+
+LDAP_END_DECL
#endif /* _LDIF_H */
--- /dev/null
+/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#ifndef _LUTIL_H
+#define _LUTIL_H 1
+
+#include <ldap_cdefs.h>
+/*
+ * Include file for LDAP utility routine
+ */
+
+LDAP_BEGIN_DECL
+
+/* ISC Base64 Routines */
+/* base64.c */
+
+LDAP_F( int )
+lutil_b64_ntop LDAP_P((
+ unsigned char const *,
+ size_t,
+ char *,
+ size_t));
+
+LDAP_F( int )
+lutil_b64_pton LDAP_P((
+ char const *,
+ unsigned char *,
+ size_t));
+
+/* detach.c */
+LDAP_F( void )
+lutil_detach LDAP_P((
+ int debug,
+ int do_close));
+
+/* passwd.c */
+LDAP_F( int )
+lutil_passwd LDAP_P((
+ const char *cred,
+ const char *passwd,
+ const char **methods ));
+
+/* utils.c */
+LDAP_F( char* )
+lutil_progname LDAP_P((
+ const char* name,
+ int argc,
+ char *argv[] ));
+
+
+LDAP_END_DECL
+
+#endif /* _LUTIL_H */
/* Define if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
+/* Define if you have the <ltdl.h> header file. */
+#undef HAVE_LTDL_H
+
/* Define if you have the <lwp/lwp.h> header file. */
#undef HAVE_LWP_LWP_H
/* Define if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
+/* Define if you have the <quipu/commonarg.h> header file. */
+#undef HAVE_QUIPU_COMMONARG_H
+
/* Define if you have the <readline/history.h> header file. */
#undef HAVE_READLINE_HISTORY_H
/* Define if you have the inet library (-linet). */
#undef HAVE_LIBINET
+/* Define if you have the ltdl library (-lltdl). */
+#undef HAVE_LIBLTDL
+
/* Define if you have the net library (-lnet). */
#undef HAVE_LIBNET
/* define if you have no termcap support */
#undef NO_TERMCAP
+/* define if you have Cyrus SASL */
+#undef HAVE_CYRUS_SASL
+
+/* define if you actually have FreeBSD fetch(3) */
+#undef HAVE_FETCH
+
/* define if you have -lreadline */
#undef HAVE_READLINE
/* define if cross compiling */
#undef CROSS_COMPILING
+/* define to you inet_aton(3) is available */
+#undef HAVE_INET_ATON
+
/* define if sys_errlist is not declared in stdio.h or errno.h */
#undef DECL_SYS_ERRLIST
/* define to support cleartext passwords */
#undef SLAPD_CLEARTEXT
+/* define to support multimaster replication */
+#undef SLAPD_MULTIMASTER
+
/* define to support phonetic */
#undef SLAPD_PHONETIC
--- /dev/null
+#
+# Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+# COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+#
+
+all: setup.txt
+
+setup.txt: lber_types.h ldap_config.h ldap_features.h portable.h
+ copy setup.mak setup.txt
+
+lber_types.h: lber_types.h.nt
+ copy lber_types.h.nt lber_types.h
+
+ldap_config.h: ldap_config.h.nt
+ copy ldap_config.h.nt ldap_config.h
+
+ldap_features.h: ldap_features.h.nt
+ copy ldap_features.h.nt ldap_features.h
+
+portable.h: portable.h.nt
+ copy portable.h.nt portable.h
/* avl.c - routines to implement an avl tree */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1993 Regents of the University of Michigan.
* All rights reserved.
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#ifndef lint
static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
static char avl_version[] = "AVL library version 1.0\n";
#endif
-#include <sys/types.h>
#include <stdio.h>
+#include <ac/stdlib.h>
+
+#define AVL_INTERNAL
#include "avl.h"
#define ROTATERIGHT(x) { \
Avlnode *tmp;\
- if ( *x == NULL || (*x)->avl_left == NULL ) {\
- (void) printf("RR error\n"); exit(1); \
+ if ( *(x) == NULL || (*(x))->avl_left == NULL ) {\
+ (void) fputs("RR error\n", stderr); exit( EXIT_FAILURE ); \
}\
- tmp = (*x)->avl_left;\
- (*x)->avl_left = tmp->avl_right;\
- tmp->avl_right = *x;\
- *x = tmp;\
+ tmp = (*(x))->avl_left;\
+ (*(x))->avl_left = tmp->avl_right;\
+ tmp->avl_right = *(x);\
+ *(x) = tmp;\
}
#define ROTATELEFT(x) { \
Avlnode *tmp;\
- if ( *x == NULL || (*x)->avl_right == NULL ) {\
- (void) printf("RL error\n"); exit(1); \
+ if ( *(x) == NULL || (*(x))->avl_right == NULL ) {\
+ (void) fputs("RL error\n", stderr); exit( EXIT_FAILURE ); \
}\
- tmp = (*x)->avl_right;\
- (*x)->avl_right = tmp->avl_left;\
- tmp->avl_left = *x;\
- *x = tmp;\
+ tmp = (*(x))->avl_right;\
+ (*(x))->avl_right = tmp->avl_left;\
+ tmp->avl_left = *(x);\
+ *(x) = tmp;\
}
/*
* and balance of an avl tree.
*/
-static
-ravl_insert( iroot, data, taller, fcmp, fdup, depth )
- Avlnode **iroot;
- caddr_t data;
- int *taller;
- IFP fcmp; /* comparison function */
- IFP fdup; /* function to call for duplicates */
- int depth;
+static int
+ravl_insert(
+ Avlnode **iroot,
+ void* data,
+ int *taller,
+ AVL_CMP fcmp, /* comparison function */
+ AVL_DUP fdup, /* function to call for duplicates */
+ int depth
+)
{
int rc, cmp, tallersub;
Avlnode *l, *r;
* NOTE: this routine may malloc memory
*/
-avl_insert( root, data, fcmp, fdup )
- Avlnode **root;
- caddr_t data;
- IFP fcmp;
- IFP fdup;
+int
+avl_insert( Avlnode **root, void* data, AVL_CMP fcmp, AVL_DUP fdup )
{
int taller;
* been shortened because of a deletion.
*/
-static
-right_balance( root )
- Avlnode **root;
+static int
+right_balance( Avlnode **root )
{
- int shorter;
+ int shorter = -1;
Avlnode *r, *l;
switch( (*root)->avl_bf ) {
* been shortened because of a deletion.
*/
-static
-left_balance( root )
- Avlnode **root;
+static int
+left_balance( Avlnode **root )
{
- int shorter;
+ int shorter = -1;
Avlnode *r, *l;
switch( (*root)->avl_bf ) {
* rebalancing.
*/
-static caddr_t
-ravl_delete( root, data, fcmp, shorter )
- Avlnode **root;
- caddr_t data;
- IFP fcmp;
- int *shorter;
+static void*
+ravl_delete( Avlnode **root, void* data, AVL_CMP fcmp, int *shorter )
{
int shortersubtree = 0;
int cmp;
- caddr_t savedata;
+ void* savedata;
Avlnode *minnode, *savenode;
if ( *root == NULLAVL )
* the avl tree rooted at root.
*/
-caddr_t
-avl_delete( root, data, fcmp )
- Avlnode **root;
- caddr_t data;
- IFP fcmp;
+void*
+avl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
{
int shorter;
return( ravl_delete( root, data, fcmp, &shorter ) );
}
-static
-avl_inapply( root, fn, arg, stopflag )
- Avlnode *root;
- IFP fn;
- caddr_t arg;
- int stopflag;
+static int
+avl_inapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
{
if ( root == 0 )
return( AVL_NOMORE );
return( avl_inapply( root->avl_right, fn, arg, stopflag ) );
}
-static
-avl_postapply( root, fn, arg, stopflag )
- Avlnode *root;
- IFP fn;
- caddr_t arg;
- int stopflag;
+static int
+avl_postapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
{
if ( root == 0 )
return( AVL_NOMORE );
return( (*fn)( root->avl_data, arg ) );
}
-static
-avl_preapply( root, fn, arg, stopflag )
- Avlnode *root;
- IFP fn;
- caddr_t arg;
- int stopflag;
+static int
+avl_preapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
{
if ( root == 0 )
return( AVL_NOMORE );
* of nodes.
*/
-avl_apply( root, fn, arg, stopflag, type )
- Avlnode *root;
- IFP fn;
- caddr_t arg;
- int stopflag;
- int type;
+int
+avl_apply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag, int type )
{
switch ( type ) {
case AVL_INORDER:
* AVL_NOMORE is returned.
*/
-avl_prefixapply( root, data, fmatch, marg, fcmp, carg, stopflag )
- Avlnode *root;
- caddr_t data;
- IFP fmatch;
- caddr_t marg;
- IFP fcmp;
- caddr_t carg;
- int stopflag;
+int
+avl_prefixapply(
+ Avlnode *root,
+ void* data,
+ AVL_CMP fmatch,
+ void* marg,
+ AVL_CMP fcmp,
+ void* carg,
+ int stopflag
+)
{
int cmp;
if ( root == 0 )
return( AVL_NOMORE );
- cmp = (*fcmp)( data, root->avl_data, carg );
+ cmp = (*fcmp)( data, root->avl_data /* , carg */);
if ( cmp == 0 ) {
if ( (*fmatch)( root->avl_data, marg ) == stopflag )
return( stopflag );
* number of items actually freed is returned.
*/
-avl_free( root, dfree )
- Avlnode *root;
- IFP dfree;
+int
+avl_free( Avlnode *root, AVL_FREE dfree )
{
int nleft, nright;
if ( dfree )
(*dfree)( root->avl_data );
+ free( root );
return( nleft + nright + 1 );
}
* < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
*/
-caddr_t
-avl_find( root, data, fcmp )
- Avlnode *root;
- caddr_t data;
- IFP fcmp;
+void*
+avl_find( Avlnode *root, const void* data, AVL_CMP fcmp )
{
int cmp;
* they match, non-zero otherwise.
*/
-caddr_t
-avl_find_lin( root, data, fcmp )
- Avlnode *root;
- caddr_t data;
- IFP fcmp;
+void*
+avl_find_lin( Avlnode *root, const void* data, AVL_CMP fcmp )
{
- caddr_t res;
+ void* res;
if ( root == 0 )
return( NULL );
return( avl_find_lin( root->avl_right, data, fcmp ) );
}
-static caddr_t *avl_list;
+/* NON-REENTRANT INTERFACE */
+
+static void* *avl_list;
static int avl_maxlist;
static int avl_nextlist;
#define AVL_GRABSIZE 100
/* ARGSUSED */
-static
-avl_buildlist( data, arg )
- caddr_t data;
- int arg;
+static int
+avl_buildlist( void* data, void* arg )
{
static int slots;
- if ( avl_list == (caddr_t *) 0 ) {
- avl_list = (caddr_t *) malloc(AVL_GRABSIZE * sizeof(caddr_t));
+ if ( avl_list == (void* *) 0 ) {
+ avl_list = (void* *) malloc(AVL_GRABSIZE * sizeof(void*));
slots = AVL_GRABSIZE;
avl_maxlist = 0;
} else if ( avl_maxlist == slots ) {
slots += AVL_GRABSIZE;
- avl_list = (caddr_t *) realloc( (char *) avl_list,
- (unsigned) slots * sizeof(caddr_t));
+ avl_list = (void* *) realloc( (char *) avl_list,
+ (unsigned) slots * sizeof(void*));
}
avl_list[ avl_maxlist++ ] = data;
* different trees) cannot be active at once.
*/
-caddr_t
-avl_getfirst( root )
- Avlnode *root;
+void*
+avl_getfirst( Avlnode *root )
{
if ( avl_list ) {
free( (char *) avl_list);
- avl_list = (caddr_t *) 0;
+ avl_list = (void* *) 0;
}
avl_maxlist = 0;
avl_nextlist = 0;
if ( root == 0 )
return( 0 );
- (void) avl_apply( root, avl_buildlist, (caddr_t) 0, -1, AVL_INORDER );
+ (void) avl_apply( root, avl_buildlist, (void*) 0, -1, AVL_INORDER );
return( avl_list[ avl_nextlist++ ] );
}
-caddr_t
-avl_getnext()
+void*
+avl_getnext( void )
{
if ( avl_list == 0 )
return( 0 );
if ( avl_nextlist == avl_maxlist ) {
- free( (caddr_t) avl_list);
- avl_list = (caddr_t *) 0;
+ free( (void*) avl_list);
+ avl_list = (void* *) 0;
return( 0 );
}
return( avl_list[ avl_nextlist++ ] );
}
-avl_dup_error()
+/* end non-reentrant code */
+
+
+int
+avl_dup_error( void* left, void* right )
{
return( -1 );
}
-avl_dup_ok()
+int
+avl_dup_ok( void* left, void* right )
{
return( 0 );
}
/* testavl.c - Test Tim Howes AVL code */
-#include <sys/types.h>
-#include <stdio.h>
-#include "avl.h"
-char *strdup( s )
-char *s;
-{
- char *new;
+#include "portable.h"
+
+#include <stdio.h>
- if ( (new = (char *) malloc( strlen( s ) + 1 )) == NULL )
- return( NULL );
+#include <ac/stdlib.h>
+#include <ac/string.h>
- strcpy( new, s );
+#define AVL_INTERNAL
+#define AVL_NONREENTRANT
+#include "avl.h"
- return( new );
-}
+static void ravl_print LDAP_P(( Avlnode *root, int depth ));
+static void myprint LDAP_P(( Avlnode *root ));
-main( argc, argv )
-int argc;
-char **argv;
+int
+main( int argc, char **argv )
{
- Avlnode *tree = NULLAVL;
+ Avlnode *tree = NULL;
char command[ 10 ];
char name[ 80 ];
char *p;
- int free(), strcmp();
printf( "> " );
while ( fgets( command, sizeof( command ), stdin ) != NULL ) {
switch( *command ) {
case 'n': /* new tree */
- ( void ) avl_free( tree, free );
- tree = NULLAVL;
+ ( void ) avl_free( tree, (AVL_FREE) free );
+ tree = NULL;
break;
case 'p': /* print */
( void ) myprint( tree );
break;
case 't': /* traverse with first, next */
+#ifdef AVL_NONREENTRANT
printf( "***\n" );
for ( p = (char * ) avl_getfirst( tree );
- p != NULL; p = (char *) avl_getnext( tree, p ) )
+ p != NULL;
+ p = (char *) avl_getnext())
printf( "%s\n", p );
printf( "***\n" );
+#else
+ printf( "*** reentrant interface not implemented ***" );
+#endif
break;
case 'f': /* find */
printf( "data? " );
if ( fgets( name, sizeof( name ), stdin ) == NULL )
- exit( 0 );
+ exit( EXIT_SUCCESS );
name[ strlen( name ) - 1 ] = '\0';
- if ( (p = (char *) avl_find( tree, name, strcmp ))
+ if ( (p = (char *) avl_find( tree, name, (AVL_CMP) strcmp ))
== NULL )
printf( "Not found.\n\n" );
else
case 'i': /* insert */
printf( "data? " );
if ( fgets( name, sizeof( name ), stdin ) == NULL )
- exit( 0 );
+ exit( EXIT_SUCCESS );
name[ strlen( name ) - 1 ] = '\0';
- if ( avl_insert( &tree, strdup( name ), strcmp,
- avl_dup_error ) != OK )
+ if ( avl_insert( &tree, strdup( name ), (AVL_CMP) strcmp,
+ avl_dup_error ) != 0 )
printf( "\nNot inserted!\n" );
break;
case 'd': /* delete */
printf( "data? " );
if ( fgets( name, sizeof( name ), stdin ) == NULL )
- exit( 0 );
+ exit( EXIT_SUCCESS );
name[ strlen( name ) - 1 ] = '\0';
- if ( avl_delete( &tree, name, strcmp ) == NULL )
+ if ( avl_delete( &tree, name, (AVL_CMP) strcmp ) == NULL )
printf( "\nNot found!\n" );
break;
case 'q': /* quit */
- exit( 0 );
+ exit( EXIT_SUCCESS );
break;
case '\n':
break;
printf( "> " );
}
- /* NOTREACHED */
+
+ return( 0 );
}
-static ravl_print( root, depth )
-Avlnode *root;
-int depth;
+static void ravl_print( Avlnode *root, int depth )
{
int i;
for ( i = 0; i < depth; i++ )
printf( " " );
- printf( "%s %d\n", root->avl_data, root->avl_bf );
+ printf( "%s %d\n", (char *) root->avl_data, root->avl_bf );
ravl_print( root->avl_left, depth+1 );
}
-myprint( root )
-Avlnode *root;
+static void myprint( Avlnode *root )
{
printf( "********\n" );
if ( root == 0 )
printf( "\tNULL\n" );
else
- ( void ) ravl_print( root, 0 );
+ ravl_print( root, 0 );
printf( "********\n" );
}
--- /dev/null
+/*
+ * Copyright 1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#ifdef LDAP_NEED_ASSERT
+
+#include <stdio.h>
+
+/*
+ * helper for our private assert() macro
+ *
+ * note: if assert() doesn't exist, like abort() or raise() won't either.
+ * could use kill() but that might be problematic. I'll just ignore this
+ * issue for now.
+ */
+
+void
+ber_pvt_assert( const char *file, int line, const char *test )
+{
+ fprintf(stderr,
+ "Assertion failed: %s, file %s, line %d\n",
+ test, file, line);
+
+ abort();
+}
+
+#endif
/* decode.c - ber input decoding routines */
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#ifdef MACOS
-#include <stdlib.h>
-#include <stdarg.h>
-#include "macos.h"
-#else /* MACOS */
-#if defined(NeXT) || defined(VMS)
-#include <stdlib.h>
-#else /* next || vms */
-#include <malloc.h>
-#endif /* next || vms */
-#if defined(BC31) || defined(_WIN32)
-#include <stdarg.h>
-#else /* BC31 || _WIN32 */
-#include <varargs.h>
-#endif /* BC31 || _WIN32 */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#ifdef PCNFS
-#include <tklib.h>
-#endif /* PCNFS */
-#endif /* MACOS */
-
-#if defined( DOS ) || defined( _WIN32 )
-#include "msdos.h"
-#endif /* DOS */
-
-#include <string.h>
-#include "lber.h"
-
-#ifdef LDAP_DEBUG
-int lber_debug;
-#endif
-#ifdef NEEDPROTOS
-static int ber_getnint( BerElement *ber, long *num, int len );
-#endif /* NEEDPROTOS */
+#include <ac/stdlib.h>
+
+#include <ac/stdarg.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#undef LDAP_F_PRE
+#define LDAP_F_PRE LDAP_F_EXPORT
+#include "lber-int.h"
+
+static ber_len_t ber_getnint LDAP_P((
+ BerElement *ber,
+ ber_int_t *num,
+ ber_len_t len ));
/* return the tag - LBER_DEFAULT returned means trouble */
-unsigned long
+ber_tag_t
ber_get_tag( BerElement *ber )
{
unsigned char xbyte;
- unsigned long tag;
+ ber_tag_t tag;
char *tagp;
- int i;
+ unsigned int i;
+
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
return( LBER_DEFAULT );
if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
- return( (unsigned long) xbyte );
+ return( (ber_tag_t) xbyte );
tagp = (char *) &tag;
tagp[0] = xbyte;
- for ( i = 1; i < sizeof(long); i++ ) {
+ for ( i = 1; i < sizeof(ber_tag_t); i++ ) {
if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
return( LBER_DEFAULT );
}
/* tag too big! */
- if ( i == sizeof(long) )
+ if ( i == sizeof(ber_tag_t) )
return( LBER_DEFAULT );
/* want leading, not trailing 0's */
- return( tag >> (sizeof(long) - i - 1) );
+ return( tag >> (sizeof(ber_tag_t) - i - 1) );
}
-unsigned long
-ber_skip_tag( BerElement *ber, unsigned long *len )
+ber_tag_t
+ber_skip_tag( BerElement *ber, ber_len_t *len )
{
- unsigned long tag;
+ ber_tag_t tag;
unsigned char lc;
- int noctets, diff;
- unsigned long netlen;
+ ber_len_t noctets;
+ int diff;
+ ber_len_t netlen;
+
+ assert( ber != NULL );
+ assert( len != NULL );
+ assert( BER_VALID( ber ) );
/*
* Any ber element looks like this: tag length contents.
* Next, read the length. The first byte contains the length of
* the length. If bit 8 is set, the length is the long form,
* otherwise it's the short form. We don't allow a length that's
- * greater than what we can hold in an unsigned long.
+ * greater than what we can hold in a ber_len_t.
*/
*len = netlen = 0;
if ( ber_read( ber, (char *) &lc, 1 ) != 1 )
return( LBER_DEFAULT );
- if ( lc & 0x80 ) {
- noctets = (lc & 0x7f);
- if ( noctets > sizeof(unsigned long) )
+ if ( lc & 0x80U ) {
+ noctets = (lc & 0x7fU);
+ if ( noctets > sizeof(ber_len_t) )
return( LBER_DEFAULT );
- diff = sizeof(unsigned long) - noctets;
- if ( ber_read( ber, (char *) &netlen + diff, noctets )
+ diff = sizeof(ber_len_t) - noctets;
+ if ( (unsigned) ber_read( ber, (char *) &netlen + diff, noctets )
!= noctets )
return( LBER_DEFAULT );
- *len = LBER_NTOHL( netlen );
+ *len = LBER_LEN_NTOH( netlen );
} else {
*len = lc;
}
return( tag );
}
-unsigned long
-ber_peek_tag( BerElement *ber, unsigned long *len )
+ber_tag_t
+ber_peek_tag(
+ LDAP_CONST BerElement *ber_in,
+ ber_len_t *len )
{
- char *save;
- unsigned long tag;
+ ber_tag_t tag;
+ BerElement *ber;
+
+ assert( ber_in != NULL );
+ assert( BER_VALID( ber_in ) );
+
+ ber = ber_dup( ber_in );
+
+ if( ber == NULL ) {
+ return LBER_ERROR;
+ }
+
+ assert( BER_VALID( ber ) );
- save = ber->ber_ptr;
tag = ber_skip_tag( ber, len );
- ber->ber_ptr = save;
+ ber_free( ber, 0 );
return( tag );
}
-static int
-ber_getnint( BerElement *ber, long *num, int len )
+static ber_len_t
+ber_getnint(
+ BerElement *ber,
+ ber_int_t *num,
+ ber_len_t len )
{
- int diff, sign, i;
- long netnum;
+ unsigned char buf[sizeof(ber_int_t)];
+
+ assert( ber != NULL );
+ assert( num != NULL );
+
+ assert( BER_VALID( ber ) );
/*
* The tag and length have already been stripped off. We should
* extend after we read it in.
*/
- if ( len > sizeof(long) )
+ if ( len > sizeof(ber_int_t) )
return( -1 );
- netnum = 0;
- diff = sizeof(long) - len;
- /* read into the low-order bytes of netnum */
- if ( ber_read( ber, ((char *) &netnum) + diff, len ) != len )
+ /* read into the low-order bytes of our buffer */
+ if ( (ber_len_t) ber_read( ber, (char *) buf, len ) != len ) {
return( -1 );
+ }
+
+ if( len ) {
+ /* sign extend if necessary */
+ ber_len_t i;
+ ber_int_t netnum = 0x80 & buf[0] ? -1 : 0;
- /* sign extend if necessary */
- sign = ((0x80 << ((len - 1) * 8)) & netnum);
- if ( sign && len < sizeof(long) ) {
- for ( i = sizeof(long) - 1; i > len - 1; i-- ) {
- netnum |= (0xffL << (i * 8));
+ /* shift in the bytes */
+ for( i=0 ; i<len; i++ ) {
+ netnum = (netnum << 8 ) | buf[i];
}
+
+ *num = netnum;
+
+ } else {
+ *num = 0;
}
- *num = LBER_NTOHL( netnum );
return( len );
}
-unsigned long
-ber_get_int( BerElement *ber, long *num )
+ber_tag_t
+ber_get_int(
+ BerElement *ber,
+ ber_int_t *num )
{
- unsigned long tag, len;
+ ber_tag_t tag;
+ ber_len_t len;
+
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
return( LBER_DEFAULT );
- if ( ber_getnint( ber, num, (int)len ) != len )
+ if ( ber_getnint( ber, num, len ) != len )
return( LBER_DEFAULT );
else
return( tag );
}
-unsigned long
-ber_get_stringb( BerElement *ber, char *buf, unsigned long *len )
+ber_tag_t
+ber_get_stringb(
+ BerElement *ber,
+ char *buf,
+ ber_len_t *len )
{
- unsigned long datalen, tag;
+ ber_len_t datalen;
+ ber_tag_t tag;
+
#ifdef STR_TRANSLATION
char *transbuf;
#endif /* STR_TRANSLATION */
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
return( LBER_DEFAULT );
if ( datalen > (*len - 1) )
return( LBER_DEFAULT );
- if ( ber_read( ber, buf, datalen ) != datalen )
+ if ( (ber_len_t) ber_read( ber, buf, datalen ) != datalen )
return( LBER_DEFAULT );
buf[datalen] = '\0';
#ifdef STR_TRANSLATION
if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
- && ber->ber_decode_translate_proc != NULL ) {
+ && ber->ber_decode_translate_proc ) {
transbuf = buf;
++datalen;
if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen,
return( LBER_DEFAULT );
}
if ( datalen > *len ) {
- free( transbuf );
+ LBER_FREE( transbuf );
return( LBER_DEFAULT );
}
SAFEMEMCPY( buf, transbuf, datalen );
- free( transbuf );
+ LBER_FREE( transbuf );
--datalen;
}
#endif /* STR_TRANSLATION */
return( tag );
}
-unsigned long
+ber_tag_t
ber_get_stringa( BerElement *ber, char **buf )
{
- unsigned long datalen, tag;
+ ber_len_t datalen;
+ ber_tag_t tag;
- if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
+ assert( ber != NULL );
+ assert( buf != NULL );
+
+ assert( BER_VALID( ber ) );
+
+ if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) {
+ *buf = NULL;
return( LBER_DEFAULT );
+ }
- if ( (*buf = (char *) malloc( (size_t)datalen + 1 )) == NULL )
+ if ( (*buf = (char *) LBER_MALLOC( datalen + 1 )) == NULL )
return( LBER_DEFAULT );
- if ( ber_read( ber, *buf, datalen ) != datalen )
+ if ( (ber_len_t) ber_read( ber, *buf, datalen ) != datalen ) {
+ LBER_FREE( *buf );
+ *buf = NULL;
return( LBER_DEFAULT );
+ }
(*buf)[datalen] = '\0';
#ifdef STR_TRANSLATION
if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
- && ber->ber_decode_translate_proc != NULL ) {
+ && ber->ber_decode_translate_proc ) {
++datalen;
if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 )
!= 0 ) {
- free( *buf );
+ LBER_FREE( *buf );
+ *buf = NULL;
return( LBER_DEFAULT );
}
}
return( tag );
}
-unsigned long
+ber_tag_t
ber_get_stringal( BerElement *ber, struct berval **bv )
{
- unsigned long len, tag;
+ ber_len_t len;
+ ber_tag_t tag;
+
+ assert( ber != NULL );
+ assert( bv != NULL );
- if ( (*bv = (struct berval *) malloc( sizeof(struct berval) )) == NULL )
+ assert( BER_VALID( ber ) );
+
+ if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) {
+ *bv = NULL;
return( LBER_DEFAULT );
+ }
- if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
+ if ( (*bv = (struct berval *) LBER_MALLOC( sizeof(struct berval) )) == NULL )
return( LBER_DEFAULT );
- if ( ((*bv)->bv_val = (char *) malloc( (size_t)len + 1 )) == NULL )
+ if ( ((*bv)->bv_val = (char *) LBER_MALLOC( len + 1 )) == NULL ) {
+ LBER_FREE( *bv );
+ *bv = NULL;
return( LBER_DEFAULT );
+ }
- if ( ber_read( ber, (*bv)->bv_val, len ) != len )
+ if ( (ber_len_t) ber_read( ber, (*bv)->bv_val, len ) != len ) {
+ ber_bvfree( *bv );
+ *bv = NULL;
return( LBER_DEFAULT );
+ }
((*bv)->bv_val)[len] = '\0';
(*bv)->bv_len = len;
#ifdef STR_TRANSLATION
if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
- && ber->ber_decode_translate_proc != NULL ) {
+ && ber->ber_decode_translate_proc ) {
++len;
if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val),
&len, 1 ) != 0 ) {
- free( (*bv)->bv_val );
+ ber_bvfree( *bv );
+ *bv = NULL;
return( LBER_DEFAULT );
}
(*bv)->bv_len = len - 1;
return( tag );
}
-unsigned long
-ber_get_bitstringa( BerElement *ber, char **buf, unsigned long *blen )
+ber_tag_t
+ber_get_bitstringa(
+ BerElement *ber,
+ char **buf,
+ ber_len_t *blen )
{
- unsigned long datalen, tag;
+ ber_len_t datalen;
+ ber_tag_t tag;
unsigned char unusedbits;
- if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
+ assert( ber != NULL );
+ assert( buf != NULL );
+ assert( blen != NULL );
+
+ assert( BER_VALID( ber ) );
+
+ if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) {
+ *buf = NULL;
return( LBER_DEFAULT );
+ }
--datalen;
- if ( (*buf = (char *) malloc( (size_t)datalen )) == NULL )
+ if ( (*buf = (char *) LBER_MALLOC( datalen )) == NULL )
return( LBER_DEFAULT );
- if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 )
+ if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 ) {
+ LBER_FREE( buf );
+ *buf = NULL;
return( LBER_DEFAULT );
+ }
- if ( ber_read( ber, *buf, datalen ) != datalen )
+ if ( (ber_len_t) ber_read( ber, *buf, datalen ) != datalen ) {
+ LBER_FREE( buf );
+ *buf = NULL;
return( LBER_DEFAULT );
+ }
*blen = datalen * 8 - unusedbits;
return( tag );
}
-unsigned long
+ber_tag_t
ber_get_null( BerElement *ber )
{
- unsigned long len, tag;
+ ber_len_t len;
+ ber_tag_t tag;
+
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
return( LBER_DEFAULT );
return( tag );
}
-unsigned long
-ber_get_boolean( BerElement *ber, int *boolval )
+ber_tag_t
+ber_get_boolean(
+ BerElement *ber,
+ ber_int_t *boolval )
{
- long longbool;
- int rc;
+ ber_int_t longbool;
+ ber_tag_t rc;
+
+ assert( ber != NULL );
+ assert( boolval != NULL );
+
+ assert( BER_VALID( ber ) );
rc = ber_get_int( ber, &longbool );
*boolval = longbool;
return( rc );
}
-unsigned long
-ber_first_element( BerElement *ber, unsigned long *len, char **last )
+ber_tag_t
+ber_first_element(
+ BerElement *ber,
+ ber_len_t *len,
+ char **last )
{
+ assert( ber != NULL );
+ assert( len != NULL );
+ assert( last != NULL );
+
/* skip the sequence header, use the len to mark where to stop */
if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) {
+ *last = NULL;
return( LBER_DEFAULT );
}
return( ber_peek_tag( ber, len ) );
}
-unsigned long
-ber_next_element( BerElement *ber, unsigned long *len, char *last )
+ber_tag_t
+ber_next_element(
+ BerElement *ber,
+ ber_len_t *len,
+ char *last )
{
+ assert( ber != NULL );
+ assert( len != NULL );
+ assert( last != NULL );
+
+ assert( BER_VALID( ber ) );
+
if ( ber->ber_ptr == last ) {
return( LBER_DEFAULT );
}
}
/* VARARGS */
-unsigned long
-ber_scanf(
-#if defined( MACOS ) || defined( BC31 ) || defined( _WIN32 )
- BerElement *ber, char *fmt, ... )
+ber_tag_t
+ber_scanf
+#if HAVE_STDARG
+ ( BerElement *ber,
+ LDAP_CONST char *fmt,
+ ... )
#else
- va_alist )
+ ( va_alist )
va_dcl
#endif
{
va_list ap;
-#if !defined( MACOS ) && !defined( BC31 ) && !defined( _WIN32 )
+#ifndef HAVE_STDARG
BerElement *ber;
char *fmt;
#endif
+ LDAP_CONST char *fmt_reset;
char *last;
char *s, **ss, ***sss;
struct berval ***bv, **bvp, *bval;
- int *i, j;
- long *l, rc, tag;
- unsigned long len;
-
-#if defined( MACOS ) || defined( BC31 ) || defined( _WIN32 )
+ ber_int_t *i;
+ int j;
+ ber_len_t *l;
+ ber_tag_t *t;
+ ber_tag_t rc, tag;
+ ber_len_t len;
+
+#ifdef HAVE_STDARG
va_start( ap, fmt );
#else
va_start( ap );
fmt = va_arg( ap, char * );
#endif
-#ifdef LDAP_DEBUG
- if ( lber_debug & 64 ) {
- fprintf( stderr, "ber_scanf fmt (%s) ber:\n", fmt );
- ber_dump( ber, 1 );
- }
-#endif
+ assert( ber != NULL );
+ assert( fmt != NULL );
+
+ assert( BER_VALID( ber ) );
+
+ fmt_reset = fmt;
+
+ ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
+ "ber_scanf fmt (%s) ber:\n", fmt );
+ ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 );
for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) {
+ /* When this is modified, remember to update
+ * the error-cleanup code below accordingly. */
switch ( *fmt ) {
+ case '!': { /* Hook */
+ BERDecodeCallback *f;
+ void *p;
+
+ f = va_arg( ap, BERDecodeCallback * );
+ p = va_arg( ap, void * );
+
+ rc = (*f)( ber, p, 0 );
+ } break;
+
case 'a': /* octet string - allocate storage as needed */
ss = va_arg( ap, char ** );
rc = ber_get_stringa( ber, ss );
break;
case 'b': /* boolean */
- i = va_arg( ap, int * );
+ i = va_arg( ap, ber_int_t * );
rc = ber_get_boolean( ber, i );
break;
case 'e': /* enumerated */
case 'i': /* int */
- l = va_arg( ap, long * );
- rc = ber_get_int( ber, l );
+ i = va_arg( ap, ber_int_t * );
+ rc = ber_get_int( ber, i );
break;
case 'l': /* length of next item */
- l = va_arg( ap, long * );
- rc = ber_peek_tag( ber, (unsigned long *)l );
+ l = va_arg( ap, ber_len_t * );
+ rc = ber_peek_tag( ber, l );
break;
case 'n': /* null */
case 's': /* octet string - in a buffer */
s = va_arg( ap, char * );
- l = va_arg( ap, long * );
- rc = ber_get_stringb( ber, s, (unsigned long *)l );
+ l = va_arg( ap, ber_len_t * );
+ rc = ber_get_stringb( ber, s, l );
break;
case 'o': /* octet string in a supplied berval */
case 'B': /* bit string - allocate storage as needed */
ss = va_arg( ap, char ** );
- l = va_arg( ap, long * ); /* for length, in bits */
- rc = ber_get_bitstringa( ber, ss, (unsigned long *)l );
+ l = va_arg( ap, ber_len_t * ); /* for length, in bits */
+ rc = ber_get_bitstringa( ber, ss, l );
break;
case 't': /* tag of next item */
- i = va_arg( ap, int * );
- *i = rc = ber_peek_tag( ber, &len );
+ t = va_arg( ap, ber_tag_t * );
+ *t = rc = ber_peek_tag( ber, &len );
break;
case 'T': /* skip tag of next item */
- i = va_arg( ap, int * );
- *i = rc = ber_skip_tag( ber, &len );
+ t = va_arg( ap, ber_tag_t * );
+ *t = rc = ber_skip_tag( ber, &len );
break;
case 'v': /* sequence of strings */
j = 0;
for ( tag = ber_first_element( ber, &len, &last );
tag != LBER_DEFAULT && rc != LBER_DEFAULT;
- tag = ber_next_element( ber, &len, last ) ) {
- if ( *sss == NULL ) {
- *sss = (char **) malloc(
- 2 * sizeof(char *) );
- } else {
- *sss = (char **) realloc( *sss,
- (j + 2) * sizeof(char *) );
- }
+ tag = ber_next_element( ber, &len, last ) )
+ {
+ *sss = (char **) LBER_REALLOC( *sss,
+ (j + 2) * sizeof(char *) );
+
rc = ber_get_stringa( ber, &((*sss)[j]) );
j++;
}
j = 0;
for ( tag = ber_first_element( ber, &len, &last );
tag != LBER_DEFAULT && rc != LBER_DEFAULT;
- tag = ber_next_element( ber, &len, last ) ) {
- if ( *bv == NULL ) {
- *bv = (struct berval **) malloc(
- 2 * sizeof(struct berval *) );
- } else {
- *bv = (struct berval **) realloc( *bv,
- (j + 2) * sizeof(struct berval *) );
- }
+ tag = ber_next_element( ber, &len, last ) )
+ {
+ *bv = (struct berval **) LBER_REALLOC( *bv,
+ (j + 2) * sizeof(struct berval *) );
+
rc = ber_get_stringal( ber, &((*bv)[j]) );
j++;
}
break;
default:
-#ifndef NO_USERINTERFACE
- fprintf( stderr, "unknown fmt %c\n", *fmt );
-#endif /* NO_USERINTERFACE */
+ if( ber->ber_debug ) {
+ ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug,
+ "ber_scanf: unknown fmt %c\n", *fmt );
+ }
rc = LBER_DEFAULT;
break;
}
va_end( ap );
- return( rc );
-}
+ if ( rc == LBER_DEFAULT ) {
+ /*
+ * Error. Reclaim malloced memory that was given to the caller.
+ * Set allocated pointers to NULL, "data length" outvalues to 0.
+ */
+#ifdef HAVE_STDARG
+ va_start( ap, fmt );
+#else
+ va_start( ap );
+ (void) va_arg( ap, BerElement * );
+ (void) va_arg( ap, char * );
+#endif
-void
-ber_bvfree( struct berval *bv )
-{
- if ( bv->bv_val != NULL )
- free( bv->bv_val );
- free( (char *) bv );
-}
+ for ( ; fmt_reset < fmt; fmt_reset++ ) {
+ switch ( *fmt_reset ) {
+ case '!': { /* Hook */
+ BERDecodeCallback *f;
+ void *p;
-void
-ber_bvecfree( struct berval **bv )
-{
- int i;
+ f = va_arg( ap, BERDecodeCallback * );
+ p = va_arg( ap, void * );
- for ( i = 0; bv[i] != NULL; i++ )
- ber_bvfree( bv[i] );
- free( (char *) bv );
-}
+ (void) (*f)( ber, p, 1 );
+ } break;
-struct berval *
-ber_bvdup( struct berval *bv )
-{
- struct berval *new;
+ case 'a': /* octet string - allocate storage as needed */
+ ss = va_arg( ap, char ** );
+ if ( *ss ) {
+ LBER_FREE( *ss );
+ *ss = NULL;
+ }
+ break;
- if ( (new = (struct berval *) malloc( sizeof(struct berval) ))
- == NULL ) {
- return( NULL );
- }
- if ( (new->bv_val = (char *) malloc( bv->bv_len + 1 )) == NULL ) {
- return( NULL );
+ case 'b': /* boolean */
+ case 'e': /* enumerated */
+ case 'i': /* int */
+ (void) va_arg( ap, int * );
+ break;
+
+ case 's': /* octet string - in a buffer */
+ (void) va_arg( ap, char * );
+ (void) va_arg( ap, ber_len_t * );
+ break;
+
+ case 'l': /* length of next item */
+ (void) va_arg( ap, ber_len_t * );
+ break;
+
+ case 't': /* tag of next item */
+ case 'T': /* skip tag of next item */
+ (void) va_arg( ap, ber_tag_t * );
+ break;
+
+ case 'o': /* octet string in a supplied berval */
+ bval = va_arg( ap, struct berval * );
+ if ( bval->bv_val != NULL ) {
+ LBER_FREE( bval->bv_val );
+ bval->bv_val = NULL;
+ }
+ bval->bv_len = 0;
+ break;
+
+ case 'O': /* octet string - allocate & include length */
+ bvp = va_arg( ap, struct berval ** );
+ if ( *bvp ) {
+ ber_bvfree( *bvp );
+ *bvp = NULL;
+ }
+ break;
+
+ case 'B': /* bit string - allocate storage as needed */
+ ss = va_arg( ap, char ** );
+ if ( *ss ) {
+ LBER_FREE( *ss );
+ *ss = NULL;
+ }
+ *(va_arg( ap, ber_len_t * )) = 0; /* for length, in bits */
+ break;
+
+ case 'v': /* sequence of strings */
+ sss = va_arg( ap, char *** );
+ if ( *sss ) {
+ for (j = 0; (*sss)[j]; j++) {
+ LBER_FREE( (*sss)[j] );
+ (*sss)[j] = NULL;
+ }
+ LBER_FREE( *sss );
+ *sss = NULL;
+ }
+ break;
+
+ case 'V': /* sequence of strings + lengths */
+ bv = va_arg( ap, struct berval *** );
+ if ( *bv ) {
+ ber_bvecfree( *bv );
+ *bv = NULL;
+ }
+ break;
+
+ case 'n': /* null */
+ case 'x': /* skip the next element - whatever it is */
+ case '{': /* begin sequence */
+ case '[': /* begin set */
+ case '}': /* end sequence */
+ case ']': /* end set */
+ break;
+
+ default:
+ /* format should be good */
+ assert( 0 );
+ }
+ }
+
+ va_end( ap );
}
- SAFEMEMCPY( new->bv_val, bv->bv_val, (size_t) bv->bv_len );
- new->bv_val[bv->bv_len] = '\0';
- new->bv_len = bv->bv_len;
- return( new );
+ return( rc );
}
ber_set_string_translators( BerElement *ber, BERTranslateProc encode_proc,
BERTranslateProc decode_proc )
{
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
ber->ber_encode_translate_proc = encode_proc;
ber->ber_decode_translate_proc = decode_proc;
}
/* dtest.c - lber decoding test program */
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#ifdef MACOS
-#include <stdlib.h>
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_CONSOLE_H
#include <console.h>
-#else /* MACOS */
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif /* MACOS */
-#include "lber.h"
+#endif
+
+#include <lber.h>
-static usage( char *name )
+static void usage( char *name )
{
fprintf( stderr, "usage: %s fmt\n", name );
}
+int
main( int argc, char **argv )
{
- long i, i2, num;
- unsigned long len;
- int tag;
- char *str, *s1, *s2;
- BerElement ber;
- Sockbuf sb;
- extern char *optarg;
-
-#ifdef MACOS
+ char *s;
+ int rc;
+
+ ber_tag_t tag;
+ ber_len_t len;
+
+ BerElement *ber;
+ Sockbuf *sb;
+
+ /* enable debugging */
+ int ival = -1;
+ ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ival );
+
+ if ( argc < 2 ) {
+ usage( argv[0] );
+ return( EXIT_FAILURE );
+ }
+
+#ifdef HAVE_CONSOLE_H
ccommand( &argv );
cshow( stdout );
-#endif /* MACOS */
+#endif
+
+ sb = ber_sockbuf_alloc_fd( fileno(stdin) );
+
+ if( (ber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+ perror( "ber_alloc_t" );
+ return( EXIT_FAILURE );
+ }
- bzero( &sb, sizeof(sb) );
- sb.sb_sd = 0;
- sb.sb_ber.ber_buf = NULL;
- if ( (tag = ber_get_next( &sb, &len, &ber )) == -1 ) {
+ if(( tag = ber_get_next( sb, &len, ber) ) == LBER_ERROR ) {
perror( "ber_get_next" );
- exit( 1 );
+ return( EXIT_FAILURE );
}
- printf( "message has tag 0x%x and length %ld\n", tag, len );
- if ( ber_scanf( &ber, "i", &i ) == -1 ) {
- fprintf( stderr, "ber_scanf returns -1\n" );
- exit( 1 );
+ printf("decode: message tag 0x%lx and length %ld\n",
+ (unsigned long) tag, (long) len );
+
+ for( s = argv[1]; *s; s++ ) {
+ char buf[128];
+ char fmt[2];
+ fmt[0] = *s;
+ fmt[1] = '\0';
+
+ printf("decode: format %s\n", fmt );
+ len = sizeof(buf);
+ rc = ber_scanf( ber, fmt, &buf[0], &len );
+
+ if( rc == LBER_ERROR ) {
+ perror( "ber_scanf" );
+ return( EXIT_FAILURE );
+ }
}
- printf( "got int %d\n", i );
- return( 0 );
+ ber_sockbuf_free( sb );
+ return( EXIT_SUCCESS );
}
/* encode.c - ber output encoding routines */
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#ifdef MACOS
-#include <stdlib.h>
-#include <stdarg.h>
-#include "macos.h"
-#else /* MACOS */
-#if defined(NeXT) || defined(VMS)
-#include <stdlib.h>
-#else /* next || vms */
-#include <malloc.h>
-#endif /* next || vms */
-#if defined( BC31 ) || defined( _WIN32 )
-#include <stdarg.h>
-#else /* BC31 || _WIN32 */
-#include <varargs.h>
-#endif /* BC31 || _WIN32 */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#ifdef PCNFS
-#include <tklib.h>
-#endif /* PCNFS */
-#endif /* MACOS */
-#ifndef VMS
-#include <memory.h>
-#endif
-#include <string.h>
-#include "lber.h"
-#if defined( DOS ) || defined( _WIN32 )
-#include "msdos.h"
-#endif /* DOS */
+#include <ac/stdlib.h>
-#ifdef NEEDPROTOS
-static int ber_put_len( BerElement *ber, unsigned long len, int nosos );
-static int ber_start_seqorset( BerElement *ber, unsigned long tag );
-static int ber_put_seqorset( BerElement *ber );
-static int ber_put_int_or_enum( BerElement *ber, long num, unsigned long tag );
-#endif /* NEEDPROTOS */
+#include <ac/stdarg.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#undef LDAP_F_PRE
+#define LDAP_F_PRE LDAP_F_EXPORT
-static int
-ber_calc_taglen( unsigned long tag )
+#include "lber-int.h"
+
+static int ber_put_len LDAP_P((
+ BerElement *ber,
+ ber_len_t len,
+ int nosos ));
+
+static int ber_start_seqorset LDAP_P((
+ BerElement *ber,
+ ber_tag_t tag ));
+
+static int ber_put_seqorset LDAP_P(( BerElement *ber ));
+
+static int ber_put_int_or_enum LDAP_P((
+ BerElement *ber,
+ ber_int_t num,
+ ber_tag_t tag ));
+
+
+static ber_len_t
+ber_calc_taglen( ber_tag_t tag )
{
int i;
- long mask;
+ ber_tag_t mask;
/* find the first non-all-zero byte in the tag */
- for ( i = sizeof(long) - 1; i > 0; i-- ) {
- mask = (0xffL << (i * 8));
+ for ( i = sizeof(ber_tag_t) - 1; i > 0; i-- ) {
+ mask = ((ber_tag_t)0xffU << (i * 8));
/* not all zero */
if ( tag & mask )
break;
}
static int
-ber_put_tag( BerElement *ber, unsigned long tag, int nosos )
+ber_put_tag(
+ BerElement *ber,
+ ber_tag_t tag,
+ int nosos )
{
- int taglen;
- unsigned long ntag;
+ int rc;
+ ber_len_t taglen;
+ ber_tag_t ntag;
+
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
taglen = ber_calc_taglen( tag );
- ntag = LBER_HTONL( tag );
+ ntag = LBER_TAG_HTON( tag );
+
+ rc = ber_write( ber,
+ ((char *) &ntag) + sizeof(ber_tag_t) - taglen,
+ taglen, nosos );
- return( ber_write( ber, ((char *) &ntag) + sizeof(long) - taglen,
- taglen, nosos ) );
+ return rc;
}
-static int
-ber_calc_lenlen( unsigned long len )
+static ber_len_t
+ber_calc_lenlen( ber_len_t len )
{
/*
* short len if it's less than 128 - one byte giving the len,
* with bit 8 0.
*/
- if ( len <= 0x7F )
+ if ( len <= (ber_len_t) 0x7FU )
return( 1 );
/*
* length of the length, followed by the length itself.
*/
- if ( len <= 0xFF )
+ if ( len <= (ber_len_t) 0xffU )
return( 2 );
- if ( len <= 0xFFFFL )
+ if ( len <= (ber_len_t) 0xffffU )
return( 3 );
- if ( len <= 0xFFFFFFL )
+ if ( len <= (ber_len_t) 0xffffffU )
return( 4 );
return( 5 );
}
static int
-ber_put_len( BerElement *ber, unsigned long len, int nosos )
+ber_put_len( BerElement *ber, ber_len_t len, int nosos )
{
int i;
char lenlen;
- long mask;
- unsigned long netlen;
+ ber_len_t mask;
+ ber_len_t netlen;
+
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
/*
* short len if it's less than 128 - one byte giving the len,
*/
if ( len <= 127 ) {
- netlen = LBER_HTONL( len );
- return( ber_write( ber, (char *) &netlen + sizeof(long) - 1,
- 1, nosos ) );
+ char length_byte = (char) len;
+ return( ber_write( ber, &length_byte, 1, nosos ) );
}
/*
*/
/* find the first non-all-zero byte */
- for ( i = sizeof(long) - 1; i > 0; i-- ) {
- mask = (0xffL << (i * 8));
+ for ( i = sizeof(ber_len_t) - 1; i > 0; i-- ) {
+ mask = ((ber_len_t)0xffU << (i * 8));
/* not all zero */
if ( len & mask )
break;
}
- lenlen = ++i;
+ lenlen = (unsigned char) ++i;
if ( lenlen > 4 )
return( -1 );
- lenlen |= 0x80;
+ lenlen |= 0x80UL;
/* write the length of the length */
if ( ber_write( ber, &lenlen, 1, nosos ) != 1 )
return( -1 );
/* write the length itself */
- netlen = LBER_HTONL( len );
- if ( ber_write( ber, (char *) &netlen + (sizeof(long) - i), i, nosos )
+ netlen = LBER_LEN_HTON( len );
+ if ( ber_write( ber, (char *) &netlen + (sizeof(ber_len_t) - i), i, nosos )
!= i )
return( -1 );
}
static int
-ber_put_int_or_enum( BerElement *ber, long num, unsigned long tag )
+ber_put_int_or_enum(
+ BerElement *ber,
+ ber_int_t num,
+ ber_tag_t tag )
{
- int i, sign, taglen;
- int len, lenlen;
- long netnum, mask;
+ int i, sign;
+ ber_len_t len, lenlen, taglen;
+ ber_uint_t unum, netnum, mask;
+
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
sign = (num < 0);
+ unum = num; /* Bit fiddling should be done with unsigned values */
/*
* high bit is set - look for first non-all-one byte
* high bit is clear - look for first non-all-zero byte
*/
- for ( i = sizeof(long) - 1; i > 0; i-- ) {
- mask = (0xffL << (i * 8));
+ for ( i = sizeof(ber_int_t) - 1; i > 0; i-- ) {
+ mask = ((ber_uint_t)0xffU << (i * 8));
if ( sign ) {
/* not all ones */
- if ( (num & mask) != mask )
+ if ( (unum & mask) != mask )
break;
} else {
/* not all zero */
- if ( num & mask )
+ if ( unum & mask )
break;
}
}
* we now have the "leading byte". if the high bit on this
* byte matches the sign bit, we need to "back up" a byte.
*/
- mask = (num & (0x80L << (i * 8)));
+ mask = (unum & ((ber_uint_t)0x80U << (i * 8)));
if ( (mask && !sign) || (sign && !mask) )
i++;
if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 )
return( -1 );
i++;
- netnum = LBER_HTONL( num );
- if ( ber_write( ber, (char *) &netnum + (sizeof(long) - i), i, 0 )
+ netnum = LBER_INT_HTON( unum );
+ if ( ber_write( ber, (char *) &netnum + (sizeof(ber_int_t) - i), i, 0 )
!= i )
return( -1 );
}
int
-ber_put_enum( BerElement *ber, long num, unsigned long tag )
+ber_put_enum(
+ BerElement *ber,
+ ber_int_t num,
+ ber_tag_t tag )
{
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
if ( tag == LBER_DEFAULT )
tag = LBER_ENUMERATED;
}
int
-ber_put_int( BerElement *ber, long num, unsigned long tag )
+ber_put_int(
+ BerElement *ber,
+ ber_int_t num,
+ ber_tag_t tag )
{
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
if ( tag == LBER_DEFAULT )
tag = LBER_INTEGER;
}
int
-ber_put_ostring( BerElement *ber, char *str, unsigned long len,
- unsigned long tag )
+ber_put_ostring(
+ BerElement *ber,
+ LDAP_CONST char *str,
+ ber_len_t len,
+ ber_tag_t tag )
{
- int taglen, lenlen, rc;
+ ber_len_t taglen, lenlen;
+ int rc;
#ifdef STR_TRANSLATION
int free_str;
#endif /* STR_TRANSLATION */
+ assert( ber != NULL );
+ assert( str != NULL );
+
+ assert( BER_VALID( ber ) );
+
if ( tag == LBER_DEFAULT )
tag = LBER_OCTETSTRING;
#ifdef STR_TRANSLATION
if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0 &&
- ber->ber_encode_translate_proc != NULL ) {
+ ber->ber_encode_translate_proc ) {
if ( (*(ber->ber_encode_translate_proc))( &str, &len, 0 )
!= 0 ) {
return( -1 );
#endif /* STR_TRANSLATION */
if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ||
- ber_write( ber, str, len, 0 ) != len ) {
+ (ber_len_t) ber_write( ber, str, len, 0 ) != len ) {
rc = -1;
} else {
/* return length of tag + length + contents */
#ifdef STR_TRANSLATION
if ( free_str ) {
- free( str );
+ LBER_FREE( str );
}
#endif /* STR_TRANSLATION */
}
int
-ber_put_string( BerElement *ber, char *str, unsigned long tag )
+ber_put_berval(
+ BerElement *ber,
+ LDAP_CONST struct berval *bv,
+ ber_tag_t tag )
+{
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
+ if( bv == NULL || bv->bv_len == 0 ) {
+ return ber_put_ostring( ber, "", (ber_len_t) 0, tag );
+ }
+
+ return ber_put_ostring( ber, bv->bv_val, bv->bv_len, tag );
+}
+
+int
+ber_put_string(
+ BerElement *ber,
+ LDAP_CONST char *str,
+ ber_tag_t tag )
{
+ assert( ber != NULL );
+ assert( str != NULL );
+
+ assert( BER_VALID( ber ) );
+
return( ber_put_ostring( ber, str, strlen( str ), tag ));
}
int
-ber_put_bitstring( BerElement *ber, char *str,
- unsigned long blen /* in bits */, unsigned long tag )
+ber_put_bitstring(
+ BerElement *ber,
+ LDAP_CONST char *str,
+ ber_len_t blen /* in bits */,
+ ber_tag_t tag )
{
- int taglen, lenlen, len;
+ ber_len_t taglen, lenlen, len;
unsigned char unusedbits;
+ assert( ber != NULL );
+ assert( str != NULL );
+
+ assert( BER_VALID( ber ) );
+
if ( tag == LBER_DEFAULT )
tag = LBER_BITSTRING;
return( -1 );
len = ( blen + 7 ) / 8;
- unusedbits = len * 8 - blen;
+ unusedbits = (unsigned char) ((len * 8) - blen);
if ( (lenlen = ber_put_len( ber, len + 1, 0 )) == -1 )
return( -1 );
if ( ber_write( ber, (char *)&unusedbits, 1, 0 ) != 1 )
return( -1 );
- if ( ber_write( ber, str, len, 0 ) != len )
+ if ( (ber_len_t) ber_write( ber, str, len, 0 ) != len )
return( -1 );
/* return length of tag + length + unused bit count + contents */
}
int
-ber_put_null( BerElement *ber, unsigned long tag )
+ber_put_null( BerElement *ber, ber_tag_t tag )
{
- int taglen;
+ ber_len_t taglen;
+
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
if ( tag == LBER_DEFAULT )
tag = LBER_NULL;
}
int
-ber_put_boolean( BerElement *ber, int boolval, unsigned long tag )
+ber_put_boolean(
+ BerElement *ber,
+ ber_int_t boolval,
+ ber_tag_t tag )
{
- int taglen;
- unsigned char trueval = 0xff;
- unsigned char falseval = 0x00;
+ ber_len_t taglen;
+ unsigned char trueval = 0xFFU;
+ unsigned char falseval = 0x00U;
+
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
if ( tag == LBER_DEFAULT )
tag = LBER_BOOLEAN;
#define FOUR_BYTE_LEN 5
static int
-ber_start_seqorset( BerElement *ber, unsigned long tag )
+ber_start_seqorset(
+ BerElement *ber,
+ ber_tag_t tag )
{
Seqorset *new;
- if ( (new = (Seqorset *) calloc( sizeof(Seqorset), 1 ))
- == NULLSEQORSET )
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
+ new = (Seqorset *) LBER_CALLOC( 1, sizeof(Seqorset) );
+
+ if ( new == NULL )
return( -1 );
+
new->sos_ber = ber;
- if ( ber->ber_sos == NULLSEQORSET )
+ if ( ber->ber_sos == NULL )
new->sos_first = ber->ber_ptr;
else
new->sos_first = ber->ber_sos->sos_ptr;
}
int
-ber_start_seq( BerElement *ber, unsigned long tag )
+ber_start_seq( BerElement *ber, ber_tag_t tag )
{
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
if ( tag == LBER_DEFAULT )
tag = LBER_SEQUENCE;
}
int
-ber_start_set( BerElement *ber, unsigned long tag )
+ber_start_set( BerElement *ber, ber_tag_t tag )
{
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
if ( tag == LBER_DEFAULT )
tag = LBER_SET;
static int
ber_put_seqorset( BerElement *ber )
{
- unsigned long len, netlen;
- int taglen, lenlen;
- unsigned char ltag = 0x80 + FOUR_BYTE_LEN - 1;
+ ber_len_t len, netlen;
+ ber_len_t taglen, lenlen;
+ unsigned char ltag = 0x80U + FOUR_BYTE_LEN - 1;
Seqorset *next;
Seqorset **sos = &ber->ber_sos;
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
/*
* If this is the toplevel sequence or set, we need to actually
* write the stuff out. Otherwise, it's already been put in
*/
len = (*sos)->sos_clen;
- netlen = LBER_HTONL( len );
- if ( sizeof(long) > 4 && len > 0xFFFFFFFFL )
+ netlen = LBER_LEN_HTON( len );
+ if ( sizeof(ber_len_t) > 4 && len > 0xffffffffUL )
return( -1 );
if ( ber->ber_options & LBER_USE_DER ) {
lenlen = FOUR_BYTE_LEN;
}
- if ( (next = (*sos)->sos_next) == NULLSEQORSET ) {
+ if ( (next = (*sos)->sos_next) == NULL ) {
/* write the tag */
if ( (taglen = ber_put_tag( ber, (*sos)->sos_tag, 1 )) == -1 )
return( -1 );
return( -1 );
/* the length itself */
- if ( ber_write( ber, (char *) &netlen + sizeof(long)
+ if ( ber_write( ber, (char *) (&netlen + 1)
- (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1, 1 )
!= FOUR_BYTE_LEN - 1 )
return( -1 );
/* The ber_ptr is at the set/seq start - move it to the end */
(*sos)->sos_ber->ber_ptr += len;
} else {
- unsigned long ntag;
+ ber_tag_t ntag;
/* the tag */
taglen = ber_calc_taglen( (*sos)->sos_tag );
- ntag = LBER_HTONL( (*sos)->sos_tag );
+ ntag = LBER_TAG_HTON( (*sos)->sos_tag );
SAFEMEMCPY( (*sos)->sos_first, (char *) &ntag +
- sizeof(long) - taglen, taglen );
+ sizeof(ber_tag_t) - taglen, taglen );
if ( ber->ber_options & LBER_USE_DER ) {
- ltag = (lenlen == 1) ? len : 0x80 + (lenlen - 1);
+ ltag = (lenlen == 1)
+ ? (unsigned char) len
+ : (unsigned char) (0x80U + (lenlen - 1));
}
/* one byte of length length */
if (lenlen > 1) {
/* Write the length itself */
SAFEMEMCPY( (*sos)->sos_first + 2,
- (char *)&netlen + sizeof(unsigned long) -
+ (char *)&netlen + sizeof(ber_len_t) -
(lenlen - 1),
lenlen - 1 );
}
} else {
/* the length itself */
SAFEMEMCPY( (*sos)->sos_first + taglen + 1,
- (char *) &netlen + sizeof(long) -
+ (char *) &netlen + sizeof(ber_len_t) -
(FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1 );
}
}
/* we're done with this seqorset, so free it up */
- free( (char *) (*sos) );
+ LBER_FREE( (char *) (*sos) );
*sos = next;
return( taglen + lenlen + len );
int
ber_put_seq( BerElement *ber )
{
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
return( ber_put_seqorset( ber ) );
}
int
ber_put_set( BerElement *ber )
{
+ assert( ber != NULL );
+ assert( BER_VALID( ber ) );
+
return( ber_put_seqorset( ber ) );
}
/* VARARGS */
int
-ber_printf(
-#if defined( MACOS ) || defined( _WIN32 ) || defined( BC31 )
- BerElement *ber, char *fmt, ... )
-#else /* MACOS || _WIN32 || BC31 */
- va_alist )
+ber_printf
+#ifdef HAVE_STDARG
+ ( BerElement *ber,
+ LDAP_CONST char *fmt,
+ ... )
+#else
+ ( va_alist )
va_dcl
-#endif /* MACOS || _WIN32 || BC31 */
+#endif
{
va_list ap;
-#if !defined( MACOS ) && !defined( _WIN32 ) && !defined( BC31 )
+#ifndef HAVE_STDARG
BerElement *ber;
char *fmt;
-#endif /* !MACOS && !_WIN32 && !BC31 */
+#endif
char *s, **ss;
- struct berval **bv;
- int rc, i;
- unsigned long len;
+ struct berval *bv, **bvp;
+ int rc;
+ ber_int_t i;
+ ber_len_t len;
-#if defined( MACOS ) || defined( _WIN32 ) || defined( BC31 )
+#ifdef HAVE_STDARG
va_start( ap, fmt );
-#else /* MACOS || _WIN32 || BC31 */
+#else
va_start( ap );
ber = va_arg( ap, BerElement * );
fmt = va_arg( ap, char * );
-#endif /* MACOS || _WIN32 || BC31 */
+#endif
+
+ assert( ber != NULL );
+ assert( fmt != NULL );
+
+ assert( BER_VALID( ber ) );
for ( rc = 0; *fmt && rc != -1; fmt++ ) {
switch ( *fmt ) {
+ case '!': { /* hook */
+ BEREncodeCallback *f;
+ void *p;
+
+ f = va_arg( ap, BEREncodeCallback * );
+ p = va_arg( ap, void * );
+
+ rc = (*f)( ber, p );
+ } break;
+
case 'b': /* boolean */
- i = va_arg( ap, int );
+ i = va_arg( ap, ber_int_t );
rc = ber_put_boolean( ber, i, ber->ber_tag );
break;
case 'i': /* int */
- i = va_arg( ap, int );
+ i = va_arg( ap, ber_int_t );
rc = ber_put_int( ber, i, ber->ber_tag );
break;
case 'e': /* enumeration */
- i = va_arg( ap, int );
+ i = va_arg( ap, ber_int_t );
rc = ber_put_enum( ber, i, ber->ber_tag );
break;
case 'o': /* octet string (non-null terminated) */
s = va_arg( ap, char * );
- len = va_arg( ap, int );
+ len = va_arg( ap, ber_len_t );
rc = ber_put_ostring( ber, s, len, ber->ber_tag );
break;
+ case 'O': /* berval octet string */
+ bv = va_arg( ap, struct berval * );
+ if( bv == NULL ) break;
+ rc = ber_put_berval( ber, bv, ber->ber_tag );
+ break;
+
case 's': /* string */
s = va_arg( ap, char * );
rc = ber_put_string( ber, s, ber->ber_tag );
break;
case 't': /* tag for the next element */
- ber->ber_tag = va_arg( ap, unsigned long );
+ ber->ber_tag = va_arg( ap, ber_tag_t );
ber->ber_usertag = 1;
break;
break;
case 'V': /* sequences of strings + lengths */
- if ( (bv = va_arg( ap, struct berval ** )) == NULL )
+ if ( (bvp = va_arg( ap, struct berval ** )) == NULL )
break;
- for ( i = 0; bv[i] != NULL; i++ ) {
- if ( (rc = ber_put_ostring( ber, bv[i]->bv_val,
- bv[i]->bv_len, ber->ber_tag )) == -1 )
+ for ( i = 0; bvp[i] != NULL; i++ ) {
+ if ( (rc = ber_put_berval( ber, bvp[i],
+ ber->ber_tag )) == -1 )
break;
}
break;
break;
default:
-#ifndef NO_USERINTERFACE
- fprintf( stderr, "unknown fmt %c\n", *fmt );
-#endif /* NO_USERINTERFACE */
+ if( ber->ber_debug ) {
+ ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug,
+ "ber_printf: unknown fmt %c\n", *fmt );
+ }
rc = -1;
break;
}
/* idtest.c - ber decoding test program using isode libraries */
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#ifdef HAVE_PSAP_H
#include <psap.h>
#include <quipu/attr.h>
+#endif
-static usage( char *name )
-{
- fprintf( stderr, "usage: %s\n", name );
-}
-
+int
main( int argc, char **argv )
{
+#ifdef HAVE_PSAP_H
PE pe;
PS psin, psout, pserr;
/* read the pe from standard in */
if ( (psin = ps_alloc( std_open )) == NULLPS ) {
perror( "ps_alloc" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( std_setup( psin, stdin ) == NOTOK ) {
perror( "std_setup" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/* write the pe to standard out */
if ( (psout = ps_alloc( std_open )) == NULLPS ) {
perror( "ps_alloc" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( std_setup( psout, stdout ) == NOTOK ) {
perror( "std_setup" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/* pretty print it to standard error */
if ( (pserr = ps_alloc( std_open )) == NULLPS ) {
perror( "ps_alloc" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( std_setup( pserr, stderr ) == NOTOK ) {
perror( "std_setup" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
while ( (pe = ps2pe( psin )) != NULLPE ) {
pe2ps( psout, pe );
}
- exit( 0 );
+ exit( EXIT_SUCCESS );
+#else
+ fprintf(stderr, "requires ISODE X.500 distribution.\n");
+ return( EXIT_FAILURE );
+#endif
}
--- /dev/null
+/*
+ * Copyright 1998 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#ifndef _LBER_INT_H
+#define _LBER_INT_H
+
+#include "lber.h"
+#include "ldap_log.h"
+#include "lber_pvt.h"
+
+LDAP_BEGIN_DECL
+
+/* these have to match lber types settings */
+#define LBER_INT_HTON(i) AC_HTONL(i)
+#define LBER_INT_NTOH(i) AC_NTOHL(i)
+#define LBER_LEN_HTON(l) AC_HTONL(l)
+#define LBER_LEN_NTOH(l) AC_NTOHL(l)
+#define LBER_TAG_HTON(t) AC_HTONL(t)
+#define LBER_TAG_NTOH(t) AC_NTOHL(t)
+
+
+struct lber_options {
+ short lbo_valid;
+#define LBER_UNINITIALIZED 0x0
+#define LBER_INITIALIZED 0x1
+#define LBER_VALID_BERELEMENT 0x2
+#define LBER_VALID_SOCKBUF 0x3
+
+ unsigned short lbo_options;
+ int lbo_debug;
+};
+
+extern struct lber_options ber_int_options;
+#define ber_int_debug ber_int_options.lbo_debug
+
+struct berelement {
+ struct lber_options ber_opts;
+#define ber_valid ber_opts.lbo_valid
+#define ber_options ber_opts.lbo_options
+#define ber_debug ber_opts.lbo_debug
+
+ ber_tag_t ber_usertag;
+
+ ber_tag_t ber_tag;
+ ber_len_t ber_len;
+
+ char *ber_buf;
+ char *ber_ptr;
+ char *ber_end;
+
+ struct seqorset *ber_sos;
+ char *ber_rwptr;
+ BERTranslateProc ber_encode_translate_proc;
+ BERTranslateProc ber_decode_translate_proc;
+};
+#define BER_VALID(ber) ((ber)->ber_valid==LBER_VALID_BERELEMENT)
+
+
+#define ber_pvt_ber_bytes(ber) ((ber)->ber_ptr - (ber)->ber_buf)
+#define ber_pvt_ber_remaining(ber) ((ber)->ber_end - (ber)->ber_ptr)
+
+struct sockbuf;
+
+struct sockbuf_io {
+ int (*sbi_setup)( struct sockbuf * sb, void *arg );
+ int (*sbi_remove)( struct sockbuf *sb );
+
+ ber_slen_t (*sbi_read)( struct sockbuf *sb, void *buf, ber_len_t len );
+ ber_slen_t (*sbi_write)( struct sockbuf *sb, void *buf, ber_len_t len );
+ int (*sbi_close)( struct sockbuf *sb );
+};
+
+struct sockbuf_sec {
+ int (*sbs_setup)( struct sockbuf * sb, void *arg );
+ int (*sbs_remove)( struct sockbuf *sb );
+
+ long (*sbs_protect)( struct sockbuf *sb, char *in, long *ilen,
+ char *out, long olen );
+ long (*sbs_release)( struct sockbuf *sb, char *in, long ilen,
+ char *out0, long olen0, char *out1, long olen1 );
+};
+
+struct sockbuf_buf {
+ ber_len_t buf_size;
+ ber_len_t buf_ptr;
+ ber_len_t buf_end;
+ char *buf_base;
+};
+
+typedef struct sockbuf_io Sockbuf_IO;
+typedef struct sockbuf_sec Sockbuf_Sec;
+typedef struct sockbuf_buf Sockbuf_Buf;
+
+extern Sockbuf_IO ber_pvt_sb_io_tcp;
+extern Sockbuf_IO ber_pvt_sb_io_udp;
+
+
+struct sockbuf {
+ struct lber_options sb_opts;
+#define sb_valid sb_opts.lbo_valid
+#define sb_options sb_opts.lbo_options
+#define sb_debug sb_opts.lbo_debug
+
+ int sb_non_block:1;
+ int sb_read_ahead:1;
+
+ int sb_buf_ready:1;
+ int sb_trans_ready:1;
+ int sb_sec_ready:1;
+
+ /* these bits indicate if the transport layer
+ * needs to read or write
+ */
+ int sb_trans_needs_read:1;
+ int sb_trans_needs_write:1;
+
+ int sb_fd;
+
+ void *sb_iodata; /* transport-layer data pointer */
+ Sockbuf_IO *sb_io; /* I/O functions */
+
+#ifdef LDAP_SASL
+ void *sb_sdata; /* security-layer data pointer */
+ Sockbuf_Sec *sb_sec;
+#endif
+
+ ber_socket_t sb_sd;
+
+#ifdef DEADWOOD
+ long sb_max_incoming;
+#endif
+ Sockbuf_Buf sb_buf;
+#ifdef LDAP_SASL
+ Sockbuf_Buf sb_sec_buf_in;
+ Sockbuf_Buf sb_sec_buf_out;
+ ber_len_t sb_sec_prev_len;
+#endif
+};
+#define SOCKBUF_VALID(ber) ((sb)->sb_valid==LBER_VALID_SOCKBUF)
+
+/* these should be internal ie: ber_int_* */
+#define ber_pvt_sb_get_desc( sb ) ((sb)->sb_sd)
+#define ber_pvt_sb_set_desc( sb, val ) ((sb)->sb_sd =(val))
+
+#define ber_pvt_sb_in_use( sb ) ((sb)->sb_sd != AC_SOCKET_INVALID)
+
+#ifdef USE_SASL
+#define ber_pvt_sb_data_ready( sb ) \
+(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready) || ((sb)->sb_sec_ready))
+#else
+#define ber_pvt_sb_data_ready( sb ) \
+(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready))
+#endif
+#define ber_pvt_sb_needs_read( sb ) \
+((sb)->sb_trans_needs_read)
+#define ber_pvt_sb_needs_write( sb ) \
+((sb)->sb_trans_needs_write)
+
+#define READBUFSIZ 8192
+
+struct seqorset {
+ BerElement *sos_ber;
+ ber_len_t sos_clen;
+ ber_tag_t sos_tag;
+ char *sos_first;
+ char *sos_ptr;
+ struct seqorset *sos_next;
+};
+
+
+/*
+ * bprint.c
+ */
+#define ber_log_printf ber_pvt_log_printf
+
+LDAP_F( int )
+ber_log_bprint LDAP_P((
+ int errlvl,
+ int loglvl,
+ const char *data,
+ ber_len_t len ));
+
+LDAP_F( int )
+ber_log_dump LDAP_P((
+ int errlvl,
+ int loglvl,
+ const BerElement *ber,
+ int inout ));
+
+LDAP_F( int )
+ber_log_sos_dump LDAP_P((
+ int errlvl,
+ int loglvl,
+ const Seqorset *sos ));
+
+
+/* memory.c */
+ /* simple macros to realloc for now */
+extern BerMemoryFunctions* ber_int_memory_fns;
+
+#ifdef CSRIMALLOC
+#define LBER_INT_MALLOC malloc
+#define LBER_INT_CALLOC calloc
+#define LBER_INT_REALLOC realloc
+#define LBER_INT_FREE free
+#define LBER_INT_VFREE ber_memvfree
+#define LBER_INT_STRDUP strdup
+
+#define LBER_MALLOC malloc
+#define LBER_CALLOC calloc
+#define LBER_REALLOC realloc
+#define LBER_FREE free
+#define LBER_VFREE ber_memvfree
+#define LBER_STRDUP strdup
+
+#else
+#define LBER_INT_MALLOC(s) ber_memalloc((s))
+#define LBER_INT_CALLOC(n,s) ber_memcalloc((n),(s))
+#define LBER_INT_REALLOC(p,s) ber_memrealloc((p),(s))
+#define LBER_INT_FREE(p) ber_memfree((p))
+#define LBER_INT_VFREE(v) ber_memvfree((void**)(v))
+#define LBER_INT_STRDUP(s) ber_strdup((s))
+
+#define LBER_MALLOC(s) ber_memalloc((s))
+#define LBER_CALLOC(n,s) ber_memcalloc((n),(s))
+#define LBER_REALLOC(p,s) ber_memrealloc((p),(s))
+#define LBER_FREE(p) ber_memfree((p))
+#define LBER_VFREE(v) ber_memvfree((void**)(v))
+#define LBER_STRDUP(s) ber_strdup((s))
+#endif
+
+/* sockbuf.c */
+
+/* these should be ber_int*() functions */
+
+LDAP_F( int )
+ber_pvt_sb_init LDAP_P(( Sockbuf *sb ));
+
+LDAP_F( int )
+ber_pvt_sb_destroy LDAP_P(( Sockbuf *sb ));
+
+#ifdef USE_SASL
+LDAP_F( int )
+ber_pvt_sb_set_sec LDAP_P(( Sockbuf *sb, Sockbuf_Sec *sec, void *arg ));
+
+LDAP_F( int )
+ber_pvt_sb_clear_sec LDAP_P(( Sockbuf *sb ));
+#endif
+
+LDAP_F( int )
+ber_pvt_sb_set_io LDAP_P(( Sockbuf *sb, Sockbuf_IO *layer, void *arg ));
+
+LDAP_F( int )
+ber_pvt_sb_clear_io LDAP_P(( Sockbuf *sb ));
+
+LDAP_F( int )
+ber_pvt_sb_close LDAP_P((Sockbuf *sb ));
+
+LDAP_F( int )
+ber_pvt_sb_set_nonblock LDAP_P(( Sockbuf *sb, int nb ));
+
+LDAP_F( int )
+ber_pvt_sb_set_readahead LDAP_P(( Sockbuf *sb, int rh ));
+
+LDAP_F( ber_slen_t )
+ber_pvt_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
+
+LDAP_F( ber_slen_t )
+ber_pvt_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
+
+LDAP_F( int )
+ber_pvt_sb_udp_set_dst LDAP_P((Sockbuf *sb, void *addr ));
+
+LDAP_F( void * )
+ber_pvt_sb_udp_get_src LDAP_P((Sockbuf *sb ));
+
+LDAP_F( int )
+ber_pvt_socket_set_nonblock LDAP_P(( ber_socket_t sd, int nb ));
+
+#endif /* _LBER_INT_H */
--- /dev/null
+/* sockbuf.c - i/o routines with support for adding i/o layers. */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif /* HAVE_IO_H */
+
+#if defined( HAVE_SYS_FILIO_H )
+#include <sys/filio.h>
+#elif defined( HAVE_SYS_IOCTL_H )
+#include <sys/ioctl.h>
+#endif
+
+#undef LDAP_F_PRE
+#define LDAP_F_PRE LDAP_F_EXPORT
+
+#include "lber-int.h"
+
+#ifdef LDAP_TEST
+#undef TEST_PARTIAL_READ
+#undef TEST_PARTIAL_WRITE
+#endif
+
+#define MAX_BUF_SIZE 65535
+#define MIN_BUF_SIZE 4096
+
+#define sockbuf_io_write( sb, buf, len ) \
+((sb)->sb_io->sbi_write( (sb), (buf), (len) ))
+
+#define sockbuf_io_read( sb, buf, len ) \
+((sb)->sb_io->sbi_read( (sb), (buf), (len) ))
+
+static ber_slen_t have_no_read( Sockbuf *sb, void *buf, ber_len_t len );
+static ber_slen_t have_no_write( Sockbuf *sb, void *buf, ber_len_t len );
+static int have_no_close( Sockbuf *sb );
+
+static Sockbuf_IO sb_IO_None=
+{
+ NULL, /* sbi_setup */
+ NULL, /* sbi_release */
+ have_no_read, /* sbi_read */
+ have_no_write, /* sbi_write */
+ have_no_close /* sbi_close */
+};
+
+static void
+update_status( Sockbuf *sb )
+{
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
+ sb->sb_buf_ready = (sb->sb_buf.buf_ptr < sb->sb_buf.buf_end);
+#ifdef USE_SASL
+ sb->sb_sec_ready = ((sb->sb_sec_buf_in.buf_end!=0) &&
+ (sb->sb_sec_buf_in.buf_ptr >=
+ sb->sb_sec_buf_in.buf_end));
+#endif
+}
+
+#ifdef LDAP_DEBUG
+static int
+status_is_ok( Sockbuf *sb )
+{
+ int obr;
+#ifdef USE_SASL
+ int osr;
+#endif
+
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
+ obr = sb->sb_buf_ready;
+#ifdef USE_SASL
+ osr = sb->sb_sec_ready;
+#endif
+
+ update_status(sb);
+ if (obr!=sb->sb_buf_ready)
+ return 0;
+
+#ifdef USE_SASL
+ if (osr!=sb->sb_sec_ready)
+ return 0;
+#endif
+
+ return 1;
+}
+#endif
+
+#ifdef USE_SASL
+static ber_len_t
+packet_length( char *buf )
+{
+ ber_len_t size;
+
+ assert( buf != NULL );
+
+ size = (((ber_len_t)buf[0])<<24)|
+ (((ber_len_t)buf[1])<<16)|
+ (((ber_len_t)buf[2])<<8)|
+ (((ber_len_t)buf[3]));
+
+ if ((size<0) || (size>MAX_BUF_SIZE)) {
+ /* somebody is trying to mess me up. */
+ lber_log_printf( LDAP_DEBUG_SASL, sb->sb_debug,
+ "SASL: received packet length of %d bytes\n",
+ size );
+ size = 16; /* this should lead to an error. */
+ }
+
+ return size + 4; /* include the size !!! */
+}
+#endif
+
+static int
+grow_buffer( Sockbuf_Buf * buf, ber_len_t minsize )
+{
+ ber_len_t pw;;
+
+ assert( buf != NULL );
+
+ for( pw=MIN_BUF_SIZE; pw<minsize; pw<<=1 ) {
+ if (pw > MAX_BUF_SIZE) {
+ /* this could mean that somebody is trying to crash us. */
+ return -1;
+ }
+ }
+ minsize = pw;
+
+ if (buf->buf_size<minsize) {
+ if ((buf->buf_base==NULL) || ((buf->buf_end==0) && (buf->buf_ptr==0))) {
+ /* empty buffer */
+ if (buf->buf_base!=NULL)
+ LBER_FREE( buf->buf_base );
+ assert( buf->buf_ptr==0 );
+ assert( buf->buf_end==0 );
+ buf->buf_base = LBER_MALLOC( minsize );
+ if (buf->buf_base==NULL)
+ return -1;
+ } else {
+ char *nb;
+ nb = LBER_REALLOC( buf->buf_base, minsize );
+ if (nb==NULL)
+ return -1;
+ buf->buf_base = nb;
+ }
+ buf->buf_size = minsize;
+ }
+ return 0;
+}
+
+#ifdef USE_SASL
+static ber_slen_t
+sockbuf_sec_release( Sockbuf *sb, char *buf, ber_len_t len )
+{
+ /* when this is called:
+ * sb->sb_sec_buf_in.buf_base points to a packet.
+ * sb->sb_sec_buf_in.buf_ptr contains the total bytes read.
+ * sb->sb_sec_end.buf_end contains the packet length.
+ *
+ * sb->sb_buf.buf_ptr == sb->sb_buf.buf_end == 0;
+ */
+ long rlen;
+ long total;
+ char *ptr;
+ char *end;
+ long size;
+
+ assert( buf != NULL );
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
+ assert( sb->sb_sec );
+ assert( sb->sb_sec->sbs_release );
+ assert( sb->sb_sec_buf_in.sb_ptr >= sb->sb_sec_buf_in.sb_end );
+
+ assert( sb->sb_buf.sb_ptr == 0 );
+ assert( sb->sb_buf.sb_end == 0 );
+
+ assert( status_is_ok(sb) );
+
+ total = 0;
+
+ ptr = sb->sb_sec_buf_in.buf_base;
+ end = ptr+ sb->sb_sec_buf_in.buf_ptr;
+ size = sb->sb_sec_buf_in.buf_end;
+
+ sb->sb_sec_ready = 1;
+
+ for(;(ptr+size<=end);) {
+ for(;;) {
+ rlen = sb->sb_sec->sbs_release( sb, ptr, size,
+ buf, len,
+ sb->sb_buf.buf_base,
+ sb->sb_buf.buf_size );
+ if (rlen==0) {
+ /* this means a security violation. */
+ return total; /* total ? total : 0 */
+ }
+ if (rlen<0) {
+ /* this means that the buffer isn't big enough. */
+ if (grow_buffer( &(sb->sb_buf), -rlen )<0)
+ /* memory violation. */
+ return total; /* total ? total : 0 */
+ continue;
+ }
+ /* if (rlen>0) */
+ break;
+ }
+ total+=rlen;
+
+ /* move to the next packet... */
+ ptr+=size;
+
+ if (ptr+4<=end)
+ size = packet_length( ptr );
+ /* size is always at least 4, so the loop condition is always OK !!*/
+ assert( size>=4 );
+
+ if (rlen<len) {
+ len-=rlen;
+ buf+=rlen;
+ } else {
+ sb->sb_buf_ready = (sb->sb_buf.buf_end = rlen - len) ? 1 : 0;
+ break;
+ }
+ }
+
+ if (ptr+size>end)
+ sb->sb_sec_ready = 0;
+ /* clean up the mess. */
+ if (ptr<end) {
+ /* copy back to beginning of buffer. */
+ SAFEMEMCPY( sb->sb_sec_buf_in.buf_base, ptr, end-ptr );
+ sb->sb_sec_buf_in.buf_ptr = 0;
+ sb->sb_sec_buf_in.buf_end -= (ptr - sb->sb_sec_buf_in.buf_base);
+ }
+ assert( status_is_ok(sb) );
+ return total;
+}
+
+static long
+sockbuf_sec_protect( Sockbuf *sb, char *buf, long len )
+{
+ long ret;
+ long blen;
+ long total;
+
+ assert( buf != NULL );
+
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
+ assert( sb->sb_sec_out.buf_end == 0 );
+ assert( sb->sb_sec_out.buf_ptr == 0 );
+
+ assert( sb->sb_sec );
+ assert( sb->sb_sec->sbs_protect );
+
+ assert( status_is_ok(sb) );
+
+ total = 0;
+ for(;(len);) {
+ for(;;) {
+ blen = len;
+ ret = sb->sb_sec->sbs_protect( sb, buf, &blen,
+ sb->sb_sec_out.buf_base+
+ sb->sb_sec_out.buf_end,
+ sb->sb_sec_out.buf_size -
+ sb->sb_sec_out.buf_end );
+ if (ret==0)
+ /* protection error ? */
+ return total;
+ if (ret<0) {
+ if (grow_buffer( &(sb->sb_sec_out),-ret-sb->sb_sec_out.buf_end )<0)
+ /* memory error */
+ return total;
+ continue;
+ }
+ /* else if (ret>0) */
+ break;
+ }
+ sb->sb_sec_out.buf_end += ret;
+ len -= blen;
+ total += blen;
+ }
+ assert( status_is_ok(sb) );
+ return total;
+}
+#endif
+
+static ber_len_t
+sockbuf_copy_out( Sockbuf *sb, char **buf, ber_len_t len )
+{
+ ber_len_t blen = (sb->sb_buf.buf_end - sb->sb_buf.buf_ptr );
+
+ assert( buf != NULL );
+
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( status_is_ok(sb) );
+
+ if (blen) {
+ ber_len_t rlen = (blen<len) ? blen : len;
+ memcpy( *buf, sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, rlen );
+ sb->sb_buf.buf_ptr+=rlen;
+ *buf+=rlen;
+ len -= rlen;
+ if (sb->sb_buf.buf_ptr >= sb->sb_buf.buf_end) {
+ sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0;
+ sb->sb_buf_ready = 0;
+ } else {
+ sb->sb_buf_ready = 1;
+ }
+ }
+ assert( status_is_ok(sb) );
+ return len;
+}
+
+Sockbuf *ber_sockbuf_alloc( void )
+{
+ Sockbuf *sb;
+
+ ber_int_options.lbo_valid = LBER_INITIALIZED;
+
+ sb = LBER_CALLOC(1, sizeof(Sockbuf));
+
+ if( sb == NULL ) return NULL;
+
+ ber_pvt_sb_init( sb );
+ return sb;
+}
+
+Sockbuf *ber_sockbuf_alloc_fd( ber_socket_t fd )
+{
+ Sockbuf *sb = ber_sockbuf_alloc();
+
+ if( sb == NULL ) return NULL;
+
+ ber_pvt_sb_set_desc( sb, fd );
+ ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
+ return sb;
+}
+
+void ber_sockbuf_free( Sockbuf *sb )
+{
+ assert(sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+ ber_pvt_sb_destroy( sb );
+ LBER_FREE(sb);
+}
+
+ber_slen_t
+ber_pvt_sb_read( Sockbuf *sb, void *buf_arg, ber_len_t len )
+{
+ char *buf;
+ ber_slen_t ret;
+
+ assert( buf_arg != NULL );
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( status_is_ok(sb) );
+
+ /* slapd might have problems with this */
+ assert( ber_pvt_sb_in_use( sb ) );
+
+#ifdef TEST_PARTIAL_READ
+ if ((rand() & 3)==1) { /* 1 out of 4 */
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+
+ if( len > 0 )
+ len = (rand() % len)+1;
+#endif
+
+ buf = (char *) buf_arg;
+
+ if (sb->sb_buf.buf_ptr!=sb->sb_buf.buf_end) {
+ len = sockbuf_copy_out( sb, &buf, len );
+ if (len==0) {
+ return (buf - (char *) buf_arg);
+ }
+ }
+
+#ifdef USE_SASL
+ if (sb->sb_sec) {
+ ber_slen_t max;
+ assert( sb->sb_sec->sbs_release );
+ assert( sb->sb_sec_buf_in.buf_base );
+ if (sb->sb_read_ahead) {
+ max = sb->sb_sec_buf_in.buf_size - sb->sb_sec_buf_in.buf_ptr;
+ } else {
+ max = sb->sb_sec_buf_in.buf_end - sb->sb_sec_buf_in.buf_ptr;
+ if (max<=0) {
+ /* special situation. This means that we need to read the first
+ * four bytes for the packet length.
+ */
+ max += 4;
+ }
+ }
+ for(;;) {
+ /* read from stream into sb_sec_buf_in */
+ for(;;) {
+ ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base +
+ sb->sb_sec_buf_in.buf_ptr, max );
+#ifdef EINTR
+ if ((ret<0) && (errno==EINTR))
+ continue;
+#endif
+ break;
+ }
+ if (ret<=0) {
+ /* read error. return */
+ goto do_return;
+ }
+ sb->sb_sec_buf_in.buf_ptr += ret;
+
+ if (sb->sb_sec_buf_in.buf_ptr < sb->sb_sec_buf_in.buf_end) {
+ /* did not finish a packet. give up. */
+ goto do_return;
+ }
+
+ if (sb->sb_sec_buf_in.buf_end == 0) {
+ /* Were trying to read the first four bytes... */
+ if (sb->sb_sec_buf_in.buf_ptr < 4) {
+ /* did not read enough for packet length. give up. */
+ goto do_return;
+ }
+ /* calculate the packet length. */
+ sb->sb_sec_buf_in.buf_end =
+ packet_length(sb->sb_sec_buf_in.buf_base );
+ if ((sb->sb_sec_buf_in.buf_end > sb->sb_sec_buf_in.buf_size) &&
+ (grow_buffer( &(sb->sb_sec_buf_in), sb->sb_sec_buf_in.buf_end)<0)) {
+ /* buffer has to be to big. exit with error. */
+ ret = -1;
+ goto do_return;
+ }
+ if (sb->sb_sec_buf_in.buf_ptr >= sb_sec_buf_in.buf_end) {
+ /* finished packet. decode it. */
+ goto decode_packet;
+ }
+ /* did not finish packet yet. try again ? */
+ if (sb->sb_read_ahead) {
+ /* we were trying to read the max anyway. forget it */
+ goto do_return;
+ }
+ }
+decode_packet:
+ /* we read enough for at least 1 packet */
+ ret = sockbuf_sec_release( sb, buf, len );
+ if (ret<=0) {
+ /* something went wrong... */
+ goto do_return;
+ }
+ buf+=ret;
+ len-=ret;
+ /* we are finished !!! */
+ if ((len==0) || (ret!=max))
+ goto do_return;
+ }
+ } else {
+#endif
+ if (sb->sb_read_ahead) {
+ ber_slen_t max;
+ max = sb->sb_buf.buf_size - sb->sb_buf.buf_end;
+ if (max> (ber_slen_t) len) {
+ for(;;) {
+ ret = sockbuf_io_read( sb,
+ sb->sb_buf.buf_base +
+ sb->sb_buf.buf_end,
+ max );
+#ifdef EINTR
+ if ((ret<0) && (errno==EINTR))
+ continue;
+#endif
+ break;
+ }
+ if (ret<=0) {
+ /* some error occured */
+ goto do_return;
+ }
+ sb->sb_buf.buf_end += ret;
+ /* move out the data... */
+ len = sockbuf_copy_out( sb, &buf, len );
+ goto do_return;
+ }
+ }
+ /* no read_ahead, just try to put the data in the buf. */
+ for(;;) {
+ ret = sockbuf_io_read( sb, buf, len );
+#ifdef EINTR
+ if ((ret<0) && (errno==EINTR))
+ continue;
+#endif
+ break;
+ }
+ if (ret>0) {
+ buf+=ret;
+ len-=ret;
+ }
+ /* we might as well return, since there is nothing to do... */
+#ifdef USE_SASL
+ }
+#endif
+do_return:
+ assert( status_is_ok(sb) );
+ if ((ret<=0) && (buf==buf_arg)) {
+ /* there was an error. */
+ return ret;
+ }
+ return (buf - ((char *) buf_arg));
+}
+
+#ifdef USE_SASL
+long sockbuf_do_write( Sockbuf *sb )
+{
+ long to_go;
+
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
+ to_go = sb->sb_sec_out.buf_end - sb->sb_sec_out.buf_ptr;
+ assert( to_go > 0 );
+ /* there is something left of the last time... */
+ for(;;) {
+ ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+
+ sb->sb_sec_out.buf_ptr, to_go );
+#ifdef EINTR
+ if ((ret<0) && (errno==EINTR))
+ continue;
+#endif
+ break;
+ }
+ if (ret<=0) /* error */
+ return ret;
+ sb->sb_sec_out.buf_ptr += ret;
+ if (ret<to_go) /* not enough data, so pretend no data was sent. */
+ return -1;
+ return ret;
+}
+#endif
+
+ber_slen_t ber_pvt_sb_write( Sockbuf *sb, void *buf, ber_len_t len_arg )
+{
+ ber_slen_t ret;
+ ber_len_t len = len_arg;
+
+ assert( buf != NULL );
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( status_is_ok(sb) );
+
+ /* slapd might have problems with this */
+ assert( ber_pvt_sb_in_use( sb ) );
+
+#ifdef TEST_PARTIAL_WRITE
+ if ((rand() & 3)==1) { /* 1 out of 4 */
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+
+ len_arg = (rand() % len_arg)+1;
+ len = len_arg;
+#endif
+
+#ifdef USE_SASL
+ if (sb->sb_sec) {
+ assert( sb->sb_sec_prev_len <= len );
+ if (sb->sb_sec_prev_len) {
+ ret = sockbuf_do_write( sb );
+ if (ret<=0)
+ return ret;
+ /* finished. */
+ len -= sb->sb_sec_prev_len;
+ sb->sb_sec_prev_len = 0;
+ sb->sb_sec_out.buf_end = sb->sb_sec_out.buf_ptr = 0;
+ }
+ /* now protect the next packet. */
+ ret = sockbuf_sec_protect( sb, buf, len );
+ if (ret<=0)
+ return ret;
+ ret = sockbuf_do_write( sb );
+ if (ret<=0) {
+ sb->sb_sec_prev_len = len;
+ return ret;
+ }
+ return len_arg;
+ } else {
+#endif
+ for(;;) {
+ ret = sockbuf_io_write( sb, buf, len );
+#ifdef EINTR
+ if ((ret<0) && (errno==EINTR))
+ continue;
+#endif
+ break;
+ }
+#ifdef USE_SASL
+ }
+#endif
+
+ return ret;
+}
+
+int ber_pvt_sb_close( Sockbuf *sb )
+{
+ int ret;
+
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( sb->sb_io );
+ assert( sb->sb_io->sbi_close );
+ assert( status_is_ok(sb) );
+ assert( ber_pvt_sb_in_use( sb ) );
+
+ ret = sb->sb_io->sbi_close( sb );
+ ber_pvt_sb_set_desc( sb, -1 );
+
+ return ret;
+}
+
+int ber_pvt_sb_set_readahead( Sockbuf *sb, int rh )
+{
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( status_is_ok(sb) );
+ sb->sb_read_ahead = (rh!=0);
+ return 0;
+}
+
+int ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
+{
+#if HAVE_FCNTL
+ int flags = fcntl(ber_pvt_sb_get_desc(sb), F_GETFL);
+ if( nb ) {
+ flags |= O_NONBLOCK;
+ } else {
+ flags &= ~O_NONBLOCK;
+ }
+ return fcntl( ber_pvt_sb_get_desc(sb), F_SETFL, flags );
+
+#elif defined( FIONBIO )
+ ioctl_t status = nb ? 1 : 0;
+ return ioctl( sd, FIONBIO, &status );
+#endif
+}
+
+#define USE_NONBLOCK
+#ifdef USE_NONBLOCK
+int ber_pvt_sb_set_nonblock( Sockbuf *sb, int nb )
+{
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( status_is_ok(sb) );
+ if (nb) {
+ sb->sb_non_block = 1;
+#if 0
+ sb->sb_read_ahead = 1;
+#endif
+ } else {
+ sb->sb_non_block = 0;
+#if 0
+ sb->sb_read_ahead = 0;
+#endif
+ }
+ if (ber_pvt_sb_in_use(sb)) {
+ return ber_pvt_socket_set_nonblock(
+ ber_pvt_sb_get_desc(sb), nb );
+ }
+ return 0;
+}
+#endif
+
+#define sockbuf_buf_init( bb ) do { \
+ Sockbuf_Buf *sbb = (bb); \
+ sbb->buf_base = NULL; \
+ sbb->buf_ptr = 0; \
+ sbb->buf_end = 0; \
+ sbb->buf_size = 0; \
+ } while(0)
+
+static int
+sockbuf_buf_destroy( Sockbuf_Buf *buf )
+{
+ assert( buf != NULL);
+
+ if (buf->buf_base)
+ LBER_FREE( buf->buf_base );
+ sockbuf_buf_init( buf );
+ return 0;
+}
+
+int ber_pvt_sb_init( Sockbuf *sb )
+{
+ assert( sb != NULL);
+
+ ber_int_options.lbo_valid = LBER_INITIALIZED;
+
+ sb->sb_valid=LBER_VALID_SOCKBUF;
+ sb->sb_options = 0;
+ sb->sb_debug = 0;
+ sb->sb_trans_ready = 0;
+ sb->sb_buf_ready = 0;
+#ifdef USE_SASL
+ sb->sb_sec_ready = 0;
+#endif
+ sb->sb_read_ahead = 1; /* test */
+ sb->sb_non_block = 0;
+ sb->sb_trans_needs_read = 0;
+ sb->sb_trans_needs_write = 0;
+ sb->sb_fd = -1;
+ sb->sb_iodata = NULL;
+ sb->sb_io = &sb_IO_None;
+ sb->sb_sd = -1;
+#ifdef DEADWOOD
+ sb->sb_max_incoming = 0;
+#endif
+ sockbuf_buf_init( &(sb->sb_buf) );
+#ifdef USE_SASL
+ sockbuf_buf_init( &(sb->sb_sec_buf_in) );
+ sockbuf_buf_init( &(sb->sb_sec_buf_out) );
+ sb->sb_sdata = NULL;
+ sb->sb_sec = NULL;
+ sb->sb_sec_prev_len = 0;
+#endif
+
+ assert( SOCKBUF_VALID( sb ) );
+ return 0;
+}
+
+int ber_pvt_sb_destroy( Sockbuf *sb )
+{
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID(sb) );
+#ifdef USE_SASL
+ ber_pvt_sb_clear_sec(sb);
+ sockbuf_buf_destroy( &(sb->sb_sec_buf_in) );
+ sockbuf_buf_destroy( &(sb->sb_sec_buf_out) );
+#endif
+ ber_pvt_sb_clear_io(sb);
+ sockbuf_buf_destroy( &(sb->sb_buf) );
+ return ber_pvt_sb_init( sb );
+}
+
+#ifdef USE_SASL
+int ber_pvt_sb_set_sec( Sockbuf *sb, Sockbuf_Sec * sec, void *arg )
+{
+ int len;
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID( *sb ) );
+ if ((sb->sb_sec) || (sec==NULL))
+ return -1;
+
+ sb->sb_sec = sec;
+
+ if ((sec->sbs_setup) && (sec->sbs_setup( sb, arg)<0)) {
+ return -1;
+ }
+
+ len = sb->sb_buf.buf_end - sb->sb_buf.buf_ptr;
+
+ if (len>0) {
+ /* move this to the security layer. */
+ if (grow_buffer( &(sb->sb_sec_buf_in), len )<0)
+ return -1;
+ memcpy( sb->sb_sec_buf_in.buf_base,
+ sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, len );
+ sb->sb_sec_buf_in.buf_ptr = len;
+ sb->sb_sec_buf_in.buf_end = (len>4) ? packet_length( sb->sb_sec_buf_in ) : 0;
+ sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0;
+ }
+ update_status();
+ return 0;
+}
+
+int ber_pvt_sb_clear_sec( Sockbuf *sb )
+{
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+
+ if (sb->sb_buf.buf_ptr!=0)
+ return -1;
+ if (sb->sb_sec==NULL)
+ return -1;
+ if ((sb->sb_sec->sbs_remove) && (sb->sb_sec->sbs_remove(sb)<0))
+ return -1;
+
+ sb->sb_sec = NULL;
+ if (sb->sb_sec_buf_in.buf_ptr!=0) {
+ if (grow_buffer( &(sb->sb_buf),
+ sb->sb_buf.buf_end + sb->sb_sec_buf_in.buf_ptr)<0)
+ return -1;
+ memcpy( sb->sb_buf.buf_base + sb->sb_buf.buf_end,
+ sb->sb_sec_buf_in.buf_base, sb->sb_sec_buf_in.buf_ptr );
+ sb->sb_buf.buf_end += sb->sb_sec_buf_in.buf_ptr;
+ sb->sb_buf_ready = 1;
+ }
+ sockbuf_buf_destroy( &(sb->sb_sec_buf_in) );
+ assert( sb->sb_sec_buf.buf_end==0 );
+ sockbuf_buf_destroy( &(sb->sb_sec_buf_out) );
+
+ sb->sb_sec_ready = 0;
+
+ return 0;
+}
+#endif
+
+int ber_pvt_sb_set_io( Sockbuf *sb, Sockbuf_IO *trans, void *arg )
+{
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+ assert( sb->sb_io == &sb_IO_None );
+
+ if (trans==NULL)
+ return -1;
+
+ sb->sb_io = trans;
+
+ if ((trans->sbi_setup) && (trans->sbi_setup( sb, arg)<0))
+ return -1;
+
+ return 0;
+}
+
+int ber_pvt_sb_clear_io( Sockbuf *sb )
+{
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+
+ if (sb->sb_io==&sb_IO_None)
+ return -1;
+
+ if ((sb->sb_io->sbi_remove) && (sb->sb_io->sbi_remove( sb )<0))
+ return -1;
+
+ sb->sb_io = &sb_IO_None;
+
+ sb->sb_trans_ready = 0;
+ sb->sb_trans_needs_read = 0;
+ sb->sb_trans_needs_write = 0;
+
+ return 0;
+}
+
+/*
+ * Support for TCP
+ */
+
+static ber_slen_t
+stream_read( Sockbuf *sb, void *buf, ber_len_t len )
+{
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+
+#if defined(MACOS)
+/*
+ * MacTCP/OpenTransport
+ */
+ return tcpread( ber_pvt_sb_get_desc(sb), 0, (unsigned char *)buf,
+ len, NULL );
+
+#elif defined( HAVE_PCNFS ) || \
+ defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
+/*
+ * PCNFS (under DOS)
+ */
+/*
+ * Windows Socket API (under DOS/Windows 3.x)
+ */
+/*
+ * 32-bit Windows Socket API (under Windows NT or Windows 95)
+ */
+ {
+ int rc;
+ rc = recv( ber_pvt_sb_get_desc(sb), buf, len, 0 );
+#ifdef HAVE_WINSOCK
+ if ( rc < 0 ) errno = WSAGetLastError();
+#endif
+ return rc;
+ }
+#elif defined( HAVE_NCSA )
+/*
+ * NCSA Telnet TCP/IP stack (under DOS)
+ */
+ return nread( ber_pvt_sb_get_desc(sb), buf, len );
+
+#else
+ return read( ber_pvt_sb_get_desc(sb), buf, len );
+#endif
+}
+
+static ber_slen_t
+stream_write( Sockbuf *sb, void *buf, ber_len_t len )
+{
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+
+#if defined(MACOS)
+/*
+ * MacTCP/OpenTransport
+ */
+#define MAX_WRITE 65535
+ return tcpwrite( ber_pvt_sb_get_desc(sb),
+ (unsigned char *)(buf),
+ (len<MAX_WRITE)? len : MAX_WRITE );
+
+#elif defined( HAVE_PCNFS) \
+ || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
+/*
+ * PCNFS (under DOS)
+ */
+/*
+ * Windows Socket API (under DOS/Windows 3.x)
+ */
+/*
+ * 32-bit Windows Socket API (under Windows NT or Windows 95)
+ */
+
+ {
+ int rc;
+ rc = send( ber_pvt_sb_get_desc(sb), buf, len, 0 );
+#ifdef HAVE_WINSOCK
+ if ( rc < 0 ) errno = WSAGetLastError();
+#endif
+ return rc;
+ }
+
+#elif defined(HAVE_NCSA)
+ return netwrite( ber_pvt_sb_get_desc(sb), buf, len );
+
+#elif defined(VMS)
+/*
+ * VMS -- each write must be 64K or smaller
+ */
+#define MAX_WRITE 65535
+ return write( ber_pvt_sb_get_desc(sb), buf,
+ (len<MAX_WRITE)? len : MAX_WRITE);
+#else
+ return write( ber_pvt_sb_get_desc(sb), buf, len );
+#endif
+}
+
+static int
+stream_close( Sockbuf *sb )
+{
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+ tcp_close( ber_pvt_sb_get_desc( sb ) );
+ return 0;
+}
+
+Sockbuf_IO ber_pvt_sb_io_tcp=
+{
+ NULL, /* sbi_setup */
+ NULL, /* sbi_release */
+ stream_read, /* sbi_read */
+ stream_write, /* sbi_write */
+ stream_close, /* sbi_close */
+};
+
+/*
+ * Support for UDP (CLDAP)
+ */
+
+struct dgram_data
+{
+ struct sockaddr dst;
+ struct sockaddr src;
+};
+
+static int
+dgram_setup( Sockbuf *sb, void *arg )
+{
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+
+ sb->sb_iodata = LBER_MALLOC( sizeof( struct dgram_data ) );
+ if (sb->sb_iodata==NULL)
+ return -1;
+ sb->sb_read_ahead = 1; /* important since udp is packet based. */
+ return 0;
+}
+
+static int
+dgram_release( Sockbuf *sb )
+{
+ assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+
+ LBER_FREE( sb->sb_iodata );
+ return 0;
+}
+
+static ber_slen_t
+dgram_read( Sockbuf *sb, void *buf, ber_len_t len )
+{
+#ifdef LDAP_CONNECTIONLESS
+ ber_slen_t rc;
+ socklen_t addrlen;
+ struct dgram_data *dd;
+
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( buf != NULL );
+
+ dd = (struct dgram_data *)(sb->sb_iodata);
+
+ addrlen = sizeof( struct sockaddr );
+ rc=recvfrom( ber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->src), &addrlen );
+
+ if ( sb->sb_debug ) {
+ ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug,
+ "dgram_read udp_read %d bytes\n",
+ rc );
+ if ( rc > 0 )
+ ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug,
+ buf, rc );
+ }
+ return rc;
+# else /* LDAP_CONNECTIONLESS */
+ return -1;
+# endif /* LDAP_CONNECTIONLESS */
+}
+
+static ber_slen_t
+dgram_write( Sockbuf *sb, void *buf, ber_len_t len )
+{
+#ifdef LDAP_CONNECTIONLESS
+ ber_slen_t rc;
+ struct dgram_data *dd;
+
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( buf != NULL );
+
+ dd = (struct dgram_data *)(sb->sb_iodata);
+
+ rc=sendto( ber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->dst),
+ sizeof( struct sockaddr ) );
+
+ if ( rc <= 0 )
+ return( -1 );
+
+ /* fake error if write was not atomic */
+ if (rc < len) {
+# ifdef EMSGSIZE
+ errno = EMSGSIZE;
+# endif
+ return( -1 );
+ }
+ return rc;
+#else
+ return -1;
+#endif
+}
+
+static int
+dgram_close( Sockbuf *sb )
+{
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
+ tcp_close( ber_pvt_sb_get_desc(sb) );
+ return 0;
+}
+
+Sockbuf_IO ber_pvt_sb_io_udp=
+{
+ dgram_setup, /* sbi_setup */
+ dgram_release, /* sbi_release */
+ dgram_read, /* sbi_read */
+ dgram_write, /* sbi_write */
+ dgram_close, /* sbi_close */
+};
+
+int ber_pvt_sb_udp_set_dst(Sockbuf *sb, void *addr )
+{
+ struct dgram_data *dd;
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( sb->sb_io == &ber_pvt_sb_io_udp );
+ dd = (struct dgram_data *) (sb->sb_iodata);
+ memcpy( &(dd->dst), addr, sizeof( struct sockaddr ) );
+ return 0;
+}
+
+void *ber_pvt_sb_udp_get_src( Sockbuf *sb )
+{
+ struct dgram_data *dd;
+
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+ assert( sb->sb_io == &ber_pvt_sb_io_udp );
+ dd = (struct dgram_data *) (sb->sb_iodata);
+ return &(dd->src);
+}
+
+/*
+ * debug routines.
+ *
+ * BUGS:
+ * These routines should really call abort, but at the moment that would
+ * break the servers.
+ */
+
+static ber_slen_t
+have_no_read( Sockbuf *sb, void *buf, ber_len_t len )
+{
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
+ ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug,
+ "warning: reading from uninitialized sockbuf\n");
+ errno = EBADF;
+ return -1;
+}
+
+static ber_slen_t
+have_no_write( Sockbuf *sb, void *buf, ber_len_t len )
+{
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
+ ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug,
+ "warning: writing to uninitialized sockbuf\n");
+ errno = EBADF;
+ return -1;
+}
+
+static int
+have_no_close( Sockbuf *sb )
+{
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
+ assert( 0 );
+ return -1;
+}
--- /dev/null
+## Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+##
+## Makefile.in for LDAP -lldap
+##
+LIBRARY = libldap.la
+XLIBRARY = ../libldap.a
+
+PROGRAMS = apitest ltest ttest
+
+SRCS = bind.c open.c result.c error.c compare.c search.c \
+ controls.c messages.c references.c extended.c \
+ modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \
+ getfilter.c sasl.c sbind.c kbind.c unbind.c friendly.c cldap.c \
+ free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
+ getdn.c getentry.c getattr.c getvalues.c addentry.c \
+ request.c getdxbyname.c os-ip.c url.c charset.c \
+ init.c options.c print.c string.c util-int.c schema.c \
+ charray.c digest.c tls.c
+OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
+ controls.lo messages.lo references.lo extended.lo \
+ modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \
+ getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \
+ free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \
+ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
+ request.lo getdxbyname.lo os-ip.lo url.lo charset.lo \
+ init.lo options.lo print.lo string.lo util-int.lo schema.lo \
+ charray.lo digest.lo tls.lo
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldap -llber
+XXLIBS = $(SECURITY_LIBS) $(TLS_LIBS)
+
+apitest: $(LIBRARY) apitest.o $(LDAP_LIBLBER_DEPEND)
+ $(LTLINK) $(LDFLAGS) -o $@ apitest.o $(LIBS)
+ltest: $(LIBRARY) test.o $(LDAP_LIBLBER_DEPEND)
+ $(LTLINK) $(LDFLAGS) -o $@ test.o $(LIBS)
+ttest: $(LIBRARY) tmpltest.o $(LDAP_LIBLBER_DEPEND)
+ $(LTLINK) $(LDFLAGS) -o $@ tmpltest.o $(LIBS)
+
+CFFILES=ldap.conf ldapfilter.conf ldaptemplates.conf ldapsearchprefs.conf
+
+install-local: $(CFFILES) FORCE
+ -$(MKDIR) $(libdir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(libdir)
+ -$(MKDIR) $(sysconfdir)
+ @for i in $(CFFILES); do \
+ if test ! -f $(sysconfdir)/$$i; then \
+ echo "installing $$i in $(sysconfdir)"; \
+ echo "$(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(sysconfdir)/$$i"; \
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(sysconfdir)/$$i; \
+ else \
+ echo "PRESERVING EXISTING CONFIGURATION FILE $(sysconfdir)/$$i" ; \
+ fi; \
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(sysconfdir)/$$i.default; \
+ done
+ -$(MKDIR) $(datadir)
+ -$(MV) $(datadir)/ldapfriendly $(datadir)/ldapfriendly-
+ $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/ldapfriendly $(datadir)/ldapfriendly
+
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * OpenLDAP API Test
+ * Written by: Kurt Zeilenga
+ *
+ * This program is designed to test API features of implementations
+ * of the IETF draft specifications.
+ *
+ */
+#include "portable.h"
+
+#include <ac/stdlib.h>
+
+#include <stdio.h>
+
+#include <ldap.h>
+
+int
+main(int argc, char **argv)
+{
+ LDAPAPIInfo api;
+ int ival;
+ char *sval;
+
+ printf("Compile time API Information\n");
+
+#ifdef LDAP_API_INFO_VERSION
+ api.ldapai_info_version = LDAP_API_INFO_VERSION;
+ printf(" API Info version: %d\n", (int) api.ldapai_info_version);
+#else
+ api.ldapai_info_version = 1;
+ printf(" API Info version: unknown\n");
+#endif
+
+#ifdef LDAP_FEATURE_INFO_VERSION
+ printf(" Feature Info version: %d\n", (int) LDAP_FEATURE_INFO_VERSION);
+#else
+ printf(" Feature Info version: unknown\n");
+ api.ldapai_info_version = 1;
+#endif
+
+#ifdef LDAP_API_VERSION
+ printf(" API version: %d\n", (int) LDAP_API_VERSION);
+#else
+ printf(" API version: unknown\n");
+#endif
+
+#ifdef LDAP_VERSION
+ printf(" Protocol Version: %d\n", (int) LDAP_VERSION);
+#else
+ printf(" Protocol Version: unknown\n");
+#endif
+#ifdef LDAP_VERSION_MIN
+ printf(" Protocol Min: %d\n", (int) LDAP_VERSION_MIN);
+#else
+ printf(" Protocol Min: unknown\n");
+#endif
+#ifdef LDAP_VERSION_MAX
+ printf(" Protocol Max: %d\n", (int) LDAP_VERSION_MAX);
+#else
+ printf(" Protocol Max: unknown\n");
+#endif
+#ifdef LDAP_VENDOR_NAME
+ printf(" Vendor Name: %s\n", LDAP_VENDOR_NAME);
+#else
+ printf(" Vendor Name: unknown\n");
+#endif
+#ifdef LDAP_VENDOR_VERSION
+ printf(" Vendor Version: %d\n", (int) LDAP_VENDOR_VERSION);
+#else
+ printf(" Vendor Version: unknown\n");
+#endif
+
+ if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) != LDAP_SUCCESS) {
+ fprintf(stderr, "%s: ldap_get_option(API_INFO) failed\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ printf("\nExecution time API Information\n");
+ printf(" API Info version: %d\n", api.ldapai_info_version);
+
+ if (api.ldapai_info_version != LDAP_API_INFO_VERSION) {
+ printf(" API INFO version mismatch: got %d, expected %d\n",
+ api.ldapai_info_version, LDAP_API_INFO_VERSION);
+ return EXIT_FAILURE;
+ }
+
+ printf(" API Version: %d\n", api.ldapai_api_version);
+ printf(" Protocol Max: %d\n", api.ldapai_protocol_version);
+
+ if(api.ldapai_extensions == NULL) {
+ printf(" Extensions: none\n");
+
+ } else {
+ int i;
+ for(i=0; api.ldapai_extensions[i] != NULL; i++) /* empty */;
+ printf(" Extensions: %d\n", i);
+ for(i=0; api.ldapai_extensions[i] != NULL; i++) {
+#ifdef LDAP_OPT_API_FEATURE_INFO
+ LDAPAPIFeatureInfo fi;
+ fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
+ fi.ldapaif_name = api.ldapai_extensions[i];
+ fi.ldapaif_version = 0;
+
+ if( ldap_get_option(NULL, LDAP_OPT_API_FEATURE_INFO, &fi) == LDAP_SUCCESS ) {
+ if(fi.ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
+ printf(" %s feature info mismatch: got %d, expected %d\n",
+ api.ldapai_extensions[i],
+ LDAP_FEATURE_INFO_VERSION,
+ fi.ldapaif_info_version);
+
+ } else {
+ printf(" %s: version %d\n",
+ fi.ldapaif_name,
+ fi.ldapaif_version);
+ }
+
+ } else {
+ printf(" %s (NO FEATURE INFO)\n",
+ api.ldapai_extensions[i]);
+ }
+
+#else
+ printf(" %s\n",
+ api.ldapai_extensions[i]);
+#endif
+
+ ldap_memfree(api.ldapai_extensions[i]);
+ }
+ ldap_memfree(api.ldapai_extensions);
+ }
+
+ printf(" Vendor Name: %s\n", api.ldapai_vendor_name);
+ ldap_memfree(api.ldapai_vendor_name);
+
+ printf(" Vendor Version: %d\n", api.ldapai_vendor_version);
+
+ printf("\nExecution time Default Options\n");
+
+ if(ldap_get_option(NULL, LDAP_OPT_DEREF, &ival) != LDAP_SUCCESS) {
+ fprintf(stderr, "%s: ldap_get_option(api) failed\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ printf(" DEREF: %d\n", ival);
+
+ if(ldap_get_option(NULL, LDAP_OPT_SIZELIMIT, &ival) != LDAP_SUCCESS) {
+ fprintf(stderr, "%s: ldap_get_option(sizelimit) failed\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ printf(" SIZELIMIT: %d\n", ival);
+
+ if(ldap_get_option(NULL, LDAP_OPT_TIMELIMIT, &ival) != LDAP_SUCCESS) {
+ fprintf(stderr, "%s: ldap_get_option(timelimit) failed\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ printf(" TIMELIMIT: %d\n", ival);
+
+ if(ldap_get_option(NULL, LDAP_OPT_REFERRALS, &ival) != LDAP_SUCCESS) {
+ fprintf(stderr, "%s: ldap_get_option(referrals) failed\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ printf(" REFERRALS: %s\n", ival ? "on" : "off");
+
+ if(ldap_get_option(NULL, LDAP_OPT_RESTART, &ival) != LDAP_SUCCESS) {
+ fprintf(stderr, "%s: ldap_get_option(restart) failed\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ printf(" RESTART: %s\n", ival ? "on" : "off");
+
+ if(ldap_get_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ival) != LDAP_SUCCESS) {
+ fprintf(stderr, "%s: ldap_get_option(protocol version) failed\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ printf(" PROTOCOL VERSION: %d\n", ival);
+
+ if(ldap_get_option(NULL, LDAP_OPT_HOST_NAME, &sval) != LDAP_SUCCESS) {
+ fprintf(stderr, "%s: ldap_get_option(host name) failed\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ if( sval != NULL ) {
+ printf(" HOST NAME: %s\n", sval);
+ ldap_memfree(sval);
+ } else {
+ puts(" HOST NAME: <not set>");
+ }
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* digest.c:
+ * DIGEST-MD5 routines
+ */
+
+#include "portable.h"
+
+#ifdef DIGEST_MD5
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+#include "ldap_pvt.h"
+
+#define TK_NOENDQUOTE -2
+#define TK_OUTOFMEM -1
+
+#define TK_EOS 0
+#define TK_UNEXPCHAR 1
+#define TK_BAREWORD 2
+#define TK_COMMA 3
+#define TK_EQUALS 4
+#define TK_QDSTRING 5
+
+struct token {
+ int type;
+ char *sval;
+};
+
+static int
+get_token(const char ** sp, char ** token_val)
+{
+ int kind;
+ const char * p;
+ const char * q;
+ char * res;
+
+ *token_val = NULL;
+
+ if( (**sp) != '\0' || iscntrl(**sp) || !isascii(**sp) ) {
+ (*sp)++;
+ return TK_UNEXPCHAR;
+ }
+
+ switch (**sp) {
+ case '\0':
+ kind = TK_EOS;
+ (*sp)++;
+ break;
+
+ case ',':
+ kind = TK_COMMA;
+ (*sp)++;
+ break;
+
+ case '=':
+ kind = TK_EQUALS;
+ (*sp)++;
+ break;
+
+ case '\"':
+ kind = TK_QDSTRING;
+ (*sp)++;
+
+ for (p = *sp;
+ **sp != '\"' && **sp != '\0' && isascii(**sp);
+ (*sp)++ )
+ {
+ if(**sp == '\\') {
+ (*sp)++;
+ if( **sp == '\0' ) break;
+ }
+ }
+
+ if ( **sp == '\"' ) {
+ q = *sp;
+ res = LDAP_MALLOC(q-p+1);
+ if ( !res ) {
+ kind = TK_OUTOFMEM;
+ } else {
+ strncpy(res,p,q-p);
+ res[q-p] = '\0';
+ *token_val = res;
+ }
+ (*sp)++;
+
+ } else {
+ kind = TK_NOENDQUOTE;
+ }
+
+ break;
+
+ default:
+ kind = TK_BAREWORD;
+ p = *sp;
+ while ( isascii(**sp) &&
+ !iscntrl(**sp) &&
+ !isspace(**sp) &&
+ **sp != '(' &&
+ **sp != ')' &&
+ **sp != '<' &&
+ **sp != '>' &&
+ **sp != '@' &&
+ **sp != ',' &&
+ **sp != ';' &&
+ **sp != ':' &&
+ **sp != '\\'&&
+ **sp != '\"'&&
+ **sp != '/' &&
+ **sp != '[' &&
+ **sp != ']' &&
+ **sp != '?' &&
+ **sp != '=' &&
+ **sp != '{' &&
+ **sp != '}' &&
+ **sp != '\0' )
+ (*sp)++;
+ q = *sp;
+ res = LDAP_MALLOC(q-p+1);
+ if ( !res ) {
+ kind = TK_OUTOFMEM;
+ } else {
+ strncpy(res,p,q-p);
+ res[q-p] = '\0';
+ *token_val = res;
+ }
+ }
+
+ return kind;
+}
+
+struct kv {
+ char *key;
+ char *value;
+};
+
+static void kv_destory( struct kv **kv )
+{
+ int i;
+
+ if( kv == NULL ) return;
+
+ for( i=0; kv[i] != NULL; i++ ) {
+ if( kv[i]->key != NULL ) {
+ LDAP_FREE( kv[i]->key );
+ }
+
+ if( kv[i]->value != NULL ) {
+ LDAP_FREE( kv[i]->value );
+ }
+
+ LDAP_FREE( kv[i] );
+ }
+
+ LDAP_FREE( kv );
+}
+
+static int kv_add( struct kv ***kvs, const struct kv *kv )
+{
+ int n;
+ struct kv **tmp_kvs;
+ struct kv *tmp_kv;
+
+ assert( kvs != NULL );
+ assert( kv != NULL );
+
+ tmp_kv = LDAP_MALLOC( sizeof(struct kv) );
+
+ if( tmp_kv == NULL ) {
+ return -1;
+ }
+
+ *tmp_kv = *kv;
+
+ if( *kvs == NULL ) {
+ tmp_kvs = LDAP_MALLOC( 2 * sizeof(struct kv *) );
+ n = 0;
+
+ } else {
+ for( n=0; (*kvs)[n] != NULL; n++ ) {
+ /* EMPTY */ ;
+ }
+
+ tmp_kvs = LDAP_REALLOC( kvs, (n+2) * sizeof(struct kv *) );
+ }
+
+ if( tmp_kvs == NULL ) {
+ LDAP_FREE( tmp_kv );
+ return -1;
+ }
+
+ *kvs = tmp_kvs;
+ kvs[n] = tmp_kvs;
+ kvs[n+1] = NULL;
+
+ return 0;
+}
+
+#define ST_ERROR -1
+#define ST_DONE 0
+#define ST_KEY 1
+#define ST_EQUALS 2
+#define ST_VALUE 3
+#define ST_SEP 4
+
+static int
+parse_key_value(
+ struct kv ***kvsp,
+ const char *str )
+{
+ int rc = 0;
+ int kind, state;
+ const char *ss = str;
+ char *sval;
+
+ struct kv **kvs = NULL;
+ struct kv kv;
+
+ assert( kvsp != NULL );
+ assert( str != NULL );
+
+ kv.key = NULL;
+ kv.value = NULL;
+
+ state = ST_KEY;
+
+ while( state > ST_DONE ) {
+ kind = get_token( &ss, &sval );
+ switch( kind ) {
+ case TK_EOS:
+ state = ( state == ST_SEP )
+ ? ST_DONE : ST_ERROR;
+ break;
+
+ case TK_BAREWORD:
+ if( state == ST_KEY ) {
+ state = ST_EQUALS;
+
+ assert( kv.key == NULL );
+ assert( kv.value == NULL );
+ kv.key = sval;
+
+ } else if ( state == ST_VALUE ) {
+ state = ST_SEP;
+
+ assert( kv.key != NULL );
+ assert( kv.value == NULL );
+ kv.value = sval;
+
+ } else {
+ state = ST_ERROR;
+ }
+ break;
+
+ case TK_COMMA:
+ state = ( state == ST_SEP )
+ ? ST_KEY : ST_ERROR;
+ break;
+
+ case TK_EQUALS:
+ state = ( state == ST_EQUALS )
+ ? ST_VALUE : ST_ERROR;
+ break;
+
+ case TK_QDSTRING:
+ if( state == ST_VALUE ) {
+ state = ST_SEP;
+
+ assert( kv.key != NULL );
+ assert( kv.value == NULL );
+ kv.value = sval;
+
+ } else {
+ state = ST_ERROR;
+ }
+ break;
+
+ default:
+ state = ST_ERROR;
+ }
+
+ if( state == ST_SEP ) {
+ /* add kv to return */
+ if( kv_add( &kvs, &kv ) != 0 ) {
+ state = ST_ERROR;
+ kind = TK_OUTOFMEM;
+
+ } else {
+ kv.key = NULL;
+ kv.value = NULL;
+ }
+ }
+ }
+
+ if( state == ST_ERROR ) {
+ if( kv.key != NULL ) LDAP_FREE(kv.key);
+ if( kv.value != NULL ) LDAP_FREE( kv.value );
+
+ kv_destory( kvs );
+ kvs = NULL;
+
+ rc = ( kind == TK_OUTOFMEM ) ? -1 : 1 ;
+ }
+
+ *kvsp = kvs;
+ return rc;
+}
+
+static int
+parse_value_list(
+ char ***valuesp,
+ const char* str )
+{
+ int rc = 0;
+ char **values = NULL;
+
+ int kind, state;
+ const char *ss = str;
+ char *sval;
+
+ assert( valuesp != NULL );
+ assert( str != NULL );
+
+ state = ST_VALUE;
+
+ while( state > ST_DONE ) {
+ kind = get_token( &ss, &sval );
+ switch( kind ) {
+ case TK_EOS:
+ state = ( state == ST_SEP )
+ ? ST_DONE : ST_ERROR;
+ break;
+
+ case TK_BAREWORD:
+ if( state == ST_VALUE ) {
+ state = ST_SEP;
+
+ } else {
+ state = ST_ERROR;
+ }
+ break;
+
+ case TK_COMMA:
+ state = ( state == ST_SEP )
+ ? ST_VALUE : ST_ERROR;
+ break;
+
+ default:
+ state = ST_ERROR;
+ }
+
+ if( state == ST_SEP ) {
+ if( ldap_charray_add( &values, sval ) != 0 ) {
+ state = ST_ERROR;
+ kind = TK_OUTOFMEM;
+ }
+
+ LDAP_FREE( sval );
+ sval = NULL;
+ }
+ }
+
+ if( state == ST_ERROR ) {
+ if( sval != NULL ) LDAP_FREE( sval );
+
+ LDAP_VFREE( values );
+ values = NULL;
+
+ rc = ( kind == TK_OUTOFMEM ) ? -1 : 1 ;
+ }
+
+ *valuesp = values;
+ return rc;
+}
+
+#endif
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#ifdef MACOS
-#include <stdlib.h>
-#else /* MACOS */
-#if defined( DOS ) || defined( _WIN32 )
-#include <malloc.h>
-#include "msdos.h"
-#else /* DOS */
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif /* DOS */
-#endif /* MACOS */
-#include "lber.h"
-#include "ldap.h"
+
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
struct ldaperror {
int e_code;
char *e_reason;
};
-static struct ldaperror ldap_errlist[] = {
- LDAP_SUCCESS, "Success",
- LDAP_OPERATIONS_ERROR, "Operations error",
- LDAP_PROTOCOL_ERROR, "Protocol error",
- LDAP_TIMELIMIT_EXCEEDED, "Timelimit exceeded",
- LDAP_SIZELIMIT_EXCEEDED, "Sizelimit exceeded",
- LDAP_COMPARE_FALSE, "Compare false",
- LDAP_COMPARE_TRUE, "Compare true",
- LDAP_STRONG_AUTH_NOT_SUPPORTED, "Strong authentication not supported",
- LDAP_STRONG_AUTH_REQUIRED, "Strong authentication required",
- LDAP_PARTIAL_RESULTS, "Partial results and referral received",
- LDAP_NO_SUCH_ATTRIBUTE, "No such attribute",
- LDAP_UNDEFINED_TYPE, "Undefined attribute type",
- LDAP_INAPPROPRIATE_MATCHING, "Inappropriate matching",
- LDAP_CONSTRAINT_VIOLATION, "Constraint violation",
- LDAP_TYPE_OR_VALUE_EXISTS, "Type or value exists",
- LDAP_INVALID_SYNTAX, "Invalid syntax",
- LDAP_NO_SUCH_OBJECT, "No such object",
- LDAP_ALIAS_PROBLEM, "Alias problem",
- LDAP_INVALID_DN_SYNTAX, "Invalid DN syntax",
- LDAP_IS_LEAF, "Object is a leaf",
- LDAP_ALIAS_DEREF_PROBLEM, "Alias dereferencing problem",
- LDAP_INAPPROPRIATE_AUTH, "Inappropriate authentication",
- LDAP_INVALID_CREDENTIALS, "Invalid credentials",
- LDAP_INSUFFICIENT_ACCESS, "Insufficient access",
- LDAP_BUSY, "DSA is busy",
- LDAP_UNAVAILABLE, "DSA is unavailable",
- LDAP_UNWILLING_TO_PERFORM, "DSA is unwilling to perform",
- LDAP_LOOP_DETECT, "Loop detected",
- LDAP_NAMING_VIOLATION, "Naming violation",
- LDAP_OBJECT_CLASS_VIOLATION, "Object class violation",
- LDAP_NOT_ALLOWED_ON_NONLEAF, "Operation not allowed on nonleaf",
- LDAP_NOT_ALLOWED_ON_RDN, "Operation not allowed on RDN",
- LDAP_ALREADY_EXISTS, "Already exists",
- LDAP_NO_OBJECT_CLASS_MODS, "Cannot modify object class",
- LDAP_RESULTS_TOO_LARGE, "Results too large",
- LDAP_OTHER, "Unknown error",
- LDAP_SERVER_DOWN, "Can't contact LDAP server",
- LDAP_LOCAL_ERROR, "Local error",
- LDAP_ENCODING_ERROR, "Encoding error",
- LDAP_DECODING_ERROR, "Decoding error",
- LDAP_TIMEOUT, "Timed out",
- LDAP_AUTH_UNKNOWN, "Unknown authentication method",
- LDAP_FILTER_ERROR, "Bad search filter",
- LDAP_USER_CANCELLED, "User cancelled operation",
- LDAP_PARAM_ERROR, "Bad parameter to an ldap routine",
- LDAP_NO_MEMORY, "Out of memory",
- -1, 0
+static const struct ldaperror ldap_errlist[] = {
+ {LDAP_SUCCESS, "Success" },
+ {LDAP_OPERATIONS_ERROR, "Operations error" },
+ {LDAP_PROTOCOL_ERROR, "Protocol error" },
+ {LDAP_TIMELIMIT_EXCEEDED, "Time limit exceeded" },
+ {LDAP_SIZELIMIT_EXCEEDED, "Size limit exceeded" },
+ {LDAP_COMPARE_FALSE, "Compare false" },
+ {LDAP_COMPARE_TRUE, "Compare true" },
+ {LDAP_STRONG_AUTH_NOT_SUPPORTED, "Authentication method not supported" },
+ {LDAP_STRONG_AUTH_REQUIRED, "Strong authentication required" },
+ {LDAP_PARTIAL_RESULTS, "Partial results and referral received" },
+
+ {LDAP_REFERRAL, "Referral"},
+ {LDAP_ADMINLIMIT_EXCEEDED, "Administrative limit exceeded"},
+ {LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
+ "Criticial extension is unavailable"},
+ {LDAP_CONFIDENTIALITY_REQUIRED, "Confidentiality required"},
+ {LDAP_SASL_BIND_IN_PROGRESS, "SASL bind in progress"},
+
+ {LDAP_NO_SUCH_ATTRIBUTE, "No such attribute" },
+ {LDAP_UNDEFINED_TYPE, "Undefined attribute type" },
+ {LDAP_INAPPROPRIATE_MATCHING, "Inappropriate matching" },
+ {LDAP_CONSTRAINT_VIOLATION, "Constraint violation" },
+ {LDAP_TYPE_OR_VALUE_EXISTS, "Type or value exists" },
+ {LDAP_INVALID_SYNTAX, "Invalid syntax" },
+
+ {LDAP_NO_SUCH_OBJECT, "No such object" },
+ {LDAP_ALIAS_PROBLEM, "Alias problem" },
+ {LDAP_INVALID_DN_SYNTAX, "Invalid DN syntax" },
+ {LDAP_IS_LEAF, "Object is a leaf" },
+ {LDAP_ALIAS_DEREF_PROBLEM, "Alias dereferencing problem" },
+
+ {LDAP_INAPPROPRIATE_AUTH, "Inappropriate authentication" },
+ {LDAP_INVALID_CREDENTIALS, "Invalid credentials" },
+ {LDAP_INSUFFICIENT_ACCESS, "Insufficient access" },
+ {LDAP_BUSY, "DSA is busy" },
+ {LDAP_UNAVAILABLE, "DSA is unavailable" },
+ {LDAP_UNWILLING_TO_PERFORM, "DSA is unwilling to perform" },
+ {LDAP_LOOP_DETECT, "Loop detected" },
+
+ {LDAP_NAMING_VIOLATION, "Naming violation" },
+ {LDAP_OBJECT_CLASS_VIOLATION, "Object class violation" },
+ {LDAP_NOT_ALLOWED_ON_NONLEAF, "Operation not allowed on nonleaf" },
+ {LDAP_NOT_ALLOWED_ON_RDN, "Operation not allowed on RDN" },
+ {LDAP_ALREADY_EXISTS, "Already exists" },
+ {LDAP_NO_OBJECT_CLASS_MODS, "Cannot modify object class" },
+ {LDAP_RESULTS_TOO_LARGE, "Results too large" },
+ {LDAP_AFFECTS_MULTIPLE_DSAS, "Operation affects multiple DSAs" },
+
+ {LDAP_OTHER, "Unknown error" },
+ {LDAP_SERVER_DOWN, "Can't contact LDAP server" },
+ {LDAP_LOCAL_ERROR, "Local error" },
+ {LDAP_ENCODING_ERROR, "Encoding error" },
+ {LDAP_DECODING_ERROR, "Decoding error" },
+ {LDAP_TIMEOUT, "Timed out" },
+ {LDAP_AUTH_UNKNOWN, "Unknown authentication method" },
+ {LDAP_FILTER_ERROR, "Bad search filter" },
+ {LDAP_USER_CANCELLED, "User cancelled operation" },
+ {LDAP_PARAM_ERROR, "Bad parameter to an ldap routine" },
+ {LDAP_NO_MEMORY, "Out of memory" },
+
+ {LDAP_CONNECT_ERROR, "Connect error" },
+ {LDAP_NOT_SUPPORTED, "Not Supported" },
+ {LDAP_CONTROL_NOT_FOUND, "Control not found" },
+ {LDAP_NO_RESULTS_RETURNED, "No results returned" },
+ {LDAP_MORE_RESULTS_TO_RETURN, "More results to return" },
+ {LDAP_CLIENT_LOOP, "Client Loop" },
+ {LDAP_REFERRAL_LIMIT_EXCEEDED, "Referral Limit Exceeded" },
+
+ {-1, 0 }
};
-char *
-ldap_err2string( int err )
+static const struct ldaperror *
+ldap_int_error( int err )
{
int i;
- Debug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 );
-
for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) {
if ( err == ldap_errlist[i].e_code )
- return( ldap_errlist[i].e_reason );
+ return &ldap_errlist[i];
}
- return( "Unknown error" );
+ return NULL;
}
-#ifndef NO_USERINTERFACE
-void
-ldap_perror( LDAP *ld, char *s )
+char *
+ldap_err2string( int err )
{
- int i;
+ const struct ldaperror *e;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 );
+
+ e = ldap_int_error( err );
+
+ return ( e != NULL ) ? e->e_reason : "Unknown error";
+}
+/* deprecated */
+void
+ldap_perror( LDAP *ld, LDAP_CONST char *str )
+{
+ const char *s;
+ const struct ldaperror *e;
Debug( LDAP_DEBUG_TRACE, "ldap_perror\n", 0, 0, 0 );
+ assert( ld != NULL );
+ assert( LDAP_VALID( ld ) );
+ assert( str );
+
+ s = ( str != NULL ) ? str : "ldap_perror";
+
if ( ld == NULL ) {
perror( s );
return;
}
- for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) {
- if ( ld->ld_errno == ldap_errlist[i].e_code ) {
- fprintf( stderr, "%s: %s\n", s,
- ldap_errlist[i].e_reason );
- if ( ld->ld_matched != NULL && *ld->ld_matched != '\0' )
- fprintf( stderr, "%s: matched: %s\n", s,
- ld->ld_matched );
- if ( ld->ld_error != NULL && *ld->ld_error != '\0' )
- fprintf( stderr, "%s: additional info: %s\n",
- s, ld->ld_error );
- fflush( stderr );
- return;
- }
+ e = ldap_int_error( ld->ld_errno );
+
+ if ( e != NULL ) {
+ fprintf( stderr, "%s: %s\n",
+ s, e->e_reason );
+ } else {
+ fprintf( stderr, "%s: unknown LDAP error number %d\n",
+ s, ld->ld_errno );
+ }
+
+ if ( ld->ld_matched != NULL && ld->ld_matched[0] != '\0' ) {
+ fprintf( stderr, "\tmatched: \"%s\"\n",
+ ld->ld_matched );
+ }
+
+ if ( ld->ld_error != NULL && ld->ld_error[0] != '\0' ) {
+ fprintf( stderr, "\tadditional info: %s\n",
+ ld->ld_error );
}
- fprintf( stderr, "%s: Not an LDAP errno %d\n", s, ld->ld_errno );
fflush( stderr );
}
-#else
-
-void
-ldap_perror( LDAP *ld, char *s )
+int
+ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit )
{
-}
+ int rc, err;
-#endif /* NO_USERINTERFACE */
+ rc = ldap_parse_result( ld, r, &err,
+ NULL, NULL, NULL, NULL, freeit );
+ return rc != LDAP_SUCCESS ? err : rc;
+}
+/*
+ * Parse LDAPResult Messages:
+ *
+ * LDAPResult ::= SEQUENCE {
+ * resultCode ENUMERATED,
+ * matchedDN LDAPDN,
+ * errorMessage LDAPString,
+ * referral [3] Referral OPTIONAL }
+ *
+ * including Bind results:
+ *
+ * BindResponse ::= [APPLICATION 1] SEQUENCE {
+ * COMPONENTS OF LDAPResult,
+ * serverSaslCreds [7] OCTET STRING OPTIONAL }
+ *
+ * and ExtendedOp results:
+ *
+ * ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+ * COMPONENTS OF LDAPResult,
+ * responseName [10] LDAPOID OPTIONAL,
+ * response [11] OCTET STRING OPTIONAL }
+ *
+ */
int
-ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit )
+ldap_parse_result(
+ LDAP *ld,
+ LDAPMessage *r,
+ int *errcodep,
+ char **matcheddnp,
+ char **errmsgp,
+ char ***referralsp,
+ LDAPControl ***serverctrls,
+ int freeit )
{
LDAPMessage *lm;
- BerElement ber;
- long along;
- int rc;
+ ber_int_t errcode;
+ char* matcheddn;
+ char* errmsg;
+
+ int rc;
+ ber_tag_t tag;
+ BerElement *ber;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 );
+
+ assert( ld != NULL );
+ assert( LDAP_VALID( ld ) );
+ assert( r != NULL );
+
+ if ( ld == NULL || r == NULL ) {
+ return LDAP_PARAM_ERROR;
+ }
+
+ if(matcheddnp != NULL) *matcheddnp = NULL;
+ if(errmsgp != NULL) *errmsgp = NULL;
+ if(referralsp != NULL) *referralsp = NULL;
+ if(serverctrls != NULL) *serverctrls = NULL;
- Debug( LDAP_DEBUG_TRACE, "ldap_result2error\n", 0, 0, 0 );
+ /* Find the next result... */
+ for ( lm = r; lm->lm_chain != NULL; lm = lm->lm_chain ) {
+ /* skip over entries and references */
+ if( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY &&
+ lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE )
+ {
+ break;
+ }
+ }
- if ( r == NULLMSG )
- return( LDAP_PARAM_ERROR );
+ if( lm == NULL ) {
+ ld->ld_errno = LDAP_NO_RESULTS_RETURNED;
+ return ld->ld_errno;
+ }
- for ( lm = r; lm->lm_chain != NULL; lm = lm->lm_chain )
- ; /* NULL */
+ errcode = LDAP_SUCCESS;
+ matcheddn = NULL;
+ errmsg = NULL;
if ( ld->ld_error ) {
- free( ld->ld_error );
+ LDAP_FREE( ld->ld_error );
ld->ld_error = NULL;
}
if ( ld->ld_matched ) {
- free( ld->ld_matched );
+ LDAP_FREE( ld->ld_matched );
ld->ld_matched = NULL;
}
- ber = *(lm->lm_ber);
- if ( ld->ld_version == LDAP_VERSION2 ) {
- rc = ber_scanf( &ber, "{iaa}", &along, &ld->ld_matched,
- &ld->ld_error );
+ /* parse results */
+
+ ber = ber_dup( lm->lm_ber );
+
+ if ( ld->ld_version < LDAP_VERSION2 ) {
+ tag = ber_scanf( ber, "{ia}",
+ &errcode, &ld->ld_error );
} else {
- rc = ber_scanf( &ber, "{ia}", &along, &ld->ld_error );
+ ber_len_t len;
+ tag = ber_scanf( ber, "{iaa" /*}*/,
+ &errcode, &ld->ld_matched, &ld->ld_error );
+
+ if( tag != LBER_ERROR ) {
+ /* peek for referrals */
+ if( ber_peek_tag(ber, &len) == LDAP_TAG_REFERRAL ) {
+ if( referralsp != NULL ) {
+ tag = ber_scanf( ber, "v", referralsp );
+
+ } else {
+ /* no place to put them so skip 'em */
+ tag = ber_scanf( ber, "x" );
+ }
+ }
+ }
+
+ /* need to clean out misc items */
+ if( tag != LBER_ERROR ) {
+ if( lm->lm_msgtype == LDAP_RES_BIND ) {
+ /* look for sasl result creditials */
+ if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) {
+ /* skip 'em */
+ tag = ber_scanf( ber, "x" );
+ }
+
+ } else if( lm->lm_msgtype == LDAP_RES_EXTENDED ) {
+ /* look for exop result oid or value */
+ if ( ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_OID ) {
+ /* skip 'em */
+ tag = ber_scanf( ber, "x" );
+ }
+
+ if ( tag != LBER_ERROR &&
+ ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_VALUE )
+ {
+ /* skip 'em */
+ tag = ber_scanf( ber, "x" );
+ }
+ }
+ }
+
+ if( tag != LBER_ERROR ) {
+ rc = ldap_int_get_controls( ber, serverctrls );
+
+ if( rc != LDAP_SUCCESS ) {
+ tag = LBER_ERROR;
+ }
+ }
+
+ if( tag != LBER_ERROR ) {
+ tag = ber_scanf( ber, /*{*/"}" );
+ }
}
- if ( rc == LBER_ERROR ) {
- ld->ld_errno = LDAP_DECODING_ERROR;
- } else {
- ld->ld_errno = (int) along;
+
+ if ( tag == LBER_ERROR ) {
+ errcode = LDAP_DECODING_ERROR;
}
- if ( freeit )
+ if( ber != NULL ) {
+ ber_free( ber, 0 );
+ }
+
+ /* return */
+ if ( errcode == LDAP_SUCCESS ) {
+ if( errcodep != NULL ) {
+ *errcodep = ld->ld_errno;
+ }
+ if( matcheddnp != NULL ) {
+ *matcheddnp = LDAP_STRDUP( ld->ld_matched );
+ }
+ if( errmsgp != NULL ) {
+ *errmsgp = LDAP_STRDUP( ld->ld_error );
+ }
+
+ /* Find the next result... */
+ for ( lm = lm->lm_chain; lm != NULL; lm = lm->lm_chain ) {
+ /* skip over entries and references */
+ if( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY &&
+ lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE )
+ {
+ /* more results to return */
+ errcode = LDAP_MORE_RESULTS_TO_RETURN;
+ break;
+ }
+ }
+ }
+
+ if ( freeit ) {
ldap_msgfree( r );
+ }
+ ld->ld_errno = errcode;
return( ld->ld_errno );
}
-#ifdef LDAP_DNS
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
*
- * getdxbyname - retrieve DX records from the DNS (from TXT records for now)
+ * ldap_getdxbyname - retrieve DX records from the DNS (from TXT records for now)
*/
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifdef MACOS
-#include <stdlib.h>
-#include "macos.h"
-#endif /* MACOS */
-
-#if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <resolv.h>
-#endif
-#include "lber.h"
-#include "ldap.h"
-#include "ldap-int.h"
-#if defined( DOS ) || defined( _WIN32 )
-#include "msdos.h"
-#endif /* DOS */
+#include "portable.h"
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
-#ifdef NEEDPROTOS
-static char ** decode_answer( unsigned char *answer, int len );
-#else /* NEEDPROTOS */
-static char **decode_answer();
-#endif /* NEEDPROTOS */
+#include <stdio.h>
+#include <ac/stdlib.h>
-extern int h_errno;
-extern char *h_errlist[];
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include "ldap-int.h"
+
+static char ** decode_answer LDAP_P(( unsigned char *answer, ber_len_t len ));
#define MAX_TO_SORT 32
/*
- * getdxbyname - lookup DNS DX records for domain and return an ordered
+ * ldap_getdxbyname - lookup DNS DX records for domain and return an ordered
* array.
*/
char **
-getdxbyname( char *domain )
+ldap_getdxbyname( const char *domain )
{
unsigned char buf[ PACKETSZ ];
char **dxs;
int rc;
- Debug( LDAP_DEBUG_TRACE, "getdxbyname( %s )\n", domain, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "ldap_getdxbyname( %s )\n", domain, 0, 0 );
memset( buf, 0, sizeof( buf ));
/*
* punt: return list conisting of the original domain name only
*/
- if (( dxs = (char **)malloc( 2 * sizeof( char * ))) == NULL ||
- ( dxs[ 0 ] = strdup( domain )) == NULL ) {
+ if (( dxs = (char **)LDAP_MALLOC( 2 * sizeof( char * ))) == NULL ||
+ ( dxs[ 0 ] = LDAP_STRDUP( domain )) == NULL ) {
if ( dxs != NULL ) {
- free( dxs );
+ LDAP_FREE( dxs );
}
dxs = NULL;
} else {
static char **
-decode_answer( unsigned char *answer, int len )
+decode_answer( unsigned char *answer, ber_len_t len )
{
HEADER *hp;
char buf[ 256 ], **dxs;
int dx_pref[ MAX_TO_SORT ];
#ifdef LDAP_DEBUG
+#ifdef notdef
if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
-/* __p_query( answer ); /* */
+ __p_query( answer );
}
+#endif
#endif /* LDAP_DEBUG */
dxs = NULL;
if ( *q >= 3 && strncasecmp( q + 1, "dx:", 3 ) == 0 ) {
txt_len = *q - 3;
r = q + 4;
- while ( isspace( *r )) {
+ while ( isspace( (unsigned char) *r )) {
++r;
--txt_len;
}
pref = 0;
- while ( isdigit( *r )) {
+ while ( isdigit( (unsigned char) *r )) {
pref *= 10;
pref += ( *r - '0' );
++r;
if ( dx_count < MAX_TO_SORT - 1 ) {
dx_pref[ dx_count ] = pref;
}
- while ( isspace( *r )) {
+ while ( isspace( (unsigned char) *r )) {
++r;
--txt_len;
}
- if ( dx_count == 0 ) {
- dxs = (char **)malloc( 2 * sizeof( char * ));
- } else {
- dxs = (char **)realloc( dxs,
+ dxs = (char **)LDAP_REALLOC( dxs,
( dx_count + 2 ) * sizeof( char * ));
- }
if ( dxs == NULL || ( dxs[ dx_count ] =
- (char *)calloc( 1, txt_len + 1 )) == NULL ) {
+ (char *)LDAP_CALLOC( 1, txt_len + 1 )) == NULL ) {
err = NO_RECOVERY;
continue;
}
return( dxs );
}
-#endif /* LDAP_DNS */
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1993 Regents of the University of Michigan.
* All rights reserved.
*
* getfilter.c -- optional add-on to libldap
*/
-#ifndef lint
-static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#if defined(NeXT)
-#include <regex.h>
-#endif
-#ifdef MACOS
-#include <stdlib.h>
-#include "macos.h"
-#else /* MACOS */
-#ifdef DOS
-#include <malloc.h>
-#include "msdos.h"
-#else /* DOS */
-#include <sys/types.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/regex.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
-#include <stdlib.h>
-#include <sys/errno.h>
-#ifndef VMS
-#include <unistd.h>
-#endif /* VMS */
-#endif /* DOS */
-#endif /* MACOS */
-
-#include "lber.h"
-#include "ldap.h"
-#include "regex.h"
-
-#ifdef NEEDPROTOS
-static int break_into_words( char *str, char *delims, char ***wordsp );
-int next_line_tokens( char **bufp, long *blenp, char ***toksp );
-void free_strarray( char **sap );
-#else /* NEEDPROTOS */
-static int break_into_words();
-int next_line_tokens();
-void free_strarray();
-#endif /* NEEDPROTOS */
-
-#if !defined( MACOS ) && !defined( DOS )
-extern int errno;
-extern char *re_comp();
#endif
+#include "ldap-int.h"
+
+static int break_into_words LDAP_P((
+ /* LDAP_CONST */ char *str,
+ LDAP_CONST char *delims,
+ char ***wordsp ));
+
#define FILT_MAX_LINE_LEN 1024
LDAPFiltDesc *
-ldap_init_getfilter( char *fname )
+ldap_init_getfilter( LDAP_CONST char *fname )
{
FILE *fp;
char *buf;
return( NULL );
}
- if (( buf = malloc( (size_t)len )) == NULL ) {
+ if (( buf = LDAP_MALLOC( (size_t)len )) == NULL ) {
fclose( fp );
return( NULL );
}
fclose( fp );
if ( rlen != len && !eof ) { /* error: didn't get the whole file */
- free( buf );
+ LDAP_FREE( buf );
return( NULL );
}
lfdp = ldap_init_getfilter_buf( buf, rlen );
- free( buf );
+ LDAP_FREE( buf );
return( lfdp );
}
LDAPFiltDesc *
-ldap_init_getfilter_buf( char *buf, long buflen )
+ldap_init_getfilter_buf( char *buf, ber_len_t buflen )
{
LDAPFiltDesc *lfdp;
LDAPFiltList *flp, *nextflp;
LDAPFiltInfo *fip, *nextfip;
- char *tag, **tok;
- int tokcnt, i;
+ char *tag, **tok;
+ int tokcnt, i;
+ int rc;
+ regex_t re;
- if (( lfdp = (LDAPFiltDesc *)calloc( 1, sizeof( LDAPFiltDesc))) == NULL ) {
+ if (( lfdp = (LDAPFiltDesc *)LDAP_CALLOC( 1, sizeof( LDAPFiltDesc))) == NULL ) {
return( NULL );
}
switch( tokcnt ) {
case 1: /* tag line */
if ( tag != NULL ) {
- free( tag );
+ LDAP_FREE( tag );
}
tag = tok[ 0 ];
- free( tok );
+ LDAP_FREE( tok );
break;
case 4:
case 5: /* start of filter info. list */
- if (( nextflp = (LDAPFiltList *)calloc( 1, sizeof( LDAPFiltList )))
+ if (( nextflp = (LDAPFiltList *)LDAP_CALLOC( 1, sizeof( LDAPFiltList )))
== NULL ) {
ldap_getfilter_free( lfdp );
return( NULL );
}
- nextflp->lfl_tag = strdup( tag );
+ nextflp->lfl_tag = LDAP_STRDUP( tag );
nextflp->lfl_pattern = tok[ 0 ];
- if ( re_comp( nextflp->lfl_pattern ) != NULL ) {
-#ifndef NO_USERINTERFACE
+ if ( (rc = regcomp( &re, nextflp->lfl_pattern, 0 )) != 0 ) {
+#ifdef LDAP_LIBUI
+ char error[512];
+ regerror(rc, &re, error, sizeof(error));
ldap_getfilter_free( lfdp );
- fprintf( stderr, "bad regular expresssion %s\n",
- nextflp->lfl_pattern );
-#if !defined( MACOS ) && !defined( DOS )
+ fprintf( stderr, "bad regular expression %s, %s\n",
+ nextflp->lfl_pattern, error );
errno = EINVAL;
-#endif
-#endif /* NO_USERINTERFACE */
+#endif /* LDAP_LIBUI */
free_strarray( tok );
return( NULL );
}
+ regfree(&re);
nextflp->lfl_delims = tok[ 1 ];
nextflp->lfl_ilist = NULL;
case 2:
case 3: /* filter, desc, and optional search scope */
if ( nextflp != NULL ) { /* add to info list */
- if (( nextfip = (LDAPFiltInfo *)calloc( 1,
+ if (( nextfip = (LDAPFiltInfo *)LDAP_CALLOC( 1,
sizeof( LDAPFiltInfo ))) == NULL ) {
ldap_getfilter_free( lfdp );
free_strarray( tok );
} else {
free_strarray( tok );
ldap_getfilter_free( lfdp );
-#if !defined( MACOS ) && !defined( DOS )
errno = EINVAL;
-#endif
return( NULL );
}
- free( tok[ 2 ] );
+ LDAP_FREE( tok[ 2 ] );
tok[ 2 ] = NULL;
} else {
nextfip->lfi_scope = LDAP_SCOPE_SUBTREE; /* default */
}
nextfip->lfi_isexact = ( strchr( tok[ 0 ], '*' ) == NULL &&
strchr( tok[ 0 ], '~' ) == NULL );
- free( tok );
+ LDAP_FREE( tok );
}
break;
default:
free_strarray( tok );
ldap_getfilter_free( lfdp );
-#if !defined( MACOS ) && !defined( DOS )
errno = EINVAL;
-#endif
return( NULL );
}
}
if ( tag != NULL ) {
- free( tag );
+ LDAP_FREE( tag );
}
return( lfdp );
void
-ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix, char *suffix )
+ldap_setfilteraffixes( LDAPFiltDesc *lfdp, LDAP_CONST char *prefix, LDAP_CONST char *suffix )
{
if ( lfdp->lfd_filtprefix != NULL ) {
- free( lfdp->lfd_filtprefix );
+ LDAP_FREE( lfdp->lfd_filtprefix );
}
- lfdp->lfd_filtprefix = ( prefix == NULL ) ? NULL : strdup( prefix );
+ lfdp->lfd_filtprefix = ( prefix == NULL ) ? NULL : LDAP_STRDUP( prefix );
if ( lfdp->lfd_filtsuffix != NULL ) {
- free( lfdp->lfd_filtsuffix );
+ LDAP_FREE( lfdp->lfd_filtsuffix );
}
- lfdp->lfd_filtsuffix = ( suffix == NULL ) ? NULL : strdup( suffix );
+ lfdp->lfd_filtsuffix = ( suffix == NULL ) ? NULL : LDAP_STRDUP( suffix );
}
LDAPFiltInfo *
-ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value )
+ldap_getfirstfilter(
+ LDAPFiltDesc *lfdp,
+ /* LDAP_CONST */ char *tagpat,
+ /* LDAP_CONST */ char *value )
{
LDAPFiltList *flp;
+ int rc;
+ regex_t re;
if ( lfdp->lfd_curvalcopy != NULL ) {
- free( lfdp->lfd_curvalcopy );
- free( lfdp->lfd_curvalwords );
+ LDAP_FREE( lfdp->lfd_curvalcopy );
+ LDAP_FREE( lfdp->lfd_curvalwords );
}
lfdp->lfd_curval = value;
lfdp->lfd_curfip = NULL;
- for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
- if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1
- && re_comp( flp->lfl_pattern ) == NULL
- && re_exec( lfdp->lfd_curval ) == 1 ) {
- lfdp->lfd_curfip = flp->lfl_ilist;
- break;
- }
+ for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
+ /* compile tagpat, continue if we fail */
+ if (regcomp(&re, tagpat, 0) != 0)
+ continue;
+
+ /* match tagpatern and tag, continue if we fail */
+ rc = regexec(&re, flp->lfl_tag, 0, NULL, 0);
+ regfree(&re);
+ if (rc != 0)
+ continue;
+
+ /* compile flp->ifl_pattern, continue if we fail */
+ if (regcomp(&re, flp->lfl_pattern, 0) != 0)
+ continue;
+
+ /* match ifl_pattern and lfd_curval, continue if we fail */
+ rc = regexec(&re, lfdp->lfd_curval, 0, NULL, 0);
+ regfree(&re);
+ if (rc != 0)
+ continue;
+
+ /* we successfully compiled both patterns and matched both values */
+ lfdp->lfd_curfip = flp->lfl_ilist;
+ break;
}
if ( lfdp->lfd_curfip == NULL ) {
return( NULL );
}
- if (( lfdp->lfd_curvalcopy = strdup( value )) == NULL ) {
+ if (( lfdp->lfd_curvalcopy = LDAP_STRDUP( value )) == NULL ) {
return( NULL );
}
if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims,
&lfdp->lfd_curvalwords ) < 0 ) {
- free( lfdp->lfd_curvalcopy );
+ LDAP_FREE( lfdp->lfd_curvalcopy );
lfdp->lfd_curvalcopy = NULL;
return( NULL );
}
void
-ldap_build_filter( char *filtbuf, unsigned long buflen, char *pattern,
- char *prefix, char *suffix, char *attr, char *value, char **valwords )
+ldap_build_filter(
+ char *filtbuf,
+ ber_len_t buflen,
+ LDAP_CONST char *pattern,
+ LDAP_CONST char *prefix,
+ LDAP_CONST char *suffix,
+ LDAP_CONST char *attr,
+ LDAP_CONST char *value,
+ char **valwords )
{
- char *p, *f;
+ const char *p;
+ char *f;
size_t slen;
int i, wordcount, wordnum, endwordnum;
if ( *p == '%' ) {
++p;
if ( *p == 'v' ) {
- if ( isdigit( *(p+1))) {
+ if ( isdigit( (unsigned char) p[1] )) {
++p;
wordnum = *p - '1';
if ( *(p+1) == '-' ) {
++p;
- if ( isdigit( *(p+1))) {
+ if ( isdigit( (unsigned char) p[1] )) {
++p;
endwordnum = *p - '1'; /* e.g., "%v2-4" */
if ( endwordnum > wordcount - 1 ) {
*f++ = *p;
}
- if ( f - filtbuf > buflen ) {
+ if ( (size_t) (f - filtbuf) > buflen ) {
/* sanity check */
--f;
break;
}
}
- if ( suffix != NULL && ( f - filtbuf ) < buflen ) {
+ if ( suffix != NULL && ( (size_t) (f - filtbuf) < buflen ) )
+ {
strcpy( f, suffix );
} else {
*f = '\0';
static int
-break_into_words( char *str, char *delims, char ***wordsp )
+break_into_words( /* LDAP_CONST */ char *str, LDAP_CONST char *delims, char ***wordsp )
{
char *word, **words;
int count;
-
- if (( words = (char **)calloc( 1, sizeof( char * ))) == NULL ) {
+ char *tok_r;
+
+ if (( words = (char **)LDAP_CALLOC( 1, sizeof( char * ))) == NULL ) {
return( -1 );
}
count = 0;
words[ count ] = NULL;
- word = strtok( str, delims );
+ word = ldap_pvt_strtok( str, delims, &tok_r );
while ( word != NULL ) {
- if (( words = (char **)realloc( words,
+ if (( words = (char **)LDAP_REALLOC( words,
( count + 2 ) * sizeof( char * ))) == NULL ) {
return( -1 );
}
words[ count ] = word;
words[ ++count ] = NULL;
- word = strtok( NULL, delims );
+ word = ldap_pvt_strtok( NULL, delims, &tok_r );
}
*wordsp = words;
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+#include "ldap_defaults.h"
+
+struct ldapoptions ldap_int_global_options =
+ { LDAP_UNINITIALIZED, LDAP_DEBUG_NONE };
+
+#undef gopts
+#define gopts ldap_int_global_options
+
+#define ATTR_NONE 0
+#define ATTR_BOOL 1
+#define ATTR_INT 2
+#define ATTR_KV 3
+#define ATTR_STRING 4
+#define ATTR_TLS 5
+
+struct ol_keyvalue {
+ const char * key;
+ int value;
+};
+
+static const struct ol_keyvalue deref_kv[] = {
+ {"never", LDAP_DEREF_NEVER},
+ {"searching", LDAP_DEREF_SEARCHING},
+ {"finding", LDAP_DEREF_FINDING},
+ {"always", LDAP_DEREF_ALWAYS},
+ {NULL, 0}
+};
+
+static const struct ol_attribute {
+ int type;
+ const char * name;
+ const void * data;
+ size_t offset;
+} attrs[] = {
+ {ATTR_KV, "DEREF", deref_kv, /* or &deref_kv[0] */
+ offsetof(struct ldapoptions, ldo_deref)},
+ {ATTR_INT, "SIZELIMIT", NULL,
+ offsetof(struct ldapoptions, ldo_sizelimit)},
+ {ATTR_INT, "TIMELIMIT", NULL,
+ offsetof(struct ldapoptions, ldo_timelimit)},
+ {ATTR_STRING, "BASE", NULL,
+ offsetof(struct ldapoptions, ldo_defbase)},
+ {ATTR_STRING, "HOST", NULL,
+ offsetof(struct ldapoptions, ldo_defhost)},
+ {ATTR_INT, "PORT", NULL,
+ offsetof(struct ldapoptions, ldo_defport)},
+ {ATTR_BOOL, "REFERRALS", NULL, LDAP_BOOL_REFERRALS},
+ {ATTR_BOOL, "RESTART", NULL, LDAP_BOOL_RESTART},
+ {ATTR_BOOL, "DNS", NULL, LDAP_BOOL_DNS},
+ {ATTR_BOOL, "TLS", NULL, LDAP_OPT_X_TLS},
+ {ATTR_TLS, "TLS_CERT", NULL, LDAP_OPT_X_TLS_CERTFILE},
+ {ATTR_TLS, "TLS_KEY", NULL, LDAP_OPT_X_TLS_KEYFILE},
+ {ATTR_TLS, "TLS_CACERT", NULL, LDAP_OPT_X_TLS_CACERTFILE},
+ {ATTR_TLS, "TLS_CACERTDIR",NULL, LDAP_OPT_X_TLS_CACERTDIR},
+ {ATTR_TLS, "TLS_REQCERT", NULL, LDAP_OPT_X_TLS_REQUIRE_CERT},
+ {ATTR_NONE, NULL, NULL, 0}
+};
+
+#define MAX_LDAP_ATTR_LEN sizeof("TLS_CACERTDIR")
+#define MAX_LDAP_ENV_PREFIX_LEN 8
+
+static void openldap_ldap_init_w_conf(const char *file)
+{
+ char linebuf[128];
+ FILE *fp;
+ int i;
+ char *cmd, *opt;
+ char *start, *end;
+
+ if (file == NULL) {
+ /* no file name */
+ return;
+ }
+
+ fp = fopen(file, "r");
+ if(fp == NULL) {
+ /* could not open file */
+ return;
+ }
+
+ while((start = fgets(linebuf, sizeof(linebuf), fp)) != NULL) {
+ /* skip lines starting with '#' */
+ if(*start == '#') continue;
+
+ /* trim leading white space */
+ while((*start != '\0') && isspace((unsigned char) *start))
+ start++;
+
+ /* anything left? */
+ if(*start == '\0') continue;
+
+ /* trim trailing white space */
+ end = &start[strlen(start)-1];
+ while(isspace((unsigned char)*end)) end--;
+ end[1] = '\0';
+
+ /* anything left? */
+ if(*start == '\0') continue;
+
+
+ /* parse the command */
+ cmd=start;
+ while((*start != '\0') && !isspace((unsigned char)*start)) {
+ start++;
+ }
+ if(*start == '\0') {
+ /* command has no argument */
+ continue;
+ }
+
+ *start++ = '\0';
+
+ /* we must have some non-whitespace to skip */
+ while(isspace((unsigned char)*start)) start++;
+ opt = start;
+
+ for(i=0; attrs[i].type != ATTR_NONE; i++) {
+ void *p;
+
+ if(strcasecmp(cmd, attrs[i].name) != 0) {
+ continue;
+ }
+
+ switch(attrs[i].type) {
+ case ATTR_BOOL:
+ if((strcasecmp(opt, "on") == 0)
+ || (strcasecmp(opt, "yes") == 0)
+ || (strcasecmp(opt, "true") == 0))
+ {
+ LDAP_BOOL_SET(&gopts, attrs[i].offset);
+
+ } else {
+ LDAP_BOOL_CLR(&gopts, attrs[i].offset);
+ }
+
+ break;
+
+ case ATTR_INT:
+ p = &((char *) &gopts)[attrs[i].offset];
+ * (int*) p = atoi(opt);
+ break;
+
+ case ATTR_KV: {
+ const struct ol_keyvalue *kv;
+
+ for(kv = attrs[i].data;
+ kv->key != NULL;
+ kv++) {
+
+ if(strcasecmp(opt, kv->key) == 0) {
+ p = &((char *) &gopts)[attrs[i].offset];
+ * (int*) p = kv->value;
+ break;
+ }
+ }
+ } break;
+
+ case ATTR_STRING:
+ p = &((char *) &gopts)[attrs[i].offset];
+ if (* (char**) p != NULL) LDAP_FREE(* (char**) p);
+ * (char**) p = LDAP_STRDUP(opt);
+ break;
+ case ATTR_TLS:
+#ifdef HAVE_TLS
+ ldap_pvt_tls_config( &gopts, attrs[i].offset, opt );
+#endif
+ break;
+ }
+ }
+ }
+
+ fclose(fp);
+}
+
+static void openldap_ldap_init_w_userconf(const char *file)
+{
+ char *home;
+ char *path;
+
+ if (file == NULL) {
+ /* no file name */
+ return;
+ }
+
+ home = getenv("HOME");
+
+ if (home != NULL) {
+ path = LDAP_MALLOC(strlen(home) + strlen(file) + 3);
+ } else {
+ path = LDAP_MALLOC(strlen(file) + 3);
+ }
+
+ if(home != NULL && path != NULL) {
+ /* we assume UNIX path syntax is used... */
+
+ /* try ~/file */
+ sprintf(path, "%s/%s", home, file);
+ openldap_ldap_init_w_conf(path);
+
+ /* try ~/.file */
+ sprintf(path, "%s/.%s", home, file);
+ openldap_ldap_init_w_conf(path);
+ }
+
+ if(path != NULL) {
+ LDAP_FREE(path);
+ }
+
+ /* try file */
+ openldap_ldap_init_w_conf(file);
+}
+
+static void openldap_ldap_init_w_env(const char *prefix)
+{
+ char buf[MAX_LDAP_ATTR_LEN+MAX_LDAP_ENV_PREFIX_LEN];
+ int len;
+ int i;
+ void *p;
+ char *value;
+
+ if (prefix == NULL) {
+ prefix = LDAP_ENV_PREFIX;
+ }
+
+ strncpy(buf, prefix, MAX_LDAP_ENV_PREFIX_LEN);
+ buf[MAX_LDAP_ENV_PREFIX_LEN] = '\0';
+ len = strlen(buf);
+
+ for(i=0; attrs[i].type != ATTR_NONE; i++) {
+ strcpy(&buf[len], attrs[i].name);
+ value = getenv(buf);
+
+ if(value == NULL) {
+ continue;
+ }
+
+ switch(attrs[i].type) {
+ case ATTR_BOOL:
+ if((strcasecmp(value, "on") == 0)
+ || (strcasecmp(value, "yes") == 0)
+ || (strcasecmp(value, "true") == 0))
+ {
+ LDAP_BOOL_SET(&gopts, attrs[i].offset);
+
+ } else {
+ LDAP_BOOL_CLR(&gopts, attrs[i].offset);
+ }
+ break;
+
+ case ATTR_INT:
+ p = &((char *) &gopts)[attrs[i].offset];
+ * (int*) p = atoi(value);
+ break;
+
+ case ATTR_KV: {
+ const struct ol_keyvalue *kv;
+
+ for(kv = attrs[i].data;
+ kv->key != NULL;
+ kv++) {
+
+ if(strcasecmp(value, kv->key) == 0) {
+ p = &((char *) &gopts)[attrs[i].offset];
+ * (int*) p = kv->value;
+ break;
+ }
+ }
+ } break;
+
+ case ATTR_STRING:
+ p = &((char *) &gopts)[attrs[i].offset];
+ if (* (char**) p != NULL) LDAP_FREE(* (char**) p);
+ if (*value == '\0') {
+ * (char**) p = NULL;
+ } else {
+ * (char**) p = LDAP_STRDUP(value);
+ }
+ break;
+ case ATTR_TLS:
+#ifdef HAVE_TLS
+ ldap_pvt_tls_config( attrs[i].offset, value );
+#endif
+ break;
+ }
+ }
+}
+
+void ldap_int_initialize( void )
+{
+ if ( gopts.ldo_valid == LDAP_INITIALIZED ) {
+ return;
+ }
+
+ ldap_int_utils_init();
+
+#ifdef HAVE_TLS
+ ldap_pvt_tls_init();
+#endif
+
+ if ( ldap_int_tblsize == 0 )
+ ldap_int_ip_init();
+
+ gopts.ldo_debug = 0;
+
+ gopts.ldo_version = LDAP_VERSION2;
+ gopts.ldo_deref = LDAP_DEREF_NEVER;
+ gopts.ldo_timelimit = LDAP_NO_LIMIT;
+ gopts.ldo_sizelimit = LDAP_NO_LIMIT;
+
+ gopts.ldo_tm_api = (struct timeval *)NULL;
+ gopts.ldo_tm_net = (struct timeval *)NULL;
+
+ gopts.ldo_defhost = LDAP_STRDUP("localhost");
+ gopts.ldo_defport = LDAP_PORT;
+
+ gopts.ldo_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT;
+
+ LDAP_BOOL_ZERO(&gopts);
+
+ LDAP_BOOL_SET(&gopts, LDAP_BOOL_REFERRALS);
+
+#ifdef HAVE_TLS
+ gopts.ldo_tls_ctx = NULL;
+#endif
+
+ gopts.ldo_valid = LDAP_INITIALIZED;
+
+ if( getenv("LDAPNOINIT") != NULL ) {
+ return;
+ }
+
+ openldap_ldap_init_w_conf(LDAP_CONF_FILE);
+ openldap_ldap_init_w_userconf(LDAP_USERRC_FILE);
+
+ {
+ char *altfile = getenv(LDAP_ENV_PREFIX "CONF");
+
+ if( altfile != NULL ) {
+ openldap_ldap_init_w_conf( altfile );
+ }
+ }
+
+ {
+ char *altfile = getenv(LDAP_ENV_PREFIX "RC");
+
+ if( altfile != NULL ) {
+ openldap_ldap_init_w_userconf( altfile );
+ }
+ }
+
+ openldap_ldap_init_w_env(NULL);
+}
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
*
* ldap-int.h - defines & prototypes internal to the LDAP library
*/
+#ifndef _LDAP_INT_H
+#define _LDAP_INT_H 1
+
+#ifdef LDAP_R_COMPILE
+#define LDAP_THREAD_SAFE 1
+#endif
+
+#include "../liblber/lber-int.h"
+
+#define ldap_debug (ldap_int_global_options.ldo_debug)
+#undef Debug
+#define Debug( level, fmt, arg1, arg2, arg3 ) \
+ ldap_log_printf( NULL, (level), (fmt), (arg1), (arg2), (arg3) )
+
+#include "ldap_log.h"
+
+#include "ldap.h"
+
+#include "ldap_pvt.h"
+
+LDAP_BEGIN_DECL
#define LDAP_URL_PREFIX "ldap://"
-#define LDAP_URL_PREFIX_LEN 7
-#define LDAP_URL_URLCOLON "URL:"
-#define LDAP_URL_URLCOLON_LEN 4
+#define LDAP_URL_PREFIX_LEN (sizeof(LDAP_URL_PREFIX)-1)
+#define LDAPS_URL_PREFIX "ldaps://"
+#define LDAPS_URL_PREFIX_LEN (sizeof(LDAPS_URL_PREFIX)-1)
+#define LDAP_URL_URLCOLON "URL:"
+#define LDAP_URL_URLCOLON_LEN (sizeof(LDAP_URL_URLCOLON)-1)
+#define NULLLDAPURLDESC ((LDAPURLDesc *)NULL)
-#ifdef LDAP_REFERRALS
#define LDAP_REF_STR "Referral:\n"
-#define LDAP_REF_STR_LEN 10
+#define LDAP_REF_STR_LEN (sizeof(LDAP_REF_STR)-1)
#define LDAP_LDAP_REF_STR LDAP_URL_PREFIX
-#define LDAP_LDAP_REF_STR_LEN LDAP_URL_PREFIX_LEN
-#ifdef LDAP_DNS
+#define LDAP_LDAP_REF_STR_LEN (sizeof(LDAP_LDAP_REF_STR)-1)
+
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
#define LDAP_DX_REF_STR "dx://"
-#define LDAP_DX_REF_STR_LEN 5
-#endif /* LDAP_DNS */
-#endif /* LDAP_REFERRALS */
+#define LDAP_DX_REF_STR_LEN (sizeof(LDAP_DX_REF_STR)-1)
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
+
+#define LDAP_DEFAULT_REFHOPLIMIT 5
+
+#define LDAP_BOOL_REFERRALS 0
+#define LDAP_BOOL_RESTART 1
+#define LDAP_BOOL_DNS 2
+#define LDAP_BOOL_TLS 3
+
+#define LDAP_BOOLEANS unsigned long
+#define LDAP_BOOL(n) (1 << (n))
+#define LDAP_BOOL_GET(lo, bool) ((lo)->ldo_booleans & LDAP_BOOL(bool) \
+ ? -1 : 0)
+#define LDAP_BOOL_SET(lo, bool) ((lo)->ldo_booleans |= LDAP_BOOL(bool))
+#define LDAP_BOOL_CLR(lo, bool) ((lo)->ldo_booleans &= ~LDAP_BOOL(bool))
+#define LDAP_BOOL_ZERO(lo) ((lo)->ldo_booleans = 0)
+
+/*
+ * This structure represents both ldap messages and ldap responses.
+ * These are really the same, except in the case of search responses,
+ * where a response has multiple messages.
+ */
+
+struct ldapmsg {
+ ber_int_t lm_msgid; /* the message id */
+ ber_tag_t lm_msgtype; /* the message type */
+ BerElement *lm_ber; /* the ber encoded message contents */
+ struct ldapmsg *lm_chain; /* for search - next msg in the resp */
+ struct ldapmsg *lm_next; /* next response */
+ time_t lm_time; /* used to maintain cache */
+};
+
+/*
+ * structure representing get/set'able options
+ * which have global defaults.
+ */
+struct ldapoptions {
+ short ldo_valid;
+#define LDAP_UNINITIALIZED 0x0
+#define LDAP_INITIALIZED 0x1
+#define LDAP_VALID_SESSION 0x2
+
+ int ldo_debug;
+ /* per API call timeout */
+ struct timeval *ldo_tm_api;
+ struct timeval *ldo_tm_net;
+
+ ber_int_t ldo_version; /* version to connect at */
+ ber_int_t ldo_deref;
+ ber_int_t ldo_timelimit;
+ ber_int_t ldo_sizelimit;
+
+ int ldo_defport;
+ char* ldo_defbase;
+ char* ldo_defhost;
+
+#ifdef LDAP_CONNECTIONLESS
+ int ldo_cldaptries; /* connectionless search retry count */
+ int ldo_cldaptimeout;/* time between retries */
+#endif
+
+ int ldo_refhoplimit; /* limit on referral nesting */
+
+ /* LDAPv3 server and client controls */
+ LDAPControl **ldo_sctrls;
+ LDAPControl **ldo_cctrls;
+
+#ifdef HAVE_TLS
+ /* tls context */
+ void *ldo_tls_ctx;
+ int ldo_tls_mode;
+#endif
+ LDAP_BOOLEANS ldo_booleans; /* boolean options */
+};
+/*
+ * structure for tracking LDAP server host, ports, DNs, etc.
+ */
+typedef struct ldap_server {
+ char *lsrv_host;
+ char *lsrv_dn; /* if NULL, use default */
+ int lsrv_port;
+ struct ldap_server *lsrv_next;
+} LDAPServer;
+
+
+/*
+ * structure for representing an LDAP server connection
+ */
+typedef struct ldap_conn {
+ Sockbuf *lconn_sb;
+ int lconn_refcnt;
+ time_t lconn_lastused; /* time */
+ int lconn_status;
+#define LDAP_CONNST_NEEDSOCKET 1
+#define LDAP_CONNST_CONNECTING 2
+#define LDAP_CONNST_CONNECTED 3
+ LDAPServer *lconn_server;
+ char *lconn_krbinstance;
+ struct ldap_conn *lconn_next;
+ BerElement *lconn_ber;/* ber receiving on this conn. */
+} LDAPConn;
+
+
+/*
+ * structure used to track outstanding requests
+ */
+typedef struct ldapreq {
+ ber_int_t lr_msgid; /* the message id */
+ int lr_status; /* status of request */
+#define LDAP_REQST_INPROGRESS 1
+#define LDAP_REQST_CHASINGREFS 2
+#define LDAP_REQST_NOTCONNECTED 3
+#define LDAP_REQST_WRITING 4
+ int lr_outrefcnt; /* count of outstanding referrals */
+ ber_int_t lr_origid; /* original request's message id */
+ int lr_parentcnt; /* count of parent requests */
+ ber_tag_t lr_res_msgtype; /* result message type */
+ ber_int_t lr_res_errno; /* result LDAP errno */
+ char *lr_res_error; /* result error string */
+ char *lr_res_matched;/* result matched DN string */
+ BerElement *lr_ber; /* ber encoded request contents */
+ LDAPConn *lr_conn; /* connection used to send request */
+ struct ldapreq *lr_parent; /* request that spawned this referral */
+ struct ldapreq *lr_refnext; /* next referral spawned */
+ struct ldapreq *lr_prev; /* previous request */
+ struct ldapreq *lr_next; /* next request */
+} LDAPRequest;
+
+/*
+ * structure for client cache
+ */
+#define LDAP_CACHE_BUCKETS 31 /* cache hash table size */
+typedef struct ldapcache {
+ LDAPMessage *lc_buckets[LDAP_CACHE_BUCKETS];/* hash table */
+ LDAPMessage *lc_requests; /* unfulfilled reqs */
+ long lc_timeout; /* request timeout */
+ ber_len_t lc_maxmem; /* memory to use */
+ ber_len_t lc_memused; /* memory in use */
+ int lc_enabled; /* enabled? */
+ unsigned long lc_options; /* options */
+#define LDAP_CACHE_OPT_CACHENOERRS 0x00000001
+#define LDAP_CACHE_OPT_CACHEALLERRS 0x00000002
+} LDAPCache;
+
+/*
+ * handy macro for checking if handle is connectionless
+ */
+
+#define LDAP_IS_CLDAP(ld) ((ld)->ld_cldapnaddr>0)
+
+/*
+ * structure representing an ldap connection
+ */
+
+struct ldap {
+ Sockbuf ld_sb; /* socket descriptor & buffer */
+
+ struct ldapoptions ld_options;
+
+#define ld_valid ld_options.ldo_valid
+#define ld_debug ld_options.ldo_debug
+
+#define ld_deref ld_options.ldo_deref
+#define ld_timelimit ld_options.ldo_timelimit
+#define ld_sizelimit ld_options.ldo_sizelimit
+
+#define ld_defbase ld_options.ldo_defbase
+#define ld_defhost ld_options.ldo_defhost
+#define ld_defport ld_options.ldo_defport
+
+#define ld_cldaptries ld_options.ldo_cldaptries
+#define ld_cldaptimeout ld_options.ldo_cldaptimeout
+#define ld_refhoplimit ld_options.ldo_refhoplimit
+
+#define ld_sctrls ld_options.ldo_sctrls
+#define ld_cctrls ld_options.ldo_cctrls
+
+ ber_int_t ld_version; /* version connected at */
+ char *ld_host;
+ int ld_port;
+
+ unsigned short ld_lberoptions;
+
+ LDAPFiltDesc *ld_filtd; /* from getfilter for ufn searches */
+ char *ld_ufnprefix; /* for incomplete ufn's */
+
+ ber_int_t ld_errno;
+ char *ld_error;
+ char *ld_matched;
+ ber_len_t ld_msgid;
+
+ /* do not mess with these */
+ LDAPRequest *ld_requests; /* list of outstanding requests */
+ LDAPMessage *ld_responses; /* list of outstanding responses */
+
+ ber_int_t *ld_abandoned; /* array of abandoned requests */
+
+ LDAPCache *ld_cache; /* non-null if cache is initialized */
+ /* stuff used by connectionless searches. */
+
+ char *ld_cldapdn; /* DN used in connectionless search */
+ int ld_cldapnaddr; /* number of addresses */
+ void **ld_cldapaddrs;/* addresses to send request to */
+
+ /* do not mess with the rest though */
+ BERTranslateProc ld_lber_encode_translate_proc;
+ BERTranslateProc ld_lber_decode_translate_proc;
+
+ LDAPConn *ld_defconn; /* default connection */
+ LDAPConn *ld_conns; /* list of server connections */
+ void *ld_selectinfo; /* platform specifics for select */
+ int (*ld_rebindproc)( struct ldap *ld, char **dnp,
+ char **passwdp, int *authmethodp, int freeit );
+ /* routine to get info needed for re-bind */
+};
+#define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION )
+
+/*
+ * in init.c
+ */
+
+extern struct ldapoptions ldap_int_global_options;
+void ldap_int_initialize LDAP_P((void));
+
+
+/* memory.c */
+ /* simple macros to realloc for now */
+#define LDAP_INT_MALLOC(s) (LBER_MALLOC((s)))
+#define LDAP_INT_CALLOC(n,s) (LBER_CALLOC((n),(s)))
+#define LDAP_INT_REALLOC(p,s) (LBER_REALLOC((p),(s)))
+#define LDAP_INT_FREE(p) (LBER_FREE((p)))
+#define LDAP_INT_VFREE(v) (LBER_VFREE((void **)(v)))
+#define LDAP_INT_STRDUP(s) (LBER_STRDUP((s)))
+
+#define LDAP_MALLOC(s) (LBER_MALLOC((s)))
+#define LDAP_CALLOC(n,s) (LBER_CALLOC((n),(s)))
+#define LDAP_REALLOC(p,s) (LBER_REALLOC((p),(s)))
+#define LDAP_FREE(p) (LBER_FREE((p)))
+#define LDAP_VFREE(v) (LBER_VFREE((void **)(v)))
+#define LDAP_STRDUP(s) (LBER_STRDUP((s)))
+
+/*
+ * in unit-int.c
+ */
+void ldap_int_utils_init LDAP_P(( void ));
+
+
+/*
+ * in print.c
+ */
+int ldap_log_printf LDAP_P((LDAP *ld, int level, const char *fmt, ...));
+
/*
* in cache.c
*/
-#ifdef NEEDPROTOS
-void add_request_to_cache( LDAP *ld, unsigned long msgtype,
- BerElement *request );
-void add_result_to_cache( LDAP *ld, LDAPMessage *result );
-int check_cache( LDAP *ld, unsigned long msgtype, BerElement *request );
-#else /* NEEDPROTOS */
-void add_request_to_cache();
-void add_result_to_cache();
-int check_cache();
-#endif /* NEEDPROTOS */
+void ldap_add_request_to_cache LDAP_P(( LDAP *ld, ber_tag_t msgtype,
+ BerElement *request ));
+void ldap_add_result_to_cache LDAP_P(( LDAP *ld, LDAPMessage *result ));
+int ldap_check_cache LDAP_P(( LDAP *ld, ber_tag_t msgtype, BerElement *request ));
+
+/*
+ * in controls.c
+ */
+LDAPControl *ldap_control_dup LDAP_P((
+ const LDAPControl *ctrl ));
+
+LDAPControl **ldap_controls_dup LDAP_P((
+ LDAPControl *const *ctrls ));
+
+int ldap_int_get_controls LDAP_P((
+ BerElement *be,
+ LDAPControl ***ctrlsp));
+int ldap_int_put_controls LDAP_P((
+ LDAP *ld,
+ LDAPControl *const *ctrls,
+ BerElement *ber ));
-#ifdef KERBEROS
+/*
+ * in dsparse.c
+ */
+int next_line_tokens LDAP_P(( char **bufp, ber_len_t *blenp, char ***toksp ));
+void free_strarray LDAP_P(( char **sap ));
+
+#ifdef HAVE_KERBEROS
/*
* in kerberos.c
*/
-#ifdef NEEDPROTOS
-char *get_kerberosv4_credentials( LDAP *ld, char *who, char *service,
- int *len );
-#else /* NEEDPROTOS */
-char *get_kerberosv4_credentials();
-#endif /* NEEDPROTOS */
+char *ldap_get_kerberosv4_credentials LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *service,
+ ber_len_t *len ));
-#endif /* KERBEROS */
+#endif /* HAVE_KERBEROS */
/*
* in open.c
*/
-#ifdef NEEDPROTOS
-int open_ldap_connection( LDAP *ld, Sockbuf *sb, char *host, int defport,
+int open_ldap_connection( LDAP *ld, Sockbuf *sb, const char *host, int defport,
char **krbinstancep, int async );
-#else /* NEEDPROTOS */
-int open_ldap_connection();
-#endif /* NEEDPROTOS */
/*
* in os-ip.c
*/
-#ifdef NEEDPROTOS
-int connect_to_host( Sockbuf *sb, char *host, unsigned long address, int port,
- int async );
-void close_connection( Sockbuf *sb );
-#else /* NEEDPROTOS */
-int connect_to_host();
-void close_connection();
-#endif /* NEEDPROTOS */
-
-#ifdef KERBEROS
-#ifdef NEEDPROTOS
-char *host_connected_to( Sockbuf *sb );
-#else /* NEEDPROTOS */
-char *host_connected_to();
-#endif /* NEEDPROTOS */
-#endif /* KERBEROS */
-
-#ifdef LDAP_REFERRALS
-#ifdef NEEDPROTOS
+extern int ldap_int_tblsize;
+int ldap_int_timeval_dup( struct timeval **dest, const struct timeval *tm );
+int ldap_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host,
+ unsigned long address, int port, int async );
+
+void ldap_close_connection( Sockbuf *sb );
+
+#ifdef HAVE_KERBEROS
+char *ldap_host_connected_to( Sockbuf *sb );
+#endif /* HAVE_KERBEROS */
+
+void ldap_int_ip_init( void );
int do_ldap_select( LDAP *ld, struct timeval *timeout );
-void *new_select_info( void );
-void free_select_info( void *sip );
-void mark_select_write( LDAP *ld, Sockbuf *sb );
-void mark_select_read( LDAP *ld, Sockbuf *sb );
-void mark_select_clear( LDAP *ld, Sockbuf *sb );
-int is_read_ready( LDAP *ld, Sockbuf *sb );
-int is_write_ready( LDAP *ld, Sockbuf *sb );
-#else /* NEEDPROTOS */
-int do_ldap_select();
-void *new_select_info();
-void free_select_info();
-void mark_select_write();
-void mark_select_read();
-void mark_select_clear();
-int is_read_ready();
-int is_write_ready();
-#endif /* NEEDPROTOS */
-#endif /* LDAP_REFERRALS */
+void *ldap_new_select_info( void );
+void ldap_free_select_info( void *sip );
+void ldap_mark_select_write( LDAP *ld, Sockbuf *sb );
+void ldap_mark_select_read( LDAP *ld, Sockbuf *sb );
+void ldap_mark_select_clear( LDAP *ld, Sockbuf *sb );
+int ldap_is_read_ready( LDAP *ld, Sockbuf *sb );
+int ldap_is_write_ready( LDAP *ld, Sockbuf *sb );
/*
* in request.c
*/
-#ifdef NEEDPROTOS
-int send_initial_request( LDAP *ld, unsigned long msgtype,
- char *dn, BerElement *ber );
-BerElement *alloc_ber_with_options( LDAP *ld );
-void set_ber_options( LDAP *ld, BerElement *ber );
-#else /* NEEDPROTOS */
-int send_initial_request();
-BerElement *alloc_ber_with_options();
-void set_ber_options();
-#endif /* NEEDPROTOS */
-
-#if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
-#ifdef NEEDPROTOS
-int send_server_request( LDAP *ld, BerElement *ber, int msgid,
+ber_int_t ldap_send_initial_request( LDAP *ld, ber_tag_t msgtype,
+ const char *dn, BerElement *ber );
+BerElement *ldap_alloc_ber_with_options( LDAP *ld );
+void ldap_set_ber_options( LDAP *ld, BerElement *ber );
+
+int ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid,
LDAPRequest *parentreq, LDAPServer *srvlist, LDAPConn *lc,
int bind );
-LDAPConn *new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
+LDAPConn *ldap_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
int connect, int bind );
-LDAPRequest *find_request_by_msgid( LDAP *ld, int msgid );
-void free_request( LDAP *ld, LDAPRequest *lr );
-void free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind );
-void dump_connection( LDAP *ld, LDAPConn *lconns, int all );
-void dump_requests_and_responses( LDAP *ld );
-#else /* NEEDPROTOS */
-int send_server_request();
-LDAPConn *new_connection();
-LDAPRequest *find_request_by_msgid();
-void free_request();
-void free_connection();
-void dump_connection();
-void dump_requests_and_responses();
-#endif /* NEEDPROTOS */
-#endif /* LDAP_REFERRALS || LDAP_DNS */
-
-#ifdef LDAP_REFERRALS
-#ifdef NEEDPROTOS
-int chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp );
-int append_referral( LDAP *ld, char **referralsp, char *s );
-#else /* NEEDPROTOS */
-int chase_referrals();
-int append_referral();
-#endif /* NEEDPROTOS */
-#endif /* LDAP_REFERRALS */
+LDAPRequest *ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid );
+void ldap_free_request( LDAP *ld, LDAPRequest *lr );
+void ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind );
+void ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all );
+void ldap_dump_requests_and_responses( LDAP *ld );
+
+int ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp );
+int ldap_append_referral( LDAP *ld, char **referralsp, char *s );
+/*
+ * in result.c:
+ */
+#ifdef LDAP_CONNECTIONLESS
+int cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber );
+#endif
/*
* in search.c
*/
-#ifdef NEEDPROTOS
-BerElement *ldap_build_search_req( LDAP *ld, char *base, int scope,
- char *filter, char **attrs, int attrsonly );
-#else /* NEEDPROTOS */
-BerElement *ldap_build_search_req();
-#endif /* NEEDPROTOS */
+BerElement *ldap_build_search_req LDAP_P((
+ LDAP *ld,
+ const char *base,
+ ber_int_t scope,
+ const char *filter,
+ char **attrs,
+ ber_int_t attrsonly,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls,
+ ber_int_t timelimit,
+ ber_int_t sizelimit ));
+/*
+ * in string.c
+ */
+ /* see <ac/string.h> */
/*
* in unbind.c
*/
-#ifdef NEEDPROTOS
-int ldap_ld_free( LDAP *ld, int close );
-int send_unbind( LDAP *ld, Sockbuf *sb );
-#else /* NEEDPROTOS */
-int ldap_ld_free();
-int send_unbind();
-#endif /* NEEDPROTOS */
+int ldap_ld_free LDAP_P((
+ LDAP *ld,
+ int close,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls ));
+int ldap_send_unbind LDAP_P((
+ LDAP *ld,
+ Sockbuf *sb,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls ));
-#ifdef LDAP_DNS
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
/*
* in getdxbyname.c
*/
-#ifdef NEEDPROTOS
-char **getdxbyname( char *domain );
-#else /* NEEDPROTOS */
-char **getdxbyname();
-#endif /* NEEDPROTOS */
-#endif /* LDAP_DNS */
+char **ldap_getdxbyname( const char *domain );
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
+
+#if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET )
+/*
+ * in charset.c
+ *
+ * added-in this stuff so that libldap.a would build, i.e. refs to
+ * these routines from open.c would resolve.
+ * hodges@stanford.edu 5-Feb-96
+ */
+#if LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET
+extern
+int ldap_t61_to_8859( char **bufp, ber_len_t *buflenp, int free_input );
+extern
+int ldap_8859_to_t61( char **bufp, ber_len_t *buflenp, int free_input );
+#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */
+#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */
+
+LDAP_END_DECL
+
+#endif /* _LDAP_INT_H */
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
*
* open.c
*/
-#ifndef lint
-static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-
-#ifdef MACOS
-#include <stdlib.h>
-#include "macos.h"
-#endif /* MACOS */
-
-#if defined( DOS ) || defined( _WIN32 )
-#include "msdos.h"
-#include <stdlib.h>
-#endif /* DOS */
-
-#if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#ifndef VMS
-#include <sys/param.h>
-#endif
-#include <netinet/in.h>
-#endif
-#include "lber.h"
-#include "ldap.h"
-#include "ldap-int.h"
-#ifdef LDAP_DEBUG
-int ldap_debug;
-#endif
+#include <ac/stdlib.h>
-#ifndef INADDR_LOOPBACK
-#define INADDR_LOOPBACK ((unsigned long) 0x7f000001)
-#endif
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 64
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
#endif
+#include "ldap-int.h"
+
/*
* ldap_open - initialize and connect to an ldap server. A magic cookie to
*/
LDAP *
-ldap_open( char *host, int port )
+ldap_open( LDAP_CONST char *host, int port )
{
LDAP *ld;
-#ifdef LDAP_REFERRALS
LDAPServer *srv;
-#endif /* LDAP_REFERRALS */
Debug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 );
return( NULL );
}
-#ifdef LDAP_REFERRALS
- if (( srv = (LDAPServer *)calloc( 1, sizeof( LDAPServer ))) ==
+ if (( srv = (LDAPServer *)LDAP_CALLOC( 1, sizeof( LDAPServer ))) ==
NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host =
- strdup( ld->ld_defhost )) == NULL )) {
- ldap_ld_free( ld, 0 );
+ LDAP_STRDUP( ld->ld_defhost )) == NULL )) {
+ if(srv != NULL) LDAP_FREE( (char*) srv );
+ ldap_ld_free( ld, 0, NULL, NULL );
return( NULL );
}
srv->lsrv_port = ld->ld_defport;
- if (( ld->ld_defconn = new_connection( ld, &srv, 1,1,0 )) == NULL ) {
- if ( ld->ld_defhost != NULL ) free( srv->lsrv_host );
- free( (char *)srv );
- ldap_ld_free( ld, 0 );
+ if (( ld->ld_defconn = ldap_new_connection( ld, &srv, 1,1,0 )) == NULL ) {
+ if ( ld->ld_defhost != NULL ) LDAP_FREE( srv->lsrv_host );
+ LDAP_FREE( (char *)srv );
+ ldap_ld_free( ld, 0, NULL, NULL );
return( NULL );
}
++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
-#else /* LDAP_REFERRALS */
- if ( open_ldap_connection( ld, &ld->ld_sb, ld->ld_defhost,
- ld->ld_defport, &ld->ld_host, 0 ) < 0 ) {
- ldap_ld_free( ld, 0 );
- return( NULL );
- }
-#endif /* LDAP_REFERRALS */
-
Debug( LDAP_DEBUG_TRACE, "ldap_open successful, ld_host is %s\n",
( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 );
/*
* ldap_init - initialize the LDAP library. A magic cookie to be used for
* future communication is returned on success, NULL on failure.
- * "defhost" may be a space-separated list of hosts or IP addresses
+ * "host" may be a space-separated list of hosts or IP addresses
*
* Example:
* LDAP *ld;
- * ld = ldap_open( default_hostname, default_port );
+ * ld = ldap_open( host, port );
*/
LDAP *
-ldap_init( char *defhost, int defport )
+ldap_init( LDAP_CONST char *defhost, int defport )
{
LDAP *ld;
+ if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
+ ldap_int_initialize();
+ }
+
Debug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 );
+#ifdef HAVE_WINSOCK2
+{ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 0 );
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ /* Tell the user that we couldn't find a usable */
+ /* WinSock DLL. */
+ return NULL;
+ }
+
+ /* Confirm that the WinSock DLL supports 2.0.*/
+ /* Note that if the DLL supports versions greater */
+ /* than 2.0 in addition to 2.0, it will still return */
+ /* 2.0 in wVersion since that is the version we */
+ /* requested. */
+
+ if ( LOBYTE( wsaData.wVersion ) != 2 ||
+ HIBYTE( wsaData.wVersion ) != 0 )
+ {
+ /* Tell the user that we couldn't find a usable */
+ /* WinSock DLL. */
+ WSACleanup( );
+ return NULL;
+ }
+} /* The WinSock DLL is acceptable. Proceed. */
+
+#elif HAVE_WINSOCK
+{ WSADATA wsaData;
+ if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
+ return( NULL );
+ }
+}
+#endif
- if ( (ld = (LDAP *) calloc( 1, sizeof(LDAP) )) == NULL ) {
+ if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
+ WSACleanup( );
return( NULL );
}
+
+ /* copy the global options */
+ memcpy(&ld->ld_options, &ldap_int_global_options,
+ sizeof(ld->ld_options));
+
+ ld->ld_valid = LDAP_VALID_SESSION;
+
+ /* but not pointers to malloc'ed items */
+ ld->ld_options.ldo_defbase = NULL;
+ ld->ld_options.ldo_defhost = NULL;
+ ld->ld_options.ldo_sctrls = NULL;
+ ld->ld_options.ldo_cctrls = NULL;
+
+ if ( defhost != NULL ) {
+ ld->ld_options.ldo_defhost = LDAP_STRDUP( defhost );
+ } else {
+ ld->ld_options.ldo_defhost = LDAP_STRDUP(
+ ldap_int_global_options.ldo_defhost);
+ }
-#ifdef LDAP_REFERRALS
- if (( ld->ld_selectinfo = new_select_info()) == NULL ) {
- free( (char*)ld );
+ if ( ld->ld_options.ldo_defhost == NULL ) {
+ LDAP_FREE( (char*)ld );
+ WSACleanup( );
return( NULL );
}
- ld->ld_options = LDAP_OPT_REFERRALS;
-#endif /* LDAP_REFERRALS */
- if ( defhost != NULL &&
- ( ld->ld_defhost = strdup( defhost )) == NULL ) {
-#ifdef LDAP_REFERRALS
- free_select_info( ld->ld_selectinfo );
-#endif /* LDAP_REFERRALS */
- free( (char*)ld );
+ if ( ldap_int_global_options.ldo_defbase != NULL ) {
+ ld->ld_options.ldo_defbase = LDAP_STRDUP(
+ ldap_int_global_options.ldo_defbase);
+ }
+
+ if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) {
+ LDAP_FREE( (char*) ld->ld_options.ldo_defhost );
+ if ( ld->ld_options.ldo_defbase == NULL ) {
+ LDAP_FREE( (char*) ld->ld_options.ldo_defbase );
+ }
+ LDAP_FREE( (char*) ld );
+ WSACleanup( );
return( NULL );
}
+ if(defport != 0) {
+ ld->ld_defport = defport;
+ }
- ld->ld_defport = ( defport == 0 ) ? LDAP_PORT : defport;
- ld->ld_version = LDAP_VERSION;
ld->ld_lberoptions = LBER_USE_DER;
- ld->ld_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT;
#if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET )
ld->ld_lberoptions |= LBER_TRANSLATE_STRINGS;
#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */
#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */
+ /* we'll assume we're talking version 2 for now */
+ ld->ld_version = LDAP_VERSION2;
+
+ ber_pvt_sb_init( &(ld->ld_sb) );
+
return( ld );
}
int
-open_ldap_connection( LDAP *ld, Sockbuf *sb, char *host, int defport,
+open_ldap_connection( LDAP *ld, Sockbuf *sb, const char *host, int defport,
char **krbinstancep, int async )
{
- int rc, port;
- char *p, *q, *r;
- char *curhost, hostname[ 2*MAXHOSTNAMELEN ];
+ int rc = -1;
+ int port;
+ const char *p, *q;
+ char *r, *curhost, hostname[ 2*MAXHOSTNAMELEN ];
Debug( LDAP_DEBUG_TRACE, "open_ldap_connection\n", 0, 0, 0 );
- defport = htons( defport );
+ defport = htons( (short) defport );
if ( host != NULL ) {
for ( p = host; p != NULL && *p != '\0'; p = q ) {
++q;
}
} else {
- curhost = p; /* avoid copy if possible */
+ curhost = (char *) p; /* avoid copy if possible */
q = NULL;
}
curhost = hostname;
}
*r++ = '\0';
- port = htons( (short)atoi( r ));
+ port = htons( (short) atoi( r ) );
} else {
port = defport;
}
- if (( rc = connect_to_host( sb, curhost, 0L,
+ if (( rc = ldap_connect_to_host( ld, sb, curhost, 0L,
port, async )) != -1 ) {
break;
}
}
} else {
- rc = connect_to_host( sb, NULL, htonl( INADDR_LOOPBACK ),
+ rc = ldap_connect_to_host( ld, sb, 0, htonl( INADDR_LOOPBACK ),
defport, async );
}
if ( rc == -1 ) {
return( rc );
}
-
+
+ ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
+
+#ifdef HAVE_TLS
+ if ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ) {
+ /*
+ * Fortunately, the lib uses blocking io...
+ */
+ if ( ldap_pvt_tls_connect( sb, ld->ld_options.ldo_tls_ctx ) <
+ 0 ) {
+ return -1;
+ }
+ /* FIXME: hostname of server must be compared with name in
+ * certificate....
+ */
+ }
+#endif
if ( krbinstancep != NULL ) {
-#ifdef KERBEROS
- if (( *krbinstancep = host_connected_to( sb )) != NULL &&
- ( p = strchr( *krbinstancep, '.' )) != NULL ) {
- *p = '\0';
+#ifdef HAVE_KERBEROS
+ char *c;
+ if (( *krbinstancep = ldap_host_connected_to( sb )) != NULL &&
+ ( c = strchr( *krbinstancep, '.' )) != NULL ) {
+ *c = '\0';
}
-#else /* KERBEROS */
+#else /* HAVE_KERBEROS */
krbinstancep = NULL;
-#endif /* KERBEROS */
+#endif /* HAVE_KERBEROS */
}
return( 0 );
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+static const LDAPAPIFeatureInfo features[] = {
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ { /* OpenLDAP Extensions API Feature */
+ LDAP_FEATURE_INFO_VERSION,
+ "X_OPENLDAP",
+ LDAP_API_FEATURE_X_OPENLDAP
+ },
+#endif
+
+#ifdef LDAP_API_FEATURE_THREAD_SAFE
+ { /* Basic Thread Safe */
+ LDAP_FEATURE_INFO_VERSION,
+ "THREAD_SAFE",
+ LDAP_API_FEATURE_THREAD_SAFE
+ },
+#endif
+#ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
+ { /* Session Thread Safe */
+ LDAP_FEATURE_INFO_VERSION,
+ "SESSION_THREAD_SAFE",
+ LDAP_API_FEATURE_SESSION_THREAD_SAFE
+ },
+#endif
+#ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
+ { /* Operation Thread Safe */
+ LDAP_FEATURE_INFO_VERSION,
+ "OPERATION_THREAD_SAFE",
+ LDAP_API_FEATURE_OPERATION_THREAD_SAFE
+ },
+#endif
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
+ { /* OpenLDAP Reentrant */
+ LDAP_FEATURE_INFO_VERSION,
+ "X_OPENLDAP_REENTRANT",
+ LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
+ },
+#endif
+#if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
+ defined( LDAP_THREAD_SAFE )
+ { /* OpenLDAP Thread Safe */
+ LDAP_FEATURE_INFO_VERSION,
+ "X_OPENLDAP_THREAD_SAFE",
+ LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
+ },
+#endif
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
+ { /* DNS */
+ LDAP_FEATURE_INFO_VERSION,
+ "X_OPENLDAP_V2_DNS",
+ LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
+ },
+#endif
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
+ { /* V2 Referrals */
+ LDAP_FEATURE_INFO_VERSION,
+ "X_OPENLDAP_V2_REFERRALS",
+ LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
+ },
+#endif
+ {0, NULL, 0}
+};
+
+int
+ldap_get_option(
+ LDAP_CONST LDAP *ld,
+ int option,
+ void *outvalue)
+{
+ LDAP_CONST struct ldapoptions *lo;
+
+ if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
+ ldap_int_initialize();
+ }
+
+ if(ld == NULL) {
+ lo = &ldap_int_global_options;
+
+ } else {
+ assert( LDAP_VALID( ld ) );
+
+ if( !LDAP_VALID( ld ) ) {
+ return LDAP_OPT_ERROR;
+ }
+
+ lo = &ld->ld_options;
+ }
+
+ if(outvalue == NULL) {
+ /* no place to get to */
+ return LDAP_OPT_ERROR;
+ }
+
+ switch(option) {
+ case LDAP_OPT_API_INFO: {
+ struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
+
+ if(info == NULL) {
+ /* outvalue must point to an apiinfo structure */
+ return LDAP_OPT_ERROR;
+ }
+
+ if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
+ /* api info version mismatch */
+ info->ldapai_info_version = LDAP_API_INFO_VERSION;
+ return LDAP_OPT_ERROR;
+ }
+
+ info->ldapai_api_version = LDAP_API_VERSION;
+ info->ldapai_api_version = LDAP_API_VERSION;
+ info->ldapai_protocol_version = LDAP_VERSION_MAX;
+
+ if(features[0].ldapaif_name == NULL) {
+ info->ldapai_extensions = NULL;
+ } else {
+ int i;
+ info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
+ sizeof(features)/sizeof(LDAPAPIFeatureInfo));
+
+ for(i=0; features[i].ldapaif_name != NULL; i++) {
+ info->ldapai_extensions[i] =
+ LDAP_STRDUP(features[i].ldapaif_name);
+ }
+
+ info->ldapai_extensions[i] = NULL;
+ }
+
+ info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
+ info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
+
+ return LDAP_OPT_SUCCESS;
+ } break;
+
+ case LDAP_OPT_DESC:
+ if(ld == NULL) {
+ /* bad param */
+ break;
+ }
+
+ * (ber_socket_t *) outvalue = ber_pvt_sb_get_desc( &(ld->ld_sb) );
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_TIMEOUT:
+ /* the caller has to free outvalue ! */
+ if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
+ {
+ return LDAP_OPT_ERROR;
+ }
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_NETWORK_TIMEOUT:
+ /* the caller has to free outvalue ! */
+ if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
+ {
+ return LDAP_OPT_ERROR;
+ }
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_DEREF:
+ * (int *) outvalue = lo->ldo_deref;
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_SIZELIMIT:
+ * (int *) outvalue = lo->ldo_sizelimit;
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_TIMELIMIT:
+ * (int *) outvalue = lo->ldo_timelimit;
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_REFERRALS:
+ * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_RESTART:
+ * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_DNS: /* LDAPv2 */
+ * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_DNS);
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_PROTOCOL_VERSION:
+ if ((ld != NULL) && ld->ld_version) {
+ * (int *) outvalue = ld->ld_version;
+ } else {
+ * (int *) outvalue = lo->ldo_version;
+ }
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_SERVER_CONTROLS:
+ * (LDAPControl ***) outvalue =
+ ldap_controls_dup( lo->ldo_sctrls );
+
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_CLIENT_CONTROLS:
+ * (LDAPControl ***) outvalue =
+ ldap_controls_dup( lo->ldo_cctrls );
+
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_HOST_NAME:
+ * (char **) outvalue = LDAP_STRDUP(lo->ldo_defhost);
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_ERROR_NUMBER:
+ if(ld == NULL) {
+ /* bad param */
+ break;
+ }
+ * (int *) outvalue = ld->ld_errno;
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_ERROR_STRING:
+ if(ld == NULL) {
+ /* bad param */
+ break;
+ }
+
+ if( ld->ld_error == NULL ) {
+ * (char **) outvalue = NULL;
+ } else {
+ * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
+ }
+
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_MATCHED_DN:
+ if(ld == NULL) {
+ /* bad param */
+ break;
+ }
+
+ if( ld->ld_matched == NULL ) {
+ * (char **) outvalue = NULL;
+ } else {
+ * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
+ }
+
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_API_FEATURE_INFO: {
+ LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
+ int i;
+
+ if(info == NULL) return LDAP_OPT_ERROR;
+
+ if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
+ /* api info version mismatch */
+ info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
+ return LDAP_OPT_ERROR;
+ }
+
+ if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
+
+ for(i=0; features[i].ldapaif_name != NULL; i++) {
+ if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
+ info->ldapaif_version =
+ features[i].ldapaif_version;
+ return LDAP_OPT_SUCCESS;
+ }
+ }
+ }
+ break;
+
+ case LDAP_OPT_DEBUG_LEVEL:
+ * (int *) outvalue = lo->ldo_debug;
+ return LDAP_OPT_SUCCESS;
+
+ default:
+#ifdef HAVE_TLS
+ if ( ldap_pvt_tls_get_option(lo, option, outvalue ) == 0 )
+ return LDAP_OPT_SUCCESS;
+#endif
+ /* bad param */
+ break;
+ }
+
+ return LDAP_OPT_ERROR;
+}
+
+int
+ldap_set_option(
+ LDAP *ld,
+ int option,
+ LDAP_CONST void *invalue)
+{
+ struct ldapoptions *lo;
+
+ if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
+ ldap_int_initialize();
+ }
+
+ if(ld == NULL) {
+ lo = &ldap_int_global_options;
+
+ } else {
+ assert( LDAP_VALID( ld ) );
+
+ if( !LDAP_VALID( ld ) ) {
+ return LDAP_OPT_ERROR;
+ }
+
+ lo = &ld->ld_options;
+ }
+
+ switch(option) {
+ case LDAP_OPT_REFERRALS:
+ if(invalue == LDAP_OPT_OFF) {
+ LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
+ } else {
+ LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
+ }
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_RESTART:
+ if(invalue == LDAP_OPT_OFF) {
+ LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
+ } else {
+ LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
+ }
+ return LDAP_OPT_SUCCESS;
+ }
+
+ /* options which can withstand invalue == NULL */
+ switch ( option ) {
+ case LDAP_OPT_SERVER_CONTROLS: {
+ LDAPControl *const *controls =
+ (LDAPControl *const *) invalue;
+
+ ldap_controls_free( lo->ldo_sctrls );
+
+ if( controls == NULL || *controls == NULL ) {
+ lo->ldo_sctrls = NULL;
+ return LDAP_OPT_SUCCESS;
+ }
+
+ lo->ldo_sctrls = ldap_controls_dup( controls );
+
+ if(lo->ldo_sctrls == NULL) {
+ /* memory allocation error ? */
+ break;
+ }
+ } return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_CLIENT_CONTROLS: {
+ LDAPControl *const *controls =
+ (LDAPControl *const *) invalue;
+
+ ldap_controls_free( lo->ldo_cctrls );
+
+ if( controls == NULL || *controls == NULL ) {
+ lo->ldo_cctrls = NULL;
+ return LDAP_OPT_SUCCESS;
+ }
+
+ lo->ldo_cctrls = ldap_controls_dup( controls );
+
+ if(lo->ldo_cctrls == NULL) {
+ /* memory allocation error ? */
+ break;
+ }
+ } return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_TIMEOUT: {
+ const struct timeval *tv =
+ (const struct timeval *) invalue;
+
+ if ( lo->ldo_tm_api != NULL ) {
+ LDAP_FREE( lo->ldo_tm_api );
+ lo->ldo_tm_api = NULL;
+ }
+
+ if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
+ return LDAP_OPT_ERROR;
+ }
+ } return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_NETWORK_TIMEOUT: {
+ const struct timeval *tv =
+ (const struct timeval *) invalue;
+
+ if ( lo->ldo_tm_net != NULL ) {
+ LDAP_FREE( lo->ldo_tm_net );
+ lo->ldo_tm_net = NULL;
+ }
+
+ if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
+ return LDAP_OPT_ERROR;
+ }
+ } return LDAP_OPT_SUCCESS;
+ }
+
+ if(invalue == NULL) {
+ /* no place to set from */
+ return LDAP_OPT_ERROR;
+ }
+
+ /* options which cannot withstand invalue == NULL */
+
+ switch(option) {
+ case LDAP_OPT_API_INFO:
+ case LDAP_OPT_DESC:
+ /* READ ONLY */
+ break;
+
+ case LDAP_OPT_DEREF:
+ lo->ldo_deref = * (const int *) invalue;
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_SIZELIMIT:
+ lo->ldo_sizelimit = * (const int *) invalue;
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_TIMELIMIT:
+ lo->ldo_timelimit = * (const int *) invalue;
+ return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_PROTOCOL_VERSION: {
+ int vers = * (const int *) invalue;
+ if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
+ /* not supported */
+ break;
+ }
+ ld->ld_version = vers;
+ } return LDAP_OPT_SUCCESS;
+
+
+ case LDAP_OPT_HOST_NAME: {
+ const char *host = (const char *) invalue;
+
+ if(lo->ldo_defhost != NULL) {
+ LDAP_FREE(lo->ldo_defhost);
+ lo->ldo_defhost = NULL;
+ }
+
+ if(host != NULL) {
+ lo->ldo_defhost = LDAP_STRDUP(host);
+ return LDAP_OPT_SUCCESS;
+ }
+
+ if(ld == NULL) {
+ /*
+ * must want global default returned
+ * to initial condition.
+ */
+ lo->ldo_defhost = LDAP_STRDUP("localhost");
+
+ } else {
+ /*
+ * must want the session default
+ * updated to the current global default
+ */
+ lo->ldo_defhost = LDAP_STRDUP(
+ ldap_int_global_options.ldo_defhost);
+ }
+ } return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_ERROR_NUMBER: {
+ int err = * (const int *) invalue;
+
+ if(ld == NULL) {
+ /* need a struct ldap */
+ break;
+ }
+
+ ld->ld_errno = err;
+ } return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_ERROR_STRING: {
+ const char *err = (const char *) invalue;
+
+ if(ld == NULL) {
+ /* need a struct ldap */
+ break;
+ }
+
+ if( ld->ld_error ) {
+ LDAP_FREE(ld->ld_error);
+ }
+
+ ld->ld_error = LDAP_STRDUP(err);
+ } return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_MATCHED_DN: {
+ const char *err = (const char *) invalue;
+
+ if(ld == NULL) {
+ /* need a struct ldap */
+ break;
+ }
+
+ if( ld->ld_matched ) {
+ LDAP_FREE(ld->ld_matched);
+ }
+
+ ld->ld_matched = LDAP_STRDUP(err);
+ } return LDAP_OPT_SUCCESS;
+
+ case LDAP_OPT_API_FEATURE_INFO:
+ /* read-only */
+ break;
+
+ case LDAP_OPT_DEBUG_LEVEL:
+ lo->ldo_debug = * (const int *) invalue;
+ return LDAP_OPT_SUCCESS;
+
+ default:
+#ifdef HAVE_TLS
+ if ( ldap_pvt_tls_set_option( lo, option, invalue ) == 0 )
+ return LDAP_OPT_SUCCESS;
+#endif
+ /* bad param */
+ break;
+ }
+ return LDAP_OPT_ERROR;
+}
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
*
* os-ip.c -- platform-specific TCP & UDP related code
*/
-#ifndef lint
-static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#ifdef _WIN32
+#include <ac/stdlib.h>
+
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_IO_H
#include <io.h>
-#include "msdos.h"
-#else /* _WIN32 */
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#endif /* _WIN32 */
-#ifdef _AIX
-#include <sys/select.h>
-#endif /* _AIX */
-#ifdef VMS
-#include "ucx_select.h"
-#endif /* VMS */
-#include "portable.h"
-#include "lber.h"
-#include "ldap.h"
+#endif /* HAVE_IO_H */
-#ifdef LDAP_REFERRALS
-#ifdef USE_SYSCONF
-#include <unistd.h>
-#endif /* USE_SYSCONF */
-#ifdef notyet
-#ifdef NEED_FILIO
-#include <sys/filio.h>
-#else /* NEED_FILIO */
-#include <sys/ioctl.h>
-#endif /* NEED_FILIO */
-#endif /* notyet */
-#endif /* LDAP_REFERRALS */
-
-#ifdef MACOS
-#define tcp_close( s ) tcpclose( s )
-#else /* MACOS */
-#ifdef DOS
-#ifdef PCNFS
-#define tcp_close( s ) close( s )
-#endif /* PCNFS */
-#ifdef NCSA
-#define tcp_close( s ) netclose( s ); netshut()
-#endif /* NCSA */
-#ifdef WINSOCK
-#define tcp_close( s ) closesocket( s ); WSACleanup();
-#endif /* WINSOCK */
-#else /* DOS */
-#define tcp_close( s ) close( s )
-#endif /* DOS */
-#endif /* MACOS */
+#include "ldap-int.h"
+
+int ldap_int_tblsize = 0;
+
+/*
+ * nonblock connect code
+ * written by Lars Uffmann, <lars.uffmann@mediaway.net>.
+ *
+ * Copyright 1999, Lars Uffmann, All rights reserved.
+ * This software is not subject to any license of my employer
+ * mediaWays GmbH.
+ *
+ * OpenLDAP COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ *
+ * Read about the rationale in ldap_connect_timeout:
+ * ftp://koobera.math.uic.edu/www/docs/connect.html.
+ */
+
+#define osip_debug(ld,fmt,arg1,arg2,arg3) \
+do { \
+ ldap_log_printf(ld, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \
+} while(0)
+static void
+ldap_pvt_set_errno(int err)
+{
+ errno = err;
+}
int
-connect_to_host( Sockbuf *sb, char *host, unsigned long address,
- int port, int async )
+ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src )
+{
+ struct timeval *new;
+
+ assert( dest != NULL );
+
+ if (src == NULL) {
+ *dest = NULL;
+ return 0;
+ }
+
+ new = (struct timeval *) malloc(sizeof(struct timeval));
+
+ if( new == NULL ) {
+ *dest = NULL;
+ return 1;
+ }
+
+ SAFEMEMCPY( (char *) new, (const char *) src, sizeof(struct timeval));
+
+ *dest = new;
+ return 0;
+}
+
+static int
+ldap_pvt_ndelay_on(LDAP *ld, int fd)
+{
+ osip_debug(ld, "ldap_ndelay_on: %d\n",fd,0,0);
+ return ber_pvt_socket_set_nonblock( fd, 1 );
+}
+
+static int
+ldap_pvt_ndelay_off(LDAP *ld, int fd)
+{
+ osip_debug(ld, "ldap_ndelay_off: %d\n",fd,0,0);
+ return ber_pvt_socket_set_nonblock( fd, 0 );
+}
+
+static ber_socket_t
+ldap_pvt_socket(LDAP *ld)
+{
+ ber_socket_t s = socket(AF_INET, SOCK_STREAM, 0);
+ osip_debug(ld, "ldap_new_socket: %d\n",s,0,0);
+ return ( s );
+}
+
+static int
+ldap_pvt_close_socket(LDAP *ld, int s)
+{
+ osip_debug(ld, "ldap_close_socket: %d\n",s,0,0);
+ return tcp_close(s);
+}
+
+static int
+ldap_pvt_prepare_socket(LDAP *ld, int fd)
+{
+ osip_debug(ld, "ldap_prepare_socket: %d\n",fd,0,0);
+
+#ifdef TCP_NODELAY
+{
+ int dummy = 1;
+ if ( setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (char*) &dummy, sizeof(dummy) ) == -1 )
+ return -1;
+}
+#endif
+ return 0;
+}
+
+#undef TRACE
+#define TRACE do { \
+ osip_debug(ld, \
+ "ldap_is_socket_ready: errror on socket %d: errno: %d (%s)\n", \
+ s, \
+ errno, \
+ strerror(errno) ); \
+} while( 0 )
+
/*
- * if host == NULL, connect using address
- * "address" and "port" must be in network byte order
- * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
- * async is only used ifdef LDAP_REFERRALS (non-0 means don't wait for connect)
- * XXX async is not used yet!
+ * check the socket for errors after select returned.
*/
+static int
+ldap_pvt_is_socket_ready(LDAP *ld, int s)
{
- int rc, i, s, connected, use_hp;
- struct sockaddr_in sin;
- struct hostent *hp;
-#ifdef notyet
-#ifdef LDAP_REFERRALS
- int status; /* for ioctl call */
-#endif /* LDAP_REFERRALS */
-#endif /* notyet */
+ osip_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0);
+
+#if defined( notyet ) /* && defined( SO_ERROR ) */
+{
+ int so_errno;
+ int dummy = sizeof(so_errno);
+ if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy ) == -1 ) {
+ return -1;
+ }
+ if ( so_errno ) {
+ ldap_pvt_set_errno(so_errno);
+ TRACE;
+ return -1;
+ }
+ return 0;
+}
+#else
+{
+ /* error slippery */
+ struct sockaddr_in sin;
+ char ch;
+ int dummy = sizeof(sin);
+ if ( getpeername( s, (struct sockaddr *) &sin, &dummy ) == -1 ) {
+ /* XXX: needs to be replace with ber_stream_read() */
+ read(s, &ch, 1);
+#ifdef HAVE_WINSOCK
+ ldap_pvt_set_errno( WSAGetLastError() );
+#endif
+ TRACE;
+ return -1;
+ }
+ return 0;
+}
+#endif
+ return -1;
+}
+#undef TRACE
+
+static int
+ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_in *sin, int async)
+{
+ struct timeval tv, *opt_tv=NULL;
+ fd_set wfds, *z=NULL;
- Debug( LDAP_DEBUG_TRACE, "connect_to_host: %s:%d\n",
- ( host == NULL ) ? "(by address)" : host, ntohs( port ), 0 );
+ if ( (opt_tv = ld->ld_options.ldo_tm_net) != NULL ) {
+ tv.tv_usec = opt_tv->tv_usec;
+ tv.tv_sec = opt_tv->tv_sec;
+ }
- connected = use_hp = 0;
+ osip_debug(ld, "ldap_connect_timeout: fd: %d tm: %d async: %d\n",
+ s, opt_tv ? tv.tv_sec : -1, async);
- if ( host != NULL && ( address = inet_addr( host )) == -1 ) {
- if ( (hp = gethostbyname( host )) == NULL ) {
- errno = EHOSTUNREACH; /* not exactly right, but... */
- return( -1 );
- }
- use_hp = 1;
+ if ( ldap_pvt_ndelay_on(ld, s) == -1 )
+ return ( -1 );
+
+ if ( connect(s, (struct sockaddr *) sin, sizeof(struct sockaddr_in)) == 0 )
+ {
+ if ( ldap_pvt_ndelay_off(ld, s) == -1 )
+ return ( -1 );
+ return ( 0 );
}
- rc = -1;
- for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ ) {
- if (( s = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
- return( -1 );
- }
-#ifdef notyet
-#ifdef LDAP_REFERRALS
- status = 1;
- if ( async && ioctl( s, FIONBIO, (caddr_t)&status ) == -1 ) {
- Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
- s, 0, 0 );
- }
-#endif /* LDAP_REFERRALS */
-#endif /* notyet */
- (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
- sin.sin_family = AF_INET;
- sin.sin_port = port;
- SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
- ( use_hp ? (char *) hp->h_addr_list[ i ] :
- (char *) &address ), sizeof( sin.sin_addr.s_addr) );
-
- if ( connect( s, (struct sockaddr *)&sin,
- sizeof( struct sockaddr_in )) >= 0 ) {
- connected = 1;
- rc = 0;
- break;
- } else {
+#ifdef HAVE_WINSOCK
+ ldap_pvt_set_errno( WSAGetLastError() );
+#endif
+
+ if ( errno != EINPROGRESS && errno != EWOULDBLOCK ) {
+ return ( -1 );
+ }
+
#ifdef notyet
-#ifdef LDAP_REFERRALS
-#ifdef EAGAIN
- if ( errno == EINPROGRESS || errno == EAGAIN ) {
-#else /* EAGAIN */
- if ( errno == EINPROGRESS ) {
-#endif /* EAGAIN */
- Debug( LDAP_DEBUG_TRACE,
- "connect would block...\n", 0, 0, 0 );
- rc = -2;
- break;
- }
-#endif /* LDAP_REFERRALS */
-#endif /* notyet */
+ if ( async ) return ( -2 );
+#endif
-#ifdef LDAP_DEBUG
- if ( ldap_debug & LDAP_DEBUG_TRACE ) {
- perror( (char *)inet_ntoa( sin.sin_addr ));
- }
+ FD_ZERO(&wfds);
+ FD_SET(s, &wfds );
+
+ if ( select(ldap_int_tblsize, z, &wfds, z, opt_tv ? &tv : NULL) == -1)
+ return ( -1 );
+
+ if ( FD_ISSET(s, &wfds) ) {
+ if ( ldap_pvt_is_socket_ready(ld, s) == -1 )
+ return ( -1 );
+ if ( ldap_pvt_ndelay_off(ld, s) == -1 )
+ return ( -1 );
+ return ( 0 );
+ }
+ osip_debug(ld, "ldap_connect_timeout: timed out\n",0,0,0);
+ ldap_pvt_set_errno( ETIMEDOUT );
+ return ( -1 );
+}
+
+#ifndef HAVE_INET_ATON
+int
+ldap_pvt_inet_aton( const char *host, struct in_addr *in)
+{
+ unsigned long u = inet_addr( host );
+ if ( u != 0xffffffff || u != (unsigned long) -1 ) {
+ in->s_addr = u;
+ return 1;
+ }
+ return 0;
+}
#endif
- close( s );
- if ( !use_hp ) {
- break;
+
+
+int
+ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
+ unsigned long address, int port, int async)
+{
+ struct sockaddr_in sin;
+ struct in_addr in;
+ ber_socket_t s = AC_SOCKET_INVALID;
+ int rc, i, use_hp = 0;
+ struct hostent *hp, he_buf;
+ int local_h_errno;
+ char *ha_buf=NULL, *p, *q;
+
+ osip_debug(ld, "ldap_connect_to_host\n",0,0,0);
+
+ if (host != NULL) {
+ if (! inet_aton( host, &in) ) {
+ rc = ldap_pvt_gethostbyname_a(host, &he_buf, &ha_buf,
+ &hp, &local_h_errno);
+
+ if ( rc < 0 )
+ ; /*XXX NO MEMORY? */
+
+ if ( (rc < 0) || (hp == NULL) ) {
+#ifdef HAVE_WINSOCK
+ ldap_pvt_set_errno( WSAGetLastError() );
+#else
+ /* not exactly right, but... */
+ ldap_pvt_set_errno( EHOSTUNREACH );
+#endif
+ if (ha_buf) LDAP_FREE(ha_buf);
+ return -1;
}
+ use_hp = 1;
}
+ address = in.s_addr;
}
- sb->sb_sd = s;
+ rc = s = -1;
+ for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) {
- if ( connected ) {
-#ifdef notyet
-#ifdef LDAP_REFERRALS
- status = 0;
- if ( !async && ioctl( s, FIONBIO, (caddr_t)&on ) == -1 ) {
- Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
- s, 0, 0 );
+ if ( (s = ldap_pvt_socket( ld )) == -1 )
+ /* use_hp ? continue : break; */
+ break;
+
+ if ( ldap_pvt_prepare_socket(ld, s) == -1 ) {
+ ldap_pvt_close_socket(ld, s);
+ /* use_hp ? continue : break; */
+ break;
}
-#endif /* LDAP_REFERRALS */
-#endif /* notyet */
- Debug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
- s, inet_ntoa( sin.sin_addr ), 0 );
- }
+ (void)memset((char *)&sin, 0, sizeof(struct sockaddr_in));
+ sin.sin_family = AF_INET;
+ sin.sin_port = port;
+ p = (char *)&sin.sin_addr.s_addr;
+ q = use_hp ? (char *)hp->h_addr_list[i] : (char *)&address;
+ SAFEMEMCPY(p, q, sizeof(p) );
- return( rc );
-}
+ osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n",
+ inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),0);
+ rc = ldap_pvt_connect(ld, s, &sin, async);
+
+ if ( (rc == 0) || (rc == -2) ) {
+ ber_pvt_sb_set_desc( sb, s );
+ break;
+ }
+
+ ldap_pvt_close_socket(ld, s);
+
+ if (!use_hp)
+ break;
+ }
+ if (ha_buf) LDAP_FREE(ha_buf);
+ return rc;
+}
void
-close_connection( Sockbuf *sb )
+ldap_close_connection( Sockbuf *sb )
{
- tcp_close( sb->sb_sd );
+ ber_pvt_sb_close( sb );
}
-#ifdef KERBEROS
+#if defined( HAVE_KERBEROS ) || defined( HAVE_TLS )
char *
-host_connected_to( Sockbuf *sb )
+ldap_host_connected_to( Sockbuf *sb )
{
struct hostent *hp;
char *p;
- int len;
+ socklen_t len;
struct sockaddr_in sin;
+ /* buffers for gethostbyaddr_r */
+ struct hostent he_buf;
+ int local_h_errno;
+ char *ha_buf=NULL;
+#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x);
+
(void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
len = sizeof( sin );
- if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
+
+ if ( getpeername( ber_pvt_sb_get_desc(sb), (struct sockaddr *)&sin, &len ) == -1 ) {
return( NULL );
}
* this is necessary for kerberos to work right, since the official
* hostname is used as the kerberos instance.
*/
- if (( hp = gethostbyaddr( (char *) &sin.sin_addr,
- sizeof( sin.sin_addr ), AF_INET )) != NULL ) {
+ if ((ldap_pvt_gethostbyaddr_a( (char *) &sin.sin_addr,
+ sizeof( sin.sin_addr ),
+ AF_INET, &he_buf, &ha_buf,
+ &hp,&local_h_errno ) ==0 ) && (hp != NULL) )
+ {
if ( hp->h_name != NULL ) {
- return( strdup( hp->h_name ));
+ char *host = LDAP_STRDUP( hp->h_name );
+ DO_RETURN( host );
}
}
- return( NULL );
+ DO_RETURN( NULL );
}
-#endif /* KERBEROS */
+#undef DO_RETURN
+
+#endif /* HAVE_KERBEROS || HAVE_TLS */
-#ifdef LDAP_REFERRALS
/* for UNIX */
struct selectinfo {
fd_set si_readfds;
void
-mark_select_write( LDAP *ld, Sockbuf *sb )
+ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
sip = (struct selectinfo *)ld->ld_selectinfo;
-
- if ( !FD_ISSET( sb->sb_sd, &sip->si_writefds )) {
- FD_SET( sb->sb_sd, &sip->si_writefds );
+
+ if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_writefds )) {
+ FD_SET( (u_int) sb->sb_sd, &sip->si_writefds );
}
}
void
-mark_select_read( LDAP *ld, Sockbuf *sb )
+ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
sip = (struct selectinfo *)ld->ld_selectinfo;
- if ( !FD_ISSET( sb->sb_sd, &sip->si_readfds )) {
- FD_SET( sb->sb_sd, &sip->si_readfds );
+ if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_readfds )) {
+ FD_SET( (u_int) sb->sb_sd, &sip->si_readfds );
}
}
void
-mark_select_clear( LDAP *ld, Sockbuf *sb )
+ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
sip = (struct selectinfo *)ld->ld_selectinfo;
- FD_CLR( sb->sb_sd, &sip->si_writefds );
- FD_CLR( sb->sb_sd, &sip->si_readfds );
+ FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_writefds );
+ FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_readfds );
}
int
-is_write_ready( LDAP *ld, Sockbuf *sb )
+ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
sip = (struct selectinfo *)ld->ld_selectinfo;
- return( FD_ISSET( sb->sb_sd, &sip->si_use_writefds ));
+ return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_writefds ));
}
int
-is_read_ready( LDAP *ld, Sockbuf *sb )
+ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
sip = (struct selectinfo *)ld->ld_selectinfo;
- return( FD_ISSET( sb->sb_sd, &sip->si_use_readfds ));
+ return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_readfds ));
}
void *
-new_select_info()
+ldap_new_select_info( void )
{
struct selectinfo *sip;
- if (( sip = (struct selectinfo *)calloc( 1,
+ if (( sip = (struct selectinfo *)LDAP_CALLOC( 1,
sizeof( struct selectinfo ))) != NULL ) {
FD_ZERO( &sip->si_readfds );
FD_ZERO( &sip->si_writefds );
void
-free_select_info( void *sip )
+ldap_free_select_info( void *sip )
{
- free( sip );
+ LDAP_FREE( sip );
+}
+
+
+void
+ldap_int_ip_init( void )
+{
+ int tblsize;
+#if defined( HAVE_SYSCONF )
+ tblsize = sysconf( _SC_OPEN_MAX );
+#elif defined( HAVE_GETDTABLESIZE )
+ tblsize = getdtablesize();
+#else
+ tblsize = FD_SETSIZE;
+#endif /* !USE_SYSCONF */
+
+#ifdef FD_SETSIZE
+ if( tblsize > FD_SETSIZE )
+ tblsize = FD_SETSIZE;
+#endif /* FD_SETSIZE*/
+ ldap_int_tblsize = tblsize;
}
do_ldap_select( LDAP *ld, struct timeval *timeout )
{
struct selectinfo *sip;
- static int tblsize;
Debug( LDAP_DEBUG_TRACE, "do_ldap_select\n", 0, 0, 0 );
- if ( tblsize == 0 ) {
-#ifdef USE_SYSCONF
- tblsize = sysconf( _SC_OPEN_MAX );
-#else /* USE_SYSCONF */
- tblsize = getdtablesize();
-#endif /* USE_SYSCONF */
- }
+ if ( ldap_int_tblsize == 0 )
+ ldap_int_ip_init();
sip = (struct selectinfo *)ld->ld_selectinfo;
sip->si_use_readfds = sip->si_readfds;
sip->si_use_writefds = sip->si_writefds;
- return( select( tblsize, &sip->si_use_readfds, &sip->si_use_writefds,
- NULL, timeout ));
+ return( select( ldap_int_tblsize,
+ &sip->si_use_readfds, &sip->si_use_writefds,
+ NULL, timeout ));
}
-#endif /* LDAP_REFERRALS */
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
*
* request.c - sending of ldap requests; handling of referrals
*/
-#ifndef lint
-static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#ifdef MACOS
-#include <stdlib.h>
-#include <time.h>
-#include "macos.h"
-#else /* MACOS */
-#if defined( DOS ) || defined( _WIN32 )
-#include "msdos.h"
-#include <time.h>
-#include <stdlib.h>
-#ifdef PCNFS
-#include <tklib.h>
-#include <tk_errno.h>
-#include <bios.h>
-#endif /* PCNFS */
-#ifdef NCSA
-#include "externs.h"
-#endif /* NCSA */
-#else /* DOS */
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-#ifdef _AIX
-#include <sys/select.h>
-#endif /* _AIX */
-#include "portable.h"
-#endif /* DOS */
-#endif /* MACOS */
-#ifdef VMS
-#include "ucx_select.h"
-#endif
-#include "lber.h"
-#include "ldap.h"
+
+#include <ac/stdlib.h>
+
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
#include "ldap-int.h"
+#include "lber.h"
-#ifdef USE_SYSCONF
-#include <unistd.h>
-#endif /* USE_SYSCONF */
-
-
-#if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
-#ifdef NEEDPROTOS
-static LDAPConn *find_connection( LDAP *ld, LDAPServer *srv, int any );
-static void use_connection( LDAP *ld, LDAPConn *lc );
-static void free_servers( LDAPServer *srvlist );
-#else /* NEEDPROTOS */
-static LDAPConn *find_connection();
-static void use_connection();
-static void free_servers();
-#endif /* NEEDPROTOS */
-#endif /* LDAP_REFERRALS || LDAP_DNS */
-
-
-#ifdef LDAP_DNS
-#ifdef NEEDPROTOS
-static LDAPServer *dn2servers( LDAP *ld, char *dn );
-#else /* NEEDPROTOS */
-static LDAPServer *dn2servers();
-#endif /* NEEDPROTOS */
-#endif /* LDAP_DNS */
-
-#ifdef LDAP_REFERRALS
-#ifdef NEEDPROTOS
-static BerElement *re_encode_request( LDAP *ld, BerElement *origber,
- int msgid, char **dnp );
-#else /* NEEDPROTOS */
-static BerElement *re_encode_request();
-#endif /* NEEDPROTOS */
-#endif /* LDAP_REFERRALS */
+static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPServer *srv, int any ));
+static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc ));
+static void free_servers LDAP_P(( LDAPServer *srvlist ));
+
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
+static LDAPServer *dn2servers LDAP_P(( LDAP *ld, const char *dn ));
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
+
+static BerElement *re_encode_request LDAP_P((
+ LDAP *ld,
+ BerElement *origber,
+ ber_int_t msgid,
+ char **dnp ));
BerElement *
-alloc_ber_with_options( LDAP *ld )
+ldap_alloc_ber_with_options( LDAP *ld )
{
BerElement *ber;
- if (( ber = ber_alloc_t( ld->ld_lberoptions )) == NULLBER ) {
+ if (( ber = ber_alloc_t( ld->ld_lberoptions )) == NULL ) {
ld->ld_errno = LDAP_NO_MEMORY;
#ifdef STR_TRANSLATION
} else {
- set_ber_options( ld, ber );
+ ldap_set_ber_options( ld, ber );
#endif /* STR_TRANSLATION */
}
void
-set_ber_options( LDAP *ld, BerElement *ber )
+ldap_set_ber_options( LDAP *ld, BerElement *ber )
{
ber->ber_options = ld->ld_lberoptions;
#ifdef STR_TRANSLATION
}
-int
-send_initial_request( LDAP *ld, unsigned long msgtype, char *dn,
+ber_int_t
+ldap_send_initial_request(
+ LDAP *ld,
+ ber_tag_t msgtype,
+ const char *dn,
BerElement *ber )
{
-#if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
- LDAPServer *servers;
-#endif /* LDAP_REFERRALS || LDAP_DNS */
+ LDAPServer *servers, *srv;
- Debug( LDAP_DEBUG_TRACE, "send_initial_request\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
-#if !defined( LDAP_REFERRALS ) && !defined( LDAP_DNS )
- if ( ber_flush( &ld->ld_sb, ber, 1 ) != 0 ) {
- ld->ld_errno = LDAP_SERVER_DOWN;
- return( -1 );
+ if ( ! ber_pvt_sb_in_use(&ld->ld_sb ) ) {
+ /* not connected yet */
+
+ if (( srv = (LDAPServer *)LDAP_CALLOC( 1, sizeof( LDAPServer ))) ==
+ NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host =
+ LDAP_STRDUP( ld->ld_defhost )) == NULL ))
+ {
+ if (srv != NULL) LDAP_FREE( srv );
+ ber_free( ber, 1 );
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( -1 );
+ }
+
+ srv->lsrv_port = ld->ld_defport;
+
+ if (( ld->ld_defconn = ldap_new_connection( ld, &srv, 1,1,0 ))
+ == NULL )
+ {
+ if ( ld->ld_defhost != NULL ) LDAP_FREE( srv->lsrv_host );
+ LDAP_FREE( (char *)srv );
+ ber_free( ber, 1 );
+ ld->ld_errno = LDAP_SERVER_DOWN;
+ return( -1 );
+ }
+ ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldap_delayed_open successful, ld_host is %s\n",
+ ( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 );
}
- ld->ld_errno = LDAP_SUCCESS;
- return( ld->ld_msgid );
-#else /* !LDAP_REFERRALS && !LDAP_DNS */
-#ifdef LDAP_DNS
- if (( ld->ld_options & LDAP_OPT_DNS ) != 0 && ldap_is_dns_dn( dn )) {
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
+ if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_DNS )
+ && ldap_is_dns_dn( dn ) )
+ {
if (( servers = dn2servers( ld, dn )) == NULL ) {
ber_free( ber, 1 );
return( -1 );
}
}
#endif /* LDAP_DEBUG */
- } else {
-#endif /* LDAP_DNS */
+ } else
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
+ {
/*
* use of DNS is turned off or this is an X.500 DN...
* use our default connection
*/
servers = NULL;
-#ifdef LDAP_DNS
}
-#endif /* LDAP_DNS */
- return( send_server_request( ld, ber, ld->ld_msgid, NULL, servers,
+ return( ldap_send_server_request( ld, ber, ld->ld_msgid, NULL, servers,
NULL, 0 ));
-#endif /* !LDAP_REFERRALS && !LDAP_DNS */
}
-#if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
int
-send_server_request( LDAP *ld, BerElement *ber, int msgid, LDAPRequest
- *parentreq, LDAPServer *srvlist, LDAPConn *lc, int bind )
+ldap_send_server_request(
+ LDAP *ld,
+ BerElement *ber,
+ ber_int_t msgid,
+ LDAPRequest *parentreq,
+ LDAPServer *srvlist,
+ LDAPConn *lc,
+ int bind )
{
LDAPRequest *lr;
+ int incparent;
- Debug( LDAP_DEBUG_TRACE, "send_server_request\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "ldap_send_server_request\n", 0, 0, 0 );
+ incparent = 0;
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
if ( lc == NULL ) {
} else {
if (( lc = find_connection( ld, srvlist, 1 )) ==
NULL ) {
- lc = new_connection( ld, &srvlist, 0, 1, bind );
+ if ( bind && (parentreq != NULL) ) {
+ /* Remember the bind in the parent */
+ incparent = 1;
+ ++parentreq->lr_outrefcnt;
+ }
+ lc = ldap_new_connection( ld, &srvlist, 0, 1, bind );
}
free_servers( srvlist );
}
if ( ld->ld_errno == LDAP_SUCCESS ) {
ld->ld_errno = LDAP_SERVER_DOWN;
}
+ if ( incparent ) {
+ /* Forget about the bind */
+ --parentreq->lr_outrefcnt;
+ }
return( -1 );
}
use_connection( ld, lc );
- if (( lr = (LDAPRequest *)calloc( 1, sizeof( LDAPRequest ))) ==
+ if (( lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ))) ==
NULL ) {
ld->ld_errno = LDAP_NO_MEMORY;
- free_connection( ld, lc, 0, 0 );
+ ldap_free_connection( ld, lc, 0, 0 );
ber_free( ber, 1 );
+ if ( incparent ) {
+ /* Forget about the bind */
+ --parentreq->lr_outrefcnt;
+ }
return( -1 );
}
lr->lr_msgid = msgid;
lr->lr_ber = ber;
lr->lr_conn = lc;
if ( parentreq != NULL ) { /* sub-request */
- ++parentreq->lr_outrefcnt;
+ if ( !incparent ) {
+ /* Increment if we didn't do it before the bind */
+ ++parentreq->lr_outrefcnt;
+ }
lr->lr_origid = parentreq->lr_origid;
lr->lr_parentcnt = parentreq->lr_parentcnt + 1;
lr->lr_parent = parentreq;
if ( ber_flush( lc->lconn_sb, ber, 0 ) != 0 ) {
#ifdef notyet
- extern int errno;
-
if ( errno == EWOULDBLOCK ) {
/* need to continue write later */
lr->lr_status = LDAP_REQST_WRITING;
- mark_select_write( ld, lc->lconn_sb );
+ ldap_mark_select_write( ld, lc->lconn_sb );
} else {
#else /* notyet */
ld->ld_errno = LDAP_SERVER_DOWN;
- free_request( ld, lr );
- free_connection( ld, lc, 0, 0 );
+ ldap_free_request( ld, lr );
+ ldap_free_connection( ld, lc, 0, 0 );
return( -1 );
#endif /* notyet */
#ifdef notyet
}
/* sent -- waiting for a response */
- mark_select_read( ld, lc->lconn_sb );
+ ldap_mark_select_read( ld, lc->lconn_sb );
}
ld->ld_errno = LDAP_SUCCESS;
LDAPConn *
-new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
+ldap_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
int connect, int bind )
{
LDAPConn *lc;
* make a new LDAP server connection
* XXX open connection synchronously for now
*/
- if (( lc = (LDAPConn *)calloc( 1, sizeof( LDAPConn ))) == NULL ||
- ( !use_ldsb && ( sb = (Sockbuf *)calloc( 1, sizeof( Sockbuf )))
- == NULL )) {
+ if (( lc = (LDAPConn *)LDAP_CALLOC( 1, sizeof( LDAPConn ))) == NULL ||
+ ( !use_ldsb && ( (sb = ber_sockbuf_alloc()) == NULL ))) {
if ( lc != NULL ) {
- free( (char *)lc );
+ LDAP_FREE( (char *)lc );
}
ld->ld_errno = LDAP_NO_MEMORY;
return( NULL );
if ( srv == NULL ) {
if ( !use_ldsb ) {
- free( (char *)lc->lconn_sb );
+ ber_sockbuf_free( lc->lconn_sb );
}
- free( (char *)lc );
+ LDAP_FREE( (char *)lc );
ld->ld_errno = LDAP_SERVER_DOWN;
return( NULL );
}
freepasswd = err = 0;
- if ( ld->ld_rebindproc == NULL ) {
+ if ( ld->ld_rebindproc == 0 ) {
binddn = passwd = "";
authmethod = LDAP_AUTH_SIMPLE;
} else {
}
if ( err != 0 ) {
- free_connection( ld, lc, 1, 0 );
+ ldap_free_connection( ld, lc, 1, 0 );
lc = NULL;
}
}
use_connection( LDAP *ld, LDAPConn *lc )
{
++lc->lconn_refcnt;
- lc->lconn_lastused = time( 0 );
+ lc->lconn_lastused = time( NULL );
}
void
-free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
+ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
{
LDAPConn *tmplc, *prevlc;
- Debug( LDAP_DEBUG_TRACE, "free_connection\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "ldap_free_connection\n", 0, 0, 0 );
if ( force || --lc->lconn_refcnt <= 0 ) {
if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
- mark_select_clear( ld, lc->lconn_sb );
+ ldap_mark_select_clear( ld, lc->lconn_sb );
if ( unbind ) {
- send_unbind( ld, lc->lconn_sb );
+ ldap_send_unbind( ld, lc->lconn_sb, NULL, NULL );
}
- close_connection( lc->lconn_sb );
- if ( lc->lconn_sb->sb_ber.ber_buf != NULL ) {
- free( lc->lconn_sb->sb_ber.ber_buf );
+ ldap_close_connection( lc->lconn_sb );
+ ber_pvt_sb_destroy( lc->lconn_sb );
+ if( lc->lconn_ber != NULL ) {
+ ber_free( lc->lconn_ber, 1 );
}
}
prevlc = NULL;
}
break;
}
+ prevlc = tmplc;
}
free_servers( lc->lconn_server );
if ( lc->lconn_krbinstance != NULL ) {
- free( lc->lconn_krbinstance );
+ LDAP_FREE( lc->lconn_krbinstance );
}
if ( lc->lconn_sb != &ld->ld_sb ) {
- free( (char *)lc->lconn_sb );
+ ber_sockbuf_free( lc->lconn_sb );
}
- free( lc );
- Debug( LDAP_DEBUG_TRACE, "free_connection: actually freed\n",
+ LDAP_FREE( lc );
+ Debug( LDAP_DEBUG_TRACE, "ldap_free_connection: actually freed\n",
0, 0, 0 );
} else {
- lc->lconn_lastused = time( 0 );
- Debug( LDAP_DEBUG_TRACE, "free_connection: refcnt %d\n",
+ lc->lconn_lastused = time( NULL );
+ Debug( LDAP_DEBUG_TRACE, "ldap_free_connection: refcnt %d\n",
lc->lconn_refcnt, 0, 0 );
}
}
#ifdef LDAP_DEBUG
void
-dump_connection( LDAP *ld, LDAPConn *lconns, int all )
+ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
{
LDAPConn *lc;
+ char timebuf[32];
fprintf( stderr, "** Connection%s:\n", all ? "s" : "" );
for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
"NeedSocket" : ( lc->lconn_status ==
LDAP_CONNST_CONNECTING ) ? "Connecting" : "Connected" );
fprintf( stderr, " last used: %s\n",
- ctime( &lc->lconn_lastused ));
+ ldap_pvt_ctime( &lc->lconn_lastused, timebuf ));
if ( !all ) {
break;
}
void
-dump_requests_and_responses( LDAP *ld )
+ldap_dump_requests_and_responses( LDAP *ld )
{
LDAPRequest *lr;
LDAPMessage *lm, *l;
}
fprintf( stderr, "** Response Queue:\n" );
- if (( lm = ld->ld_responses ) == NULLMSG ) {
+ if (( lm = ld->ld_responses ) == NULL ) {
fprintf( stderr, " Empty\n" );
}
- for ( ; lm != NULLMSG; lm = lm->lm_next ) {
- fprintf( stderr, " * msgid %d, type %d\n",
- lm->lm_msgid, lm->lm_msgtype );
+ for ( ; lm != NULL; lm = lm->lm_next ) {
+ fprintf( stderr, " * msgid %d, type %lu\n",
+ lm->lm_msgid, (unsigned long) lm->lm_msgtype );
if (( l = lm->lm_chain ) != NULL ) {
fprintf( stderr, " chained responses:\n" );
- for ( ; l != NULLMSG; l = l->lm_chain ) {
+ for ( ; l != NULL; l = l->lm_chain ) {
fprintf( stderr,
- " * msgid %d, type %d\n",
- l->lm_msgid, l->lm_msgtype );
+ " * msgid %d, type %lu\n",
+ l->lm_msgid,
+ (unsigned long) l->lm_msgtype );
}
}
}
void
-free_request( LDAP *ld, LDAPRequest *lr )
+ldap_free_request( LDAP *ld, LDAPRequest *lr )
{
LDAPRequest *tmplr, *nextlr;
- Debug( LDAP_DEBUG_TRACE, "free_request (origid %d, msgid %d)\n",
+ Debug( LDAP_DEBUG_TRACE, "ldap_free_request (origid %d, msgid %d)\n",
lr->lr_origid, lr->lr_msgid, 0 );
if ( lr->lr_parent != NULL ) {
/* free all referrals (child requests) */
for ( tmplr = lr->lr_refnext; tmplr != NULL; tmplr = nextlr ) {
nextlr = tmplr->lr_refnext;
- free_request( ld, tmplr );
+ ldap_free_request( ld, tmplr );
}
}
}
if ( lr->lr_res_error != NULL ) {
- free( lr->lr_res_error );
+ LDAP_FREE( lr->lr_res_error );
}
if ( lr->lr_res_matched != NULL ) {
- free( lr->lr_res_matched );
+ LDAP_FREE( lr->lr_res_matched );
}
- free( lr );
+ LDAP_FREE( lr );
}
while ( srvlist != NULL ) {
nextsrv = srvlist->lsrv_next;
if ( srvlist->lsrv_dn != NULL ) {
- free( srvlist->lsrv_dn );
+ LDAP_FREE( srvlist->lsrv_dn );
}
if ( srvlist->lsrv_host != NULL ) {
- free( srvlist->lsrv_host );
+ LDAP_FREE( srvlist->lsrv_host );
}
- free( srvlist );
+ LDAP_FREE( srvlist );
srvlist = nextsrv;
}
}
-#endif /* LDAP_REFERRALS || LDAP_DNS */
-#ifdef LDAP_REFERRALS
/*
* XXX merging of errors in this routine needs to be improved
*/
int
-chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp )
+ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp )
{
int rc, count, len, newdn;
-#ifdef LDAP_DNS
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
int ldapref;
-#endif /* LDAP_DNS */
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
char *p, *ports, *ref, *tmpref, *refdn, *unfollowed;
LDAPRequest *origreq;
LDAPServer *srv;
BerElement *ber;
- Debug( LDAP_DEBUG_TRACE, "chase_referrals\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n", 0, 0, 0 );
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
*hadrefp = 0;
/* parse out & follow referrals */
for ( ref = p; rc == 0 && ref != NULL; ref = p ) {
-#ifdef LDAP_DNS
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
ldapref = 0;
-#endif /* LDAP_DNS */
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
if (( p = strchr( ref, '\n' )) != NULL ) {
*p++ = '\0';
LDAP_LDAP_REF_STR, LDAP_LDAP_REF_STR_LEN ) == 0 ) {
Debug( LDAP_DEBUG_TRACE,
"chasing LDAP referral: <%s>\n", ref, 0, 0 );
-#ifdef LDAP_DNS
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
ldapref = 1;
-#endif /* LDAP_DNS */
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
tmpref = ref + LDAP_LDAP_REF_STR_LEN;
-#ifdef LDAP_DNS
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
} else if ( len > LDAP_DX_REF_STR_LEN && strncasecmp( ref,
LDAP_DX_REF_STR, LDAP_DX_REF_STR_LEN ) == 0 ) {
Debug( LDAP_DEBUG_TRACE,
"chasing DX referral: <%s>\n", ref, 0, 0 );
tmpref = ref + LDAP_DX_REF_STR_LEN;
-#endif /* LDAP_DNS */
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
} else {
Debug( LDAP_DEBUG_TRACE,
"ignoring unknown referral <%s>\n", ref, 0, 0 );
- rc = append_referral( ld, &unfollowed, ref );
+ rc = ldap_append_referral( ld, &unfollowed, ref );
*hadrefp = 1;
continue;
}
return( -1 );
}
-#ifdef LDAP_DNS
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
if ( ldapref ) {
-#endif /* LDAP_DNS */
- if (( srv = (LDAPServer *)calloc( 1,
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
+ if (( srv = (LDAPServer *)LDAP_CALLOC( 1,
sizeof( LDAPServer ))) == NULL ) {
ber_free( ber, 1 );
ld->ld_errno = LDAP_NO_MEMORY;
return( -1 );
}
- if (( srv->lsrv_host = strdup( tmpref )) == NULL ) {
- free( (char *)srv );
+ if (( srv->lsrv_host = LDAP_STRDUP( tmpref )) == NULL ) {
+ LDAP_FREE( (char *)srv );
ber_free( ber, 1 );
ld->ld_errno = LDAP_NO_MEMORY;
return( -1 );
*ports++ = '\0';
srv->lsrv_port = atoi( ports );
} else {
- srv->lsrv_port = LDAP_PORT;
+ srv->lsrv_port = ldap_int_global_options.ldo_defport;
}
-#ifdef LDAP_DNS
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
} else {
srv = dn2servers( ld, tmpref );
}
-#endif /* LDAP_DNS */
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
- if ( srv != NULL && send_server_request( ld, ber, ld->ld_msgid,
+ if ( srv != NULL && ldap_send_server_request( ld, ber, ld->ld_msgid,
lr, srv, NULL, 1 ) >= 0 ) {
++count;
} else {
Debug( LDAP_DEBUG_ANY,
"Unable to chase referral (%s)\n",
ldap_err2string( ld->ld_errno ), 0, 0 );
- rc = append_referral( ld, &unfollowed, ref );
+ rc = ldap_append_referral( ld, &unfollowed, ref );
}
if ( !newdn && refdn != NULL ) {
- free( refdn );
+ LDAP_FREE( refdn );
}
}
- free( *errstrp );
+ LDAP_FREE( *errstrp );
*errstrp = unfollowed;
return(( rc == 0 ) ? count : rc );
int
-append_referral( LDAP *ld, char **referralsp, char *s )
+ldap_append_referral( LDAP *ld, char **referralsp, char *s )
{
int first;
if ( *referralsp == NULL ) {
first = 1;
- *referralsp = (char *)malloc( strlen( s ) + LDAP_REF_STR_LEN
+ *referralsp = (char *)LDAP_MALLOC( strlen( s ) + LDAP_REF_STR_LEN
+ 1 );
} else {
first = 0;
- *referralsp = (char *)realloc( *referralsp,
+ *referralsp = (char *)LDAP_REALLOC( *referralsp,
strlen( *referralsp ) + strlen( s ) + 2 );
}
static BerElement *
-re_encode_request( LDAP *ld, BerElement *origber, int msgid, char **dnp )
+re_encode_request( LDAP *ld, BerElement *origber, ber_int_t msgid, char **dnp )
{
/*
* XXX this routine knows way too much about how the lber library works!
*/
- unsigned long along, tag;
- long ver;
+ ber_int_t along;
+ ber_len_t len;
+ ber_tag_t tag;
+ ber_int_t ver;
int rc;
BerElement tmpber, *ber;
char *orig_dn;
Debug( LDAP_DEBUG_TRACE,
- "re_encode_request: new msgid %d, new dn <%s>\n",
- msgid, ( *dnp == NULL ) ? "NONE" : *dnp, 0 );
+ "re_encode_request: new msgid %ld, new dn <%s>\n",
+ (long) msgid, ( *dnp == NULL ) ? "NONE" : *dnp, 0 );
tmpber = *origber;
* all LDAP requests are sequences that start with a message id,
* followed by a sequence that is tagged with the operation code
*/
- if ( ber_scanf( &tmpber, "{i", &along ) != LDAP_TAG_MSGID ||
- ( tag = ber_skip_tag( &tmpber, &along )) == LBER_DEFAULT ) {
+ if ( ber_scanf( &tmpber, "{i", /*}*/ &along ) != LDAP_TAG_MSGID ||
+ ( tag = ber_skip_tag( &tmpber, &len )) == LBER_DEFAULT ) {
ld->ld_errno = LDAP_DECODING_ERROR;
return( NULL );
}
- if (( ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
return( NULL );
}
/* bind requests have a version number before the DN & other stuff */
- if ( tag == LDAP_REQ_BIND && ber_get_int( &tmpber, (long *)&ver ) ==
+ if ( tag == LDAP_REQ_BIND && ber_get_int( &tmpber, &ver ) ==
LBER_DEFAULT ) {
ld->ld_errno = LDAP_DECODING_ERROR;
ber_free( ber, 1 );
if ( *dnp == NULL ) {
*dnp = orig_dn;
} else {
- free( orig_dn );
+ LDAP_FREE( orig_dn );
}
if ( tag == LDAP_REQ_BIND ) {
- rc = ber_printf( ber, "{it{is", msgid, tag, ver, *dnp );
+ rc = ber_printf( ber, "{it{is" /*}}*/, msgid, tag, ver, *dnp );
} else {
- rc = ber_printf( ber, "{it{s", msgid, tag, *dnp );
+ rc = ber_printf( ber, "{it{s" /*}}*/, msgid, tag, *dnp );
}
if ( rc == -1 ) {
if ( ber_write( ber, tmpber.ber_ptr, ( tmpber.ber_end -
tmpber.ber_ptr ), 0 ) != ( tmpber.ber_end - tmpber.ber_ptr ) ||
- ber_printf( ber, "}}" ) == -1 ) {
+ ber_printf( ber, /*{{*/ "}}" ) == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
ber_free( ber, 1 );
return( NULL );
if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
Debug( LDAP_DEBUG_ANY, "re_encode_request new request is:\n",
0, 0, 0 );
- ber_dump( ber, 0 );
+ ber_log_dump( LDAP_DEBUG_BER, ldap_debug, ber, 0 );
}
#endif /* LDAP_DEBUG */
LDAPRequest *
-find_request_by_msgid( LDAP *ld, int msgid )
+ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
{
LDAPRequest *lr;
return( lr );
}
-#endif /* LDAP_REFERRALS */
-#ifdef LDAP_DNS
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
static LDAPServer *
-dn2servers( LDAP *ld, char *dn ) /* dn can also be a domain.... */
+dn2servers( LDAP *ld, const char *dn ) /* dn can also be a domain.... */
{
- char *p, *domain, *host, *server_dn, **dxs;
+ char *p, *host, *server_dn, **dxs;
+ const char *domain;
int i, port;
LDAPServer *srvlist, *prevsrv, *srv;
domain = dn;
}
- if (( dxs = getdxbyname( domain )) == NULL ) {
+ if (( dxs = ldap_getdxbyname( domain )) == NULL ) {
ld->ld_errno = LDAP_NO_MEMORY;
return( NULL );
}
srvlist = NULL;
for ( i = 0; dxs[ i ] != NULL; ++i ) {
- port = LDAP_PORT;
+ port = ldap_int_global_options.ldo_defport;
server_dn = NULL;
if ( strchr( dxs[ i ], ':' ) == NULL ) {
host = dxs[ i ];
}
if ( host != NULL ) { /* found a server we can use */
- if (( srv = (LDAPServer *)calloc( 1,
+ if (( srv = (LDAPServer *)LDAP_CALLOC( 1,
sizeof( LDAPServer ))) == NULL ) {
free_servers( srvlist );
srvlist = NULL;
prevsrv = srv;
/* copy in info. */
- if (( srv->lsrv_host = strdup( host )) == NULL ||
+ if (( srv->lsrv_host = LDAP_STRDUP( host )) == NULL ||
( server_dn != NULL && ( srv->lsrv_dn =
- strdup( server_dn )) == NULL )) {
+ LDAP_STRDUP( server_dn )) == NULL )) {
free_servers( srvlist );
srvlist = NULL;
break; /* exit loop & return */
return( srvlist );
}
-#endif /* LDAP_DNS */
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
--- /dev/null
+/*
+ * Copyright 1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * schema.c: parsing routines used by servers and clients to process
+ * schema definitions
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+#include <ldap_schema.h>
+
+
+static LDAP_CONST char *
+choose_name( char *names[], LDAP_CONST char *fallback )
+{
+ return( (names != NULL && names[0] != NULL) ? names[0] : fallback );
+}
+
+LDAP_CONST char *
+ldap_syntax2name( LDAP_SYNTAX * syn )
+{
+ return( syn->syn_oid );
+}
+
+LDAP_CONST char *
+ldap_matchingrule2name( LDAP_MATCHING_RULE * mr )
+{
+ return( choose_name( mr->mr_names, mr->mr_oid ) );
+}
+
+LDAP_CONST char *
+ldap_attributetype2name( LDAP_ATTRIBUTE_TYPE * at )
+{
+ return( choose_name( at->at_names, at->at_oid ) );
+}
+
+LDAP_CONST char *
+ldap_objectclass2name( LDAP_OBJECT_CLASS * oc )
+{
+ return( choose_name( oc->oc_names, oc->oc_oid ) );
+}
+
+
+/*
+ * When pretty printing the entities we will be appending to a buffer.
+ * Since checking for overflow, realloc'ing and checking if no error
+ * is extremely boring, we will use a protection layer that will let
+ * us blissfully ignore the error until the end. This layer is
+ * implemented with the help of the next type.
+ */
+
+typedef struct safe_string {
+ char * val;
+ ber_len_t size;
+ ber_len_t pos;
+ int at_whsp;
+} safe_string;
+
+static safe_string *
+new_safe_string(int size)
+{
+ safe_string * ss;
+
+ ss = LDAP_MALLOC(sizeof(safe_string));
+ if ( !ss )
+ return(NULL);
+
+ ss->val = LDAP_MALLOC(size);
+ if ( !ss->val ) {
+ LDAP_FREE(ss);
+ return(NULL);
+ }
+
+ ss->size = size;
+ ss->pos = 0;
+ ss->at_whsp = 0;
+
+ return ss;
+}
+
+static void
+safe_string_free(safe_string * ss)
+{
+ if ( !ss )
+ return;
+ LDAP_FREE(ss->val);
+ LDAP_FREE(ss);
+}
+
+static char *
+safe_string_val(safe_string * ss)
+{
+ ss->val[ss->pos] = '\0';
+ return(ss->val);
+}
+
+static int
+append_to_safe_string(safe_string * ss, char * s)
+{
+ int l = strlen(s);
+ char * temp;
+
+ /*
+ * Some runaway process is trying to append to a string that
+ * overflowed and we could not extend.
+ */
+ if ( !ss->val )
+ return -1;
+
+ /* We always make sure there is at least one position available */
+ if ( ss->pos + l >= ss->size-1 ) {
+ ss->size *= 2;
+ temp = LDAP_REALLOC(ss->val, ss->size);
+ if ( !temp ) {
+ /* Trouble, out of memory */
+ LDAP_FREE(ss->val);
+ return -1;
+ }
+ ss->val = temp;
+ }
+ strncpy(&ss->val[ss->pos], s, l);
+ ss->pos += l;
+ if ( ss->pos > 0 && isspace(ss->val[ss->pos-1]) )
+ ss->at_whsp = 1;
+ else
+ ss->at_whsp = 0;
+
+ return 0;
+}
+
+static int
+print_literal(safe_string *ss, char *s)
+{
+ return(append_to_safe_string(ss,s));
+}
+
+static int
+print_whsp(safe_string *ss)
+{
+ if ( ss->at_whsp )
+ return(append_to_safe_string(ss,""));
+ else
+ return(append_to_safe_string(ss," "));
+}
+
+static int
+print_numericoid(safe_string *ss, char *s)
+{
+ if ( s )
+ return(append_to_safe_string(ss,s));
+ else
+ return(append_to_safe_string(ss,""));
+}
+
+/* This one is identical to print_qdescr */
+static int
+print_qdstring(safe_string *ss, char *s)
+{
+ print_whsp(ss);
+ print_literal(ss,"'");
+ append_to_safe_string(ss,s);
+ print_literal(ss,"'");
+ return(print_whsp(ss));
+}
+
+static int
+print_qdescr(safe_string *ss, char *s)
+{
+ print_whsp(ss);
+ print_literal(ss,"'");
+ append_to_safe_string(ss,s);
+ print_literal(ss,"'");
+ return(print_whsp(ss));
+}
+
+static int
+print_qdescrlist(safe_string *ss, char **sa)
+{
+ char **sp;
+ int ret = 0;
+
+ for (sp=sa; *sp; sp++) {
+ ret = print_qdescr(ss,*sp);
+ }
+ /* If the list was empty, we return zero that is potentially
+ * incorrect, but since we will be still appending things, the
+ * overflow will be detected later. Maybe FIX.
+ */
+ return(ret);
+}
+
+static int
+print_qdescrs(safe_string *ss, char **sa)
+{
+ /* The only way to represent an empty list is as a qdescrlist
+ * so, if the list is empty we treat it as a long list.
+ * Really, this is what the syntax mandates. We should not
+ * be here if the list was empty, but if it happens, a label
+ * has already been output and we cannot undo it.
+ */
+ if ( !sa[0] || ( sa[0] && sa[1] ) ) {
+ print_whsp(ss);
+ print_literal(ss,"(");
+ print_qdescrlist(ss,sa);
+ print_literal(ss,")");
+ return(print_whsp(ss));
+ } else {
+ return(print_qdescr(ss,*sa));
+ }
+}
+
+static int
+print_woid(safe_string *ss, char *s)
+{
+ print_whsp(ss);
+ append_to_safe_string(ss,s);
+ return print_whsp(ss);
+}
+
+static int
+print_oidlist(safe_string *ss, char **sa)
+{
+ char **sp;
+
+ for (sp=sa; *(sp+1); sp++) {
+ print_woid(ss,*sp);
+ print_literal(ss,"$");
+ }
+ return(print_woid(ss,*sp));
+}
+
+static int
+print_oids(safe_string *ss, char **sa)
+{
+ if ( sa[0] && sa[1] ) {
+ print_literal(ss,"(");
+ print_oidlist(ss,sa);
+ print_whsp(ss);
+ return(print_literal(ss,")"));
+ } else {
+ return(print_woid(ss,*sa));
+ }
+}
+
+static int
+print_noidlen(safe_string *ss, char *s, int l)
+{
+ char buf[64];
+ int ret;
+
+ ret = print_numericoid(ss,s);
+ if ( l ) {
+ sprintf(buf,"{%d}",l);
+ ret = print_literal(ss,buf);
+ }
+ return(ret);
+}
+
+char *
+ldap_syntax2str( const LDAP_SYNTAX * syn )
+{
+ safe_string * ss;
+ char * retstring;
+
+ ss = new_safe_string(256);
+ if ( !ss )
+ return NULL;
+
+ print_literal(ss,"(");
+ print_whsp(ss);
+
+ print_numericoid(ss, syn->syn_oid);
+ print_whsp(ss);
+
+ if ( syn->syn_desc ) {
+ print_literal(ss,"DESC");
+ print_qdstring(ss,syn->syn_desc);
+ }
+
+ print_whsp(ss);
+ print_literal(ss,")");
+
+ retstring = LDAP_STRDUP(safe_string_val(ss));
+ safe_string_free(ss);
+ return(retstring);
+}
+
+char *
+ldap_matchingrule2str( const LDAP_MATCHING_RULE * mr )
+{
+ safe_string * ss;
+ char * retstring;
+
+ ss = new_safe_string(256);
+ if ( !ss )
+ return NULL;
+
+ print_literal(ss,"(");
+ print_whsp(ss);
+
+ print_numericoid(ss, mr->mr_oid);
+ print_whsp(ss);
+
+ if ( mr->mr_names ) {
+ print_literal(ss,"NAME");
+ print_qdescrs(ss,mr->mr_names);
+ }
+
+ if ( mr->mr_desc ) {
+ print_literal(ss,"DESC");
+ print_qdstring(ss,mr->mr_desc);
+ }
+
+ if ( mr->mr_obsolete == LDAP_SCHEMA_YES ) {
+ print_literal(ss, "OBSOLETE");
+ print_whsp(ss);
+ }
+
+ if ( mr->mr_syntax_oid ) {
+ print_literal(ss,"SYNTAX");
+ print_whsp(ss);
+ print_literal(ss, mr->mr_syntax_oid);
+ print_whsp(ss);
+ }
+
+ print_whsp(ss);
+ print_literal(ss,")");
+
+ retstring = LDAP_STRDUP(safe_string_val(ss));
+ safe_string_free(ss);
+ return(retstring);
+}
+
+char *
+ldap_objectclass2str( const LDAP_OBJECT_CLASS * oc )
+{
+ safe_string * ss;
+ char * retstring;
+
+ ss = new_safe_string(256);
+ if ( !ss )
+ return NULL;
+
+ print_literal(ss,"(");
+ print_whsp(ss);
+
+ print_numericoid(ss, oc->oc_oid);
+ print_whsp(ss);
+
+ if ( oc->oc_names ) {
+ print_literal(ss,"NAME");
+ print_qdescrs(ss,oc->oc_names);
+ }
+
+ if ( oc->oc_desc ) {
+ print_literal(ss,"DESC");
+ print_qdstring(ss,oc->oc_desc);
+ }
+
+ if ( oc->oc_obsolete == LDAP_SCHEMA_YES ) {
+ print_literal(ss, "OBSOLETE");
+ print_whsp(ss);
+ }
+
+ if ( oc->oc_sup_oids ) {
+ print_literal(ss,"SUP");
+ print_whsp(ss);
+ print_oids(ss,oc->oc_sup_oids);
+ print_whsp(ss);
+ }
+
+ switch (oc->oc_kind) {
+ case LDAP_SCHEMA_ABSTRACT:
+ print_literal(ss,"ABSTRACT");
+ break;
+ case LDAP_SCHEMA_STRUCTURAL:
+ print_literal(ss,"STRUCTURAL");
+ break;
+ case LDAP_SCHEMA_AUXILIARY:
+ print_literal(ss,"AUXILIARY");
+ break;
+ default:
+ print_literal(ss,"KIND-UNKNOWN");
+ break;
+ }
+ print_whsp(ss);
+
+ if ( oc->oc_at_oids_must ) {
+ print_literal(ss,"MUST");
+ print_whsp(ss);
+ print_oids(ss,oc->oc_at_oids_must);
+ print_whsp(ss);
+ }
+
+ if ( oc->oc_at_oids_may ) {
+ print_literal(ss,"MAY");
+ print_whsp(ss);
+ print_oids(ss,oc->oc_at_oids_may);
+ print_whsp(ss);
+ }
+
+ print_whsp(ss);
+ print_literal(ss,")");
+
+ retstring = LDAP_STRDUP(safe_string_val(ss));
+ safe_string_free(ss);
+ return(retstring);
+}
+
+char *
+ldap_attributetype2str( const LDAP_ATTRIBUTE_TYPE * at )
+{
+ safe_string * ss;
+ char * retstring;
+
+ ss = new_safe_string(256);
+ if ( !ss )
+ return NULL;
+
+ print_literal(ss,"(");
+ print_whsp(ss);
+
+ print_numericoid(ss, at->at_oid);
+ print_whsp(ss);
+
+ if ( at->at_names ) {
+ print_literal(ss,"NAME");
+ print_qdescrs(ss,at->at_names);
+ }
+
+ if ( at->at_desc ) {
+ print_literal(ss,"DESC");
+ print_qdstring(ss,at->at_desc);
+ }
+
+ if ( at->at_obsolete == LDAP_SCHEMA_YES ) {
+ print_literal(ss, "OBSOLETE");
+ print_whsp(ss);
+ }
+
+ if ( at->at_sup_oid ) {
+ print_literal(ss,"SUP");
+ print_woid(ss,at->at_sup_oid);
+ }
+
+ if ( at->at_equality_oid ) {
+ print_literal(ss,"EQUALITY");
+ print_woid(ss,at->at_equality_oid);
+ }
+
+ if ( at->at_ordering_oid ) {
+ print_literal(ss,"ORDERING");
+ print_woid(ss,at->at_ordering_oid);
+ }
+
+ if ( at->at_substr_oid ) {
+ print_literal(ss,"SUBSTR");
+ print_woid(ss,at->at_substr_oid);
+ }
+
+ if ( at->at_syntax_oid ) {
+ print_literal(ss,"SYNTAX");
+ print_whsp(ss);
+ print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len);
+ print_whsp(ss);
+ }
+
+ if ( at->at_single_value == LDAP_SCHEMA_YES ) {
+ print_literal(ss,"SINGLE-VALUE");
+ print_whsp(ss);
+ }
+
+ if ( at->at_collective == LDAP_SCHEMA_YES ) {
+ print_literal(ss,"COLLECTIVE");
+ print_whsp(ss);
+ }
+
+ if ( at->at_no_user_mod == LDAP_SCHEMA_YES ) {
+ print_literal(ss,"NO-USER-MODIFICATION");
+ print_whsp(ss);
+ }
+
+ if ( at->at_usage != LDAP_SCHEMA_USER_APPLICATIONS ) {
+ print_literal(ss,"USAGE");
+ print_whsp(ss);
+ switch (at->at_usage) {
+ case LDAP_SCHEMA_DIRECTORY_OPERATION:
+ print_literal(ss,"directoryOperation");
+ break;
+ case LDAP_SCHEMA_DISTRIBUTED_OPERATION:
+ print_literal(ss,"distributedOperation");
+ break;
+ case LDAP_SCHEMA_DSA_OPERATION:
+ print_literal(ss,"dSAOperation");
+ break;
+ default:
+ print_literal(ss,"UNKNOWN");
+ break;
+ }
+ }
+
+ print_whsp(ss);
+ print_literal(ss,")");
+
+ retstring = LDAP_STRDUP(safe_string_val(ss));
+ safe_string_free(ss);
+ return(retstring);
+}
+
+/*
+ * Now come the parsers. There is one parser for each entity type:
+ * objectclasses, attributetypes, etc.
+ *
+ * Each of them is written as a recursive-descent parser, except that
+ * none of them is really recursive. But the idea is kept: there
+ * is one routine per non-terminal that eithers gobbles lexical tokens
+ * or calls lower-level routines, etc.
+ *
+ * The scanner is implemented in the routine get_token. Actually,
+ * get_token is more than a scanner and will return tokens that are
+ * in fact non-terminals in the grammar. So you can see the whole
+ * approach as the combination of a low-level bottom-up recognizer
+ * combined with a scanner and a number of top-down parsers. Or just
+ * consider that the real grammars recognized by the parsers are not
+ * those of the standards. As a matter of fact, our parsers are more
+ * liberal than the spec when there is no ambiguity.
+ *
+ * The difference is pretty academic (modulo bugs or incorrect
+ * interpretation of the specs).
+ */
+
+#define TK_NOENDQUOTE -2
+#define TK_OUTOFMEM -1
+#define TK_EOS 0
+#define TK_UNEXPCHAR 1
+#define TK_BAREWORD 2
+#define TK_QDSTRING 3
+#define TK_LEFTPAREN 4
+#define TK_RIGHTPAREN 5
+#define TK_DOLLAR 6
+#define TK_QDESCR TK_QDSTRING
+
+struct token {
+ int type;
+ char *sval;
+};
+
+static int
+get_token(const char ** sp, char ** token_val)
+{
+ int kind;
+ const char * p;
+ const char * q;
+ char * res;
+
+ *token_val = NULL;
+ switch (**sp) {
+ case '\0':
+ kind = TK_EOS;
+ (*sp)++;
+ break;
+ case '(':
+ kind = TK_LEFTPAREN;
+ (*sp)++;
+ break;
+ case ')':
+ kind = TK_RIGHTPAREN;
+ (*sp)++;
+ break;
+ case '$':
+ kind = TK_DOLLAR;
+ (*sp)++;
+ break;
+ case '\'':
+ kind = TK_QDSTRING;
+ (*sp)++;
+ p = *sp;
+ while ( **sp != '\'' && **sp != '\0' )
+ (*sp)++;
+ if ( **sp == '\'' ) {
+ q = *sp;
+ res = LDAP_MALLOC(q-p+1);
+ if ( !res ) {
+ kind = TK_OUTOFMEM;
+ } else {
+ strncpy(res,p,q-p);
+ res[q-p] = '\0';
+ *token_val = res;
+ }
+ (*sp)++;
+ } else {
+ kind = TK_NOENDQUOTE;
+ }
+ break;
+ default:
+ kind = TK_BAREWORD;
+ p = *sp;
+ while ( !isspace(**sp) &&
+ **sp != '(' &&
+ **sp != ')' &&
+ **sp != '$' &&
+ **sp != '\'' &&
+ **sp != '\0' )
+ (*sp)++;
+ q = *sp;
+ res = LDAP_MALLOC(q-p+1);
+ if ( !res ) {
+ kind = TK_OUTOFMEM;
+ } else {
+ strncpy(res,p,q-p);
+ res[q-p] = '\0';
+ *token_val = res;
+ }
+ break;
+/* kind = TK_UNEXPCHAR; */
+/* break; */
+ }
+
+ return kind;
+}
+
+/* Gobble optional whitespace */
+static void
+parse_whsp(const char **sp)
+{
+ while (isspace(**sp))
+ (*sp)++;
+}
+
+/* TBC:!!
+ * General note for all parsers: to guarantee the algorithm halts they
+ * must always advance the pointer even when an error is found. For
+ * this one is not that important since an error here is fatal at the
+ * upper layers, but it is a simple strategy that will not get in
+ * endless loops.
+ */
+
+/* Parse a sequence of dot-separated decimal strings */
+static char *
+parse_numericoid(const char **sp, int *code, const int allow_quoted)
+{
+ char * res;
+ const char * start = *sp;
+ int len;
+ int quoted = 0;
+
+ /* Netscape puts the SYNTAX value in quotes (incorrectly) */
+ if ( allow_quoted && **sp == '\'' ) {
+ quoted = 1;
+ (*sp)++;
+ start++;
+ }
+ /* Each iteration of this loop gets one decimal string */
+ while (**sp) {
+ if ( !isdigit(**sp) ) {
+ /*
+ * Initial char is not a digit or char after dot is
+ * not a digit
+ */
+ *code = LDAP_SCHERR_NODIGIT;
+ return NULL;
+ }
+ (*sp)++;
+ while ( isdigit(**sp) )
+ (*sp)++;
+ if ( **sp != '.' )
+ break;
+ /* Otherwise, gobble the dot and loop again */
+ (*sp)++;
+ }
+ /* Now *sp points at the char past the numericoid. Perfect. */
+ len = *sp - start;
+ res = LDAP_MALLOC(len+1);
+ if (!res) {
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return(NULL);
+ }
+ strncpy(res,start,len);
+ res[len] = '\0';
+ if ( allow_quoted && quoted ) {
+ if ( **sp == '\'' ) {
+ (*sp)++;
+ } else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ LDAP_FREE(res);
+ return NULL;
+ }
+ }
+ return(res);
+}
+
+/* Parse a qdescr or a list of them enclosed in () */
+static char **
+parse_qdescrs(const char **sp, int *code)
+{
+ char ** res;
+ char ** res1;
+ int kind;
+ char * sval;
+ int size;
+ int pos;
+
+ parse_whsp(sp);
+ kind = get_token(sp,&sval);
+ if ( kind == TK_LEFTPAREN ) {
+ /* Let's presume there will be at least 2 entries */
+ size = 3;
+ res = LDAP_CALLOC(3,sizeof(char *));
+ if ( !res ) {
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return NULL;
+ }
+ pos = 0;
+ while (1) {
+ parse_whsp(sp);
+ kind = get_token(sp,&sval);
+ if ( kind == TK_RIGHTPAREN )
+ break;
+ if ( kind == TK_QDESCR ) {
+ if ( pos == size-2 ) {
+ size++;
+ res1 = LDAP_REALLOC(res,size*sizeof(char *));
+ if ( !res1 ) {
+ LDAP_VFREE(res);
+ LDAP_FREE(sval);
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return(NULL);
+ }
+ res = res1;
+ }
+ res[pos] = sval;
+ pos++;
+ parse_whsp(sp);
+ } else {
+ LDAP_VFREE(res);
+ LDAP_FREE(sval);
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ return(NULL);
+ }
+ }
+ res[pos] = NULL;
+ parse_whsp(sp);
+ return(res);
+ } else if ( kind == TK_QDESCR ) {
+ res = LDAP_CALLOC(2,sizeof(char *));
+ if ( !res ) {
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return NULL;
+ }
+ res[0] = sval;
+ res[1] = NULL;
+ parse_whsp(sp);
+ return res;
+ } else {
+ LDAP_FREE(sval);
+ *code = LDAP_SCHERR_BADNAME;
+ return NULL;
+ }
+}
+
+/* Parse a woid */
+static char *
+parse_woid(const char **sp, int *code)
+{
+ char * sval;
+ int kind;
+
+ parse_whsp(sp);
+ kind = get_token(sp, &sval);
+ if ( kind != TK_BAREWORD ) {
+ LDAP_FREE(sval);
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ return NULL;
+ }
+ parse_whsp(sp);
+ return sval;
+}
+
+/* Parse a noidlen */
+static char *
+parse_noidlen(const char **sp, int *code, int *len, int allow_quoted)
+{
+ char * sval;
+ int quoted = 0;
+
+ *len = 0;
+ /* Netscape puts the SYNTAX value in quotes (incorrectly) */
+ if ( allow_quoted && **sp == '\'' ) {
+ quoted = 1;
+ (*sp)++;
+ }
+ sval = parse_numericoid(sp, code, 0);
+ if ( !sval ) {
+ return NULL;
+ }
+ if ( **sp == '{' ) {
+ (*sp)++;
+ *len = atoi(*sp);
+ while ( isdigit(**sp) )
+ (*sp)++;
+ if ( **sp != '}' ) {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ LDAP_FREE(sval);
+ return NULL;
+ }
+ (*sp)++;
+ }
+ if ( allow_quoted && quoted ) {
+ if ( **sp == '\'' ) {
+ (*sp)++;
+ } else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ LDAP_FREE(sval);
+ return NULL;
+ }
+ }
+ return sval;
+}
+
+/*
+ * Next routine will accept a qdstring in place of an oid if
+ * allow_quoted is set. This is necessary to interoperate with
+ * Netscape Directory server that will improperly quote each oid (at
+ * least those of the descr kind) in the SUP clause.
+ */
+
+/* Parse a woid or a $-separated list of them enclosed in () */
+static char **
+parse_oids(const char **sp, int *code, const int allow_quoted)
+{
+ char ** res;
+ char ** res1;
+ int kind;
+ char * sval;
+ int size;
+ int pos;
+
+ /*
+ * Strictly speaking, doing this here accepts whsp before the
+ * ( at the begining of an oidlist, but this is harmless. Also,
+ * we are very liberal in what we accept as an OID. Maybe
+ * refine later.
+ */
+ parse_whsp(sp);
+ kind = get_token(sp,&sval);
+ if ( kind == TK_LEFTPAREN ) {
+ /* Let's presume there will be at least 2 entries */
+ size = 3;
+ res = LDAP_CALLOC(3,sizeof(char *));
+ if ( !res ) {
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return NULL;
+ }
+ pos = 0;
+ parse_whsp(sp);
+ kind = get_token(sp,&sval);
+ if ( kind == TK_BAREWORD ||
+ ( allow_quoted && kind == TK_QDSTRING ) ) {
+ res[pos] = sval;
+ pos++;
+ } else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ LDAP_FREE(sval);
+ LDAP_VFREE(res);
+ return NULL;
+ }
+ parse_whsp(sp);
+ while (1) {
+ kind = get_token(sp,&sval);
+ if ( kind == TK_RIGHTPAREN )
+ break;
+ if ( kind == TK_DOLLAR ) {
+ parse_whsp(sp);
+ kind = get_token(sp,&sval);
+ if ( kind == TK_BAREWORD ||
+ ( allow_quoted &&
+ kind == TK_QDSTRING ) ) {
+ if ( pos == size-2 ) {
+ size++;
+ res1 = LDAP_REALLOC(res,size*sizeof(char *));
+ if ( !res1 ) {
+ LDAP_FREE(sval);
+ LDAP_VFREE(res);
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return(NULL);
+ }
+ res = res1;
+ }
+ res[pos] = sval;
+ pos++;
+ } else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ LDAP_FREE(sval);
+ LDAP_VFREE(res);
+ return NULL;
+ }
+ parse_whsp(sp);
+ } else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ LDAP_FREE(sval);
+ LDAP_VFREE(res);
+ return NULL;
+ }
+ }
+ res[pos] = NULL;
+ parse_whsp(sp);
+ return(res);
+ } else if ( kind == TK_BAREWORD ||
+ ( allow_quoted && kind == TK_QDSTRING ) ) {
+ res = LDAP_CALLOC(2,sizeof(char *));
+ if ( !res ) {
+ LDAP_FREE(sval);
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return NULL;
+ }
+ res[0] = sval;
+ res[1] = NULL;
+ parse_whsp(sp);
+ return res;
+ } else {
+ LDAP_FREE(sval);
+ *code = LDAP_SCHERR_BADNAME;
+ return NULL;
+ }
+}
+
+void
+ldap_syntax_free( LDAP_SYNTAX * syn )
+{
+ LDAP_FREE(syn->syn_oid);
+ LDAP_FREE(syn->syn_desc);
+ LDAP_FREE(syn);
+}
+
+LDAP_SYNTAX *
+ldap_str2syntax( const char * s, int * code, const char ** errp )
+{
+ int kind;
+ const char * ss = s;
+ char * sval;
+ int seen_desc = 0;
+ LDAP_SYNTAX * syn;
+ char ** ssdummy;
+
+ if ( !s ) {
+ *code = LDAP_SCHERR_EMPTY;
+ *errp = "";
+ return NULL;
+ }
+
+ *errp = s;
+ syn = LDAP_CALLOC(1,sizeof(LDAP_SYNTAX));
+
+ if ( !syn ) {
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return NULL;
+ }
+
+ kind = get_token(&ss,&sval);
+ if ( kind != TK_LEFTPAREN ) {
+ LDAP_FREE(sval);
+ *code = LDAP_SCHERR_NOLEFTPAREN;
+ ldap_syntax_free(syn);
+ return NULL;
+ }
+
+ parse_whsp(&ss);
+ syn->syn_oid = parse_numericoid(&ss,code,0);
+ if ( !syn->syn_oid ) {
+ *errp = ss;
+ ldap_syntax_free(syn);
+ return NULL;
+ }
+ parse_whsp(&ss);
+
+ /*
+ * Beyond this point we will be liberal and accept the items
+ * in any order.
+ */
+ while (1) {
+ kind = get_token(&ss,&sval);
+ switch (kind) {
+ case TK_EOS:
+ *code = LDAP_SCHERR_NORIGHTPAREN;
+ *errp = ss;
+ ldap_syntax_free(syn);
+ return NULL;
+ case TK_RIGHTPAREN:
+ return syn;
+ case TK_BAREWORD:
+ if ( !strcmp(sval,"DESC") ) {
+ LDAP_FREE(sval);
+ if ( seen_desc ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_syntax_free(syn);
+ return(NULL);
+ }
+ seen_desc = 1;
+ parse_whsp(&ss);
+ kind = get_token(&ss,&sval);
+ if ( kind != TK_QDSTRING ) {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_syntax_free(syn);
+ return NULL;
+ }
+ syn->syn_desc = sval;
+ parse_whsp(&ss);
+ } else if ( sval[0] == 'X' && sval[1] == '-' ) {
+ LDAP_FREE(sval);
+ /* Should be parse_qdstrings */
+ ssdummy = parse_qdescrs(&ss, code);
+ if ( !ssdummy ) {
+ *errp = ss;
+ ldap_syntax_free(syn);
+ return NULL;
+ }
+ } else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_syntax_free(syn);
+ return NULL;
+ }
+ break;
+ default:
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_syntax_free(syn);
+ return NULL;
+ }
+ }
+}
+
+void
+ldap_matchingrule_free( LDAP_MATCHING_RULE * mr )
+{
+ LDAP_FREE(mr->mr_oid);
+ LDAP_VFREE(mr->mr_names);
+ LDAP_FREE(mr->mr_desc);
+ LDAP_FREE(mr->mr_syntax_oid);
+ LDAP_FREE(mr);
+}
+
+LDAP_MATCHING_RULE *
+ldap_str2matchingrule( const char * s, int * code, const char ** errp )
+{
+ int kind;
+ const char * ss = s;
+ char * sval;
+ int be_liberal = 1; /* Future additional argument */
+ int seen_name = 0;
+ int seen_desc = 0;
+ int seen_obsolete = 0;
+ int seen_syntax = 0;
+ LDAP_MATCHING_RULE * mr;
+ char ** ssdummy;
+ const char * savepos;
+
+ if ( !s ) {
+ *code = LDAP_SCHERR_EMPTY;
+ *errp = "";
+ return NULL;
+ }
+
+ *errp = s;
+ mr = LDAP_CALLOC(1,sizeof(LDAP_MATCHING_RULE));
+
+ if ( !mr ) {
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return NULL;
+ }
+
+ kind = get_token(&ss,&sval);
+ if ( kind != TK_LEFTPAREN ) {
+ *code = LDAP_SCHERR_NOLEFTPAREN;
+ LDAP_FREE(sval);
+ ldap_matchingrule_free(mr);
+ return NULL;
+ }
+
+ parse_whsp(&ss);
+ savepos = ss;
+ mr->mr_oid = parse_numericoid(&ss,code,be_liberal);
+ if ( !mr->mr_oid ) {
+ if ( be_liberal ) {
+ /* Backtracking */
+ ss = savepos;
+ kind = get_token(&ss,&sval);
+ if ( kind == TK_BAREWORD ) {
+ if ( !strcmp(sval, "NAME") ||
+ !strcmp(sval, "DESC") ||
+ !strcmp(sval, "OBSOLETE") ||
+ !strcmp(sval, "SYNTAX") ||
+ !strncmp(sval, "X-", 2) ) {
+ /* Missing OID, backtrack */
+ ss = savepos;
+ } else {
+ /* Non-numerical OID, ignore */
+ }
+ }
+ LDAP_FREE(sval);
+ } else {
+ *errp = ss;
+ ldap_matchingrule_free(mr);
+ return NULL;
+ }
+ }
+ parse_whsp(&ss);
+
+ /*
+ * Beyond this point we will be liberal and accept the items
+ * in any order.
+ */
+ while (1) {
+ kind = get_token(&ss,&sval);
+ switch (kind) {
+ case TK_EOS:
+ *code = LDAP_SCHERR_NORIGHTPAREN;
+ *errp = ss;
+ ldap_matchingrule_free(mr);
+ return NULL;
+ case TK_RIGHTPAREN:
+ return mr;
+ case TK_BAREWORD:
+ if ( !strcmp(sval,"NAME") ) {
+ LDAP_FREE(sval);
+ if ( seen_name ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_matchingrule_free(mr);
+ return(NULL);
+ }
+ seen_name = 1;
+ mr->mr_names = parse_qdescrs(&ss,code);
+ if ( !mr->mr_names ) {
+ if ( *code != LDAP_SCHERR_OUTOFMEM )
+ *code = LDAP_SCHERR_BADNAME;
+ *errp = ss;
+ ldap_matchingrule_free(mr);
+ return NULL;
+ }
+ } else if ( !strcmp(sval,"DESC") ) {
+ LDAP_FREE(sval);
+ if ( seen_desc ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_matchingrule_free(mr);
+ return(NULL);
+ }
+ seen_desc = 1;
+ parse_whsp(&ss);
+ kind = get_token(&ss,&sval);
+ if ( kind != TK_QDSTRING ) {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_matchingrule_free(mr);
+ return NULL;
+ }
+ mr->mr_desc = sval;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"OBSOLETE") ) {
+ LDAP_FREE(sval);
+ if ( seen_obsolete ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_matchingrule_free(mr);
+ return(NULL);
+ }
+ seen_obsolete = 1;
+ mr->mr_obsolete = LDAP_SCHEMA_YES;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"SYNTAX") ) {
+ LDAP_FREE(sval);
+ if ( seen_syntax ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_matchingrule_free(mr);
+ return(NULL);
+ }
+ seen_syntax = 1;
+ parse_whsp(&ss);
+ mr->mr_syntax_oid =
+ parse_numericoid(&ss,code,be_liberal);
+ if ( !mr->mr_syntax_oid ) {
+ *errp = ss;
+ ldap_matchingrule_free(mr);
+ return NULL;
+ }
+ parse_whsp(&ss);
+ } else if ( sval[0] == 'X' && sval[1] == '-' ) {
+ LDAP_FREE(sval);
+ /* Should be parse_qdstrings */
+ ssdummy = parse_qdescrs(&ss, code);
+ if ( !ssdummy ) {
+ *errp = ss;
+ ldap_matchingrule_free(mr);
+ return NULL;
+ }
+ } else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_matchingrule_free(mr);
+ return NULL;
+ }
+ break;
+ default:
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_matchingrule_free(mr);
+ return NULL;
+ }
+ }
+}
+
+void
+ldap_attributetype_free(LDAP_ATTRIBUTE_TYPE * at)
+{
+ LDAP_FREE(at->at_oid);
+ LDAP_VFREE(at->at_names);
+ LDAP_FREE(at->at_desc);
+ LDAP_FREE(at->at_sup_oid);
+ LDAP_FREE(at->at_equality_oid);
+ LDAP_FREE(at->at_ordering_oid);
+ LDAP_FREE(at->at_substr_oid);
+ LDAP_FREE(at->at_syntax_oid);
+ LDAP_FREE(at);
+}
+
+LDAP_ATTRIBUTE_TYPE *
+ldap_str2attributetype( const char * s, int * code, const char ** errp )
+{
+ int kind;
+ const char * ss = s;
+ char * sval;
+ int be_liberal = 1; /* Future additional argument */
+ int seen_name = 0;
+ int seen_desc = 0;
+ int seen_obsolete = 0;
+ int seen_sup = 0;
+ int seen_equality = 0;
+ int seen_ordering = 0;
+ int seen_substr = 0;
+ int seen_syntax = 0;
+ int seen_usage = 0;
+ int seen_kind = 0;
+ int seen_must = 0;
+ int seen_may = 0;
+ LDAP_ATTRIBUTE_TYPE * at;
+ char ** ssdummy;
+ const char * savepos;
+
+ if ( !s ) {
+ *code = LDAP_SCHERR_EMPTY;
+ *errp = "";
+ return NULL;
+ }
+
+ *errp = s;
+ at = LDAP_CALLOC(1,sizeof(LDAP_ATTRIBUTE_TYPE));
+
+ if ( !at ) {
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return NULL;
+ }
+
+ kind = get_token(&ss,&sval);
+ if ( kind != TK_LEFTPAREN ) {
+ *code = LDAP_SCHERR_NOLEFTPAREN;
+ LDAP_FREE(sval);
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+
+ /*
+ * Definitions MUST begin with an OID in the numericoid format.
+ * However, this routine is used by clients to parse the response
+ * from servers and very well known servers will provide an OID
+ * in the wrong format or even no OID at all. We do our best to
+ * extract info from those servers.
+ */
+ parse_whsp(&ss);
+ savepos = ss;
+ at->at_oid = parse_numericoid(&ss,code,0);
+ if ( !at->at_oid ) {
+ if ( be_liberal ) {
+ /* Backtracking */
+ ss = savepos;
+ kind = get_token(&ss,&sval);
+ if ( kind == TK_BAREWORD ) {
+ if ( !strcmp(sval, "NAME") ||
+ !strcmp(sval, "DESC") ||
+ !strcmp(sval, "OBSOLETE") ||
+ !strcmp(sval, "SUP") ||
+ !strcmp(sval, "EQUALITY") ||
+ !strcmp(sval, "ORDERING") ||
+ !strcmp(sval, "SUBSTR") ||
+ !strcmp(sval, "SYNTAX") ||
+ !strcmp(sval, "SINGLE-VALUE") ||
+ !strcmp(sval, "COLLECTIVE") ||
+ !strcmp(sval, "NO-USER-MODIFICATION") ||
+ !strcmp(sval, "USAGE") ||
+ !strncmp(sval, "X-", 2) ) {
+ /* Missing OID, backtrack */
+ ss = savepos;
+ } else {
+ /* Non-numerical OID, ignore */
+ }
+ }
+ LDAP_FREE(sval);
+ } else {
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ }
+ parse_whsp(&ss);
+
+ /*
+ * Beyond this point we will be liberal and accept the items
+ * in any order.
+ */
+ while (1) {
+ kind = get_token(&ss,&sval);
+ switch (kind) {
+ case TK_EOS:
+ *code = LDAP_SCHERR_NORIGHTPAREN;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return NULL;
+ case TK_RIGHTPAREN:
+ return at;
+ case TK_BAREWORD:
+ if ( !strcmp(sval,"NAME") ) {
+ LDAP_FREE(sval);
+ if ( seen_name ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ seen_name = 1;
+ at->at_names = parse_qdescrs(&ss,code);
+ if ( !at->at_names ) {
+ if ( *code != LDAP_SCHERR_OUTOFMEM )
+ *code = LDAP_SCHERR_BADNAME;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ } else if ( !strcmp(sval,"DESC") ) {
+ LDAP_FREE(sval);
+ if ( seen_desc ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ seen_desc = 1;
+ parse_whsp(&ss);
+ kind = get_token(&ss,&sval);
+ if ( kind != TK_QDSTRING ) {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ at->at_desc = sval;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"OBSOLETE") ) {
+ LDAP_FREE(sval);
+ if ( seen_obsolete ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ seen_obsolete = 1;
+ at->at_obsolete = LDAP_SCHEMA_YES;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"SUP") ) {
+ LDAP_FREE(sval);
+ if ( seen_sup ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ seen_sup = 1;
+ at->at_sup_oid = parse_woid(&ss,code);
+ if ( !at->at_sup_oid ) {
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ } else if ( !strcmp(sval,"EQUALITY") ) {
+ LDAP_FREE(sval);
+ if ( seen_equality ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ seen_equality = 1;
+ at->at_equality_oid = parse_woid(&ss,code);
+ if ( !at->at_equality_oid ) {
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ } else if ( !strcmp(sval,"ORDERING") ) {
+ LDAP_FREE(sval);
+ if ( seen_ordering ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ seen_ordering = 1;
+ at->at_ordering_oid = parse_woid(&ss,code);
+ if ( !at->at_ordering_oid ) {
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ } else if ( !strcmp(sval,"SUBSTR") ) {
+ LDAP_FREE(sval);
+ if ( seen_substr ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ seen_substr = 1;
+ at->at_substr_oid = parse_woid(&ss,code);
+ if ( !at->at_substr_oid ) {
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ } else if ( !strcmp(sval,"SYNTAX") ) {
+ LDAP_FREE(sval);
+ if ( seen_syntax ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ seen_syntax = 1;
+ parse_whsp(&ss);
+ at->at_syntax_oid =
+ parse_noidlen(&ss,
+ code,
+ &at->at_syntax_len,
+ be_liberal);
+ if ( !at->at_syntax_oid ) {
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"SINGLE-VALUE") ) {
+ LDAP_FREE(sval);
+ if ( at->at_single_value ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ at->at_single_value = LDAP_SCHEMA_YES;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"COLLECTIVE") ) {
+ LDAP_FREE(sval);
+ if ( at->at_collective ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ at->at_collective = LDAP_SCHEMA_YES;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"NO-USER-MODIFICATION") ) {
+ LDAP_FREE(sval);
+ if ( at->at_no_user_mod ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ at->at_no_user_mod = LDAP_SCHEMA_YES;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"USAGE") ) {
+ LDAP_FREE(sval);
+ if ( seen_usage ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return(NULL);
+ }
+ seen_usage = 1;
+ parse_whsp(&ss);
+ kind = get_token(&ss,&sval);
+ if ( kind != TK_BAREWORD ) {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ if ( !strcasecmp(sval,"userApplications") )
+ at->at_usage =
+ LDAP_SCHEMA_USER_APPLICATIONS;
+ else if ( !strcasecmp(sval,"directoryOperation") )
+ at->at_usage =
+ LDAP_SCHEMA_DIRECTORY_OPERATION;
+ else if ( !strcasecmp(sval,"distributedOperation") )
+ at->at_usage =
+ LDAP_SCHEMA_DISTRIBUTED_OPERATION;
+ else if ( !strcasecmp(sval,"dSAOperation") )
+ at->at_usage =
+ LDAP_SCHEMA_DSA_OPERATION;
+ else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ LDAP_FREE(sval);
+ parse_whsp(&ss);
+ } else if ( sval[0] == 'X' && sval[1] == '-' ) {
+ LDAP_FREE(sval);
+ /* Should be parse_qdstrings */
+ ssdummy = parse_qdescrs(&ss, code);
+ if ( !ssdummy ) {
+ *errp = ss;
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ } else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ break;
+ default:
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_attributetype_free(at);
+ return NULL;
+ }
+ }
+}
+
+void
+ldap_objectclass_free(LDAP_OBJECT_CLASS * oc)
+{
+ LDAP_FREE(oc->oc_oid);
+ LDAP_VFREE(oc->oc_names);
+ LDAP_FREE(oc->oc_desc);
+ LDAP_VFREE(oc->oc_sup_oids);
+ LDAP_VFREE(oc->oc_at_oids_must);
+ LDAP_VFREE(oc->oc_at_oids_may);
+ LDAP_FREE(oc);
+}
+
+LDAP_OBJECT_CLASS *
+ldap_str2objectclass( const char * s, int * code, const char ** errp )
+{
+ int kind;
+ const char * ss = s;
+ char * sval;
+ int be_liberal = 1; /* Future additional argument */
+ int seen_name = 0;
+ int seen_desc = 0;
+ int seen_obsolete = 0;
+ int seen_sup = 0;
+ int seen_kind = 0;
+ int seen_must = 0;
+ int seen_may = 0;
+ LDAP_OBJECT_CLASS * oc;
+ char ** ssdummy;
+ const char * savepos;
+
+ if ( !s ) {
+ *code = LDAP_SCHERR_EMPTY;
+ *errp = "";
+ return NULL;
+ }
+
+ *errp = s;
+ oc = LDAP_CALLOC(1,sizeof(LDAP_OBJECT_CLASS));
+
+ if ( !oc ) {
+ *code = LDAP_SCHERR_OUTOFMEM;
+ return NULL;
+ }
+
+ kind = get_token(&ss,&sval);
+ if ( kind != TK_LEFTPAREN ) {
+ *code = LDAP_SCHERR_NOLEFTPAREN;
+ LDAP_FREE(sval);
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+
+ /*
+ * Definitions MUST begin with an OID in the numericoid format.
+ * However, this routine is used by clients to parse the response
+ * from servers and very well known servers will provide an OID
+ * in the wrong format or even no OID at all. We do our best to
+ * extract info from those servers.
+ */
+ parse_whsp(&ss);
+ savepos = ss;
+ oc->oc_oid = parse_numericoid(&ss,code,0);
+ if ( !oc->oc_oid ) {
+ if ( be_liberal ) {
+ /* Backtracking */
+ ss = savepos;
+ kind = get_token(&ss,&sval);
+ if ( kind == TK_BAREWORD ) {
+ if ( !strcmp(sval, "NAME") ||
+ !strcmp(sval, "DESC") ||
+ !strcmp(sval, "OBSOLETE") ||
+ !strcmp(sval, "SUP") ||
+ !strcmp(sval, "ABSTRACT") ||
+ !strcmp(sval, "STRUCTURAL") ||
+ !strcmp(sval, "AUXILIARY") ||
+ !strcmp(sval, "MUST") ||
+ !strncmp(sval, "X-", 2) ) {
+ /* Missing OID, backtrack */
+ ss = savepos;
+ } else {
+ /* Non-numerical OID, ignore */
+ }
+ }
+ LDAP_FREE(sval);
+ } else {
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+ }
+ parse_whsp(&ss);
+
+ /*
+ * Beyond this point we will be liberal an accept the items
+ * in any order.
+ */
+ while (1) {
+ kind = get_token(&ss,&sval);
+ switch (kind) {
+ case TK_EOS:
+ *code = LDAP_SCHERR_NORIGHTPAREN;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return NULL;
+ case TK_RIGHTPAREN:
+ return oc;
+ case TK_BAREWORD:
+ if ( !strcmp(sval,"NAME") ) {
+ LDAP_FREE(sval);
+ if ( seen_name ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return(NULL);
+ }
+ seen_name = 1;
+ oc->oc_names = parse_qdescrs(&ss,code);
+ if ( !oc->oc_names ) {
+ if ( *code != LDAP_SCHERR_OUTOFMEM )
+ *code = LDAP_SCHERR_BADNAME;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+ } else if ( !strcmp(sval,"DESC") ) {
+ LDAP_FREE(sval);
+ if ( seen_desc ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return(NULL);
+ }
+ seen_desc = 1;
+ parse_whsp(&ss);
+ kind = get_token(&ss,&sval);
+ if ( kind != TK_QDSTRING ) {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+ oc->oc_desc = sval;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"OBSOLETE") ) {
+ LDAP_FREE(sval);
+ if ( seen_obsolete ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return(NULL);
+ }
+ seen_obsolete = 1;
+ oc->oc_obsolete = LDAP_SCHEMA_YES;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"SUP") ) {
+ LDAP_FREE(sval);
+ if ( seen_sup ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return(NULL);
+ }
+ seen_sup = 1;
+ oc->oc_sup_oids = parse_oids(&ss,
+ code,
+ be_liberal);
+ if ( !oc->oc_sup_oids ) {
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+ } else if ( !strcmp(sval,"ABSTRACT") ) {
+ LDAP_FREE(sval);
+ if ( seen_kind ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return(NULL);
+ }
+ seen_kind = 1;
+ oc->oc_kind = LDAP_SCHEMA_ABSTRACT;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"STRUCTURAL") ) {
+ LDAP_FREE(sval);
+ if ( seen_kind ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return(NULL);
+ }
+ seen_kind = 1;
+ oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"AUXILIARY") ) {
+ LDAP_FREE(sval);
+ if ( seen_kind ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return(NULL);
+ }
+ seen_kind = 1;
+ oc->oc_kind = LDAP_SCHEMA_AUXILIARY;
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"MUST") ) {
+ LDAP_FREE(sval);
+ if ( seen_must ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return(NULL);
+ }
+ seen_must = 1;
+ oc->oc_at_oids_must = parse_oids(&ss,code,0);
+ if ( !oc->oc_at_oids_must ) {
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+ parse_whsp(&ss);
+ } else if ( !strcmp(sval,"MAY") ) {
+ LDAP_FREE(sval);
+ if ( seen_may ) {
+ *code = LDAP_SCHERR_DUPOPT;
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return(NULL);
+ }
+ seen_may = 1;
+ oc->oc_at_oids_may = parse_oids(&ss,code,0);
+ if ( !oc->oc_at_oids_may ) {
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+ parse_whsp(&ss);
+ } else if ( sval[0] == 'X' && sval[1] == '-' ) {
+ LDAP_FREE(sval);
+ /* Should be parse_qdstrings */
+ ssdummy = parse_qdescrs(&ss, code);
+ if ( !ssdummy ) {
+ *errp = ss;
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+ } else {
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+ break;
+ default:
+ *code = LDAP_SCHERR_UNEXPTOKEN;
+ *errp = ss;
+ LDAP_FREE(sval);
+ ldap_objectclass_free(oc);
+ return NULL;
+ }
+ }
+}
+
+static char *err2text[] = {
+ "",
+ "Out of memory",
+ "Unexpected token",
+ "Missing opening parenthesis",
+ "Missing closing parenthesis",
+ "Expecting digit",
+ "Expecting a name",
+ "Bad description",
+ "Bad superiors",
+ "Duplicate option",
+ "Unexpected end of data"
+};
+
+char *
+ldap_scherr2str(int code)
+{
+ if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) {
+ return "Unknown error";
+ } else {
+ return err2text[code];
+ }
+}
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* search.c
*/
-#ifndef lint
-static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifdef MACOS
-#include <stdlib.h>
-#include "macos.h"
-#endif /* MACOS */
-
-#if defined( DOS ) || defined( _WIN32 )
-#include "msdos.h"
-#endif /* DOS */
-
-#if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif
-#include "lber.h"
-#include "ldap.h"
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include "ldap-int.h"
-#ifdef NEEDPROTOS
-static char *find_right_paren( char *s );
-static char *put_complex_filter( BerElement *ber, char *str,
- unsigned long tag, int not );
-static int put_filter( BerElement *ber, char *str );
-static int put_simple_filter( BerElement *ber, char *str );
-static int put_substring_filter( BerElement *ber, char *type, char *str );
-static int put_filter_list( BerElement *ber, char *str );
-#else
-static char *find_right_paren();
-static char *put_complex_filter();
-static int put_filter();
-static int put_simple_filter();
-static int put_substring_filter();
-static int put_filter_list();
-#endif /* NEEDPROTOS */
+static int ldap_is_attr_oid LDAP_P((
+ const char *attr ));
+
+static int ldap_is_attr_desc LDAP_P((
+ const char *attr ));
+
+static int hex2value LDAP_P((
+ int c ));
+
+static ber_slen_t filter_value_unescape LDAP_P((
+ char *filter ));
+
+static char *find_right_paren LDAP_P((
+ char *s ));
+
+static char *find_wildcard LDAP_P((
+ char *s ));
+
+static char *put_complex_filter LDAP_P((
+ BerElement *ber,
+ char *str,
+ ber_tag_t tag,
+ int not ));
+
+static int put_filter LDAP_P((
+ BerElement *ber,
+ char *str ));
+
+static int put_simple_filter LDAP_P((
+ BerElement *ber,
+ char *str ));
+
+static int put_substring_filter LDAP_P((
+ BerElement *ber,
+ char *type,
+ char *str ));
+
+static int put_filter_list LDAP_P((
+ BerElement *ber,
+ char *str ));
/*
- * ldap_search - initiate an ldap (and X.500) search operation. Parameters:
+ * ldap_search_ext - initiate an ldap search operation.
+ *
+ * Parameters:
+ *
+ * ld LDAP descriptor
+ * base DN of the base object
+ * scope the search scope - one of LDAP_SCOPE_BASE,
+ * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
+ * filter a string containing the search filter
+ * (e.g., "(|(cn=bob)(sn=bob))")
+ * attrs list of attribute types to return for matches
+ * attrsonly 1 => attributes only 0 => attributes and values
+ *
+ * Example:
+ * char *attrs[] = { "mail", "title", 0 };
+ * ldap_search_ext( ld, "c=us,o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob",
+ * attrs, attrsonly, sctrls, ctrls, timeout, sizelimit,
+ * &msgid );
+ */
+int
+ldap_search_ext(
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls,
+ struct timeval *timeout,
+ int sizelimit,
+ int *msgidp )
+{
+ BerElement *ber;
+ int timelimit;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 );
+
+ /*
+ * if timeout is provided, use only tv_sec as timelimit.
+ * otherwise, use default.
+ */
+ timelimit = (timeout != NULL)
+ ? timeout->tv_sec
+ : -1;
+
+ ber = ldap_build_search_req( ld, base, scope, filter, attrs,
+ attrsonly, sctrls, cctrls, timelimit, sizelimit );
+
+ if ( ber == NULL ) {
+ return ld->ld_errno;
+ }
+
+#ifndef LDAP_NOCACHE
+ if ( ld->ld_cache != NULL ) {
+ if ( ldap_check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) {
+ ber_free( ber, 1 );
+ ld->ld_errno = LDAP_SUCCESS;
+ *msgidp = ld->ld_msgid;
+ return ld->ld_errno;
+ }
+ ldap_add_request_to_cache( ld, LDAP_REQ_SEARCH, ber );
+ }
+#endif /* LDAP_NOCACHE */
+
+ /* send the message */
+ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber );
+
+ if( *msgidp < 0 )
+ return ld->ld_errno;
+
+ return LDAP_SUCCESS;
+}
+
+int
+ldap_search_ext_s(
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls,
+ struct timeval *timeout,
+ int sizelimit,
+ LDAPMessage **res )
+{
+ int rc;
+ int msgid;
+
+ rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
+ sctrls, cctrls, timeout, sizelimit, &msgid );
+
+ if ( rc != LDAP_SUCCESS ) {
+ return( rc );
+ }
+
+ if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 )
+ return( ld->ld_errno );
+
+ return( ldap_result2error( ld, *res, 0 ) );
+}
+
+/*
+ * ldap_search - initiate an ldap search operation.
+ *
+ * Parameters:
*
* ld LDAP descriptor
* base DN of the base object
* attrs, attrsonly );
*/
int
-ldap_search( LDAP *ld, char *base, int scope, char *filter,
+ldap_search(
+ LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter,
char **attrs, int attrsonly )
{
BerElement *ber;
Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
- if (( ber = ldap_build_search_req( ld, base, scope, filter, attrs,
- attrsonly )) == NULLBER ) {
+ ber = ldap_build_search_req( ld, base, scope, filter, attrs,
+ attrsonly, NULL, NULL, -1, -1 );
+
+ if ( ber == NULL ) {
return( -1 );
}
-#ifndef NO_CACHE
+#ifndef LDAP_NOCACHE
if ( ld->ld_cache != NULL ) {
- if ( check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) {
+ if ( ldap_check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) {
ber_free( ber, 1 );
ld->ld_errno = LDAP_SUCCESS;
return( ld->ld_msgid );
}
- add_request_to_cache( ld, LDAP_REQ_SEARCH, ber );
+ ldap_add_request_to_cache( ld, LDAP_REQ_SEARCH, ber );
}
-#endif /* NO_CACHE */
+#endif /* LDAP_NOCACHE */
/* send the message */
- return ( send_initial_request( ld, LDAP_REQ_SEARCH, base, ber ));
+ return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber ));
}
BerElement *
-ldap_build_search_req( LDAP *ld, char *base, int scope, char *filter,
- char **attrs, int attrsonly )
+ldap_build_search_req(
+ LDAP *ld,
+ LDAP_CONST char *base_in,
+ ber_int_t scope,
+ LDAP_CONST char *filter_in,
+ char **attrs,
+ ber_int_t attrsonly,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls,
+ ber_int_t timelimit,
+ ber_int_t sizelimit )
{
BerElement *ber;
int err;
+ char *base;
+ char *filter;
/*
* Create the search request. It looks like this:
*/
/* create a message to send */
- if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
- return( NULLBER );
+ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
+ return( NULL );
+ }
+
+ if ( base_in == NULL ) {
+ /* no base provided, use session default base */
+ base = ld->ld_options.ldo_defbase;
+ } else {
+ base = (char *) base_in;
}
if ( base == NULL ) {
+ /* no session default base, use top */
base = "";
}
-#ifdef CLDAP
- if ( ld->ld_sb.sb_naddr > 0 ) {
+#ifdef LDAP_CONNECTIONLESS
+ if ( ld->ld_cldapnaddr > 0 ) {
err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid,
- ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
- ld->ld_sizelimit, ld->ld_timelimit, attrsonly );
+ ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
+ (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
+ (timelimit < 0) ? ld->ld_timelimit : timelimit,
+ attrsonly );
} else {
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
err = ber_printf( ber, "{it{seeiib", ++ld->ld_msgid,
- LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
- ld->ld_sizelimit, ld->ld_timelimit, attrsonly );
-#ifdef CLDAP
+ LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
+ (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
+ (timelimit < 0) ? ld->ld_timelimit : timelimit,
+ attrsonly );
+#ifdef LDAP_CONNECTIONLESS
}
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
if ( err == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
ber_free( ber, 1 );
- return( NULLBER );
+ return( NULL );
}
- filter = strdup( filter );
+ filter = LDAP_STRDUP( filter_in );
err = put_filter( ber, filter );
- free( filter );
+ LDAP_FREE( filter );
if ( err == -1 ) {
ld->ld_errno = LDAP_FILTER_ERROR;
ber_free( ber, 1 );
- return( NULLBER );
+ return( NULL );
}
- if ( ber_printf( ber, "{v}}}", attrs ) == -1 ) {
+ if ( ber_printf( ber, /*{*/ "{v}}", attrs ) == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
ber_free( ber, 1 );
- return( NULLBER );
+ return( NULL );
+ }
+
+ /* Put Server Controls */
+ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+
+ if ( ber_printf( ber, /*{*/ "}", attrs ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULL );
}
return( ber );
}
+static int ldap_is_attr_oid LDAP_P(( const char *attr ))
+{
+ int i, c, digit=0;
+
+ for( i=0 ; c = attr[i] ; i++ ) {
+ if( c >= '0' && c <= '9' ) {
+ digit=1;
+
+ } else if ( c != '.' ) {
+ /* not digit nor '.' */
+ return 0;
+
+ } else if ( !digit ) {
+ /* '.' but prev not digit */
+ return 0;
+
+ } else {
+ /* '.' */
+ digit = 0;
+ }
+ }
+
+ return digit;
+
+}
+
+static int ldap_is_attr_desc LDAP_P(( const char *attr ))
+{
+ /* cheap attribute description check */
+ int i, c;
+
+ for( i=0; c = attr[i]; i++ ) {
+ if (( c >= '0' && c <= '9' )
+ || ( c >= 'A' && c <= 'Z' )
+ || ( c >= 'a' && c <= 'z' )
+ || ( c == '.' || c == '-' )
+ || ( c == ';' )) continue;
+
+ return 0;
+ }
+
+ return i > 0;
+}
+
static char *
find_right_paren( char *s )
{
return( *s ? s : NULL );
}
+static int hex2value( int c )
+{
+ if( c >= '0' && c <= '9' ) {
+ return c - '0';
+ }
+
+ if( c >= 'A' && c <= 'F' ) {
+ return c + (10 - (int) 'A');
+ }
+
+ if( c >= 'a' && c <= 'f' ) {
+ return c + (10 - (int) 'a');
+ }
+
+ return -1;
+}
+
+static char *
+find_wildcard( char *s )
+{
+ for( ; *s != '\0' ; s++ ) {
+ switch( *s ) {
+ case '*': /* found wildcard */
+ return s;
+
+ case '\\':
+ s++; /* skip over escape */
+ if( hex2value( s[0] ) >= 0 && hex2value( s[1] ) >= 0 ) {
+ /* skip over lead digit of two hex digit code */
+ s++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/* unescape filter value */
+/* support both LDAP v2 and v3 escapes */
+/* output can include nul characters */
+static ber_slen_t
+filter_value_unescape( char *fval )
+{
+ ber_slen_t r, v;
+ int v1, v2;
+
+ for( r=v=0; fval[v] != '\0'; v++ ) {
+ switch( fval[v] ) {
+ case '\\':
+ /* escape */
+ v++;
+
+ if ( fval[v] == '\0' ) {
+ /* escape at end of string */
+ return -1;
+
+ } else if (( v1 = hex2value( fval[v] )) < 0 ) {
+ /* LDAPv3 escape */
+
+ if (( v2 = hex2value( fval[v+1] )) < 0 ) {
+ /* must be two digit code */
+ return -1;
+ }
+
+ fval[r++] = v1 * 16 + v2;
+ v++;
+
+ } else {
+ /* LDAPv2 escape */
+ fval[r++] = fval[v];
+ }
+
+ break;
+
+ default:
+ fval[r++] = fval[v];
+ }
+ }
+
+ fval[r] = '\0';
+ return r;
+}
+
static char *
-put_complex_filter( BerElement *ber, char *str, unsigned long tag, int not )
+put_complex_filter( BerElement *ber, char *str, ber_tag_t tag, int not )
{
char *next;
*/
/* put explicit tag */
- if ( ber_printf( ber, "t{", tag ) == -1 )
+ if ( ber_printf( ber, "t{" /*}*/, tag ) == -1 )
return( NULL );
-/*
- if ( !not && ber_printf( ber, "{" ) == -1 )
- return( NULL );
-*/
str++;
if ( (next = find_right_paren( str )) == NULL )
*next++ = ')';
/* flush explicit tagged thang */
- if ( ber_printf( ber, "}" ) == -1 )
- return( NULL );
-/*
- if ( !not && ber_printf( ber, "}" ) == -1 )
+ if ( ber_printf( ber, /*{*/ "}" ) == -1 )
return( NULL );
-*/
return( next );
}
static int
put_filter( BerElement *ber, char *str )
{
- char *next, *tmp, *s, *d;
- int parens, balance, escape, gotescape;
+ char *next;
+ int parens, balance, escape;
/*
* A Filter looks like this:
* substrings [4] SubstringFilter,
* greaterOrEqual [5] AttributeValueAssertion,
* lessOrEqual [6] AttributeValueAssertion,
- * present [7] AttributeType,,
- * approxMatch [8] AttributeValueAssertion
+ * present [7] AttributeType,
+ * approxMatch [8] AttributeValueAssertion,
+ * extensibleMatch [9] MatchingRuleAssertion -- LDAPv3
* }
*
* SubstringFilter ::= SEQUENCE {
* final [2] IA5String
* }
* }
+ *
+ * MatchingRuleAssertion ::= SEQUENCE { -- LDAPv3
+ * matchingRule [1] MatchingRuleId OPTIONAL,
+ * type [2] AttributeDescription OPTIONAL,
+ * matchValue [3] AssertionValue,
+ * dnAttributes [4] BOOLEAN DEFAULT FALSE }
+ *
* Note: tags in a choice are always explicit
*/
Debug( LDAP_DEBUG_TRACE, "put_filter \"%s\"\n", str, 0, 0 );
- gotescape = parens = 0;
+ parens = 0;
while ( *str ) {
switch ( *str ) {
case '(':
balance--;
}
if ( *next == '\\' && ! escape )
- gotescape = escape = 1;
+ escape = 1;
else
escape = 0;
if ( balance )
return( -1 );
*next = '\0';
- tmp = strdup( str );
- if ( gotescape ) {
- escape = 0;
- for ( s = d = tmp; *s; s++ ) {
- if ( *s != '\\' || escape ) {
- *d++ = *s;
- escape = 0;
- } else {
- escape = 1;
- }
- }
- *d = '\0';
- }
- if ( put_simple_filter( ber, tmp ) == -1 ) {
- free( tmp );
+ if ( put_simple_filter( ber, str ) == -1 ) {
return( -1 );
}
- free( tmp );
*next++ = ')';
str = next;
parens--;
case ')':
Debug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0,
0 );
- if ( ber_printf( ber, "]" ) == -1 )
+ if ( ber_printf( ber, /*[*/ "]" ) == -1 )
return( -1 );
str++;
parens--;
Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0,
0 );
next = strchr( str, '\0' );
- tmp = strdup( str );
- if ( strchr( tmp, '\\' ) != NULL ) {
- escape = 0;
- for ( s = d = tmp; *s; s++ ) {
- if ( *s != '\\' || escape ) {
- *d++ = *s;
- escape = 0;
- } else {
- escape = 1;
- }
- }
- *d = '\0';
- }
- if ( put_simple_filter( ber, tmp ) == -1 ) {
- free( tmp );
+ if ( put_simple_filter( ber, str ) == -1 ) {
return( -1 );
}
- free( tmp );
str = next;
break;
}
Debug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 );
while ( *str ) {
- while ( *str && isspace( *str ) )
+ while ( *str && isspace( (unsigned char) *str ) )
str++;
if ( *str == '\0' )
break;
}
static int
-put_simple_filter( BerElement *ber, char *str )
+put_simple_filter(
+ BerElement *ber,
+ char *str )
{
char *s;
- char *value, savechar;
- unsigned long ftype;
- int rc;
+ char *value;
+ ber_tag_t ftype;
+ int rc = -1;
Debug( LDAP_DEBUG_TRACE, "put_simple_filter \"%s\"\n", str, 0, 0 );
- if ( (s = strchr( str, '=' )) == NULL )
- return( -1 );
+ str = LDAP_STRDUP( str );
+ if( str == NULL ) return -1;
+
+ if ( (s = strchr( str, '=' )) == NULL ) {
+ goto done;
+ }
+
value = s + 1;
*s-- = '\0';
- savechar = *s;
switch ( *s ) {
case '<':
ftype = LDAP_FILTER_LE;
*s = '\0';
+ if(! ldap_is_attr_desc( str ) ) goto done;
break;
+
case '>':
ftype = LDAP_FILTER_GE;
*s = '\0';
+ if(! ldap_is_attr_desc( str ) ) goto done;
break;
+
case '~':
ftype = LDAP_FILTER_APPROX;
*s = '\0';
+ if(! ldap_is_attr_desc( str ) ) goto done;
break;
+
+ case ':':
+ /* RFC2254 extensible filters are off the form:
+ * type [:dn] [:rule] := value
+ * or [:dn]:rule := value
+ */
+ ftype = LDAP_FILTER_EXT;
+ *s = '\0';
+
+ {
+ char *dn = strchr( str, ':' );
+ char *rule = NULL;
+
+ if( dn == NULL ) {
+ if(! ldap_is_attr_desc( str ) ) goto done;
+ break;
+ }
+
+ *dn++ = '\0';
+ rule = strchr( dn, ':' );
+
+ if( rule == NULL ) {
+ /* one colon */
+ if ( strcmp(dn, "dn") == 0 ) {
+ /* must have attribute */
+ if( !ldap_is_attr_desc( str ) ) {
+ goto done;
+ }
+
+ rule = "";
+
+ } else {
+ rule = dn;
+ dn = NULL;
+ }
+
+ } else {
+ /* two colons */
+ *rule++ = '\0';
+
+ if ( strcmp(dn, "dn") != 0 ) {
+ /* must have "dn" */
+ goto done;
+ }
+ }
+
+ if ( *str == '\0' && *rule == '\0' ) {
+ /* must have either type or rule */
+ goto done;
+ }
+
+ if ( *str != '\0' && !ldap_is_attr_desc( str ) ) {
+ goto done;
+ }
+
+ if ( *rule != '\0' && !ldap_is_attr_oid( rule ) ) {
+ goto done;
+ }
+
+ rc = ber_printf( ber, "t{" /*}*/, ftype );
+
+ if( rc != -1 && *rule != '\0' ) {
+ rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_OID, rule );
+ }
+ if( rc != -1 && *str != '\0' ) {
+ rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_TYPE, str );
+ }
+
+ if( rc != -1 ) {
+ ber_slen_t len = filter_value_unescape( value );
+
+ if( len >= 0 ) {
+ rc = ber_printf( ber, "totb}",
+ LDAP_FILTER_EXT_VALUE, value, len,
+ LDAP_FILTER_EXT_DNATTRS, dn != NULL);
+ } else {
+ rc = -1;
+ }
+ }
+ }
+ break;
+
default:
- if ( strchr( value, '*' ) == NULL ) {
+ if ( find_wildcard( value ) == NULL ) {
ftype = LDAP_FILTER_EQUALITY;
} else if ( strcmp( value, "*" ) == 0 ) {
ftype = LDAP_FILTER_PRESENT;
} else {
rc = put_substring_filter( ber, str, value );
- *(value-1) = '=';
- return( rc );
+ goto done;
}
break;
}
if ( ftype == LDAP_FILTER_PRESENT ) {
rc = ber_printf( ber, "ts", ftype, str );
+
} else {
- rc = ber_printf( ber, "t{ss}", ftype, str, value );
+ ber_slen_t len = filter_value_unescape( value );
+
+ if( len >= 0 ) {
+ rc = ber_printf( ber, "t{so}",
+ ftype, str, value, len );
+ }
}
- *s = savechar;
- *(value-1) = '=';
- return( rc == -1 ? rc : 0 );
+ if( rc != -1 ) rc = 0;
+
+done:
+ LDAP_FREE( str );
+ return rc;
}
static int
put_substring_filter( BerElement *ber, char *type, char *val )
{
char *nextstar, gotstar = 0;
- unsigned long ftype;
+ ber_tag_t ftype = LDAP_FILTER_SUBSTRINGS;
Debug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type,
val, 0 );
- if ( ber_printf( ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type ) == -1 )
+ if ( ber_printf( ber, "t{s{", ftype, type ) == -1 )
return( -1 );
- while ( val != NULL ) {
- if ( (nextstar = strchr( val, '*' )) != NULL )
+ for( ; val != NULL; val=nextstar ) {
+ if ( (nextstar = find_wildcard( val )) != NULL )
*nextstar++ = '\0';
if ( gotstar == 0 ) {
} else {
ftype = LDAP_SUBSTRING_ANY;
}
+
if ( *val != '\0' ) {
- if ( ber_printf( ber, "ts", ftype, val ) == -1 )
+ ber_slen_t len = filter_value_unescape( val );
+
+ if ( len < 0 ) {
+ return -1;
+ }
+
+ if ( ber_printf( ber, "to", ftype, val, len ) == -1 ) {
return( -1 );
+ }
}
gotstar = 1;
- if ( nextstar != NULL )
- *(nextstar-1) = '*';
- val = nextstar;
}
- if ( ber_printf( ber, "}}" ) == -1 )
+ if ( ber_printf( ber, /* {{ */ "}}" ) == -1 )
return( -1 );
return( 0 );
}
int
-ldap_search_st( LDAP *ld, char *base, int scope, char *filter, char **attrs,
+ldap_search_st(
+ LDAP *ld, LDAP_CONST char *base, int scope,
+ LDAP_CONST char *filter, char **attrs,
int attrsonly, struct timeval *timeout, LDAPMessage **res )
{
int msgid;
}
int
-ldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs,
- int attrsonly, LDAPMessage **res )
+ldap_search_s(
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res )
{
int msgid;
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#ifdef MACOS
-#include <stdlib.h>
-#ifdef THINK_C
-#include <console.h>
-#include <unix.h>
-#include <fcntl.h>
-#endif /* THINK_C */
-#include "macos.h"
-#else /* MACOS */
-#if defined( DOS ) || defined( _WIN32 )
-#include "msdos.h"
-#if defined( WINSOCK ) || defined( _WIN32 )
-#include "console.h"
-#endif /* WINSOCK */
-#else /* DOS */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
#include <sys/stat.h>
+
+#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
-#ifndef VMS
+#endif
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
#include <fcntl.h>
-#include <unistd.h>
-#endif /* VMS */
-#endif /* DOS */
-#endif /* MACOS */
-
-#include "lber.h"
-#include "ldap.h"
-
-#if !defined( PCNFS ) && !defined( WINSOCK ) && !defined( MACOS )
-#define MOD_USE_BVALS
-#endif /* !PCNFS && !WINSOCK && !MACOS */
-
-#ifdef NEEDPROTOS
-static void handle_result( LDAP *ld, LDAPMessage *lm );
-static void print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s );
-static void print_search_entry( LDAP *ld, LDAPMessage *res );
-static void free_list( char **list );
-#else
-static void handle_result();
-static void print_ldap_result();
-static void print_search_entry();
-static void free_list();
-#endif /* NEEDPROTOS */
-#define NOCACHEERRMSG "don't compile with -DNO_CACHE if you desire local caching"
+/* including the "internal" defs is legit and nec. since this test routine has
+ * a-priori knowledge of libldap internal workings.
+ * hodges@stanford.edu 5-Feb-96
+ */
+#include "ldap-int.h"
+
+/* local functions */
+#ifndef HAVE_GETLINE
+static char *getline LDAP_P(( char *line, int len, FILE *fp, char *prompt ));
+#endif
+static char **get_list LDAP_P(( char *prompt ));
+static int file_read LDAP_P(( char *path, struct berval *bv ));
+static LDAPMod **get_modlist LDAP_P(( char *prompt1, char *prompt2, char *prompt3 ));
+static void handle_result LDAP_P(( LDAP *ld, LDAPMessage *lm ));
+static void print_ldap_result LDAP_P(( LDAP *ld, LDAPMessage *lm, char *s ));
+static void print_search_entry LDAP_P(( LDAP *ld, LDAPMessage *res ));
+static void free_list LDAP_P(( char **list ));
+
+#define NOCACHEERRMSG "don't compile with -DLDAP_NOCACHE if you desire local caching"
-char *dnsuffix;
+static char *dnsuffix;
-#ifndef WINSOCK
+#ifndef HAVE_GETLINE
static char *
getline( char *line, int len, FILE *fp, char *prompt )
{
return( line );
}
-#endif /* WINSOCK */
+#endif
static char **
get_list( char *prompt )
}
-#ifdef MOD_USE_BVALS
static int
file_read( char *path, struct berval *bv )
{
FILE *fp;
- long rlen;
+ ber_slen_t rlen;
int eof;
if (( fp = fopen( path, "r" )) == NULL ) {
eof = feof( fp );
fclose( fp );
- if ( rlen != bv->bv_len ) {
+ if ( (ber_len_t) rlen != bv->bv_len ) {
perror( path );
free( bv->bv_val );
return( -1 );
return( bv->bv_len );
}
-#endif /* MOD_USE_BVALS */
static LDAPMod **
int num;
LDAPMod tmp;
LDAPMod **result;
-#ifdef MOD_USE_BVALS
struct berval **bvals;
-#endif /* MOD_USE_BVALS */
num = 0;
result = NULL;
tmp.mod_type = strdup( buf );
tmp.mod_values = get_list( prompt3 );
-#ifdef MOD_USE_BVALS
+
if ( tmp.mod_values != NULL ) {
int i;
tmp.mod_bvalues = bvals;
tmp.mod_op |= LDAP_MOD_BVALUES;
}
-#endif /* MOD_USE_BVALS */
if ( result == NULL )
result = (LDAPMod **) malloc( sizeof(LDAPMod *) );
}
-#ifdef LDAP_REFERRALS
-int
+static int
bind_prompt( LDAP *ld, char **dnp, char **passwdp, int *authmethodp,
int freeit )
{
static char dn[256], passwd[256];
if ( !freeit ) {
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
getline( dn, sizeof(dn), stdin,
"re-bind method (0->simple, 1->krbv41, 2->krbv42, 3->krbv41&2)? " );
if (( *authmethodp = atoi( dn )) == 3 ) {
} else {
*authmethodp |= 0x80;
}
-#else /* KERBEROS */
+#else /* HAVE_KERBEROS */
*authmethodp = LDAP_AUTH_SIMPLE;
-#endif /* KERBEROS */
+#endif /* HAVE_KERBEROS */
getline( dn, sizeof(dn), stdin, "re-bind dn? " );
strcat( dn, dnsuffix );
return( LDAP_SUCCESS );
}
-#endif /* LDAP_REFERRALS */
int
-#ifdef WINSOCK
-ldapmain(
-#else /* WINSOCK */
-main(
-#endif /* WINSOCK */
- int argc, char **argv )
+main( int argc, char **argv )
{
- LDAP *ld;
+ LDAP *ld = NULL;
int i, c, port, cldapflg, errflg, method, id, msgtype;
char line[256], command1, command2, command3;
char passwd[64], dn[256], rdn[64], attr[64], value[256];
int copyoptions = 0;
LDAPURLDesc *ludp;
- extern char *optarg;
- extern int optind;
-
-#ifdef MACOS
- if (( argv = get_list( "cmd line arg?" )) == NULL ) {
- exit( 1 );
- }
- for ( argc = 0; argv[ argc ] != NULL; ++argc ) {
- ;
- }
-#endif /* MACOS */
-
host = NULL;
port = LDAP_PORT;
dnsuffix = "";
while (( c = getopt( argc, argv, "uh:d:s:p:t:T:" )) != -1 ) {
switch( c ) {
case 'u':
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
cldapflg++;
-#else /* CLDAP */
- printf( "Compile with -DCLDAP for UDP support\n" );
-#endif /* CLDAP */
+#else /* LDAP_CONNECTIONLESS */
+ printf( "Compile with -DLDAP_CONNECTIONLESS for UDP support\n" );
+#endif /* LDAP_CONNECTIONLESS */
break;
case 'd':
#ifdef LDAP_DEBUG
ldap_debug = atoi( optarg );
+#ifdef LBER_DEBUG
if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
- lber_debug = ldap_debug;
+ ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug );
}
+#endif
#else
printf( "Compile with -DLDAP_DEBUG for debugging\n" );
#endif
port = atoi( optarg );
break;
-#if !defined(MACOS) && !defined(DOS)
case 't': /* copy ber's to given file */
copyfname = strdup( optarg );
copyoptions = LBER_TO_FILE;
copyfname = strdup( optarg );
copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY);
break;
-#endif
default:
++errflg;
if ( errflg || optind < argc - 1 ) {
fprintf( stderr, usage, argv[ 0 ] );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
- printf( "%sldap_open( %s, %d )\n", cldapflg ? "c" : "",
+ printf( "%s( %s, %d )\n",
+ cldapflg ? "cldap_open" : "ldap_init",
host == NULL ? "(null)" : host, port );
if ( cldapflg ) {
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
ld = cldap_open( host, port );
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
} else {
- ld = ldap_open( host, port );
+ ld = ldap_init( host, port );
}
if ( ld == NULL ) {
- perror( "ldap_open" );
- exit(1);
+ perror( cldapflg ? "cldap_open" : "ldap_init" );
+ exit( EXIT_FAILURE );
}
-#if !defined(MACOS) && !defined(DOS)
if ( copyfname != NULL ) {
if ( (ld->ld_sb.sb_fd = open( copyfname, O_WRONLY | O_CREAT,
0600 )) == -1 ) {
perror( copyfname );
- exit ( 1 );
+ exit ( EXIT_FAILURE );
}
ld->ld_sb.sb_options = copyoptions;
}
-#endif
bound = 0;
timeout.tv_sec = 0;
break;
case 'b': /* asynch bind */
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
getline( line, sizeof(line), stdin,
"method (0->simple, 1->krbv41, 2->krbv42)? " );
method = atoi( line ) | 0x80;
-#else /* KERBEROS */
+#else /* HAVE_KERBEROS */
method = LDAP_AUTH_SIMPLE;
-#endif /* KERBEROS */
+#endif /* HAVE_KERBEROS */
getline( dn, sizeof(dn), stdin, "dn? " );
strcat( dn, dnsuffix );
break;
case 'B': /* synch bind */
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
getline( line, sizeof(line), stdin,
"method 0->simple 1->krbv41 2->krbv42 3->krb? " );
method = atoi( line );
method = LDAP_AUTH_KRBV4;
else
method = method | 0x80;
-#else /* KERBEROS */
+#else /* HAVE_KERBEROS */
method = LDAP_AUTH_SIMPLE;
-#endif /* KERBEROS */
+#endif /* HAVE_KERBEROS */
getline( dn, sizeof(dn), stdin, "dn? " );
strcat( dn, dnsuffix );
#ifdef LDAP_DEBUG
getline( line, sizeof(line), stdin, "debug level? " );
ldap_debug = atoi( line );
+#ifdef LBER_DEBUG
if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
- lber_debug = ldap_debug;
+ ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug );
}
+#endif
#else
printf( "Compile with -DLDAP_DEBUG for debugging\n" );
#endif
break;
case 'q': /* quit */
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
if ( cldapflg )
cldap_close( ld );
-#endif /* CLDAP */
-#ifdef LDAP_REFERRALS
- if ( !cldapflg )
-#else /* LDAP_REFERRALS */
- if ( !cldapflg && bound )
-#endif /* LDAP_REFERRALS */
+#endif /* LDAP_CONNECTIONLESS */
+
+ if ( !cldapflg ) {
ldap_unbind( ld );
- exit( 0 );
+ }
+ exit( EXIT_SUCCESS );
break;
case 'r': /* result or remove */
printf( "\nresult: msgtype %d msgid %d\n",
msgtype, res->lm_msgid );
handle_result( ld, res );
- res = NULLMSG;
+ res = NULL;
break;
case 'm': /* remove */
attrsonly = atoi( line );
if ( cldapflg ) {
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
getline( line, sizeof(line), stdin,
"Requestor DN (for logging)? " );
if ( cldap_search_s( ld, dn, scope, filter, types,
printf( "\nresult: msgid %d\n",
res->lm_msgid );
handle_result( ld, res );
- res = NULLMSG;
+ res = NULL;
}
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
} else {
if (( id = ldap_search( ld, dn, scope, filter,
types, attrsonly )) == -1 ) {
else {
printf( "\nresult: err %d\n", id );
handle_result( ld, res );
- res = NULLMSG;
+ res = NULL;
}
free_list( types );
break;
break;
case 'e': /* enable cache */
-#ifdef NO_CACHE
+#ifdef LDAP_NOCACHE
printf( NOCACHEERRMSG );
-#else /* NO_CACHE */
+#else /* LDAP_NOCACHE */
getline( line, sizeof(line), stdin, "Cache timeout (secs)? " );
i = atoi( line );
getline( line, sizeof(line), stdin, "Maximum memory to use (bytes)? " );
} else {
printf( "ldap_enable_cache failed\n" );
}
-#endif /* NO_CACHE */
+#endif /* LDAP_NOCACHE */
break;
case 'x': /* uncache entry */
-#ifdef NO_CACHE
+#ifdef LDAP_NOCACHE
printf( NOCACHEERRMSG );
-#else /* NO_CACHE */
+#else /* LDAP_NOCACHE */
getline( line, sizeof(line), stdin, "DN? " );
ldap_uncache_entry( ld, line );
-#endif /* NO_CACHE */
+#endif /* LDAP_NOCACHE */
break;
case 'X': /* uncache request */
-#ifdef NO_CACHE
+#ifdef LDAP_NOCACHE
printf( NOCACHEERRMSG );
-#else /* NO_CACHE */
+#else /* LDAP_NOCACHE */
getline( line, sizeof(line), stdin, "request msgid? " );
ldap_uncache_request( ld, atoi( line ));
-#endif /* NO_CACHE */
+#endif /* LDAP_NOCACHE */
break;
case 'o': /* set ldap options */
getline( line, sizeof(line), stdin, "sizelimit?" );
ld->ld_sizelimit = atoi( line );
- ld->ld_options = 0;
+ LDAP_BOOL_ZERO(&ld->ld_options);
#ifdef STR_TRANSLATION
getline( line, sizeof(line), stdin,
}
#endif /* STR_TRANSLATION */
-#ifdef LDAP_DNS
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
getline( line, sizeof(line), stdin,
"Use DN & DNS to determine where to send requests (0=no, 1=yes)?" );
if ( atoi( line ) != 0 ) {
- ld->ld_options |= LDAP_OPT_DNS;
+ LDAP_BOOL_SET(&ld->ld_options, LDAP_BOOL_DNS);
}
-#endif /* LDAP_DNS */
+#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */
-#ifdef LDAP_REFERRALS
getline( line, sizeof(line), stdin,
"Recognize and chase referrals (0=no, 1=yes)?" );
if ( atoi( line ) != 0 ) {
- ld->ld_options |= LDAP_OPT_REFERRALS;
+ LDAP_BOOL_SET(&ld->ld_options, LDAP_BOOL_REFERRALS);
getline( line, sizeof(line), stdin,
"Prompt for bind credentials when chasing referrals (0=no, 1=yes)?" );
if ( atoi( line ) != 0 ) {
ldap_set_rebind_proc( ld, bind_prompt );
}
}
-#endif /* LDAP_REFERRALS */
break;
case 'O': /* set cache options */
-#ifdef NO_CACHE
+#ifdef LDAP_NOCACHE
printf( NOCACHEERRMSG );
-#else /* NO_CACHE */
+#else /* LDAP_NOCACHE */
getline( line, sizeof(line), stdin, "cache errors (0=smart, 1=never, 2=always)?" );
switch( atoi( line )) {
case 0:
default:
printf( "not a valid cache option\n" );
}
-#endif /* NO_CACHE */
+#endif /* LDAP_NOCACHE */
break;
case '?': /* help */
break;
default:
- printf( "Unknown result type 0x%x\n", lm->lm_msgtype );
+ printf( "Unknown result type 0x%lx\n",
+ (unsigned long) lm->lm_msgtype );
print_ldap_result( ld, lm, "unknown" );
}
}
/*
if ( ld->ld_error != NULL && *ld->ld_error != '\0' )
fprintf( stderr, "Additional info: %s\n", ld->ld_error );
- if ( NAME_ERROR( ld->ld_errno ) && ld->ld_matched != NULL )
+ if ( LDAP_NAME_ERROR( ld->ld_errno ) && ld->ld_matched != NULL )
fprintf( stderr, "Matched DN: %s\n", ld->ld_matched );
*/
}
static void
print_search_entry( LDAP *ld, LDAPMessage *res )
{
- BerElement *ber;
- char *a, *dn, *ufn;
- struct berval **vals;
- int i;
LDAPMessage *e;
- for ( e = ldap_first_entry( ld, res ); e != NULLMSG;
- e = ldap_next_entry( ld, e ) ) {
+ for ( e = ldap_first_entry( ld, res ); e != NULL;
+ e = ldap_next_entry( ld, e ) )
+ {
+ BerElement *ber = NULL;
+ char *a, *dn, *ufn;
+
if ( e->lm_msgtype == LDAP_RES_SEARCH_RESULT )
break;
ufn = ldap_dn2ufn( dn );
printf( "\tUFN: %s\n", ufn );
-#ifdef WINSOCK
- ldap_memfree( dn );
- ldap_memfree( ufn );
-#else /* WINSOCK */
+
free( dn );
free( ufn );
-#endif /* WINSOCK */
for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL;
- a = ldap_next_attribute( ld, e, ber ) ) {
+ a = ldap_next_attribute( ld, e, ber ) )
+ {
+ struct berval **vals;
+
printf( "\t\tATTR: %s\n", a );
if ( (vals = ldap_get_values_len( ld, e, a ))
== NULL ) {
printf( "\t\t\t(no values)\n" );
} else {
+ int i;
for ( i = 0; vals[i] != NULL; i++ ) {
int j, nonascii;
nonascii = 0;
- for ( j = 0; j < vals[i]->bv_len; j++ )
+ for ( j = 0; (ber_len_t) j < vals[i]->bv_len; j++ )
if ( !isascii( vals[i]->bv_val[j] ) ) {
nonascii = 1;
break;
if ( nonascii ) {
printf( "\t\t\tlength (%ld) (not ascii)\n", vals[i]->bv_len );
#ifdef BPRINT_NONASCII
- lber_bprint( vals[i]->bv_val,
+ ber_bprint( vals[i]->bv_val,
vals[i]->bv_len );
#endif /* BPRINT_NONASCII */
continue;
ber_bvecfree( vals );
}
}
+
+ if(ber != NULL) {
+ ber_free( ber, 0 );
+ }
}
if ( res->lm_msgtype == LDAP_RES_SEARCH_RESULT
- || res->lm_chain != NULLMSG )
+ || res->lm_chain != NULL )
print_ldap_result( ld, res, "search" );
}
-
-
-#ifdef WINSOCK
-void
-ldap_perror( LDAP *ld, char *s )
-{
- char *errs;
-
- if ( ld == NULL ) {
- perror( s );
- return;
- }
-
- errs = ldap_err2string( ld->ld_errno );
- printf( "%s: %s\n", s, errs == NULL ? "unknown error" : errs );
- if ( ld->ld_error != NULL && *ld->ld_error != '\0' ) {
- printf( "%s: additional info: %s\n", s, ld->ld_error );
- }
-}
-#endif /* WINSOCK */
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ *
+ * tls.c - Handle tls/ssl using SSLeay or OpenSSL.
+ */
+
+#include "portable.h"
+
+#ifdef HAVE_TLS
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#include "ldap-int.h"
+
+#ifdef LDAP_R_COMPILE
+#include <ldap_pvt_thread.h>
+#endif
+
+#ifdef HAVE_OPENSSL_SSL_H
+#include <openssl/ssl.h>
+#elif defined( HAVE_SSL_H )
+#include <ssl.h>
+#endif
+
+static int tls_opt_trace = 1;
+static char *tls_opt_certfile = NULL;
+static char *tls_opt_keyfile = NULL;
+static char *tls_opt_cacertfile = NULL;
+static char *tls_opt_cacertdir = NULL;
+static int tls_opt_require_cert = 0;
+static char *tls_opt_ciphersuite = NULL;
+
+#define HAS_TLS( sb ) ((sb)->sb_io==&tls_io)
+
+static int tls_setup( Sockbuf *sb, void *arg );
+static int tls_remove( Sockbuf *sb );
+static ber_slen_t tls_read( Sockbuf *sb, void *buf, ber_len_t len );
+static ber_slen_t tls_write( Sockbuf *sb, void *buf, ber_len_t len );
+static int tls_close( Sockbuf *sb );
+static int tls_report_error( void );
+
+static Sockbuf_IO tls_io=
+{
+ tls_setup,
+ tls_remove,
+ tls_read,
+ tls_write,
+ tls_close
+};
+
+static void tls_info_cb( SSL *ssl, int where, int ret );
+static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
+static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
+static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length );
+static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir );
+
+static SSL_CTX *tls_def_ctx = NULL;
+
+#ifdef LDAP_R_COMPILE
+/*
+ * provide mutexes for the SSLeay library.
+ */
+static ldap_pvt_thread_mutex_t tls_mutexes[CRYPTO_NUM_LOCKS];
+
+static void tls_locking_cb( int mode, int type, const char *file, int line )
+{
+ if ( mode & CRYPTO_LOCK ) {
+ ldap_pvt_thread_mutex_lock( tls_mutexes+type );
+ } else {
+ ldap_pvt_thread_mutex_unlock( tls_mutexes+type );
+ }
+}
+
+/*
+ * an extra mutex for the default ctx.
+ */
+
+static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
+
+static void tls_init_threads( void )
+{
+ int i;
+
+ for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) {
+ ldap_pvt_thread_mutex_init( tls_mutexes+i );
+ }
+ CRYPTO_set_locking_callback( tls_locking_cb );
+ /* FIXME: the thread id should be added somehow... */
+
+ ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
+}
+#endif /* LDAP_R_COMPILE */
+
+/*
+ * Initialize tls system. Should be called only once.
+ */
+int
+ldap_pvt_tls_init( void )
+{
+ static int tls_initialized = 0;
+
+ if ( tls_initialized )
+ return -1;
+#ifdef LDAP_R_COMPILE
+ tls_init_threads();
+#endif
+ SSL_load_error_strings();
+ SSLeay_add_ssl_algorithms();
+ /* FIXME: mod_ssl does this */
+ X509V3_add_standard_extensions();
+ return 0;
+}
+
+/*
+ * initialize the default context
+ */
+int
+ldap_pvt_tls_init_def_ctx( void )
+{
+ STACK_OF(X509_NAME) *calist;
+
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex );
+#endif
+ if ( tls_def_ctx == NULL ) {
+ tls_def_ctx = SSL_CTX_new( SSLv23_method() );
+ if ( tls_def_ctx == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: could not allocate default ctx.\n",0,0,0);
+ goto error_exit;
+ }
+ if ( tls_opt_ciphersuite &&
+ !SSL_CTX_set_cipher_list( tls_def_ctx,
+ tls_opt_ciphersuite ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: could not set cipher list %s.\n",
+ tls_opt_ciphersuite, 0, 0 );
+ tls_report_error();
+ goto error_exit;
+ }
+ if ( !SSL_CTX_load_verify_locations( tls_def_ctx,
+ tls_opt_cacertfile,
+ tls_opt_cacertdir ) ||
+ !SSL_CTX_set_default_verify_paths( tls_def_ctx ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: could not load verify locations (file:`%s',dir:`%s').\n",
+ tls_opt_cacertfile,tls_opt_cacertdir,0);
+ tls_report_error();
+ goto error_exit;
+ }
+ calist = get_ca_list( tls_opt_cacertfile, tls_opt_cacertdir );
+ if ( !calist ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: could not load client CA list (file:`%s',dir:`%s').\n",
+ tls_opt_cacertfile,tls_opt_cacertdir,0);
+ tls_report_error();
+ goto error_exit;
+ }
+ SSL_CTX_set_client_CA_list( tls_def_ctx, calist );
+ if ( tls_opt_keyfile &&
+ !SSL_CTX_use_PrivateKey_file( tls_def_ctx,
+ tls_opt_keyfile,
+ SSL_FILETYPE_PEM ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: could not use key file `%s'.\n",
+ tls_opt_keyfile,0,0);
+ tls_report_error();
+ goto error_exit;
+ }
+ if ( tls_opt_certfile &&
+ !SSL_CTX_use_certificate_file( tls_def_ctx,
+ tls_opt_certfile,
+ SSL_FILETYPE_PEM ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: could not use certificate `%s'.\n",
+ tls_opt_certfile,0,0);
+ tls_report_error();
+ goto error_exit;
+ }
+ if ( ( tls_opt_certfile || tls_opt_keyfile ) &&
+ !SSL_CTX_check_private_key( tls_def_ctx ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "TLS: private key mismatch.\n",
+ 0,0,0);
+ tls_report_error();
+ goto error_exit;
+ }
+ if ( tls_opt_trace ) {
+ SSL_CTX_set_info_callback( tls_def_ctx, tls_info_cb );
+ }
+ SSL_CTX_set_verify( tls_def_ctx, (tls_opt_require_cert) ?
+ (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) :
+ SSL_VERIFY_PEER, 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 ); */
+ }
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
+#endif
+ return 0;
+error_exit:
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
+#endif
+ return -1;
+}
+
+static STACK_OF(X509_NAME) *
+get_ca_list( char * bundle, char * dir )
+{
+ STACK_OF(X509_NAME) *ca_list = NULL;
+
+ if ( bundle ) {
+ ca_list = SSL_load_client_CA_file( bundle );
+ }
+ /*
+ * FIXME: We have now to go over all files in dir, load them
+ * and add every certificate there to ca_list.
+ */
+ return ca_list;
+}
+
+static SSL *
+alloc_handle( Sockbuf *sb, void *ctx_arg )
+{
+ int err;
+ SSL_CTX *ctx;
+ SSL *ssl;
+
+ if ( ctx_arg ) {
+ ctx = (SSL_CTX *) ctx_arg;
+ } else {
+ if ( ldap_pvt_tls_init_def_ctx() < 0 )
+ return NULL;
+ ctx = tls_def_ctx;
+ }
+
+ ssl = SSL_new( ctx );
+ if ( ssl == NULL ) {
+ Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
+ return NULL;
+ }
+
+ if ( tls_opt_trace ) {
+ SSL_set_info_callback( ssl, tls_info_cb );
+ }
+ sb->sb_iodata = ssl;
+ SSL_set_fd( ssl, ber_pvt_sb_get_desc( sb ) );
+ return ssl;
+}
+
+static void
+update_flags( Sockbuf *sb, SSL * ssl )
+{
+ sb->sb_trans_needs_read = SSL_want_read(ssl) ? 1 : 0;
+ sb->sb_trans_needs_write = SSL_want_write(ssl) ? 1 : 0;
+}
+
+/*
+ * Call this to do a TLS connect on a sockbuf. ctx_arg can be
+ * a SSL_CTX * or NULL, in which case the default ctx is used.
+ *
+ * Return value:
+ *
+ * 0 - Success. Connection is ready for communication.
+ * <0 - Error. Can't create a TLS stream.
+ * >0 - Partial success.
+ * Do a select (using information from lber_pvt_sb_needs_{read,write}
+ * and call again.
+ */
+
+int
+ldap_pvt_tls_connect( Sockbuf *sb, void *ctx_arg )
+{
+ int err;
+ SSL *ssl;
+
+ if ( HAS_TLS( sb ) ) {
+ ssl = (SSL *) sb->sb_iodata;
+ } else {
+ ssl = alloc_handle( sb, ctx_arg );
+ if ( ssl == NULL )
+ return -1;
+ ber_pvt_sb_clear_io( sb );
+ ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
+ }
+
+ err = SSL_connect( ssl );
+
+ if ( err <= 0 ) {
+ if (
+#ifdef EWOULDBLOCK
+ (errno==EWOULDBLOCK) ||
+#endif
+#ifdef EAGAIN
+ (errno==EAGAIN) ||
+#endif
+ (0)) {
+ update_flags( sb, ssl );
+ return 1;
+ }
+ Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
+ ber_pvt_sb_clear_io( sb );
+ ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Call this to do a TLS accept on a sockbuf.
+ * Everything else is the same as with tls_connect.
+ */
+int
+ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
+{
+ int err;
+ SSL *ssl;
+
+ if ( HAS_TLS( sb ) ) {
+ ssl = (SSL *) sb->sb_iodata;
+ } else {
+ ssl = alloc_handle( sb, ctx_arg );
+ if ( ssl == NULL )
+ return -1;
+ ber_pvt_sb_clear_io( sb );
+ ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
+ }
+
+ err = SSL_accept( ssl );
+
+ if ( err <= 0 ) {
+ if ( !SSL_want_nothing( ssl ) ) {
+ update_flags( sb, ssl );
+ return 1;
+ }
+ Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
+ tls_report_error();
+ ber_pvt_sb_clear_io( sb );
+ ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
+ return -1;
+ }
+ return 0;
+}
+
+const char *
+ldap_pvt_tls_get_peer( LDAP *ld )
+{
+}
+
+const char *
+ldap_pvt_tls_get_peer_issuer( LDAP *ld )
+{
+}
+
+int
+ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg )
+{
+ int i;
+
+ switch( option ) {
+ case LDAP_OPT_X_TLS_CACERTFILE:
+ case LDAP_OPT_X_TLS_CACERTDIR:
+ case LDAP_OPT_X_TLS_CERTFILE:
+ case LDAP_OPT_X_TLS_KEYFILE:
+ return ldap_pvt_tls_set_option( NULL, option, (void *) arg );
+ case LDAP_OPT_X_TLS_REQUIRE_CERT:
+ i = ( ( strcasecmp( arg, "on" ) == 0 ) ||
+ ( strcasecmp( arg, "yes" ) == 0) ||
+ ( strcasecmp( arg, "true" ) == 0 ) );
+ return ldap_pvt_tls_set_option( NULL, option, (void *) &i );
+ case LDAP_OPT_X_TLS:
+ if ( strcasecmp( arg, "never" ) == 0 )
+ return ldap_pvt_tls_set_option( lo, option,
+ LDAP_OPT_X_TLS_NEVER );
+ if ( strcasecmp( arg, "demand" ) == 0 )
+ return ldap_pvt_tls_set_option( lo, option,
+ LDAP_OPT_X_TLS_DEMAND );
+ if ( strcasecmp( arg, "allow" ) == 0 )
+ return ldap_pvt_tls_set_option( lo, option,
+ LDAP_OPT_X_TLS_ALLOW );
+ if ( strcasecmp( arg, "try" ) == 0 )
+ return ldap_pvt_tls_set_option( lo, option,
+ LDAP_OPT_X_TLS_TRY );
+ if ( strcasecmp( arg, "hard" ) == 0 )
+ return ldap_pvt_tls_set_option( lo, option,
+ LDAP_OPT_X_TLS_HARD );
+ return -1;
+ default:
+ return -1;
+ }
+}
+
+int
+ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg )
+{
+ switch( option ) {
+ case LDAP_OPT_X_TLS:
+ *(int *)arg = lo->ldo_tls_mode;
+ break;
+ case LDAP_OPT_X_TLS_CERT:
+ if ( lo == NULL )
+ arg = (void *) tls_def_ctx;
+ else
+ arg = lo->ldo_tls_ctx;
+ break;
+ case LDAP_OPT_X_TLS_CACERTFILE:
+ *(char **)arg = tls_opt_cacertfile ?
+ strdup( tls_opt_cacertfile ) : NULL;
+ break;
+ case LDAP_OPT_X_TLS_CACERTDIR:
+ *(char **)arg = tls_opt_cacertdir ?
+ strdup( tls_opt_cacertdir ) : NULL;
+ break;
+ case LDAP_OPT_X_TLS_CERTFILE:
+ *(char **)arg = tls_opt_certfile ?
+ strdup( tls_opt_certfile ) : NULL;
+ break;
+ case LDAP_OPT_X_TLS_KEYFILE:
+ *(char **)arg = tls_opt_keyfile ?
+ strdup( tls_opt_keyfile ) : NULL;
+ break;
+ case LDAP_OPT_X_TLS_REQUIRE_CERT:
+ *(int *)arg = tls_opt_require_cert;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int
+ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg )
+{
+ switch( option ) {
+ case LDAP_OPT_X_TLS:
+ switch( *(int *) arg ) {
+ case LDAP_OPT_X_TLS_NEVER:
+ case LDAP_OPT_X_TLS_DEMAND:
+ case LDAP_OPT_X_TLS_ALLOW:
+ case LDAP_OPT_X_TLS_TRY:
+ case LDAP_OPT_X_TLS_HARD:
+ lo->ldo_tls_mode = *(int *)arg;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case LDAP_OPT_X_TLS_CERT:
+ if ( lo == NULL )
+ tls_def_ctx = (SSL_CTX *) arg;
+ else
+ lo->ldo_tls_ctx = arg;
+ break;
+ }
+ if ( lo != NULL )
+ return -1;
+ switch( option ) {
+ case LDAP_OPT_X_TLS_CACERTFILE:
+ if ( tls_opt_cacertfile ) free( tls_opt_cacertfile );
+ tls_opt_cacertfile = arg ? strdup( (char *) arg ) : NULL;
+ break;
+ case LDAP_OPT_X_TLS_CACERTDIR:
+ if ( tls_opt_cacertdir ) free( tls_opt_cacertdir );
+ tls_opt_cacertdir = arg ? strdup( (char *) arg ) : NULL;
+ break;
+ case LDAP_OPT_X_TLS_CERTFILE:
+ if ( tls_opt_certfile ) free( tls_opt_certfile );
+ tls_opt_certfile = arg ? strdup( (char *) arg ) : NULL;
+ break;
+ case LDAP_OPT_X_TLS_KEYFILE:
+ if ( tls_opt_keyfile ) free( tls_opt_keyfile );
+ tls_opt_keyfile = arg ? strdup( (char *) arg ) : NULL;
+ break;
+ case LDAP_OPT_X_TLS_REQUIRE_CERT:
+ tls_opt_require_cert = * (int *) arg;
+ break;
+ case LDAP_OPT_X_TLS_CIPHER_SUITE:
+ if ( tls_opt_ciphersuite ) free( tls_opt_ciphersuite );
+ tls_opt_ciphersuite = arg ? strdup( (char *) arg ) : NULL;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int
+tls_setup( Sockbuf *sb, void *arg )
+{
+ sb->sb_iodata = arg;
+ return 0;
+}
+
+static int
+tls_remove( Sockbuf *sb )
+{
+ SSL_free( (SSL *) sb->sb_iodata );
+ return 0;
+}
+
+static ber_slen_t
+tls_write( Sockbuf *sb, void *buf, ber_len_t sz )
+{
+ int ret = SSL_write( (SSL *)sb->sb_iodata, buf, sz );
+
+ update_flags(sb, (SSL *)sb->sb_iodata );
+ return ret;
+}
+
+static ber_slen_t
+tls_read( Sockbuf *sb, void *buf, ber_len_t sz )
+{
+ int ret = SSL_read( (SSL *)sb->sb_iodata, buf, sz );
+
+ update_flags(sb, (SSL *)sb->sb_iodata );
+ return ret;
+}
+
+static int
+tls_close( Sockbuf *sb )
+{
+ tcp_close( ber_pvt_sb_get_desc( sb ) );
+ return 0;
+}
+
+/* Derived from openssl/apps/s_cb.c */
+static void
+tls_info_cb( SSL *ssl, int where, int ret )
+{
+ int w;
+ char *op;
+
+ w = where & ~SSL_ST_MASK;
+ if ( w & SSL_ST_CONNECT ) {
+ op = "SSL_connect";
+ } else if ( w & SSL_ST_ACCEPT ) {
+ op = "SSL_accept";
+ } else {
+ op = "undefined";
+ }
+
+ if ( where & SSL_CB_LOOP ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "TLS trace: %s:%s\n",
+ op, SSL_state_string_long( ssl ), 0 );
+ } else if ( where & SSL_CB_ALERT ) {
+ op = ( where & SSL_CB_READ ) ? "read" : "write";
+ Debug( LDAP_DEBUG_TRACE,
+ "TLS trace: SSL3 alert %s:%s:%s\n",
+ op,
+ SSL_alert_type_string_long( ret ),
+ SSL_alert_desc_string_long( ret) );
+ } else if ( where & SSL_CB_EXIT ) {
+ if ( ret == 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "TLS trace: %s:failed in %s\n",
+ op, SSL_state_string_long( ssl ), 0 );
+ } else if ( ret < 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "TLS trace: %s:error in %s\n",
+ op, SSL_state_string_long( ssl ), 0 );
+ }
+ }
+}
+
+static int
+tls_verify_cb( int ok, X509_STORE_CTX *ctx )
+{
+ X509 *cert;
+ int errnum;
+ int errdepth;
+ X509_NAME *subject;
+ X509_NAME *issuer;
+ char *sname;
+ char *iname;
+
+ cert = X509_STORE_CTX_get_current_cert( ctx );
+ errnum = X509_STORE_CTX_get_error( ctx );
+ errdepth = X509_STORE_CTX_get_error_depth( ctx );
+
+ /*
+ * X509_get_*_name return pointers to the internal copies of
+ * those things requested. So do not free them.
+ */
+ subject = X509_get_subject_name( cert );
+ issuer = X509_get_issuer_name( cert );
+ /* X509_NAME_oneline, if passed a NULL buf, allocate memomry */
+ sname = X509_NAME_oneline( subject, NULL, 0 );
+ iname = X509_NAME_oneline( issuer, NULL, 0 );
+ Debug( LDAP_DEBUG_TRACE,
+ "TLS certificate verification: depth: %d, subject: %s, issuer: %s\n",
+ errdepth,
+ sname ? sname : "-unknown-",
+ iname ? iname : "-unknown-" );
+ if ( sname )
+ free ( sname );
+ if ( iname )
+ free ( iname );
+
+ return 1;
+}
+
+/* Inspired by ERR_print_errors in OpenSSL */
+static int
+tls_report_error( void )
+{
+ unsigned long l;
+ char buf[200];
+ const char *file;
+ int line;
+
+ while ( ( l = ERR_get_error_line( &file, &line ) ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "TLS: %s %s:%d\n",
+ ERR_error_string( l, buf ), file, line );
+ }
+}
+
+static RSA *
+tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length )
+{
+ RSA *tmp_rsa;
+
+ /* FIXME: Pregenerate the key on startup */
+ /* FIXME: Who frees the key? */
+ tmp_rsa = RSA_generate_key( key_length, RSA_F4, NULL, NULL );
+
+ if ( !tmp_rsa ) {
+ Debug( LDAP_DEBUG_ANY, "TLS: Failed to generate temporary %d-bit %s RSA key\n",
+ key_length, is_export ? "export" : "domestic", 0 );
+ return NULL;
+ }
+ return tmp_rsa;
+}
+
+static DH *
+tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length )
+{
+ return NULL;
+}
+
+#else
+static int dummy;
+#endif
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* tmplout.c: display template library output routines for LDAP clients
* 12 April 1994 by Mark C Smith
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdlib.h>
-#ifdef MACOS
-#include "macos.h"
-#else /* MACOS */
-#ifdef DOS
-#include <malloc.h>
-#include "msdos.h"
-#else /* DOS */
-#include <sys/time.h>
-#include <sys/types.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
-#endif /* DOS */
-#endif /* MACOS */
+#endif
+
+#include <ldap.h>
+#include <disptmpl.h>
+
+#include "ldap_log.h"
-#ifdef VMS
-#include <sys/socket.h>
-#endif /* VMS */
+#include "ldap-int.h"
+#include "ldap_defaults.h"
-#include "lber.h"
-#include "ldap.h"
-#include "disptmpl.h"
+#define writeptype ldap_writeptype
-#ifdef NEEDPROTOS
-static int do_entry2text( LDAP *ld, char *buf, char *base, LDAPMessage *entry,
+/* local functions */
+static int do_entry2text LDAP_P((
+ LDAP *ld, char *buf, char *base, LDAPMessage *entry,
struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
writeptype writeproc, void *writeparm, char *eol, int rdncount,
- unsigned long opts, char *urlprefix );
-static int do_entry2text_search( LDAP *ld, char *dn, char *base,
+ unsigned long opts, char *urlprefix ));
+static int do_entry2text_search LDAP_P((
+ LDAP *ld, char *dn, char *base,
LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs,
char ***defvals, writeptype writeproc, void *writeparm, char *eol,
- int rdncount, unsigned long opts, char *urlprefix );
-static int do_vals2text( LDAP *ld, char *buf, char **vals, char *label,
+ int rdncount, unsigned long opts, char *urlprefix ));
+static int do_vals2text LDAP_P((
+ LDAP *ld, char *buf, char **vals, char *label,
int labelwidth, unsigned long syntaxid, writeptype writeproc,
- void *writeparm, char *eol, int rdncount, char *urlprefix );
-static int max_label_len( struct ldap_disptmpl *tmpl );
-static int output_label( char *buf, char *label, int width,
- writeptype writeproc, void *writeparm, char *eol, int html );
-static int output_dn( char *buf, char *dn, int width, int rdncount,
- writeptype writeproc, void *writeparm, char *eol, char *urlprefix );
-static void strcat_escaped( char *s1, char *s2 );
-static char *time2text( char *ldtimestr, int dateonly );
-static long gtime( struct tm *tm );
-static int searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry,
+ void *writeparm, char *eol, int rdncount, char *urlprefix ));
+static int max_label_len LDAP_P(( struct ldap_disptmpl *tmpl ));
+static int output_label LDAP_P((
+ char *buf, char *label, int width,
+ writeptype writeproc, void *writeparm, char *eol, int html ));
+static int output_dn LDAP_P((
+ char *buf, char *dn, int width, int rdncount,
+ writeptype writeproc, void *writeparm, char *eol, char *urlprefix ));
+static void strcat_escaped LDAP_P(( char *s1, char *s2 ));
+static char *time2text LDAP_P(( char *ldtimestr, int dateonly ));
+static long gtime LDAP_P(( struct tm *tm ));
+static int searchaction LDAP_P((
+ LDAP *ld, char *buf, char *base, LDAPMessage *entry,
char *dn, struct ldap_tmplitem *tip, int labelwidth, int rdncount,
- writeptype writeproc, void *writeparm, char *eol, char *urlprefix );
-#else /* NEEDPROTOS */
-static int do_entry2text();
-static int do_entry2text_search();
-static int do_vals2text();
-static int max_label_len();
-static int output_label();
-static int output_dn();
-static void strcat_escaped();
-static char *time2text();
-static long gtime();
-static int searchaction();
-#endif /* NEEDPROTOS */
+ writeptype writeproc, void *writeparm, char *eol, char *urlprefix ));
#define DEF_LABEL_WIDTH 15
#define SEARCH_TIMEOUT_SECS 120
#define OCATTRNAME "objectClass"
-#define NONFATAL_LDAP_ERR( err ) ( err == LDAP_SUCCESS || \
- err == LDAP_TIMELIMIT_EXCEEDED || err == LDAP_SIZELIMIT_EXCEEDED )
+#define NONFATAL_LDAP_ERR( err ) ( (err) == LDAP_SUCCESS || \
+ (err) == LDAP_TIMELIMIT_EXCEEDED || (err) == LDAP_SIZELIMIT_EXCEEDED )
#define DEF_LDAP_URL_PREFIX "ldap:///"
}
if ( buf == NULL ) {
- if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
+ if (( buf = LDAP_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) {
ld->ld_errno = LDAP_NO_MEMORY;
- free( dn );
+ LDAP_FREE( dn );
return( ld->ld_errno );
}
freebuf = 1;
sprintf( buf + strlen( buf ),
"%s\">Move Up To <EM>%s</EM></A>%s<BR>",
( vals[ 1 ] == NULL ) ? "??one" : "",
- ( untagged != NULL ) ? untagged + 1 : vals[ 1 ], eol, eol );
+ ( untagged != NULL ) ? untagged + 1 : vals[ 1 ], eol );
(*writeproc)( writeparm, buf, strlen( buf ));
/*
freevals = 1;
}
- if ( islower( *attr )) { /* cosmetic -- upcase attr. name */
- *attr = toupper( *attr );
- }
+ *attr = TOUPPER( (unsigned char) *attr );
err = do_vals2text( ld, buf, vals, attr, labelwidth,
LDAP_SYN_CASEIGNORESTR, writeproc, writeparm, eol,
ldap_value_free( vals );
}
}
+
+ if( ber != NULL) {
+ ber_free( ber, 0 );
+ }
} else {
for ( rowp = ldap_first_tmplrow( tmpl );
- NONFATAL_LDAP_ERR( err ) && rowp != NULLTMPLITEM;
+ NONFATAL_LDAP_ERR( err ) && rowp != NULL;
rowp = ldap_next_tmplrow( tmpl, rowp )) {
- for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM;
+ for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULL;
colp = ldap_next_tmplcol( tmpl, rowp, colp )) {
vals = NULL;
if ( colp->ti_attrname == NULL || ( vals = ldap_get_values( ld,
if ( show && LDAP_GET_SYN_TYPE( colp->ti_syntaxid )
== LDAP_SYN_TYPE_BOOLEAN && LDAP_IS_TMPLITEM_OPTION_SET(
colp, LDAP_DITEM_OPT_HIDEIFFALSE ) &&
- toupper( vals[ 0 ][ 0 ] ) != 'T' ) {
+ TOUPPER( (unsigned char) vals[ 0 ][ 0 ] ) != 'T' ) {
show = 0;
}
if ( colp->ti_syntaxid == LDAP_SYN_SEARCHACTION ) {
if (( opts & LDAP_DISP_OPT_DOSEARCHACTIONS ) != 0 ) {
if ( colp->ti_attrname == NULL || ( show &&
- toupper( vals[ 0 ][ 0 ] ) == 'T' )) {
+ TOUPPER( (unsigned char) vals[ 0 ][ 0 ] ) == 'T' )) {
err = searchaction( ld, buf, base, entry, dn, colp,
labelwidth, rdncount, writeproc,
writeparm, eol, urlprefix );
(*writeproc)( writeparm, buf, strlen( buf ));
}
- free( dn );
+ LDAP_FREE( dn );
if ( freebuf ) {
- free( buf );
+ LDAP_FREE( buf );
}
return( err );
struct ldap_disptmpl *tmpl;
struct timeval timeout;
- if ( dn == NULL && entry == NULLMSG ) {
+ if ( dn == NULL && entry == NULL ) {
ld->ld_errno = LDAP_PARAM_ERROR;
return( ld->ld_errno );
}
timeout.tv_sec = SEARCH_TIMEOUT_SECS;
timeout.tv_usec = 0;
- if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
+ if (( buf = LDAP_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) {
ld->ld_errno = LDAP_NO_MEMORY;
return( ld->ld_errno );
}
if ( dn == NULL ) {
if (( dn = ldap_get_dn( ld, entry )) == NULL ) {
- free( buf );
+ LDAP_FREE( buf );
if ( freetmpls ) {
ldap_free_templates( tmpllist );
}
if ( tmpllist != NULL ) {
- ldmp = NULLMSG;
+ ldmp = NULL;
if ( entry == NULL ) {
char *ocattrs[2];
ocattrs[0] = OCATTRNAME;
ocattrs[1] = NULL;
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_CLDAP( ld ))
err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE,
"objectClass=*", ocattrs, 0, &ldmp, NULL );
else
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE,
"objectClass=*", ocattrs, 0, &timeout, &ldmp );
fetchattrs = ldap_tmplattrs( tmpl, NULL, 1, LDAP_SYN_OPT_DEFER );
}
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_CLDAP( ld ))
err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*",
fetchattrs, 0, &ldmp, NULL );
else
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*",
fetchattrs, 0, &timeout, &ldmp );
if ( freedn ) {
- free( dn );
+ LDAP_FREE( dn );
}
if ( fetchattrs != NULL ) {
ldap_value_free( fetchattrs );
if ( freetmpls ) {
ldap_free_templates( tmpllist );
}
- free( buf );
+ LDAP_FREE( buf );
return( ld->ld_errno );
}
err = do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals,
writeproc, writeparm, eol, rdncount, opts, urlprefix );
- free( buf );
+ LDAP_FREE( buf );
if ( freetmpls ) {
ldap_free_templates( tmpllist );
}
}
if ( buf == NULL ) {
- if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
+ if (( buf = LDAP_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) {
ld->ld_errno = LDAP_NO_MEMORY;
return( ld->ld_errno );
}
p = s = outval;
while (( s = strchr( s, '$' )) != NULL ) {
*s++ = '\0';
- while ( isspace( *s )) {
+ while ( isspace( (unsigned char) *s )) {
++s;
}
if ( html ) {
break;
case LDAP_SYN_BOOLEAN:
- outval = toupper( outval[ 0 ] ) == 'T' ? "TRUE" : "FALSE";
+ outval = TOUPPER((unsigned char) outval[0]) == 'T' ? "TRUE" : "FALSE";
++writeoutval;
break;
case LDAP_SYN_LABELEDURL:
if ( !notascii && ( p = strchr( outval, '$' )) != NULL ) {
*p++ = '\0';
- while ( isspace( *p )) {
+ while ( isspace( (unsigned char) *p )) {
++p;
}
s = outval;
} else if ( !notascii && ( s = strchr( outval, ' ' )) != NULL ) {
*s++ = '\0';
- while ( isspace( *s )) {
+ while ( isspace( (unsigned char) *s )) {
++s;
}
p = outval;
}
if ( freebuf ) {
- free( buf );
+ LDAP_FREE( buf );
}
return( LDAP_SUCCESS );
maxlen = 0;
- for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULLTMPLITEM;
+ for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULL;
rowp = ldap_next_tmplrow( tmpl, rowp )) {
- for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM;
+ for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULL;
colp = ldap_next_tmplcol( tmpl, rowp, colp )) {
if (( len = strlen( colp->ti_label )) > maxlen ) {
maxlen = len;
-#define HREF_CHAR_ACCEPTABLE( c ) (( c >= '-' && c <= '9' ) || \
- ( c >= '@' && c <= 'Z' ) || \
- ( c == '_' ) || \
- ( c >= 'a' && c <= 'z' ))
+#define HREF_CHAR_ACCEPTABLE( c ) (( (c) >= '-' && (c) <= '9' ) || \
+ ( (c) >= '@' && (c) <= 'Z' ) || \
+ ( (c) == '_' ) || \
+ ( (c) >= 'a' && (c) <= 'z' ))
static void
strcat_escaped( char *s1, char *s2 )
}
-#define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
+#define GET2BYTENUM( p ) (( *(p) - '0' ) * 10 + ( *((p)+1) - '0' ))
static char *
time2text( char *ldtimestr, int dateonly )
struct tm t;
char *p, *timestr, zone, *fmterr = "badly formatted time";
time_t gmttime;
+ char timebuf[32];
+ int ndigits;
- memset( (char *)&t, 0, sizeof( struct tm ));
- if ( (int) strlen( ldtimestr ) < 13 ) {
- return( fmterr );
+ if (strlen( ldtimestr ) < 12 ) {
+ return( fmterr );
+ }
+
+ for ( ndigits=0; isdigit((unsigned char) ldtimestr[ndigits]); ndigits++) {
+ ; /* EMPTY */
}
- for ( p = ldtimestr; p - ldtimestr < 12; ++p ) {
- if ( !isdigit( *p )) {
+ if ( ndigits != 12 && ndigits != 14) {
return( fmterr );
}
- }
+
+ memset( (char *)&t, 0, sizeof( struct tm ));
p = ldtimestr;
+
+ if( ndigits == 14) {
+ /* came with a century */
+ /* POSIX says tm_year should be year - 1900 */
+ t.tm_year = 100 * GET2BYTENUM( p ) - 1900;
+ p += 2;
+ }
t.tm_year = GET2BYTENUM( p ); p += 2;
+
t.tm_mon = GET2BYTENUM( p ) - 1; p += 2;
t.tm_mday = GET2BYTENUM( p ); p += 2;
t.tm_hour = GET2BYTENUM( p ); p += 2;
}
gmttime = gtime( &t );
- timestr = ctime( &gmttime );
+ timestr = ldap_pvt_ctime( &gmttime, timebuf );
+
timestr[ strlen( timestr ) - 1 ] = zone; /* replace trailing newline */
if ( dateonly ) {
- strcpy( timestr + 11, timestr + 20 );
+ SAFEMEMCPY( timestr + 11, timestr + 20, strlen( timestr + 20 ) + 1 );
}
return( timestr );
/* gtime.c - inverse gmtime */
-
-#if !defined( MACOS ) && !defined( _WIN32 ) && !defined( DOS )
-#include <sys/time.h>
-#endif /* !MACOS */
-
/* gtime(): the inverse of localtime().
This routine was supplied by Mike Accetta at CMU many years ago.
*/
-static int dmsize[] = {
+static const int dmsize[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
#define dysize(y) \
(((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
-#define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900)
+/*
+ * Y2K YEAR
+ */
+ /* per STDC & POSIX tm_year should be offset by 1900 */
+#define YEAR_POSIX(y) ((y) + 1900)
+
+ /*
+ * year is < 1900, year is offset by 1900
+ */
+#define YEAR_CAREFUL(y) ((y) < 1900 ? (y) + 1900 : (y))
+
+#define YEAR(y) YEAR_CAREFUL(y)
/* \f */
struct ldap_tmplitem *tip, int labelwidth, int rdncount,
writeptype writeproc, void *writeparm, char *eol, char *urlprefix )
{
- int err, lderr, i, count, html;
+ int err = 0, lderr, i, count, html;
char **vals, **members;
char *value, *filtpattern, *attr, *selectname;
char *retattrs[2], filter[ 256 ];
return( LDAP_PARAM_ERROR );
} else if ( strcasecmp( attr, "-dnt" ) == 0 ) {
value = dn;
+ } else if ( strcasecmp( attr, "-dn" ) == 0 ) {
+ value = dn;
} else if (( vals = ldap_get_values( ld, entry, attr )) != NULL ) {
value = vals[ 0 ];
} else {
timeout.tv_sec = SEARCH_TIMEOUT_SECS;
timeout.tv_usec = 0;
-#ifdef CLDAP
+#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_CLDAP( ld ))
lderr = cldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs,
0, &ldmp, NULL );
else
-#endif /* CLDAP */
+#endif /* LDAP_CONNECTIONLESS */
lderr = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs,
0, &timeout, &ldmp );
if ( lderr == LDAP_SUCCESS || NONFATAL_LDAP_ERR( lderr )) {
if (( count = ldap_count_entries( ld, ldmp )) > 0 ) {
- if (( members = (char **)malloc( (count + 1) * sizeof(char *)))
+ if (( members = (char **)LDAP_MALLOC( (count + 1) * sizeof(char *)))
== NULL ) {
err = LDAP_NO_MEMORY;
} else {
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
+
#include <stdio.h>
-#include <sys/types.h>
-#include "lber.h"
-#include "ldap.h"
-#include "disptmpl.h"
-#include "srchpref.h"
-
-#ifdef MACOS
-#include <stdlib.h>
-#include <console.h>
-#endif /* MACOS */
-#ifdef NEEDPROTOS
-void dump_tmpl( struct ldap_disptmpl *tmpl );
-void dump_srchpref( struct ldap_searchobj *sp );
-#else /* NEEDPROTOS */
-void dump_tmpl();
-void dump_srchpref();
-#endif /* NEEDPROTOS */
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/time.h>
+
+#ifdef HAVE_CONSOLE_H
+#include <console.h>
+#endif /* HAVE_CONSOLE_H */
+#include <ldap.h>
+#include <disptmpl.h>
+#include <srchpref.h>
-#define NULLSTRINGIFNULL( s ) ( s == NULL ? "(null)" : s )
+static void dump_tmpl ( struct ldap_disptmpl *tmpl );
+static void dump_srchpref( struct ldap_searchobj *sp );
+#define NULLSTRINGIFNULL( s ) ( (s) == NULL ? "(null)" : (s) )
int
main( int argc, char **argv )
struct ldap_searchobj *so, *sop;
int err;
-#ifdef MACOS
+#ifdef HAVE_CONSOLE_H
ccommand( &argv );
for ( argc = 0; argv[ argc ] != NULL; ++argc ) {
;
if (( err = ldap_init_templates( "ldaptemplates.conf", &templates ))
!= 0 ) {
fprintf( stderr, "ldap_init_templates failed (%d)\n", err );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if (( err = ldap_init_searchprefs( "ldapsearchprefs.conf", &so ))
!= 0 ) {
fprintf( stderr, "ldap_init_searchprefs failed (%d)\n", err );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( argc == 1 ) {
printf( "*** Display Templates:\n" );
- for ( dtp = ldap_first_disptmpl( templates ); dtp != NULLDISPTMPL;
+ for ( dtp = ldap_first_disptmpl( templates ); dtp != NULL;
dtp = ldap_next_disptmpl( templates, dtp )) {
dump_tmpl( dtp );
printf( "\n\n" );
}
printf( "\n\n*** Search Objects:\n" );
- for ( sop = ldap_first_searchobj( so ); sop != NULLSEARCHOBJ;
+ for ( sop = ldap_first_searchobj( so ); sop != NULL;
sop = ldap_next_searchobj( so, sop )) {
dump_srchpref( sop );
printf( "\n\n" );
ldap_free_templates( templates );
ldap_free_searchprefs( so );
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
-static char *syn_name[] = {
+static const char *const syn_name[] = {
"?", "CIS", "MLS", "DN", "BOOL", "JPEG", "JPEGBTN", "FAX", "FAXBTN",
"AUDIOBTN", "TIME", "DATE", "URL", "SEARCHACT", "LINKACT", "ADDDNACT",
"VERIFYACT",
};
-static char *syn_type[] = {
+static const char *const syn_type[] = {
"?", "txt", "img", "?", "bool", "?", "?", "?", "btn",
"?", "?", "?", "?", "?", "?", "?",
"action", "?"
static char *includeattrs[] = { "objectClass", "sn", NULL };
-static char *item_opts[] = {
+static const char *const item_opts[] = {
"ro", "sort", "1val", "hide", "required", "hideiffalse", NULL
};
-static unsigned long item_opt_vals[] = {
+static const unsigned long item_opt_vals[] = {
LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES,
LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY,
LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE,
printf( "\ntemplate items:\n" );
rowcnt = 0;
- for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULLTMPLITEM;
+ for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULL;
rowp = ldap_next_tmplrow( tmpl, rowp )) {
++rowcnt;
colcnt = 0;
- for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM;
+ for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULL;
colp = ldap_next_tmplcol( tmpl, rowp, colp )) {
++colcnt;
printf( " %2d-%d: %s (%s%s", rowcnt, colcnt,
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* unbind.c
*/
-#ifndef lint
-static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+/* An Unbind Request looks like this:
+ *
+ * UnbindRequest ::= NULL
+ *
+ * and has no response.
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#ifdef MACOS
-#include <stdlib.h>
-#include "macos.h"
-#else /* MACOS */
-#if defined( DOS ) || defined( _WIN32 )
-#include "msdos.h"
-#ifdef NCSA
-#include "externs.h"
-#endif /* NCSA */
-#else /* DOS */
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#endif /* DOS */
-#endif /* MACOS */
-
-#include "lber.h"
-#include "ldap.h"
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include "ldap-int.h"
+int
+ldap_unbind_ext(
+ LDAP *ld,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls )
+{
+ return ldap_ld_free( ld, 1, sctrls, cctrls );
+}
int
ldap_unbind( LDAP *ld )
{
Debug( LDAP_DEBUG_TRACE, "ldap_unbind\n", 0, 0, 0 );
- return( ldap_ld_free( ld, 1 ));
+ return( ldap_unbind_ext( ld, NULL, NULL ) );
}
int
-ldap_ld_free( LDAP *ld, int close )
+ldap_ld_free(
+ LDAP *ld,
+ int close,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls )
{
LDAPMessage *lm, *next;
int err = LDAP_SUCCESS;
-#ifdef LDAP_REFERRALS
LDAPRequest *lr, *nextlr;
-#endif /* LDAP_REFERRALS */
- if ( ld->ld_sb.sb_naddr == 0 ) {
-#ifdef LDAP_REFERRALS
+ if ( ld->ld_cldapnaddr == 0 ) {
/* free LDAP structure and outstanding requests/responses */
for ( lr = ld->ld_requests; lr != NULL; lr = nextlr ) {
nextlr = lr->lr_next;
- free_request( ld, lr );
+ ldap_free_request( ld, lr );
}
/* free and unbind from all open connections */
while ( ld->ld_conns != NULL ) {
- free_connection( ld, ld->ld_conns, 1, close );
+ ldap_free_connection( ld, ld->ld_conns, 1, close );
}
-#else /* LDAP_REFERRALS */
- if ( close ) {
- err = send_unbind( ld, &ld->ld_sb );
- close_connection( &ld->ld_sb );
- }
-#endif /* LDAP_REFERRALS */
} else {
int i;
- for ( i = 0; i < ld->ld_sb.sb_naddr; ++i ) {
- free( ld->ld_sb.sb_addrs[ i ] );
+ for ( i = 0; i < ld->ld_cldapnaddr; ++i ) {
+ LDAP_FREE( ld->ld_cldapaddrs[ i ] );
}
- free( ld->ld_sb.sb_addrs );
- free( ld->ld_sb.sb_fromaddr );
+ LDAP_FREE( ld->ld_cldapaddrs );
}
for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
ldap_msgfree( lm );
}
-#ifndef NO_CACHE
- if ( ld->ld_cache != NULL )
+#ifndef LDAP_NOCACHE
+ if ( ld->ld_cache != NULL ) {
ldap_destroy_cache( ld );
-#endif /* !NO_CACHE */
- if ( ld->ld_error != NULL )
- free( ld->ld_error );
- if ( ld->ld_matched != NULL )
- free( ld->ld_matched );
- if ( ld->ld_host != NULL )
- free( ld->ld_host );
- if ( ld->ld_ufnprefix != NULL )
- free( ld->ld_ufnprefix );
- if ( ld->ld_filtd != NULL )
+ ld->ld_cache = NULL;
+ }
+#endif /* !LDAP_NOCACHE */
+
+ if ( ld->ld_error != NULL ) {
+ LDAP_FREE( ld->ld_error );
+ ld->ld_error = NULL;
+ }
+
+ if ( ld->ld_matched != NULL ) {
+ LDAP_FREE( ld->ld_matched );
+ ld->ld_matched = NULL;
+ }
+
+ if ( ld->ld_host != NULL ) {
+ LDAP_FREE( ld->ld_host );
+ ld->ld_host = NULL;
+ }
+
+ if ( ld->ld_ufnprefix != NULL ) {
+ LDAP_FREE( ld->ld_ufnprefix );
+ ld->ld_ufnprefix = NULL;
+ }
+
+ if ( ld->ld_filtd != NULL ) {
ldap_getfilter_free( ld->ld_filtd );
-#ifndef LDAP_REFERRALS
- if ( ld->ld_sb.sb_ber.ber_buf != NULL )
- free( ld->ld_sb.sb_ber.ber_buf );
-#endif /* !LDAP_REFERRALS */
- if ( ld->ld_abandoned != NULL )
- free( ld->ld_abandoned );
+ ld->ld_filtd = NULL;
+ }
+
+ if ( ld->ld_abandoned != NULL ) {
+ LDAP_FREE( ld->ld_abandoned );
+ ld->ld_abandoned = NULL;
+ }
+
+ if ( ld->ld_selectinfo != NULL ) {
+ ldap_free_select_info( ld->ld_selectinfo );
+ ld->ld_selectinfo = NULL;
+ }
+
+ if ( ld->ld_options.ldo_defbase != NULL ) {
+ LDAP_FREE( ld->ld_options.ldo_defbase );
+ ld->ld_options.ldo_defbase = NULL;
+ }
+
+ if ( ld->ld_options.ldo_defhost != NULL ) {
+ LDAP_FREE( ld->ld_options.ldo_defhost );
+ ld->ld_options.ldo_defhost = NULL;
+ }
-#ifdef LDAP_REFERRALS
- if ( ld->ld_selectinfo != NULL )
- free_select_info( ld->ld_selectinfo );
-#endif /* LDAP_REFERRALS */
+ if ( ld->ld_options.ldo_tm_api != NULL ) {
+ LDAP_FREE( ld->ld_options.ldo_tm_api );
+ ld->ld_options.ldo_tm_api = NULL;
+ }
- if ( ld->ld_defhost != NULL )
- free( ld->ld_defhost );
+ if ( ld->ld_options.ldo_tm_net != NULL ) {
+ LDAP_FREE( ld->ld_options.ldo_tm_net );
+ ld->ld_options.ldo_tm_net = NULL;
+ }
- free( (char *) ld );
+ ber_pvt_sb_destroy( &(ld->ld_sb) );
+
+ LDAP_FREE( (char *) ld );
+
+ WSACleanup();
return( err );
}
int
ldap_unbind_s( LDAP *ld )
{
- return( ldap_ld_free( ld, 1 ));
+ return( ldap_unbind_ext( ld, NULL, NULL ) );
}
int
-send_unbind( LDAP *ld, Sockbuf *sb )
+ldap_send_unbind(
+ LDAP *ld,
+ Sockbuf *sb,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls )
{
BerElement *ber;
- Debug( LDAP_DEBUG_TRACE, "send_unbind\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "ldap_send_unbind\n", 0, 0, 0 );
/* create a message to send */
- if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
return( ld->ld_errno );
}
/* fill it in */
- if ( ber_printf( ber, "{itn}", ++ld->ld_msgid,
+ if ( ber_printf( ber, "{itn" /*}*/, ++ld->ld_msgid,
LDAP_REQ_UNBIND ) == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
ber_free( ber, 1 );
return( ld->ld_errno );
}
+ /* Put Server Controls */
+ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
+ ber_free( ber, 1 );
+ return ld->ld_errno;
+ }
+
+ if ( ber_printf( ber, /*{*/ "}", LDAP_REQ_UNBIND ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( ld->ld_errno );
+ }
+
/* send the message */
if ( ber_flush( sb, ber, 1 ) == -1 ) {
ld->ld_errno = LDAP_SERVER_DOWN;
/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
* Copyright (c) 1996 Regents of the University of Michigan.
* All rights reserved.
*
- * LIBLDAP url.c -- LDAP URL related routines
+ * LIBLDAP url.c -- LDAP URL (RFC 2255) related routines
*
* LDAP URLs look like this:
- * l d a p : / / hostport / dn [ ? attributes [ ? scope [ ? filter ] ] ]
+ * ldap[s]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
*
* where:
* attributes is a comma separated list
* scope is one of these three strings: base one sub (default=base)
- * filter is an string-represented filter as in RFC 1558
+ * filter is an string-represented filter as in RFC 2254
*
- * e.g., ldap://ldap.itd.umich.edu/c=US?o,description?one?o=umich
+ * e.g., ldap://host:port/dc=com?o,cn?base?o=openldap?extension
*
* We also tolerate URLs that look like: <ldapurl> and <URL:ldapurl>
*/
-#ifndef lint
-static char copyright[] = "@(#) Copyright (c) 1996 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifdef MACOS
-#include <stdlib.h>
-#include "macos.h"
-#endif /* MACOS */
-
-#if defined( DOS ) || defined( _WIN32 )
-#include <stdlib.h>
-#include <malloc.h>
-#include "msdos.h"
-#endif /* DOS || _WIN32 */
-
-#if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif /* !MACOS && !DOS && !_WIN32 */
-
-#include "lber.h"
-#include "ldap.h"
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include "ldap-int.h"
-#ifdef NEEDPROTOS
-static int skip_url_prefix( char **urlp, int *enclosedp );
-static void hex_unescape( char *s );
-static int unhex( char c );
-#else /* NEEDPROTOS */
-static int skip_url_prefix();
-static void hex_unescape();
-static int unhex();
-#endif /* NEEDPROTOS */
+/* local functions */
+static const char* skip_url_prefix LDAP_P((
+ const char *url,
+ int *enclosedp,
+ int *ldaps ));
int
-ldap_is_ldap_url( char *url )
+ldap_is_ldap_url( LDAP_CONST char *url )
{
int enclosed;
+ int ldaps;
+
+ if( url == NULL ) {
+ return 0;
+ }
+
+ if( skip_url_prefix( url, &enclosed, &ldaps) == NULL ) {
+ return 0;
+ }
- return( url != NULL && skip_url_prefix( &url, &enclosed ));
+ return !ldaps;
}
+int
+ldap_is_ldaps_url( LDAP_CONST char *url )
+{
+ int enclosed;
+ int ldaps;
+
+ if( url == NULL ) {
+ return 0;
+ }
+
+ if( skip_url_prefix( url, &enclosed, &ldaps) == NULL ) {
+ return 0;
+ }
+
+ return ldaps;
+}
-static int
-skip_url_prefix( char **urlp, int *enclosedp )
+static const char*
+skip_url_prefix(
+ const char *url,
+ int *enclosedp,
+ int *ldaps )
{
/*
* return non-zero if this looks like a LDAP URL; zero if not
* if non-zero returned, *urlp will be moved past "ldap://" part of URL
*/
- if ( *urlp == NULL ) {
- return( 0 );
+ const char *p;
+
+ if ( url == NULL ) {
+ return( NULL );
}
+ p = url;
+
/* skip leading '<' (if any) */
- if ( **urlp == '<' ) {
+ if ( *p == '<' ) {
*enclosedp = 1;
- ++*urlp;
+ ++p;
} else {
*enclosedp = 0;
}
/* skip leading "URL:" (if any) */
- if ( strlen( *urlp ) >= LDAP_URL_URLCOLON_LEN && strncasecmp(
- *urlp, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
- *urlp += LDAP_URL_URLCOLON_LEN;
+ if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 )
+ {
+ p += LDAP_URL_URLCOLON_LEN;
}
- /* check for missing "ldap://" prefix */
- if ( strlen( *urlp ) < LDAP_URL_PREFIX_LEN ||
- strncasecmp( *urlp, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) != 0 ) {
- return( 0 );
+ /* check for "ldap://" prefix */
+ if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) {
+ /* skip over "ldap://" prefix and return success */
+ p += LDAP_URL_PREFIX_LEN;
+ *ldaps = 0;
+ return( p );
}
- /* skip over "ldap://" prefix and return success */
- *urlp += LDAP_URL_PREFIX_LEN;
- return( 1 );
+ /* check for "ldaps://" prefix */
+ if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
+ /* skip over "ldaps://" prefix and return success */
+ p += LDAPS_URL_PREFIX_LEN;
+ *ldaps = 1;
+ return( p );
+ }
+
+ return( NULL );
}
+static int str2scope( const char *p )
+{
+ if ( strcasecmp( p, "one" ) == 0 ) {
+ return LDAP_SCOPE_ONELEVEL;
+
+ } else if ( strcasecmp( p, "onetree" ) == 0 ) {
+ return LDAP_SCOPE_ONELEVEL;
+
+ } else if ( strcasecmp( p, "base" ) == 0 ) {
+ return LDAP_SCOPE_BASE;
+
+ } else if ( strcasecmp( p, "sub" ) == 0 ) {
+ return LDAP_SCOPE_SUBTREE;
+
+ } else if ( strcasecmp( p, "subtree" ) == 0 ) {
+ return LDAP_SCOPE_SUBTREE;
+ }
+
+ return( -1 );
+}
+
int
-ldap_url_parse( char *url, LDAPURLDesc **ludpp )
+ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
{
/*
* Pick apart the pieces of an LDAP URL.
*/
LDAPURLDesc *ludp;
- char *attrs, *p, *q;
- int enclosed, i, nattrs;
+ char *p, *q;
+ int i, enclosed, ldaps;
+ const char *url_tmp;
+ char *url;
- Debug( LDAP_DEBUG_TRACE, "ldap_url_parse(%s)\n", url, 0, 0 );
+ if( url_in == NULL && ludpp == NULL ) {
+ return LDAP_URL_ERR_PARAM;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_url_parse(%s)\n", url_in, 0, 0 );
*ludpp = NULL; /* pessimistic */
- if ( !skip_url_prefix( &url, &enclosed )) {
- return( LDAP_URL_ERR_NOTLDAP );
- }
+ url_tmp = skip_url_prefix( url_in, &enclosed, &ldaps );
- /* allocate return struct */
- if (( ludp = (LDAPURLDesc *)calloc( 1, sizeof( LDAPURLDesc )))
- == NULLLDAPURLDESC ) {
- return( LDAP_URL_ERR_MEM );
+ if ( url_tmp == NULL ) {
+ return LDAP_URL_ERR_NOTLDAP;
}
/* make working copy of the remainder of the URL */
- if (( url = strdup( url )) == NULL ) {
- ldap_free_urldesc( ludp );
+ if (( url = LDAP_STRDUP( url_tmp )) == NULL ) {
return( LDAP_URL_ERR_MEM );
}
- if ( enclosed && *((p = url + strlen( url ) - 1)) == '>' ) {
+ if ( enclosed ) {
+ p = &url[strlen(url)-1];
+
+ if( *p != '>' ) {
+ LDAP_FREE( url );
+ return LDAP_URL_ERR_BADENCLOSURE;
+ }
+
*p = '\0';
}
- /* set defaults */
+ /* allocate return struct */
+ ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc ));
+
+ if ( ludp == NULL ) {
+ LDAP_FREE( url );
+ return LDAP_URL_ERR_MEM;
+ }
+
+ ludp->lud_host = NULL;
+ ludp->lud_port = 0;
+ ludp->lud_dn = NULL;
+ ludp->lud_attrs = NULL;
+ ludp->lud_filter = NULL;
+ ludp->lud_ldaps = ldaps;
ludp->lud_scope = LDAP_SCOPE_BASE;
- ludp->lud_filter = "(objectClass=*)";
- /* lud_string is the only malloc'd string space we use */
- ludp->lud_string = url;
+ ludp->lud_filter = LDAP_STRDUP("(objectClass=*)");
- /* scan forward for '/' that marks end of hostport and begin. of dn */
- if (( ludp->lud_dn = strchr( url, '/' )) == NULL ) {
+ if( ludp->lud_filter == NULL ) {
+ LDAP_FREE( url );
ldap_free_urldesc( ludp );
- return( LDAP_URL_ERR_NODN );
+ return LDAP_URL_ERR_MEM;
}
- /* terminate hostport; point to start of dn */
- *ludp->lud_dn++ = '\0';
+ /* scan forward for '/' that marks end of hostport and begin. of dn */
+ p = strchr( url, '/' );
- if (( p = strchr( url, ':' )) != NULL ) {
+ if( p != NULL ) {
+ /* terminate hostport; point to start of dn */
*p++ = '\0';
- ludp->lud_port = atoi( p );
}
- if ( *url == '\0' ) {
- ludp->lud_host = NULL;
- } else {
- ludp->lud_host = url;
- hex_unescape( ludp->lud_host );
- }
-
- /* scan for '?' that marks end of dn and beginning of attributes */
- if (( attrs = strchr( ludp->lud_dn, '?' )) != NULL ) {
- /* terminate dn; point to start of attrs. */
- *attrs++ = '\0';
-
- /* scan for '?' that marks end of attrs and begin. of scope */
- if (( p = strchr( attrs, '?' )) != NULL ) {
- /*
- * terminate attrs; point to start of scope and scan for
- * '?' that marks end of scope and begin. of filter
- */
- *p++ = '\0';
-
- if (( q = strchr( p, '?' )) != NULL ) {
- /* terminate scope; point to start of filter */
- *q++ = '\0';
- if ( *q != '\0' ) {
- ludp->lud_filter = q;
- hex_unescape( ludp->lud_filter );
- }
- }
+ if (( q = strchr( url, ':' )) != NULL ) {
+ *q++ = '\0';
+ ldap_pvt_hex_unescape( q );
- if ( strcasecmp( p, "one" ) == 0 ) {
- ludp->lud_scope = LDAP_SCOPE_ONELEVEL;
- } else if ( strcasecmp( p, "base" ) == 0 ) {
- ludp->lud_scope = LDAP_SCOPE_BASE;
- } else if ( strcasecmp( p, "sub" ) == 0 ) {
- ludp->lud_scope = LDAP_SCOPE_SUBTREE;
- } else if ( *p != '\0' ) {
- ldap_free_urldesc( ludp );
- return( LDAP_URL_ERR_BADSCOPE );
- }
+ if( *q == '\0' ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADURL;
}
+
+ ludp->lud_port = atoi( q );
}
- if ( *ludp->lud_dn == '\0' ) {
- ludp->lud_dn = NULL;
+ ldap_pvt_hex_unescape( url );
+ ludp->lud_host = LDAP_STRDUP( url );
+
+ if( ludp->lud_host == NULL ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_MEM;
+ }
+
+ if( p == NULL ) {
+ LDAP_FREE( url );
+ *ludpp = ludp;
+ return LDAP_URL_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of dn */
+ q = strchr( p, '?' );
+
+ if( q != NULL ) {
+ /* terminate dn part */
+ *q++ = '\0';
+ }
+
+ if( *p != '\0' ) {
+ /* parse dn part */
+ ldap_pvt_hex_unescape( p );
+ ludp->lud_dn = LDAP_STRDUP( p );
} else {
- hex_unescape( ludp->lud_dn );
+ ludp->lud_dn = LDAP_STRDUP( "" );
+ }
+
+ if( ludp->lud_dn == NULL ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_MEM;
+ }
+
+ if( q == NULL ) {
+ /* no more */
+ LDAP_FREE( url );
+ *ludpp = ludp;
+ return LDAP_URL_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of attributes */
+ p = q;
+ q = strchr( p, '?' );
+
+ if( q != NULL ) {
+ /* terminate attributes part */
+ *q++ = '\0';
+ }
+
+ if( *p != '\0' ) {
+ /* parse attributes */
+ ldap_pvt_hex_unescape( p );
+ ludp->lud_attrs = ldap_str2charray( p, "," );
+
+ if( ludp->lud_attrs == NULL ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADATTRS;
+ }
+ }
+
+ if ( q == NULL ) {
+ /* no more */
+ LDAP_FREE( url );
+ *ludpp = ludp;
+ return LDAP_URL_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of scope */
+ p = q;
+ q = strchr( p, '?' );
+
+ if( q != NULL ) {
+ /* terminate the scope part */
+ *q++ = '\0';
}
- /*
- * if attrs list was included, turn it into a null-terminated array
- */
- if ( attrs != NULL && *attrs != '\0' ) {
- for ( nattrs = 1, p = attrs; *p != '\0'; ++p ) {
- if ( *p == ',' ) {
- ++nattrs;
- }
+ if( *p != '\0' ) {
+ /* parse the scope */
+ ldap_pvt_hex_unescape( p );
+ ludp->lud_scope = str2scope( p );
+
+ if( ludp->lud_scope == -1 ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADSCOPE;
}
+ }
+
+ if ( q == NULL ) {
+ /* no more */
+ LDAP_FREE( url );
+ *ludpp = ludp;
+ return LDAP_URL_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of filter */
+ p = q;
+ q = strchr( p, '?' );
- if (( ludp->lud_attrs = (char **)calloc( nattrs + 1,
- sizeof( char * ))) == NULL ) {
+ if( q != NULL ) {
+ /* terminate the filter part */
+ *q++ = '\0';
+ }
+
+ if( *p != '\0' ) {
+ /* parse the filter */
+ ldap_pvt_hex_unescape( p );
+
+ if( ! *p ) {
+ /* missing filter */
+ LDAP_FREE( url );
ldap_free_urldesc( ludp );
- return( LDAP_URL_ERR_MEM );
+ return LDAP_URL_ERR_BADFILTER;
}
- for ( i = 0, p = attrs; i < nattrs; ++i ) {
- ludp->lud_attrs[ i ] = p;
- if (( p = strchr( p, ',' )) != NULL ) {
- *p++ ='\0';
- }
- hex_unescape( ludp->lud_attrs[ i ] );
+ LDAP_FREE( ludp->lud_filter );
+ ludp->lud_filter = LDAP_STRDUP( p );
+
+ if( ludp->lud_filter == NULL ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_MEM;
}
}
- *ludpp = ludp;
+ if ( q == NULL ) {
+ /* no more */
+ LDAP_FREE( url );
+ *ludpp = ludp;
+ return LDAP_URL_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of extensions */
+ p = q;
+ q = strchr( p, '?' );
+
+ if( q != NULL ) {
+ /* extra '?' */
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADURL;
+ }
+
+ /* parse the extensions */
+ ludp->lud_exts = ldap_str2charray( p, "," );
- return( 0 );
+ if( ludp->lud_exts == NULL ) {
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADEXTS;
+ }
+
+ for( i=0; ludp->lud_exts[i] != NULL; i++ ) {
+ ldap_pvt_hex_unescape( ludp->lud_exts[i] );
+ }
+
+ if( i == 0 ) {
+ /* must have 1 or more */
+ ldap_charray_free( ludp->lud_exts );
+ LDAP_FREE( url );
+ ldap_free_urldesc( ludp );
+ return LDAP_URL_ERR_BADEXTS;
+ }
+
+ /* no more */
+ *ludpp = ludp;
+ LDAP_FREE( url );
+ return LDAP_URL_SUCCESS;
}
void
ldap_free_urldesc( LDAPURLDesc *ludp )
{
- if ( ludp != NULLLDAPURLDESC ) {
- if ( ludp->lud_string != NULL ) {
- free( ludp->lud_string );
- }
- if ( ludp->lud_attrs != NULL ) {
- free( ludp->lud_attrs );
- }
- free( ludp );
+ if ( ludp == NULL ) {
+ return;
+ }
+
+ if ( ludp->lud_host != NULL ) {
+ LDAP_FREE( ludp->lud_host );
+ }
+
+ if ( ludp->lud_dn != NULL ) {
+ LDAP_FREE( ludp->lud_dn );
+ }
+
+ if ( ludp->lud_filter != NULL ) {
+ LDAP_FREE( ludp->lud_filter);
}
+
+ if ( ludp->lud_attrs != NULL ) {
+ LDAP_VFREE( ludp->lud_attrs );
+ }
+
+ if ( ludp->lud_exts != NULL ) {
+ LDAP_VFREE( ludp->lud_exts );
+ }
+
+ LDAP_FREE( ludp );
}
int
-ldap_url_search( LDAP *ld, char *url, int attrsonly )
+ldap_url_search( LDAP *ld, LDAP_CONST char *url, int attrsonly )
{
int err;
LDAPURLDesc *ludp;
BerElement *ber;
-#ifdef LDAP_REFERRALS
LDAPServer *srv = NULL;
-#endif /* LDAP_REFERRALS */
if ( ldap_url_parse( url, &ludp ) != 0 ) {
ld->ld_errno = LDAP_PARAM_ERROR;
return( -1 );
}
- if (( ber = ldap_build_search_req( ld, ludp->lud_dn, ludp->lud_scope,
- ludp->lud_filter, ludp->lud_attrs, attrsonly )) == NULLBER ) {
+ ber = ldap_build_search_req( ld, ludp->lud_dn, ludp->lud_scope,
+ ludp->lud_filter, ludp->lud_attrs, attrsonly, NULL, NULL,
+ -1, -1 );
+
+ if ( ber == NULL ) {
return( -1 );
}
err = 0;
if ( ludp->lud_host != NULL || ludp->lud_port != 0 ) {
-#ifdef LDAP_REFERRALS
- if (( srv = (LDAPServer *)calloc( 1, sizeof( LDAPServer )))
- == NULL || ( srv->lsrv_host = strdup( ludp->lud_host ==
+ if (( srv = (LDAPServer *)LDAP_CALLOC( 1, sizeof( LDAPServer )))
+ == NULL || ( srv->lsrv_host = LDAP_STRDUP( ludp->lud_host ==
NULL ? ld->ld_defhost : ludp->lud_host )) == NULL ) {
if ( srv != NULL ) {
- free( srv );
+ LDAP_FREE( srv );
}
ld->ld_errno = LDAP_NO_MEMORY;
err = -1;
} else {
if ( ludp->lud_port == 0 ) {
- srv->lsrv_port = LDAP_PORT;
+ srv->lsrv_port = ldap_int_global_options.ldo_defport;
} else {
- srv->lsrv_port = ludp->lud_port;
+ srv->lsrv_port = ludp->lud_port;
}
}
-#else /* LDAP_REFERRALS */
- ld->ld_errno = LDAP_LOCAL_ERROR;
- err = -1;
-#endif /* LDAP_REFERRALS */
}
if ( err != 0 ) {
ber_free( ber, 1 );
} else {
-#ifdef LDAP_REFERRALS
- err = send_server_request( ld, ber, ld->ld_msgid, NULL, srv,
+ err = ldap_send_server_request( ld, ber, ld->ld_msgid, NULL, srv,
NULL, 1 );
-#else /* LDAP_REFERRALS */
- err = send_initial_request( ld, LDAP_REQ_SEARCH,
- ludp->lud_dn, ber );
-#endif /* LDAP_REFERRALS */
}
ldap_free_urldesc( ludp );
int
-ldap_url_search_st( LDAP *ld, char *url, int attrsonly,
+ldap_url_search_st( LDAP *ld, LDAP_CONST char *url, int attrsonly,
struct timeval *timeout, LDAPMessage **res )
{
int msgid;
int
-ldap_url_search_s( LDAP *ld, char *url, int attrsonly, LDAPMessage **res )
+ldap_url_search_s(
+ LDAP *ld, LDAP_CONST char *url, int attrsonly, LDAPMessage **res )
{
int msgid;
}
-static void
-hex_unescape( char *s )
+void
+ldap_pvt_hex_unescape( char *s )
{
/*
* Remove URL hex escapes from s... done in place. The basic concept for
for ( p = s; *s != '\0'; ++s ) {
if ( *s == '%' ) {
if ( *++s != '\0' ) {
- *p = unhex( *s ) << 4;
+ *p = ldap_pvt_unhex( *s ) << 4;
}
if ( *++s != '\0' ) {
- *p++ += unhex( *s );
+ *p++ += ldap_pvt_unhex( *s );
}
} else {
*p++ = *s;
}
-static int
-unhex( char c )
+int
+ldap_pvt_unhex( int c )
{
return( c >= '0' && c <= '9' ? c - '0'
: c >= 'A' && c <= 'F' ? c - 'A' + 10
--- /dev/null
+##
+## Makefile.in for LDAP -lldap
+##
+LIBRARY = libldap_r.la
+XLIBRARY = ../libldap_r.a
+
+PROGRAMS = apitest ltest ttest
+
+XXDIR = $(srcdir)/../libldap
+XXSRCS = apitest.c test.c tmpltest.c extended.c \
+ bind.c controls.c open.c result.c error.c compare.c search.c \
+ modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \
+ getfilter.c sasl.c sbind.c kbind.c unbind.c friendly.c cldap.c \
+ free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
+ getdn.c getentry.c getattr.c getvalues.c addentry.c \
+ request.c getdxbyname.c os-ip.c url.c charset.c \
+ init.c options.c print.c string.c util-int.c schema.c \
+ charray.c digest.c tls.c
+SRCS = thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \
+ thr_sleep.c thr_stub.c rdwr.c
+OBJS = extended.lo \
+ bind.lo controls.lo open.lo result.lo error.lo compare.lo search.lo \
+ modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \
+ getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \
+ free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \
+ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
+ request.lo getdxbyname.lo os-ip.lo url.lo charset.lo \
+ init.lo options.lo print.lo string.lo util-int.lo schema.lo \
+ thr_posix.lo thr_cthreads.lo thr_thr.lo thr_lwp.lo thr_nt.lo \
+ thr_sleep.lo thr_stub.lo rdwr.lo \
+ charray.lo digest.lo tls.lo
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XDEFS = -DLDAP_R_COMPILE -I$(XXDIR)
+XLIBS = -lldap_r -llber
+XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
+XXXLIBS = $(LTHREAD_LIBS)
+
+.links :
+ @for i in $(XXSRCS); do \
+ $(RM) $$i ; \
+ $(LN_S) $(XXDIR)/$$i . ; \
+ done
+ touch .links
+
+$(XXSRCS) : .links
+
+clean-local: FORCE
+ @$(RM) .links
+
+depend-common: .links
+
+apitest: $(LIBRARY) apitest.o $(LDAP_LIBLBER_DEPEND)
+ $(LTLINK) $(LDFLAGS) -o $@ apitest.o $(LIBS)
+ltest: $(LIBRARY) test.o $(LDAP_LIBLBER_DEPEND)
+ $(LTLINK) $(LDFLAGS) -o $@ test.o $(LIBS)
+ttest: $(LIBRARY) tmpltest.o $(LDAP_LIBLBER_DEPEND)
+ $(LTLINK) $(LDFLAGS) -o $@ tmpltest.o $(LIBS)
+
+install-local: $(CFFILES) FORCE
+ -$(MKDIR) $(libdir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(libdir)
--- /dev/null
+/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+/* thr_cthreads.c - wrapper for mach cthreads */
+
+#include "portable.h"
+
+#if defined( HAVE_MACH_CTHREADS )
+#include "ldap_pvt_thread.h"
+
+/***********************************************************************
+ * *
+ * under NEXTSTEP or OPENSTEP use CThreads *
+ * lukeh@xedoc.com.au *
+ * *
+ ***********************************************************************/
+
+int
+ldap_pvt_thread_initialize( void )
+{
+ return 0;
+}
+
+int
+ldap_pvt_thread_destroy( void )
+{
+ return 0;
+}
+
+int
+ldap_pvt_thread_create( ldap_pvt_thread_t * thread,
+ int detach,
+ void *(*start_routine)( void *), void *arg)
+{
+ *thread = cthread_fork( (cthread_fn_t) start_routine, arg);
+ return ( *thread == NULL ? -1 : 0 );
+}
+
+void
+ldap_pvt_thread_exit( void *retval )
+{
+ cthread_exit( (any_t) retval );
+}
+
+int
+ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
+{
+ void *status;
+ status = (void *) cthread_join ( thread );
+ if (thread_return != NULL)
+ {
+ *thread_return = status;
+ }
+ return 0;
+}
+
+int
+ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
+{
+ return 0;
+}
+
+int
+ldap_pvt_thread_yield( void )
+{
+ cthread_yield();
+ return 0;
+}
+
+int
+ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
+{
+ condition_init( cond );
+ return( 0 );
+}
+
+int
+ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond )
+{
+ condition_clear( cond );
+ return( 0 );
+}
+
+int
+ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
+{
+ condition_signal( cond );
+ return( 0 );
+}
+
+int
+ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
+{
+ condition_broadcast( cond );
+ return( 0 );
+}
+
+int
+ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond,
+ ldap_pvt_thread_mutex_t *mutex )
+{
+ condition_wait( cond, mutex );
+ return( 0 );
+}
+
+int
+ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
+{
+ mutex_init( mutex );
+ mutex->name = NULL;
+ return ( 0 );
+}
+
+int
+ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
+{
+ mutex_clear( mutex );
+ return ( 0 );
+}
+
+int
+ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
+{
+ mutex_lock( mutex );
+ return ( 0 );
+}
+
+int
+ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
+{
+ mutex_unlock( mutex );
+ return ( 0 );
+}
+
+int
+ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
+{
+ return mutex_try_lock( mutex );
+}
+
+#endif /* HAVE_MACH_CTHREADS */
/* ldbm.c - ldap dbm compatibility routines */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
-#include <stdio.h>
-#include "ldbm.h"
+/* Patched for Berkeley DB version 2.0; /KSp; 98/02/23
+ *
+ * - DB version 2.6.4b ; 1998/12/28, /KSp
+ * - DB_DBT_MALLOC ; 1998/03/22, /KSp
+ * - basic implementation; 1998/02/23, /KSp
+ */
-#ifdef LDBM_USE_GDBM
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-/*****************************************************************
- * *
- * use gdbm *
- * *
- *****************************************************************/
+#include "portable.h"
-LDBM
-ldbm_open( char *name, int rw, int mode, int dbcachesize )
-{
- LDBM db;
- struct stat st;
+#ifdef SLAPD_LDBM
- if ( (db = gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
- return( NULL );
- }
- if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
- dbcachesize = (dbcachesize / st.st_blksize);
- gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
- }
+#include <stdio.h>
- return( db );
-}
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/errno.h>
-void
-ldbm_close( LDBM ldbm )
-{
- gdbm_close( ldbm );
-}
+#include "ldbm.h"
+#include "ldap_pvt_thread.h"
-void
-ldbm_sync( LDBM ldbm )
-{
- gdbm_sync( ldbm );
-}
void
ldbm_datum_free( LDBM ldbm, Datum data )
{
- free( data.dptr );
+ if ( data.dptr ) {
+ free( data.dptr );
+ memset( &data, 0, sizeof( Datum ));
+ data.dptr = NULL;
+ }
}
+
Datum
ldbm_datum_dup( LDBM ldbm, Datum data )
{
Datum dup;
+ ldbm_datum_init( dup );
+
if ( data.dsize == 0 ) {
dup.dsize = 0;
dup.dptr = NULL;
return( dup );
}
dup.dsize = data.dsize;
- if ( dup.dptr = (char *) malloc( data.dsize ) )
+ if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL )
memcpy( dup.dptr, data.dptr, data.dsize );
return( dup );
}
-Datum
-ldbm_fetch( LDBM ldbm, Datum key )
+static int ldbm_initialized = 0;
+
+#ifndef HAVE_BERKELEY_DB2
+/* Everything but DB2 is non-reentrant */
+
+static ldap_pvt_thread_mutex_t ldbm_big_mutex;
+#define LDBM_LOCK (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
+#define LDBM_UNLOCK (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
+
+int ldbm_initialize( void )
{
- return( gdbm_fetch( ldbm, key ) );
+ if(ldbm_initialized++) return 1;
+
+ ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
+
+ return 0;
}
-int
-ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
+int ldbm_shutdown( void )
{
- int rc;
+ if( !ldbm_initialized ) return 1;
- rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
- if ( flags & LDBM_SYNC )
- gdbm_sync( ldbm );
- return( rc );
+ ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex );
+
+ return 0;
}
-int
-ldbm_delete( LDBM ldbm, Datum key )
-{
- int rc;
+#else
- rc = gdbm_delete( ldbm, key );
- gdbm_sync( ldbm );
- return( rc );
+void *
+ldbm_malloc( size_t size )
+{
+ return( calloc( 1, size ));
}
-Datum
-ldbm_firstkey( LDBM ldbm )
+#ifdef LDAP_SYSLOG
+#include <ac/syslog.h>
+#endif
+
+static void
+ldbm_db_errcall( const char *prefix, char *message )
{
- return( gdbm_firstkey( ldbm ) );
+#ifdef LDAP_SYSLOG
+ syslog( LOG_INFO, "ldbm_db_errcall(): %s %s", prefix, message );
+#endif
}
-Datum
-ldbm_nextkey( LDBM ldbm, Datum key )
+/* a dbEnv for BERKELEYv2 */
+static DB_ENV ldbm_Env_internal;
+DB_ENV *ldbm_Env = NULL;
+
+/* Berkeley DB 2.x is reentrant */
+#define LDBM_LOCK ((void)0)
+#define LDBM_UNLOCK ((void)0)
+
+int ldbm_initialize( void )
{
- return( gdbm_nextkey( ldbm, key ) );
+ int err;
+ int envFlags;
+
+ if(ldbm_initialized++) return 1;
+
+ memset( &ldbm_Env_internal, 0, sizeof( DB_ENV ));
+ ldbm_Env = &ldbm_Env_internal;
+
+ ldbm_Env->db_errcall = ldbm_db_errcall;
+ ldbm_Env->db_errpfx = "==>";
+
+ envFlags = DB_CREATE | DB_THREAD;
+
+ if ( ( err = db_appinit( NULL, NULL, ldbm_Env, envFlags )) ) {
+ char error[BUFSIZ];
+
+ if ( err < 0 ) {
+ sprintf( error, "%ld\n", (long) err );
+ } else {
+ sprintf( error, "%s\n", strerror( err ));
+ }
+
+#ifdef LDAP_SYSLOG
+ syslog( LOG_INFO,
+ "ldbm_initialize(): FATAL error in db_appinit() : %s\n",
+ error );
+#endif
+ return( 1 );
+ }
+
+ return 0;
}
-int
-ldbm_errno( LDBM ldbm )
+int ldbm_shutdown( void )
{
- return( (int) gdbm_errno );
+ if( !ldbm_initialized ) return 1;
+
+ db_appexit( ldbm_Env );
+
+ return 0;
}
-#else
+#endif
+
#if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
/*****************************************************************
LDBM
ldbm_open( char *name, int rw, int mode, int dbcachesize )
{
- LDBM ret;
+ LDBM ret = NULL;
+
+#ifdef HAVE_BERKELEY_DB2
+ DB_INFO dbinfo;
+
+ memset( &dbinfo, 0, sizeof( dbinfo ));
+
+#if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
+ DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 4
+ /*
+ * BerkeleyDB 2.4 do not allow db_cachesize
+ * to be specified if an DB_ENV is.
+ */
+#else
+ /* set db_cachesize of MPOOL is NOT being used. */
+ if (( ldbm_Env == NULL ) || ( ldbm_Env->mp_info == NULL ))
+ dbinfo.db_cachesize = dbcachesize;
+#endif
+
+ dbinfo.db_pagesize = DEFAULT_DB_PAGE_SIZE;
+ dbinfo.db_malloc = ldbm_malloc;
+
+ LDBM_LOCK;
+ (void) db_open( name, DB_TYPE, rw, mode, ldbm_Env, &dbinfo, &ret );
+ LDBM_UNLOCK;
+
+#else
void *info;
BTREEINFO binfo;
HASHINFO hinfo;
} else {
info = NULL;
}
+
+ LDBM_LOCK;
ret = dbopen( name, rw, mode, DB_TYPE, info );
+ LDBM_UNLOCK;
+
+#endif
+
return( ret );
}
void
ldbm_close( LDBM ldbm )
{
+ LDBM_LOCK;
+#ifdef HAVE_BERKELEY_DB2
+ (*ldbm->close)( ldbm, 0 );
+#else
(*ldbm->close)( ldbm );
+#endif
+ LDBM_UNLOCK;
}
void
ldbm_sync( LDBM ldbm )
{
+ LDBM_LOCK;
(*ldbm->sync)( ldbm, 0 );
-}
-
-void
-ldbm_datum_free( LDBM ldbm, Datum data )
-{
- free( data.dptr );
-}
-
-Datum
-ldbm_datum_dup( LDBM ldbm, Datum data )
-{
- Datum dup;
-
- if ( data.dsize == 0 ) {
- dup.dsize = 0;
- dup.dptr = NULL;
-
- return( dup );
- }
- dup.dsize = data.dsize;
- if ( dup.dptr = (char *) malloc( data.dsize ) )
- memcpy( dup.dptr, data.dptr, data.dsize );
-
- return( dup );
+ LDBM_UNLOCK;
}
Datum
Datum data;
int rc;
+ LDBM_LOCK;
+
+#ifdef HAVE_BERKELEY_DB2
+ ldbm_datum_init( data );
+
+ data.flags = DB_DBT_MALLOC;
+
+ if ( (rc = (*ldbm->get)( ldbm, NULL, &key, &data, 0 )) != 0 ) {
+ ldbm_datum_free( ldbm, data );
+#else
if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) {
+ /* Berkeley DB 1.85 don't malloc the data for us */
+ /* duplicate it for to ensure reentrancy */
data = ldbm_datum_dup( ldbm, data );
} else {
+#endif
data.dptr = NULL;
data.dsize = 0;
}
+ LDBM_UNLOCK;
+
return( data );
}
{
int rc;
+ LDBM_LOCK;
+
+#ifdef HAVE_BERKELEY_DB2
+ rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
+ rc = (-1 ) * rc;
+#else
rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC );
+#endif
+
if ( flags & LDBM_SYNC )
(*ldbm->sync)( ldbm, 0 );
+
+ LDBM_UNLOCK;
+
return( rc );
}
{
int rc;
+ LDBM_LOCK;
+
+#ifdef HAVE_BERKELEY_DB2
+ rc = (*ldbm->del)( ldbm, NULL, &key, 0 );
+ rc = (-1 ) * rc;
+#else
rc = (*ldbm->del)( ldbm, &key, 0 );
+#endif
(*ldbm->sync)( ldbm, 0 );
+
+ LDBM_UNLOCK;
+
return( rc );
}
Datum
-ldbm_firstkey( LDBM ldbm )
+ldbm_firstkey( LDBM ldbm, LDBMCursor **dbch )
{
Datum key, data;
+
+#ifdef HAVE_BERKELEY_DB2
+ LDBMCursor *dbci;
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ key.flags = data.flags = DB_DBT_MALLOC;
+
+ LDBM_LOCK;
+
+ /* acquire a cursor for the DB */
+
+# if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
+ DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
+
+ if ( (*ldbm->cursor)( ldbm, NULL, &dbci ))
+
+# else
+ if ( (*ldbm->cursor)( ldbm, NULL, &dbci, 0 ))
+# endif
+ {
+ key.dptr = NULL;
+ return( key );
+ } else {
+ *dbch = dbci;
+ if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
+ ldbm_datum_free( ldbm, data );
+ }
+ else {
+#else
int rc;
+ LDBM_LOCK;
+
if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
key = ldbm_datum_dup( ldbm, key );
- } else {
+ }
+ else {
+#endif
key.dptr = NULL;
key.dsize = 0;
}
+
+#ifdef HAVE_BERKELEY_DB2
+ }
+#endif
+
+ LDBM_UNLOCK;
+
return( key );
}
Datum
-ldbm_nextkey( LDBM ldbm, Datum key )
+ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
{
Datum data;
+
+#ifdef HAVE_BERKELEY_DB2
+ ldbm_datum_init( data );
+
+ ldbm_datum_free( ldbm, key );
+ key.flags = data.flags = DB_DBT_MALLOC;
+
+ LDBM_LOCK;
+
+ if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
+ ldbm_datum_free( ldbm, data );
+ }
+ else {
+#else
int rc;
+ LDBM_LOCK;
+
if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
key = ldbm_datum_dup( ldbm, key );
- } else {
+ }
+ else {
+#endif
key.dptr = NULL;
key.dsize = 0;
}
+
+ LDBM_UNLOCK;
+
return( key );
}
return( errno );
}
-#else
+#elif defined( HAVE_GDBM )
-#ifdef LDBM_USE_NDBM
+#ifdef HAVE_ST_BLKSIZE
+#include <sys/stat.h>
+#endif
/*****************************************************************
* *
- * if no gdbm, fall back to using ndbm, the standard unix thing *
+ * use gdbm *
* *
*****************************************************************/
-/* ARGSUSED */
LDBM
ldbm_open( char *name, int rw, int mode, int dbcachesize )
{
- return( dbm_open( name, rw, mode ) );
+ LDBM db;
+#ifdef HAVE_ST_BLKSIZE
+ struct stat st;
+#endif
+
+ LDBM_LOCK;
+
+ if ( (db = gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
+ LDBM_UNLOCK;
+ return( NULL );
+ }
+
+#ifdef HAVE_ST_BLKSIZE
+ if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
+ dbcachesize = (dbcachesize / st.st_blksize);
+ gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
+ }
+#else
+ dbcachesize = (dbcachesize / 4096);
+ gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
+#endif
+
+ LDBM_UNLOCK;
+
+ return( db );
}
void
ldbm_close( LDBM ldbm )
{
- dbm_close( ldbm );
+ LDBM_LOCK;
+ gdbm_close( ldbm );
+ LDBM_UNLOCK;
}
-/* ARGSUSED */
void
ldbm_sync( LDBM ldbm )
{
- return;
+ LDBM_LOCK;
+ gdbm_sync( ldbm );
+ LDBM_UNLOCK;
+}
+
+Datum
+ldbm_fetch( LDBM ldbm, Datum key )
+{
+ Datum d;
+
+ LDBM_LOCK;
+ d = gdbm_fetch( ldbm, key );
+ LDBM_UNLOCK;
+
+ return d;
}
+int
+ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
+{
+ int rc;
+
+ LDBM_LOCK;
+ rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
+ if ( flags & LDBM_SYNC )
+ gdbm_sync( ldbm );
+ LDBM_UNLOCK;
+
+ return( rc );
+}
+
+int
+ldbm_delete( LDBM ldbm, Datum key )
+{
+ int rc;
+
+ LDBM_LOCK;
+ rc = gdbm_delete( ldbm, key );
+ gdbm_sync( ldbm );
+ LDBM_UNLOCK;
+
+ return( rc );
+}
+
+Datum
+ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
+{
+ Datum d;
+
+ LDBM_LOCK;
+ d = gdbm_firstkey( ldbm );
+ LDBM_UNLOCK;
+
+ return d;
+}
+
+Datum
+ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
+{
+ Datum d;
+
+ LDBM_LOCK;
+ d = gdbm_nextkey( ldbm, key );
+ LDBM_UNLOCK;
+
+ return d;
+}
+
+int
+ldbm_errno( LDBM ldbm )
+{
+ int err;
+
+ LDBM_LOCK;
+ err = gdbm_errno;
+ LDBM_UNLOCK;
+
+ return( err );
+}
+
+#elif HAVE_MDBM
+
+/* MMAPED DBM HASHING DATABASE */
+
+#include <ac/string.h>
+
+/* #define MDBM_DEBUG */
+
+#ifdef MDBM_DEBUG
+#include <stdio.h>
+#endif
+
+#define NO_NULL_KEY
+/* #define MDBM_CHAIN */
+
+#ifdef MDBM_CHAIN
+
+/* Use chaining */
+
+
+#define mdbm_store mdbm_chain_store
+#define mdbm_fetch mdbm_chain_fetch
+#define mdbm_delete mdbm_chain_delete
+#define mdbm_first mdbm_chain_first
+#define mdbm_next mdbm_chain_next
+
+#endif
+
+#define MDBM_PG_SZ (4*1024)
+
+/*****************************************************************
+ * *
+ * use mdbm *
+ * *
+ *****************************************************************/
+
+LDBM
+ldbm_open( char *name, int rw, int mode, int dbcachesize )
+{
+ LDBM db;
+
+#ifdef MDBM_DEBUG
+ fprintf( stdout,
+ "==>(mdbm)ldbm_open(name=%s,rw=%x,mode=%x,cachesize=%d)\n",
+ name ? name : "NULL", rw, mode, dbcachesize );
+ fflush( stdout );
+#endif
+
+ LDBM_LOCK; /* We need locking here, this is the only non-thread
+ * safe function we have.
+ */
+
+ if ( (db = mdbm_open( name, rw, mode, MDBM_PG_SZ )) == NULL ) {
+
+ LDBM_UNLOCK;
+#ifdef MDBM_DEBUG
+ fprintf( stdout, "<==(mdbm)ldbm_open(db=NULL)\n" );
+ fflush( stdout );
+#endif
+ return( NULL );
+
+ }
+
+#ifdef MDBM_CHAIN
+ (void)mdbm_set_chain(db);
+#endif
+
+ LDBM_UNLOCK;
+
+#ifdef MDBM_DEBUG
+ fprintf( stdout, "<==(mdbm)ldbm_open(db=%p)\n", db );
+ fflush( stdout );
+#endif
+
+ return( db );
+
+}
+
+
+
+
void
-ldbm_datum_free( LDBM ldbm, Datum data )
+ldbm_close( LDBM ldbm )
{
- return;
+
+ /* Open and close are not reentrant so we need to use locks here */
+
+#ifdef MDBM_DEBUG
+ fprintf( stdout,
+ "==>(mdbm)ldbm_close(db=%p)\n", ldbm );
+ fflush( stdout );
+#endif
+
+ LDBM_LOCK;
+ mdbm_close( ldbm );
+ LDBM_UNLOCK;
+
+#ifdef MDBM_DEBUG
+ fprintf( stdout, "<==(mdbm)ldbm_close()\n" );
+ fflush( stdout );
+#endif
+
+}
+
+
+
+
+void
+ldbm_sync( LDBM ldbm )
+{
+
+ /* XXX: Not sure if this is re-entrant need to check code, if so
+ * you can leave LOCKS out.
+ */
+
+ LDBM_LOCK;
+ mdbm_sync( ldbm );
+ LDBM_UNLOCK;
+
}
+
+#define MAX_MDBM_RETRY 5
+
Datum
-ldbm_datum_dup( LDBM ldbm, Datum data )
+ldbm_fetch( LDBM ldbm, Datum key )
{
- Datum dup;
+ Datum d;
+ kvpair k;
+ int retry = 0;
- if ( data.dsize == 0 ) {
- dup.dsize = 0;
- dup.dptr = NULL;
+ /* This hack is needed because MDBM does not take keys
+ * which begin with NULL when working in the chaining
+ * mode.
+ */
- return( dup );
+ /* LDBM_LOCK; */
+
+#ifdef NO_NULL_KEY
+ k.key.dsize = key.dsize + 1;
+ k.key.dptr = malloc(k.key.dsize);
+ *(k.key.dptr) = 'l';
+ memcpy( (void *)(k.key.dptr + 1), key.dptr, key.dsize );
+#else
+ k.key = key;
+#endif
+
+ k.val.dptr = NULL;
+ k.val.dsize = 0;
+
+ do {
+
+ d = mdbm_fetch( ldbm, k );
+
+ if ( d.dsize > 0 ) {
+
+ if ( k.val.dptr != NULL ) {
+
+ free( k.val.dptr );
+
+ }
+
+ if ( (k.val.dptr = malloc( d.dsize )) != NULL ) {
+
+ k.val.dsize = d.dsize;
+ d = mdbm_fetch( ldbm, k );
+
+ } else {
+
+ d.dsize = 0;
+ break;
+
+ }
+
+ }/* if ( d.dsize > 0 ) */
+
+ } while ((d.dsize > k.val.dsize) && (++retry < MAX_MDBM_RETRY));
+
+ /* LDBM_UNLOCK; */
+
+#ifdef NO_NULL_KEY
+ free(k.key.dptr);
+#endif
+
+ return d;
+
+}
+
+
+
+
+int
+ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
+{
+ int rc;
+ Datum int_key; /* Internal key */
+
+#ifdef MDBM_DEBUG
+ fprintf( stdout,
+ "==>(mdbm)ldbm_store(db=%p, key(dptr=%p,sz=%d), data(dptr=%p,sz=%d), flags=%x)\n",
+ ldbm, key.dptr, key.dsize, data.dptr, data.dsize, flags );
+ fflush( stdout );
+#endif
+
+ /* LDBM_LOCK; */
+
+#ifdef NO_NULL_KEY
+ int_key.dsize = key.dsize + 1;
+ int_key.dptr = malloc( int_key.dsize );
+ *(int_key.dptr) = 'l'; /* Must not be NULL !*/
+ memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
+#else
+ int_key = key;
+#endif
+
+ rc = mdbm_store( ldbm, int_key, data, flags );
+ if ( flags & LDBM_SYNC ) {
+ mdbm_sync( ldbm );
}
- dup.dsize = data.dsize;
- if ( dup.dptr = (char *) malloc( data.dsize ) )
- memcpy( dup.dptr, data.dptr, data.dsize );
- return( dup );
+ /* LDBM_UNLOCK; */
+
+#ifdef MDBM_DEBUG
+ fprintf( stdout, "<==(mdbm)ldbm_store(rc=%d)\n", rc );
+ fflush( stdout );
+#endif
+
+#ifdef NO_NULL_KEY
+ free(int_key.dptr);
+#endif
+
+ return( rc );
+
+}
+
+
+
+int
+ldbm_delete( LDBM ldbm, Datum key )
+{
+ int rc;
+ Datum int_key;
+
+ /* LDBM_LOCK; */
+
+#ifdef NO_NULL_KEY
+ int_key.dsize = key.dsize + 1;
+ int_key.dptr = malloc(int_key.dsize);
+ *(int_key.dptr) = 'l';
+ memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
+#else
+ int_key = key;
+#endif
+
+ rc = mdbm_delete( ldbm, int_key );
+
+ /* LDBM_UNLOCK; */
+#ifdef NO_NULL_KEY
+ free(int_key.dptr);
+#endif
+
+ return( rc );
+
+}
+
+
+
+
+static Datum
+ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) )
+{
+
+ kvpair out;
+ kvpair in;
+ Datum ret;
+ size_t sz = MDBM_PAGE_SIZE(ldbm);
+#ifdef NO_NULL_KEY
+ int delta = 1;
+#else
+ int delta = 0;
+#endif
+
+ /* LDBM_LOCK; */
+
+ in.key.dsize = sz; /* Assume first key in one pg */
+ in.key.dptr = malloc(sz);
+
+ in.val.dptr = NULL; /* Don't need data just key */
+ in.val.dsize = 0;
+
+ ret.dptr = NULL;
+ ret.dsize = NULL;
+
+ out = fptr( ldbm, in );
+
+ if (out.key.dsize > 0) {
+
+ ret.dsize = out.key.dsize - delta;
+ if ((ret.dptr = (char *)malloc(ret.dsize)) == NULL) {
+
+ ret.dsize = 0;
+ ret.dptr = NULL;
+
+ } else {
+
+ memcpy(ret.dptr, (void *)(out.key.dptr + delta),
+ ret.dsize );
+
+ }
+
+ }
+
+ /* LDBM_UNLOCK; */
+
+ free(in.key.dptr);
+
+ return ret;
+
+}
+
+
+
+
+Datum
+ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
+{
+
+ return ldbm_get_next( ldbm, mdbm_first );
+
+}
+
+
+
+
+Datum
+ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
+{
+
+ /* XXX:
+ * don't know if this will affect the LDAP server opertaion
+ * but mdbm cannot take and input key.
+ */
+
+ return ldbm_get_next( ldbm, mdbm_next );
+
+}
+
+int
+ldbm_errno( LDBM ldbm )
+{
+ /* XXX: best we can do with current mdbm interface */
+ return( errno );
+
+}
+
+
+
+
+#elif defined( HAVE_NDBM )
+
+/*****************************************************************
+ * *
+ * if no gdbm or mdbm, fall back to using ndbm, the standard unix thing *
+ * *
+ *****************************************************************/
+
+/* ARGSUSED */
+LDBM
+ldbm_open( char *name, int rw, int mode, int dbcachesize )
+{
+ LDBM ldbm;
+
+ LDBM_LOCK;
+ ldbm = dbm_open( name, rw, mode );
+ LDBM_UNLOCK;
+
+ return( ldbm );
+}
+
+void
+ldbm_close( LDBM ldbm )
+{
+ LDBM_LOCK;
+ dbm_close( ldbm );
+ LDBM_UNLOCK;
+}
+
+/* ARGSUSED */
+void
+ldbm_sync( LDBM ldbm )
+{
+ return;
}
Datum
ldbm_fetch( LDBM ldbm, Datum key )
{
- return( ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) ) );
+ Datum d;
+
+ LDBM_LOCK;
+ d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
+ LDBM_UNLOCK;
+
+ return d;
}
int
ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
{
- return( dbm_store( ldbm, key, data, flags ) );
+ int rc;
+
+ LDBM_LOCK;
+ rc = dbm_store( ldbm, key, data, flags );
+ LDBM_UNLOCK;
+
+ return rc;
}
int
ldbm_delete( LDBM ldbm, Datum key )
{
- return( dbm_delete( ldbm, key ) );
+ int rc;
+
+ LDBM_LOCK;
+ rc = dbm_delete( ldbm, key );
+ LDBM_UNLOCK;
+
+ return rc;
}
Datum
-ldbm_firstkey( LDBM ldbm )
+ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
{
- return( dbm_firstkey( ldbm ) );
+ Datum d;
+
+ LDBM_LOCK;
+ d = dbm_firstkey( ldbm );
+ LDBM_UNLOCK;
+
+ return d;
}
Datum
-ldbm_nextkey( LDBM ldbm, Datum key )
+ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
{
- return( dbm_nextkey( ldbm ) );
+ Datum d;
+
+ LDBM_LOCK;
+ d = dbm_nextkey( ldbm );
+ LDBM_UNLOCK;
+
+ return d;
}
int
ldbm_errno( LDBM ldbm )
{
- return( dbm_error( ldbm ) );
+ int err;
+
+ LDBM_LOCK;
+ err = dbm_error( ldbm );
+ LDBM_UNLOCK;
+
+ return err;
}
#endif /* ndbm */
-#endif /* db */
-#endif /* gdbm */
+#endif /* ldbm */
--- /dev/null
+##
+## Makefile for -lldif
+##
+
+LIBRARY = libldif.a
+SRCS = line64.c fetch.c
+OBJS = line64.o fetch.o
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
--- /dev/null
+/* line64.c - routines for dealing with the slapd line format */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
+#ifdef HAVE_FETCH
+#include <fetch.h>
+#endif
+
+#include "ldap_log.h"
+#include "lber_pvt.h"
+#include "ldap_pvt.h"
+#include "ldap_config.h"
+#include "ldif.h"
+
+int
+ldif_fetch_url(
+ LDAP_CONST char *urlstr,
+ char **valuep,
+ ber_len_t *vlenp
+)
+{
+ FILE *url;
+ char buffer[1024];
+ char *p = NULL;
+ size_t total;
+ size_t bytes;
+
+ *valuep = NULL;
+ *vlenp = 0;
+
+#ifdef HAVE_FETCH
+ url = fetchGetURL( (char*) urlstr, "" );
+
+#else
+ if( strncasecmp( "file://", urlstr, sizeof("file://")-1 ) == 0 ) {
+ p = strchr( &urlstr[sizeof("file://")-1], '/' );
+ if( p == NULL ) {
+ return -1;
+ }
+
+ if( *p != *LDAP_DIRSEP ) {
+ /* skip over false root */
+ p++;
+ }
+
+ p = ber_strdup( p );
+ ldap_pvt_hex_unescape( p );
+
+ url = fopen( p, "r" );
+
+ } else {
+ return -1;
+ }
+#endif
+
+ if( url == NULL ) {
+ return -1;
+ }
+
+ total = 0;
+
+ while( bytes = fread( buffer, 1, sizeof(buffer), url ) ) {
+ char *newp = ber_memrealloc( p, total + bytes );
+ if( newp == NULL ) {
+ ber_memfree( p );
+ fclose( url );
+ return -1;
+ }
+ newp = p;
+ SAFEMEMCPY( &p[total], buffer, bytes );
+ total += bytes;
+ }
+
+ fclose( url );
+
+ *valuep = p;
+ *vlenp = total;
+
+ return 0;
+}
+
--- /dev/null
+# Microsoft Developer Studio Project File - Name="libldif" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=libldif - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libldif.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libldif.mak" CFG="libldif - Win32 Single Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libldif - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "libldif - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "libldif - Win32 Single Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "libldif - Win32 Single Release" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF "$(CFG)" == "libldif - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release"
+# PROP Intermediate_Dir "Release\libldif"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\Release\oldif32.lib"
+
+!ELSEIF "$(CFG)" == "libldif - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug"
+# PROP Intermediate_Dir "Debug\libldif"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\Debug\oldif32.lib"
+
+!ELSEIF "$(CFG)" == "libldif - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "libldif_"
+# PROP BASE Intermediate_Dir "libldif_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\SDebug"
+# PROP Intermediate_Dir "SDebug\libldif"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\Debug\oldif32.lib"
+# ADD LIB32 /nologo /out:"..\SDebug\oldif32.lib"
+
+!ELSEIF "$(CFG)" == "libldif - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "libldif0"
+# PROP BASE Intermediate_Dir "libldif0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\SRelease"
+# PROP Intermediate_Dir "SRelease\libldif"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\Release\oldif32.lib"
+# ADD LIB32 /nologo /out:"..\SRelease\oldif32.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "libldif - Win32 Release"
+# Name "libldif - Win32 Debug"
+# Name "libldif - Win32 Single Debug"
+# Name "libldif - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\fetch.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\ldif.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\line64.c
+# End Source File
+# End Target
+# End Project
/* line64.c - routines for dealing with the slapd line format */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "lber.h"
-#include "ldap.h"
+
+#include <ac/stdlib.h>
+#include <ac/ctype.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
+int ldif_debug = 0;
+
+#include "ldap_log.h"
+#include "lber_pvt.h"
#include "ldif.h"
#define RIGHT2 0x03
#define RIGHT4 0x0f
#define CONTINUED_LINE_MARKER '\001'
-static char nib2b64[0x40f] =
+#ifdef CSRIMALLOC
+#define ber_memalloc malloc
+#define ber_memcalloc calloc
+#define ber_memrealloc realloc
+#define ber_strdup strdup
+#endif
+
+static const char nib2b64[0x40] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static unsigned char b642nib[0x80] = {
+static const unsigned char b642nib[0x80] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
/*
- * str_parse_line - takes a line of the form "type:[:] value" and splits it
+ * ldif_parse_line - takes a line of the form "type:[:] value" and splits it
* into components "type" and "value". if a double colon separates type from
* value, then value is encoded in base 64, and parse_line un-decodes it
* (in place) before returning.
*/
int
-str_parse_line(
- char *line,
- char **type,
- char **value,
- int *vlen
+ldif_parse_line(
+ LDAP_CONST char *line,
+ char **typep,
+ char **valuep,
+ ber_len_t *vlenp
)
{
- char *p, *s, *d, *byte, *stop;
+ char *s, *p, *d;
char nib;
- int i, b64;
+ int b64, url;
+ char *freeme, *type, *value;
+ ber_len_t vlen;
+
+ *typep = NULL;
+ *valuep = NULL;
+ *vlenp = 0;
/* skip any leading space */
- while ( isspace( *line ) ) {
+ while ( isspace( (unsigned char) *line ) ) {
line++;
}
- *type = line;
- for ( s = line; *s && *s != ':'; s++ )
- ; /* NULL */
- if ( *s == '\0' ) {
- Debug( LDAP_DEBUG_PARSE, "parse_line missing ':'\n", 0, 0, 0 );
+ freeme = ber_strdup( line );
+
+ if( freeme == NULL ) {
+ ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+ "ldif_parse_line: line malloc failed\n");
+ return( -1 );
+ }
+
+ type = freeme;
+
+ s = strchr( type, ':' );
+
+ if ( s == NULL ) {
+ ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
+ "ldif_parse_line: missing ':' after %s\n",
+ type );
+ ber_memfree( freeme );
return( -1 );
}
/* trim any space between type and : */
- for ( p = s - 1; p > line && isspace( *p ); p-- ) {
+ for ( p = &s[-1]; p > type && isspace( * (unsigned char *) p ); p-- ) {
*p = '\0';
}
*s++ = '\0';
- /* check for double : - indicates base 64 encoded value */
- if ( *s == ':' ) {
+ if ( *s == '\0' ) {
+ /* no value */
+ value = NULL;
+ vlen = 0;
+ goto done;
+ }
+
+ url = 0;
+ b64 = 0;
+
+ if ( *s == '<' ) {
+ s++;
+ url = 1;
+ } else if ( *s == ':' ) {
+ /* base 64 encoded value */
s++;
b64 = 1;
-
- /* single : - normally encoded value */
- } else {
- b64 = 0;
}
/* skip space between : and value */
- while ( isspace( *s ) ) {
+ while ( isspace( (unsigned char) *s ) ) {
s++;
}
/* if no value is present, error out */
if ( *s == '\0' ) {
- Debug( LDAP_DEBUG_PARSE, "parse_line missing value\n", 0,0,0 );
- return( -1 );
+ ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
+ "ldif_parse_line: %s missing %svalue\n", type,
+ url ? "URL " : b64 ? "base64 " : "" );
+ value = NULL;
+ vlen = 0;
+ goto done;
}
/* check for continued line markers that should be deleted */
}
*d = '\0';
- *value = s;
if ( b64 ) {
- stop = strchr( s, '\0' );
- byte = s;
- for ( p = s, *vlen = 0; p < stop; p += 4, *vlen += 3 ) {
- for ( i = 0; i < 3; i++ ) {
+ char *byte = s;
+
+ value = s;
+
+ for ( p = s, vlen = 0; p < d; p += 4, vlen += 3 ) {
+ int i;
+ for ( i = 0; i < 4; i++ ) {
if ( p[i] != '=' && (p[i] & 0x80 ||
b642nib[ p[i] & 0x7f ] > 0x3f) ) {
- Debug( LDAP_DEBUG_ANY,
- "invalid base 64 encoding char (%c) 0x%x\n",
- p[i], p[i], 0 );
+ ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+ "ldif_parse_line: %s: invalid base64 encoding"
+ " char (%c) 0x%x\n",
+ type, p[i], p[i] );
+ ber_memfree( freeme );
return( -1 );
}
}
byte[1] = (nib & RIGHT4) << 4;
/* third digit */
if ( p[2] == '=' ) {
- *vlen += 1;
+ vlen += 1;
break;
}
nib = b642nib[ p[2] & 0x7f ];
byte[2] = (nib & RIGHT2) << 6;
/* fourth digit */
if ( p[3] == '=' ) {
- *vlen += 2;
+ vlen += 2;
break;
}
nib = b642nib[ p[3] & 0x7f ];
byte += 3;
}
- s[ *vlen ] = '\0';
+ s[ vlen ] = '\0';
+
+ } else if ( url ) {
+ if( ldif_fetch_url( s, &value, &vlen ) ) {
+ ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+ "ldif_parse_line: %s: URL \"%s\" fetch failed\n",
+ type, s );
+ ber_memfree( freeme );
+ return( -1 );
+ }
+
} else {
- *vlen = (int) (d - s);
+ value = s;
+ vlen = (int) (d - s);
}
+done:
+ type = ber_strdup( type );
+
+ if( type == NULL ) {
+ ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+ "ldif_parse_line: type malloc failed\n");
+ ber_memfree( freeme );
+ return( -1 );
+ }
+
+ if( !url && value != NULL ) {
+ value = ber_strdup( value );
+ if( value == NULL ) {
+ ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+ "ldif_parse_line: value malloc failed\n");
+ ber_memfree( type );
+ ber_memfree( freeme );
+ return( -1 );
+ }
+ }
+
+ ber_memfree( freeme );
+
+ *typep = type;
+ *valuep = value;
+ *vlenp = vlen;
+
return( 0 );
}
/*
- * str_getline - return the next "line" (minus newline) of input from a
+ * ldif_getline - return the next "line" (minus newline) of input from a
* string buffer of lines separated by newlines, terminated by \n\n
* or \0. this routine handles continued lines, bundling them into
* a single big line before returning. if a line begins with a white
* space character, it is a continuation of the previous line. the white
* space character (nb: only one char), and preceeding newline are changed
* into CONTINUED_LINE_MARKER chars, to be deleted later by the
- * str_parse_line() routine above.
+ * ldif_parse_line() routine above.
*
- * it takes a pointer to a pointer to the buffer on the first call,
+ * ldif_getline will skip over any line which starts '#'.
+ *
+ * ldif_getline takes a pointer to a pointer to the buffer on the first call,
* which it updates and must be supplied on subsequent calls.
*/
char *
-str_getline( char **next )
+ldif_getline( char **next )
{
- char *l;
- char c;
+ char *line;
- if ( *next == NULL || **next == '\n' || **next == '\0' ) {
- return( NULL );
- }
+ do {
+ if ( *next == NULL || **next == '\n' || **next == '\0' ) {
+ return( NULL );
+ }
+
+ line = *next;
+
+ while ( (*next = strchr( *next, '\n' )) != NULL ) {
+ unsigned char c = *(*next + 1);
+
+ if ( !isspace( c ) || c == '\n' ) {
+ *(*next)++ = '\0';
+ break;
+ }
- l = *next;
- while ( (*next = strchr( *next, '\n' )) != NULL ) {
- c = *(*next + 1);
- if ( isspace( c ) && c != '\n' ) {
**next = CONTINUED_LINE_MARKER;
*(*next+1) = CONTINUED_LINE_MARKER;
- } else {
- *(*next)++ = '\0';
- break;
+ (*next)++;
}
- *(*next)++;
- }
+ } while( *line == '#' );
- return( l );
+ return( line );
}
+/* compatibility with U-Mich off by one bug */
+#define LDIF_KLUDGE 1
+
void
-put_type_and_value( char **out, char *t, char *val, int vlen )
+ldif_sput(
+ char **out,
+ int type,
+ LDAP_CONST char *name,
+ LDAP_CONST char *val,
+ ber_len_t vlen )
{
- unsigned char *byte, *p, *stop;
+ const unsigned char *byte, *stop;
unsigned char buf[3];
unsigned long bits;
char *save;
- int i, b64, pad, len, savelen;
- len = 0;
+ int pad;
+
+ ber_len_t savelen;
+ ber_len_t len=0;
+ ber_len_t i;
+
+ /* prefix */
+ switch( type ) {
+ case LDIF_PUT_COMMENT:
+ if( name != NULL ) break;
- /* put the type + ": " */
- for ( p = (unsigned char *) t; *p; p++, len++ ) {
- *(*out)++ = *p;
+ *(*out)++ = '#';
+ len++;
+
+ if( vlen ) {
+ *(*out)++ = ' ';
+ len++;
+ break;
+ }
+
+ /* no value, fall-thru */
+
+ case LDIF_PUT_SEP:
+ *(*out)++ = '\n';
+ return;
}
- *(*out)++ = ':';
- len++;
+
+ /* name (attribute type) */
+ if( name != NULL ) {
+ /* put the name + ":" */
+ for ( i=0 ; name[i]; i++ ) {
+ *(*out)++ = name[i];
+ len++;
+ }
+
+ if( type != LDIF_PUT_COMMENT ) {
+ *(*out)++ = ':';
+ len++;
+ }
+
+#ifdef LDAP_DEBUG
+ } else {
+ assert( type == LDIF_PUT_COMMENT );
+#endif
+ }
+
+ switch( type ) {
+ case LDIF_PUT_NOVALUE:
+ *(*out)++ = '\n';
+ return;
+
+ case LDIF_PUT_URL: /* url value */
+ *(*out)++ = '<';
+ len++;
+ break;
+
+ case LDIF_PUT_B64: /* base64 value */
+ *(*out)++ = ':';
+ len++;
+ break;
+ }
+
+ switch( type ) {
+ case LDIF_PUT_TEXT:
+ case LDIF_PUT_URL:
+ case LDIF_PUT_B64:
+ *(*out)++ = ' ';
+ len++;
+ /* fall-thru */
+
+ case LDIF_PUT_COMMENT:
+ /* pre-encoded names */
+ for ( i=0; i < vlen; i++ ) {
+ if ( len > LDIF_LINE_WIDTH ) {
+ *(*out)++ = '\n';
+ *(*out)++ = ' ';
+ len = 1;
+ }
+
+ *(*out)++ = val[i];
+ len++;
+ }
+ *(*out)++ = '\n';
+ return;
+ }
+
save = *out;
savelen = len;
+
*(*out)++ = ' ';
- b64 = 0;
+ len++;
- stop = (unsigned char *) (val + vlen);
- if ( isascii( val[0] ) && isspace( val[0] ) || val[0] == ':' ) {
- b64 = 1;
- } else {
- for ( byte = (unsigned char *) val; byte < stop;
- byte++, len++ ) {
+ if( vlen == 0 ) {
+ *(*out)++ = '\n';
+ return;
+ }
+
+ stop = (const unsigned char *) (val + vlen);
+
+ if ( type == LDIF_PUT_VALUE
+ && isgraph( val[0] ) && val[0] != ':' && val[0] != '<'
+ && isgraph( val[vlen-1] )
+ && strcasecmp( name, "userPassword" ) != 0 /* encode userPassword */
+ && strcasecmp( name, "2.5.4.35" ) != 0 /* encode userPassword */
+ ) {
+ int b64 = 0;
+
+ for ( byte = (const unsigned char *) val; byte < stop;
+ byte++, len++ )
+ {
if ( !isascii( *byte ) || !isprint( *byte ) ) {
b64 = 1;
break;
}
- if ( len > LINE_WIDTH ) {
+ if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
*(*out)++ = '\n';
*(*out)++ = ' ';
len = 1;
}
*(*out)++ = *byte;
}
+
+ if( !b64 ) {
+ *(*out)++ = '\n';
+ return;
+ }
}
- if ( b64 ) {
- *out = save;
- *(*out)++ = ':';
- *(*out)++ = ' ';
- len = savelen + 2;
- /* convert to base 64 (3 bytes => 4 base 64 digits) */
- for ( byte = (unsigned char *) val; byte < stop - 2;
- byte += 3 ) {
- bits = (byte[0] & 0xff) << 16;
- bits |= (byte[1] & 0xff) << 8;
- bits |= (byte[2] & 0xff);
-
- for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
- if ( len > LINE_WIDTH ) {
- *(*out)++ = '\n';
- *(*out)++ = ' ';
- len = 1;
- }
- /* get b64 digit from high order 6 bits */
- *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
+ *out = save;
+ *(*out)++ = ':';
+ *(*out)++ = ' ';
+ len = savelen + 2;
+
+ /* convert to base 64 (3 bytes => 4 base 64 digits) */
+ for ( byte = (const unsigned char *) val;
+ byte < stop - 2;
+ byte += 3 )
+ {
+ bits = (byte[0] & 0xff) << 16;
+ bits |= (byte[1] & 0xff) << 8;
+ bits |= (byte[2] & 0xff);
+
+ for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
+ if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
+ *(*out)++ = '\n';
+ *(*out)++ = ' ';
+ len = 1;
}
+
+ /* get b64 digit from high order 6 bits */
+ *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
}
+ }
- /* add padding if necessary */
- if ( byte < stop ) {
- for ( i = 0; byte + i < stop; i++ ) {
- buf[i] = byte[i];
- }
- for ( pad = 0; i < 3; i++, pad++ ) {
- buf[i] = '\0';
+ /* add padding if necessary */
+ if ( byte < stop ) {
+ for ( i = 0; byte + i < stop; i++ ) {
+ buf[i] = byte[i];
+ }
+ for ( pad = 0; i < 3; i++, pad++ ) {
+ buf[i] = '\0';
+ }
+ byte = buf;
+ bits = (byte[0] & 0xff) << 16;
+ bits |= (byte[1] & 0xff) << 8;
+ bits |= (byte[2] & 0xff);
+
+ for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
+ if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
+ *(*out)++ = '\n';
+ *(*out)++ = ' ';
+ len = 1;
}
- byte = buf;
- bits = (byte[0] & 0xff) << 16;
- bits |= (byte[1] & 0xff) << 8;
- bits |= (byte[2] & 0xff);
-
- for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
- if ( len > LINE_WIDTH ) {
- *(*out)++ = '\n';
- *(*out)++ = ' ';
- len = 1;
- }
+ if( i + pad < 4 ) {
/* get b64 digit from low order 6 bits */
*(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
- }
-
- for ( ; pad > 0; pad-- ) {
- *(*out - pad) = '=';
+ } else {
+ *(*out)++ = '=';
}
}
}
}
-char *
-ldif_type_and_value( char *type, char *val, int vlen )
/*
- * return malloc'd, zero-terminated LDIF line
+ * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
*/
+char *
+ldif_put(
+ int type,
+ LDAP_CONST char *name,
+ LDAP_CONST char *val,
+ ber_len_t vlen )
{
char *buf, *p;
- int tlen;
+ ber_len_t nlen;
+
+ nlen = ( name != NULL ) ? strlen( name ) : 0;
- tlen = strlen( type );
- if (( buf = (char *)malloc( LDIF_SIZE_NEEDED( tlen, vlen ) + 1 )) !=
- NULL ) {
+ buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED( nlen, vlen ) + 1 );
+
+ if ( buf == NULL ) {
+ ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+ "ldif_type_and_value: malloc failed!" );
+ return NULL;
}
p = buf;
- put_type_and_value( &p, type, val, vlen );
+ ldif_sput( &p, type, name, val, vlen );
*p = '\0';
return( buf );
}
+
+int ldif_is_not_printable(
+ LDAP_CONST char *val,
+ ber_len_t vlen )
+{
+ if( vlen == 0 || val == NULL ) {
+ return -1;
+ }
+
+ if( isgraph( val[0] ) && val[0] != ':' && val[0] != '<' &&
+ isgraph( val[vlen-1] ) )
+ {
+ ber_len_t i;
+
+ for ( i = 0; val[i]; i++ ) {
+ if ( !isascii( val[i] ) || !isprint( val[i] ) ) {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * slap_read_ldif - read an ldif record. Return 1 for success, 0 for EOF.
+ */
+int
+ldif_read_record(
+ FILE *fp,
+ int *lno, /* ptr to line number counter */
+ char **bufp, /* ptr to malloced output buffer */
+ int *buflenp ) /* ptr to length of *bufp */
+{
+ char linebuf[BUFSIZ], *line;
+ ber_len_t lcur = 0, len, linesize;
+ int last_ch = '\n', found_entry = 0, stop;
+
+ line = linebuf;
+ linesize = sizeof( linebuf );
+
+ for ( stop = feof( fp ); !stop; last_ch = line[len-1] ) {
+ if ( fgets( line, linesize, fp ) == NULL ) {
+ stop = 1;
+ /* Add \n in case the file does not end with newline */
+ line = "\n";
+ }
+ len = strlen( line );
+
+ if ( last_ch == '\n' ) {
+ (*lno)++;
+
+ if ( line[0] == '\n' ) {
+ if ( !found_entry )
+ continue;
+ break;
+ }
+
+ if ( !found_entry ) {
+ /* Found a new entry */
+ found_entry = 1;
+
+ if ( isdigit( (unsigned char) line[0] ) ) {
+ /* skip index */
+ continue;
+ }
+ }
+ }
+
+ if ( *buflenp - lcur <= len ) {
+ char *nbufp = ber_memrealloc( *bufp, *buflenp += len + BUFSIZ );
+ if( nbufp == NULL ) {
+ return 0;
+ }
+ *bufp = nbufp;
+ }
+ strcpy( *bufp + lcur, line );
+ lcur += len;
+ }
+
+ return( found_entry );
+}
--- /dev/null
+##
+## Makefile for -lutil
+##
+
+LIBRARY = liblutil.a
+SRCS = base64.c debug.c detach.c \
+ md5.c passwd.c sha1.c getpass.c lockf.c utils.c
+OBJS = base64.o debug.o detach.o \
+ md5.o passwd.o sha1.o getpass.o lockf.o utils.o \
+ @LIBOBJS@
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * Modified by Kurt D. Zeilenga for inclusion into OpenLDAP
+ */
+
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "portable.h"
+
+#include <ac/assert.h>
+#include <ac/stdlib.h>
+#include <ac/ctype.h>
+#include <ac/string.h>
+
+/* include socket.h to get sys/types.h and/or winsock2.h */
+#include <ac/socket.h>
+
+#include "lutil.h"
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+lutil_b64_ntop(
+ u_char const *src,
+ size_t srclength,
+ char *target,
+ size_t targsize)
+{
+ size_t datalength = 0;
+ u_char input[3];
+ u_char output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ assert(output[0] < 64);
+ assert(output[1] < 64);
+ assert(output[2] < 64);
+ assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ assert(output[0] < 64);
+ assert(output[1] < 64);
+ assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return (datalength);
+}
+
+/* skips all whitespace anywhere.
+ converts characters, four at a time, starting at (or after)
+ src from base - 64 numbers into three 8 bit bytes in the target area.
+ it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+lutil_b64_pton(
+ char const *src,
+ u_char *target,
+ size_t targsize)
+{
+ int tarindex, state, ch;
+ char *pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isascii(ch) && isspace(ch)) /* Skip whitespace anywhere. */
+ continue;
+
+ if (ch == Pad64)
+ break;
+
+ pos = strchr(Base64, ch);
+ if (pos == 0) /* A non-base64 character. */
+ return (-1);
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex+1] = ((pos - Base64) & 0x0f)
+ << 4 ;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex+1] = ((pos - Base64) & 0x03)
+ << 6;
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == Pad64) { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state) {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return (-1);
+
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (! (isascii(ch) && isspace(ch)))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != Pad64)
+ return (-1);
+ ch = *src++; /* Skip the = */
+ /* Fall through to "single trailing =" case. */
+ /* FALLTHROUGH */
+
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (! (isascii(ch) && isspace(ch)))
+ return (-1);
+
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (target && target[tarindex] != 0)
+ return (-1);
+ }
+ } else {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return (-1);
+ }
+
+ return (tarindex);
+}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdarg.h>
+#include <ac/string.h>
+
+#include "ldap_log.h"
+#include "ldap_defaults.h"
+
+static FILE *log_file;
+
+int lutil_debug_file( FILE *file )
+{
+ log_file = log_file;
+
+ return 0;
+}
+
+void (lutil_debug)( int level, int debug, const char *fmt, ... )
+{
+ char buffer[4096];
+ va_list vl;
+
+ if ( !(level & debug ) )
+ return;
+
+#ifdef HAVE_WINSOCK
+ if( log_file == NULL )
+ {
+ log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
+
+ if ( log_file == NULL )
+ log_file = fopen( "openldap.log", "w" );
+
+ if ( log_file == NULL )
+ return;
+ }
+#endif
+
+ va_start( vl, fmt );
+
+#ifdef HAVE_VSNPRINTF
+ vsnprintf( buffer, sizeof(buffer), fmt, vl );
+#else
+ vsprintf( buffer, fmt, vl );
+#endif
+ buffer[sizeof(buffer)-1] = '\0';
+
+ if( log_file != NULL ) {
+ fputs( buffer, log_file );
+ fflush( log_file );
+ }
+
+ fputs( buffer, stderr );
+ va_end( vl );
+}
--- /dev/null
+/*
+ * Copyright (c) 1990, 1994 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#include "lutil.h"
+
+void
+lutil_detach( int debug, int do_close )
+{
+ int i, sd, nbits;
+
+#ifdef HAVE_SYSCONF
+ nbits = sysconf( _SC_OPEN_MAX );
+#elif HAVE_GETDTABLESIZE
+ nbits = getdtablesize();
+#else
+ nbits = FD_SETSIZE;
+#endif
+
+#ifdef FD_SETSIZE
+ if ( nbits > FD_SETSIZE ) {
+ nbits = FD_SETSIZE;
+ }
+#endif /* FD_SETSIZE */
+
+ if ( debug == 0 ) {
+ for ( i = 0; i < 5; i++ ) {
+#if HAVE_THR
+ switch ( fork1() )
+#else
+ switch ( fork() )
+#endif
+ {
+ case -1:
+ sleep( 5 );
+ continue;
+
+ case 0:
+ break;
+
+ default:
+ _exit( EXIT_SUCCESS );
+ }
+ break;
+ }
+
+ if ( do_close )
+ for ( i = 3; i < nbits; i++ )
+ close( i );
+
+ (void) chdir( "/" );
+
+ if ( (sd = open( "/dev/null", O_RDWR )) == -1 ) {
+ perror( "/dev/null" );
+ exit( EXIT_FAILURE );
+ }
+ for ( i = 0; i < 3; i++ )
+ if ( sd != i && isatty( i ) )
+ (void) dup2( sd, i );
+ if ( sd > 2 )
+ close( sd );
+
+#ifdef HAVE_SETSID
+ (void) setsid();
+#elif TIOCNOTTY
+ if ( (sd = open( "/dev/tty", O_RDWR )) != -1 ) {
+ (void) ioctl( sd, TIOCNOTTY, NULL );
+ (void) close( sd );
+ }
+#endif
+ }
+
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ getopt.c
+
+ modified public-domain AT&T getopt(3)
+ modified by Kurt Zeilenga for inclusion into OpenLDAP
+*/
+
+#include "portable.h"
+
+#ifndef HAVE_GETOPT
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+int opterr = 1;
+int optind = 1;
+int optopt;
+char * optarg;
+
+static void ERR (char * const argv[], const char * s, char c)
+{
+ char errbuf[2];
+
+#ifdef DF_TRACE_DEBUG
+printf("DF_TRACE_DEBUG: static void ERR () in getopt.c\n");
+#endif
+ if (opterr)
+ {
+ errbuf[0] = c;
+ errbuf[1] = '\n';
+ (void) write(STDERR_FILENO,argv[0],strlen(argv[0]));
+ (void) write(STDERR_FILENO,s,strlen(s));
+ (void) write(STDERR_FILENO,errbuf,sizeof errbuf);
+ }
+}
+
+int getopt (int argc, char * const argv [], const char * opts)
+{
+ static int sp = 1, error = (int) '?';
+ static char sw = '-', eos = '\0', arg = ':';
+ register char c, * cp;
+
+#ifdef DF_TRACE_DEBUG
+printf("DF_TRACE_DEBUG: int getopt () in getopt.c\n");
+#endif
+ if (sp == 1)
+ if (optind >= argc || argv[optind][0] != sw
+ || argv[optind][1] == eos)
+ return EOF;
+ else if (strcmp(argv[optind],"--") == 0)
+ {
+ optind++;
+ return EOF;
+ }
+ c = argv[optind][sp];
+ optopt = (int) c;
+ if (c == arg || (cp = strchr(opts,c)) == NULL)
+ {
+ ERR(argv,": illegal option--",c);
+ if (argv[optind][++sp] == eos)
+ {
+ optind++;
+ sp = 1;
+ }
+ return error;
+ }
+ else if (*++cp == arg)
+ {
+ if (argv[optind][sp + 1] != eos)
+ optarg = &argv[optind++][sp + 1];
+ else if (++optind >= argc)
+ {
+ ERR(argv,": option requires an argument--",c);
+ sp = 1;
+ return error;
+ }
+ else
+ optarg = argv[optind++];
+ sp = 1;
+ }
+ else
+ {
+ if (argv[optind][++sp] == eos)
+ {
+ sp = 1;
+ optind++;
+ }
+ optarg = NULL;
+ }
+ return (int) c;
+}
+#endif /* HAVE_GETOPT */
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * Copyright (c) 1992, 1993 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#include "portable.h"
+
+#ifndef HAVE_GETPASS
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/termios.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_CONIO_H
+#include <conio.h>
+#endif
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "ldap_defaults.h"
+
+char *
+getpass( const char *prompt )
+{
+#if !defined(HAVE_POSIX_TERMIOS) && !defined(HAVE_SGTTY_H)
+ static char buf[256];
+ int i, c;
+
+#ifdef DEBUG
+ if (debug & D_TRACE)
+ printf("->getpass(%s)\n", prompt);
+#endif
+ printf("%s", prompt);
+ i = 0;
+ while ( (c = getch()) != EOF && c != '\n' && c != '\r' )
+ buf[i++] = c;
+ if ( c == EOF )
+ return( NULL );
+ buf[i] = '\0';
+ return (buf);
+#else
+ int no_pass = 0;
+ char i, j, k;
+ TERMIO_TYPE ttyb;
+ TERMFLAG_TYPE flags;
+ static char pbuf[513];
+ register char *p;
+ register int c;
+ FILE *fi;
+ RETSIGTYPE (*sig)( int sig );
+
+#ifdef DEBUG
+ if (debug & D_TRACE)
+ printf("->getpass(%s)\n", prompt);
+#endif
+ /*
+ * Stolen from the getpass() routine. Can't use the plain
+ * getpass() for two reasons. One is that LDAP passwords
+ * can be really, really long - much longer than 8 chars.
+ * The second is that we like to make this client available
+ * out of inetd via a Merit asynch port, and we need to be
+ * able to do telnet control codes to turn on and off line
+ * blanking.
+ */
+ if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
+ fi = stdin;
+ else
+ setbuf(fi, (char *)NULL);
+ sig = SIGNAL (SIGINT, SIG_IGN);
+ if (fi != stdin) {
+ if (GETATTR(fileno(fi), &ttyb) < 0)
+ perror("GETATTR");
+ }
+ flags = GETFLAGS( ttyb );
+ SETFLAGS( ttyb, flags & ~ECHO );
+ if (fi != stdin) {
+ if (SETATTR(fileno(fi), &ttyb) < 0)
+ perror("SETATTR");
+ }
+
+ /* blank the line if through Merit */
+ if (fi == stdin) {
+ printf("%c%c%c", 255, 251, 1);
+ fflush(stdout);
+ (void) scanf("%c%c%c", &i, &j, &k);
+ fflush(stdin);
+ }
+
+ /* fetch the password */
+ fprintf(stdout, "%s", prompt);
+ fflush(stdout);
+ for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) {
+ if (c == '\r')
+ break;
+ if (p < &pbuf[512])
+ *p++ = c;
+ }
+ if (c == EOF)
+ no_pass = 1;
+ else {
+ *p = '\0';
+ if (*(p - 1) == '\r')
+ *(p - 1) = '\0';
+ }
+
+ /* unblank the line if through Merit */
+ if (fi == stdin) {
+ printf("%c%c%c", 255, 252, 1);
+ fflush(stdout);
+ (void) scanf("%c%c%c", &i, &j, &k);
+ fflush(stdin);
+ printf("\n"); fflush(stdout);
+ }
+ fprintf(stdout, "\n");
+ fflush(stdout);
+
+ /* tidy up */
+ SETFLAGS( ttyb, flags );
+ if (fi != stdin) {
+ if (SETATTR(fileno(fi), &ttyb) < 0)
+ perror("SETATTR");
+ }
+ (void) SIGNAL (SIGINT, sig);
+ if (fi != stdin)
+ (void) fclose(fi);
+ else
+ i = getchar();
+ if (no_pass)
+ return(NULL);
+ return(pbuf);
+#endif
+}
+
+#endif /* !HAVE_GETPASS */
--- /dev/null
+# Microsoft Developer Studio Project File - Name="liblutil" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=liblutil - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "liblutil.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "liblutil.mak" CFG="liblutil - Win32 Single Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "liblutil - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "liblutil - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "liblutil - Win32 Single Debug" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE "liblutil - Win32 Single Release" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF "$(CFG)" == "liblutil - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release"
+# PROP Intermediate_Dir "Release\liblutil"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\Release\olutil32.lib"
+
+!ELSEIF "$(CFG)" == "liblutil - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug"
+# PROP Intermediate_Dir "Debug\liblutil"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\Debug\olutil32.lib"
+
+!ELSEIF "$(CFG)" == "liblutil - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "liblutil"
+# PROP BASE Intermediate_Dir "liblutil"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\SDebug"
+# PROP Intermediate_Dir "SDebug\liblutil"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\Debug\olutil32.lib"
+# ADD LIB32 /nologo /out:"..\SDebug\olutil32.lib"
+
+!ELSEIF "$(CFG)" == "liblutil - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "libluti0"
+# PROP BASE Intermediate_Dir "libluti0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\SRelease"
+# PROP Intermediate_Dir "SRelease\liblutil"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\Release\olutil32.lib"
+# ADD LIB32 /nologo /out:"..\SRelease\olutil32.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "liblutil - Win32 Release"
+# Name "liblutil - Win32 Debug"
+# Name "liblutil - Win32 Single Debug"
+# Name "liblutil - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\ac\bytes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\debug.c
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\getopt-compat.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\getopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\getpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\ldap_cdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\lockf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil_lockf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil_md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil_sha1.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\nt_err.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ntservice.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\passwd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\portable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapdmsg.mc
+
+!IF "$(CFG)" == "liblutil - Win32 Release"
+
+# Begin Custom Build - Building slapd message file
+IntDir=.\Release\liblutil
+InputPath=.\slapdmsg.mc
+
+"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ mkdir $(IntDir)
+ mc -v slapdmsg.mc -r $(IntDir)
+ rc /v /r $(IntDir)\slapdmsg.rc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "liblutil - Win32 Debug"
+
+# Begin Custom Build - Building slapd message file
+IntDir=.\Debug\liblutil
+InputPath=.\slapdmsg.mc
+
+"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ mkdir $(IntDir)
+ mc -v slapdmsg.mc -r $(IntDir)
+ rc /v /r $(IntDir)\slapdmsg.rc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "liblutil - Win32 Single Debug"
+
+# Begin Custom Build - Building slapd message file
+IntDir=.\SDebug\liblutil
+InputPath=.\slapdmsg.mc
+
+"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ mkdir $(IntDir)
+ mc -v slapdmsg.mc -r $(IntDir)
+ rc /v /r $(IntDir)\slapdmsg.rc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "liblutil - Win32 Single Release"
+
+# Begin Custom Build - Building slapd message file
+IntDir=.\SRelease\liblutil
+InputPath=.\slapdmsg.mc
+
+"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ mkdir $(IntDir)
+ mc -v slapdmsg.mc -r $(IntDir)
+ rc /v /r $(IntDir)\slapdmsg.rc
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\utils.c
+# End Source File
+# End Target
+# End Project
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * Modified by Kurt D. Zeilenga for inclusion into OpenLDAP
+ * I hereby disclaim copyright in any changes I have made; this
+ * code remains in the public domain.
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
+ not require an integer type which is exactly 32 bits. This work
+ draws on the changes for the same purpose by Tatu Ylonen
+ <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
+ that code, there is no copyright issue. I hereby disclaim
+ copyright in any changes I have made; this code remains in the
+ public domain. */
+
+#include "portable.h"
+
+#include <ac/string.h>
+
+/* include socket.h to get sys/types.h and/or winsock2.h */
+#include <ac/socket.h>
+
+#include <lutil_md5.h>
+
+/* Little-endian byte-swapping routines. Note that these do not
+ depend on the size of datatypes such as uint32, nor do they require
+ us to detect the endianness of the machine we are running on. It
+ is possible they should be macros for speed, but I would be
+ surprised if they were a performance bottleneck for MD5. */
+
+static uint32
+getu32( const unsigned char *addr )
+{
+ return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
+ | addr[1]) << 8 | addr[0];
+}
+
+static void
+putu32( uint32 data, unsigned char *addr )
+{
+ addr[0] = (unsigned char)data;
+ addr[1] = (unsigned char)(data >> 8);
+ addr[2] = (unsigned char)(data >> 16);
+ addr[3] = (unsigned char)(data >> 24);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+lutil_MD5Init( struct lutil_MD5Context *ctx )
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+lutil_MD5Update(
+ struct lutil_MD5Context *ctx,
+ const unsigned char *buf,
+ unsigned int len
+)
+{
+ uint32 t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = (t + ((uint32)len << 3)) & 0xffffffff) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if ( t ) {
+ unsigned char *p = ctx->in + t;
+
+ t = 64-t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ lutil_MD5Transform(ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+ }
+
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ lutil_MD5Transform(ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+lutil_MD5Final( unsigned char *digest, struct lutil_MD5Context *ctx )
+{
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ lutil_MD5Transform(ctx->buf, ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count-8);
+ }
+
+ /* Append length in bits and transform */
+ putu32(ctx->bits[0], ctx->in + 56);
+ putu32(ctx->bits[1], ctx->in + 60);
+
+ lutil_MD5Transform(ctx->buf, ctx->in);
+ putu32(ctx->buf[0], digest);
+ putu32(ctx->buf[1], digest + 4);
+ putu32(ctx->buf[2], digest + 8);
+ putu32(ctx->buf[3], digest + 12);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+lutil_MD5Transform( uint32 *buf, const unsigned char *inraw )
+{
+ register uint32 a, b, c, d;
+ uint32 in[16];
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ in[i] = getu32 (inraw + 4 * i);
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+#endif
+
+#ifdef TEST
+/* Simple test program. Can use it to manually run the tests from
+ RFC1321 for example. */
+#include <stdio.h>
+
+int
+main (int argc, char **argv )
+{
+ struct lutil_MD5Context context;
+ unsigned char checksum[16];
+ int i;
+ int j;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ for (j = 1; j < argc; ++j)
+ {
+ printf ("MD5 (\"%s\") = ", argv[j]);
+ lutil_MD5Init (&context);
+ lutil_MD5Update (&context, argv[j], strlen (argv[j]));
+ lutil_MD5Final (checksum, &context);
+ for (i = 0; i < 16; i++)
+ {
+ printf ("%02x", (unsigned int) checksum[i]);
+ }
+ printf ("\n");
+ }
+ return EXIT_SUCCESS;
+}
+#endif /* TEST */
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* ntservice.c */
+#include "portable.h"
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+
+#include <stdio.h>
+
+#include <windows.h>
+#include <winsvc.h>
+
+#include <ldap.h>
+
+#define ldap_debug slap_debug
+extern int slap_debug;
+
+#include "ldap_log.h"
+#include "ldap_pvt_thread.h"
+
+
+#include "ldap_defaults.h"
+
+#include "slapdmsg.h"
+
+#define SCM_NOTIFICATION_INTERVAL 5000
+#define THIRTY_SECONDS (30 * 1000)
+
+int is_NT_Service = 1; /* assume this is an NT service until determined that */
+ /* startup was from the command line */
+
+SERVICE_STATUS SLAPDServiceStatus;
+SERVICE_STATUS_HANDLE hSLAPDServiceStatus;
+
+ldap_pvt_thread_cond_t started_event, stopped_event;
+ldap_pvt_thread_t start_status_tid, stop_status_tid;
+
+void (*stopfunc)(int);
+
+/* in nt_err.c */
+char *GetLastErrorString( void );
+
+int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName)
+{
+ HKEY hKey;
+ DWORD dwValue, dwDisposition;
+ SC_HANDLE schSCManager, schService;
+
+ fprintf( stderr, "The install path is %s.\n", lpszBinaryPathName );
+ if ((schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE ) ) != NULL )
+ {
+ if ((schService = CreateService(
+ schSCManager,
+ lpszServiceName,
+ TEXT("OpenLDAP Directory Service"),
+ SC_MANAGER_CREATE_SERVICE,
+ SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL,
+ lpszBinaryPathName,
+ NULL, NULL, NULL, NULL, NULL)) != NULL)
+ {
+ char regpath[132];
+ CloseServiceHandle(schService);
+ CloseServiceHandle(schSCManager);
+
+ sprintf( regpath, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
+ lpszServiceName );
+ /* Create the registry key for event logging to the Windows NT event log. */
+ if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+ regpath, 0,
+ "REG_SZ", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
+ &dwDisposition) != ERROR_SUCCESS)
+ {
+ fprintf( stderr, "RegCreateKeyEx() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() );
+ RegCloseKey(hKey);
+ return(0);
+ }
+ if ( RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ, lpszBinaryPathName, strlen(lpszBinaryPathName) + 1) != ERROR_SUCCESS)
+ {
+ fprintf( stderr, "RegSetValueEx(EventMessageFile) failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() );
+ RegCloseKey(hKey);
+ return(0);
+ }
+
+ dwValue = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
+ if ( RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD)) != ERROR_SUCCESS)
+ {
+ fprintf( stderr, "RegCreateKeyEx(TypesSupported) failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() );
+ RegCloseKey(hKey);
+ return(0);
+ }
+ RegCloseKey(hKey);
+ return(1);
+ }
+ else
+ {
+ fprintf( stderr, "CreateService() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() );
+ CloseServiceHandle(schSCManager);
+ return(0);
+ }
+ }
+ else
+ fprintf( stderr, "OpenSCManager() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() );
+ return(0);
+}
+
+
+int srv_remove(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName)
+{
+ SC_HANDLE schSCManager, schService;
+
+ fprintf( stderr, "The installed path is %s.\n", lpszBinaryPathName );
+ if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE)) != NULL )
+ {
+ if ((schService = OpenService(schSCManager, lpszServiceName, DELETE)) != NULL)
+ {
+ if ( DeleteService(schService) == TRUE)
+ {
+ CloseServiceHandle(schService);
+ CloseServiceHandle(schSCManager);
+ return(1);
+ } else {
+ fprintf( stderr, "DeleteService() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() );
+ fprintf( stderr, "The %s service has not been removed.\n", lpszBinaryPathName);
+ CloseServiceHandle(schService);
+ CloseServiceHandle(schSCManager);
+ return(0);
+ }
+ } else {
+ fprintf( stderr, "OpenService() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() );
+ CloseServiceHandle(schSCManager);
+ return(0);
+ }
+ }
+ else
+ fprintf( stderr, "OpenSCManager() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() );
+ return(0);
+}
+
+
+
+static void *start_status_routine( void *ptr )
+{
+ DWORD wait_result;
+ int done = 0;
+
+ while ( !done )
+ {
+ wait_result = WaitForSingleObject( started_event, SCM_NOTIFICATION_INTERVAL );
+ switch ( wait_result )
+ {
+ case WAIT_ABANDONED:
+ case WAIT_OBJECT_0:
+ /* the object that we were waiting for has been destroyed (ABANDONED) or
+ * signalled (TIMEOUT_0). We can assume that the startup process is
+ * complete and tell the Service Control Manager that we are now runnng */
+ SLAPDServiceStatus.dwCurrentState = SERVICE_RUNNING;
+ SLAPDServiceStatus.dwWin32ExitCode = NO_ERROR;
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = 1000;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ done = 1;
+ break;
+ case WAIT_TIMEOUT:
+ /* We've waited for the required time, so send an update to the Service Control
+ * Manager saying to wait again. */
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ break;
+ case WAIT_FAILED:
+ /* theres been some problem with WaitForSingleObject so tell the Service
+ * Control Manager to wait 30 seconds before deploying its assasin and
+ * then leave the thread. */
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ done = 1;
+ break;
+ }
+ }
+ ldap_pvt_thread_exit(NULL);
+ return NULL;
+}
+
+
+
+static void *stop_status_routine( void *ptr )
+{
+ DWORD wait_result;
+ int done = 0;
+
+ while ( !done )
+ {
+ wait_result = WaitForSingleObject( stopped_event, SCM_NOTIFICATION_INTERVAL );
+ switch ( wait_result )
+ {
+ case WAIT_ABANDONED:
+ case WAIT_OBJECT_0:
+ /* the object that we were waiting for has been destroyed (ABANDONED) or
+ * signalled (TIMEOUT_0). The shutting down process is therefore complete
+ * and the final SERVICE_STOPPED message will be sent to the service control
+ * manager prior to the process terminating. */
+ done = 1;
+ break;
+ case WAIT_TIMEOUT:
+ /* We've waited for the required time, so send an update to the Service Control
+ * Manager saying to wait again. */
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ break;
+ case WAIT_FAILED:
+ /* theres been some problem with WaitForSingleObject so tell the Service
+ * Control Manager to wait 30 seconds before deploying its assasin and
+ * then leave the thread. */
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ done = 1;
+ break;
+ }
+ }
+ ldap_pvt_thread_exit(NULL);
+ return NULL;
+}
+
+
+
+void WINAPI SLAPDServiceCtrlHandler( IN DWORD Opcode)
+{
+ switch (Opcode)
+ {
+ case SERVICE_CONTROL_STOP:
+ case SERVICE_CONTROL_SHUTDOWN:
+
+ Debug( LDAP_DEBUG_TRACE, "Service Shutdown ordered\n", 0, 0, 0 );
+ SLAPDServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+
+ ldap_pvt_thread_cond_init( &stopped_event );
+ if ( stopped_event == NULL )
+ {
+ /* the event was not created. We will ask the service control manager for 30
+ * seconds to shutdown */
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ }
+ else
+ {
+ /* start a thread to report the progress to the service control manager
+ * until the stopped_event is fired. */
+ if ( ldap_pvt_thread_create( &stop_status_tid, 0, stop_status_routine, NULL ) == 0 )
+ {
+
+ }
+ else {
+ /* failed to create the thread that tells the Service Control Manager that the
+ * service stopping is proceeding.
+ * tell the Service Control Manager to wait another 30 seconds before deploying its
+ * assasin. */
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ }
+ }
+ stopfunc( -1 );
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ break;
+ }
+ return;
+}
+
+void *getRegParam( char *svc, char *value )
+{
+ HKEY hkey;
+ char path[255];
+ DWORD vType;
+ static char vValue[1024];
+ DWORD valLen = sizeof( vValue );
+
+ if ( svc != NULL )
+ sprintf ( path, "SOFTWARE\\OpenLDAP\\%s\\Parameters", svc );
+ else
+ strcpy (path, "SOFTWARE\\OpenLDAP\\Parameters" );
+
+ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &hkey ) != ERROR_SUCCESS )
+ {
+ /*Debug( LDAP_DEBUG_ANY, "RegOpenKeyEx() %s\n", GetLastErrorString(), 0, 0); */
+ return NULL;
+ }
+
+ if ( RegQueryValueEx( hkey, value, NULL, &vType, vValue, &valLen ) != ERROR_SUCCESS )
+ {
+ /*Debug( LDAP_DEBUG_ANY, "RegQueryValueEx() %s\n", GetLastErrorString(), 0, 0 );*/
+ RegCloseKey( hkey );
+ return NULL;
+ }
+ RegCloseKey( hkey );
+
+ switch ( vType )
+ {
+ case REG_BINARY:
+ case REG_DWORD:
+ return (void*)&vValue;
+ case REG_SZ:
+ return (void*)&vValue;
+ }
+ return (void*)NULL;
+}
+
+void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *urls )
+{
+ char *Inserts[5];
+ WORD i = 0, j;
+ HANDLE hEventLog;
+
+ hEventLog = RegisterEventSource( NULL, svc );
+
+ Inserts[i] = (char *)malloc( 20 );
+ itoa( slap_debug, Inserts[i++], 10 );
+ Inserts[i++] = ldap_pvt_strdup( configfile );
+ Inserts[i++] = ldap_pvt_strdup( urls ? urls : "ldap:///" );
+ Inserts[i++] = ldap_pvt_strdup( is_NT_Service ? "svc" : "cmd" );
+
+ ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0,
+ MSG_SLAPD_STARTED, NULL, i, 0, Inserts, NULL );
+
+ for ( j = 0; j < i; j++ )
+ ldap_memfree( Inserts[j] );
+ DeregisterEventSource( hEventLog );
+}
+
+
+
+void LogSlapdStoppedEvent( char *svc )
+{
+ HANDLE hEventLog;
+
+ hEventLog = RegisterEventSource( NULL, svc );
+ ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0,
+ MSG_SLAPD_STOPPED, NULL, 0, 0, NULL, NULL );
+ DeregisterEventSource( hEventLog );
+}
+
+
+void CommenceStartupProcessing( LPCTSTR lpszServiceName,
+ void (*stopper)(int) )
+{
+ hSLAPDServiceStatus = RegisterServiceCtrlHandler( lpszServiceName, (LPHANDLER_FUNCTION)SLAPDServiceCtrlHandler);
+
+ stopfunc = stopper;
+
+ /* initialize the Service Status structure */
+ SLAPDServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ SLAPDServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+ SLAPDServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+ SLAPDServiceStatus.dwWin32ExitCode = NO_ERROR;
+ SLAPDServiceStatus.dwServiceSpecificExitCode = 0;
+ SLAPDServiceStatus.dwCheckPoint = 1;
+ SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2;
+
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+
+ /* start up a thread to keep sending SERVICE_START_PENDING to the Service Control Manager
+ * until the slapd listener is completed and listening. Only then should we send
+ * SERVICE_RUNNING to the Service Control Manager. */
+ ldap_pvt_thread_cond_init( &started_event );
+ if ( started_event == NULL)
+ {
+ /* failed to create the event to determine when the startup process is complete so
+ * tell the Service Control Manager to wait another 30 seconds before deploying its
+ * assasin */
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ }
+ else
+ {
+ /* start a thread to report the progress to the service control manager
+ * until the started_event is fired. */
+ if ( ldap_pvt_thread_create( &start_status_tid, 0, start_status_routine, NULL ) == 0 )
+ {
+
+ }
+ else {
+ /* failed to create the thread that tells the Service Control Manager that the
+ * service startup is proceeding.
+ * tell the Service Control Manager to wait another 30 seconds before deploying its
+ * assasin. */
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ }
+ }
+}
+
+void ReportSlapdShutdownComplete( )
+{
+ if ( is_NT_Service )
+ {
+ /* stop sending SERVICE_STOP_PENDING messages to the Service Control Manager */
+ ldap_pvt_thread_cond_signal( &stopped_event );
+ ldap_pvt_thread_cond_destroy( &stopped_event );
+
+ /* wait for the thread sending the SERVICE_STOP_PENDING messages to the Service Control Manager to die.
+ * if the wait fails then put ourselves to sleep for half the Service Control Manager update interval */
+ if (ldap_pvt_thread_join( stop_status_tid, (void *) NULL ) == -1)
+ ldap_pvt_thread_sleep( SCM_NOTIFICATION_INTERVAL / 2 );
+
+ SLAPDServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ SLAPDServiceStatus.dwCheckPoint++;
+ SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL;
+ SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+ }
+}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * lutil_password(credentials, password)
+ *
+ * Returns true if user supplied credentials matches
+ * the stored password.
+ *
+ * Due to the use of the crypt(3) function
+ * this routine is NOT thread-safe.
+ */
+
+#include "portable.h"
+
+#include <ac/stdlib.h>
+
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include "lutil_md5.h"
+#include "lutil_sha1.h"
+#include "lutil.h"
+
+#ifdef HAVE_SHADOW_H
+# include <shadow.h>
+#endif
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+static int supported_hash(
+ const char* method,
+ const char** methods )
+{
+ int i;
+
+ if(methods == NULL) {
+ return 1;
+ }
+
+ for(i=0; methods[i] != NULL; i++) {
+ if(strcasecmp(method, methods[i]) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static const char *passwd_hash(
+ const char* passwd,
+ const char* method,
+ const char** methods )
+{
+ int len;
+
+ if( !supported_hash( method, methods ) ) {
+ return NULL;
+ }
+
+ len = strlen(method);
+
+ if( strncasecmp( passwd, method, len ) == 0 ) {
+ return &passwd[len];
+ }
+
+ return NULL;
+}
+
+/*
+ * Return 0 if creds are good.
+ */
+int
+lutil_passwd(
+ const char *cred,
+ const char *passwd,
+ const char **methods)
+{
+ const char *p;
+
+ if (cred == NULL || passwd == NULL) {
+ return -1;
+ }
+
+ if ((p = passwd_hash( passwd, "{MD5}", methods )) != NULL ) {
+ lutil_MD5_CTX MD5context;
+ unsigned char MD5digest[16];
+ char base64digest[25]; /* ceiling(sizeof(input)/3) * 4 + 1 */
+
+ lutil_MD5Init(&MD5context);
+ lutil_MD5Update(&MD5context,
+ (const unsigned char *)cred, strlen(cred));
+ lutil_MD5Final(MD5digest, &MD5context);
+
+ if ( lutil_b64_ntop(MD5digest, sizeof(MD5digest),
+ base64digest, sizeof(base64digest)) < 0)
+ {
+ return ( 1 );
+ }
+
+ return( strcmp(p, base64digest) );
+
+ } else if ((p = passwd_hash( passwd, "{SHA}", methods )) != NULL ) {
+ lutil_SHA1_CTX SHA1context;
+ unsigned char SHA1digest[20];
+ char base64digest[29]; /* ceiling(sizeof(input)/3) * 4 + 1 */
+
+ lutil_SHA1Init(&SHA1context);
+ lutil_SHA1Update(&SHA1context,
+ (const unsigned char *) cred, strlen(cred));
+ lutil_SHA1Final(SHA1digest, &SHA1context);
+
+ if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest),
+ base64digest, sizeof(base64digest)) < 0)
+ {
+ return ( 1 );
+ }
+
+ return( strcmp(p, base64digest) );
+
+ } else if ((p = passwd_hash( passwd, "{SSHA}", methods )) != NULL ) {
+ lutil_SHA1_CTX SHA1context;
+ unsigned char SHA1digest[20];
+ int pw_len = strlen(p);
+ int rc;
+ unsigned char *orig_pass = NULL;
+
+ /* base64 un-encode password */
+ orig_pass = (unsigned char *)malloc((size_t)(pw_len * 0.75 + 1));
+ if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
+ {
+ free(orig_pass);
+ return ( 1 );
+ }
+
+ /* hash credentials with salt */
+ lutil_SHA1Init(&SHA1context);
+ lutil_SHA1Update(&SHA1context,
+ (const unsigned char *) cred, strlen(cred));
+ lutil_SHA1Update(&SHA1context,
+ (const unsigned char *) orig_pass + sizeof(SHA1digest),
+ rc - sizeof(SHA1digest));
+ lutil_SHA1Final(SHA1digest, &SHA1context);
+
+ /* compare */
+ rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
+ free(orig_pass);
+ return(rc);
+
+ } else if ((p = passwd_hash( passwd, "{SMD5}", methods )) != NULL ) {
+ lutil_MD5_CTX MD5context;
+ unsigned char MD5digest[16];
+ int pw_len = strlen(p);
+ int rc;
+ unsigned char *orig_pass = NULL;
+
+ /* base64 un-encode password */
+ orig_pass = (unsigned char *)malloc((size_t)(pw_len * 0.75 + 1));
+ if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
+ {
+ free(orig_pass);
+ return ( 1 );
+ }
+
+ /* hash credentials with salt */
+ lutil_MD5Init(&MD5context);
+ lutil_MD5Update(&MD5context,
+ (const unsigned char *) cred, strlen(cred));
+ lutil_MD5Update(&MD5context,
+ (const unsigned char *) orig_pass + sizeof(MD5digest),
+ rc - sizeof(MD5digest));
+ lutil_MD5Final(MD5digest, &MD5context);
+
+ /* compare */
+ rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
+ free(orig_pass);
+ return ( rc );
+
+#ifdef SLAPD_CRYPT
+ } else if ((p = passwd_hash( passwd, "{CRYPT}", methods )) != NULL ) {
+ return( strcmp(p, crypt(cred, p)) );
+
+# if defined( HAVE_GETSPNAM ) \
+ || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
+ } else if ((p = passwd_hash( passwd, "{UNIX}", methods )) != NULL ) {
+
+# ifdef HAVE_GETSPNAM
+ struct spwd *spwd = getspnam(p);
+
+ if(spwd == NULL) {
+ return 1; /* not found */
+ }
+
+ return strcmp(spwd->sp_pwdp, crypt(cred, spwd->sp_pwdp));
+# else
+ struct passwd *pwd = getpwnam(p);
+
+ if(pwd == NULL) {
+ return 1; /* not found */
+ }
+
+ return strcmp(pwd->pw_passwd, crypt(cred, pwd->pw_passwd));
+# endif
+# endif
+#endif
+ }
+
+#ifdef SLAPD_CLEARTEXT
+ return supported_hash("{CLEARTEXT}", methods ) &&
+ strcmp(passwd, cred) != 0;
+#else
+ return( 1 );
+#endif
+
+}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Acquired from:
+ * $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */
+
+/*
+ * SHA-1 in C
+ * By Steve Reid <steve@edmweb.com>
+ * 100% Public Domain
+ *
+ * Test Vectors (from FIPS PUB 180-1)
+ * "abc"
+ * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+ * A million repetitions of "a"
+ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+ */
+
+
+#include "portable.h"
+#include <ac/string.h>
+
+/* include socket.h to get sys/types.h and/or winsock2.h */
+#include <ac/socket.h>
+
+#if defined(HAVE_SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+
+#include "lutil_sha1.h"
+
+#define SHA1HANDSOFF /* Copies data before messing with it. */
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/*
+ * blk0() and blk() perform the initial expand.
+ * I got the idea of expanding during the round function from SSLeay
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define blk0(i) (block[i] = (rol(block[i],24)&0xFF00FF00) \
+ |(rol(block[i],8)&0x00FF00FF))
+#else
+# define blk0(i) block[i]
+#endif
+#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
+ ^block[(i+2)&15]^block[i&15],1))
+
+/*
+ * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
+ */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/*
+ * Hash a single 512-bit block. This is the core of the algorithm.
+ */
+void
+lutil_SHA1Transform( uint32 *state, const unsigned char *buffer )
+{
+ uint32 a, b, c, d, e;
+
+ /* Assumes u_int is 32 bits and char 8 bits.
+ * I don't know why uint32 isn't used (or what the difference is). */
+#ifdef SHA1HANDSOFF
+ u_int block[16];
+ (void)memcpy(block, buffer, 64);
+#else
+ u_int *block = (u_int *)buffer;
+#endif
+
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/*
+ * lutil_SHA1Init - Initialize new context
+ */
+void
+lutil_SHA1Init( lutil_SHA1_CTX *context )
+{
+
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/*
+ * Run your data through this.
+ */
+void
+lutil_SHA1Update(
+ lutil_SHA1_CTX *context,
+ const unsigned char *data,
+ uint32 len
+)
+{
+ u_int i, j;
+
+ j = context->count[0];
+ if ((context->count[0] += len << 3) < j)
+ context->count[1] += (len>>29)+1;
+ j = (j >> 3) & 63;
+ if ((j + len) > 63) {
+ (void)memcpy(&context->buffer[j], data, (i = 64-j));
+ lutil_SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64)
+ lutil_SHA1Transform(context->state, &data[i]);
+ j = 0;
+ } else {
+ i = 0;
+ }
+ (void)memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/*
+ * Add padding and return the message digest.
+ */
+void
+lutil_SHA1Final( unsigned char *digest, lutil_SHA1_CTX *context )
+{
+ u_int i;
+ unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ lutil_SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448)
+ lutil_SHA1Update(context, (unsigned char *)"\0", 1);
+ lutil_SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+
+ if (digest) {
+ for (i = 0; i < 20; i++)
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+}
+
+
+/* sha1hl.c
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$OpenBSD: sha1hl.c,v 1.1 1997/07/12 20:06:03 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+
+#include <ac/errno.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+
+/* ARGSUSED */
+char *
+lutil_SHA1End( lutil_SHA1_CTX *ctx, char *buf )
+{
+ int i;
+ char *p = buf;
+ unsigned char digest[20];
+ static const char hex[]="0123456789abcdef";
+
+ if (p == NULL && (p = malloc(41)) == NULL)
+ return 0;
+
+ lutil_SHA1Final(digest,ctx);
+ for (i = 0; i < 20; i++) {
+ p[i + i] = hex[digest[i] >> 4];
+ p[i + i + 1] = hex[digest[i] & 0x0f];
+ }
+ p[i + i] = '\0';
+ return(p);
+}
+
+char *
+lutil_SHA1File( char *filename, char *buf )
+{
+ unsigned char buffer[BUFSIZ];
+ lutil_SHA1_CTX ctx;
+ int fd, num, oerrno;
+
+ lutil_SHA1Init(&ctx);
+
+ if ((fd = open(filename,O_RDONLY)) < 0)
+ return(0);
+
+ while ((num = read(fd, buffer, sizeof(buffer))) > 0)
+ lutil_SHA1Update(&ctx, buffer, num);
+
+ oerrno = errno;
+ close(fd);
+ errno = oerrno;
+ return(num < 0 ? 0 : lutil_SHA1End(&ctx, buf));
+}
+
+char *
+lutil_SHA1Data( const unsigned char *data, size_t len, char *buf )
+{
+ lutil_SHA1_CTX ctx;
+
+ lutil_SHA1Init(&ctx);
+ lutil_SHA1Update(&ctx, data, len);
+ return(lutil_SHA1End(&ctx, buf));
+}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+
+#include <lutil.h>
+#include <ldap_defaults.h>
+
+char* lutil_progname( const char* name, int argc, char *argv[] )
+{
+ char *progname;
+
+ if(argc == 0) {
+ return strdup( name );
+ }
+
+ progname = strrchr ( argv[0], *LDAP_DIRSEP );
+ progname = strdup( progname ? &progname[1] : argv[0] );
+
+ return progname;
+}
--- /dev/null
+##
+## Makefile.in for slapd
+##
+PROGRAMS=slapd
+XPROGRAMS=sslapd libbackends.a .backend
+XSRCS=version.c
+SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \
+ attr.c entry.c config.c backend.c result.c operation.c \
+ dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
+ value.c ava.c bind.c unbind.c abandon.c filterentry.c \
+ phonetic.c acl.c str2filter.c aclparse.c init.c user.c \
+ repl.c lock.c controls.c extended.c \
+ schema.c schemaparse.c monitor.c configinfo.c \
+ root_dse.c sasl.c module.c suffixalias.c
+OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \
+ attr.o entry.o config.o backend.o result.o operation.o \
+ dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
+ value.o ava.o bind.o unbind.o abandon.o filterentry.o \
+ phonetic.o acl.o str2filter.o aclparse.o init.o user.o \
+ repl.o lock.o controls.o extended.o \
+ schema.o schemaparse.o monitor.o configinfo.o \
+ root_dse.o sasl.o module.o suffixalias.o
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+SLAP_DIR=
+SLAPD_MODULES=@SLAPD_MODULES_LIST@
+XDEFS = $(MODULES_CPPFLAGS)
+XLDFLAGS = $(MODULES_LDFLAGS) $(SLAPD_MODULES)
+
+# $(LTHREAD_LIBS) must be last
+XLIBS = libbackends.a -lavl -lldbm -lldif -lldap_r -llber -llutil
+XXLIBS = $(LDBM_LIBS) $(SLAPD_LIBS) \
+ $(PERL_LDFLAGS) $(SECURITY_LIBS) \
+ $(LDIF_LIBS) $(LUTIL_LIBS)
+XXXLIBS = $(LTHREAD_LIBS) $(MODULES_LIBS)
+
+BUILD_OPT = "--enable-slapd"
+BUILD_SRV = @BUILD_SLAPD@
+
+all-local-srv: all-cffiles
+
+slapd: libbackends.a version.o
+ $(LTLINK) -o $@ $(OBJS) version.o $(LIBS)
+ (cd tools; $(MAKE) $(MFLAGS) all)
+
+sslapd: version.o
+ $(LTLINK) -static -o $@ $(OBJS) version.o $(LIBS)
+
+.backend: FORCE
+ @for i in back-*; do \
+ if [ -d $$i ]; then \
+ echo " "; echo " cd $$i; $(MAKE) $(MFLAGS) all"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) all ); \
+ fi; \
+ done; \
+ echo " "
+
+libbackends.a: .backend
+ @$(RM) -r tmp
+ @$(MKDIR) tmp
+ @-for i in back-*/*.a; do \
+ ( \
+ cd tmp; \
+ $(AR) x ../$$i; \
+ pre=`echo $$i | sed -e 's/\/.*$$//' -e 's/back-//'`; \
+ for j in *.o; do \
+ mv $$j $${pre}$$j; \
+ done; \
+ $(AR) ruv libbackends.a *.o 2>&1 | grep -v truncated; \
+ $(RM) *.o __.SYMDEF; \
+ echo "added backend library $$i"; \
+ ); \
+ done
+ @mv -f tmp/libbackends.a ./libbackends.a
+ @$(RM) -r tmp
+ @if [ ! -z "$(RANLIB)" ]; then \
+ $(RANLIB) libbackends.a; \
+ fi
+ @ls -l libbackends.a
+
+version.c: libbackends.a $(OBJS) $(SLAPD_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) -s -n Versionstr slapd > $@
+
+depend-local-srv: FORCE
+ @for i in back-* shell-backends tools; do \
+ if [ -d $$i ]; then \
+ echo; echo " cd $$i; $(MAKE) $(MFLAGS) depend"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) depend ); \
+ fi; \
+ done
+
+clean-local-srv: FORCE
+ @for i in back-* shell-backends tools; do \
+ if [ -d $$i ]; then \
+ echo; echo " cd $$i; $(MAKE) $(MFLAGS) clean"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) clean ); \
+ fi; \
+ done
+ rm -f *.tmp all-cffiles
+
+veryclean-local-srv: FORCE
+ @for i in back-* shell-backends tools; do \
+ if [ -d $$i ]; then \
+ echo; echo " cd $$i; $(MAKE) $(MFLAGS) clean"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) veryclean ); \
+ fi; \
+ done
+
+install-local-srv: install-slapd install-conf install-tools
+
+install-slapd: FORCE
+ @-$(MKDIR) $(libexecdir)
+ @-$(MKDIR) $(localstatedir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 slapd $(libexecdir)
+ @if [ ! -z "$(SLAPD_MODULES)" ]; then \
+ for i in back-* shell-backends tools; do \
+ if [ -d $$i ]; then \
+ echo; echo " cd $$i; $(MAKE) $(MFLAGS) install"; \
+ ( cd $$i; $(MAKE) $(MFLAGS) install ); \
+ fi; \
+ done; \
+ fi
+
+
+CFFILES=slapd.conf slapd.at.conf slapd.oc.conf
+
+all-cffiles: slapd
+ @for i in $(CFFILES); do \
+ tmpcf=$$i.tmp; \
+ $(SED) -e 's;%SYSCONFDIR%;$(sysconfdir);' \
+ -e 's;%LOCALSTATEDIR%;$(localstatedir);' \
+ $(srcdir)/$$i > $$tmpcf ; \
+ done
+ touch all-cffiles
+
+install-conf: FORCE
+ @-$(MKDIR) $(sysconfdir)
+ @for i in $(CFFILES); do \
+ tmpcf=$$i.tmp ; \
+ if test $$i = slapd.conf ; then \
+ mode=600 ; \
+ else \
+ mode=644 ; \
+ fi ; \
+ if test ! -f $(sysconfdir)/$$i; then \
+ echo "installing $$i in $(sysconfdir)"; \
+ echo "$(INSTALL) $(INSTALLFLAGS) -m $$mode $$tmpcf $(sysconfdir)/$$i"; \
+ $(INSTALL) $(INSTALLFLAGS) -m $$mode $$tmpcf $(sysconfdir)/$$i; \
+ else \
+ echo "PRESERVING EXISTING CONFIGURATION FILE $(sysconfdir)/$$i" ; \
+ fi; \
+ $(INSTALL) $(INSTALLFLAGS) -m $$mode $$tmpcf $(sysconfdir)/$$i.default ; \
+ done
+
+install-tools: FORCE
+ @-$(MKDIR) $(sbindir)
+ (cd tools; $(MAKE) $(MFLAGS) install)
+
/* abandon.c - decode and handle an ldap abandon operation */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* is provided ``as is'' without express or implied warranty.
*/
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
+#include "portable.h"
-extern Backend *select_backend();
+#include <stdio.h>
+#include <ac/socket.h>
-extern char *default_referral;
+#include "slap.h"
-void
+int
do_abandon(
Connection *conn,
Operation *op
)
{
- int id;
- Backend *be;
+ ber_int_t id;
Operation *o;
+ Operation **oo;
+ int rc, notfound;
Debug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
*/
if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0 ,0 );
- return;
+ Debug( LDAP_DEBUG_ANY, "do_abandon: ber_scanf failed\n", 0, 0 ,0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
}
- Debug( LDAP_DEBUG_ARGS, "do_abandon: id %d\n", id, 0 ,0 );
+ if( (rc = get_ctrls( conn, op, 0 )) != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "do_abandon: get_ctrls failed\n", 0, 0 ,0 );
+ return rc;
+ }
+ Debug( LDAP_DEBUG_ARGS, "do_abandon: id=%ld\n", (long) id, 0 ,0 );
+
+ if( id <= 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_abandon: bad msgid %ld\n", (long) id, 0, 0 );
+ return LDAP_SUCCESS;
+ }
+
+ notfound = 1; /* not found */
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
/*
* find the operation being abandoned and set the o_abandon
* flag. It's up to the backend to periodically check this
* flag and abort the operation at a convenient time.
*/
- pthread_mutex_lock( &conn->c_opsmutex );
for ( o = conn->c_ops; o != NULL; o = o->o_next ) {
- if ( o->o_msgid == id )
- break;
+ if ( o->o_msgid == id ) {
+ ldap_pvt_thread_mutex_lock( &o->o_abandonmutex );
+ o->o_abandon = 1;
+ ldap_pvt_thread_mutex_unlock( &o->o_abandonmutex );
+
+ notfound = 0;
+ goto done;
+ }
+ }
+
+ for ( oo = &conn->c_pending_ops;
+ (*oo != NULL) && ((*oo)->o_msgid != id);
+ oo = &(*oo)->o_next )
+ {
+ /* EMPTY */ ;
}
- if ( o != NULL ) {
- pthread_mutex_lock( &o->o_abandonmutex );
- o->o_abandon = 1;
- pthread_mutex_unlock( &o->o_abandonmutex );
- } else {
- Debug( LDAP_DEBUG_TRACE, "do_abandon: op not found\n", 0, 0,
- 0 );
+ if( *oo != NULL ) {
+ o = *oo;
+ *oo = (*oo)->o_next;
+ slap_op_free( o );
+ notfound = 0;
}
- pthread_mutex_unlock( &conn->c_opsmutex );
+
+done:
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+ Debug( LDAP_DEBUG_TRACE, "do_abandon: op=%ld %sfound\n",
+ id, notfound ? "not " : "", 0 );
+
+ return LDAP_SUCCESS;
}
/* acl.c - routines to parse and check acl's */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#ifdef sunos5
-#include "regexpr.h"
-#else
-#include "regex.h"
-#endif
-#include "slap.h"
-extern Attribute *attr_find();
-extern char *re_comp();
-extern struct acl *global_acl;
-extern int global_default_access;
-extern char *access2str();
-extern char *dn_normalize_case();
+#include <ac/regex.h>
+#include <ac/socket.h>
+#include <ac/string.h>
-int acl_access_allowed();
-int access_allowed();
-struct acl *acl_get_applicable();
+#include "slap.h"
-static int regex_matches();
+static int regex_matches(char *pat, char *str, char *buf, regmatch_t *matches);
+static void string_expand(char *newbuf, int bufsiz, char *pattern,
+ char *match, regmatch_t *matches);
-extern pthread_mutex_t regex_mutex;
/*
- * access_allowed - check whether dn is allowed the requested access
+ * access_allowed - check whether op->o_ndn is allowed the requested access
* to entry e, attribute attr, value val. if val is null, access to
* the whole attribute is assumed (all values). this routine finds
* the applicable acl and calls acl_access_allowed() to make the
Entry *e,
char *attr,
struct berval *val,
- char *dn,
int access
)
{
- int rc;
- struct acl *a;
+ int rc;
+ AccessControl *a;
+ char *edn;
+
+ regmatch_t matches[MAXREMATCHES];
+ int i;
+ int n;
if ( be == NULL ) {
return( 0 );
}
- a = acl_get_applicable( be, op, e, attr );
- rc = acl_access_allowed( a, be, conn, e, val, op, access );
+ edn = e->e_ndn;
+
+ Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: entry (%s) attr (%s)\n",
+ e->e_dn, attr, 0 );
+
+ /* the lastmod attributes are ignored by ACL checking */
+ if ( oc_check_no_usermod_attr( attr ) ) {
+ Debug( LDAP_DEBUG_ACL, "Operational attribute: %s access allowed\n",
+ attr, 0, 0 );
+ return(1);
+ }
+
+ memset(matches, 0, sizeof(matches));
+
+ a = acl_get_applicable( be, op, e, attr, MAXREMATCHES, matches );
+
+ if (a) {
+ for (i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++) {
+ Debug( LDAP_DEBUG_ARGS, "=> match[%d]: %d %d ", i,
+ (int)matches[i].rm_so, (int)matches[i].rm_eo );
+
+ if( matches[i].rm_so <= matches[0].rm_eo ) {
+ for ( n = matches[i].rm_so; n < matches[i].rm_eo; n++) {
+ Debug( LDAP_DEBUG_ARGS, "%c", edn[n], 0, 0 );
+ }
+ }
+ Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
+ }
+ }
+
+ rc = acl_access_allowed( a, be, conn, e, val, op, access, edn, matches );
+
+ Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: exit (%s) attr (%s)\n",
+ e->e_dn, attr, 0);
return( rc );
}
* acl_access_allowed().
*/
-struct acl *
+AccessControl *
acl_get_applicable(
Backend *be,
Operation *op,
Entry *e,
- char *attr
+ char *attr,
+ int nmatch,
+ regmatch_t *matches
)
{
int i;
- struct acl *a;
- char *edn;
+ AccessControl *a;
+ char *edn;
- Debug( LDAP_DEBUG_ACL, "=> acl_get: entry (%s) attr (%s)\n", e->e_dn,
- attr, 0 );
+ Debug( LDAP_DEBUG_ACL, "\n=> acl_get: entry (%s) attr (%s)\n",
+ e->e_dn, attr, 0 );
- if ( be_isroot( be, op->o_dn ) ) {
+ if ( be_isroot( be, op->o_ndn ) ) {
Debug( LDAP_DEBUG_ACL,
"<= acl_get: no acl applicable to database root\n", 0, 0,
0 );
return( NULL );
}
+ edn = e->e_ndn;
+
+ Debug( LDAP_DEBUG_ARGS, "=> acl_get: edn %s\n", edn, 0, 0 );
+
/* check for a backend-specific acl that matches the entry */
for ( i = 1, a = be->be_acl; a != NULL; a = a->acl_next, i++ ) {
- if ( a->acl_dnpat != NULL ) {
- edn = dn_normalize_case( strdup( e->e_dn ) );
- if ( ! regex_matches( a->acl_dnpat, edn ) ) {
- free( edn );
+ if (a->acl_dn_pat != NULL) {
+ Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n",
+ i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub);
+
+ if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) {
continue;
+
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "=> acl_get:[%d] backend ACL match\n",
+ i, 0, 0);
}
- free( edn );
}
+
if ( a->acl_filter != NULL ) {
- if ( test_filter( NULL, NULL, NULL, e, a->acl_filter )
- != 0 ) {
+ if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) {
continue;
}
}
+
+ Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr %s\n", i, attr, 0);
+
if ( attr == NULL || a->acl_attrs == NULL ||
- charray_inlist( a->acl_attrs, attr ) ) {
- Debug( LDAP_DEBUG_ACL, "<= acl_get: backend acl #%d\n",
- i, e->e_dn, attr );
+ charray_inlist( a->acl_attrs, attr ) )
+ {
+ Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] backend acl %s attr: %s\n",
+ i, e->e_dn, attr );
return( a );
}
+ matches[0].rm_so = matches[0].rm_eo = -1;
}
/* check for a global acl that matches the entry */
for ( i = 1, a = global_acl; a != NULL; a = a->acl_next, i++ ) {
- if ( a->acl_dnpat != NULL ) {
- edn = dn_normalize_case( strdup( e->e_dn ) );
- if ( ! regex_matches( a->acl_dnpat, edn ) ) {
- free( edn );
+ if (a->acl_dn_pat != NULL) {
+ Debug( LDAP_DEBUG_TRACE, "=> dn pat: [%d] %s nsub: %d\n",
+ i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub);
+
+ if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) {
continue;
+
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "=> acl_get: [%d] global ACL match\n",
+ i, 0, 0);
}
- free( edn );
}
+
if ( a->acl_filter != NULL ) {
- if ( test_filter( NULL, NULL, NULL, e, a->acl_filter )
- != 0 ) {
+ if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) {
continue;
}
}
- if ( attr == NULL || a->acl_attrs == NULL || charray_inlist(
- a->acl_attrs, attr ) ) {
- Debug( LDAP_DEBUG_ACL, "<= acl_get: global acl #%d\n",
- i, e->e_dn, attr );
+
+ Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr\n", i, 0, 0);
+
+ if ( attr == NULL || a->acl_attrs == NULL ||
+ charray_inlist( a->acl_attrs, attr ) )
+ {
+ Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] global acl %s attr: %s\n",
+ i, e->e_dn, attr );
return( a );
}
+
+ matches[0].rm_so = matches[0].rm_eo = -1;
}
- Debug( LDAP_DEBUG_ACL, "<= acl_get: no match\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ACL, "<= acl_get: no match\n", 0, 0, 0 );
return( NULL );
}
int
acl_access_allowed(
- struct acl *a,
+ AccessControl *a,
Backend *be,
Connection *conn,
Entry *e,
struct berval *val,
Operation *op,
- int access
+ int access,
+ char *edn,
+ regmatch_t *matches
)
{
int i;
- char *edn, *odn;
- struct access *b;
- Attribute *at;
- struct berval bv;
+ Access *b;
int default_access;
- Debug( LDAP_DEBUG_ACL, "=> acl: %s access to value \"%s\" by \"%s\"\n",
- access2str( access ), val ? val->bv_val : "any", op->o_dn ?
- op->o_dn : "" );
+ Debug( LDAP_DEBUG_ACL,
+ "\n=> acl_access_allowed: %s access to entry \"%s\"\n",
+ access2str( access ), e->e_dn, 0 );
- if ( be_isroot( be, op->o_dn ) ) {
- Debug( LDAP_DEBUG_ACL, "<= acl: granted to database root\n",
+ Debug( LDAP_DEBUG_ACL,
+ "\n=> acl_access_allowed: %s access to value \"%s\" by \"%s\"\n",
+ access2str( access ),
+ val ? val->bv_val : "any",
+ op->o_ndn ? op->o_ndn : "" );
+
+ if ( be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= acl_access_allowed: granted to database root\n",
0, 0, 0 );
return( 1 );
}
- default_access = be->be_dfltaccess ? be->be_dfltaccess :
- global_default_access;
+ default_access = be->be_dfltaccess ? be->be_dfltaccess : global_default_access;
+
if ( a == NULL ) {
Debug( LDAP_DEBUG_ACL,
- "<= acl: %s by default (no matching to)\n",
+ "<= acl_access_allowed: %s by default (no matching to)\n",
default_access >= access ? "granted" : "denied", 0, 0 );
return( default_access >= access );
}
- odn = NULL;
- if ( op->o_dn != NULL ) {
- odn = dn_normalize_case( strdup( op->o_dn ) );
- bv.bv_val = odn;
- bv.bv_len = strlen( odn );
- }
for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) {
- if ( b->a_dnpat != NULL ) {
+ /* AND <who> clauses */
+ if ( b->a_dn_pat != NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<= check a_dn_pat: %s\n",
+ b->a_dn_pat, 0, 0);
/*
* if access applies to the entry itself, and the
* user is bound as somebody in the same namespace as
* the entry, OR the given dn matches the dn pattern
*/
- if ( strcasecmp( b->a_dnpat, "self" ) == 0 && op->o_dn
- != NULL && *(op->o_dn) && e->e_dn != NULL ) {
- edn = dn_normalize_case( strdup( e->e_dn ) );
- if ( strcasecmp( edn, op->o_dn ) == 0 ) {
- free( edn );
- if ( odn ) free( odn );
- Debug( LDAP_DEBUG_ACL,
- "<= acl: matched by clause #%d access %s\n",
- i, (b->a_access & ~ACL_SELF) >=
- access ? "granted" : "denied", 0 );
-
- return( (b->a_access & ~ACL_SELF)
- >= access );
+ if ( strcasecmp( b->a_dn_pat, "anonymous" ) == 0 ) {
+ if (op->o_ndn != NULL && op->o_ndn[0] != '\0' ) {
+ continue;
}
- free( edn );
- } else {
- if ( regex_matches( b->a_dnpat, odn ) ) {
- if ( odn ) free( odn );
- Debug( LDAP_DEBUG_ACL,
- "<= acl: matched by clause #%d access %s\n",
- i, (b->a_access & ~ACL_SELF) >= access ?
- "granted" : "denied", 0 );
-
- return( (b->a_access & ~ACL_SELF)
- >= access );
+
+ } else if ( strcasecmp( b->a_dn_pat, "self" ) == 0 ) {
+ if( op->o_ndn == NULL || op->o_ndn[0] == '\0' ) {
+ continue;
+ }
+
+ if ( e->e_dn == NULL || strcmp( edn, op->o_ndn ) != 0 ) {
+ continue;
}
+
+ } else if ( strcmp( b->a_dn_pat, ".*" ) != 0 &&
+ !regex_matches( b->a_dn_pat, op->o_ndn, edn, matches ) )
+ {
+ continue;
+ }
+ }
+
+ if ( b->a_sockurl_pat != NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "<= check a_sockurl_pat: %s\n",
+ b->a_sockurl_pat, 0, 0 );
+
+ if ( strcmp( b->a_sockurl_pat, ".*" ) != 0 &&
+ !regex_matches( b->a_sockurl_pat, conn->c_listener_url,
+ edn, matches ) )
+ {
+ continue;
}
}
- if ( b->a_addrpat != NULL ) {
- if ( regex_matches( b->a_addrpat, conn->c_addr ) ) {
- if ( odn ) free( odn );
- Debug( LDAP_DEBUG_ACL,
- "<= acl: matched by clause #%d access %s\n",
- i, (b->a_access & ~ACL_SELF) >= access ?
- "granted" : "denied", 0 );
-
- return( (b->a_access & ~ACL_SELF) >= access );
+
+ if ( b->a_domain_pat != NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "<= check a_domain_pat: %s\n",
+ b->a_domain_pat, 0, 0 );
+
+ if ( strcmp( b->a_domain_pat, ".*" ) != 0 &&
+ !regex_matches( b->a_domain_pat, conn->c_peer_domain,
+ edn, matches ) )
+ {
+ continue;
}
}
- if ( b->a_domainpat != NULL ) {
- if ( regex_matches( b->a_domainpat, conn->c_domain ) ) {
- if ( odn ) free( odn );
- Debug( LDAP_DEBUG_ACL,
- "<= acl: matched by clause #%d access %s\n",
- i, (b->a_access & ~ACL_SELF) >= access ?
- "granted" : "denied", 0 );
-
- return( (b->a_access & ~ACL_SELF) >= access );
+
+ if ( b->a_peername_pat != NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "<= check a_peername_path: %s\n",
+ b->a_peername_pat, 0, 0 );
+
+ if ( strcmp( b->a_peername_pat, ".*" ) != 0 &&
+ !regex_matches( b->a_peername_pat, conn->c_peer_name,
+ edn, matches ) )
+ {
+ continue;
}
}
- if ( b->a_dnattr != NULL && op->o_dn != NULL ) {
- /* see if asker is listed in dnattr */
- if ( (at = attr_find( e->e_attrs, b->a_dnattr ))
- != NULL && value_find( at->a_vals, &bv,
- at->a_syntax, 3 ) == 0 )
+
+ if ( b->a_sockname_pat != NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "<= check a_sockname_path: %s\n",
+ b->a_sockname_pat, 0, 0 );
+
+ if ( strcmp( b->a_sockname_pat, ".*" ) != 0 &&
+ !regex_matches( b->a_sockname_pat, conn->c_sock_name,
+ edn, matches ) )
{
- if ( (b->a_access & ACL_SELF) && (val == NULL
- || value_cmp( &bv, val, at->a_syntax,
- 2 )) ) {
+ continue;
+ }
+ }
+
+ if ( b->a_dn_at != NULL && op->o_ndn != NULL ) {
+ Attribute *at;
+ struct berval bv;
+
+ Debug( LDAP_DEBUG_ARGS, "<= check a_dn_at: %s\n",
+ b->a_dn_at, 0, 0);
+
+ bv.bv_val = op->o_ndn;
+ bv.bv_len = strlen( bv.bv_val );
+
+ /* see if asker is listed in dnattr */
+ if ( (at = attr_find( e->e_attrs, b->a_dn_at )) != NULL &&
+ value_find( at->a_vals, &bv, at->a_syntax, 3 ) == 0 )
+ {
+ if ( ACL_IS_SELF(b->a_access) &&
+ (val == NULL || value_cmp( &bv, val, at->a_syntax, 2 )) )
+ {
continue;
}
- if ( odn ) free( odn );
- Debug( LDAP_DEBUG_ACL,
- "<= acl: matched by clause #%d access %s\n",
- i, (b->a_access & ~ACL_SELF) >= access ?
- "granted" : "denied", 0 );
+ /* asker not listed in dnattr - check for self access */
+ } else if ( ! ACL_IS_SELF(b->a_access) || val == NULL ||
+ value_cmp( &bv, val, at->a_syntax, 2 ) != 0 )
+ {
+ continue;
+ }
+ }
+
+ if ( b->a_group_pat != NULL && op->o_ndn != NULL ) {
+ char buf[1024];
- return( (b->a_access & ~ACL_SELF) >= access );
+ /* b->a_group is an unexpanded entry name, expanded it should be an
+ * entry with objectclass group* and we test to see if odn is one of
+ * the values in the attribute group
+ */
+ /* see if asker is listed in dnattr */
+ string_expand(buf, sizeof(buf), b->a_group_pat, edn, matches);
+ if ( dn_normalize_case(buf) == NULL ) {
+ /* did not expand to a valid dn */
+ continue;
}
- /* asker not listed in dnattr - check for self access */
- if ( ! (b->a_access & ACL_SELF) || val == NULL ||
- value_cmp( &bv, val, at->a_syntax, 2 ) != 0 ) {
+ if (backend_group(be, e, buf, op->o_ndn,
+ b->a_group_oc, b->a_group_at) != 0)
+ {
continue;
}
+ }
- if ( odn ) free( odn );
- Debug( LDAP_DEBUG_ACL,
- "<= acl: matched by clause #%d (self) access %s\n",
- i, (b->a_access & ~ACL_SELF) >= access ? "granted"
- : "denied", 0 );
+ Debug( LDAP_DEBUG_ACL,
+ "<= acl_access_allowed: matched by clause #%d access %s\n",
+ i,
+ ACL_GRANT(b->a_access, access) ? "granted" : "denied",
+ 0 );
- return( (b->a_access & ~ACL_SELF) >= access );
- }
+ return ACL_GRANT(b->a_access, access );
}
- if ( odn ) free( odn );
- Debug( LDAP_DEBUG_ACL, "<= acl: %s by default (no matching by)\n",
+ Debug( LDAP_DEBUG_ACL,
+ "<= acl_access_allowed: %s by default (no matching by)\n",
default_access >= access ? "granted" : "denied", 0, 0 );
return( default_access >= access );
}
/*
- * acl_check_mods - check access control on the given entry to see if
+ * acl_check_modlist - check access control on the given entry to see if
* it allows the given modifications by the user associated with op.
* returns LDAP_SUCCESS mods allowed ok
* anything else mods not allowed - return is an error
*/
int
-acl_check_mods(
+acl_check_modlist(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
- LDAPMod *mods
+ LDAPModList *mlist
)
{
int i;
- struct acl *a;
+ AccessControl *a;
+ char *edn = e->e_ndn;
+
+ for ( ; mlist != NULL; mlist = mlist->ml_next ) {
+ regmatch_t matches[MAXREMATCHES];
- for ( ; mods != NULL; mods = mods->mod_next ) {
- if ( strcasecmp( mods->mod_type, "modifiersname" ) == 0 ||
- strcasecmp( mods->mod_type, "modifytimestamp" ) == 0 ) {
+ /* the lastmod attributes are ignored by ACL checking */
+ if ( oc_check_no_usermod_attr( mlist->ml_type ) ) {
+ Debug( LDAP_DEBUG_ACL, "Operational attribute: %s access allowed\n",
+ mlist->ml_type, 0, 0 );
continue;
}
- a = acl_get_applicable( be, op, e, mods->mod_type );
+ a = acl_get_applicable( be, op, e, mlist->ml_type,
+ MAXREMATCHES, matches );
- switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) {
+ switch ( mlist->ml_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_REPLACE:
case LDAP_MOD_ADD:
- if ( mods->mod_bvalues == NULL ) {
+ if ( mlist->ml_bvalues == NULL ) {
break;
}
- for ( i = 0; mods->mod_bvalues[i] != NULL; i++ ) {
- if ( ! acl_access_allowed( a, be, conn, e,
- mods->mod_bvalues[i], op, ACL_WRITE ) ) {
+ for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) {
+ if ( ! acl_access_allowed( a, be, conn, e, mlist->ml_bvalues[i],
+ op, ACL_WRITE, edn, matches) )
+ {
return( LDAP_INSUFFICIENT_ACCESS );
}
}
break;
case LDAP_MOD_DELETE:
- if ( mods->mod_bvalues == NULL ) {
+ if ( mlist->ml_bvalues == NULL ) {
if ( ! acl_access_allowed( a, be, conn, e,
- NULL, op, ACL_WRITE ) ) {
+ NULL, op, ACL_WRITE, edn, matches) )
+ {
return( LDAP_INSUFFICIENT_ACCESS );
}
break;
}
- for ( i = 0; mods->mod_bvalues[i] != NULL; i++ ) {
- if ( ! acl_access_allowed( a, be, conn, e,
- mods->mod_bvalues[i], op, ACL_WRITE ) ) {
+ for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) {
+ if ( ! acl_access_allowed( a, be, conn, e, mlist->ml_bvalues[i],
+ op, ACL_WRITE, edn, matches) )
+ {
return( LDAP_INSUFFICIENT_ACCESS );
}
}
return( LDAP_SUCCESS );
}
-#ifdef sunos5
-
-static int
-regex_matches( char *pat, char *str )
+static void
+string_expand(
+ char *newbuf,
+ int bufsiz,
+ char *pat,
+ char *match,
+ regmatch_t *matches)
{
- char *e;
- int rc;
-
- if ( (e = compile( pat, NULL, NULL )) == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "compile( \"%s\", \"%s\") failed\n", pat, str, 0 );
- return( 0 );
+ int size;
+ char *sp;
+ char *dp;
+ int flag;
+
+ size = 0;
+ newbuf[0] = '\0';
+
+ flag = 0;
+ for ( dp = newbuf, sp = pat; size < bufsiz && *sp ; sp++) {
+ /* did we previously see a $ */
+ if (flag) {
+ if (*sp == '$') {
+ *dp++ = '$';
+ size++;
+ } else if (*sp >= '0' && *sp <= '9' ) {
+ int n;
+ int i;
+ int l;
+
+ n = *sp - '0';
+ *dp = '\0';
+ i = matches[n].rm_so;
+ l = matches[n].rm_eo;
+ for ( ; size < 512 && i < l; size++, i++ ) {
+ *dp++ = match[i];
+ size++;
+ }
+ *dp = '\0';
+ }
+ flag = 0;
+ } else {
+ if (*sp == '$') {
+ flag = 1;
+ } else {
+ *dp++ = *sp;
+ size++;
+ }
+ }
}
- rc = step( str ? str : "", e );
- free( e );
+ *dp = '\0';
- return( rc );
+ Debug( LDAP_DEBUG_TRACE, "=> string_expand: pattern: %s\n", pat, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "=> string_expand: expanded: %s\n", newbuf, 0, 0 );
}
-#else /* sunos5 */
-
static int
-regex_matches( char *pat, char *str )
+regex_matches(
+ char *pat, /* pattern to expand and match against */
+ char *str, /* string to match against pattern */
+ char *buf, /* buffer with $N expansion variables */
+ regmatch_t *matches /* offsets in buffer for $N expansion variables */
+)
{
- char *e;
+ regex_t re;
+ char newbuf[512];
int rc;
- pthread_mutex_lock( ®ex_mutex );
- if ( (e = re_comp( pat )) != NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "re_comp( \"%s\", \"%s\") failed because (%s)\n", pat, str,
- e );
- pthread_mutex_unlock( ®ex_mutex );
+ if(str == NULL) str = "";
+
+ string_expand(newbuf, sizeof(newbuf), pat, buf, matches);
+ if (( rc = regcomp(&re, newbuf, REG_EXTENDED|REG_ICASE))) {
+ char error[512];
+ regerror(rc, &re, error, sizeof(error));
+
+ Debug( LDAP_DEBUG_TRACE,
+ "compile( \"%s\", \"%s\") failed %s\n",
+ pat, str, error );
return( 0 );
}
- rc = re_exec( str ? str : "" );
- pthread_mutex_unlock( ®ex_mutex );
- return( rc == 1 );
+ rc = regexec(&re, str, 0, NULL, 0);
+ regfree( &re );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "=> regex_matches: string: %s\n", str, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE,
+ "=> regex_matches: rc: %d %s\n",
+ rc, !rc ? "matches" : "no matches", 0 );
+ return( !rc );
}
-#endif /* sunos5 */
/* acl.c - routines to parse and check acl's */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include "regex.h"
-#include "slap.h"
-#include "portable.h"
-extern Filter *str2filter();
-extern char *re_comp();
-extern struct acl *global_acl;
-extern char **str2charray();
-extern char *dn_upcase();
+#include <ac/ctype.h>
+#include <ac/regex.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include "slap.h"
-static void split();
-static void acl_append();
-static void access_append();
-static void acl_usage();
+static void split(char *line, int splitchar, char **left, char **right);
+static void acl_append(AccessControl **l, AccessControl *a);
+static void access_append(Access **l, Access *a);
+static void acl_usage(void);
#ifdef LDAP_DEBUG
-static void print_acl();
-static void print_access();
+static void print_acl(AccessControl *a);
+static void print_access(Access *b);
#endif
+static int
+regtest(char *fname, int lineno, char *pat) {
+ int e;
+ regex_t re;
+
+ char buf[512];
+ unsigned size;
+
+ char *sp;
+ char *dp;
+ int flag;
+
+ sp = pat;
+ dp = buf;
+ size = 0;
+ buf[0] = '\0';
+
+ for (size = 0, flag = 0; (size < sizeof(buf)) && *sp; sp++) {
+ if (flag) {
+ if (*sp == '$'|| (*sp >= '0' && *sp <= '9')) {
+ *dp++ = *sp;
+ size++;
+ }
+ flag = 0;
+
+ } else {
+ if (*sp == '$') {
+ flag = 1;
+ } else {
+ *dp++ = *sp;
+ size++;
+ }
+ }
+ }
+
+ *dp = '\0';
+ if ( size >= (sizeof(buf)-1) ) {
+ fprintf( stderr,
+ "%s: line %d: regular expression \"%s\" too large\n",
+ fname, lineno, pat, 0 );
+ acl_usage();
+ }
+
+ if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) {
+ char error[512];
+ regerror(e, &re, error, sizeof(error));
+ fprintf( stderr,
+ "%s: line %d: regular expression \"%s\" bad because of %s\n",
+ fname, lineno, pat, error );
+ acl_usage();
+ return(0);
+ }
+ regfree(&re);
+ return(1);
+}
+
void
parse_acl(
Backend *be,
)
{
int i;
- char *e, *left, *right;
- struct acl *a;
- struct access *b;
+ char *left, *right;
+ AccessControl *a;
+ Access *b;
a = NULL;
for ( i = 1; i < argc; i++ ) {
fname, lineno );
acl_usage();
}
- a = (struct acl *) ch_calloc( 1, sizeof(struct acl) );
+ a = (AccessControl *) ch_calloc( 1, sizeof(AccessControl) );
for ( ++i; i < argc; i++ ) {
if ( strcasecmp( argv[i], "by" ) == 0 ) {
i--;
}
if ( strcasecmp( argv[i], "*" ) == 0 ) {
- a->acl_dnpat = strdup( ".*" );
+ a->acl_dn_pat = ch_strdup( ".*" );
continue;
}
fname, lineno, right );
acl_usage();
}
+
} else if ( strcasecmp( left, "dn" ) == 0 ) {
- if ( (e = re_comp( right )) != NULL ) {
+ int e;
+
+ if ((e = regcomp(&a->acl_dn_re, right,
+ REG_EXTENDED|REG_ICASE))) {
+ char buf[512];
+ regerror(e, &a->acl_dn_re, buf, sizeof(buf));
fprintf( stderr,
- "%s: line %d: regular expression \"%s\" bad because of %s\n",
- fname, lineno, right, e );
+ "%s: line %d: regular expression \"%s\" bad because of %s\n",
+ fname, lineno, right, buf );
acl_usage();
+
+ } else {
+ a->acl_dn_pat = ch_strdup( right );
}
- a->acl_dnpat = dn_upcase( strdup(
- right ) );
- } else if ( strncasecmp( left, "attr", 4 )
- == 0 ) {
+
+ } else if ( strncasecmp( left, "attr", 4 ) == 0 ) {
char **alist;
alist = str2charray( right, "," );
charray_merge( &a->acl_attrs, alist );
- free( alist );
+ charray_free( alist );
+
} else {
fprintf( stderr,
- "%s: line %d: expecting <what> got \"%s\"\n",
+ "%s: line %d: expecting <what> got \"%s\"\n",
fname, lineno, left );
acl_usage();
}
} else if ( strcasecmp( argv[i], "by" ) == 0 ) {
if ( a == NULL ) {
fprintf( stderr,
- "%s: line %d: to clause required before by clause in access line\n",
+ "%s: line %d: to clause required before by clause in access line\n",
fname, lineno );
acl_usage();
}
* by clause consists of <who> and <access>
*/
- b = (struct access *) ch_calloc( 1,
- sizeof(struct access) );
+ b = (Access *) ch_calloc( 1, sizeof(Access) );
if ( ++i == argc ) {
fprintf( stderr,
}
/* get <who> */
- split( argv[i], '=', &left, &right );
- if ( strcasecmp( argv[i], "*" ) == 0 ) {
- b->a_dnpat = strdup( ".*" );
- } else if ( strcasecmp( argv[i], "self" ) == 0 ) {
- b->a_dnpat = strdup( "self" );
- } else if ( strcasecmp( left, "dn" ) == 0 ) {
- if ( (e = re_comp( right )) != NULL ) {
- fprintf( stderr,
- "%s: line %d: regular expression \"%s\" bad: %s\n",
- fname, lineno, right, e );
- acl_usage();
+ for ( ; i < argc; i++ ) {
+ char *pat;
+ split( argv[i], '=', &left, &right );
+
+ if ( strcasecmp( argv[i], "*" ) == 0 ) {
+ pat = ch_strdup( ".*" );
+ } else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
+ pat = ch_strdup( "anonymous" );
+ } else if ( strcasecmp( argv[i], "self" ) == 0 ) {
+ pat = ch_strdup( "self" );
+ } else if ( strcasecmp( left, "dn" ) == 0 ) {
+ regtest(fname, lineno, right);
+ pat = ch_strdup( right );
+ } else {
+ pat = NULL;
}
- b->a_dnpat = dn_upcase( strdup( right ) );
- } else if ( strcasecmp( left, "dnattr" )
- == 0 ) {
- b->a_dnattr = strdup( right );
- } else if ( strcasecmp( left, "domain" )
- == 0 ) {
- char *s;
-
- if ( (e = re_comp( right )) != NULL ) {
- fprintf( stderr,
- "%s: line %d: regular expression \"%s\" bad: %s\n",
- fname, lineno, right, e );
- acl_usage();
+
+ if( pat != NULL ) {
+ if( b->a_dn_pat != NULL ) {
+ fprintf( stderr,
+ "%s: line %d: dn pattern already specified.\n",
+ fname, lineno );
+ acl_usage();
+ }
+
+ b->a_dn_pat = pat;
+ continue;
}
- b->a_domainpat = strdup( right );
- /* normalize the domain */
- for ( s = b->a_domainpat; *s; s++ ) {
- *s = TOLOWER( *s );
+
+ if ( strcasecmp( left, "dnattr" ) == 0 ) {
+ if( b->a_dn_pat != NULL ) {
+ fprintf( stderr,
+ "%s: line %d: dnaddr already specified.\n",
+ fname, lineno );
+ acl_usage();
+ }
+
+ b->a_dn_at = ch_strdup( right );
+ continue;
}
- } else if ( strcasecmp( left, "addr" ) == 0 ) {
- if ( (e = re_comp( right )) != NULL ) {
- fprintf( stderr,
- "%s: line %d: regular expression \"%s\" bad: %s\n",
- fname, lineno, right, e );
- acl_usage();
+
+ if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) {
+ char *name = NULL;
+ char *value = NULL;
+
+ if( b->a_group_pat != NULL ) {
+ fprintf( stderr,
+ "%s: line %d: group pattern already specified.\n",
+ fname, lineno );
+ acl_usage();
+ }
+
+ /* format of string is "group/objectClassValue/groupAttrName" */
+ if ((value = strchr(left, '/')) != NULL) {
+ *value++ = '\0';
+ if (value && *value
+ && (name = strchr(value, '/')) != NULL)
+ {
+ *name++ = '\0';
+ }
+ }
+
+ regtest(fname, lineno, right);
+ b->a_group_pat = ch_strdup( right );
+
+ if (value && *value) {
+ b->a_group_oc = ch_strdup(value);
+ *--value = '/';
+ } else {
+ b->a_group_oc = ch_strdup("groupOfNames");
+
+ if (name && *name) {
+ b->a_group_at = ch_strdup(name);
+ *--name = '/';
+
+ } else {
+ b->a_group_at = ch_strdup("member");
+ }
+ }
+ continue;
}
- b->a_addrpat = strdup( right );
- } else {
- fprintf( stderr,
- "%s: line %d: expecting <who> got \"%s\"\n",
- fname, lineno, left );
- acl_usage();
- }
- if ( ++i == argc ) {
- fprintf( stderr,
- "%s: line %d: premature eol: expecting <access>\n",
- fname, lineno );
- acl_usage();
- }
+ if ( strcasecmp( left, "peername" ) == 0 ) {
+ if( b->a_peername_pat != NULL ) {
+ fprintf( stderr,
+ "%s: line %d: peername pattern already specified.\n",
+ fname, lineno );
+ acl_usage();
+ }
- /* get <access> */
- split( argv[i], '=', &left, &right );
- if ( (b->a_access = str2access( left )) == -1 ) {
- fprintf( stderr,
- "%s: line %d: expecting <access> got \"%s\"\n",
- fname, lineno, left );
- acl_usage();
- }
- access_append( &a->acl_access, b );
+ regtest(fname, lineno, right);
+ b->a_peername_pat = ch_strdup( right );
+ continue;
+ }
+
+ if ( strcasecmp( left, "sockname" ) == 0 ) {
+ if( b->a_sockname_pat != NULL ) {
+ fprintf( stderr,
+ "%s: line %d: sockname pattern already specified.\n",
+ fname, lineno );
+ acl_usage();
+ }
+
+ regtest(fname, lineno, right);
+ b->a_sockname_pat = ch_strdup( right );
+ continue;
+ }
+
+ if ( strcasecmp( left, "domain" ) == 0 ) {
+ if( b->a_domain_pat != NULL ) {
+ fprintf( stderr,
+ "%s: line %d: domain pattern already specified.\n",
+ fname, lineno );
+ acl_usage();
+ }
+
+ regtest(fname, lineno, right);
+ b->a_domain_pat = ch_strdup( right );
+ continue;
+ }
+
+ if ( strcasecmp( left, "sockurl" ) == 0 ) {
+ if( b->a_sockurl_pat != NULL ) {
+ fprintf( stderr,
+ "%s: line %d: sockurl pattern already specified.\n",
+ fname, lineno );
+ acl_usage();
+ }
+
+ regtest(fname, lineno, right);
+ b->a_sockurl_pat = ch_strdup( right );
+ continue;
+ }
+ /* get <access> */
+ if ( ACL_IS_INVALID(ACL_SET(b->a_access, str2access( left ))) ) {
+ fprintf( stderr,
+ "%s: line %d: expecting <access> got \"%s\"\n",
+ fname, lineno, left );
+ acl_usage();
+ }
+ access_append( &a->acl_access, b );
+ break;
+ }
} else {
fprintf( stderr,
"%s: line %d: expecting \"to\" or \"by\" got \"%s\"\n",
/* if we have no real access clause, complain and do nothing */
if ( a == NULL ) {
-
fprintf( stderr,
- "%s: line %d: warning: no access clause(s) specified in access line\n",
+ "%s: line %d: warning: no access clause(s) specified in access line\n",
fname, lineno );
} else {
+
+#ifdef LDAP_DEBUG
+ if (ldap_debug & LDAP_DEBUG_ACL)
+ print_acl(a);
+#endif
if ( a->acl_access == NULL ) {
fprintf( stderr,
- "%s: line %d: warning: no by clause(s) specified in access line\n",
+ "%s: line %d: warning: no by clause(s) specified in access line\n",
fname, lineno );
}
{
static char buf[12];
- if ( access & ACL_SELF ) {
+ if ( ACL_IS_SELF( access ) ) {
strcpy( buf, "self" );
} else {
buf[0] = '\0';
}
- if ( access & ACL_NONE ) {
+ if ( ACL_IS_NONE(access) ) {
strcat( buf, "none" );
- } else if ( access & ACL_COMPARE ) {
+ } else if ( ACL_IS_AUTH(access) ) {
+ strcat( buf, "auth" );
+ } else if ( ACL_IS_COMPARE(access) ) {
strcat( buf, "compare" );
- } else if ( access & ACL_SEARCH ) {
+ } else if ( ACL_IS_SEARCH(access) ) {
strcat( buf, "search" );
- } else if ( access & ACL_READ ) {
+ } else if ( ACL_IS_READ(access) ) {
strcat( buf, "read" );
- } else if ( access & ACL_WRITE ) {
+ } else if ( ACL_IS_WRITE(access) ) {
strcat( buf, "write" );
+
} else {
strcat( buf, "unknown" );
}
{
int access;
- access = 0;
+ ACL_CLR(access);
+
if ( strncasecmp( str, "self", 4 ) == 0 ) {
- access |= ACL_SELF;
+ ACL_SET_SELF(access);
str += 4;
}
if ( strcasecmp( str, "none" ) == 0 ) {
- access |= ACL_NONE;
+ ACL_SET_NONE(access);
+ } else if ( strcasecmp( str, "auth" ) == 0 ) {
+ ACL_SET_AUTH(access);
} else if ( strcasecmp( str, "compare" ) == 0 ) {
- access |= ACL_COMPARE;
+ ACL_SET_COMPARE(access);
} else if ( strcasecmp( str, "search" ) == 0 ) {
- access |= ACL_SEARCH;
+ ACL_SET_SEARCH(access);
} else if ( strcasecmp( str, "read" ) == 0 ) {
- access |= ACL_READ;
+ ACL_SET_READ(access);
} else if ( strcasecmp( str, "write" ) == 0 ) {
- access |= ACL_WRITE;
+ ACL_SET_WRITE(access);
} else {
- access = -1;
+ ACL_SET_INVALID(access);
}
return( access );
}
static void
-acl_usage()
+acl_usage( void )
{
- fprintf( stderr, "\n<access clause> ::= access to <what> [ by <who> <access> ]+ \n" );
- fprintf( stderr, "<what> ::= * | [dn=<regex>] [filter=<ldapfilter>] [attrs=<attrlist>]\n" );
- fprintf( stderr, "<attrlist> ::= <attr> | <attr> , <attrlist>\n" );
- fprintf( stderr, "<attr> ::= <attrname> | entry | children\n" );
- fprintf( stderr, "<who> ::= * | self | dn=<regex> | addr=<regex> |\n\tdomain=<regex> | dnattr=<dnattrname>\n" );
- fprintf( stderr, "<access> ::= [self]{none | compare | search | read | write }\n" );
- exit( 1 );
+ fprintf( stderr, "\n"
+ "<access clause> ::= access to <what> [ by <who> <access> ]+ \n"
+ "<what> ::= * | [dn=<regex>] [filter=<ldapfilter>] [attrs=<attrlist>]\n"
+ "<attrlist> ::= <attr> | <attr> , <attrlist>\n"
+ "<attr> ::= <attrname> | entry | children\n"
+ "<who> ::= [ * | anonymous | self | dn=<regex> ]\n"
+ "\t[dnattr=<attrname>]\n"
+ "\t[group[/<objectclass>[/<attrname>]]=<regex>]\n"
+ "\t[peername=<regex>] [sockname=<regex>]\n"
+ "\t[domain=<regex>] [sockurl=<regex>]\n"
+ "<access> ::= [self]{none|auth|compare|search|read|write}\n"
+ );
+ exit( EXIT_FAILURE );
}
static void
}
static void
-access_append( struct access **l, struct access *a )
+access_append( Access **l, Access *a )
{
for ( ; *l != NULL; l = &(*l)->a_next )
; /* NULL */
}
static void
-acl_append( struct acl **l, struct acl *a )
+acl_append( AccessControl **l, AccessControl *a )
{
for ( ; *l != NULL; l = &(*l)->acl_next )
; /* NULL */
#ifdef LDAP_DEBUG
static void
-print_access( struct access *b )
+print_access( Access *b )
{
- printf( "\tby" );
- if ( b->a_dnpat != NULL ) {
- printf( " dn=%s", b->a_dnpat );
- } else if ( b->a_addrpat != NULL ) {
- printf( " addr=%s", b->a_addrpat );
- } else if ( b->a_domainpat != NULL ) {
- printf( " domain=%s", b->a_domainpat );
- } else if ( b->a_dnattr != NULL ) {
- printf( " dnattr=%s", b->a_dnattr );
+ fprintf( stderr, "\tby" );
+
+ if ( b->a_dn_pat != NULL ) {
+ if( strcmp(b->a_dn_pat, "anonymous") == 0 ) {
+ fprintf( stderr, " anonymous" );
+
+ } else if( strcmp(b->a_dn_pat, "self") == 0 ) {
+ fprintf( stderr, " self" );
+
+ } else {
+ fprintf( stderr, " dn=%s", b->a_dn_pat );
+ }
}
- printf( " %s\n", access2str( b->a_access ) );
+
+ if ( b->a_dn_at != NULL ) {
+ fprintf( stderr, " dnattr=%s", b->a_dn_at );
+ }
+
+ if ( b->a_group_pat != NULL ) {
+ fprintf( stderr, " group: %s", b->a_group_pat );
+
+ if ( b->a_group_oc ) {
+ fprintf( stderr, " objectClass: %s", b->a_group_oc );
+
+ if ( b->a_group_at ) {
+ fprintf( stderr, " attributeType: %s", b->a_group_at );
+ }
+ }
+ }
+
+ if ( b->a_peername_pat != NULL ) {
+ fprintf( stderr, " peername=%s", b->a_peername_pat );
+ }
+ if ( b->a_sockname_pat != NULL ) {
+ fprintf( stderr, " sockname=%s", b->a_sockname_pat );
+ }
+
+ if ( b->a_domain_pat != NULL ) {
+ fprintf( stderr, " domain=%s", b->a_domain_pat );
+ }
+
+ if ( b->a_sockurl_pat != NULL ) {
+ fprintf( stderr, " sockurl=%s", b->a_sockurl_pat );
+ }
+
+ fprintf( stderr, "\n" );
}
static void
-print_acl( struct acl *a )
+print_acl( AccessControl *a )
{
int i;
- struct access *b;
+ Access *b;
if ( a == NULL ) {
- printf( "NULL\n" );
+ fprintf( stderr, "NULL\n" );
}
- printf( "access to" );
+ fprintf( stderr, "ACL: access to" );
if ( a->acl_filter != NULL ) {
- printf( " filter=" );
+ fprintf( stderr," filter=" );
filter_print( a->acl_filter );
}
- if ( a->acl_dnpat != NULL ) {
- printf( " dn=" );
- printf( a->acl_dnpat );
+ if ( a->acl_dn_pat != NULL ) {
+ fprintf( stderr, " dn=" );
+ fprintf( stderr, a->acl_dn_pat );
}
if ( a->acl_attrs != NULL ) {
int first = 1;
- printf( " attrs=" );
+ fprintf( stderr, "\n attrs=" );
for ( i = 0; a->acl_attrs[i] != NULL; i++ ) {
if ( ! first ) {
- printf( "," );
+ fprintf( stderr, "," );
}
- printf( a->acl_attrs[i] );
+ fprintf( stderr, a->acl_attrs[i] );
first = 0;
}
}
- printf( "\n" );
+ fprintf( stderr, "\n" );
for ( b = a->acl_access; b != NULL; b = b->a_next ) {
print_access( b );
}
+ fprintf( stderr, "\n" );
}
-#endif
+#endif /* LDAP_DEBUG */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
-extern char *dn_normalize();
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/socket.h>
-extern char *default_referral;
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
-extern int global_lastmod;
+#include "slap.h"
-static void add_created_attrs();
+static int add_created_attrs(Operation *op, Entry *e);
-void
-do_add( conn, op )
- Connection *conn;
- Operation *op;
+int
+do_add( Connection *conn, Operation *op )
{
BerElement *ber = op->o_ber;
- char *dn, *last;
- unsigned long len, tag;
+ char *dn, *ndn, *last;
+ ber_len_t len;
+ ber_tag_t tag;
Entry *e;
Backend *be;
+ int rc = LDAP_SUCCESS;
Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_add: SASL bind in progress.\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
+ "SASL bind in progress", NULL, NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the add request. It looks like this:
*
* }
*/
- e = (Entry *) ch_calloc( 1, sizeof(Entry) );
-
/* get the name */
- if ( ber_scanf( ber, "{a", &dn ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "decoding error" );
- return;
+ if ( ber_scanf( ber, "{a", /*}*/ &dn ) == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+ }
+
+ ndn = ch_strdup( dn );
+
+ if ( dn_normalize_case( ndn ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "do_add: invalid dn (%s)\n", dn, 0, 0 );
+ send_ldap_result( conn, op, LDAP_INVALID_DN_SYNTAX, NULL,
+ "invalid DN", NULL, NULL );
+ free( dn );
+ free( ndn );
+ return LDAP_INVALID_DN_SYNTAX;
}
+
+ e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
e->e_dn = dn;
- dn = dn_normalize( strdup( dn ) );
- Debug( LDAP_DEBUG_ARGS, " do_add: dn (%s)\n", dn, 0, 0 );
+ e->e_ndn = ndn;
+ e->e_private = NULL;
+
+ Debug( LDAP_DEBUG_ARGS, " do_add: ndn (%s)\n", e->e_ndn, 0, 0 );
/* get the attrs */
e->e_attrs = NULL;
struct berval **vals;
if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) {
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
- NULL, "decoding error" );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
entry_free( e );
- return;
+ return -1;
}
if ( vals == NULL ) {
Debug( LDAP_DEBUG_ANY, "no values for type %s\n", type,
0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- NULL );
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "no values for type", NULL, NULL );
+ free( type );
entry_free( e );
- return;
+ return LDAP_PROTOCOL_ERROR;
}
attr_merge( e, type, vals );
ber_bvecfree( vals );
}
- Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d ADD dn=\"%s\"\n",
- conn->c_connid, op->o_opid, dn, 0, 0 );
+ if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) {
+ entry_free( e );
+ Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+ }
+
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ entry_free( e );
+ Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
+
+ Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d ADD dn=\"%s\"\n",
+ op->o_connid, op->o_opid, e->e_ndn, 0, 0 );
/*
* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
- if ( (be = select_backend( dn )) == NULL ) {
+ be = select_backend( e->e_ndn );
+ if ( be == NULL ) {
entry_free( e );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ send_ldap_result( conn, op, LDAP_REFERRAL, NULL,
+ NULL, default_referral, NULL );
+ return rc;
}
/*
* 2) this backend is master for what it holds;
* 3) it's a replica and the dn supplied is the updatedn.
*/
- if ( be->be_add != NULL ) {
+ if ( be->be_add ) {
/* do the update here */
- if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
- op->o_dn ) == 0 ) {
- if ( (be->be_lastmod == ON || be->be_lastmod == 0 &&
- global_lastmod == ON) && be->be_updatedn == NULL ) {
- add_created_attrs( op, e );
+#ifdef SLAPD_MULTIMASTER
+ if ( (be->be_lastmod == ON || (be->be_lastmod == UNDEFINED &&
+ global_lastmod == ON)) && (be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn )) )
+#else
+ if ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
+#endif
+ {
+#ifndef SLAPD_MULTIMASTER
+ if ( (be->be_lastmod == ON || (be->be_lastmod == UNDEFINED &&
+ global_lastmod == ON)) && be->be_update_ndn == NULL )
+#endif
+ {
+ rc = add_created_attrs( op, e );
+
+ if( rc != LDAP_SUCCESS ) {
+ entry_free( e );
+ send_ldap_result( conn, op, rc,
+ NULL, "no-user-modification attribute type",
+ NULL, NULL );
+ return rc;
+ }
}
+
if ( (*be->be_add)( be, conn, op, e ) == 0 ) {
- replog( be, LDAP_REQ_ADD, e->e_dn, e, 0 );
+#ifdef SLAPD_MULTIMASTER
+ if (be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ))
+#endif
+ {
+ replog( be, op, e->e_dn, e );
+ }
+ be_entry_release_w( be, e );
}
+
+#ifndef SLAPD_MULTIMASTER
} else {
entry_free( e );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+ be->be_update_refs ? be->be_update_refs : default_referral, NULL );
+#endif
}
} else {
+ Debug( LDAP_DEBUG_ARGS, " do_add: HHH\n", 0, 0, 0 );
entry_free( e );
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
+
+ return rc;
}
-static void
+static int
add_created_attrs( Operation *op, Entry *e )
{
- char buf[20];
+ char buf[22];
struct berval bv;
struct berval *bvals[2];
- Attribute **a, **next;
- Attribute *tmp;
+ Attribute *a;
struct tm *ltm;
+ time_t currenttime;
Debug( LDAP_DEBUG_TRACE, "add_created_attrs\n", 0, 0, 0 );
bvals[0] = &bv;
bvals[1] = NULL;
- /* remove any attempts by the user to add these attrs */
- for ( a = &e->e_attrs; *a != NULL; a = next ) {
- if ( strcasecmp( (*a)->a_type, "createtimestamp" ) == 0
- || strcasecmp( (*a)->a_type, "creatorsname" ) == 0 ) {
- tmp = *a;
- *a = (*a)->a_next;
- attr_free( tmp );
- next = a;
- } else {
- next = &(*a)->a_next;
+ /* return error on any attempts by the user to add these attrs */
+ for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
+ if ( oc_check_no_usermod_attr( a->a_type ) ) {
+ return LDAP_CONSTRAINT_VIOLATION;
}
}
if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
- bv.bv_val = "NULLDN";
+ bv.bv_val = "<anonymous>";
bv.bv_len = strlen( bv.bv_val );
} else {
bv.bv_val = op->o_dn;
}
attr_merge( e, "creatorsname", bvals );
- pthread_mutex_lock( ¤ttime_mutex );
- ltm = localtime( ¤ttime );
- strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
- pthread_mutex_unlock( ¤ttime_mutex );
+ currenttime = slap_get_time();
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
bv.bv_val = buf;
bv.bv_len = strlen( bv.bv_val );
attr_merge( e, "createtimestamp", bvals );
+
+ return LDAP_SUCCESS;
}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/* attr.c - routines for dealing with attributes */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
+
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+#endif
+
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
-#include <sys/stat.h>
-#include "portable.h"
+#endif
+
+#include "ldap_defaults.h"
#include "slap.h"
-extern char **charray_dup();
-extern char *ch_malloc();
-extern int errno;
+#ifdef LDAP_DEBUG
+static void at_index_print( void );
+#endif
void
attr_free( Attribute *a )
free( a );
}
+void
+attrs_free( Attribute *a )
+{
+ Attribute *next;
+
+ for( ; a != NULL ; a = next ) {
+ next = a->a_next;
+ attr_free( a );
+ }
+}
+
+Attribute *attr_dup( Attribute *a )
+{
+ Attribute *tmp;
+
+ if( a == NULL) return NULL;
+
+ tmp = ch_malloc( sizeof(Attribute) );
+
+ if( a->a_vals != NULL ) {
+ int i;
+
+ for( i=0; a->a_vals[i] != NULL; i++ ) {
+ /* EMPTY */ ;
+ }
+
+ tmp->a_vals = ch_malloc((i+1) * sizeof(struct berval*));
+
+ for( i=0; a->a_vals[i] != NULL; i++ ) {
+ tmp->a_vals[i] = ber_bvdup( a->a_vals[i] );
+ }
+
+ tmp->a_vals[i] = NULL;
+
+ } else {
+ tmp->a_vals = NULL;
+ }
+
+ tmp->a_type = ch_strdup( a->a_type );
+ tmp->a_syntax = a->a_syntax;
+ tmp->a_next = NULL;
+
+ return tmp;
+}
+
+Attribute *attrs_dup( Attribute *a )
+{
+ Attribute *tmp, **next;
+
+ if( a == NULL ) return NULL;
+
+ tmp = NULL;
+ next = &tmp;
+
+ for( ; a != NULL ; a = a->a_next ) {
+ *next = attr_dup( a );
+ next = &((*next)->a_next);
+ }
+ *next = NULL;
+
+ return tmp;
+}
+
/*
* attr_normalize - normalize an attribute name (make it all lowercase)
*/
char *
attr_normalize( char *s )
{
- char *save;
-
- for ( save = s; *s; s++ ) {
- *s = TOLOWER( *s );
- }
+ assert( s != NULL );
- return( save );
+ return( str2lower( s ) );
}
/*
Attribute ***a
)
{
- int i;
-
if ( *a == NULL ) {
for ( *a = &e->e_attrs; **a != NULL; *a = &(**a)->a_next ) {
if ( strcasecmp( (**a)->a_type, type ) == 0 ) {
if ( **a == NULL ) {
**a = (Attribute *) ch_malloc( sizeof(Attribute) );
- (**a)->a_type = attr_normalize( strdup( type ) );
+ (**a)->a_type = attr_normalize( ch_strdup( type ) );
(**a)->a_vals = NULL;
(**a)->a_syntax = attr_syntax( type );
(**a)->a_next = NULL;
struct berval **vals
)
{
- int i;
Attribute **a;
for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
if ( *a == NULL ) {
*a = (Attribute *) ch_malloc( sizeof(Attribute) );
- (*a)->a_type = attr_normalize( strdup( type ) );
+ (*a)->a_type = attr_normalize( ch_strdup( type ) );
(*a)->a_vals = NULL;
(*a)->a_syntax = attr_syntax( type );
(*a)->a_next = NULL;
#define DEFAULT_SYNTAX SYNTAX_CIS
-struct asyntaxinfo {
- char **asi_names;
- int asi_syntax;
-};
-
-static Avlnode *attr_syntaxes = NULL;
-
-static int
-attr_syntax_cmp(
- struct asyntaxinfo *a1,
- struct asyntaxinfo *a2
-)
-{
- return( strcasecmp( a1->asi_names[0], a2->asi_names[0] ) );
-}
-
-static int
-attr_syntax_name_cmp(
- char *type,
- struct asyntaxinfo *a
-)
-{
- return( strcasecmp( type, a->asi_names[0] ) );
-}
-
-static int
-attr_syntax_names_cmp(
- char *type,
- struct asyntaxinfo *a
-)
-{
- int i;
-
- for ( i = 0; a->asi_names[i] != NULL; i++ ) {
- if ( strcasecmp( type, a->asi_names[i] ) == 0 ) {
- return( 0 );
- }
- }
- return( 1 );
-}
-
-static int
-attr_syntax_dup(
- struct asyntaxinfo *a1,
- struct asyntaxinfo *a2
-)
-{
- if ( a1->asi_syntax != a2->asi_syntax ) {
- return( -1 );
- }
-
- return( 1 );
-}
-
/*
* attr_syntax - return the syntax of attribute type
*/
int
attr_syntax( char *type )
{
- struct asyntaxinfo *asi = NULL;
+ AttributeType *sat;
- if ( (asi = (struct asyntaxinfo *) avl_find( attr_syntaxes, type,
- attr_syntax_name_cmp )) != NULL || (asi = (struct asyntaxinfo *)
- avl_find_lin( attr_syntaxes, type, attr_syntax_names_cmp ))
- != NULL )
- {
- return( asi->asi_syntax );
+ sat = at_find(type);
+ if ( sat ) {
+ return( sat->sat_syntax_compat );
}
return( DEFAULT_SYNTAX );
)
{
char *save;
- struct asyntaxinfo *a;
- int i, lasti;
+ LDAP_ATTRIBUTE_TYPE *at;
+ int lasti;
+ int code;
+ const char *err;
if ( argc < 2 ) {
Debug( LDAP_DEBUG_ANY,
return;
}
- a = (struct asyntaxinfo *) ch_calloc( 1, sizeof(struct asyntaxinfo) );
+ at = (LDAP_ATTRIBUTE_TYPE *)
+ ch_calloc( 1, sizeof(LDAP_ATTRIBUTE_TYPE) );
lasti = argc - 1;
if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 ||
strcasecmp( argv[lasti], "cis" ) == 0 ) {
- a->asi_syntax = SYNTAX_CIS;
+ at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15";
+ at->at_equality_oid = "2.5.13.2";
+ at->at_ordering_oid = "2.5.13.3";
+ at->at_substr_oid = "2.5.13.4";
} else if ( strcasecmp( argv[lasti], "telephone" ) == 0 ||
strcasecmp( argv[lasti], "tel" ) == 0 ) {
- a->asi_syntax = (SYNTAX_CIS | SYNTAX_TEL);
+ at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.50";
+ at->at_equality_oid = "2.5.13.20";
+ at->at_substr_oid = "2.5.13.21";
} else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) {
- a->asi_syntax = (SYNTAX_CIS | SYNTAX_DN);
+ at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.12";
+ at->at_equality_oid = "2.5.13.1";
} else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 ||
strcasecmp( argv[lasti], "ces" ) == 0 ) {
- a->asi_syntax = SYNTAX_CES;
+ at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15";
+ at->at_equality_oid = "2.5.13.5";
+ at->at_ordering_oid = "2.5.13.6";
+ at->at_substr_oid = "2.5.13.7";
} else if ( strcasecmp( argv[lasti], "binary" ) == 0 ||
strcasecmp( argv[lasti], "bin" ) == 0 ) {
- a->asi_syntax = SYNTAX_BIN;
+ at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.5";
+ /* There is no match for binary syntax. Really */
} else {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n",
- fname, lineno, 0 );
+ fname, lineno, argv[lasti] );
Debug( LDAP_DEBUG_ANY,
"possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n",
0, 0, 0 );
- free( (char *) a );
+ free( (AttributeType *) at );
return;
}
+
save = argv[lasti];
argv[lasti] = NULL;
- a->asi_names = charray_dup( argv );
+ at->at_names = charray_dup( argv );
argv[lasti] = save;
- switch ( avl_insert( &attr_syntaxes, a, attr_syntax_cmp,
- attr_syntax_dup ) ) {
- case -1: /* duplicate - different syntaxes */
- Debug( LDAP_DEBUG_ARGS, "%s: line %d: duplicate attribute\n",
- fname, lineno, 0 );
- /* FALL */
+ code = at_add( at, &err );
+ if ( code ) {
+ fprintf( stderr, "%s: line %d: %s %s\n",
+ fname, lineno, scherr2str(code), err);
+ exit( EXIT_FAILURE );
+ }
+ ldap_memfree(at);
+}
- case 1: /* duplicate - same syntaxes */
- charray_free( a->asi_names );
- free( (char *) a );
- break;
+int
+at_fake_if_needed(
+ char *name
+)
+{
+ char *argv[3];
- default: /* inserted */
- break;
+ if ( at_find( name ) ) {
+ return 0;
+ } else {
+ argv[0] = name;
+ argv[1] = "cis";
+ argv[2] = NULL;
+ attr_syntax_config( "implicit", 0, 2, argv );
+ return 0;
}
}
-#ifdef LDAP_DEBUG
+struct aindexrec {
+ char *air_name;
+ AttributeType *air_at;
+};
+
+static Avlnode *attr_index = NULL;
+static AttributeType *attr_list = NULL;
+
+static int
+attr_index_cmp(
+ struct aindexrec *air1,
+ struct aindexrec *air2
+)
+{
+ return (strcasecmp( air1->air_name, air2->air_name ));
+}
+
+static int
+attr_index_name_cmp(
+ char *type,
+ struct aindexrec *air
+)
+{
+ return (strcasecmp( type, air->air_name ));
+}
+
+AttributeType *
+at_find(
+ const char *name
+)
+{
+ struct aindexrec *air = NULL;
+
+ if ( (air = (struct aindexrec *) avl_find( attr_index, name,
+ (AVL_CMP) attr_index_name_cmp )) != NULL ) {
+ return( air->air_at );
+ }
+ return( NULL );
+}
+
+int
+at_append_to_list(
+ AttributeType *sat,
+ AttributeType ***listp
+)
+{
+ AttributeType **list;
+ AttributeType **list1;
+ int size;
+
+ list = *listp;
+ if ( !list ) {
+ size = 2;
+ list = calloc(size, sizeof(AttributeType *));
+ if ( !list ) {
+ return -1;
+ }
+ } else {
+ size = 0;
+ list1 = *listp;
+ while ( *list1 ) {
+ size++;
+ list1++;
+ }
+ size += 2;
+ list1 = realloc(list, size*sizeof(AttributeType *));
+ if ( !list1 ) {
+ return -1;
+ }
+ list = list1;
+ }
+ list[size-2] = sat;
+ list[size-1] = NULL;
+ *listp = list;
+ return 0;
+}
+
+int
+at_delete_from_list(
+ int pos,
+ AttributeType ***listp
+)
+{
+ AttributeType **list;
+ AttributeType **list1;
+ int i;
+ int j;
+
+ if ( pos < 0 ) {
+ return -2;
+ }
+ list = *listp;
+ for ( i=0; list[i]; i++ )
+ ;
+ if ( pos >= i ) {
+ return -2;
+ }
+ for ( i=pos, j=pos+1; list[j]; i++, j++ ) {
+ list[i] = list[j];
+ }
+ list[i] = NULL;
+ /* Tell the runtime this can be shrinked */
+ list1 = realloc(list, (i+1)*sizeof(AttributeType **));
+ if ( !list1 ) {
+ return -1;
+ }
+ *listp = list1;
+ return 0;
+}
-static
-attr_syntax_printnode( struct asyntaxinfo *a )
+int
+at_find_in_list(
+ AttributeType *sat,
+ AttributeType **list
+)
{
int i;
- printf( "syntax: 0x%x\n", a->asi_syntax );
- for ( i = 0; a->asi_names[i] != NULL; i++ ) {
- printf( " name: %s\n", a->asi_names[i] );
+ if ( !list ) {
+ return -1;
+ }
+ for ( i=0; list[i]; i++ ) {
+ if ( sat == list[i] ) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static int
+at_insert(
+ AttributeType *sat,
+ const char **err
+)
+{
+ AttributeType **atp;
+ struct aindexrec *air;
+ char **names;
+
+ atp = &attr_list;
+ while ( *atp != NULL ) {
+ atp = &(*atp)->sat_next;
+ }
+ *atp = sat;
+
+ if ( sat->sat_oid ) {
+ air = (struct aindexrec *)
+ ch_calloc( 1, sizeof(struct aindexrec) );
+ air->air_name = sat->sat_oid;
+ air->air_at = sat;
+ if ( avl_insert( &attr_index, (caddr_t) air,
+ (AVL_CMP) attr_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = sat->sat_oid;
+ ldap_memfree(air);
+ return SLAP_SCHERR_DUP_ATTR;
+ }
+ /* FIX: temporal consistency check */
+ at_find(air->air_name);
+ }
+ if ( (names = sat->sat_names) ) {
+ while ( *names ) {
+ air = (struct aindexrec *)
+ ch_calloc( 1, sizeof(struct aindexrec) );
+ air->air_name = ch_strdup(*names);
+ air->air_at = sat;
+ if ( avl_insert( &attr_index, (caddr_t) air,
+ (AVL_CMP) attr_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = *names;
+ ldap_memfree(air);
+ return SLAP_SCHERR_DUP_ATTR;
+ }
+ /* FIX: temporal consistency check */
+ at_find(air->air_name);
+ names++;
+ }
+ }
+
+ return 0;
+}
+
+int
+at_add(
+ LDAP_ATTRIBUTE_TYPE *at,
+ const char **err
+)
+{
+ AttributeType *sat;
+ AttributeType *sat1;
+ MatchingRule *mr;
+ Syntax *syn;
+ int code;
+ char *errattr;
+
+ if ( at->at_names && at->at_names[0] ) {
+ errattr = at->at_names[0];
+ } else if ( at->at_oid ) {
+ errattr = at->at_oid;
+ } else {
+ errattr = "";
+ return SLAP_SCHERR_ATTR_INCOMPLETE;
}
+ sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
+ memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE));
+ if ( at->at_sup_oid ) {
+ if ( (sat1 = at_find(at->at_sup_oid)) ) {
+ sat->sat_sup = sat1;
+ if ( at_append_to_list(sat, &sat1->sat_subtypes) ) {
+ *err = errattr;
+ return SLAP_SCHERR_OUTOFMEM;
+ }
+ } else {
+ *err = at->at_sup_oid;
+ return SLAP_SCHERR_ATTR_NOT_FOUND;
+ }
+ }
+
+ if ( at->at_syntax_oid ) {
+ if ( (syn = syn_find(sat->sat_syntax_oid)) ) {
+ sat->sat_syntax = syn;
+ } else {
+ *err = sat->sat_syntax_oid;
+ return SLAP_SCHERR_SYN_NOT_FOUND;
+ }
+ if ( !strcmp(at->at_syntax_oid,
+ "1.3.6.1.4.1.1466.115.121.1.15") ) {
+ if ( at->at_equality_oid &&
+ !strcmp(at->at_equality_oid, "2.5.13.5") ) {
+ sat->sat_syntax_compat = SYNTAX_CES;
+ } else {
+ sat->sat_syntax_compat = SYNTAX_CIS;
+ }
+ } else if ( !strcmp(at->at_syntax_oid,
+ "1.3.6.1.4.1.1466.115.121.1.50") ) {
+ sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL;
+ } else if ( !strcmp(at->at_syntax_oid,
+ "1.3.6.1.4.1.1466.115.121.1.12") ) {
+ sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_DN;
+ } else if ( !strcmp(at->at_syntax_oid, "1.3.6.1.4.1.1466.115.121.1.5") ) {
+ sat->sat_syntax_compat = SYNTAX_BIN;
+ } else {
+ sat->sat_syntax_compat = DEFAULT_SYNTAX;
+ }
+ } else {
+ sat->sat_syntax_compat = DEFAULT_SYNTAX;
+ }
+
+ if ( sat->sat_equality_oid ) {
+ if ( (mr = mr_find(sat->sat_equality_oid)) ) {
+ sat->sat_equality = mr;
+ } else {
+ *err = sat->sat_equality_oid;
+ return SLAP_SCHERR_MR_NOT_FOUND;
+ }
+ }
+ if ( sat->sat_ordering_oid ) {
+ if ( (mr = mr_find(sat->sat_ordering_oid)) ) {
+ sat->sat_ordering = mr;
+ } else {
+ *err = sat->sat_ordering_oid;
+ return SLAP_SCHERR_MR_NOT_FOUND;
+ }
+ }
+ if ( sat->sat_substr_oid ) {
+ if ( (mr = mr_find(sat->sat_substr_oid)) ) {
+ sat->sat_substr = mr;
+ } else {
+ *err = sat->sat_substr_oid;
+ return SLAP_SCHERR_MR_NOT_FOUND;
+ }
+ }
+
+ /*
+ * Now inherit definitions from superiors. We only check the
+ * direct superior since that one has already inherited from
+ * its own superiorss
+ */
+ if ( sat->sat_sup ) {
+ if ( !sat->sat_syntax ) {
+ sat->sat_syntax = sat->sat_sup->sat_syntax;
+ sat->sat_syntax_len = sat->sat_sup->sat_syntax_len;
+ }
+ if ( !sat->sat_equality ) {
+ sat->sat_equality = sat->sat_sup->sat_equality;
+ }
+ if ( !sat->sat_ordering ) {
+ sat->sat_ordering = sat->sat_sup->sat_ordering;
+ }
+ if ( !sat->sat_substr ) {
+ sat->sat_substr = sat->sat_sup->sat_substr;
+ }
+ }
+ code = at_insert(sat,err);
+ return code;
+}
+
+
+char *
+at_canonical_name( char * a_type )
+{
+ AttributeType *atp;
+
+ if ( (atp=at_find(a_type)) == NULL ) {
+
+ return a_type;
+
+ } else if ( atp->sat_names
+ && atp->sat_names[0]
+ && (*(atp->sat_names[0]) != '\0') ) {
+
+ return atp->sat_names[0];
+
+ } else if (atp->sat_oid && (*atp->sat_oid != '\0')) {
+
+ return atp->sat_oid;
+
+ } else {
+
+ return a_type;
+
+ }
+
+}/* char * at_canonica_name() */
+
+
+#if defined( SLAPD_SCHEMA_DN )
+
+int
+at_schema_info( Entry *e )
+{
+ struct berval val;
+ struct berval *vals[2];
+ AttributeType *at;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ for ( at = attr_list; at; at = at->sat_next ) {
+ val.bv_val = ldap_attributetype2str( &at->sat_atype );
+ if ( val.bv_val ) {
+ val.bv_len = strlen( val.bv_val );
+ Debug( LDAP_DEBUG_TRACE, "Merging at [%d] %s\n",
+ val.bv_len, val.bv_val, 0 );
+ attr_merge( e, "attributeTypes", vals );
+ ldap_memfree( val.bv_val );
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+#endif
+
+#ifdef LDAP_DEBUG
+
+static int
+at_index_printnode( struct aindexrec *air )
+{
+
+ printf( "%s = %s\n", air->air_name, ldap_attributetype2str(&air->air_at->sat_atype) );
return( 0 );
}
-static
-attr_syntax_print()
+static void
+at_index_print( void )
{
- (void) avl_apply( attr_syntaxes, attr_syntax_printnode, 0, -1,
- AVL_INORDER );
+ printf("Printing attribute type index:\n");
+ (void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode,
+ 0, -1, AVL_INORDER );
}
#endif
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/* ava.c - routines for dealing with attribute value assertions */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
int
if ( ber_scanf( ber, "{ao}", &ava->ava_type, &ava->ava_value )
== LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, " get_ava ber_scanf\n", 0, 0, 0 );
- return( LDAP_PROTOCOL_ERROR );
+ return( -1 );
}
attr_normalize( ava->ava_type );
value_normalize( ava->ava_value.bv_val, attr_syntax( ava->ava_type ) );
- return( 0 );
+ return( LDAP_SUCCESS );
}
void
--- /dev/null
+SRCS = idl.c add.c search.c cache.c dbcache.c dn2id.c entry.c id2entry.c \
+ index.c id2children.c nextid.c abandon.c compare.c group.c \
+ modify.c modrdn.c delete.c init.c config.c bind.c attr.c \
+ filterindex.c unbind.c kerberos.c close.c alias.c startup.c \
+ timing.c porter.c txn.c tools.c
+OBJS = idl.lo add.lo search.lo cache.lo dbcache.lo dn2id.lo entry.lo id2entry.lo \
+ index.lo id2children.lo nextid.lo abandon.lo compare.lo group.lo \
+ modify.lo modrdn.lo delete.lo init.lo config.lo bind.lo attr.lo \
+ filterindex.lo unbind.lo kerberos.lo close.lo alias.lo startup.lo \
+ timing.lo porter.lo txn.lo tools.lo
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-bdb2"
+BUILD_MOD = @BUILD_BDB2@
+LINKAGE = @BUILD_BDB2_DYNAMIC@
+
+LIBBASE = back_bdb2
+
+XINCPATH = -I.. -I$(srcdir)/..
+XDEFS = $(MODULES_CPPFLAGS)
+XLDFLAGS = $(MODULES_LDFLAGS)
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+ @touch $@
+
--- /dev/null
+/* add.c - ldap bdb2 back-end add routine */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+static DB_LOCK lock;
+
+
+static int
+bdb2i_back_add_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char *pdn;
+ Entry *p = NULL;
+ int rc;
+ struct timeval time1;
+
+ Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_add: %s\n", e->e_dn, 0, 0);
+
+ if ( ( bdb2i_dn2id( be, e->e_ndn ) ) != NOID ) {
+ entry_free( e );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL, NULL );
+ return( -1 );
+ }
+
+ if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
+ 0, 0, 0 );
+
+ entry_free( e );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL, NULL );
+ return( -1 );
+ }
+
+ /*
+ * Get the parent dn and see if the corresponding entry exists.
+ * If the parent does not exist, only allow the "root" user to
+ * add the entry.
+ */
+
+ pdn = dn_parent( be, e->e_ndn );
+
+ if( pdn != NULL && *pdn != '\0' ) {
+ Entry *matched = NULL;
+
+ assert( *pdn != '\0' );
+
+ /* get parent with writer lock */
+ if ( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL ) {
+ char *matched_dn;
+ struct berval **refs;
+
+ if( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ bdb2i_cache_return_entry_w( &li->li_cache, matched );
+
+ } else {
+ matched_dn = NULL;
+ refs = default_referral;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+ 0, 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched_dn, NULL, NULL, NULL );
+
+ if ( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ entry_free( e );
+ free( pdn );
+ return -1;
+ }
+
+ free(pdn);
+
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
+ Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+
+
+ if ( is_entry_alias( p ) ) {
+ /* parent is an alias, don't allow add */
+
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
+ Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+
+ if ( is_entry_referral( p ) ) {
+ /* parent is an referral, don't allow add */
+ char *matched_dn = ch_strdup( matched->e_dn );
+ struct berval **refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
+ Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
+ entry_free( e );
+ return -1;
+ }
+
+ } else {
+ if(pdn != NULL) {
+ assert( *pdn == '\0' );
+ free(pdn);
+ }
+
+ /* no parent, must be adding entry to root */
+ if ( !be_isroot( be, op->o_ndn ) && !be_issuffix(be, "") ) {
+ Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
+ pdn == NULL ? "suffix" : "entry at root",
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+ }
+
+ e->e_id = bdb2i_next_id( be );
+
+ /*
+ * Try to add the entry to the cache, assign it a new dnid.
+ */
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ rc = bdb2i_cache_add_entry_rw( &li->li_cache, e, CACHE_WRITE_LOCK );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-CACHE", conn, op );
+
+ if ( rc != 0 ) {
+ if( p != NULL) {
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+ }
+
+ Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
+ 0 );
+
+ /* free the entry */
+ entry_free( e );
+
+ send_ldap_result( conn, op,
+ rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ return( -1 );
+ }
+
+ rc = -1;
+
+ /*
+ * Add the entry to the attribute indexes, then add it to
+ * the id2entry and dn2id index.
+ */
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ /* attribute indexes */
+ if ( bdb2i_index_add_entry( be, e ) != 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "bdb2i_index_add_entry failed\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
+
+ goto return_results;
+ }
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ /* dn2id index */
+ if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "bdb2i_dn2id_add failed\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
+
+ goto return_results;
+ }
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ /* id2entry index */
+ if ( bdb2i_id2entry_add( be, e ) != 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "bdb2i_id2entry_add failed\n", 0,
+ 0, 0 );
+ (void) bdb2i_dn2id_delete( be, e->e_ndn );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
+
+ goto return_results;
+ }
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
+
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 0;
+
+return_results:;
+ if (p != NULL) {
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rc ) {
+ /* free entry and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+ }
+
+ return( rc );
+}
+
+
+int
+bdb2_back_add(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ return( -1 );
+ }
+
+ /* check, if a new default attribute index will be created,
+ in which case we have to open the index file BEFORE TP */
+ switch ( slapMode & SLAP_MODE ) {
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+ bdb2i_check_default_attr_index_add( li, e );
+ break;
+ }
+
+ ret = bdb2i_back_add_internal( be, conn, op, e );
+
+ /* if the operation was successful, we will delay the unlock */
+ if ( ret )
+ (void) bdb2i_leave_backend_w( lock );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD", conn, op );
+
+ return( ret );
+}
+
+
+int
+bdb2i_release_add_lock( void )
+{
+ (void) bdb2i_leave_backend_w( lock );
+ return 0;
+}
+
+
--- /dev/null
+/* back-bdb2.h - ldap bdb2 back-end header file */
+
+#ifndef _BACK_BDB2_H_
+#define _BACK_BDB2_H_
+
+#include "ldbm.h"
+#include "db.h"
+
+LDAP_BEGIN_DECL
+
+#define DEFAULT_CACHE_SIZE 1000
+
+/* since DEFAULT_DB_PAGE_SIZE is 1K, we have 128K,
+ which is suggested by Sleepycat */
+#define DEFAULT_DBCACHE_SIZE (128 * DEFAULT_DB_PAGE_SIZE)
+
+#define DEFAULT_DB_DIRECTORY "/usr/tmp"
+#define DEFAULT_DB_HOME "/usr/tmp"
+#define DEFAULT_MODE 0600
+
+#define SUBLEN 3
+
+#define DN_BASE_PREFIX '='
+#define DN_ONE_PREFIX '@'
+#define DN_SUBTREE_PREFIX '?'
+
+#define SLAPD_FILTER_DN_ONE ((ber_tag_t) -2)
+#define SLAPD_FILTER_DN_SUBTREE ((ber_tag_t) -3)
+
+
+#define BDB2_SUFFIX ".bdb2"
+
+
+/*
+ * there is a single index for each attribute. these prefixes ensure
+ * that there is no collision among keys.
+ */
+#define EQ_PREFIX '=' /* prefix for equality keys */
+#define APPROX_PREFIX '~' /* prefix for approx keys */
+#define SUB_PREFIX '*' /* prefix for substring keys */
+#define CONT_PREFIX '\\' /* prefix for continuation keys */
+
+/* allow 3 characters per byte + PREFIX + EOS */
+#define CONT_SIZE ( sizeof(long)*3 + 1 + 1 )
+
+
+#define UNKNOWN_PREFIX '?' /* prefix for unknown keys */
+
+#define DEFAULT_BLOCKSIZE 8192
+
+/*
+ * This structure represents an id block on disk and an id list
+ * in core.
+ *
+ * The fields have the following meanings:
+ *
+ * b_nmax maximum number of ids in this block. if this is == ALLIDSBLOCK,
+ * then this block represents all ids.
+ * b_nids current number of ids in use in this block. if this
+ * is == INDBLOCK, then this block is an indirect block
+ * containing a list of other blocks containing actual ids.
+ * the list is terminated by an id of NOID.
+ * b_ids a list of the actual ids themselves
+ */
+
+typedef ID ID_BLOCK;
+
+#define ID_BLOCK_NMAX_OFFSET 0
+#define ID_BLOCK_NIDS_OFFSET 1
+#define ID_BLOCK_IDS_OFFSET 2
+
+/* all ID_BLOCK macros operate on a pointer to a ID_BLOCK */
+
+#define ID_BLOCK_NMAX(b) ((b)[ID_BLOCK_NMAX_OFFSET])
+#define ID_BLOCK_NIDS(b) ((b)[ID_BLOCK_NIDS_OFFSET])
+#define ID_BLOCK_ID(b, n) ((b)[ID_BLOCK_IDS_OFFSET+(n)])
+
+#define ID_BLOCK_NOID(b, n) (ID_BLOCK_ID((b),(n)) == NOID)
+
+#define ID_BLOCK_ALLIDS_VALUE 0
+#define ID_BLOCK_ALLIDS(b) (ID_BLOCK_NMAX(b) == ID_BLOCK_ALLIDS_VALUE)
+
+#define ID_BLOCK_INDIRECT_VALUE 0
+#define ID_BLOCK_INDIRECT(b) (ID_BLOCK_NIDS(b) == ID_BLOCK_INDIRECT_VALUE)
+
+/* for the in-core cache of entries */
+struct cache {
+ int c_maxsize;
+ int c_cursize;
+ Avlnode *c_dntree;
+ Avlnode *c_idtree;
+ Entry *c_lruhead; /* lru - add accessed entries here */
+ Entry *c_lrutail; /* lru - rem lru entries from here */
+ ldap_pvt_thread_mutex_t c_mutex;
+};
+
+#define CACHE_READ_LOCK 0
+#define CACHE_WRITE_LOCK 1
+
+/* for the cache of open index files (re-used for txn) */
+struct dbcache {
+ int dbc_refcnt;
+ int dbc_maxids;
+ int dbc_maxindirect;
+ long dbc_blksize;
+ char *dbc_name;
+ LDBM dbc_db;
+
+ struct dbcache *next;
+};
+
+typedef struct dbcache BDB2_TXN_FILES;
+typedef struct dbcache DBCache;
+
+
+/* for the cache of attribute information (which are indexed, etc.) */
+struct attrinfo {
+ char *ai_type; /* type name (cn, sn, ...) */
+ int ai_indexmask; /* how the attr is indexed */
+#define INDEX_PRESENCE 0x0001
+#define INDEX_EQUALITY 0x0002
+#define INDEX_APPROX 0x0004
+#define INDEX_SUB 0x0008
+#define INDEX_UNKNOWN 0x0010
+#define INDEX_FROMINIT 0x1000
+ int ai_syntaxmask; /* what kind of syntax */
+/* ...from slap.h...
+#define SYNTAX_CIS 0x01
+#define SYNTAX_CES 0x02
+#define SYNTAX_BIN 0x04
+ ... etc. ...
+*/
+};
+
+/* TP stuff */
+
+typedef struct _bdb2_txn_head {
+
+ /* log size and timer to control checkpoints */
+ u_int32_t txn_log;
+ u_int32_t txn_time;
+
+ /* a list of all DB files in use */
+ BDB2_TXN_FILES *dbFiles;
+
+ /* we have five fixed files */
+#define BDB2_DB_DN_FILE 0
+#define BDB2_DB_DN2ID_FILE 1
+#define BDB2_DB_ID2ENTRY_FILE 2
+#define BDB2_DB_ID2CHILDREN_FILE 3
+#define BDB2_DB_OC_IDX_FILE 4
+
+ /* a database handle for the NEXTID file
+ (must be opened like all DB files at startup
+ and closed on shutdown */
+ LDBM nextidFile;
+
+ /* is the default attribute index set to non-none */
+ int withDefIDX;
+#define BDB2_WITH_DEF_IDX 1
+
+ /* a handle for the backend's environment */
+ DB_ENV **dbenvH;
+
+} BDB2_TXN_HEAD;
+
+
+/* end of TP stuff */
+
+
+/* the private description of a backend type */
+struct ldbtype {
+ char *lty_dbhome;
+ size_t lty_mpsize;
+ int lty_betiming;
+};
+
+#define with_timing(bi) (((struct ldbtype *) \
+ (bi)->bi_private)->lty_betiming == 1)
+
+/* The DB environment */
+extern DB_ENV bdb2i_dbEnv;
+
+
+/* the private description of a database */
+struct ldbminfo {
+ ID li_nextid;
+ char *li_nextid_file;
+ int li_mode;
+ char *li_directory;
+ struct cache li_cache;
+ Avlnode *li_attrs;
+ int li_dbcachesize;
+ int li_dbcachewsync;
+
+ /* a list of all files of the database */
+ BDB2_TXN_HEAD li_txn_head;
+
+};
+
+
+#include "proto-back-bdb2.h"
+
+LDAP_END_DECL
+
+#endif /* _back_bdb2_h_ */
--- /dev/null
+/* close.c - close bdb2 backend database */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+
+static int
+bdb2i_back_db_close_internal( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ DB_LOCK lock;
+
+ /* since close will probably write the NEXTID file,
+ wee need transaction control */
+ if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
+ return( -1 );
+ }
+
+ if ( li->li_nextid != NOID ) {
+ Debug( LDAP_DEBUG_TRACE, "bdb2 backend saving nextid\n", 0, 0, 0 );
+ if ( bdb2i_next_id_save( be ) < 0 ) {
+ Debug( LDAP_DEBUG_ANY, "bdb2 backend nextid save failed!\n",
+ 0, 0, 0 );
+ }
+ }
+
+ /* before closing all files, leave the backend (thus commiting
+ all writes) and set a last checkpoint */
+ (void) bdb2i_leave_backend_w( lock );
+ (void) bdb2i_set_txn_checkpoint( bdb2i_dbEnv.tx_info, 1 );
+
+ /* close all DB files */
+ Debug( LDAP_DEBUG_TRACE, "bdb2 backend closing DB files\n", 0, 0, 0 );
+ bdb2i_txn_close_files( be );
+ Debug( LDAP_DEBUG_TRACE, "bdb2 backend done closing DB files\n", 0, 0, 0 );
+
+ return 0;
+}
+
+
+int
+bdb2_back_db_close( BackendDB *be )
+{
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ ret = bdb2i_back_db_close_internal( be );
+
+ bdb2i_stop_timing( be->bd_info, time1, "CLOSE", NULL, NULL );
+
+ return( ret );
+}
+
+
--- /dev/null
+/* ldbmcache.c - maintain a cache of open bdb2 files */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "ldap_defaults.h"
+#include "slap.h"
+#include "back-bdb2.h"
+
+struct dbcache *
+bdb2i_cache_open(
+ BackendDB *be,
+ char *name,
+ char *suffix,
+ int flags
+)
+{
+ /* all files are open, so return handle from file cache */
+ switch ( slapMode & SLAP_MODE ) {
+
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+ {
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char buf[MAXPATHLEN];
+
+ /* use short name */
+ sprintf( buf, "%s%s", name, suffix );
+ return( bdb2i_get_db_file_cache( li, buf ));
+
+ }
+ break;
+
+ default:
+ /* if not SERVER or TOOL, who else would ask?
+ NO ONE, so return error */
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_cache_open: database user (%d) unknown -- cannot open \"%s%s\".\n",
+ slapMode, name, suffix );
+ return( NULL );
+ }
+}
+
+void
+bdb2i_cache_close( BackendDB *be, struct dbcache *db )
+{
+ /* all files stay open until SERVER or TOOL shut down */
+ switch ( slapMode & SLAP_MODE ) {
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+ return;
+
+ default:
+ /* if unknown user, complain */
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_cache_close: database user (%d) unknown -- ignored.\n",
+ slapMode, 0, 0 );
+ return;
+ }
+}
+
+void
+bdb2i_cache_really_close( BackendDB *be, struct dbcache *db )
+{
+ /* all files stay open until SERVER or TOOL shut down */
+ switch ( slapMode & SLAP_MODE ) {
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+ return;
+
+ default:
+ /* if unknown user, complain */
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_cache_really_close: database user (%d) unknown -- ignored.\n",
+ slapMode, 0, 0 );
+ return;
+ }
+}
+
+void
+bdb2i_cache_flush_all( BackendDB *be )
+{
+ /* if SERVER or TOOL, syncing is done by TP, or during shutdown */
+ switch ( slapMode & SLAP_MODE ) {
+
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+ return;
+
+ default:
+ /* if unknown user, complain */
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_cache_flush_all: database user (%d) unknown -- ignored.\n",
+ slapMode, 0, 0 );
+ return;
+ }
+}
+
+Datum
+bdb2i_cache_fetch(
+ struct dbcache *db,
+ Datum key
+)
+{
+ Datum data;
+
+ ldbm_datum_init( data );
+
+ data = bdb2i_db_fetch( db->dbc_db, key );
+
+ return( data );
+}
+
+int
+bdb2i_cache_store(
+ struct dbcache *db,
+ Datum key,
+ Datum data,
+ int flags
+)
+{
+ int rc;
+ struct timeval time1;
+
+#ifdef LDBM_DEBUG
+ Statslog( LDAP_DEBUG_STATS,
+ "=> bdb2i_cache_store(): key.dptr=%s, key.dsize=%d\n",
+ key.dptr, key.dsize, 0, 0, 0 );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "=> bdb2i_cache_store(): key.dptr=0x%08x, data.dptr=0x%0 8x\n",
+ key.dptr, data.dptr, 0, 0, 0 );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "=> bdb2i_cache_store(): data.dptr=%s, data.dsize=%d\n",
+ data.dptr, data.dsize, 0, 0, 0 );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "=> bdb2i_cache_store(): flags=0x%08x\n",
+ flags, 0, 0, 0, 0 );
+#endif /* LDBM_DEBUG */
+
+ if ( slapMode & SLAP_TIMED_MODE )
+ bdb2i_uncond_start_timing( &time1 );
+
+ rc = bdb2i_db_store( db->dbc_db, key, data, flags );
+
+ if ( slapMode & SLAP_TIMED_MODE ) {
+ char buf[BUFSIZ];
+ char buf2[BUFSIZ];
+
+ *buf2 = '\0';
+ if ( !( strcasecmp( db->dbc_name, "dn.bdb2" )))
+ sprintf( buf2, " [%s]", key.dptr );
+ sprintf( buf, "ADD-BDB2( %s%s )", db->dbc_name, buf2 );
+ bdb2i_uncond_stop_timing( time1, buf,
+ NULL, NULL, LDAP_DEBUG_TRACE );
+ }
+
+ return( rc );
+}
+
+int
+bdb2i_cache_delete(
+ struct dbcache *db,
+ Datum key
+)
+{
+ int rc;
+
+ rc = bdb2i_db_delete( db->dbc_db, key );
+
+ return( rc );
+}
--- /dev/null
+/* delete.c - bdb2 backend delete routine */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+static int
+bdb2i_back_delete_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *matched = NULL;
+ char *pdn = NULL;
+ Entry *e, *p = NULL;
+ int rc = -1, manageDSAit;
+
+ Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_delete: %s\n", dn, 0, 0);
+
+ /* get entry with writer lock */
+ if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: no such object %s\n",
+ dn, 0, 0);
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ return( -1 );
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ goto return_results;
+ }
+
+
+ if ( bdb2i_has_children( be, e ) ) {
+ Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: non leaf %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_WRITE ) )
+ {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb2i_back_delete: insufficient access %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+#endif
+
+ /* find parent's entry */
+ if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
+ if( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- bdb2i_back_delete: parent does not exist\n", 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- bdb2i_back_delete: no access to parent\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ } else {
+ /* no parent, must be root to delete */
+ if( ! be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- bdb2i_back_delete: no parent & not root\n", 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+ }
+
+ /* delete from dn2id mapping */
+ if ( bdb2i_dn2id_delete( be, e->e_ndn ) != 0 ) {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb2i_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* delete from disk and cache */
+ if ( bdb2i_id2entry_delete( be, e ) != 0 ) {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb2i_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 0;
+
+return_results:;
+ if ( pdn != NULL ) free(pdn);
+
+ if( p != NULL ) {
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
+ }
+
+ /* free entry and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+
+ if ( matched != NULL ) free(matched);
+
+ return rc;
+}
+
+
+int
+bdb2_back_delete(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ return( -1 );
+ }
+
+ ret = bdb2i_back_delete_internal( be, conn, op, dn );
+ (void) bdb2i_leave_backend_w( lock );
+ bdb2i_stop_timing( be->bd_info, time1, "DEL", conn, op );
+
+ return( ret );
+}
+
+
--- /dev/null
+/* dn2id.c - routines to deal with the dn2id index */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+int
+bdb2i_dn2id_add(
+ BackendDB *be,
+ char *dn,
+ ID id
+)
+{
+ int rc, flags;
+ struct dbcache *db;
+ Datum key, data;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id_add( \"%s\", %ld )\n", dn, id, 0 );
+
+ if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "Could not open/create dn2id%s\n",
+ BDB2_SUFFIX, 0, 0 );
+ return( -1 );
+ }
+
+ ldbm_datum_init( key );
+ key.dsize = strlen( dn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
+
+ ldbm_datum_init( data );
+ data.dptr = (char *) &id;
+ data.dsize = sizeof(ID);
+
+ flags = LDBM_INSERT;
+ if ( li->li_dbcachewsync ) flags |= LDBM_SYNC;
+
+ rc = bdb2i_cache_store( db, key, data, flags );
+
+ free( key.dptr );
+
+ if ( rc != -1 ) {
+ char *pdn = dn_parent( NULL, dn );
+
+ if( pdn != NULL ) {
+ ldbm_datum_init( key );
+ key.dsize = strlen( pdn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, pdn );
+ rc = bdb2i_idl_insert_key( be, db, key, id );
+ free( key.dptr );
+ free( pdn );
+ }
+ }
+
+ if ( rc != -1 ) {
+ char **subtree = dn_subtree( NULL, dn );
+
+ if( subtree != NULL ) {
+ int i;
+ for( i=0; subtree[i] != NULL; i++ ) {
+ ldbm_datum_init( key );
+ key.dsize = strlen( subtree[i] ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_SUBTREE_PREFIX, subtree[i] );
+
+ rc = bdb2i_idl_insert_key( be, db, key, id );
+
+ free( key.dptr );
+ }
+
+ charray_free( subtree );
+ }
+ }
+
+ bdb2i_cache_close( be, db );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id_add %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+ID
+bdb2i_dn2id(
+ BackendDB *be,
+ char *dn
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct dbcache *db;
+ ID id;
+ Datum key, data;
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id( \"%s\" )\n", dn, 0, 0 );
+
+ /* first check the cache */
+ if ( (id = bdb2i_cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) {
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id %ld (in cache)\n", id,
+ 0, 0 );
+ return( id );
+ }
+
+ if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "<= bdb2i_dn2id could not open dn2id%s\n",
+ BDB2_SUFFIX, 0, 0 );
+ return( NOID );
+ }
+
+ ldbm_datum_init( key );
+
+ key.dsize = strlen( dn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
+
+ data = bdb2i_cache_fetch( db, key );
+
+ bdb2i_cache_close( be, db );
+
+ free( key.dptr );
+
+ if ( data.dptr == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id NOID\n", 0, 0, 0 );
+ return( NOID );
+ }
+
+ (void) memcpy( (char *) &id, data.dptr, sizeof(ID) );
+
+ ldbm_datum_free( db->dbc_db, data );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id %ld\n", id, 0, 0 );
+ return( id );
+}
+
+ID_BLOCK *
+bdb2i_dn2idl(
+ BackendDB *be,
+ char *dn,
+ int prefix )
+{
+ struct dbcache *db;
+ Datum key;
+ ID_BLOCK *idl;
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2idl( \"%c%s\" )\n", prefix, dn, 0 );
+
+ if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "<= bdb2i_dn2idl could not open dn2id%s\n", BDB2_SUFFIX,
+ 0, 0 );
+ return( NULL );
+ }
+
+ ldbm_datum_init( key );
+
+ key.dsize = strlen( dn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", prefix, dn );
+
+ idl = bdb2i_idl_fetch( be, db, key );
+
+ free( key.dptr );
+
+ bdb2i_cache_close( be, db );
+
+ return( idl );
+}
+
+int
+bdb2i_dn2id_delete(
+ BackendDB *be,
+ char *dn
+)
+{
+ struct dbcache *db;
+ Datum key;
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id_delete( \"%s\" )\n", dn, 0, 0 );
+
+ if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "<= bdb2i_dn2id_delete could not open dn2id%s\n", BDB2_SUFFIX,
+ 0, 0 );
+ return( -1 );
+ }
+
+ ldbm_datum_init( key );
+
+ key.dsize = strlen( dn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
+
+ rc = bdb2i_cache_delete( db, key );
+
+ free( key.dptr );
+
+ bdb2i_cache_close( be, db );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id_delete %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+/*
+ * dn2entry - look up dn in the cache/indexes and return the corresponding
+ * entry.
+ */
+
+Entry *
+bdb2i_dn2entry_rw(
+ BackendDB *be,
+ char *dn,
+ Entry **matched,
+ int rw
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ ID id;
+ Entry *e = NULL;
+ char *pdn;
+
+ Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
+ rw ? "w" : "r", dn, 0);
+
+ if( matched != NULL ) {
+ /* caller cares about match */
+ *matched = NULL;
+ }
+
+ if ( (id = bdb2i_dn2id( be, dn )) != NOID &&
+ (e = bdb2i_id2entry_rw( be, id, rw )) != NULL )
+ {
+ return( e );
+ }
+
+ if ( id != NOID ) {
+ Debug(LDAP_DEBUG_ANY,
+ "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n",
+ rw ? "w" : "r", id, dn);
+ /* must have been deleted from underneath us */
+ /* treat as if NOID was found */
+ }
+
+ /* caller doesn't care about match */
+ if( matched == NULL ) return NULL;
+
+ /* entry does not exist - see how much of the dn does exist */
+ /* dn_parent checks returns NULL if dn is suffix */
+ if ( (pdn = dn_parent( be, dn )) != NULL ) {
+ /* get entry with reader lock */
+ if ( (e = bdb2i_dn2entry_r( be, pdn, matched )) != NULL ) {
+ *matched = e;
+ }
+ free( pdn );
+ }
+
+ return( NULL );
+}
+
+
--- /dev/null
+#ifndef _BDB2_EXTERNAL_H
+#define _BDB2_EXTERNAL_H
+
+LDAP_BEGIN_DECL
+
+extern int bdb2_back_initialize LDAP_P(( BackendInfo *bi ));
+extern int bdb2_back_open LDAP_P(( BackendInfo *bi ));
+extern int bdb2_back_close LDAP_P(( BackendInfo *bi ));
+extern int bdb2_back_destroy LDAP_P(( BackendInfo *bi ));
+
+extern int bdb2_back_config LDAP_P(( BackendInfo *bt,
+ char *fname, int lineno, int argc, char **argv ));
+
+extern int bdb2_back_db_init LDAP_P(( BackendDB *bd ));
+extern int bdb2_back_db_open LDAP_P(( BackendDB *bd ));
+extern int bdb2_back_db_close LDAP_P(( BackendDB *bd ));
+extern int bdb2_back_db_destroy LDAP_P(( BackendDB *bd ));
+
+extern int bdb2_back_db_config LDAP_P(( BackendDB *bd,
+ char *fname, int lineno, int argc, char **argv ));
+
+extern int bdb2_back_bind LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *dn, int method, char* mech,
+ struct berval *cred, char** edn ));
+
+extern int bdb2_back_unbind LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op ));
+
+extern int bdb2_back_search LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *base, int scope, int deref, int sizelimit, int timelimit,
+ Filter *filter, char *filterstr, char **attrs, int attrsonly ));
+
+extern int bdb2_back_compare LDAP_P((BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *dn, Ava *ava ));
+
+extern int bdb2_back_modify LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *dn, LDAPModList *ml ));
+
+extern int bdb2_back_modrdn LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *dn, char*newrdn, int deleteoldrdn,
+ char *newSuperior ));
+
+extern int bdb2_back_add LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op, Entry *e ));
+
+extern int bdb2_back_delete LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op, char *dn ));
+
+extern int bdb2_back_abandon LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op, int msgid ));
+
+extern int bdb2_back_group LDAP_P(( BackendDB *bd,
+ Entry *target, char* gr_ndn, char* op_ndn,
+ char* objectclassValue, char* groupattrName));
+
+/* hooks for slap tools */
+extern int bdb2_tool_entry_open LDAP_P(( BackendDB *be, int mode ));
+extern int bdb2_tool_entry_close LDAP_P(( BackendDB *be ));
+extern ID bdb2_tool_entry_first LDAP_P(( BackendDB *be ));
+extern ID bdb2_tool_entry_next LDAP_P(( BackendDB *be ));
+extern Entry* bdb2_tool_entry_get LDAP_P(( BackendDB *be, ID id ));
+extern ID bdb2_tool_entry_put LDAP_P(( BackendDB *be, Entry *e ));
+extern int bdb2_tool_index_attr LDAP_P(( BackendDB *be, char* type ));
+extern int bdb2_tool_index_change LDAP_P(( BackendDB *be, char* type,
+ struct berval **bv, ID id, int op ));
+extern int bdb2_tool_sync LDAP_P(( BackendDB *be ));
+
+LDAP_END_DECL
+
+#endif /* _BDB2_EXTERNAL_H */
+
--- /dev/null
+/* filterindex.c - generate the list of candidate entries from a filter */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+
+static ID_BLOCK *ava_candidates( BackendDB *be, Ava *ava, int type );
+static ID_BLOCK *presence_candidates( BackendDB *be, char *type );
+static ID_BLOCK *approx_candidates( BackendDB *be, Ava *ava );
+static ID_BLOCK *list_candidates( BackendDB *be, Filter *flist, int ftype );
+static ID_BLOCK *substring_candidates( BackendDB *be, Filter *f );
+static ID_BLOCK *substring_comp_candidates( BackendDB *be, char *type, char *val, int prepost );
+
+/*
+ * test_filter - test a filter against a single entry.
+ * returns 0 filter matched
+ * -1 filter did not match
+ * >0 an ldap error code
+ */
+
+ID_BLOCK *
+bdb2i_filter_candidates(
+ BackendDB *be,
+ Filter *f
+)
+{
+ ID_BLOCK *result, *tmp1, *tmp2;
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_filter_candidates\n", 0, 0, 0 );
+
+ result = NULL;
+ switch ( f->f_choice ) {
+ case SLAPD_FILTER_DN_ONE:
+ Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 );
+ result = bdb2i_dn2idl( be, f->f_dn, DN_SUBTREE_PREFIX );
+ break;
+
+ case SLAPD_FILTER_DN_SUBTREE:
+ Debug( LDAP_DEBUG_FILTER, "\tDN SUBTREE\n", 0, 0, 0 );
+ result = bdb2i_dn2idl( be, f->f_dn, DN_SUBTREE_PREFIX );
+ break;
+
+ case LDAP_FILTER_EQUALITY:
+ Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
+ result = ava_candidates( be, &f->f_ava, LDAP_FILTER_EQUALITY );
+ break;
+
+ case LDAP_FILTER_SUBSTRINGS:
+ Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
+ result = substring_candidates( be, f );
+ break;
+
+ case LDAP_FILTER_GE:
+ Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
+ result = ava_candidates( be, &f->f_ava, LDAP_FILTER_GE );
+ break;
+
+ case LDAP_FILTER_LE:
+ Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
+ result = ava_candidates( be, &f->f_ava, LDAP_FILTER_LE );
+ break;
+
+ case LDAP_FILTER_PRESENT:
+ Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
+ result = presence_candidates( be, f->f_type );
+ break;
+
+ case LDAP_FILTER_APPROX:
+ Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
+ result = approx_candidates( be, &f->f_ava );
+ break;
+
+ case LDAP_FILTER_AND:
+ Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
+ result = list_candidates( be, f->f_and, LDAP_FILTER_AND );
+ break;
+
+ case LDAP_FILTER_OR:
+ Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
+ result = list_candidates( be, f->f_or, LDAP_FILTER_OR );
+ break;
+
+ case LDAP_FILTER_NOT:
+ Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
+ tmp1 = bdb2i_idl_allids( be );
+ tmp2 = bdb2i_filter_candidates( be, f->f_not );
+ result = bdb2i_idl_notin( be, tmp1, tmp2 );
+ bdb2i_idl_free( tmp2 );
+ bdb2i_idl_free( tmp1 );
+ break;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_filter_candidates %ld\n",
+ result ? ID_BLOCK_NIDS(result) : 0, 0, 0 );
+ return( result );
+}
+
+static ID_BLOCK *
+ava_candidates(
+ BackendDB *be,
+ Ava *ava,
+ int type
+)
+{
+ ID_BLOCK *idl;
+
+ Debug( LDAP_DEBUG_TRACE, "=> ava_candidates 0x%x\n", type, 0, 0 );
+
+ switch ( type ) {
+ case LDAP_FILTER_EQUALITY:
+ idl = bdb2i_index_read( be, ava->ava_type, INDEX_EQUALITY,
+ ava->ava_value.bv_val );
+ break;
+
+ case LDAP_FILTER_GE:
+ idl = bdb2i_idl_allids( be );
+ break;
+
+ case LDAP_FILTER_LE:
+ idl = bdb2i_idl_allids( be );
+ break;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= ava_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
+ return( idl );
+}
+
+static ID_BLOCK *
+presence_candidates(
+ BackendDB *be,
+ char *type
+)
+{
+ ID_BLOCK *idl;
+
+ Debug( LDAP_DEBUG_TRACE, "=> presence_candidates\n", 0, 0, 0 );
+
+ idl = bdb2i_index_read( be, type, 0, "*" );
+
+ Debug( LDAP_DEBUG_TRACE, "<= presence_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
+ return( idl );
+}
+
+static ID_BLOCK *
+approx_candidates(
+ BackendDB *be,
+ Ava *ava
+)
+{
+ char *w, *c;
+ ID_BLOCK *idl, *tmp;
+
+ Debug( LDAP_DEBUG_TRACE, "=> approx_candidates\n", 0, 0, 0 );
+
+ idl = NULL;
+ for ( w = first_word( ava->ava_value.bv_val ); w != NULL;
+ w = next_word( w ) ) {
+ c = phonetic( w );
+ if ( (tmp = bdb2i_index_read( be, ava->ava_type, INDEX_APPROX, c ))
+ == NULL ) {
+ free( c );
+ bdb2i_idl_free( idl );
+ Debug( LDAP_DEBUG_TRACE, "<= approx_candidates NULL\n",
+ 0, 0, 0 );
+ return( NULL );
+ }
+ free( c );
+
+ if ( idl == NULL ) {
+ idl = tmp;
+ } else {
+ idl = bdb2i_idl_intersection( be, idl, tmp );
+ }
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= approx_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
+ return( idl );
+}
+
+static ID_BLOCK *
+list_candidates(
+ BackendDB *be,
+ Filter *flist,
+ int ftype
+)
+{
+ ID_BLOCK *idl, *tmp, *tmp2;
+ Filter *f;
+
+ Debug( LDAP_DEBUG_TRACE, "=> list_candidates 0x%x\n", ftype, 0, 0 );
+
+ idl = NULL;
+ for ( f = flist; f != NULL; f = f->f_next ) {
+ if ( (tmp = bdb2i_filter_candidates( be, f )) == NULL &&
+ ftype == LDAP_FILTER_AND ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= list_candidates NULL\n", 0, 0, 0 );
+ bdb2i_idl_free( idl );
+ return( NULL );
+ }
+
+ tmp2 = idl;
+ if ( idl == NULL ) {
+ idl = tmp;
+ } else if ( ftype == LDAP_FILTER_AND ) {
+ idl = bdb2i_idl_intersection( be, idl, tmp );
+ bdb2i_idl_free( tmp );
+ bdb2i_idl_free( tmp2 );
+ } else {
+ idl = bdb2i_idl_union( be, idl, tmp );
+ bdb2i_idl_free( tmp );
+ bdb2i_idl_free( tmp2 );
+ }
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= list_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
+ return( idl );
+}
+
+static ID_BLOCK *
+substring_candidates(
+ BackendDB *be,
+ Filter *f
+)
+{
+ int i;
+ ID_BLOCK *idl, *tmp, *tmp2;
+
+ Debug( LDAP_DEBUG_TRACE, "=> substring_candidates\n", 0, 0, 0 );
+
+ idl = NULL;
+
+ /* initial */
+ if ( f->f_sub_initial != NULL ) {
+ if ( (int) strlen( f->f_sub_initial ) < SUBLEN - 1 ) {
+ idl = bdb2i_idl_allids( be );
+ } else if ( (idl = substring_comp_candidates( be, f->f_sub_type,
+ f->f_sub_initial, '^' )) == NULL ) {
+ return( NULL );
+ }
+ }
+
+ /* final */
+ if ( f->f_sub_final != NULL ) {
+ if ( (int) strlen( f->f_sub_final ) < SUBLEN - 1 ) {
+ tmp = bdb2i_idl_allids( be );
+ } else if ( (tmp = substring_comp_candidates( be, f->f_sub_type,
+ f->f_sub_final, '$' )) == NULL ) {
+ bdb2i_idl_free( idl );
+ return( NULL );
+ }
+
+ if ( idl == NULL ) {
+ idl = tmp;
+ } else {
+ tmp2 = idl;
+ idl = bdb2i_idl_intersection( be, idl, tmp );
+ bdb2i_idl_free( tmp );
+ bdb2i_idl_free( tmp2 );
+ }
+ }
+
+ for ( i = 0; f->f_sub_any != NULL && f->f_sub_any[i] != NULL; i++ ) {
+ if ( (int) strlen( f->f_sub_any[i] ) < SUBLEN ) {
+ tmp = bdb2i_idl_allids( be );
+ } else if ( (tmp = substring_comp_candidates( be, f->f_sub_type,
+ f->f_sub_any[i], 0 )) == NULL ) {
+ bdb2i_idl_free( idl );
+ return( NULL );
+ }
+
+ if ( idl == NULL ) {
+ idl = tmp;
+ } else {
+ tmp2 = idl;
+ idl = bdb2i_idl_intersection( be, idl, tmp );
+ bdb2i_idl_free( tmp );
+ bdb2i_idl_free( tmp2 );
+ }
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= substring_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
+ return( idl );
+}
+
+static ID_BLOCK *
+substring_comp_candidates(
+ BackendDB *be,
+ char *type,
+ char *val,
+ int prepost
+)
+{
+ int i, len;
+ ID_BLOCK *idl, *tmp, *tmp2;
+ char *p;
+ char buf[SUBLEN + 1];
+
+ Debug( LDAP_DEBUG_TRACE, "=> substring_comp_candidates\n", 0, 0, 0 );
+
+ len = strlen( val );
+ idl = NULL;
+
+ /* prepend ^ for initial substring */
+ if ( prepost == '^' ) {
+ buf[0] = '^';
+ for ( i = 0; i < SUBLEN - 1; i++ ) {
+ buf[i + 1] = val[i];
+ }
+ buf[SUBLEN] = '\0';
+
+ if ( (idl = bdb2i_index_read( be, type, INDEX_SUB, buf )) == NULL ) {
+ return( NULL );
+ }
+ } else if ( prepost == '$' ) {
+ p = val + len - SUBLEN + 1;
+ for ( i = 0; i < SUBLEN - 1; i++ ) {
+ buf[i] = p[i];
+ }
+ buf[SUBLEN - 1] = '$';
+ buf[SUBLEN] = '\0';
+
+ if ( (idl = bdb2i_index_read( be, type, INDEX_SUB, buf )) == NULL ) {
+ return( NULL );
+ }
+ }
+
+ for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
+ for ( i = 0; i < SUBLEN; i++ ) {
+ buf[i] = p[i];
+ }
+ buf[SUBLEN] = '\0';
+
+ if ( (tmp = bdb2i_index_read( be, type, INDEX_SUB, buf )) == NULL ) {
+ bdb2i_idl_free( idl );
+ return( NULL );
+ }
+
+ if ( idl == NULL ) {
+ idl = tmp;
+ } else {
+ tmp2 = idl;
+ idl = bdb2i_idl_intersection( be, idl, tmp );
+ bdb2i_idl_free( tmp );
+ bdb2i_idl_free( tmp2 );
+ }
+
+ /* break if no candidates */
+ if( idl == NULL ) {
+ break;
+ }
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= substring_comp_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
+ return( idl );
+}
--- /dev/null
+/* id2children.c - routines to deal with the id2children index */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+
+int
+bdb2i_has_children(
+ BackendDB *be,
+ Entry *p
+)
+{
+ struct dbcache *db;
+ Datum key;
+ int rc = 0;
+ ID_BLOCK *idl;
+
+ ldbm_datum_init( key );
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_has_children( %ld )\n", p->e_id , 0, 0 );
+
+ if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX,
+ LDBM_WRCREAT )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "<= bdb2i_has_children: could not open \"dn2id" BDB2_SUFFIX "\"\n",
+ 0, 0, 0 );
+ return( 0 );
+ }
+
+ key.dsize = strlen( p->e_ndn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, p->e_ndn );
+
+ idl = bdb2i_idl_fetch( be, db, key );
+
+ free( key.dptr );
+
+ bdb2i_cache_close( be, db );
+
+ if( idl != NULL ) {
+ bdb2i_idl_free( idl );
+ rc = 1;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_has_children( %ld ): %s\n",
+ p->e_id, rc ? "yes" : "no", 0 );
+ return( rc );
+}
--- /dev/null
+/* id2entry.c - routines to deal with the id2entry index */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+
+/*
+ * This routine adds (or updates) an entry on disk.
+ * The cache should already be updated.
+ */
+
+int
+bdb2i_id2entry_add( BackendDB *be, Entry *e )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct dbcache *db;
+ Datum key, data;
+ int len, rc, flags;
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_id2entry_add( %ld, \"%s\" )\n", e->e_id,
+ e->e_dn, 0 );
+
+ if ( (db = bdb2i_cache_open( be, "id2entry", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
+ BDB2_SUFFIX, 0, 0 );
+ return( -1 );
+ }
+
+ key.dptr = (char *) &e->e_id;
+ key.dsize = sizeof(ID);
+
+ ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+ data.dptr = entry2str( e, &len );
+ data.dsize = len + 1;
+
+ /* store it */
+ flags = LDBM_REPLACE;
+ if ( li->li_dbcachewsync ) flags |= LDBM_SYNC;
+ rc = bdb2i_cache_store( db, key, data, flags );
+
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
+
+ bdb2i_cache_close( be, db );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_add %d\n", rc, 0, 0 );
+
+ return( rc );
+}
+
+int
+bdb2i_id2entry_delete( BackendDB *be, Entry *e )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct dbcache *db;
+ Datum key;
+ int rc;
+
+ Debug(LDAP_DEBUG_TRACE, "=> bdb2i_id2entry_delete( %ld, \"%s\" )\n", e->e_id,
+ e->e_dn, 0 );
+
+#ifdef notdef
+#ifdef LDAP_DEBUG
+ /* check for writer lock */
+ assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1);
+#endif
+#endif
+
+ ldbm_datum_init( key );
+
+ if ( (db = bdb2i_cache_open( be, "id2entry", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
+ BDB2_SUFFIX, 0, 0 );
+ return( -1 );
+ }
+
+ if ( bdb2i_cache_delete_entry( &li->li_cache, e ) != 0 ) {
+ Debug(LDAP_DEBUG_ANY, "could not delete %ld (%s) from cache\n",
+ e->e_id, e->e_dn, 0 );
+ }
+
+ key.dptr = (char *) &e->e_id;
+ key.dsize = sizeof(ID);
+
+ rc = bdb2i_cache_delete( db, key );
+
+ bdb2i_cache_close( be, db );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_delete %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+/* returns entry with reader/writer lock */
+Entry *
+bdb2i_id2entry_rw( BackendDB *be, ID id, int rw )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct dbcache *db;
+ Datum key, data;
+ Entry *e;
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_id2entry_%s( %ld )\n",
+ rw ? "w" : "r", id, 0 );
+
+ if ( (e = bdb2i_cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) 0x%lx (cache)\n",
+ rw ? "w" : "r", id, (unsigned long)e );
+ return( e );
+ }
+
+ if ( (db = bdb2i_cache_open( be, "id2entry", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "Could not open id2entry%s\n",
+ BDB2_SUFFIX, 0, 0 );
+ return( NULL );
+ }
+
+ key.dptr = (char *) &id;
+ key.dsize = sizeof(ID);
+
+ data = bdb2i_cache_fetch( db, key );
+
+ if ( data.dptr == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) not found\n",
+ rw ? "w" : "r", id, 0 );
+ bdb2i_cache_close( be, db );
+ return( NULL );
+ }
+
+ e = str2entry( data.dptr );
+
+ ldbm_datum_free( db->dbc_db, data );
+ bdb2i_cache_close( be, db );
+
+ if ( e == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) (failed)\n",
+ rw ? "w" : "r", id, 0 );
+ return( NULL );
+ }
+
+ e->e_id = id;
+
+ if ( bdb2i_cache_add_entry_rw( &li->li_cache, e, rw ) != 0 ) {
+ entry_free( e );
+
+ /* see if it got added underneath us */
+ if((e = bdb2i_cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= bdb2i_id2entry_%s( %ld ) 0x%lx (cache)\n",
+ rw ? "w" : "r", id, (unsigned long)e );
+ return( e );
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "<= bdb2i_id2entry_%s( %ld ) (cache add failed)\n",
+ rw ? "w" : "r", id, 0 );
+ return( NULL );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) 0x%lx (disk)\n",
+ rw ? "w" : "r", id, (unsigned long) e );
+
+ return( e );
+}
+
+
--- /dev/null
+/* idl.c - ldap id list handling routines */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "ldap_defaults.h"
+#include "slap.h"
+#include "back-bdb2.h"
+
+static ID_BLOCK* idl_dup( ID_BLOCK *idl );
+
+/* Allocate an ID_BLOCK with room for nids ids */
+ID_BLOCK *
+bdb2i_idl_alloc( unsigned int nids )
+{
+ ID_BLOCK *new;
+
+ /* nmax + nids + space for the ids */
+ new = (ID_BLOCK *) ch_calloc( (ID_BLOCK_IDS_OFFSET + nids), sizeof(ID) );
+ ID_BLOCK_NMAX(new) = nids;
+ ID_BLOCK_NIDS(new) = 0;
+
+ return( new );
+}
+
+
+/* Allocate an empty ALLIDS ID_BLOCK */
+ID_BLOCK *
+bdb2i_idl_allids( BackendDB *be )
+{
+ ID_BLOCK *idl;
+
+ idl = bdb2i_idl_alloc( 0 );
+ ID_BLOCK_NMAX(idl) = ID_BLOCK_ALLIDS_VALUE;
+ ID_BLOCK_NIDS(idl) = bdb2i_next_id_get( be );
+
+ return( idl );
+}
+
+
+/* Free an ID_BLOCK */
+void
+bdb2i_idl_free( ID_BLOCK *idl )
+{
+ if ( idl == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb2i_idl_free: called with NULL pointer\n",
+ 0, 0, 0 );
+ return;
+ }
+
+ free( (char *) idl );
+}
+
+
+/* Fetch an single ID_BLOCK from the cache */
+static ID_BLOCK *
+idl_fetch_one(
+ BackendDB *be,
+ struct dbcache *db,
+ Datum key
+)
+{
+ Datum data;
+ ID_BLOCK *idl;
+
+ ldbm_datum_init( data );
+
+ /* Debug( LDAP_DEBUG_TRACE, "=> idl_fetch_one\n", 0, 0, 0 ); */
+
+ data = bdb2i_cache_fetch( db, key );
+
+ if( data.dptr == NULL ) {
+ return NULL;
+ }
+
+ idl = idl_dup( (ID_BLOCK *) data.dptr);
+ ldbm_datum_free( db->dbc_db, data );
+
+ return( idl );
+}
+
+
+/* Fetch a set of ID_BLOCKs from the cache
+ * if not INDIRECT
+ * if block return is an ALLIDS block,
+ * return an new ALLIDS block
+ * otherwise
+ * return block
+ * construct super block from all blocks referenced by INDIRECT block
+ * return super block
+ */
+ID_BLOCK *
+bdb2i_idl_fetch(
+ BackendDB *be,
+ struct dbcache *db,
+ Datum key
+)
+{
+ Datum data;
+ ID_BLOCK *idl;
+ ID_BLOCK **tmp;
+ char *kstr;
+ int i, nids;
+
+ idl = idl_fetch_one( be, db, key );
+
+ if ( idl == NULL ) {
+ return NULL;
+ }
+
+ if ( ID_BLOCK_ALLIDS(idl) ) {
+ /* all ids block */
+ /* make sure we have the current value of highest id */
+ bdb2i_idl_free( idl );
+ idl = bdb2i_idl_allids( be );
+
+ return( idl );
+ }
+
+ if ( ! ID_BLOCK_INDIRECT( idl ) ) {
+ /* regular block */
+ return( idl );
+ }
+
+ /*
+ * this is an indirect block which points to other blocks.
+ * we need to read in all the blocks it points to and construct
+ * a big id list containing all the ids, which we will return.
+ */
+
+ /* count the number of blocks & allocate space for pointers to them */
+ for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ )
+ ; /* NULL */
+ tmp = (ID_BLOCK **) ch_malloc( (i + 1) * sizeof(ID_BLOCK *) );
+
+ /* read in all the blocks */
+ kstr = (char *) ch_malloc( key.dsize + CONT_SIZE );
+ nids = 0;
+ for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) {
+ ldbm_datum_init( data );
+
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(idl, i), key.dptr );
+ data.dptr = kstr;
+ data.dsize = strlen( kstr ) + 1;
+
+ if ( (tmp[i] = idl_fetch_one( be, db, data )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_idl_fetch of (%s) returns NULL\n", data.dptr, 0, 0 );
+ continue;
+ }
+
+ nids += ID_BLOCK_NIDS(tmp[i]);
+ }
+ tmp[i] = NULL;
+ free( kstr );
+ bdb2i_idl_free( idl );
+
+ /* allocate space for the big block */
+ idl = bdb2i_idl_alloc( nids );
+ ID_BLOCK_NIDS(idl) = nids;
+ nids = 0;
+
+ /* copy in all the ids from the component blocks */
+ for ( i = 0; tmp[i] != NULL; i++ ) {
+ if ( tmp[i] == NULL ) {
+ continue;
+ }
+
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(idl, nids),
+ (char *) &ID_BLOCK_ID(tmp[i], 0),
+ ID_BLOCK_NIDS(tmp[i]) * sizeof(ID) );
+ nids += ID_BLOCK_NIDS(tmp[i]);
+
+ bdb2i_idl_free( tmp[i] );
+ }
+ free( (char *) tmp );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_idl_fetch %ld ids (%ld max)\n",
+ ID_BLOCK_NIDS(idl), ID_BLOCK_NMAX(idl), 0 );
+ return( idl );
+}
+
+
+/* store a single block */
+static int
+idl_store(
+ BackendDB *be,
+ struct dbcache *db,
+ Datum key,
+ ID_BLOCK *idl
+)
+{
+ int rc, flags;
+ Datum data;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ ldbm_datum_init( data );
+
+ /* Debug( LDAP_DEBUG_TRACE, "=> idl_store\n", 0, 0, 0 ); */
+
+ data.dptr = (char *) idl;
+ data.dsize = (ID_BLOCK_IDS_OFFSET + ID_BLOCK_NMAX(idl)) * sizeof(ID);
+
+#ifdef LDBM_DEBUG
+ Statslog( LDAP_DEBUG_STATS, "<= idl_store(): rc=%d\n",
+ rc, 0, 0, 0, 0 );
+#endif
+
+ flags = LDBM_REPLACE;
+ if( li->li_dbcachewsync ) flags |= LDBM_SYNC;
+ rc = bdb2i_cache_store( db, key, data, flags );
+
+ /* Debug( LDAP_DEBUG_TRACE, "<= idl_store %d\n", rc, 0, 0 ); */
+ return( rc );
+}
+
+
+/* split the block at id
+ * locate ID greater than or equal to id.
+ */
+static void
+idl_split_block(
+ ID_BLOCK *b,
+ ID id,
+ ID_BLOCK **right,
+ ID_BLOCK **left
+)
+{
+ unsigned int nr, nl;
+
+ /* find where to split the block *//* XXX linear search XXX */
+ for ( nr = 0; nr < ID_BLOCK_NIDS(b) && id > ID_BLOCK_ID(b, nr); nr++ )
+ ; /* NULL */
+
+ nl = ID_BLOCK_NIDS(b) - nr;
+
+ *right = bdb2i_idl_alloc( nr == 0 ? 1 : nr );
+ *left = bdb2i_idl_alloc( nl + (nr == 0 ? 0 : 1));
+
+ /*
+ * everything before the id being inserted in the first block
+ * unless there is nothing, in which case the id being inserted
+ * goes there.
+ */
+ if ( nr == 0 ) {
+ ID_BLOCK_NIDS(*right) = 1;
+ ID_BLOCK_ID(*right, 0) = id;
+ } else {
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(*right, 0),
+ (char *) &ID_BLOCK_ID(b, 0),
+ nr * sizeof(ID) );
+ ID_BLOCK_NIDS(*right) = nr;
+ ID_BLOCK_ID(*left, 0) = id;
+ }
+
+ /* the id being inserted & everything after in the second block */
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(*left, (nr == 0 ? 0 : 1)),
+ (char *) &ID_BLOCK_ID(b, nr),
+ nl * sizeof(ID) );
+ ID_BLOCK_NIDS(*left) = nl + (nr == 0 ? 0 : 1);
+}
+
+
+/*
+ * idl_change_first - called when an indirect block's first key has
+ * changed, meaning it needs to be stored under a new key, and the
+ * header block pointing to it needs updating.
+ */
+static int
+idl_change_first(
+ BackendDB *be,
+ struct dbcache *db,
+ Datum hkey, /* header block key */
+ ID_BLOCK *h, /* header block */
+ int pos, /* pos in h to update */
+ Datum bkey, /* data block key */
+ ID_BLOCK *b /* data block */
+)
+{
+ int rc;
+
+ /* Debug( LDAP_DEBUG_TRACE, "=> idl_change_first\n", 0, 0, 0 ); */
+
+ /* delete old key block */
+ if ( (rc = bdb2i_cache_delete( db, bkey )) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_db_delete of (%s) returns %d\n", bkey.dptr, rc,
+ 0 );
+ return( rc );
+ }
+
+ /* write block with new key */
+ sprintf( bkey.dptr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(b, 0), hkey.dptr );
+ bkey.dsize = strlen( bkey.dptr ) + 1;
+ if ( (rc = idl_store( be, db, bkey, b )) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "idl_store of (%s) returns %d\n", bkey.dptr, rc, 0 );
+ return( rc );
+ }
+
+ /* update + write indirect header block */
+ ID_BLOCK_ID(h, pos) = ID_BLOCK_ID(b, 0);
+ if ( (rc = idl_store( be, db, hkey, h )) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "idl_store of (%s) returns %d\n", hkey.dptr, rc, 0 );
+ return( rc );
+ }
+
+ return( 0 );
+}
+
+
+int
+bdb2i_idl_insert_key(
+ BackendDB *be,
+ struct dbcache *db,
+ Datum key,
+ ID id
+)
+{
+ int i, j, first, rc;
+ ID_BLOCK *idl, *tmp, *tmp2, *tmp3;
+ char *kstr;
+ Datum k2;
+
+ ldbm_datum_init( k2 );
+
+ if ( (idl = idl_fetch_one( be, db, key )) == NULL ) {
+#ifdef LDBM_DEBUG
+ Statslog( LDAP_DEBUG_STATS, "=> bdb2i_idl_insert_key(): no key yet\n",
+ 0, 0, 0, 0, 0 );
+#endif
+
+ idl = bdb2i_idl_alloc( 1 );
+ ID_BLOCK_ID(idl, ID_BLOCK_NIDS(idl)++) = id;
+ rc = idl_store( be, db, key, idl );
+
+ bdb2i_idl_free( idl );
+ return( rc );
+ }
+
+ if ( ID_BLOCK_ALLIDS( idl ) ) {
+ /* ALLIDS */
+ bdb2i_idl_free( idl );
+ return 0;
+ }
+
+ if ( ! ID_BLOCK_INDIRECT( idl ) ) {
+ /* regular block */
+ switch ( bdb2i_idl_insert( &idl, id, db->dbc_maxids ) ) {
+ case 0: /* id inserted - store the updated block */
+ case 1:
+ rc = idl_store( be, db, key, idl );
+ break;
+
+ case 2: /* id already there - nothing to do */
+ rc = 0;
+ break;
+
+ case 3: /* id not inserted - block must be split */
+ /* check threshold for marking this an all-id block */
+ if ( db->dbc_maxindirect < 2 ) {
+ bdb2i_idl_free( idl );
+ idl = bdb2i_idl_allids( be );
+ rc = idl_store( be, db, key, idl );
+ break;
+ }
+
+ idl_split_block( idl, id, &tmp, &tmp2 );
+ bdb2i_idl_free( idl );
+
+ /* create the header indirect block */
+ idl = bdb2i_idl_alloc( 3 );
+ ID_BLOCK_NMAX(idl) = 3;
+ ID_BLOCK_NIDS(idl) = ID_BLOCK_INDIRECT_VALUE;
+ ID_BLOCK_ID(idl, 0) = ID_BLOCK_ID(tmp, 0);
+ ID_BLOCK_ID(idl, 1) = ID_BLOCK_ID(tmp2, 0);
+ ID_BLOCK_ID(idl, 2) = NOID;
+
+ /* store it */
+ rc = idl_store( be, db, key, idl );
+
+ /* store the first id block */
+ kstr = (char *) ch_malloc( key.dsize + CONT_SIZE );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(tmp, 0), key.dptr );
+ k2.dptr = kstr;
+ k2.dsize = strlen( kstr ) + 1;
+ rc = idl_store( be, db, k2, tmp );
+
+ /* store the second id block */
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(tmp2, 0), key.dptr );
+ k2.dptr = kstr;
+ k2.dsize = strlen( kstr ) + 1;
+ rc = idl_store( be, db, k2, tmp2 );
+
+ free( kstr );
+ bdb2i_idl_free( tmp );
+ bdb2i_idl_free( tmp2 );
+ break;
+ }
+
+ bdb2i_idl_free( idl );
+ return( rc );
+ }
+
+ /*
+ * this is an indirect block which points to other blocks.
+ * we need to read in the block into which the id should be
+ * inserted, then insert the id and store the block. we might
+ * have to split the block if it is full, which means we also
+ * need to write a new "header" block.
+ */
+
+ /* select the block to try inserting into *//* XXX linear search XXX */
+ for ( i = 0; !ID_BLOCK_NOID(idl, i) && id > ID_BLOCK_ID(idl, i); i++ )
+ ; /* NULL */
+ if ( i != 0 ) {
+ i--;
+ first = 0;
+ } else {
+ first = 1;
+ }
+
+ /* get the block */
+ kstr = (char *) ch_malloc( key.dsize + CONT_SIZE );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(idl, i), key.dptr );
+ k2.dptr = kstr;
+ k2.dsize = strlen( kstr ) + 1;
+ if ( (tmp = idl_fetch_one( be, db, k2 )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "nonexistent continuation block (%s)\n",
+ k2.dptr, 0, 0 );
+ free( kstr );
+ bdb2i_idl_free( idl );
+ return( -1 );
+ }
+
+ /* insert the id */
+ switch ( bdb2i_idl_insert( &tmp, id, db->dbc_maxids ) ) {
+ case 0: /* id inserted ok */
+ if ( (rc = idl_store( be, db, k2, tmp )) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "idl_store of (%s) returns %d\n", k2.dptr, rc, 0 );
+ }
+ break;
+
+ case 1: /* id inserted - first id in block has changed */
+ /*
+ * key for this block has changed, so we have to
+ * write the block under the new key, delete the
+ * old key block + update and write the indirect
+ * header block.
+ */
+
+ rc = idl_change_first( be, db, key, idl, i, k2, tmp );
+ break;
+
+ case 2: /* id not inserted - already there */
+ break;
+
+ case 3: /* id not inserted - block is full */
+ /*
+ * first, see if it will fit in the next block,
+ * without splitting, unless we're trying to insert
+ * into the beginning of the first block.
+ */
+
+ /* is there a next block? */
+ if ( !first && !ID_BLOCK_NOID(idl, i + 1) ) {
+ /* read it in */
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(idl, i + 1), key.dptr );
+ k2.dptr = kstr;
+ k2.dsize = strlen( kstr ) + 1;
+ if ( (tmp2 = idl_fetch_one( be, db, k2 )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "idl_fetch_one (%s) returns NULL\n",
+ k2.dptr, 0, 0 );
+ break;
+ }
+
+ switch ( (rc = bdb2i_idl_insert( &tmp2, id,
+ db->dbc_maxids )) ) {
+ case 1: /* id inserted first in block */
+ rc = idl_change_first( be, db, key, idl,
+ i + 1, k2, tmp2 );
+ /* FALL */
+
+ case 2: /* id already there - how? */
+ case 0: /* id inserted */
+ if ( rc == 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "id %ld already in next block\n",
+ id, 0, 0 );
+ }
+ free( kstr );
+ bdb2i_idl_free( tmp );
+ bdb2i_idl_free( tmp2 );
+ bdb2i_idl_free( idl );
+ return( 0 );
+
+ case 3: /* split the original block */
+ break;
+ }
+ bdb2i_idl_free( tmp2 );
+ }
+
+ /*
+ * must split the block, write both new blocks + update
+ * and write the indirect header block.
+ */
+
+ /* count how many indirect blocks *//* XXX linear count XXX */
+ for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ )
+ ; /* NULL */
+
+ /* check it against all-id thresholed */
+ if ( j + 1 > db->dbc_maxindirect ) {
+ /*
+ * we've passed the all-id threshold, meaning
+ * that this set of blocks should be replaced
+ * by a single "all-id" block. our job: delete
+ * all the indirect blocks, and replace the header
+ * block by an all-id block.
+ */
+
+ /* delete all indirect blocks */
+ for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ ) {
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(idl, j), key.dptr );
+ k2.dptr = kstr;
+ k2.dsize = strlen( kstr ) + 1;
+
+ rc = bdb2i_cache_delete( db, k2 );
+ }
+
+ /* store allid block in place of header block */
+ bdb2i_idl_free( idl );
+ idl = bdb2i_idl_allids( be );
+ rc = idl_store( be, db, key, idl );
+
+ free( kstr );
+ bdb2i_idl_free( idl );
+ bdb2i_idl_free( tmp );
+ return( rc );
+ }
+
+ idl_split_block( tmp, id, &tmp2, &tmp3 );
+ bdb2i_idl_free( tmp );
+
+ /* create a new updated indirect header block */
+ tmp = bdb2i_idl_alloc( ID_BLOCK_NMAX(idl) + 1 );
+ ID_BLOCK_NIDS(tmp) = ID_BLOCK_INDIRECT_VALUE;
+ /* everything up to the split block */
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(tmp, 0),
+ (char *) &ID_BLOCK_ID(idl, 0),
+ i * sizeof(ID) );
+ /* the two new blocks */
+ ID_BLOCK_ID(tmp, i) = ID_BLOCK_ID(tmp2, 0);
+ ID_BLOCK_ID(tmp, i + 1) = ID_BLOCK_ID(tmp3, 0);
+ /* everything after the split block */
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(tmp, i + 2),
+ (char *) &ID_BLOCK_ID(idl, i + 1),
+ (ID_BLOCK_NMAX(idl) - i - 1) * sizeof(ID) );
+
+ /* store the header block */
+ rc = idl_store( be, db, key, tmp );
+
+ /* store the first id block */
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(tmp2, 0), key.dptr );
+ k2.dptr = kstr;
+ k2.dsize = strlen( kstr ) + 1;
+ rc = idl_store( be, db, k2, tmp2 );
+
+ /* store the second id block */
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(tmp3, 0), key.dptr );
+ k2.dptr = kstr;
+ k2.dsize = strlen( kstr ) + 1;
+ rc = idl_store( be, db, k2, tmp3 );
+
+ bdb2i_idl_free( tmp2 );
+ bdb2i_idl_free( tmp3 );
+ break;
+ }
+
+ free( kstr );
+ bdb2i_idl_free( tmp );
+ bdb2i_idl_free( idl );
+ return( rc );
+}
+
+
+/*
+ * bdb2i_idl_insert - insert an id into an id list.
+ *
+ * returns
+ * 0 id inserted
+ * 1 id inserted, first id in block has changed
+ * 2 id not inserted, already there
+ * 3 id not inserted, block must be split
+ */
+int
+bdb2i_idl_insert( ID_BLOCK **idl, ID id, unsigned int maxids )
+{
+ unsigned int i, j;
+
+ if ( ID_BLOCK_ALLIDS( *idl ) ) {
+ return( 2 ); /* already there */
+ }
+
+ /* is it already there? *//* XXX linear search XXX */
+ for ( i = 0; i < ID_BLOCK_NIDS(*idl) && id > ID_BLOCK_ID(*idl, i); i++ ) {
+ ; /* NULL */
+ }
+ if ( i < ID_BLOCK_NIDS(*idl) && ID_BLOCK_ID(*idl, i) == id ) {
+ return( 2 ); /* already there */
+ }
+
+ /* do we need to make room for it? */
+ if ( ID_BLOCK_NIDS(*idl) == ID_BLOCK_NMAX(*idl) ) {
+ /* make room or indicate block needs splitting */
+ if ( ID_BLOCK_NMAX(*idl) >= maxids ) {
+ return( 3 ); /* block needs splitting */
+ }
+
+ ID_BLOCK_NMAX(*idl) *= 2;
+ if ( ID_BLOCK_NMAX(*idl) > maxids ) {
+ ID_BLOCK_NMAX(*idl) = maxids;
+ }
+ *idl = (ID_BLOCK *) ch_realloc( (char *) *idl,
+ (ID_BLOCK_NMAX(*idl) + ID_BLOCK_IDS_OFFSET) * sizeof(ID) );
+ }
+
+ /* make a slot for the new id */
+ SAFEMEMCPY( &ID_BLOCK_ID(*idl, i), &ID_BLOCK_ID(*idl, i+1),
+ ID_BLOCK_NIDS(*idl) - i );
+
+ ID_BLOCK_ID(*idl, i) = id;
+ ID_BLOCK_NIDS(*idl)++;
+ (void) memset(
+ (char *) &ID_BLOCK_ID((*idl), ID_BLOCK_NIDS(*idl)),
+ '\0',
+ (ID_BLOCK_NMAX(*idl) - ID_BLOCK_NIDS(*idl)) * sizeof(ID) );
+
+ return( i == 0 ? 1 : 0 ); /* inserted - first id changed or not */
+}
+
+
+int
+bdb2i_idl_delete_key (
+ BackendDB *be,
+ struct dbcache *db,
+ Datum key,
+ ID id
+)
+{
+ Datum data;
+ ID_BLOCK *idl, *tmp;
+ unsigned i;
+ int j, nids;
+ char *kstr;
+
+ if ( (idl = idl_fetch_one( be, db, key ) ) == NULL )
+ {
+ /* It wasn't found. Hmm... */
+ return -1;
+ }
+
+ if ( ID_BLOCK_ALLIDS( idl ) ) {
+ bdb2i_idl_free( idl );
+ return 0;
+ }
+
+ if ( ! ID_BLOCK_INDIRECT( idl ) ) {
+ for ( i=0; i < ID_BLOCK_NIDS(idl); i++ ) {
+ if ( ID_BLOCK_ID(idl, i) == id ) {
+ if( --ID_BLOCK_NIDS(idl) == 0 ) {
+ bdb2i_cache_delete( db, key );
+
+ } else {
+ SAFEMEMCPY (
+ &ID_BLOCK_ID(idl, i),
+ &ID_BLOCK_ID(idl, i+1),
+ (ID_BLOCK_NIDS(idl)-i) * sizeof(ID) );
+
+ ID_BLOCK_ID(idl, ID_BLOCK_NIDS(idl)) = NOID;
+
+ idl_store( be, db, key, idl );
+ }
+
+ bdb2i_idl_free( idl );
+ return 0;
+ }
+ /* We didn't find the ID. Hmmm... */
+ }
+ bdb2i_idl_free( idl );
+ return -1;
+ }
+
+ /* We have to go through an indirect block and find the ID
+ in the list of IDL's
+ */
+ for ( nids = 0; !ID_BLOCK_NOID(idl, nids); nids++ )
+ ; /* NULL */
+ kstr = (char *) ch_malloc( key.dsize + CONT_SIZE );
+ for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ )
+ {
+ ldbm_datum_init( data );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX, ID_BLOCK_ID(idl, j), key.dptr );
+ data.dptr = kstr;
+ data.dsize = strlen( kstr ) + 1;
+
+ if ( (tmp = idl_fetch_one( be, db, data )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_idl_fetch of (%s) returns NULL\n", data.dptr, 0, 0 );
+ continue;
+ }
+ /*
+ Now try to find the ID in tmp
+ */
+ for ( i=0; i < ID_BLOCK_NIDS(tmp); i++ )
+ {
+ if ( ID_BLOCK_ID(tmp, i) == id )
+ {
+ SAFEMEMCPY(
+ &ID_BLOCK_ID(tmp, i),
+ &ID_BLOCK_ID(tmp, i+1),
+ (ID_BLOCK_NIDS(tmp)-(i+1)) * sizeof(ID));
+ ID_BLOCK_ID(tmp, ID_BLOCK_NIDS(tmp)-1 ) = NOID;
+ ID_BLOCK_NIDS(tmp)--;
+
+ if ( ID_BLOCK_NIDS(tmp) ) {
+ idl_store ( be, db, data, tmp );
+
+ } else {
+ bdb2i_cache_delete( db, data );
+ SAFEMEMCPY(
+ &ID_BLOCK_ID(idl, j),
+ &ID_BLOCK_ID(idl, j+1),
+ (nids-(j+1)) * sizeof(ID));
+ ID_BLOCK_ID(idl, nids-1) = NOID;
+ nids--;
+ if ( ! nids )
+ bdb2i_cache_delete( db, key );
+ else
+ idl_store( be, db, key, idl );
+ }
+ bdb2i_idl_free( tmp );
+ free( kstr );
+ bdb2i_idl_free( idl );
+ return 0;
+ }
+ }
+ bdb2i_idl_free( tmp );
+ }
+ free( kstr );
+ bdb2i_idl_free( idl );
+ return -1;
+}
+
+
+/* return a duplicate of a single ID_BLOCK */
+static ID_BLOCK *
+idl_dup( ID_BLOCK *idl )
+{
+ ID_BLOCK *new;
+
+ if ( idl == NULL ) {
+ return( NULL );
+ }
+
+ new = bdb2i_idl_alloc( ID_BLOCK_NMAX(idl) );
+ SAFEMEMCPY(
+ (char *) new,
+ (char *) idl,
+ (ID_BLOCK_NMAX(idl) + ID_BLOCK_IDS_OFFSET) * sizeof(ID) );
+
+ return( new );
+}
+
+
+/* return the smaller ID_BLOCK */
+static ID_BLOCK *
+idl_min( ID_BLOCK *a, ID_BLOCK *b )
+{
+ return( ID_BLOCK_NIDS(a) > ID_BLOCK_NIDS(b) ? b : a );
+}
+
+
+/*
+ * bdb2i_idl_intersection - return a intersection b
+ */
+ID_BLOCK *
+bdb2i_idl_intersection(
+ BackendDB *be,
+ ID_BLOCK *a,
+ ID_BLOCK *b
+)
+{
+ unsigned int ai, bi, ni;
+ ID_BLOCK *n;
+
+ if ( a == NULL || b == NULL ) {
+ return( NULL );
+ }
+ if ( ID_BLOCK_ALLIDS( a ) ) {
+ return( idl_dup( b ) );
+ }
+ if ( ID_BLOCK_ALLIDS( b ) ) {
+ return( idl_dup( a ) );
+ }
+
+ n = idl_dup( idl_min( a, b ) );
+
+ for ( ni = 0, ai = 0, bi = 0; ai < ID_BLOCK_NIDS(a); ai++ ) {
+ for ( ;
+ bi < ID_BLOCK_NIDS(b) && ID_BLOCK_ID(b, bi) < ID_BLOCK_ID(a, ai);
+ bi++ )
+ {
+ ; /* NULL */
+ }
+
+ if ( bi == ID_BLOCK_NIDS(b) ) {
+ break;
+ }
+
+ if ( ID_BLOCK_ID(b, bi) == ID_BLOCK_ID(a, ai) ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
+ }
+ }
+
+ if ( ni == 0 ) {
+ bdb2i_idl_free( n );
+ return( NULL );
+ }
+ ID_BLOCK_NIDS(n) = ni;
+
+ return( n );
+}
+
+
+/*
+ * bdb2i_idl_union - return a union b
+ */
+ID_BLOCK *
+bdb2i_idl_union(
+ BackendDB *be,
+ ID_BLOCK *a,
+ ID_BLOCK *b
+)
+{
+ unsigned int ai, bi, ni;
+ ID_BLOCK *n;
+
+ if ( a == NULL ) {
+ return( idl_dup( b ) );
+ }
+ if ( b == NULL ) {
+ return( idl_dup( a ) );
+ }
+ if ( ID_BLOCK_ALLIDS( a ) || ID_BLOCK_ALLIDS( b ) ) {
+ return( bdb2i_idl_allids( be ) );
+ }
+
+ if ( ID_BLOCK_NIDS(b) < ID_BLOCK_NIDS(a) ) {
+ n = a;
+ a = b;
+ b = n;
+ }
+
+ n = bdb2i_idl_alloc( ID_BLOCK_NIDS(a) + ID_BLOCK_NIDS(b) );
+
+ for ( ni = 0, ai = 0, bi = 0;
+ ai < ID_BLOCK_NIDS(a) && bi < ID_BLOCK_NIDS(b);
+ )
+ {
+ if ( ID_BLOCK_ID(a, ai) < ID_BLOCK_ID(b, bi) ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai++);
+
+ } else if ( ID_BLOCK_ID(b, bi) < ID_BLOCK_ID(a, ai) ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(b, bi++);
+
+ } else {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
+ ai++, bi++;
+ }
+ }
+
+ for ( ; ai < ID_BLOCK_NIDS(a); ai++ ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
+ }
+ for ( ; bi < ID_BLOCK_NIDS(b); bi++ ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(b, bi);
+ }
+ ID_BLOCK_NIDS(n) = ni;
+
+ return( n );
+}
+
+
+/*
+ * bdb2i_idl_notin - return a intersection ~b (or a minus b)
+ */
+ID_BLOCK *
+bdb2i_idl_notin(
+ BackendDB *be,
+ ID_BLOCK *a,
+ ID_BLOCK *b
+)
+{
+ unsigned int ni, ai, bi;
+ ID_BLOCK *n;
+
+ if ( a == NULL ) {
+ return( NULL );
+ }
+ if ( b == NULL || ID_BLOCK_ALLIDS( b )) {
+ return( idl_dup( a ) );
+ }
+
+ if ( ID_BLOCK_ALLIDS( a ) ) {
+ n = bdb2i_idl_alloc( SLAPD_LDBM_MIN_MAXIDS );
+ ni = 0;
+
+ for ( ai = 1, bi = 0;
+ ai < ID_BLOCK_NIDS(a) && ni < ID_BLOCK_NMAX(n) && bi < ID_BLOCK_NMAX(b);
+ ai++ )
+ {
+ if ( ID_BLOCK_ID(b, bi) == ai ) {
+ bi++;
+ } else {
+ ID_BLOCK_ID(n, ni++) = ai;
+ }
+ }
+
+ for ( ; ai < ID_BLOCK_NIDS(a) && ni < ID_BLOCK_NMAX(n); ai++ ) {
+ ID_BLOCK_ID(n, ni++) = ai;
+ }
+
+ if ( ni == ID_BLOCK_NMAX(n) ) {
+ bdb2i_idl_free( n );
+ return( bdb2i_idl_allids( be ) );
+ } else {
+ ID_BLOCK_NIDS(n) = ni;
+ return( n );
+ }
+ }
+
+ n = idl_dup( a );
+
+ ni = 0;
+ for ( ai = 0, bi = 0; ai < ID_BLOCK_NIDS(a); ai++ ) {
+ for ( ;
+ bi < ID_BLOCK_NIDS(b) && ID_BLOCK_ID(b, bi) < ID_BLOCK_ID(a, ai);
+ bi++ )
+ {
+ ; /* NULL */
+ }
+
+ if ( bi == ID_BLOCK_NIDS(b) ) {
+ break;
+ }
+
+ if ( ID_BLOCK_ID(b, bi) != ID_BLOCK_ID(a, ai) ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
+ }
+ }
+
+ for ( ; ai < ID_BLOCK_NIDS(a); ai++ ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
+ }
+ ID_BLOCK_NIDS(n) = ni;
+
+ return( n );
+}
+
+
+/* return the first ID in the block
+ * if ALLIDS block
+ * NIDS > 1 return 1
+ * otherwise return NOID
+ * otherwise return first ID
+ *
+ * cursor is set to 1
+ */
+ID
+bdb2i_idl_firstid( ID_BLOCK *idl, ID *cursor )
+{
+ *cursor = 1;
+
+ if ( idl == NULL || ID_BLOCK_NIDS(idl) == 0 ) {
+ return( NOID );
+ }
+
+ if ( ID_BLOCK_ALLIDS( idl ) ) {
+ return( ID_BLOCK_NIDS(idl) > 1 ? 1 : NOID );
+ }
+
+ return( ID_BLOCK_ID(idl, 0) );
+}
+
+
+/* return next ID after id
+ * if ALLIDS block, cursor is id
+ * increment id
+ * if id < NIDS return id
+ * otherwise NOID.
+ * otherwise cursor is index into block
+ * if index < nids
+ * return id at index then increment
+ */
+ID
+bdb2i_idl_nextid( ID_BLOCK *idl, ID *cursor )
+{
+ if ( ID_BLOCK_ALLIDS( idl ) ) {
+ if( ++(*cursor) < ID_BLOCK_NIDS(idl) ) {
+ return *cursor;
+ } else {
+ return NOID;
+ }
+ }
+
+ if ( *cursor < ID_BLOCK_NIDS(idl) ) {
+ return ID_BLOCK_ID(idl, (*cursor)++);
+ }
+ return NOID;
+}
--- /dev/null
+/* index.c - routines for dealing with attribute indexes */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+
+static int add_value(BackendDB *be, struct dbcache *db, char *type, int indextype, char *val, ID id);
+static int index2prefix(int indextype);
+
+int
+bdb2i_index_add_entry(
+ BackendDB *be,
+ Entry *e
+)
+{
+ Attribute *ap;
+ struct berval bv;
+ struct berval *bvals[2];
+
+ Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
+ e->e_dn, 0 );
+
+ /*
+ * dn index entry - make it look like an attribute so it works
+ * with bdb2i_index_add_values() call
+ */
+
+ bv.bv_val = ch_strdup( e->e_ndn );
+ bv.bv_len = strlen( bv.bv_val );
+ bvals[0] = &bv;
+ bvals[1] = NULL;
+
+ /* add the dn to the indexes */
+ {
+ char *dn = ch_strdup( "dn" );
+ bdb2i_index_add_values( be, dn, bvals, e->e_id );
+ free( dn );
+ }
+
+ free( bv.bv_val );
+
+ /* add each attribute to the indexes */
+ for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
+ bdb2i_index_add_values( be, ap->a_type, ap->a_vals, e->e_id );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
+ e->e_ndn, 0 );
+ return( 0 );
+}
+
+int
+bdb2i_index_add_mods(
+ BackendDB *be,
+ LDAPModList *ml,
+ ID id
+)
+{
+ int rc;
+
+ for ( ; ml != NULL; ml = ml->ml_next ) {
+ LDAPMod *mod = &ml->ml_mod;
+
+ switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
+ case LDAP_MOD_ADD:
+ case LDAP_MOD_REPLACE:
+ rc = bdb2i_index_add_values( be, mod->mod_type,
+ mod->mod_bvalues, id );
+ break;
+ case LDAP_MOD_SOFTADD:
+ case LDAP_MOD_DELETE:
+ rc = 0;
+ break;
+ }
+
+ if ( rc != 0 ) {
+ return( rc );
+ }
+ }
+
+ return( 0 );
+}
+
+ID_BLOCK *
+bdb2i_index_read(
+ BackendDB *be,
+ char *type,
+ int indextype,
+ char *val
+)
+{
+ struct dbcache *db;
+ Datum key;
+ ID_BLOCK *idl;
+ int indexmask, syntax;
+ char prefix;
+ char *realval, *tmpval;
+ char buf[BUFSIZ];
+
+ char *at_cn;
+
+ ldbm_datum_init( key );
+
+ prefix = index2prefix( indextype );
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_index_read( \"%c%s\" -> \"%s\" )\n",
+ prefix, type, val );
+
+ bdb2i_attr_masks( be->be_private, type, &indexmask, &syntax );
+ if ( ! (indextype & indexmask) ) {
+ idl = bdb2i_idl_allids( be );
+ Debug( LDAP_DEBUG_TRACE,
+ "<= bdb2i_index_read %ld candidates (allids - not indexed)\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
+ return( idl );
+ }
+
+ attr_normalize( type );
+ at_cn = at_canonical_name(type);
+
+ if ( (db = bdb2i_cache_open( be, at_cn, BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "<= bdb2i_index_read NULL (could not open %s%s)\n", at_cn,
+ BDB2_SUFFIX, 0 );
+ return( NULL );
+ }
+
+ realval = val;
+ tmpval = NULL;
+ if ( prefix != UNKNOWN_PREFIX ) {
+ unsigned int len = strlen( val );
+
+ if ( (len + 2) < sizeof(buf) ) {
+ realval = buf;
+ } else {
+ /* value + prefix + null */
+ tmpval = (char *) ch_malloc( len + 2 );
+ realval = tmpval;
+ }
+
+ realval[0] = prefix;
+ strcpy( &realval[1], val );
+ }
+
+ key.dptr = realval;
+ key.dsize = strlen( realval ) + 1;
+
+ idl = bdb2i_idl_fetch( be, db, key );
+ if ( tmpval != NULL ) {
+ free( tmpval );
+ }
+
+ bdb2i_cache_close( be, db );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_index_read %ld candidates\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
+ return( idl );
+}
+
+static int
+add_value(
+ BackendDB *be,
+ struct dbcache *db,
+ char *type,
+ int indextype,
+ char *val,
+ ID id
+)
+{
+ int rc;
+ Datum key;
+ char *tmpval = NULL;
+ char *realval = val;
+ char buf[BUFSIZ];
+
+ char prefix = index2prefix( indextype );
+
+ ldbm_datum_init( key );
+
+ Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
+
+ if ( prefix != UNKNOWN_PREFIX ) {
+ unsigned int len = strlen( val );
+
+ if ( (len + 2) < sizeof(buf) ) {
+ realval = buf;
+ } else {
+ /* value + prefix + null */
+ tmpval = (char *) ch_malloc( len + 2 );
+ realval = tmpval;
+ }
+ realval[0] = prefix;
+ strcpy( &realval[1], val );
+ }
+
+ key.dptr = realval;
+ key.dsize = strlen( realval ) + 1;
+
+ rc = bdb2i_idl_insert_key( be, db, key, id );
+
+ if ( tmpval != NULL ) {
+ free( tmpval );
+ }
+
+ ldap_pvt_thread_yield();
+
+ /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
+ return( rc );
+}
+
+int
+bdb2i_index_add_values(
+ BackendDB *be,
+ char *type,
+ struct berval **vals,
+ ID id
+)
+{
+ char *val, *p, *code, *w;
+ unsigned i, j, len;
+ int indexmask, syntax;
+ char buf[SUBLEN + 1];
+ char vbuf[BUFSIZ];
+ char *bigbuf;
+ struct dbcache *db;
+
+ char *at_cn;
+
+ if( vals == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "=> bdb2i_index_add_values( \"%s\", NULL, %ld )\n",
+ type, id, 0 );
+ return 0;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_index_add_values( \"%s\", %ld )\n",
+ type, id, 0 );
+ attr_normalize( type );
+ bdb2i_attr_masks( be->be_private, type, &indexmask, &syntax );
+ if ( indexmask == 0 ) {
+ return( 0 );
+ }
+ at_cn = at_canonical_name(type);
+
+ if ( (db = bdb2i_cache_open( be, at_cn, BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "<= bdb2i_index_add_values -1 (could not open/create %s%s)\n",
+ at_cn, BDB2_SUFFIX, 0 );
+ return( -1 );
+ }
+
+ for ( i = 0; vals[i] != NULL; i++ ) {
+ /*
+ * presence index entry
+ */
+ if ( indexmask & INDEX_PRESENCE ) {
+ add_value( be, db, at_cn, INDEX_PRESENCE, "*", id );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "*** bdb2i_index_add_values syntax 0x%x syntax bin 0x%x\n",
+ syntax, SYNTAX_BIN, 0 );
+ if ( syntax & SYNTAX_BIN ) {
+ bdb2i_cache_close( be, db );
+ return( 0 );
+ }
+
+ bigbuf = NULL;
+ len = vals[i]->bv_len;
+
+ /* value + null */
+ if ( len + 2 > sizeof(vbuf) ) {
+ bigbuf = (char *) ch_malloc( len + 1 );
+ val = bigbuf;
+ } else {
+ val = vbuf;
+ }
+ (void) memcpy( val, vals[i]->bv_val, len );
+ val[len] = '\0';
+
+ value_normalize( val, syntax );
+
+ /* value_normalize could change the length of val */
+ len = strlen( val );
+
+ /*
+ * equality index entry
+ */
+ if ( indexmask & INDEX_EQUALITY ) {
+ add_value( be, db, at_cn, INDEX_EQUALITY, val, id );
+ }
+
+ /*
+ * approximate index entry
+ */
+ if ( indexmask & INDEX_APPROX ) {
+ for ( w = first_word( val ); w != NULL;
+ w = next_word( w ) ) {
+ if ( (code = phonetic( w )) != NULL ) {
+ add_value( be, db, at_cn, INDEX_APPROX,
+ code, id );
+ free( code );
+ }
+ }
+ }
+
+ /*
+ * substrings index entry
+ */
+ if ( indexmask & INDEX_SUB ) {
+ /* leading and trailing */
+ if ( len > SUBLEN - 2 ) {
+ buf[0] = '^';
+ for ( j = 0; j < SUBLEN - 1; j++ ) {
+ buf[j + 1] = val[j];
+ }
+ buf[SUBLEN] = '\0';
+
+ add_value( be, db, at_cn, INDEX_SUB, buf, id );
+
+ p = val + len - SUBLEN + 1;
+ for ( j = 0; j < SUBLEN - 1; j++ ) {
+ buf[j] = p[j];
+ }
+ buf[SUBLEN - 1] = '$';
+ buf[SUBLEN] = '\0';
+
+ add_value( be, db, at_cn, INDEX_SUB, buf, id );
+ }
+
+ /* any */
+ for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
+ for ( j = 0; j < SUBLEN; j++ ) {
+ buf[j] = p[j];
+ }
+ buf[SUBLEN] = '\0';
+
+ add_value( be, db, at_cn, INDEX_SUB, buf, id );
+ }
+ }
+
+ if ( bigbuf != NULL ) {
+ free( bigbuf );
+ }
+ }
+ bdb2i_cache_close( be, db );
+
+ return( 0 );
+}
+
+static int
+index2prefix( int indextype )
+{
+ int prefix;
+
+ switch ( indextype ) {
+ case INDEX_EQUALITY:
+ prefix = EQ_PREFIX;
+ break;
+ case INDEX_APPROX:
+ prefix = APPROX_PREFIX;
+ break;
+ case INDEX_SUB:
+ prefix = SUB_PREFIX;
+ break;
+ default:
+ prefix = UNKNOWN_PREFIX;
+ break;
+ }
+
+ return( prefix );
+}
--- /dev/null
+/* init.c - initialize bdb2 backend */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+
+#ifdef SLAPD_BDB2_DYNAMIC
+
+int back_bdb2_LTX_init_module(int argc, char *argv[]) {
+ BackendInfo bi;
+
+ memset( &bi, 0, sizeof(bi) );
+ bi.bi_type = "bdb2";
+ bi.bi_init = bdb2_back_initialize;
+
+ backend_add(&bi);
+ return 0;
+}
+
+#endif /* SLAPD_BDB2_DYNAMIC */
+
+static int
+bdb2i_back_init_private(
+ BackendInfo *bi
+)
+{
+ struct ldbtype *bt;
+
+ /* allocate backend-type-specific stuff */
+ bt = (struct ldbtype *) ch_calloc( 1, sizeof(struct ldbtype) );
+
+ bt->lty_dbhome = DEFAULT_DB_HOME;
+ bt->lty_mpsize = DEFAULT_DBCACHE_SIZE;
+
+ if ( slapMode & SLAP_TIMED_MODE )
+ bt->lty_betiming = 1;
+
+ bi->bi_private = bt;
+
+ return 0;
+}
+
+
+int
+bdb2_back_initialize(
+ BackendInfo *bi
+)
+{
+ int ret;
+
+ bi->bi_open = bdb2_back_open;
+ bi->bi_config = bdb2_back_config;
+ bi->bi_close = bdb2_back_close;
+ bi->bi_destroy = bdb2_back_destroy;
+
+ bi->bi_db_init = bdb2_back_db_init;
+ bi->bi_db_config = bdb2_back_db_config;
+ bi->bi_db_open = bdb2_back_db_open;
+ bi->bi_db_close = bdb2_back_db_close;
+ bi->bi_db_destroy = bdb2_back_db_destroy;
+
+ bi->bi_op_bind = bdb2_back_bind;
+ bi->bi_op_unbind = bdb2_back_unbind;
+ bi->bi_op_search = bdb2_back_search;
+ bi->bi_op_compare = bdb2_back_compare;
+ bi->bi_op_modify = bdb2_back_modify;
+ bi->bi_op_modrdn = bdb2_back_modrdn;
+ bi->bi_op_add = bdb2_back_add;
+ bi->bi_op_delete = bdb2_back_delete;
+ bi->bi_op_abandon = bdb2_back_abandon;
+
+ bi->bi_entry_release_rw = bdb2_back_entry_release_rw;
+ bi->bi_acl_group = bdb2_back_group;
+
+ /*
+ * hooks for slap tools
+ */
+ bi->bi_tool_entry_open = bdb2_tool_entry_open;
+ bi->bi_tool_entry_close = bdb2_tool_entry_close;
+ bi->bi_tool_entry_first = bdb2_tool_entry_first;
+ bi->bi_tool_entry_next = bdb2_tool_entry_next;
+ bi->bi_tool_entry_get = bdb2_tool_entry_get;
+ bi->bi_tool_entry_put = bdb2_tool_entry_put;
+ bi->bi_tool_index_attr = bdb2_tool_index_attr;
+ bi->bi_tool_index_change = bdb2_tool_index_change;
+ bi->bi_tool_sync = bdb2_tool_sync;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ ret = bdb2i_back_init_private( bi );
+
+ Debug( LDAP_DEBUG_TRACE, "bdb2_back_initialize: done (%d).\n", ret, 0, 0 );
+
+ return( ret );
+}
+
+int
+bdb2_back_destroy(
+ BackendInfo *bi
+)
+{
+ return 0;
+}
+
+int
+bdb2_back_open(
+ BackendInfo *bi
+)
+{
+ static int initialized = 0;
+ int rc;
+
+ if ( initialized++ ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb2_back_open: backend already initialized.\n", 0, 0, 0 );
+ return 0;
+
+ }
+
+ /* initialize the underlying database system */
+ rc = bdb2i_back_startup( bi );
+
+ return rc;
+}
+
+int
+bdb2_back_close(
+ BackendInfo *bi
+)
+{
+ int rc;
+
+ /* close the underlying database system */
+ rc = bdb2i_back_shutdown( bi );
+
+ return rc;
+}
+
+/* BDB2 changed */
+static int
+bdb2i_back_db_init_internal(
+ BackendDB *be
+)
+{
+ struct ldbminfo *li;
+ char *argv[ 4 ];
+
+ /* allocate backend-database-specific stuff */
+ li = (struct ldbminfo *) ch_calloc( 1, sizeof(struct ldbminfo) );
+
+ /* arrange to read nextid later (on first request for it) */
+ li->li_nextid = NOID;
+#if SLAPD_NEXTID_CHUNK > 1
+ li->li_nextid_wrote = NOID;
+#endif
+
+ /* default cache size */
+ li->li_cache.c_maxsize = DEFAULT_CACHE_SIZE;
+
+ /* default database cache size */
+ li->li_dbcachesize = DEFAULT_DBCACHE_SIZE;
+
+ /* default cache mode is sync on write */
+ li->li_dbcachewsync = 1;
+
+ /* default file creation mode */
+ li->li_mode = DEFAULT_MODE;
+
+ /* default database directory */
+ li->li_directory = DEFAULT_DB_DIRECTORY;
+
+ argv[ 0 ] = "objectclass";
+ argv[ 1 ] = "pres,eq";
+ argv[ 2 ] = NULL;
+ bdb2i_attr_index_config( li, "ldbm objectclass initialization",
+ 0, 2, argv, 1 );
+
+ /* initialize the cache mutex */
+ ldap_pvt_thread_mutex_init( &li->li_cache.c_mutex );
+
+ /* initialize the TP file head */
+ if ( bdb2i_txn_head_init( &li->li_txn_head ) != 0 )
+ return 1;
+
+ be->be_private = li;
+
+ return 0;
+}
+
+
+int
+bdb2_back_db_init(
+ BackendDB *be
+)
+{
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ ret = bdb2i_back_db_init_internal( be );
+ bdb2i_stop_timing( be->bd_info, time1, "DB-INIT", NULL, NULL );
+
+ return( ret );
+}
+
+
+int
+bdb2_back_db_open(
+ BackendDB *be
+)
+{
+ int rc;
+
+ rc = bdb2_back_db_startup( be );
+
+ return( rc );
+}
+
+int
+bdb2_back_db_destroy(
+ BackendDB *be
+)
+{
+ /* should free/destroy every in be_private */
+ free( be->be_private );
+ be->be_private = NULL;
+ return 0;
+}
+
+
--- /dev/null
+/* modify.c - bdb2 backend modify routine */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+int
+bdb2i_back_modify_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ LDAPModList *modlist,
+ Entry *e
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ LDAPModList *ml;
+ int err;
+
+ Debug(LDAP_DEBUG_ARGS, "bdb2i_back_modify:\n", 0, 0, 0);
+
+ if ( (err = acl_check_modlist( be, conn, op, e, modlist )) != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
+ goto error_return;
+ }
+
+ for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
+ LDAPMod *mod = &ml->ml_mod;
+
+ switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
+ case LDAP_MOD_ADD:
+ err = bdb2i_add_values( e, mod, op->o_ndn );
+ break;
+
+ case LDAP_MOD_DELETE:
+ err = bdb2i_delete_values( e, mod, op->o_ndn );
+ break;
+
+ case LDAP_MOD_REPLACE:
+ err = bdb2i_replace_values( e, mod, op->o_ndn );
+ break;
+
+ case LDAP_MOD_SOFTADD:
+ /* Avoid problems in index_add_mods()
+ * We need to add index if necessary.
+ */
+ mod->mod_op = LDAP_MOD_ADD;
+ if ( (err = bdb2i_add_values( e, mod, op->o_ndn ))
+ == LDAP_TYPE_OR_VALUE_EXISTS ) {
+
+ err = LDAP_SUCCESS;
+ mod->mod_op = LDAP_MOD_SOFTADD;
+
+ }
+ break;
+ }
+
+ if ( err != LDAP_SUCCESS ) {
+ /* unlock entry, delete from cache */
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
+ goto error_return;
+ }
+ }
+
+ /* check that the entry still obeys the schema */
+ if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL, NULL );
+ goto error_return;
+ }
+
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ if ( op->o_abandon ) {
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ goto error_return;
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ /* modify indexes */
+ if ( bdb2i_index_add_mods( be, modlist, e->e_id ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto error_return;
+ }
+
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ if ( op->o_abandon ) {
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ goto error_return;
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ /* change the entry itself */
+ if ( bdb2i_id2entry_add( be, e ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto error_return;
+ }
+
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ return( 0 );
+
+error_return:;
+ return( -1 );
+}
+
+
+int
+bdb2_back_modify(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ LDAPModList *modlist
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret, manageDSAit;
+ Entry *matched;
+ Entry *e;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ return( -1 );
+ }
+
+ /* check, if a new default attribute index will be created,
+ in which case we have to open the index file BEFORE TP */
+ switch ( slapMode & SLAP_MODE ) {
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+ bdb2i_check_default_attr_index_mod( li, modlist );
+ break;
+ }
+
+ if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ ret = -1;
+ goto done;
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+
+ ber_bvecfree( refs );
+
+ ret = -1;
+ goto done;
+ }
+
+ ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e );
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+
+done:
+ (void) bdb2i_leave_backend_w( lock );
+ bdb2i_stop_timing( be->bd_info, time1, "MOD", conn, op );
+
+ return( ret );
+}
+
+
+int
+bdb2i_add_values(
+ Entry *e,
+ LDAPMod *mod,
+ char *dn
+)
+{
+ int i;
+ Attribute *a;
+
+ /* check if the values we're adding already exist */
+ if ( (a = attr_find( e->e_attrs, mod->mod_type )) != NULL ) {
+ for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) {
+ if ( value_find( a->a_vals, mod->mod_bvalues[i],
+ a->a_syntax, 3 ) == 0 ) {
+ return( LDAP_TYPE_OR_VALUE_EXISTS );
+ }
+ }
+ }
+
+ /* no - add them */
+ if( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) {
+ return( LDAP_CONSTRAINT_VIOLATION );
+ }
+
+ return( LDAP_SUCCESS );
+}
+
+int
+bdb2i_delete_values(
+ Entry *e,
+ LDAPMod *mod,
+ char *dn
+)
+{
+ int i, j, k, found;
+ Attribute *a;
+
+ /* delete the entire attribute */
+ if ( mod->mod_bvalues == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n",
+ mod->mod_type, 0, 0 );
+ return( attr_delete( &e->e_attrs, mod->mod_type ) ?
+ LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS );
+ }
+
+ /* delete specific values - find the attribute first */
+ if ( (a = attr_find( e->e_attrs, mod->mod_type )) == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "could not find attribute %s\n",
+ mod->mod_type, 0, 0 );
+ return( LDAP_NO_SUCH_ATTRIBUTE );
+ }
+
+ /* find each value to delete */
+ for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) {
+ found = 0;
+ for ( j = 0; a->a_vals[j] != NULL; j++ ) {
+ if ( value_cmp( mod->mod_bvalues[i], a->a_vals[j],
+ a->a_syntax, 3 ) != 0 ) {
+ continue;
+ }
+ found = 1;
+
+ /* found a matching value - delete it */
+ ber_bvfree( a->a_vals[j] );
+ for ( k = j + 1; a->a_vals[k] != NULL; k++ ) {
+ a->a_vals[k - 1] = a->a_vals[k];
+ }
+ a->a_vals[k - 1] = NULL;
+
+ /* delete the entire attribute, if no values remain */
+ if ( a->a_vals[0] == NULL) {
+ Debug( LDAP_DEBUG_ARGS,
+ "removing entire attribute %s\n",
+ mod->mod_type, 0, 0 );
+ if ( attr_delete( &e->e_attrs, mod->mod_type ) ) {
+ return LDAP_NO_SUCH_ATTRIBUTE;
+ }
+ }
+
+ break;
+ }
+
+ /* looked through them all w/o finding it */
+ if ( ! found ) {
+ Debug( LDAP_DEBUG_ARGS,
+ "could not find value for attr %s\n",
+ mod->mod_type, 0, 0 );
+ return( LDAP_NO_SUCH_ATTRIBUTE );
+ }
+ }
+
+ return( LDAP_SUCCESS );
+}
+
+int
+bdb2i_replace_values(
+ Entry *e,
+ LDAPMod *mod,
+ char *dn
+)
+{
+ (void) attr_delete( &e->e_attrs, mod->mod_type );
+
+ if ( mod->mod_bvalues != NULL &&
+ attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 )
+ {
+ return( LDAP_CONSTRAINT_VIOLATION );
+ }
+
+ return( LDAP_SUCCESS );
+}
--- /dev/null
+/* id.c - keep track of the next id to be given out */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "slap.h"
+#include "back-bdb2.h"
+
+/* reading and writing NEXTID is handled in txn.c */
+#define next_id_read(be) bdb2i_get_nextid( (be) )
+#define next_id_write(be,id) bdb2i_put_nextid( (be), (id) )
+
+
+int
+bdb2i_next_id_save( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ ID id = bdb2i_next_id_get( be );
+ int rc;
+
+ rc = next_id_write( be, id );
+
+ return rc;
+}
+
+ID
+bdb2i_next_id( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ ID id;
+
+ /* first time in here since startup - try to read the nexid */
+ if ( li->li_nextid == NOID ) {
+ li->li_nextid = next_id_read( be );
+
+ if ( li->li_nextid == NOID ) {
+ li->li_nextid = 1;
+ }
+ }
+
+ id = li->li_nextid++;
+
+ (void) next_id_write( be, li->li_nextid );
+
+ return( id );
+}
+
+ID
+bdb2i_next_id_get( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ ID id;
+
+ /* first time in here since startup - try to read the nexid */
+ if ( li->li_nextid == NOID ) {
+ li->li_nextid = next_id_read( be );
+
+ if ( li->li_nextid == NOID ) {
+ li->li_nextid = 1;
+ }
+ }
+
+ id = li->li_nextid;
+
+ return( id );
+}
--- /dev/null
+/* porter.c - port functions of the bdb2 backend */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/errno.h>
+
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+
+#define PORTER_OBJ "bdb2_backend"
+
+
+int
+bdb2i_enter_backend_rw( DB_LOCK *lock, int writer )
+{
+ u_int32_t locker;
+ db_lockmode_t lock_type;
+ DBT lock_dbt;
+ int ret = 0;
+
+ switch ( slapMode & SLAP_MODE ) {
+
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+ if ( ( ret = lock_id( bdb2i_dbEnv.lk_info, &locker )) != 0 ) {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_enter_backend(): unable to get locker id -- %s\n",
+ strerror( ret ), 0, 0 );
+ return( ret );
+
+ }
+
+ lock_type = writer ? DB_LOCK_WRITE : DB_LOCK_READ;
+ lock_dbt.data = PORTER_OBJ;
+ lock_dbt.size = strlen( PORTER_OBJ );
+
+ switch ( ( ret = lock_get( bdb2i_dbEnv.lk_info, locker, 0,
+ &lock_dbt, lock_type, lock ))) {
+
+ case 0:
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb2i_enter_backend() -- %s lock granted\n",
+ writer ? "write" : "read", 0, 0 );
+ break;
+
+ case DB_LOCK_NOTGRANTED:
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_enter_backend() -- %s lock NOT granted\n",
+ writer ? "write" : "read", 0, 0 );
+ break;
+
+ case DB_LOCK_DEADLOCK:
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_enter_backend() -- %s lock returned DEADLOCK\n",
+ writer ? "write" : "read", 0, 0 );
+ break;
+
+ default:
+ ret = errno;
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_enter_backend() -- %s lock returned ERROR: %s\n",
+ writer ? "write" : "read", strerror( ret ), 0 );
+ break;
+
+ }
+ break;
+ }
+
+ /* if we are a writer and we have the backend lock,
+ start transaction control */
+ if ( writer && ( ret == 0 )) {
+
+ ret = bdb2i_start_transction( bdb2i_dbEnv.tx_info );
+
+ }
+
+ return( ret );
+}
+
+
+int
+bdb2i_leave_backend_rw( DB_LOCK lock, int writer )
+{
+ /* since one or more error can occure,
+ we must have several return codes that are or'ed at the end */
+ int ret_transaction = 0;
+ int ret_lock = 0;
+
+ /* if we are a writer, finish the transaction */
+ if ( writer ) {
+
+ ret_transaction = bdb2i_finish_transaction();
+
+ }
+
+ /* check whether checkpointing is needed */
+ ret_transaction |= bdb2i_set_txn_checkpoint( bdb2i_dbEnv.tx_info, 0 );
+
+ /* now release the lock */
+ switch ( slapMode & SLAP_MODE ) {
+
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+ switch( ( ret_lock = lock_put( bdb2i_dbEnv.lk_info, lock ))) {
+
+ case 0:
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb2i_leave_backend() -- %s lock released\n",
+ writer ? "write" : "read", 0, 0 );
+ break;
+
+ case DB_LOCK_NOTHELD:
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_leave_backend() -- %s lock NOT held\n",
+ writer ? "write" : "read", 0, 0 );
+ break;
+
+ case DB_LOCK_DEADLOCK:
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_leave_backend() -- %s lock returned DEADLOCK\n",
+ writer ? "write" : "read", 0, 0 );
+ break;
+
+ default:
+ ret_lock = errno;
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_leave_backend() -- %s lock returned ERROR: %s\n",
+ writer ? "write" : "read", strerror( ret_lock ), 0 );
+ break;
+
+ }
+ break;
+ }
+
+ return( ret_transaction | ret_lock );
+}
+
+
--- /dev/null
+#ifndef _PROTO_BACK_BDB2
+#define _PROTO_BACK_BDB2
+
+#include <ldap_cdefs.h>
+
+#include <ac/time.h> /* Needed in add.c compare.c struct timeval */
+
+#include "external.h"
+
+LDAP_BEGIN_DECL
+
+/*
+ * add.c
+ */
+int bdb2i_release_add_lock LDAP_P(());
+
+/*
+ * alias.c
+ */
+
+Entry * bdb2i_deref_r LDAP_P((
+ Backend *be,
+ Entry *e,
+ char *dn,
+ int *err,
+ Entry **matched,
+ char **text ));
+
+#define deref_entry_r( be, e, err, matched, text ) \
+ bdb2i_deref_r( be, e, NULL, err, matched, text )
+#define deref_dn_r( be, dn, err, matched, text ) \
+ bdb2i_deref_r( be, NULL, dn, err, matched, text )
+
+/*
+ * attr.c
+ */
+
+void bdb2i_attr_masks LDAP_P(( struct ldbminfo *li, char *type, int *indexmask,
+ int *syntaxmask ));
+void bdb2i_attr_index_config LDAP_P(( struct ldbminfo *li, char *fname,
+ int lineno, int argc, char **argv, int init ));
+
+/*
+ * cache.c
+ */
+
+int bdb2i_cache_add_entry_rw LDAP_P(( struct cache *cache, Entry *e, int rw ));
+int bdb2i_cache_update_entry LDAP_P(( struct cache *cache, Entry *e ));
+void bdb2i_cache_return_entry_rw LDAP_P(( struct cache *cache, Entry *e,
+ int rw ));
+#define bdb2i_cache_return_entry_r(c, e) bdb2i_cache_return_entry_rw((c), (e), 0)
+#define bdb2i_cache_return_entry_w(c, e) bdb2i_cache_return_entry_rw((c), (e), 1)
+
+ID bdb2i_cache_find_entry_dn2id LDAP_P(( BackendDB *be, struct cache *cache,
+ char *dn ));
+Entry * bdb2i_cache_find_entry_id LDAP_P(( struct cache *cache, ID id, int rw ));
+int bdb2i_cache_delete_entry LDAP_P(( struct cache *cache, Entry *e ));
+
+/*
+ * dbcache.c
+ */
+
+struct dbcache * bdb2i_cache_open LDAP_P(( BackendDB *be, char *name, char *suffix,
+ int flags ));
+void bdb2i_cache_close LDAP_P(( BackendDB *be, struct dbcache *db ));
+void bdb2i_cache_really_close LDAP_P(( BackendDB *be, struct dbcache *db ));
+void bdb2i_cache_flush_all LDAP_P(( BackendDB *be ));
+Datum bdb2i_cache_fetch LDAP_P(( struct dbcache *db, Datum key ));
+int bdb2i_cache_store LDAP_P(( struct dbcache *db, Datum key, Datum data, int flags ));
+int bdb2i_cache_delete LDAP_P(( struct dbcache *db, Datum key ));
+
+/*
+ * dn2id.c
+ */
+
+int bdb2i_dn2id_add LDAP_P(( BackendDB *be, char *dn, ID id ));
+ID bdb2i_dn2id LDAP_P(( BackendDB *be, char *dn ));
+int bdb2i_dn2id_delete LDAP_P(( BackendDB *be, char *dn ));
+
+ID_BLOCK *
+bdb2i_dn2idl LDAP_P((
+ BackendDB *be,
+ char *dn,
+ int prefix ));
+
+Entry * bdb2i_dn2entry_rw LDAP_P((
+ BackendDB *be,
+ char *dn,
+ Entry **matched,
+ int rw ));
+
+#define bdb2i_dn2entry_r(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 0)
+#define bdb2i_dn2entry_w(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 1)
+
+/*
+ * entry.c
+ */
+int bdb2_back_entry_release_rw LDAP_P(( BackendDB *be, Entry *e, int rw ));
+
+/*
+ * filterindex.c
+ */
+
+ID_BLOCK * bdb2i_filter_candidates LDAP_P(( BackendDB *be, Filter *f ));
+
+/*
+ * id2children.c
+ */
+
+int bdb2i_has_children LDAP_P(( BackendDB *be, Entry *p ));
+
+/*
+ * id2entry.c
+ */
+
+int bdb2i_id2entry_add LDAP_P(( BackendDB *be, Entry *e ));
+int bdb2i_id2entry_delete LDAP_P(( BackendDB *be, Entry *e ));
+
+Entry * bdb2i_id2entry_rw LDAP_P(( BackendDB *be, ID id, int rw ));
+#define bdb2i_id2entry_r(be, id) bdb2i_id2entry_rw((be), (id), 0)
+#define bdb2i_id2entry_w(be, id) bdb2i_id2entry_rw((be), (id), 1)
+
+/*
+ * idl.c
+ */
+
+ID_BLOCK * bdb2i_idl_alloc LDAP_P(( unsigned int nids ));
+ID_BLOCK * bdb2i_idl_allids LDAP_P(( BackendDB *be ));
+void bdb2i_idl_free LDAP_P(( ID_BLOCK *idl ));
+ID_BLOCK * bdb2i_idl_fetch LDAP_P(( BackendDB *be, struct dbcache *db, Datum key ));
+int bdb2i_idl_insert_key LDAP_P(( BackendDB *be, struct dbcache *db, Datum key, ID id ));
+int bdb2i_idl_insert LDAP_P(( ID_BLOCK **idl, ID id, unsigned int maxids ));
+int bdb2i_idl_delete_key LDAP_P(( BackendDB *be, struct dbcache *db, Datum key, ID id ));
+ID_BLOCK * bdb2i_idl_intersection LDAP_P(( BackendDB *be, ID_BLOCK *a, ID_BLOCK *b ));
+ID_BLOCK * bdb2i_idl_union LDAP_P(( BackendDB *be, ID_BLOCK *a, ID_BLOCK *b ));
+ID_BLOCK * bdb2i_idl_notin LDAP_P(( BackendDB *be, ID_BLOCK *a, ID_BLOCK *b ));
+ID bdb2i_idl_firstid LDAP_P(( ID_BLOCK *idl, ID *cursor ));
+ID bdb2i_idl_nextid LDAP_P(( ID_BLOCK *idl, ID *cursor ));
+
+/*
+ * index.c
+ */
+
+int bdb2i_index_add_entry LDAP_P(( BackendDB *be, Entry *e ));
+int bdb2i_index_add_mods LDAP_P(( BackendDB *be, LDAPModList *ml, ID id ));
+ID_BLOCK * bdb2i_index_read LDAP_P(( BackendDB *be, char *type, int indextype, char *val ));
+int bdb2i_index_add_values LDAP_P(( BackendDB *be, char *type, struct berval **vals, ID id ));
+
+/*
+ * kerberos.c
+ */
+
+#ifdef HAVE_KERBEROS
+/* bdb2i_krbv4_ldap_auth LDAP_P(( BackendDB *be, struct berval *cred, AUTH_DAT *ad )); */
+#endif
+
+/*
+ * modify.c
+ * These prototypes are placed here because they are used by modify and
+ * modify rdn which are implemented in different files.
+ *
+ * We need bdb2i_back_modify_internal here because of LDAP modrdn & modify use
+ * it. If we do not add this, there would be a bunch of code replication
+ * here and there and of course the likelihood of bugs increases.
+ * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
+ *
+ */
+
+int bdb2i_add_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+int bdb2i_delete_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+int bdb2i_replace_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+int bdb2i_back_modify_internal LDAP_P((Backend *be, Connection *conn, Operation *op,
+ char *dn, LDAPModList *mods, Entry *e));
+/*
+ * nextid.c
+ */
+
+ID bdb2i_next_id LDAP_P(( BackendDB *be ));
+void bdb2i_next_id_return LDAP_P(( BackendDB *be, ID id ));
+ID bdb2i_next_id_get LDAP_P(( BackendDB *be ));
+int bdb2i_next_id_save LDAP_P(( BackendDB *be ));
+
+/*
+ * startup.c
+ */
+
+int bdb2i_back_startup LDAP_P(( BackendInfo *bi ));
+int bdb2i_back_shutdown LDAP_P(( BackendInfo *bi ));
+int bdb2i_back_db_startup LDAP_P(( BackendDB *be ));
+int bdb2i_back_db_shutdown LDAP_P(( BackendDB *be ));
+
+/*
+ * timing.c
+ */
+
+void bdb2i_uncond_start_timing LDAP_P(( struct timeval *time1 ));
+#define bdb2i_start_timing(bi,time1) if ( with_timing( bi )) bdb2i_uncond_start_timing( (time1) )
+void bdb2i_uncond_stop_timing LDAP_P(( struct timeval time1,
+ char *func, Connection *conn, Operation *op, int level ));
+#define bdb2i_stop_timing(bi,time1,func,conn,op) if ( with_timing( bi )) bdb2i_uncond_stop_timing( (time1), (func), (conn), (op), LDAP_DEBUG_ANY )
+
+/*
+ * porter.c
+ */
+
+int bdb2i_enter_backend_rw LDAP_P(( DB_LOCK *lock, int writer ));
+#define bdb2i_enter_backend_r(lock) bdb2i_enter_backend_rw((lock), 0 )
+#define bdb2i_enter_backend_w(lock) bdb2i_enter_backend_rw((lock), 1 )
+int bdb2i_leave_backend_rw LDAP_P(( DB_LOCK lock, int writer ));
+#define bdb2i_leave_backend_r(lock) bdb2i_leave_backend_rw((lock), 0 )
+#define bdb2i_leave_backend_w(lock) bdb2i_leave_backend_rw((lock), 1 )
+
+/*
+ * txn.c
+ */
+
+int bdb2i_txn_head_init LDAP_P(( BDB2_TXN_HEAD *head ));
+void bdb2i_txn_attr_config LDAP_P((
+ struct ldbminfo *li,
+ char *attr,
+ int open ));
+int bdb2i_txn_open_files LDAP_P(( BackendDB *be ));
+void bdb2i_txn_close_files LDAP_P(( BackendDB *be ));
+BDB2_TXN_FILES *bdb2i_get_db_file_cache LDAP_P((
+ struct ldbminfo *li,
+ char *name ));
+int bdb2i_check_additional_attr_index LDAP_P(( struct ldbminfo *li ));
+void bdb2i_check_default_attr_index_add LDAP_P((
+ struct ldbminfo *li,
+ Entry *e ));
+void bdb2i_check_default_attr_index_mod LDAP_P((
+ struct ldbminfo *li,
+ LDAPModList *modlist ));
+ID bdb2i_get_nextid LDAP_P(( BackendDB *be ));
+int bdb2i_put_nextid LDAP_P(( BackendDB *be, ID id ));
+LDBM bdb2i_db_open LDAP_P(( char *name, int type, int rw, int mode,
+ int dbcachesize ));
+int bdb2i_db_store LDAP_P(( LDBM ldbm, Datum key, Datum data, int flags ));
+int bdb2i_db_delete LDAP_P(( LDBM ldbm, Datum key ));
+Datum bdb2i_db_fetch LDAP_P(( LDBM ldbm, Datum key ));
+Datum bdb2i_db_firstkey LDAP_P(( LDBM ldbm, DBC **dbch ));
+Datum bdb2i_db_nextkey LDAP_P(( LDBM ldbm, Datum key, DBC *dbcp ));
+int bdb2i_start_transction LDAP_P(( DB_TXNMGR *txmgr ));
+int bdb2i_finish_transaction LDAP_P(( ));
+int bdb2i_set_txn_checkpoint LDAP_P(( DB_TXNMGR *txmgr, int forced ));
+
+
+LDAP_END_DECL
+#endif
--- /dev/null
+/* search.c - bdb2 backend search function */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+static ID_BLOCK *base_candidate(
+ Backend *be, Entry *e );
+
+static ID_BLOCK *search_candidates(
+ Backend *be, Entry *e, Filter *filter,
+ int scope, int deref, int manageDSAit );
+
+static int
+bdb2i_back_search_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *base,
+ int scope,
+ int deref,
+ int slimit,
+ int tlimit,
+ Filter *filter,
+ char *filterstr,
+ char **attrs,
+ int attrsonly
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ int rc, err;
+ char *text;
+ time_t stoptime;
+ ID_BLOCK *candidates;
+ ID id, cursor;
+ Entry *e;
+ struct berval **v2refs = NULL;
+ Entry *matched = NULL;
+ char *realbase = NULL;
+ int nentries = 0;
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug(LDAP_DEBUG_TRACE, "=> bdb2_back_search\n", 0, 0, 0);
+
+ /* get entry with reader lock */
+ if ( deref & LDAP_DEREF_FINDING ) {
+ e = deref_dn_r( be, base, &err, &matched, &text );
+
+ } else {
+ e = bdb2i_dn2entry_r( be, base, &matched );
+ err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
+ text = NULL;
+ }
+
+ if ( e == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, err,
+ matched_dn, text, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ return 1;
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ char *matched_dn = ch_strdup( e->e_dn );
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
+
+ return 1;
+ }
+
+ if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
+ tlimit = -1; /* allow root to set no limit */
+ } else {
+ tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
+ be->be_timelimit : tlimit;
+ stoptime = op->o_time + tlimit;
+ }
+
+ if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
+ slimit = -1; /* allow root to set no limit */
+ } else {
+ slimit = (slimit > be->be_sizelimit || slimit < 1) ?
+ be->be_sizelimit : slimit;
+ }
+
+ if ( scope == LDAP_SCOPE_BASE) {
+ candidates = base_candidate( be, e );
+
+ } else {
+ candidates = search_candidates( be, e, filter,
+ scope, deref, manageDSAit );
+ }
+
+ /* need normalized dn below */
+ realbase = ch_strdup( e->e_ndn );
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+
+ if ( candidates == NULL ) {
+ /* no candidates */
+ Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
+ 0, 0 );
+
+ send_search_result( conn, op,
+ LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 0 );
+
+ rc = 1;
+ goto done;
+ }
+
+ for ( id = bdb2i_idl_firstid( candidates, &cursor ); id != NOID;
+ id = bdb2i_idl_nextid( candidates, &cursor ) )
+ {
+ int scopeok = 0;
+
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+
+ if ( op->o_abandon ) {
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ rc = 0;
+ goto done;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ /* check time limit */
+ if ( tlimit != -1 && slap_get_time() > stoptime ) {
+ send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+ NULL, NULL, v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
+ }
+
+ /* get the entry with reader lock */
+ e = bdb2i_id2entry_r( be, id );
+
+ if ( e == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n",
+ id, 0, 0 );
+
+ goto loop_continue;
+ }
+
+ if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
+ Entry *matched;
+ int err;
+ char *text;
+
+ e = deref_entry_r( be, e, &err, &matched, &text );
+
+ if( e == NULL ) {
+ e = matched;
+ goto loop_continue;
+ }
+
+ if( e->e_id == id ) {
+ /* circular loop */
+ goto loop_continue;
+ }
+
+ /* need to skip alias which deref into scope */
+ if( scope & LDAP_SCOPE_ONELEVEL ) {
+ char *pdn = dn_parent( NULL, e->e_ndn );
+ if ( pdn != NULL ) {
+ if( strcmp( pdn, realbase ) ) {
+ free( pdn );
+ goto loop_continue;
+ }
+ free(pdn);
+ }
+
+ } else if ( dn_issuffix( e->e_ndn, realbase ) ) {
+ /* alias is within scope */
+ Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n",
+ e->e_dn, 0, 0 );
+ goto loop_continue;
+ }
+
+ scopeok = 1;
+ }
+
+ /*
+ * if it's a referral, add it to the list of referrals. only do
+ * this for non-base searches, and don't check the filter
+ * explicitly here since it's only a candidate anyway.
+ */
+ if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
+ is_entry_referral( e ) )
+ {
+ struct berval **refs = get_entry_referrals(
+ be, conn, op, e );
+
+ send_search_reference( be, conn, op,
+ e, refs, scope, NULL, &v2refs );
+
+ ber_bvecfree( refs );
+
+ goto loop_continue;
+ }
+
+ /* if it matches the filter and scope, send it */
+ if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+ char *dn;
+
+ /* check scope */
+ if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
+ if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
+ (void) dn_normalize_case( dn );
+ scopeok = (dn == realbase)
+ ? 1
+ : (strcmp( dn, realbase ) ? 0 : 1 );
+ free( dn );
+
+ } else {
+ scopeok = (realbase == NULL || *realbase == '\0');
+ }
+
+ } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
+ dn = ch_strdup( e->e_ndn );
+ scopeok = dn_issuffix( dn, realbase );
+ free( dn );
+
+ } else {
+ scopeok = 1;
+ }
+
+ if ( scopeok ) {
+ /* check size limit */
+ if ( --slimit == -1 ) {
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ send_search_result( conn, op,
+ LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
+ v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
+ }
+
+ if (e) {
+ switch ( send_search_entry( be, conn, op, e,
+ attrs, attrsonly, NULL ) ) {
+ case 0: /* entry sent ok */
+ nentries++;
+ break;
+ case 1: /* entry not sent */
+ break;
+ case -1: /* connection closed */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ rc = 0;
+ goto done;
+ }
+ }
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n",
+ id, 0, 0 );
+ }
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n",
+ id, 0, 0 );
+ }
+
+loop_continue:
+ if( e != NULL ) {
+ /* free reader lock */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ }
+
+ ldap_pvt_thread_yield();
+ }
+ send_search_result( conn, op,
+ v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+ NULL, NULL, v2refs, NULL, nentries );
+
+ rc = 0;
+
+done:
+ bdb2i_idl_free( candidates );
+
+ ber_bvecfree( v2refs );
+ if( realbase ) free( realbase );
+
+ return rc;
+}
+
+
+int
+bdb2_back_search(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *base,
+ int scope,
+ int deref,
+ int slimit,
+ int tlimit,
+ Filter *filter,
+ char *filterstr,
+ char **attrs,
+ int attrsonly
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ return( -1 );
+
+ }
+
+ ret = bdb2i_back_search_internal( be, conn, op, base, scope, deref,
+ slimit, tlimit, filter, filterstr, attrs, attrsonly );
+
+ (void) bdb2i_leave_backend_r( lock );
+ bdb2i_stop_timing( be->bd_info, time1, "SRCH", conn, op );
+
+ return( ret );
+}
+
+
+static ID_BLOCK *
+base_candidate(
+ Backend *be,
+ Entry *e
+)
+{
+ ID_BLOCK *idl;
+
+ Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
+ e->e_dn, 0, 0);
+
+ idl = bdb2i_idl_alloc( 1 );
+ bdb2i_idl_insert( &idl, e->e_id, 1 );
+
+ return( idl );
+}
+
+static ID_BLOCK *
+search_candidates(
+ Backend *be,
+ Entry *e,
+ Filter *filter,
+ int scope,
+ int deref,
+ int manageDSAit
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ ID_BLOCK *candidates;
+ Filter *f, *rf, *af, *lf;
+
+ Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
+ e->e_ndn, scope, deref );
+
+ f = NULL;
+
+ if( !manageDSAit ) {
+ /* match referrals */
+ rf = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_next = NULL;
+ rf->f_choice = LDAP_FILTER_OR;
+ rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ rf->f_or->f_avtype = ch_strdup( "objectclass" );
+ rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
+ rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
+ rf->f_or->f_next = filter;
+ f = rf;
+ } else {
+ rf = NULL;
+ f = filter;
+ }
+
+ if( deref & LDAP_DEREF_SEARCHING ) {
+ /* match aliases */
+ af = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_next = NULL;
+ af->f_choice = LDAP_FILTER_OR;
+ af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ af->f_or->f_avtype = ch_strdup( "objectclass" );
+ af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
+ af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
+ af->f_or->f_next = f;
+ f = af;
+ } else {
+ af = NULL;
+ }
+
+ if ( scope == LDAP_SCOPE_SUBTREE ) {
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+
+ lf->f_and->f_choice = SLAPD_FILTER_DN_SUBTREE;
+ lf->f_and->f_dn = e->e_ndn;
+
+ lf->f_and->f_next = f;
+ f = lf;
+
+ } else if ( scope == LDAP_SCOPE_ONELEVEL ) {
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+
+ lf->f_and->f_choice = SLAPD_FILTER_DN_ONE;
+ lf->f_and->f_dn = e->e_ndn;
+
+ lf->f_and->f_next = f;
+ f = lf;
+
+ } else {
+ lf = NULL;
+ }
+
+ candidates = bdb2i_filter_candidates( be, f );
+
+ /* free up filter additions we allocated above */
+ if( lf != NULL ) {
+ free( lf->f_and );
+ free( lf );
+ }
+
+ if( af != NULL ) {
+ af->f_or->f_next = NULL;
+ filter_free( af );
+ }
+
+ if( rf != NULL ) {
+ rf->f_or->f_next = NULL;
+ filter_free( rf );
+ }
+
+ return( candidates );
+}
--- /dev/null
+/* tools.c - tools for slap tools */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+
+static LDBMCursor *cursorp = NULL;
+static DBCache *id2entry = NULL;
+
+int bdb2_tool_entry_open(
+ BackendDB *be, int mode )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ int flags;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry == NULL );
+
+ switch( mode ) {
+ case 1:
+ flags = LDBM_WRCREAT;
+ break;
+ case 2:
+#ifdef TRUNCATE_MODE
+ flags = LDBM_NEWDB;
+#else
+ flags = LDBM_WRCREAT;
+#endif
+ break;
+ default:
+ flags = LDBM_READER;
+ }
+
+ li->li_dbcachewsync = 0;
+
+ if ( (id2entry = bdb2i_cache_open( be, "id2entry", BDB2_SUFFIX, flags ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry" BDB2_SUFFIX "\n",
+ 0, 0, 0 );
+ return( -1 );
+ }
+
+ return 0;
+}
+
+int bdb2_tool_entry_close(
+ BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ bdb2i_cache_close( be, id2entry );
+ li->li_dbcachewsync = 1;
+ id2entry = NULL;
+
+ return 0;
+}
+
+ID bdb2_tool_entry_first(
+ BackendDB *be )
+{
+ Datum key;
+ ID id;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ key = ldbm_firstkey( id2entry->dbc_db, &cursorp );
+
+ if( key.dptr == NULL ) {
+ return NOID;
+ }
+
+ memcpy( &id, key.dptr, key.dsize );
+
+ ldbm_datum_free( id2entry->dbc_db, key );
+
+ return id;
+}
+
+ID bdb2_tool_entry_next(
+ BackendDB *be )
+{
+ Datum key;
+ ID id;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ /* allow for NEXTID */
+ ldbm_datum_init( key );
+
+ key = ldbm_nextkey( id2entry->dbc_db, key, cursorp );
+
+ if( key.dptr == NULL ) {
+ return NOID;
+ }
+
+ memcpy( &id, key.dptr, key.dsize );
+
+ ldbm_datum_free( id2entry->dbc_db, key );
+
+ return id;
+}
+
+Entry* bdb2_tool_entry_get( BackendDB *be, ID id )
+{
+ Entry *e;
+ Datum key, data;
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ ldbm_datum_init( key );
+
+ key.dptr = (char *) &id;
+ key.dsize = sizeof(ID);
+
+ data = bdb2i_cache_fetch( id2entry, key );
+
+ if ( data.dptr == NULL ) {
+ return NULL;
+ }
+
+ e = str2entry( data.dptr );
+ ldbm_datum_free( id2entry->dbc_db, data );
+
+ return e;
+}
+
+ID bdb2_tool_entry_put(
+ BackendDB *be,
+ Entry *e )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Datum key, data;
+ int rc, len;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ if( bdb2i_next_id_get( be ) == NOID ) {
+ return NOID;
+ }
+
+ e->e_id = li->li_nextid++;
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2_tool_entry_put( %ld, \"%s\" )\n",
+ e->e_id, e->e_dn, 0 );
+
+ rc = bdb2i_index_add_entry( be, e );
+
+ if( rc != 0 ) {
+ return NOID;
+ }
+
+ rc = bdb2i_dn2id_add( be, e->e_ndn, e->e_id );
+
+ if( rc != 0 ) {
+ return NOID;
+ }
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ key.dptr = (char *) &e->e_id;
+ key.dsize = sizeof(ID);
+
+ data.dptr = entry2str( e, &len );
+ data.dsize = len + 1;
+
+ /* store it */
+ rc = bdb2i_cache_store( id2entry, key, data, LDBM_REPLACE );
+
+ if( rc != 0 ) {
+ (void) bdb2i_dn2id_delete( be, e->e_ndn );
+ return NOID;
+ }
+
+ return e->e_id;
+}
+
+int bdb2_tool_index_attr(
+ BackendDB *be,
+ char* type )
+{
+ static DBCache *db = NULL;
+ int indexmask, syntaxmask;
+ char * at_cn;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+
+ bdb2i_attr_masks( be->be_private, type, &indexmask, &syntaxmask );
+
+ attr_normalize( type );
+ at_cn = at_canonical_name( type );
+
+ if ( (db = bdb2i_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_NEWDB ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "<= index_read NULL (could not open %s%s)\n", at_cn,
+ BDB2_SUFFIX, 0 );
+ return 0;
+ }
+
+ bdb2i_cache_close( be, db );
+
+ return indexmask != 0;
+}
+
+int bdb2_tool_index_change(
+ BackendDB *be,
+ char* type,
+ struct berval **bv,
+ ID id,
+ int op )
+{
+ assert( slapMode & SLAP_TOOL_MODE );
+
+ bdb2i_index_add_values( be,
+ type, bv, id );
+
+ return 0;
+}
+
+int bdb2_tool_sync( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+
+ if ( li->li_nextid != NOID ) {
+ bdb2i_next_id_save( be );
+ }
+
+ return 0;
+}
--- /dev/null
+/* txn.c - TP support functions of the bdb2 backend */
+
+#include "portable.h"
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include "txn.h"
+
+/* default DB files */
+char *bdb2i_fixed_filenames[] = {
+ "id2entry",
+ "dn2id",
+ "objectclass",
+ NULL
+};
+
+
+int
+bdb2i_txn_head_init( BDB2_TXN_HEAD *head )
+{
+ int dbFile;
+ BDB2_TXN_FILES **fileNodeH;
+
+ /* for each fixed DB file allocate a file descriptor node and
+ initialize the file's name */
+ fileNodeH = &head->dbFiles;
+
+ for ( dbFile = 0; bdb2i_fixed_filenames[dbFile] != NULL; dbFile++ ) {
+ char fileName[MAXPATHLEN];
+
+ *fileNodeH = (BDB2_TXN_FILES *) ch_calloc( 1, sizeof( BDB2_TXN_FILES ));
+
+ if ( *fileNodeH == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "bdb2i_txn_head_init(): out of memory!\n",
+ 0, 0, 0 );
+ return( 1 );
+ }
+
+ sprintf( fileName, "%s" BDB2_SUFFIX, bdb2i_fixed_filenames[dbFile] );
+ (*fileNodeH)->dbc_name = ch_strdup( fileName );
+
+ fileNodeH = &(*fileNodeH)->next;
+
+ }
+
+ /* set defaults for checkpointing */
+ head->txn_log = BDB2_TXN_CHKP_MAX_LOG;
+ head->txn_time = BDB2_TXN_CHKP_MAX_TIME;
+
+ /* initialize the txn_dirty_mutex */
+ ldap_pvt_thread_mutex_init( &txn_dirty_mutex );
+
+ return 0;
+}
+
+
+static void
+bdb2i_init_db_file_cache( struct ldbminfo *li, BDB2_TXN_FILES *fileinfo )
+{
+ struct stat st;
+ char buf[MAXPATHLEN];
+
+ fileinfo->dbc_refcnt = 1;
+
+ sprintf( buf, "%s" LDAP_DIRSEP "%s",
+ li->li_directory, fileinfo->dbc_name );
+
+ if ( stat( buf, &st ) == 0 ) {
+ fileinfo->dbc_blksize = st.st_blksize;
+ } else {
+ fileinfo->dbc_blksize = DEFAULT_BLOCKSIZE;
+ }
+
+ fileinfo->dbc_maxids = ( fileinfo->dbc_blksize / sizeof( ID )) -
+ ID_BLOCK_IDS_OFFSET;
+ fileinfo->dbc_maxindirect = ( SLAPD_LDBM_MIN_MAXIDS /
+ fileinfo->dbc_maxids ) + 1;
+
+}
+
+
+/* create a DB file cache entry for a specified index attribute
+ (if not already done); the function is called during config
+ file read for all index'ed attributes; if "default" index with
+ a non-none selection is given, this is remembered for run-time
+ extension of the list of index files; the function is also
+ called before add or modify operations to check for putative
+ new "default" index files; at that time, files are also opened
+*/
+void
+bdb2i_txn_attr_config(
+ struct ldbminfo *li,
+ char *attr,
+ int open )
+{
+ BDB2_TXN_HEAD *head = &li->li_txn_head;
+
+ /* the "attribute" 'default' is special */
+ if ( strcasecmp( attr, "default" )) {
+
+ /* create a new index file node, if the index is not known already */
+ BDB2_TXN_FILES **fileNodeH;
+ char fileName[MAXPATHLEN];
+
+ sprintf( fileName, "%s%s", attr, BDB2_SUFFIX );
+
+ /* search for the end of the list or a node describing
+ the current attribute */
+ for ( fileNodeH = &head->dbFiles;
+ ( *fileNodeH && strcasecmp( (*fileNodeH)->dbc_name, fileName ));
+ fileNodeH = &(*fileNodeH)->next ) {
+
+ }
+
+ /* unless we have that attribute already... */
+ if ( *fileNodeH == NULL ) {
+ BDB2_TXN_FILES *p;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb2i_txn_attr_config(): adding node for \"%s\"\n",
+ fileName, 0, 0 );
+
+ /* if we're out of memory, we have to see, how to exit... */
+ if ( ( *fileNodeH = p = (BDB2_TXN_FILES *)
+ ch_calloc( 1, sizeof( BDB2_TXN_FILES )) ) == NULL ) {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_txn_attr_config(): out of memory -- FATAL.\n",
+ 0, 0, 0 );
+
+ /* during configuration (no files are opened)
+ we can just exit, otherwise we kill ourself and
+ hope to shutdown cleanly... */
+ if ( open ) {
+ pthread_kill( pthread_self(), LDAP_SIGUSR1 );
+ } else {
+ exit( EXIT_FAILURE );
+ }
+ }
+
+ p->dbc_name = ch_strdup( fileName );
+
+ /* if requested for, we have to open the DB file */
+ /* BUT NOT "objectclass", 'cause that's a default index ! */
+ if ( open && strcasecmp( fileName, "objectclass" )) {
+
+ /* re-use filename to get the complete path */
+ sprintf( fileName, "%s" LDAP_DIRSEP "%s",
+ li->li_directory, p->dbc_name );
+
+ /* since we have an mpool, we should not define a cache size */
+ p->dbc_db = bdb2i_db_open( fileName, DB_TYPE,
+ LDBM_WRCREAT, li->li_mode, 0 );
+
+ /* if the files could not be opened, something is wrong;
+ complain */
+ if ( p->dbc_db == NULL ) {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n",
+ p->dbc_name, 0, 0 );
+ pthread_kill( pthread_self(), LDAP_SIGUSR1 );
+
+ }
+
+ bdb2i_init_db_file_cache( li, p );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb2i_txn_attr_config(): NEW INDEX FILE \"%s\"\n",
+ p->dbc_name, 0, 0 );
+
+ }
+ }
+
+ } else { /* it is "attribute" 'default' */
+
+ head->withDefIDX = BDB2_WITH_DEF_IDX;
+
+ }
+}
+
+
+/* open the NEXTID file for read/write; if it does not exist,
+ create it (access to the file must be preceeded by a rewind)
+*/
+static int
+bdb2i_open_nextid( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ BDB2_TXN_HEAD *head = &li->li_txn_head;
+ LDBM db = NULL;
+ DB_INFO dbinfo;
+ char fileName[MAXPATHLEN];
+
+ sprintf( fileName, "%s" LDAP_DIRSEP "%s",
+ li->li_directory, NEXTID_NAME );
+
+ /* try to open the file for read and write */
+ memset( &dbinfo, 0, sizeof( dbinfo ));
+ dbinfo.db_pagesize = DEFAULT_DB_PAGE_SIZE;
+ dbinfo.db_malloc = ldbm_malloc;
+
+ (void) db_open( fileName, DB_RECNO, DB_CREATE | DB_THREAD,
+ li->li_mode, &bdb2i_dbEnv, &dbinfo, &db );
+
+ if ( db == NULL ) {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_open_nextid: could not open \"%s\"\n",
+ NEXTID_NAME, 0, 0 );
+ return( -1 );
+
+ }
+
+ /* the file is open for read/write */
+ head->nextidFile = db;
+
+ return( 0 );
+}
+
+
+/* open all DB during startup of the backend (necessary due to TP)
+ additional files may be opened during slapd life-time due to
+ default indexes (must be configured in slapd.conf;
+ see bdb2i_txn_attr_config)
+ also, set the counter and timer for TP checkpointing
+*/
+int
+bdb2i_txn_open_files( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ BDB2_TXN_HEAD *head = &li->li_txn_head;
+ BDB2_TXN_FILES *dbFile;
+ int rc;
+
+ for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
+ char fileName[MAXPATHLEN];
+
+ sprintf( fileName, "%s" LDAP_DIRSEP "%s",
+ li->li_directory, dbFile->dbc_name );
+
+ /* since we have an mpool, we should not define a cache size */
+ dbFile->dbc_db = bdb2i_db_open( fileName, DB_TYPE,
+ LDBM_WRCREAT, li->li_mode, 0 );
+
+ /* if the files could not be opened, something is wrong; complain */
+ if ( dbFile->dbc_db == NULL ) {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n",
+ dbFile->dbc_name, 0, 0 );
+ return( -1 );
+
+ }
+
+ /* initialize the file info */
+ bdb2i_init_db_file_cache( li, dbFile );
+
+ Debug( LDAP_DEBUG_TRACE, "bdb2i_txn_open_files(): OPEN INDEX \"%s\"\n",
+ dbFile->dbc_name, 0, 0 );
+
+ }
+
+ rc = bdb2i_open_nextid( be );
+
+ txn_max_pending_log = head->txn_log;
+ txn_max_pending_time = head->txn_time;
+
+ return rc;
+}
+
+
+/* close all DB files during shutdown of the backend */
+void
+bdb2i_txn_close_files( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ BDB2_TXN_HEAD *head = &li->li_txn_head;
+ BDB2_TXN_FILES *dbFile;
+
+ for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
+
+ ldbm_close( dbFile->dbc_db );
+
+ }
+
+ if ( head->nextidFile )
+ ldbm_close( head->nextidFile );
+
+}
+
+
+/* get the db_cache structure associated with a specified
+ DB file (replaces the on-the-fly opening of files in cache_open()
+*/
+BDB2_TXN_FILES *
+bdb2i_get_db_file_cache( struct ldbminfo *li, char *name )
+{
+ BDB2_TXN_HEAD *head = &li->li_txn_head;
+ BDB2_TXN_FILES *dbFile;
+ int dbFileNum;
+
+ Debug( LDAP_DEBUG_TRACE, "bdb2i_get_db_file_cache(): looking for file %s\n",
+ name, 0, 0 );
+
+ for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
+
+ /* we've got it */
+ if ( !strcasecmp( dbFile->dbc_name, name )) return( dbFile );
+
+ }
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_get_db_file_cache(): UPS, could't find \"%s\" \n", name, 0, 0 );
+
+ /* ups, we couldn't find the file */
+ return( NULL );
+
+}
+
+
+/* check for new attribute indexes, that might have been created
+ during former runs of slapd */
+/* this is called during startup of the slapd server */
+int
+bdb2i_check_additional_attr_index( struct ldbminfo *li )
+{
+ DIR *datadir;
+ struct dirent *file;
+
+ if ( ( datadir = opendir( li->li_directory ) ) == NULL ) {
+ int err = errno;
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_check_additional_attr_index(): ERROR while opening datadir: %s\n",
+ strerror( err ), 0, 0 );
+ return( 1 );
+
+ }
+
+ for ( file = readdir( datadir ); file; file = readdir( datadir )) {
+ char filename[MAXPATHLEN];
+ int namelen;
+
+ strcpy( filename, file->d_name );
+ namelen = strlen( filename );
+
+ if ( namelen > strlen( BDB2_SUFFIX )) {
+
+ if ( !strcasecmp( filename + namelen - strlen( BDB2_SUFFIX ),
+ BDB2_SUFFIX )) {
+
+ *(filename + namelen - strlen( BDB2_SUFFIX )) = '\0';
+ bdb2i_txn_attr_config( li, filename, 0 );
+
+ Debug( LDAP_DEBUG_TRACE, "INDEX FILE: %s\n", filename, 0, 0 );
+
+ }
+
+ }
+
+ }
+
+ closedir( datadir );
+
+ return 0;
+}
+
+
+/* check for the addition of new attribute indexes during add */
+/* this is called after startup of the slapd server */
+/* DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US
+ FROM ADDING ATTRIBUTES LATER ON */
+void
+bdb2i_check_default_attr_index_add( struct ldbminfo *li, Entry *e )
+{
+ BDB2_TXN_HEAD *head = &li->li_txn_head;
+
+ if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) {
+ Attribute *ap;
+
+ for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
+ if ( strcasecmp( ap->a_type, "objectclass" ))
+ bdb2i_txn_attr_config( li, ap->a_type, 1 );
+ }
+ }
+}
+
+
+/* check for the addition of new attribute indexes during modify */
+/* this is called after startup of the slapd server */
+/* DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US
+ FROM ADDING ATTRIBUTES LATER ON */
+void
+bdb2i_check_default_attr_index_mod( struct ldbminfo *li, LDAPModList *modlist )
+{
+ BDB2_TXN_HEAD *head = &li->li_txn_head;
+
+ if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) {
+ LDAPModList *ml;
+ char *default_attrs[] = { "modifytimestamp", "modifiersname", NULL };
+ int attr;
+
+ for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
+ LDAPMod *mod = &ml->ml_mod;
+
+ if (( mod->mod_op & ~LDAP_MOD_BVALUES ) == LDAP_MOD_ADD )
+ if ( strcasecmp( mod->mod_type, "objectclass" ))
+ bdb2i_txn_attr_config( li, mod->mod_type, 1 );
+ }
+
+ /* these attributes are default when modifying */
+ for ( attr = 0; default_attrs[attr]; attr++ ) {
+ bdb2i_txn_attr_config( li, default_attrs[attr], 1 );
+ }
+ }
+}
+
+
+/* get the next ID from the NEXTID file */
+ID
+bdb2i_get_nextid( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ BDB2_TXN_HEAD *head = &li->li_txn_head;
+ ID id;
+ Datum key;
+ Datum data;
+ db_recno_t rec = NEXTID_RECNO;
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ key.data = &rec;
+ key.size = sizeof( rec );
+
+ data = bdb2i_db_fetch( head->nextidFile, key );
+ if ( data.data == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "next_id_read: could not get nextid from \"%s\"\n",
+ NEXTID_NAME, 0, 0 );
+ return NOID;
+ }
+
+ id = atol( data.data );
+ ldbm_datum_free( head->nextidFile, data );
+
+ if ( id < 1 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "next_id_read %ld: return non-positive integer\n",
+ id, 0, 0 );
+ return NOID;
+ }
+
+ return( id );
+}
+
+
+int
+bdb2i_put_nextid( BackendDB *be, ID id )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ BDB2_TXN_HEAD *head = &li->li_txn_head;
+ int rc, flags;
+ Datum key;
+ Datum data;
+ db_recno_t rec = NEXTID_RECNO;
+ char buf[20];
+
+ sprintf( buf, "%ld\n", id );
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ key.data = &rec;
+ key.size = sizeof( rec );
+
+ data.data = &buf;
+ data.size = sizeof( buf );
+
+ flags = LDBM_REPLACE;
+ if ( li->li_dbcachewsync ) flags |= LDBM_SYNC;
+
+ if (( rc = bdb2i_db_store( head->nextidFile, key, data, flags )) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "next_id_write(%ld): store failed (%d)\n",
+ id, rc, 0 );
+ return( -1 );
+ }
+
+ return( rc );
+}
+
+
+/* BDB2 backend-private functions of libldbm */
+LDBM
+bdb2i_db_open(
+ char *name,
+ int type,
+ int rw,
+ int mode,
+ int dbcachesize )
+{
+ LDBM ret = NULL;
+ DB_INFO dbinfo;
+
+ memset( &dbinfo, 0, sizeof( dbinfo ));
+ if ( bdb2i_dbEnv.mp_info == NULL )
+ dbinfo.db_cachesize = dbcachesize;
+ dbinfo.db_pagesize = DEFAULT_DB_PAGE_SIZE;
+ dbinfo.db_malloc = ldbm_malloc;
+
+ (void) db_open( name, type, rw, mode, &bdb2i_dbEnv, &dbinfo, &ret );
+
+ return( ret );
+}
+
+
+int
+bdb2i_db_store( LDBM ldbm, Datum key, Datum data, int flags )
+{
+ int rc;
+
+ rc = (*ldbm->put)( ldbm, txnid, &key, &data, flags & ~LDBM_SYNC );
+ rc = (-1 ) * rc;
+
+ if ( txnid != NULL ) {
+
+ /* if the store was OK, set the dirty flag,
+ otherwise set the abort flag */
+ if ( rc == 0 ) {
+
+ txn_dirty = 1;
+
+ } else {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_db_store: transaction failed: aborted.\n",
+ 0, 0, 0 );
+ txn_do_abort = 1;
+
+ }
+ }
+
+ return( rc );
+}
+
+
+int
+bdb2i_db_delete( LDBM ldbm, Datum key )
+{
+ int rc;
+
+ rc = (*ldbm->del)( ldbm, txnid, &key, 0 );
+ rc = (-1 ) * rc;
+
+ if ( txnid != NULL ) {
+
+ /* if the delete was OK, set the dirty flag,
+ otherwise set the abort flag */
+ if ( rc == 0 ) {
+
+ txn_dirty = 1;
+
+ } else {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_db_delete: transaction failed: aborted.\n",
+ 0, 0, 0 );
+ txn_do_abort = 1;
+
+ }
+ }
+
+ return( rc );
+}
+
+
+Datum
+bdb2i_db_fetch( LDBM ldbm, Datum key )
+{
+ Datum data;
+ int rc;
+
+ ldbm_datum_init( data );
+ data.flags = DB_DBT_MALLOC;
+
+ if ( (rc = (*ldbm->get)( ldbm, txnid, &key, &data, 0 )) != 0 ) {
+ if (( txnid != NULL ) && ( rc != DB_NOTFOUND )) {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_db_fetch: transaction failed: aborted.\n",
+ 0, 0, 0 );
+ txn_do_abort = 1;
+
+ }
+ if ( data.dptr ) free( data.dptr );
+ data.dptr = NULL;
+ data.dsize = 0;
+ }
+
+ return( data );
+}
+
+
+Datum
+bdb2i_db_firstkey( LDBM ldbm, DBC **dbch )
+{
+ Datum key, data;
+ int rc;
+ DBC *dbci;
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ key.flags = data.flags = DB_DBT_MALLOC;
+
+#if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
+ DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
+
+ if ( (*ldbm->cursor)( ldbm, txnid, &dbci ))
+
+#else
+
+ if ( (*ldbm->cursor)( ldbm, txnid, &dbci, 0 ))
+
+#endif
+ {
+ if ( txnid != NULL ) {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_db_firstkey: transaction failed: aborted.\n",
+ 0, 0, 0 );
+ txn_do_abort = 1;
+
+ }
+ key.flags = 0;
+ return( key );
+ } else {
+ *dbch = dbci;
+ if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
+ ldbm_datum_free( ldbm, data );
+ } else {
+ if ( txnid != NULL ) {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_db_firstkey: transaction failed: aborted.\n",
+ 0, 0, 0 );
+ txn_do_abort = 1;
+
+ }
+ ldbm_datum_free( ldbm, key );
+ key.flags = 0;
+ key.dptr = NULL;
+ key.dsize = 0;
+ }
+ }
+
+ return( key );
+}
+
+
+Datum
+bdb2i_db_nextkey( LDBM ldbm, Datum key, DBC *dbcp )
+{
+ Datum data;
+ int rc;
+
+ ldbm_datum_init( data );
+ ldbm_datum_free( ldbm, key );
+ key.flags = data.flags = DB_DBT_MALLOC;
+
+ if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
+ ldbm_datum_free( ldbm, data );
+ } else {
+ if ( txnid != NULL ) {
+
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_db_nextkey: transaction failed: aborted.\n",
+ 0, 0, 0 );
+ txn_do_abort = 1;
+
+ }
+ key.flags = 0;
+ key.dptr = NULL;
+ key.dsize = 0;
+ }
+
+ return( key );
+}
+
+
+/* Transaction control of write access */
+/* Since these functions are only used by one writer at a time,
+ we do not have any concurrency (locking) problem */
+
+/* initialize a new transaction */
+int
+bdb2i_start_transction( DB_TXNMGR *txmgr )
+{
+ int rc;
+
+ txnid = NULL;
+ txn_do_abort = 0;
+
+ if (( rc = txn_begin( txmgr, NULL, &txnid )) != 0 ) {
+ int err = errno;
+ Debug( LDAP_DEBUG_ANY, "bdb2i_start_transction failed: %d: errno=%s\n",
+ rc, strerror( err ), 0 );
+
+ if ( txnid != NULL )
+ (void) txn_abort( txnid );
+ return( -1 );
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb2i_start_transaction: transaction started.\n",
+ 0, 0, 0 );
+
+ return( 0 );
+}
+
+
+/* finish the transaction */
+int
+bdb2i_finish_transaction()
+{
+ int rc = 0;
+
+ /* if transaction was NOT selected, just return */
+ if ( txnid == NULL ) return( 0 );
+
+ /* if nothing was wrong so far, we can try to commit the transaction */
+ /* complain, if the commit fails */
+ if (( txn_do_abort == 0 ) && ( txn_commit( txnid )) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_finish_transaction: transaction commit failed: aborted.\n",
+ 0, 0, 0 );
+ txn_do_abort = 1;
+ }
+
+ /* if anything went wrong, we have to abort the transaction */
+ if ( txn_do_abort ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_finish_transaction: transaction aborted.\n",
+ 0, 0, 0 );
+ (void) txn_abort( txnid );
+ rc = -1;
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb2i_finish_transaction: transaction commited.\n",
+ 0, 0, 0 );
+ }
+
+ /* XXX do NOT free the txnid memory !!! */
+ txnid = NULL;
+ txn_do_abort = 0;
+
+ return( rc );
+}
+
+
+/* set a checkpoint
+ either forced (during shutdown) or when logsize or time are exceeded
+ (is called by reader and writer, so protect txn_dirty)
+*/
+int
+bdb2i_set_txn_checkpoint( DB_TXNMGR *txmgr, int forced )
+{
+ int rc = 0;
+
+ /* set dirty mutex */
+ ldap_pvt_thread_mutex_lock( &txn_dirty_mutex );
+
+ if ( txn_dirty ) {
+ int rc;
+ u_int32_t logsize;
+ u_int32_t mins;
+ time_t now;
+
+ logsize = forced ? (u_int32_t) 0 : txn_max_pending_log;
+ mins = forced ? (u_int32_t) 0 : txn_max_pending_time;
+
+ now = slap_get_time();
+
+ rc = txn_checkpoint( txmgr, logsize, mins );
+
+ /* if checkpointing was successful, reset txn_dirty */
+ if ( rc == 0 ) {
+ DB_TXN_STAT *statp = NULL;
+
+ /* check whether the checkpoint was actually written;
+ if so, unset the txn_dirty flag */
+ if (( rc = txn_stat( txmgr, &statp, ldbm_malloc )) == 0 ) {
+
+ if ( statp && ( statp->st_time_ckp >= now )) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb2i_set_txn_checkpoint succeded.\n",
+ 0, 0, 0 );
+ txn_dirty = 0;
+
+ }
+
+ if ( statp ) free( statp );
+
+ } else {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb2i_set_txn_checkpoint: txn_stat failed: %d\n",
+ rc, 0, 0 );
+ }
+ } else {
+ Debug( LDAP_DEBUG_ANY, "bdb2i_set_txn_checkpoint failed: %d\n",
+ rc, 0, 0 );
+ }
+ }
+
+ /* release dirty mutex */
+ ldap_pvt_thread_mutex_unlock( &txn_dirty_mutex );
+
+ return( rc );
+}
+
+
--- /dev/null
+/* txn.h - Header for TP support functions of the bdb2 backend */
+
+#ifndef _BDB2_TXN_H_
+#define _BDB2_TXN_H_
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include <ac/dirent.h>
+#include <ac/errno.h>
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#include "ldap_defaults.h"
+#include "slap.h"
+#include "back-bdb2.h"
+
+
+
+/* the DB environment for the backend */
+DB_ENV bdb2i_dbEnv;
+
+
+/* variables for transaction support */
+DB_TXN *txnid = NULL;
+int txn_do_abort = 0;
+
+u_int32_t txn_max_pending_log;
+u_int32_t txn_max_pending_time;
+int txn_dirty = 0;
+ldap_pvt_thread_mutex_t txn_dirty_mutex;
+
+/* defaults for checkpointing */
+#define BDB2_TXN_CHKP_MAX_LOG 2000 /* checkpoint every 2MB lock file
+ (approx. 20 ADD TXNs) */
+#define BDB2_TXN_CHKP_MAX_TIME 5 /* checkpoint after 5 minutes */
+
+
+/* the name of the file and the record number of the NEXTID datum */
+#define NEXTID_NAME "NEXTID"
+#define NEXTID_RECNO (db_recno_t) 1
+
+
+
+#endif /* _BDB2_TXN_H_ */
+
--- /dev/null
+SRCS = init.c config.c search.c bind.c unbind.c add.c compare.c \
+ delete.c modify.c modrdn.c
+OBJS = init.lo config.lo search.lo bind.lo unbind.lo add.lo compare.lo \
+ delete.lo modify.lo modrdn.lo
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-ldap"
+BUILD_MOD = @BUILD_LDAP@
+LINKAGE = @BUILD_LDAP_DYNAMIC@
+
+LIBBASE = back_ldap
+
+XINCPATH = -I.. -I$(srcdir)/..
+XDEFS = $(MODULES_CPPFLAGS)
+XLDFLAGS = $(MODULES_LDFLAGS)
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+ @touch $@
+
--- /dev/null
+/* init.c - initialize ldap backend */
+
+/*
+ * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
+ *
+ * Permission is granted to anyone to use this software for any purpose
+ * on any computer system, and to alter it and redistribute it, subject
+ * to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits should appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits should appear in the documentation.
+ *
+ * 4. This notice may not be removed or altered.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-ldap.h"
+
+#ifdef SLAPD_LDAP_DYNAMIC
+
+int back_ldap_LTX_init_module(int argc, char *argv[]) {
+ BackendInfo bi;
+
+ memset( &bi, 0, sizeof(bi) );
+ bi.bi_type = "ldap";
+ bi.bi_init = ldap_back_initialize;
+
+ backend_add(&bi);
+ return 0;
+}
+
+#endif /* SLAPD_LDAP_DYNAMIC */
+
+int
+ldap_back_initialize(
+ BackendInfo *bi
+)
+{
+ bi->bi_open = 0;
+ bi->bi_config = 0;
+ bi->bi_close = 0;
+ bi->bi_destroy = 0;
+
+ bi->bi_db_init = ldap_back_db_init;
+ bi->bi_db_config = ldap_back_db_config;
+ bi->bi_db_open = 0;
+ bi->bi_db_close = 0;
+ bi->bi_db_destroy = ldap_back_db_destroy;
+
+ bi->bi_op_bind = ldap_back_bind;
+ bi->bi_op_unbind = 0;
+ bi->bi_op_search = ldap_back_search;
+ bi->bi_op_compare = ldap_back_compare;
+ bi->bi_op_modify = ldap_back_modify;
+ bi->bi_op_modrdn = ldap_back_modrdn;
+ bi->bi_op_add = ldap_back_add;
+ bi->bi_op_delete = ldap_back_delete;
+ bi->bi_op_abandon = 0;
+
+ bi->bi_acl_group = 0;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = ldap_back_conn_destroy;
+
+ return 0;
+}
+
+int
+ldap_back_db_init(
+ Backend *be
+)
+{
+ struct ldapinfo *li;
+
+ li = (struct ldapinfo *) ch_calloc( 1, sizeof(struct ldapinfo) );
+ ldap_pvt_thread_mutex_init( &li->conn_mutex );
+
+ be->be_private = li;
+
+ return li == NULL;
+}
+
+int
+ldap_back_db_destroy(
+ Backend *be
+)
+{
+ struct ldapinfo *li;
+
+ if (be->be_private) {
+ li = (struct ldapinfo *)be->be_private;
+ if (li->host) {
+ free(li->host);
+ li->host = NULL;
+ }
+ ldap_pvt_thread_mutex_destroy( &li->conn_mutex );
+ }
+
+ free( be->be_private );
+ return 0;
+}
--- /dev/null
+SRCS = idl.c add.c search.c cache.c dbcache.c dn2id.c entry.c id2entry.c \
+ index.c id2children.c nextid.c abandon.c compare.c group.c \
+ modify.c modrdn.c delete.c init.c config.c bind.c attr.c \
+ filterindex.c unbind.c kerberos.c close.c alias.c tools.c
+OBJS = idl.lo add.lo search.lo cache.lo dbcache.lo dn2id.lo entry.lo id2entry.lo \
+ index.lo id2children.lo nextid.lo abandon.lo compare.lo group.lo \
+ modify.lo modrdn.lo delete.lo init.lo config.lo bind.lo attr.lo \
+ filterindex.lo unbind.lo kerberos.lo close.lo alias.lo tools.lo
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-ldbm"
+BUILD_MOD = @BUILD_LDBM@
+LINKAGE = @BUILD_LDBM_DYNAMIC@
+
+LIBBASE = back_ldbm
+
+XINCPATH = -I.. -I$(srcdir)/..
+XDEFS = $(MODULES_CPPFLAGS)
+XLDFLAGS = $(MODULES_LDFLAGS)
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+ @touch $@
+
/* abandon.c - ldbm backend abandon routine */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
+
+/*ARGSUSED*/
+void
ldbm_back_abandon()
{
}
/* add.c - ldap ldbm back-end add routine */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "back-ldbm.h"
-
-extern int global_schemacheck;
-extern char *dn_parent();
-extern char *dn_normalize();
-extern Entry *dn2entry();
+#include "proto-back-ldbm.h"
int
ldbm_back_add(
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
- char *dn = NULL, *pdn = NULL;
- Entry *p;
-
- dn = dn_normalize( strdup( e->e_dn ) );
- matched = NULL;
- if ( (p = dn2entry( be, dn, &matched )) != NULL ) {
- cache_return_entry( &li->li_cache, p );
+ char *pdn;
+ Entry *p = NULL;
+ int rootlock = 0;
+ int rc;
+
+ Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
+
+ /* nobody else can add until we lock our parent */
+ ldap_pvt_thread_mutex_lock(&li->li_add_mutex);
+
+ if ( ( dn2id( be, e->e_ndn ) ) != NOID ) {
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
entry_free( e );
- free( dn );
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
- if ( matched != NULL ) {
- free( matched );
- }
- /* XXX race condition here til we cache_add_entry_lock below XXX */
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
- Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n", 0, 0,
- 0 );
- entry_free( e );
- free( dn );
- send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
- "" );
- return( -1 );
- }
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
- /*
- * Try to add the entry to the cache, assign it a new dnid
- * and mark it locked. This should only fail if the entry
- * already exists.
- */
+ Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
+ 0, 0, 0 );
- e->e_id = next_id( be );
- if ( cache_add_entry_lock( &li->li_cache, e, ENTRY_STATE_CREATING )
- != 0 ) {
- Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
- 0 );
- next_id_return( be, e->e_id );
entry_free( e );
- free( dn );
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
* add the entry.
*/
- if ( (pdn = dn_parent( be, dn )) != NULL ) {
- /* no parent */
- matched = NULL;
- if ( (p = dn2entry( be, pdn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, "" );
+ pdn = dn_parent( be, e->e_ndn );
+
+ if( pdn != NULL && *pdn != '\0' ) {
+ Entry *matched = NULL;
+
+ assert( *pdn != '\0' );
+
+ /* get parent with writer lock */
+ if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
+ char *matched_dn;
+ struct berval **refs;
+
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
+
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+
+ } else {
+ matched_dn = NULL;
+ refs = default_referral;
}
- Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
- 0, 0 );
- goto error_return;
- }
- if ( matched != NULL ) {
- free( matched );
+
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+ 0, 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ entry_free( e );
+ free( pdn );
+ return -1;
}
- if ( ! access_allowed( be, conn, op, p, "children", NULL,
- op->o_dn, ACL_WRITE ) ) {
+ /* don't need the add lock anymore */
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
+
+ free(pdn);
+
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
- goto error_return;
+ NULL, NULL, NULL, NULL );
+
+
+ entry_free( e );
+ return -1;
}
- } else {
- if ( ! be_isroot( be, op->o_dn ) ) {
- Debug( LDAP_DEBUG_TRACE, "no parent & not root\n", 0,
+
+ if ( is_entry_alias( p ) ) {
+ /* parent is an alias, don't allow add */
+
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+
+ Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
0, 0 );
+
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+
+ if ( is_entry_referral( p ) ) {
+ /* parent is a referral, don't allow add */
+ char *matched_dn = ch_strdup( p->e_dn );
+ struct berval **refs = is_entry_referral( p )
+ ? get_entry_referrals( be, conn, op, p )
+ : NULL;
+
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+
+ Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
+ entry_free( e );
+ return -1;
+ }
+
+ } else {
+ if(pdn != NULL) {
+ assert( *pdn == '\0' );
+ free(pdn);
+ }
+
+ /* no parent, must be adding entry to root */
+ if ( !be_isroot( be, op->o_ndn ) && !be_issuffix( be, "" ) ) {
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
+
+ Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
+ pdn == NULL ? "suffix" : "entry at root",
+ 0, 0 );
+
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
- goto error_return;
+ NULL, NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
}
- p = NULL;
+
+ /*
+ * no parent, acquire the root write lock
+ * and release the add lock.
+ */
+ ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
+ rootlock = 1;
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
}
+ e->e_id = next_id( be );
+
/*
- * add it to the id2children index for the parent
+ * Try to add the entry to the cache, assign it a new dnid.
*/
+ rc = cache_add_entry_rw(&li->li_cache, e, CACHE_WRITE_LOCK);
- if ( id2children_add( be, p, e ) != 0 ) {
- Debug( LDAP_DEBUG_TRACE, "id2children_add failed\n", 0,
- 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "",
- "" );
- goto error_return;
+ if ( rc != 0 ) {
+ if( p != NULL) {
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rootlock ) {
+ /* release root lock */
+ ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
+ }
+
+ Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
+ 0 );
+
+ /* free the entry */
+ entry_free( e );
+
+ send_ldap_result( conn, op,
+ rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ return( -1 );
}
+ rc = -1;
+
/*
* Add the entry to the attribute indexes, then add it to
* the id2children index, dn2id index, and the id2entry index.
if ( index_add_entry( be, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "index_add_entry failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- goto error_return;
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ goto return_results;
}
/* dn2id index */
- if ( dn2id_add( be, dn, e->e_id ) != 0 ) {
+ if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- goto error_return;
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ goto return_results;
}
/* id2entry index */
if ( id2entry_add( be, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
0, 0 );
- (void) dn2id_delete( be, dn );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- goto error_return;
+ (void) dn2id_delete( be, e->e_ndn );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ goto return_results;
+ }
+
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 0;
+
+return_results:;
+ if (p != NULL) {
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rootlock ) {
+ /* release root lock */
+ ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
+ }
+
+ if ( rc ) {
+ /* free entry and writer lock */
+ cache_return_entry_w( &li->li_cache, e );
}
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
- if ( dn != NULL )
- free( dn );
- if ( pdn != NULL )
- free( pdn );
- cache_set_state( &li->li_cache, e, 0 );
- cache_return_entry( &li->li_cache, e );
- return( 0 );
-
-error_return:;
- if ( dn != NULL )
- free( dn );
- if ( pdn != NULL )
- free( pdn );
- next_id_return( be, e->e_id );
- cache_delete_entry( &li->li_cache, e );
- cache_return_entry( &li->li_cache, e );
-
- return( -1 );
+ return( rc );
}
/* attr.c - backend routines for dealing with attributes */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "back-ldbm.h"
-extern char **str2charray();
-
static int
ainfo_type_cmp(
char *type,
- struct attrinfo *a
+ AttrInfo *a
)
{
return( strcasecmp( type, a->ai_type ) );
static int
ainfo_cmp(
- struct attrinfo *a,
- struct attrinfo *b
+ AttrInfo *a,
+ AttrInfo *b
)
{
return( strcasecmp( a->ai_type, b->ai_type ) );
static int
ainfo_dup(
- struct attrinfo *a,
- struct attrinfo *b
+ AttrInfo *a,
+ AttrInfo *b
)
{
/*
int *syntaxmask
)
{
- struct attrinfo *a;
+ AttrInfo *a;
*indexmask = 0;
*syntaxmask = 0;
- if ( (a = (struct attrinfo *) avl_find( li->li_attrs, type,
- ainfo_type_cmp )) == NULL ) {
- if ( (a = (struct attrinfo *) avl_find( li->li_attrs, "default",
- ainfo_type_cmp )) == NULL ) {
+ if ( (a = (AttrInfo *) avl_find( li->li_attrs, type,
+ (AVL_CMP) ainfo_type_cmp )) == NULL ) {
+ if ( (a = (AttrInfo *) avl_find( li->li_attrs, "default",
+ (AVL_CMP) ainfo_type_cmp )) == NULL ) {
return;
}
}
{
int i, j;
char **attrs, **indexes;
- struct attrinfo *a;
+ AttrInfo *a;
attrs = str2charray( argv[0], "," );
if ( argc > 1 ) {
indexes = str2charray( argv[1], "," );
}
for ( i = 0; attrs[i] != NULL; i++ ) {
- a = (struct attrinfo *) ch_malloc( sizeof(struct attrinfo) );
- a->ai_type = strdup( attrs[i] );
+ a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
+ a->ai_type = ch_strdup( attrs[i] );
a->ai_syntaxmask = attr_syntax( a->ai_type );
if ( argc == 1 ) {
a->ai_indexmask = (INDEX_PRESENCE | INDEX_EQUALITY |
a->ai_indexmask |= INDEX_FROMINIT;
}
- switch (avl_insert( &li->li_attrs, a, ainfo_cmp, ainfo_dup )) {
+ switch (avl_insert( &li->li_attrs, (caddr_t) a,
+ (AVL_CMP) ainfo_cmp, (AVL_DUP) ainfo_dup ))
+ {
case 1: /* duplicate - updating init version */
free( a->ai_type );
free( (char *) a );
if ( argc > 1 )
charray_free( indexes );
}
+
+
+static void
+ainfo_free( void *attr )
+{
+ AttrInfo *ai = attr;
+ free( ai->ai_type );
+ free( ai );
+}
+
+void
+attr_index_destroy( Avlnode *tree )
+{
+ avl_free( tree, ainfo_free );
+}
+
/* back-ldbm.h - ldap ldbm back-end header file */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
#ifndef _BACK_LDBM_H_
#define _BACK_LDBM_H_
#include "ldbm.h"
+LDAP_BEGIN_DECL
+
#define DEFAULT_CACHE_SIZE 1000
-#define DEFAULT_DBCACHE_SIZE 100000
+
+#ifdef HAVE_BERKELEY_DB2
+# define DEFAULT_DBCACHE_SIZE (100 * DEFAULT_DB_PAGE_SIZE)
+#else
+# define DEFAULT_DBCACHE_SIZE 100000
+#endif
+
#define DEFAULT_DB_DIRECTORY "/usr/tmp"
#define DEFAULT_MODE 0600
#define SUBLEN 3
+#define DN_BASE_PREFIX '='
+#define DN_ONE_PREFIX '@'
+#define DN_SUBTREE_PREFIX '?'
+
+#define SLAPD_FILTER_DN_ONE ((ber_tag_t) -2)
+#define SLAPD_FILTER_DN_SUBTREE ((ber_tag_t) -3)
+
/*
- * there is a single index for each attribute. these prefixes insure
+ * there is a single index for each attribute. these prefixes ensure
* that there is no collision among keys.
*/
#define EQ_PREFIX '=' /* prefix for equality keys */
#define SUB_PREFIX '*' /* prefix for substring keys */
#define CONT_PREFIX '\\' /* prefix for continuation keys */
+/* allow 3 characters per byte + PREFIX + EOS */
+#define CONT_SIZE ( sizeof(long)*3 + 1 + 1 )
+
+#define UNKNOWN_PREFIX '?' /* prefix for unknown keys */
+
#define DEFAULT_BLOCKSIZE 8192
/*
* the list is terminated by an id of NOID.
* b_ids a list of the actual ids themselves
*/
-typedef struct block {
- ID b_nmax; /* max number of ids in this list */
-#define ALLIDSBLOCK 0 /* == 0 => this is an allid block */
- ID b_nids; /* current number of ids used */
-#define INDBLOCK 0 /* == 0 => this is an indirect blk */
- ID b_ids[1]; /* the ids - actually bigger */
-} Block, IDList;
-#define ALLIDS( idl ) ((idl)->b_nmax == ALLIDSBLOCK)
-#define INDIRECT_BLOCK( idl ) ((idl)->b_nids == INDBLOCK)
+typedef ID ID_BLOCK;
+
+#define ID_BLOCK_NMAX_OFFSET 0
+#define ID_BLOCK_NIDS_OFFSET 1
+#define ID_BLOCK_IDS_OFFSET 2
+
+/* all ID_BLOCK macros operate on a pointer to a ID_BLOCK */
+
+#define ID_BLOCK_NMAX(b) ((b)[ID_BLOCK_NMAX_OFFSET])
+#define ID_BLOCK_NIDS(b) ((b)[ID_BLOCK_NIDS_OFFSET])
+#define ID_BLOCK_ID(b, n) ((b)[ID_BLOCK_IDS_OFFSET+(n)])
+
+#define ID_BLOCK_NOID(b, n) (ID_BLOCK_ID((b),(n)) == NOID)
+
+#define ID_BLOCK_ALLIDS_VALUE 0
+#define ID_BLOCK_ALLIDS(b) (ID_BLOCK_NMAX(b) == ID_BLOCK_ALLIDS_VALUE)
+
+#define ID_BLOCK_INDIRECT_VALUE 0
+#define ID_BLOCK_INDIRECT(b) (ID_BLOCK_NIDS(b) == ID_BLOCK_INDIRECT_VALUE)
/* for the in-core cache of entries */
-struct cache {
+typedef struct ldbm_cache {
int c_maxsize;
int c_cursize;
Avlnode *c_dntree;
Avlnode *c_idtree;
Entry *c_lruhead; /* lru - add accessed entries here */
Entry *c_lrutail; /* lru - rem lru entries from here */
- pthread_mutex_t c_mutex;
-};
+ ldap_pvt_thread_mutex_t c_mutex;
+} Cache;
+
+#define CACHE_READ_LOCK 0
+#define CACHE_WRITE_LOCK 1
/* for the cache of open index files */
-struct dbcache {
- char *dbc_name;
+typedef struct ldbm_dbcache {
int dbc_refcnt;
- time_t dbc_lastref;
- pthread_mutex_t dbc_mutex;
- pthread_cond_t dbc_cv;
- int dbc_readers;
- long dbc_blksize;
int dbc_maxids;
int dbc_maxindirect;
- LDBM dbc_db;
-};
+ time_t dbc_lastref;
+ long dbc_blksize;
+ char *dbc_name;
+ LDBM dbc_db;
+} DBCache;
/* for the cache of attribute information (which are indexed, etc.) */
-struct attrinfo {
+typedef struct ldbm_attrinfo {
char *ai_type; /* type name (cn, sn, ...) */
int ai_indexmask; /* how the attr is indexed */
-#define INDEX_PRESENCE 0x01
-#define INDEX_EQUALITY 0x02
-#define INDEX_APPROX 0x04
-#define INDEX_SUB 0x08
-#define INDEX_UNKNOWN 0x10
-#define INDEX_FROMINIT 0x20
+#define INDEX_PRESENCE 0x0001
+#define INDEX_EQUALITY 0x0002
+#define INDEX_APPROX 0x0004
+#define INDEX_SUB 0x0008
+#define INDEX_UNKNOWN 0x0010
+#define INDEX_FROMINIT 0x1000
int ai_syntaxmask; /* what kind of syntax */
/* ...from slap.h...
#define SYNTAX_CIS 0x01
#define SYNTAX_BIN 0x04
... etc. ...
*/
-};
+} AttrInfo;
-#define MAXDBCACHE 10
+#define MAXDBCACHE 16
struct ldbminfo {
ID li_nextid;
- pthread_mutex_t li_nextid_mutex;
+ ldap_pvt_thread_mutex_t li_nextid_mutex;
+ ldap_pvt_thread_mutex_t li_root_mutex;
+ ldap_pvt_thread_mutex_t li_add_mutex;
int li_mode;
char *li_directory;
- struct cache li_cache;
+ Cache li_cache;
Avlnode *li_attrs;
int li_dbcachesize;
- struct dbcache li_dbcache[MAXDBCACHE];
- pthread_mutex_t li_dbcache_mutex;
- pthread_cond_t li_dbcache_cv;
+ int li_dbcachewsync;
+ DBCache li_dbcache[MAXDBCACHE];
+ ldap_pvt_thread_mutex_t li_dbcache_mutex;
+ ldap_pvt_thread_cond_t li_dbcache_cv;
+#ifdef HAVE_BERKELEY_DB2
+ DB_ENV li_db_env;
+#endif
};
-#ifdef NEEDPROTOS
+LDAP_END_DECL
+
#include "proto-back-ldbm.h"
-#endif
#endif /* _back_ldbm_h_ */
--- /dev/null
+# Microsoft Developer Studio Project File - Name="backldbm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=backldbm - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "backldbm.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "backldbm.mak" CFG="backldbm - Win32 Single Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "backldbm - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "backldbm - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "backldbm - Win32 Single Debug" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE "backldbm - Win32 Single Release" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF "$(CFG)" == "backldbm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release"
+# PROP Intermediate_Dir "..\Release\backldbm"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "backldbm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug"
+# PROP Intermediate_Dir "..\Debug\backldbm"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\\" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "backldbm - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "backldbm"
+# PROP BASE Intermediate_Dir "backldbm"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\SDebug"
+# PROP Intermediate_Dir "..\SDebug\backldbm"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\\" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\\" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "backldbm - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "backldb0"
+# PROP BASE Intermediate_Dir "backldb0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\SRelease"
+# PROP Intermediate_Dir "..\SRelease\backldbm"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\\" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "backldbm - Win32 Release"
+# Name "backldbm - Win32 Debug"
+# Name "backldbm - Win32 Single Debug"
+# Name "backldbm - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\abandon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\add.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\alias.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\attr.c
+# End Source File
+# Begin Source File
+
+SOURCE=".\back-ldbm.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\bind.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\close.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\compare.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\config.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbcache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dn2id.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\entry.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\external.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\filterindex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\group.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\id2children.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\id2entry.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\idl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\index.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\kerberos.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modify.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modrdn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\nextid.c
+# End Source File
+# Begin Source File
+
+SOURCE=".\proto-back-ldbm.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\search.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\startup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tools.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\unbind.c
+# End Source File
+# End Target
+# End Project
/* bind.c - ldbm backend bind and unbind routines */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/krb.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
#include "slap.h"
#include "back-ldbm.h"
-#ifdef KERBEROS
-#include "krb.h"
-#endif
+#include "proto-back-ldbm.h"
-extern Entry *dn2entry();
-extern Attribute *attr_find();
+#include <lutil.h>
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
extern int krbv4_ldap_auth();
#endif
+static int
+crypted_value_find(
+ struct berval **vals,
+ struct berval *v,
+ int syntax,
+ int normalize,
+ struct berval *cred
+)
+{
+ int i;
+ for ( i = 0; vals[i] != NULL; i++ ) {
+ if ( syntax != SYNTAX_BIN ) {
+ int result;
+
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_lock( &crypt_mutex );
+#endif
+
+ result = lutil_passwd(
+ (char*) cred->bv_val,
+ (char*) vals[i]->bv_val,
+ NULL );
+
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_unlock( &crypt_mutex );
+#endif
+
+ return result;
+
+ } else {
+ if ( value_cmp( vals[i], v, syntax, normalize ) == 0 ) {
+ return( 0 );
+ }
+ }
+ }
+
+ return( 1 );
+}
+
int
ldbm_back_bind(
Backend *be,
Operation *op,
char *dn,
int method,
- struct berval *cred
+ char *mech,
+ struct berval *cred,
+ char** edn
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
Entry *e;
Attribute *a;
int rc;
- char *matched = NULL;
-#ifdef KERBEROS
+ Entry *matched;
+#ifdef HAVE_KERBEROS
char krbname[MAX_K_NAME_SZ + 1];
AUTH_DAT ad;
#endif
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
+ Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_bind: dn: %s\n", dn, 0, 0);
+
+ *edn = NULL;
+
+ /* get entry with reader lock */
+ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
/* allow noauth binds */
- if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) {
- /*
- * bind successful, but return 1 so we don't
- * authorize based on noauth credentials
- */
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- rc = 1;
- } else if ( be_isroot_pw( be, dn, cred ) ) {
- /* front end will send result */
- rc = 0;
+ rc = 1;
+ if ( method == LDAP_AUTH_SIMPLE ) {
+ if( cred->bv_len == 0 ) {
+ /* SUCCESS */
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+
+ } else if ( be_isroot_pw( be, dn, cred ) ) {
+ *edn = ch_strdup( be_root_dn( be ) );
+ rc = 0; /* front end will send result */
+
+ } else {
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+ }
+
+ } else if ( method == LDAP_AUTH_SASL ) {
+ if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
+ /* insert DIGEST calls here */
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL, NULL );
+ }
+
} else {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, NULL );
- rc = 1;
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
}
+
if ( matched != NULL ) {
- free( matched );
+ ber_bvecfree( refs );
+ free( matched_dn );
}
return( rc );
}
+ *edn = ch_strdup( e->e_dn );
+
+ /* check for deleted */
+
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( is_entry_alias( e ) ) {
+ /* entry is an alias, don't allow bind */
+ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow bind */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ rc = 1;
+ goto return_results;
+ }
+
switch ( method ) {
case LDAP_AUTH_SIMPLE:
if ( cred->bv_len == 0 ) {
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- return( 1 );
- } else if ( be_isroot_pw( be, dn, cred ) ) {
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
+ }
+
+ /* check for root dn/passwd */
+ if ( be_isroot_pw( be, dn, cred ) ) {
/* front end will send result */
- return( 0 );
+ if(*edn != NULL) free( *edn );
+ *edn = ch_strdup( be_root_dn( be ) );
+ rc = 0;
+ goto return_results;
+ }
+
+ if ( ! access_allowed( be, conn, op, e,
+ "userpassword", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
}
if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
- if ( be_isroot_pw( be, dn, cred ) ) {
- /* front end will send result */
- return( 0 );
- }
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ NULL, NULL, NULL, NULL );
+
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
}
- if ( value_find( a->a_vals, cred, a->a_syntax, 0 ) != 0 ) {
- if ( be_isroot_pw( be, dn, cred ) ) {
- /* front end will send result */
- return( 0 );
- }
+ if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
+ {
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ NULL, NULL, NULL, NULL );
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
}
+
+ rc = 0;
break;
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
case LDAP_AUTH_KRBV41:
+ if ( ! access_allowed( be, conn, op, e,
+ "krbname", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
}
+
+ if ( ! access_allowed( be, conn, op, e,
+ "krbname", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
: "", ad.pinst, ad.prealm );
+
+
if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) {
/*
* no krbName values present: check against DN
*/
if ( strcasecmp( dn, krbname ) == 0 ) {
+ rc = 0;
break;
}
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+
} else { /* look for krbName match */
struct berval krbval;
krbval.bv_val = krbname;
krbval.bv_len = strlen( krbname );
- if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 )
- != 0 ) {
+ if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
send_ldap_result( conn, op,
- LDAP_INVALID_CREDENTIALS, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ LDAP_INVALID_CREDENTIALS,
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
}
}
+ rc = 0;
break;
case LDAP_AUTH_KRBV42:
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
#endif
+ case LDAP_AUTH_SASL:
+ /* insert SASL code here */
+
default:
send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
- NULL, "auth method not supported" );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ NULL, "auth method not supported", NULL, NULL );
+ rc = 1;
+ goto return_results;
}
- cache_return_entry( &li->li_cache, e );
+return_results:;
+ /* free entry and reader lock */
+ cache_return_entry_r( &li->li_cache, e );
- /* success: front end will send result */
- return( 0 );
+ /* front end with send result on success (rc==0) */
+ return( rc );
}
+
/* cache.c - routines to maintain an in-core cache of entries */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/errno.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
+
#include "back-ldbm.h"
-static int cache_delete_entry_internal();
+/* LDBM backend specific entry info -- visible only to the cache */
+typedef struct ldbm_entry_info {
+ ldap_pvt_thread_rdwr_t lei_rdwr; /* reader/writer lock */
+
+ /*
+ * remaining fields require backend cache lock to access
+ * These items are specific to the LDBM backend and should
+ * be hidden.
+ */
+ int lei_state; /* for the cache */
+#define CACHE_ENTRY_UNDEFINED 0
+#define CACHE_ENTRY_CREATING 1
+#define CACHE_ENTRY_READY 2
+#define CACHE_ENTRY_DELETED 3
+
+ int lei_refcnt; /* # threads ref'ing this entry */
+ Entry *lei_lrunext; /* for cache lru list */
+ Entry *lei_lruprev;
+} EntryInfo;
+#define LEI(e) ((EntryInfo *) ((e)->e_private))
+
+static int cache_delete_entry_internal(Cache *cache, Entry *e);
#ifdef LDAP_DEBUG
-static void lru_print();
+static void lru_print(Cache *cache);
#endif
-/*
- * the cache has three entry points (ways to find things):
- *
- * by entry e.g., if you already have an entry from the cache
- * and want to delete it. (really by entry ptr)
- * by dn e.g., when looking for the base object of a search
- * by id e.g., for search candidates
- *
- * these correspond to three different avl trees that are maintained.
- */
+static int
+cache_entry_rdwr_lock(Entry *e, int rw)
+{
+ Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%slock: ID: %ld\n",
+ rw ? "w" : "r", e->e_id, 0);
+
+ if (rw)
+ return ldap_pvt_thread_rdwr_wlock(&LEI(e)->lei_rdwr);
+ else
+ return ldap_pvt_thread_rdwr_rlock(&LEI(e)->lei_rdwr);
+}
static int
-cache_entry_cmp( Entry *e1, Entry *e2 )
+cache_entry_rdwr_trylock(Entry *e, int rw)
{
- return( e1 < e2 ? -1 : (e1 > e2 ? 1 : 0) );
+ Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%strylock: ID: %ld\n",
+ rw ? "w" : "r", e->e_id, 0);
+
+ if (rw)
+ return ldap_pvt_thread_rdwr_wtrylock(&LEI(e)->lei_rdwr);
+ else
+ return ldap_pvt_thread_rdwr_rtrylock(&LEI(e)->lei_rdwr);
}
static int
-cache_entrydn_cmp( Entry *e1, Entry *e2 )
+cache_entry_rdwr_unlock(Entry *e, int rw)
{
- return( strcasecmp( e1->e_dn, e2->e_dn ) );
+ Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%sunlock: ID: %ld\n",
+ rw ? "w" : "r", e->e_id, 0);
+
+ if (rw)
+ return ldap_pvt_thread_rdwr_wunlock(&LEI(e)->lei_rdwr);
+ else
+ return ldap_pvt_thread_rdwr_runlock(&LEI(e)->lei_rdwr);
}
static int
-cache_entryid_cmp( Entry *e1, Entry *e2 )
+cache_entry_rdwr_init(Entry *e)
{
- return( e1->e_id < e2->e_id ? -1 : (e1->e_id > e2->e_id ? 1 : 0) );
+ return ldap_pvt_thread_rdwr_init( &LEI(e)->lei_rdwr );
}
-void
-cache_set_state( struct cache *cache, Entry *e, int state )
+static int
+cache_entry_rdwr_destroy(Entry *e)
{
- /* set cache mutex */
- pthread_mutex_lock( &cache->c_mutex );
+ return ldap_pvt_thread_rdwr_destroy( &LEI(e)->lei_rdwr );
+}
- e->e_state = state;
+static int
+cache_entry_private_init( Entry*e )
+{
+ assert( e->e_private == NULL );
- /* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
+ if( e->e_private != NULL ) {
+ /* this should never happen */
+ return 1;
+ }
+
+ e->e_private = ch_calloc(1, sizeof(struct ldbm_entry_info));
+
+ if( cache_entry_rdwr_init( e ) != 0 ) {
+ free( LEI(e) );
+ e->e_private = NULL;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+cache_entry_private_destroy( Entry*e )
+{
+ assert( e->e_private );
+
+ cache_entry_rdwr_destroy( e );
+
+ free( e->e_private );
+ e->e_private = NULL;
+ return 0;
}
void
-cache_return_entry( struct cache *cache, Entry *e )
+cache_return_entry_rw( Cache *cache, Entry *e, int rw )
{
+ ID id;
+ int refcnt;
+
/* set cache mutex */
- pthread_mutex_lock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_lock( &cache->c_mutex );
- if ( --e->e_refcnt == 0 && e->e_state == ENTRY_STATE_DELETED ) {
- entry_free( e );
- }
+ assert( e->e_private );
- /* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
+ cache_entry_rdwr_unlock(e, rw);
+
+ id = e->e_id;
+ refcnt = --LEI(e)->lei_refcnt;
+
+ if ( LEI(e)->lei_state == CACHE_ENTRY_CREATING ) {
+ LEI(e)->lei_state = CACHE_ENTRY_READY;
+
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "====> cache_return_entry_%s( %ld ): created (%d)\n",
+ rw ? "w" : "r", id, refcnt );
+
+ } else if ( LEI(e)->lei_state == CACHE_ENTRY_DELETED ) {
+ if( refcnt > 0 ) {
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "====> cache_return_entry_%s( %ld ): delete pending (%d)\n",
+ rw ? "w" : "r", id, refcnt );
+
+ } else {
+ cache_entry_private_destroy( e );
+ entry_free( e );
+
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "====> cache_return_entry_%s( %ld ): deleted (%d)\n",
+ rw ? "w" : "r", id, refcnt );
+ }
+
+ } else {
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "====> cache_return_entry_%s( %ld ): returned (%d)\n",
+ rw ? "w" : "r", id, refcnt);
+ }
}
-#define LRU_DELETE( cache, e ) { \
- if ( e->e_lruprev != NULL ) { \
- e->e_lruprev->e_lrunext = e->e_lrunext; \
+#define LRU_DELETE( cache, e ) do { \
+ if ( LEI(e)->lei_lruprev != NULL ) { \
+ LEI(LEI(e)->lei_lruprev)->lei_lrunext = LEI(e)->lei_lrunext; \
} else { \
- cache->c_lruhead = e->e_lrunext; \
+ (cache)->c_lruhead = LEI(e)->lei_lrunext; \
} \
- if ( e->e_lrunext != NULL ) { \
- e->e_lrunext->e_lruprev = e->e_lruprev; \
+ if ( LEI(e)->lei_lrunext != NULL ) { \
+ LEI(LEI(e)->lei_lrunext)->lei_lruprev = LEI(e)->lei_lruprev; \
} else { \
- cache->c_lrutail = e->e_lruprev; \
+ (cache)->c_lrutail = LEI(e)->lei_lruprev; \
} \
-}
+} while(0)
-#define LRU_ADD( cache, e ) { \
- e->e_lrunext = cache->c_lruhead; \
- if ( e->e_lrunext != NULL ) { \
- e->e_lrunext->e_lruprev = e; \
+#define LRU_ADD( cache, e ) do { \
+ LEI(e)->lei_lrunext = (cache)->c_lruhead; \
+ if ( LEI(e)->lei_lrunext != NULL ) { \
+ LEI(LEI(e)->lei_lrunext)->lei_lruprev = (e); \
} \
- cache->c_lruhead = e; \
- e->e_lruprev = NULL; \
- if ( cache->c_lrutail == NULL ) { \
- cache->c_lrutail = e; \
+ (cache)->c_lruhead = (e); \
+ LEI(e)->lei_lruprev = NULL; \
+ if ( (cache)->c_lrutail == NULL ) { \
+ (cache)->c_lrutail = (e); \
} \
-}
+} while(0)
/*
- * cache_create_entry_lock - create an entry in the cache, and lock it.
+ * cache_add_entry_rw - create and lock an entry in the cache
* returns: 0 entry has been created and locked
* 1 entry already existed
* -1 something bad happened
*/
int
-cache_add_entry_lock(
- struct cache *cache,
+cache_add_entry_rw(
+ Cache *cache,
Entry *e,
- int state
+ int rw
)
{
int i, rc;
Entry *ee;
/* set cache mutex */
- pthread_mutex_lock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_lock( &cache->c_mutex );
- if ( avl_insert( &cache->c_dntree, e, cache_entrydn_cmp, avl_dup_error )
- != 0 ) {
- Debug( LDAP_DEBUG_TRACE,
- "entry %20s id %d already in dn cache\n", e->e_dn,
- e->e_id, 0 );
+ assert( e->e_private == NULL );
+ if( cache_entry_private_init(e) != 0 ) {
/* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug( LDAP_DEBUG_ANY,
+ "====> cache_add_entry( %ld ): \"%s\": private init failed!\n",
+ e->e_id, e->e_dn, 0 );
+
+ return( -1 );
+ }
+
+ if ( avl_insert( &cache->c_dntree, (caddr_t) e,
+ (AVL_CMP) entry_dn_cmp, avl_dup_error ) != 0 )
+ {
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "====> cache_add_entry( %ld ): \"%s\": already in dn cache\n",
+ e->e_id, e->e_dn, 0 );
+
+ cache_entry_private_destroy(e);
+
return( 1 );
}
/* id tree */
- if ( avl_insert( &cache->c_idtree, e, cache_entryid_cmp, avl_dup_error )
- != 0 ) {
- Debug( LDAP_DEBUG_ANY, "entry %20s id %d already in id cache\n",
- e->e_dn, e->e_id, 0 );
+ if ( avl_insert( &cache->c_idtree, (caddr_t) e,
+ (AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 )
+ {
+ Debug( LDAP_DEBUG_ANY,
+ "====> cache_add_entry( %ld ): \"%s\": already in id cache\n",
+ e->e_id, e->e_dn, 0 );
+
/* delete from dn tree inserted above */
- if ( avl_delete( &cache->c_dntree, e, cache_entrydn_cmp )
- == NULL ) {
- Debug( LDAP_DEBUG_ANY, "can't delete from dn cache\n",
+ if ( avl_delete( &cache->c_dntree, (caddr_t) e,
+ (AVL_CMP) entry_dn_cmp ) == NULL )
+ {
+ Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
0, 0, 0 );
}
+ cache_entry_private_destroy(e);
+
/* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
return( -1 );
}
- e->e_state = state;
- e->e_refcnt = 1;
+ cache_entry_rdwr_lock( e, rw );
+
+ /* put the entry into 'CREATING' state */
+ /* will be marked after when entry is returned */
+ LEI(e)->lei_state = CACHE_ENTRY_CREATING;
+ LEI(e)->lei_refcnt = 1;
/* lru */
LRU_ADD( cache, e );
* first 10 on the tail of the list.
*/
i = 0;
- while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt
- != 0 && i < 10 ) {
+ while ( cache->c_lrutail != NULL &&
+ LEI(cache->c_lrutail)->lei_refcnt != 0 &&
+ i < 10 )
+ {
/* move this in-use entry to the front of the q */
ee = cache->c_lrutail;
LRU_DELETE( cache, ee );
* found at least one to delete - try to get back under
* the max cache size.
*/
- while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt
- == 0 && cache->c_cursize > cache->c_maxsize ) {
+ while ( cache->c_lrutail != NULL &&
+ LEI(cache->c_lrutail)->lei_refcnt == 0 &&
+ cache->c_cursize > cache->c_maxsize )
+ {
e = cache->c_lrutail;
/* delete from cache and lru q */
+ /* XXX do we need rc ? */
rc = cache_delete_entry_internal( cache, e );
+ cache_entry_private_destroy( e );
+ entry_free( e );
+ }
+ }
+
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+ return( 0 );
+}
+
+/*
+ * cache_update_entry - update a LOCKED entry which has been deleted.
+ * returns: 0 entry has been created and locked
+ * 1 entry already existed
+ * -1 something bad happened
+ */
+int
+cache_update_entry(
+ Cache *cache,
+ Entry *e
+)
+{
+ int i, rc;
+ Entry *ee;
+
+ /* set cache mutex */
+ ldap_pvt_thread_mutex_lock( &cache->c_mutex );
+ assert( e->e_private );
+
+ if ( avl_insert( &cache->c_dntree, (caddr_t) e,
+ (AVL_CMP) entry_dn_cmp, avl_dup_error ) != 0 )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "====> cache_update_entry( %ld ): \"%s\": already in dn cache\n",
+ e->e_id, e->e_dn, 0 );
+
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+ return( 1 );
+ }
+
+ /* id tree */
+ if ( avl_insert( &cache->c_idtree, (caddr_t) e,
+ (AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 )
+ {
+ Debug( LDAP_DEBUG_ANY,
+ "====> cache_update_entry( %ld ): \"%s\": already in id cache\n",
+ e->e_id, e->e_dn, 0 );
+
+ /* delete from dn tree inserted above */
+ if ( avl_delete( &cache->c_dntree, (caddr_t) e,
+ (AVL_CMP) entry_dn_cmp ) == NULL )
+ {
+ Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
+ 0, 0, 0 );
+ }
+
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+ return( -1 );
+ }
+
+
+ /* put the entry into 'CREATING' state */
+ /* will be marked after when entry is returned */
+ LEI(e)->lei_state = CACHE_ENTRY_CREATING;
+
+ /* lru */
+ LRU_ADD( cache, e );
+ if ( ++cache->c_cursize > cache->c_maxsize ) {
+ /*
+ * find the lru entry not currently in use and delete it.
+ * in case a lot of entries are in use, only look at the
+ * first 10 on the tail of the list.
+ */
+ i = 0;
+ while ( cache->c_lrutail != NULL &&
+ LEI(cache->c_lrutail)->lei_refcnt != 0 &&
+ i < 10 )
+ {
+ /* move this in-use entry to the front of the q */
+ ee = cache->c_lrutail;
+ LRU_DELETE( cache, ee );
+ LRU_ADD( cache, ee );
+ i++;
+ }
+
+ /*
+ * found at least one to delete - try to get back under
+ * the max cache size.
+ */
+ while ( cache->c_lrutail != NULL &&
+ LEI(cache->c_lrutail)->lei_refcnt == 0 &&
+ cache->c_cursize > cache->c_maxsize )
+ {
+ e = cache->c_lrutail;
+
+ /* delete from cache and lru q */
+ /* XXX do we need rc ? */
+ rc = cache_delete_entry_internal( cache, e );
+ cache_entry_private_destroy( e );
entry_free( e );
}
}
/* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
return( 0 );
}
/*
- * cache_find_entry_dn - find an entry in the cache, given dn
+ * cache_find_entry_dn2id - find an entry in the cache, given dn
*/
-Entry *
-cache_find_entry_dn(
- struct cache *cache,
+ID
+cache_find_entry_dn2id(
+ Backend *be,
+ Cache *cache,
char *dn
)
{
Entry e, *ep;
+ ID id;
+ int count = 0;
+
+ e.e_dn = dn;
+ e.e_ndn = ch_strdup( dn );
+ (void) dn_normalize_case( e.e_ndn );
+try_again:
/* set cache mutex */
- pthread_mutex_lock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_lock( &cache->c_mutex );
+
+ if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e,
+ (AVL_CMP) entry_dn_cmp )) != NULL )
+ {
+ int state;
+ count++;
+
+ /*
+ * ep now points to an unlocked entry
+ * we do not need to lock the entry if we only
+ * check the state, refcnt, LRU, and id.
+ */
+
+ assert( ep->e_private );
+
+ /* save id */
+ id = ep->e_id;
+ state = LEI(ep)->lei_state;
- e.e_dn = dn;
- if ( (ep = (Entry *) avl_find( cache->c_dntree, &e, cache_entrydn_cmp ))
- != NULL ) {
/*
* entry is deleted or not fully created yet
*/
- if ( ep->e_state == ENTRY_STATE_DELETED ||
- ep->e_state == ENTRY_STATE_CREATING )
- {
+ if ( state != CACHE_ENTRY_READY ) {
+ assert(state != CACHE_ENTRY_UNDEFINED);
+
/* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
- return( NULL );
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug(LDAP_DEBUG_TRACE,
+ "====> cache_find_entry_dn2id(\"%s\"): %ld (not ready) %d\n",
+ dn, id, state);
+
+ ldap_pvt_thread_yield();
+ goto try_again;
}
- ep->e_refcnt++;
/* lru */
LRU_DELETE( cache, ep );
LRU_ADD( cache, ep );
+
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug(LDAP_DEBUG_TRACE,
+ "====> cache_find_entry_dn2id(\"%s\"): %ld (%d tries)\n",
+ dn, id, count);
+
+ } else {
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ id = NOID;
}
- /* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
+ free(e.e_ndn);
- return( ep );
+ return( id );
}
/*
Entry *
cache_find_entry_id(
- struct cache *cache,
- ID id
+ Cache *cache,
+ ID id,
+ int rw
)
{
Entry e;
Entry *ep;
+ int count = 0;
+ e.e_id = id;
+
+try_again:
/* set cache mutex */
- pthread_mutex_lock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_lock( &cache->c_mutex );
+
+ if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e,
+ (AVL_CMP) entry_id_cmp )) != NULL )
+ {
+ int state;
+ ID ep_id;
+
+ count++;
+
+ assert( ep->e_private );
+
+ ep_id = ep->e_id;
+ state = LEI(ep)->lei_state;
- e.e_id = id;
- if ( (ep = (Entry *) avl_find( cache->c_idtree, &e, cache_entryid_cmp ))
- != NULL ) {
/*
* entry is deleted or not fully created yet
*/
- if ( ep->e_state == ENTRY_STATE_DELETED ||
- ep->e_state == ENTRY_STATE_CREATING )
- {
+ if ( state != CACHE_ENTRY_READY ) {
+
+ assert(state != CACHE_ENTRY_UNDEFINED);
+
/* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
- return( NULL );
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug(LDAP_DEBUG_TRACE,
+ "====> cache_find_entry_id( %ld ): %ld (not ready) %d\n",
+ id, ep_id, state);
+
+ ldap_pvt_thread_yield();
+ goto try_again;
+ }
+
+ /* acquire reader lock */
+ if ( cache_entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) {
+ /* could not acquire entry lock...
+ * owner cannot free as we have the cache locked.
+ * so, unlock the cache, yield, and try again.
+ */
+
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug(LDAP_DEBUG_TRACE,
+ "====> cache_find_entry_id( %ld ): %ld (busy) %d\n",
+ id, ep_id, state);
+
+ ldap_pvt_thread_yield();
+ goto try_again;
}
- ep->e_refcnt++;
/* lru */
LRU_DELETE( cache, ep );
LRU_ADD( cache, ep );
+
+ LEI(ep)->lei_refcnt++;
+
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+
+ Debug(LDAP_DEBUG_TRACE,
+ "====> cache_find_entry_id( %ld ) \"%s\" (found) (%d tries)\n",
+ ep_id, ep->e_dn, count);
+
+ return( ep );
}
/* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
- return( ep );
+ return( NULL );
}
/*
*/
int
cache_delete_entry(
- struct cache *cache,
+ Cache *cache,
Entry *e
)
{
int rc;
/* set cache mutex */
- pthread_mutex_lock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_lock( &cache->c_mutex );
+
+ assert( e->e_private );
+
+ Debug( LDAP_DEBUG_TRACE, "====> cache_delete_entry( %ld )\n",
+ e->e_id, 0, 0 );
rc = cache_delete_entry_internal( cache, e );
/* free cache mutex */
- pthread_mutex_unlock( &cache->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
return( rc );
}
static int
cache_delete_entry_internal(
- struct cache *cache,
+ Cache *cache,
Entry *e
)
{
+ int rc = 0; /* return code */
+
/* dn tree */
- if ( avl_delete( &cache->c_dntree, e, cache_entrydn_cmp ) == NULL ) {
- return( -1 );
+ if ( avl_delete( &cache->c_dntree, (caddr_t) e, (AVL_CMP) entry_dn_cmp )
+ == NULL )
+ {
+ rc = -1;
}
/* id tree */
- if ( avl_delete( &cache->c_idtree, e, cache_entryid_cmp ) == NULL ) {
- return( -1 );
+ if ( avl_delete( &cache->c_idtree, (caddr_t) e, (AVL_CMP) entry_id_cmp )
+ == NULL )
+ {
+ rc = -1;
+ }
+
+ if (rc != 0) {
+ return rc;
}
/* lru */
/*
* flag entry to be freed later by a call to cache_return_entry()
*/
- e->e_state = ENTRY_STATE_DELETED;
+ LEI(e)->lei_state = CACHE_ENTRY_DELETED;
return( 0 );
}
+void
+cache_release_all( Cache *cache )
+{
+ Entry *e;
+ int rc;
+
+ /* set cache mutex */
+ ldap_pvt_thread_mutex_lock( &cache->c_mutex );
+
+ Debug( LDAP_DEBUG_TRACE, "====> cache_release_all\n", 0, 0, 0 );
+
+ while ( (e = cache->c_lrutail) != NULL && LEI(e)->lei_refcnt == 0 ) {
+ assert(!ldap_pvt_thread_rdwr_active(&LEI(e)->lei_rdwr));
+
+ /* delete from cache and lru q */
+ /* XXX do we need rc ? */
+ rc = cache_delete_entry_internal( cache, e );
+ cache_entry_private_destroy( e );
+ entry_free( e );
+ }
+
+ if ( cache->c_cursize ) {
+ Debug( LDAP_DEBUG_TRACE, "Entry-cache could not be emptied\n", 0, 0, 0 );
+ }
+
+ /* free cache mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
+}
+
#ifdef LDAP_DEBUG
static void
-lru_print( struct cache *cache )
+lru_print( Cache *cache )
{
Entry *e;
fprintf( stderr, "LRU queue (head to tail):\n" );
- for ( e = cache->c_lruhead; e != NULL; e = e->e_lrunext ) {
- fprintf( stderr, "\tdn %20s id %d refcnt %d\n", e->e_dn,
- e->e_id, e->e_refcnt );
+ for ( e = cache->c_lruhead; e != NULL; e = LEI(e)->lei_lrunext ) {
+ fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n",
+ e->e_dn, e->e_id, LEI(e)->lei_refcnt );
}
fprintf( stderr, "LRU queue (tail to head):\n" );
- for ( e = cache->c_lrutail; e != NULL; e = e->e_lruprev ) {
- fprintf( stderr, "\tdn %20s id %d refcnt %d\n", e->e_dn,
- e->e_id, e->e_refcnt );
+ for ( e = cache->c_lrutail; e != NULL; e = LEI(e)->lei_lruprev ) {
+ fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n",
+ e->e_dn, e->e_id, LEI(e)->lei_refcnt );
}
}
#endif
+
/* close.c - close ldbm backend */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
-ldbm_back_close( Backend *be )
+int
+ldbm_back_db_close( Backend *be )
{
Debug( LDAP_DEBUG_TRACE, "ldbm backend syncing\n", 0, 0, 0 );
ldbm_cache_flush_all( be );
Debug( LDAP_DEBUG_TRACE, "ldbm backend done syncing\n", 0, 0, 0 );
+
+ cache_release_all( &((struct ldbminfo *) be->be_private)->li_cache );
+
+ return 0;
}
/* compare.c - ldbm backend compare routine */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "back-ldbm.h"
-
-extern Entry *dn2entry();
-extern Attribute *attr_find();
+#include "proto-back-ldbm.h"
int
ldbm_back_compare(
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
+ Entry *matched;
Entry *e;
Attribute *a;
- int i;
+ int rc;
+ int manageDSAit = get_manageDSAit( op );
+
+ /* get entry with reader lock */
+ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
return( 1 );
}
- if ( ! access_allowed( be, conn, op, e, ava->ava_type, &ava->ava_value,
- op->o_dn, ACL_COMPARE ) ) {
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ rc = 1;
+ goto return_results;
}
- if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ if ( ! access_allowed( be, conn, op, e,
+ ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
}
- if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 ) {
- send_ldap_result( conn, op, LDAP_COMPARE_TRUE, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( 0 );
+ if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE,
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
}
- send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( 0 );
+ if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 )
+ send_ldap_result( conn, op, LDAP_COMPARE_TRUE,
+ NULL, NULL, NULL, NULL );
+ else
+ send_ldap_result( conn, op, LDAP_COMPARE_FALSE,
+ NULL, NULL, NULL, NULL );
+
+ rc = 0;
+
+return_results:;
+ cache_return_entry_r( &li->li_cache, e );
+ return( rc );
}
/* config.c - ldbm backend configuration file routine */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "back-ldbm.h"
-ldbm_back_config(
+
+int
+ldbm_back_db_config(
Backend *be,
char *fname,
int lineno,
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
if ( li == NULL ) {
- fprintf( stderr, "%s: line %d: ldbm backend info is null!\n",
+ fprintf( stderr, "%s: line %d: ldbm database info is null!\n",
fname, lineno );
- exit( 1 );
+ return( 1 );
}
/* directory where database files live */
fprintf( stderr,
"%s: line %d: missing dir in \"directory <dir>\" line\n",
fname, lineno );
- exit( 1 );
+ return( 1 );
}
- li->li_directory = strdup( argv[1] );
+ if ( li->li_directory )
+ free( li->li_directory );
+ li->li_directory = ch_strdup( argv[1] );
/* mode with which to create new database files */
} else if ( strcasecmp( argv[0], "mode" ) == 0 ) {
fprintf( stderr,
"%s: line %d: missing mode in \"mode <mode>\" line\n",
fname, lineno );
- exit( 1 );
+ return( 1 );
}
li->li_mode = strtol( argv[1], NULL, 0 );
fprintf( stderr,
"%s: line %d: missing attr in \"index <attr> [pres,eq,approx,sub]\" line\n",
fname, lineno );
- exit( 1 );
+ return( 1 );
} else if ( argc > 3 ) {
fprintf( stderr,
"%s: line %d: extra junk after \"index <attr> [pres,eq,approx,sub]\" line (ignored)\n",
fprintf( stderr,
"%s: line %d: missing size in \"cachesize <size>\" line\n",
fname, lineno );
- exit( 1 );
+ return( 1 );
}
li->li_cache.c_maxsize = atoi( argv[1] );
fprintf( stderr,
"%s: line %d: missing size in \"dbcachesize <size>\" line\n",
fname, lineno );
- exit( 1 );
+ return( 1 );
}
li->li_dbcachesize = atoi( argv[1] );
+ /* no write sync */
+ } else if ( strcasecmp( argv[0], "dbcachenowsync" ) == 0 ) {
+ li->li_dbcachewsync = 0;
+
/* anything else */
} else {
fprintf( stderr,
"%s: line %d: unknown directive \"%s\" in ldbm database definition (ignored)\n",
fname, lineno, argv[0] );
}
+
+ return 0;
}
/* ldbmcache.c - maintain a cache of open ldbm files */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/param.h>
+
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include <sys/stat.h>
-#include <errno.h>
-#include "portable.h"
-#include "slap.h"
-#include "ldapconfig.h"
-#include "back-ldbm.h"
-#ifndef SYSERRLIST_IN_STDIO
-extern int sys_nerr;
-extern char *sys_errlist[];
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
#endif
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
-struct dbcache *
+#include "ldap_defaults.h"
+#include "slap.h"
+#include "back-ldbm.h"
+
+DBCache *
ldbm_cache_open(
Backend *be,
char *name,
int i, lru;
time_t oldtime, curtime;
char buf[MAXPATHLEN];
- LDBM db;
+#ifdef HAVE_ST_BLKSIZE
struct stat st;
+#endif
- sprintf( buf, "%s/%s%s", li->li_directory, name, suffix );
+ sprintf( buf, "%s" LDAP_DIRSEP "%s%s",
+ li->li_directory, name, suffix );
Debug( LDAP_DEBUG_TRACE, "=> ldbm_cache_open( \"%s\", %d, %o )\n", buf,
flags, li->li_mode );
lru = 0;
- pthread_mutex_lock( ¤ttime_mutex );
- curtime = currenttime;
- pthread_mutex_unlock( ¤ttime_mutex );
+ curtime = slap_get_time();
oldtime = curtime;
- pthread_mutex_lock( &li->li_dbcache_mutex );
+ ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
for ( i = 0; i < MAXDBCACHE && li->li_dbcache[i].dbc_name != NULL;
i++ ) {
/* already open - return it */
li->li_dbcache[i].dbc_refcnt++;
Debug( LDAP_DEBUG_TRACE,
"<= ldbm_cache_open (cache %d)\n", i, 0, 0 );
- pthread_mutex_unlock( &li->li_dbcache_mutex );
+ ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
return( &li->li_dbcache[i] );
}
0, 0, 0 );
lru = -1;
while ( lru == -1 ) {
- pthread_cond_wait( &li->li_dbcache_cv,
+ ldap_pvt_thread_cond_wait( &li->li_dbcache_cv,
&li->li_dbcache_mutex );
for ( i = 0; i < MAXDBCACHE; i++ ) {
if ( li->li_dbcache[i].dbc_refcnt
if ( (li->li_dbcache[i].dbc_db = ldbm_open( buf, flags, li->li_mode,
li->li_dbcachesize )) == NULL ) {
+ int err = errno;
Debug( LDAP_DEBUG_TRACE,
- "<= ldbm_cache_open NULL \"%s\" errno %d reason \"%s\")\n",
- buf, errno, errno > -1 && errno < sys_nerr ?
- sys_errlist[errno] : "unknown" );
- pthread_mutex_unlock( &li->li_dbcache_mutex );
+ "<= ldbm_cache_open NULL \"%s\" errno=%d reason=\"%s\")\n",
+ buf, err, err > -1 && err < sys_nerr ?
+ sys_errlist[err] : "unknown" );
+ ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
return( NULL );
}
- li->li_dbcache[i].dbc_name = strdup( buf );
+ li->li_dbcache[i].dbc_name = ch_strdup( buf );
li->li_dbcache[i].dbc_refcnt = 1;
li->li_dbcache[i].dbc_lastref = curtime;
+#ifdef HAVE_ST_BLKSIZE
if ( stat( buf, &st ) == 0 ) {
li->li_dbcache[i].dbc_blksize = st.st_blksize;
- } else {
+ } else
+#endif
+ {
li->li_dbcache[i].dbc_blksize = DEFAULT_BLOCKSIZE;
}
li->li_dbcache[i].dbc_maxids = (li->li_dbcache[i].dbc_blksize /
- sizeof(ID)) - 2;
+ sizeof(ID)) - ID_BLOCK_IDS_OFFSET;
li->li_dbcache[i].dbc_maxindirect = (SLAPD_LDBM_MIN_MAXIDS /
li->li_dbcache[i].dbc_maxids) + 1;
Debug( LDAP_DEBUG_ARGS,
- "ldbm_cache_open (blksize %d) (maxids %d) (maxindirect %d)\n",
+ "ldbm_cache_open (blksize %ld) (maxids %d) (maxindirect %d)\n",
li->li_dbcache[i].dbc_blksize, li->li_dbcache[i].dbc_maxids,
li->li_dbcache[i].dbc_maxindirect );
Debug( LDAP_DEBUG_TRACE, "<= ldbm_cache_open (opened %d)\n", i, 0, 0 );
- pthread_mutex_unlock( &li->li_dbcache_mutex );
+ ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
return( &li->li_dbcache[i] );
}
void
-ldbm_cache_close( Backend *be, struct dbcache *db )
+ldbm_cache_close( Backend *be, DBCache *db )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- pthread_mutex_lock( &li->li_dbcache_mutex );
+ ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
if ( --db->dbc_refcnt == 0 ) {
- pthread_cond_signal( &li->li_dbcache_cv );
+ ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
}
- pthread_mutex_unlock( &li->li_dbcache_mutex );
+ ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
}
void
-ldbm_cache_really_close( Backend *be, struct dbcache *db )
+ldbm_cache_really_close( Backend *be, DBCache *db )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- pthread_mutex_lock( &li->li_dbcache_mutex );
+ ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
if ( --db->dbc_refcnt == 0 ) {
- pthread_cond_signal( &li->li_dbcache_cv );
+ ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
ldbm_close( db->dbc_db );
free( db->dbc_name );
db->dbc_name = NULL;
}
- pthread_mutex_unlock( &li->li_dbcache_mutex );
+ ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
}
void
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
int i;
- pthread_mutex_lock( &li->li_dbcache_mutex );
+ ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
for ( i = 0; i < MAXDBCACHE; i++ ) {
if ( li->li_dbcache[i].dbc_name != NULL ) {
Debug( LDAP_DEBUG_TRACE, "ldbm flushing db (%s)\n",
li->li_dbcache[i].dbc_name, 0, 0 );
- pthread_mutex_lock( &li->li_dbcache[i].dbc_mutex );
ldbm_sync( li->li_dbcache[i].dbc_db );
- pthread_mutex_unlock( &li->li_dbcache[i].dbc_mutex );
+ if ( li->li_dbcache[i].dbc_refcnt != 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "refcnt = %d, couldn't close db (%s)\n",
+ li->li_dbcache[i].dbc_refcnt,
+ li->li_dbcache[i].dbc_name, 0 );
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm closing db (%s)\n",
+ li->li_dbcache[i].dbc_name, 0, 0 );
+ ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
+ ldbm_close( li->li_dbcache[i].dbc_db );
+ free( li->li_dbcache[i].dbc_name );
+ li->li_dbcache[i].dbc_name = NULL;
+ }
}
}
- pthread_mutex_unlock( &li->li_dbcache_mutex );
+ ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
}
Datum
ldbm_cache_fetch(
- struct dbcache *db,
+ DBCache *db,
Datum key
)
{
Datum data;
- pthread_mutex_lock( &db->dbc_mutex );
-#ifdef reentrant_database
- /* increment reader count */
- db->dbc_readers++
- pthread_mutex_unlock( &db->dbc_mutex );
-#endif
-
- data = ldbm_fetch( db->dbc_db, key );
-
-#ifdef reentrant_database
- pthread_mutex_lock( &db->dbc_mutex );
- /* decrement reader count & signal any waiting writers */
- if ( --db->dbc_readers == 0 ) {
- pthread_cond_signal( &db->dbc_cv );
- }
-#endif
- pthread_mutex_unlock( &db->dbc_mutex );
+ return ldbm_fetch( db->dbc_db, key );
return( data );
}
int
ldbm_cache_store(
- struct dbcache *db,
+ DBCache *db,
Datum key,
Datum data,
int flags
{
int rc;
- pthread_mutex_lock( &db->dbc_mutex );
-#ifdef reentrant_database
- /* wait for reader count to drop to zero */
- while ( db->dbc_readers > 0 ) {
- pthread_cond_wait( &db->dbc_cv, &db->dbc_mutex );
- }
-#endif
+#ifdef LDBM_DEBUG
+ Statslog( LDAP_DEBUG_STATS,
+ "=> ldbm_cache_store(): key.dptr=%s, key.dsize=%d\n",
+ key.dptr, key.dsize, 0, 0, 0 );
- rc = ldbm_store( db->dbc_db, key, data, flags );
+ Statslog( LDAP_DEBUG_STATS,
+ "=> ldbm_cache_store(): key.dptr=0x%08x, data.dptr=0x%0 8x\n",
+ key.dptr, data.dptr, 0, 0, 0 );
- pthread_mutex_unlock( &db->dbc_mutex );
+ Statslog( LDAP_DEBUG_STATS,
+ "=> ldbm_cache_store(): data.dptr=%s, data.dsize=%d\n",
+ data.dptr, data.dsize, 0, 0, 0 );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "=> ldbm_cache_store(): flags=0x%08x\n",
+ flags, 0, 0, 0, 0 );
+#endif /* LDBM_DEBUG */
+
+ rc = ldbm_store( db->dbc_db, key, data, flags );
return( rc );
}
int
ldbm_cache_delete(
- struct dbcache *db,
+ DBCache *db,
Datum key
)
{
int rc;
- pthread_mutex_lock( &db->dbc_mutex );
-#ifdef reentrant_database
- /* wait for reader count to drop to zero - then write */
- while ( db->dbc_readers > 0 ) {
- pthread_cond_wait( &db->dbc_cv, &db->dbc_mutex );
- }
-#endif
-
rc = ldbm_delete( db->dbc_db, key );
- pthread_mutex_unlock( &db->dbc_mutex );
-
return( rc );
}
/* delete.c - ldbm backend delete routine */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
-
-extern Entry *dn2entry();
-extern Attribute *attr_find();
+#include "proto-back-ldbm.h"
int
ldbm_back_delete(
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
- Entry *e;
+ Entry *matched = NULL;
+ char *pdn = NULL;
+ Entry *e, *p = NULL;
+ int rootlock = 0;
+ int rc = -1;
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", dn, 0, 0);
+
+ /* get entry with writer lock */
+ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: no such object %s\n",
+ dn, 0, 0);
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
if ( matched != NULL ) {
- free( matched );
+ ber_bvecfree( refs );
+ free( matched_dn );
}
+
return( -1 );
}
- if ( has_children( be, e ) ) {
- send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, "",
- "" );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_WRITE ) )
+ {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- ldbm_back_delete: insufficient access %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
}
+#endif
- if ( ! access_allowed( be, conn, op, e, "entry", NULL, op->o_dn,
- ACL_WRITE ) ) {
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ if ( !manageDSAit && is_entry_referral( e ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ rc = 1;
+ goto return_results;
}
- /* XXX delete from parent's id2children entry XXX */
+
+ if ( has_children( be, e ) ) {
+ Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* delete from parent's id2children entry */
+ if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
+ if( (p = dn2entry_w( be, pdn, &matched )) == NULL) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- ldbm_back_delete: parent does not exist\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- ldbm_back_delete: no access to parent\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ } else {
+ /* no parent, must be root to delete */
+ if( ! be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- ldbm_back_delete: no parent & not root\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
+ rootlock = 1;
+ }
/* delete from dn2id mapping */
- if ( dn2id_delete( be, e->e_dn ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ if ( dn2id_delete( be, e->e_ndn ) != 0 ) {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- ldbm_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
}
/* delete from disk and cache */
if ( id2entry_delete( be, e ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- ldbm_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
}
- cache_return_entry( &li->li_cache, e );
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 0;
+
+return_results:;
+ if ( pdn != NULL ) free(pdn);
+
+ if( p != NULL ) {
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rootlock ) {
+ /* release root lock */
+ ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
+ }
+
+ /* free entry and writer lock */
+ cache_return_entry_w( &li->li_cache, e );
+
+ if ( matched != NULL ) free(matched);
- return( 0 );
+ return rc;
}
/* dn2id.c - routines to deal with the dn2id index */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
-
-extern struct dbcache *ldbm_cache_open();
-extern Entry *cache_find_entry_dn();
-extern Entry *id2entry();
-extern char *dn_parent();
-extern Datum ldbm_cache_fetch();
+#include "proto-back-ldbm.h"
int
dn2id_add(
ID id
)
{
- int rc;
- struct dbcache *db;
+ int rc, flags;
+ DBCache *db;
Datum key, data;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
Debug( LDAP_DEBUG_TRACE, "=> dn2id_add( \"%s\", %ld )\n", dn, id, 0 );
return( -1 );
}
- dn = strdup( dn );
- dn_normalize_case( dn );
+ ldbm_datum_init( key );
+ key.dsize = strlen( dn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
- key.dptr = dn;
- key.dsize = strlen( dn ) + 1;
+ ldbm_datum_init( data );
data.dptr = (char *) &id;
data.dsize = sizeof(ID);
- rc = ldbm_cache_store( db, key, data, LDBM_INSERT );
+ flags = LDBM_INSERT;
+ if ( li->li_dbcachewsync ) flags |= LDBM_SYNC;
+
+ rc = ldbm_cache_store( db, key, data, flags );
+
+ free( key.dptr );
+
+ if ( rc != -1 ) {
+ char *pdn = dn_parent( NULL, dn );
+
+ if( pdn != NULL ) {
+ ldbm_datum_init( key );
+ key.dsize = strlen( pdn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, pdn );
+ rc = idl_insert_key( be, db, key, id );
+ free( key.dptr );
+ free( pdn );
+ }
+ }
+
+ if ( rc != -1 ) {
+ char **subtree = dn_subtree( NULL, dn );
+
+ if( subtree != NULL ) {
+ int i;
+ for( i=0; subtree[i] != NULL; i++ ) {
+ ldbm_datum_init( key );
+ key.dsize = strlen( subtree[i] ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s",
+ DN_SUBTREE_PREFIX, subtree[i] );
+
+ rc = idl_insert_key( be, db, key, id );
+
+ free( key.dptr );
+
+ if(rc == -1) break;
+ }
+
+ charray_free( subtree );
+ }
+
+ }
- free( dn );
ldbm_cache_close( be, db );
Debug( LDAP_DEBUG_TRACE, "<= dn2id_add %d\n", rc, 0, 0 );
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- struct dbcache *db;
- Entry *e;
+ DBCache *db;
ID id;
Datum key, data;
Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn, 0, 0 );
- dn = strdup( dn );
- dn_normalize_case( dn );
-
/* first check the cache */
- if ( (e = cache_find_entry_dn( &li->li_cache, dn )) != NULL ) {
- id = e->e_id;
- free( dn );
- Debug( LDAP_DEBUG_TRACE, "<= dn2id %d (in cache)\n", e->e_id,
- 0, 0 );
- cache_return_entry( &li->li_cache, e );
-
+ if ( (id = cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) {
+ Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld (in cache)\n", id,
+ 0, 0 );
return( id );
}
if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
- == NULL ) {
- free( dn );
+ == NULL ) {
Debug( LDAP_DEBUG_ANY, "<= dn2id could not open dn2id%s\n",
- LDBM_SUFFIX, 0, 0 );
+ LDBM_SUFFIX, 0, 0 );
return( NOID );
}
- key.dptr = dn;
- key.dsize = strlen( dn ) + 1;
+ ldbm_datum_init( key );
+
+ key.dsize = strlen( dn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
data = ldbm_cache_fetch( db, key );
ldbm_cache_close( be, db );
- free( dn );
+
+ free( key.dptr );
if ( data.dptr == NULL ) {
Debug( LDAP_DEBUG_TRACE, "<= dn2id NOID\n", 0, 0, 0 );
ldbm_datum_free( db->dbc_db, data );
- Debug( LDAP_DEBUG_TRACE, "<= dn2id %d\n", id, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld\n", id, 0, 0 );
return( id );
}
+ID_BLOCK *
+dn2idl(
+ Backend *be,
+ char *dn,
+ int prefix
+)
+{
+ DBCache *db;
+ Datum key;
+ ID_BLOCK *idl;
+
+ Debug( LDAP_DEBUG_TRACE, "=> dn2idl( \"%c%s\" )\n", prefix, dn, 0 );
+
+ if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "<= dn2idl could not open dn2id%s\n",
+ LDBM_SUFFIX, 0, 0 );
+ return NULL;
+ }
+
+ ldbm_datum_init( key );
+
+ key.dsize = strlen( dn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", prefix, dn );
+
+ idl = idl_fetch( be, db, key );
+
+ ldbm_cache_close( be, db );
+
+ free( key.dptr );
+
+ return( idl );
+}
+
+
int
dn2id_delete(
Backend *be,
char *dn
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- struct dbcache *db;
+ DBCache *db;
Datum key;
int rc;
return( -1 );
}
- dn_normalize_case( dn );
- key.dptr = dn;
- key.dsize = strlen( dn ) + 1;
+ ldbm_datum_init( key );
+
+ key.dsize = strlen( dn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
rc = ldbm_cache_delete( db, key );
+ free( key.dptr );
+
ldbm_cache_close( be, db );
Debug( LDAP_DEBUG_TRACE, "<= dn2id_delete %d\n", rc, 0, 0 );
*/
Entry *
-dn2entry(
+dn2entry_rw(
Backend *be,
char *dn,
- char **matched
+ Entry **matched,
+ int rw
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
ID id;
- Entry *e;
+ Entry *e = NULL;
char *pdn;
- if ( (id = dn2id( be, dn )) != NOID && (e = id2entry( be, id ))
- != NULL ) {
+ Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
+ rw ? "w" : "r", dn, 0);
+
+ if( matched != NULL ) {
+ /* caller cares about match */
+ *matched = NULL;
+ }
+
+ if ( (id = dn2id( be, dn )) != NOID &&
+ (e = id2entry_rw( be, id, rw )) != NULL )
+ {
return( e );
}
- *matched = NULL;
- /* stop when we get to the suffix */
- if ( be_issuffix( be, dn ) ) {
- return( NULL );
+ if ( id != NOID ) {
+ Debug(LDAP_DEBUG_ANY,
+ "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n",
+ rw ? "w" : "r", id, dn);
+ /* must have been deleted from underneath us */
+ /* treat as if NOID was found */
}
+ /* caller doesn't care about match */
+ if( matched == NULL ) return NULL;
+
/* entry does not exist - see how much of the dn does exist */
+ /* dn_parent checks returns NULL if dn is suffix */
if ( (pdn = dn_parent( be, dn )) != NULL ) {
- if ( (e = dn2entry( be, pdn, matched )) != NULL ) {
- *matched = pdn;
- cache_return_entry( &li->li_cache, e );
- } else {
- free( pdn );
+ /* get entry with reader lock */
+ if ( (e = dn2entry_r( be, pdn, matched )) != NULL ) {
+ *matched = e;
}
+ free( pdn );
}
- return( NULL );
+ return NULL;
}
+
--- /dev/null
+/* entry.c - ldbm backend entry_release routine */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
+
+
+int
+ldbm_back_entry_release_rw(
+ Backend *be,
+ Entry *e,
+ int rw
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ /* free entry and reader or writer lock */
+ cache_return_entry_rw( &li->li_cache, e, rw );
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#ifndef _LDBM_EXTERNAL_H
+#define _LDBM_EXTERNAL_H
+
+LDAP_BEGIN_DECL
+
+extern int ldbm_back_initialize LDAP_P(( BackendInfo *bi ));
+extern int ldbm_back_open LDAP_P(( BackendInfo *bi ));
+extern int ldbm_back_close LDAP_P(( BackendInfo *bi ));
+extern int ldbm_back_destroy LDAP_P(( BackendInfo *bi ));
+
+extern int ldbm_back_db_init LDAP_P(( BackendDB *bd ));
+extern int ldbm_back_db_open LDAP_P(( BackendDB *bd ));
+extern int ldbm_back_db_close LDAP_P(( BackendDB *bd ));
+extern int ldbm_back_db_destroy LDAP_P(( BackendDB *bd ));
+
+extern int ldbm_back_db_config LDAP_P(( BackendDB *bd,
+ char *fname, int lineno, int argc, char **argv ));
+
+extern int ldbm_back_bind LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *dn, int method, char* mech,
+ struct berval *cred, char** edn ));
+
+extern int ldbm_back_unbind LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op ));
+
+extern int ldbm_back_search LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *base, int scope, int deref, int sizelimit, int timelimit,
+ Filter *filter, char *filterstr, char **attrs, int attrsonly ));
+
+extern int ldbm_back_compare LDAP_P((BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *dn, Ava *ava ));
+
+extern int ldbm_back_modify LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *dn, LDAPModList *ml ));
+
+extern int ldbm_back_modrdn LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *dn, char* newrdn, int deleteoldrdn,
+ char *newSuperior ));
+
+extern int ldbm_back_add LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op, Entry *e ));
+
+extern int ldbm_back_delete LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op, char *dn ));
+
+extern int ldbm_back_abandon LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op, ber_int_t msgid ));
+
+extern int ldbm_back_group LDAP_P(( BackendDB *bd,
+ Entry *target, char* gr_ndn, char* op_ndn,
+ char* objectclassValue, char* groupattrName));
+
+
+/* hooks for slap tools */
+extern int ldbm_tool_entry_open LDAP_P(( BackendDB *be, int mode ));
+extern int ldbm_tool_entry_close LDAP_P(( BackendDB *be ));
+extern ID ldbm_tool_entry_first LDAP_P(( BackendDB *be ));
+extern ID ldbm_tool_entry_next LDAP_P(( BackendDB *be ));
+extern Entry* ldbm_tool_entry_get LDAP_P(( BackendDB *be, ID id ));
+extern ID ldbm_tool_entry_put LDAP_P(( BackendDB *be, Entry *e ));
+extern int ldbm_tool_index_attr LDAP_P(( BackendDB *be, char* type ));
+extern int ldbm_tool_index_change LDAP_P(( BackendDB *be, char* type,
+ struct berval **bv, ID id, int op ));
+extern int ldbm_tool_sync LDAP_P(( BackendDB *be ));
+
+
+LDAP_END_DECL
+
+#endif /* _LDBM_EXTERNAL_H */
+
/* filterindex.c - generate the list of candidate entries from a filter */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "back-ldbm.h"
-extern char *first_word();
-extern char *next_word();
-extern char *phonetic();
-extern IDList *index_read();
-extern IDList *idl_intersection();
-extern IDList *idl_union();
-extern IDList *idl_notin();
-extern IDList *idl_allids();
-
-static IDList *ava_candidates();
-static IDList *presence_candidates();
-static IDList *approx_candidates();
-static IDList *list_candidates();
-static IDList *substring_candidates();
-static IDList *substring_comp_candidates();
+static ID_BLOCK *ava_candidates( Backend *be, Ava *ava, int type );
+static ID_BLOCK *presence_candidates( Backend *be, char *type );
+static ID_BLOCK *approx_candidates( Backend *be, Ava *ava );
+static ID_BLOCK *list_candidates( Backend *be, Filter *flist, int ftype );
+static ID_BLOCK *substring_candidates( Backend *be, Filter *f );
+static ID_BLOCK *substring_comp_candidates( Backend *be, char *type, char *val, int prepost );
/*
* test_filter - test a filter against a single entry.
* >0 an ldap error code
*/
-IDList *
+ID_BLOCK *
filter_candidates(
Backend *be,
Filter *f
)
{
- IDList *result;
+ ID_BLOCK *result, *tmp1, *tmp2;
Debug( LDAP_DEBUG_TRACE, "=> filter_candidates\n", 0, 0, 0 );
result = NULL;
switch ( f->f_choice ) {
+ case SLAPD_FILTER_DN_ONE:
+ Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 );
+ result = dn2idl( be, f->f_dn, DN_ONE_PREFIX );
+ break;
+
+ case SLAPD_FILTER_DN_SUBTREE:
+ Debug( LDAP_DEBUG_FILTER, "\tDN SUBTREE\n", 0, 0, 0 );
+ result = dn2idl( be, f->f_dn, DN_SUBTREE_PREFIX );
+ break;
+
case LDAP_FILTER_EQUALITY:
Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
result = ava_candidates( be, &f->f_ava, LDAP_FILTER_EQUALITY );
case LDAP_FILTER_NOT:
Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
- result = idl_notin( be, idl_allids( be ), filter_candidates( be,
- f->f_not ) );
+ tmp1 = idl_allids( be );
+ tmp2 = filter_candidates( be, f->f_not );
+ result = idl_notin( be, tmp1, tmp2 );
+ idl_free( tmp2 );
+ idl_free( tmp1 );
break;
}
- Debug( LDAP_DEBUG_TRACE, "<= filter_candidates %d\n",
- result ? result->b_nids : 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= filter_candidates %ld\n",
+ result ? ID_BLOCK_NIDS(result) : 0, 0, 0 );
return( result );
}
-static IDList *
+static ID_BLOCK *
ava_candidates(
Backend *be,
Ava *ava,
int type
)
{
- IDList *idl;
+ ID_BLOCK *idl;
Debug( LDAP_DEBUG_TRACE, "=> ava_candidates 0x%x\n", type, 0, 0 );
break;
}
- Debug( LDAP_DEBUG_TRACE, "<= ava_candidates %d\n",
- idl ? idl->b_nids : 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= ava_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
return( idl );
}
-static IDList *
+static ID_BLOCK *
presence_candidates(
Backend *be,
char *type
)
{
- IDList *idl;
+ ID_BLOCK *idl;
Debug( LDAP_DEBUG_TRACE, "=> presence_candidates\n", 0, 0, 0 );
idl = index_read( be, type, 0, "*" );
- Debug( LDAP_DEBUG_TRACE, "<= presence_candidates %d\n",
- idl ? idl->b_nids : 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= presence_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
return( idl );
}
-static IDList *
+static ID_BLOCK *
approx_candidates(
Backend *be,
Ava *ava
)
{
char *w, *c;
- IDList *idl, *tmp;
+ ID_BLOCK *idl, *tmp;
Debug( LDAP_DEBUG_TRACE, "=> approx_candidates\n", 0, 0, 0 );
}
}
- Debug( LDAP_DEBUG_TRACE, "<= approx_candidates %d\n",
- idl ? idl->b_nids : 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= approx_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
return( idl );
}
-static IDList *
+static ID_BLOCK *
list_candidates(
Backend *be,
Filter *flist,
int ftype
)
{
- IDList *idl, *tmp, *tmp2;
+ ID_BLOCK *idl, *tmp, *tmp2;
Filter *f;
Debug( LDAP_DEBUG_TRACE, "=> list_candidates 0x%x\n", ftype, 0, 0 );
}
}
- Debug( LDAP_DEBUG_TRACE, "<= list_candidates %d\n",
- idl ? idl->b_nids : 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= list_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
return( idl );
}
-static IDList *
+static ID_BLOCK *
substring_candidates(
Backend *be,
Filter *f
)
{
int i;
- IDList *idl, *tmp, *tmp2;
+ ID_BLOCK *idl, *tmp, *tmp2;
Debug( LDAP_DEBUG_TRACE, "=> substring_candidates\n", 0, 0, 0 );
}
}
- Debug( LDAP_DEBUG_TRACE, "<= substring_candidates %d\n",
- idl ? idl->b_nids : 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= substring_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
return( idl );
}
-static IDList *
+static ID_BLOCK *
substring_comp_candidates(
Backend *be,
char *type,
)
{
int i, len;
- IDList *idl, *tmp, *tmp2;
+ ID_BLOCK *idl, *tmp, *tmp2;
char *p;
char buf[SUBLEN + 1];
idl_free( tmp );
idl_free( tmp2 );
}
+
+ /* break if no candidates */
+ if( idl == NULL ) {
+ break;
+ }
}
- Debug( LDAP_DEBUG_TRACE, "<= substring_comp_candidates %d\n",
- idl ? idl->b_nids : 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= substring_comp_candidates %ld\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
return( idl );
}
--- /dev/null
+/* group.c - ldbm backend acl group routine */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
+
+
+/* return 0 IFF op_dn is a value in member attribute
+ * of entry with gr_dn AND that entry has an objectClass
+ * value of groupOfNames
+ */
+int
+ldbm_back_group(
+ Backend *be,
+ Entry *target,
+ char *gr_ndn,
+ char *op_ndn,
+ char *objectclassValue,
+ char *groupattrName
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *e;
+ int rc = 1;
+
+ Attribute *attr;
+ struct berval bv;
+
+ Debug( LDAP_DEBUG_ARGS,
+ "=> ldbm_back_group: gr dn: \"%s\"\n",
+ gr_ndn, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS,
+ "=> ldbm_back_group: op dn: \"%s\"\n",
+ op_ndn, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS,
+ "=> ldbm_back_group: objectClass: \"%s\" attrName: \"%s\"\n",
+ objectclassValue, groupattrName, 0 );
+
+ Debug( LDAP_DEBUG_ARGS,
+ "=> ldbm_back_group: tr dn: \"%s\"\n",
+ target->e_ndn, 0, 0 );
+
+ if (strcmp(target->e_ndn, gr_ndn) == 0) {
+ /* we already have a LOCKED copy of the entry */
+ e = target;
+ Debug( LDAP_DEBUG_ARGS,
+ "=> ldbm_back_group: target is group: \"%s\"\n",
+ gr_ndn, 0, 0 );
+
+ } else {
+ /* can we find group entry with reader lock */
+ if ((e = dn2entry_r(be, gr_ndn, NULL )) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "=> ldbm_back_group: cannot find group: \"%s\"\n",
+ gr_ndn, 0, 0 );
+ return( 1 );
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "=> ldbm_back_group: found group: \"%s\"\n",
+ gr_ndn, 0, 0 );
+ }
+
+ /* find it's objectClass and member attribute values
+ * make sure this is a group entry
+ * finally test if we can find op_dn in the member attribute value list *
+ */
+
+ rc = 1;
+
+ if ((attr = attr_find(e->e_attrs, "objectclass")) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: failed to find objectClass\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = "ALIAS";
+ bv.bv_len = sizeof("ALIAS")-1;
+
+ if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: group is an alias\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = "REFERRAL";
+ bv.bv_len = sizeof("REFERRAL")-1;
+
+ if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: group is a referral\n",
+ 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = objectclassValue;
+ bv.bv_len = strlen( bv.bv_val );
+
+ if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: failed to find %s in objectClass\n",
+ objectclassValue, 0, 0 );
+ goto return_results;
+ }
+
+ if ((attr = attr_find(e->e_attrs, groupattrName)) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: failed to find %s\n",
+ groupattrName, 0, 0 );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: found objectClass %s and %s\n",
+ objectclassValue, groupattrName, 0 );
+
+ bv.bv_val = op_ndn;
+ bv.bv_len = strlen( op_ndn );
+
+ if( value_find( attr->a_vals, &bv, attr->a_syntax, 1) != 0 )
+ {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: \"%s\" not in \"%s\": %s\n",
+ op_ndn, gr_ndn, groupattrName );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: \"%s\" is in \"%s\": %s\n",
+ op_ndn, gr_ndn, groupattrName );
+
+ rc = 0;
+
+return_results:
+ if( target != e ) {
+ /* free entry and reader lock */
+ cache_return_entry_r( &li->li_cache, e );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: rc=%d\n", rc, 0, 0 );
+ return(rc);
+}
+
/* id2children.c - routines to deal with the id2children index */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-#include "back-ldbm.h"
-
-struct dbcache *ldbm_cache_open();
-extern Datum ldbm_cache_fetch();
-IDList *idl_fetch();
+#include "portable.h"
-int
-id2children_add(
- Backend *be,
- Entry *p,
- Entry *e
-)
-{
- struct dbcache *db;
- Datum key, data;
- int len, rc;
- IDList *idl;
- char buf[20];
-
- Debug( LDAP_DEBUG_TRACE, "=> id2children_add( %d, %d )\n", p ? p->e_id
- : 0, e->e_id, 0 );
-
- if ( (db = ldbm_cache_open( be, "id2children", LDBM_SUFFIX,
- LDBM_WRCREAT )) == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "<= id2children_add -1 could not open \"id2children%s\"\n",
- LDBM_SUFFIX, 0, 0 );
- return( -1 );
- }
-
- sprintf( buf, "%c%d", EQ_PREFIX, p ? p->e_id : 0 );
- key.dptr = buf;
- key.dsize = strlen( buf ) + 1;
+#include <stdio.h>
+#include <ac/string.h>
- if ( idl_insert_key( be, db, key, e->e_id ) != 0 ) {
- Debug( LDAP_DEBUG_TRACE, "<= id2children_add -1 (idl_insert)\n",
- 0, 0, 0 );
- ldbm_cache_close( be, db );
- return( -1 );
- }
+#include <ac/socket.h>
- ldbm_cache_close( be, db );
+#include "slap.h"
+#include "back-ldbm.h"
- Debug( LDAP_DEBUG_TRACE, "<= id2children_add 0\n", 0, 0, 0 );
- return( 0 );
-}
int
has_children(
Entry *p
)
{
- struct dbcache *db;
+ DBCache *db;
Datum key;
- int rc;
- IDList *idl;
- char buf[20];
+ int rc = 0;
+ ID_BLOCK *idl;
+
+ ldbm_datum_init( key );
- Debug( LDAP_DEBUG_TRACE, "=> has_children( %d )\n", p->e_id , 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "=> has_children( %ld )\n", p->e_id , 0, 0 );
- if ( (db = ldbm_cache_open( be, "id2children", LDBM_SUFFIX,
+ if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX,
LDBM_WRCREAT )) == NULL ) {
Debug( LDAP_DEBUG_ANY,
- "<= has_children -1 could not open \"id2children%s\"\n",
+ "<= has_children -1 could not open \"dn2id%s\"\n",
LDBM_SUFFIX, 0, 0 );
return( 0 );
}
- sprintf( buf, "%c%d", EQ_PREFIX, p->e_id );
- key.dptr = buf;
- key.dsize = strlen( buf ) + 1;
+ key.dsize = strlen( p->e_ndn ) + 2;
+ key.dptr = ch_malloc( key.dsize );
+ sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, p->e_ndn );
idl = idl_fetch( be, db, key );
+ free( key.dptr );
+
ldbm_cache_close( be, db );
- rc = idl ? 1 : 0;
- idl_free( idl );
- Debug( LDAP_DEBUG_TRACE, "<= has_children %d\n", rc, 0, 0 );
+ if( idl != NULL ) {
+ idl_free( idl );
+ rc = 1;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= has_children( %ld ): %s\n",
+ p->e_id, rc ? "yes" : "no", 0 );
return( rc );
}
/* id2entry.c - routines to deal with the id2entry index */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
-extern struct dbcache *ldbm_cache_open();
-extern Datum ldbm_cache_fetch();
-extern char *dn_parent();
-extern Entry *str2entry();
-extern Entry *cache_find_entry_id();
-extern char *entry2str();
-extern pthread_mutex_t entry2str_mutex;
+/*
+ * This routine adds (or updates) an entry on disk.
+ * The cache should already be updated.
+ */
int
id2entry_add( Backend *be, Entry *e )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- struct dbcache *db;
+ DBCache *db;
Datum key, data;
- int len, rc;
+ int len, rc, flags;
- Debug( LDAP_DEBUG_TRACE, "=> id2entry_add( %d, \"%s\" )\n", e->e_id,
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ Debug( LDAP_DEBUG_TRACE, "=> id2entry_add( %ld, \"%s\" )\n", e->e_id,
e->e_dn, 0 );
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
key.dptr = (char *) &e->e_id;
key.dsize = sizeof(ID);
- pthread_mutex_lock( &entry2str_mutex );
- data.dptr = entry2str( e, &len, 1 );
+ ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+ data.dptr = entry2str( e, &len );
data.dsize = len + 1;
- /* store it - LDBM_SYNC ensures id2entry is always consistent */
- rc = ldbm_cache_store( db, key, data, LDBM_REPLACE|LDBM_SYNC );
+ /* store it */
+ flags = LDBM_REPLACE;
+ if ( li->li_dbcachewsync ) flags |= LDBM_SYNC;
+ rc = ldbm_cache_store( db, key, data, flags );
- pthread_mutex_unlock( &entry2str_mutex );
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
ldbm_cache_close( be, db );
- (void) cache_add_entry_lock( &li->li_cache, e, 0 );
Debug( LDAP_DEBUG_TRACE, "<= id2entry_add %d\n", rc, 0, 0 );
+
return( rc );
}
id2entry_delete( Backend *be, Entry *e )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- struct dbcache *db;
+ DBCache *db;
Datum key;
int rc;
- Debug( LDAP_DEBUG_TRACE, "=> id2entry_delete( %d, \"%s\" )\n", e->e_id,
+ Debug(LDAP_DEBUG_TRACE, "=> id2entry_delete( %ld, \"%s\" )\n", e->e_id,
e->e_dn, 0 );
+#ifdef notdef
+#ifdef LDAP_DEBUG
+ /* check for writer lock */
+ assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1);
+#endif
+#endif
+
+ ldbm_datum_init( key );
+
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
- == NULL ) {
+ == NULL ) {
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
LDBM_SUFFIX, 0, 0 );
return( -1 );
}
if ( cache_delete_entry( &li->li_cache, e ) != 0 ) {
- Debug( LDAP_DEBUG_ANY, "could not delete %d (%s) from cache\n",
+ Debug(LDAP_DEBUG_ANY, "could not delete %ld (%s) from cache\n",
e->e_id, e->e_dn, 0 );
}
return( rc );
}
+/* returns entry with reader/writer lock */
Entry *
-id2entry( Backend *be, ID id )
+id2entry_rw( Backend *be, ID id, int rw )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- struct dbcache *db;
+ DBCache *db;
Datum key, data;
Entry *e;
- Debug( LDAP_DEBUG_TRACE, "=> id2entry( %ld )\n", id, 0, 0 );
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ Debug( LDAP_DEBUG_TRACE, "=> id2entry_%s( %ld )\n",
+ rw ? "w" : "r", id, 0 );
- if ( (e = cache_find_entry_id( &li->li_cache, id )) != NULL ) {
- Debug( LDAP_DEBUG_TRACE, "<= id2entry 0x%x (cache)\n", e, 0,
- 0 );
+ if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
+ rw ? "w" : "r", id, (unsigned long) e );
return( e );
}
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
- == NULL ) {
+ == NULL ) {
Debug( LDAP_DEBUG_ANY, "Could not open id2entry%s\n",
LDBM_SUFFIX, 0, 0 );
return( NULL );
data = ldbm_cache_fetch( db, key );
if ( data.dptr == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "<= id2entry( %ld ) not found\n", id,
- 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) not found\n",
+ rw ? "w" : "r", id, 0 );
ldbm_cache_close( be, db );
return( NULL );
}
- if ( (e = str2entry( data.dptr )) != NULL ) {
- e->e_id = id;
- (void) cache_add_entry_lock( &li->li_cache, e, 0 );
- }
-
+ e = str2entry( data.dptr );
ldbm_datum_free( db->dbc_db, data );
ldbm_cache_close( be, db );
- Debug( LDAP_DEBUG_TRACE, "<= id2entry( %ld ) 0x%x (disk)\n", id, e, 0 );
+ if ( e == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (failed)\n",
+ rw ? "w" : "r", id, 0 );
+ return( NULL );
+ }
+
+ e->e_id = id;
+
+ if( cache_add_entry_rw( &li->li_cache, e, rw ) != 0 ) {
+ entry_free( e );
+
+ /* XXX this is a kludge.
+ * maybe the entry got added underneath us
+ * There are many underlying race condtions in the cache/disk code.
+ */
+ if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
+ rw ? "w" : "r", id, (unsigned long) e );
+ return( e );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (cache add failed)\n",
+ rw ? "w" : "r", id, 0 );
+ return NULL;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (disk)\n",
+ rw ? "w" : "r", id, (unsigned long) e );
+
return( e );
}
/* idl.c - ldap id list handling routines */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "ldap_defaults.h"
#include "slap.h"
-#include "ldapconfig.h"
#include "back-ldbm.h"
-extern Datum ldbm_cache_fetch();
+static ID_BLOCK* idl_dup( ID_BLOCK *idl );
-IDList *
-idl_alloc( int nids )
+/* Allocate an ID_BLOCK with room for nids ids */
+ID_BLOCK *
+idl_alloc( unsigned int nids )
{
- IDList *new;
+ ID_BLOCK *new;
/* nmax + nids + space for the ids */
- new = (IDList *) ch_calloc( (2 + nids), sizeof(ID) );
- new->b_nmax = nids;
- new->b_nids = 0;
+ new = (ID_BLOCK *) ch_calloc( (ID_BLOCK_IDS_OFFSET + nids), sizeof(ID) );
+ ID_BLOCK_NMAX(new) = nids;
+ ID_BLOCK_NIDS(new) = 0;
return( new );
}
-IDList *
+
+/* Allocate an empty ALLIDS ID_BLOCK */
+ID_BLOCK *
idl_allids( Backend *be )
{
- IDList *idl;
+ ID_BLOCK *idl;
idl = idl_alloc( 0 );
- idl->b_nmax = ALLIDSBLOCK;
- idl->b_nids = next_id_get( be );
+ ID_BLOCK_NMAX(idl) = ID_BLOCK_ALLIDS_VALUE;
+ ID_BLOCK_NIDS(idl) = next_id_get( be );
return( idl );
}
+/* Free an ID_BLOCK */
void
-idl_free( IDList *idl )
+idl_free( ID_BLOCK *idl )
{
if ( idl == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "idl_free: called with NULL pointer\n",
+ 0, 0, 0 );
return;
}
free( (char *) idl );
}
-static IDList *
+
+/* Fetch an single ID_BLOCK from the cache */
+static ID_BLOCK *
idl_fetch_one(
Backend *be,
- struct dbcache *db,
+ DBCache *db,
Datum key
)
{
- Datum data, k2;
- IDList *idl;
- IDList **tmp;
- char *kstr;
- int i, nids;
+ Datum data;
+ ID_BLOCK *idl;
/* Debug( LDAP_DEBUG_TRACE, "=> idl_fetch_one\n", 0, 0, 0 ); */
data = ldbm_cache_fetch( db, key );
- idl = (IDList *) data.dptr;
+ if( data.dptr == NULL ) {
+ return NULL;
+ }
+
+ idl = idl_dup( (ID_BLOCK *) data.dptr);
+ ldbm_datum_free( db->dbc_db, data );
return( idl );
}
-IDList *
+
+/* Fetch a set of ID_BLOCKs from the cache
+ * if not INDIRECT
+ * if block return is an ALLIDS block,
+ * return an new ALLIDS block
+ * otherwise
+ * return block
+ * construct super block from all blocks referenced by INDIRECT block
+ * return super block
+ */
+ID_BLOCK *
idl_fetch(
Backend *be,
- struct dbcache *db,
+ DBCache *db,
Datum key
)
{
- Datum data, k2;
- IDList *idl;
- IDList **tmp;
+ Datum data;
+ ID_BLOCK *idl;
+ ID_BLOCK **tmp;
char *kstr;
int i, nids;
- /* Debug( LDAP_DEBUG_TRACE, "=> idl_fetch\n", 0, 0, 0 ); */
-
- data = ldbm_cache_fetch( db, key );
+ idl = idl_fetch_one( be, db, key );
- if ( (idl = (IDList *) data.dptr) == NULL ) {
- return( NULL );
+ if ( idl == NULL ) {
+ return NULL;
}
- /* regular block */
- if ( ! INDIRECT_BLOCK( idl ) ) {
- /*
- Debug( LDAP_DEBUG_TRACE, "<= idl_fetch %d ids (%d max)\n",
- idl->b_nids, idl->b_nmax, 0 );
- */
-
+ if ( ID_BLOCK_ALLIDS(idl) ) {
+ /* all ids block */
/* make sure we have the current value of highest id */
- if ( idl->b_nmax == ALLIDSBLOCK ) {
- idl_free( idl );
- idl = idl_allids( be );
- }
+ idl_free( idl );
+ idl = idl_allids( be );
+
+ return( idl );
+ }
+
+ if ( ! ID_BLOCK_INDIRECT( idl ) ) {
+ /* regular block */
return( idl );
}
*/
/* count the number of blocks & allocate space for pointers to them */
- for ( i = 0; idl->b_ids[i] != NOID; i++ )
+ for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ )
; /* NULL */
- tmp = (IDList **) ch_malloc( (i + 1) * sizeof(IDList *) );
+ tmp = (ID_BLOCK **) ch_malloc( (i + 1) * sizeof(ID_BLOCK *) );
/* read in all the blocks */
- kstr = (char *) ch_malloc( key.dsize + 20 );
+ kstr = (char *) ch_malloc( key.dsize + CONT_SIZE );
nids = 0;
- for ( i = 0; idl->b_ids[i] != NOID; i++ ) {
- sprintf( kstr, "%c%s%d", CONT_PREFIX, key.dptr, idl->b_ids[i] );
- k2.dptr = kstr;
- k2.dsize = strlen( kstr ) + 1;
+ for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) {
+ ldbm_datum_init( data );
- if ( (tmp[i] = idl_fetch_one( be, db, k2 )) == NULL ) {
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(idl, i), key.dptr );
+
+ data.dptr = kstr;
+ data.dsize = strlen( kstr ) + 1;
+
+ if ( (tmp[i] = idl_fetch_one( be, db, data )) == NULL ) {
Debug( LDAP_DEBUG_ANY,
- "idl_fetch of (%s) returns NULL\n", k2.dptr, 0, 0 );
+ "idl_fetch of (%s) returns NULL\n", data.dptr, 0, 0 );
continue;
}
- nids += tmp[i]->b_nids;
+ nids += ID_BLOCK_NIDS(tmp[i]);
}
tmp[i] = NULL;
+ free( kstr );
idl_free( idl );
/* allocate space for the big block */
idl = idl_alloc( nids );
- idl->b_nids = nids;
+ ID_BLOCK_NIDS(idl) = nids;
nids = 0;
/* copy in all the ids from the component blocks */
continue;
}
- SAFEMEMCPY( (char *) &idl->b_ids[nids], (char *) tmp[i]->b_ids,
- tmp[i]->b_nids * sizeof(ID) );
- nids += tmp[i]->b_nids;
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(idl, nids),
+ (char *) &ID_BLOCK_ID(tmp[i], 0),
+ ID_BLOCK_NIDS(tmp[i]) * sizeof(ID) );
+ nids += ID_BLOCK_NIDS(tmp[i]);
idl_free( tmp[i] );
}
free( (char *) tmp );
- Debug( LDAP_DEBUG_TRACE, "<= idl_fetch %d ids (%d max)\n", idl->b_nids,
- idl->b_nmax, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= idl_fetch %ld ids (%ld max)\n",
+ ID_BLOCK_NIDS(idl), ID_BLOCK_NMAX(idl), 0 );
return( idl );
}
+
+/* store a single block */
static int
idl_store(
Backend *be,
- struct dbcache *db,
+ DBCache *db,
Datum key,
- IDList *idl
+ ID_BLOCK *idl
)
{
- int rc;
+ int rc, flags;
Datum data;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ ldbm_datum_init( data );
/* Debug( LDAP_DEBUG_TRACE, "=> idl_store\n", 0, 0, 0 ); */
data.dptr = (char *) idl;
- data.dsize = (2 + idl->b_nmax) * sizeof(ID);
+ data.dsize = (ID_BLOCK_IDS_OFFSET + ID_BLOCK_NMAX(idl)) * sizeof(ID);
+
+#ifdef LDBM_DEBUG
+ Statslog( LDAP_DEBUG_STATS, "<= idl_store(): rc=%d\n",
+ rc, 0, 0, 0, 0 );
+#endif
- rc = ldbm_cache_store( db, key, data, LDBM_REPLACE );
+ flags = LDBM_REPLACE;
+ if( li->li_dbcachewsync ) flags |= LDBM_SYNC;
+ rc = ldbm_cache_store( db, key, data, flags );
/* Debug( LDAP_DEBUG_TRACE, "<= idl_store %d\n", rc, 0, 0 ); */
return( rc );
}
+/* split the block at id
+ * locate ID greater than or equal to id.
+ */
static void
idl_split_block(
- IDList *b,
+ ID_BLOCK *b,
ID id,
- IDList **n1,
- IDList **n2
+ ID_BLOCK **right,
+ ID_BLOCK **left
)
{
- int i;
+ unsigned int nr, nl;
- /* find where to split the block */
- for ( i = 0; i < b->b_nids && id > b->b_ids[i]; i++ )
+ /* find where to split the block *//* XXX linear search XXX */
+ for ( nr = 0; nr < ID_BLOCK_NIDS(b) && id > ID_BLOCK_ID(b, nr); nr++ )
; /* NULL */
- *n1 = idl_alloc( i == 0 ? 1 : i );
- *n2 = idl_alloc( b->b_nids - i + (i == 0 ? 0 : 1));
+ nl = ID_BLOCK_NIDS(b) - nr;
+
+ *right = idl_alloc( nr == 0 ? 1 : nr );
+ *left = idl_alloc( nl + (nr == 0 ? 0 : 1));
/*
* everything before the id being inserted in the first block
* unless there is nothing, in which case the id being inserted
* goes there.
*/
- SAFEMEMCPY( (char *) &(*n1)->b_ids[0], (char *) &b->b_ids[0],
- i * sizeof(ID) );
- (*n1)->b_nids = (i == 0 ? 1 : i);
-
- if ( i == 0 ) {
- (*n1)->b_ids[0] = id;
+ if ( nr == 0 ) {
+ ID_BLOCK_NIDS(*right) = 1;
+ ID_BLOCK_ID(*right, 0) = id;
} else {
- (*n2)->b_ids[0] = id;
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(*right, 0),
+ (char *) &ID_BLOCK_ID(b, 0),
+ nr * sizeof(ID) );
+ ID_BLOCK_NIDS(*right) = nr;
+ ID_BLOCK_ID(*left, 0) = id;
}
/* the id being inserted & everything after in the second block */
- SAFEMEMCPY( (char *) &(*n2)->b_ids[i == 0 ? 0 : 1],
- (char *) &b->b_ids[i], (b->b_nids - i) * sizeof(ID) );
- (*n2)->b_nids = b->b_nids - i + (i == 0 ? 0 : 1);
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(*left, (nr == 0 ? 0 : 1)),
+ (char *) &ID_BLOCK_ID(b, nr),
+ nl * sizeof(ID) );
+ ID_BLOCK_NIDS(*left) = nl + (nr == 0 ? 0 : 1);
}
+
/*
* idl_change_first - called when an indirect block's first key has
* changed, meaning it needs to be stored under a new key, and the
* header block pointing to it needs updating.
*/
-
static int
idl_change_first(
Backend *be,
- struct dbcache *db,
+ DBCache *db,
Datum hkey, /* header block key */
- IDList *h, /* header block */
+ ID_BLOCK *h, /* header block */
int pos, /* pos in h to update */
Datum bkey, /* data block key */
- IDList *b /* data block */
+ ID_BLOCK *b /* data block */
)
{
int rc;
}
/* write block with new key */
- sprintf( bkey.dptr, "%c%s%d", CONT_PREFIX, hkey.dptr, b->b_ids[0] );
+ sprintf( bkey.dptr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(b, 0), hkey.dptr );
+
bkey.dsize = strlen( bkey.dptr ) + 1;
if ( (rc = idl_store( be, db, bkey, b )) != 0 ) {
Debug( LDAP_DEBUG_ANY,
}
/* update + write indirect header block */
- h->b_ids[pos] = b->b_ids[0];
+ ID_BLOCK_ID(h, pos) = ID_BLOCK_ID(b, 0);
if ( (rc = idl_store( be, db, hkey, h )) != 0 ) {
Debug( LDAP_DEBUG_ANY,
"idl_store of (%s) returns %d\n", hkey.dptr, rc, 0 );
return( 0 );
}
+
int
idl_insert_key(
Backend *be,
- struct dbcache *db,
+ DBCache *db,
Datum key,
ID id
)
{
int i, j, first, rc;
- IDList *idl, *tmp, *tmp2, *tmp3;
+ ID_BLOCK *idl, *tmp, *tmp2, *tmp3;
char *kstr;
Datum k2;
+ ldbm_datum_init( k2 );
+
if ( (idl = idl_fetch_one( be, db, key )) == NULL ) {
+#ifdef LDBM_DEBUG
+ Statslog( LDAP_DEBUG_STATS, "=> idl_insert_key(): no key yet\n",
+ 0, 0, 0, 0, 0 );
+#endif
+
idl = idl_alloc( 1 );
- idl->b_ids[idl->b_nids++] = id;
+ ID_BLOCK_ID(idl, ID_BLOCK_NIDS(idl)++) = id;
rc = idl_store( be, db, key, idl );
idl_free( idl );
return( rc );
}
- /* regular block */
- if ( ! INDIRECT_BLOCK( idl ) ) {
+ if ( ID_BLOCK_ALLIDS( idl ) ) {
+ /* ALLIDS */
+ idl_free( idl );
+ return 0;
+ }
+
+ if ( ! ID_BLOCK_INDIRECT( idl ) ) {
+ /* regular block */
switch ( idl_insert( &idl, id, db->dbc_maxids ) ) {
case 0: /* id inserted - store the updated block */
case 1:
idl_free( idl );
idl = idl_allids( be );
rc = idl_store( be, db, key, idl );
- idl_free( idl );
-
- return( rc );
+ break;
}
idl_split_block( idl, id, &tmp, &tmp2 );
/* create the header indirect block */
idl = idl_alloc( 3 );
- idl->b_nmax = 3;
- idl->b_nids = INDBLOCK;
- idl->b_ids[0] = tmp->b_ids[0];
- idl->b_ids[1] = tmp2->b_ids[0];
- idl->b_ids[2] = NOID;
+ ID_BLOCK_NMAX(idl) = 3;
+ ID_BLOCK_NIDS(idl) = ID_BLOCK_INDIRECT_VALUE;
+ ID_BLOCK_ID(idl, 0) = ID_BLOCK_ID(tmp, 0);
+ ID_BLOCK_ID(idl, 1) = ID_BLOCK_ID(tmp2, 0);
+ ID_BLOCK_ID(idl, 2) = NOID;
/* store it */
rc = idl_store( be, db, key, idl );
/* store the first id block */
- kstr = (char *) ch_malloc( key.dsize + 20 );
- sprintf( kstr, "%c%s%d", CONT_PREFIX, key.dptr,
- tmp->b_ids[0] );
+ kstr = (char *) ch_malloc( key.dsize + CONT_SIZE );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(tmp, 0), key.dptr );
+
k2.dptr = kstr;
k2.dsize = strlen( kstr ) + 1;
rc = idl_store( be, db, k2, tmp );
/* store the second id block */
- sprintf( kstr, "%c%s%d", CONT_PREFIX, key.dptr,
- tmp2->b_ids[0] );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(tmp2, 0), key.dptr );
k2.dptr = kstr;
k2.dsize = strlen( kstr ) + 1;
rc = idl_store( be, db, k2, tmp2 );
* need to write a new "header" block.
*/
- /* select the block to try inserting into */
- for ( i = 0; idl->b_ids[i] != NOID && id > idl->b_ids[i]; i++ )
+ /* select the block to try inserting into *//* XXX linear search XXX */
+ for ( i = 0; !ID_BLOCK_NOID(idl, i) && id > ID_BLOCK_ID(idl, i); i++ )
; /* NULL */
if ( i != 0 ) {
i--;
}
/* get the block */
- kstr = (char *) ch_malloc( key.dsize + 20 );
- sprintf( kstr, "%c%s%d", CONT_PREFIX, key.dptr, idl->b_ids[i] );
+ kstr = (char *) ch_malloc( key.dsize + CONT_SIZE );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(idl, i), key.dptr );
k2.dptr = kstr;
k2.dsize = strlen( kstr ) + 1;
if ( (tmp = idl_fetch_one( be, db, k2 )) == NULL ) {
Debug( LDAP_DEBUG_ANY, "nonexistent continuation block (%s)\n",
k2.dptr, 0, 0 );
+ free( kstr );
+ idl_free( idl );
return( -1 );
}
*/
/* is there a next block? */
- if ( !first && idl->b_ids[i + 1] != NOID ) {
+ if ( !first && !ID_BLOCK_NOID(idl, i + 1) ) {
/* read it in */
- sprintf( kstr, "%c%s%d", CONT_PREFIX, key.dptr,
- idl->b_ids[i + 1] );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(idl, i + 1), key.dptr );
k2.dptr = kstr;
k2.dsize = strlen( kstr ) + 1;
if ( (tmp2 = idl_fetch_one( be, db, k2 )) == NULL ) {
case 0: /* id inserted */
if ( rc == 2 ) {
Debug( LDAP_DEBUG_ANY,
- "id %d already in next block\n",
+ "id %ld already in next block\n",
id, 0, 0 );
}
free( kstr );
return( 0 );
case 3: /* split the original block */
- idl_free( tmp2 );
break;
}
-
+ idl_free( tmp2 );
}
/*
* and write the indirect header block.
*/
- /* count how many indirect blocks */
- for ( j = 0; idl->b_ids[j] != NOID; j++ )
+ /* count how many indirect blocks *//* XXX linear count XXX */
+ for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ )
; /* NULL */
/* check it against all-id thresholed */
*/
/* delete all indirect blocks */
- for ( j = 0; idl->b_ids[j] != NOID; j++ ) {
- sprintf( kstr, "%c%s%d", CONT_PREFIX, key.dptr,
- idl->b_ids[j] );
+ for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ ) {
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(idl, j), key.dptr );
k2.dptr = kstr;
k2.dsize = strlen( kstr ) + 1;
idl_free( tmp );
/* create a new updated indirect header block */
- tmp = idl_alloc( idl->b_nmax + 1 );
- tmp->b_nids = INDBLOCK;
+ tmp = idl_alloc( ID_BLOCK_NMAX(idl) + 1 );
+ ID_BLOCK_NIDS(tmp) = ID_BLOCK_INDIRECT_VALUE;
/* everything up to the split block */
- SAFEMEMCPY( (char *) tmp->b_ids, (char *) idl->b_ids,
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(tmp, 0),
+ (char *) &ID_BLOCK_ID(idl, 0),
i * sizeof(ID) );
/* the two new blocks */
- tmp->b_ids[i] = tmp2->b_ids[0];
- tmp->b_ids[i + 1] = tmp3->b_ids[0];
+ ID_BLOCK_ID(tmp, i) = ID_BLOCK_ID(tmp2, 0);
+ ID_BLOCK_ID(tmp, i + 1) = ID_BLOCK_ID(tmp3, 0);
/* everything after the split block */
- SAFEMEMCPY( (char *) &tmp->b_ids[i + 2], (char *)
- &idl->b_ids[i + 1], (idl->b_nmax - i - 1) * sizeof(ID) );
+ SAFEMEMCPY(
+ (char *) &ID_BLOCK_ID(tmp, i + 2),
+ (char *) &ID_BLOCK_ID(idl, i + 1),
+ (ID_BLOCK_NMAX(idl) - i - 1) * sizeof(ID) );
/* store the header block */
rc = idl_store( be, db, key, tmp );
/* store the first id block */
- sprintf( kstr, "%c%s%d", CONT_PREFIX, key.dptr,
- tmp2->b_ids[0] );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(tmp2, 0), key.dptr );
k2.dptr = kstr;
k2.dsize = strlen( kstr ) + 1;
rc = idl_store( be, db, k2, tmp2 );
/* store the second id block */
- sprintf( kstr, "%c%s%d", CONT_PREFIX, key.dptr,
- tmp3->b_ids[0] );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(tmp3, 0), key.dptr );
k2.dptr = kstr;
k2.dsize = strlen( kstr ) + 1;
rc = idl_store( be, db, k2, tmp3 );
return( rc );
}
+
/*
* idl_insert - insert an id into an id list.
- * returns 0 id inserted
+ *
+ * returns
+ * 0 id inserted
* 1 id inserted, first id in block has changed
* 2 id not inserted, already there
* 3 id not inserted, block must be split
*/
-
int
-idl_insert( IDList **idl, ID id, int maxids )
+idl_insert( ID_BLOCK **idl, ID id, unsigned int maxids )
{
- int i, j;
+ unsigned int i;
- if ( ALLIDS( *idl ) ) {
+ if ( ID_BLOCK_ALLIDS( *idl ) ) {
return( 2 ); /* already there */
}
- /* is it already there? XXX bin search XXX */
- for ( i = 0; i < (*idl)->b_nids && id > (*idl)->b_ids[i]; i++ ) {
+ /* is it already there? *//* XXX linear search XXX */
+ for ( i = 0; i < ID_BLOCK_NIDS(*idl) && id > ID_BLOCK_ID(*idl, i); i++ ) {
; /* NULL */
}
- if ( i < (*idl)->b_nids && (*idl)->b_ids[i] == id ) {
+ if ( i < ID_BLOCK_NIDS(*idl) && ID_BLOCK_ID(*idl, i) == id ) {
return( 2 ); /* already there */
}
/* do we need to make room for it? */
- if ( (*idl)->b_nids == (*idl)->b_nmax ) {
+ if ( ID_BLOCK_NIDS(*idl) == ID_BLOCK_NMAX(*idl) ) {
/* make room or indicate block needs splitting */
- if ( (*idl)->b_nmax == maxids ) {
+ if ( ID_BLOCK_NMAX(*idl) >= maxids ) {
return( 3 ); /* block needs splitting */
}
- (*idl)->b_nmax *= 2;
- if ( (*idl)->b_nmax > maxids ) {
- (*idl)->b_nmax = maxids;
+ ID_BLOCK_NMAX(*idl) *= 2;
+ if ( ID_BLOCK_NMAX(*idl) > maxids ) {
+ ID_BLOCK_NMAX(*idl) = maxids;
}
- *idl = (IDList *) ch_realloc( (char *) *idl,
- ((*idl)->b_nmax + 2) * sizeof(ID) );
+ *idl = (ID_BLOCK *) ch_realloc( (char *) *idl,
+ (ID_BLOCK_NMAX(*idl) + ID_BLOCK_IDS_OFFSET) * sizeof(ID) );
}
/* make a slot for the new id */
- for ( j = (*idl)->b_nids; j != i; j-- ) {
- (*idl)->b_ids[j] = (*idl)->b_ids[j-1];
- }
- (*idl)->b_ids[i] = id;
- (*idl)->b_nids++;
- (void) memset( (char *) &(*idl)->b_ids[(*idl)->b_nids], '\0',
- ((*idl)->b_nmax - (*idl)->b_nids) * sizeof(ID) );
+ SAFEMEMCPY( &ID_BLOCK_ID(*idl, i), &ID_BLOCK_ID(*idl, i+1),
+ ID_BLOCK_NIDS(*idl) - i );
+
+ ID_BLOCK_ID(*idl, i) = id;
+ ID_BLOCK_NIDS(*idl)++;
+ (void) memset(
+ (char *) &ID_BLOCK_ID((*idl), ID_BLOCK_NIDS(*idl)),
+ '\0',
+ (ID_BLOCK_NMAX(*idl) - ID_BLOCK_NIDS(*idl)) * sizeof(ID) );
return( i == 0 ? 1 : 0 ); /* inserted - first id changed or not */
}
-static IDList *
-idl_dup( IDList *idl )
+
+int
+idl_delete_key (
+ Backend *be,
+ DBCache *db,
+ Datum key,
+ ID id
+)
+{
+ Datum data;
+ ID_BLOCK *idl, *tmp;
+ unsigned i;
+ int j, nids;
+ char *kstr;
+
+ if ( (idl = idl_fetch_one( be, db, key ) ) == NULL )
+ {
+ /* It wasn't found. Hmm... */
+ return -1;
+ }
+
+ if ( ID_BLOCK_ALLIDS( idl ) ) {
+ idl_free( idl );
+ return 0;
+ }
+
+ if ( ! ID_BLOCK_INDIRECT( idl ) ) {
+ for ( i=0; i < ID_BLOCK_NIDS(idl); i++ ) {
+ if ( ID_BLOCK_ID(idl, i) == id ) {
+ if( --ID_BLOCK_NIDS(idl) == 0 ) {
+ ldbm_cache_delete( db, key );
+
+ } else {
+ SAFEMEMCPY (
+ &ID_BLOCK_ID(idl, i),
+ &ID_BLOCK_ID(idl, i+1),
+ (ID_BLOCK_NIDS(idl)-i) * sizeof(ID) );
+
+ ID_BLOCK_ID(idl, ID_BLOCK_NIDS(idl)) = NOID;
+
+ idl_store( be, db, key, idl );
+ }
+
+ idl_free( idl );
+ return 0;
+ }
+ /* We didn't find the ID. Hmmm... */
+ }
+ idl_free( idl );
+ return -1;
+ }
+
+ /* We have to go through an indirect block and find the ID
+ in the list of IDL's
+ */
+ for ( nids = 0; !ID_BLOCK_NOID(idl, nids); nids++ )
+ ; /* NULL */
+ kstr = (char *) ch_malloc( key.dsize + CONT_SIZE );
+
+ for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ )
+ {
+ ldbm_datum_init( data );
+ sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+ ID_BLOCK_ID(idl, j), key.dptr );
+ data.dptr = kstr;
+ data.dsize = strlen( kstr ) + 1;
+
+ if ( (tmp = idl_fetch_one( be, db, data )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "idl_fetch of (%s) returns NULL\n", data.dptr, 0, 0 );
+ continue;
+ }
+ /*
+ Now try to find the ID in tmp
+ */
+ for ( i=0; i < ID_BLOCK_NIDS(tmp); i++ )
+ {
+ if ( ID_BLOCK_ID(tmp, i) == id )
+ {
+ SAFEMEMCPY(
+ &ID_BLOCK_ID(tmp, i),
+ &ID_BLOCK_ID(tmp, i+1),
+ (ID_BLOCK_NIDS(tmp)-(i+1)) * sizeof(ID));
+ ID_BLOCK_ID(tmp, ID_BLOCK_NIDS(tmp)-1 ) = NOID;
+ ID_BLOCK_NIDS(tmp)--;
+
+ if ( ID_BLOCK_NIDS(tmp) ) {
+ idl_store ( be, db, data, tmp );
+
+ } else {
+ ldbm_cache_delete( db, data );
+ SAFEMEMCPY(
+ &ID_BLOCK_ID(idl, j),
+ &ID_BLOCK_ID(idl, j+1),
+ (nids-(j+1)) * sizeof(ID));
+ ID_BLOCK_ID(idl, nids-1) = NOID;
+ nids--;
+ if ( ! nids )
+ ldbm_cache_delete( db, key );
+ else
+ idl_store( be, db, key, idl );
+ }
+ idl_free( tmp );
+ free( kstr );
+ idl_free( idl );
+ return 0;
+ }
+ }
+ idl_free( tmp );
+ }
+ free( kstr );
+ idl_free( idl );
+ return -1;
+}
+
+
+/* return a duplicate of a single ID_BLOCK */
+static ID_BLOCK *
+idl_dup( ID_BLOCK *idl )
{
- IDList *new;
+ ID_BLOCK *new;
if ( idl == NULL ) {
return( NULL );
}
- new = idl_alloc( idl->b_nmax );
- SAFEMEMCPY( (char *) new, (char *) idl, (idl->b_nmax + 2)
- * sizeof(ID) );
+ new = idl_alloc( ID_BLOCK_NMAX(idl) );
+
+ SAFEMEMCPY(
+ (char *) new,
+ (char *) idl,
+ (ID_BLOCK_NMAX(idl) + ID_BLOCK_IDS_OFFSET) * sizeof(ID) );
return( new );
}
-static IDList *
-idl_min( IDList *a, IDList *b )
+
+/* return the smaller ID_BLOCK */
+static ID_BLOCK *
+idl_min( ID_BLOCK *a, ID_BLOCK *b )
{
- return( a->b_nids > b->b_nids ? b : a );
+ return( ID_BLOCK_NIDS(a) > ID_BLOCK_NIDS(b) ? b : a );
}
+
/*
* idl_intersection - return a intersection b
*/
-
-IDList *
+ID_BLOCK *
idl_intersection(
Backend *be,
- IDList *a,
- IDList *b
+ ID_BLOCK *a,
+ ID_BLOCK *b
)
{
- int ai, bi, ni;
- IDList *n;
+ unsigned int ai, bi, ni;
+ ID_BLOCK *n;
if ( a == NULL || b == NULL ) {
return( NULL );
}
- if ( ALLIDS( a ) ) {
+ if ( ID_BLOCK_ALLIDS( a ) ) {
return( idl_dup( b ) );
}
- if ( ALLIDS( b ) ) {
+ if ( ID_BLOCK_ALLIDS( b ) ) {
return( idl_dup( a ) );
}
n = idl_dup( idl_min( a, b ) );
- for ( ni = 0, ai = 0, bi = 0; ai < a->b_nids; ai++ ) {
- for ( ; bi < b->b_nids && b->b_ids[bi] < a->b_ids[ai]; bi++ )
+ for ( ni = 0, ai = 0, bi = 0; ai < ID_BLOCK_NIDS(a); ai++ ) {
+ for ( ;
+ bi < ID_BLOCK_NIDS(b) && ID_BLOCK_ID(b, bi) < ID_BLOCK_ID(a, ai);
+ bi++ )
+ {
; /* NULL */
+ }
- if ( bi == b->b_nids ) {
+ if ( bi == ID_BLOCK_NIDS(b) ) {
break;
}
- if ( b->b_ids[bi] == a->b_ids[ai] ) {
- n->b_ids[ni++] = a->b_ids[ai];
+ if ( ID_BLOCK_ID(b, bi) == ID_BLOCK_ID(a, ai) ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
}
}
idl_free( n );
return( NULL );
}
- n->b_nids = ni;
+ ID_BLOCK_NIDS(n) = ni;
return( n );
}
+
/*
* idl_union - return a union b
*/
-
-IDList *
+ID_BLOCK *
idl_union(
Backend *be,
- IDList *a,
- IDList *b
+ ID_BLOCK *a,
+ ID_BLOCK *b
)
{
- int ai, bi, ni;
- IDList *n;
+ unsigned int ai, bi, ni;
+ ID_BLOCK *n;
if ( a == NULL ) {
return( idl_dup( b ) );
if ( b == NULL ) {
return( idl_dup( a ) );
}
- if ( ALLIDS( a ) || ALLIDS( b ) ) {
+ if ( ID_BLOCK_ALLIDS( a ) || ID_BLOCK_ALLIDS( b ) ) {
return( idl_allids( be ) );
}
- if ( b->b_nids < a->b_nids ) {
+ if ( ID_BLOCK_NIDS(b) < ID_BLOCK_NIDS(a) ) {
n = a;
a = b;
b = n;
}
- n = idl_alloc( a->b_nids + b->b_nids );
+ n = idl_alloc( ID_BLOCK_NIDS(a) + ID_BLOCK_NIDS(b) );
+
+ for ( ni = 0, ai = 0, bi = 0;
+ ai < ID_BLOCK_NIDS(a) && bi < ID_BLOCK_NIDS(b);
+ )
+ {
+ if ( ID_BLOCK_ID(a, ai) < ID_BLOCK_ID(b, bi) ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai++);
+
+ } else if ( ID_BLOCK_ID(b, bi) < ID_BLOCK_ID(a, ai) ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(b, bi++);
- for ( ni = 0, ai = 0, bi = 0; ai < a->b_nids && bi < b->b_nids; ) {
- if ( a->b_ids[ai] < b->b_ids[bi] ) {
- n->b_ids[ni++] = a->b_ids[ai++];
- } else if ( b->b_ids[bi] < a->b_ids[ai] ) {
- n->b_ids[ni++] = b->b_ids[bi++];
} else {
- n->b_ids[ni++] = a->b_ids[ai];
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
ai++, bi++;
}
}
- for ( ; ai < a->b_nids; ai++ ) {
- n->b_ids[ni++] = a->b_ids[ai];
+ for ( ; ai < ID_BLOCK_NIDS(a); ai++ ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
}
- for ( ; bi < b->b_nids; bi++ ) {
- n->b_ids[ni++] = b->b_ids[bi];
+ for ( ; bi < ID_BLOCK_NIDS(b); bi++ ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(b, bi);
}
- n->b_nids = ni;
+ ID_BLOCK_NIDS(n) = ni;
return( n );
}
+
/*
* idl_notin - return a intersection ~b (or a minus b)
*/
-
-IDList *
+ID_BLOCK *
idl_notin(
Backend *be,
- IDList *a,
- IDList *b
+ ID_BLOCK *a,
+ ID_BLOCK *b
)
{
- int ni, ai, bi;
- IDList *n;
+ unsigned int ni, ai, bi;
+ ID_BLOCK *n;
if ( a == NULL ) {
return( NULL );
}
- if ( b == NULL ) {
+ if ( b == NULL || ID_BLOCK_ALLIDS( b )) {
return( idl_dup( a ) );
}
- if ( ALLIDS( b ) ) {
- return( NULL );
- }
- if ( ALLIDS( a ) ) {
+ if ( ID_BLOCK_ALLIDS( a ) ) {
n = idl_alloc( SLAPD_LDBM_MIN_MAXIDS );
ni = 0;
- for ( ai = 1, bi = 0; ai < a->b_nids && ni < n->b_nmax &&
- bi < b->b_nmax; ai++ ) {
- if ( b->b_ids[bi] == ai ) {
+ for ( ai = 1, bi = 0;
+ ai < ID_BLOCK_NIDS(a) && ni < ID_BLOCK_NMAX(n) && bi < ID_BLOCK_NMAX(b);
+ ai++ )
+ {
+ if ( ID_BLOCK_ID(b, bi) == ai ) {
bi++;
} else {
- n->b_ids[ni++] = ai;
+ ID_BLOCK_ID(n, ni++) = ai;
}
}
- for ( ; ai < a->b_nids && ni < n->b_nmax; ai++ ) {
- n->b_ids[ni++] = ai;
+ for ( ; ai < ID_BLOCK_NIDS(a) && ni < ID_BLOCK_NMAX(n); ai++ ) {
+ ID_BLOCK_ID(n, ni++) = ai;
}
- if ( ni == n->b_nmax ) {
+ if ( ni == ID_BLOCK_NMAX(n) ) {
idl_free( n );
return( idl_allids( be ) );
} else {
- n->b_nids = ni;
+ ID_BLOCK_NIDS(n) = ni;
return( n );
}
}
n = idl_dup( a );
ni = 0;
- for ( ai = 0, bi = 0; ai < a->b_nids; ai++ ) {
- for ( ; bi < b->b_nids && b->b_ids[bi] < a->b_ids[ai];
- bi++ ) {
+ for ( ai = 0, bi = 0; ai < ID_BLOCK_NIDS(a); ai++ ) {
+ for ( ;
+ bi < ID_BLOCK_NIDS(b) && ID_BLOCK_ID(b, bi) < ID_BLOCK_ID(a, ai);
+ bi++ )
+ {
; /* NULL */
}
- if ( bi == b->b_nids ) {
+ if ( bi == ID_BLOCK_NIDS(b) ) {
break;
}
- if ( b->b_ids[bi] != a->b_ids[ai] ) {
- n->b_ids[ni++] = a->b_ids[ai];
+ if ( ID_BLOCK_ID(b, bi) != ID_BLOCK_ID(a, ai) ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
}
}
- for ( ; ai < a->b_nids; ai++ ) {
- n->b_ids[ni++] = a->b_ids[ai];
+ for ( ; ai < ID_BLOCK_NIDS(a); ai++ ) {
+ ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai);
}
- n->b_nids = ni;
+ ID_BLOCK_NIDS(n) = ni;
return( n );
}
+/* return the first ID in the block
+ * if ALLIDS block
+ * NIDS > 1 return 1
+ * otherwise return NOID
+ * otherwise return first ID
+ *
+ * cursor is set to 1
+ */
ID
-idl_firstid( IDList *idl )
+idl_firstid( ID_BLOCK *idl, ID *cursor )
{
- if ( idl == NULL || idl->b_nids == 0 ) {
+ *cursor = 1;
+
+ if ( idl == NULL || ID_BLOCK_NIDS(idl) == 0 ) {
return( NOID );
}
- if ( ALLIDS( idl ) ) {
- return( idl->b_nids == 1 ? NOID : 1 );
+ if ( ID_BLOCK_ALLIDS( idl ) ) {
+ return( ID_BLOCK_NIDS(idl) > 1 ? 1 : NOID );
}
- return( idl->b_ids[0] );
+ return( ID_BLOCK_ID(idl, 0) );
}
+/* return next ID
+ * if ALLIDS block, cursor is id.
+ * increment id
+ * if id < NIDS return id
+ * otherwise NOID.
+ * otherwise cursor is index into block
+ * if index < nids
+ * return id at index then increment
+ */
ID
-idl_nextid( IDList *idl, ID id )
+idl_nextid( ID_BLOCK *idl, ID *cursor )
{
- int i;
-
- if ( ALLIDS( idl ) ) {
- return( ++id < idl->b_nids ? id : NOID );
+ if ( ID_BLOCK_ALLIDS( idl ) ) {
+ if( ++(*cursor) < ID_BLOCK_NIDS(idl) ) {
+ return *cursor;
+ } else {
+ return NOID;
+ }
}
- for ( i = 0; i < idl->b_nids && idl->b_ids[i] < id; i++ ) {
- ; /* NULL */
+ if ( *cursor < ID_BLOCK_NIDS(idl) ) {
+ return( ID_BLOCK_ID(idl, (*cursor)++) );
}
- i++;
- if ( i >= idl->b_nids ) {
- return( NOID );
- } else {
- return( idl->b_ids[i] );
- }
+ return( NOID );
}
/* index.c - routines for dealing with attribute indexes */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-#include "back-ldbm.h"
-extern char *first_word();
-extern char *next_word();
-extern char *phonetic();
-extern IDList *idl_fetch();
-extern IDList *idl_allids();
-extern struct dbcache *ldbm_cache_open();
+#include <ac/string.h>
+#include <ac/socket.h>
-int index_add_values();
+#include "slap.h"
+#include "back-ldbm.h"
-static int add_value();
-static int index2prefix();
+static int change_value(Backend *be,
+ DBCache *db,
+ char *type,
+ int indextype,
+ char *val,
+ ID id,
+ int
+ (*idl_func)(Backend *, DBCache *, Datum, ID));
+static int index2prefix(int indextype);
int
index_add_entry(
)
{
Attribute *ap;
- char *dnval;
struct berval bv;
struct berval *bvals[2];
/*
* dn index entry - make it look like an attribute so it works
- * with index_add_values() call
+ * with index_change_values() call
*/
- bv.bv_val = strdup( e->e_dn );
+ bv.bv_val = ch_strdup( e->e_ndn );
bv.bv_len = strlen( bv.bv_val );
- (void) dn_normalize_case( bv.bv_val );
bvals[0] = &bv;
bvals[1] = NULL;
/* add the dn to the indexes */
- index_add_values( be, "dn", bvals, e->e_id );
+ {
+ char *dn = ch_strdup("dn");
+ index_change_values( be, dn, bvals, e->e_id, SLAP_INDEX_ADD_OP );
+ free( dn );
+ }
free( bv.bv_val );
/* add each attribute to the indexes */
for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
- index_add_values( be, ap->a_type, ap->a_vals, e->e_id );
+ index_change_values( be, ap->a_type, ap->a_vals, e->e_id,
+ SLAP_INDEX_ADD_OP );
}
Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
- e->e_dn, 0 );
+ e->e_ndn, 0 );
return( 0 );
}
int
index_add_mods(
Backend *be,
- LDAPMod *mods,
+ LDAPModList *ml,
ID id
)
{
int rc;
- for ( ; mods != NULL; mods = mods->mod_next ) {
- switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) {
- case LDAP_MOD_ADD:
+ for ( ; ml != NULL; ml = ml->ml_next ) {
+ LDAPMod *mod = &ml->ml_mod;
+
+ switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_REPLACE:
- rc = index_add_values( be, mods->mod_type,
- mods->mod_bvalues, id );
+ /* XXX: Delete old index data==>problem when this
+ * gets called we lost values already!
+ */
+ case LDAP_MOD_ADD:
+ rc = index_change_values( be,
+ mod->mod_type,
+ mod->mod_bvalues,
+ id,
+ SLAP_INDEX_ADD_OP );
break;
-
case LDAP_MOD_DELETE:
+ rc = index_change_values( be,
+ mod->mod_type,
+ mod->mod_bvalues,
+ id,
+ SLAP_INDEX_DELETE_OP );
+ break;
+ case LDAP_MOD_SOFTADD: /* SOFTADD means index was there */
rc = 0;
break;
}
return( 0 );
}
-IDList *
+ID_BLOCK *
index_read(
Backend *be,
char *type,
char *val
)
{
- struct dbcache *db;
+ DBCache *db;
Datum key;
- IDList *idl;
+ ID_BLOCK *idl;
int indexmask, syntax;
char prefix;
char *realval, *tmpval;
char buf[BUFSIZ];
+ char *at_cn;
+
+ ldbm_datum_init( key );
+
prefix = index2prefix( indextype );
- Debug( LDAP_DEBUG_TRACE, "=> index_read( \"%s\" \"%c\" \"%s\" )\n",
- type, prefix, val );
+ Debug( LDAP_DEBUG_TRACE, "=> index_read(\"%c%s\"->\"%s\")\n",
+ prefix, type, val );
attr_masks( be->be_private, type, &indexmask, &syntax );
if ( ! (indextype & indexmask) ) {
idl = idl_allids( be );
Debug( LDAP_DEBUG_TRACE,
- "<= index_read %d candidates (allids - not indexed)\n",
- idl ? idl->b_nids : 0, 0, 0 );
+ "<= index_read %ld candidates (allids - not indexed)\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
return( idl );
}
attr_normalize( type );
- if ( (db = ldbm_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
+ at_cn = at_canonical_name( type );
+
+ if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
== NULL ) {
Debug( LDAP_DEBUG_ANY,
- "<= index_read NULL (could not open %s%s)\n", type,
+ "<= index_read NULL (could not open %s%s)\n", at_cn,
LDBM_SUFFIX, 0 );
return( NULL );
}
realval = val;
tmpval = NULL;
- if ( prefix != '\0' ) {
- int len;
+ if ( prefix != UNKNOWN_PREFIX ) {
+ unsigned int len = strlen( val );
- if ( (len = strlen( val )) < sizeof(buf) ) {
- buf[0] = prefix;
- strcpy( &buf[1], val );
+ if ( (len + 2) < sizeof(buf) ) {
realval = buf;
} else {
/* value + prefix + null */
tmpval = (char *) ch_malloc( len + 2 );
- tmpval[0] = prefix;
- strcat( &tmpval[1], val );
realval = tmpval;
}
+
+ realval[0] = prefix;
+ strcpy( &realval[1], val );
}
key.dptr = realval;
key.dsize = strlen( realval ) + 1;
idl = idl_fetch( be, db, key );
+ if ( tmpval != NULL ) {
+ free( tmpval );
+ }
ldbm_cache_close( be, db );
- Debug( LDAP_DEBUG_TRACE, "<= index_read %d candidates\n",
- idl ? idl->b_nids : 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n",
+ idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
return( idl );
}
+/* Add or remove stuff from index files */
+
static int
-add_value(
+change_value(
Backend *be,
- struct dbcache *db,
+ DBCache *db,
char *type,
int indextype,
char *val,
- ID id
+ ID id,
+ int (*idl_func)(Backend *, DBCache *, Datum, ID)
)
{
int rc;
Datum key;
- IDList *idl;
- char prefix;
- char *realval, *tmpval, *s;
+ char *tmpval = NULL;
+ char *realval = val;
char buf[BUFSIZ];
- prefix = index2prefix( indextype );
- Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
+ char prefix = index2prefix( indextype );
- realval = val;
- tmpval = NULL;
- idl = NULL;
- if ( prefix != '\0' ) {
- int len;
+ ldbm_datum_init( key );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "=> change_value( \"%c%s\", op=%s )\n",
+ prefix, val, (idl_func == idl_insert_key ? "ADD":"DELETE") );
- if ( (len = strlen( val )) < sizeof(buf) ) {
- buf[0] = prefix;
- strcpy( &buf[1], val );
+ if ( prefix != UNKNOWN_PREFIX ) {
+ unsigned int len = strlen( val );
+
+ if ( (len + 2) < sizeof(buf) ) {
realval = buf;
- } else {
+ } else {
/* value + prefix + null */
tmpval = (char *) ch_malloc( len + 2 );
- tmpval[0] = prefix;
- strcat( &tmpval[1], val );
realval = tmpval;
- }
+ }
+ realval[0] = prefix;
+ strcpy( &realval[1], val );
}
key.dptr = realval;
key.dsize = strlen( realval ) + 1;
- rc = idl_insert_key( be, db, key, id );
+ rc = idl_func( be, db, key, id );
if ( tmpval != NULL ) {
free( tmpval );
}
- idl_free( idl );
- pthread_yield();
+ ldap_pvt_thread_yield();
+
+ Debug( LDAP_DEBUG_TRACE, "<= change_value %d\n", rc, 0, 0 );
- /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
return( rc );
-}
+
+}/* static int change_value() */
+
int
-index_add_values(
+index_change_values(
Backend *be,
char *type,
struct berval **vals,
- ID id
+ ID id,
+ unsigned int op
)
{
char *val, *p, *code, *w;
- int i, j, len;
+ unsigned i, j, len;
int indexmask, syntax;
char buf[SUBLEN + 1];
char vbuf[BUFSIZ];
char *bigbuf;
- struct dbcache *db;
+ DBCache *db;
+
+ int (*idl_funct)(Backend *,
+ DBCache *,
+ Datum, ID);
+ char *at_cn; /* Attribute canonical name */
+ int mode;
+
+ if( vals == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "=> index_change_values( %s, NULL, %ld, op=%s )\n",
+ type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
+ return 0;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "=> index_change_values( \"%s\", %ld, op=%s )\n",
+ type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
- Debug( LDAP_DEBUG_TRACE, "=> index_add_values( \"%s\", %ld )\n", type,
- id, 0 );
+
+ if (op == SLAP_INDEX_ADD_OP) {
+
+ /* Add values */
+
+ idl_funct = idl_insert_key;
+ mode = LDBM_WRCREAT;
+
+ } else {
+
+ /* Delete values */
+
+ idl_funct = idl_delete_key;
+ mode = LDBM_WRITER;
+
+ }
+ attr_normalize(type);
attr_masks( be->be_private, type, &indexmask, &syntax );
+
if ( indexmask == 0 ) {
return( 0 );
}
- if ( (db = ldbm_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
- == NULL ) {
+ at_cn = at_canonical_name( type );
+
+ if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, mode ))
+ == NULL ) {
Debug( LDAP_DEBUG_ANY,
- "<= index_add_values -1 (could not open/create %s%s)\n",
- type, LDBM_SUFFIX, 0 );
+ "<= index_change_values (couldn't open(%s%s),md=%s)\n",
+ at_cn,
+ LDBM_SUFFIX,
+ ((mode==LDBM_WRCREAT)?"LDBM_WRCREAT":"LDBM_WRITER") );
return( -1 );
}
* presence index entry
*/
if ( indexmask & INDEX_PRESENCE ) {
- add_value( be, db, type, INDEX_PRESENCE, "*", id );
+
+ change_value( be, db, at_cn, INDEX_PRESENCE,
+ "*", id, idl_funct );
+
}
- Debug( LDAP_DEBUG_TRACE, "*** index_add_values syntax 0x%x syntax bin 0x%x\n",
- syntax, SYNTAX_BIN, 0 );
+ Debug( LDAP_DEBUG_TRACE,
+ "index_change_values syntax 0x%x syntax bin 0x%x\n",
+ syntax, SYNTAX_BIN, 0 );
+
if ( syntax & SYNTAX_BIN ) {
+
ldbm_cache_close( be, db );
return( 0 );
+
}
bigbuf = NULL;
value_normalize( val, syntax );
+ /* value_normalize could change the length of val */
+ len = strlen( val );
+
/*
* equality index entry
*/
if ( indexmask & INDEX_EQUALITY ) {
- add_value( be, db, type, INDEX_EQUALITY, val, id );
+
+ change_value( be, db, at_cn, INDEX_EQUALITY,
+ val, id, idl_funct);
+
}
/*
for ( w = first_word( val ); w != NULL;
w = next_word( w ) ) {
if ( (code = phonetic( w )) != NULL ) {
- add_value( be, db, type, INDEX_APPROX,
- code, id );
+ change_value( be,
+ db,
+ at_cn,
+ INDEX_APPROX,
+ code,
+ id,
+ idl_funct );
free( code );
}
}
}
buf[SUBLEN] = '\0';
- add_value( be, db, type, INDEX_SUB, buf, id );
+ change_value( be, db, at_cn, INDEX_SUB,
+ buf, id, idl_funct );
p = val + len - SUBLEN + 1;
for ( j = 0; j < SUBLEN - 1; j++ ) {
buf[SUBLEN - 1] = '$';
buf[SUBLEN] = '\0';
- add_value( be, db, type, INDEX_SUB, buf, id );
+ change_value( be, db, at_cn, INDEX_SUB,
+ buf, id, idl_funct );
}
/* any */
}
buf[SUBLEN] = '\0';
- add_value( be, db, type, INDEX_SUB, buf, id );
+ change_value( be, db, at_cn, INDEX_SUB,
+ buf, id, idl_funct );
}
}
free( bigbuf );
}
}
+
ldbm_cache_close( be, db );
return( 0 );
+
}
static int
prefix = SUB_PREFIX;
break;
default:
- prefix = '\0';
+ prefix = UNKNOWN_PREFIX;
break;
}
/* init.c - initialize ldbm backend */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
-ldbm_back_init(
+#ifdef SLAPD_LDBM_DYNAMIC
+
+int back_ldbm_LTX_init_module(int argc, char *argv[]) {
+ BackendInfo bi;
+
+ memset( &bi, 0, sizeof(bi) );
+ bi.bi_type = "ldbm";
+ bi.bi_init = ldbm_back_initialize;
+
+ backend_add(&bi);
+ return 0;
+}
+
+#endif /* SLAPD_LDBM_DYNAMIC */
+
+int
+ldbm_back_initialize(
+ BackendInfo *bi
+)
+{
+ bi->bi_open = ldbm_back_open;
+ bi->bi_config = 0;
+ bi->bi_close = ldbm_back_close;
+ bi->bi_destroy = ldbm_back_destroy;
+
+ bi->bi_db_init = ldbm_back_db_init;
+ bi->bi_db_config = ldbm_back_db_config;
+ bi->bi_db_open = ldbm_back_db_open;
+ bi->bi_db_close = ldbm_back_db_close;
+ bi->bi_db_destroy = ldbm_back_db_destroy;
+
+ bi->bi_op_bind = ldbm_back_bind;
+ bi->bi_op_unbind = ldbm_back_unbind;
+ bi->bi_op_search = ldbm_back_search;
+ bi->bi_op_compare = ldbm_back_compare;
+ bi->bi_op_modify = ldbm_back_modify;
+ bi->bi_op_modrdn = ldbm_back_modrdn;
+ bi->bi_op_add = ldbm_back_add;
+ bi->bi_op_delete = ldbm_back_delete;
+ bi->bi_op_abandon = ldbm_back_abandon;
+
+ bi->bi_entry_release_rw = ldbm_back_entry_release_rw;
+ bi->bi_acl_group = ldbm_back_group;
+
+ /*
+ * hooks for slap tools
+ */
+ bi->bi_tool_entry_open = ldbm_tool_entry_open;
+ bi->bi_tool_entry_close = ldbm_tool_entry_close;
+ bi->bi_tool_entry_first = ldbm_tool_entry_first;
+ bi->bi_tool_entry_next = ldbm_tool_entry_next;
+ bi->bi_tool_entry_get = ldbm_tool_entry_get;
+ bi->bi_tool_entry_put = ldbm_tool_entry_put;
+ bi->bi_tool_index_attr = ldbm_tool_index_attr;
+ bi->bi_tool_index_change = ldbm_tool_index_change;
+ bi->bi_tool_sync = ldbm_tool_sync;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ return 0;
+}
+
+int
+ldbm_back_destroy(
+ BackendInfo *bi
+)
+{
+ return 0;
+}
+
+int
+ldbm_back_open(
+ BackendInfo *bi
+)
+{
+ int rc;
+
+ /* initialize the underlying database system */
+ rc = ldbm_initialize();
+
+ return rc;
+}
+
+int
+ldbm_back_close(
+ BackendInfo *bi
+)
+{
+ /* terminate the underlying database system */
+ ldbm_shutdown();
+
+ return 0;
+}
+
+int
+ldbm_back_db_init(
Backend *be
)
{
struct ldbminfo *li;
char *argv[ 4 ];
- int i;
- /* allocate backend-specific stuff */
+ /* allocate backend-database-specific stuff */
li = (struct ldbminfo *) ch_calloc( 1, sizeof(struct ldbminfo) );
/* arrange to read nextid later (on first request for it) */
- li->li_nextid = -1;
+ li->li_nextid = NOID;
/* default cache size */
li->li_cache.c_maxsize = DEFAULT_CACHE_SIZE;
/* default database cache size */
li->li_dbcachesize = DEFAULT_DBCACHE_SIZE;
+ /* default cache mode is sync on write */
+ li->li_dbcachewsync = 1;
+
/* default file creation mode */
li->li_mode = DEFAULT_MODE;
/* default database directory */
- li->li_directory = DEFAULT_DB_DIRECTORY;
+ li->li_directory = ch_strdup( DEFAULT_DB_DIRECTORY );
- /* always index dn, id2children, objectclass (used in some searches) */
- argv[ 0 ] = "dn";
- argv[ 1 ] = "dn";
- argv[ 2 ] = NULL;
- attr_syntax_config( "ldbm dn initialization", 0, 2, argv );
- argv[ 0 ] = "dn";
- argv[ 1 ] = "sub";
- argv[ 2 ] = "eq";
- argv[ 3 ] = NULL;
- attr_index_config( li, "ldbm dn initialization", 0, 3, argv, 1 );
- argv[ 0 ] = "id2children";
- argv[ 1 ] = "eq";
- argv[ 2 ] = NULL;
- attr_index_config( li, "ldbm id2children initialization", 0, 2, argv,
- 1 );
argv[ 0 ] = "objectclass";
- argv[ 1 ] = strdup( "pres,eq" );
+ argv[ 1 ] = "pres,eq";
argv[ 2 ] = NULL;
- attr_index_config( li, "ldbm objectclass initialization", 0, 2, argv,
- 1 );
- free( argv[ 1 ] );
+ attr_index_config( li, "ldbm objectclass initialization",
+ 0, 2, argv, 1 );
/* initialize various mutex locks & condition variables */
- pthread_mutex_init( &li->li_cache.c_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &li->li_nextid_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &li->li_dbcache_mutex, pthread_mutexattr_default );
- pthread_cond_init( &li->li_dbcache_cv, pthread_condattr_default );
- for ( i = 0; i < MAXDBCACHE; i++ ) {
- pthread_mutex_init( &li->li_dbcache[i].dbc_mutex,
- pthread_mutexattr_default );
- pthread_cond_init( &li->li_dbcache[i].dbc_cv,
- pthread_condattr_default );
- }
+ ldap_pvt_thread_mutex_init( &li->li_root_mutex );
+ ldap_pvt_thread_mutex_init( &li->li_add_mutex );
+ ldap_pvt_thread_mutex_init( &li->li_cache.c_mutex );
+ ldap_pvt_thread_mutex_init( &li->li_nextid_mutex );
+ ldap_pvt_thread_mutex_init( &li->li_dbcache_mutex );
+ ldap_pvt_thread_cond_init( &li->li_dbcache_cv );
be->be_private = li;
+
+ return 0;
+}
+
+int
+ldbm_back_db_open(
+ BackendDB *be
+)
+{
+ return 0;
+}
+
+int
+ldbm_back_db_destroy(
+ BackendDB *be
+)
+{
+ /* should free/destroy every in be_private */
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ free( li->li_directory );
+ attr_index_destroy( li->li_attrs );
+
+ ldap_pvt_thread_mutex_destroy( &li->li_root_mutex );
+ ldap_pvt_thread_mutex_destroy( &li->li_add_mutex );
+ ldap_pvt_thread_mutex_destroy( &li->li_cache.c_mutex );
+ ldap_pvt_thread_mutex_destroy( &li->li_nextid_mutex );
+ ldap_pvt_thread_mutex_destroy( &li->li_dbcache_mutex );
+ ldap_pvt_thread_cond_destroy( &li->li_dbcache_cv );
+
+ free( be->be_private );
+ be->be_private = NULL;
+
+ return 0;
}
/* kerberos.c - ldbm backend kerberos bind routines */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#ifdef HAVE_KERBEROS
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/krb.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "back-ldbm.h"
-#ifdef KERBEROS
-#include "krb.h"
-
#define LDAP_KRB_PRINCIPAL "ldapserver"
extern char *ldap_srvtab;
-extern Entry *dn2entry();
extern Attribute *attr_find();
krbv4_ldap_auth(
/* modify.c - ldbm backend modify routine */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
#include "slap.h"
#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
-extern int global_schemacheck;
-extern Entry *dn2entry();
-extern Attribute *attr_find();
+/* We need this function because of LDAP modrdn. If we do not
+ * add this there would be a bunch of code replication here
+ * and there and of course the likelihood of bugs increases.
+ * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
+ */
-static int add_values();
-static int delete_values();
-static int replace_values();
-
-int
-ldbm_back_modify(
+int ldbm_modify_internal(
Backend *be,
Connection *conn,
Operation *op,
char *dn,
- LDAPMod *mods
+ LDAPModList *modlist,
+ Entry *e
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
- Entry *e;
- int i, err, modtype;
+ int err;
LDAPMod *mod;
+ LDAPModList *ml;
+ Attribute *a;
+ Attribute *save_attrs;
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
- NULL );
- if ( matched != NULL ) {
- free( matched );
- }
- return( -1 );
+ if ( (err = acl_check_modlist( be, conn, op, e, modlist ))
+ != LDAP_SUCCESS )
+ {
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
+ return -1;
}
- /* lock entry */
- if ( (err = acl_check_mods( be, conn, op, e, mods )) != LDAP_SUCCESS ) {
- send_ldap_result( conn, op, err, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
- }
+ save_attrs = e->e_attrs;
+ e->e_attrs = attrs_dup( e->e_attrs );
+
+ for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
+ mod = &ml->ml_mod;
- for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_ADD:
- err = add_values( e, mod, op->o_dn );
+ err = add_values( e, mod, op->o_ndn );
break;
case LDAP_MOD_DELETE:
- err = delete_values( e, mod, op->o_dn );
+ err = delete_values( e, mod, op->o_ndn );
break;
case LDAP_MOD_REPLACE:
- err = replace_values( e, mod, op->o_dn );
+ err = replace_values( e, mod, op->o_ndn );
break;
+
+ case LDAP_MOD_SOFTADD:
+ /* Avoid problems in index_add_mods()
+ * We need to add index if necessary.
+ */
+ mod->mod_op = LDAP_MOD_ADD;
+ if ( (err = add_values( e, mod, op->o_ndn ))
+ == LDAP_TYPE_OR_VALUE_EXISTS ) {
+
+ err = LDAP_SUCCESS;
+ mod->mod_op = LDAP_MOD_SOFTADD;
+
+ }
+ break;
}
if ( err != LDAP_SUCCESS ) {
+ attrs_free( e->e_attrs );
+ e->e_attrs = save_attrs;
/* unlock entry, delete from cache */
- send_ldap_result( conn, op, err, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
+ return -1;
}
}
/* check for abandon */
- pthread_mutex_lock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
- pthread_mutex_unlock( &op->o_abandonmutex );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ attrs_free( e->e_attrs );
+ e->e_attrs = save_attrs;
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ return -1;
}
- pthread_mutex_unlock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* check that the entry still obeys the schema */
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL,
- NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ attrs_free( e->e_attrs );
+ e->e_attrs = save_attrs;
+ Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL, NULL );
+ return -1;
+ }
+
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ if ( op->o_abandon ) {
+ attrs_free( e->e_attrs );
+ e->e_attrs = save_attrs;
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ return -1;
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ /* remove old indices */
+ if( save_attrs != NULL ) {
+ for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
+ mod = &ml->ml_mod;
+ if( ( mod->mod_op & ~LDAP_MOD_BVALUES )
+ == LDAP_MOD_REPLACE )
+ {
+ /* Need to remove all values from indexes */
+ a = attr_find( save_attrs, mod->mod_type );
+
+ if( a != NULL ) {
+ (void) index_change_values( be,
+ mod->mod_type,
+ a->a_vals,
+ e->e_id,
+ SLAP_INDEX_DELETE_OP);
+ }
+ }
+ }
+ attrs_free( save_attrs );
}
/* modify indexes */
- if ( index_add_mods( be, mods, e->e_id ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ if ( index_add_mods( be, modlist, e->e_id ) != 0 ) {
+ /* our indices are likely hosed */
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ return -1;
}
/* check for abandon */
- pthread_mutex_lock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
- pthread_mutex_unlock( &op->o_abandonmutex );
- cache_return_entry( &li->li_cache, e );
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ return -1;
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ return 0;
+}
+
+
+int
+ldbm_back_modify(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ LDAPModList *modlist
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *matched;
+ Entry *e;
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
+
+ /* acquire and lock entry */
+ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
+ char* matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if ( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
return( -1 );
}
- pthread_mutex_unlock( &op->o_abandonmutex );
+
+ if ( !manageDSAit && is_entry_referral( e ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ goto error_return;
+ }
+
+ /* Modify the entry */
+ if ( ldbm_modify_internal( be, conn, op, dn, modlist, e ) != 0 ) {
+ goto error_return;
+ }
/* change the entry itself */
if ( id2entry_add( be, e ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto error_return;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
-
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ cache_return_entry_w( &li->li_cache, e );
return( 0 );
+
+error_return:;
+ cache_return_entry_w( &li->li_cache, e );
+ return( -1 );
}
-static int
+int
add_values(
Entry *e,
LDAPMod *mod,
return( LDAP_SUCCESS );
}
-static int
+int
delete_values(
Entry *e,
LDAPMod *mod,
a->a_vals[k - 1] = a->a_vals[k];
}
a->a_vals[k - 1] = NULL;
+
+ /* delete the entire attribute, if no values remain */
+ if ( a->a_vals[0] == NULL) {
+ Debug( LDAP_DEBUG_ARGS,
+ "removing entire attribute %s\n",
+ mod->mod_type, 0, 0 );
+ if ( attr_delete( &e->e_attrs, mod->mod_type ) ) {
+ return LDAP_NO_SUCH_ATTRIBUTE;
+ }
+ }
+
break;
}
return( LDAP_SUCCESS );
}
-static int
+int
replace_values(
Entry *e,
LDAPMod *mod,
{
(void) attr_delete( &e->e_attrs, mod->mod_type );
- if ( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) {
+ if ( mod->mod_bvalues != NULL &&
+ attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 )
+ {
return( LDAP_CONSTRAINT_VIOLATION );
}
/* modrdn.c - ldbm backend modrdn routine */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+/*
+ * LDAP v3 newSuperior support. Add new rdn as an attribute.
+ * (Full support for v2 also used software/ideas contributed
+ * by Roy Hooper rhooper@cyberus.ca, thanks to him for his
+ * submission!.)
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
-
-extern Entry *dn2entry();
-extern char *dn_parent();
+#include "proto-back-ldbm.h"
int
ldbm_back_modrdn(
Operation *op,
char *dn,
char *newrdn,
- int deleteoldrdn
+ int deleteoldrdn,
+ char *newSuperior
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
- char *pdn, *newdn, *p;
- char sep[2];
- Entry *e, *e2;
-
- matched = NULL;
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+ char *p_dn = NULL, *p_ndn = NULL;
+ char *new_dn = NULL, *new_ndn = NULL;
+ Entry *e, *p = NULL;
+ Entry *matched = NULL;
+ int rootlock = 0;
+ int rc = -1;
+ /* Added to support LDAP v2 correctly (deleteoldrdn thing) */
+ char *new_rdn_val = NULL; /* Val of new rdn */
+ char *new_rdn_type = NULL; /* Type of new rdn */
+ char *old_rdn; /* Old rdn's attr type & val */
+ char *old_rdn_type = NULL; /* Type of old rdn attr. */
+ char *old_rdn_val = NULL; /* Old rdn attribute value */
+ /* Added to support newSuperior */
+ Entry *np = NULL; /* newSuperior Entry */
+ char *np_dn = NULL; /* newSuperior dn */
+ char *np_ndn = NULL; /* newSuperior ndn */
+ char *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
+ /* Used to interface with ldbm_modify_internal() */
+ struct berval add_bv; /* Stores new rdn att */
+ struct berval *add_bvals[2]; /* Stores new rdn att */
+ struct berval del_bv; /* Stores old rdn att */
+ struct berval *del_bvals[2]; /* Stores old rdn att */
+ LDAPModList mod[2]; /* Used to delete old rdn */
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n",
+ (newSuperior ? newSuperior : "NULL"),
+ 0, 0 );
+
+ /* get entry with writer lock */
+ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
+ char* matched_dn = NULL;
+ struct berval** refs = NULL;
+
+ if( matched != NULL ) {
+ matched_dn = strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
if ( matched != NULL ) {
- free( matched );
+ ber_bvecfree( refs );
+ free( matched_dn );
}
+
return( -1 );
}
- if ( (pdn = dn_parent( be, dn )) != NULL ) {
- /* parent + rdn + separator(s) + null */
- newdn = (char *) ch_malloc( strlen( pdn ) + strlen( newrdn )
- + 3 );
- if ( dn_type( dn ) == DN_X500 ) {
- strcpy( newdn, newrdn );
- strcat( newdn, ", " );
- strcat( newdn, pdn );
- } else {
- strcpy( newdn, newrdn );
- p = strchr( newrdn, '\0' );
- p--;
- if ( *p != '.' && *p != '@' ) {
- if ( (p = strpbrk( dn, ".@" )) != NULL ) {
- sep[0] = *p;
- sep[1] = '\0';
- strcat( newdn, sep );
- }
- }
- strcat( newdn, pdn );
+#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+#endif
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ goto return_results;
+ }
+
+ if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) {
+
+ /* Make sure parent entry exist and we can write its
+ * children.
+ */
+
+ if( (p = dn2entry_w( be, p_ndn, &matched )) == NULL) {
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
}
+
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: wr to children of entry %s OK\n",
+ p_ndn, 0, 0 );
+
+ p_dn = dn_parent( be, e->e_dn );
+
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: parent dn=%s\n",
+ p_dn, 0, 0 );
+
} else {
- newdn = strdup( newrdn );
+ /* no parent, modrdn entry directly under root */
+ if( ! be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
+ rootlock = 1;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: no parent, locked root\n",
+ 0, 0, 0 );
+
}
- (void) dn_normalize( newdn );
- matched = NULL;
- if ( (e2 = dn2entry( be, newdn, &matched )) != NULL ) {
- free( newdn );
- free( pdn );
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
- cache_return_entry( &li->li_cache, e2 );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ new_parent_dn = p_dn; /* New Parent unless newSuperior given */
+
+ if ( (np_dn = newSuperior) != NULL) {
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: new parent requested...\n",
+ 0, 0, 0 );
+
+ np_ndn = ch_strdup( np_dn );
+ (void) dn_normalize_case( np_ndn );
+
+ /* newSuperior == oldParent?, if so ==> ERROR */
+ /* newSuperior == entry being moved?, if so ==> ERROR */
+ /* Get Entry with dn=newSuperior. Does newSuperior exist? */
+
+ if( (np = dn2entry_w( be, np_ndn, &matched )) == NULL) {
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
+ np_ndn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: wr to new parent OK np=%p, id=%d\n",
+ np, np->e_id, 0 );
+
+ /* check newSuperior for "children" acl */
+ if ( !access_allowed( be, conn, op, np, "children", NULL,
+ ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: no wr to newSup children\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ if ( is_entry_alias( np ) ) {
+ /* entry is an alias, don't allow bind */
+ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ goto return_results;
+ }
+
+ if ( is_entry_referral( np ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: wr to new parent's children OK\n",
+ 0, 0 , 0 );
+
+ new_parent_dn = np_dn;
}
- if ( matched != NULL ) {
- free( matched );
+
+ /* Build target dn and make sure target entry doesn't exist already. */
+
+ build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn );
+
+
+ new_ndn = ch_strdup(new_dn);
+ (void) dn_normalize_case( new_ndn );
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new ndn=%s\n",
+ new_ndn, 0, 0 );
+
+ if (dn2id ( be, new_ndn ) != NOID) {
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
}
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: new ndn=%s does not exist\n",
+ new_ndn, 0, 0 );
+
/* check for abandon */
- pthread_mutex_lock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
- pthread_mutex_unlock( &op->o_abandonmutex );
- free( newdn );
- free( pdn );
- cache_return_entry( &li->li_cache, e2 );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
- }
- pthread_mutex_unlock( &op->o_abandonmutex );
-
- /* add new one */
- if ( dn2id_add( be, newdn, e->e_id ) != 0 ) {
- free( newdn );
- free( pdn );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ goto return_results;
}
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* delete old one */
- if ( dn2id_delete( be, dn ) != 0 ) {
- free( newdn );
- free( pdn );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ if ( dn2id_delete( be, e->e_ndn ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
}
(void) cache_delete_entry( &li->li_cache, e );
free( e->e_dn );
- e->e_dn = newdn;
-
- /* XXX
- * At some point here we need to update the attribute values in
- * the entry itself that were effected by this RDN change
- * (respecting the value of the deleteoldrdn parameter).
- *
- * Since the code to do this has not yet been written, treat this
- * omission as a (documented) bug.
+ free( e->e_ndn );
+ e->e_dn = new_dn;
+ e->e_ndn = new_ndn;
+
+ /* add new one */
+ if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+
+ /* Get attribute type and attribute value of our new rdn, we will
+ * need to add that to our new entry
+ */
+
+ if ( (new_rdn_type = rdn_attr_type( newrdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out type of newrdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ if ( (new_rdn_val = rdn_attr_value( newrdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out val of newrdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: new_rdn_val=\"%s\", new_rdn_type=\"%s\"\n",
+ new_rdn_val, new_rdn_type, 0 );
+
+ /* Retrieve the old rdn from the entry's dn */
+
+ if ( (old_rdn = dn_rdn( be, dn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out old_rdn from dn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out the old_rdn type\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) {
+
+ /* Not a big deal but we may say something */
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n",
+ old_rdn_type, new_rdn_type, 0 );
+
+ }
+
+#ifdef DNS_DN
+ if ( dn_type( old_rdn ) == DN_X500 ) {
+#endif
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n",
+ 0, 0, 0 );
+
+ /* Add new attribute value to the entry.
+ */
+
+ add_bvals[0] = &add_bv; /* Array of bervals */
+ add_bvals[1] = NULL;
+
+ add_bv.bv_val = new_rdn_val;
+ add_bv.bv_len = strlen(new_rdn_val);
+
+ mod[0].ml_type = new_rdn_type;
+ mod[0].ml_bvalues = add_bvals;
+ mod[0].ml_op = LDAP_MOD_SOFTADD;
+ mod[0].ml_next = NULL;
+
+ /* Remove old rdn value if required */
+
+ if (deleteoldrdn) {
+ /* Get value of old rdn */
+
+ if ((old_rdn_val = rdn_attr_value( old_rdn ))
+ == NULL) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ del_bvals[0] = &del_bv; /* Array of bervals */
+ del_bvals[1] = NULL;
+
+ /* Remove old value of rdn as an attribute. */
+
+ del_bv.bv_val = old_rdn_val;
+ del_bv.bv_len = strlen(old_rdn_val);
+
+ /* No need to normalize old_rdn_type, delete_values()
+ * does that for us
+ */
+ mod[0].ml_next = &mod[1];
+ mod[1].ml_type = old_rdn_type;
+ mod[1].ml_bvalues = del_bvals;
+ mod[1].ml_op = LDAP_MOD_DELETE;
+ mod[1].ml_next = NULL;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: removing old_rdn_val=%s\n",
+ old_rdn_val, 0, 0 );
+ }
+
+#ifdef DNS_DN
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DNS DN\n",
+ 0, 0, 0 );
+ /* XXXV3: not sure of what to do here */
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: not fully implemented...\n",
+ 0, 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+
+ }
+#endif
+
+ /* modify memory copy of entry */
+ if ( ldbm_modify_internal( be, conn, op, dn, &mod[0], e )
+ != 0 ) {
+
+ goto return_results;
+
+ }
+
+ (void) cache_update_entry( &li->li_cache, e );
+
+ /* NOTE: after this you must not free new_dn or new_ndn!
+ * They are used by cache.
*/
/* id2entry index */
if ( id2entry_add( be, e ) != 0 ) {
entry_free( e );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+ goto return_results_after;
+ }
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- return( -1 );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 0;
+ goto return_results_after;
+
+return_results:
+ if( new_dn != NULL ) free( new_dn );
+ if( new_ndn != NULL ) free( new_ndn );
+
+return_results_after:
+ /* NOTE:
+ * new_dn and new_ndn are not deallocated because they are used by
+ * the cache entry.
+ */
+ if( p_dn != NULL ) free( p_dn );
+ if( p_ndn != NULL ) free( p_ndn );
+
+ if( matched != NULL ) free( matched );
+
+ /* LDAP v2 supporting correct attribute handling. */
+ if( new_rdn_type != NULL ) free(new_rdn_type);
+ if( new_rdn_val != NULL ) free(new_rdn_val);
+ if( old_rdn != NULL ) free(old_rdn);
+ if( old_rdn_type != NULL ) free(old_rdn_type);
+ if( old_rdn_val != NULL ) free(old_rdn_val);
+
+
+ /* LDAP v3 Support */
+ if ( np_dn != NULL ) free( np_dn );
+ if ( np_ndn != NULL ) free( np_ndn );
+
+ if( np != NULL ) {
+ /* free new parent and writer lock */
+ cache_return_entry_w( &li->li_cache, np );
+ }
+
+ if( p != NULL ) {
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rootlock ) {
+ /* release root writer lock */
+ ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
}
- free( pdn );
- cache_return_entry( &li->li_cache, e );
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- return( 0 );
+ /* free entry and writer lock */
+ cache_return_entry_w( &li->li_cache, e );
+ return( rc );
}
-/* id.c - keep track of the next id to be given out */
+/* nextid.c - keep track of the next id to be given out */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
+
#include "slap.h"
#include "back-ldbm.h"
-ID
-next_id( Backend *be )
+static ID
+next_id_read( Backend *be )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char buf[MAXPATHLEN];
- char buf2[20];
- FILE *fp;
- ID id;
-
- sprintf( buf, "%s/NEXTID", li->li_directory );
-
- pthread_mutex_lock( &li->li_nextid_mutex );
- /* first time in here since startup - try to read the nexid */
- if ( li->li_nextid == -1 ) {
- if ( (fp = fopen( buf, "r" )) == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "next_id %d: could not open \"%s\"\n",
- li->li_nextid, buf, 0 );
- li->li_nextid = 1;
- } else {
- if ( fgets( buf2, sizeof(buf2), fp ) != NULL ) {
- li->li_nextid = atol( buf2 );
- } else {
- Debug( LDAP_DEBUG_ANY,
- "next_id %d: could not fgets nextid from \"%s\"\n",
- li->li_nextid, buf2, 0 );
- li->li_nextid = 1;
- }
- fclose( fp );
- }
+ ID id = NOID;
+ Datum key, data;
+ DBCache *db;
+
+ if ( (db = ldbm_cache_open( be, "nextid", LDBM_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "Could not open/create nextid" LDBM_SUFFIX "\n",
+ 0, 0, 0 );
+ return( NOID );
}
- li->li_nextid++;
- if ( (fp = fopen( buf, "w" )) == NULL ) {
- Debug( LDAP_DEBUG_ANY, "next_id %d: could not open \"%s\"\n",
- li->li_nextid, buf, 0 );
+ ldbm_datum_init( key );
+ key.dptr = (char *) &id;
+ key.dsize = sizeof(ID);
+
+ data = ldbm_cache_fetch( db, key );
+
+ if( data.dptr != NULL ) {
+ memcpy( &id, data.dptr, sizeof( ID ) );
+ ldbm_datum_free( db->dbc_db, data );
+
} else {
- if ( fprintf( fp, "%ld\n", li->li_nextid ) == EOF ) {
- Debug( LDAP_DEBUG_ANY, "next_id %d: cannot fprintf\n",
- li->li_nextid, 0, 0 );
- }
- if( fclose( fp ) != 0 ) {
- Debug( LDAP_DEBUG_ANY, "next_id %d: cannot fclose\n",
- li->li_nextid, 0, 0 );
- }
+ id = 1;
}
- id = li->li_nextid - 1;
- pthread_mutex_unlock( &li->li_nextid_mutex );
- return( id );
+ ldbm_cache_close( be, db );
+ return id;
}
-void
-next_id_return( Backend *be, ID id )
+ID
+next_id_write( Backend *be, ID id )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char buf[MAXPATHLEN];
- FILE *fp;
+ Datum key, data;
+ DBCache *db;
+ ID noid = NOID;
+ int flags;
- pthread_mutex_lock( &li->li_nextid_mutex );
- if ( id != li->li_nextid - 1 ) {
- pthread_mutex_unlock( &li->li_nextid_mutex );
- return;
+ if ( (db = ldbm_cache_open( be, "nextid", LDBM_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "Could not open/create nextid" LDBM_SUFFIX "\n",
+ 0, 0, 0 );
+ return( NOID );
}
- sprintf( buf, "%s/NEXTID", li->li_directory );
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
- li->li_nextid--;
- if ( (fp = fopen( buf, "w" )) == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "next_id_return of %d: could not open \"%s\" next id %d\n",
- id, buf, li->li_nextid );
- } else {
- if ( fprintf( fp, "%ld\n", li->li_nextid ) == EOF ) {
- Debug( LDAP_DEBUG_ANY,
- "next_id_return of %d: cannot fprintf \"%s\" next id %d\n",
- id, buf, li->li_nextid );
- }
- if( fclose( fp ) != 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "next_id_return of %d: cannot fclose \"%s\" next id %d\n",
- id, buf, li->li_nextid );
- }
+ key.dptr = (char *) &noid;
+ key.dsize = sizeof(ID);
+
+ data.dptr = (char *) &id;
+ data.dsize = sizeof(ID);
+
+ flags = LDBM_REPLACE;
+ if( li->li_dbcachewsync ) flags |= LDBM_SYNC;
+
+ if ( ldbm_cache_store( db, key, data, flags ) != 0 ) {
+ id = NOID;
}
- pthread_mutex_unlock( &li->li_nextid_mutex );
+
+ ldbm_cache_close( be, db );
+ return id;
}
ID
next_id_get( Backend *be )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char buf[MAXPATHLEN];
- char buf2[20];
- FILE *fp;
- ID id;
-
- sprintf( buf, "%s/NEXTID", li->li_directory );
-
- pthread_mutex_lock( &li->li_nextid_mutex );
- /* first time in here since startup - try to read the nexid */
- if ( li->li_nextid == -1 ) {
- if ( (fp = fopen( buf, "r" )) == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "next_id %d: could not open \"%s\"\n",
- li->li_nextid, buf, 0 );
- li->li_nextid = 1;
- } else {
- if ( fgets( buf2, sizeof(buf2), fp ) != NULL ) {
- li->li_nextid = atol( buf2 );
- } else {
- Debug( LDAP_DEBUG_ANY,
- "next_id %d: cannot fgets nextid from \"%s\"\n",
- li->li_nextid, buf2, 0 );
- li->li_nextid = 1;
- }
- fclose( fp );
- }
+ ID id = NOID;
+
+ ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex );
+
+ if ( li->li_nextid == NOID ) {
+ li->li_nextid = next_id_read( be );
}
+
id = li->li_nextid;
- pthread_mutex_unlock( &li->li_nextid_mutex );
- return( id );
+ ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex );
+ return id;
+}
+
+ID
+next_id( Backend *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ ID id = NOID;
+
+ ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex );
+
+ if ( li->li_nextid == NOID ) {
+ li->li_nextid = next_id_read( be );
+ }
+
+ if ( li->li_nextid != NOID ) {
+ id = li->li_nextid++;
+
+ (void) next_id_write( be, li->li_nextid );
+ }
+
+ ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex );
+ return id;
+
}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
#ifndef _PROTO_BACK_LDBM
#define _PROTO_BACK_LDBM
+#include <ldap_cdefs.h>
+
+#include "external.h"
+
+LDAP_BEGIN_DECL
+
+/*
+ * alias.c
+ */
+Entry *deref_internal_r LDAP_P((
+ Backend *be,
+ Entry *e,
+ char *dn,
+ int *err,
+ Entry **matched,
+ char **text ));
+
+#define deref_entry_r( be, e, err, matched, text ) \
+ deref_internal_r( be, e, NULL, err, matched, text )
+#define deref_dn_r( be, dn, err, matched, text ) \
+ deref_internal_r( be, NULL, dn, err, matched, text)
+
/*
* attr.c
*/
-void attr_masks( struct ldbminfo *li, char *type, int *indexmask,
- int *syntaxmask );
-void attr_index_config( struct ldbminfo *li, char *fname, int lineno,
- int argc, char **argv, int init );
+void attr_masks LDAP_P(( struct ldbminfo *li, char *type, int *indexmask,
+ int *syntaxmask ));
+void attr_index_config LDAP_P(( struct ldbminfo *li, char *fname, int lineno,
+ int argc, char **argv, int init ));
+void attr_index_destroy LDAP_P(( Avlnode *tree ));
/*
* cache.c
*/
-void cache_set_state( struct cache *cache, Entry *e, int state );
-void cache_return_entry( struct cache *cache, Entry *e );
-int cache_add_entry_lock( struct cache *cache, Entry *e, int state );
-Entry * cache_find_entry_dn( struct cache *cache, char *dn );
-Entry * cache_find_entry_id( struct cache *cache, ID id );
-int cache_delete_entry( struct cache *cache, Entry *e );
+int cache_add_entry_rw LDAP_P(( Cache *cache, Entry *e, int rw ));
+int cache_update_entry LDAP_P(( Cache *cache, Entry *e ));
+void cache_return_entry_rw LDAP_P(( Cache *cache, Entry *e, int rw ));
+#define cache_return_entry_r(c, e) cache_return_entry_rw((c), (e), 0)
+#define cache_return_entry_w(c, e) cache_return_entry_rw((c), (e), 1)
+
+ID cache_find_entry_dn2id LDAP_P(( Backend *be, Cache *cache, char *dn ));
+Entry * cache_find_entry_id LDAP_P(( Cache *cache, ID id, int rw ));
+int cache_delete_entry LDAP_P(( Cache *cache, Entry *e ));
+void cache_release_all LDAP_P(( Cache *cache ));
/*
* dbcache.c
*/
-struct dbcache * ldbm_cache_open( Backend *be, char *name, char *suffix,
- int flags );
-void ldbm_cache_close( Backend *be, struct dbcache *db );
-void ldbm_cache_flush_all( Backend *be );
-Datum ldbm_cache_fetch( struct dbcache *db, Datum key );
-int ldbm_cache_store( struct dbcache *db, Datum key, Datum data, int flags );
-int ldbm_cache_delete( struct dbcache *db, Datum key );
+DBCache * ldbm_cache_open LDAP_P(( Backend *be,
+ char *name, char *suffix, int flags ));
+void ldbm_cache_close LDAP_P(( Backend *be, DBCache *db ));
+void ldbm_cache_really_close LDAP_P(( Backend *be, DBCache *db ));
+void ldbm_cache_flush_all LDAP_P(( Backend *be ));
+Datum ldbm_cache_fetch LDAP_P(( DBCache *db, Datum key ));
+int ldbm_cache_store LDAP_P(( DBCache *db, Datum key, Datum data, int flags ));
+int ldbm_cache_delete LDAP_P(( DBCache *db, Datum key ));
/*
* dn2id.c
*/
-int dn2id_add( Backend *be, char *dn, ID id );
-ID dn2id( Backend *be, char *dn );
-int dn2id_delete( Backend *be, char *dn );
-Entry * dn2entry( Backend *be, char *dn, char **matched );
+int dn2id_add LDAP_P(( Backend *be, char *dn, ID id ));
+ID dn2id LDAP_P(( Backend *be, char *dn ));
+ID_BLOCK *dn2idl LDAP_P(( Backend *be, char *dn, int prefix ));
+int dn2id_delete LDAP_P(( Backend *be, char *dn ));
+
+Entry * dn2entry_rw LDAP_P(( Backend *be, char *dn, Entry **matched, int rw ));
+#define dn2entry_r(be, dn, m) dn2entry_rw((be), (dn), (m), 0)
+#define dn2entry_w(be, dn, m) dn2entry_rw((be), (dn), (m), 1)
+
+/*
+ * entry.c
+ */
+int ldbm_back_entry_release_rw LDAP_P(( Backend *be, Entry *e, int rw ));
/*
* filterindex.c
*/
-IDList * filter_candidates( Backend *be, Filter *f );
+ID_BLOCK * filter_candidates LDAP_P(( Backend *be, Filter *f ));
/*
* id2children.c
*/
-int id2children_add( Backend *be, Entry *p, Entry *e );
-int has_children( Backend *be, Entry *p );
+int id2children_add LDAP_P(( Backend *be, Entry *p, Entry *e ));
+int id2children_remove LDAP_P(( Backend *be, Entry *p, Entry *e ));
+int has_children LDAP_P(( Backend *be, Entry *p ));
/*
* id2entry.c
*/
-int id2entry_add( Backend *be, Entry *e );
-int id2entry_delete( Backend *be, Entry *e );
-Entry * id2entry( Backend *be, ID id );
+int id2entry_add LDAP_P(( Backend *be, Entry *e ));
+int id2entry_delete LDAP_P(( Backend *be, Entry *e ));
+
+Entry * id2entry_rw LDAP_P(( Backend *be, ID id, int rw ));
+#define id2entry_r(be, id) id2entry_rw((be), (id), 0)
+#define id2entry_w(be, id) id2entry_rw((be), (id), 1)
/*
* idl.c
*/
-IDList * idl_alloc( int nids );
-IDList * idl_allids( Backend *be );
-void idl_free( IDList *idl );
-IDList * idl_fetch( Backend *be, struct dbcache *db, Datum key );
-int idl_insert_key( Backend *be, struct dbcache *db, Datum key, ID id );
-int idl_insert( IDList **idl, ID id, int maxids );
-IDList * idl_intersection( Backend *be, IDList *a, IDList *b );
-IDList * idl_union( Backend *be, IDList *a, IDList *b );
-IDList * idl_notin( Backend *be, IDList *a, IDList *b );
-ID idl_firstid( IDList *idl );
-ID idl_nextid( IDList *idl, ID id );
+ID_BLOCK * idl_alloc LDAP_P(( unsigned int nids ));
+ID_BLOCK * idl_allids LDAP_P(( Backend *be ));
+void idl_free LDAP_P(( ID_BLOCK *idl ));
+ID_BLOCK * idl_fetch LDAP_P(( Backend *be, DBCache *db, Datum key ));
+int idl_insert_key LDAP_P(( Backend *be, DBCache *db, Datum key, ID id ));
+int idl_insert LDAP_P(( ID_BLOCK **idl, ID id, unsigned int maxids ));
+int idl_delete_key LDAP_P(( Backend *be, DBCache *db, Datum key, ID id ));
+ID_BLOCK * idl_intersection LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b ));
+ID_BLOCK * idl_union LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b ));
+ID_BLOCK * idl_notin LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b ));
+ID idl_firstid LDAP_P(( ID_BLOCK *idl, ID *cursor ));
+ID idl_nextid LDAP_P(( ID_BLOCK *idl, ID *cursor ));
/*
* index.c
*/
-int index_add_entry( Backend *be, Entry *e );
-int index_add_mods( Backend *be, LDAPMod *mods, ID id );
-IDList * index_read( Backend *be, char *type, int indextype, char *val );
-int index_add_values( Backend *be, char *type, struct berval **vals, ID id );
+int index_add_entry LDAP_P(( Backend *be, Entry *e ));
+int index_add_mods LDAP_P(( Backend *be, LDAPModList *ml, ID id ));
+ID_BLOCK * index_read LDAP_P(( Backend *be,
+ char *type, int indextype, char *val ));
+/* Possible operations supported (op) by index_change_values() */
+int index_change_values LDAP_P(( Backend *be,
+ char *type,
+ struct berval **vals,
+ ID id,
+ unsigned int op ));
/*
* kerberos.c
*/
-#ifdef KERBEROS
-/* krbv4_ldap_auth( Backend *be, struct berval *cred, AUTH_DAT *ad ); */
+#ifdef HAVE_KERBEROS
+/* krbv4_ldap_auth LDAP_P(( Backend *be, struct berval *cred, AUTH_DAT *ad )); */
#endif
+
+/*
+ * modify.c
+ * These prototypes are placed here because they are used by modify and
+ * modify rdn which are implemented in different files.
+ *
+ * We need ldbm_internal_modify here because of LDAP modrdn & modify use
+ * it. If we do not add this, there would be a bunch of code replication
+ * here and there and of course the likelihood of bugs increases.
+ * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
+ *
+ */
+
+int add_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+int delete_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+int replace_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+int ldbm_modify_internal LDAP_P((Backend *be,
+ Connection *conn, Operation *op,
+ char *dn, LDAPModList *mods, Entry *e));
/*
* nextid.c
*/
-ID next_id( Backend *be );
-void next_id_return( Backend *be, ID id );
-ID next_id_get( Backend *be );
+ID next_id LDAP_P(( Backend *be ));
+ID next_id_get LDAP_P(( Backend *be ));
+ID next_id_write LDAP_P(( Backend *be, ID id ));
+LDAP_END_DECL
#endif
/* search.c - ldbm backend search function */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
+
+static ID_BLOCK *base_candidate(
+ Backend *be, Entry *e );
+
+static ID_BLOCK *search_candidates(
+ Backend *be, Entry *e, Filter *filter,
+ int scope, int deref, int manageDSAit );
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
-
-extern ID dn2id();
-extern IDList *idl_alloc();
-extern Entry *id2entry();
-extern Entry *dn2entry();
-extern Attribute *attr_find();
-extern IDList *filter_candidates();
-extern char *ch_realloc();
-extern char *dn_parent();
-
-static IDList *base_candidates();
-static IDList *onelevel_candidates();
-static IDList *subtree_candidates();
-
-#define GRABSIZE BUFSIZ
-
-#define MAKE_SPACE( n ) { \
- if ( rcur + n > rbuf + rmaxsize ) { \
- int offset = rcur - rbuf; \
- rbuf = ch_realloc( rbuf, rmaxsize + GRABSIZE ); \
- rmaxsize += GRABSIZE; \
- rcur = rbuf + offset; \
- } \
-}
int
ldbm_back_search(
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- int err;
+ int rc, err;
+ char *text;
time_t stoptime;
- IDList *candidates;
- ID id;
+ ID_BLOCK *candidates;
+ ID id, cursor;
Entry *e;
- Attribute *ref;
- char *matched = NULL;
- int rmaxsize, nrefs;
- char *rbuf, *rcur, *r;
+ struct berval **v2refs = NULL;
+ Entry *matched = NULL;
+ char *realbase = NULL;
int nentries = 0;
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug(LDAP_DEBUG_TRACE, "=> ldbm_back_search\n", 0, 0, 0);
+
+ /* get entry with reader lock */
+ if ( deref & LDAP_DEREF_FINDING ) {
+ e = deref_dn_r( be, base, &err, &matched, &text );
+
+ } else {
+ e = dn2entry_r( be, base, &matched );
+ err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
+ text = NULL;
+ }
+
+ if ( e == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, err,
+ matched_dn, text, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ return 1;
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ char *matched_dn = ch_strdup( e->e_dn );
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
- if ( tlimit == 0 && be_isroot( be, op->o_dn ) ) {
+ cache_return_entry_r( &li->li_cache, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
+
+ return 1;
+ }
+
+ if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
tlimit = -1; /* allow root to set no limit */
} else {
tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
be->be_timelimit : tlimit;
stoptime = op->o_time + tlimit;
}
- if ( slimit == 0 && be_isroot( be, op->o_dn ) ) {
+
+ if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
slimit = -1; /* allow root to set no limit */
} else {
slimit = (slimit > be->be_sizelimit || slimit < 1) ?
be->be_sizelimit : slimit;
}
- switch ( scope ) {
- case LDAP_SCOPE_BASE:
- candidates = base_candidates( be, conn, op, base, filter,
- attrs, attrsonly, &matched, &err );
- break;
-
- case LDAP_SCOPE_ONELEVEL:
- candidates = onelevel_candidates( be, conn, op, base, filter,
- attrs, attrsonly, &matched, &err );
- break;
-
- case LDAP_SCOPE_SUBTREE:
- candidates = subtree_candidates( be, conn, op, base, filter,
- attrs, attrsonly, &matched, NULL, &err, 1 );
- break;
-
- default:
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, "",
- "Bad scope" );
- return( -1 );
+ if ( scope == LDAP_SCOPE_BASE) {
+ candidates = base_candidate( be, e );
+
+ } else {
+ candidates = search_candidates( be, e, filter,
+ scope, deref, manageDSAit );
}
- /* null candidates means we could not find the base object */
+ /* need normalized dn below */
+ realbase = ch_strdup( e->e_ndn );
+ cache_return_entry_r( &li->li_cache, e );
+
if ( candidates == NULL ) {
- send_ldap_result( conn, op, err, matched, "" );
- if ( matched != NULL ) {
- free( matched );
- }
- return( -1 );
+ /* no candidates */
+ Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
+ 0, 0 );
+
+ send_search_result( conn, op,
+ LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 0 );
+
+ rc = 1;
+ goto done;
}
- rmaxsize = 0;
- nrefs = 0;
- rbuf = rcur = NULL;
- MAKE_SPACE( sizeof("Referral:") + 1 );
- strcpy( rbuf, "Referral:" );
- rcur = strchr( rbuf, '\0' );
- for ( id = idl_firstid( candidates ); id != NOID;
- id = idl_nextid( candidates, id ) ) {
+ for ( id = idl_firstid( candidates, &cursor ); id != NOID;
+ id = idl_nextid( candidates, &cursor ) )
+ {
+ int scopeok = 0;
+
/* check for abandon */
- pthread_mutex_lock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+
if ( op->o_abandon ) {
- pthread_mutex_unlock( &op->o_abandonmutex );
- idl_free( candidates );
- free( rbuf );
- return( 0 );
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ rc = 0;
+ goto done;
}
- pthread_mutex_unlock( &op->o_abandonmutex );
+
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* check time limit */
- pthread_mutex_lock( ¤ttime_mutex );
- time( ¤ttime );
- if ( tlimit != -1 && currenttime > stoptime ) {
- pthread_mutex_unlock( ¤ttime_mutex );
- send_ldap_search_result( conn, op,
- LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
- NULL, nentries );
- idl_free( candidates );
- free( rbuf );
- return( 0 );
+ if ( tlimit != -1 && slap_get_time() > stoptime ) {
+ send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+ NULL, NULL, v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
}
- pthread_mutex_unlock( ¤ttime_mutex );
- /* get the entry */
- if ( (e = id2entry( be, id )) == NULL ) {
- Debug( LDAP_DEBUG_ARGS, "candidate %d not found\n", id,
- 0, 0 );
- continue;
+ /* get the entry with reader lock */
+ e = id2entry_r( be, id );
+
+ if ( e == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n",
+ id, 0, 0 );
+
+ goto loop_continue;
+ }
+
+ if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
+ Entry *matched;
+ int err;
+ char *text;
+
+ e = deref_entry_r( be, e, &err, &matched, &text );
+
+ if( e == NULL ) {
+ e = matched;
+ goto loop_continue;
+ }
+
+ if( e->e_id == id ) {
+ /* circular loop */
+ goto loop_continue;
+ }
+
+ /* need to skip alias which deref into scope */
+ if( scope & LDAP_SCOPE_ONELEVEL ) {
+ char *pdn = dn_parent( NULL, e->e_ndn );
+ if ( pdn != NULL ) {
+ if( strcmp( pdn, realbase ) ) {
+ free( pdn );
+ goto loop_continue;
+ }
+ free(pdn);
+ }
+
+ } else if ( dn_issuffix( e->e_ndn, realbase ) ) {
+ /* alias is within scope */
+ Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n",
+ e->e_dn, 0, 0 );
+ goto loop_continue;
+ }
+
+ scopeok = 1;
}
/*
* if it's a referral, add it to the list of referrals. only do
- * this for subtree searches, and don't check the filter explicitly
- * here since it's only a candidate anyway.
+ * this for non-base searches, and don't check the filter
+ * explicitly here since it's only a candidate anyway.
*/
- if ( e->e_dn != NULL && strncasecmp( e->e_dn, "ref=", 4 )
- == 0 && (ref = attr_find( e->e_attrs, "ref" )) != NULL &&
- scope == LDAP_SCOPE_SUBTREE )
+ if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
+ is_entry_referral( e ) )
{
- int i, len;
+ struct berval **refs = get_entry_referrals(
+ be, conn, op, e );
- if ( ref->a_vals == NULL ) {
- Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n", 0,
- 0, 0 );
- } else {
- for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
- /* referral + newline + null */
- MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
- *rcur++ = '\n';
- strncpy( rcur, ref->a_vals[i]->bv_val,
- ref->a_vals[i]->bv_len );
- rcur = rcur + ref->a_vals[i]->bv_len;
- *rcur = '\0';
- nrefs++;
- }
- }
+ send_search_reference( be, conn, op,
+ e, refs, scope, NULL, &v2refs );
- /* otherwise it's an entry - see if it matches the filter */
- } else {
- /* if it matches the filter and scope, send it */
- if ( test_filter( be, conn, op, e, filter ) == 0 ) {
- int scopeok;
- char *dn;
+ ber_bvecfree( refs );
- /* check scope */
- scopeok = 1;
- if ( scope == LDAP_SCOPE_ONELEVEL ) {
- if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
- (void) dn_normalize( dn );
- scopeok = (dn == base) ? 1 : (! strcasecmp( dn, base ));
- } else {
- scopeok = (base == NULL || *base == '\0');
- }
- free( dn );
- } else if ( scope == LDAP_SCOPE_SUBTREE ) {
- dn = strdup( e->e_dn );
- (void) dn_normalize( dn );
- scopeok = dn_issuffix( dn, base );
+ goto loop_continue;
+ }
+
+ /* if it matches the filter and scope, send it */
+ if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+ char *dn;
+
+ /* check scope */
+ if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
+ if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
+ (void) dn_normalize_case( dn );
+ scopeok = (dn == realbase)
+ ? 1
+ : (strcmp( dn, realbase ) ? 0 : 1 );
free( dn );
+
+ } else {
+ scopeok = (realbase == NULL || *realbase == '\0');
}
- if ( scopeok ) {
- /* check size limit */
- if ( --slimit == -1 ) {
- cache_return_entry( &li->li_cache, e );
- send_ldap_search_result( conn, op,
- LDAP_SIZELIMIT_EXCEEDED, NULL,
- nrefs > 0 ? rbuf : NULL, nentries );
- idl_free( candidates );
- free( rbuf );
- return( 0 );
- }
+ } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
+ dn = ch_strdup( e->e_ndn );
+ scopeok = dn_issuffix( dn, realbase );
+ free( dn );
+
+ } else {
+ scopeok = 1;
+ }
+
+ if ( scopeok ) {
+ /* check size limit */
+ if ( --slimit == -1 ) {
+ cache_return_entry_r( &li->li_cache, e );
+ send_search_result( conn, op,
+ LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
+ v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
+ }
+ if (e) {
switch ( send_search_entry( be, conn, op, e,
- attrs, attrsonly ) ) {
+ attrs, attrsonly, NULL ) ) {
case 0: /* entry sent ok */
nentries++;
break;
case 1: /* entry not sent */
break;
case -1: /* connection closed */
- cache_return_entry( &li->li_cache, e );
- idl_free( candidates );
- free( rbuf );
- return( 0 );
+ cache_return_entry_r( &li->li_cache, e );
+ rc = 0;
+ goto done;
}
}
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n",
+ id, 0, 0 );
}
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n",
+ id, 0, 0 );
}
- cache_return_entry( &li->li_cache, e );
+loop_continue:
+ if( e != NULL ) {
+ /* free reader lock */
+ cache_return_entry_r( &li->li_cache, e );
+ }
- pthread_yield();
+ ldap_pvt_thread_yield();
}
+ send_search_result( conn, op,
+ v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+ NULL, NULL, v2refs, NULL, nentries );
+
+ rc = 0;
+
+done:
idl_free( candidates );
- if ( nrefs > 0 ) {
- send_ldap_search_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- rbuf, nentries );
- } else {
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
- nentries );
- }
- free( rbuf );
- return( 0 );
+ ber_bvecfree( v2refs );
+ if( realbase ) free( realbase );
+
+ return rc;
}
-static IDList *
-base_candidates(
+static ID_BLOCK *
+base_candidate(
Backend *be,
- Connection *conn,
- Operation *op,
- char *base,
- Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- int *err
+ Entry *e
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- int rc;
- ID id;
- IDList *idl;
- Entry *e;
+ ID_BLOCK *idl;
- *err = LDAP_SUCCESS;
- if ( (e = dn2entry( be, base, matched )) == NULL ) {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
- }
+ Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
+ e->e_dn, 0, 0);
idl = idl_alloc( 1 );
idl_insert( &idl, e->e_id, 1 );
- cache_return_entry( &li->li_cache, e );
-
return( idl );
}
-static IDList *
-onelevel_candidates(
+static ID_BLOCK *
+search_candidates(
Backend *be,
- Connection *conn,
- Operation *op,
- char *base,
+ Entry *e,
Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- int *err
+ int scope,
+ int deref,
+ int manageDSAit
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Entry *e;
- Filter *f;
- char buf[20];
- IDList *candidates;
-
- *err = LDAP_SUCCESS;
- e = NULL;
- /* get the base object */
- if ( base != NULL && *base != '\0' && (e = dn2entry( be, base,
- matched )) == NULL ) {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
+ ID_BLOCK *candidates;
+ Filter *f, *rf, *af, *lf;
+
+ Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
+ e->e_ndn, scope, deref );
+
+ f = NULL;
+
+ if( !manageDSAit ) {
+ /* match referrals */
+ rf = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_next = NULL;
+ rf->f_choice = LDAP_FILTER_OR;
+ rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ rf->f_or->f_avtype = ch_strdup( "objectclass" );
+ rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
+ rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
+ rf->f_or->f_next = filter;
+ f = rf;
+ } else {
+ rf = NULL;
+ f = filter;
}
- /*
- * modify the filter to be something like this:
- *
- * parent=baseobject & originalfilter
- */
-
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_AND;
- f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_and->f_choice = LDAP_FILTER_EQUALITY;
- f->f_and->f_ava.ava_type = strdup( "id2children" );
- sprintf( buf, "%d", e != NULL ? e->e_id : 0 );
- f->f_and->f_ava.ava_value.bv_val = strdup( buf );
- f->f_and->f_ava.ava_value.bv_len = strlen( buf );
- f->f_and->f_next = filter;
-
- /* from here, it's just like subtree_candidates */
- candidates = subtree_candidates( be, conn, op, base, f, attrs,
- attrsonly, matched, e, err, 0 );
-
- /* free up just the filter stuff we allocated above */
- f->f_and->f_next = NULL;
- filter_free( f );
+ if( deref & LDAP_DEREF_SEARCHING ) {
+ /* match aliases */
+ af = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_next = NULL;
+ af->f_choice = LDAP_FILTER_OR;
+ af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ af->f_or->f_avtype = ch_strdup( "objectclass" );
+ af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
+ af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
+ af->f_or->f_next = f;
+ f = af;
+ } else {
+ af = NULL;
+ }
- return( candidates );
-}
+ if ( scope == LDAP_SCOPE_SUBTREE ) {
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
-static IDList *
-subtree_candidates(
- Backend *be,
- Connection *conn,
- Operation *op,
- char *base,
- Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- Entry *e,
- int *err,
- int lookupbase
-)
-{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Filter *f;
- IDList *candidates;
-
- /*
- * get the base object - unless we already have it (from one-level).
- * also, unless this is a one-level search or a subtree search
- * starting at the very top of our subtree, we need to modify the
- * filter to be something like this:
- *
- * dn=*baseobjectdn & (originalfilter | ref=*)
- *
- * the "objectclass=referral" part is used to select referrals to return
- */
-
- *err = LDAP_SUCCESS;
- f = NULL;
- if ( lookupbase ) {
- if ( base != NULL && *base != '\0' && (e = dn2entry( be, base,
- matched )) == NULL ) {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
- }
-
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_OR;
- f->f_or = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_or->f_choice = LDAP_FILTER_EQUALITY;
- f->f_or->f_avtype = strdup( "objectclass" );
- f->f_or->f_avvalue.bv_val = strdup( "referral" );
- f->f_or->f_avvalue.bv_len = strlen( "referral" );
- f->f_or->f_next = filter;
- filter = f;
-
- if ( ! be_issuffix( be, base ) ) {
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_AND;
- f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
- f->f_and->f_sub_type = strdup( "dn" );
- f->f_and->f_sub_initial = NULL;
- f->f_and->f_sub_any = NULL;
- f->f_and->f_sub_final = strdup( base );
- value_normalize( f->f_and->f_sub_final, SYNTAX_CIS );
- f->f_and->f_next = filter;
- filter = f;
- }
+ lf->f_and->f_choice = SLAPD_FILTER_DN_SUBTREE;
+ lf->f_and->f_dn = e->e_ndn;
+
+ lf->f_and->f_next = f;
+ f = lf;
+
+ } else if ( scope == LDAP_SCOPE_ONELEVEL ) {
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+
+ lf->f_and->f_choice = SLAPD_FILTER_DN_ONE;
+ lf->f_and->f_dn = e->e_ndn;
+
+ lf->f_and->f_next = f;
+ f = lf;
+
+ } else {
+ lf = NULL;
}
- candidates = filter_candidates( be, filter );
+ candidates = filter_candidates( be, f );
+
+ /* free up filter additions we allocated above */
+ if( lf != NULL ) {
+ free( lf->f_and );
+ free( lf );
+ }
- /* free up just the parts we allocated above */
- if ( f != NULL ) {
- f->f_and->f_next = NULL;
- filter_free( f );
+ if( af != NULL ) {
+ af->f_or->f_next = NULL;
+ filter_free( af );
}
- if ( e != NULL ) {
- cache_return_entry( &li->li_cache, e );
+ if( rf != NULL ) {
+ rf->f_or->f_next = NULL;
+ filter_free( rf );
}
return( candidates );
--- /dev/null
+/* startup.c - startup ldbm backend */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <direct.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "ldap_defaults.h"
+#include "slap.h"
+#include "back-ldbm.h"
+
+#ifdef HAVE_DB1_DB_H
+# include <db1/db.h>
+#else
+# include <db.h>
+#endif
+
+#ifdef HAVE_BERKELEY_DB2
+
+void
+ldbm_db_errcall( const char *prefix, const char *message )
+{
+ Debug( LDAP_DEBUG_ANY, "ldbm_db_errcall(): %s %s", prefix, message, 0 );
+}
+
+#endif /* HAVE_BERKELEY_DB2 */
+
+
+void
+ldbm_back_startup(
+ Backend *be
+)
+{
+#ifndef HAVE_BERKELEY_DB2
+ /* make sure we have one and only one big mutex */
+ static int protect = 0;
+
+ if(!protect++) {
+ ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
+ }
+
+#else
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ DB_ENV *dbEnv = &li->li_db_env;
+ int envFlags = DB_CREATE | DB_THREAD;
+ int err = 0;
+ char *home;
+
+ /* if the data directory is not an absolute path, have it relative
+ to the current working directory (which should not be configured !) */
+ if ( *li->li_directory != *LDAP_DIRSEP ) {
+ char cwd[MAXPATHLEN];
+
+ (void) getcwd( cwd, MAXPATHLEN );
+ sprintf( cwd, "%s" LDAP_DIRSEP "%s", cwd, li->li_directory );
+ free( li->li_directory );
+ li->li_directory = strdup( cwd );
+
+ }
+
+ /* set the DB home directory to the data dir */
+ home = li->li_directory;
+
+ /* general initialization of the environment */
+ memset( dbEnv, 0, sizeof( DB_ENV ));
+ dbEnv->db_errcall = ldbm_db_errcall;
+ dbEnv->db_errpfx = "==>";
+
+ /* now do the db_appinit */
+ if ( ( err = db_appinit( home, NULL, dbEnv, envFlags )) ) {
+ char error[BUFSIZ];
+
+ if ( err < 0 ) sprintf( error, "%ld\n", (long) err );
+ else sprintf( error, "%s\n", strerror( err ));
+
+ fprintf( stderr,
+ "ldbm_back_startup(): FATAL error in db_appinit() : %s\n",
+ error );
+ exit( EXIT_FAILURE );
+
+ }
+#endif
+}
+
+
+void
+ldbm_back_shutdown(
+ Backend *be
+)
+{
+#ifdef HAVE_BERKELEY_DB2
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ (void) db_appexit( &li->li_db_env );
+#endif
+}
--- /dev/null
+/* tools.c - tools for slap tools */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-ldbm.h"
+
+static LDBMCursor *cursorp = NULL;
+static DBCache *id2entry = NULL;
+
+int ldbm_tool_entry_open(
+ BackendDB *be, int mode )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ int flags;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry == NULL );
+
+ switch( mode ) {
+ case 1:
+ flags = LDBM_WRCREAT;
+ break;
+ case 2:
+#ifdef TRUNCATE_MODE
+ flags = LDBM_NEWDB;
+#else
+ flags = LDBM_WRCREAT;
+#endif
+ break;
+ default:
+ flags = LDBM_READER;
+ }
+
+ li->li_dbcachewsync = 0;
+
+ if ( (id2entry = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, flags ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry" LDBM_SUFFIX "\n",
+ 0, 0, 0 );
+ return( -1 );
+ }
+
+ return 0;
+}
+
+int ldbm_tool_entry_close(
+ BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ ldbm_cache_close( be, id2entry );
+ li->li_dbcachewsync = 1;
+ id2entry = NULL;
+
+ return 0;
+}
+
+ID ldbm_tool_entry_first(
+ BackendDB *be )
+{
+ Datum key;
+ ID id;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ key = ldbm_firstkey( id2entry->dbc_db, &cursorp );
+
+ if( key.dptr == NULL ) {
+ return NOID;
+ }
+
+ memcpy( &id, key.dptr, key.dsize );
+
+ ldbm_datum_free( id2entry->dbc_db, key );
+
+ return id;
+}
+
+ID ldbm_tool_entry_next(
+ BackendDB *be )
+{
+ Datum key;
+ ID id;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ /* allow for NEXTID */
+ ldbm_datum_init( key );
+
+ key = ldbm_nextkey( id2entry->dbc_db, key, cursorp );
+
+ if( key.dptr == NULL ) {
+ return NOID;
+ }
+
+ memcpy( &id, key.dptr, key.dsize );
+
+ ldbm_datum_free( id2entry->dbc_db, key );
+
+ return id;
+}
+
+Entry* ldbm_tool_entry_get( BackendDB *be, ID id )
+{
+ Entry *e;
+ Datum key, data;
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ ldbm_datum_init( key );
+
+ key.dptr = (char *) &id;
+ key.dsize = sizeof(ID);
+
+ data = ldbm_cache_fetch( id2entry, key );
+
+ if ( data.dptr == NULL ) {
+ return NULL;
+ }
+
+ e = str2entry( data.dptr );
+ ldbm_datum_free( id2entry->dbc_db, data );
+
+ return e;
+}
+
+ID ldbm_tool_entry_put(
+ BackendDB *be,
+ Entry *e )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Datum key, data;
+ int rc, len;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+ assert( id2entry != NULL );
+
+ if( next_id_get( be ) == NOID ) {
+ return NOID;
+ }
+
+ e->e_id = li->li_nextid++;
+
+ Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_put( %ld, \"%s\" )\n",
+ e->e_id, e->e_dn, 0 );
+
+ rc = index_add_entry( be, e );
+
+ if( rc != 0 ) {
+ return NOID;
+ }
+
+ rc = dn2id_add( be, e->e_ndn, e->e_id );
+
+ if( rc != 0 ) {
+ return NOID;
+ }
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ key.dptr = (char *) &e->e_id;
+ key.dsize = sizeof(ID);
+
+ data.dptr = entry2str( e, &len );
+ data.dsize = len + 1;
+
+ /* store it */
+ rc = ldbm_cache_store( id2entry, key, data, LDBM_REPLACE );
+
+ if( rc != 0 ) {
+ (void) dn2id_delete( be, e->e_ndn );
+ return NOID;
+ }
+
+ return e->e_id;
+}
+
+int ldbm_tool_index_attr(
+ BackendDB *be,
+ char* type )
+{
+ static DBCache *db = NULL;
+ int indexmask, syntaxmask;
+ char * at_cn;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+
+ attr_masks( be->be_private, type, &indexmask, &syntaxmask );
+
+ attr_normalize( type );
+ at_cn = at_canonical_name( type );
+
+ if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_NEWDB ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "<= index_read NULL (could not open %s%s)\n", at_cn,
+ LDBM_SUFFIX, 0 );
+ return 0;
+ }
+
+ ldbm_cache_close( be, db );
+
+ return indexmask != 0;
+}
+
+int ldbm_tool_index_change(
+ BackendDB *be,
+ char* type,
+ struct berval **bv,
+ ID id,
+ int op )
+{
+ assert( slapMode & SLAP_TOOL_MODE );
+
+ index_change_values( be,
+ type, bv, id, op );
+
+ return 0;
+}
+
+int ldbm_tool_sync( BackendDB *be )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ assert( slapMode & SLAP_TOOL_MODE );
+
+ if ( li->li_nextid != NOID ) {
+ next_id_write( be, li->li_nextid );
+ }
+
+ return 0;
+}
/* unbind.c - handle an ldap unbind operation */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+#include <ac/socket.h>
+
#include "slap.h"
-int
+void
ldbm_back_unbind(
Backend *be,
Connection *conn,
Operation *op
)
{
- return( 0 );
}
--- /dev/null
+SRCS = search.c config.c init.c
+OBJS = search.lo config.lo init.lo
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-passwd"
+BUILD_MOD = @BUILD_PASSWD@
+LINKAGE = @BUILD_PASSWD_DYNAMIC@
+
+LIBBASE = back_passwd
+
+XINCPATH = -I.. -I$(srcdir)/..
+XDEFS = $(MODULES_CPPFLAGS)
+XLDFLAGS = $(MODULES_LDFLAGS)
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+ @touch $@
+
--- /dev/null
+/* init.c - initialize passwd backend */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "external.h"
+
+#ifdef SLAPD_PASSWD_DYNAMIC
+
+int back_passwd_LTX_init_module(int argc, char *argv[]) {
+ BackendInfo bi;
+
+ memset( &bi, 0, sizeof(bi) );
+ bi.bi_type = "passwd";
+ bi.bi_init = passwd_back_initialize;
+
+ backend_add(&bi);
+ return 0;
+}
+
+#endif /* SLAPD_PASSWD_DYNAMIC */
+
+int
+passwd_back_initialize(
+ BackendInfo *bi
+)
+{
+ bi->bi_open = 0;
+ bi->bi_config = 0;
+ bi->bi_close = 0;
+ bi->bi_destroy = 0;
+
+ bi->bi_db_init = 0;
+ bi->bi_db_config = 0;
+ bi->bi_db_open = 0;
+ bi->bi_db_close = 0;
+ bi->bi_db_destroy = 0;
+
+ bi->bi_op_bind = 0;
+ bi->bi_op_unbind = 0;
+ bi->bi_op_search = passwd_back_search;
+ bi->bi_op_compare = 0;
+ bi->bi_op_modify = 0;
+ bi->bi_op_modrdn = 0;
+ bi->bi_op_add = 0;
+ bi->bi_op_delete = 0;
+ bi->bi_op_abandon = 0;
+
+ bi->bi_acl_group = 0;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ return 0;
+}
--- /dev/null
+###########################################################################
+#
+# Copyright 1999, John C. Quillan, All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted only
+# as authorized by the OpenLDAP Public License. A copy of this
+# license is available at http://www.OpenLDAP.org/license.html or
+# in file LICENSE in the top-level directory of the distribution.
+#
+##########################################################################
+
+SRCS = init.c search.c close.c config.c bind.c unbind.c compare.c \
+ modify.c add.c modrdn.c delete.c
+OBJS = init.lo search.lo close.lo config.lo bind.lo unbind.lo compare.lo \
+ modify.lo add.lo modrdn.lo delete.lo
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-perl"
+BUILD_MOD = @BUILD_PERL@
+LINKAGE = @BUILD_PERL_DYNAMIC@
+
+LIBBASE = back_perl
+
+XINCPATH = -I.. -I$(srcdir)/..
+XDEFS = $(PERL_CPPFLAGS) $(MODULES_CPPFLAGS)
+XLDFLAGS = $(MODULES_LDFLAGS)
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+ @touch $@
+
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+/* #include <ac/types.h>
+ #include <ac/socket.h>
+*/
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+int
+perl_back_add(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e
+)
+{
+ int len;
+ int count;
+ int return_code;
+
+ PerlBackend *perl_back = (PerlBackend *) be->be_private;
+
+ ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );
+ ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+
+ {
+ dSP; ENTER; SAVETMPS;
+
+ PUSHMARK(sp);
+ XPUSHs( perl_back->pb_obj_ref );
+ XPUSHs(sv_2mortal(newSVpv( entry2str( e, &len ), 0 )));
+
+ PUTBACK;
+
+ count = perl_call_method("add", G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1) {
+ croak("Big trouble in back_search\n");
+ }
+
+ return_code = POPi;
+
+ PUTBACK; FREETMPS; LEAVE;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
+ ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
+
+ if( return_code != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ }
+
+ Debug( LDAP_DEBUG_ANY, "Here ADD\n", 0, 0, 0 );
+ return( 0 );
+}
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+/* init.c - initialize shell backend */
+
+#include <stdio.h>
+/* #include <ac/types.h>
+ #include <ac/socket.h>
+*/
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+
+/**********************************************************
+ *
+ * Config
+ *
+ **********************************************************/
+int
+perl_back_db_config(
+ BackendDB *be,
+ char *fname,
+ int lineno,
+ int argc,
+ char **argv
+)
+{
+ SV* loc_sv;
+ PerlBackend *perl_back = (PerlBackend *) be->be_private;
+ char eval_str[EVAL_BUF_SIZE];
+ int count ;
+ int args;
+ int return_code;
+
+
+ if ( strcasecmp( argv[0], "perlModule" ) == 0 ) {
+ if ( argc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s.pm: line %d: missing module in \"perlModule <module>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ strncpy(eval_str, argv[1], EVAL_BUF_SIZE );
+
+ perl_require_pv( strcat( eval_str, ".pm" ));
+
+ if (SvTRUE(GvSV(errgv))) {
+ fprintf(stderr , "Error %s\n", SvPV(GvSV(errgv), na)) ;
+
+ } else {
+ dSP; ENTER; SAVETMPS;
+ PUSHMARK(sp);
+ XPUSHs(sv_2mortal(newSVpv(argv[1], 0)));
+ PUTBACK;
+
+ count = perl_call_method("new", G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1) {
+ croak("Big trouble in config\n") ;
+ }
+
+ perl_back->pb_obj_ref = newSVsv(POPs);
+
+ PUTBACK; FREETMPS; LEAVE ;
+ }
+
+ } else if ( strcasecmp( argv[0], "perlModulePath" ) == 0 ) {
+ if ( argc < 2 ) {
+ fprintf( stderr,
+ "%s: line %d: missing module in \"PerlModulePath <module>\" line\n",
+ fname, lineno );
+ return( 1 );
+ }
+
+ sprintf( eval_str, "push @INC, '%s';", argv[1] );
+ loc_sv = perl_eval_pv( eval_str, 0 );
+
+ } else {
+ /*
+ * Pass it to Perl module if defined
+ */
+
+ {
+ dSP ; ENTER ; SAVETMPS;
+
+ PUSHMARK(sp) ;
+ XPUSHs( perl_back->pb_obj_ref );
+
+ /* Put all arguments on the perl stack */
+ for( args = 0; args < argc; args++ ) {
+ XPUSHs(sv_2mortal(newSVpv(argv[args], 0)));
+ }
+
+ PUTBACK ;
+
+ count = perl_call_method("config", G_SCALAR);
+
+ SPAGAIN ;
+
+ if (count != 1) {
+ croak("Big trouble in config\n") ;
+ }
+
+ return_code = POPi;
+
+ PUTBACK ; FREETMPS ; LEAVE ;
+
+ }
+
+ /* if the module rejected it then we should reject it */
+ if ( return_code != 0 ) {
+ fprintf( stderr,
+ "Unknown perl backeng config: %s\n", argv[0]);
+ exit( EXIT_FAILURE );
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+ /* init.c - initialize shell backend */
+
+#include <stdio.h>
+/* #include <ac/types.h>
+ #include <ac/socket.h>
+*/
+
+
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+
+
+PerlInterpreter *perl_interpreter = NULL;
+ldap_pvt_thread_mutex_t perl_interpreter_mutex;
+
+#ifdef SLAPD_PERL_DYNAMIC
+
+int back_perl_LTX_init_module(int argc, char *argv[]) {
+ BackendInfo bi;
+
+ memset( &bi, 0, sizeof(bi) );
+ bi.bi_type = "perl";
+ bi.bi_init = perl_back_initialize;
+
+ backend_add(&bi);
+ return 0;
+}
+
+#endif /* SLAPD_PERL_DYNAMIC */
+
+
+/**********************************************************
+ *
+ * Init
+ *
+ **********************************************************/
+
+int
+perl_back_initialize(
+ BackendInfo *bi
+)
+{
+ char *embedding[] = { "", "-e", "0" };
+
+ Debug( LDAP_DEBUG_TRACE, "perl backend open\n", 0, 0, 0 );
+
+ if( perl_interpreter != NULL ) {
+ Debug( LDAP_DEBUG_ANY, "perl backend open: already opened\n",
+ 0, 0, 0 );
+ return 1;
+ }
+
+ perl_interpreter = perl_alloc();
+ perl_construct(perl_interpreter);
+ perl_parse(perl_interpreter, NULL, 3, embedding, (char **)NULL);
+ perl_run(perl_interpreter);
+
+ bi->bi_open = perl_back_open;
+ bi->bi_config = 0;
+ bi->bi_close = perl_back_close;
+ bi->bi_destroy = perl_back_destroy;
+
+ bi->bi_db_init = perl_back_db_init;
+ bi->bi_db_config = perl_back_db_config;
+ bi->bi_db_open = 0;
+ bi->bi_db_close = 0;
+ bi->bi_db_destroy = perl_back_db_destroy;
+
+ bi->bi_op_bind = perl_back_bind;
+ bi->bi_op_unbind = perl_back_unbind;
+ bi->bi_op_search = perl_back_search;
+ bi->bi_op_compare = perl_back_compare;
+ bi->bi_op_modify = perl_back_modify;
+ bi->bi_op_modrdn = perl_back_modrdn;
+ bi->bi_op_add = perl_back_add;
+ bi->bi_op_delete = perl_back_delete;
+ bi->bi_op_abandon = 0;
+
+ bi->bi_acl_group = 0;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ return 0;
+}
+
+int
+perl_back_open(
+ BackendInfo *bi
+)
+{
+ ldap_pvt_thread_mutex_init( &perl_interpreter_mutex );
+ return 0;
+}
+
+int
+perl_back_db_init(
+ Backend *be
+)
+{
+ be->be_private = (PerlBackend *) ch_malloc( sizeof(PerlBackend) );
+ memset( be->be_private, 0, sizeof(PerlBackend));
+
+ Debug( LDAP_DEBUG_TRACE, "perl backend db init\n", 0, 0, 0 );
+
+ return 0;
+}
+
--- /dev/null
+SRCS = init.c config.c fork.c search.c bind.c unbind.c add.c delete.c \
+ modify.c modrdn.c compare.c abandon.c result.c
+OBJS = init.lo config.lo fork.lo search.lo bind.lo unbind.lo add.lo delete.lo \
+ modify.lo modrdn.lo compare.lo abandon.lo result.lo
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-shell"
+BUILD_MOD = @BUILD_SHELL@
+LINKAGE = @BUILD_SHELL_DYNAMIC@
+
+LIBBASE = back_shell
+
+XINCPATH = -I.. -I$(srcdir)/..
+XDEFS = $(MODULES_CPPFLAGS)
+XLDFLAGS = $(MODULES_LDFLAGS)
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+ @touch $@
+
/* add.c - shell backend add function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "shell.h"
-extern pthread_mutex_t entry2str_mutex;
-extern char *entry2str();
-
-void
+int
shell_back_add(
Backend *be,
Connection *conn,
if ( si->si_add == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "add not implemented" );
- return;
+ "add not implemented", NULL, NULL );
+ return( -1 );
}
- if ( (op->o_private = forkandexec( si->si_add, &rfp, &wfp )) == -1 ) {
+ if ( (op->o_private = (void *) forkandexec( si->si_add, &rfp, &wfp )) == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
- return;
+ "could not fork/exec", NULL, NULL );
+ return( -1 );
}
/* write out the request to the add process */
fprintf( wfp, "ADD\n" );
- fprintf( wfp, "msgid: %d\n", op->o_msgid );
+ fprintf( wfp, "msgid: %ld\n", op->o_msgid );
print_suffixes( wfp, be );
- pthread_mutex_lock( &entry2str_mutex );
- fprintf( wfp, "%s", entry2str( e, &len, 0 ) );
- pthread_mutex_unlock( &entry2str_mutex );
+ ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+ fprintf( wfp, "%s", entry2str( e, &len ) );
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
fclose( wfp );
/* read in the result and send it along */
read_and_send_results( be, conn, op, rfp, NULL, 0 );
fclose( rfp );
+ return( 0 );
}
/* fork.c - fork and exec a process, connecting stdin/out w/pipes */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
#include "slap.h"
+#include "shell.h"
+pid_t
forkandexec(
char **args,
FILE **rfp,
)
{
int p2c[2], c2p[2];
- int pid;
+ pid_t pid;
if ( pipe( p2c ) != 0 || pipe( c2p ) != 0 ) {
Debug( LDAP_DEBUG_ANY, "pipe failed\n", 0, 0, 0 );
* parent *rfp <- c2p[0] | c2p[1] <- stdout child
*/
- switch ( (pid = fork()) ) {
+#ifdef HAVE_THR
+ switch ( (pid = fork1()) )
+#else
+ switch ( (pid = fork()) )
+#endif
+ {
case 0: /* child */
+ /*
+ * child could deadlock here due to resources locked
+ * by our parent
+ *
+ * If so, configure --without-threads or implement forking
+ * via a surrogate parent.
+ */
close( p2c[1] );
close( c2p[0] );
if ( dup2( p2c[0], 0 ) == -1 || dup2( c2p[1], 1 ) == -1 ) {
Debug( LDAP_DEBUG_ANY, "dup2 failed\n", 0, 0, 0 );
- exit( -1 );
+ exit( EXIT_FAILURE );
}
execv( args[0], args );
Debug( LDAP_DEBUG_ANY, "execv failed\n", 0, 0, 0 );
- exit( -1 );
+ exit( EXIT_FAILURE );
case -1: /* trouble */
Debug( LDAP_DEBUG_ANY, "fork failed\n", 0, 0, 0 );
/* init.c - initialize shell backend */
+#include "portable.h"
+
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+
#include "slap.h"
#include "shell.h"
-shell_back_init(
+#ifdef SLAPD_SHELL_DYNAMIC
+
+int back_shell_LTX_init_module(int argc, char *argv[]) {
+ BackendInfo bi;
+
+ memset( &bi, 0, sizeof(bi) );
+ bi.bi_type = "shell";
+ bi.bi_init = shell_back_initialize;
+
+ backend_add(&bi);
+ return 0;
+}
+
+#endif /* SLAPD_SHELL_DYNAMIC */
+
+int
+shell_back_initialize(
+ BackendInfo *bi
+)
+{
+ bi->bi_open = 0;
+ bi->bi_config = 0;
+ bi->bi_close = 0;
+ bi->bi_destroy = 0;
+
+ bi->bi_db_init = shell_back_db_init;
+ bi->bi_db_config = shell_back_db_config;
+ bi->bi_db_open = 0;
+ bi->bi_db_close = 0;
+ bi->bi_db_destroy = shell_back_db_destroy;
+
+ bi->bi_op_bind = shell_back_bind;
+ bi->bi_op_unbind = shell_back_unbind;
+ bi->bi_op_search = shell_back_search;
+ bi->bi_op_compare = shell_back_compare;
+ bi->bi_op_modify = shell_back_modify;
+ bi->bi_op_modrdn = shell_back_modrdn;
+ bi->bi_op_add = shell_back_add;
+ bi->bi_op_delete = shell_back_delete;
+ bi->bi_op_abandon = shell_back_abandon;
+
+ bi->bi_acl_group = 0;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ return 0;
+}
+
+int
+shell_back_db_init(
Backend *be
)
{
si = (struct shellinfo *) ch_calloc( 1, sizeof(struct shellinfo) );
be->be_private = si;
+
+ return si == NULL;
+}
+
+int
+shell_back_db_destroy(
+ Backend *be
+)
+{
+ free( be->be_private );
+ return 0;
}
/* result.c - shell backend result reading function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
#include "slap.h"
#include "shell.h"
-extern Entry *str2entry();
-
int
read_and_send_results(
Backend *be,
buf, 0, 0 );
} else {
send_search_entry( be, conn, op, e, attrs,
- attrsonly );
+ attrsonly, NULL );
entry_free( e );
}
/* otherwise, front end will send this result */
if ( err != 0 || op->o_tag != LDAP_REQ_BIND ) {
- send_ldap_result( conn, op, err, matched, info );
+ send_ldap_result( conn, op, err, matched, info, NULL, NULL );
}
free( buf );
--- /dev/null
+###########################################################################
+#
+# Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted only
+# as authorized by the OpenLDAP Public License. A copy of this
+# license is available at http://www.OpenLDAP.org/license.html or
+# in file LICENSE in the top-level directory of the distribution.
+#
+##########################################################################
+
+SRCS = tcl_init.c tcl_search.c tcl_close.c tcl_config.c tcl_bind.c \
+ tcl_unbind.c tcl_compare.c tcl_modify.c tcl_add.c tcl_modrdn.c \
+ tcl_delete.c tcl_abandon.c tcl_util.c
+OBJS = tcl_init.lo tcl_search.lo tcl_close.lo tcl_config.lo tcl_bind.lo \
+ tcl_unbind.lo tcl_compare.lo tcl_modify.lo tcl_add.lo tcl_modrdn.lo \
+ tcl_delete.lo tcl_abandon.lo tcl_util.lo
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-tcl"
+BUILD_MOD = @BUILD_TCL@
+LINKAGE = @BUILD_TCL_DYNAMIC@
+
+LIBBASE = back_tcl
+
+XDEFS = $(MODULES_CPPFLAGS)
+XLDFLAGS = $(MODULES_LDFLAGS)
+XINCPATH = -I.. -I$(srcdir)/..
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+ @touch $@
+
--- /dev/null
+/* add.c - tcl add routine
+ *
+ * $Id: tcl_add.c,v 1.7 1999/08/02 23:38:43 hallvard Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_add (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ Entry * e
+)
+{
+ char *command, *suf_tcl, *entrystr, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_add == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "add not implemented", NULL, NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ entrystr = tcl_clean_entry (e);
+
+ command = (char *) ch_malloc (strlen (ti->ti_add) + strlen
+ (suf_tcl) +
+ strlen (entrystr) + 32);
+ sprintf (command, "%s ADD {%ld} {%s} {%s}",
+ ti->ti_add, op->o_msgid, suf_tcl, entrystr);
+ Tcl_Free (suf_tcl);
+ free (entrystr);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_add_error: %s\n", results, 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL, NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* bind.c - tcl bind routines
+ *
+ * $Id: tcl_bind.c,v 1.8 1999/08/02 23:38:43 hallvard Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_bind (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn,
+ int method,
+ char *mech,
+ struct berval *cred,
+ char **edn
+)
+{
+ char *command, *suf_tcl, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ *edn = NULL;
+
+ if (ti->ti_bind == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "bind not implemented", NULL, NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_bind) + strlen
+ (suf_tcl) +
+ strlen (dn) + strlen (cred->bv_val) + 64);
+ sprintf (command, "%s BIND {%ld} {%s} {%s} {%d} {%lu} {%s}",
+ ti->ti_bind, op->o_msgid, suf_tcl, dn, method, cred->bv_len,
+ cred->bv_val);
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_bind_error: %s\n", results, 0, 0);
+ } else {
+ err = interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL, NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* compare.c - tcl compare routines
+ *
+ * $Id: tcl_compare.c,v 1.7 1999/08/02 23:38:43 hallvard Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_compare (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn,
+ Ava * ava
+)
+{
+ char *command, *suf_tcl, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_compare == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "compare not implemented", NULL, NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_compare) +
+ strlen (suf_tcl) + strlen (dn) + strlen (ava->ava_type) +
+ strlen (ava->ava_value.bv_val) + 64);
+ sprintf (command, "%s COMPARE {%ld} {%s} {%s} {%s: %s}",
+ ti->ti_compare, op->o_msgid, suf_tcl, dn, ava->ava_type,
+ ava->ava_value.bv_val);
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_compare_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL, NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* delete.c - tcl delete routines
+ *
+ * $Id: tcl_delete.c,v 1.7 1999/08/02 23:38:43 hallvard Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+tcl_back_delete (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn
+)
+{
+ char *command, *suf_tcl, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_delete == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "delete not implemented", NULL, NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_delete) + strlen (suf_tcl)
+ + strlen (dn) + 64);
+ sprintf (command, "%s DELETE {%ld} {%s} {%s}",
+ ti->ti_delete, op->o_msgid, suf_tcl, dn);
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_delete_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL, NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* tcl_init.c - tcl backend initialization
+ *
+ * $Id: tcl_init.c,v 1.11 1999/08/07 09:37:45 hyc Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+ldap_pvt_thread_mutex_t tcl_interpreter_mutex;
+
+#ifdef SLAPD_TCL_DYNAMIC
+
+void back_tcl_LTX_init_module(int argc, char *argv[]) {
+ BackendInfo bi;
+
+ memset( &bi, 0, sizeof(bi) );
+ bi.bi_type = "tcl";
+ bi.bi_init = tcl_back_initialize;
+
+ backend_add(&bi);
+}
+
+#endif /* SLAPD_TCL_DYNAMIC */
+
+int
+tcl_back_initialize (
+ BackendInfo * bi
+)
+{
+ /* Initialize the global interpreter array */
+ global_i = (struct i_info *) ch_malloc (sizeof (struct i_info));
+
+ global_i->count = 0;
+ global_i->name = "default";
+ global_i->next = NULL;
+ global_i->interp = Tcl_CreateInterp ();
+ Tcl_Init (global_i->interp);
+
+ /* Initialize the global interpreter lock */
+ ldap_pvt_thread_mutex_init (&tcl_interpreter_mutex);
+
+ bi->bi_open = tcl_back_open;
+ bi->bi_config = 0;
+ bi->bi_close = tcl_back_close;
+ bi->bi_destroy = tcl_back_destroy;
+
+ bi->bi_db_init = tcl_back_db_init;
+ bi->bi_db_config = tcl_back_db_config;
+ bi->bi_db_open = tcl_back_db_open;
+ bi->bi_db_close = tcl_back_db_close;
+ bi->bi_db_destroy = tcl_back_db_destroy;
+
+ bi->bi_op_bind = tcl_back_bind;
+ bi->bi_op_unbind = tcl_back_unbind;
+ bi->bi_op_search = tcl_back_search;
+ bi->bi_op_compare = tcl_back_compare;
+ bi->bi_op_modify = tcl_back_modify;
+ bi->bi_op_modrdn = tcl_back_modrdn;
+ bi->bi_op_add = tcl_back_add;
+ bi->bi_op_delete = tcl_back_delete;
+ bi->bi_op_abandon = tcl_back_abandon;
+
+ bi->bi_acl_group = 0;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ return 0;
+}
+
+int
+tcl_back_open (
+ BackendInfo * bi
+)
+{
+ /* Initialize the global interpreter array */
+ global_i = (struct i_info *) ch_malloc (sizeof (struct i_info));
+
+ global_i->count = 0;
+ global_i->name = "default";
+ global_i->next = NULL;
+ global_i->interp = Tcl_CreateInterp ();
+ Tcl_Init (global_i->interp);
+
+ /* Initialize the global interpreter lock */
+ ldap_pvt_thread_mutex_init (&tcl_interpreter_mutex);
+
+ return (0);
+}
+
+int
+tcl_back_db_init (
+ Backend * be
+)
+{
+ struct tclinfo *ti;
+
+ ti = (struct tclinfo *) ch_calloc (1, sizeof (struct tclinfo));
+
+ /*
+ * For some reason this causes problems
+ * specifically set to NULL
+ */
+ ti->ti_bind = NULL;
+ ti->ti_unbind = NULL;
+ ti->ti_search = NULL;
+ ti->ti_compare = NULL;
+ ti->ti_modify = NULL;
+ ti->ti_modrdn = NULL;
+ ti->ti_add = NULL;
+ ti->ti_delete = NULL;
+ ti->ti_abandon = NULL;
+
+ be->be_private = ti;
+
+ return ti == NULL;
+}
+
+int
+tcl_back_db_open (
+ BackendDB * bd
+)
+{
+ struct tclinfo *ti = (struct tclinfo *) bd->be_private;
+
+ if (ti->ti_ii->interp == NULL) { /* we need to make a new one */
+ ti->ti_ii->interp = Tcl_CreateInterp ();
+ Tcl_Init (ti->ti_ii->interp);
+ }
+
+ /* raise that count for the interpreter */
+ ti->ti_ii->count++;
+
+ /* now let's (try to) load the script */
+ readtclscript (ti->script_path, ti->ti_ii->interp);
+
+ /* Intall the debug command */
+ Tcl_CreateCommand (ti->ti_ii->interp, "ldap:debug", &tcl_ldap_debug,
+ NULL, NULL);
+
+ return 0;
+}
--- /dev/null
+/* modify.c - tcl modify routines
+ *
+ * $Id: tcl_modify.c,v 1.7 1999/08/02 23:38:43 hallvard Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_modify (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn,
+ LDAPModList * modlist
+)
+{
+ char *command, *suf_tcl, *bp, *tcl_mods, *results;
+ int i, code, err = 0, len, bsize;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_modify == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "modify not implemented", NULL, NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ tcl_mods = (char *) ch_malloc (BUFSIZ);
+ tcl_mods[0] = '\0';
+ bsize = BUFSIZ;
+ bp = tcl_mods;
+
+ for (; modlist != NULL; modlist = modlist->ml_next) {
+ LDAPMod *mods = &modlist->ml_mod;
+ char *op = NULL;
+
+ switch (mods->mod_op & ~LDAP_MOD_BVALUES) {
+ case LDAP_MOD_ADD:
+ op = "add";
+ break;
+ case LDAP_MOD_DELETE:
+ op = "delete";
+ break;
+ case LDAP_MOD_REPLACE:
+ op = "replace";
+ break;
+ }
+
+ len = strlen (mods->mod_type) + strlen (op) + 7;
+ while (bp + len - tcl_mods > bsize) {
+ bsize += BUFSIZ;
+ tcl_mods = (char *) ch_realloc (tcl_mods, bsize);
+ }
+ sprintf (bp, "{ {%s: %s} ", op, mods->mod_type);
+ bp += len;
+ for (i = 0;
+ mods->mod_bvalues != NULL && mods->mod_bvalues[i]
+ != NULL;
+ i++) {
+ len = strlen (mods->mod_type) + strlen (
+ mods->mod_bvalues[i]->bv_val) + 5 +
+ (mods->mod_bvalues[i + 1] == NULL ? 2 : 0);
+ while (bp + len - tcl_mods > bsize) {
+ bsize += BUFSIZ;
+ tcl_mods = (char *) ch_realloc (tcl_mods, bsize);
+ }
+ sprintf (bp, "{%s: %s} %s", mods->mod_type,
+ mods->mod_bvalues[i]->bv_val,
+ mods->mod_bvalues[i + 1] ==
+ NULL ? "} " : "");
+ bp += len;
+ }
+ }
+
+ command = (char *) ch_malloc (strlen (ti->ti_modify) + strlen (suf_tcl)
+ + strlen (dn) + strlen (tcl_mods) + 64);
+ /* This space is simply for aesthetics--\ */
+ sprintf (command, "%s MODIFY {%ld} {%s} {%s} { %s}",
+ ti->ti_modify, op->o_msgid, suf_tcl, dn, tcl_mods);
+ Tcl_Free (suf_tcl);
+ free (tcl_mods);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_modify_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL, NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* modrdn.c - tcl modify rdn routines
+ *
+ * $Id: tcl_modrdn.c,v 1.9 1999/08/02 23:38:43 hallvard Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+/*
+ * LDAP v3 newSuperior support.
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_modrdn (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn,
+ char *newrdn,
+ int deleteoldrdn,
+ char *newSuperior
+)
+{
+ char *command, *suf_tcl, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_modrdn == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "modrdn not implemented", NULL, NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_modrdn) + strlen (suf_tcl)
+ + strlen (dn) + strlen (newrdn)
+ + (newSuperior ? strlen(newSuperior) : 0) + 64);
+ if ( newSuperior ) {
+ sprintf (command, "%s MODRDN {%ld} {%s} {%s} {%s} %d {%s}",
+ ti->ti_add, op->o_msgid, suf_tcl, dn, newrdn,
+ deleteoldrdn ? 1 : 0, newSuperior );
+ } else {
+ sprintf (command, "%s MODRDN {%ld} {%s} {%s} {%s} %d",
+ ti->ti_add, op->o_msgid, suf_tcl, dn, newrdn,
+ deleteoldrdn ? 1 : 0 );
+ }
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_modrdn_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL, NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* search.c - tcl search routines
+ *
+ * $Id: tcl_search.c,v 1.7 1999/08/02 23:38:43 hallvard Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_search (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *base,
+ int scope,
+ int deref,
+ int sizelimit,
+ int timelimit,
+ Filter * filter,
+ char *filterstr,
+ char **attrs,
+ int attrsonly
+)
+{
+ char *attrs_tcl = NULL, *suf_tcl, *results, *command;
+ int i, err = 0, code;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+ Entry *e;
+
+ if (ti->ti_search == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "search not implemented", NULL, NULL );
+ return (-1);
+ }
+
+ for (i = 0; attrs != NULL && attrs[i] != NULL; i++);
+ if (i > 0)
+ attrs_tcl = Tcl_Merge (i, attrs);
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_search) + strlen (suf_tcl)
+ + strlen (base) + 40 + strlen (filterstr) + (attrs_tcl ==
+ NULL ? 5
+ : strlen (attrs_tcl)) + 72);
+ sprintf (command,
+ "%s SEARCH {%ld} {%s} {%s} {%d} {%d} {%d} {%d} {%s} {%d} {%s}",
+ ti->ti_search, op->o_msgid, suf_tcl, base, scope, deref,
+ sizelimit, timelimit, filterstr, attrsonly ? 1 : 0,
+ attrs_tcl ==
+ NULL ? "{all}" : attrs_tcl);
+ Tcl_Free (attrs_tcl);
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_search_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL, NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* result.c - tcl backend utility functions
+ *
+ * $Id: tcl_util.c,v 1.9 1999/08/17 17:01:02 kdz Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+interp_send_results (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *result,
+ char **attrs,
+ int attrsonly
+)
+{
+ int bsize, len, argcPtr, i, err, code;
+ char *buf, *bp, **argvPtr, *line, *matched, *info;
+ Entry *e;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ /*
+ * read in the result and send it along
+ */
+ buf = (char *) ch_malloc (BUFSIZ);
+ buf[0] = '\0';
+ bsize = BUFSIZ;
+ bp = buf;
+ code = Tcl_SplitList (ti->ti_ii->interp, result, &argcPtr, &argvPtr);
+ if (code != TCL_OK) {
+ argcPtr = 0;
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "internal backend error", NULL, NULL );
+ return -1;
+ }
+ for (i = 0; i < argcPtr; i++) {
+ line = argvPtr[i];
+
+ /*
+ * ignore lines beginning with DEBUG:
+ */
+ if (strncasecmp (line, "DEBUG:", 6) == 0) {
+ continue;
+ }
+ len = strlen (line) + 1;
+ while (bp + len - buf > bsize) {
+ bsize += BUFSIZ;
+ buf = (char *) ch_realloc (buf, bsize);
+ }
+ sprintf (bp, "%s\n", line);
+ bp += len;
+
+ /*
+ * line marked the end of an entry or result
+ */
+ if (line[0] == '\0') {
+ if (strncasecmp (buf, "RESULT", 6) == 0) {
+ break;
+ }
+ if ((e = str2entry (buf)) == NULL) {
+ Debug (LDAP_DEBUG_SHELL,
+ "str2entry(%s) failed\n",
+ buf, 0, 0);
+ } else {
+ send_search_entry (be, conn, op, e, attrs,
+ attrsonly, NULL );
+ entry_free (e);
+ }
+
+ bp = buf;
+ }
+ }
+
+ (void) str2result (buf, &err, &matched, &info);
+
+ /*
+ * otherwise, front end will send this result
+ */
+ if (err != 0 || op->o_tag != LDAP_REQ_BIND) {
+ send_ldap_result (conn, op, err, matched, info, NULL, NULL );
+ }
+
+ free (buf);
+ Tcl_Free ((char *) argvPtr);
+ return (err);
+}
+
+char *
+tcl_clean_entry (
+ Entry * e
+)
+{
+ char *entrystr, *mark1, *mark2, *buf, *bp, *dup;
+ int len, bsize;
+
+ ldap_pvt_thread_mutex_lock(&entry2str_mutex);
+ entrystr = entry2str (e, &len);
+
+ buf = (char *) ch_malloc (BUFSIZ);
+ buf[0] = '\0';
+ bsize = BUFSIZ;
+ bp = buf;
+ bp++[0] = ' ';
+
+ mark1 = entrystr;
+ do {
+ if (mark1[0] == '\n') {
+ mark1++;
+ }
+ dup = (char *) ch_strdup (mark1);
+ if (dup[0] != '\0') {
+ if ((mark2 = (char *) strchr (dup, '\n')) != NULL) {
+ mark2[0] = '\0';
+ }
+ len = strlen (dup) + 3;
+ while (bp + len - buf > bsize) {
+ bsize += BUFSIZ;
+ buf = (char *) ch_realloc (buf, bsize);
+ }
+ if (mark1[0] == '\0') {
+ sprintf (bp, "{} ");
+ } else {
+ sprintf (bp, "{%s} ", dup);
+ }
+ bp += len;
+ if (mark2 != NULL) {
+ mark2[0] = '\n';
+ }
+ }
+ free (dup);
+ } while ((mark1 = (char *) strchr (mark1, '\n')) != NULL);
+
+ ldap_pvt_thread_mutex_unlock (&entry2str_mutex);
+ return buf;
+}
+
+int
+tcl_ldap_debug (
+ ClientData clientData,
+ Tcl_Interp * interp,
+ int argc,
+ char *argv[]
+)
+{
+ if (argv[1] != NULL) {
+ Debug (LDAP_DEBUG_SHELL, "tcl_debug: %s\n", argv[1], 0, 0);
+ }
+ return TCL_OK;
+}
+
+void
+readtclscript (
+ char *script,
+ Tcl_Interp * my_tcl)
+{
+ int code;
+ FILE *f;
+
+ f = fopen (script, "r");
+ if (f == NULL) {
+ Debug (LDAP_DEBUG_SHELL, "Could not open scriptpath %s\n", script,
+ 0, 0);
+ return;
+ }
+ fclose (f);
+ code = Tcl_EvalFile (my_tcl, script);
+ if (code != TCL_OK) {
+ Debug (LDAP_DEBUG_SHELL, "%s: %s\n", script,
+ Tcl_GetVar (my_tcl, "errorInfo", TCL_GLOBAL_ONLY), 0);
+ Debug (LDAP_DEBUG_SHELL, "%s: error at line\n", script,
+ my_tcl->errorLine, 0);
+ return;
+ }
+}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/* backend.c - routines for dealing with back-end databases */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include <sys/stat.h>
+
#include "slap.h"
+#include "lutil.h"
-#ifdef LDAP_LDBM
-extern int ldbm_back_bind();
-extern int ldbm_back_unbind();
-extern int ldbm_back_search();
-extern int ldbm_back_compare();
-extern int ldbm_back_modify();
-extern int ldbm_back_modrdn();
-extern int ldbm_back_add();
-extern int ldbm_back_delete();
-extern int ldbm_back_abandon();
-extern int ldbm_back_config();
-extern int ldbm_back_init();
-extern int ldbm_back_close();
-#endif
-
-#ifdef LDAP_PASSWD
-extern int passwd_back_search();
-extern int passwd_back_config();
-#endif
-
-#ifdef LDAP_SHELL
-extern int shell_back_bind();
-extern int shell_back_unbind();
-extern int shell_back_search();
-extern int shell_back_compare();
-extern int shell_back_modify();
-extern int shell_back_modrdn();
-extern int shell_back_add();
-extern int shell_back_delete();
-extern int shell_back_abandon();
-extern int shell_back_config();
-extern int shell_back_init();
-#endif
-
-extern int defsize;
-extern int deftime;
-
-#define BACKEND_GRAB_SIZE 10
-
-int nbackends;
-Backend *backends;
-static int maxbackends;
+#include "ldap_defaults.h"
-Backend *
-new_backend(
+#ifdef SLAPD_LDAP
+#include "back-ldap/external.h"
+#endif
+#ifdef SLAPD_LDBM
+#include "back-ldbm/external.h"
+#endif
+#ifdef SLAPD_BDB2
+#include "back-bdb2/external.h"
+#endif
+#ifdef SLAPD_PASSWD
+#include "back-passwd/external.h"
+#endif
+#ifdef SLAPD_PERL
+#include "back-perl/external.h"
+#endif
+#ifdef SLAPD_SHELL
+#include "back-shell/external.h"
+#endif
+#ifdef SLAPD_TCL
+#include "back-tcl/external.h"
+#endif
+
+static BackendInfo binfo[] = {
+#if defined(SLAPD_LDAP) && !defined(SLAPD_LDAP_DYNAMIC)
+ {"ldap", ldap_back_initialize},
+#endif
+#if defined(SLAPD_LDBM) && !defined(SLAPD_LDBM_DYNAMIC)
+ {"ldbm", ldbm_back_initialize},
+#endif
+#if defined(SLAPD_BDB2) && !defined(SLAPD_BDB2_DYNAMIC)
+ {"bdb2", bdb2_back_initialize},
+#endif
+#if defined(SLAPD_PASSWD) && !defined(SLAPD_PASSWD_DYNAMIC)
+ {"passwd", passwd_back_initialize},
+#endif
+#if defined(SLAPD_PERL) && !defined(SLAPD_PERL_DYNAMIC)
+ {"perl", perl_back_initialize},
+#endif
+#if defined(SLAPD_SHELL) && !defined(SLAPD_SHELL_DYNAMIC)
+ {"shell", shell_back_initialize},
+#endif
+#if defined(SLAPD_TCL) && !defined(SLAPD_LDAP_TCL)
+ {"tcl", tcl_back_initialize},
+#endif
+ {NULL}
+};
+
+int nBackendInfo = 0;
+BackendInfo *backendInfo = NULL;
+
+int nBackendDB = 0;
+BackendDB *backendDB = NULL;
+
+int backend_init(void)
+{
+ int rc = -1;
+
+ if((nBackendInfo != 0) || (backendInfo != NULL)) {
+ /* already initialized */
+ Debug( LDAP_DEBUG_ANY,
+ "backend_init: already initialized.\n", 0, 0, 0 );
+ return -1;
+ }
+
+ for( ;
+ binfo[nBackendInfo].bi_type != NULL;
+ nBackendInfo++ )
+ {
+ rc = binfo[nBackendInfo].bi_init( &binfo[nBackendInfo] );
+
+ if(rc != 0) {
+ Debug( LDAP_DEBUG_ANY,
+ "backend_init: initialized for type \"%s\"\n",
+ binfo[nBackendInfo].bi_type, 0, 0 );
+
+ /* destroy those we've already inited */
+ for( nBackendInfo--;
+ nBackendInfo >= 0 ;
+ nBackendInfo-- )
+ {
+ if ( binfo[nBackendInfo].bi_destroy ) {
+ binfo[nBackendInfo].bi_destroy(
+ &binfo[nBackendInfo] );
+ }
+ }
+ return rc;
+ }
+ }
+
+ if ( nBackendInfo > 0) {
+ backendInfo = binfo;
+ return 0;
+ }
+
+#ifdef SLAPD_MODULES
+ return 0;
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "backend_init: failed\n",
+ 0, 0, 0 );
+
+ return rc;
+#endif /* SLAPD_MODULES */
+}
+
+int backend_add(BackendInfo *aBackendInfo)
+{
+ int rc = 0;
+
+ if ((rc = aBackendInfo->bi_init(aBackendInfo)) != 0) {
+ Debug( LDAP_DEBUG_ANY,
+ "backend_add: initialization for type \"%s\" failed\n",
+ aBackendInfo->bi_type, 0, 0 );
+ return rc;
+ }
+
+ /* now add the backend type to the Backend Info List */
+ {
+ BackendInfo *newBackendInfo = 0;
+
+ /* if backendInfo == binfo no deallocation of old backendInfo */
+ if (backendInfo == binfo) {
+ newBackendInfo = ch_calloc(nBackendInfo + 1, sizeof(BackendInfo));
+ memcpy(newBackendInfo, backendInfo, sizeof(BackendInfo) *
+ nBackendInfo);
+ } else {
+ newBackendInfo = ch_realloc(backendInfo, sizeof(BackendInfo) *
+ (nBackendInfo + 1));
+ }
+ memcpy(&newBackendInfo[nBackendInfo], aBackendInfo,
+ sizeof(BackendInfo));
+ backendInfo = newBackendInfo;
+ nBackendInfo++;
+
+ return 0;
+ }
+}
+
+int backend_startup(Backend *be)
+{
+ int i;
+ int rc = 0;
+
+ if( ! ( nBackendDB > 0 ) ) {
+ /* no databases */
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup: %d databases to startup.\n",
+ nBackendDB, 0, 0 );
+ return 1;
+ }
+
+ if(be != NULL) {
+ /* startup a specific backend database */
+ Debug( LDAP_DEBUG_TRACE,
+ "backend_startup: starting database\n",
+ 0, 0, 0 );
+
+ if ( be->bd_info->bi_open ) {
+ rc = be->bd_info->bi_open( be->bd_info );
+ }
+
+ if(rc != 0) {
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup: bi_open failed!\n",
+ 0, 0, 0 );
+ return rc;
+ }
+
+ if ( be->bd_info->bi_db_open ) {
+ rc = be->bd_info->bi_db_open( be );
+ }
+
+ if(rc != 0) {
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup: bi_db_open failed!\n",
+ 0, 0, 0 );
+ return rc;
+ }
+
+ return rc;
+ }
+
+ /* open each backend type */
+ for( i = 0; i < nBackendInfo; i++ ) {
+ if( backendInfo[i].bi_nDB == 0) {
+ /* no database of this type, don't open */
+ continue;
+ }
+
+ if( backendInfo[i].bi_open ) {
+ rc = backendInfo[i].bi_open(
+ &backendInfo[i] );
+ }
+
+ if(rc != 0) {
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup: bi_open %d failed!\n",
+ i, 0, 0 );
+ return rc;
+ }
+ }
+
+ /* open each backend database */
+ for( i = 0; i < nBackendDB; i++ ) {
+ if ( backendDB[i].bd_info->bi_db_open ) {
+ rc = backendDB[i].bd_info->bi_db_open(
+ &backendDB[i] );
+ }
+
+ if(rc != 0) {
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup: bi_db_open %d failed!\n",
+ i, 0, 0 );
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
+int backend_num( Backend *be )
+{
+ int i;
+
+ if( be == NULL ) return -1;
+
+ for( i = 0; i < nBackendDB; i++ ) {
+ if( be == &backendDB[i] ) return i;
+ }
+ return -1;
+}
+
+int backend_shutdown( Backend *be )
+{
+ int i;
+ int rc = 0;
+
+ if( be != NULL ) {
+ /* shutdown a specific backend database */
+
+ if ( be->bd_info->bi_nDB == 0 ) {
+ /* no database of this type, we never opened it */
+ return 0;
+ }
+
+ if ( be->bd_info->bi_db_close ) {
+ be->bd_info->bi_db_close( be );
+ }
+
+ if( be->bd_info->bi_close ) {
+ be->bd_info->bi_close( be->bd_info );
+ }
+
+ return 0;
+ }
+
+ /* close each backend database */
+ for( i = 0; i < nBackendDB; i++ ) {
+ BackendInfo *bi;
+
+ if ( backendDB[i].bd_info->bi_db_close ) {
+ backendDB[i].bd_info->bi_db_close(
+ &backendDB[i] );
+ }
+
+ if(rc != 0) {
+ Debug( LDAP_DEBUG_ANY,
+ "backend_close: bi_close %s failed!\n",
+ bi->bi_type, 0, 0 );
+ }
+ }
+
+ /* close each backend type */
+ for( i = 0; i < nBackendInfo; i++ ) {
+ if( backendInfo[i].bi_nDB == 0 ) {
+ /* no database of this type */
+ continue;
+ }
+
+ if( backendInfo[i].bi_close ) {
+ backendInfo[i].bi_close(
+ &backendInfo[i] );
+ }
+ }
+
+ return 0;
+}
+
+int backend_destroy(void)
+{
+ int i;
+
+ /* destroy each backend database */
+ for( i = 0; i < nBackendDB; i++ ) {
+ if ( backendDB[i].bd_info->bi_db_destroy ) {
+ backendDB[i].bd_info->bi_db_destroy(
+ &backendDB[i] );
+ }
+ }
+
+ /* destroy each backend type */
+ for( i = 0; i < nBackendInfo; i++ ) {
+ if( backendInfo[i].bi_destroy ) {
+ backendInfo[i].bi_destroy(
+ &backendInfo[i] );
+ }
+ }
+
+#ifdef SLAPD_MODULES
+ if (backendInfo != binfo) {
+ free(backendInfo);
+ }
+#endif /* SLAPD_MODULES */
+
+ nBackendInfo = 0;
+ backendInfo = NULL;
+
+ return 0;
+}
+
+BackendInfo* backend_info(char *type)
+{
+ int i;
+
+ /* search for the backend type */
+ for( i = 0; i < nBackendInfo; i++ ) {
+ if( strcasecmp(backendInfo[i].bi_type, type) == 0 ) {
+ return &backendInfo[i];
+ }
+ }
+
+ return NULL;
+}
+
+
+BackendDB *
+backend_db_init(
char *type
)
{
Backend *be;
- int foundit;
+ BackendInfo *bi = backend_info(type);
+ int rc = 0;
- if ( nbackends == maxbackends ) {
- maxbackends += BACKEND_GRAB_SIZE;
- backends = (Backend *) ch_realloc( (char *) backends,
- maxbackends * sizeof(Backend) );
- memset( &backends[nbackends], '\0', BACKEND_GRAB_SIZE *
- sizeof(Backend) );
+ if( bi == NULL ) {
+ fprintf( stderr, "Unrecognized database type (%s)\n", type );
+ return NULL;
}
+ backendDB = (BackendDB *) ch_realloc(
+ (char *) backendDB,
+ (nBackendDB + 1) * sizeof(Backend) );
+
+ memset( &backendDB[nbackends], '\0', sizeof(Backend) );
+
be = &backends[nbackends++];
+
+ be->bd_info = bi;
be->be_sizelimit = defsize;
be->be_timelimit = deftime;
- foundit = 0;
-
-#ifdef LDAP_LDBM
- if ( strcasecmp( type, "ldbm" ) == 0 ) {
- be->be_bind = ldbm_back_bind;
- be->be_unbind = ldbm_back_unbind;
- be->be_search = ldbm_back_search;
- be->be_compare = ldbm_back_compare;
- be->be_modify = ldbm_back_modify;
- be->be_modrdn = ldbm_back_modrdn;
- be->be_add = ldbm_back_add;
- be->be_delete = ldbm_back_delete;
- be->be_abandon = ldbm_back_abandon;
- be->be_config = ldbm_back_config;
- be->be_init = ldbm_back_init;
- be->be_close = ldbm_back_close;
- be->be_type = "ldbm";
- foundit = 1;
- }
-#endif
-
-#ifdef LDAP_PASSWD
- if ( strcasecmp( type, "passwd" ) == 0 ) {
- be->be_bind = NULL;
- be->be_unbind = NULL;
- be->be_search = passwd_back_search;
- be->be_compare = NULL;
- be->be_modify = NULL;
- be->be_modrdn = NULL;
- be->be_add = NULL;
- be->be_delete = NULL;
- be->be_abandon = NULL;
- be->be_config = passwd_back_config;
- be->be_init = NULL;
- be->be_close = NULL;
- be->be_type = "passwd";
- foundit = 1;
- }
-#endif
-
-#ifdef LDAP_SHELL
- if ( strcasecmp( type, "shell" ) == 0 ) {
- be->be_bind = shell_back_bind;
- be->be_unbind = shell_back_unbind;
- be->be_search = shell_back_search;
- be->be_compare = shell_back_compare;
- be->be_modify = shell_back_modify;
- be->be_modrdn = shell_back_modrdn;
- be->be_add = shell_back_add;
- be->be_delete = shell_back_delete;
- be->be_abandon = shell_back_abandon;
- be->be_config = shell_back_config;
- be->be_init = shell_back_init;
- be->be_close = NULL;
- be->be_type = "shell";
- foundit = 1;
- }
-#endif
-
- if ( be->be_init != NULL ) {
- (*be->be_init)( be );
- }
-
- if ( foundit == 0 ) {
- fprintf( stderr, "Unrecognized database type (%s)\n", type );
- exit( 1 );
+
+ be->be_realm = global_realm != NULL
+ ? ch_strdup( global_realm ) : NULL;
+
+ if(bi->bi_db_init) {
+ rc = bi->bi_db_init( be );
+ }
+
+ if(rc != 0) {
+ fprintf( stderr, "database init failed (%s)\n", type );
+ nbackends--;
+ return NULL;
}
+ bi->bi_nDB++;
return( be );
}
+void
+be_db_close( void )
+{
+ int i;
+
+ for ( i = 0; i < nbackends; i++ ) {
+ if ( backends[i].bd_info->bi_db_close ) {
+ (*backends[i].bd_info->bi_db_close)( &backends[i] );
+ }
+ }
+}
+
Backend *
select_backend( char * dn )
{
dnlen = strlen( dn );
for ( i = 0; i < nbackends; i++ ) {
- for ( j = 0; backends[i].be_suffix != NULL &&
- backends[i].be_suffix[j] != NULL; j++ ) {
- len = strlen( backends[i].be_suffix[j] );
+ for ( j = 0; backends[i].be_nsuffix != NULL &&
+ backends[i].be_nsuffix[j] != NULL; j++ )
+ {
+ len = strlen( backends[i].be_nsuffix[j] );
if ( len > dnlen ) {
continue;
}
- if ( strcasecmp( backends[i].be_suffix[j],
+ if ( strcmp( backends[i].be_nsuffix[j],
dn + (dnlen - len) ) == 0 ) {
return( &backends[i] );
}
}
}
+#ifdef LDAP_ALLOW_NULL_SEARCH_BASE
+ /* Add greg@greg.rim.or.jp
+ * It's quick hack for cheap client
+ * Some browser offer a NULL base at ldap_search
+ *
+ * Should only be used as a last resort. -Kdz
+ */
+ if(dnlen == 0) {
+ Debug( LDAP_DEBUG_TRACE,
+ "select_backend: use default backend\n", 0, 0, 0 );
+ return( &backends[0] );
+ }
+#endif /* LDAP_ALLOW_NULL_SEARCH_BASE */
+
return( NULL );
}
{
int i;
- for ( i = 0; be->be_suffix != NULL && be->be_suffix[i] != NULL; i++ ) {
- if ( strcasecmp( be->be_suffix[i], suffix ) == 0 ) {
+ for ( i = 0; be->be_nsuffix != NULL && be->be_nsuffix[i] != NULL; i++ ) {
+ if ( strcmp( be->be_nsuffix[i], suffix ) == 0 ) {
return( 1 );
}
}
}
int
-be_isroot( Backend *be, char *dn )
+be_isroot( Backend *be, char *ndn )
{
- if ( dn == NULL ) {
+ int rc;
+
+ if ( ndn == NULL || be->be_root_ndn == NULL ) {
return( 0 );
}
- return( be->be_rootdn ? strcasecmp( be->be_rootdn, dn ) == 0
- : 0 );
+ rc = strcmp( be->be_root_ndn, ndn ) ? 0 : 1;
+
+ return(rc);
+}
+
+char *
+be_root_dn( Backend *be )
+{
+ if ( be->be_root_dn == NULL ) {
+ return( "" );
+ }
+
+ return be->be_root_dn;
}
int
-be_isroot_pw( Backend *be, char *dn, struct berval *cred )
+be_isroot_pw( Backend *be, char *ndn, struct berval *cred )
{
- if ( ! be_isroot( be, dn ) || be->be_rootpw == NULL ) {
+ int result;
+
+ if ( ! be_isroot( be, ndn ) ) {
return( 0 );
}
- return( strcmp( be->be_rootpw, cred->bv_val ) == 0 );
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_lock( &crypt_mutex );
+#endif
+
+ result = lutil_passwd( cred->bv_val, be->be_root_pw, NULL );
+
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_unlock( &crypt_mutex );
+#endif
+
+ return result == 0;
}
-void
-be_close()
+int
+be_entry_release_rw( Backend *be, Entry *e, int rw )
+{
+ if ( be->be_release ) {
+ /* free and release entry from backend */
+ return be->be_release( be, e, rw );
+ } else {
+ /* free entry */
+ entry_free( e );
+ return 0;
+ }
+}
+
+int
+backend_unbind(
+ Connection *conn,
+ Operation *op
+)
{
int i;
for ( i = 0; i < nbackends; i++ ) {
- if ( backends[i].be_close != NULL ) {
- (*backends[i].be_close)( &backends[i] );
+ if ( backends[i].be_unbind ) {
+ (*backends[i].be_unbind)( &backends[i], conn, op );
}
}
+
+ return 0;
}
+int
+backend_connection_init(
+ Connection *conn
+)
+{
+ int i;
+
+ for ( i = 0; i < nbackends; i++ ) {
+ if ( backends[i].be_connection_init ) {
+ (*backends[i].be_connection_init)( &backends[i], conn);
+ }
+ }
+
+ return 0;
+}
-void
-be_unbind(
- Connection *conn,
- Operation *op
+int
+backend_connection_destroy(
+ Connection *conn
)
{
int i;
for ( i = 0; i < nbackends; i++ ) {
- if ( backends[i].be_unbind != NULL ) {
- (*backends[i].be_unbind)( &backends[i], conn, op );
+ if ( backends[i].be_connection_destroy ) {
+ (*backends[i].be_connection_destroy)( &backends[i], conn);
}
}
+
+ return 0;
}
+
+int
+backend_group(
+ Backend *be,
+ Entry *target,
+ char *gr_ndn,
+ char *op_ndn,
+ char *objectclassValue,
+ char *groupattrName
+)
+{
+ if (be->be_group)
+ return( be->be_group(be, target, gr_ndn, op_ndn,
+ objectclassValue, groupattrName) );
+ else
+ return(1);
+}
+
+#ifdef SLAPD_SCHEMA_DN
+Attribute *backend_subschemasubentry( Backend *be )
+{
+ /* should be backend specific */
+ static struct berval ss_val = {
+ sizeof(SLAPD_SCHEMA_DN)-1,
+ SLAPD_SCHEMA_DN };
+ static struct berval *ss_vals[2] = { &ss_val, NULL };
+ static Attribute ss_attr = {
+ "subschemasubentry",
+ ss_vals,
+ SYNTAX_DN | SYNTAX_CIS,
+ NULL
+ };
+
+ return &ss_attr;
+}
+#endif
/* bind.c - decode an ldap bind operation and pass it to a backend db */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/string.h>
+#include <ac/socket.h>
-extern char *default_referral;
+#include "slap.h"
-void
+int
do_bind(
Connection *conn,
Operation *op
)
{
BerElement *ber = op->o_ber;
- int version, method, len, rc;
- char *dn;
+ ber_int_t version;
+ ber_tag_t method;
+ char *mech;
+ char *dn, *ndn;
+ ber_tag_t tag;
+ int rc = LDAP_SUCCESS;
struct berval cred;
Backend *be;
Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
+ dn = NULL;
+ ndn = NULL;
+ mech = NULL;
+ cred.bv_val = NULL;
+
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+ /* Force to connection to "anonymous" until bind succeeds.
+ * This may need to be relocated or done on a case by case basis
+ * to handle certain SASL mechanisms.
+ */
+
+ if ( conn->c_cdn != NULL ) {
+ free( conn->c_cdn );
+ conn->c_cdn = NULL;
+ }
+
+ if ( conn->c_dn != NULL ) {
+ free( conn->c_dn );
+ conn->c_dn = NULL;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+ if ( op->o_dn != NULL ) {
+ free( op->o_dn );
+ op->o_dn = ch_strdup( "" );
+ }
+
+ if ( op->o_ndn != NULL ) {
+ free( op->o_ndn );
+ op->o_ndn = ch_strdup( "" );
+ }
+
/*
* Parse the bind request. It looks like this:
*
* authentication CHOICE {
* simple [0] OCTET STRING -- passwd
* krbv42ldap [1] OCTET STRING
- * krbv42dsa [1] OCTET STRING
+ * krbv42dsa [2] OCTET STRING
+ * SASL [3] SaslCredentials
* }
+ * }
+ *
+ * SaslCredentials ::= SEQUENCE {
+ * mechanism LDAPString,
+ * credentials OCTET STRING OPTIONAL
* }
*/
-#ifdef COMPAT30
- /*
- * in version 3.0 there is an extra SEQUENCE tag after the
- * BindRequest SEQUENCE tag.
- */
+ tag = ber_scanf( ber, "{iat" /*}*/, &version, &dn, &method );
+
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ rc = -1;
+ goto cleanup;
+ }
+
+ ndn = ch_strdup( dn );
- {
- BerElement tber;
- unsigned long tlen, ttag;
+ if ( dn_normalize_case( ndn ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "bind: invalid dn (%s)\n", dn, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
+ "invalid DN", NULL, NULL );
+ goto cleanup;
+ }
+
+ op->o_protocol = version;
+
+ if( method != LDAP_AUTH_SASL ) {
+ tag = ber_scanf( ber, /*{*/ "o}", &cred );
- tber = *op->o_ber;
- ttag = ber_skip_tag( &tber, &tlen );
- if ( ber_peek_tag( &tber, &tlen ) == LBER_SEQUENCE ) {
- Debug( LDAP_DEBUG_ANY, "version 3.0 detected\n", 0, 0, 0 );
- conn->c_version = 30;
- rc = ber_scanf(ber, "{{iato}}", &version, &dn, &method, &cred);
} else {
- rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
+ tag = ber_scanf( ber, "{a" /*}*/, &mech );
+
+ if ( tag != LBER_ERROR ) {
+ ber_len_t len;
+ tag = ber_peek_tag( ber, &len );
+
+ if ( tag == LDAP_TAG_LDAPCRED ) {
+ tag = ber_scanf( ber, "o", &cred );
+ }
+
+ if ( tag != LBER_ERROR ) {
+ tag = ber_scanf( ber, /*{{*/ "}}" );
+ }
+ }
}
+
+ if ( tag == LBER_ERROR ) {
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR,
+ "decoding error" );
+ rc = -1;
+ goto cleanup;
}
-#else
- rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
-#endif
- if ( rc == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "decoding error" );
- return;
- }
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- switch ( method ) {
- case LDAP_AUTH_SIMPLE_30:
- method = LDAP_AUTH_SIMPLE;
- break;
-#ifdef KERBEROS
- case LDAP_AUTH_KRBV41_30:
- method = LDAP_AUTH_KRBV41;
- break;
- case LDAP_AUTH_KRBV42_30:
- method = LDAP_AUTH_KRBV42;
- break;
-#endif
- }
+
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "do_bind: get_ctrls failed\n", 0, 0, 0 );
+ goto cleanup;
+ }
+
+ if( method == LDAP_AUTH_SASL ) {
+ Debug( LDAP_DEBUG_TRACE, "do_sasl_bind: dn (%s) mech %s\n",
+ dn, mech, NULL );
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "do_bind: version=%ld dn=\"%s\" method=%ld\n",
+ (unsigned long) version, dn, (unsigned long) method );
}
-#endif /* compat30 */
- dn_normalize( dn );
- Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d BIND dn=\"%s\" method=%d\n",
- conn->c_connid, op->o_opid, dn, method, 0 );
+ Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d BIND dn=\"%s\" method=%ld\n",
+ op->o_connid, op->o_opid, ndn, (unsigned long) method, 0 );
+
+ if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
+ Debug( LDAP_DEBUG_ANY, "do_bind: unknown version=%ld\n",
+ (unsigned long) version, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+ NULL, "version not supported", NULL, NULL );
+ goto cleanup;
+ }
- if ( version != LDAP_VERSION2 ) {
- if ( dn != NULL ) {
- free( dn );
+ if ( method == LDAP_AUTH_SASL ) {
+ if ( version < LDAP_VERSION3 ) {
+ Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%ld\n",
+ (unsigned long) version, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "sasl bind requires LDAPv3" );
+ rc = -1;
+ goto cleanup;
}
- if ( cred.bv_val != NULL ) {
- free( cred.bv_val );
+
+ if( mech == NULL || *mech == '\0' ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_bind: no sasl mechanism provided\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, "no sasl mechanism provided", NULL, NULL );
+ goto cleanup;
}
- Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "version not supported" );
- return;
- }
+ if( !charray_inlist( supportedSASLMechanisms, mech ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_bind: sasl mechanism=\"%s\" not supported.\n",
+ mech, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, "sasl mechanism not supported", NULL, NULL );
+ goto cleanup;
+ }
- Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
- version, dn, method );
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
- /* accept null binds */
- if ( dn == NULL || *dn == '\0' ) {
- if ( dn != NULL ) {
- free( dn );
+ if ( conn->c_authmech != NULL ) {
+ assert( conn->c_bind_in_progress );
+
+ if((strcmp(conn->c_authmech, mech) != 0)) {
+ /* mechanism changed, cancel in progress bind */
+ conn->c_bind_in_progress = 0;
+ if( conn->c_authstate != NULL ) {
+ free(conn->c_authstate);
+ conn->c_authstate = NULL;
+ }
+ free(conn->c_authmech);
+ conn->c_authmech = NULL;
+ }
+
+#ifdef LDAP_DEBUG
+ } else {
+ assert( !conn->c_bind_in_progress );
+ assert( conn->c_authmech == NULL );
+ assert( conn->c_authstate == NULL );
+#endif
}
- if ( cred.bv_val != NULL ) {
- free( cred.bv_val );
+
+ } else {
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+ if ( conn->c_authmech != NULL ) {
+ assert( conn->c_bind_in_progress );
+
+ /* cancel in progress bind */
+ conn->c_bind_in_progress = 0;
+
+ if( conn->c_authstate != NULL ) {
+ free(conn->c_authstate);
+ conn->c_authstate = NULL;
+ }
+ free(conn->c_authmech);
+ conn->c_authmech = NULL;
}
+ }
+
+ conn->c_protocol = version;
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- return;
+ /* accept null binds */
+ if ( ndn == NULL || *ndn == '\0' ) {
+ /*
+ * we already forced connection to "anonymous", we just
+ * need to send success
+ */
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+ goto cleanup;
}
/*
* if we don't hold it.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
- if ( cred.bv_val != NULL ) {
- free( cred.bv_val );
- }
+ if ( (be = select_backend( ndn )) == NULL ) {
if ( cred.bv_len == 0 ) {
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+
+ } else if ( default_referral ) {
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
+
} else {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
+ NULL, NULL, NULL, NULL );
}
- return;
+
+ goto cleanup;
}
- if ( be->be_bind != NULL ) {
- if ( (*be->be_bind)( be, conn, op, dn, method, &cred ) == 0 ) {
- pthread_mutex_lock( &conn->c_dnmutex );
- if ( conn->c_dn != NULL ) {
- free( conn->c_dn );
+ if ( be->be_bind ) {
+ /* alias suffix */
+ char *edn;
+
+ /* deref suffix alias if appropriate */
+ ndn = suffix_alias( be, ndn );
+
+ if ( (*be->be_bind)( be, conn, op, ndn, method, mech, &cred, &edn ) == 0 ) {
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+ conn->c_cdn = dn;
+ dn = NULL;
+
+ if(edn != NULL) {
+ conn->c_dn = edn;
+ } else {
+ conn->c_dn = ndn;
+ ndn = NULL;
}
- conn->c_dn = strdup( dn );
- pthread_mutex_unlock( &conn->c_dnmutex );
+
+ Debug( LDAP_DEBUG_TRACE, "do_bind: bound \"%s\" to \"%s\"\n",
+ conn->c_cdn, conn->c_dn, method );
+
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
/* send this here to avoid a race condition */
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
+
+ } else if (edn != NULL) {
+ free( edn );
}
+
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
- free( dn );
+cleanup:
+ if( dn != NULL ) {
+ free( dn );
+ }
+ if( ndn != NULL ) {
+ free( ndn );
+ }
+ if ( mech != NULL ) {
+ free( mech );
+ }
if ( cred.bv_val != NULL ) {
free( cred.bv_val );
}
+
+ return rc;
}
/* ch_malloc.c - malloc routines that test returns from malloc and friends */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#define CH_FREE 1
+
+#include "portable.h"
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
-char *
+#ifndef CSRIMALLOC
+
+void *
ch_malloc(
- unsigned long size
+ ber_len_t size
)
{
- char *new;
+ void *new;
- if ( (new = (char *) malloc( size )) == NULL ) {
- Debug( LDAP_DEBUG_ANY, "malloc of %d bytes failed\n", size, 0, 0 );
- exit( 1 );
+ if ( (new = (void *) ber_memalloc( size )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "ch_malloc of %lu bytes failed\n",
+ (long) size, 0, 0 );
+ assert( 0 );
+ exit( EXIT_FAILURE );
}
return( new );
}
-char *
+void *
ch_realloc(
- char *block,
- unsigned long size
+ void *block,
+ ber_len_t size
)
{
- char *new;
+ void *new;
if ( block == NULL ) {
return( ch_malloc( size ) );
}
- if ( (new = (char *) realloc( block, size )) == NULL ) {
- Debug( LDAP_DEBUG_ANY, "realloc of %d bytes failed\n", size, 0, 0 );
- exit( 1 );
+ if( size == 0 ) {
+ ch_free( block );
+ }
+
+ if ( (new = (void *) ber_memrealloc( block, size )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "ch_realloc of %lu bytes failed\n",
+ (long) size, 0, 0 );
+ assert( 0 );
+ exit( EXIT_FAILURE );
}
return( new );
}
-char *
+void *
ch_calloc(
- unsigned long nelem,
- unsigned long size
+ ber_len_t nelem,
+ ber_len_t size
+)
+{
+ void *new;
+
+ if ( (new = (void *) ber_memcalloc( nelem, size )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "ch_calloc of %lu elems of %lu bytes failed\n",
+ (long) nelem, (long) size, 0 );
+ assert( 0 );
+ exit( EXIT_FAILURE );
+ }
+
+ return( new );
+}
+
+char *
+ch_strdup(
+ const char *string
)
{
char *new;
- if ( (new = (char *) calloc( nelem, size )) == NULL ) {
- Debug( LDAP_DEBUG_ANY, "calloc of %d elems of %d bytes failed\n",
- nelem, size, 0 );
- exit( 1 );
+ if ( (new = ber_strdup( string )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "ch_strdup(%s) failed\n", string, 0, 0 );
+ assert( 0 );
+ exit( EXIT_FAILURE );
}
return( new );
}
+
+void
+ch_free( void *ptr )
+{
+ ber_memfree( ptr );
+}
+
+#endif
/* charray.c - routines for dealing with char * arrays */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
void
(n + 2) * sizeof(char *) );
}
- (*a)[n++] = s;
+ (*a)[n++] = ch_strdup(s);
(*a)[n] = NULL;
}
*a = (char **) ch_realloc( (char *) *a, (n + nn + 1) * sizeof(char *) );
for ( i = 0; i < nn; i++ ) {
- (*a)[n + i] = s[i];
+ (*a)[n + i] = ch_strdup(s[i]);
}
(*a)[n + nn] = NULL;
}
new = (char **) ch_malloc( (i + 1) * sizeof(char *) );
for ( i = 0; a[i] != NULL; i++ ) {
- new[i] = strdup( a[i] );
+ new[i] = ch_strdup( a[i] );
}
new[i] = NULL;
return( new );
}
+
+char *
+charray2str( char **a )
+{
+ char *s;
+ int i;
+ size_t cur, len = 0;
+
+ if( a == NULL ) return NULL;
+
+ for( i=0 ; a[i] != NULL ; i++ ) {
+ len += strlen( a[i] );
+ }
+
+ if( len == 0 ) return NULL;
+
+ s = ch_malloc( len + 1 );
+
+ cur = 0;
+ for( i=0 ; a[i] != NULL ; i++ ) {
+ len = strlen( a[i] );
+ strncpy( &s[cur], a[i], len );
+ cur += len;
+ }
+ s[len] = '\0';
+ return s;
+}
+
+
char **
str2charray( char *str, char *brkstr )
{
char **res;
char *s;
+ char *lasts;
int i;
+ /* protect the input string from strtok */
+ str = ch_strdup( str );
+
i = 1;
for ( s = str; *s; s++ ) {
if ( strchr( brkstr, *s ) != NULL ) {
res = (char **) ch_malloc( (i + 1) * sizeof(char *) );
i = 0;
- for ( s = strtok( str, brkstr ); s != NULL; s = strtok( NULL,
- brkstr ) ) {
- res[i++] = strdup( s );
+
+ for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
+ s != NULL;
+ s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
+ {
+ res[i++] = ch_strdup( s );
}
+
res[i] = NULL;
+ free( str );
return( res );
}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/socket.h>
-extern char *default_referral;
+#include "slap.h"
-void
+int
do_compare(
Connection *conn,
Operation *op
)
{
- char *dn;
+ char *ndn;
Ava ava;
- int rc;
Backend *be;
+ int rc = LDAP_SUCCESS;
Debug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_compare: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the compare request. It looks like this:
*
* }
*/
- if ( ber_scanf( op->o_ber, "{a{ao}}", &dn, &ava.ava_type,
+ if ( ber_scanf( op->o_ber, "{a{ao}}", &ndn, &ava.ava_type,
&ava.ava_value ) == LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
}
+
+ if( dn_normalize_case( ndn ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "do_compare: invalid dn (%s)\n", ndn, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
+ "invalid DN", NULL, NULL );
+ free( ndn );
+ ava_free( &ava, 0 );
+ return rc;
+ }
+
+ if( ( rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ free( ndn );
+ ava_free( &ava, 0 );
+ Debug( LDAP_DEBUG_ANY, "do_compare: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
+
value_normalize( ava.ava_value.bv_val, attr_syntax( ava.ava_type ) );
- dn_normalize( dn );
Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n",
- dn, ava.ava_type, ava.ava_value.bv_val );
+ ndn, ava.ava_type, ava.ava_value.bv_val );
- Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d CMP dn=\"%s\" attr=\"%s\"\n",
- conn->c_connid, op->o_opid, dn, ava.ava_type, 0 );
+ Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d CMP dn=\"%s\" attr=\"%s\"\n",
+ op->o_connid, op->o_opid, ndn, ava.ava_type, 0 );
/*
* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
+ if ( (be = select_backend( ndn )) == NULL ) {
+ free( ndn );
ava_free( &ava, 0 );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
+ return 1;
}
- if ( be->be_compare != NULL ) {
- (*be->be_compare)( be, conn, op, dn, &ava );
+ /* deref suffix alias if appropriate */
+ ndn = suffix_alias( be, ndn );
+
+ if ( be->be_compare ) {
+ (*be->be_compare)( be, conn, op, ndn, &ava );
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
- free( dn );
+ free( ndn );
ava_free( &ava, 0 );
+
+ return rc;
}
/* config.c - configuration file handling routines */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/socket.h>
+
+#include "ldap_defaults.h"
#include "slap.h"
-#include "ldapconfig.h"
#define MAXARGS 100
-extern Backend *new_backend();
-extern char *default_referral;
-extern int ldap_syslog;
-extern int global_schemacheck;
-
/*
* defaults for various global variables
*/
int defsize = SLAPD_DEFAULT_SIZELIMIT;
int deftime = SLAPD_DEFAULT_TIMELIMIT;
-struct acl *global_acl = NULL;
+AccessControl *global_acl = NULL;
int global_default_access = ACL_READ;
char *replogfile;
-int global_lastmod;
+int global_lastmod = ON;
+int global_idletimeout = 0;
+char *global_realm = NULL;
char *ldap_srvtab = "";
-static char *fp_getline();
-static void fp_getline_init();
-static void fp_parse_line();
+char *slapd_pid_file = NULL;
+char *slapd_args_file = NULL;
+
+static char *fp_getline(FILE *fp, int *lineno);
+static void fp_getline_init(int *lineno);
+static int fp_parse_line(char *line, int *argcp, char **argv);
-static char *strtok_quote();
+static char *strtok_quote(char *line, char *sep);
-void
-read_config( char *fname, Backend **bep, FILE *pfp )
+int
+read_config( char *fname )
{
FILE *fp;
- char *line, *savefname, *dn;
+ char *line, *savefname, *saveline;
int cargc, savelineno;
char *cargv[MAXARGS];
int lineno, i;
- Backend *be;
+#ifdef HAVE_TLS
+ int rc;
+#endif
+ struct berval *vals[2];
+ struct berval val;
+
+ static BackendInfo *bi = NULL;
+ static BackendDB *be = NULL;
+
+ vals[0] = &val;
+ vals[1] = NULL;
- if ( (fp = pfp) == NULL && (fp = fopen( fname, "r" )) == NULL ) {
+ if ( (fp = fopen( fname, "r" )) == NULL ) {
ldap_syslog = 1;
Debug( LDAP_DEBUG_ANY,
"could not open config file \"%s\" - absolute path?\n",
fname, 0, 0 );
perror( fname );
- exit( 1 );
+ return 1;
}
Debug( LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0 );
- be = *bep;
+
+ if ( schema_init( ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "error initializing the schema\n",
+ 0, 0, 0 );
+ return( 1 );
+ }
+
fp_getline_init( &lineno );
+
while ( (line = fp_getline( fp, &lineno )) != NULL ) {
/* skip comments and blank lines */
if ( line[0] == '#' || line[0] == '\0' ) {
Debug( LDAP_DEBUG_CONFIG, "line %d (%s)\n", lineno, line, 0 );
- fp_parse_line( line, &cargc, cargv );
+ /* fp_parse_line is destructive, we save a copy */
+ saveline = ch_strdup( line );
+
+ if ( fp_parse_line( line, &cargc, cargv ) != 0 ) {
+ return( 1 );
+ }
if ( cargc < 1 ) {
Debug( LDAP_DEBUG_ANY,
continue;
}
+ if ( strcasecmp( cargv[0], "backend" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing type in \"backend <type>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ if( be != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: backend line must appear before any database definition\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ bi = backend_info( cargv[1] );
+
/* start of a new database definition */
- if ( strcasecmp( cargv[0], "database" ) == 0 ) {
+ } else if ( strcasecmp( cargv[0], "database" ) == 0 ) {
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing type in \"database <type>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
- *bep = new_backend( cargv[1] );
- be = *bep;
+ bi = NULL;
+ be = backend_db_init( cargv[1] );
- /* set size limit */
+ /* assign a default depth limit for alias deref */
+ be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;
+
+ /* get pid file name */
+ } else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing file name in \"pidfile <file>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ slapd_pid_file = ch_strdup( cargv[1] );
+
+ /* get args file name */
+ } else if ( strcasecmp( cargv[0], "argsfile" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing file name in \"argsfile <file>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ slapd_args_file = ch_strdup( cargv[1] );
+
+ /* set DIGEST realm */
+ } else if ( strcasecmp( cargv[0], "digest-realm" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing realm in \"digest-realm <realm>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+ if ( be != NULL ) {
+ be->be_realm = ch_strdup( cargv[1] );
+
+ } else if ( global_realm != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: already set global realm!\n",
+ fname, lineno, 0 );
+ return 1;
+
+ } else {
+ global_realm = ch_strdup( cargv[1] );
+ }
+
+ /* set time limit */
} else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing limit in \"sizelimit <limit>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
defsize = atoi( cargv[1] );
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing limit in \"timelimit <limit>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
deftime = atoi( cargv[1] );
/* set database suffix */
} else if ( strcasecmp( cargv[0], "suffix" ) == 0 ) {
+ Backend *tmp_be;
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing dn in \"suffix <dn>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
} else if ( cargc > 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: extra cruft after <dn> in \"suffix %s\" line (ignored)\n",
Debug( LDAP_DEBUG_ANY,
"%s: line %d: suffix line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
+ } else if ( ( tmp_be = select_backend( cargv[1] ) ) == be ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: suffix already served by this backend (ignored)\n",
+ fname, lineno, 0 );
+ } else if ( tmp_be != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: suffix already served by a preceeding backend \"%s\" (ignored)\n",
+ fname, lineno, tmp_be->be_suffix[0] );
} else {
- dn = strdup( cargv[1] );
+ char *dn = ch_strdup( cargv[1] );
(void) dn_normalize( dn );
charray_add( &be->be_suffix, dn );
+ (void) str2upper( dn );
+ charray_add( &be->be_nsuffix, dn );
+ free( dn );
+ }
+
+ /* set database suffixAlias */
+ } else if ( strcasecmp( cargv[0], "suffixAlias" ) == 0 ) {
+ Backend *tmp_be;
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: missing alias and aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ } else if ( cargc < 3 ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: missing aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ } else if ( cargc > 3 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
+ fname, lineno, 0 );
}
+ if ( be == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: suffixAlias line"
+ " must appear inside a database definition (ignored)\n",
+ fname, lineno, 0 );
+ } else if ( (tmp_be = select_backend( cargv[1] )) != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: suffixAlias served by"
+ " a preceeding backend \"%s\" (ignored)\n",
+ fname, lineno, tmp_be->be_suffix[0] );
+
+ } else if ( (tmp_be = select_backend( cargv[2] )) != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: suffixAlias derefs to differnet backend"
+ " a preceeding backend \"%s\" (ignored)\n",
+ fname, lineno, tmp_be->be_suffix[0] );
+
+ } else {
+ char *alias, *aliased_dn;
+
+ alias = ch_strdup( cargv[1] );
+ (void) dn_normalize( alias );
+
+ aliased_dn = ch_strdup( cargv[2] );
+ (void) dn_normalize( aliased_dn );
+
+ (void) dn_normalize_case( alias );
+ (void) dn_normalize_case( aliased_dn );
+ charray_add( &be->be_suffixAlias, alias );
+ charray_add( &be->be_suffixAlias, aliased_dn );
+
+ free(alias);
+ free(aliased_dn);
+ }
+
+ /* set max deref depth */
+ } else if ( strcasecmp( cargv[0], "maxDerefDepth" ) == 0 ) {
+ int i;
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+ if ( be == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: depth line must appear inside a database definition (ignored)\n",
+ fname, lineno, 0 );
+ } else if ((i = atoi(cargv[1])) < 0) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: depth must be positive (ignored)\n",
+ fname, lineno, 0 );
+
+ } else {
+ be->be_max_deref_depth = i;
+ }
+
+
/* set magic "root" dn for this database */
} else if ( strcasecmp( cargv[0], "rootdn" ) == 0 ) {
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing dn in \"rootdn <dn>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: rootdn line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
} else {
- dn = strdup( cargv[1] );
- (void) dn_normalize( dn );
- be->be_rootdn = dn;
+ be->be_root_dn = ch_strdup( cargv[1] );
+ be->be_root_ndn = ch_strdup( cargv[1] );
+
+ if( dn_normalize_case( be->be_root_ndn ) == NULL ) {
+ free( be->be_root_dn );
+ free( be->be_root_ndn );
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: rootdn DN is invalid\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
}
/* set super-secret magic database password */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing passwd in \"rootpw <passwd>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: rootpw line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
} else {
- be->be_rootpw = strdup( cargv[1] );
+ be->be_root_pw = ch_strdup( cargv[1] );
}
/* make this database read-only */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing on|off in \"readonly <on|off>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing URL in \"referral <URL>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
- default_referral = (char *) malloc( strlen( cargv[1] )
- + sizeof("Referral:\n") + 1 );
- strcpy( default_referral, "Referral:\n" );
- strcat( default_referral, cargv[1] );
+ vals[0]->bv_val = cargv[1];
+ vals[0]->bv_len = strlen( vals[0]->bv_val );
+ value_add( &default_referral, vals );
+
+ /* specify locale */
+ } else if ( strcasecmp( cargv[0], "locale" ) == 0 ) {
+#ifdef HAVE_LOCALE_H
+ char *locale;
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing locale in \"locale <name | on | off>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ locale = (strcasecmp( cargv[1], "on" ) == 0 ? ""
+ : strcasecmp( cargv[1], "off" ) == 0 ? "C"
+ : ch_strdup( cargv[1] ) );
+
+ if ( setlocale( LC_CTYPE, locale ) == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ (*locale
+ ? "%s: line %d: bad locale \"%s\"\n"
+ : "%s: line %d: bad locale\n"),
+ fname, lineno, locale );
+ return( 1 );
+ }
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"locale\" unsupported\n",
+ fname, lineno, 0 );
+ return( 1 );
+#endif
/* specify an objectclass */
} else if ( strcasecmp( cargv[0], "objectclass" ) == 0 ) {
- parse_oc( be, fname, lineno, cargc, cargv );
+ if ( *cargv[1] == '(' ) {
+ char * p;
+ p = strchr(saveline,'(');
+ parse_oc( fname, lineno, p );
+ } else {
+ parse_oc_old( be, fname, lineno, cargc, cargv );
+ }
/* specify an attribute */
} else if ( strcasecmp( cargv[0], "attribute" ) == 0 ) {
- attr_syntax_config( fname, lineno, cargc - 1,
- &cargv[1] );
+ if ( *cargv[1] == '(' ) {
+ char * p;
+ p = strchr(saveline,'(');
+ parse_at( fname, lineno, p );
+ } else {
+ attr_syntax_config( fname, lineno, cargc - 1,
+ &cargv[1] );
+ }
/* turn on/off schema checking */
} else if ( strcasecmp( cargv[0], "schemacheck" ) == 0 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing on|off in \"schemacheck <on|off>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
- if ( strcasecmp( cargv[1], "on" ) == 0 ) {
- global_schemacheck = 1;
- } else {
+ if ( strcasecmp( cargv[1], "off" ) == 0 ) {
global_schemacheck = 0;
+ } else {
+ global_schemacheck = 1;
}
/* specify access control info */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing limit in \"defaultaccess <access>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
- if ( (global_default_access =
- str2access( cargv[1] )) == -1 ) {
+ if ( ACL_IS_INVALID(ACL_SET(global_default_access,
+ str2access(cargv[1]))) )
+ {
Debug( LDAP_DEBUG_ANY,
-"%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n",
+"%s: line %d: bad access \"%s\" expecting [self]{none|auth|compare|search|read|write}\n",
fname, lineno, cargv[1] );
- exit( 1 );
+ return( 1 );
}
} else {
- if ( (be->be_dfltaccess =
- str2access( cargv[1] )) == -1 ) {
+ if ( ACL_IS_INVALID(ACL_SET(be->be_dfltaccess,
+ str2access(cargv[1]))) )
+ {
Debug( LDAP_DEBUG_ANY,
-"%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n",
+ "%s: line %d: bad access \"%s\", "
+ "expecting [self]{none|auth|compare|search|read|write}\n",
fname, lineno, cargv[1] );
- exit( 1 );
+ return( 1 );
}
}
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing level in \"loglevel <level>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
ldap_syslog = atoi( cargv[1] );
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing host in \"replica <host[:port]>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
if ( strncasecmp( cargv[i], "host=", 5 )
== 0 ) {
charray_add( &be->be_replica,
- strdup( cargv[i] + 5 ) );
+ cargv[i] + 5 );
break;
}
}
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing dn in \"updatedn <dn>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: updatedn line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
} else {
- be->be_updatedn = strdup( cargv[1] );
- (void) dn_normalize( be->be_updatedn );
+ be->be_update_ndn = ch_strdup( cargv[1] );
+ if( dn_normalize_case( be->be_update_ndn ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: updatedn DN is invalid\n",
+ fname, lineno, 0 );
+ return 1;
+ }
+ }
+
+ } else if ( strcasecmp( cargv[0], "updateref" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing dn in \"updateref <ldapurl>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+ if ( be == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: updateref line must appear inside a database definition (ignored)\n",
+ fname, lineno, 0 );
+ } else if ( be->be_update_ndn == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: updateref line must after updatedn (ignored)\n",
+ fname, lineno, 0 );
+ } else {
+ vals[0]->bv_val = cargv[1];
+ vals[0]->bv_len = strlen( vals[0]->bv_val );
+ value_add( &be->be_update_refs, vals );
}
/* replication log file to which changes are appended */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing dn in \"replogfile <filename>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be ) {
- be->be_replogfile = strdup( cargv[1] );
+ be->be_replogfile = ch_strdup( cargv[1] );
} else {
- replogfile = strdup( cargv[1] );
+ replogfile = ch_strdup( cargv[1] );
}
/* maintain lastmodified{by,time} attributes */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing on|off in \"lastmod <on|off>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( strcasecmp( cargv[1], "on" ) == 0 ) {
if ( be )
global_lastmod = OFF;
}
+ /* set idle timeout value */
+ } else if ( strcasecmp( cargv[0], "idletimeout" ) == 0 ) {
+ int i;
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing timeout value in \"idletimeout <seconds>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ i = atoi( cargv[1] );
+
+ if( i < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: timeout value (%d) invalid \"idletimeout <seconds>\" line\n",
+ fname, lineno, i );
+ return( 1 );
+ }
+
+ global_idletimeout = i;
+
/* include another config file */
} else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing filename in \"include <filename>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
- savefname = strdup( cargv[1] );
+ savefname = ch_strdup( cargv[1] );
savelineno = lineno;
- read_config( savefname, bep, NULL );
- be = *bep;
+
+ if ( read_config( savefname ) != 0 ) {
+ return( 1 );
+ }
+
free( savefname );
lineno = savelineno - 1;
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing filename in \"srvtab <filename>\" line\n",
fname, lineno, 0 );
- exit( 1 );
- }
- ldap_srvtab = strdup( cargv[1] );
-
- /* pass anything else to the current backend config routine */
+ return( 1 );
+ }
+ ldap_srvtab = ch_strdup( cargv[1] );
+
+#ifdef SLAPD_MODULES
+ } else if (strcasecmp( cargv[0], "moduleload") == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing filename in \"moduleload <filename>\" line\n",
+ fname, lineno, 0 );
+ exit( EXIT_FAILURE );
+ }
+ if (module_load(cargv[1], cargc - 2, (cargc > 2) ? cargv + 2 : NULL)) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: failed to load or initialize module %s\n",
+ fname, lineno, cargv[1]);
+ exit( EXIT_FAILURE );
+ }
+ } else if (strcasecmp( cargv[0], "modulepath") == 0 ) {
+ if ( cargc != 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing path in \"modulepath <path>\" line\n",
+ fname, lineno, 0 );
+ exit( EXIT_FAILURE );
+ }
+ if (module_path( cargv[1] )) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: failed to set module search path to %s\n",
+ fname, lineno, cargv[1]);
+ exit( EXIT_FAILURE );
+ }
+
+#endif /*SLAPD_MODULES*/
+
+#ifdef HAVE_TLS
+ } else if ( !strcasecmp( cargv[0], "TLSProtocol" ) ) {
+ rc = ldap_pvt_tls_set_option( NULL,
+ LDAP_OPT_X_TLS_PROTOCOL,
+ cargv[1] );
+ if ( rc )
+ return rc;
+
+ } else if ( !strcasecmp( cargv[0], "TLSCipherSuite" ) ) {
+ rc = ldap_pvt_tls_set_option( NULL,
+ LDAP_OPT_X_TLS_CIPHER_SUITE,
+ cargv[1] );
+ if ( rc )
+ return rc;
+
+ } else if ( !strcasecmp( cargv[0], "TLSCertificateFile" ) ) {
+ rc = ldap_pvt_tls_set_option( NULL,
+ LDAP_OPT_X_TLS_CERTFILE,
+ cargv[1] );
+ if ( rc )
+ return rc;
+
+ } else if ( !strcasecmp( cargv[0], "TLSCertificateKeyFile" ) ) {
+ rc = ldap_pvt_tls_set_option( NULL,
+ LDAP_OPT_X_TLS_KEYFILE,
+ cargv[1] );
+ if ( rc )
+ return rc;
+
+ } else if ( !strcasecmp( cargv[0], "TLSCACertificatePath" ) ) {
+ rc = ldap_pvt_tls_set_option( NULL,
+ LDAP_OPT_X_TLS_CACERTDIR,
+ cargv[1] );
+ if ( rc )
+ return rc;
+
+ } else if ( !strcasecmp( cargv[0], "TLSCACertificateFile" ) ) {
+ rc = ldap_pvt_tls_set_option( NULL,
+ LDAP_OPT_X_TLS_CACERTFILE,
+ cargv[1] );
+ if ( rc )
+ return rc;
+ } else if ( !strcasecmp( cargv[0], "TLSVerifyClient" ) ) {
+ rc = ldap_pvt_tls_set_option( NULL,
+ LDAP_OPT_X_TLS_REQUIRE_CERT,
+ cargv[1] );
+ if ( rc )
+ return rc;
+
+#endif
+
+ /* pass anything else to the current backend info/db config routine */
} else {
- if ( be == NULL ) {
- Debug( LDAP_DEBUG_ANY,
-"%s: line %d: unknown directive \"%s\" outside database definition (ignored)\n",
- fname, lineno, cargv[0] );
- } else if ( be->be_config == NULL ) {
+ if ( bi != NULL ) {
+ if ( bi->bi_config == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: unknown directive \"%s\" inside backend info definition (ignored)\n",
+ fname, lineno, cargv[0] );
+ } else {
+ if ( (*bi->bi_config)( bi, fname, lineno, cargc, cargv )
+ != 0 )
+ {
+ return( 1 );
+ }
+ }
+ } else if ( be != NULL ) {
+ if ( be->be_config == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: unknown directive \"%s\" inside backend database definition (ignored)\n",
+ fname, lineno, cargv[0] );
+ } else {
+ if ( (*be->be_config)( be, fname, lineno, cargc, cargv )
+ != 0 )
+ {
+ return( 1 );
+ }
+ }
+ } else {
Debug( LDAP_DEBUG_ANY,
-"%s: line %d: unknown directive \"%s\" inside database definition (ignored)\n",
+"%s: line %d: unknown directive \"%s\" outside backend info and database definitions (ignored)\n",
fname, lineno, cargv[0] );
- } else {
- (*be->be_config)( be, fname, lineno, cargc,
- cargv );
}
}
+ free( saveline );
}
fclose( fp );
+ return( 0 );
}
-static void
+static int
fp_parse_line(
char *line,
int *argcp,
if ( *argcp == MAXARGS ) {
Debug( LDAP_DEBUG_ANY, "Too many tokens (max %d)\n",
MAXARGS, 0, 0 );
- exit( 1 );
+ return( 1 );
}
argv[(*argcp)++] = token;
}
argv[*argcp] = NULL;
+ return 0;
}
static char *
} else {
inquote = 1;
}
- strcpy( next, next + 1 );
+ SAFEMEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
break;
case '\\':
- strcpy( next, next + 1 );
+ if ( next[1] )
+ SAFEMEMCPY( next,
+ next + 1, strlen( next + 1 ) + 1 );
+ next++; /* dont parse the escaped character */
break;
default:
if ( (p = strchr( buf, '\n' )) != NULL ) {
*p = '\0';
}
- if ( ! isspace( buf[0] ) ) {
+ if ( ! isspace( (unsigned char) buf[0] ) ) {
return( line );
}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "ldap_defaults.h"
#include "slap.h"
-#include "ldapconfig.h"
#if defined( SLAPD_CONFIG_DN )
-extern int nbackends;
-extern Backend *backends;
-extern char *default_referral;
-
/*
* no mutex protection in here - take our chances!
*/
void
-config_info( Connection *conn, Operation *op )
+config_info(
+ Connection *conn,
+ Operation *op,
+ char **attrs,
+ int attrsonly )
{
Entry *e;
char buf[BUFSIZ];
vals[1] = NULL;
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
e->e_attrs = NULL;
- e->e_dn = strdup( SLAPD_CONFIG_DN );
+ e->e_dn = ch_strdup( SLAPD_CONFIG_DN );
+ e->e_ndn = ch_strdup( SLAPD_CONFIG_DN );
+ (void) dn_normalize_case( e->e_ndn );
+ e->e_private = NULL;
+
+ {
+ char *rdn = ch_strdup( SLAPD_CONFIG_DN );
+ val.bv_val = strchr( rdn, '=' );
+
+ if( val.bv_val != NULL ) {
+ *val.bv_val = '\0';
+ val.bv_len = strlen( ++val.bv_val );
+
+ attr_merge( e, rdn, vals );
+ }
+
+ free( rdn );
+ }
for ( i = 0; i < nbackends; i++ ) {
strcpy( buf, backends[i].be_type );
attr_merge( e, "database", vals );
}
- if ( default_referral != NULL ) {
- strcpy( buf, default_referral );
- val.bv_val = buf;
- val.bv_len = strlen( buf );
- attr_merge( e, "database", vals );
- }
+ val.bv_val = "top";
+ val.bv_len = sizeof("top")-1;
+ attr_merge( e, "objectClass", vals );
+
+ val.bv_val = "LDAPsubentry";
+ val.bv_len = sizeof("LDAPsubentry")-1;
+ attr_merge( e, "objectClass", vals );
+
+ val.bv_val = "extensibleObject";
+ val.bv_len = sizeof("extensibleObject")-1;
+ attr_merge( e, "objectClass", vals );
- send_search_entry( &backends[0], conn, op, e, NULL, 0 );
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+ send_search_entry( &backends[0], conn, op, e,
+ attrs, attrsonly, NULL );
+ send_search_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 1 );
entry_free( e );
}
-#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <signal.h>
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/errno.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include "slap.h"
-extern Operation *op_add();
-extern int active_threads;
-extern pthread_mutex_t active_threads_mutex;
-extern pthread_mutex_t new_conn_mutex;
-extern long ops_initiated;
-extern long ops_completed;
-extern pthread_mutex_t ops_mutex;
-extern pthread_t listener_tid;
-#ifndef SYSERRLIST_IN_STDIO
-extern int sys_nerr;
-extern char *sys_errlist[];
-#endif
+/* we need LBER internals */
+#include "../../libraries/liblber/lber-int.h"
+
+/* protected by connections_mutex */
+static ldap_pvt_thread_mutex_t connections_mutex;
+static Connection *connections = NULL;
+static unsigned long conn_nextid = 0;
+
+/* structure state (protected by connections_mutex) */
+#define SLAP_C_UNINITIALIZED 0x00 /* MUST BE ZERO (0) */
+#define SLAP_C_UNUSED 0x01
+#define SLAP_C_USED 0x02
+
+/* connection state (protected by c_mutex ) */
+#define SLAP_C_INVALID 0x00 /* MUST BE ZERO (0) */
+#define SLAP_C_INACTIVE 0x01 /* zero threads */
+#define SLAP_C_ACTIVE 0x02 /* one or more threads */
+#define SLAP_C_BINDING 0x03 /* binding */
+#define SLAP_C_CLOSING 0x04 /* closing */
+
+char* connection_state2str( int state ) {
+ switch( state ) {
+ case SLAP_C_INVALID: return "!";
+ case SLAP_C_INACTIVE: return "|";
+ case SLAP_C_ACTIVE: return "";
+ case SLAP_C_BINDING: return "B";
+ case SLAP_C_CLOSING: return "C";
+ }
+
+ return "?";
+}
+
+static Connection* connection_get( ber_socket_t s );
+
+static int connection_input( Connection *c );
+static void connection_close( Connection *c );
+
+static int connection_op_activate( Connection *conn, Operation *op );
+static int connection_resched( Connection *conn );
+static void connection_abandon( Connection *conn );
+static void connection_destroy( Connection *c );
struct co_arg {
Connection *co_conn;
Operation *co_op;
};
+/*
+ * Initialize connection management infrastructure.
+ */
+int connections_init(void)
+{
+ assert( connections == NULL );
+
+ if( connections != NULL) {
+ Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n",
+ 0, 0, 0 );
+ return -1;
+ }
+
+ /* should check return of every call */
+ ldap_pvt_thread_mutex_init( &connections_mutex );
+
+ connections = (Connection *) calloc( dtblsize, sizeof(Connection) );
+
+ if( connections == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "connections_init: allocation (%d*%ld) of connection array failed\n",
+ dtblsize, (long) sizeof(Connection), 0 );
+ return -1;
+ }
+
+ assert( connections[0].c_struct_state == SLAP_C_UNINITIALIZED );
+ assert( connections[dtblsize-1].c_struct_state == SLAP_C_UNINITIALIZED );
+
+ /*
+ * per entry initialization of the Connection array initialization
+ * will be done by connection_init()
+ */
+
+ return 0;
+}
+
+/*
+ * Destroy connection management infrastructure.
+ */
+int connections_destroy(void)
+{
+ ber_socket_t i;
+
+ /* should check return of every call */
+
+ if( connections == NULL) {
+ Debug( LDAP_DEBUG_ANY, "connections_destroy: nothing to destroy.\n",
+ 0, 0, 0 );
+ return -1;
+ }
+
+ for ( i = 0; i < dtblsize; i++ ) {
+ if( connections[i].c_struct_state != SLAP_C_UNINITIALIZED ) {
+ ber_sockbuf_free( connections[i].c_sb );
+ ldap_pvt_thread_mutex_destroy( &connections[i].c_mutex );
+ ldap_pvt_thread_mutex_destroy( &connections[i].c_write_mutex );
+ ldap_pvt_thread_cond_destroy( &connections[i].c_write_cv );
+ }
+ }
+
+ free( connections );
+ connections = NULL;
+
+ ldap_pvt_thread_mutex_destroy( &connections_mutex );
+ return 0;
+}
+
+/*
+ * shutdown all connections
+ */
+int connections_shutdown(void)
+{
+ ber_socket_t i;
+
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+ for ( i = 0; i < dtblsize; i++ ) {
+ if( connections[i].c_struct_state != SLAP_C_USED ) {
+ continue;
+ }
+
+ ldap_pvt_thread_mutex_lock( &connections[i].c_mutex );
+
+ /* connections_mutex and c_mutex are locked */
+ connection_closing( &connections[i] );
+ connection_close( &connections[i] );
+
+ ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex );
+ }
+
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+
+ return 0;
+}
+
+/*
+ * Timeout idle connections.
+ */
+int connections_timeout_idle(time_t now)
+{
+ int i = 0;
+ int connindex;
+ Connection* c;
+
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+ for( c = connection_first( &connindex );
+ c != NULL;
+ c = connection_next( c, &connindex ) )
+ {
+ if( difftime( c->c_activitytime+global_idletimeout, now) < 0 ) {
+ /* close it */
+ connection_closing( c );
+ connection_close( c );
+ i++;
+ }
+ }
+ connection_done( c );
+
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+
+ return i;
+}
+
+static Connection* connection_get( ber_socket_t s )
+{
+ /* connections_mutex should be locked by caller */
+
+ Connection *c;
+
+ Debug( LDAP_DEBUG_ARGS,
+ "connection_get(%ld)\n",
+ (long) s, 0, 0 );
+
+ assert( connections != NULL );
+
+ if(s == AC_SOCKET_INVALID) {
+ return NULL;
+ }
+
+#ifndef HAVE_WINSOCK
+ c = &connections[s];
+
+ assert( c->c_struct_state != SLAP_C_UNINITIALIZED );
+
+#else
+ c = NULL;
+ {
+ ber_socket_t i;
+
+ for(i=0; i<dtblsize; i++) {
+ if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
+ assert( connections[i].c_conn_state == SLAP_C_INVALID );
+ assert( connections[i].c_sb == 0 );
+ break;
+ }
+
+ if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
+ assert( connections[i].c_conn_state == SLAP_C_INVALID );
+ assert( !ber_pvt_sb_in_use( connections[i].c_sb ) );
+ continue;
+ }
+
+ /* state can actually change from used -> unused by resched,
+ * so don't assert details here.
+ */
+
+ if( ber_pvt_sb_get_desc( connections[i].c_sb ) == s ) {
+ c = &connections[i];
+ break;
+ }
+ }
+ }
+#endif
+
+ if( c != NULL ) {
+ ldap_pvt_thread_mutex_lock( &c->c_mutex );
+
+ if( c->c_struct_state != SLAP_C_USED ) {
+ /* connection must have been closed due to resched */
+
+ assert( c->c_conn_state == SLAP_C_INVALID );
+ assert( !ber_pvt_sb_in_use( c->c_sb ) );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_get(%d): connection not used\n",
+ s, 0, 0 );
+
+ ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+ return NULL;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_get(%d): got connid=%ld\n",
+ s, c->c_connid, 0 );
+
+ c->c_n_get++;
+
+ assert( c->c_struct_state == SLAP_C_USED );
+ assert( c->c_conn_state != SLAP_C_INVALID );
+ assert( ber_pvt_sb_in_use( c->c_sb ) );
+
+ c->c_activitytime = slap_get_time();
+ }
+
+ return c;
+}
+
+static void connection_return( Connection *c )
+{
+ ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+}
+
+long connection_init(
+ ber_socket_t s,
+ const char* url,
+ const char* dnsname,
+ const char* peername,
+ const char* sockname,
+ int use_tls )
+{
+ unsigned long id;
+ Connection *c;
+
+ assert( connections != NULL );
+
+ assert( dnsname != NULL );
+ assert( peername != NULL );
+ assert( sockname != NULL );
+
+#ifndef HAVE_TLS
+ assert( !use_tls );
+#endif
+
+ if( s == AC_SOCKET_INVALID ) {
+ Debug( LDAP_DEBUG_ANY,
+ "connection_init(%ld): invalid.\n",
+ (long) s, 0, 0 );
+ return -1;
+ }
+
+ assert( s >= 0 );
+#ifndef HAVE_WINSOCK
+ assert( s < dtblsize );
+#endif
+
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+#ifndef HAVE_WINSOCK
+ c = &connections[s];
+
+#else
+ {
+ unsigned int i;
+
+ c = NULL;
+
+ for( i=0; i < dtblsize; i++) {
+ if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
+ assert( connections[i].c_sb == 0 );
+ c = &connections[i];
+ break;
+ }
+
+ if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
+ assert( !ber_pvt_sb_in_use( connections[i].c_sb ));
+ c = &connections[i];
+ break;
+ }
+
+ assert( connections[i].c_struct_state == SLAP_C_USED );
+ assert( connections[i].c_conn_state != SLAP_C_INVALID );
+ assert( ber_pvt_sb_in_use( connections[i].c_sb ));
+ }
+
+ if( c == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "connection_init(%d): connection table full (%d/%d)\n",
+ s, i, dtblsize);
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+ return -1;
+ }
+ }
+#endif
+
+ assert( c != NULL );
+ assert( c->c_struct_state != SLAP_C_USED );
+ assert( c->c_conn_state == SLAP_C_INVALID );
+
+ if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
+ c->c_dn = NULL;
+ c->c_cdn = NULL;
+
+ c->c_listener_url = NULL;
+ c->c_peer_domain = NULL;
+ c->c_peer_name = NULL;
+ c->c_sock_name = NULL;
+
+ c->c_ops = NULL;
+ c->c_pending_ops = NULL;
+ c->c_authmech = NULL;
+ c->c_authstate = NULL;
+
+#ifdef HAVE_CYRUS_SASL
+ c->c_sasl_context = NULL;
+#endif
+
+ c->c_sb = ber_sockbuf_alloc( );
+
+ /* should check status of thread calls */
+ ldap_pvt_thread_mutex_init( &c->c_mutex );
+ ldap_pvt_thread_mutex_init( &c->c_write_mutex );
+ ldap_pvt_thread_cond_init( &c->c_write_cv );
+
+ c->c_struct_state = SLAP_C_UNUSED;
+ }
+
+ ldap_pvt_thread_mutex_lock( &c->c_mutex );
+
+ assert( c->c_struct_state == SLAP_C_UNUSED );
+ assert( c->c_dn == NULL );
+ assert( c->c_cdn == NULL );
+ assert( c->c_listener_url == NULL );
+ assert( c->c_peer_domain == NULL );
+ assert( c->c_peer_name == NULL );
+ assert( c->c_sock_name == NULL );
+ assert( c->c_ops == NULL );
+ assert( c->c_pending_ops == NULL );
+ assert( c->c_authmech == NULL );
+ assert( c->c_authstate == NULL );
+#ifdef HAVE_CYRUS_SASL
+ assert( c->c_sasl_context == NULL );
+#endif
+
+ c->c_listener_url = ch_strdup( url );
+ c->c_peer_domain = ch_strdup( dnsname );
+ c->c_peer_name = ch_strdup( peername );
+ c->c_sock_name = ch_strdup( sockname );
+
+ c->c_n_ops_received = 0;
+ c->c_n_ops_executing = 0;
+ c->c_n_ops_pending = 0;
+ c->c_n_ops_completed = 0;
+
+ c->c_n_get = 0;
+ c->c_n_read = 0;
+ c->c_n_write = 0;
+
+ /* assume LDAPv3 until bind */
+ c->c_protocol = LDAP_VERSION3;
+
+ c->c_activitytime = c->c_starttime = slap_get_time();
+
+ ber_pvt_sb_set_desc( c->c_sb, s );
+ ber_pvt_sb_set_io( c->c_sb, &ber_pvt_sb_io_tcp, NULL );
+
+ if( ber_pvt_sb_set_nonblock( c->c_sb, 1 ) < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "connection_init(%d, %s): set nonblocking failed\n",
+ s, c->c_peer_name,0 );
+ }
+
+ id = c->c_connid = conn_nextid++;
+
+ c->c_conn_state = SLAP_C_INACTIVE;
+ c->c_struct_state = SLAP_C_USED;
+
+#ifdef HAVE_TLS
+ if ( use_tls ) {
+ c->c_is_tls = 1;
+ c->c_needs_tls_accept = 1;
+ }
+#endif
+
+ ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+
+ backend_connection_init(c);
+
+ return id;
+}
+
+static void
+connection_destroy( Connection *c )
+{
+ /* note: connections_mutex should be locked by caller */
+
+ assert( connections != NULL );
+ assert( c != NULL );
+ assert( c->c_struct_state != SLAP_C_UNUSED );
+ assert( c->c_conn_state != SLAP_C_INVALID );
+ assert( c->c_ops == NULL );
+
+ backend_connection_destroy(c);
+
+ c->c_protocol = 0;
+ c->c_connid = -1;
+
+ c->c_activitytime = c->c_starttime = 0;
+
+ if(c->c_dn != NULL) {
+ free(c->c_dn);
+ c->c_dn = NULL;
+ }
+ if(c->c_cdn != NULL) {
+ free(c->c_cdn);
+ c->c_cdn = NULL;
+ }
+ if(c->c_listener_url != NULL) {
+ free(c->c_listener_url);
+ c->c_listener_url = NULL;
+ }
+ if(c->c_peer_domain != NULL) {
+ free(c->c_peer_domain);
+ c->c_peer_domain = NULL;
+ }
+ if(c->c_peer_name != NULL) {
+ free(c->c_peer_name);
+ c->c_peer_name = NULL;
+ }
+ if(c->c_sock_name != NULL) {
+ free(c->c_sock_name);
+ c->c_sock_name = NULL;
+ }
+ if(c->c_authmech != NULL ) {
+ free(c->c_authmech);
+ c->c_authmech = NULL;
+ }
+ if(c->c_authstate != NULL ) {
+ free(c->c_authstate);
+ c->c_authstate = NULL;
+ }
+
+#ifdef HAVE_CYRUS_SASL
+ if(c->c_sasl_context != NULL ) {
+ sasl_dispose( &c->c_sasl_context );
+ c->c_sasl_context = NULL;
+ }
+#endif
+
+ if ( ber_pvt_sb_in_use(c->c_sb) ) {
+ int sd = ber_pvt_sb_get_desc(c->c_sb);
+
+ slapd_remove( sd, 0 );
+ ber_pvt_sb_close( c->c_sb );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld fd=%d closed\n",
+ c->c_connid, sd, 0, 0, 0 );
+ }
+
+ ber_pvt_sb_destroy( c->c_sb );
+
+ c->c_conn_state = SLAP_C_INVALID;
+ c->c_struct_state = SLAP_C_UNUSED;
+}
+
+int connection_state_closing( Connection *c )
+{
+ /* c_mutex must be locked by caller */
+
+ int state;
+ assert( c != NULL );
+ assert( c->c_struct_state == SLAP_C_USED );
+
+ state = c->c_conn_state;
+
+ assert( state != SLAP_C_INVALID );
+
+ return state == SLAP_C_CLOSING;
+}
+
+static void connection_abandon( Connection *c )
+{
+ /* c_mutex must be locked by caller */
+
+ Operation *o;
+
+ for( o = c->c_ops; o != NULL; o = o->o_next ) {
+ ldap_pvt_thread_mutex_lock( &o->o_abandonmutex );
+ o->o_abandon = 1;
+ ldap_pvt_thread_mutex_unlock( &o->o_abandonmutex );
+ }
+
+ /* remove pending operations */
+ for( o = slap_op_pop( &c->c_pending_ops );
+ o != NULL;
+ o = slap_op_pop( &c->c_pending_ops ) )
+ {
+ slap_op_free( o );
+ }
+}
+
+void connection_closing( Connection *c )
+{
+ assert( connections != NULL );
+ assert( c != NULL );
+ assert( c->c_struct_state == SLAP_C_USED );
+ assert( c->c_conn_state != SLAP_C_INVALID );
+
+ /* c_mutex must be locked by caller */
+
+ if( c->c_conn_state != SLAP_C_CLOSING ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_closing: readying conn=%ld sd=%d for close\n",
+ c->c_connid, ber_pvt_sb_get_desc( c->c_sb ), 0 );
+
+ /* update state to closing */
+ c->c_conn_state = SLAP_C_CLOSING;
+
+ /* don't listen on this port anymore */
+ slapd_clr_read( ber_pvt_sb_get_desc( c->c_sb ), 1 );
+
+ /* shutdown I/O -- not yet implemented */
+
+ /* abandon active operations */
+ connection_abandon( c );
+
+ /* wake write blocked operations */
+ slapd_clr_write( ber_pvt_sb_get_desc(c->c_sb), 1 );
+ ldap_pvt_thread_cond_signal( &c->c_write_cv );
+ }
+}
+
+static void connection_close( Connection *c )
+{
+ assert( connections != NULL );
+ assert( c != NULL );
+ assert( c->c_struct_state == SLAP_C_USED );
+ assert( c->c_conn_state == SLAP_C_CLOSING );
+
+ /* note: connections_mutex and c_mutex should be locked by caller */
+
+ if( c->c_ops != NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_close: deferring conn=%ld sd=%d\n",
+ c->c_connid, ber_pvt_sb_get_desc( c->c_sb ), 0 );
+
+ return;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%ld sd=%d\n",
+ c->c_connid, ber_pvt_sb_get_desc( c->c_sb ), 0 );
+
+ connection_destroy( c );
+}
+
+unsigned long connections_nextid(void)
+{
+ unsigned long id;
+ assert( connections != NULL );
+
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+ id = conn_nextid;
+
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+
+ return id;
+}
+
+Connection* connection_first( ber_socket_t *index )
+{
+ assert( connections != NULL );
+ assert( index != NULL );
+
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+ *index = 0;
+
+ return connection_next(NULL, index);
+}
+
+Connection* connection_next( Connection *c, ber_socket_t *index )
+{
+ 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)++) {
+ if( connections[*index].c_struct_state == SLAP_C_UNINITIALIZED ) {
+ assert( connections[*index].c_conn_state == SLAP_C_INVALID );
+#ifndef HAVE_WINSOCK
+ continue;
+#else
+ break;
+#endif
+ }
+
+ if( connections[*index].c_struct_state == SLAP_C_USED ) {
+ assert( connections[*index].c_conn_state != SLAP_C_INVALID );
+ c = &connections[(*index)++];
+ break;
+ }
+
+ assert( connections[*index].c_struct_state == SLAP_C_UNUSED );
+ assert( connections[*index].c_conn_state == SLAP_C_INVALID );
+ }
+
+ if( c != NULL ) {
+ ldap_pvt_thread_mutex_lock( &c->c_mutex );
+ }
+
+ return c;
+}
+
+void connection_done( Connection *c )
+{
+ assert( connections != NULL );
+
+ if( c != NULL ) {
+ ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+ }
+
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+}
+
/*
* connection_activity - handle the request operation op on connection
* conn. This routine figures out what kind of operation it is and
* calls the appropriate stub to handle it.
*/
-static void
-connection_operation( struct co_arg *arg )
+static void *
+connection_operation( void *arg_v )
{
- unsigned long len;
-
- pthread_mutex_lock( &arg->co_conn->c_opsmutex );
- arg->co_conn->c_opsinitiated++;
- pthread_mutex_unlock( &arg->co_conn->c_opsmutex );
+ int rc;
+ struct co_arg *arg = arg_v;
+ ber_tag_t tag = arg->co_op->o_tag;
+ Connection *conn = arg->co_conn;
- pthread_mutex_lock( &ops_mutex );
- ops_initiated++;
- pthread_mutex_unlock( &ops_mutex );
+ ldap_pvt_thread_mutex_lock( &num_ops_mutex );
+ num_ops_initiated++;
+ ldap_pvt_thread_mutex_unlock( &num_ops_mutex );
- switch ( arg->co_op->o_tag ) {
+ switch ( tag ) {
case LDAP_REQ_BIND:
- do_bind( arg->co_conn, arg->co_op );
+ rc = do_bind( conn, arg->co_op );
break;
-#ifdef COMPAT30
- case LDAP_REQ_UNBIND_30:
-#endif
case LDAP_REQ_UNBIND:
- do_unbind( arg->co_conn, arg->co_op );
+ rc = do_unbind( conn, arg->co_op );
break;
case LDAP_REQ_ADD:
- do_add( arg->co_conn, arg->co_op );
+ rc = do_add( conn, arg->co_op );
break;
-#ifdef COMPAT30
- case LDAP_REQ_DELETE_30:
-#endif
case LDAP_REQ_DELETE:
- do_delete( arg->co_conn, arg->co_op );
+ rc = do_delete( conn, arg->co_op );
break;
case LDAP_REQ_MODRDN:
- do_modrdn( arg->co_conn, arg->co_op );
+ rc = do_modrdn( conn, arg->co_op );
break;
case LDAP_REQ_MODIFY:
- do_modify( arg->co_conn, arg->co_op );
+ rc = do_modify( conn, arg->co_op );
break;
case LDAP_REQ_COMPARE:
- do_compare( arg->co_conn, arg->co_op );
+ rc = do_compare( conn, arg->co_op );
break;
case LDAP_REQ_SEARCH:
- do_search( arg->co_conn, arg->co_op );
+ rc = do_search( conn, arg->co_op );
break;
-#ifdef COMPAT30
- case LDAP_REQ_ABANDON_30:
-#endif
case LDAP_REQ_ABANDON:
- do_abandon( arg->co_conn, arg->co_op );
+ rc = do_abandon( conn, arg->co_op );
+ break;
+
+ case LDAP_REQ_EXTENDED:
+ rc = do_extended( conn, arg->co_op );
break;
default:
- Debug( LDAP_DEBUG_ANY, "unknown request 0x%x\n",
- arg->co_op->o_tag, 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "unknown LDAP request 0x%lx\n",
+ tag, 0, 0 );
+ arg->co_op->o_tag = LBER_ERROR;
+ send_ldap_disconnect( conn, arg->co_op,
+ LDAP_PROTOCOL_ERROR, "unknown LDAP request" );
+ rc = -1;
break;
}
- pthread_mutex_lock( &arg->co_conn->c_opsmutex );
- arg->co_conn->c_opscompleted++;
- op_delete( &arg->co_conn->c_ops, arg->co_op );
- pthread_mutex_unlock( &arg->co_conn->c_opsmutex );
+ if( rc == -1 ) tag = LBER_ERROR;
+
+ ldap_pvt_thread_mutex_lock( &num_ops_mutex );
+ num_ops_completed++;
+ ldap_pvt_thread_mutex_unlock( &num_ops_mutex );
+
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+ conn->c_n_ops_executing--;
+ conn->c_n_ops_completed++;
+ slap_op_remove( &conn->c_ops, arg->co_op );
+ slap_op_free( arg->co_op );
+ arg->co_op = NULL;
+ arg->co_conn = NULL;
free( (char *) arg );
+ arg = NULL;
- pthread_mutex_lock( &ops_mutex );
- ops_completed++;
- pthread_mutex_unlock( &ops_mutex );
+ switch( tag ) {
+ case LBER_ERROR:
+ case LDAP_REQ_UNBIND:
+ /* c_mutex is locked */
+ connection_closing( conn );
+ break;
+
+ case LDAP_REQ_BIND:
+ if( conn->c_conn_state == SLAP_C_BINDING) {
+ conn->c_conn_state = SLAP_C_ACTIVE;
+ }
+ conn->c_bind_in_progress = ( rc == LDAP_SASL_BIND_IN_PROGRESS );
+ }
- pthread_mutex_lock( &active_threads_mutex );
+ ldap_pvt_thread_mutex_lock( &active_threads_mutex );
active_threads--;
- pthread_mutex_unlock( &active_threads_mutex );
+ if( active_threads < 1 ) {
+ ldap_pvt_thread_cond_signal(&active_threads_cond);
+ }
+ ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
+
+ connection_resched( conn );
+
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+ return NULL;
+}
+
+int connection_read(ber_socket_t s)
+{
+ int rc = 0;
+ Connection *c;
+ assert( connections != NULL );
+
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+ /* get (locked) connection */
+ c = connection_get( s );
+
+ if( c == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "connection_read(%ld): no connection!\n",
+ (long) s, 0, 0 );
+
+ slapd_remove(s, 0);
+
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+ return -1;
+ }
+
+ c->c_n_read++;
+
+ if( c->c_conn_state == SLAP_C_CLOSING ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_read(%d): closing, ignoring input for id=%ld\n",
+ s, c->c_connid, 0 );
+
+ connection_return( c );
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+ return 0;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_read(%d): checking for input on id=%ld\n",
+ s, c->c_connid, 0 );
+
+#ifdef HAVE_TLS
+ if ( c->c_is_tls && c->c_needs_tls_accept ) {
+ rc = ldap_pvt_tls_accept( c->c_sb, NULL );
+ if ( rc < 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_read(%d): TLS accept error error=%d id=%ld, closing\n",
+ s, rc, c->c_connid );
+
+ c->c_needs_tls_accept = 0;
+ /* connections_mutex and c_mutex are locked */
+ connection_closing( c );
+ connection_close( c );
+ } else if ( rc == 0 ) {
+ c->c_needs_tls_accept = 0;
+ }
+ connection_return( c );
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+ return 0;
+ }
+#endif
+
+#define CONNECTION_INPUT_LOOP 1
+
+#ifdef DATA_READY_LOOP
+ while(!rc && ber_pvt_sb_data_ready(&c->c_sb))
+#elif CONNECTION_INPUT_LOOP
+ while(!rc)
+#endif
+ {
+ /* How do we do this without getting into a busy loop ? */
+ rc = connection_input( c );
+ }
+
+ if( rc < 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_read(%d): input error=%d id=%ld, closing.\n",
+ s, rc, c->c_connid );
+
+ /* connections_mutex and c_mutex are locked */
+ connection_closing( c );
+ connection_close( c );
+ }
+
+ if ( ber_pvt_sb_needs_read( c->c_sb ) )
+ slapd_set_read( s, 1 );
+ if ( ber_pvt_sb_needs_write( c->c_sb ) )
+ slapd_set_write( s, 1 );
+ connection_return( c );
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+ return 0;
}
-void
-connection_activity(
+static int
+connection_input(
Connection *conn
)
{
- pthread_attr_t attr;
- struct co_arg *arg;
- unsigned long tag, len;
- long msgid;
+ Operation *op;
+ ber_tag_t tag;
+ ber_len_t len;
+ ber_int_t msgid;
BerElement *ber;
- char *tmpdn;
if ( conn->c_currentber == NULL && (conn->c_currentber = ber_alloc())
== NULL ) {
Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
- return;
+ return -1;
}
errno = 0;
- if ( (tag = ber_get_next( &conn->c_sb, &len, conn->c_currentber ))
- != LDAP_TAG_MESSAGE ) {
+ if ( (tag = ber_get_next( conn->c_sb, &len, conn->c_currentber ))
+ != LDAP_TAG_MESSAGE )
+ {
+ int err = errno;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ber_get_next on fd %d failed errno=%d (%s)\n",
+ ber_pvt_sb_get_desc( conn->c_sb ), err,
+ err > -1 && err < sys_nerr ? sys_errlist[err] : "unknown" );
Debug( LDAP_DEBUG_TRACE,
- "ber_get_next on fd %d failed errno %d (%s)\n",
- conn->c_sb.sb_sd, errno, errno > -1 && errno < sys_nerr ?
- sys_errlist[errno] : "unknown" );
- Debug( LDAP_DEBUG_TRACE, "*** got %d of %d so far\n",
- conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf,
- conn->c_currentber->ber_len, 0 );
-
- if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
+ "\t*** got %ld of %lu so far\n",
+ (long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf),
+ conn->c_currentber->ber_len, 0 );
+
+ if ( err != EWOULDBLOCK && err != EAGAIN ) {
/* log, close and send error */
ber_free( conn->c_currentber, 1 );
conn->c_currentber = NULL;
- close_connection( conn, conn->c_connid, -1 );
+ return -2;
}
-
- return;
+ return 1;
}
+
ber = conn->c_currentber;
conn->c_currentber = NULL;
if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
/* log, close and send error */
- Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%x\n", tag, 0,
+ Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0,
0 );
ber_free( ber, 1 );
-
- close_connection( conn, conn->c_connid, -1 );
- return;
+ 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%x\n", tag, 0,
+ Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0,
0 );
ber_free( ber, 1 );
- close_connection( conn, conn->c_connid, -1 );
- return;
+ return -1;
+ }
+
+ if(tag == LDAP_REQ_BIND) {
+ /* immediately abandon all exiting operations upon BIND */
+ connection_abandon( conn );
+ }
+
+ op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++ );
+
+ if ( conn->c_conn_state == SLAP_C_BINDING
+ || conn->c_conn_state == SLAP_C_CLOSING )
+ {
+ Debug( LDAP_DEBUG_ANY, "deferring operation\n", 0, 0, 0 );
+ conn->c_n_ops_pending++;
+ slap_op_add( &conn->c_pending_ops, op );
+
+ } else {
+ conn->c_n_ops_executing++;
+ connection_op_activate( conn, op );
}
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- (void) ber_skip_tag( ber, &len );
+#ifdef NO_THREADS
+ if ( conn->c_struct_state != SLAP_C_USED ) {
+ /* connection must have got closed underneath us */
+ return 1;
}
#endif
+ assert( conn->c_struct_state == SLAP_C_USED );
- arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
- arg->co_conn = conn;
+ return 0;
+}
+
+static int
+connection_resched( Connection *conn )
+{
+ Operation *op;
+
+ if( conn->c_conn_state == SLAP_C_CLOSING ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_resched: attempting closing conn=%ld sd=%d\n",
+ conn->c_connid, ber_pvt_sb_get_desc( conn->c_sb ), 0 );
+
+ connection_close( conn );
+ return 0;
+ }
+
+ if( conn->c_conn_state != SLAP_C_ACTIVE ) {
+ /* other states need different handling */
+ return 0;
+ }
+
+ for( op = slap_op_pop( &conn->c_pending_ops );
+ op != NULL;
+ op = slap_op_pop( &conn->c_pending_ops ) )
+ {
+ /* pending operations should not be marked for abandonment */
+ assert(!op->o_abandon);
+
+ conn->c_n_ops_pending--;
+ conn->c_n_ops_executing++;
+
+ connection_op_activate( conn, op );
+
+ if ( conn->c_conn_state == SLAP_C_BINDING ) {
+ break;
+ }
+ }
+ return 0;
+}
+
+static int connection_op_activate( Connection *conn, Operation *op )
+{
+ struct co_arg *arg;
+ char *tmpdn;
+ int status;
+ ber_tag_t tag = op->o_tag;
+
+ if(tag == LDAP_REQ_BIND) {
+ conn->c_conn_state = SLAP_C_BINDING;
+ }
- pthread_mutex_lock( &conn->c_dnmutex );
if ( conn->c_dn != NULL ) {
- tmpdn = strdup( conn->c_dn );
+ tmpdn = ch_strdup( conn->c_dn );
} else {
tmpdn = NULL;
}
- pthread_mutex_unlock( &conn->c_dnmutex );
- pthread_mutex_lock( &conn->c_opsmutex );
- arg->co_op = op_add( &conn->c_ops, ber, msgid, tag, tmpdn,
- conn->c_opsinitiated, conn->c_connid );
- pthread_mutex_unlock( &conn->c_opsmutex );
+ arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
+ arg->co_conn = conn;
+ arg->co_op = op;
+
+ arg->co_op->o_bind_in_progress = conn->c_bind_in_progress;
+
+ arg->co_op->o_dn = ch_strdup( tmpdn != NULL ? tmpdn : "" );
+ arg->co_op->o_ndn = ch_strdup( arg->co_op->o_dn );
+ (void) dn_normalize_case( arg->co_op->o_ndn );
- if ( tmpdn != NULL ) {
+ arg->co_op->o_protocol = conn->c_protocol;
+ arg->co_op->o_connid = conn->c_connid;
+
+ arg->co_op->o_authtype = conn->c_authtype;
+ arg->co_op->o_authmech = conn->c_authmech != NULL
+ ? ch_strdup( conn->c_authmech ) : NULL;
+
+ slap_op_add( &conn->c_ops, arg->co_op );
+
+ if( tmpdn != NULL ) {
free( tmpdn );
}
- pthread_attr_init( &attr );
- pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
- if ( pthread_create( &arg->co_op->o_tid, attr,
- (void *) connection_operation, (void *) arg ) != 0 ) {
- Debug( LDAP_DEBUG_ANY, "pthread_create failed\n", 0, 0, 0 );
- } else {
- pthread_mutex_lock( &active_threads_mutex );
- active_threads++;
- pthread_mutex_unlock( &active_threads_mutex );
+ ldap_pvt_thread_mutex_lock( &active_threads_mutex );
+ active_threads++;
+ ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
+
+ status = ldap_pvt_thread_create( &arg->co_op->o_tid, 1,
+ connection_operation, (void *) arg );
+
+ if ( status != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
+
+ /* should move op to pending list */
+ }
+
+ return status;
+}
+
+int connection_write(ber_socket_t s)
+{
+ Connection *c;
+ assert( connections != NULL );
+
+ ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+ c = connection_get( s );
+
+ slapd_clr_write( s, 0);
+
+ if( c == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "connection_write(%ld): no connection!\n",
+ (long) s, 0, 0 );
+ slapd_remove(s, 0);
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+ return -1;
}
- pthread_attr_destroy( &attr );
+
+ c->c_n_write++;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "connection_write(%d): waking output for id=%ld\n",
+ s, c->c_connid, 0 );
+
+ ldap_pvt_thread_cond_signal( &c->c_write_cv );
+
+ if ( ber_pvt_sb_needs_read( c->c_sb ) )
+ slapd_set_read( s, 1 );
+ if ( ber_pvt_sb_needs_write( c->c_sb ) )
+ slapd_set_write( s, 1 );
+ connection_return( c );
+ ldap_pvt_thread_mutex_unlock( &connections_mutex );
+ return 0;
}
--- /dev/null
+/*
+ * Copyright 1999 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+
+#include "../../libraries/liblber/lber-int.h"
+
+char *supportedControls[] = {
+ LDAP_CONTROL_MANAGEDSAIT,
+ NULL
+};
+
+int get_ctrls(
+ Connection *conn,
+ Operation *op,
+ int sendres )
+{
+ int nctrls = 0;
+ ber_tag_t tag;
+ ber_len_t len;
+ char *opaque;
+ BerElement *ber = op->o_ber;
+ LDAPControl ***ctrls = &op->o_ctrls;
+ int rc = LDAP_SUCCESS;
+ char *errmsg = NULL;
+
+ len = ber_pvt_ber_remaining(ber);
+
+ if( len == 0) {
+ /* no controls */
+ rc = LDAP_SUCCESS;
+ return rc;
+ }
+
+ if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
+ if( tag == LBER_ERROR ) {
+ rc = -1;
+ errmsg = "unexpected data in PDU";
+ }
+
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "=> get_ctrls\n", 0, 0, 0 );
+
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ rc = -1;
+ errmsg = "controls require LDAPv3";
+ goto return_results;
+ }
+
+ /* set through each element */
+ *ctrls = ch_malloc( 1 * sizeof(LDAPControl *) );
+
+#if 0
+ if( *ctrls == NULL ) {
+ rc = LDAP_NO_MEMORY;
+ errmsg = "no memory";
+ goto return_results;
+ }
+#endif
+
+ ctrls[nctrls] = NULL;
+
+ for( tag = ber_first_element( ber, &len, &opaque );
+ tag != LBER_ERROR;
+ tag = ber_next_element( ber, &len, opaque ) )
+ {
+ LDAPControl *tctrl;
+ LDAPControl **tctrls;
+
+ tctrl = ch_calloc( 1, sizeof(LDAPControl) );
+ tctrl->ldctl_oid = NULL;
+ tctrl->ldctl_value.bv_val = NULL;
+
+ /* allocate pointer space for current controls (nctrls)
+ * + this control + extra NULL
+ */
+ tctrls = (tctrl == NULL) ? NULL :
+ ch_realloc(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
+
+#if 0
+ if( tctrls == NULL ) {
+ /* one of the above allocation failed */
+
+ if( tctrl != NULL ) {
+ ch_free( tctrl );
+ }
+
+ ldap_controls_free(*ctrls);
+ *ctrls = NULL;
+
+ rc = LDAP_NO_MEMORY;
+ errmsg = "no memory";
+ goto return_results;
+ }
+#endif
+
+ tctrls[nctrls++] = tctrl;
+ tctrls[nctrls] = NULL;
+
+ tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
+
+ if( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n",
+ 0, 0, 0 );
+ *ctrls = NULL;
+ ldap_controls_free( tctrls );
+ rc = -1;
+ errmsg = "decoding controls error";
+ goto return_results;
+ }
+
+ tag = ber_peek_tag( ber, &len );
+
+ if( tag == LBER_BOOLEAN ) {
+ ber_int_t crit;
+ tag = ber_scanf( ber, "b", &crit );
+
+ if( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n",
+ 0, 0, 0 );
+ *ctrls = NULL;
+ ldap_controls_free( tctrls );
+ rc = -1;
+ errmsg = "decoding controls error";
+ goto return_results;
+ }
+
+ tctrl->ldctl_iscritical = (crit != 0);
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: oid=\"%s\" (%scritical)\n",
+ tctrl->ldctl_oid,
+ tctrl->ldctl_iscritical ? "" : "non",
+ 0 );
+
+ if( tag == LBER_OCTETSTRING ) {
+ tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
+
+ if( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get value failed.\n",
+ 0, 0, 0 );
+ *ctrls = NULL;
+ ldap_controls_free( tctrls );
+ rc = -1;
+ errmsg = "decoding controls error";
+ goto return_results;
+ }
+ }
+
+ if( tctrl->ldctl_iscritical &&
+ !charray_inlist( supportedControls, tctrl->ldctl_oid ) )
+ {
+ rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
+ errmsg = "critical extension is unavailable ";
+ goto return_results;
+ }
+
+ *ctrls = tctrls;
+ }
+
+return_results:
+ Debug( LDAP_DEBUG_TRACE, "<= get_ctrls: %d %d %s\n",
+ nctrls, rc, errmsg ? errmsg : "");
+
+ if( sendres && rc != LDAP_SUCCESS ) {
+ if( rc == -1 ) {
+ send_ldap_disconnect( conn, op, rc, errmsg );
+ } else {
+ send_ldap_result( conn, op, rc,
+ NULL, errmsg, NULL, NULL );
+ }
+ }
+
+ return rc;
+}
+
+
+int get_manageDSAit( Operation *op )
+{
+ int i;
+ if( op == NULL || op->o_ctrls == NULL ) {
+ return 0;
+ }
+
+ for( i=0; op->o_ctrls[i] != NULL; i++ ) {
+ if( strcmp( LDAP_CONTROL_MANAGEDSAIT, op->o_ctrls[i]->ldctl_oid )
+ == 0 )
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <signal.h>
-#ifdef _AIX
-#include <sys/select.h>
-#endif
+
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#include "ldap_defaults.h"
#include "slap.h"
-#include "portable.h"
-#include "ldapconfig.h"
-#ifdef NEED_FILIO
-#include <sys/filio.h>
-#else /* NEED_FILIO */
-#include <sys/ioctl.h>
-#endif /* NEED_FILIO */
-#ifdef USE_SYSCONF
-#include <unistd.h>
-#endif /* USE_SYSCONF */
-
-extern Operation *op_add();
-
-#ifndef SYSERRLIST_IN_STDIO
-extern int sys_nerr;
-extern char *sys_errlist[];
-#endif
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
-extern int active_threads;
-extern pthread_mutex_t active_threads_mutex;
-extern pthread_mutex_t new_conn_mutex;
-extern int slapd_shutdown;
-extern pthread_t listener_tid;
-extern int num_conns;
-extern pthread_mutex_t ops_mutex;
-extern int g_argc;
-extern char **g_argv;
-
-int dtblsize;
-Connection *c;
-
-static void set_shutdown();
-static void do_nothing();
-void
-daemon(
- int port
+#ifdef HAVE_TCPD
+#include <tcpd.h>
+
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_NOTICE;
+#endif /* TCP Wrappers */
+
+/* globals */
+time_t starttime;
+ber_socket_t dtblsize;
+
+typedef struct slap_listener {
+ char* sl_url;
+ char* sl_name;
+#ifdef HAVE_TLS
+ int sl_is_tls;
+#endif
+ ber_socket_t sl_sd;
+ struct sockaddr_in sl_addr;
+} Listener;
+
+Listener **slap_listeners = NULL;
+
+#ifdef HAVE_WINSOCK2
+/* in nt_main.c */
+extern ldap_pvt_thread_cond_t started_event;
+
+/* forward reference */
+static void hit_socket(void);
+/* In wsa_err.c */
+char *WSAGetLastErrorString();
+static ldap_pvt_thread_t hit_tid;
+
+#define WAKE_LISTENER(w) \
+do {\
+ if( w ) {\
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );\
+ hit_socket(); \
+ }\
+} while(0)
+#else
+#define WAKE_LISTENER(w) \
+do {\
+ if( w ) {\
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );\
+ }\
+} while(0)
+#endif
+
+#ifndef HAVE_WINSOCK
+static
+#endif
+volatile sig_atomic_t slapd_shutdown = 0;
+
+static ldap_pvt_thread_t listener_tid;
+static volatile sig_atomic_t slapd_listener = 0;
+
+static struct slap_daemon {
+ ldap_pvt_thread_mutex_t sd_mutex;
+
+ int sd_nactives;
+
+#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;
+} slap_daemon;
+
+/*
+ * Add a descriptor to daemon control
+ */
+static void slapd_add(ber_socket_t s) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+
+ assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
+ assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
+ assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
+
+#ifndef HAVE_WINSOCK
+ if (s >= slap_daemon.sd_nfds) {
+ slap_daemon.sd_nfds = s + 1;
+ }
+#endif
+
+ FD_SET( s, &slap_daemon.sd_actives );
+ FD_SET( s, &slap_daemon.sd_readers );
+
+ Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n",
+ (long) s,
+ FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
+ FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+}
+
+/*
+ * Remove the descriptor from daemon control
+ */
+void slapd_remove(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
+ (long) s,
+ FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
+ FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
+
+ FD_CLR( s, &slap_daemon.sd_actives );
+ FD_CLR( s, &slap_daemon.sd_readers );
+ FD_CLR( s, &slap_daemon.sd_writers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+}
+
+void slapd_clr_write(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ assert( FD_ISSET( s, &slap_daemon.sd_actives) );
+ FD_CLR( s, &slap_daemon.sd_writers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+ if( wake ) {
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+ }
+}
+
+void slapd_set_write(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ assert( FD_ISSET( s, &slap_daemon.sd_actives) );
+ FD_SET( (unsigned) s, &slap_daemon.sd_writers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+ if( wake ) {
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+ }
+}
+
+void slapd_clr_read(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ assert( FD_ISSET( s, &slap_daemon.sd_actives) );
+ FD_CLR( s, &slap_daemon.sd_readers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+ if( wake ) {
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+ }
+}
+
+void slapd_set_read(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ assert( FD_ISSET( s, &slap_daemon.sd_actives) );
+ FD_SET( s, &slap_daemon.sd_readers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+ if( wake ) {
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+ }
+}
+
+static void slapd_close(ber_socket_t s) {
+ Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
+ (long) s, 0, 0 );
+ tcp_close(s);
+}
+
+
+Listener *
+open_listener(
+ const char* url,
+ int port,
+ int tls_port )
+{
+ int tmp, rc;
+ Listener l;
+ Listener *li;
+ LDAPURLDesc *lud;
+ char *s;
+
+ rc = ldap_url_parse( url, &lud );
+
+ if( rc != LDAP_URL_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: listen URL \"%s\" parse error=%d\n",
+ url, rc, 0 );
+ return NULL;
+ }
+
+#ifndef HAVE_TLS
+ if( lud->lud_ldaps ) {
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: TLS not supported (%s)\n",
+ url, 0, 0 );
+ ldap_free_urldesc( lud );
+ return NULL;
+ }
+
+ if(! lud->lud_port ) {
+ lud->lud_port = port;
+ }
+
+#else
+ l.sl_is_tls = lud->lud_ldaps;
+
+ if(! lud->lud_port ) {
+ lud->lud_port = lud->lud_ldaps ? tls_port : port;
+ }
+#endif
+
+ port = lud->lud_port;
+
+ (void) memset( (void*) &l.sl_addr, '\0', sizeof(l.sl_addr) );
+
+ l.sl_addr.sin_family = AF_INET;
+ l.sl_addr.sin_port = htons( (unsigned short) lud->lud_port );
+
+ if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
+ || strcmp(lud->lud_host, "*") == 0 )
+ {
+ l.sl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ } else {
+ /* host or address was specified */
+ if( !inet_aton( lud->lud_host, &l.sl_addr.sin_addr ) ) {
+ struct hostent *he = gethostbyname( lud->lud_host );
+ if( he == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "invalid host (%s) in URL: %s",
+ lud->lud_host, url, 0);
+ ldap_free_urldesc( lud );
+ return NULL;
+ }
+
+ memcpy( &l.sl_addr.sin_addr, he->h_addr,
+ sizeof( l.sl_addr.sin_addr ) );
+ }
+ }
+
+ ldap_free_urldesc( lud );
+
+
+ if ( (l.sl_sd = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID ) {
+#ifndef HAVE_WINSOCK
+ int err = errno;
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: socket() failed errno=%d (%s)\n", err,
+ err > -1 && err < sys_nerr ? sys_errlist[err] :
+ "unknown", 0 );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: socket() failed errno=%d (%s)\n",
+ WSAGetLastError(),
+ WSAGetLastErrorString(), 0 );
+#endif
+ return NULL;
+ }
+
+#ifndef HAVE_WINSOCK
+ if ( l.sl_sd >= dtblsize ) {
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: listener descriptor %ld is too great %ld\n",
+ (long) l.sl_sd, (long) dtblsize, 0 );
+ tcp_close( l.sl_sd );
+ return NULL;
+ }
+#endif
+
+#ifdef SO_REUSEADDR
+ /* enable address reuse */
+ tmp = 1;
+ if ( setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &tmp, sizeof(tmp) ) == -1 )
+ {
+ int err = errno;
+ Debug( LDAP_DEBUG_ANY,
+ "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
+ (long) l.sl_sd, err,
+ err > -1 && err < sys_nerr
+ ? sys_errlist[err] : "unknown" );
+ }
+#endif
+#ifdef SO_KEEPALIVE
+ /* enable keep alives */
+ tmp = 1;
+ if ( setsockopt( l.sl_sd, SOL_SOCKET, SO_KEEPALIVE,
+ (char *) &tmp, sizeof(tmp) ) == -1 )
+ {
+ int err = errno;
+ Debug( LDAP_DEBUG_ANY,
+ "slapd(%ld): setsockopt(SO_KEEPALIVE) failed errno=%d (%s)\n",
+ (long) l.sl_sd, err,
+ err > -1 && err < sys_nerr
+ ? sys_errlist[err] : "unknown" );
+ }
+#endif
+#ifdef TCP_NODELAY
+ /* enable no delay */
+ tmp = 1;
+ if ( setsockopt( l.sl_sd, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&tmp, sizeof(tmp) ) )
+ {
+ int err = errno;
+ Debug( LDAP_DEBUG_ANY,
+ "slapd(%ld): setsockopt(TCP_NODELAY) failed errno=%d (%s)\n",
+ (long) l.sl_sd, err,
+ err > -1 && err < sys_nerr
+ ? sys_errlist[err] : "unknown" );
+ }
+#endif
+
+ if ( bind( l.sl_sd, (struct sockaddr *) &l.sl_addr, sizeof(l.sl_addr) ) == -1 ) {
+ int err = errno;
+ Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
+ (long) l.sl_sd, err,
+ err > -1 && err < sys_nerr
+ ? sys_errlist[err] : "unknown" );
+ tcp_close( l.sl_sd );
+ return NULL;
+ }
+
+ l.sl_url = ch_strdup( url );
+
+ l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
+ s = inet_ntoa( l.sl_addr.sin_addr );
+ sprintf( l.sl_name, "IP=%s:%d",
+ s != NULL ? s : "unknown" , port );
+
+ li = ch_malloc( sizeof( Listener ) );
+ *li = l;
+
+ Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
+ l.sl_url, 0, 0 );
+
+ return li;
+}
+
+static int sockinit(void);
+static int sockdestroy(void);
+
+int slapd_daemon_init(char *urls, int port, int tls_port )
+{
+ int i, rc;
+ char **u;
+
+#ifndef HAVE_TLS
+ assert( tls_port == 0 );
+#endif
+
+ Debug( LDAP_DEBUG_ARGS, "daemon_init: %s (%d/%d)\n",
+ urls ? urls : "<null>", port, tls_port );
+
+ if( rc = sockinit() ) {
+ return rc;
+ }
+
+#ifdef HAVE_SYSCONF
+ dtblsize = sysconf( _SC_OPEN_MAX );
+#elif HAVE_GETDTABLESIZE
+ dtblsize = getdtablesize();
+#else
+ dtblsize = FD_SETSIZE;
+#endif
+
+#ifdef FD_SETSIZE
+ if(dtblsize > FD_SETSIZE) {
+ dtblsize = FD_SETSIZE;
+ }
+#endif /* !FD_SETSIZE */
+
+ FD_ZERO( &slap_daemon.sd_readers );
+ FD_ZERO( &slap_daemon.sd_writers );
+
+ if( urls == NULL ) {
+ urls = "ldap:///";
+ }
+
+ u = str2charray( urls, " " );
+
+ if( u == NULL || u[0] == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
+ urls, 0, 0 );
+
+ return -1;
+ }
+
+ for( i=0; u[i] != NULL; i++ ) {
+ Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
+ u[i], 0, 0 );
+ }
+
+ if( i == 0 ) {
+ Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
+ urls, 0, 0 );
+ charray_free( u );
+ return -1;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
+ i, 0, 0 );
+
+ slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
+
+ for(i = 0; u[i] != NULL; i++ ) {
+ slap_listeners[i] = open_listener( u[i], port, tls_port );
+
+ if( slap_listeners[i] == NULL ) {
+ charray_free( u );
+ return -1;
+ }
+ }
+ slap_listeners[i] = NULL;
+
+ Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
+ i, 0, 0 );
+
+ charray_free( u );
+ ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
+ return !i;
+}
+
+
+int
+slapd_daemon_destroy(void)
+{
+ connections_destroy();
+ sockdestroy();
+ return 0;
+}
+
+
+static void *
+slapd_daemon_task(
+ void *ptr
)
{
- Operation *o;
- BerElement ber;
- unsigned long len, tag, msgid;
- int i;
- int tcps, ns;
- struct sockaddr_in addr;
- fd_set readfds;
- fd_set writefds;
- FILE *fp;
- int on = 1;
-
-#ifdef USE_SYSCONF
- dtblsize = sysconf( _SC_OPEN_MAX );
-#else /* USE_SYSCONF */
- dtblsize = getdtablesize();
-#endif /* USE_SYSCONF */
-
- c = (Connection *) ch_calloc( 1, dtblsize * sizeof(Connection) );
-
- for ( i = 0; i < dtblsize; i++ ) {
- c[i].c_dn = NULL;
- c[i].c_addr = NULL;
- c[i].c_domain = NULL;
- c[i].c_ops = NULL;
- c[i].c_sb.sb_sd = -1;
- c[i].c_sb.sb_options = LBER_NO_READ_AHEAD;
- c[i].c_sb.sb_naddr = 0;
- c[i].c_sb.sb_ber.ber_buf = NULL;
- c[i].c_sb.sb_ber.ber_ptr = NULL;
- c[i].c_sb.sb_ber.ber_end = NULL;
- c[i].c_writewaiter = 0;
- c[i].c_connid = 0;
- pthread_mutex_init( &c[i].c_dnmutex,
- pthread_mutexattr_default );
- pthread_mutex_init( &c[i].c_opsmutex,
- pthread_mutexattr_default );
- pthread_mutex_init( &c[i].c_pdumutex,
- pthread_mutexattr_default );
- pthread_cond_init( &c[i].c_wcv, pthread_condattr_default );
- }
-
- if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
- Debug( LDAP_DEBUG_ANY, "socket() failed errno %d (%s)", errno,
- errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
- "unknown", 0 );
- exit( 1 );
- }
-
- i = 1;
- if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR, (char *) &i,
- sizeof(i) ) == -1 ) {
- Debug( LDAP_DEBUG_ANY, "setsockopt() failed errno %d (%s)",
- errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
- "unknown", 0 );
- }
-
- (void) memset( (void *) &addr, '\0', sizeof(addr) );
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = htons( port );
- if ( bind( tcps, (struct sockaddr *) &addr, sizeof(addr) ) == -1 ) {
- Debug( LDAP_DEBUG_ANY, "bind() failed errno %d (%s)\n",
- errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
- "unknown", 0 );
- exit( 1 );
- }
-
- if ( listen( tcps, 5 ) == -1 ) {
- Debug( LDAP_DEBUG_ANY, "listen() failed errno %d (%s)",
- errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
- "unknown", 0 );
- exit( 1 );
- }
-
- (void) SIGNAL( SIGPIPE, SIG_IGN );
- (void) SIGNAL( SIGUSR1, (void *) do_nothing );
- (void) SIGNAL( SIGUSR2, (void *) set_shutdown );
- (void) SIGNAL( SIGTERM, (void *) set_shutdown );
- (void) SIGNAL( SIGHUP, (void *) set_shutdown );
-
- Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
-#ifdef SLAPD_PIDFILE
- if ( (fp = fopen( SLAPD_PIDFILE, "w" )) != NULL ) {
- fprintf( fp, "%d\n", getpid() );
- fclose( fp );
- }
-#endif
-#ifdef SLAPD_ARGSFILE
- if ( (fp = fopen( SLAPD_ARGSFILE, "w" )) != NULL ) {
- for ( i = 0; i < g_argc; i++ ) {
- fprintf( fp, "%s ", g_argv[i] );
+ int l;
+
+ time( &starttime );
+
+ for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+ if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
+ continue;
+
+ if ( listen( slap_listeners[l]->sl_sd, 5 ) == -1 ) {
+ int err = errno;
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: listen(%s, 5) failed errno=%d (%s)\n",
+ (long) slap_listeners[l]->sl_url, err,
+ err > -1 && err < sys_nerr
+ ? sys_errlist[err] : "unknown" );
+
+ return( (void*)-1 );
}
- fprintf( fp, "\n" );
- fclose( fp );
+
+ slapd_add( slap_listeners[l]->sl_sd );
+ }
+
+#ifdef HAVE_WINSOCK
+ if ( started_event != NULL ) {
+ ldap_pvt_thread_cond_signal( &started_event );
}
#endif
+ /* initialization complete. Here comes the loop. */
while ( !slapd_shutdown ) {
+ ber_socket_t i;
+ int ns;
+ int at;
+ ber_socket_t nfds;
+#define SLAPD_EBADF_LIMIT 10
+ int ebadf = 0;
+
+#define SLAPD_IDLE_CHECK_LIMIT 4
+ time_t last_idle_check = slap_get_time();
+ time_t now;
+
+
+ fd_set readfds;
+ fd_set writefds;
+
struct sockaddr_in from;
- struct hostent *hp;
+#if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
+ struct hostent *hp;
+#endif
struct timeval zero;
struct timeval *tvp;
- int len, pid;
+
+ if( global_idletimeout > 0 && difftime(
+ last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
+ now ) < 0 )
+ {
+ connections_timeout_idle(now);
+ }
FD_ZERO( &writefds );
FD_ZERO( &readfds );
- FD_SET( tcps, &readfds );
-
- pthread_mutex_lock( &active_threads_mutex );
- Debug( LDAP_DEBUG_CONNS,
- "listening for connections on %d, activity on:",
- tcps, 0, 0 );
- for ( i = 0; i < dtblsize; i++ ) {
- if ( c[i].c_sb.sb_sd != -1 ) {
- FD_SET( c[i].c_sb.sb_sd, &readfds );
-
- if ( c[i].c_writewaiter ) {
- FD_SET( c[i].c_sb.sb_sd, &writefds );
- }
- Debug( LDAP_DEBUG_CONNS, " %dr%s", i,
- c[i].c_writewaiter ? "w" : "", 0 );
- }
- }
- Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
zero.tv_sec = 0;
zero.tv_usec = 0;
- Debug( LDAP_DEBUG_CONNS, "before select active_threads %d\n",
- active_threads, 0, 0 );
-#ifdef PTHREAD_PREEMPTIVE
+
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+
+#ifdef FD_SET_MANUAL_COPY
+ for( s = 0; s < nfds; s++ ) {
+ if(FD_ISSET( &slap_sd_writers, s )) {
+ FD_SET( &writefds, s );
+ }
+ if(FD_ISSET( &slap_sd_writers, s )) {
+ FD_SET( &writefds, s );
+ }
+ }
+#else
+ memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
+ memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
+#endif
+
+ for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+ if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
+ continue;
+ FD_SET( slap_listeners[l]->sl_sd, &readfds );
+ }
+
+#ifndef HAVE_WINSOCK
+ nfds = slap_daemon.sd_nfds;
+#else
+ nfds = dtblsize;
+#endif
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+ ldap_pvt_thread_mutex_lock( &active_threads_mutex );
+ at = active_threads;
+ ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
+
+#if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
tvp = NULL;
#else
- tvp = active_threads ? &zero : NULL;
+ tvp = at ? &zero : NULL;
#endif
- pthread_mutex_unlock( &active_threads_mutex );
- switch ( select( dtblsize, &readfds, &writefds, 0, tvp ) ) {
- case -1: /* failure - try again */
+ for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+ if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
+ continue;
+
Debug( LDAP_DEBUG_CONNS,
- "select failed errno %d (%s)\n",
- errno, errno > -1 && errno < sys_nerr ?
- sys_errlist[errno] : "unknown", 0 );
+ "daemon: select: listen=%d active_threads=%d tvp=%s\n",
+ slap_listeners[l]->sl_sd, at,
+ tvp == NULL ? "NULL" : "zero" );
+ }
+
+ switch(ns = select( nfds, &readfds,
+#ifdef HAVE_WINSOCK
+ /* don't pass empty fd_set */
+ ( writefds.fd_count > 0 ? &writefds : NULL ),
+#else
+ &writefds,
+#endif
+ NULL, tvp ))
+ {
+ case -1: { /* failure - try again */
+#ifdef HAVE_WINSOCK
+ int err = WSAGetLastError();
+#else
+ int err = errno;
+#endif
+
+ if( err == EBADF && ++ebadf < SLAPD_EBADF_LIMIT) {
+ continue;
+ }
+
+ if( err != EINTR ) {
+ Debug( LDAP_DEBUG_CONNS,
+ "daemon: select failed (%d): %s\n",
+ err,
+ err >= 0 && err < sys_nerr
+ ? sys_errlist[err] : "unknown",
+ 0 );
+
+
+ slapd_shutdown = -1;
+ }
+ }
continue;
case 0: /* timeout - let threads run */
- Debug( LDAP_DEBUG_CONNS, "select timeout - yielding\n",
+ ebadf = 0;
+ Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
0, 0, 0 );
- pthread_yield();
+ ldap_pvt_thread_yield();
continue;
default: /* something happened - deal with it */
- Debug( LDAP_DEBUG_CONNS, "select activity\n", 0, 0, 0 );
- ; /* FALL */
+ ebadf = 0;
+ Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
+ ns, 0, 0 );
+ /* FALL THRU */
}
- pthread_mutex_lock( ¤ttime_mutex );
- time( ¤ttime );
- pthread_mutex_unlock( ¤ttime_mutex );
- /* new connection */
- pthread_mutex_lock( &new_conn_mutex );
- if ( FD_ISSET( tcps, &readfds ) ) {
- len = sizeof(from);
- if ( (ns = accept( tcps, (struct sockaddr *) &from,
- &len )) == -1 ) {
+ for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+ ber_int_t s;
+ socklen_t len = sizeof(from);
+ long id;
+
+ char *dnsname;
+ char *peeraddr;
+
+ char peername[sizeof("IP=255.255.255.255:65336")];
+
+ if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
+ continue;
+
+ if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
+ continue;
+
+ if ( (s = accept( slap_listeners[l]->sl_sd,
+ (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
+ {
+ int err = errno;
Debug( LDAP_DEBUG_ANY,
- "accept() failed errno %d (%s)", errno,
- errno > -1 && errno < sys_nerr ?
- sys_errlist[errno] : "unknown", 0 );
- pthread_mutex_unlock( &new_conn_mutex );
+ "daemon: accept(%ld) failed errno=%d (%s)\n", err,
+ (long) slap_listeners[l]->sl_sd,
+ err >= 0 && err < sys_nerr ?
+ sys_errlist[err] : "unknown");
continue;
}
- if ( ioctl( ns, FIONBIO, (caddr_t) &on ) == -1 ) {
+
+#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( !FD_ISSET( s, &slap_daemon.sd_actives) );
+ assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
+ assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+#endif
+
+#ifndef HAVE_WINSOCK
+ /* make sure descriptor number isn't too great */
+ if ( s >= dtblsize ) {
Debug( LDAP_DEBUG_ANY,
- "FIONBIO ioctl on %d faled\n", ns, 0, 0 );
+ "daemon: %ld beyond descriptor table size %ld\n",
+ (long) s, (long) dtblsize, 0 );
+ slapd_close(s);
+ continue;
}
- c[ns].c_sb.sb_sd = ns;
- Debug( LDAP_DEBUG_CONNS, "new connection on %d\n", ns,
- 0, 0 );
+#endif
+
+ Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
+ (long) s, 0, 0 );
- pthread_mutex_lock( &ops_mutex );
- c[ns].c_connid = num_conns++;
- pthread_mutex_unlock( &ops_mutex );
len = sizeof(from);
- if ( getpeername( ns, (struct sockaddr *) &from, &len )
- == 0 ) {
- char *s;
-#ifdef REVERSE_LOOKUP
- hp = gethostbyaddr( (char *)
- &(from.sin_addr.s_addr),
- sizeof(from.sin_addr.s_addr), AF_INET );
+
+ if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
+ int err = errno;
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
+ (long) s, err,
+ err >= 0 && err < sys_nerr ?
+ sys_errlist[err] : "unknown" );
+ slapd_close(s);
+ continue;
+ }
+
+ peeraddr = inet_ntoa( from.sin_addr );
+ sprintf( peername, "IP=%s:%d",
+ peeraddr != NULL ? peeraddr : "unknown",
+ (unsigned) ntohs( from.sin_port ) );
+
+#if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
+ hp = gethostbyaddr( (char *)
+ &(from.sin_addr.s_addr),
+ sizeof(from.sin_addr.s_addr), AF_INET );
+
+ if(hp) {
+ dnsname = str2lower( hp->h_name );
+
+ } else {
+ dnsname = NULL;
+ }
#else
- hp = NULL;
+ dnsname = NULL;
#endif
- Statslog( LDAP_DEBUG_STATS,
- "conn=%d fd=%d connection from %s (%s)\n",
- c[ns].c_connid, ns, hp == NULL ? "unknown"
- : hp->h_name, inet_ntoa( from.sin_addr ),
- 0 );
+#ifdef HAVE_TCPD
+ if( !hosts_ctl("slapd",
+ dnsname != NULL ? dnsname : STRING_UNKNOWN,
+ peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
+ STRING_UNKNOWN ))
+ {
+ /* DENY ACCESS */
+ Statslog( LDAP_DEBUG_ANY,
+ "fd=%ld connection from %s (%s) denied.\n",
+ (long) s,
+ dnsname != NULL ? dnsname : "unknown",
+ peeraddr != NULL ? peeraddr : "unknown",
+ 0, 0 );
- if ( c[ns].c_addr != NULL ) {
- free( c[ns].c_addr );
- }
- c[ns].c_addr = strdup( inet_ntoa(
- from.sin_addr ) );
- if ( c[ns].c_domain != NULL ) {
- free( c[ns].c_domain );
- }
- c[ns].c_domain = strdup( hp == NULL ? "" :
- hp->h_name );
- /* normalize the domain */
- for ( s = c[ns].c_domain; *s; s++ ) {
- *s = TOLOWER( *s );
- }
- } else {
- Statslog( LDAP_DEBUG_STATS,
- "conn=%d fd=%d connection from unknown\n",
- c[ns].c_connid, ns, 0, 0, 0 );
+ slapd_close(s);
+ continue;
}
- pthread_mutex_lock( &c[ns].c_dnmutex );
- if ( c[ns].c_dn != NULL ) {
- free( c[ns].c_dn );
- c[ns].c_dn = NULL;
+#endif /* HAVE_TCPD */
+
+ if( (id = connection_init(s,
+ slap_listeners[l]->sl_url,
+ dnsname != NULL ? dnsname : "unknown",
+ peername,
+ slap_listeners[l]->sl_name,
+#ifdef HAVE_TLS
+ slap_listeners[l]->sl_is_tls
+#else
+ 0
+#endif
+ )) < 0 )
+ {
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: connection_init(%ld, %s, %s) failed.\n",
+ (long) s,
+ peername,
+ slap_listeners[l]->sl_name );
+ slapd_close(s);
+ continue;
}
- pthread_mutex_unlock( &c[ns].c_dnmutex );
- c[ns].c_starttime = currenttime;
- c[ns].c_opsinitiated = 0;
- c[ns].c_opscompleted = 0;
+
+ Statslog( LDAP_DEBUG_STATS,
+ "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
+ id, (long) s,
+ peername,
+ slap_listeners[l]->sl_name,
+ 0 );
+
+ slapd_add( s );
+ continue;
}
- pthread_mutex_unlock( &new_conn_mutex );
- Debug( LDAP_DEBUG_CONNS, "activity on:", 0, 0, 0 );
- for ( i = 0; i < dtblsize; i++ ) {
- int r, w;
+#ifdef LDAP_DEBUG
+ Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
+#ifdef HAVE_WINSOCK
+ for ( i = 0; i < readfds.fd_count; i++ ) {
+ Debug( LDAP_DEBUG_CONNS, " %d%s",
+ readfds.fd_array[i], "r", 0 );
+ }
+ for ( i = 0; i < writefds.fd_count; i++ ) {
+ Debug( LDAP_DEBUG_CONNS, " %d%s",
+ writefds.fd_array[i], "w", 0 );
+ }
+#else
+ for ( i = 0; i < nfds; i++ ) {
+ int a, r, w;
+ int is_listener = 0;
+ for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+ if ( i == slap_listeners[l]->sl_sd ) {
+ is_listener = 1;
+ break;
+ }
+ }
+ if ( is_listener ) {
+ continue;
+ }
r = FD_ISSET( i, &readfds );
w = FD_ISSET( i, &writefds );
- if ( i != tcps && (r || w) ) {
+ if ( r || w ) {
Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
r ? "r" : "", w ? "w" : "" );
}
}
+#endif
Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
+#endif
- for ( i = 0; i < dtblsize; i++ ) {
- if ( i == tcps || (! FD_ISSET( i, &readfds ) &&
- ! FD_ISSET( i, &writefds )) ) {
+ /* loop through the writers */
+#ifdef HAVE_WINSOCK
+ for ( i = 0; i < writefds.fd_count; i++ )
+#else
+ for ( i = 0; i < nfds; i++ )
+#endif
+ {
+ ber_socket_t wd;
+ int is_listener = 0;
+#ifdef HAVE_WINSOCK
+ wd = writefds.fd_array[i];
+#else
+ if( ! FD_ISSET( i, &writefds ) ) {
continue;
}
+ wd = i;
+#endif
+
+ for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+ if ( i == slap_listeners[l]->sl_sd ) {
+ is_listener = 1;
+ break;
+ }
+ }
+ if ( is_listener ) {
+ continue;
+ }
+ Debug( LDAP_DEBUG_CONNS,
+ "daemon: write active on %d\n",
+ wd, 0, 0 );
- if ( FD_ISSET( i, &writefds ) ) {
- Debug( LDAP_DEBUG_CONNS,
- "signaling write waiter on %d\n", i, 0, 0 );
+ /*
+ * NOTE: it is possible that the connection was closed
+ * and that the stream is now inactive.
+ * connection_write() must valid the stream is still
+ * active.
+ */
+
+ if ( connection_write( wd ) < 0 ) {
+ FD_CLR( (unsigned) wd, &readfds );
+ slapd_close( wd );
+ }
+ }
+
+#ifdef HAVE_WINSOCK
+ for ( i = 0; i < readfds.fd_count; i++ )
+#else
+ for ( i = 0; i < nfds; i++ )
+#endif
+ {
+ ber_socket_t rd;
+ int is_listener = 0;
+
+#ifdef HAVE_WINSOCK
+ rd = readfds.fd_array[i];
+#else
+ if( ! FD_ISSET( i, &readfds ) ) {
+ continue;
+ }
+ rd = i;
+#endif
- pthread_mutex_lock( &active_threads_mutex );
- pthread_cond_signal( &c[i].c_wcv );
- c[i].c_writewaiter = 0;
- active_threads++;
- pthread_mutex_unlock( &active_threads_mutex );
+ for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+ if ( rd == slap_listeners[l]->sl_sd ) {
+ is_listener = 1;
+ break;
+ }
+ }
+ if ( is_listener ) {
+ continue;
}
- if ( FD_ISSET( i, &readfds ) ) {
- Debug( LDAP_DEBUG_CONNS,
- "read activity on %d\n", i, 0, 0 );
+ Debug ( LDAP_DEBUG_CONNS,
+ "daemon: read activity on %d\n", rd, 0, 0 );
+
+ /*
+ * NOTE: it is possible that the connection was closed
+ * and that the stream is now inactive.
+ * connection_read() must valid the stream is still
+ * active.
+ */
- connection_activity( &c[i] );
+ if ( connection_read( rd ) < 0 ) {
+ slapd_close( rd );
}
}
+ ldap_pvt_thread_yield();
+ }
- pthread_yield();
+ if( slapd_shutdown > 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "daemon: shutdown requested and initiated.\n",
+ 0, 0, 0 );
+
+ } else if ( slapd_shutdown < 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "daemon: abnormal condition, shutdown initiated.\n",
+ 0, 0, 0 );
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "daemon: no active streams, shutdown initiated.\n",
+ 0, 0, 0 );
}
- close( tcps );
- pthread_mutex_lock( &active_threads_mutex );
+ for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+ if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
+ slapd_close( slap_listeners[l]->sl_sd );
+ break;
+ }
+ }
+
+ ldap_pvt_thread_mutex_lock( &active_threads_mutex );
Debug( LDAP_DEBUG_ANY,
- "slapd shutting down - waiting for %d threads to terminate\n",
+ "slapd shutdown: waiting for %d threads to terminate\n",
active_threads, 0, 0 );
while ( active_threads > 0 ) {
- pthread_mutex_unlock( &active_threads_mutex );
- pthread_yield();
- pthread_mutex_lock( &active_threads_mutex );
- }
- pthread_mutex_unlock( &active_threads_mutex );
-
- /* let backends do whatever cleanup they need to do */
- Debug( LDAP_DEBUG_TRACE,
- "slapd shutting down - waiting for backends to close down\n", 0, 0,
- 0 );
- be_close();
- Debug( LDAP_DEBUG_ANY, "slapd stopping\n", 0, 0, 0 );
+ ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
+ }
+ ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
+
+ return NULL;
}
-static void
-set_shutdown()
+
+int slapd_daemon( void )
{
- Debug( LDAP_DEBUG_ANY, "slapd got shutdown signal\n", 0, 0, 0 );
- slapd_shutdown = 1;
- pthread_kill( listener_tid, SIGUSR1 );
- (void) SIGNAL( SIGUSR2, (void *) set_shutdown );
- (void) SIGNAL( SIGTERM, (void *) set_shutdown );
- (void) SIGNAL( SIGHUP, (void *) set_shutdown );
+ int rc;
+
+ connections_init();
+
+#define SLAPD_LISTENER_THREAD 1
+#if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
+
+ /* listener as a separate THREAD */
+ rc = ldap_pvt_thread_create( &listener_tid,
+ 0, slapd_daemon_task, NULL );
+
+ if ( rc != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
+ return rc;
+ }
+
+ /* wait for the listener thread to complete */
+ ldap_pvt_thread_join( listener_tid, (void *) NULL );
+#else
+ /* expermimental code */
+ listener_tid = pthread_self();
+ slapd_daemon_task( NULL );
+#endif
+
+ return 0;
+
+}
+
+#ifdef HAVE_WINSOCK2
+int sockinit(void)
+{
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 0 );
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ /* Tell the user that we couldn't find a usable */
+ /* WinSock DLL. */
+ return -1;
+ }
+
+ /* Confirm that the WinSock DLL supports 2.0.*/
+ /* Note that if the DLL supports versions greater */
+ /* than 2.0 in addition to 2.0, it will still return */
+ /* 2.0 in wVersion since that is the version we */
+ /* requested. */
+
+ if ( LOBYTE( wsaData.wVersion ) != 2 ||
+ HIBYTE( wsaData.wVersion ) != 0 )
+ {
+ /* Tell the user that we couldn't find a usable */
+ /* WinSock DLL. */
+ WSACleanup();
+ return -1;
+ }
+
+ /* The WinSock DLL is acceptable. Proceed. */
+ return 0;
+}
+
+int sockdestroy(void)
+{
+ WSACleanup();
+ return 0;
}
-static void
-do_nothing()
+void hit_socket(void)
+{
+ ber_socket_t s;
+ int on = 1;
+ extern struct sockaddr_in bind_addr;
+
+ /* throw something at the socket to terminate the select() in the daemon thread. */
+ if (( s = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID )
+ Debug( LDAP_DEBUG_ANY,
+ "slap_set_shutdown: socket failed\n\tWSAGetLastError=%d (%s)\n",
+ WSAGetLastError(), WSAGetLastErrorString(), 0 );
+
+ if ( ioctlsocket( s, FIONBIO, &on ) == -1 )
+ Debug( LDAP_DEBUG_ANY,
+ "slap_set_shutdown:FIONBIO ioctl on %d faled\n\tWSAGetLastError=%d (%s)\n",
+ s, WSAGetLastError(), WSAGetLastError() );
+
+ bind_addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
+
+ if ( connect( s, (struct sockaddr *)&bind_addr, sizeof( struct sockaddr_in )) == SOCKET_ERROR ) {
+ Debug( LDAP_DEBUG_ANY,
+ "hit_socket: error on connect: %d\n",
+ WSAGetLastError(), 0, 0 );
+ /* we can probably expect some error to occur here, mostly WSAEWOULDBLOCK */
+ }
+
+ tcp_close(s);
+}
+
+#elif HAVE_WINSOCK
+static int sockinit(void)
+{ WSADATA wsaData;
+ if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
+ return -1;
+ }
+ return 0;
+}
+static int sockdestroy(void)
+{
+ WSACleanup();
+ return 0;
+}
+
+#else
+static int sockinit(void)
+{
+ return 0;
+}
+static int sockdestroy(void)
+{
+ return 0;
+}
+#endif
+
+void
+slap_set_shutdown( int sig )
+{
+ int l;
+ slapd_shutdown = sig;
+#ifndef HAVE_WINSOCK
+ if(slapd_listener) {
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+ }
+#else
+ /* trying to "hit" the socket seems to always get a */
+ /* EWOULDBLOCK error, so just close the listen socket to */
+ /* break out of the select since we're shutting down anyway */
+ for ( l = 0; slap_listeners[l] != NULL; l++ ) {
+ if ( slap_listeners[l]->sl_sd >= 0 ) {
+ tcp_close( slap_listeners[l]->sl_sd );
+ }
+ }
+#endif
+ /* reinstall self */
+ (void) SIGNAL( sig, slap_set_shutdown );
+}
+
+void
+slap_do_nothing( int sig )
{
- Debug( LDAP_DEBUG_TRACE, "slapd got SIGUSR1\n", 0, 0, 0 );
- (void) SIGNAL( SIGUSR1, (void *) do_nothing );
+ /* reinstall self */
+ (void) SIGNAL( sig, slap_do_nothing );
}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/string.h>
+#include <ac/socket.h>
-extern char *default_referral;
+#include "slap.h"
-void
+int
do_delete(
Connection *conn,
Operation *op
)
{
- char *dn, *odn;
+ char *ndn;
Backend *be;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_delete: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the delete request. It looks like this:
*
* DelRequest := DistinguishedName
*/
- if ( ber_scanf( op->o_ber, "a", &dn ) == LBER_ERROR ) {
+ if ( ber_scanf( op->o_ber, "a", &ndn ) == LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+ }
+
+ if( dn_normalize_case( ndn ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "do_delete: invalid dn (%s)\n", ndn, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
+ "invalid DN", NULL, NULL );
+ free( ndn );
+ return rc;
}
- odn = strdup( dn );
- dn_normalize( dn );
- Debug( LDAP_DEBUG_ARGS, "do_delete: dn (%s)\n", dn, 0, 0 );
+ if( ( rc = get_ctrls( conn, op, 1 ) ) != LDAP_SUCCESS ) {
+ free( ndn );
+ Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
- Debug( LDAP_DEBUG_STATS, "DEL dn=\"%s\"\n", dn, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS, "do_delete: dn (%s)\n", ndn, 0, 0 );
+ Debug( LDAP_DEBUG_STATS, "DEL dn=\"%s\"\n", ndn, 0, 0 );
/*
* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
- free( odn );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ if ( (be = select_backend( ndn )) == NULL ) {
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
+ free( ndn );
+ return rc;
}
+ /* deref suffix alias if appropriate */
+ ndn = suffix_alias( be, ndn );
+
/*
* do the delete if 1 && (2 || 3)
* 1) there is a delete function implemented in this backend;
* 2) this backend is master for what it holds;
- * 3) it's a replica and the dn supplied is the updatedn.
+ * 3) it's a replica and the dn supplied is the update_ndn.
*/
- if ( be->be_delete != NULL ) {
+ if ( be->be_delete ) {
/* do the update here */
- if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
- op->o_dn ) == 0 ) {
- if ( (*be->be_delete)( be, conn, op, dn ) == 0 ) {
- replog( be, LDAP_REQ_DELETE, odn, NULL, 0 );
+#ifndef SLAPD_MULTIMASTER
+ if ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
+#endif
+ {
+ if ( (*be->be_delete)( be, conn, op, ndn ) == 0 ) {
+#ifdef SLAPD_MULTIMASTER
+ if (be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ))
+#endif
+ {
+ replog( be, op, ndn, NULL );
+ }
}
+#ifndef SLAPD_MULTIMASTER
} else {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+ be->be_update_refs ? be->be_update_refs : default_referral, NULL );
+#endif
}
+
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
- free( dn );
- free( odn );
+ free( ndn );
+ return rc;
}
/* dn.c - routines for dealing with distinguished names */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
#include "portable.h"
-#include "slap.h"
-static char **dn_explode();
+#include <stdio.h>
+
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
-#define DNSEPARATOR(c) (c == ',' || c == ';')
-#define SEPARATOR(c) (c == ',' || c == ';' || c == '+')
-#define SPACE(c) (c == ' ' || c == '\n')
-#define NEEDSESCAPE(c) (c == '\\' || c == '"')
-#define B4TYPE 0
-#define INTYPE 1
-#define B4EQUAL 2
-#define B4VALUE 3
-#define INVALUE 4
-#define INQUOTEDVALUE 5
-#define B4SEPARATOR 6
+#include "slap.h"
+
+#define B4LEADTYPE 0
+#define B4TYPE 1
+#define INOIDTYPE 2
+#define INKEYTYPE 3
+#define B4EQUAL 4
+#define B4VALUE 5
+#define INVALUE 6
+#define INQUOTEDVALUE 7
+#define B4SEPARATOR 8
/*
* dn_normalize - put dn into a canonical format. the dn is
- * normalized in place, as well as returned.
+ * normalized in place, as well as returned if valid.
*/
char *
char *d, *s;
int state, gotesc;
- /* Debug( LDAP_DEBUG_TRACE, "=> dn_normalize \"%s\"\n", dn, 0, 0 ); */
-
gotesc = 0;
- state = B4TYPE;
+ state = B4LEADTYPE;
for ( d = s = dn; *s; s++ ) {
switch ( state ) {
+ case B4LEADTYPE:
case B4TYPE:
- if ( ! SPACE( *s ) ) {
- state = INTYPE;
+ if ( LEADOIDCHAR(*s) ) {
+ state = INOIDTYPE;
+ *d++ = *s;
+ } else if ( LEADKEYCHAR(*s) ) {
+ state = INKEYTYPE;
+ *d++ = *s;
+ } else if ( ! SPACE( *s ) ) {
+ dn = NULL;
+ state = INKEYTYPE;
*d++ = *s;
}
break;
- case INTYPE:
- if ( *s == '=' ) {
+
+ case INOIDTYPE:
+ if ( OIDCHAR(*s) ) {
+ *d++ = *s;
+ } else if ( *s == '=' ) {
+ state = B4VALUE;
+ *d++ = *s;
+ } else if ( SPACE( *s ) ) {
+ state = B4EQUAL;
+ } else {
+ dn = NULL;
+ *d++ = *s;
+ }
+ break;
+
+ case INKEYTYPE:
+ if ( KEYCHAR(*s) ) {
+ *d++ = *s;
+ } else if ( *s == '=' ) {
state = B4VALUE;
*d++ = *s;
} else if ( SPACE( *s ) ) {
state = B4EQUAL;
} else {
+ dn = NULL;
*d++ = *s;
}
break;
+
case B4EQUAL:
if ( *s == '=' ) {
state = B4VALUE;
} else if ( ! SPACE( *s ) ) {
/* not a valid dn - but what can we do here? */
*d++ = *s;
+ dn = NULL;
}
break;
+
case B4VALUE:
if ( *s == '"' ) {
state = INQUOTEDVALUE;
*d++ = *s;
}
break;
+
case INVALUE:
if ( !gotesc && SEPARATOR( *s ) ) {
while ( SPACE( *(d - 1) ) )
*d++ = *s;
}
break;
+
case INQUOTEDVALUE:
if ( !gotesc && *s == '"' ) {
state = B4SEPARATOR;
}
break;
default:
+ dn = NULL;
Debug( LDAP_DEBUG_ANY,
"dn_normalize - unknown state %d\n", state, 0, 0 );
break;
}
*d = '\0';
- /* Debug( LDAP_DEBUG_TRACE, "<= dn_normalize \"%s\"\n", dn, 0, 0 ); */
+ if( gotesc ) {
+ /* shouldn't be left in escape */
+ dn = NULL;
+ }
+
+ /* check end state */
+ switch( state ) {
+ case B4LEADTYPE: /* looking for first type */
+ case B4SEPARATOR: /* looking for separator */
+ case INVALUE: /* inside value */
+ break;
+ default:
+ dn = NULL;
+ }
+
return( dn );
}
/*
* dn_normalize_case - put dn into a canonical form suitable for storing
* in a hash database. this involves normalizing the case as well as
- * the format. the dn is normalized in place as well as returned.
+ * the format. the dn is normalized in place as well as returned if valid.
*/
char *
dn_normalize_case( char *dn )
{
- char *s;
+ str2upper( dn );
/* normalize format */
- dn_normalize( dn );
-
- /* normalize case */
- for ( s = dn; *s; s++ ) {
- *s = TOUPPER( *s );
- }
+ dn = dn_normalize( dn );
+ /* and upper case it */
return( dn );
}
)
{
char *s;
- int inquote, gotesc;
+ int inquote;
+
+ if( dn == NULL ) {
+ return NULL;
+ }
+
+ while(*dn && SPACE(*dn)) {
+ dn++;
+ }
- if ( dn == NULL || *dn == '\0' || be_issuffix( be, dn ) ) {
+ if( *dn == '\0' ) {
+ return( NULL );
+ }
+
+ if ( be != NULL && be_issuffix( be, dn ) ) {
return( NULL );
}
if ( *(s + 1) == '\0' ) {
return( NULL );
} else {
- return( strdup( s + 1 ) );
+ return( ch_strdup( &s[1] ) );
+ }
+ }
+
+ /*
+ * else assume it is an X.500-style name, which looks like
+ * foo=bar,sha=baz,...
+ */
+
+ inquote = 0;
+ for ( s = dn; *s; s++ ) {
+ if ( *s == '\\' ) {
+ if ( *(s + 1) ) {
+ s++;
+ }
+ continue;
+ }
+ if ( inquote ) {
+ if ( *s == '"' ) {
+ inquote = 0;
+ }
+ } else {
+ if ( *s == '"' ) {
+ inquote = 1;
+ } else if ( DNSEPARATOR( *s ) ) {
+ return( ch_strdup( &s[1] ) );
+ }
+ }
+ }
+
+ return( ch_strdup( "" ) );
+}
+
+char * dn_rdn(
+ Backend *be,
+ char *dn )
+{
+ char *s;
+ int inquote;
+
+ if( dn == NULL ) {
+ return NULL;
+ }
+
+ while(*dn && SPACE(*dn)) {
+ dn++;
+ }
+
+ if( *dn == '\0' ) {
+ return( NULL );
+ }
+
+ if ( be != NULL && be_issuffix( be, dn ) ) {
+ return( NULL );
+ }
+
+ dn = ch_strdup( dn );
+
+#ifdef DNS_DN
+ /*
+ * no =, assume it is a dns name, like blah@some.domain.name
+ * if the blah@ part is there, return some.domain.name. if
+ * it's just some.domain.name, return domain.name.
+ */
+ if ( strchr( dn, '=' ) == NULL ) {
+ if ( (s = strchr( dn, '@' )) == NULL ) {
+ if ( (s = strchr( dn, '.' )) == NULL ) {
+ return( dn );
+ }
}
+ *s = '\0';
+ return( dn );
}
+#endif
/*
* else assume it is an X.500-style name, which looks like
*/
inquote = 0;
+
for ( s = dn; *s; s++ ) {
if ( *s == '\\' ) {
- if ( *(s + 1) )
+ if ( *(s + 1) ) {
s++;
+ }
continue;
}
if ( inquote ) {
- if ( *s == '"' )
+ if ( *s == '"' ) {
inquote = 0;
+ }
} else {
- if ( *s == '"' )
+ if ( *s == '"' ) {
inquote = 1;
- else if ( DNSEPARATOR( *s ) )
- return( strdup( s + 1 ) );
+ } else if ( DNSEPARATOR( *s ) ) {
+ *s = '\0';
+ return( dn );
+ }
}
}
- return( NULL );
+ return( dn );
+}
+
+
+/*
+ * return a charray of all subtrees to which the DN resides in
+ */
+char **dn_subtree(
+ Backend *be,
+ char *dn )
+{
+ char *child, *parent;
+ char **subtree = NULL;
+
+ child = dn;
+
+ do {
+ charray_add( &subtree, child );
+
+ parent = dn_parent( be, child );
+
+ if( child != dn ) {
+ free( child );
+ }
+
+ child = parent;
+ } while ( child != NULL );
+
+ return subtree;
}
+
/*
* dn_issuffix - tells whether suffix is a suffix of dn. both dn
* and suffix must be normalized.
return( 0 );
}
- return( strcasecmp( dn + dnlen - suffixlen, suffix ) == 0 );
+ return( strcmp( dn + dnlen - suffixlen, suffix ) == 0 );
}
+#ifdef DNS_DN
/*
* dn_type - tells whether the given dn is an X.500 thing or DNS thing
* returns (defined in slap.h): DN_DNS dns-style thing
{
return( strchr( dn, '=' ) == NULL ? DN_DNS : DN_X500 );
}
+#endif
char *
-dn_upcase( char *dn )
+str2upper( char *str )
{
char *s;
/* normalize case */
- for ( s = dn; *s; s++ ) {
- *s = TOUPPER( *s );
+ for ( s = str; *s; s++ ) {
+ *s = TOUPPER( (unsigned char) *s );
}
- return( dn );
+ return( str );
+}
+
+char *
+str2lower( char *str )
+{
+ char *s;
+
+ /* normalize case */
+ for ( s = str; *s; s++ ) {
+ *s = TOLOWER( (unsigned char) *s );
+ }
+
+ return( str );
+}
+
+
+/*
+ * get_next_substring(), rdn_attr_type(), rdn_attr_value(), and
+ * build_new_dn().
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+/* get_next_substring:
+ *
+ * Gets next substring in s, using d (or the end of the string '\0') as a
+ * string delimiter, and places it in a duplicated memory space. Leading
+ * spaces are ignored. String s **must** be null-terminated.
+ */
+
+static char *
+get_next_substring( char * s, char d )
+{
+
+ char *str, *r;
+
+ r = str = ch_malloc( strlen(s) + 1 );
+
+ /* Skip leading spaces */
+
+ while ( *s && SPACE(*s) ) {
+
+ s++;
+
+ }
+
+ /* Copy word */
+
+ while ( *s && (*s != d) ) {
+
+ /* Don't stop when you see trailing spaces may be a multi-word
+ * string, i.e. name=John Doe!
+ */
+
+ *str++ = *s++;
+
+ }
+
+ *str = '\0';
+
+ return r;
+
+}
+
+
+/* rdn_attr_type:
+ *
+ * Given a string (i.e. an rdn) of the form:
+ * "attribute_type = attribute_value"
+ * this function returns the type of an attribute, that is the
+ * string "attribute_type" which is placed in newly allocated
+ * memory. The returned string will be null-terminated.
+ */
+
+char * rdn_attr_type( char * s )
+{
+
+ return get_next_substring( s, '=' );
+
+}
+
+
+/* rdn_attr_value:
+ *
+ * Given a string (i.e. an rdn) of the form:
+ * "attribute_type = attribute_value"
+ * this function returns "attribute_type" which is placed in newly allocated
+ * memory. The returned string will be null-terminated and may contain
+ * spaces (i.e. "John Doe\0").
+ */
+
+char *
+rdn_attr_value( char * rdn )
+{
+
+ char *str;
+
+ if ( (str = strchr( rdn, '=' )) != NULL ) {
+
+ return get_next_substring(++str, '\0');
+
+ }
+
+ return NULL;
+
+}
+
+
+int rdn_validate( const char * rdn )
+{
+ /* just a simple check for now */
+ return strchr( rdn, '=' ) != NULL;
+}
+
+
+/* build_new_dn:
+ *
+ * Used by ldbm/bdb2_back_modrdn to create the new dn of entries being
+ * renamed.
+ *
+ * new_dn = parent (p_dn) + separator(s) + rdn (newrdn) + null.
+ */
+
+void
+build_new_dn( char ** new_dn, char *e_dn, char * p_dn, char * newrdn )
+{
+
+ if ( p_dn == NULL ) {
+
+ *new_dn = ch_strdup( newrdn );
+ return;
+
+ }
+
+ *new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn ) + 3 );
+
+#ifdef DNS_DN
+ if ( dn_type( e_dn ) == DN_X500 ) {
+#endif
+
+ strcpy( *new_dn, newrdn );
+ strcat( *new_dn, "," );
+ strcat( *new_dn, p_dn );
+
+#ifdef DNS_DN
+ } else {
+
+ char *s;
+ char sep[2];
+
+ strcpy( *new_dn, newrdn );
+ s = strchr( newrdn, '\0' );
+ s--;
+
+ if ( (*s != '.') && (*s != '@') ) {
+
+ if ( (s = strpbrk( e_dn, ".@" )) != NULL ) {
+
+ sep[0] = *s;
+ sep[1] = '\0';
+ strcat( *new_dn, sep );
+
+ }
+
+ }
+
+ strcat( *new_dn, p_dn );
+
+ }
+#endif
+
}
/* entry.c - routines for dealing with entries */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-void entry_free();
-char *entry2str();
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
static unsigned char *ebuf; /* buf returned by entry2str */
static unsigned char *ecur; /* pointer to end of currently used ebuf */
static int emaxsize;/* max size of ebuf */
+int entry_destroy(void)
+{
+ free( ebuf );
+ ebuf = NULL;
+ ecur = NULL;
+ emaxsize = 0;
+ return 0;
+}
+
Entry *
-str2entry( char *s )
+str2entry( char *s )
{
- int i;
Entry *e;
Attribute **a;
char *type;
char *value;
char *next;
- int vlen, nvals, maxvals;
+ ber_len_t vlen;
+ int nvals, maxvals;
struct berval bval;
struct berval *vals[2];
char ptype[64];
/*
- * In string format, an entry looks like this:
+ * LDIF is used as the string format.
+ * An entry looks like this:
*
- * <id>\n
* dn: <dn>\n
* [<attr>:[:] <value>\n]
* [<tab><continuedvalue>\n]*
* or newline.
*/
- Debug( LDAP_DEBUG_TRACE, "=> str2entry\n", s, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "=> str2entry\n",
+ s ? s : "NULL", 0, 0 );
+
+ next = s;
+ /* initialize reader/writer lock */
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
- /* check to see if there's an id included */
- next = s;
- if ( isdigit( *s ) ) {
- e->e_id = atoi( s );
- if ( (s = str_getline( &next )) == NULL ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= str2entry NULL (missing newline after id)\n",
- 0, 0, 0 );
- return( NULL );
- }
+ if( e == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= str2entry NULL (entry allocation failed)\n",
+ 0, 0, 0 );
+ return( NULL );
}
+ e->e_id = NOID;
+ e->e_private = NULL;
+
/* dn + attributes */
e->e_attrs = NULL;
vals[0] = &bval;
vals[1] = NULL;
ptype[0] = '\0';
- while ( (s = str_getline( &next )) != NULL ) {
+ while ( (s = ldif_getline( &next )) != NULL ) {
if ( *s == '\n' || *s == '\0' ) {
break;
}
- if ( str_parse_line( s, &type, &value, &vlen ) != 0 ) {
+ if ( ldif_parse_line( s, &type, &value, &vlen ) != 0 ) {
Debug( LDAP_DEBUG_TRACE,
"<= str2entry NULL (parse_line)\n", 0, 0, 0 );
continue;
maxvals = 0;
a = NULL;
}
+
if ( strcasecmp( type, "dn" ) == 0 ) {
+ free( type );
+
if ( e->e_dn != NULL ) {
Debug( LDAP_DEBUG_ANY,
- "str2entry: entry %d has multiple dns \"%s\" and \"%s\" (second ignored)\n",
- e->e_id, e->e_dn, value );
+ "str2entry: entry %ld has multiple dns \"%s\" and \"%s\" (second ignored)\n",
+ e->e_id, e->e_dn,
+ value != NULL ? value : NULL );
+ if( value != NULL ) free( value );
continue;
}
- e->e_dn = strdup( value );
+ e->e_dn = value != NULL ? value : ch_strdup( "" );
+
+ if ( e->e_ndn != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "str2entry: entry %ld already has a normalized dn \"%s\" for \"%s\" (first ignored)\n",
+ e->e_id, e->e_ndn,
+ value != NULL ? value : NULL );
+ free( e->e_ndn );
+ }
+ e->e_ndn = ch_strdup( e->e_dn );
+ (void) dn_normalize_case( e->e_ndn );
continue;
}
!= 0 ) {
Debug( LDAP_DEBUG_TRACE,
"<= str2entry NULL (attr_merge)\n", 0, 0, 0 );
+ entry_free( e );
+ free( value );
+ free( type );
return( NULL );
}
+
+ free( value );
+ free( type );
nvals++;
}
/* check to make sure there was a dn: line */
if ( e->e_dn == NULL ) {
- Debug( LDAP_DEBUG_ANY, "str2entry: entry %d has no dn\n",
+ Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n",
e->e_id, 0, 0 );
entry_free( e );
return( NULL );
}
- Debug( LDAP_DEBUG_TRACE, "<= str2entry 0x%x\n", e, 0, 0 );
+ if ( e->e_ndn == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "str2entry: entry %ld (\"%s\") has no normalized dn\n",
+ e->e_id, e->e_dn, 0 );
+ entry_free( e );
+ return( NULL );
+ }
+
+ Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> %ld (0x%lx)\n",
+ e->e_dn, e->e_id, (unsigned long)e );
+
return( e );
}
char *
entry2str(
Entry *e,
- int *len,
- int printid
-)
+ int *len )
{
Attribute *a;
struct berval *bv;
ecur = ebuf;
- if ( printid ) {
- /* id + newline */
- MAKE_SPACE( 10 );
- sprintf( (char *) ecur, "%ld\n", e->e_id );
- ecur = (unsigned char *) strchr( (char *) ecur, '\0' );
- }
-
/* put the dn */
if ( e->e_dn != NULL ) {
/* put "dn: <dn>" */
tmplen = strlen( e->e_dn );
MAKE_SPACE( LDIF_SIZE_NEEDED( 2, tmplen ));
- put_type_and_value( (char **) &ecur, "dn", e->e_dn, tmplen );
+ ldif_sput( (char **) &ecur, LDIF_PUT_VALUE, "dn", e->e_dn, tmplen );
}
/* put the attributes */
bv = a->a_vals[i];
tmplen = strlen( a->a_type );
MAKE_SPACE( LDIF_SIZE_NEEDED( tmplen, bv->bv_len ));
- put_type_and_value( (char **) &ecur, a->a_type,
+ ldif_sput( (char **) &ecur, LDIF_PUT_VALUE, a->a_type,
bv->bv_val, bv->bv_len );
}
}
void
entry_free( Entry *e )
{
- int i;
Attribute *a, *next;
if ( e->e_dn != NULL ) {
free( e->e_dn );
+ e->e_dn = NULL;
+ }
+ if ( e->e_ndn != NULL ) {
+ free( e->e_ndn );
+ e->e_ndn = NULL;
}
for ( a = e->e_attrs; a != NULL; a = next ) {
next = a->a_next;
attr_free( a );
}
+ e->e_attrs = NULL;
+ e->e_private = NULL;
free( e );
}
+
+/*
+ * These routines are used only by Backend.
+ *
+ * the Entry has three entry points (ways to find things):
+ *
+ * by entry e.g., if you already have an entry from the cache
+ * and want to delete it. (really by entry ptr)
+ * by dn e.g., when looking for the base object of a search
+ * by id e.g., for search candidates
+ *
+ * these correspond to three different avl trees that are maintained.
+ */
+
+int
+entry_cmp( Entry *e1, Entry *e2 )
+{
+ return( e1 < e2 ? -1 : (e1 > e2 ? 1 : 0) );
+}
+
+int
+entry_dn_cmp( Entry *e1, Entry *e2 )
+{
+ /* compare their normalized UPPERCASED dn's */
+ return( strcmp( e1->e_ndn, e2->e_ndn ) );
+}
+
+int
+entry_id_cmp( Entry *e1, Entry *e2 )
+{
+ return( e1->e_id < e2->e_id ? -1 : (e1->e_id > e2->e_id ? 1 : 0) );
+}
+
/* filter.c - routines for parsing and dealing with filters */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-static int get_filter_list();
-static int get_substring_filter();
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
-extern int get_ava();
-extern char *ch_malloc();
-extern char *ch_realloc();
+static int get_filter_list(Connection *conn, BerElement *ber, Filter **f, char **fstr);
+static int get_substring_filter(Connection *conn, BerElement *ber, Filter *f, char **fstr);
int
get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr )
{
- unsigned long tag, len;
+ ber_len_t len;
int err;
Filter *f;
char *ftmp;
* lessOrEqual [6] AttributeValueAssertion,
* present [7] AttributeType,,
* approxMatch [8] AttributeValueAssertion
+ * extensibleMatch [9] MatchingRuleAssertion
* }
*
* SubstringFilter ::= SEQUENCE {
* final [2] IA5String
* }
* }
+ *
+ * MatchingRuleAssertion ::= SEQUENCE {
+ * matchingRule [1] MatchingRuleId OPTIONAL,
+ * type [2] AttributeDescription OPTIONAL,
+ * matchValue [3] AssertionValue,
+ * dnAttributes [4] BOOLEAN DEFAULT FALSE
+ * }
+ *
*/
f = (Filter *) ch_malloc( sizeof(Filter) );
- *filt = f;
f->f_next = NULL;
- err = 0;
+ err = LDAP_SUCCESS;
*fstr = NULL;
f->f_choice = ber_peek_tag( ber, &len );
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- switch ( f->f_choice ) {
- case LDAP_FILTER_EQUALITY:
- case LDAP_FILTER_GE:
- case LDAP_FILTER_LE:
- case LDAP_FILTER_PRESENT:
- case LDAP_FILTER_PRESENT_30:
- case LDAP_FILTER_APPROX:
- (void) ber_skip_tag( ber, &len );
- if ( f->f_choice == LDAP_FILTER_PRESENT_30 ) {
- f->f_choice = LDAP_FILTER_PRESENT;
- }
- break;
- default:
- break;
- }
- }
-#endif
+
switch ( f->f_choice ) {
case LDAP_FILTER_EQUALITY:
Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
- if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
+ if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) {
*fstr = ch_malloc(4 + strlen( f->f_avtype ) +
f->f_avvalue.bv_len);
sprintf( *fstr, "(%s=%s)", f->f_avtype,
case LDAP_FILTER_GE:
Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
- if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
+ if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) {
*fstr = ch_malloc(5 + strlen( f->f_avtype ) +
f->f_avvalue.bv_len);
sprintf( *fstr, "(%s>=%s)", f->f_avtype,
case LDAP_FILTER_LE:
Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
- if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
+ if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) {
*fstr = ch_malloc(5 + strlen( f->f_avtype ) +
f->f_avvalue.bv_len);
sprintf( *fstr, "(%s<=%s)", f->f_avtype,
case LDAP_FILTER_PRESENT:
Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
if ( ber_scanf( ber, "a", &f->f_type ) == LBER_ERROR ) {
- err = LDAP_PROTOCOL_ERROR;
+ err = -1;
} else {
err = LDAP_SUCCESS;
attr_normalize( f->f_type );
case LDAP_FILTER_APPROX:
Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
- if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
+ if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) {
*fstr = ch_malloc(5 + strlen( f->f_avtype ) +
f->f_avvalue.bv_len);
sprintf( *fstr, "(%s~=%s)", f->f_avtype,
case LDAP_FILTER_AND:
Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
if ( (err = get_filter_list( conn, ber, &f->f_and, &ftmp ))
- == 0 ) {
+ == LDAP_SUCCESS ) {
+ if (ftmp == NULL) ftmp = ch_strdup("");
*fstr = ch_malloc( 4 + strlen( ftmp ) );
sprintf( *fstr, "(&%s)", ftmp );
free( ftmp );
case LDAP_FILTER_OR:
Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
if ( (err = get_filter_list( conn, ber, &f->f_or, &ftmp ))
- == 0 ) {
+ == LDAP_SUCCESS ) {
+ if (ftmp == NULL) ftmp = ch_strdup("");
*fstr = ch_malloc( 4 + strlen( ftmp ) );
sprintf( *fstr, "(|%s)", ftmp );
free( ftmp );
case LDAP_FILTER_NOT:
Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
(void) ber_skip_tag( ber, &len );
- if ( (err = get_filter( conn, ber, &f->f_not, &ftmp )) == 0 ) {
+ if ( (err = get_filter( conn, ber, &f->f_not, &ftmp )) == LDAP_SUCCESS ) {
+ if (ftmp == NULL) ftmp = ch_strdup("");
*fstr = ch_malloc( 4 + strlen( ftmp ) );
sprintf( *fstr, "(!%s)", ftmp );
free( ftmp );
}
break;
+ case LBER_DEFAULT:
+ Debug( LDAP_DEBUG_ANY, "decoding filter error\n",
+ 0, 0, 0 );
+ err = -1;
+ break;
+
default:
- Debug( LDAP_DEBUG_ANY, "unknown filter type %d\n", f->f_choice,
- 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n",
+ f->f_choice, 0, 0 );
err = LDAP_PROTOCOL_ERROR;
break;
}
- if ( err != 0 ) {
+ if ( err != LDAP_SUCCESS ) {
free( (char *) f );
if ( *fstr != NULL ) {
free( *fstr );
}
+ } else {
+ *filt = f;
}
Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
{
Filter **new;
int err;
- unsigned long tag, len;
+ ber_tag_t tag;
+ ber_len_t len;
char *last, *ftmp;
Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- (void) ber_skip_tag( ber, &len );
- }
-#endif
*fstr = NULL;
new = f;
for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
- tag = ber_next_element( ber, &len, last ) ) {
- if ( (err = get_filter( conn, ber, new, &ftmp )) != 0 )
+ tag = ber_next_element( ber, &len, last ) )
+ {
+ if ( (err = get_filter( conn, ber, new, &ftmp )) != LDAP_SUCCESS )
return( err );
if ( *fstr == NULL ) {
*fstr = ftmp;
*new = NULL;
Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
- return( 0 );
+ return( LDAP_SUCCESS );
}
static int
char **fstr
)
{
- unsigned long tag, len, rc;
+ ber_tag_t tag;
+ ber_len_t len;
+ ber_tag_t rc;
char *val, *last;
int syntax;
Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- (void) ber_skip_tag( ber, &len );
- }
-#endif
- if ( ber_scanf( ber, "{a", &f->f_sub_type ) == LBER_ERROR ) {
- return( LDAP_PROTOCOL_ERROR );
+ if ( ber_scanf( ber, "{a" /*}*/, &f->f_sub_type ) == LBER_ERROR ) {
+ return( -1 );
}
attr_normalize( f->f_sub_type );
syntax = attr_syntax( f->f_sub_type );
*fstr = ch_malloc( strlen( f->f_sub_type ) + 3 );
sprintf( *fstr, "(%s=", f->f_sub_type );
for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
- tag = ber_next_element( ber, &len, last ) ) {
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- rc = ber_scanf( ber, "{a}", &val );
- } else
-#endif
- rc = ber_scanf( ber, "a", &val );
+ tag = ber_next_element( ber, &len, last ) )
+ {
+ rc = ber_scanf( ber, "a", &val );
if ( rc == LBER_ERROR ) {
- return( LDAP_PROTOCOL_ERROR );
+ return( -1 );
}
if ( val == NULL || *val == '\0' ) {
if ( val != NULL ) {
value_normalize( val, syntax );
switch ( tag ) {
-#ifdef COMPAT30
- case LDAP_SUBSTRING_INITIAL_30:
-#endif
case LDAP_SUBSTRING_INITIAL:
Debug( LDAP_DEBUG_FILTER, " INITIAL\n", 0, 0, 0 );
if ( f->f_sub_initial != NULL ) {
strcat( *fstr, val );
break;
-#ifdef COMPAT30
- case LDAP_SUBSTRING_ANY_30:
-#endif
case LDAP_SUBSTRING_ANY:
Debug( LDAP_DEBUG_FILTER, " ANY\n", 0, 0, 0 );
charray_add( &f->f_sub_any, val );
strcat( *fstr, val );
break;
-#ifdef COMPAT30
- case LDAP_SUBSTRING_FINAL_30:
-#endif
case LDAP_SUBSTRING_FINAL:
Debug( LDAP_DEBUG_FILTER, " FINAL\n", 0, 0, 0 );
if ( f->f_sub_final != NULL ) {
strcat( *fstr, ")" );
Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
- return( 0 );
+ return( LDAP_SUCCESS );
}
void
break;
default:
- Debug( LDAP_DEBUG_ANY, "unknown filter type %d\n", f->f_choice,
- 0, 0 );
+ Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n",
+ f->f_choice, 0, 0 );
break;
}
free( f );
Filter *p;
if ( f == NULL ) {
- printf( "NULL" );
+ fprintf( stderr, "NULL" );
}
switch ( f->f_choice ) {
case LDAP_FILTER_EQUALITY:
- printf( "(%s=%s)", f->f_ava.ava_type,
+ fprintf( stderr, "(%s=%s)", f->f_ava.ava_type,
f->f_ava.ava_value.bv_val );
break;
case LDAP_FILTER_GE:
- printf( "(%s>=%s)", f->f_ava.ava_type,
+ fprintf( stderr, "(%s>=%s)", f->f_ava.ava_type,
f->f_ava.ava_value.bv_val );
break;
case LDAP_FILTER_LE:
- printf( "(%s<=%s)", f->f_ava.ava_type,
+ fprintf( stderr, "(%s<=%s)", f->f_ava.ava_type,
f->f_ava.ava_value.bv_val );
break;
case LDAP_FILTER_APPROX:
- printf( "(%s~=%s)", f->f_ava.ava_type,
+ fprintf( stderr, "(%s~=%s)", f->f_ava.ava_type,
f->f_ava.ava_value.bv_val );
break;
case LDAP_FILTER_SUBSTRINGS:
- printf( "(%s=", f->f_sub_type );
+ fprintf( stderr, "(%s=", f->f_sub_type );
if ( f->f_sub_initial != NULL ) {
- printf( "%s", f->f_sub_initial );
+ fprintf( stderr, "%s", f->f_sub_initial );
}
if ( f->f_sub_any != NULL ) {
for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
- printf( "*%s", f->f_sub_any[i] );
+ fprintf( stderr, "*%s", f->f_sub_any[i] );
}
}
charray_free( f->f_sub_any );
if ( f->f_sub_final != NULL ) {
- printf( "*%s", f->f_sub_final );
+ fprintf( stderr, "*%s", f->f_sub_final );
}
break;
case LDAP_FILTER_PRESENT:
- printf( "%s=*", f->f_type );
+ fprintf( stderr, "%s=*", f->f_type );
break;
case LDAP_FILTER_AND:
case LDAP_FILTER_OR:
case LDAP_FILTER_NOT:
- printf( "(%c", f->f_choice == LDAP_FILTER_AND ? '&' :
+ fprintf( stderr, "(%c", f->f_choice == LDAP_FILTER_AND ? '&' :
f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
for ( p = f->f_list; p != NULL; p = p->f_next ) {
filter_print( p );
}
- printf( ")" );
+ fprintf( stderr, ")" );
break;
default:
- printf( "unknown type %d", f->f_choice );
+ fprintf( stderr, "unknown type %lu", f->f_choice );
break;
}
}
/* filterentry.c - apply a filter to an entry */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#ifdef sunos5
-#include "regexpr.h"
-#else
-#include "regex.h"
-#endif
-#include "slap.h"
-extern Attribute *attr_find();
-extern char *first_word();
-extern char *next_word();
-extern char *phonetic();
-extern char *re_comp();
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/regex.h>
-#ifndef sunos5
-extern pthread_mutex_t regex_mutex;
-#endif
+#include "slap.h"
-static int test_filter_list();
-static int test_substring_filter();
-static int test_ava_filter();
-static int test_approx_filter();
-static int test_presence_filter();
+static int test_filter_list(Backend *be, Connection *conn, Operation *op, Entry *e, Filter *flist, int ftype);
+static int test_substring_filter(Backend *be, Connection *conn, Operation *op, Entry *e, Filter *f);
+static int test_ava_filter(Backend *be, Connection *conn, Operation *op, Entry *e, Ava *ava, int type);
+static int test_approx_filter(Backend *be, Connection *conn, Operation *op, Entry *e, Ava *ava);
+static int test_presence_filter(Backend *be, Connection *conn, Operation *op, Entry *e, char *type);
/*
* test_filter - test a filter against a single entry.
break;
default:
- Debug( LDAP_DEBUG_ANY, " unknown filter type %d\n",
+ Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n",
f->f_choice, 0, 0 );
rc = -1;
}
int i, rc;
Attribute *a;
- if ( be != NULL && ! access_allowed( be, conn, op, e, ava->ava_type,
- &ava->ava_value, op->o_dn, ACL_SEARCH ) ) {
+ if ( be != NULL && ! access_allowed( be, conn, op, e,
+ ava->ava_type, &ava->ava_value, ACL_SEARCH ) )
+ {
return( -2 );
}
break;
case LDAP_FILTER_GE:
- if ( rc > 0 ) {
+ if ( rc >= 0 ) {
return( 0 );
}
break;
case LDAP_FILTER_LE:
- if ( rc < 0 ) {
+ if ( rc <= 0 ) {
return( 0 );
}
break;
char *type
)
{
- if ( be != NULL && ! access_allowed( be, conn, op, e, type, NULL,
- op->o_dn, ACL_SEARCH ) ) {
+ if ( be != NULL && ! access_allowed( be, conn, op, e,
+ type, NULL, ACL_SEARCH ) )
+ {
return( -2 );
}
)
{
char *w1, *w2, *c1, *c2;
- int i, rc, match;
+ int i;
Attribute *a;
- if ( be != NULL && ! access_allowed( be, conn, op, e, ava->ava_type,
- NULL, op->o_dn, ACL_SEARCH ) ) {
+ if ( be != NULL && ! access_allowed( be, conn, op, e,
+ ava->ava_type, NULL, ACL_SEARCH ) )
+ {
return( -2 );
}
w2 = next_word( w2 ) ) {
c2 = phonetic( w2 );
if ( strcmp( c1, c2 ) == 0 ) {
+ free( c2 );
break;
}
+ free( c2 );
}
free( c1 );
- free( c2 );
/*
* if we stopped because we ran out of words
int ftype
)
{
- int rc, nomatch;
+ int nomatch;
Filter *f;
Debug( LDAP_DEBUG_FILTER, "=> test_filter_list\n", 0, 0, 0 );
char pat[BUFSIZ];
char buf[BUFSIZ];
struct berval *val;
+ regex_t re;
Debug( LDAP_DEBUG_FILTER, "begin test_substring_filter\n", 0, 0, 0 );
- if ( be != NULL && ! access_allowed( be, conn, op, e, f->f_sub_type,
- NULL, op->o_dn, ACL_SEARCH ) ) {
+ if ( be != NULL && ! access_allowed( be, conn, op, e,
+ f->f_sub_type, NULL, ACL_SEARCH ) )
+ {
return( -2 );
}
}
/* compile the regex */
-#ifdef sunos5
- if ( (p = compile( pat, NULL, NULL )) == NULL ) {
- Debug( LDAP_DEBUG_ANY, "compile failed (%s)\n", p, 0, 0 );
- return( -1 );
- }
-#else /* sunos5 */
- pthread_mutex_lock( ®ex_mutex );
- if ( (p = re_comp( pat )) != 0 ) {
- Debug( LDAP_DEBUG_ANY, "re_comp failed (%s)\n", p, 0, 0 );
- pthread_mutex_unlock( ®ex_mutex );
+ Debug( LDAP_DEBUG_FILTER, "test_substring_filter: regcomp pat: %s\n",
+ pat, 0, 0 );
+ if ((rc = regcomp(&re, pat, 0))) {
+ char error[512];
+
+ regerror(rc, &re, error, sizeof(error));
+ Debug( LDAP_DEBUG_ANY, "regcomp failed (%s) %s\n",
+ p, error, 0 );
return( -1 );
}
-#endif /* sunos5 */
/* for each value in the attribute see if regex matches */
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
}
value_normalize( realval, a->a_syntax );
-#ifdef sunos5
- rc = step( realval, p );
-#else /* sunos5 */
- rc = re_exec( realval );
-#endif /* sunos5 */
+ rc = !regexec(&re, realval, 0, NULL, 0);
if ( tmp != NULL ) {
free( tmp );
}
if ( rc == 1 ) {
-#ifdef sunos5
- free( p );
-#else /* sunos5 */
- pthread_mutex_unlock( ®ex_mutex );
-#endif /* sunos5 */
+ regfree(&re);
return( 0 );
}
}
-#ifdef sunos5
- free( p );
-#else /* sunos5 */
- pthread_mutex_unlock( ®ex_mutex );
-#endif /* sunos5 */
+
+ regfree(&re);
Debug( LDAP_DEBUG_FILTER, "end test_substring_filter 1\n", 0, 0, 0 );
return( 1 );
/* init.c - initialize various things */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
-#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include "slap.h"
-extern pthread_mutex_t active_threads_mutex;
-extern pthread_mutex_t new_conn_mutex;
-extern pthread_mutex_t currenttime_mutex;
-extern pthread_mutex_t entry2str_mutex;
-extern pthread_mutex_t replog_mutex;
-extern pthread_mutex_t ops_mutex;
-extern pthread_mutex_t num_sent_mutex;
-#ifndef sunos5
-extern pthread_mutex_t regex_mutex;
+/*
+ * read-only global variables or variables only written by the listener
+ * thread (after they are initialized) - no need to protect them with a mutex.
+ */
+int slap_debug = 0;
+
+#ifdef LDAP_DEBUG
+int ldap_syslog = LDAP_DEBUG_STATS;
+#else
+int ldap_syslog;
#endif
-init()
+int ldap_syslog_level = LOG_DEBUG;
+struct berval **default_referral = NULL;
+int g_argc;
+char **g_argv;
+
+/*
+ * global variables that need mutex protection
+ */
+int active_threads;
+ldap_pvt_thread_mutex_t active_threads_mutex;
+ldap_pvt_thread_cond_t active_threads_cond;
+
+ldap_pvt_thread_mutex_t gmtime_mutex;
+#ifdef SLAPD_CRYPT
+ldap_pvt_thread_mutex_t crypt_mutex;
+#endif
+
+int num_conns;
+long num_ops_initiated;
+long num_ops_completed;
+ldap_pvt_thread_mutex_t num_ops_mutex;
+
+long num_entries_sent;
+long num_refs_sent;
+long num_bytes_sent;
+long num_pdu_sent;
+ldap_pvt_thread_mutex_t num_sent_mutex;
+/*
+ * these mutexes must be used when calling the entry2str()
+ * routine since it returns a pointer to static data.
+ */
+ldap_pvt_thread_mutex_t entry2str_mutex;
+ldap_pvt_thread_mutex_t replog_mutex;
+
+static char* slap_name;
+int slapMode = SLAP_UNDEFINED_MODE;
+
+static ldap_pvt_thread_mutex_t currenttime_mutex;
+
+int
+slap_init( int mode, char *name )
{
- pthread_mutex_init( &active_threads_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &new_conn_mutex, pthread_mutexattr_default );
- pthread_mutex_init( ¤ttime_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &entry2str_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &replog_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &ops_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &num_sent_mutex, pthread_mutexattr_default );
-#ifndef sunos5
- pthread_mutex_init( ®ex_mutex, pthread_mutexattr_default );
+ int rc;
+
+ assert( mode );
+
+ if( slapMode != SLAP_UNDEFINED_MODE ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s init: init called twice (old=%d, new=%d)\n",
+ name, slapMode, mode );
+ return 1;
+ }
+
+ slapMode = mode;
+
+ switch ( slapMode & SLAP_MODE ) {
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+ Debug( LDAP_DEBUG_TRACE,
+ "%s init: initiated %s.\n",
+ name, ( mode & SLAP_TOOL_MODE ) ? "tool" : "server", 0 );
+
+ slap_name = name;
+
+ (void) ldap_pvt_thread_initialize();
+
+ ldap_pvt_thread_mutex_init( &active_threads_mutex );
+ ldap_pvt_thread_cond_init( &active_threads_cond );
+
+ ldap_pvt_thread_mutex_init( ¤ttime_mutex );
+ ldap_pvt_thread_mutex_init( &entry2str_mutex );
+ ldap_pvt_thread_mutex_init( &replog_mutex );
+ ldap_pvt_thread_mutex_init( &num_ops_mutex );
+ ldap_pvt_thread_mutex_init( &num_sent_mutex );
+
+ ldap_pvt_thread_mutex_init( &gmtime_mutex );
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_init( &crypt_mutex );
#endif
+
+ rc = backend_init( );
+ break;
+
+ default:
+ Debug( LDAP_DEBUG_ANY,
+ "%s init: undefined mode (%d).\n", name, mode, 0 );
+ rc = 1;
+ break;
+ }
+
+ return rc;
+}
+
+int slap_startup( Backend *be )
+{
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "%s startup: initiated.\n",
+ slap_name, 0, 0 );
+
+ rc = backend_startup( be );
+
+ if( rc == 0 ) {
+ rc = sasl_init();
+ }
+
+ return rc;
+}
+
+int slap_shutdown( Backend *be )
+{
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "%s shutdown: initiated\n",
+ slap_name, 0, 0 );
+
+ sasl_destroy();
+
+ /* let backends do whatever cleanup they need to do */
+ rc = backend_shutdown( be );
+
+ return rc;
+}
+
+int slap_destroy(void)
+{
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "%s shutdown: freeing system resources.\n",
+ slap_name, 0, 0 );
+
+ rc = backend_destroy();
+
+ entry_destroy();
+
+ ldap_pvt_thread_destroy();
+
+ /* should destory the above mutex */
+ return rc;
+}
+
+/* should create a utils.c for these */
+time_t slap_get_time(void)
+{
+ time_t t;
+ ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
+ time( &t );
+ ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ return t;
}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="libslapd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=libslapd - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libslapd.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libslapd.mak" CFG="libslapd - Win32 Single Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libslapd - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "libslapd - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "libslapd - Win32 Single Debug" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE "libslapd - Win32 Single Release" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF "$(CFG)" == "libslapd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "libslapd"
+# PROP BASE Intermediate_Dir "libslapd"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release\libslapd"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "libslapd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "libslap0"
+# PROP BASE Intermediate_Dir "libslap0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug\libslapd"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "libslapd - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "libslap1"
+# PROP BASE Intermediate_Dir "libslap1"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SDebug"
+# PROP Intermediate_Dir "SDebug\libslapd"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "libslapd - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "libslap2"
+# PROP BASE Intermediate_Dir "libslap2"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "SRelease"
+# PROP Intermediate_Dir "SRelease\libslapd"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "libslapd - Win32 Release"
+# Name "libslapd - Win32 Debug"
+# Name "libslapd - Win32 Single Debug"
+# Name "libslapd - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\abandon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\acl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\aclparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\add.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\attr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ava.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\backend.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bind.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ch_malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\charray.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\compare.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\config.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\configinfo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\connection.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\controls.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\daemon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\entry.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\extended.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\filter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\filterentry.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modify.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modrdn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\monitor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\operation.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\phonetic.c
+# End Source File
+# Begin Source File
+
+SOURCE=".\proto-slap.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\repl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\root_dse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sasl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\schema.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\schemaparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\search.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\str2filter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\suffixalias.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\unbind.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\user.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\value.c
+# End Source File
+# End Target
+# End Project
/* lock.c - routines to open and apply an advisory lock to a file */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
-#include <stdio.h>
-#include <sys/time.h>
-#include <sys/types.h>
#include "portable.h"
-#ifdef USE_LOCKF
-#include <unistd.h>
-#endif
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
-#include <sys/socket.h>
+#endif
#include "slap.h"
FILE *
}
/* acquire the lock */
-#ifdef USE_LOCKF
- while ( lockf( fileno( *lfp ), F_LOCK, 0 ) != 0 ) {
-#else
- while ( flock( fileno( *lfp ), LOCK_EX ) != 0 ) {
-#endif
- ; /* NULL */
- }
+ ldap_lockf( fileno(*lfp) );
/* open the log file */
if ( (fp = fopen( fname, type )) == NULL ) {
Debug( LDAP_DEBUG_ANY, "could not open \"%s\"\n", fname, 0, 0 );
-#ifdef USE_LOCKF
- lockf( fileno( *lfp ), F_ULOCK, 0 );
-#else
- flock( fileno( *lfp ), LOCK_UN );
-#endif
+ ldap_unlockf( fileno(*lfp) );
+ fclose( *lfp );
+ *lfp = NULL;
return( NULL );
}
lock_fclose( FILE *fp, FILE *lfp )
{
/* unlock */
-#ifdef USE_LOCKF
- lockf( fileno( lfp ), F_ULOCK, 0 );
-#else
- flock( fileno( lfp ), LOCK_UN );
-#endif
+ ldap_unlockf( fileno(lfp) );
fclose( lfp );
return( fclose( fp ) );
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/signal.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+#include <ac/signal.h>
+#include <ac/errno.h>
+
+#include "ldap_defaults.h"
#include "slap.h"
-#include "ldapconfig.h"
+#include "lutil.h"
-extern void daemon();
-extern int lber_debug;
+#ifdef LDAP_SIGCHLD
+static RETSIGTYPE wait4child( int sig );
+#endif
-extern char Versionstr[];
+#ifdef HAVE_WINSOCK
+#define MAIN_RETURN(x) return
+struct sockaddr_in bind_addr;
-/*
- * read-only global variables or variables only written by the listener
- * thread (after they are initialized) - no need to protect them with a mutex.
- */
-int ldap_debug;
-#ifdef LDAP_DEBUG
-int ldap_syslog = LDAP_DEBUG_STATS;
+/* in nt_main.c */
+extern SERVICE_STATUS SLAPDServiceStatus;
+extern SERVICE_STATUS_HANDLE hSLAPDServiceStatus;
+extern ldap_pvt_thread_cond_t started_event, stopped_event;
+extern int is_NT_Service;
+
+void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *urls );
+void LogSlapdStoppedEvent( char *svc );
+
+void CommenceStartupProcessing( LPCTSTR serviceName,
+ void(*stopper)(int));
+void ReportSlapdShutdownComplete( void );
+void *getRegParam( char *svc, char *value );
+
+#define SERVICE_EXIT( e, n ) \
+ if ( is_NT_Service ) \
+{ \
+ SLAPDServiceStatus.dwWin32ExitCode = e; \
+ SLAPDServiceStatus.dwServiceSpecificExitCode = n; \
+}
#else
-int ldap_syslog;
-#endif
-int ldap_syslog_level = LOG_DEBUG;
-int udp;
-int slapd_shutdown;
-char *default_referral;
-char *configfile;
-time_t starttime;
-pthread_t listener_tid;
-int g_argc;
-char **g_argv;
-/*
- * global variables that need mutex protection
- */
-time_t currenttime;
-pthread_mutex_t currenttime_mutex;
-int active_threads;
-pthread_mutex_t active_threads_mutex;
-pthread_mutex_t new_conn_mutex;
-long ops_initiated;
-long ops_completed;
-int num_conns;
-pthread_mutex_t ops_mutex;
-long num_entries_sent;
-long num_bytes_sent;
-pthread_mutex_t num_sent_mutex;
+#define SERVICE_EXIT( e, n )
+#define MAIN_RETURN(x) return(x)
+#endif
+
/*
- * these mutexes must be used when calling the entry2str()
- * routine since it returns a pointer to static data.
+ * when more than one slapd is running on one machine, each one might have
+ * it's own LOCAL for syslogging and must have its own pid/args files
*/
-pthread_mutex_t entry2str_mutex;
-pthread_mutex_t replog_mutex;
-#ifndef sunos5
-pthread_mutex_t regex_mutex;
+
+#ifndef HAVE_MKVERSION
+const char Versionstr[] =
+ OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Server (slapd)";
#endif
-static
-usage( name )
- char *name;
+#ifdef LOG_LOCAL4
+
+#define DEFAULT_SYSLOG_USER LOG_LOCAL4
+
+typedef struct _str2intDispatch {
+ char *stringVal;
+ int abbr;
+ int intVal;
+} STRDISP, *STRDISP_P;
+
+
+/* table to compute syslog-options to integer */
+static STRDISP syslog_types[] = {
+ { "LOCAL0", 6, LOG_LOCAL0 },
+ { "LOCAL1", 6, LOG_LOCAL1 },
+ { "LOCAL2", 6, LOG_LOCAL2 },
+ { "LOCAL3", 6, LOG_LOCAL3 },
+ { "LOCAL4", 6, LOG_LOCAL4 },
+ { "LOCAL5", 6, LOG_LOCAL5 },
+ { "LOCAL6", 6, LOG_LOCAL6 },
+ { "LOCAL7", 6, LOG_LOCAL7 },
+ { NULL }
+};
+
+static int cnvt_str2int( char *, STRDISP_P, int );
+
+#endif /* LOG_LOCAL4 */
+
+
+static void
+usage( char *name )
{
- fprintf( stderr, "usage: %s [-d debuglevel] [-f configfile] [-p portnumber] [-s sysloglevel]\n", name );
+ fprintf( stderr,
+ "usage: %s options\n", name );
+ fprintf( stderr,
+#if LDAP_CONNECTIONLESS
+ "\t-c\t\tEnable (experimental) Connectionless LDAP\n"
+#endif
+ "\t-d level\tDebug Level" "\n"
+ "\t-f filename\tConfiguration File\n"
+#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
+ "\t-g group\tGroup (id or name) to ran as\n"
+#endif
+ "\t-h URLs\tList of URLs to serve\n"
+#ifdef LOG_LOCAL4
+ "\t-l sysloguser\tSyslog User (default: LOCAL4)\n"
+#endif
+#ifdef HAVE_WINSOCK
+ "\t-n NTserviceName\tNT service name\n"
+#endif
+
+ "\t-p port\tLDAP Port\n"
+#ifdef HAVE_TLS
+ "\t-P port\tLDAP over TLS Port\n"
+#endif
+ "\t-s level\tSyslog Level\n"
+#ifdef SLAPD_BDB2
+ "\t-t\t\tEnable BDB2 timing\n"
+#endif
+#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
+ "\t-u user\tUser (id or name) to ran as\n"
+#endif
+ );
}
-main( argc, argv )
- int argc;
- char **argv;
+#ifdef HAVE_WINSOCK
+void WINAPI ServiceMain( DWORD argc, LPTSTR *argv )
+#else
+int main( int argc, char **argv )
+#endif
{
int i;
- int inetd = 0;
- int port;
- char *myname;
- Backend *be = NULL;
- FILE *fp = NULL;
- extern char *optarg;
-
- configfile = SLAPD_DEFAULT_CONFIGFILE;
- port = LDAP_PORT;
+ int rc;
+ char *urls = NULL;
+#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
+ char *username = NULL;
+ char *groupname = NULL;
+#endif
+#ifdef LOG_LOCAL4
+ int syslogUser = DEFAULT_SYSLOG_USER;
+#endif
+#ifdef HAVE_WINSOCK
+ char *NTservice = SERVICE_NAME;
+ char *configfile = ".\\slapd.conf";
+#else
+ char *configfile = SLAPD_DEFAULT_CONFIGFILE;
+#endif
+ char *serverName;
+ int serverMode = SLAP_SERVER_MODE;
+
+ int port = LDAP_PORT;
+#ifdef HAVE_TLS
+ int tls_port = LDAPS_PORT;
+#else
+ int tls_port = 0;
+#endif
+
+#ifdef CSRIMALLOC
+ FILE *leakfile;
+ if( ( leakfile = fopen( "slapd.leak", "w" )) == NULL ) {
+ leakfile = stderr;
+ }
+#endif
+
g_argc = argc;
g_argv = argv;
- while ( (i = getopt( argc, argv, "d:f:ip:s:u" )) != EOF ) {
+#ifdef HAVE_WINSOCK
+ {
+ int *i;
+ char *newConfigFile;
+ if ( is_NT_Service ) CommenceStartupProcessing( NTservice, slap_set_shutdown );
+ i = (int*)getRegParam( NULL, "Port" );
+ if ( i != NULL )
+ {
+ port = *i;
+ Debug ( LDAP_DEBUG_ANY, "new port from registry is: %d\n", port, 0, 0 );
+ }
+#ifdef HAVE_TLS
+ i = (int*)getRegParam( NULL, "TLSPort" );
+ if ( i != NULL )
+ {
+ tls_port = *i;
+ Debug ( LDAP_DEBUG_ANY, "new TLS port from registry is: %d\n", tls_port, 0, 0 );
+ }
+#endif
+ i = (int*)getRegParam( NULL, "DebugLevel" );
+ if ( i != NULL )
+ {
+ slap_debug = *i;
+ Debug( LDAP_DEBUG_ANY, "new debug level from registry is: %d\n", slap_debug, 0, 0 );
+ }
+ newConfigFile = (char*)getRegParam( NULL, "ConfigFile" );
+ if ( newConfigFile != NULL )
+ {
+ configfile = newConfigFile;
+ Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile, 0, 0 );
+ }
+ }
+#endif
+
+ while ( (i = getopt( argc, argv,
+ "d:f:h:p:s:"
+#ifdef LOG_LOCAL4
+ "l:"
+#endif
+#ifdef SLAPD_BDB2
+ "t"
+#endif
+#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
+ "u:g:"
+#endif
+#ifdef LDAP_CONNECTIONLESS
+ "c"
+#endif
+#ifdef HAVE_WINSOCK
+ "n:"
+#endif
+#ifdef HAVE_TLS
+ "P:"
+#endif
+ )) != EOF ) {
switch ( i ) {
+ case 'h': /* listen URLs */
+ urls = ch_strdup( optarg );
+ break;
+
#ifdef LDAP_DEBUG
case 'd': /* turn on debugging */
- if ( optarg[0] == '?' ) {
- printf( "Debug levels:\n" );
- printf( "\tLDAP_DEBUG_TRACE\t%d\n",
- LDAP_DEBUG_TRACE );
- printf( "\tLDAP_DEBUG_PACKETS\t%d\n",
- LDAP_DEBUG_PACKETS );
- printf( "\tLDAP_DEBUG_ARGS\t\t%d\n",
- LDAP_DEBUG_ARGS );
- printf( "\tLDAP_DEBUG_CONNS\t%d\n",
- LDAP_DEBUG_CONNS );
- printf( "\tLDAP_DEBUG_BER\t\t%d\n",
- LDAP_DEBUG_BER );
- printf( "\tLDAP_DEBUG_FILTER\t%d\n",
- LDAP_DEBUG_FILTER );
- printf( "\tLDAP_DEBUG_CONFIG\t%d\n",
- LDAP_DEBUG_CONFIG );
- printf( "\tLDAP_DEBUG_ACL\t\t%d\n",
- LDAP_DEBUG_ACL );
- printf( "\tLDAP_DEBUG_STATS\t\t%d\n",
- LDAP_DEBUG_STATS );
- printf( "\tLDAP_DEBUG_STATS2\t\t%d\n",
- LDAP_DEBUG_STATS2 );
- printf( "\tLDAP_DEBUG_SHELL\t\t%d\n",
- LDAP_DEBUG_SHELL );
- printf( "\tLDAP_DEBUG_PARSE\t\t%d\n",
- LDAP_DEBUG_PARSE );
- printf( "\tLDAP_DEBUG_ANY\t\t%d\n",
- LDAP_DEBUG_ANY );
- exit( 0 );
- } else {
- ldap_debug = atoi( optarg );
- lber_debug = (ldap_debug & LDAP_DEBUG_BER);
- }
+ slap_debug |= atoi( optarg );
break;
#else
case 'd': /* turn on debugging */
#endif
case 'f': /* read config file */
- configfile = strdup( optarg );
+ configfile = ch_strdup( optarg );
break;
- case 'i': /* run from inetd */
- inetd = 1;
- break;
+ case 'p': { /* port on which to listen */
+ int p = atoi( optarg );
+ if(! p ) {
+ fprintf(stderr, "-p %s must be numeric\n", optarg);
+ } else if( p < 0 || p >= 1<<16) {
+ fprintf(stderr, "-p %s invalid\n", optarg);
+ } else {
+ port = p;
+ }
+ } break;
- case 'p': /* port on which to listen */
- port = atoi( optarg );
- break;
+#ifdef HAVE_TLS
+ case 'P': { /* port on which to listen for TLS */
+ int p = atoi( optarg );
+ if(! p ) {
+ fprintf(stderr, "-P %s must be numeric\n", optarg);
+ } else if( p < 0 || p >= 1<<16) {
+ fprintf(stderr, "-P %s invalid\n", optarg);
+ } else {
+ tls_port = p;
+ }
+ } break;
+#endif
case 's': /* set syslog level */
ldap_syslog = atoi( optarg );
break;
- case 'u': /* do udp */
- udp = 1;
+#ifdef LOG_LOCAL4
+ case 'l': /* set syslog local user */
+ syslogUser = cnvt_str2int( optarg,
+ syslog_types, DEFAULT_SYSLOG_USER );
break;
+#endif
+#ifdef LDAP_CONNECTIONLESS
+ case 'c': /* do connectionless (udp) */
+ /* udp = 1; */
+ fprintf( stderr, "connectionless support not supported");
+ exit( EXIT_FAILURE );
+ break;
+#endif
+
+#ifdef SLAPD_BDB2
+ case 't': /* timed server */
+ serverMode |= SLAP_TIMED_MODE;
+ break;
+#endif
+
+#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
+ case 'u': /* user name */
+ if( username ) free(username);
+ username = ch_strdup( optarg );
+ break;
+
+ case 'g': /* group name */
+ if( groupname ) free(groupname);
+ groupname = ch_strdup( optarg );
+ break;
+#endif /* SETUID && GETUID */
+
+#ifdef HAVE_WINSOCK
+ case 'n': /* NT service name */
+ NTservice = ch_strdup( optarg );
+ break;
+#endif
default:
usage( argv[0] );
- exit( 1 );
+ rc = 1;
+ SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 );
+ goto stop;
}
}
+ ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
+ ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
+ ldif_debug = slap_debug;
+
Debug( LDAP_DEBUG_TRACE, "%s", Versionstr, 0, 0 );
- if ( (myname = strrchr( argv[0], '/' )) == NULL ) {
- myname = strdup( argv[0] );
+ if ( (serverName = strrchr( argv[0], *LDAP_DIRSEP )) == NULL ) {
+ serverName = ch_strdup( argv[0] );
} else {
- myname = strdup( myname + 1 );
+ serverName = ch_strdup( serverName + 1 );
}
- if ( ! inetd ) {
- /* pre-open config file before detach in case it is a relative path */
- fp = fopen( configfile, "r" );
- detach();
- }
#ifdef LOG_LOCAL4
- openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
+ openlog( serverName, OPENLOG_OPTIONS, syslogUser );
#else
- openlog( myname, OPENLOG_OPTIONS );
+ openlog( serverName, OPENLOG_OPTIONS );
+#endif
+
+ if( slapd_daemon_init( urls, port, tls_port ) != 0 ) {
+ rc = 1;
+ SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
+ goto stop;
+ }
+
+#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
+ if ( username != NULL || groupname != NULL ) {
+ slap_init_user( username, groupname );
+ }
#endif
- init();
- read_config( configfile, &be, fp );
+ if ( slap_init( serverMode, serverName ) != 0 ) {
+ rc = 1;
+ SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 );
+ goto destroy;
+ }
- if ( ! inetd ) {
- pthread_attr_t attr;
- int status;
+ if ( read_config( configfile ) != 0 ) {
+ rc = 1;
+ SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 );
+ goto destroy;
+ }
- time( &starttime );
- pthread_attr_init( &attr );
- pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
+#ifdef HAVE_TLS
+ ldap_pvt_tls_init();
+ ldap_pvt_tls_init_def_ctx();
+#endif
- if ( pthread_create( &listener_tid, attr, (void *) daemon,
- (void *) port ) != 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "listener pthread_create failed\n", 0, 0, 0 );
- exit( 1 );
- }
- pthread_attr_destroy( &attr );
- pthread_join( listener_tid, (void *) &status );
- pthread_exit( 0 );
- } else {
- Connection c;
- Operation *o;
- BerElement ber;
- unsigned long len, tag;
- long msgid;
- int flen;
- struct sockaddr_in from;
- struct hostent *hp;
-
- c.c_dn = NULL;
- c.c_ops = NULL;
- c.c_sb.sb_sd = 0;
- c.c_sb.sb_options = 0;
- c.c_sb.sb_naddr = udp ? 1 : 0;
- c.c_sb.sb_ber.ber_buf = NULL;
- c.c_sb.sb_ber.ber_ptr = NULL;
- c.c_sb.sb_ber.ber_end = NULL;
- pthread_mutex_init( &c.c_dnmutex, pthread_mutexattr_default );
- pthread_mutex_init( &c.c_opsmutex, pthread_mutexattr_default );
- pthread_mutex_init( &c.c_pdumutex, pthread_mutexattr_default );
-#ifdef notdefcldap
- c.c_sb.sb_addrs = (void **) saddrlist;
- c.c_sb.sb_fromaddr = &faddr;
- c.c_sb.sb_useaddr = saddrlist[ 0 ] = &saddr;
-#endif
- flen = sizeof(from);
- if ( getpeername( 0, (struct sockaddr *) &from, &flen ) == 0 ) {
-#ifdef REVERSE_LOOKUP
- hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
- sizeof(from.sin_addr.s_addr), AF_INET );
+ (void) SIGNAL( LDAP_SIGUSR1, slap_do_nothing );
+ (void) SIGNAL( LDAP_SIGUSR2, slap_set_shutdown );
+#ifdef SIGPIPE
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+#ifdef SIGHUP
+ (void) SIGNAL( SIGHUP, slap_set_shutdown );
+#endif
+ (void) SIGNAL( SIGINT, slap_set_shutdown );
+ (void) SIGNAL( SIGTERM, slap_set_shutdown );
+#ifdef LDAP_SIGCHLD
+ (void) SIGNAL( LDAP_SIGCHLD, wait4child );
+#endif
+#ifdef SIGBREAK
+ /* SIGBREAK is generated when Ctrl-Break is pressed. */
+ (void) SIGNAL( SIGBREAK, slap_set_shutdown );
+#endif
+
+#ifndef HAVE_WINSOCK
+#ifdef LDAP_DEBUG
+ lutil_detach( ldap_debug, 0 );
#else
- hp = NULL;
+ lutil_detach( 0, 0 );
#endif
+#endif /* HAVE_WINSOCK */
- Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n",
- hp == NULL ? "unknown" : hp->h_name,
- inet_ntoa( from.sin_addr ), 0 );
+#ifdef CSRIMALLOC
+ mal_leaktrace(1);
+#endif
- c.c_addr = inet_ntoa( from.sin_addr );
- c.c_domain = strdup( hp == NULL ? "" : hp->h_name );
- } else {
- Debug( LDAP_DEBUG_ARGS, "connection from unknown\n",
- 0, 0, 0 );
- }
+ if ( slap_startup( NULL ) != 0 ) {
+ rc = 1;
+ SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
+ goto shutdown;
+ }
- ber_init( &ber, 0 );
- while ( (tag = ber_get_next( &c.c_sb, &len, &ber ))
- == LDAP_TAG_MESSAGE ) {
- pthread_mutex_lock( ¤ttime_mutex );
- time( ¤ttime );
- pthread_mutex_unlock( ¤ttime_mutex );
-
- if ( (tag = ber_get_int( &ber, &msgid ))
- != LDAP_TAG_MSGID ) {
- /* log and send error */
- Debug( LDAP_DEBUG_ANY,
- "ber_get_int returns 0x%x\n", tag, 0, 0 );
- return;
- }
+ {
+ FILE *fp;
- if ( (tag = ber_peek_tag( &ber, &len ))
- == LBER_ERROR ) {
- /* log, close and send error */
- Debug( LDAP_DEBUG_ANY,
- "ber_peek_tag returns 0x%x\n", tag, 0, 0 );
- ber_free( &ber, 1 );
- close( c.c_sb.sb_sd );
- c.c_sb.sb_sd = -1;
- return;
- }
+ Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
- connection_activity( &c );
+ if (( slapd_pid_file != NULL ) &&
+ (( fp = fopen( slapd_pid_file, "w" )) != NULL ))
+ {
+ fprintf( fp, "%d\n", (int) getpid() );
+ fclose( fp );
+ }
- ber_free( &ber, 1 );
+ if (( slapd_args_file != NULL ) &&
+ (( fp = fopen( slapd_args_file, "w" )) != NULL ))
+ {
+ for ( i = 0; i < g_argc; i++ ) {
+ fprintf( fp, "%s ", g_argv[i] );
+ }
+ fprintf( fp, "\n" );
+ fclose( fp );
}
}
+
+#ifdef HAVE_WINSOCK
+ LogSlapdStartedEvent( NTservice, slap_debug, configfile, urls );
+#endif
+
+ rc = slapd_daemon();
+
+#ifdef HAVE_WINSOCK
+ /* Throw away the event that we used during the startup process. */
+ if ( is_NT_Service )
+ ldap_pvt_thread_cond_destroy( &started_event );
+#endif
+
+shutdown:
+ /* remember an error during shutdown */
+ rc |= slap_shutdown( NULL );
+
+destroy:
+ /* remember an error during destroy */
+ rc |= slap_destroy();
+
+stop:
+#ifdef HAVE_WINSOCK
+ LogSlapdStoppedEvent( NTservice );
+#endif
+
+ Debug( LDAP_DEBUG_ANY, "slapd stopped.\n", 0, 0, 0 );
+
+#ifdef HAVE_WINSOCK
+ ReportSlapdShutdownComplete();
+#endif
+
+ closelog();
+ slapd_daemon_destroy();
+
+#ifdef CSRIMALLOC
+ mal_dumpleaktrace( leakfile );
+#endif
+
+ MAIN_RETURN(rc);
+}
+
+
+#ifdef LDAP_SIGCHLD
+
+/*
+ * Catch and discard terminated child processes, to avoid zombies.
+ */
+
+static RETSIGTYPE
+wait4child( int sig )
+{
+ int save_errno = errno;
+
+#ifdef WNOHANG
+ errno = 0;
+#ifdef HAVE_WAITPID
+ while ( waitpid( (pid_t)-1, NULL, WNOHANG ) >= 0 || errno == EINTR )
+ ; /* NULL */
+#else
+ while ( wait3( NULL, WNOHANG, NULL ) >= 0 || errno == EINTR )
+ ; /* NULL */
+#endif
+#else
+ (void) wait( NULL );
+#endif
+ (void) SIGNAL( sig, wait4child );
+ errno = save_errno;
}
+
+#endif /* SIGCHLD || SIGCLD */
+
+
+#ifdef LOG_LOCAL4
+
+/*
+ * Convert a string to an integer by means of a dispatcher table
+ * if the string is not in the table return the default
+ */
+
+static int
+cnvt_str2int( char *stringVal, STRDISP_P dispatcher, int defaultVal )
+{
+ int retVal = defaultVal;
+ STRDISP_P disp;
+
+ for (disp = dispatcher; disp->stringVal; disp++) {
+
+ if (!strncasecmp (stringVal, disp->stringVal, disp->abbr)) {
+
+ retVal = disp->intVal;
+ break;
+
+ }
+ }
+
+ return (retVal);
+}
+
+#endif /* LOG_LOCAL4 */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "slap.h"
-extern char *default_referral;
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
-extern int global_lastmod;
+static void modlist_free(LDAPModList *ml);
-static void modlist_free();
-static void add_lastmods();
+static int add_modified_attrs( Operation *op, LDAPModList **modlist );
-void
+int
do_modify(
Connection *conn,
Operation *op
)
{
- char *dn, *odn;
+ char *ndn;
char *last;
- unsigned long tag, len;
- LDAPMod *mods, *tmp;
- LDAPMod **modtail;
+ ber_tag_t tag;
+ ber_len_t len;
+ LDAPModList *modlist;
+ LDAPModList **modtail;
+#ifdef LDAP_DEBUG
+ LDAPModList *tmp;
+#endif
Backend *be;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_modify: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the modify request. It looks like this:
*
* }
*/
- if ( ber_scanf( op->o_ber, "{a", &dn ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ if ( ber_scanf( op->o_ber, "{a" /*}*/, &ndn ) == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_ANY, "do_modify: ber_scanf failed\n", 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
}
- odn = strdup( dn );
- dn_normalize( dn );
- Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", dn, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", ndn, 0, 0 );
+
+ if( dn_normalize_case( ndn ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "do_modify: invalid dn (%s)\n", ndn, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
+ "invalid DN", NULL, NULL );
+ free( ndn );
+ return rc;
+ }
/* collect modifications & save for later */
- mods = NULL;
- modtail = &mods;
+ modlist = NULL;
+ modtail = &modlist;
+
for ( tag = ber_first_element( op->o_ber, &len, &last );
tag != LBER_DEFAULT;
tag = ber_next_element( op->o_ber, &len, last ) )
{
- (*modtail) = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
+ ber_int_t mop;
+
+ (*modtail) = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
- if ( ber_scanf( op->o_ber, "{i{a[V]}}", &(*modtail)->mod_op,
- &(*modtail)->mod_type, &(*modtail)->mod_bvalues )
+ if ( ber_scanf( op->o_ber, "{i{a[V]}}", &mop,
+ &(*modtail)->ml_type, &(*modtail)->ml_bvalues )
== LBER_ERROR )
{
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "decoding error" );
- free( dn );
- free( odn );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding modlist error" );
+ free( ndn );
free( *modtail );
- modlist_free( mods );
- return;
+ *modtail = NULL;
+ modlist_free( modlist );
+ return -1;
}
- if ( (*modtail)->mod_op != LDAP_MOD_ADD &&
- (*modtail)->mod_op != LDAP_MOD_DELETE &&
- (*modtail)->mod_op != LDAP_MOD_REPLACE )
+ (*modtail)->ml_op = mop;
+
+ if ( (*modtail)->ml_op != LDAP_MOD_ADD &&
+ (*modtail)->ml_op != LDAP_MOD_DELETE &&
+ (*modtail)->ml_op != LDAP_MOD_REPLACE )
{
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "unrecognized modify operation" );
- free( dn );
- free( odn );
- modlist_free( mods );
- return;
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "unrecognized modify operation", NULL, NULL );
+ free( ndn );
+ modlist_free( modlist );
+ return LDAP_PROTOCOL_ERROR;
}
- if ( (*modtail)->mod_bvalues == NULL && (*modtail)->mod_op
- != LDAP_MOD_DELETE ) {
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "no values given" );
- free( dn );
- free( odn );
- modlist_free( mods );
- return;
+ if ( (*modtail)->ml_bvalues == NULL
+ && (*modtail)->ml_op != LDAP_MOD_DELETE )
+ {
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "unrecognized modify operation", NULL, NULL );
+ free( ndn );
+ modlist_free( modlist );
+ return LDAP_PROTOCOL_ERROR;
}
- attr_normalize( (*modtail)->mod_type );
+ attr_normalize( (*modtail)->ml_type );
- modtail = &(*modtail)->mod_next;
+ modtail = &(*modtail)->ml_next;
}
*modtail = NULL;
#ifdef LDAP_DEBUG
Debug( LDAP_DEBUG_ARGS, "modifications:\n", 0, 0, 0 );
- for ( tmp = mods; tmp != NULL; tmp = tmp->mod_next ) {
- Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n", tmp->mod_op
- == LDAP_MOD_ADD ? "add" : (tmp->mod_op == LDAP_MOD_DELETE ?
- "delete" : "replace"), tmp->mod_type, 0 );
+ for ( tmp = modlist; tmp != NULL; tmp = tmp->ml_next ) {
+ Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n",
+ tmp->ml_op == LDAP_MOD_ADD
+ ? "add" : (tmp->ml_op == LDAP_MOD_DELETE
+ ? "delete" : "replace"), tmp->ml_type, 0 );
}
#endif
- Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d MOD dn=\"%s\"\n",
- conn->c_connid, op->o_opid, dn, 0, 0 );
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ free( ndn );
+ modlist_free( modlist );
+ Debug( LDAP_DEBUG_ANY, "do_modify: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
+
+ Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d MOD dn=\"%s\"\n",
+ op->o_connid, op->o_opid, ndn, 0, 0 );
/*
* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
- free( odn );
- modlist_free( mods );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ if ( (be = select_backend( ndn )) == NULL ) {
+ free( ndn );
+ modlist_free( modlist );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
+ return rc;
}
+ /* deref suffix alias if appropriate */
+ ndn = suffix_alias( be, ndn );
+
/*
* do the modify if 1 && (2 || 3)
* 1) there is a modify function implemented in this backend;
* 2) this backend is master for what it holds;
- * 3) it's a replica and the dn supplied is the updatedn.
+ * 3) it's a replica and the dn supplied is the update_ndn.
*/
- if ( be->be_modify != NULL ) {
+ if ( be->be_modify ) {
/* do the update here */
- if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
- op->o_dn ) == 0 ) {
- if ( (be->be_lastmod == ON || be->be_lastmod == 0 &&
- global_lastmod == ON) && be->be_updatedn == NULL ) {
- add_lastmods( op, &mods );
+#ifndef SLAPD_MULTIMASTER
+ /* we don't have to check for replicator dn
+ * because we accept each modify request
+ */
+ if ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
+#endif
+ {
+ if ( (be->be_lastmod == ON || (be->be_lastmod == UNDEFINED &&
+ global_lastmod == ON)) && be->be_update_ndn == NULL )
+ {
+ rc = add_modified_attrs( op, &modlist );
+
+ if( rc != LDAP_SUCCESS ) {
+ free( ndn );
+ modlist_free( modlist );
+ send_ldap_result( conn, op, rc,
+ NULL, "no-user-modification attribute type",
+ NULL, NULL );
+ return rc;
+ }
}
- if ( (*be->be_modify)( be, conn, op, odn, mods )
- == 0 ) {
- replog( be, LDAP_REQ_MODIFY, dn, mods, 0 );
+
+ if ( (*be->be_modify)( be, conn, op, ndn, modlist ) == 0
+#ifdef SLAPD_MULTIMASTER
+ && ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) != 0 )
+#endif
+ ) {
+ /* but we log only the ones not from a replicator user */
+ replog( be, op, ndn, modlist );
}
+#ifndef SLAPD_MULTIMASTER
/* send a referral */
} else {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+ be->be_update_refs ? be->be_update_refs : default_referral,
+ NULL );
+#endif
}
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
- free( dn );
- free( odn );
- modlist_free( mods );
+ free( ndn );
+ modlist_free( modlist );
+ return rc;
}
-static void
-modlist_free(
- LDAPMod *mods
-)
-{
- LDAPMod *next;
-
- for ( ; mods != NULL; mods = next ) {
- next = mods->mod_next;
- free( mods->mod_type );
- if ( mods->mod_bvalues != NULL )
- ber_bvecfree( mods->mod_bvalues );
- free( mods );
- }
-}
-
-static void
-add_lastmods( Operation *op, LDAPMod **mods )
+static int
+add_modified_attrs( Operation *op, LDAPModList **modlist )
{
- char buf[20];
+ char buf[22];
struct berval bv;
struct berval *bvals[2];
- LDAPMod **m;
- LDAPMod *tmp;
+ LDAPModList *m;
struct tm *ltm;
-
- Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
+ time_t currenttime;
bvals[0] = &bv;
bvals[1] = NULL;
/* remove any attempts by the user to modify these attrs */
- for ( m = mods; *m != NULL; m = &(*m)->mod_next ) {
- if ( strcasecmp( (*m)->mod_type, "modifytimestamp" ) == 0
- || strcasecmp( (*m)->mod_type, "modifiersname" ) == 0 ) {
- tmp = *m;
- *m = (*m)->mod_next;
- free( tmp->mod_type );
- if ( tmp->mod_bvalues != NULL ) {
- ber_bvecfree( tmp->mod_bvalues );
- }
- free( tmp );
+ for ( m = *modlist; m != NULL; m = m->ml_next ) {
+ if ( oc_check_no_usermod_attr( m->ml_type ) ) {
+ return LDAP_CONSTRAINT_VIOLATION;
}
}
bv.bv_val = op->o_dn;
bv.bv_len = strlen( bv.bv_val );
}
- tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
- tmp->mod_type = strdup( "modifiersname" );
- tmp->mod_op = LDAP_MOD_REPLACE;
- tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
- 2 * sizeof(struct berval *) );
- tmp->mod_bvalues[0] = ber_bvdup( &bv );
- tmp->mod_next = *mods;
- *mods = tmp;
-
- pthread_mutex_lock( ¤ttime_mutex );
- ltm = localtime( ¤ttime );
- strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
- pthread_mutex_unlock( ¤ttime_mutex );
+ m = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
+ m->ml_type = ch_strdup( "modifiersname" );
+ m->ml_op = LDAP_MOD_REPLACE;
+ m->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *));
+ m->ml_bvalues[0] = ber_bvdup( &bv );
+ m->ml_next = *modlist;
+ *modlist = m;
+
+ currenttime = slap_get_time();
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
bv.bv_val = buf;
bv.bv_len = strlen( bv.bv_val );
- tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
- tmp->mod_type = strdup( "modifytimestamp" );
- tmp->mod_op = LDAP_MOD_REPLACE;
- tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
- 2 * sizeof(struct berval *) );
- tmp->mod_bvalues[0] = ber_bvdup( &bv );
- tmp->mod_next = *mods;
- *mods = tmp;
+ m = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
+ m->ml_type = ch_strdup( "modifytimestamp" );
+ m->ml_op = LDAP_MOD_REPLACE;
+ m->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *));
+ m->ml_bvalues[0] = ber_bvdup( &bv );
+ m->ml_next = *modlist;
+ *modlist = m;
+
+ return LDAP_SUCCESS;
+}
+
+static void
+modlist_free(
+ LDAPModList *ml
+)
+{
+ LDAPModList *next;
+
+ for ( ; ml != NULL; ml = next ) {
+ next = ml->ml_next;
+
+ free( ml->ml_type );
+ if ( ml->ml_bvalues != NULL )
+ ber_bvecfree( ml->ml_bvalues );
+
+ free( ml );
+ }
}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
* is provided ``as is'' without express or implied warranty.
*/
+/*
+ * LDAP v3 newSuperior support.
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/socket.h>
+#include <ac/string.h>
-extern char *default_referral;
+#include "slap.h"
-void
+int
do_modrdn(
Connection *conn,
Operation *op
)
{
- char *dn, *odn, *newrdn;
- int deloldrdn;
+ char *ndn, *newrdn;
+ ber_int_t deloldrdn;
Backend *be;
+ /* Vars for LDAP v3 newSuperior support */
+ char *newSuperior = NULL;
+ char *nnewSuperior = NULL;
+ Backend *newSuperior_be = NULL;
+ ber_len_t length;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_modrdn: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the modrdn request. It looks like this:
*
* ModifyRDNRequest := SEQUENCE {
* entry DistinguishedName,
* newrdn RelativeDistinguishedName
+ * deleteoldrdn BOOLEAN,
+ * newSuperior [0] LDAPDN OPTIONAL (v3 Only!)
* }
*/
- if ( ber_scanf( op->o_ber, "{aab}", &dn, &newrdn, &deloldrdn )
+ if ( ber_scanf( op->o_ber, "{aab", &ndn, &newrdn, &deloldrdn )
== LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+ }
+
+ if( dn_normalize_case( ndn ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid dn (%s)\n", ndn, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
+ "invalid DN", NULL, NULL );
+ free( ndn );
+ free( newrdn );
+ return rc;
+ }
+
+ if( !rdn_validate( newrdn ) ) {
+ Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid rdn (%s)\n", newrdn, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
+ "invalid RDN", NULL, NULL );
+ free( ndn );
+ free( newrdn );
+ return rc;
+ }
+
+ /* Check for newSuperior parameter, if present scan it */
+
+ if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) {
+ if ( op->o_protocol < LDAP_VERSION3 ) {
+ /* Conection record indicates v2 but field
+ * newSuperior is present: report error.
+ */
+ Debug( LDAP_DEBUG_ANY,
+ "modrdn(v2): invalid field newSuperior!\n",
+ 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" );
+ return -1;
+ }
+
+ if ( ber_scanf( op->o_ber, "a", &newSuperior )
+ == LBER_ERROR ) {
+
+ Debug( LDAP_DEBUG_ANY, "ber_scanf(\"a\"}) failed\n",
+ 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+ }
+
+ nnewSuperior = ch_strdup( newSuperior );
+
+ if( dn_normalize_case( nnewSuperior ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid new superior (%s)\n",
+ newSuperior, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
+ "invalid (new superior) DN", NULL, NULL );
+ free( ndn );
+ free( newrdn );
+ return rc;
+ }
+
}
- odn = strdup( dn );
- dn_normalize( dn );
Debug( LDAP_DEBUG_ARGS,
- "do_modrdn: dn (%s) newrdn (%s) deloldrdn (%d)\n", dn, newrdn,
- deloldrdn );
+ "do_modrdn: dn (%s) newrdn (%s) newsuperior (%s)\n",
+ ndn, newrdn,
+ newSuperior != NULL ? newSuperior : "" );
+
+ if ( ber_scanf( op->o_ber, /*{*/ "}") == LBER_ERROR ) {
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ free( nnewSuperior );
+ Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+ }
+
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ Debug( LDAP_DEBUG_ANY, "do_modrdn: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
- Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d MODRDN dn=\"%s\"\n",
- conn->c_connid, op->o_opid, dn, 0, 0 );
+ Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d MODRDN dn=\"%s\"\n",
+ op->o_connid, op->o_opid, ndn, 0, 0 );
/*
* We could be serving multiple database backends. Select the
* if we don't hold it.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
- free( odn );
- free( newrdn );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ if ( (be = select_backend( ndn )) == NULL ) {
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ free( nnewSuperior );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
+ return rc;
}
+ /* Make sure that the entry being changed and the newSuperior are in
+ * the same backend, otherwise we return an error.
+ */
+ if( newSuperior != NULL ) {
+ newSuperior_be = select_backend( nnewSuperior );
+
+ if ( newSuperior_be != be ) {
+ /* newSuperior is in same backend */
+ rc = LDAP_AFFECTS_MULTIPLE_DSAS;
+
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ free( nnewSuperior );
+
+ return rc;
+ }
+
+ /* deref suffix alias if appropriate */
+ nnewSuperior = suffix_alias( be, nnewSuperior );
+ }
+
+ /* deref suffix alias if appropriate */
+ ndn = suffix_alias( be, ndn );
+
/*
* do the add if 1 && (2 || 3)
* 1) there is an add function implemented in this backend;
* 2) this backend is master for what it holds;
- * 3) it's a replica and the dn supplied is the updatedn.
+ * 3) it's a replica and the dn supplied is the update_ndn.
*/
- if ( be->be_modrdn != NULL ) {
+ if ( be->be_modrdn ) {
/* do the update here */
- if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
- op->o_dn ) == 0 ) {
- if ( (*be->be_modrdn)( be, conn, op, dn, newrdn,
- deloldrdn ) == 0 ) {
- replog( be, LDAP_REQ_MODRDN, odn, newrdn,
- deloldrdn );
+#ifndef SLAPD_MULTIMASTER
+ if ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
+#endif
+ {
+ if ( (*be->be_modrdn)( be, conn, op, ndn, newrdn,
+ deloldrdn, newSuperior ) == 0
+#ifdef SLAPD_MULTIMASTER
+ && ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) )
+#endif
+ ) {
+ struct replog_moddn moddn;
+ moddn.newrdn = newrdn;
+ moddn.deloldrdn = deloldrdn;
+ moddn.newsup = newSuperior;
+
+ replog( be, op, ndn, &moddn );
}
+#ifndef SLAPD_MULTIMASTER
} else {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+ be->be_update_refs ? be->be_update_refs : default_referral, NULL );
+#endif
}
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
- free( dn );
- free( odn );
- free( newrdn );
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ free( nnewSuperior );
+ return rc;
}
--- /dev/null
+#include "portable.h"
+#include <stdio.h>
+#include "slap.h"
+
+#ifdef SLAPD_MODULES
+
+#include <ltdl.h>
+
+int module_load(const char* file_name, int argc, char *argv[]) {
+ lt_dlhandle* module = NULL;
+ int (*initialize) LDAP_P((int argc, char *argv[]));
+
+ if (lt_dlinit()) {
+ Debug(LDAP_DEBUG_ANY, "lt_dlinit failed: %s\n", lt_dlerror(), 0, 0);
+ return -1;
+ }
+
+ if ((module = lt_dlopen(file_name)) == NULL) {
+ Debug(LDAP_DEBUG_ANY, "lt_dlopen failed: (%s) %s\n", file_name,
+ lt_dlerror(), 0);
+ return -1;
+ }
+
+ Debug(LDAP_DEBUG_CONFIG, "loaded module %s\n", file_name, 0, 0);
+
+ if ((initialize = lt_dlsym(module, "init_module")))
+ return initialize(argc, argv);
+
+ Debug(LDAP_DEBUG_CONFIG, "module %s: no init_module() function found\n",
+ file_name, 0, 0);
+ return -1;
+}
+
+int module_path(const char *path) {
+
+ if (lt_dlinit()) {
+ Debug(LDAP_DEBUG_ANY, "lt_dlinit failed: %s\n", lt_dlerror(), 0, 0);
+ return -1;
+ }
+
+ return lt_dlsetsearchpath( path );
+}
+#endif /* SLAPD_MODULES */
+
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
* is provided ``as is'' without express or implied warranty.
*/
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-#include "ldapconfig.h"
-
-#if defined( SLAPD_MONITOR_DN )
+#include "portable.h"
-extern int nbackends;
-extern Backend *backends;
-extern int active_threads;
-extern int dtblsize;
-extern Connection *c;
-extern long ops_initiated;
-extern long ops_completed;
-extern long num_entries_sent;
-extern long num_bytes_sent;
-extern time_t currenttime;
-extern time_t starttime;
-extern int num_conns;
+#include <stdio.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
-extern char Versionstr[];
+#include "ldap_defaults.h"
+#include "slap.h"
-/*
- * no mutex protection in here - take our chances!
- */
+#if defined( SLAPD_MONITOR_DN )
void
-monitor_info( Connection *conn, Operation *op )
+monitor_info(
+ Connection *conn,
+ Operation *op,
+ char ** attrs,
+ int attrsonly )
{
Entry *e;
- char buf[BUFSIZ], buf2[20];
+ char buf[BUFSIZ];
struct berval val;
struct berval *vals[2];
- int i, nconns, nwritewaiters, nreadwaiters;
+ int nconns, nwritewaiters, nreadwaiters;
struct tm *ltm;
- char *p, *tmpdn;
+ char *p;
+ char buf2[22];
+ char buf3[22];
+ Connection *c;
+ int connindex;
+ time_t currenttime;
vals[0] = &val;
vals[1] = NULL;
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+ /* initialize reader/writer lock */
e->e_attrs = NULL;
- e->e_dn = strdup( SLAPD_MONITOR_DN );
+ e->e_dn = ch_strdup( SLAPD_MONITOR_DN );
+ e->e_ndn = ch_strdup(SLAPD_MONITOR_DN);
+ (void) dn_normalize_case( e->e_ndn );
+ e->e_private = NULL;
+
+ {
+ char *rdn = ch_strdup( SLAPD_MONITOR_DN );
+ val.bv_val = strchr( rdn, '=' );
- val.bv_val = Versionstr;
+ if( val.bv_val != NULL ) {
+ *val.bv_val = '\0';
+ val.bv_len = strlen( ++val.bv_val );
+
+ attr_merge( e, rdn, vals );
+ }
+
+ free( rdn );
+ }
+
+ val.bv_val = (char *) Versionstr;
if (( p = strchr( Versionstr, '\n' )) == NULL ) {
val.bv_len = strlen( Versionstr );
} else {
}
attr_merge( e, "version", vals );
+ ldap_pvt_thread_mutex_lock( &active_threads_mutex );
sprintf( buf, "%d", active_threads );
+ ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "threads", vals );
nconns = 0;
nwritewaiters = 0;
nreadwaiters = 0;
- for ( i = 0; i < dtblsize; i++ ) {
- if ( c[i].c_sb.sb_sd != -1 ) {
- nconns++;
- if ( c[i].c_writewaiter ) {
- nwritewaiters++;
- }
- if ( c[i].c_gettingber ) {
- nreadwaiters++;
- }
- ltm = localtime( &c[i].c_starttime );
- strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
- pthread_mutex_lock( &c[i].c_dnmutex );
- sprintf( buf, "%d : %s : %ld : %ld : %s : %s%s", i,
- buf2, c[i].c_opsinitiated, c[i].c_opscompleted,
- c[i].c_dn ? c[i].c_dn : "NULLDN",
- c[i].c_gettingber ? "r" : "",
- c[i].c_writewaiter ? "w" : "" );
- pthread_mutex_unlock( &c[i].c_dnmutex );
- val.bv_val = buf;
- val.bv_len = strlen( buf );
- attr_merge( e, "connection", vals );
+
+ /* loop through the connections */
+ for ( c = connection_first( &connindex );
+ c != NULL;
+ c = connection_next( c, &connindex ))
+ {
+ nconns++;
+ if ( c->c_writewaiter ) {
+ nwritewaiters++;
}
+ if ( c->c_currentber != NULL ) {
+ nreadwaiters++;
+ }
+
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( &c->c_starttime );
+ strftime( buf2, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
+
+ ltm = gmtime( &c->c_activitytime );
+ strftime( buf3, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( &c->.c_starttime );
+ strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
+
+ ltm = localtime( &c->c_activitytime );
+ strftime( buf3, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
+#endif
+
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
+ sprintf( buf,
+ "%ld : %ld "
+ ": %ld/%ld/%ld/%ld "
+ ": %ld/%ld/%ld "
+ ": %s%s%s%s%s%s "
+ ": %s : %s : %s "
+ ": %s : %s : %s : %s ",
+
+ c->c_connid,
+ (long) c->c_protocol,
+
+ c->c_n_ops_received, c->c_n_ops_executing,
+ c->c_n_ops_pending, c->c_n_ops_completed,
+
+ /* add low-level counters here */
+ c->c_n_get, c->c_n_read, c->c_n_write,
+
+ c->c_currentber ? "r" : "",
+ c->c_writewaiter ? "w" : "",
+ c->c_ops != NULL ? "x" : "",
+ c->c_pending_ops != NULL ? "p" : "",
+ connection_state2str( c->c_conn_state ),
+ c->c_bind_in_progress ? "S" : "",
+
+ c->c_cdn ? c->c_cdn : "<anonymous>",
+
+ c->c_listener_url,
+ c->c_peer_domain,
+ c->c_peer_name,
+ c->c_sock_name,
+
+ buf2,
+ buf3
+ );
+
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ attr_merge( e, "connection", vals );
}
+ connection_done(c);
+
sprintf( buf, "%d", nconns );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "currentconnections", vals );
+ attr_merge( e, "currentConnections", vals );
- sprintf( buf, "%d", num_conns );
+ sprintf( buf, "%ld", connections_nextid() );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "totalconnections", vals );
+ attr_merge( e, "totalConnections", vals );
- sprintf( buf, "%d", dtblsize );
+ sprintf( buf, "%ld", (long) dtblsize );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "dtablesize", vals );
+ attr_merge( e, "dTableSize", vals );
sprintf( buf, "%d", nwritewaiters );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "writewaiters", vals );
+ attr_merge( e, "writeWaiters", vals );
sprintf( buf, "%d", nreadwaiters );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "readwaiters", vals );
+ attr_merge( e, "readWaiters", vals );
- sprintf( buf, "%ld", ops_initiated );
+ ldap_pvt_thread_mutex_lock(&num_ops_mutex);
+ sprintf( buf, "%ld", num_ops_initiated );
+ ldap_pvt_thread_mutex_unlock(&num_ops_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "opsinitiated", vals );
+ attr_merge( e, "opsInitiated", vals );
- sprintf( buf, "%ld", ops_completed );
+ ldap_pvt_thread_mutex_lock(&num_ops_mutex);
+ sprintf( buf, "%ld", num_ops_completed );
+ ldap_pvt_thread_mutex_unlock(&num_ops_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "opscompleted", vals );
+ attr_merge( e, "opsCompleted", vals );
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
sprintf( buf, "%ld", num_entries_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "entriessent", vals );
+ attr_merge( e, "entriesSent", vals );
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
+ sprintf( buf, "%ld", num_refs_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ attr_merge( e, "referencesSent", vals );
+
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
+ sprintf( buf, "%ld", num_pdu_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ attr_merge( e, "pduSent", vals );
+
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
sprintf( buf, "%ld", num_bytes_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "bytessent", vals );
+ attr_merge( e, "bytesSent", vals );
+
+ currenttime = slap_get_time();
- ltm = localtime( ¤ttime );
- strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "currenttime", vals );
- ltm = localtime( &starttime );
- strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( &starttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( &starttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "starttime", vals );
val.bv_len = strlen( buf );
attr_merge( e, "nbackends", vals );
-#ifdef THREAD_SUNOS5_LWP
- sprintf( buf, "%d", thr_getconcurrency() );
+#ifdef HAVE_THREAD_CONCURRENCY
+ sprintf( buf, "%d", ldap_pvt_thread_get_concurrency() );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "concurrency", vals );
#endif
- send_search_entry( &backends[0], conn, op, e, NULL, 0 );
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+ val.bv_val = "top";
+ val.bv_len = sizeof("top")-1;
+ attr_merge( e, "objectClass", vals );
+
+ val.bv_val = "LDAPsubentry";
+ val.bv_len = sizeof("LDAPsubentry")-1;
+ attr_merge( e, "objectClass", vals );
+
+ val.bv_val = "extensibleObject";
+ val.bv_len = sizeof("extensibleObject")-1;
+ attr_merge( e, "objectClass", vals );
+
+ send_search_entry( &backends[0], conn, op, e,
+ attrs, attrsonly, NULL );
+ send_search_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 1 );
entry_free( e );
}
/* operation.c - routines to deal with pending ldap operations */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
void
-op_free( Operation *op )
+slap_op_free( Operation *op )
{
- if ( op->o_ber != NULL )
+ assert( op->o_next == NULL );
+
+ if ( op->o_ber != NULL ) {
ber_free( op->o_ber, 1 );
+ }
if ( op->o_dn != NULL ) {
free( op->o_dn );
}
- /* pthread_mutex_destroy( &op->o_abandonmutex ); */
+ if ( op->o_ndn != NULL ) {
+ free( op->o_ndn );
+ }
+ if ( op->o_authmech != NULL ) {
+ free( op->o_authmech );
+ }
+ if ( op->o_ctrls != NULL ) {
+ ldap_controls_free( op->o_ctrls );
+ }
+
+ ldap_pvt_thread_mutex_destroy( &op->o_abandonmutex );
+
free( (char *) op );
}
Operation *
-op_add(
- Operation **olist,
+slap_op_alloc(
BerElement *ber,
- unsigned long msgid,
- unsigned long tag,
- char *dn,
- int id,
- int connid
+ ber_int_t msgid,
+ ber_tag_t tag,
+ ber_int_t id
+)
+{
+ Operation *op;
+
+ op = (Operation *) ch_calloc( 1, sizeof(Operation) );
+
+ ldap_pvt_thread_mutex_init( &op->o_abandonmutex );
+ op->o_abandon = 0;
+
+ op->o_ber = ber;
+ op->o_msgid = msgid;
+ op->o_tag = tag;
+
+ op->o_dn = NULL;
+ op->o_ndn = NULL;
+ op->o_authmech = NULL;
+ op->o_ctrls = NULL;
+
+ op->o_time = slap_get_time();
+ op->o_opid = id;
+ op->o_next = NULL;
+
+ return( op );
+}
+
+int slap_op_add(
+ Operation **olist,
+ Operation *op
)
{
Operation **tmp;
for ( tmp = olist; *tmp != NULL; tmp = &(*tmp)->o_next )
; /* NULL */
- *tmp = (Operation *) calloc( 1, sizeof(Operation) );
- pthread_mutex_init( &(*tmp)->o_abandonmutex,
- pthread_mutexattr_default );
- (*tmp)->o_ber = ber;
- (*tmp)->o_msgid = msgid;
- (*tmp)->o_tag = tag;
- (*tmp)->o_abandon = 0;
- (*tmp)->o_dn = strdup( dn != NULL ? dn : "" );
- pthread_mutex_lock( ¤ttime_mutex );
- (*tmp)->o_time = currenttime;
- pthread_mutex_unlock( ¤ttime_mutex );
- (*tmp)->o_opid = id;
- (*tmp)->o_connid = connid;
- (*tmp)->o_next = NULL;
-
- return( *tmp );
+ *tmp = op;
+
+ return 0;
}
-void
-op_delete( Operation **olist, Operation *op )
+int
+slap_op_remove( Operation **olist, Operation *op )
{
Operation **tmp;
; /* NULL */
if ( *tmp == NULL ) {
- Debug( LDAP_DEBUG_ANY, "op_delete: can't find op %d\n",
+ Debug( LDAP_DEBUG_ANY, "op_delete: can't find op %ld\n",
op->o_msgid, 0, 0 );
- return;
+ return -1;
}
*tmp = (*tmp)->o_next;
- op_free( op );
+ op->o_next = NULL;
+
+ return 0;
+}
+
+Operation * slap_op_pop( Operation **olist )
+{
+ Operation *tmp = *olist;
+
+ if(tmp != NULL) {
+ *olist = tmp->o_next;
+ tmp->o_next = NULL;
+ }
+
+ return tmp;
}
+
/* phonetic.c - routines to do phonetic matching */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
#include "slap.h"
-#if !defined(METAPHONE) && !defined(SOUNDEX)
+#if !defined(METAPHONE) && !defined(SLAPD_PHONETIC)
#define METAPHONE
#endif
#define iswordbreak(x) (!isascii(x) || isspace((unsigned char) (x)) || \
ispunct((unsigned char) (x)) || \
- isdigit((unsigned char) (x)) || x == '\0')
+ isdigit((unsigned char) (x)) || (x) == '\0')
char *
first_word( char *s )
; /* NULL */
save = *s;
*s = '\0';
- ret = strdup( w );
+ ret = ch_strdup( w );
*s = save;
return( ret );
#define MAXPHONEMELEN 4
#endif
-#if defined(SOUNDEX)
+#if defined(SLAPD_PHONETIC)
/* lifted from isode-8.0 */
char *
{
char code, adjacent, ch;
char *p;
- char **c;
- int i, cmax;
+ int i;
char phoneme[MAXPHONEMELEN + 1];
p = s;
}
adjacent = '0';
- phoneme[0] = TOUPPER(*p);
+ phoneme[0] = TOUPPER((unsigned char)*p);
phoneme[1] = '\0';
for ( i = 0; i < 99 && (! iswordbreak(*p)); p++ ) {
- ch = TOUPPER (*p);
+ ch = TOUPPER ((unsigned char)*p);
code = '0';
if ( i > 0 )
phoneme[i] = '\0';
- return( strdup( phoneme ) );
+ return( ch_strdup( phoneme ) );
}
#else
*/
/* Character coding array */
-static char vsvfn[26] = {
+static const char vsvfn[26] = {
1, 16, 4, 16, 9, 2, 4, 16, 9, 2, 0, 2, 2,
/* A B C D E F G H I J K L M */
2, 1, 4, 0, 2, 4, 4, 1, 0, 0, 0, 8, 0};
phonetic( char *Word )
{
char *n, *n_start, *n_end; /* pointers to string */
- char *metaph, *metaph_end; /* pointers to metaph */
+ char *metaph_end; /* pointers to metaph */
char ntrans[40]; /* word with uppercase letters */
- char newm[8];/* new metaph for comparison */
int KSflag; /* state flag for X -> KS */
char buf[MAXPHONEMELEN + 2];
char *Metaph;
for (n = ntrans + 4, n_end = ntrans + 35; !iswordbreak( *Word ) &&
n < n_end; Word++) {
- if (isalpha(*Word))
- *n++ = TOUPPER(*Word);
+ if (isalpha((unsigned char)*Word))
+ *n++ = TOUPPER((unsigned char)*Word);
}
Metaph = buf;
*Metaph = '\0';
if (n == ntrans + 4) {
- return( strdup( buf ) ); /* Return if null */
+ return( ch_strdup( buf ) ); /* Return if null */
}
n_end = n; /* Set n_end to end of string */
}
*Metaph = 0; /* Null terminate */
- return( strdup( buf ) );
+ return( ch_strdup( buf ) );
}
#endif /* metaphone */
-#endif /* soundex */
+#endif /* SLAPD_PHONETIC */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
#ifndef _PROTO_SLAP
#define _PROTO_SLAP
+#include <ldap_cdefs.h>
+
+LDAP_BEGIN_DECL
+
/*
* acl.c
*/
-int access_allowed( Backend *be, Connection *conn, Operation *op, Entry *e,
- char *attr, struct berval *val, char *dn, int access );
-struct acl * acl_get_applicable( Backend *be, Operation *op, Entry *e,
- char *attr );
-int acl_access_allowed( struct acl *a, Backend *be, Connection *conn, Entry *e,
- struct berval *val, Operation *op, int access );
-int acl_check_mods( Backend *be, Connection *conn, Operation *op, Entry *e,
- LDAPMod *mods );
+int access_allowed LDAP_P(( Backend *be, Connection *conn,
+ Operation *op, Entry *e,
+ char *attr, struct berval *val, int access ));
+
+AccessControl * acl_get_applicable LDAP_P(( Backend *be,
+ Operation *op, Entry *e,
+ char *attr, int nmatches, regmatch_t *matches ));
+
+int acl_access_allowed LDAP_P((
+ AccessControl *a, Backend *be, Connection *conn, Entry *e,
+ struct berval *val, Operation *op, int access, char *edn,
+ regmatch_t *matches ));
+
+int acl_check_modlist LDAP_P(( Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ LDAPModList *ml ));
/*
* aclparse.c
*/
-void parse_acl( Backend *be, char *fname, int lineno, int argc, char **argv );
-char * access2str( int access );
-int str2access( char *str );
+void parse_acl LDAP_P(( Backend *be, char *fname, int lineno, int argc, char **argv ));
+char * access2str LDAP_P(( int access ));
+int str2access LDAP_P(( char *str ));
/*
* attr.c
*/
-void attr_free( Attribute *a );
-char * attr_normalize( char *s );
-int attr_merge_fast( Entry *e, char *type, struct berval **vals, int nvals,
- int naddvals, int *maxvals, Attribute ***a );
-int attr_merge( Entry *e, char *type, struct berval **vals );
-Attribute * attr_find( Attribute *a, char *type );
-int attr_delete( Attribute **attrs, char *type );
-int attr_syntax( char *type );
-void attr_syntax_config( char *fname, int lineno, int argc, char **argv );
+void attr_free LDAP_P(( Attribute *a ));
+Attribute *attr_dup LDAP_P(( Attribute *a ));
+char * attr_normalize LDAP_P(( char *s ));
+int attr_merge_fast LDAP_P(( Entry *e, char *type, struct berval **vals, int nvals,
+ int naddvals, int *maxvals, Attribute ***a ));
+int attr_merge LDAP_P(( Entry *e, char *type, struct berval **vals ));
+Attribute * attr_find LDAP_P(( Attribute *a, char *type ));
+int attr_delete LDAP_P(( Attribute **attrs, char *type ));
+int attr_syntax LDAP_P(( char *type ));
+void attr_syntax_config LDAP_P(( char *fname, int lineno, int argc, char **argv ));
+AttributeType * at_find LDAP_P(( const char *name ));
+int at_find_in_list LDAP_P(( AttributeType *sat, AttributeType **list ));
+int at_append_to_list LDAP_P(( AttributeType *sat, AttributeType ***listp ));
+int at_delete_from_list LDAP_P(( int pos, AttributeType ***listp ));
+int at_fake_if_needed LDAP_P(( char *name ));
+int at_schema_info LDAP_P(( Entry *e ));
+int at_add LDAP_P(( LDAP_ATTRIBUTE_TYPE *at, const char **err ));
+char * at_canonical_name LDAP_P(( char * a_type ));
+
+void attrs_free LDAP_P(( Attribute *a ));
+Attribute *attrs_dup LDAP_P(( Attribute *a ));
/*
* ava.c
*/
-int get_ava( BerElement *ber, Ava *ava );
-void ava_free( Ava *ava, int freeit );
+int get_ava LDAP_P(( BerElement *ber, Ava *ava ));
+void ava_free LDAP_P(( Ava *ava, int freeit ));
/*
* backend.c
*/
-Backend * new_backend( char *type );
-Backend * select_backend( char * dn );
-int be_issuffix( Backend *be, char *suffix );
-int be_isroot( Backend *be, char *dn );
-int be_isroot_pw( Backend *be, char *dn, struct berval *cred );
-void be_close();
+int backend_init LDAP_P((void));
+int backend_add LDAP_P((BackendInfo *aBackendInfo));
+int backend_num LDAP_P((Backend *be));
+int backend_startup LDAP_P((Backend *be));
+int backend_shutdown LDAP_P((Backend *be));
+int backend_destroy LDAP_P((void));
+
+BackendInfo * backend_info LDAP_P(( char *type ));
+BackendDB * backend_db_init LDAP_P(( char *type ));
+
+BackendDB * select_backend LDAP_P(( char * dn ));
+
+int be_issuffix LDAP_P(( Backend *be, char *suffix ));
+int be_isroot LDAP_P(( Backend *be, char *ndn ));
+int be_isroot_pw LDAP_P(( Backend *be, char *ndn, struct berval *cred ));
+char* be_root_dn LDAP_P(( Backend *be ));
+int be_entry_release_rw LDAP_P(( Backend *be, Entry *e, int rw ));
+#define be_entry_release_r( be, e ) be_entry_release_rw( be, e, 0 )
+#define be_entry_release_w( be, e ) be_entry_release_rw( be, e, 1 )
+
+
+extern int backend_unbind LDAP_P((Connection *conn, Operation *op));
+
+extern int backend_connection_init LDAP_P((Connection *conn));
+extern int backend_connection_destroy LDAP_P((Connection *conn));
+
+extern int backend_group LDAP_P((Backend *be,
+ Entry *target,
+ char *gr_ndn, char *op_ndn,
+ char *objectclassValue, char *groupattrName));
+
+#ifdef SLAPD_SCHEMA_DN
+/* temporary extern for temporary routine*/
+extern Attribute *backend_subschemasubentry( Backend * );
+#endif
+
/*
* ch_malloc.c
*/
-char * ch_malloc( unsigned long size );
-char * ch_realloc( char *block, unsigned long size );
-char * ch_calloc( unsigned long nelem, unsigned long size );
+#ifdef CSRIMALLOC
+#define ch_malloc malloc
+#define ch_realloc realloc
+#define ch_calloc calloc
+#define ch_strdup strdup
+#define ch_free free
+
+#else
+void * ch_malloc LDAP_P(( ber_len_t size ));
+void * ch_realloc LDAP_P(( void *block, ber_len_t size ));
+void * ch_calloc LDAP_P(( ber_len_t nelem, ber_len_t size ));
+char * ch_strdup LDAP_P(( const char *string ));
+void ch_free LDAP_P(( void * ));
+
+#ifndef CH_FREE
+#undef free
+#define free ch_free
+#endif
+#endif
/*
* charray.c
*/
-void charray_add( char ***a, char *s );
-void charray_merge( char ***a, char **s );
-void charray_free( char **array );
-int charray_inlist( char **a, char *s );
-char ** charray_dup( char **a );
-char ** str2charray( char *str, char *brkstr );
+void charray_add LDAP_P(( char ***a, char *s ));
+void charray_merge LDAP_P(( char ***a, char **s ));
+void charray_free LDAP_P(( char **array ));
+int charray_inlist LDAP_P(( char **a, char *s ));
+char ** charray_dup LDAP_P(( char **a ));
+char ** str2charray LDAP_P(( char *str, char *brkstr ));
+char * charray2str LDAP_P(( char **a ));
+
+/*
+ * controls.c
+ */
+int get_ctrls LDAP_P((
+ Connection *co,
+ Operation *op,
+ int senderrors ));
+
+int get_manageDSAit LDAP_P(( Operation *op ));
/*
* config.c
*/
-void read_config( char *fname, Backend **bep, FILE *pfp );
+int read_config LDAP_P(( char *fname ));
/*
* connection.c
*/
+int connections_init LDAP_P((void));
+int connections_shutdown LDAP_P((void));
+int connections_destroy LDAP_P((void));
+int connections_timeout_idle LDAP_P((time_t));
+
+long connection_init LDAP_P((
+ ber_socket_t s,
+ const char* url,
+ const char* dnsname,
+ const char* peername,
+ const char* sockname,
+ int use_tls ));
+
+void connection_closing LDAP_P(( Connection *c ));
+int connection_state_closing LDAP_P(( Connection *c ));
+char *connection_state2str LDAP_P(( int state ));
-void connection_activity( Connection *conn );
+int connection_write LDAP_P((ber_socket_t s));
+int connection_read LDAP_P((ber_socket_t s));
+
+unsigned long connections_nextid(void);
+
+Connection* connection_first LDAP_P((ber_socket_t *));
+Connection* connection_next LDAP_P((Connection *, ber_socket_t *));
+void connection_done LDAP_P((Connection *));
/*
* dn.c
*/
-char * dn_normalize( char *dn );
-char * dn_normalize_case( char *dn );
-char * dn_parent( Backend *be, char *dn );
-int dn_issuffix( char *dn, char *suffix );
-int dn_type( char *dn );
-char * dn_upcase( char *dn );
-
+char * dn_normalize LDAP_P(( char *dn ));
+char * dn_normalize_case LDAP_P(( char *dn ));
+char * dn_parent LDAP_P(( Backend *be, char *dn ));
+char ** dn_subtree LDAP_P(( Backend *be, char *dn ));
+char * dn_rdn LDAP_P(( Backend *be, char *dn ));
+int dn_issuffix LDAP_P(( char *dn, char *suffix ));
+#ifdef DNS_DN
+int dn_type LDAP_P(( char *dn ));
+#endif
+char * str2upper LDAP_P(( char *str ));
+char * str2lower LDAP_P(( char *str ));
+int rdn_validate LDAP_P(( const char* str ));
+char * rdn_attr_value LDAP_P(( char * rdn ));
+char * rdn_attr_type LDAP_P(( char * rdn ));
+void build_new_dn LDAP_P(( char ** new_dn, char *e_dn, char * p_dn,
+ char * newrdn ));
/*
* entry.c
*/
-Entry * str2entry( char *s );
-char * entry2str( Entry *e, int *len, int printid );
-void entry_free( Entry *e );
+int entry_destroy LDAP_P((void));
+
+Entry * str2entry LDAP_P(( char *s ));
+char * entry2str LDAP_P(( Entry *e, int *len ));
+void entry_free LDAP_P(( Entry *e ));
+
+int entry_cmp LDAP_P(( Entry *a, Entry *b ));
+int entry_dn_cmp LDAP_P(( Entry *a, Entry *b ));
+int entry_id_cmp LDAP_P(( Entry *a, Entry *b ));
/*
* filter.c
*/
-int get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr );
-void filter_free( Filter *f );
-void filter_print( Filter *f );
+int get_filter LDAP_P(( Connection *conn, BerElement *ber, Filter **filt, char **fstr ));
+void filter_free LDAP_P(( Filter *f ));
+void filter_print LDAP_P(( Filter *f ));
/*
* filterentry.c
*/
-int test_filter( Backend *be, Connection *conn, Operation *op, Entry *e,
- Filter *f );
+int test_filter LDAP_P(( Backend *be, Connection *conn, Operation *op, Entry *e,
+ Filter *f ));
/*
* lock.c
*/
-FILE * lock_fopen( char *fname, char *type, FILE **lfp );
-int lock_fclose( FILE *fp, FILE *lfp );
+FILE * lock_fopen LDAP_P(( char *fname, char *type, FILE **lfp ));
+int lock_fclose LDAP_P(( FILE *fp, FILE *lfp ));
+
+/*
+ * module.c
+ */
+
+#ifdef SLAPD_MODULES
+int load_module LDAP_P(( const char* file_name, int argc, char *argv[] ));
+#endif /* SLAPD_MODULES */
/*
* monitor.c
*/
+extern char *supportedExtensions[];
+extern char *supportedControls[];
-void monitor_info( Connection *conn, Operation *op );
+void monitor_info LDAP_P((
+ Connection *conn,
+ Operation *op,
+ char ** attrs,
+ int attrsonly ));
/*
* operation.c
*/
-void op_free( Operation *op );
-Operation * op_add( Operation **olist, BerElement *ber, unsigned long msgid,
- unsigned long tag, char *dn, int id, int connid );
-void op_delete( Operation **olist, Operation *op );
+void slap_op_free LDAP_P(( Operation *op ));
+Operation * slap_op_alloc LDAP_P((
+ BerElement *ber, ber_int_t msgid,
+ ber_tag_t tag, ber_int_t id ));
+
+int slap_op_add LDAP_P(( Operation **olist, Operation *op ));
+int slap_op_remove LDAP_P(( Operation **olist, Operation *op ));
+Operation * slap_op_pop LDAP_P(( Operation **olist ));
/*
* phonetic.c
*/
-char * first_word( char *s );
-char * next_word( char *s );
-char * word_dup( char *w );
-char * phonetic( char *s );
+char * first_word LDAP_P(( char *s ));
+char * next_word LDAP_P(( char *s ));
+char * word_dup LDAP_P(( char *w ));
+char * phonetic LDAP_P(( char *s ));
/*
* repl.c
*/
-void replog( Backend *be, int optype, char *dn, void *change, int flag );
+void replog LDAP_P(( Backend *be, Operation *op, char *dn, void *change ));
/*
* result.c
*/
-void send_ldap_result( Connection *conn, Operation *op, int err, char *matched,
- char *text );
-void send_ldap_search_result( Connection *conn, Operation *op, int err,
- char *matched, char *text, int nentries );
-void close_connection( Connection *conn, int opconnid, int opid );
+struct berval **get_entry_referrals LDAP_P((
+ Backend *be, Connection *conn, Operation *op,
+ Entry *e ));
+
+void send_ldap_result LDAP_P((
+ Connection *conn, Operation *op,
+ int err, char *matched, char *text,
+ struct berval **refs,
+ LDAPControl **ctrls ));
+
+void send_ldap_disconnect LDAP_P((
+ Connection *conn, Operation *op,
+ int err, char *text ));
+
+void send_search_result LDAP_P((
+ Connection *conn, Operation *op,
+ int err, char *matched, char *text,
+ struct berval **refs,
+ LDAPControl **ctrls,
+ int nentries ));
+
+int send_search_reference LDAP_P((
+ Backend *be, Connection *conn, Operation *op,
+ Entry *e, struct berval **refs, int scope,
+ LDAPControl **ctrls,
+ struct berval ***v2refs ));
+
+int send_search_entry LDAP_P((
+ Backend *be, Connection *conn, Operation *op,
+ Entry *e, char **attrs, int attrsonly,
+ LDAPControl **ctrls ));
+
+int str2result LDAP_P(( char *s,
+ int *code, char **matched, char **info ));
+
+/*
+ * sasl.c
+ */
+extern char **supportedSASLMechanisms;
+
+int sasl_init(void);
+int sasl_destroy(void);
/*
* schema.c
*/
-int oc_schema_check( Entry *e );
+int oc_schema_check LDAP_P(( Entry *e ));
+int oc_check_operational_attr LDAP_P(( char *type ));
+int oc_check_usermod_attr LDAP_P(( char *type ));
+int oc_check_no_usermod_attr LDAP_P(( char *type ));
+ObjectClass *oc_find LDAP_P((const char *ocname));
+int oc_add LDAP_P((LDAP_OBJECT_CLASS *oc, const char **err));
+Syntax *syn_find LDAP_P((const char *synname));
+int syn_add LDAP_P((LDAP_SYNTAX *syn, slap_syntax_check_func *check, const char **err));
+MatchingRule *mr_find LDAP_P((const char *mrname));
+int mr_add LDAP_P((LDAP_MATCHING_RULE *mr, slap_mr_normalize_func *normalize, slap_mr_compare_func *compare, const char **err));
+void schema_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly));
+int schema_init LDAP_P((void));
+
+int is_entry_objectclass LDAP_P(( Entry *, char* objectclass ));
+#define is_entry_alias(e) is_entry_objectclass((e), "ALIAS")
+#define is_entry_referral(e) is_entry_objectclass((e), "REFERRAL")
+
/*
* schemaparse.c
*/
-void parse_oc( Backend *be, char *fname, int lineno, int argc, char **argv );
-
+void parse_oc_old LDAP_P(( Backend *be, char *fname, int lineno, int argc, char **argv ));
+void parse_oc LDAP_P(( char *fname, int lineno, char *line ));
+void parse_at LDAP_P(( char *fname, int lineno, char *line ));
+char *scherr2str LDAP_P((int code));
/*
* str2filter.c
*/
-Filter * str2filter( char *str );
+Filter * str2filter LDAP_P(( char *str ));
+
+/*
+ * suffixalias.c
+ */
+char *suffix_alias LDAP_P(( Backend *be, char *ndn ));
/*
* value.c
*/
-int value_add_fast( struct berval ***vals, struct berval **addvals, int nvals,
- int naddvals, int *maxvals );
-int value_add( struct berval ***vals, struct berval **addvals );
-void value_normalize( char *s, int syntax );
-int value_cmp( struct berval *v1, struct berval *v2, int syntax,
- int normalize );
-int value_ncmp( struct berval *v1, struct berval *v2, int syntax, int len,
- int normalize );
-int value_find( struct berval **vals, struct berval *v, int syntax,
- int normalize );
+int value_add_fast LDAP_P(( struct berval ***vals, struct berval **addvals, int nvals,
+ int naddvals, int *maxvals ));
+int value_add LDAP_P(( struct berval ***vals, struct berval **addvals ));
+void value_normalize LDAP_P(( char *s, int syntax ));
+int value_cmp LDAP_P(( struct berval *v1, struct berval *v2, int syntax,
+ int normalize ));
+int value_find LDAP_P(( struct berval **vals, struct berval *v, int syntax,
+ int normalize ));
+
+/*
+ * user.c
+ */
+#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
+void slap_init_user LDAP_P(( char *username, char *groupname ));
+#endif
+
+/*
+ * Other...
+ */
+
+extern struct berval **default_referral;
+extern char *replogfile;
+extern const char Versionstr[];
+extern int active_threads;
+extern int defsize;
+extern int deftime;
+extern int g_argc;
+extern int global_default_access;
+extern int global_lastmod;
+extern int global_idletimeout;
+extern int global_schemacheck;
+extern char *global_realm;
+extern int lber_debug;
+extern int ldap_syslog;
+
+extern ldap_pvt_thread_mutex_t num_sent_mutex;
+extern long num_bytes_sent;
+extern long num_pdu_sent;
+extern long num_entries_sent;
+extern long num_refs_sent;
+
+extern ldap_pvt_thread_mutex_t num_ops_mutex;
+extern long num_ops_completed;
+extern long num_ops_initiated;
+
+extern char *slapd_pid_file;
+extern char *slapd_args_file;
+extern char **g_argv;
+extern time_t starttime;
+
+time_t slap_get_time LDAP_P((void));
+
+extern ldap_pvt_thread_mutex_t active_threads_mutex;
+extern ldap_pvt_thread_cond_t active_threads_cond;
+
+extern ldap_pvt_thread_mutex_t entry2str_mutex;
+extern ldap_pvt_thread_mutex_t replog_mutex;
+
+#ifdef SLAPD_CRYPT
+extern ldap_pvt_thread_mutex_t crypt_mutex;
+#endif
+extern ldap_pvt_thread_mutex_t gmtime_mutex;
+
+extern AccessControl *global_acl;
+
+int slap_init LDAP_P((int mode, char* name));
+int slap_startup LDAP_P(( Backend *be ));
+int slap_shutdown LDAP_P(( Backend *be ));
+int slap_destroy LDAP_P((void));
+
+struct sockaddr_in;
+
+extern int slapd_daemon_init( char *urls, int port, int tls_port );
+extern int slapd_daemon_destroy(void);
+extern int slapd_daemon(void);
+
+extern void slapd_set_write LDAP_P((ber_socket_t s, int wake));
+extern void slapd_clr_write LDAP_P((ber_socket_t s, int wake));
+extern void slapd_set_read LDAP_P((ber_socket_t s, int wake));
+extern void slapd_clr_read LDAP_P((ber_socket_t s, int wake));
+
+extern void slapd_remove LDAP_P((ber_socket_t s, int wake));
+
+extern void slap_set_shutdown LDAP_P((int sig));
+extern void slap_do_nothing LDAP_P((int sig));
+
+extern void config_info LDAP_P((
+ Connection *conn,
+ Operation *op,
+ char ** attrs,
+ int attrsonly ));
+
+extern void root_dse_info LDAP_P((
+ Connection *conn,
+ Operation *op,
+ char ** attrs,
+ int attrsonly ));
+
+extern int do_abandon LDAP_P((Connection *conn, Operation *op));
+extern int do_add LDAP_P((Connection *conn, Operation *op));
+extern int do_bind LDAP_P((Connection *conn, Operation *op));
+extern int do_compare LDAP_P((Connection *conn, Operation *op));
+extern int do_delete LDAP_P((Connection *conn, Operation *op));
+extern int do_modify LDAP_P((Connection *conn, Operation *op));
+extern int do_modrdn LDAP_P((Connection *conn, Operation *op));
+extern int do_search LDAP_P((Connection *conn, Operation *op));
+extern int do_unbind LDAP_P((Connection *conn, Operation *op));
+extern int do_extended LDAP_P((Connection *conn, Operation *op));
+
+
+extern ber_socket_t dtblsize;
+
+LDAP_END_DECL
#endif /* _proto_slap */
+
/* repl.c - log modifications for replication purposes */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
+
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/socket.h>
+
+#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
-#include <sys/socket.h>
-#include <slap.h>
+#endif
-extern pthread_mutex_t replog_mutex;
-extern pthread_mutex_t entry2str_mutex;
-extern time_t currenttime;
-extern char *replogfile;
+#include "slap.h"
-extern FILE *lock_fopen();
-extern int lock_fclose();
-extern char *ch_malloc();
-extern char *entry2str();
void
replog(
Backend *be,
- int optype,
+ Operation *op,
char *dn,
- void *change,
- int flag
+ void *change
)
{
- LDAPMod *mods;
+ LDAPModList *ml;
Entry *e;
- char *newrdn, *tmp;
- int deleteoldrdn;
+ struct replog_moddn *moddn;
+ char *tmp;
FILE *fp, *lfp;
int len, i;
return;
}
- pthread_mutex_lock( &replog_mutex );
+ ldap_pvt_thread_mutex_lock( &replog_mutex );
if ( (fp = lock_fopen( be->be_replogfile ? be->be_replogfile :
replogfile, "a", &lfp )) == NULL ) {
- pthread_mutex_unlock( &replog_mutex );
+ ldap_pvt_thread_mutex_unlock( &replog_mutex );
return;
}
i++ ) {
fprintf( fp, "replica: %s\n", be->be_replica[i] );
}
- fprintf( fp, "time: %ld\n", currenttime );
+ fprintf( fp, "time: %ld\n", (long) slap_get_time() );
fprintf( fp, "dn: %s\n", dn );
- switch ( optype ) {
+ switch ( op->o_tag ) {
case LDAP_REQ_MODIFY:
fprintf( fp, "changetype: modify\n" );
- mods = change;
- for ( ; mods != NULL; mods = mods->mod_next ) {
- switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) {
+ ml = change;
+ for ( ; ml != NULL; ml = ml->ml_next ) {
+ switch ( ml->ml_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_ADD:
- fprintf( fp, "add: %s\n", mods->mod_type );
+ fprintf( fp, "add: %s\n", ml->ml_type );
break;
case LDAP_MOD_DELETE:
- fprintf( fp, "delete: %s\n", mods->mod_type );
+ fprintf( fp, "delete: %s\n", ml->ml_type );
break;
case LDAP_MOD_REPLACE:
- fprintf( fp, "replace: %s\n", mods->mod_type );
+ fprintf( fp, "replace: %s\n", ml->ml_type );
break;
}
- for ( i = 0; mods->mod_bvalues != NULL &&
- mods->mod_bvalues[i] != NULL; i++ ) {
+ for ( i = 0; ml->ml_bvalues != NULL &&
+ ml->ml_bvalues[i] != NULL; i++ ) {
char *buf, *bufp;
- len = strlen( mods->mod_type );
+ len = strlen( ml->ml_type );
len = LDIF_SIZE_NEEDED( len,
- mods->mod_bvalues[i]->bv_len ) + 1;
- buf = ch_malloc( len );
+ ml->ml_bvalues[i]->bv_len ) + 1;
+ buf = (char *) ch_malloc( len );
bufp = buf;
- put_type_and_value( &bufp, mods->mod_type,
- mods->mod_bvalues[i]->bv_val,
- mods->mod_bvalues[i]->bv_len );
+ ldif_sput( &bufp, LDIF_PUT_VALUE,
+ ml->ml_type,
+ ml->ml_bvalues[i]->bv_val,
+ ml->ml_bvalues[i]->bv_len );
*bufp = '\0';
fputs( buf, fp );
case LDAP_REQ_ADD:
e = change;
fprintf( fp, "changetype: add\n" );
- pthread_mutex_lock( &entry2str_mutex );
- tmp = entry2str( e, &len, 0 );
+ ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+ tmp = entry2str( e, &len );
while ( (tmp = strchr( tmp, '\n' )) != NULL ) {
tmp++;
- if ( ! isspace( *tmp ) )
+ if ( ! isspace( (unsigned char) *tmp ) )
break;
}
fprintf( fp, "%s", tmp );
- pthread_mutex_unlock( &entry2str_mutex );
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
break;
case LDAP_REQ_DELETE:
break;
case LDAP_REQ_MODRDN:
- newrdn = change;
+ moddn = change;
fprintf( fp, "changetype: modrdn\n" );
- fprintf( fp, "newrdn: %s\n", newrdn );
- fprintf( fp, "deleteoldrdn: %d\n", flag ? 1 : 0 );
+ fprintf( fp, "newrdn: %s\n", moddn->newrdn );
+ fprintf( fp, "deleteoldrdn: %d\n", moddn->deloldrdn ? 1 : 0 );
+ if( moddn->newsup != NULL ) {
+ fprintf( fp, "newsuperior: %s\n", moddn->newsup );
+ }
}
fprintf( fp, "\n" );
lock_fclose( fp, lfp );
- pthread_mutex_unlock( &replog_mutex );
+ ldap_pvt_thread_mutex_unlock( &replog_mutex );
}
/* result.c - routines to send ldap results, errors, and referrals */
-#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <errno.h>
-#include <signal.h>
#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/errno.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#include "ldap_defaults.h"
#include "slap.h"
-#ifndef SYSERRLIST_IN_STDIO
-extern int sys_nerr;
-extern char *sys_errlist[];
-#endif
-extern int active_threads;
-extern pthread_mutex_t active_threads_mutex;
-extern pthread_mutex_t new_conn_mutex;
-extern pthread_t listener_tid;
-extern struct acl *acl_get_applicable();
-extern long num_entries_sent;
-extern long num_bytes_sent;
-extern pthread_mutex_t num_sent_mutex;
+/* we need LBER internals */
+#include "../../libraries/liblber/lber-int.h"
-void close_connection();
+static char *v2ref( struct berval **ref )
+{
+ size_t len, i;
+ char *v2;
-static void
-send_ldap_result2(
- Connection *conn,
- Operation *op,
- int err,
- char *matched,
- char *text,
- int nentries
-)
+ if(ref == NULL) return NULL;
+
+ len = sizeof("Referral:");
+ v2 = ch_strdup("Referral:");
+
+ for( i=0; ref[i] != NULL; i++ ) {
+ v2 = ch_realloc( v2, len + ref[i]->bv_len + 1 );
+ v2[len-1] = '\n';
+ memcpy(&v2[len], ref[i]->bv_val, ref[i]->bv_len );
+ len += ref[i]->bv_len;
+ }
+
+ v2[len-1] = '\0';
+ return v2;
+}
+
+static ber_tag_t req2res( ber_tag_t tag )
{
- BerElement *ber;
- int rc, sd;
- unsigned long tag, bytes;
+ switch( tag ) {
+ case LDAP_REQ_ADD:
+ case LDAP_REQ_BIND:
+ case LDAP_REQ_COMPARE:
+ case LDAP_REQ_EXTENDED:
+ case LDAP_REQ_MODIFY:
+ case LDAP_REQ_MODRDN:
+ tag++;
+ break;
- Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n", err, matched ?
- matched : "", text ? text : "" );
+ case LDAP_REQ_DELETE:
+ tag = LDAP_RES_DELETE;
+ break;
- switch ( op->o_tag ) {
- case LBER_DEFAULT:
+ case LDAP_REQ_ABANDON:
+ case LDAP_REQ_UNBIND:
tag = LBER_SEQUENCE;
break;
tag = LDAP_RES_SEARCH_RESULT;
break;
- case LDAP_REQ_DELETE:
- tag = LDAP_RES_DELETE;
- break;
-
default:
- tag = op->o_tag + 1;
- break;
+ assert( 0 );
+ tag = LBER_ERROR;
}
+ return tag;
+}
-#ifdef COMPAT30
- if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
- == NULLBER ) {
-#else
- if ( (ber = der_alloc()) == NULLBER ) {
-#endif
- Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
- return;
+static void trim_refs_urls(
+ struct berval **refs )
+{
+ unsigned i;
+
+ if( refs == NULL ) return;
+
+ for( i=0; refs[i] != NULL; i++ ) {
+ if( refs[i]->bv_len > sizeof("ldap://") &&
+ strncasecmp( refs[i]->bv_val, "ldap://",
+ sizeof("ldap://")-1 ) == 0 )
+ {
+ unsigned j;
+ for( j=sizeof("ldap://"); j<refs[i]->bv_len ; j++ ) {
+ if( refs[i]->bv_val[j] = '/' ) {
+ refs[i]->bv_val[j] = '\0';
+ refs[i]->bv_len = j;
+ break;
+ }
+ }
+ }
+ }
+}
+
+struct berval **get_entry_referrals(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e )
+{
+ Attribute *attr;
+ struct berval **refs;
+ unsigned i, j;
+
+ attr = attr_find( e->e_attrs, "ref" );
+
+ if( attr == NULL ) return NULL;
+
+ for( i=0; attr->a_vals[i] != NULL; i++ ) {
+ /* count references */
}
-#ifdef CLDAP
- if ( op->o_cldap ) {
- rc = ber_printf( ber, "{is{t{ess}}}", op->o_msgid, "", tag,
- err, matched ? matched : "", text ? text : "" );
- } else
-#endif
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- rc = ber_printf( ber, "{it{{ess}}}", op->o_msgid, tag, err,
- matched ? matched : "", text ? text : "" );
- } else
-#endif
- rc = ber_printf( ber, "{it{ess}}", op->o_msgid, tag, err,
- matched ? matched : "", text ? text : "" );
+ if( i < 1 ) return NULL;
- if ( rc == -1 ) {
- Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
- return;
+ refs = ch_malloc( i + 1 );
+
+ for( i=0, j=0; attr->a_vals[i] != NULL; i++ ) {
+ unsigned k;
+ struct berval *ref = ber_bvdup( attr->a_vals[i] );
+
+ /* trim the label */
+ for( k=0; k<ref->bv_len; k++ ) {
+ if( isspace(ref->bv_val[k]) ) {
+ ref->bv_val[k] = '\0';
+ ref->bv_len = k;
+ break;
+ }
+ }
+
+ if( ref->bv_len > 0 ) {
+ refs[j++] = ref;
+
+ } else {
+ ber_bvfree( ref );
+ }
+ }
+
+ refs[j] = NULL;
+
+ if( j == 0 ) {
+ ber_bvecfree( refs );
+ refs = NULL;
}
+ /* we should check that a referral value exists... */
+
+ return refs;
+}
+
+static long send_ldap_ber(
+ Connection *conn,
+ BerElement *ber )
+{
+ ber_len_t bytes = ber_pvt_ber_bytes( ber );
+
/* write only one pdu at a time - wait til it's our turn */
- pthread_mutex_lock( &conn->c_pdumutex );
+ ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
+
+ /* lock the connection */
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
/* write the pdu */
- bytes = ber->ber_ptr - ber->ber_buf;
- pthread_mutex_lock( &new_conn_mutex );
- while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
- 1 ) != 0 ) {
- pthread_mutex_unlock( &new_conn_mutex );
+ while( 1 ) {
+ int err;
+
+ if ( connection_state_closing( conn ) ) {
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+ return 0;
+ }
+
+ if ( ber_flush( conn->c_sb, ber, 1 ) == 0 ) {
+ break;
+ }
+
+ err = errno;
+
/*
* we got an error. if it's ewouldblock, we need to
* wait on the socket being writable. otherwise, figure
* it's a hard error and return.
*/
- Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno %d msg (%s)\n",
- errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno]
+ Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno=%d reason=\"%s\"\n",
+ err, err > -1 && err < sys_nerr ? sys_errlist[err]
: "unknown", 0 );
- if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
- close_connection( conn, op->o_connid, op->o_opid );
+ if ( err != EWOULDBLOCK && err != EAGAIN ) {
+ connection_closing( conn );
- pthread_mutex_unlock( &conn->c_pdumutex );
- return;
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+ return( -1 );
}
/* wait for socket to be write-ready */
- pthread_mutex_lock( &active_threads_mutex );
- active_threads--;
conn->c_writewaiter = 1;
- pthread_kill( listener_tid, SIGUSR1 );
- pthread_cond_wait( &conn->c_wcv, &active_threads_mutex );
- pthread_mutex_unlock( &active_threads_mutex );
+ slapd_set_write( ber_pvt_sb_get_desc( conn->c_sb ), 1 );
- pthread_yield();
- pthread_mutex_lock( &new_conn_mutex );
+ ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
+ conn->c_writewaiter = 0;
}
- pthread_mutex_unlock( &new_conn_mutex );
- pthread_mutex_unlock( &conn->c_pdumutex );
- pthread_mutex_lock( &num_sent_mutex );
- num_bytes_sent += bytes;
- pthread_mutex_unlock( &num_sent_mutex );
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
- Statslog( LDAP_DEBUG_STATS,
- "conn=%d op=%d RESULT err=%d tag=%d nentries=%d\n", conn->c_connid,
- op->o_opid, err, tag, nentries );
+ return bytes;
+}
+
+static void
+send_ldap_response(
+ Connection *conn,
+ Operation *op,
+ ber_tag_t tag,
+ ber_int_t msgid,
+ ber_int_t err,
+ char *matched,
+ char *text,
+ struct berval **ref,
+ char *resoid,
+ struct berval *resdata,
+ LDAPControl **ctrls
+)
+{
+ BerElement *ber;
+ int rc;
+ long bytes;
+
+ assert( ctrls == NULL ); /* ctrls not implemented */
+
+ ber = ber_alloc_t( LBER_USE_DER );
+
+ Debug( LDAP_DEBUG_TRACE, "send_ldap_response: msgid=%ld tag=%ld err=%ld\n",
+ (long) msgid, (long) tag, (long) err );
+
+ if ( ber == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
+ return;
+ }
+
+#ifdef LDAP_CONNECTIONLESS
+ if ( op->o_cldap ) {
+ rc = ber_printf( ber, "{is{t{ess}}}", msgid, "", tag,
+ err, matched ? matched : "", text ? text : "" );
+ } else
+#endif
+ {
+ rc = ber_printf( ber, "{it{ess",
+ msgid, tag, err,
+ matched == NULL ? "" : matched,
+ text == NULL ? "" : text );
+
+ if( rc != -1 && ref != NULL ) {
+ rc = ber_printf( ber, "{V}", ref );
+ }
+
+ if( rc != -1 && resoid != NULL ) {
+ rc = ber_printf( ber, "s", resoid );
+ }
+
+ if( rc != -1 && resdata != NULL ) {
+ rc = ber_printf( ber, "O", resdata );
+
+ }
+
+ if( rc != -1 ) {
+ rc = ber_printf( ber, "}}" );
+ }
+ }
+
+ if ( rc == -1 ) {
+ Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
+ return;
+ }
+ /* send BER */
+ bytes = send_ldap_ber( conn, ber );
+
+ if ( bytes < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_ldap_response: ber write failed\n",
+ 0, 0, 0 );
+ return;
+ }
+
+ ldap_pvt_thread_mutex_lock( &num_sent_mutex );
+ num_bytes_sent += bytes;
+ num_pdu_sent++;
+ ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
return;
}
+
void
-send_ldap_result(
+send_ldap_disconnect(
Connection *conn,
Operation *op,
- int err,
- char *matched,
+ ber_int_t err,
char *text
)
{
-#ifdef CLDAP
+ ber_tag_t tag;
+ ber_int_t msgid;
+ char *reqoid;
+
+#define LDAP_UNSOLICITED_ERROR(e) \
+ ( (e) == LDAP_PROTOCOL_ERROR \
+ || (e) == LDAP_STRONG_AUTH_REQUIRED \
+ || (e) == LDAP_UNAVAILABLE )
+
+ assert( LDAP_UNSOLICITED_ERROR( err ) );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "send_ldap_disconnect %d:%s\n",
+ err, text ? text : "", NULL );
+
+ if ( op->o_protocol < LDAP_VERSION3 ) {
+ reqoid = NULL;
+ tag = req2res( op->o_tag );
+ msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
+
+ } else {
+ reqoid = LDAP_NOTICE_DISCONNECT;
+ tag = LDAP_RES_EXTENDED;
+ msgid = 0;
+ }
+
+#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
- SAFEMEMCPY( (char *)conn->c_sb.sb_useaddr, &op->o_clientaddr,
- sizeof( struct sockaddr ));
+ ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
- conn->c_sb.sb_useaddr)->sin_addr ),
- ((struct sockaddr_in *) conn->c_sb.sb_useaddr)->sin_port,
+ &op->o_clientaddr)->sin_addr ),
+ ((struct sockaddr_in *) &op->o_clientaddr)->sin_port,
0 );
}
#endif
- send_ldap_result2( conn, op, err, matched, text, 0 );
+ send_ldap_response( conn, op, tag, msgid,
+ err, NULL, text, NULL,
+ reqoid, NULL, NULL );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld op=%ld DISCONNECT err=%ld tag=%lu text=%s\n",
+ (long) op->o_connid, (long) op->o_opid,
+ (long) tag, (long) err, text ? text : "" );
}
void
-send_ldap_search_result(
+send_ldap_result(
Connection *conn,
Operation *op,
- int err,
+ ber_int_t err,
char *matched,
char *text,
+ struct berval **ref,
+ LDAPControl **ctrls
+)
+{
+ ber_tag_t tag;
+ ber_int_t msgid;
+ char *tmp = NULL;
+
+ assert( !LDAP_API_ERROR( err ) );
+
+ Debug( LDAP_DEBUG_TRACE, "send_ldap_result: conn=%ld op=%ld p=%d\n",
+ (long) op->o_connid, (long) op->o_opid, op->o_protocol );
+ Debug( LDAP_DEBUG_ARGS, "send_ldap_result: %d:%s:%s\n",
+ err, matched ? matched : "", text ? text : "" );
+
+ assert( err != LDAP_PARTIAL_RESULTS );
+
+ if( op->o_tag != LDAP_REQ_SEARCH ) {
+ trim_refs_urls( ref );
+ }
+
+ if ( err == LDAP_REFERRAL ) {
+ if( ref == NULL ) {
+ err = LDAP_NO_SUCH_OBJECT;
+ } else if ( op->o_protocol < LDAP_VERSION3 ) {
+ err = LDAP_PARTIAL_RESULTS;
+ tmp = text = v2ref( ref );
+ ref = NULL;
+ }
+ }
+
+ tag = req2res( op->o_tag );
+ msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
+
+#ifdef LDAP_CONNECTIONLESS
+ if ( op->o_cldap ) {
+ ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
+ Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
+ inet_ntoa(((struct sockaddr_in *)
+ &op->o_clientaddr)->sin_addr ),
+ ((struct sockaddr_in *) &op->o_clientaddr)->sin_port,
+ 0 );
+ }
+#endif
+
+ send_ldap_response( conn, op, tag, msgid,
+ err, matched, text, ref,
+ NULL, NULL, ctrls );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld op=%ld RESULT tag=%lu err=%ld text=%s\n",
+ (long) op->o_connid, (long) op->o_opid,
+ (long) tag, (long) err, text ? text : "" );
+
+ if( tmp != NULL ) {
+ free(tmp);
+ }
+}
+
+
+void
+send_search_result(
+ Connection *conn,
+ Operation *op,
+ ber_int_t err,
+ char *matched,
+ char *text,
+ struct berval **refs,
+ LDAPControl **ctrls,
int nentries
)
{
- send_ldap_result2( conn, op, err, matched, text, nentries );
+ ber_tag_t tag;
+ ber_int_t msgid;
+ char *tmp = NULL;
+ assert( !LDAP_API_ERROR( err ) );
+
+ Debug( LDAP_DEBUG_TRACE, "send_ldap_search_result %d:%s:%s\n",
+ err, matched ? matched : "", text ? text : "" );
+
+ assert( err != LDAP_PARTIAL_RESULTS );
+
+ trim_refs_urls( refs );
+
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ /* send references in search results */
+ if( err == LDAP_REFERRAL ) {
+ err = LDAP_PARTIAL_RESULTS;
+ }
+
+ tmp = text = v2ref( refs );
+ refs = NULL;
+
+ } else {
+ /* don't send references in search results */
+ assert( refs == NULL );
+ refs = NULL;
+
+ if( err == LDAP_REFERRAL ) {
+ err = LDAP_SUCCESS;
+ }
+ }
+
+ tag = req2res( op->o_tag );
+ msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
+
+#ifdef LDAP_CONNECTIONLESS
+ if ( op->o_cldap ) {
+ ber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr );
+ Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
+ inet_ntoa(((struct sockaddr_in *)
+ &op->o_clientaddr)->sin_addr ),
+ ((struct sockaddr_in *) &op->o_clientaddr)->sin_port,
+ 0 );
+ }
+#endif
+
+ send_ldap_response( conn, op, tag, msgid,
+ err, matched, text, refs,
+ NULL, NULL, ctrls );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld op=%ld SEARCH RESULT tag=%lu err=%ld text=%s\n",
+ (long) op->o_connid, (long) op->o_opid,
+ (long) tag, (long) err, text ? text : "" );
+
}
+
int
send_search_entry(
Backend *be,
Operation *op,
Entry *e,
char **attrs,
- int attrsonly
+ int attrsonly,
+ LDAPControl **ctrls
)
{
BerElement *ber;
Attribute *a;
- int i, rc, bytes, sd;
- struct acl *acl;
+ int i, rc=-1, bytes;
+ AccessControl *acl;
+ char *edn;
+ int userattrs;
+ int opattrs;
- Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "=> send_search_entry: \"%s\"\n", e->e_dn, 0, 0 );
- if ( ! access_allowed( be, conn, op, e, "entry", NULL, op->o_dn,
- ACL_READ ) ) {
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_READ ) )
+ {
Debug( LDAP_DEBUG_ACL, "acl: access to entry not allowed\n",
0, 0, 0 );
return( 1 );
}
-#ifdef COMPAT30
- if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
- == NULLBER ) {
-#else
- if ( (ber = der_alloc()) == NULLBER ) {
-#endif
+ edn = e->e_ndn;
+
+ ber = ber_alloc_t( LBER_USE_DER );
+
+ if ( ber == NULL ) {
Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ber_alloc" );
- return( 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "allocating BER error", NULL, NULL );
+ goto error_return;
}
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- rc = ber_printf( ber, "{it{{s{", op->o_msgid,
- LDAP_RES_SEARCH_ENTRY, e->e_dn );
- } else
-#endif
- rc = ber_printf( ber, "{it{s{", op->o_msgid,
- LDAP_RES_SEARCH_ENTRY, e->e_dn );
+ rc = ber_printf( ber, "{it{s{", op->o_msgid,
+ LDAP_RES_SEARCH_ENTRY, e->e_dn );
if ( rc == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ber_printf dn" );
- return( 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encoding dn error", NULL, NULL );
+ goto error_return;
}
+ /* check for special all user attributes ("*") type */
+ userattrs = ( attrs == NULL ) ? 1
+ : charray_inlist( attrs, LDAP_ALL_USER_ATTRIBUTES );
+
+ /* check for special all operational attributes ("+") type */
+ opattrs = ( attrs == NULL ) ? 0
+ : charray_inlist( attrs, LDAP_ALL_OPERATIONAL_ATTRIBUTES );
+
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- if ( attrs != NULL && ! charray_inlist( attrs, a->a_type ) ) {
- continue;
+ regmatch_t matches[MAXREMATCHES];
+
+ if ( attrs == NULL ) {
+ /* all addrs request, skip operational attributes */
+ if( !opattrs && oc_check_operational_attr( a->a_type ) ) {
+ continue;
+ }
+
+ } else {
+ /* specific addrs requested */
+ if ( oc_check_operational_attr( a->a_type ) ) {
+ if( !opattrs && !charray_inlist( attrs, a->a_type ) )
+ {
+ continue;
+ }
+ } else {
+ if (!userattrs && !charray_inlist( attrs, a->a_type ) )
+ {
+ continue;
+ }
+ }
}
- acl = acl_get_applicable( be, op, e, a->a_type );
+ acl = acl_get_applicable( be, op, e, a->a_type,
+ MAXREMATCHES, matches );
- if ( ! acl_access_allowed( acl, be, conn, e, NULL, op,
- ACL_READ ) ) {
+ if ( ! acl_access_allowed( acl, be, conn, e,
+ NULL, op, ACL_READ, edn, matches ) )
+ {
continue;
}
- if ( ber_printf( ber, "{s[", a->a_type ) == -1 ) {
+ if (( rc = ber_printf( ber, "{s[" /*]}*/ , a->a_type )) == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, "ber_printf type" );
- return( 1 );
+ NULL, "encoding type error", NULL, NULL );
+ goto error_return;
}
if ( ! attrsonly ) {
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
- if ( a->a_syntax & SYNTAX_DN &&
- ! acl_access_allowed( acl, be, conn, e,
- a->a_vals[i], op, ACL_READ ) )
+ if ( a->a_syntax & SYNTAX_DN &&
+ ! acl_access_allowed( acl, be, conn, e, a->a_vals[i], op,
+ ACL_READ, edn, matches) )
{
continue;
}
- if ( ber_printf( ber, "o",
- a->a_vals[i]->bv_val,
- a->a_vals[i]->bv_len ) == -1 )
- {
+ if (( rc = ber_printf( ber, "O", a->a_vals[i] )) == -1 ) {
Debug( LDAP_DEBUG_ANY,
"ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
- send_ldap_result( conn, op,
- LDAP_OPERATIONS_ERROR, NULL,
- "ber_printf value" );
- return( 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encoding value error", NULL, NULL );
+ goto error_return;
}
}
}
- if ( ber_printf( ber, "]}" ) == -1 ) {
+ if (( rc = ber_printf( ber, /*{[*/ "]}" )) == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, "ber_printf type end" );
- return( 1 );
+ NULL, "encode end error", NULL, NULL );
+ goto error_return;
}
}
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- rc = ber_printf( ber, "}}}}" );
- } else
+#ifdef SLAPD_SCHEMA_DN
+ /* eventually will loop through generated operational attributes */
+ /* only have subschemaSubentry implemented */
+ a = backend_subschemasubentry( be );
+
+ do {
+ regmatch_t matches[MAXREMATCHES];
+
+ if ( attrs == NULL ) {
+ /* all addrs request, skip operational attributes */
+ if( !opattrs && oc_check_operational_attr( a->a_type ) ) {
+ continue;
+ }
+
+ } else {
+ /* specific addrs requested */
+ if ( oc_check_operational_attr( a->a_type ) ) {
+ if( !opattrs && !charray_inlist( attrs, a->a_type ) )
+ {
+ continue;
+ }
+ } else {
+ if (!userattrs && !charray_inlist( attrs, a->a_type ) )
+ {
+ continue;
+ }
+ }
+ }
+
+ acl = acl_get_applicable( be, op, e, a->a_type,
+ MAXREMATCHES, matches );
+
+ if ( ! acl_access_allowed( acl, be, conn, e,
+ NULL, op, ACL_READ, edn, matches ) )
+ {
+ continue;
+ }
+
+ if (( rc = ber_printf( ber, "{s[" /*]}*/ , a->a_type )) == -1 ) {
+ Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
+ ber_free( ber, 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encoding type error", NULL, NULL );
+ goto error_return;
+ }
+
+ if ( ! attrsonly ) {
+ for ( i = 0; a->a_vals[i] != NULL; i++ ) {
+ if ( a->a_syntax & SYNTAX_DN &&
+ ! acl_access_allowed( acl, be, conn, e, a->a_vals[i], op,
+ ACL_READ, edn, matches) )
+ {
+ continue;
+ }
+
+ if (( rc = ber_printf( ber, "O", a->a_vals[i] )) == -1 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "ber_printf failed\n", 0, 0, 0 );
+ ber_free( ber, 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encoding value error", NULL, NULL );
+ goto error_return;
+ }
+ }
+ }
+
+ if (( rc = ber_printf( ber, /*{[*/ "]}" )) == -1 ) {
+ Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
+ ber_free( ber, 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encode end error", NULL, NULL );
+ goto error_return;
+ }
+ } while (0);
#endif
- rc = ber_printf( ber, "}}}" );
+
+ rc = ber_printf( ber, /*{{{*/ "}}}" );
if ( rc == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ber_printf entry end" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encode entry end error", NULL, NULL );
return( 1 );
}
- /* write only one pdu at a time - wait til it's our turn */
- pthread_mutex_lock( &conn->c_pdumutex );
+ bytes = send_ldap_ber( conn, ber );
- bytes = ber->ber_ptr - ber->ber_buf;
- pthread_mutex_lock( &new_conn_mutex );
- while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
- 1 ) != 0 ) {
- pthread_mutex_unlock( &new_conn_mutex );
- /*
- * we got an error. if it's ewouldblock, we need to
- * wait on the socket being writable. otherwise, figure
- * it's a hard error and return.
- */
+ if ( bytes < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_ldap_response: ber write failed\n",
+ 0, 0, 0 );
+ return -1;
+ }
- Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno %d msg (%s)\n",
- errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno]
- : "unknown", 0 );
+ ldap_pvt_thread_mutex_lock( &num_sent_mutex );
+ num_bytes_sent += bytes;
+ num_entries_sent++;
+ num_pdu_sent++;
+ ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
- if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
- close_connection( conn, op->o_connid, op->o_opid );
+ Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld ENTRY dn=\"%s\"\n",
+ (long) conn->c_connid, (long) op->o_opid, e->e_dn, 0, 0 );
- pthread_mutex_unlock( &conn->c_pdumutex );
- return( -1 );
+ Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
+
+ rc = 0;
+
+error_return:;
+ return( rc );
+}
+
+int
+send_search_reference(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ struct berval **refs,
+ int scope,
+ LDAPControl **ctrls,
+ struct berval ***v2refs
+)
+{
+ BerElement *ber;
+ int rc;
+ int bytes;
+
+ Debug( LDAP_DEBUG_TRACE, "=> send_search_reference (%s)\n", e->e_dn, 0, 0 );
+
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_READ ) )
+ {
+ Debug( LDAP_DEBUG_ACL,
+ "send_search_reference: access to entry not allowed\n",
+ 0, 0, 0 );
+ return( 1 );
+ }
+
+ if ( ! access_allowed( be, conn, op, e,
+ "ref", NULL, ACL_READ ) )
+ {
+ Debug( LDAP_DEBUG_ACL,
+ "send_search_reference: access to reference not allowed\n",
+ 0, 0, 0 );
+ return( 1 );
+ }
+
+ if( refs == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_search_reference: null ref in (%s)\n",
+ e->e_dn, 0, 0 );
+ return( 1 );
+ }
+
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ /* save the references for the result */
+ if( *refs == NULL ) {
+ value_add( v2refs, refs );
}
+ return 0;
+ }
- /* wait for socket to be write-ready */
- pthread_mutex_lock( &active_threads_mutex );
- active_threads--;
- conn->c_writewaiter = 1;
- pthread_kill( listener_tid, SIGUSR1 );
- pthread_cond_wait( &conn->c_wcv, &active_threads_mutex );
- pthread_mutex_unlock( &active_threads_mutex );
+ ber = ber_alloc_t( LBER_USE_DER );
- pthread_yield();
- pthread_mutex_lock( &new_conn_mutex );
+ if ( ber == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_search_reference: ber_alloc failed\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "alloc BER error", NULL, NULL );
+ return -1;
}
- pthread_mutex_unlock( &new_conn_mutex );
- pthread_mutex_unlock( &conn->c_pdumutex );
- pthread_mutex_lock( &num_sent_mutex );
- num_bytes_sent += bytes;
- num_entries_sent++;
- pthread_mutex_unlock( &num_sent_mutex );
+ rc = ber_printf( ber, "{it{V}}", op->o_msgid,
+ LDAP_RES_SEARCH_REFERENCE, refs );
- pthread_mutex_lock( &new_conn_mutex );
- if ( conn->c_connid == op->o_connid ) {
- rc = 0;
- Statslog( LDAP_DEBUG_STATS2, "conn=%d op=%d ENTRY dn=\"%s\"\n",
- conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
- } else {
- rc = -1;
+ if ( rc == -1 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_search_reference: ber_printf failed\n", 0, 0, 0 );
+ ber_free( ber, 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encode dn error", NULL, NULL );
+ return -1;
}
- pthread_mutex_unlock( &new_conn_mutex );
- Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
+ bytes = send_ldap_ber( conn, ber );
- return( rc );
+ ldap_pvt_thread_mutex_lock( &num_sent_mutex );
+ num_bytes_sent += bytes;
+ num_refs_sent++;
+ num_pdu_sent++;
+ ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
+
+ Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld ENTRY dn=\"%s\"\n",
+ (long) conn->c_connid, (long) op->o_opid, e->e_dn, 0, 0 );
+
+ Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
+
+ return 0;
}
+
int
str2result(
char *s,
return( rc );
}
-
-/*
- * close_connection - close a connection. takes the connection to close,
- * the connid associated with the operation generating the close (so we
- * don't accidentally close a connection that's not ours), and the opid
- * of the operation generating the close (for logging purposes).
- */
-void
-close_connection( Connection *conn, int opconnid, int opid )
-{
- pthread_mutex_lock( &new_conn_mutex );
- if ( conn->c_sb.sb_sd != -1 && conn->c_connid == opconnid ) {
- Statslog( LDAP_DEBUG_STATS,
- "conn=%d op=%d fd=%d closed errno=%d\n", conn->c_connid,
- opid, conn->c_sb.sb_sd, errno, 0 );
- close( conn->c_sb.sb_sd );
- conn->c_sb.sb_sd = -1;
- conn->c_version = 0;
- }
- pthread_mutex_unlock( &new_conn_mutex );
-}
--- /dev/null
+/* root_dse.c - Provides the ROOT DSA-Specific Entry
+ *
+ * Copyright 1999 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+
+#include "ldap_defaults.h"
+#include "slap.h"
+
+void
+root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
+{
+ char buf[BUFSIZ];
+ Entry *e;
+ struct berval val;
+ struct berval *vals[2];
+ int i, j;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
+ e->e_attrs = NULL;
+ e->e_dn = ch_strdup( LDAP_ROOT_DSE );
+ e->e_ndn = ch_strdup( LDAP_ROOT_DSE );
+ (void) dn_normalize_case( e->e_ndn );
+ e->e_private = NULL;
+
+ for ( i = 0; i < nbackends; i++ ) {
+ for ( j = 0; backends[i].be_suffix[j] != NULL; j++ ) {
+ val.bv_val = backends[i].be_suffix[j];
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "namingContexts", vals );
+ }
+ }
+
+#if defined( SLAPD_MONITOR_DN )
+ val.bv_val = SLAPD_MONITOR_DN;
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "namingContexts", vals );
+ /* subschemasubentry is added by send_search_entry() */
+#endif
+
+#if defined( SLAPD_CONFIG_DN )
+ val.bv_val = SLAPD_CONFIG_DN;
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "namingContexts", vals );
+#endif
+
+#if defined( SLAPD_SCHEMA_DN )
+ val.bv_val = SLAPD_SCHEMA_DN;
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "namingContexts", vals );
+#endif
+
+ /* altServer unsupported */
+
+ /* supportedControl */
+ for ( i=0; supportedControls[i] != NULL; i++ ) {
+ val.bv_val = supportedControls[i];
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "supportedControl", vals );
+ }
+
+ /* supportedExtension */
+ for ( i=0; supportedExtensions[i] != NULL; i++ ) {
+ val.bv_val = supportedExtensions[i];
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "supportedExtension", vals );
+ }
+
+ /* supportedLDAPVersion */
+ for ( i=LDAP_VERSION_MIN; i<=LDAP_VERSION_MAX; i++ ) {
+ sprintf(buf,"%d",i);
+ val.bv_val = buf;
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "supportedLDAPVersion", vals );
+ }
+
+ /* supportedSASLMechanism */
+ if( supportedSASLMechanisms != NULL ) {
+ for ( i=0; supportedSASLMechanisms[i] != NULL; i++ ) {
+ val.bv_val = supportedSASLMechanisms[i];
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "supportedSASLMechanisms", vals );
+ }
+ }
+
+ if ( default_referral != NULL ) {
+ attr_merge( e, "ref", default_referral );
+ }
+
+ val.bv_val = "top";
+ val.bv_len = sizeof("top")-1;
+ attr_merge( e, "objectClass", vals );
+
+ val.bv_val = "LDAPsubentry";
+ val.bv_len = sizeof("LDAPsubentry")-1;
+ attr_merge( e, "objectClass", vals );
+
+ val.bv_val = "extensibleObject";
+ val.bv_len = sizeof("extensibleObject")-1;
+ attr_merge( e, "objectClass", vals );
+
+ send_search_entry( &backends[0], conn, op,
+ e, attrs, attrsonly, NULL );
+ send_search_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 1 );
+
+ entry_free( e );
+}
+
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <ac/stdlib.h>
+#include <stdio.h>
+
+#include "slap.h"
+#include "proto-slap.h"
+
+#include <lber.h>
+#include <ldap_log.h>
+
+char **supportedSASLMechanisms = NULL;
+
+#ifdef HAVE_CYRUS_SASL
+static sasl_callback_t callbacks[] = {
+ { SASL_CB_LIST_END, NULL, NULL }
+};
+
+int sasl_init( void )
+{
+ int rc;
+ char *mechs;
+ sasl_conn_t *server = NULL;
+
+ rc = sasl_server_init( callbacks, "slapd" );
+
+ if( rc != SASL_OK ) {
+ Debug( LDAP_DEBUG_ANY, "sasl_server_init failed\n",
+ 0, 0, 0 );
+ return -1;
+ }
+
+ rc = sasl_server_new( "ldap", NULL, NULL, NULL,
+ SASL_SECURITY_LAYER,
+ &server );
+
+ if( rc != SASL_OK ) {
+ Debug( LDAP_DEBUG_ANY, "sasl_server_new failed\n",
+ 0, 0, 0 );
+ return -1;
+ }
+
+#ifdef RESTRICT_SASL
+ {
+ sasl_security_properties_t secprops;
+ memset(&secprops, 0, sizeof(secprops));
+ secprops.security_flags = SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS;
+ secprops.property_names = NULL;
+ secprops.property_values = NULL;
+
+ rc = sasl_setprop( server, SASL_SEC_PROPS, &secprops );
+
+ if( rc != SASL_OK ) {
+ Debug( LDAP_DEBUG_ANY, "sasl_setprop failed\n",
+ 0, 0, 0 );
+ return -1;
+ }
+ }
+#endif
+
+ rc = sasl_listmech( server, NULL, NULL, ",", NULL,
+ &mechs, NULL, NULL);
+
+ if( rc != SASL_OK ) {
+ Debug( LDAP_DEBUG_ANY, "sasl_listmech failed: %d\n",
+ rc, 0, 0 );
+ return -1;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "SASL mechanisms: %s\n",
+ mechs, 0, 0 );
+
+ supportedSASLMechanisms = str2charray( mechs, "," );
+ sasl_dispose( &server );
+
+ return 0;
+}
+
+int sasl_destroy( void )
+{
+ charray_free( supportedSASLMechanisms );
+ return 0;
+}
+
+#else
+/* no SASL support */
+int sasl_init( void ) { return 0; }
+int sasl_destroy( void ) { return 0; }
+#endif
/* schema.c - routines to enforce schema definitions */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Attribute *attr_find();
-extern char **str2charray();
-extern void charray_merge();
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "ldap_defaults.h"
+#include "slap.h"
-extern struct objclass *global_oc;
-extern int global_schemacheck;
+static char * oc_check_required(Entry *e, char *ocname);
+static int oc_check_allowed(char *type, struct berval **ocl);
-static struct objclass *oc_find();
-static int oc_check_required();
-static int oc_check_allowed();
/*
* oc_check - check that entry e conforms to the schema required by
oc_schema_check( Entry *e )
{
Attribute *a, *aoc;
- struct objclass *oc;
int i;
int ret = 0;
if ( (aoc = attr_find( e->e_attrs, "objectclass" )) == NULL ) {
Debug( LDAP_DEBUG_ANY, "No object class for entry (%s)\n",
e->e_dn, 0, 0 );
- return( 0 );
+ return( 1 );
}
/* check that the entry has required attrs for each oc */
for ( i = 0; aoc->a_vals[i] != NULL; i++ ) {
- if ( oc_check_required( e, aoc->a_vals[i]->bv_val ) != 0 ) {
+ char *s = oc_check_required( e, aoc->a_vals[i]->bv_val );
+
+ if (s != NULL) {
Debug( LDAP_DEBUG_ANY,
- "Entry (%s), required attr (%s) missing\n",
- e->e_dn, aoc->a_vals[i]->bv_val, 0 );
+ "Entry (%s), oc \"%s\" requires attr \"%s\"\n",
+ e->e_dn, aoc->a_vals[i]->bv_val, s );
ret = 1;
}
}
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
if ( oc_check_allowed( a->a_type, aoc->a_vals ) != 0 ) {
Debug( LDAP_DEBUG_ANY,
- "Entry (%s), attr (%s) not allowed\n",
+ "Entry (%s), attr \"%s\" not allowed\n",
e->e_dn, a->a_type, 0 );
ret = 1;
}
return( ret );
}
-static int
+static char *
oc_check_required( Entry *e, char *ocname )
{
- struct objclass *oc;
+ ObjectClass *oc;
+ AttributeType *at;
int i;
Attribute *a;
+ char **pp;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "oc_check_required entry (%s), objectclass \"%s\"\n",
+ e->e_dn, ocname, 0 );
/* find global oc defn. it we don't know about it assume it's ok */
if ( (oc = oc_find( ocname )) == NULL ) {
return( 0 );
}
+ /* check for empty oc_required */
+ if(oc->soc_required == NULL) {
+ return( 0 );
+ }
+
/* for each required attribute */
- for ( i = 0; oc->oc_required[i] != NULL; i++ ) {
+ for ( i = 0; oc->soc_required[i] != NULL; i++ ) {
+ at = oc->soc_required[i];
/* see if it's in the entry */
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- if ( strcasecmp( a->a_type, oc->oc_required[i] )
- == 0 ) {
+ if ( at->sat_oid &&
+ strcmp( a->a_type, at->sat_oid ) == 0 ) {
+ break;
+ }
+ pp = at->sat_names;
+ if ( pp == NULL ) {
+ /* Empty name list => not found */
+ a = NULL;
+ break;
+ }
+ while ( *pp ) {
+ if ( strcasecmp( a->a_type, *pp ) == 0 ) {
+ break;
+ }
+ pp++;
+ }
+ if ( *pp ) {
break;
}
}
-
/* not there => schema violation */
if ( a == NULL ) {
- return( 1 );
+ if ( at->sat_names && at->sat_names[0] ) {
+ return at->sat_names[0];
+ } else {
+ return at->sat_oid;
+ }
}
}
- return( 0 );
+ return( NULL );
+}
+
+static char *oc_usermod_attrs[] = {
+ /*
+ * OpenLDAP doesn't support any user modification of
+ * operational attributes.
+ */
+ NULL
+};
+
+static char *oc_operational_attrs[] = {
+ /*
+ * these are operational attributes
+ * most could be user modifiable
+ */
+ "objectClasses",
+ "attributeTypes",
+ "matchingRules",
+ "matchingRuleUse",
+ "dITStructureRules",
+ "dITContentRules",
+ "nameForms",
+ "ldapSyntaxes",
+ "namingContexts",
+ "supportedExtension",
+ "supportedControl",
+ "supportedSASLMechanisms",
+ "supportedLDAPversion",
+ "subschemaSubentry", /* NO USER MOD */
+ NULL
+
+};
+
+/* this list should be extensible */
+static char *oc_no_usermod_attrs[] = {
+ /*
+ * Operational and 'no user modification' attributes
+ * which are STORED in the directory server.
+ */
+
+ /* RFC2252, 3.2.1 */
+ "creatorsName",
+ "createTimestamp",
+ "modifiersName",
+ "modifyTimestamp",
+
+ NULL
+};
+
+
+/*
+ * check to see if attribute is 'operational' or not.
+ */
+int
+oc_check_operational_attr( char *type )
+{
+ return charray_inlist( oc_operational_attrs, type )
+ || charray_inlist( oc_usermod_attrs, type )
+ || charray_inlist( oc_no_usermod_attrs, type );
+}
+
+/*
+ * check to see if attribute can be user modified or not.
+ */
+int
+oc_check_usermod_attr( char *type )
+{
+ return charray_inlist( oc_usermod_attrs, type );
+}
+
+/*
+ * check to see if attribute is 'no user modification' or not.
+ */
+int
+oc_check_no_usermod_attr( char *type )
+{
+ return charray_inlist( oc_no_usermod_attrs, type );
}
+
static int
oc_check_allowed( char *type, struct berval **ocl )
{
- struct objclass *oc;
+ ObjectClass *oc;
+ AttributeType *at;
int i, j;
+ char **pp;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "oc_check_allowed type \"%s\"\n", type, 0, 0 );
/* always allow objectclass attribute */
if ( strcasecmp( type, "objectclass" ) == 0 ) {
return( 0 );
}
+ /*
+ * All operational attributions are allowed by schema rules.
+ * However, we only check attributions which are stored in the
+ * the directory regardless if they are user or non-user modified.
+ */
+ if ( oc_check_usermod_attr( type ) || oc_check_no_usermod_attr( type ) ) {
+ return( 0 );
+ }
+
/* check that the type appears as req or opt in at least one oc */
for ( i = 0; ocl[i] != NULL; i++ ) {
/* if we know about the oc */
if ( (oc = oc_find( ocl[i]->bv_val )) != NULL ) {
/* does it require the type? */
- for ( j = 0; oc->oc_required[j] != NULL; j++ ) {
- if ( strcasecmp( oc->oc_required[j], type )
- == 0 ) {
+ for ( j = 0; oc->soc_required != NULL &&
+ oc->soc_required[j] != NULL; j++ ) {
+ at = oc->soc_required[j];
+ if ( at->sat_oid &&
+ strcmp(at->sat_oid, type ) == 0 ) {
return( 0 );
}
+ pp = at->sat_names;
+ if ( pp == NULL )
+ continue;
+ while ( *pp ) {
+ if ( strcasecmp( *pp, type ) == 0 ) {
+ return( 0 );
+ }
+ pp++;
+ }
}
/* does it allow the type? */
- for ( j = 0; oc->oc_allowed[j] != NULL; j++ ) {
- if ( strcasecmp( oc->oc_allowed[j], type )
- == 0 || strcmp( oc->oc_allowed[j], "*" )
- == 0 )
- {
+ for ( j = 0; oc->soc_allowed != NULL &&
+ oc->soc_allowed[j] != NULL; j++ ) {
+ at = oc->soc_allowed[j];
+ if ( at->sat_oid &&
+ strcmp(at->sat_oid, type ) == 0 ) {
return( 0 );
}
+ pp = at->sat_names;
+ if ( pp == NULL )
+ continue;
+ while ( *pp ) {
+ if ( strcasecmp( *pp, type ) == 0 ||
+ strcmp( *pp, "*" ) == 0 ) {
+ return( 0 );
+ }
+ pp++;
+ }
}
/* maybe the next oc allows it */
return( 1 );
}
-static struct objclass *
-oc_find( char *ocname )
+struct oindexrec {
+ char *oir_name;
+ ObjectClass *oir_oc;
+};
+
+static Avlnode *oc_index = NULL;
+static ObjectClass *oc_list = NULL;
+
+static int
+oc_index_cmp(
+ struct oindexrec *oir1,
+ struct oindexrec *oir2
+)
{
- struct objclass *oc;
+ return (strcasecmp( oir1->oir_name, oir2->oir_name ));
+}
- for ( oc = global_oc; oc != NULL; oc = oc->oc_next ) {
- if ( strcasecmp( oc->oc_name, ocname ) == 0 ) {
- return( oc );
+static int
+oc_index_name_cmp(
+ char *name,
+ struct oindexrec *oir
+)
+{
+ return (strcasecmp( name, oir->oir_name ));
+}
+
+ObjectClass *
+oc_find( const char *ocname )
+{
+ struct oindexrec *oir = NULL;
+
+ if ( (oir = (struct oindexrec *) avl_find( oc_index, ocname,
+ (AVL_CMP) oc_index_name_cmp )) != NULL ) {
+ return( oir->oir_oc );
+ }
+ return( NULL );
+}
+
+static int
+oc_create_required(
+ ObjectClass *soc,
+ char **attrs,
+ const char **err
+)
+{
+ char **attrs1;
+ AttributeType *sat;
+ AttributeType **satp;
+ int i;
+
+ if ( attrs ) {
+ attrs1 = attrs;
+ while ( *attrs1 ) {
+ sat = at_find(*attrs1);
+ if ( !sat ) {
+ *err = *attrs1;
+ return SLAP_SCHERR_ATTR_NOT_FOUND;
+ }
+ if ( at_find_in_list(sat, soc->soc_required) < 0) {
+ if ( at_append_to_list(sat, &soc->soc_required) ) {
+ *err = *attrs1;
+ return SLAP_SCHERR_OUTOFMEM;
+ }
+ }
+ attrs1++;
+ }
+ /* Now delete duplicates from the allowed list */
+ for ( satp = soc->soc_required; *satp; satp++ ) {
+ i = at_find_in_list(*satp,soc->soc_allowed);
+ if ( i >= 0 ) {
+ at_delete_from_list(i, &soc->soc_allowed);
+ }
}
}
+ return 0;
+}
+
+static int
+oc_create_allowed(
+ ObjectClass *soc,
+ char **attrs,
+ const char **err
+)
+{
+ char **attrs1;
+ AttributeType *sat;
+
+ if ( attrs ) {
+ attrs1 = attrs;
+ while ( *attrs1 ) {
+ sat = at_find(*attrs1);
+ if ( !sat ) {
+ *err = *attrs1;
+ return SLAP_SCHERR_ATTR_NOT_FOUND;
+ }
+ if ( at_find_in_list(sat, soc->soc_required) < 0 &&
+ at_find_in_list(sat, soc->soc_allowed) < 0 ) {
+ if ( at_append_to_list(sat, &soc->soc_allowed) ) {
+ *err = *attrs1;
+ return SLAP_SCHERR_OUTOFMEM;
+ }
+ }
+ attrs1++;
+ }
+ }
+ return 0;
+}
+
+static int
+oc_add_sups(
+ ObjectClass *soc,
+ char **sups,
+ const char **err
+)
+{
+ int code;
+ ObjectClass *soc1;
+ int nsups;
+ char **sups1;
+ int add_sups = 0;
+
+ if ( sups ) {
+ if ( !soc->soc_sups ) {
+ /* We are at the first recursive level */
+ add_sups = 1;
+ nsups = 0;
+ sups1 = sups;
+ while ( *sups1 ) {
+ nsups++;
+ sups1++;
+ }
+ nsups++;
+ soc->soc_sups = (ObjectClass **)ch_calloc(1,
+ nsups*sizeof(ObjectClass *));
+ }
+ nsups = 0;
+ sups1 = sups;
+ while ( *sups1 ) {
+ soc1 = oc_find(*sups1);
+ if ( !soc1 ) {
+ *err = *sups1;
+ return SLAP_SCHERR_CLASS_NOT_FOUND;
+ }
+ if ( add_sups )
+ soc->soc_sups[nsups] = soc1;
+
+ code = oc_add_sups(soc,soc1->soc_sup_oids, err);
+ if ( code )
+ return code;
+
+ if ( code = oc_create_required(soc,
+ soc1->soc_at_oids_must,err) )
+ return code;
+ if ( code = oc_create_allowed(soc,
+ soc1->soc_at_oids_may,err) )
+ return code;
+ nsups++;
+ sups1++;
+ }
+ }
+ return 0;
+}
+
+static int
+oc_insert(
+ ObjectClass *soc,
+ const char **err
+)
+{
+ ObjectClass **ocp;
+ struct oindexrec *oir;
+ char **names;
+
+ ocp = &oc_list;
+ while ( *ocp != NULL ) {
+ ocp = &(*ocp)->soc_next;
+ }
+ *ocp = soc;
+
+ if ( soc->soc_oid ) {
+ oir = (struct oindexrec *)
+ ch_calloc( 1, sizeof(struct oindexrec) );
+ oir->oir_name = soc->soc_oid;
+ oir->oir_oc = soc;
+ if ( avl_insert( &oc_index, (caddr_t) oir,
+ (AVL_CMP) oc_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = soc->soc_oid;
+ ldap_memfree(oir);
+ return SLAP_SCHERR_DUP_CLASS;
+ }
+ /* FIX: temporal consistency check */
+ oc_find(oir->oir_name);
+ }
+ if ( (names = soc->soc_names) ) {
+ while ( *names ) {
+ oir = (struct oindexrec *)
+ ch_calloc( 1, sizeof(struct oindexrec) );
+ oir->oir_name = ch_strdup(*names);
+ oir->oir_oc = soc;
+ if ( avl_insert( &oc_index, (caddr_t) oir,
+ (AVL_CMP) oc_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = *names;
+ ldap_memfree(oir);
+ return SLAP_SCHERR_DUP_CLASS;
+ }
+ /* FIX: temporal consistency check */
+ oc_find(oir->oir_name);
+ names++;
+ }
+ }
+ return 0;
+}
+
+int
+oc_add(
+ LDAP_OBJECT_CLASS *oc,
+ const char **err
+)
+{
+ ObjectClass *soc;
+ int code;
+
+ soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
+ memcpy( &soc->soc_oclass, oc, sizeof(LDAP_OBJECT_CLASS));
+ if ( code = oc_add_sups(soc,soc->soc_sup_oids,err) )
+ return code;
+ if ( code = oc_create_required(soc,soc->soc_at_oids_must,err) )
+ return code;
+ if ( code = oc_create_allowed(soc,soc->soc_at_oids_may,err) )
+ return code;
+ code = oc_insert(soc,err);
+ return code;
+}
+
+struct sindexrec {
+ char *sir_name;
+ Syntax *sir_syn;
+};
+
+static Avlnode *syn_index = NULL;
+static Syntax *syn_list = NULL;
+
+static int
+syn_index_cmp(
+ struct sindexrec *sir1,
+ struct sindexrec *sir2
+)
+{
+ return (strcmp( sir1->sir_name, sir2->sir_name ));
+}
+
+static int
+syn_index_name_cmp(
+ char *name,
+ struct sindexrec *sir
+)
+{
+ return (strcmp( name, sir->sir_name ));
+}
+
+Syntax *
+syn_find( const char *synname )
+{
+ struct sindexrec *sir = NULL;
+
+ if ( (sir = (struct sindexrec *) avl_find( syn_index, synname,
+ (AVL_CMP) syn_index_name_cmp )) != NULL ) {
+ return( sir->sir_syn );
+ }
return( NULL );
}
+static int
+syn_insert(
+ Syntax *ssyn,
+ const char **err
+)
+{
+ Syntax **synp;
+ struct sindexrec *sir;
+
+ synp = &syn_list;
+ while ( *synp != NULL ) {
+ synp = &(*synp)->ssyn_next;
+ }
+ *synp = ssyn;
+
+ if ( ssyn->ssyn_oid ) {
+ sir = (struct sindexrec *)
+ ch_calloc( 1, sizeof(struct sindexrec) );
+ sir->sir_name = ssyn->ssyn_oid;
+ sir->sir_syn = ssyn;
+ if ( avl_insert( &syn_index, (caddr_t) sir,
+ (AVL_CMP) syn_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = ssyn->ssyn_oid;
+ ldap_memfree(sir);
+ return SLAP_SCHERR_DUP_SYNTAX;
+ }
+ /* FIX: temporal consistency check */
+ syn_find(sir->sir_name);
+ }
+ return 0;
+}
+
+int
+syn_add(
+ LDAP_SYNTAX *syn,
+ slap_syntax_check_func *check,
+ const char **err
+)
+{
+ Syntax *ssyn;
+ int code;
+
+ ssyn = (Syntax *) ch_calloc( 1, sizeof(Syntax) );
+ memcpy( &ssyn->ssyn_syn, syn, sizeof(LDAP_SYNTAX));
+ ssyn->ssyn_check = check;
+ code = syn_insert(ssyn,err);
+ return code;
+}
+
+struct mindexrec {
+ char *mir_name;
+ MatchingRule *mir_mr;
+};
+
+static Avlnode *mr_index = NULL;
+static MatchingRule *mr_list = NULL;
+
+static int
+mr_index_cmp(
+ struct mindexrec *mir1,
+ struct mindexrec *mir2
+)
+{
+ return (strcmp( mir1->mir_name, mir2->mir_name ));
+}
+
+static int
+mr_index_name_cmp(
+ char *name,
+ struct mindexrec *mir
+)
+{
+ return (strcmp( name, mir->mir_name ));
+}
+
+MatchingRule *
+mr_find( const char *mrname )
+{
+ struct mindexrec *mir = NULL;
+
+ if ( (mir = (struct mindexrec *) avl_find( mr_index, mrname,
+ (AVL_CMP) mr_index_name_cmp )) != NULL ) {
+ return( mir->mir_mr );
+ }
+ return( NULL );
+}
+
+static int
+mr_insert(
+ MatchingRule *smr,
+ const char **err
+)
+{
+ MatchingRule **mrp;
+ struct mindexrec *mir;
+ char **names;
+
+ mrp = &mr_list;
+ while ( *mrp != NULL ) {
+ mrp = &(*mrp)->smr_next;
+ }
+ *mrp = smr;
+
+ if ( smr->smr_oid ) {
+ mir = (struct mindexrec *)
+ ch_calloc( 1, sizeof(struct mindexrec) );
+ mir->mir_name = smr->smr_oid;
+ mir->mir_mr = smr;
+ if ( avl_insert( &mr_index, (caddr_t) mir,
+ (AVL_CMP) mr_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = smr->smr_oid;
+ ldap_memfree(mir);
+ return SLAP_SCHERR_DUP_RULE;
+ }
+ /* FIX: temporal consistency check */
+ mr_find(mir->mir_name);
+ }
+ if ( (names = smr->smr_names) ) {
+ while ( *names ) {
+ mir = (struct mindexrec *)
+ ch_calloc( 1, sizeof(struct mindexrec) );
+ mir->mir_name = ch_strdup(*names);
+ mir->mir_mr = smr;
+ if ( avl_insert( &mr_index, (caddr_t) mir,
+ (AVL_CMP) mr_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = *names;
+ ldap_memfree(mir);
+ return SLAP_SCHERR_DUP_RULE;
+ }
+ /* FIX: temporal consistency check */
+ mr_find(mir->mir_name);
+ names++;
+ }
+ }
+ return 0;
+}
+
+int
+mr_add(
+ LDAP_MATCHING_RULE *mr,
+ slap_mr_normalize_func *normalize,
+ slap_mr_compare_func *compare,
+ const char **err
+)
+{
+ MatchingRule *smr;
+ Syntax *syn;
+ int code;
+
+ smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
+ memcpy( &smr->smr_mrule, mr, sizeof(LDAP_MATCHING_RULE));
+ smr->smr_normalize = normalize;
+ smr->smr_compare = compare;
+ if ( smr->smr_syntax_oid ) {
+ if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
+ smr->smr_syntax = syn;
+ } else {
+ *err = smr->smr_syntax_oid;
+ return SLAP_SCHERR_SYN_NOT_FOUND;
+ }
+ } else {
+ *err = "";
+ return SLAP_SCHERR_MR_INCOMPLETE;
+ }
+ code = mr_insert(smr,err);
+ return code;
+}
+
+static int
+case_exact_normalize(
+ struct berval *val,
+ struct berval **normalized
+)
+{
+ struct berval *newval;
+ char *p, *q;
+
+ newval = ber_bvdup( val );
+ p = q = newval->bv_val;
+ /* Ignore initial whitespace */
+ while ( isspace( *p++ ) )
+ ;
+ while ( *p ) {
+ if ( isspace( *p ) ) {
+ *q++ = *p++;
+ /* Ignore the extra whitespace */
+ while ( isspace(*p++) )
+ ;
+ } else {
+ *q++ = *p++;
+ }
+ }
+ /*
+ * If the string ended in space, backup the pointer one
+ * position. One is enough because the above loop collapsed
+ * all whitespace to a single space.
+ */
+ if ( p != newval->bv_val && isspace( *(p-1) ) ) {
+ *(q-1) = '\0';
+ }
+ newval->bv_len = strlen( newval->bv_val );
+ normalized = &newval;
+
+ return 0;
+}
+
+static int
+case_exact_compare(
+ struct berval *val1,
+ struct berval *val2
+)
+{
+ return strcmp( val1->bv_val, val2->bv_val );
+}
+
+int
+case_ignore_normalize(
+ struct berval *val,
+ struct berval **normalized
+)
+{
+ struct berval *newval;
+ char *p, *q;
+
+ newval = ber_bvdup( val );
+ p = q = newval->bv_val;
+ /* Ignore initial whitespace */
+ while ( isspace( *p++ ) )
+ ;
+ while ( *p ) {
+ if ( isspace( *p ) ) {
+ *q++ = *p++;
+ /* Ignore the extra whitespace */
+ while ( isspace(*p++) )
+ ;
+ } else {
+ *q++ = TOUPPER( *p++ );
+ }
+ }
+ /*
+ * If the string ended in space, backup the pointer one
+ * position. One is enough because the above loop collapsed
+ * all whitespace to a single space.
+ */
+ if ( p != newval->bv_val && isspace( *(p-1) ) ) {
+ *(q-1) = '\0';
+ }
+ newval->bv_len = strlen( newval->bv_val );
+ normalized = &newval;
+
+ return 0;
+}
+
+static int
+case_ignore_compare(
+ struct berval *val1,
+ struct berval *val2
+)
+{
+ return strcasecmp( val1->bv_val, val2->bv_val );
+}
+
+int
+register_syntax(
+ char * desc,
+ slap_syntax_check_func *check )
+{
+ LDAP_SYNTAX *syn;
+ int code;
+ const char *err;
+
+ syn = ldap_str2syntax( desc, &code, &err);
+ if ( !syn ) {
+ Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s before %s in %s\n",
+ ldap_scherr2str(code), err, desc );
+ return( -1 );
+ }
+ code = syn_add( syn, check, &err );
+ if ( code ) {
+ Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n",
+ scherr2str(code), err, desc );
+ return( -1 );
+ }
+ return( 0 );
+}
+
+int
+register_matching_rule(
+ char * desc,
+ slap_mr_normalize_func *normalize,
+ slap_mr_compare_func *compare )
+{
+ LDAP_MATCHING_RULE *mr;
+ int code;
+ const char *err;
+
+ mr = ldap_str2matchingrule( desc, &code, &err);
+ if ( !mr ) {
+ Debug( LDAP_DEBUG_ANY, "Error in register_matching_rule: %s before %s in %s\n",
+ ldap_scherr2str(code), err, desc );
+ return( -1 );
+ }
+ code = mr_add( mr, normalize, compare, &err );
+ if ( code ) {
+ Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s for %s in %s\n",
+ scherr2str(code), err, desc );
+ return( -1 );
+ }
+ return( 0 );
+}
+
+struct syntax_defs_rec {
+ char *sd_desc;
+ slap_syntax_check_func *sd_check;
+};
+
+struct syntax_defs_rec syntax_defs[] = {
+ {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'DN' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'INTEGER' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )", NULL},
+ {"( 1.3.6.1.1.1.0.0 DESC 'NIS netgroup triple' )", NULL},
+ {"( 1.3.6.1.1.1.0.1 DESC 'Boot parameter' )", NULL},
+ {NULL, NULL}
+};
+
+struct mrule_defs_rec {
+ char *mrd_desc;
+ slap_mr_normalize_func *mrd_normalize;
+ slap_mr_compare_func *mrd_compare;
+};
+
+/*
+ * Other matching rules in X.520 that we do not use:
+ *
+ * 2.5.13.9 numericStringOrderingMatch
+ * 2.5.13.12 caseIgnoreListSubstringsMatch
+ * 2.5.13.13 booleanMatch
+ * 2.5.13.15 integerOrderingMatch
+ * 2.5.13.18 octetStringOrderingMatch
+ * 2.5.13.19 octetStringSubstringsMatch
+ * 2.5.13.25 uTCTimeMatch
+ * 2.5.13.26 uTCTimeOrderingMatch
+ * 2.5.13.31 directoryStringFirstComponentMatch
+ * 2.5.13.32 wordMatch
+ * 2.5.13.33 keywordMatch
+ * 2.5.13.34 certificateExactMatch
+ * 2.5.13.35 certificateMatch
+ * 2.5.13.36 certificatePairExactMatch
+ * 2.5.13.37 certificatePairMatch
+ * 2.5.13.38 certificateListExactMatch
+ * 2.5.13.39 certificateListMatch
+ * 2.5.13.40 algorithmIdentifierMatch
+ * 2.5.13.41 storedPrefixMatch
+ * 2.5.13.42 attributeCertificateMatch
+ * 2.5.13.43 readerAndKeyIDMatch
+ * 2.5.13.44 attributeIntegrityMatch
+ */
+
+struct mrule_defs_rec mrule_defs[] = {
+ {"( 2.5.13.0 NAME 'objectIdentifierMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", NULL, NULL},
+ {"( 2.5.13.1 NAME 'distinguishedNameMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", NULL, NULL},
+ {"( 2.5.13.2 NAME 'caseIgnoreMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ case_ignore_normalize, case_ignore_compare},
+ {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ case_ignore_normalize, case_ignore_compare},
+ {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ case_ignore_normalize, case_ignore_compare},
+ /* Next three are not in the RFC's, but are needed for compatibility */
+ {"( 2.5.13.5 NAME 'caseExactMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ case_exact_normalize, case_exact_compare},
+ {"( 2.5.13.6 NAME 'caseExactOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ case_exact_normalize, case_exact_compare},
+ {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ case_exact_normalize, case_exact_compare},
+ {"( 2.5.13.8 NAME 'numericStringMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", NULL, NULL},
+ {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", NULL, NULL},
+ {"( 2.5.13.11 NAME 'caseIgnoreListMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", NULL, NULL},
+ {"( 2.5.13.14 NAME 'integerMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", NULL, NULL},
+ {"( 2.5.13.16 NAME 'bitStringMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )", NULL, NULL},
+ {"( 2.5.13.17 NAME 'octetStringMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", NULL, NULL},
+ {"( 2.5.13.20 NAME 'telephoneNumberMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )", NULL, NULL},
+ {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", NULL, NULL},
+ {"( 2.5.13.22 NAME 'presentationAddressMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )", NULL, NULL},
+ {"( 2.5.13.23 NAME 'uniqueMemberMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", NULL, NULL},
+ {"( 2.5.13.24 NAME 'protocolInformationMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )", NULL, NULL},
+ {"( 2.5.13.27 NAME 'generalizedTimeMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", NULL, NULL},
+ {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", NULL, NULL},
+ {"( 2.5.13.29 NAME 'integerFirstComponentMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", NULL, NULL},
+ {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+ case_exact_normalize, case_exact_compare},
+ {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+ case_ignore_normalize, case_ignore_compare},
+ {NULL, NULL, NULL}
+};
+
+int
+schema_init( void )
+{
+ int res;
+ int i;
+ static int schema_init_done = 0;
+
+ /* We are called from read_config that is recursive */
+ if ( schema_init_done )
+ return( 0 );
+ for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
+ res = register_syntax( syntax_defs[i].sd_desc,
+ syntax_defs[i].sd_check );
+ if ( res ) {
+ fprintf( stderr, "schema_init: Error registering syntax %s\n",
+ syntax_defs[i].sd_desc );
+ exit( EXIT_FAILURE );
+ }
+ }
+ for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
+ res = register_matching_rule( mrule_defs[i].mrd_desc,
+ ( mrule_defs[i].mrd_normalize ?
+ mrule_defs[i].mrd_normalize : case_ignore_normalize ),
+ ( mrule_defs[i].mrd_compare ?
+ mrule_defs[i].mrd_compare : case_ignore_compare ) );
+ if ( res ) {
+ fprintf( stderr, "schema_init: Error registering matching rule %s\n",
+ mrule_defs[i].mrd_desc );
+ exit( EXIT_FAILURE );
+ }
+ }
+ schema_init_done = 1;
+ return( 0 );
+}
+
+#if defined( SLAPD_SCHEMA_DN )
+
+static int
+syn_schema_info( Entry *e )
+{
+ struct berval val;
+ struct berval *vals[2];
+ Syntax *syn;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ for ( syn = syn_list; syn; syn = syn->ssyn_next ) {
+ val.bv_val = ldap_syntax2str( &syn->ssyn_syn );
+ if ( val.bv_val ) {
+ val.bv_len = strlen( val.bv_val );
+ Debug( LDAP_DEBUG_TRACE, "Merging syn [%d] %s\n",
+ val.bv_len, val.bv_val, 0 );
+ attr_merge( e, "ldapSyntaxes", vals );
+ ldap_memfree( val.bv_val );
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+mr_schema_info( Entry *e )
+{
+ struct berval val;
+ struct berval *vals[2];
+ MatchingRule *mr;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ for ( mr = mr_list; mr; mr = mr->smr_next ) {
+ val.bv_val = ldap_matchingrule2str( &mr->smr_mrule );
+ if ( val.bv_val ) {
+ val.bv_len = strlen( val.bv_val );
+ Debug( LDAP_DEBUG_TRACE, "Merging mr [%d] %s\n",
+ val.bv_len, val.bv_val, 0 );
+ attr_merge( e, "matchingRules", vals );
+ ldap_memfree( val.bv_val );
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+oc_schema_info( Entry *e )
+{
+ struct berval val;
+ struct berval *vals[2];
+ ObjectClass *oc;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ for ( oc = oc_list; oc; oc = oc->soc_next ) {
+ val.bv_val = ldap_objectclass2str( &oc->soc_oclass );
+ if ( val.bv_val ) {
+ val.bv_len = strlen( val.bv_val );
+ Debug( LDAP_DEBUG_TRACE, "Merging oc [%d] %s\n",
+ val.bv_len, val.bv_val, 0 );
+ attr_merge( e, "objectClasses", vals );
+ ldap_memfree( val.bv_val );
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void
+schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
+{
+ Entry *e;
+ struct berval val;
+ struct berval *vals[2];
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
+ e->e_attrs = NULL;
+ e->e_dn = ch_strdup( SLAPD_SCHEMA_DN );
+ e->e_ndn = ch_strdup( SLAPD_SCHEMA_DN );
+ (void) dn_normalize_case( e->e_ndn );
+ e->e_private = NULL;
+
+ {
+ char *rdn = ch_strdup( SLAPD_SCHEMA_DN );
+ val.bv_val = strchr( rdn, '=' );
+
+ if( val.bv_val != NULL ) {
+ *val.bv_val = '\0';
+ val.bv_len = strlen( ++val.bv_val );
+
+ attr_merge( e, rdn, vals );
+ }
+
+ free( rdn );
+ }
+
+ if ( syn_schema_info( e ) ) {
+ /* Out of memory, do something about it */
+ entry_free( e );
+ return;
+ }
+ if ( mr_schema_info( e ) ) {
+ /* Out of memory, do something about it */
+ entry_free( e );
+ return;
+ }
+ if ( at_schema_info( e ) ) {
+ /* Out of memory, do something about it */
+ entry_free( e );
+ return;
+ }
+ if ( oc_schema_info( e ) ) {
+ /* Out of memory, do something about it */
+ entry_free( e );
+ return;
+ }
+
+ val.bv_val = "top";
+ val.bv_len = sizeof("top")-1;
+ attr_merge( e, "objectClass", vals );
+
+ val.bv_val = "LDAPsubentry";
+ val.bv_len = sizeof("LDAPsubentry")-1;
+ attr_merge( e, "objectClass", vals );
+
+ val.bv_val = "subschema";
+ val.bv_len = sizeof("subschema")-1;
+ attr_merge( e, "objectClass", vals );
+
+ val.bv_val = "extensibleObject";
+ val.bv_len = sizeof("extensibleObject")-1;
+ attr_merge( e, "objectClass", vals );
+
+ send_search_entry( &backends[0], conn, op,
+ e, attrs, attrsonly, NULL );
+ send_search_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 1 );
+
+ entry_free( e );
+}
+#endif
+
#ifdef LDAP_DEBUG
-static
-oc_print( struct objclass *oc )
+static void
+oc_print( ObjectClass *oc )
{
int i;
+ const char *mid;
- printf( "objectclass %s\n", oc->oc_name );
- if ( oc->oc_required != NULL ) {
- printf( "\trequires %s", oc->oc_required[0] );
- for ( i = 1; oc->oc_required[i] != NULL; i++ ) {
- printf( ",%s", oc->oc_required[i] );
- }
+ printf( "objectclass %s\n", ldap_objectclass2name( &oc->soc_oclass ) );
+ if ( oc->soc_required != NULL ) {
+ mid = "\trequires ";
+ for ( i = 0; oc->soc_required[i] != NULL; i++, mid = "," )
+ printf( "%s%s", mid,
+ ldap_attributetype2name( &oc->soc_required[i]->sat_atype ) );
printf( "\n" );
}
- if ( oc->oc_allowed != NULL ) {
- printf( "\tallows %s", oc->oc_allowed[0] );
- for ( i = 1; oc->oc_allowed[i] != NULL; i++ ) {
- printf( ",%s", oc->oc_allowed[i] );
- }
+ if ( oc->soc_allowed != NULL ) {
+ mid = "\tallows ";
+ for ( i = 0; oc->soc_allowed[i] != NULL; i++, mid = "," )
+ printf( "%s%s", mid,
+ ldap_attributetype2name( &oc->soc_allowed[i]->sat_atype ) );
printf( "\n" );
}
}
#endif
+
+
+int is_entry_objectclass(
+ Entry* e,
+ char* oc)
+{
+ Attribute *attr;
+ struct berval bv;
+
+ if( e == NULL || oc == NULL || *oc == '\0' )
+ return 0;
+
+ /*
+ * find objectClass attribute
+ */
+ attr = attr_find(e->e_attrs, "objectclass");
+
+ if( attr == NULL ) {
+ /* no objectClass attribute */
+ return 0;
+ }
+
+ bv.bv_val = oc;
+ bv.bv_len = strlen( bv.bv_val );
+
+ if( value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ /* entry is not of this objectclass */
+ return 0;
+ }
+
+ return 1;
+}
--- /dev/null
+# OpenLDAP Core schema
+#
+# Includes "standard" schema items from:
+# RFC2251-RFC2256 (LDAPv3)
+# RFC2079 (URI)
+#
+
+# Standard X.501(93) Operational Attribute Types from RFC2252
+
+attribute ( 2.5.18.1 NAME 'createTimestamp' EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attribute ( 2.5.18.2 NAME 'modifyTimestamp' EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attribute ( 2.5.18.3 NAME 'creatorsName' EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attribute ( 2.5.18.4 NAME 'modifiersName' EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attribute ( 2.5.18.10 NAME 'subschemaSubentry'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION
+ SINGLE-VALUE USAGE directoryOperation )
+
+attribute ( 2.5.21.5 NAME 'attributeTypes'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )
+
+attribute ( 2.5.21.6 NAME 'objectClasses'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )
+
+attribute ( 2.5.21.4 NAME 'matchingRules'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )
+
+attribute ( 2.5.21.8 NAME 'matchingRuleUse'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )
+
+# LDAP Operational Attributes from RFC2252
+
+attribute ( 1.3.6.1.4.1.1466.101.120.5 NAME 'namingContexts'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.7 NAME 'supportedExtension'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.13 NAME 'supportedControl'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.14 NAME 'supportedSASLMechanisms'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.15 NAME 'supportedLDAPVersion'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )
+
+# LDAP Subschema Atrribute from RFC2252
+
+attribute ( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )
+
+# X.500 Subschema attributes from RFC2252
+
+attribute ( 2.5.21.1 NAME 'dITStructureRules' EQUALITY integerFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 USAGE directoryOperation )
+
+attribute ( 2.5.21.7 NAME 'nameForms'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )
+
+attribute ( 2.5.21.2 NAME 'dITContentRules'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )
+
+# Object Classes from RFC2252
+
+# extensibleObject moved forward, since it depends on top
+# ldapSyntaxes (operational) is admissible in next:
+
+objectclass ( 2.5.20.1 NAME 'subschema' AUXILIARY
+ MAY ( dITStructureRules $ nameForms $ ditContentRules $
+ objectClasses $ attributeTypes $ matchingRules $
+ matchingRuleUse ) )
+
+# Standard attribute types from RFC2256
+
+attribute ( 2.5.4.0 NAME 'objectClass' EQUALITY objectIdentifierMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
+
+attribute ( 2.5.4.1 NAME 'aliasedObjectName' EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
+
+# Defined, but no longer used
+
+attribute ( 2.5.4.2 NAME 'knowledgeInformation' EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+# Place here since other attribute types derive from it
+
+attribute ( 2.5.4.41 NAME 'name' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+attribute ( 2.5.4.3 NAME ( 'cn' 'commonName' ) SUP name )
+
+attribute ( 2.5.4.4 NAME ( 'sn' 'surname' ) SUP name )
+
+attribute ( 2.5.4.5 NAME 'serialNumber' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} )
+
+# (2-letter code from ISO 3166)
+
+attribute ( 2.5.4.6 NAME ( 'c' 'countryName' ) SUP name SINGLE-VALUE )
+
+attribute ( 2.5.4.7 NAME ( 'l' 'localityName' ) SUP name )
+
+attribute ( 2.5.4.8 NAME ( 'st' 'stateOrProvinceName' ) SUP name )
+
+attribute ( 2.5.4.9 NAME ( 'street' 'streetAddress' ) EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attribute ( 2.5.4.10 NAME ( 'o' 'organizationName' ) SUP name )
+
+attribute ( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' ) SUP name )
+
+attribute ( 2.5.4.12 NAME 'title' SUP name )
+
+attribute ( 2.5.4.13 NAME 'description' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )
+
+# Obsoleted by enhancedSearchGuide
+
+attribute ( 2.5.4.14 NAME 'searchGuide'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.25 )
+
+attribute ( 2.5.4.15 NAME 'businessCategory' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+# Show stopper: we don't have the definition of caseIgnoreListSubstringsMatch
+#attribute ( 2.5.4.16 NAME 'postalAddress' EQUALITY caseIgnoreListMatch
+# SUBSTR caseIgnoreListSubstringsMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+attribute ( 2.5.4.16 NAME 'postalAddress' EQUALITY caseIgnoreListMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+attribute ( 2.5.4.17 NAME 'postalCode' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
+
+attribute ( 2.5.4.18 NAME 'postOfficeBox' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
+
+attribute ( 2.5.4.19 NAME 'physicalDeliveryOfficeName' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attribute ( 2.5.4.20 NAME 'telephoneNumber' EQUALITY telephoneNumberMatch
+ SUBSTR telephoneNumberSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.50{32} )
+
+attribute ( 2.5.4.21 NAME 'telexNumber'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 )
+
+attribute ( 2.5.4.22 NAME 'teletexTerminalIdentifier'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 )
+
+attribute ( 2.5.4.23 NAME ( 'facsimileTelephoneNumber' 'fax' )
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.22 )
+
+attribute ( 2.5.4.24 NAME 'x121Address' EQUALITY numericStringMatch
+ SUBSTR numericStringSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{15} )
+
+attribute ( 2.5.4.25 NAME 'internationaliSDNNumber' EQUALITY numericStringMatch
+ SUBSTR numericStringSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} )
+
+attribute ( 2.5.4.26 NAME 'registeredAddress' SUP postalAddress
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+attribute ( 2.5.4.27 NAME 'destinationIndicator' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128} )
+
+attribute ( 2.5.4.28 NAME 'preferredDeliveryMethod'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.14
+ SINGLE-VALUE )
+
+attribute ( 2.5.4.29 NAME 'presentationAddress'
+ EQUALITY presentationAddressMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.43
+ SINGLE-VALUE )
+
+attribute ( 2.5.4.30 NAME 'supportedApplicationContext'
+ EQUALITY objectIdentifierMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
+
+# Placed here because others derive from it.
+
+# We had a dn definition in slapd.at.conf and Netscape lists both
+# names for that OID. This is wrong, 'dn' is used internally in slapd
+# as the name of a pseudo-attribute type that contains the
+# distinguished name of an entry. On the other hand, the attribute
+# type distinguishedName is meant to be an "abstract" type and other
+# dn-valued attribute types derive from it. So at most, 'dn' would
+# be a subtype of distinguishedName.
+
+attribute ( 2.5.4.49 NAME 'distinguishedName'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attribute ( 2.5.4.31 NAME 'member' SUP distinguishedName )
+
+attribute ( 2.5.4.32 NAME 'owner' SUP distinguishedName )
+
+attribute ( 2.5.4.33 NAME 'roleOccupant' SUP distinguishedName )
+
+attribute ( 2.5.4.34 NAME 'seeAlso' SUP distinguishedName )
+
+attribute ( 2.5.4.35 NAME 'userPassword' EQUALITY octetStringMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
+
+# Must be stored and requested in the binary form, as
+# userCertificate;binary
+
+attribute ( 2.5.4.36 NAME 'userCertificate'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
+
+# As above
+
+attribute ( 2.5.4.37 NAME 'cACertificate'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
+
+# As above
+
+attribute ( 2.5.4.38 NAME 'authorityRevocationList'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+# As above
+
+attribute ( 2.5.4.39 NAME 'certificateRevocationList'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+# As above
+
+attribute ( 2.5.4.40 NAME 'crossCertificatePair'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.10 )
+
+# 2.5.4.41 is 'name', moved above since other attribute types derive from it
+
+attribute ( 2.5.4.42 NAME 'givenName' SUP name )
+
+attribute ( 2.5.4.43 NAME 'initials' SUP name )
+
+attribute ( 2.5.4.45 NAME 'x500UniqueIdentifier' EQUALITY bitStringMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )
+
+attribute ( 2.5.4.46 NAME 'dnQualifier' EQUALITY caseIgnoreMatch
+ ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )
+
+attribute ( 2.5.4.47 NAME 'enhancedSearchGuide'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.21 )
+
+attribute ( 2.5.4.48 NAME 'protocolInformation'
+ EQUALITY protocolInformationMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )
+
+# 2.5.4.49 is distinguishedName, moved up
+
+attribute ( 2.5.4.50 NAME 'uniqueMember' EQUALITY uniqueMemberMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )
+
+attribute ( 2.5.4.51 NAME 'houseIdentifier' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+# This attribute is to be stored and requested in the binary form, as
+# 'supportedAlgorithms;binary'.
+
+attribute ( 2.5.4.52 NAME 'supportedAlgorithms'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.49 )
+
+# This attribute is to be stored and requested in the binary form, as
+# 'deltaRevocationList;binary'.
+
+attribute ( 2.5.4.53 NAME 'deltaRevocationList'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+attribute ( 2.5.4.54 NAME 'dmdName' SUP name )
+
+# Standard object classes from RFC2256
+
+objectclass ( 2.5.6.0 NAME 'top' ABSTRACT MUST objectClass )
+
+objectclass ( 2.5.6.1 NAME 'alias' SUP top STRUCTURAL MUST aliasedObjectName )
+
+objectclass ( 2.5.6.2 NAME 'country' SUP top STRUCTURAL MUST c
+ MAY ( searchGuide $ description ) )
+
+objectclass ( 2.5.6.3 NAME 'locality' SUP top STRUCTURAL
+ MAY ( street $ seeAlso $ searchGuide $ st $ l $ description ) )
+
+objectclass ( 2.5.6.4 NAME 'organization' SUP top STRUCTURAL MUST o
+ MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+ x121Address $ registeredAddress $ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ street $ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+objectclass ( 2.5.6.5 NAME 'organizationalUnit' SUP top STRUCTURAL MUST ou
+ MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+ x121Address $ registeredAddress $ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ street $ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+objectclass ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn )
+ MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
+
+objectclass ( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL
+ MAY ( title $ x121Address $ registeredAddress $
+ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ street $ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ ou $ st $ l ) )
+
+# Notice that preferredDeliveryMethod is duplicate
+
+objectclass ( 2.5.6.8 NAME 'organizationalRole' SUP top STRUCTURAL MUST cn
+ MAY ( x121Address $ registeredAddress $ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $
+ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ ou $ st $ l $ description ) )
+
+objectclass ( 2.5.6.9 NAME 'groupOfNames' SUP top STRUCTURAL MUST ( member $ cn )
+ MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
+
+# Notice that preferredDeliveryMethod is duplicate
+# It seems they could not agree on wheter telephoneNumber is MAY
+# in person. Probably it wasn't originally at was added as an
+# afterthought
+
+objectclass ( 2.5.6.10 NAME 'residentialPerson' SUP person STRUCTURAL MUST l
+ MAY ( businessCategory $ x121Address $ registeredAddress $
+ destinationIndicator $ preferredDeliveryMethod $ telexNumber $
+ teletexTerminalIdentifier $ telephoneNumber $
+ internationaliSDNNumber $
+ facsimileTelephoneNumber $ preferredDeliveryMethod $ street $
+ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ st $ l ) )
+
+objectclass ( 2.5.6.11 NAME 'applicationProcess' SUP top STRUCTURAL MUST cn
+ MAY ( seeAlso $ ou $ l $ description ) )
+
+objectclass ( 2.5.6.12 NAME 'applicationEntity' SUP top STRUCTURAL
+ MUST ( presentationAddress $ cn )
+ MAY ( supportedApplicationContext $ seeAlso $ ou $ o $ l $
+ description ) )
+
+# This one was wrong in our schema, it only allowed the aditional
+# knowledgeInformation attribute, while it is derived from
+# applicationEntity and should allow all its attributes as well.
+
+objectclass ( 2.5.6.13 NAME 'dSA' SUP applicationEntity STRUCTURAL
+ MAY knowledgeInformation )
+
+objectclass ( 2.5.6.14 NAME 'device' SUP top STRUCTURAL MUST cn
+ MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) )
+
+objectclass ( 2.5.6.15 NAME 'strongAuthenticationUser' SUP top AUXILIARY
+ MUST userCertificate )
+
+objectclass ( 2.5.6.16 NAME 'certificationAuthority' SUP top AUXILIARY
+ MUST ( authorityRevocationList $ certificateRevocationList $
+ cACertificate ) MAY crossCertificatePair )
+
+# New
+
+objectclass ( 2.5.6.17 NAME 'groupOfUniqueNames' SUP top STRUCTURAL
+ MUST ( uniqueMember $ cn )
+ MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
+
+# New
+
+objectclass ( 2.5.6.18 NAME 'userSecurityInformation' SUP top AUXILIARY
+ MAY ( supportedAlgorithms ) )
+
+# New
+
+objectclass ( 2.5.6.16.2 NAME 'certificationAuthority-V2' SUP
+ certificationAuthority
+ AUXILIARY MAY ( deltaRevocationList ) )
+
+# New
+
+objectclass ( 2.5.6.19 NAME 'cRLDistributionPoint' SUP top STRUCTURAL
+ MUST ( cn ) MAY ( certificateRevocationList $
+ authorityRevocationList $
+ deltaRevocationList ) )
+
+# New
+
+objectclass ( 2.5.6.20 NAME 'dmd' SUP top STRUCTURAL MUST ( dmdName )
+ MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+ x121Address $ registeredAddress $ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ street $ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+# Next objectclass is defined in RFC2252, but has to be put after top
+
+objectclass ( 1.3.6.1.4.1.1466.101.120.111 NAME 'extensibleObject'
+ SUP top AUXILIARY )
+
+#
+# Standard Track URI label schema from RFC2079
+#
+attribute ( 1.3.6.1.4.1.250.1.57 NAME 'labeledURI'
+ DESC 'Uniform Resource Identifier with optional label'
+ EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+objectclass ( 1.3.6.1.4.1.250.3.15 NAME 'labeledURIObject'
+ DESC 'object that contains the URI attribute type'
+ MAY ( labeledURI ) SUP top AUXILIARY )
+
+#
+# From draft-ietf-ldapext-nameref-00.txt
+# used to represent referrals in the directory
+#
+attribute ( 2.16.840.1.113730.3.1.34 NAME 'ref' DESC 'URL Reference'
+ EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ USAGE distributedOperation )
+
+objectclass ( 2.16.840.1.113730.3.2.6 NAME 'referral'
+ SUP top STRUCTURAL MAY ( ref ) )
+
+#
+# LDAPsubEntry
+# OID not assigned (1.3.6.1.4.1.1466.115.121.1.??)
+#
+objectclass ( NAME 'LDAPsubEntry'
+ DESC 'Limited X.501 Subentry class, named by cn'
+ SUP top STRUCTURAL MUST ( cn ) )
--- /dev/null
+# Assorted definitions from several sources
+
+#
+# RFC2247
+#
+objectclass ( 1.3.6.1.4.1.1466.344 NAME 'dcObject' SUP top AUXILIARY MUST dc )
+
+#
+# This comes from RFC2377
+#
+objectclass ( 1.3.6.1.1.3.1 NAME 'uidObject' SUP top AUXILIARY MUST uid )
+
+# Origin of this has not been identified. We had it and Netscape has it
+# too.
+
+attribute ( 1.3.6.1.4.1.250.1.60 NAME ( 'timeToLive' 'ttl' )
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+objectclass ( 1.3.6.1.4.1.250.3.18 NAME 'cacheObject' SUP top MAY ttl )
+
+#
+# RFC 2079
+#
--- /dev/null
+# These come from RFC1274 and are in ASN.1 syntax. They have been
+# translated with some imagination. Only attributes and classes we
+# already had are here. In general, the matching rules in the
+# attribute types are incomplete or incorrect and have to be checked.
+
+# Note: It seems that the pilot schema evolved beyond what was
+# described in RFC1274. It also seems that Umich followed the changes
+# but we don't know where are documented. More worrisome is that it
+# seems that Netscape does not know either. Searches on Altavista
+# have not shed any light, so we will have to ask for help.
+
+# This file uses definitions from slapd.std.schema
+
+# ccitt.data.pss.ucl.pilot ( 0.9.2342.19200300.100 )
+# 1 pilotAttributeType
+# 3 pilotAttributeSyntax
+# 4 pilotObjectClass
+# 10 pilotGroups
+
+# Believe it or not, this is case-insensitive
+
+attribute ( 0.9.2342.19200300.100.1.1 NAME ( 'uid' 'userid' )
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.2 NAME 'textEncodedORAddress'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.3 NAME ( 'mail' 'rfc822Mailbox' )
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.4 NAME 'info' EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.5 NAME ( 'drink' 'favouriteDrink' )
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.6 NAME 'roomNumber'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.7 NAME 'photo'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+attribute ( 0.9.2342.19200300.100.1.8 NAME 'userClass'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.9 NAME 'host'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.10 NAME 'manager'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attribute ( 0.9.2342.19200300.100.1.11 NAME 'documentIdentifier'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.12 NAME 'documentTitle'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.13 NAME 'documentVersion'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.14 NAME 'documentAuthor'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attribute ( 0.9.2342.19200300.100.1.15 NAME 'documentLocation'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.20 NAME ( 'homeTelephoneNumber' 'homePhone' )
+ EQUALITY telephoneNumberMatch
+ SUBSTR telephoneNumberSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )
+
+attribute ( 0.9.2342.19200300.100.1.21 NAME 'secretary'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# Netscape defines this with syntax 1.15 TBC
+
+attribute ( 0.9.2342.19200300.100.1.22 NAME 'otherMailbox'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.39 )
+
+# Netscape defines this with syntax 1.15 TBC
+# Mathcing rules for this are unknown
+
+attribute ( 0.9.2342.19200300.100.1.23 NAME 'lastModifiedTime'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.53 )
+
+attribute ( 0.9.2342.19200300.100.1.24 NAME 'lastModifiedBy'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# This is the definition as defined in RFC2247
+# Terrific, we don't know about caseIgnoreIA5SubstringsMatch
+
+#attribute ( 0.9.2342.19200300.100.1.25 NAME 'dc'
+# EQUALITY caseIgnoreIA5Match
+# SUBSTR caseIgnoreIA5SubstringsMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attribute ( 0.9.2342.19200300.100.1.25 NAME 'dc'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+# This is aRecord in RFC1274. However, objectclass dNSDomain as we
+# and Netscape use it is very different.
+
+attribute ( 0.9.2342.19200300.100.1.26 NAME 'dNSRecord'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# 0.9.2342.19200300.100.1.27 was probably intended to be mDRecord in
+# RFC1274, but they got it wrong and did not define it, thought it
+# is referenced by dNSDomain in it.
+
+# 0.9.2342.19200300.100.1.28 was mXRecord in RFC1274
+# 0.9.2342.19200300.100.1.29 was nSRecord in RFC1274
+# 0.9.2342.19200300.100.1.30 was sOARecord in RFC1274
+# 0.9.2342.19200300.100.1.31 was cNAMERecord in RFC1274
+
+# Terrific, we don't know about caseIgnoreIA5SubstringsMatch
+#attribute ( 0.9.2342.19200300.100.1.37 NAME 'associatedDomain'
+# EQUALITY caseIgnoreIA5Match
+# SUBSTR caseIgnoreIA5SubstringsMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+attribute ( 0.9.2342.19200300.100.1.37 NAME 'associatedDomain'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.38 NAME 'associatedName'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# Netscape gives syntax 1.15 to this. TBC
+# We take the matching rules from postalAddress in RFC2256
+# Show stopper: we don't have the definition of caseIgnoreListSubstringsMatch
+
+attribute ( 0.9.2342.19200300.100.1.39 NAME 'homePostalAddress'
+ EQUALITY caseIgnoreListMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+attribute ( 0.9.2342.19200300.100.1.40 NAME 'personalTitle'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.41 NAME ( 'mobileTelephoneNumber' 'mobile' )
+ EQUALITY telephoneNumberMatch
+ SUBSTR telephoneNumberSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )
+
+attribute ( 0.9.2342.19200300.100.1.42 NAME ( 'pagerTelephoneNumber' 'pager' )
+ EQUALITY telephoneNumberMatch
+ SUBSTR telephoneNumberSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )
+
+attribute ( 0.9.2342.19200300.100.1.43 NAME ( 'co' 'friendlyCountryName' )
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.44 NAME 'uniqueIdentifier'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.45 NAME 'organizationalStatus'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( 0.9.2342.19200300.100.1.46 NAME 'janetMailbox'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# Netscape gives syntax 1.27 (integer). However, 1.32 is only listed
+# in RFC2252 without explanation. The SINGLE-VALUE thing comes from
+# Netscape and is not backed by RFC1274.
+
+attribute ( 0.9.2342.19200300.100.1.47 NAME 'mailPreferenceOption'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.32 SINGLE-VALUE )
+
+attribute ( 0.9.2342.19200300.100.1.48 NAME 'buildingName'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+# 0.9.2342.19200300.100.1.49 was dSAQuality in RFC1274
+# 0.9.2342.19200300.100.1.50 was singleLevelQuality in RFC1274
+# 0.9.2342.19200300.100.1.51 was subtreeMinimumQuality in RFC1274
+# 0.9.2342.19200300.100.1.52 was subtreeMaximumQuality in RFC1274
+
+# Netscape assigns binary syntax to this. RFC1274 is more detailed
+# about this but RFC2252 does not seem to list a specific syntax.
+# We had this as 'bin'
+
+attribute ( 0.9.2342.19200300.100.1.53 NAME 'personalSignature'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+attribute ( 0.9.2342.19200300.100.1.54 NAME 'dITRedirect'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# Netscape gives syntax 1.5 to this. We had it as 'bin'.
+
+attribute ( 0.9.2342.19200300.100.1.55 NAME 'audio'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.4 )
+
+attribute ( 0.9.2342.19200300.100.1.56 NAME 'documentPublisher'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# This one is ripped from Netscape and is a pilot object. It is not
+# in RFC1274, but we had it as 'bin'.
+
+attribute ( 0.9.2342.19200300.100.1.60 NAME 'jpegPhoto'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+# These attributes are pilot-related attributes that we had and Netscape
+# has too, however, the OID is unknown for them and Netscape uses a
+# string in place of the missing OID. We will do the same until we
+# can make head or tails of this.
+
+attribute ( abstract-oid NAME 'abstract'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( authorcn-oid NAME ( 'documentAuthorCommonName' 'authorCn' )
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( authorsn-oid NAME ( 'documentAuthorSurname' 'authorSn' )
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( documentStore-oid NAME 'documentStore'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( keyWords-oid NAME 'keyWords'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( obsoletedByDocument-oid NAME 'obsoletedByDocument'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attribute ( obsoletesDocument-oid NAME 'obsoletesDocument'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attribute ( subject-oid NAME 'subject'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attribute ( updatedByDocument-oid NAME 'updatedByDocument'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attribute ( updatesDocument-oid NAME 'updatesDocument'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# In classes, STRUCTURAL or AUXILIARY is chosen depending on the
+# textual description that accompanies the class in RFC1274
+
+# This is pilotObject from the RFC. However, we had both photo
+# and jpegPhoto attributes. Nestcape does too.
+
+objectclass ( 0.9.2342.19200300.100.4.3 NAME 'pilotObject' SUP top
+ AUXILIARY MAY ( info $ photo $ manager $ uniqueIdentifier $
+ lastModifiedTime $ lastModifiedBy $ dITRedirect $ audio $
+ jpegPhoto ) )
+
+# This is probably wrong. RFC1274 defines a pilotPerson. We did not
+# have it and we did have a newPilotPerson instead. However, the
+# definition is the same. Maybe it changed and was not reflected
+# in the RFC.
+
+objectclass ( 0.9.2342.19200300.100.4.4 NAME 'newPilotPerson' SUP person
+ STRUCTURAL MAY ( uid $ textEncodedORAddress $ mail $ drink $
+ roomNumber $ userClass $ homePhone $ homePostalAddress $
+ secretary $ personalTitle $ preferredDeliveryMethod $
+ businessCategory $ janetMailbox $ otherMailbox $ mobile $
+ pager $ organizationalStatus $ mailPreferenceOption $
+ personalSignature ) )
+
+# The text is unclear about whether it is STRUCTURAL or AUXILIARY
+# I think it was meant to be STRUCTURAL, it is the least restrictive
+# of the options and RFC2377 explains uidObject as an auxiliary.
+
+objectclass ( 0.9.2342.19200300.100.4.5 NAME 'account' SUP top
+ STRUCTURAL MUST uid MAY ( description $ seeAlso $ l $ o $ ou $
+ host ) )
+
+# Netscape says this is derived from pilotObject, but RFC1274 says top.
+# Which is it? Our attribute list matches that of Netscape, so we will
+# go with Netscape for the time being.
+
+# Besides, this objectclass is a mess. I can only presume that
+# originally documentAuthor, but later someone noticed that not all
+# authors had DN's, so authorCN and authorSN were added. Other
+# attributes were added as well. However, either no one remembered to
+# assign OIDs to these attribute types or their assignments have been
+# lost. See their definitions above for the Netscape kludge that we
+# have adopted. FIX NEEDED.
+
+objectclass ( 0.9.2342.19200300.100.4.6 NAME 'document' SUP pilotObject
+ MUST documentIdentifier MAY ( cn $ description $ seeAlso $ l $
+ o $ ou $ documentTitle $ documentVersion $ documentAuthor $
+ documentLocation $ documentPublisher $
+ abstract $ authorCN $ authorSN $ documentStore $ keywords $
+ obsoletedByDocument $ obsoletesDocument $ subject $
+ updatedByDocument $ updatesDocument ) )
+
+objectclass ( 0.9.2342.19200300.100.4.7 NAME 'room' SUP top STRUCTURAL
+ MUST cn MAY ( roomNumber $ description $ seeAlso $ telephoneNumber ) )
+
+objectclass ( 0.9.2342.19200300.100.4.9 NAME 'documentSeries' SUP top
+ STRUCTURAL MUST cn MAY ( description $ seeAlso $ telephonenumber $
+ l $ o $ ou ) )
+
+# This definition is much longer than that in RFC1274 and is taken from RFC2247
+
+objectclass ( 0.9.2342.19200300.100.4.13 NAME 'domain' SUP top STRUCTURAL
+ MUST dc
+ MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+ x121Address $ registeredAddress $ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $
+ street $ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ st $ l $ description $ o $
+ associatedName ) )
+
+# This class has in RFC1274 two attributes postalAttributeSet and
+# telecomunicationAttributeSet that we did not have. We let them out
+# for now. Netscape does not have them either.
+
+objectclass ( 0.9.2342.19200300.100.4.14 NAME 'RFC822localPart' SUP domain
+ MAY ( cn $ sn $ description $ seeAlso $ telephonenumber ) )
+
+# Another wonderful inconsistency. This objectclass has little
+# relationship to the way it was defined in RFC1274, that was derived
+# from domain, adding ARecord, MDRecord, MXRecord, NSRecord, SOARecord
+# and CNAMERecord attribute types of syntax DNSRecordSyntax. On the
+# other hand, we had dNSRecord and Netscape has it too. The OID for
+# dNSRecord is the one used in RFC1274 for ARecord. Netscape also has
+# a manager attribute type here that we did not. It seems a mistake
+# and we do not include it.
+
+objectclass ( 0.9.2342.19200300.100.4.15 NAME 'dNSDomain' SUP 'domain'
+ MAY dnsrecord )
+
+objectclass ( 0.9.2342.19200300.100.4.17 NAME 'domainRelatedObject'
+ SUP 'top' MUST associatedDomain )
+
+# Well, first notice we (and Netscape) were using co as short for
+# friendlyCountryName
+
+objectclass ( 0.9.2342.19200300.100.4.18 NAME 'friendlyCountry' SUP country
+ MUST co )
+
+objectclass ( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObject'
+ SUP top MUST userPassword )
+
+# Nice test case of class with two superiors. Netscape does not give
+# OID for this objectclass and gives top as its superior. We use the
+# OID given in RFC1274
+
+objectclass ( 0.9.2342.19200300.100.4.20 NAME 'pilotOrganization'
+ SUP ( organization $ organizationalUnit ) MAY buildingName )
+
+
+
+
/* schemaparse.c - routines to parse config file objectclass definitions */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
+#include "ldap_schema.h"
-extern char **str2charray();
-extern void charray_merge();
+static Avlnode *object_classes = NULL;
-struct objclass *global_oc;
-int global_schemacheck;
+int global_schemacheck = 1; /* schemacheck on is default */
-static void oc_usage();
+static void oc_usage_old(void);
+static void oc_usage(void);
+
+static char *err2text[] = {
+ "",
+ "Out of memory",
+ "Objectclass not found",
+ "Attribute type not found",
+ "Duplicate objectclass",
+ "Duplicate attributetype",
+ "Duplicate syntax",
+ "Duplicate matchingrule",
+ "OID or name required",
+ "Syntax or superior required",
+ "Matchingrule not found",
+ "Syntax not found",
+ "Syntax required"
+};
+
+char *
+scherr2str(int code)
+{
+ if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) {
+ return "Unknown error";
+ } else {
+ return err2text[code];
+ }
+}
void
-parse_oc(
+parse_oc_old(
Backend *be,
char *fname,
int lineno,
{
int i;
char last;
- struct objclass *oc;
- struct objclass **ocp;
+ LDAP_OBJECT_CLASS *oc;
+ int code;
+ const char *err;
+ char **namep;
- oc = (struct objclass *) ch_calloc( 1, sizeof(struct objclass) );
- oc->oc_name = strdup( argv[1] );
+ oc = (LDAP_OBJECT_CLASS *) ch_calloc( 1, sizeof(LDAP_OBJECT_CLASS) );
+ oc->oc_names = ch_calloc( 2, sizeof(char *) );
+ oc->oc_names[0] = ch_strdup( argv[1] );
+ oc->oc_names[1] = NULL;
+ if ( strcasecmp( oc->oc_names[0], "top" ) ) {
+ oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
+ }
for ( i = 2; i < argc; i++ ) {
/* required attributes */
if ( strcasecmp( argv[i], "requires" ) == 0 ) {
do {
i++;
if ( i < argc ) {
+ char **s = str2charray( argv[i], "," );
last = argv[i][strlen( argv[i] ) - 1];
- charray_merge( &oc->oc_required,
- str2charray( argv[i], "," ) );
+ charray_merge( &oc->oc_at_oids_must, s );
+ charray_free( s );
}
} while ( i < argc && last == ',' );
do {
i++;
if ( i < argc ) {
+ char **s = str2charray( argv[i], "," );
last = argv[i][strlen( argv[i] ) - 1];
- charray_merge( &oc->oc_allowed,
- str2charray( argv[i], "," ) );
+
+ charray_merge( &oc->oc_at_oids_may, s );
+ charray_free( s );
}
} while ( i < argc && last == ',' );
fprintf( stderr,
"%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n",
fname, lineno, argv[i] );
- oc_usage();
+ oc_usage_old();
}
}
- ocp = &global_oc;
- while ( *ocp != NULL ) {
- ocp = &(*ocp)->oc_next;
+ /*
+ * There was no requirement in the old schema that all attributes
+ * types were defined before use and they would just default to
+ * SYNTAX_CIS. To support this, we need to make attribute types
+ * out of thin air.
+ */
+ if ( oc->oc_at_oids_must ) {
+ namep = oc->oc_at_oids_must;
+ while ( *namep ) {
+ code = at_fake_if_needed( *namep );
+ if ( code ) {
+ fprintf( stderr, "%s: line %d: %s %s\n",
+ fname, lineno, scherr2str(code), *namep);
+ exit( EXIT_FAILURE );
+ }
+ namep++;
+ }
+ }
+ if ( oc->oc_at_oids_may ) {
+ namep = oc->oc_at_oids_may;
+ while ( *namep ) {
+ code = at_fake_if_needed( *namep );
+ if ( code ) {
+ fprintf( stderr, "%s: line %d: %s %s\n",
+ fname, lineno, scherr2str(code), *namep);
+ exit( EXIT_FAILURE );
+ }
+ namep++;
+ }
+ }
+
+ code = oc_add(oc,&err);
+ if ( code ) {
+ fprintf( stderr, "%s: line %d: %s %s\n",
+ fname, lineno, scherr2str(code), err);
+ exit( EXIT_FAILURE );
+ }
+ ldap_memfree(oc);
+}
+
+void
+parse_oc(
+ char *fname,
+ int lineno,
+ char *line
+)
+{
+ LDAP_OBJECT_CLASS *oc;
+ int code;
+ const char *err;
+
+ oc = ldap_str2objectclass(line,&code,&err);
+ if ( !oc ) {
+ fprintf( stderr, "%s: line %d: %s before %s\n",
+ fname, lineno, ldap_scherr2str(code), err );
+ oc_usage();
}
- *ocp = oc;
+ code = oc_add(oc,&err);
+ if ( code ) {
+ fprintf( stderr, "%s: line %d: %s %s\n",
+ fname, lineno, scherr2str(code), err);
+ exit( EXIT_FAILURE );
+ }
+ ldap_memfree(oc);
}
static void
-oc_usage()
+oc_usage( void )
+{
+ fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
+ fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n");
+ fprintf( stderr, " [ \"NAME\" qdescrs ]\n");
+ fprintf( stderr, " [ \"DESC\" qdstring ]\n");
+ fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
+ fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n");
+ fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
+ fprintf( stderr, " ; default structural\n");
+ fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n");
+ fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n");
+ fprintf( stderr, "whsp \")\"\n");
+ exit( EXIT_FAILURE );
+}
+
+static void
+oc_usage_old( void )
{
fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
fprintf( stderr, " [ requires <attrlist> ]\n" );
fprintf( stderr, " [ allows <attrlist> ]\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
+static void
+at_usage( void )
+{
+ fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
+ fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
+ fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
+ fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
+ fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
+ fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
+ fprintf( stderr, " ; AttributeType\n");
+ fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
+ fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
+ fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
+ fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
+ fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
+ fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
+ fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
+ fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
+ fprintf( stderr, " ; userApplications\n");
+ fprintf( stderr, " ; directoryOperation\n");
+ fprintf( stderr, " ; distributedOperation\n");
+ fprintf( stderr, " ; dSAOperation\n");
+ fprintf( stderr, "whsp \")\"\n");
+ exit( EXIT_FAILURE );
+}
+
+void
+parse_at(
+ char *fname,
+ int lineno,
+ char *line
+)
+{
+ LDAP_ATTRIBUTE_TYPE *at;
+ int code;
+ const char *err;
+
+ at = ldap_str2attributetype(line,&code,&err);
+ if ( !at ) {
+ fprintf( stderr, "%s: line %d: %s before %s\n",
+ fname, lineno, ldap_scherr2str(code), err );
+ at_usage();
+ }
+ code = at_add(at,&err);
+ if ( code ) {
+ fprintf( stderr, "%s: line %d: %s %s\n",
+ fname, lineno, scherr2str(code), err);
+ exit( EXIT_FAILURE );
+ }
+ ldap_memfree(at);
+}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-#include "ldapconfig.h"
-extern int get_filter();
-extern Backend *select_backend();
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "ldap_defaults.h"
+#include "slap.h"
-extern char *default_referral;
-void
-do_search( conn, op )
- Connection *conn; /* where to send results */
- Operation *op; /* info about the op to which we're responding */
+int
+do_search(
+ Connection *conn, /* where to send results */
+ Operation *op /* info about the op to which we're responding */
+)
{
int i, err;
- int scope, deref, attrsonly;
- int sizelimit, timelimit;
- char *base, *fstr;
- Filter *filter;
- char **attrs;
+ ber_int_t scope, deref, attrsonly;
+ ber_int_t sizelimit, timelimit;
+ char *base = NULL, *fstr = NULL;
+ Filter *filter = NULL;
+ char **attrs = NULL;
Backend *be;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_search: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the search request. It looks like this:
*
*/
/* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
- if ( ber_scanf( op->o_ber, "{aiiiib", &base, &scope, &deref, &sizelimit,
+ if ( ber_scanf( op->o_ber, "{aiiiib",
+ &base, &scope, &deref, &sizelimit,
&timelimit, &attrsonly ) == LBER_ERROR ) {
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ rc = -1;
+ goto return_results;
}
- if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
- && scope != LDAP_SCOPE_SUBTREE ) {
- free( base );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "Unknown search scope" );
- return;
+
+ switch( scope ) {
+ case LDAP_SCOPE_BASE:
+ case LDAP_SCOPE_ONELEVEL:
+ case LDAP_SCOPE_SUBTREE:
+ break;
+ default:
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "invalid scope", NULL, NULL );
+ rc = -1;
+ goto return_results;
+ }
+
+ switch( deref ) {
+ case LDAP_DEREF_NEVER:
+ case LDAP_DEREF_FINDING:
+ case LDAP_DEREF_SEARCHING:
+ case LDAP_DEREF_ALWAYS:
+ break;
+ default:
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "invalid deref", NULL, NULL );
+ rc = -1;
+ goto return_results;
+ }
+
+ if( dn_normalize_case( base ) == NULL ) {
+ send_ldap_result( conn, op, LDAP_INVALID_DN_SYNTAX,
+ NULL, "invalid DN", NULL, NULL );
+ rc = -1;
+ goto return_results;
}
- (void) dn_normalize( base );
Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base, scope, deref );
Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", sizelimit, timelimit,
attrsonly);
/* filter - returns a "normalized" version */
- filter = NULL;
- fstr = NULL;
if ( (err = get_filter( conn, op->o_ber, &filter, &fstr )) != 0 ) {
- if ( fstr != NULL ) {
- free( fstr );
+ if( err == -1 ) {
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decode error" );
+ } else {
+ send_ldap_result( conn, op, err,
+ NULL, "Bad search filter", NULL, NULL );
}
- free( base );
- send_ldap_result( conn, op, err, NULL, "Bad search filter" );
- return;
+ goto return_results;
}
+
Debug( LDAP_DEBUG_ARGS, " filter: %s\n", fstr, 0, 0 );
/* attributes */
- attrs = NULL;
- if ( ber_scanf( op->o_ber, "{v}}", &attrs ) == LBER_ERROR ) {
- free( base );
- free( fstr );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ if ( ber_scanf( op->o_ber, /*{*/ "{v}}", &attrs ) == LBER_ERROR ) {
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ rc = -1;
+ goto return_results;
}
+
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "do_search: get_ctrls failed\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ rc = 0;
+
Debug( LDAP_DEBUG_ARGS, " attrs:", 0, 0, 0 );
+
if ( attrs != NULL ) {
for ( i = 0; attrs[i] != NULL; i++ ) {
attr_normalize( attrs[i] );
Debug( LDAP_DEBUG_ARGS, " %s", attrs[i], 0, 0 );
}
}
+
Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
Statslog( LDAP_DEBUG_STATS,
- "conn=%d op=%d SRCH base=\"%s\" scope=%d filter=\"%s\"\n",
- conn->c_connid, op->o_opid, base, scope, fstr );
+ "conn=%ld op=%d SRCH base=\"%s\" scope=%d filter=\"%s\"\n",
+ op->o_connid, op->o_opid, base, scope, fstr );
-#if defined( SLAPD_MONITOR_DN ) || defined( SLAPD_CONFIG_DN ) || defined( SLAPD_SCHEMA_DN )
if ( scope == LDAP_SCOPE_BASE ) {
#if defined( SLAPD_MONITOR_DN )
- if ( strcasecmp( base, SLAPD_MONITOR_DN ) == 0 ) {
- free( base );
- free( fstr );
- monitor_info( conn, op );
- return;
+ if ( strcmp( base, SLAPD_MONITOR_DN ) == 0 ) {
+ monitor_info( conn, op, attrs, attrsonly );
+ goto return_results;
}
#endif
+
#if defined( SLAPD_CONFIG_DN )
- if ( strcasecmp( base, SLAPD_CONFIG_DN ) == 0 ) {
- free( base );
- free( fstr );
- config_info( conn, op );
- return;
+ if ( strcmp( base, SLAPD_CONFIG_DN ) == 0 ) {
+ config_info( conn, op, attrs, attrsonly );
+ goto return_results;
}
#endif
+
#if defined( SLAPD_SCHEMA_DN )
- if ( strcasecmp( base, SLAPD_SCHEMA_DN ) == 0 ) {
- free( base );
- free( fstr );
- schema_info( conn, op );
- return;
+ if ( strcmp( base, SLAPD_SCHEMA_DN ) == 0 ) {
+ schema_info( conn, op, attrs, attrsonly );
+ goto return_results;
}
#endif
+
+ if ( strcmp( base, LDAP_ROOT_DSE ) == 0 ) {
+ root_dse_info( conn, op, attrs, attrsonly );
+ goto return_results;
+ }
}
-#endif /* monitor or config or schema dn */
/*
* We could be serving multiple database backends. Select the
* if we don't hold it.
*/
if ( (be = select_backend( base )) == NULL ) {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
-
- free( base );
- free( fstr );
- filter_free( filter );
- if ( attrs != NULL ) {
- charray_free( attrs );
- }
- return;
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
+
+ goto return_results;
}
+ /* deref the base if needed */
+ base = suffix_alias( be, base );
+
/* actually do the search and send the result(s) */
- if ( be->be_search != NULL ) {
+ if ( be->be_search ) {
(*be->be_search)( be, conn, op, base, scope, deref, sizelimit,
timelimit, filter, fstr, attrs, attrsonly );
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
- free( base );
- free( fstr );
- filter_free( filter );
+return_results:;
+ if( base != NULL) free( base );
+ if( fstr != NULL) free( fstr );
+ if( filter != NULL) filter_free( filter );
if ( attrs != NULL ) {
charray_free( attrs );
}
+
+ return rc;
}
*/
-#include <sys/types.h>
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/string.h>
+#include <ac/unistd.h>
+
#include <pwd.h>
-#include <varargs.h>
+
#include <lber.h>
#include <ldap.h>
+
#include "shellutil.h"
#include "passwd-shell.h"
-#ifdef LDAP_DEBUG
-void debug_printf();
-#else /* LDAP_DEBUG */
-#define debug_printf()
-#endif /* LDAP_DEBUG */
-
-
-static void pwdfile_search( struct ldop *op, FILE *ofp );
-static struct ldentry *pw2entry( struct ldop *op, struct passwd *pw );
+static void pwdfile_search LDAP_P(( struct ldop *op, FILE *ofp ));
+static struct ldentry *pw2entry LDAP_P(( struct ldop *op, struct passwd *pw ));
static char tmpbuf[ MAXLINELEN * 2 ];
+int
main( int argc, char **argv )
{
int c, errflg;
struct ldop op;
- extern int optind;
- extern char *optarg;
if (( progname = strrchr( argv[ 0 ], '/' )) == NULL ) {
progname = estrdup( argv[ 0 ] );
if ( errflg || optind < argc ) {
fprintf( stderr, "usage: %s [-d]\n", progname );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
debug_printf( "started\n" );
(void) memset( (char *)&op, '\0', sizeof( op ));
if ( parse_input( stdin, stdout, &op ) < 0 ) {
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
if ( op.ldop_op != LDOP_SEARCH ) {
write_result( stdout, LDAP_UNWILLING_TO_PERFORM, NULL,
"Command Not Implemented" );
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
#ifdef LDAP_DEBUG
pwdfile_search( &op, stdout );
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
*/
-#include <sys/types.h>
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
+
+#include <ac/stdlib.h>
+#include <ac/stdarg.h>
+
#include <pwd.h>
-#include <varargs.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+
#include <lber.h>
#include <ldap.h>
#include "shellutil.h"
while ( args != NULL ) {
if (( p = strchr( args, ' ' )) != NULL ) {
*p++ = '\0';
- while ( isspace( *p )) {
+ while ( isspace( (unsigned char) *p )) {
++p;
}
}
for ( i = 0; ips[ i ].ip_type != 0; ++i ) {
if ( strncasecmp( *linep, ips[ i ].ip_tag, p - *linep ) == 0 ) {
- while ( isspace( *(++p) )) {
+ while ( isspace( (unsigned char) *(++p) )) {
;
}
*linep = p;
if (( p = strdup( s )) == NULL ) {
debug_printf( "strdup failed\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
return( p );
if ( p == NULL ) {
debug_printf( "realloc( p, %d ) failed\n", size );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
return( p );
if (( p = calloc( nelem, elsize )) == NULL ) {
debug_printf( "calloc( %d, %d ) failed\n", nelem, elsize );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
return( p );
/* VARARGS */
void
-debug_printf( va_alist /* char *fmt, args... */ )
+debug_printf
+#if HAVE_STDARG
+ ( char *fmt, ... )
+#else
+ ( va_alist )
va_dcl
+#endif
{
- char *fmt;
va_list ap;
-
- if ( debugflg ) {
- va_start( ap );
- fmt = va_arg( ap, char * );
- fprintf( stderr, "%s: ", progname );
- vfprintf( stderr, fmt, ap );
- va_end( ap );
- }
+#if !HAVE_STDARG
+ char *fmt;
+#endif
+
+ if ( debugflg ) {
+#if HAVE_STDARG
+ va_start( ap, fmt );
+#else
+ va_start( ap );
+ fmt = va_arg( ap, char * );
+#endif
+ fprintf( stderr, "%s: ", progname );
+ vfprintf( stderr, fmt, ap );
+ va_end( ap );
+ }
}
/* slap.h - stand alone ldap server include file */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
#ifndef _SLDAPD_H_
#define _SLDAPD_H_
-#define LDAP_SYSLOG
+#include <ac/stdlib.h>
+
+#include <sys/types.h>
+#include <ac/syslog.h>
+#include <ac/regex.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
+#ifdef HAVE_CYRUS_SASL
+#include <sasl.h>
+#endif
-#include <syslog.h>
#include "avl.h"
-#include "lber.h"
-#include "ldap.h"
-#include "lthread.h"
+
+#ifndef ldap_debug
+#define ldap_debug slap_debug
+#endif
+
+
+#include "ldap_log.h"
+
+#include <ldap.h>
+#include <ldap_schema.h>
+
+#include "ldap_pvt_thread.h"
#include "ldif.h"
+LDAP_BEGIN_DECL
+
+#ifdef f_next
+#undef f_next /* name conflict between sys/file.h on SCO and struct filter */
+#endif
+
+#define SERVICE_NAME OPENLDAP_PACKAGE "-slapd"
+
+/* LDAPMod.mod_op value ===> Must be kept in sync with ldap.h!
+ *
+ * This is a value used internally by the backends. It is needed to allow
+ * adding values that already exist without getting an error as required by
+ * modrdn when the new rdn was already an attribute value itself.
+ * JCG 05/1999 (gomez@engr.sgi.com)
+ */
+#define LDAP_MOD_SOFTADD 0x1000
+
+#ifdef DNS_DN
#define DN_DNS 0
#define DN_X500 1
+#endif
#define ON 1
#define OFF (-1)
+#define UNDEFINED 0
+
+#define MAXREMATCHES 10
+
+/* XXYYZ: these macros assume 'x' is an ASCII x */
+#define DNSEPARATOR(c) ((c) == ',' || (c) == ';')
+#define SEPARATOR(c) ((c) == ',' || (c) == ';' || (c) == '+')
+#define SPACE(c) ((c) == ' ' || (c) == '\n')
+
+#define ASCII_LOWER(c) ( (c) >= 'a' && (c) <= 'z' )
+#define ASCII_UPPER(c) ( (c) >= 'A' && (c) <= 'Z' )
+#define ASCII_ALPHA(c) ( ASCII_LOWER(c) || ASCII_UPPER(c) )
+#define ASCII_DIGIT(c) ( (c) >= '0' && (c) <= '9' )
+#define ASCII_ALNUM(c) ( ASCII_ALPHA(c) || ASCII_DIGIT(c) )
+
+#define LEADKEYCHAR(c) ( ASCII_ALPHA(c) )
+#define KEYCHAR(c) ( ASCII_ALNUM(c) || (c) == '-' )
+#define LEADOIDCHAR(c) ( ASCII_DIGIT(c) )
+#define OIDCHAR(c) ( ASCII_DIGIT(c) || (c) == '.' )
+
+#define LEADATTRCHAR(c) ( LEADKEYCHAR(c) || LEADOIDCHAR(c) )
+#define ATTRCHAR(c) ( KEYCHAR((c)) || (c) == '.' )
+
+#define NEEDSESCAPE(c) ((c) == '\\' || (c) == '"')
+
+#define SLAP_SCHERR_OUTOFMEM 1
+#define SLAP_SCHERR_CLASS_NOT_FOUND 2
+#define SLAP_SCHERR_ATTR_NOT_FOUND 3
+#define SLAP_SCHERR_DUP_CLASS 4
+#define SLAP_SCHERR_DUP_ATTR 5
+#define SLAP_SCHERR_DUP_SYNTAX 6
+#define SLAP_SCHERR_DUP_RULE 7
+#define SLAP_SCHERR_NO_NAME 8
+#define SLAP_SCHERR_ATTR_INCOMPLETE 9
+#define SLAP_SCHERR_MR_NOT_FOUND 10
+#define SLAP_SCHERR_SYN_NOT_FOUND 11
+#define SLAP_SCHERR_MR_INCOMPLETE 12
+
+extern int slap_debug;
+
+struct slap_op;
+struct slap_conn;
+
+struct replog_moddn {
+ char *newrdn;
+ int deloldrdn;
+ char *newsup;
+};
/*
* represents an attribute value assertion (i.e., attr=value)
*/
-typedef struct ava {
+typedef struct slap_ava {
char *ava_type;
struct berval ava_value;
} Ava;
+typedef struct slap_mra {
+ char *mra_rule;
+ char *mra_type;
+ char *mra_value;
+ int mra_dnattrs;
+} Mra;
+
/*
* represents a search filter
*/
-typedef struct filter {
- unsigned long f_choice; /* values taken from ldap.h */
+typedef struct slap_filter {
+ ber_tag_t f_choice; /* values taken from ldap.h */
- union {
+ union f_un_u {
/* present */
char *f_un_type;
/* equality, lessorequal, greaterorequal, approx */
Ava f_un_ava;
+ /* extensible */
+ Mra f_un_fra;
+
/* and, or, not */
- struct filter *f_un_complex;
+ struct slap_filter *f_un_complex;
/* substrings */
struct sub {
char *f_un_sub_final;
} f_un_sub;
} f_un;
+
+#define f_dn f_un.f_un_type /* used for DN indices */
#define f_type f_un.f_un_type
#define f_ava f_un.f_un_ava
#define f_avtype f_un.f_un_ava.ava_type
#define f_avvalue f_un.f_un_ava.ava_value
+#define f_mra f_un.f_un_mra
+#define f_mrtype f_un.f_un_mra.mra_type
+#define f_mrvalue f_un.f_un_mra.mra_value
+#define f_mrdnaddrs f_un.f_un_mra.mra_dnattrs
#define f_and f_un.f_un_complex
#define f_or f_un.f_un_complex
#define f_not f_un.f_un_complex
#define f_sub_any f_un.f_un_sub.f_un_sub_any
#define f_sub_final f_un.f_un_sub.f_un_sub_final
- struct filter *f_next;
+ struct slap_filter *f_next;
} Filter;
/*
* represents an attribute (type + values + syntax)
*/
-typedef struct attr {
+typedef struct slap_attr {
char *a_type;
struct berval **a_vals;
int a_syntax;
- struct attr *a_next;
+ struct slap_attr *a_next;
} Attribute;
/*
* the id used in the indexes to refer to an entry
*/
typedef unsigned long ID;
-#define NOID ((unsigned long)-1)
+#define NOID ((ID)~0)
/*
* represents an entry in core
*/
-typedef struct entry {
- char *e_dn; /* DN of this entry */
- Attribute *e_attrs; /* list of attributes + values */
-
- ID e_id; /* id of this entry - this should */
- /* really be private to back-ldbm */
- char e_state; /* for the cache */
-#define ENTRY_STATE_DELETED 1
-#define ENTRY_STATE_CREATING 2
- int e_refcnt; /* # threads ref'ing this entry */
- struct entry *e_lrunext; /* for cache lru list */
- struct entry *e_lruprev;
+typedef struct slap_entry {
+ /*
+ * The ID field should only be changed before entry is
+ * inserted into a cache. The ID value is backend
+ * specific.
+ */
+ ID e_id;
+
+ char *e_dn; /* DN of this entry */
+ char *e_ndn; /* normalized DN of this entry */
+ Attribute *e_attrs; /* list of attributes + values */
+
+ /* for use by the backend for any purpose */
+ void* e_private;
} Entry;
/*
*/
/* the "by" part */
-struct access {
- char *a_dnpat;
- char *a_addrpat;
- char *a_domainpat;
- char *a_dnattr;
- long a_access;
-#define ACL_NONE 0x01
-#define ACL_COMPARE 0x02
-#define ACL_SEARCH 0x04
-#define ACL_READ 0x08
-#define ACL_WRITE 0x10
-#define ACL_SELF 0x40
- struct access *a_next;
-};
+typedef struct slap_access {
+
+#define ACL_NONE 0x0001
+#define ACL_AUTH 0x0004
+#define ACL_COMPARE 0x0008
+#define ACL_SEARCH 0x0010
+#define ACL_READ 0x0020
+#define ACL_WRITE 0x0040
+#define ACL_PRIV_MASK 0x00ff
+
+#define ACL_SELF 0x4000
+#define ACL_INVALID (-1)
+
+#define ACL_IS(a,lvl) (((a) & (lvl)) == (lvl))
+
+#define ACL_IS_NONE(a) ACL_IS((a),ACL_SELF)
+#define ACL_IS_AUTH(a) ACL_IS((a),ACL_AUTH)
+#define ACL_IS_COMPARE(a) ACL_IS((a),ACL_COMPARE)
+#define ACL_IS_SEARCH(a) ACL_IS((a),ACL_SEARCH)
+#define ACL_IS_READ(a) ACL_IS((a),ACL_READ)
+#define ACL_IS_WRITE(a) ACL_IS((a),ACL_WRITE)
+#define ACL_IS_SELF(a) ACL_IS((a),ACL_SELF)
+#define ACL_IS_INVALID(a) ((a) == ACL_INVALID)
+
+#define ACL_CLR(a) ((a) = 0)
+#define ACL_SET(a,lvl) ((a) |= (lvl))
+#define ACL_SET_NONE(a) ACL_SET((a),ACL_SELF)
+#define ACL_SET_AUTH(a) ACL_SET((a),ACL_AUTH)
+#define ACL_SET_COMPARE(a) ACL_SET((a),ACL_COMPARE)
+#define ACL_SET_SEARCH(a) ACL_SET((a),ACL_SEARCH)
+#define ACL_SET_READ(a) ACL_SET((a),ACL_READ)
+#define ACL_SET_WRITE(a) ACL_SET((a),ACL_WRITE)
+#define ACL_SET_SELF(a) ACL_SET((a),ACL_SELF)
+#define ACL_SET_INVALID(a) ((a) = ACL_INVALID)
+
+#define ACL_PRIV(a) ((a) & ACL_PRIV_MASK)
+#define ACL_GRANT(a,lvl) (ACL_PRIV(a) >= (lvl))
+
+ int a_access;
+
+ char *a_dn_pat;
+ char *a_dn_at;
+
+ char *a_peername_pat;
+ char *a_sockname_pat;
+
+ char *a_domain_pat;
+ char *a_sockurl_pat;
+
+ /* ACL Groups */
+ char *a_group_pat;
+ char *a_group_oc;
+ char *a_group_at;
+
+ struct slap_access *a_next;
+} Access;
/* the "to" part */
-struct acl {
+typedef struct slap_acl {
/* "to" part: the entries this acl applies to */
Filter *acl_filter;
- char *acl_dnpat;
+ regex_t acl_dn_re;
+ char *acl_dn_pat;
char **acl_attrs;
/* "by" part: list of who has what access to the entries */
- struct access *acl_access;
+ Access *acl_access;
- struct acl *acl_next;
-};
+ struct slap_acl *acl_next;
+} AccessControl;
/*
- * represents schema information for a database
+ * A list of LDAPMods
*/
+typedef struct ldapmodlist {
+ struct ldapmod ml_mod;
+ struct ldapmodlist *ml_next;
+#define ml_op ml_mod.mod_op
+#define ml_type ml_mod.mod_type
+#define ml_values ml_mod.mod_values
+#define ml_bvalues ml_mod.mod_bvalues
+} LDAPModList;
-struct objclass {
- char *oc_name;
- char **oc_required;
- char **oc_allowed;
- struct objclass *oc_next;
-};
+/*
+ * represents schema information for a database
+ */
+typedef int slap_syntax_check_func LDAP_P((struct berval * val));
+
+typedef struct slap_syntax {
+ LDAP_SYNTAX ssyn_syn;
+ slap_syntax_check_func *ssyn_check;
+ struct slap_syntax *ssyn_next;
+} Syntax;
+#define ssyn_oid ssyn_syn.syn_oid
+#define ssyn_desc ssyn_syn.syn_desc
+
+typedef int slap_mr_normalize_func LDAP_P((struct berval * val, struct berval **normalized));
+typedef int slap_mr_compare_func LDAP_P((struct berval * val1, struct berval * val2));
+
+typedef struct slap_matching_rule {
+ LDAP_MATCHING_RULE smr_mrule;
+ slap_mr_normalize_func *smr_normalize;
+ slap_mr_compare_func *smr_compare;
+ Syntax *smr_syntax;
+ struct slap_matching_rule *smr_next;
+} MatchingRule;
+#define smr_oid smr_mrule.mr_oid
+#define smr_names smr_mrule.mr_names
+#define smr_desc smr_mrule.mr_desc
+#define smr_obsolete smr_mrule.mr_obsolete
+#define smr_syntax_oid smr_mrule.mr_syntax_oid
+
+typedef struct slap_attribute_type {
+ LDAP_ATTRIBUTE_TYPE sat_atype;
+ struct slap_attribute_type *sat_sup;
+ struct slap_attribute_type **sat_subtypes;
+ MatchingRule *sat_equality;
+ MatchingRule *sat_ordering;
+ MatchingRule *sat_substr;
+ Syntax *sat_syntax;
+ /* The next one is created to help in the transition */
+ int sat_syntax_compat;
+ struct slap_attribute_type *sat_next;
+} AttributeType;
+#define sat_oid sat_atype.at_oid
+#define sat_names sat_atype.at_names
+#define sat_desc sat_atype.at_desc
+#define sat_obsolete sat_atype.at_obsolete
+#define sat_sup_oid sat_atype.at_sup_oid
+#define sat_equality_oid sat_atype.at_equality_oid
+#define sat_ordering_oid sat_atype.at_ordering_oid
+#define sat_substr_oid sat_atype.at_substr_oid
+#define sat_syntax_oid sat_atype.at_syntax_oid
+#define sat_syntax_len sat_atype.at_syntax_len
+#define sat_single_value sat_atype.at_single_value
+#define sat_collective sat_atype.at_collective
+#define sat_no_user_mods sat_atype.at_no_user_mods
+#define sat_usage sat_atype.at_usage
+
+typedef struct slap_object_class {
+ LDAP_OBJECT_CLASS soc_oclass;
+ struct slap_object_class **soc_sups;
+ AttributeType **soc_required;
+ AttributeType **soc_allowed;
+ struct slap_object_class *soc_next;
+} ObjectClass;
+#define soc_oid soc_oclass.oc_oid
+#define soc_names soc_oclass.oc_names
+#define soc_desc soc_oclass.oc_desc
+#define soc_obsolete soc_oclass.oc_obsolete
+#define soc_sup_oids soc_oclass.oc_sup_oids
+#define soc_kind soc_oclass.oc_kind
+#define soc_at_oids_must soc_oclass.oc_at_oids_must
+#define soc_at_oids_may soc_oclass.oc_at_oids_may
/*
- * represents a "database"
+ * Backend-info
+ * represents a backend
*/
-typedef struct backend {
+typedef struct slap_backend_info BackendInfo; /* per backend type */
+typedef struct slap_backend_db BackendDB; /* per backend database */
+
+extern int nBackendInfo;
+extern int nBackendDB;
+extern BackendInfo *backendInfo;
+extern BackendDB *backendDB;
+
+extern int slapMode;
+#define SLAP_UNDEFINED_MODE 0x0000
+#define SLAP_SERVER_MODE 0x0001
+#define SLAP_TOOL_MODE 0x0002
+#define SLAP_MODE 0x0003
+
+#define SLAP_TRUNCATE_MODE 0x0100
+#ifdef SLAPD_BDB2
+#define SLAP_TIMED_MODE 0x1000
+#endif
+#define SLAP_TOOLID_MODE 4
+
+/* temporary aliases */
+typedef BackendDB Backend;
+#define nbackends nBackendDB
+#define backends backendDB
+
+struct slap_backend_db {
+ BackendInfo *bd_info; /* pointer to shared backend info */
+
+ /* BackendInfo accessors */
+#define be_config bd_info->bi_db_config
+#define be_type bd_info->bi_type
+
+#define be_bind bd_info->bi_op_bind
+#define be_unbind bd_info->bi_op_unbind
+#define be_add bd_info->bi_op_add
+#define be_compare bd_info->bi_op_compare
+#define be_delete bd_info->bi_op_delete
+#define be_modify bd_info->bi_op_modify
+#define be_modrdn bd_info->bi_op_modrdn
+#define be_search bd_info->bi_op_search
+
+#define be_release bd_info->bi_entry_release_rw
+#define be_group bd_info->bi_acl_group
+
+#define be_connection_init bd_info->bi_connection_init
+#define be_connection_destroy bd_info->bi_connection_destroy
+
+#ifdef SLAPD_TOOLS
+#define be_entry_open bd_info->bi_tool_entry_open
+#define be_entry_close bd_info->bi_tool_entry_close
+#define be_entry_first bd_info->bi_tool_entry_first
+#define be_entry_next bd_info->bi_tool_entry_next
+#define be_entry_get bd_info->bi_tool_entry_get
+#define be_entry_put bd_info->bi_tool_entry_put
+#define be_index_attr bd_info->bi_tool_index_attr
+#define be_index_change bd_info->bi_tool_index_change
+#define be_sync bd_info->bi_tool_sync
+#endif
+
+ /* these should be renamed from be_ to bd_ */
char **be_suffix; /* the DN suffixes of data in this backend */
- char *be_rootdn; /* the magic "root" dn for this db */
- char *be_rootpw; /* the magic "root" password for this db */
+ char **be_nsuffix; /* the normalized DN suffixes in this backend */
+ char **be_suffixAlias; /* pairs of DN suffix aliases and deref values */
+ char *be_root_dn; /* the magic "root" dn for this db */
+ char *be_root_ndn; /* the magic "root" normalized dn for this db */
+ char *be_root_pw; /* the magic "root" password for this db */
int be_readonly; /* 1 => db is in "read only" mode */
+ unsigned int be_max_deref_depth; /* limit for depth of an alias deref */
int be_sizelimit; /* size limit for this backend */
int be_timelimit; /* time limit for this backend */
- struct acl *be_acl; /* access control list for this backend */
+ AccessControl *be_acl; /* access control list for this backend */
int be_dfltaccess; /* access given if no acl matches */
char **be_replica; /* replicas of this backend (in master) */
char *be_replogfile; /* replication log file (in master) */
- char *be_updatedn; /* allowed to make changes (in replicas) */
+ char *be_update_ndn; /* allowed to make changes (in replicas) */
+ struct berval **be_update_refs; /* where to refer modifying clients to */
int be_lastmod; /* keep track of lastmodified{by,time} */
- char *be_type; /* type of database */
-
- void *be_private; /* anything the backend needs */
-
- IFP be_bind; /* backend bind routine */
- IFP be_unbind; /* backend unbind routine */
- IFP be_search; /* backend search routine */
- IFP be_compare; /* backend compare routine */
- IFP be_modify; /* backend modify routine */
- IFP be_modrdn; /* backend modrdn routine */
- IFP be_add; /* backend add routine */
- IFP be_delete; /* backend delete routine */
- IFP be_abandon; /* backend abandon routine */
- IFP be_config; /* backend config routine */
- IFP be_init; /* backend init routine */
- IFP be_close; /* backend close routine */
-} Backend;
+
+ char *be_realm;
+
+ void *be_private; /* anything the backend database needs */
+};
+
+struct slap_backend_info {
+ char *bi_type; /* type of backend */
+
+ /*
+ * per backend type routines:
+ * bi_init: called to allocate a backend_info structure,
+ * called once BEFORE configuration file is read.
+ * bi_init() initializes this structure hence is
+ * called directly from be_initialize()
+ * bi_config: called per 'backend' specific option
+ * all such options must before any 'database' options
+ * bi_config() is called only from read_config()
+ * bi_open: called to open each database, called
+ * once AFTER configuration file is read but
+ * BEFORE any bi_db_open() calls.
+ * bi_open() is called from backend_startup()
+ * bi_close: called to close each database, called
+ * once during shutdown after all bi_db_close calls.
+ * bi_close() is called from backend_shutdown()
+ * bi_destroy: called to destroy each database, called
+ * once during shutdown after all bi_db_destroy calls.
+ * bi_destory() is called from backend_destroy()
+ */
+ int (*bi_init) LDAP_P((BackendInfo *bi));
+ int (*bi_config) LDAP_P((BackendInfo *bi,
+ char *fname, int lineno, int argc, char **argv ));
+ int (*bi_open) LDAP_P((BackendInfo *bi));
+ int (*bi_close) LDAP_P((BackendInfo *bi));
+ int (*bi_destroy) LDAP_P((BackendInfo *bi));
+
+ /*
+ * per database routines:
+ * bi_db_init: called to initialize each database,
+ * called upon reading 'database <type>'
+ * called only from backend_db_init()
+ * bi_db_config: called to configure each database,
+ * called per database to handle per database options
+ * called only from read_config()
+ * bi_db_open: called to open each database
+ * called once per database immediately AFTER bi_open()
+ * calls but before daemon startup.
+ * called only by backend_startup()
+ * bi_db_close: called to close each database
+ * called once per database during shutdown but BEFORE
+ * any bi_close call.
+ * called only by backend_shutdown()
+ * bi_db_destroy: called to destroy each database
+ * called once per database during shutdown AFTER all
+ * bi_close calls but before bi_destory calls.
+ * called only by backend_destory()
+ */
+ int (*bi_db_init) LDAP_P((Backend *bd));
+ int (*bi_db_config) LDAP_P((Backend *bd,
+ char *fname, int lineno, int argc, char **argv ));
+ int (*bi_db_open) LDAP_P((Backend *bd));
+ int (*bi_db_close) LDAP_P((Backend *bd));
+ int (*bi_db_destroy) LDAP_P((Backend *db));
+
+ /* LDAP Operations Handling Routines */
+ int (*bi_op_bind) LDAP_P(( BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ char *dn, int method, char* mechanism,
+ struct berval *cred, char** edn ));
+ int (*bi_op_unbind) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o ));
+ int (*bi_op_search) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ char *base, int scope, int deref,
+ int slimit, int tlimit,
+ Filter *f, char *filterstr, char **attrs,
+ int attrsonly));
+ int (*bi_op_compare)LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ char *dn, Ava *ava));
+ int (*bi_op_modify) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ char *dn, LDAPModList *m));
+ int (*bi_op_modrdn) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ char *dn, char *newrdn, int deleteoldrdn,
+ char *newSuperior));
+ int (*bi_op_add) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ Entry *e));
+ int (*bi_op_delete) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ char *dn));
+ int (*bi_op_abandon) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ ber_int_t msgid));
+
+ /* Auxilary Functions */
+ int (*bi_entry_release_rw) LDAP_P((BackendDB *bd, Entry *e, int rw));
+
+ int (*bi_acl_group) LDAP_P((Backend *bd,
+ Entry *e, char *bdn, char *edn,
+ char *objectclassValue, char *groupattrName ));
+
+ int (*bi_connection_init) LDAP_P((BackendDB *bd,
+ struct slap_conn *c));
+ int (*bi_connection_destroy) LDAP_P((BackendDB *bd,
+ struct slap_conn *c));
+
+ /* hooks for slap tools */
+ int (*bi_tool_entry_open) LDAP_P(( BackendDB *be, int mode ));
+ int (*bi_tool_entry_close) LDAP_P(( BackendDB *be ));
+ ID (*bi_tool_entry_first) LDAP_P(( BackendDB *be ));
+ ID (*bi_tool_entry_next) LDAP_P(( BackendDB *be ));
+ Entry* (*bi_tool_entry_get) LDAP_P(( BackendDB *be, ID id ));
+ ID (*bi_tool_entry_put) LDAP_P(( BackendDB *be, Entry *e ));
+ int (*bi_tool_index_attr) LDAP_P(( BackendDB *be, char* type ));
+ int (*bi_tool_index_change) LDAP_P(( BackendDB *be, char* type,
+ struct berval **bv, ID id, int op ));
+ int (*bi_tool_sync) LDAP_P(( BackendDB *be ));
+
+#define SLAP_INDEX_ADD_OP 0x0001
+#define SLAP_INDEX_DELETE_OP 0x0002
+
+ unsigned int bi_nDB; /* number of databases of this type */
+ void *bi_private; /* anything the backend type needs */
+};
/*
* represents an operation pending from an ldap client
*/
-typedef struct op {
+typedef struct slap_op {
+ ber_int_t o_opid; /* id of this operation */
+ ber_int_t o_msgid; /* msgid of the request */
+
+ ldap_pvt_thread_t o_tid; /* thread handling this op */
+
BerElement *o_ber; /* ber of the request */
- long o_msgid; /* msgid of the request */
- unsigned long o_tag; /* tag of the request */
+
+ ber_tag_t o_tag; /* tag of the request */
time_t o_time; /* time op was initiated */
+
+ int o_bind_in_progress; /* multi-step bind in progress */
+
char *o_dn; /* dn bound when op was initiated */
- int o_authtype; /* auth method used to bind dn */
+ char *o_ndn; /* normalized dn bound when op was initiated */
+ ber_int_t o_protocol; /* version of the LDAP protocol used by client */
+ ber_tag_t o_authtype; /* auth method used to bind dn */
/* values taken from ldap.h */
/* LDAP_AUTH_* */
- int o_opid; /* id of this operation */
- int o_connid; /* id of conn initiating this op */
-#ifdef CLDAP
+ char *o_authmech; /* SASL mechanism used to bind dn */
+
+ LDAPControl **o_ctrls; /* controls */
+
+ unsigned long o_connid; /* id of conn initiating this op */
+
+#ifdef LDAP_CONNECTIONLESS
int o_cldap; /* != 0 if this came in via CLDAP */
struct sockaddr o_clientaddr; /* client address if via CLDAP */
char o_searchbase; /* search base if via CLDAP */
#endif
- struct op *o_next; /* next operation pending */
- pthread_t o_tid; /* thread handling this op */
- int o_abandon; /* signals op has been abandoned */
- pthread_mutex_t o_abandonmutex; /* signals op has been abandoned */
- int o_private; /* anything the backend needs */
+ ldap_pvt_thread_mutex_t o_abandonmutex; /* protects o_abandon */
+ int o_abandon; /* abandon flag */
+
+ struct slap_op *o_next; /* next operation in list */
+ void *o_private; /* anything the backend needs */
} Operation;
/*
* represents a connection from an ldap client
*/
-typedef struct conn {
- Sockbuf c_sb; /* ber connection stuff */
- char *c_dn; /* current DN bound to this conn */
- pthread_mutex_t c_dnmutex; /* mutex for c_dn field */
- int c_authtype; /* auth method used to bind c_dn */
-#ifdef COMPAT
- int c_version; /* for compatibility w/2.0, 3.0 */
-#endif
- char *c_addr; /* address of client on this conn */
- char *c_domain; /* domain of client on this conn */
- Operation *c_ops; /* list of pending operations */
- pthread_mutex_t c_opsmutex; /* mutex for c_ops list & stats */
- pthread_mutex_t c_pdumutex; /* only one pdu written at a time */
- pthread_cond_t c_wcv; /* used to wait for sd write-ready*/
- int c_gettingber; /* in the middle of ber_get_next */
- BerElement *c_currentber; /* ber we're getting */
- int c_writewaiter; /* signals write-ready sd waiter */
- int c_pduwaiters; /* signals threads waiting 4 pdu */
+typedef struct slap_conn {
+ int c_struct_state; /* structure management state */
+ int c_conn_state; /* connection state */
+
+ ldap_pvt_thread_mutex_t c_mutex; /* protect the connection */
+ Sockbuf *c_sb; /* ber connection stuff */
+
+ /* only can be changed by connect_init */
time_t c_starttime; /* when the connection was opened */
- int c_connid; /* id of this connection for stats*/
- int c_opsinitiated; /* # ops initiated/next op id */
- int c_opscompleted; /* # ops completed */
+ time_t c_activitytime; /* when the connection was last used */
+ unsigned long c_connid; /* id of this connection for stats*/
+
+ char *c_listener_url; /* listener URL */
+ char *c_peer_domain; /* DNS name of client */
+ char *c_peer_name; /* peer name (trans=addr:port) */
+ char *c_sock_name; /* sock name (trans=addr:port) */
+
+#ifdef HAVE_CYRUS_SASL
+ sasl_conn_t *c_sasl_context;
+#endif
+
+ /* only can be changed by binding thread */
+ int c_bind_in_progress; /* multi-op bind in progress */
+
+ char *c_cdn; /* DN provided by the client */
+ char *c_dn; /* DN bound to this conn */
+ ber_int_t c_protocol; /* version of the LDAP protocol used by client */
+ ber_tag_t c_authtype;/* auth method used to bind c_dn */
+ char *c_authmech; /* SASL mechanism used to bind c_dn */
+ void *c_authstate; /* SASL state data */
+
+ Operation *c_ops; /* list of operations being processed */
+ Operation *c_pending_ops; /* list of pending operations */
+
+ ldap_pvt_thread_mutex_t c_write_mutex; /* only one pdu written at a time */
+ ldap_pvt_thread_cond_t c_write_cv; /* used to wait for sd write-ready*/
+
+ BerElement *c_currentber; /* ber we're attempting to read */
+ int c_writewaiter; /* true if writer is waiting */
+
+#ifdef HAVE_TLS
+ int c_is_tls; /* true if this LDAP over raw TLS */
+ int c_needs_tls_accept; /* true if SSL_accept should be called */
+#endif
+
+ long c_n_ops_received; /* num of ops received (next op_id) */
+ long c_n_ops_executing; /* num of ops currently executing */
+ long c_n_ops_pending; /* num of ops pending execution */
+ long c_n_ops_completed; /* num of ops completed */
+
+ long c_n_get; /* num of get calls */
+ long c_n_read; /* num of read calls */
+ long c_n_write; /* num of write calls */
} Connection;
#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) \
- { \
- if ( ldap_debug & level ) \
- fprintf( stderr, fmt, connid, opid, arg1, arg2, arg3 );\
- if ( ldap_syslog & level ) \
- syslog( ldap_syslog_level, fmt, connid, opid, arg1, \
- arg2, arg3 ); \
- }
+ do { \
+ if ( ldap_debug & (level) ) \
+ fprintf( stderr, (fmt), (connid), (opid), (arg1), (arg2), (arg3) );\
+ if ( ldap_syslog & (level) ) \
+ syslog( ldap_syslog_level, (fmt), (connid), (opid), (arg1), \
+ (arg2), (arg3) ); \
+ } while (0)
#else
#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 )
#endif
-#ifdef NEEDPROTOS
+LDAP_END_DECL
+
#include "proto-slap.h"
-#endif
#endif /* _slap_h_ */
requires
objectClass
+objectclass ldapsubentry
+ requires
+ objectclass
+
objectclass alias
requires
aliasedObjectName,
objectClass
+objectclass referral
+ requires
+ ref,
+ objectClass
+
+objectclass dcobject
+ requires
+ objectClass,
+ dc
+
+objectclass uidobject
+ requires
+ objectClass,
+ uid
+
objectclass country
requires
objectClass,
/* str2filter.c - parse an rfc 1588 string filter */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/socket.h>
+
#include "slap.h"
-static char *find_matching_paren();
-static Filter *str2list();
-static Filter *str2simple();
-static int str2subvals();
+static char *find_matching_paren(char *s);
+static Filter *str2list(char *str, long unsigned int ftype);
+static Filter *str2simple(char *str);
+static int str2subvals(char *val, Filter *f);
Filter *
str2filter( char *str )
{
- Filter *f;
+ Filter *f = NULL;
char *end;
Debug( LDAP_DEBUG_FILTER, "str2filter \"%s\"\n", str, 0, 0 );
fp = &f->f_list;
while ( *str ) {
- while ( *str && isspace( *str ) )
+ while ( *str && isspace( (unsigned char) *str ) )
str++;
if ( *str == '\0' )
break;
f->f_choice = LDAP_FILTER_PRESENT;
} else {
f->f_choice = LDAP_FILTER_SUBSTRINGS;
- f->f_sub_type = strdup( str );
+ f->f_sub_type = ch_strdup( str );
if ( str2subvals( value, f ) != 0 ) {
filter_free( f );
*(value-1) = '=';
}
if ( f->f_choice == LDAP_FILTER_PRESENT ) {
- f->f_type = strdup( str );
+ f->f_type = ch_strdup( str );
} else {
- f->f_avtype = strdup( str );
- f->f_avvalue.bv_val = strdup( value );
+ f->f_avtype = ch_strdup( str );
+ f->f_avvalue.bv_val = ch_strdup( value );
f->f_avvalue.bv_len = strlen( value );
}
*nextstar++ = '\0';
if ( gotstar == 0 ) {
- f->f_sub_initial = strdup( val );
+ f->f_sub_initial = ch_strdup( val );
} else if ( nextstar == NULL ) {
- f->f_sub_final = strdup( val );
+ f->f_sub_final = ch_strdup( val );
} else {
- charray_add( &f->f_sub_any, strdup( val ) );
+ charray_add( &f->f_sub_any, ch_strdup( val ) );
}
gotstar = 1;
# Stand alone LDAP server tools makefile
#
#-----------------------------------------------------------------------------
-HAVE_ISODE = @HAVE_ISODE@
BUILD_LDBM = @BUILD_LDBM@
BUILD_BDB2 = @BUILD_BDB2@
+BUILD_QUIPU = @BUILD_QUIPU@
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
+SLAP_DIR=../
+SLAPD_MODULES = @SLAPD_MODULES_LIST@
XDEFS = $(MODULES_CPPFLAGS)
-XLDFLAGS = $(MODULES_LDFLAGS)
+XLDFLAGS = $(MODULES_LDFLAGS) $(SLAPD_MODULES)
XLIBS = -lavl -lldif -lldbm -lldap_r -llber -llutil
-XXLIBS = $(SLAPD_LIBS) \
- $(PERL_LDFLAGS) $(LDBM_LIBS) $(KRB_LIBS) $(TLS_LIBS) $(LUTIL_LIBS)
-XXXLIBS = $(LTHREAD_LIBS)
+XXLIBS = $(LDAPD_LIBS) $(SLAPD_LIBS) \
+ $(PERL_LDFLAGS) $(LDBM_LIBS) $(SECURITY_LIBS) \
+ $(LDIF_LIBS) $(LUTIL_LIBS)
+XXXLIBS = $(LTHREAD_LIBS) $(MODULES_LIBS)
-PROGRAMS=ldif2index ldif2ldbm ldbmcat ldif2id2entry ldif2id2children \
- centipede ldbmtest ldif
+PROGRAMS=ldif slapadd slapcat slapindex
+LDBMPROGRAMS=centipede sizecount
+BDB2PROGRAMS=
+QUIPUPROGRAMS=chlog2replog edb2ldif
-PROGRAMS2=ldif2index-bdb2 ldif2ldbm-bdb2 \
- ldif2id2entry-bdb2 ldif2id2children-bdb2
-
-SRCS = centipede.c ldbmcat.c ldbmtest.c sizecount.c \
- ldif.c ldif2id2children.c ldif2id2entry.c ldif2index.c ldif2ldbm.c \
- mimic.c
-
-SRCS2 = ldif2id2children-bdb2.c ldif2id2entry-bdb2.c \
- ldif2index-bdb2.c ldif2ldbm-bdb2.c
+SRCS = ldif.c mimic.c slapcommon.c
XSRCS = edb2-vers.c
-EDB2LDIFSRCS = edb2ldif.c ldapsyntax.c
-EDB2LDIFOBJS = edb2ldif.o ldapsyntax.o
+LDBMSRCS = centipede.c sizecount.c
+
+BDB2SRCS =
-OBJS2 = mimic.o \
- ../config.o ../ch_malloc.o ../backend.o ../charray.o \
+QUIPUSRCS = edb2ldif.c ldapsyntax.c chlog2replog.c
+SLAPD_OBJS = ../config.o ../ch_malloc.o ../backend.o ../charray.o \
../module.o ../aclparse.o ../schema.o ../filterentry.o \
../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \
../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \
../controls.o ../schemaparse.o
+SLAPOBJS = $(SLAPD_OBJS) slapcommon.o mimic.o
-all-local: build-ldbm build-bdb2 build-edb2ldif build-chlog2replog
-
-build-ldbm: FORCE
- @if [ "$(BUILD_LDBM)" = "yes" ]; then \
- $(MAKE) $(MFLAGS) ldbm-tools; \
- else \
- echo "run configure with --with-ldbm to build LDBM tools"; \
- fi
-
-build-bdb2: FORCE
- @if [ "$(BUILD_BDB2)" = "yes" ]; then \
- $(MAKE) $(MFLAGS) bdb2-tools; \
- else \
- echo "run configure with --enable-bdb2 to build BDB2 tools"; \
- fi
-
-ldbm-tools: $(PROGRAMS)
-
-bdb2-tools: $(PROGRAMS2)
-
-build-edb2ldif: FORCE
- @if [ "$(HAVE_ISODE)" = "yes" ]; then \
- $(MAKE) $(MFLAGS) edb2ldif; \
- else \
- echo "run configure with --with-isode to build edb2ldif"; \
- fi
-
-edb2ldif: edb2-vers.o
- $(CC) $(LDFLAGS) -o $@ $(EDB2LDIFOBJS) edb2-vers.o $(LIBS)
-
-edb2-vers.c: $(EDB2LDIFOBJS)
- @-$(RM) $@
- $(MKVERSION) ebd2ldif > $@
+EDB2LDIFSRCS = edb2ldif.c ldapsyntax.c
+EDB2LDIFOBJS = edb2ldif.o ldapsyntax.o
-build-chlog2replog: FORCE
- @if [ "$(HAVE_ISODE)" = "yes" ]; then \
- $(MAKE) $(MFLAGS) chlog2replog; \
- else \
- echo "run configure with --with-isode to build chlog2replog"; \
- fi
+all-local: build-progs build-ldbm build-bdb2 build-quipu
-chlog2replog: chlog2replog.o ../lock.o ../ch_malloc.o $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ chlog2replog.o ../lock.o ../ch_malloc.o $(LIBS)
+build-progs: $(PROGRAMS)
-ldif2index: ldif2index.o ../libbackends.a $(OBJS2) $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ ldif2index.o $(OBJS2) ../libbackends.a $(LIBS)
+build-ldbm: ldbm-tools-$(BUILD_LDBM)
+ldbm-tools-no:
+ @echo "run configure with --enable-ldbm to build LDBM tools"
-ldif2index-bdb2: ldif2index-bdb2.o ../libbackends.a \
- $(OBJS2) $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ ldif2index-bdb2.o $(OBJS2) ../libbackends.a $(LIBS)
+ldbm-tools-yes ldbm-tools-mod: $(LDBMPROGRAMS)
-ldif2ldbm: ldif2ldbm.o ../libbackends.a $(OBJS2) $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ ldif2ldbm.o $(OBJS2) ../libbackends.a $(LIBS)
+build-bdb2: bdb2-tools-$(BUILD_BDB2)
+bdb2-tools-no:
+ @echo "run configure with --enable-bdb2 to build BDB2 tools"
-ldif2ldbm-bdb2: ldif2ldbm-bdb2.o ../libbackends.a $(OBJS2) $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ ldif2ldbm-bdb2.o $(OBJS2) ../libbackends.a $(LIBS)
+bdb2-tools-yes bdb2-tools-mod: $(BDB2PROGRAMS)
-ldif2id2entry: ldif2id2entry.o ../libbackends.a $(OBJS2) $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ ldif2id2entry.o $(OBJS2) ../libbackends.a $(LIBS)
+build-quipu: quipu-tools-$(BUILD_QUIPU)
+quipu-tools-no:
+ @echo "run configure with --enable-quipu to build QUIPU tools"
-ldif2id2entry-bdb2: ldif2id2entry-bdb2.o ../libbackends.a \
- $(OBJS2) $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ ldif2id2entry-bdb2.o $(OBJS2) ../libbackends.a $(LIBS)
+quipu-tools-yes quipu-tools-mod: $(QUIPUPROGRAMS)
-ldif2id2children: ldif2id2children.o ../libbackends.a \
- $(OBJS2) $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ ldif2id2children.o $(OBJS2) ../libbackends.a $(LIBS)
+#
+# SLAP Tools
+#
+slapadd: slapadd.o ../libbackends.a $(SLAPOBJS) $(SLAPD_LIBDEPEND)
+ $(LTLINK) -o $@ slapadd.o $(SLAPOBJS) ../libbackends.a $(LIBS)
-ldif2id2children-bdb2: ldif2id2children-bdb2.o ../libbackends.a \
- $(OBJS2) $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ ldif2id2children-bdb2.o $(OBJS2) ../libbackends.a $(LIBS)
+slapcat: slapcat.o ../libbackends.a $(SLAPOBJS) $(SLAPD_LIBDEPEND)
+ $(LTLINK) -o $@ slapcat.o $(SLAPOBJS) ../libbackends.a $(LIBS)
-ldbmcat: ldbmcat.o $(SLAPD_LIBDEPEND)
- $(LTLINK) -o $@ ldbmcat.o $(LIBS)
+slapindex: slapindex.o ../libbackends.a $(SLAPOBJS) $(SLAPD_LIBDEPEND)
+ $(LTLINK) -o $@ slapindex.o $(SLAPOBJS) ../libbackends.a $(LIBS)
ldif: ldif.o $(SLAPD_LIBDEPEND)
$(LTLINK) -o $@ ldif.o $(LIBS)
+#
+# LDBM Specific Tools
+#
centipede: centipede.o $(SLAPD_LIBDEPEND)
$(LTLINK) -o $@ centipede.o $(LIBS)
sizecount: sizecount.o ../phonetic.o ../ch_malloc.o $(SLAPD_LIBDEPEND)
$(LTLINK) -o $@ sizecount.o ../phonetic.o ../ch_malloc.o $(LIBS)
-ldbmtest: ldbmtest.o ../libbackends.a $(OBJS2) $(SLAPD_LIBDEPEND)
- $(LTLINK) -o ldbmtest ldbmtest.o $(OBJS2) ../libbackends.a $(LIBS)
+#
+# BDBM Specific Tools
+#
+
+#
+# QUIPU Specific Tools
+#
+edb2ldif: edb2-vers.o
+ $(CC) $(LDFLAGS) -o $@ $(EDB2LDIFOBJS) edb2-vers.o $(LIBS)
+
+edb2-vers.c: $(EDB2LDIFOBJS)
+ @-$(RM) $@
+ $(MKVERSION) ebd2ldif > $@
+
+chlog2replog: chlog2replog.o ../lock.o ../ch_malloc.o $(SLAPD_LIBDEPEND)
+ $(LTLINK) -o $@ chlog2replog.o ../lock.o ../ch_malloc.o $(LIBS)
clean-local: FORCE
- $(RM) $(PROGRAMS) $(PROGRAMS2) $(XPROGRAMS) $(XSRCS) edb2-vers.c \
- *.o core .libs/*
+ $(RM) $(PROGRAMS) $(LDBMPROGRAMS) $(BDB2PROGRAMS) $(QUIPUPROGRAMS) \
+ $(XPROGRAMS) $(XSRCS) *.o core .libs/*
depend-local: FORCE
- @DEPEND=no ; DEPEND_LDBM= ; DEPEND_BDB2= ; DEPEND_ISODE= ; \
- if [ "$(BUILD_LDBM)" = "yes" ]; then \
- DEPEND_LDBM="$(SRCS)"; \
- DEPEND=yes ; \
+ @DEPEND_LDBM= ; DEPEND_BDB2= ; DEPEND_QUIPU= ; \
+ if [ "$(BUILD_LDBM)" != "no" ]; then \
+ DEPEND_LDBM="$(LDBMSRCS)"; \
fi; \
- if [ "$(BUILD_BDB2)" = "yes" ]; then \
- DEPEND_BDB2="$(SRCS2)"; \
- DEPEND=yes ; \
+ if [ "$(BUILD_BDB2)" != "no" ]; then \
+ DEPEND_BDB2="$(BDBMSRCS)"; \
fi; \
- if [ "$(HAVE_ISODE)" = "yes" ]; then \
- DEPEND_ISODE="$(ISODEINCLUDEFLAG) chlog2replog.c $(EDB2LDIFSRCS)"; \
- DEPEND=yes ; \
+ if [ "$(BUILD_QUIPU)" != "no" ]; then \
+ DEPEND_QUIPU="$(QUIPUINCLUDEFLAG) $(QUIPUSRCS)"; \
fi; \
- if [ "$$DEPEND" = "yes" ]; then \
- $(MKDEP) $(DEFS) $(DEFINES) $$DEPEND_ISODE \
- $$DEPEND_LDBM $$DEPEND_BDB2; \
- else \
- echo "slapd-tools: no dependencies to make"; \
- fi
+ $(MKDEP) $(DEFS) $(DEFINES) $(SRCS) $$DEPEND_QUIPU \
+ $$DEPEND_LDBM $$DEPEND_BDB2
-install-local: install-ldbm install-bdb2 install-isode FORCE
+install-local: install-ldbm-$(BUILD_LDBM) install-bdb2-$(BUILD_BDB2) \
+ install-quipu-$(HAVE_QUIPU)
-install-ldbm: FORCE
+install-ldbm-no install-bdb2-no install-quipu-no:
+
+install-ldbm-yes install-ldbm-mod: FORCE
@-$(MKDIR) $(sbindir)
- @if [ "$(BUILD_LDBM)" = "yes" ]; then \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif2ldbm $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif2index $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif2id2entry $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif2id2children $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldbmcat $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 centipede $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldbmtest $(sbindir) ; \
- else \
- exit 0 ; \
- fi
-
-install-bdb2: FORCE
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 slapcat $(sbindir) ; \
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 slapentry $(sbindir) ; \
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 slapindex $(sbindir) ; \
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif $(sbindir) ; \
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 centipede $(sbindir)
+
+install-bdb2-yes install-bdb2-mod: FORCE
@-$(MKDIR) $(sbindir)
- @if [ "$(BUILD_BDB2)" = "yes" ]; then \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif2ldbm-bdb2 $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif2index-bdb2 $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif2id2entry-bdb2 $(sbindir) ; \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldif2id2children-bdb2 $(sbindir) ; \
- else \
- exit 0 ; \
- fi
-
-install-isode: FORCE
- @-$(MKDIR) $(sbindir)
- @if [ "$(HAVE_ISODE)" = "yes" ]; then \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 edb2ldif $(sbindir); \
- $(LTINSTALL) $(INSTALLFLAGS) -m 755 chlog2replog $(sbindir); \
- else \
- exit 0 ; \
- fi
+install-quipu-yes: FORCE
+ @-$(MKDIR) $(sbindir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 edb2ldif $(sbindir); \
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 chlog2replog $(sbindir)
/* centipede.c - generate and install indexing information (view w/tabstop=4) */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <lber.h>
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h> /* get link(), unlink() */
+
#include <ldap.h>
-#include <ldapconfig.h>
#include <ldbm.h>
+int slap_debug;
+
#define DEFAULT_LDAPFILTER "(objectclass=*)"
#define CENTROID_VALUE 1
int verbose;
int not;
-static LDAP *start_ldap_search();
-static LDAP *bind_to_destination_ldap();
-static int create_tmp_files();
-static int generate_new_centroids();
-static LDAPMod **diff_centroids();
-static LDAPMod **full_centroid();
-static char **charray_add_dup();
+static LDAP *start_ldap_search(char *ldapsrcurl, char *ldapfilter, char **attrs);
+static LDAP *bind_to_destination_ldap(char *ldapsrcurl, char *ldapdesturl);
+static int create_tmp_files(char **attrs, char ***tmpfile, LDBM **ldbm);
+static int generate_new_centroids(LDAP *ld, char **attrs, LDBM *ldbm);
+static LDAPMod **diff_centroids(char *attr, LDBM oldbm, LDBM nldbm, int nentries);
+static LDAPMod **full_centroid(char *attr, LDBM ldbm, int nentries);
+static char **charray_add_dup(char ***a, int *cur, int *max, char *s);
static void usage( char *name )
{
fprintf( stderr, "\t-c size\t\tldbm cache size\n" );
}
+int
main( int argc, char **argv )
{
- char *ldapfilter, *ldapref;
+ char *ldapfilter;
char *ldapsrcurl, *ldapdesturl;
LDAP *ld;
LDAPMod **mods;
char buf[BUFSIZ];
int i, j, k, count;
char *s;
- extern int optind;
- extern char *optarg;
ldapsrcurl = NULL;
ldapdesturl = NULL;
- ldaphost = LDAPHOST;
- ldapbase = DEFAULT_BASE;
+ ldaphost = NULL;
+ ldapbase = NULL;
srcldapauthmethod = LDAP_AUTH_SIMPLE;
destldapauthmethod = LDAP_AUTH_SIMPLE;
srcldapbinddn = NULL;
srcldapauthmethod = LDAP_AUTH_KRBV4;
} else {
fprintf( stderr, "%s: unknown auth method\n", optarg );
- fprintf( stderr, "expecting \"simple\" or \"kerberos\"\n",
- optarg );
- exit( 1 );
+ fputs( "expecting \"simple\" or \"kerberos\"\n", stderr );
+ exit( EXIT_FAILURE );
}
break;
destldapauthmethod = LDAP_AUTH_KRBV4;
} else {
fprintf( stderr, "%s: unknown auth method\n", optarg );
- fprintf( stderr, "expecting \"simple\" or \"kerberos\"\n",
- optarg );
- exit( 1 );
+ fputs( "expecting \"simple\" or \"kerberos\"\n", stderr );
+ exit( EXIT_FAILURE );
}
break;
default:
usage( argv[0] );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
}
if ( optind == argc || ldapsrcurl == NULL || ldapdesturl == NULL ) {
usage( argv[0] );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
attrs = &argv[optind];
if ( (ld = start_ldap_search( ldapsrcurl, ldapfilter, attrs )) == NULL ) {
fprintf( stderr, "could not initiate ldap search\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( create_tmp_files( attrs, &tmpfile, &ldbm ) != 0 ) {
fprintf( stderr, "could not create temp files\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/*
if ( (count = generate_new_centroids( ld, attrs, ldbm )) < 1 ) {
if ( count == 0 ) {
fprintf( stderr, "no entries matched\n" );
- exit( 0 );
+ exit( EXIT_SUCCESS );
} else {
fprintf( stderr, "could not generate new centroid\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
}
if ( (ld = bind_to_destination_ldap( ldapsrcurl, ldapdesturl )) == NULL ) {
fprintf( stderr,
"could not bind to index server, or could not create index entry\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
for ( i = 0; ldbm[i] != NULL; i++ ) {
free( ldbm );
free( tmpfile );
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
/*
char *s, *s2;
int i;
- if ( strncmp( ldapsrcurl, "ldap://", 7 ) == 0 ) {
- s = ldapsrcurl + 7;
+ if ( strncmp( ldapsrcurl, "ldap://", 7 ) != 0 ) {
+ fputs( "Not an LDAP URL", stderr ); /* Should be smarter? */
+ return( NULL );
}
+ s = ldapsrcurl + 7;
if ( (s2 = strchr( s, '/' )) == NULL ) {
ldapbase = strdup( s );
} else {
fflush( stdout );
}
- if ( (ld = ldap_open( ldaphost, LDAP_PORT )) == NULL ) {
- perror( "ldap_open" );
+ if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) {
+ perror( "ldap_init" );
return( NULL );
}
char **val;
char last;
+ ldbm_datum_init( data );
+
if ( verbose ) {
printf( "Generating new centroids for..." );
fflush( stdout );
/* for each value */
for ( j = 0; val[j] != NULL; j++ ) {
+
+ ldbm_datum_init( key );
+
/* normalize the value */
for ( s = val[j]; *s; s++ ) {
- if ( isascii( *s ) ) {
- *s = tolower( *s );
- }
+ *s = TOLOWER( (unsigned char) *s );
last = *s;
}
if ( isascii( last ) && isdigit( last ) ) {
/* generate a word-based centroid */
} else {
- for ( w = strtok( val[j], WORD_BREAKS ); w != NULL;
- w = strtok( NULL, WORD_BREAKS ) ) {
+ char *lasts;
+ for ( w = ldap_pvt_strtok( val[j], WORD_BREAKS, &lasts );
+ w != NULL;
+ w = ldap_pvt_strtok( NULL, WORD_BREAKS, &lasts ) ) {
key.dptr = w;
key.dsize = strlen( key.dptr ) + 1;
(void) ldbm_store( ldbm[i], key, data, LDBM_INSERT );
Datum olast, nlast;
Datum lastkey, key;
Datum data;
- int rc;
LDAPMod **mods;
char **avals, **dvals;
int amax, acur, dmax, dcur;
char **vals;
+ LDBMCursor *ocursorp;
+ LDBMCursor *ncursorp;
+
if ( verbose ) {
printf( "Generating mods for differential %s centroid...", attr );
fflush( stdout );
}
+ ldbm_datum_init( okey );
+ ldbm_datum_init( nkey );
+ ldbm_datum_init( olast );
+ ldbm_datum_init( nlast );
+ ldbm_datum_init( lastkey );
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
if ( (mods = (LDAPMod **) malloc( sizeof(LDAPMod *) * 4 )) == NULL ||
(mods[0] = (LDAPMod *) malloc( sizeof(LDAPMod) )) == NULL ||
(mods[1] = (LDAPMod *) malloc( sizeof(LDAPMod) )) == NULL ||
(vals[0] = (char *) malloc( 20 )) == NULL )
{
perror( "malloc" );
- exit( -1 );
+ exit( EXIT_FAILURE );
}
/* add values in mods[0] */
mods[0]->mod_op = LDAP_MOD_ADD;
olast.dptr = NULL;
nlast.dptr = NULL;
- for ( okey = ldbm_firstkey( oldbm ), nkey = ldbm_firstkey( nldbm );
+
+ for ( okey = ldbm_firstkey( oldbm, &ocursorp ),
+ nkey = ldbm_firstkey( nldbm, &ncursorp );
okey.dptr != NULL && nkey.dptr != NULL; )
{
- rc = strcmp( okey.dptr, nkey.dptr );
+ int rc = strcmp( okey.dptr, nkey.dptr );
if ( rc == 0 ) {
/* value is in both places - leave it */
}
nlast = nkey;
- okey = ldbm_nextkey( oldbm, olast );
- nkey = ldbm_nextkey( nldbm, nlast );
+ okey = ldbm_nextkey( oldbm, olast, ocursorp );
+ nkey = ldbm_nextkey( nldbm, nlast, ncursorp );
+
} else if ( rc > 0 ) {
/* new value is not in old centroid - add it */
if ( charray_add_dup( &avals, &acur, &amax, nkey.dptr ) == NULL ) {
ldbm_datum_free( nldbm, nlast );
}
nlast = nkey;
- nkey = ldbm_nextkey( nldbm, nlast );
+
+ nkey = ldbm_nextkey( nldbm, nlast, ncursorp );
+
} else {
/* old value is not in new centroid - delete it */
if ( charray_add_dup( &dvals, &dcur, &dmax, okey.dptr ) == NULL ) {
ldbm_datum_free( oldbm, olast );
}
olast = okey;
- okey = ldbm_nextkey( oldbm, olast );
+
+ okey = ldbm_nextkey( oldbm, olast, ocursorp );
}
}
return( NULL );
}
- okey = ldbm_nextkey( oldbm, olast );
+ okey = ldbm_nextkey( oldbm, olast, ocursorp );
if ( olast.dptr != NULL ) {
ldbm_datum_free( oldbm, olast );
}
return( NULL );
}
- nkey = ldbm_nextkey( nldbm, nlast );
+ nkey = ldbm_nextkey( nldbm, nlast, ncursorp );
if ( nlast.dptr != NULL ) {
ldbm_datum_free( nldbm, nlast );
}
/* generate list of values to add */
lastkey.dptr = NULL;
- for ( key = ldbm_firstkey( nldbm ); key.dptr != NULL;
- key = ldbm_nextkey( nldbm, lastkey ) ) {
+ for ( key = ldbm_firstkey( nldbm, &ncursorp ); key.dptr != NULL;
+ key = ldbm_nextkey( nldbm, lastkey, ncursorp ) )
+ {
/* see if it's in the old one */
data = ldbm_fetch( oldbm, key );
/* generate list of values to delete */
lastkey.dptr = NULL;
- for ( key = ldbm_firstkey( oldbm ); key.dptr != NULL;
- key = ldbm_nextkey( oldbm, lastkey ) ) {
+ for ( key = ldbm_firstkey( oldbm, &ocursorp ); key.dptr != NULL;
+ key = ldbm_nextkey( oldbm, lastkey, ocursorp ) )
+ {
/* see if it's in the new one */
data = ldbm_fetch( nldbm, key );
char **vals;
int vcur, vmax;
+ LDBMCursor *cursorp;
+
if ( verbose ) {
printf( "Generating mods for full %s centroid...", attr );
fflush( stdout );
}
+ ldbm_datum_init( key );
+ ldbm_datum_init( lastkey );
+
if ( (mods = (LDAPMod **) malloc( sizeof(LDAPMod *) * 3 )) == NULL ||
(mods[0] = (LDAPMod *) malloc( sizeof(LDAPMod) )) == NULL ||
(mods[1] = (LDAPMod *) malloc( sizeof(LDAPMod) )) == NULL ||
(vals[0] = (char *) malloc( 20 )) == NULL )
{
perror( "malloc" );
- exit( -1 );
+ exit( EXIT_FAILURE );
}
mods[0]->mod_op = LDAP_MOD_REPLACE;
mods[0]->mod_type = attr;
lastkey.dptr = NULL;
vals = NULL;
vcur = vmax = 0;
- for ( key = ldbm_firstkey( ldbm ); key.dptr != NULL;
- key = ldbm_nextkey( ldbm, lastkey ) ) {
+
+ for ( key = ldbm_firstkey( ldbm, &cursorp ); key.dptr != NULL;
+ key = ldbm_nextkey( ldbm, lastkey, cursorp ) )
+ {
if ( charray_add_dup( &vals, &vcur, &vmax, key.dptr ) == NULL ) {
ldap_mods_free( mods, 1 );
return( NULL );
/* first, pick out the destination ldap server info */
if ( ldapbase != NULL ) {
free( ldapbase );
+ ldapbase = NULL;
}
- if ( strncmp( ldapdesturl, "ldap://", 7 ) == 0 ) {
- s = ldapdesturl + 7;
+ if ( strncmp( ldapdesturl, "ldap://", 7 ) != 0 ) {
+ fputs( "Not an LDAP URL", stderr ); /* Should be smarter? */
+ return( NULL );
}
+ s = ldapdesturl + 7;
if ( (s2 = strchr( s, '/' )) == NULL ) {
ldapbase = strdup( s );
} else {
free( ldapbase );
ldapbase = strdup( buf );
- if ( (ld = ldap_open( ldaphost, LDAP_PORT )) == NULL ) {
- perror( "ldap_open" );
+ if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) {
+ perror( "ldap_init" );
return( NULL );
}
char *s
)
{
- int n;
-
if ( *a == NULL ) {
*a = (char **) malloc( (BUFSIZ + 1) * sizeof(char *) );
*cur = 0;
* slapd/slurpd locking conventions.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
#include <quipu/commonarg.h>
#include <quipu/attrvalue.h>
#include "ldif.h"
-static int dn2ldif();
-static void de_t61();
+static int dn2ldif(PS ps, DN dn);
+static void de_t61(char *s, int t61mark);
extern FILE *lock_fopen( char *, char *, FILE ** );
extern int lock_fclose( FILE *, FILE * );
-extern char *ch_realloc( char *, unsigned long );
+extern void *ch_realloc( void *, unsigned long );
short ldap_dn_syntax;
PS rps;
}
-#define SEPARATOR(c) (c == ',' || c == ';')
-#define SPACE(c) (c == ' ' || c == '\n')
+#define SEPARATOR(c) ((c) == ',' || (c) == ';')
+#define SPACE(c) ((c) == ' ' || (c) == '\n')
static int
dn2ldif( PS ps, DN dn )
static void
-de_t61( s, t61mark )
-char *s;
-int t61mark;
+de_t61(char *s, int t61mark)
{
char *next = s;
- int c, hex;
+ unsigned char c;
+ unsigned int hex;
while ( *s ) {
switch ( *s ) {
char *
-getattr( buf, sep )
-char *buf;
-char sep;
+getattr(char *buf, char sep)
{
char *val;
#define RBSIZE 255
char *
-getattr_ldif( buf )
-char *buf;
+getattr_ldif(char *buf)
{
return( getattr( buf, ':' ));
}
char *
-getattr_edb( buf )
-char *buf;
+getattr_edb(char *buf)
{
return( getattr( buf, '=' ));
}
char *
-getval( buf, sep )
-char *buf;
-char sep;
+getval(char *buf, char sep)
{
char *val;
}
char *
-getval_ldif( buf )
-char *buf;
+getval_ldif(char *buf)
{
return( getval( buf, ':' ));
}
char *
-getval_edb( buf )
-char *buf;
+getval_edb(char *buf)
{
return( getval( buf, '=' ));
}
int
-isDNsyntax( attr )
-char *attr;
+isDNsyntax(char *attr)
{
- oid_table_attr *p, *name2attr();
+ oid_table_attr *p, *name2attr(char *);
p = name2attr( attr );
if ( p == ( oid_table_attr * ) 0 ) {
void
-print_as( as, modtype, ofp )
-Attr_Sequence as;
-int modtype;
-FILE *ofp;
+print_as(Attr_Sequence as, int modtype, FILE *ofp)
{
Attr_Sequence p;
AV_Sequence av;
}
if ( obuf != NULL ) {
fputs( obuf, ofp );
- free( obuf );
+ ber_memfree( obuf );
}
}
if ( modtype != 0 ) {
break;
default:
usage( progname );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
}
if (( dn_suffix == NULL ) || ( nreplicas == 0 )) {
usage( progname );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( ofile == NULL ) {
if (( std_ps = ps_alloc( std_open )) == NULLPS ||
std_setup( std_ps, ofp ) != OK ) {
fprintf( stderr, "std_ps setup failed - help!\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if (( rps = ps_alloc( str_open )) == NULLPS ||
str_setup( rps, NULLCP, 0, 0 ) != OK ) {
fprintf( stderr, "rps setup failed - help!\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/* See if we've got a line continuation to deal with */
nbuflen = strlen( nbuf );
if ( state == ST_CONCAT ) {
- for ( p = nbuf; isspace( *p ); p++, nbuflen-- ); /* skip space */
+ for ( p = nbuf; isspace( (unsigned char) *p ); p++, nbuflen-- )
+ ; /* skip space */
buf = realloc( buf, buflen + nbuflen + 1 );
strcat( buf, p );
buflen += ( nbuflen );
if ( ofile != NULL ) {
if (( ofp = lock_fopen( ofile, "a", &lfp )) == NULL ) {
perror( "open" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
}
/*
sprintf( nbuf, "%s.lock", ofile );
(void) unlink( nbuf );
}
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <sys/types.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/dirent.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
#include <sys/stat.h>
#include <quipu/config.h>
static int edb2ldif( FILE *outfp, char *edbfile, char *basedn, int recurse );
static int convert_entry( FILE *fp, char *edbname, FILE *outfp,
char *basedn, char *loc_addvals, int loc_addlen, char *linebuf );
+static int add_rdn_values (Attr_Sequence entryas, RDN rdn);
static int read_edbmap( char *mapfile, struct edbmap **edbmapp );
static char *file2rdn( struct edbmap *edbmap, char *filename );
static void free_edbmap( struct edbmap *edbmap );
int ldap_syslog_level = 0;
-main( argc, argv )
- int argc;
- char **argv;
+int
+main( int argc, char **argv )
{
char *usage = "usage: %s [-d] [-o] [-r] [-v] [-b basedn] [-a addvalsfile] [-f fileattrdir] [-i ignoreattr...] [edbfile...]\n";
char edbfile[ MAXNAMLEN ], *basedn;
int c, rc, errflg, ignore_count, recurse;
- extern int optind;
- extern char *optarg;
extern char dsa_mode;
#ifdef HAVE_FILE_ATTR_DIR
extern char *file_attr_directory;
always_addvals = NULL;
basedn = NULL;
- while (( c = getopt( argc, argv, "dorva:b:f:h:i:" )) != -1 ) {
+ while (( c = getopt( argc, argv, "dorva:b:f:h:i:" )) != EOF ) {
switch( c ) {
case 'd':
#ifdef LDAP_DEBUG
} else if (( always_addvals = read_file( optarg, &always_addlen ))
== NULL ) {
print_err( optarg );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
break;
}
if ( file_attr_directory == NULL ) {
print_err( "malloc" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
#else /* HAVE_FILE_ATTR_DIR */
fprintf( stderr, "Ignoring -f: this option requires a newer version of ISODE.\n" );
}
if ( ignore_attr == NULL ) {
print_err( "malloc/realloc" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
ignore_attr[ ignore_count ] = optarg;
ignore_attr[ ++ignore_count ] = NULL;
if ( errflg ) {
fprintf( stderr, usage, progname );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( basedn == NULL ) {
if ( init_syntaxes() < 0 ) {
fprintf( stderr, "%s: init_syntaxes failed -- check your oid tables \n",
progname );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
fprintf( stderr, "edb2ldif: exit( %d )\n", ( rc < 0 ) ? 1 : 0 );
#endif
- exit( ( rc < 0 ) ? 1 : 0 );
+ exit( ( rc < 0 ) ? EXIT_FAILURE : EXIT_SUCCESS );
}
static int
-edb2ldif( outfp, edbfile, basedn, recurse )
- FILE *outfp;
- char *edbfile;
- char *basedn;
- int recurse;
+edb2ldif( FILE *outfp, char *edbfile, char *basedn, int recurse )
{
FILE *fp;
char *addvals, *p, *rdn, line[ MAX_LINE_SIZE + 1 ];
* return > 0 if entry converted, 0 if end of file, < 0 if error occurs
*/
static int
-convert_entry( fp, edbname, outfp, basedn, loc_addvals, loc_addlen, linebuf )
- FILE *fp;
- char *edbname;
- FILE *outfp;
- char *basedn;
- char *loc_addvals;
- int loc_addlen;
- char *linebuf;
+convert_entry(
+ FILE *fp,
+ char *edbname,
+ FILE *outfp,
+ char *basedn,
+ char *loc_addvals,
+ int loc_addlen,
+ char *linebuf
+)
{
Attr_Sequence as, tmpas;
AV_Sequence av;
}
-int
-add_rdn_values( entryas, rdn )
- Attr_Sequence entryas;
- RDN rdn;
+static int
+add_rdn_values( Attr_Sequence entryas, RDN rdn )
{
/*
* this routine is based on code from the real_unravel_attribute() routine
/* read the EDB.map file and return a linked list of translations */
static int
-read_edbmap( mapfile, edbmapp )
- char *mapfile;
- struct edbmap **edbmapp;
+read_edbmap( char *mapfile, struct edbmap **edbmapp )
{
FILE *fp;
char *p, *filename, *rdn, line[ MAX_LINE_SIZE + 1 ];
}
*filename++ = '\0';
- while ( isspace( *filename )) { /* strip leading whitespace */
+ while ( isspace((unsigned char) *filename) ) { /* strip leading whitespace */
++filename;
}
}
p = filename + strlen( filename ) - 1;
- while ( isspace( *p )) { /* strip trailing whitespace */
+ while ( isspace((unsigned char) *p) ) { /* strip trailing whitespace */
*p-- = '\0';
}
rdn = line;
- while ( isspace( *rdn )) { /* strip leading whitespace */
+ while ( isspace((unsigned char) *rdn)) { /* strip leading whitespace */
++rdn;
}
}
p = rdn + strlen( rdn ) - 1;
- while ( isspace( *p )) { /* strip trailing whitespace */
+ while ( isspace((unsigned char) *p)) { /* strip trailing whitespace */
*p-- = '\0';
}
static char *
-file2rdn( edbmap, filename )
- struct edbmap *edbmap;
- char *filename;
+file2rdn( struct edbmap *edbmap, char *filename )
{
#ifdef LDAP_DEBUG
if ( debugflg ) {
/* free the edbmap list */
static void
-free_edbmap( edbmap )
- struct edbmap *edbmap;
+free_edbmap( struct edbmap *edbmap )
{
struct edbmap *tmp;
static void
-print_err( msg )
- char *msg;
+print_err( char *msg )
{
- extern int sys_nerr;
- extern char *sys_errlist[];
- extern int errno;
-
#ifdef LDAP_DEBUG
if ( debugflg ) {
fprintf( stderr, "print_err( \"%s\" )\n", msg );
#endif
if ( errno > sys_nerr ) {
- fprintf( stderr, "%s: %s: error %d\n", progname, msg, errno );
+ fprintf( stderr, "%s: %s: errno=%d\n", progname, msg, errno );
} else {
fprintf( stderr, "%s: %s: %s\n", progname, msg, sys_errlist[ errno ] );
}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+
#include <quipu/commonarg.h>
#include <quipu/attrvalue.h>
#include <quipu/ds_error.h>
#include <quipu/ds_search.h>
/* #include <quipu/dap2.h> */
#include <quipu/dua.h>
-#include <sys/types.h>
-#include "lber.h"
-#include "ldap.h"
+#include <ldap.h>
+
#include "ldif.h"
#include "ldapsyntax.h"
extern char *progname;
-#define SEPARATOR(c) (c == ',' || c == ';')
-#define SPACE(c) (c == ' ' || c == '\n')
+#define SEPARATOR(c) ((c) == ',' || (c) == ';')
+#define SPACE(c) ((c) == ' ' || (c) == '\n')
int
if ( fputs( buf, outfp ) == EOF ) {
rc = -1;
}
- free( buf );
+ ber_memfree( buf );
}
}
int t61mark;
{
char *next = s;
- int c, hex;
+ unsigned char c;
+ unsigned int hex;
while ( *s ) {
switch ( *s ) {
char *p;
if ( strncmp( s, "{CRYPT}", 7 ) == 0 ) {
- strcpy( s, s + 7 ); /* strip off "{CRYPT}" */
+ SAFEMEMCPY( s, s + 7, strlen( s + 7 ) + 1 ); /* strip off "{CRYPT}" */
for ( p = s; *p != '\0'; ++p) { /* "decrypt" each byte */
if ( *p != CRYPT_MASK ) {
if ( pe->pe_class == PE_CLASS_UNIV && pe->pe_form == PE_FORM_PRIM
&& pe->pe_id == PE_PRIM_BITS ) {
len = ps_get_abs( pe );
- if (( phber = der_alloc()) == NULLBER ) {
+ if (( phber = der_alloc()) == NULL ) {
return( -1 );
}
- if ( ber_printf( phber, "t{[tB]{B}}", 0xA3, 0x81, faxparamset,
- 31, (char *)pe->pe_prim, len * 8 ) == -1 ) {
+ if ( ber_printf( phber, "t{[tB]{B}}",
+ (ber_tag_t) 0xA3, (ber_tag_t) 0x81, faxparamset, (ber_len_t) 31,
+ (char *)pe->pe_prim, (ber_len_t) (len * 8) ) == -1 )
+ {
ber_free( phber, 1 );
return( -1 );
}
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "ldbm.h"
-#include "../slap.h"
-
-usage( name )
-char *name;
-{
- fprintf( stderr, "usage: %s [-n] <filename>\n", name );
- exit( 1 );
-}
-
-main( argc, argv )
- int argc;
- char **argv;
-{
- Datum key, last, data;
- LDBM dbp;
- int rc, type;
- long id;
- char *file, *s;
- int printid = 1;
-
- if ( argc < 2 || argc > 3 || ( argc == 3 && strcmp( argv[1], "-n" )
- != 0 )) {
- usage( argv[0] );
- }
- if ( argc == 3 && strcmp( argv[1], "-n" ) == 0 ) {
- printid = 0;
- file = argv[2];
- } else {
- file = argv[1];
- }
-
- if ( (dbp = ldbm_open( file, LDBM_READER, 0, 0 )) == NULL ) {
- perror( file );
- exit ( 1 );
- }
-
- last.dptr = NULL;
- for ( key = ldbm_firstkey( dbp ); key.dptr != NULL;
- key = ldbm_nextkey( dbp, last ) ) {
- if ( last.dptr != NULL )
- ldbm_datum_free( dbp, last );
- data = ldbm_fetch( dbp, key );
- s = data.dptr;
- if ( !printid && isdigit( *s )) {
- if (( s = strchr( s, '\n' )) != NULL ) {
- ++s;
- }
- }
- if ( s != NULL ) {
- puts( s );
- }
- ldbm_datum_free( dbp, data );
- last = key;
- }
- if ( last.dptr != NULL )
- ldbm_datum_free( dbp, last );
- ldbm_close( dbp );
-
- exit( 0 );
-}
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
+#include <limits.h>
+
+#include <ac/stdlib.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
-#include <sys/wait.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
#include <sys/stat.h>
-#include <limits.h>
-#include "portable.h"
-#include "ldapconfig.h"
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "ldap_defaults.h"
#include "../slap.h"
#include "../back-ldbm/back-ldbm.h"
-#define EDITOR "/usr/ucb/vi"
-
-extern IDList *idl_fetch();
-extern Backend *select_backend();
-extern struct dbcache *ldbm_cache_open();
-
-static struct dbcache *openchoice();
-static void print_entry();
-static void free_and_close();
-static void edit_entry();
-static void get_keydata();
-
-struct dbcache *dbc;
-LDBM dbp;
-char *tailorfile;
-Backend *be = NULL;
-int ldap_debug;
-int ldap_syslog;
-int ldap_syslog_level;
-int global_schemacheck;
-int num_entries_sent;
-int num_bytes_sent;
-int active_threads;
-char *default_referral;
-struct objclass *global_oc;
-time_t currenttime;
-pthread_t listener_tid;
-pthread_mutex_t num_sent_mutex;
-pthread_mutex_t entry2str_mutex;
-pthread_mutex_t active_threads_mutex;
-pthread_mutex_t new_conn_mutex;
-pthread_mutex_t currenttime_mutex;
-pthread_mutex_t replog_mutex;
-pthread_mutex_t ops_mutex;
-pthread_mutex_t regex_mutex;
-
-main( argc, argv )
- int argc;
- char **argv;
+static DBCache *openchoice(char c, int mode, int verbose, char **fname);
+static void print_entry(FILE *fp, char c, Datum *key, char *klabel, Datum *data, char *dlabel);
+static void free_and_close(DBCache *dbc, Datum key, Datum data);
+static void edit_entry(char c, Datum *data);
+static void get_keydata(FILE *fp, char c, Datum *key, Datum *data);
+
+static DBCache *dbc;
+static LDBM dbp;
+static Backend *be = NULL;
+
+int
+main( int argc, char **argv )
{
char buf[256];
Datum savekey, key, data, last;
char *fname;
- ID id;
- IDList *idl;
+ ID id, cursor;
+ ID_BLOCK *idl;
Backend *tbe;
int i;
- extern char *optarg;
+ char *tailorfile;
+
+ LDBMCursor *cursorp;
+
+ fprintf(stderr,
+ "ldbmtest not updated to support new index formats!\n" );
+ exit( EXIT_FAILURE );
+
+
+ ldbm_datum_init( savekey );
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+ ldbm_datum_init( last );
tailorfile = SLAPD_DEFAULT_CONFIGFILE;
while ( (i = getopt( argc, argv, "d:f:" )) != EOF ) {
fprintf( stderr,
"usage: %s [-d level] [-f slapdconfigfile]\n",
argv[0] );
- exit( -1 );
- break;
+ exit( EXIT_FAILURE );
}
}
* initialize stuff and figure out which backend we're dealing with
*/
- init();
- read_config( tailorfile, &be, NULL );
+ slap_init(SLAP_TOOL_MODE, "ldbmtest");
+ read_config( tailorfile );
+ slap_startup( NULL );
while ( 1 ) {
printf( "dbtest: " );
}
break;
- case 'l': /* lookup somethig in an index */
+ case 'l': /* lookup something in an index */
if ( (dbc = openchoice( buf[1], LDBM_READER, 1, NULL ))
== NULL ) {
continue;
get_keydata( stdin, buf[1], &key, NULL );
if ( (idl = idl_fetch( be, dbc, key )) != NULL ) {
data.dptr = (char *) idl;
- data.dsize = (idl->b_nmax + 1) * sizeof(ID);
+ data.dsize = (ID_BLOCK_NMAX(idl) + 1) * sizeof(ID);
print_entry( stdout, buf[1], &key, "key: ",
&data, "data:\n" );
}
}
savekey.dptr = NULL;
- for ( key = ldbm_firstkey( dbc->dbc_db );
+ for ( key = ldbm_firstkey( dbc->dbc_db, &cursorp );
key.dptr != NULL;
- key = ldbm_nextkey( dbc->dbc_db, key ) ) {
+ key = ldbm_nextkey( dbc->dbc_db, key, cursorp ) )
+ {
if ( savekey.dptr != NULL )
ldbm_datum_free( dbc->dbc_db, savekey );
savekey = key;
"key: ", NULL, NULL );
}
- ldbm_datum_free( dbc->dbc_db, data );
+ if ( data.dptr != NULL ) {
+ ldbm_datum_free( dbc->dbc_db, data );
+ }
}
if ( savekey.dptr != NULL )
ldbm_datum_free( dbc->dbc_db, savekey );
if ( ldbm_errno( dbc->dbc_db ) == 0 ) {
perror( "ldbm_delete" );
} else {
- fprintf( stderr, "db_errno %d",
+ fprintf( stderr, "db_errno=%d",
ldbm_errno( dbc->dbc_db ) );
}
}
free_and_close( dbc, key, data );
break;
+#ifndef HAVE_WINSOCK
case 'e': /* edit an entry */
if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
== NULL ) {
if ( ldbm_errno( dbc->dbc_db ) == 0 ) {
perror( "ldbm_fetch" );
} else {
- fprintf( stderr, "db_errno %d\n",
+ fprintf( stderr, "db_errno=%d\n",
ldbm_errno( dbc->dbc_db ) );
}
free_and_close( dbc, key, data );
if ( ldbm_errno( dbc->dbc_db ) == 0 ) {
perror( "ldbm_store" );
} else {
- fprintf( stderr, "db_errno %d\n",
+ fprintf( stderr, "db_errno=%d\n",
ldbm_errno( dbc->dbc_db ) );
}
}
free_and_close( dbc, key, data );
break;
+#endif
case 'a': /* add an entry */
if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
if ( ldbm_errno( dbc->dbc_db ) == 0 ) {
perror( "ldbm_store" );
} else {
- fprintf( stderr, "db_errno %d\n",
+ fprintf( stderr, "db_errno=%d\n",
ldbm_errno( dbc->dbc_db ) );
}
}
get_keydata( stdin, buf[1], &key, &data );
- idl = (IDList *) data.dptr;
- for ( id = idl_firstid( idl ); id != NOID;
- id = idl_nextid( idl, id ) ) {
+ idl = (ID_BLOCK *) data.dptr;
+ for ( id = idl_firstid( idl, &cursor ); id != NOID;
+ id = idl_nextid( idl, &cursor ) ) {
if ( idl_insert_key( be, dbc, key, id )
!= 0 ) {
fprintf( stderr,
- "idl_insert_key (%s) %d failed\n",
+ "idl_insert_key (%s) %ld failed\n",
key.dptr, id );
continue;
}
printf( "suffix: " );
fflush( stdout );
if ( fgets( buf, sizeof(buf), stdin ) == NULL ) {
- exit( 0 );
+ exit( EXIT_SUCCESS );
} else {
buf[strlen( buf ) - 1] = '\0';
}
- (void) dn_normalize( buf );
+ (void) dn_normalize_case( buf );
if ( (tbe = select_backend( buf )) == NULL ) {
fprintf( stderr, "unknown suffix \"%s\"\n",
buf );
}
last.dptr = NULL;
- for ( key = ldbm_firstkey( dbp ); key.dptr != NULL;
- key = ldbm_nextkey( dbp, last ) ) {
+
+ for ( key = ldbm_firstkey( dbp, &cursorp );
+ key.dptr != NULL;
+ key = ldbm_nextkey( dbp, last, cursorp ) )
+ {
if ( last.dptr != NULL ) {
ldbm_datum_free( dbp, last );
}
printf( " b => change default backend\n" );
printf( " B => print default backend\n" );
printf( "where <c> is a char selecting the index:\n" );
- printf( " c => id2children\n" );
printf( " d => dn2id\n" );
printf( " e => id2entry\n" );
printf( " f => arbitrary file\n" );
}
}
- return( 0 );
+ slap_shutdown( NULL );
+ slap_destroy();
+
+ return( EXIT_SUCCESS );
}
static void
-free_and_close( dbc, key, data )
- struct dbcache *dbc;
- Datum key;
- Datum data;
+free_and_close( DBCache *dbc, Datum key, Datum data )
{
ldbm_cache_really_close( be, dbc );
if ( key.dptr != NULL )
}
static int
-dnid_cmp( a, b )
- long *a;
- long *b;
+dnid_cmp( const void *a, const void *b )
{
- return( *a - *b );
+ return( *(const long int *)a - *(const long int *)b );
}
static char *
-myrealloc( p, size )
- char *p;
- int size;
+myrealloc( char *p, int size )
{
if ( p == NULL )
return( (char *) malloc( size ) );
}
static void
-get_idlist( fp, data )
- FILE *fp;
- Datum *data;
+get_idlist( FILE *fp, Datum *data )
{
char buf[20];
- int i, j, fd, tty;
- IDList *p;
- int psize, pmax;
- int nmax, nids;
+ int i, fd, tty;
+ ID_BLOCK *p;
+ unsigned int psize, pmax;
+ unsigned int nmax, nids;
fd = fileno( fp );
tty = isatty( fd );
if ( psize + sizeof(ID) > pmax ) {
pmax += BUFSIZ;
- p = (IDList *) myrealloc( (char *) p, pmax );
+ p = (ID_BLOCK *) myrealloc( (char *) p, pmax );
}
if ( strncmp( buf, "nids=0", 6 ) == 0 ) {
continue;
}
- p->b_ids[i++] = atol( buf );
+ ID_BLOCK_ID(p,i++) = atol( buf );
psize += sizeof(ID);
}
if ( nmax == 0 ) {
printf( "%d IDs entered. Max number of ids? [%d] ", i,
i );
if ( fgets( buf, sizeof(buf), fp ) != NULL &&
- isdigit( buf[0] ) ) {
+ isdigit( (unsigned char) buf[0] ) ) {
nmax = atol( buf );
}
} else {
}
}
if ( i > 0 ) {
- p->b_nmax = nmax;
+ ID_BLOCK_NMAX(p) = nmax;
if ( nids != 0 ) {
- p->b_nids = 0;
- p->b_ids[i] = NOID;
+ ID_BLOCK_NIDS(p) = 0;
+ ID_BLOCK_ID(p,i) = NOID;
} else {
- p->b_nids = i;
+ ID_BLOCK_NIDS(p) = i;
}
- qsort( (void *) p->b_ids, i, sizeof(ID), (void *) dnid_cmp );
+ qsort( (void *) &ID_BLOCK_ID(p, 0), i, sizeof(ID), dnid_cmp );
}
data->dptr = (char *) p;
- data->dsize = (nmax + 2) * sizeof(ID);
+ data->dsize = (nmax + ID_BLOCK_IDS_OFFSET) * sizeof(ID);
}
static void
-get_entry( fp, data )
- FILE *fp;
- Datum *data;
+get_entry( FILE *fp, Datum *data )
{
char buf[BUFSIZ];
char *p;
- int pmax, psize, len;
+ unsigned int pmax, psize, len;
int fd;
fd = fileno( fp );
data->dsize = psize + 1;
}
+#ifndef HAVE_WINSOCK
static void
-edit_entry( c, data )
- char c;
- Datum *data;
+edit_entry( char c, Datum *data )
{
int fd, pid;
char tmpname[20];
FILE *fp;
+#ifndef HAVE_WAITPID
WAITSTATUSTYPE status;
+#endif
strcpy( tmpname, "/tmp/dbtestXXXXXX" );
-#ifdef ultrix
+#ifndef HAVE_MKSTEMP
if ( (fd = open( mktemp( tmpname ), O_RDWR, 0600 )) == -1 ) {
perror( tmpname );
return;
char *editor;
if ( (editor = getenv( "EDITOR" )) == NULL ) {
- editor = EDITOR;
+ editor = LDAP_EDITOR;
}
execl( editor, editor, tmpname, NULL );
perror( "execl" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
fclose( fp );
-#ifdef USE_WAITPID
- if ( waitpid( (pid_t) -1, 0, WAIT_FLAGS ) < 0 ) {
+#ifdef HAVE_WAITPID
+ if ( waitpid( (pid_t) -1, NULL, WAIT_FLAGS ) < 0 )
#else
- if ( wait3( &status, WAIT_FLAGS, 0 ) < 0 ) {
+ if ( wait3( (pid_t) -1, &status, WAIT_FLAGS, 0 ) < 0 )
#endif
+ {
perror( "wait" );
return;
}
perror( tmpname );
return;
}
- ldbm_datum_free( NULL, *data );
+ if ( data->dptr != NULL ) {
+ ldbm_datum_free( NULL, *data );
+ }
get_keydata( fp, c, NULL, data );
fclose( fp );
unlink( tmpname );
}
+#endif
-static struct dbcache *
-openfile( name, namesiz, mode, verbose, c )
- char *name;
- int namesiz;
- int mode;
- int verbose;
- char c;
+static DBCache *
+openfile( char *name, int namesiz, int mode, int verbose, char c )
{
- struct dbcache *dbc;
+ DBCache *dbc;
if ( name == NULL || *name == '\0' ) {
if ( c == 'f' ) {
printf( " file: " );
if ( fgets( name, namesiz, stdin ) == NULL )
- exit( 0 );
+ exit( EXIT_SUCCESS );
name[strlen( name ) - 1] = '\0';
} else {
printf( " attr: " );
if ( fgets( name, namesiz, stdin ) == NULL )
- exit( 0 );
+ exit( EXIT_SUCCESS );
name[strlen( name ) - 1] = '\0';
}
}
return( dbc );
}
-static struct dbcache *
-openchoice( c, mode, verbose, fname )
- char c;
- int mode;
- int verbose;
- char **fname;
+static DBCache *
+openchoice( char c, int mode, int verbose, char **fname )
{
static char name[MAXPATHLEN];
switch ( c ) {
- case 'c': /* id2children */
- sprintf( name, "id2children" );
- break;
case 'd': /* dn2id */
sprintf( name, "dn2id" );
break;
}
break;
default:
- printf( "specify one of [fdeci] to select file\n" );
+ printf( "specify one of [fdei] to select file\n" );
return( NULL );
break;
}
}
static void
-print_entry( fp, c, key, klabel, data, dlabel )
- FILE *fp;
- char c;
- Datum *key;
- char *klabel;
- Datum *data;
- char *dlabel;
+print_entry(
+ FILE *fp,
+ char c,
+ Datum *key,
+ char *klabel,
+ Datum *data,
+ char *dlabel
+)
{
ID id;
- IDList *idl;
- int i;
+ ID_BLOCK *idl;
+ unsigned int i;
char msg[2];
if ( data != NULL && data->dptr == NULL ) {
if ( ldbm_errno( dbp ) == 0 )
perror( msg );
else
- fprintf( stderr, "%s: db_errno %d\n", msg,
+ fprintf( stderr, "%s: db_errno=%d\n", msg,
ldbm_errno( dbp ) );
return;
}
key->dsize );
if ( data != NULL ) {
SAFEMEMCPY( (char *) &id, data->dptr, sizeof(ID) );
- fprintf( fp, "%s%d\n", dlabel ? dlabel : "", id );
+ fprintf( fp, "%s%ld\n", dlabel ? dlabel : "", id );
}
break;
case 'e': /* id2entry - key is dnid, data is entry */
if ( key != NULL ) {
SAFEMEMCPY( (char *) &id, key->dptr, sizeof(ID) );
- fprintf( fp, "%s %d\n", klabel, id );
+ fprintf( fp, "%s %ld\n", klabel, id );
}
if ( data != NULL ) {
if ( dlabel ) {
}
break;
- case 'c':
case 'i': /* index - key is string, data is dnid[] */
if ( key != NULL )
fprintf( fp, "%s%s (len %d)\n", klabel, key->dptr,
key->dsize );
if ( data != NULL ) {
- idl = (IDList *) data->dptr;
+ idl = (ID_BLOCK *) data->dptr;
if ( dlabel )
- fprintf( fp, "%s\tnmax=%d\n\tncur=%d\n", dlabel,
- idl->b_nmax, idl->b_nids );
+ fprintf( fp, "%s\tnmax=%ld\n\tncur=%ld\n", dlabel,
+ ID_BLOCK_NMAX(idl), ID_BLOCK_NIDS(idl) );
- if ( INDIRECT_BLOCK( idl ) ) {
- for ( i = 0; idl->b_ids[i] != NOID; i++ ) {
- fprintf( fp, "\t%d\n", idl->b_ids[i] );
+ if ( ID_BLOCK_INDIRECT( idl ) ) {
+ for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) {
+ fprintf( fp, "\t%ld\n", ID_BLOCK_ID(idl, i) );
}
- } else if ( ALLIDS( idl ) ) {
- fprintf( fp, "\tALLIDS (1..%d)\n",
- idl->b_nids - 1 );
+ } else if ( ID_BLOCK_ALLIDS( idl ) ) {
+ fprintf( fp, "\tALLIDS\n" );
} else {
- for ( i = 0; i < idl->b_nids; i++ ) {
- fprintf( fp, "\t%d\n", idl->b_ids[i] );
+ for ( i = 0; i < ID_BLOCK_NIDS(idl); i++ ) {
+ fprintf( fp, "\t%ld\n", ID_BLOCK_ID(idl,i) );
}
}
}
break;
default:
- fprintf( stderr, "specify [deci] to select a file\n" );
+ fprintf( stderr, "specify [dei] to select a file\n" );
break;
}
}
static void
-get_keydata( fp, c, key, data )
- FILE *fp;
- char c;
- Datum *key;
- Datum *data;
+get_keydata( FILE *fp, char c, Datum *key, Datum *data )
{
static char kbuf[BUFSIZ], dbuf[BUFSIZ];
long n;
if ( tty )
printf( " dn: " );
if ( fgets( kbuf, sizeof(kbuf), fp ) == NULL ) {
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
kbuf[strlen( kbuf ) - 1] = '\0';
key->dptr = strdup( kbuf );
if ( tty )
printf( " dnid: " );
if ( fgets( dbuf, sizeof(dbuf), fp ) == NULL ) {
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
n = atol( dbuf );
data->dptr = (char *) malloc( sizeof(n) );
if ( tty )
printf( " dnid: " );
if ( fgets( kbuf, sizeof(kbuf), fp ) == NULL ) {
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
n = atol( kbuf );
key->dptr = (char *) malloc( sizeof(n) );
}
break;
- case 'c': /* id2children - key is string dnid, data is dnid[] */
case 'i': /* index - key is string, data is dnid[] */
if ( key != NULL ) {
if ( tty )
printf( " key: " );
if ( fgets( kbuf, sizeof(kbuf), fp ) == NULL ) {
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
kbuf[strlen( kbuf ) - 1] = '\0';
key->dptr = strdup( kbuf );
break;
default:
- fprintf(stderr, "specify [deci] to select file type\n");
+ fprintf(stderr, "specify [dei] to select file type\n");
break;
}
}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="ldbmtest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=ldbmtest - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ldbmtest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ldbmtest.mak" CFG="ldbmtest - Win32 Single Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ldbmtest - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "ldbmtest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "ldbmtest - Win32 Single Debug" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "ldbmtest - Win32 Single Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ldbmtest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release"
+# PROP Intermediate_Dir "..\Release\ldbmtest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libdb.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "ldbmtest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug"
+# PROP Intermediate_Dir "..\Debug\ldbmtest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libdb.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "ldbmtest - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ldbmtest"
+# PROP BASE Intermediate_Dir "ldbmtest"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\SDebug"
+# PROP Intermediate_Dir "..\SDebug\ldbmtest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libdbs.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "ldbmtest - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ldbmtes0"
+# PROP BASE Intermediate_Dir "ldbmtes0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\SRelease"
+# PROP Intermediate_Dir "..\SRelease\ldbmtest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libdbs.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "ldbmtest - Win32 Release"
+# Name "ldbmtest - Win32 Debug"
+# Name "ldbmtest - Win32 Single Debug"
+# Name "ldbmtest - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\ldbmtest.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mimic.c
+# End Source File
+# End Target
+# End Project
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <memory.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "lber.h"
-#include "ldap.h"
-#include "ldif.h"
-int ldap_syslog;
-int ldap_syslog_level;
+#include <ac/stdlib.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+#include <ldap.h>
-usage( name )
-char *name;
+#include "ldif.h"
+
+static void
+usage( char *name )
{
fprintf( stderr, "usage: %s [-b] <attrtype>\n", name );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
-main( argc, argv )
- int argc;
- char **argv;
+int
+main( int argc, char **argv )
{
char buf[BUFSIZ];
char *type, *out;
- int binary = 0;
+ int len, binary = 0;
if (argc < 2 || argc > 3 ) {
usage( argv[0] );
if (( val = (char *) malloc( BUFSIZ )) == NULL ) {
perror( "malloc" );
- exit( 1 );
+ return EXIT_FAILURE;
}
max = BUFSIZ;
cur = 0;
if (( val = (char *) realloc( val, max )) ==
NULL ) {
perror( "realloc" );
- exit( 1 );
+ return EXIT_FAILURE;
}
}
memcpy( val + cur, buf, nread );
cur += nread;
}
- if (( out = ldif_type_and_value( type, val, cur )) == NULL ) {
- perror( "ldif_type_and_value" );
- exit( 1 );
+ if (( out = ldif_put( LDIF_PUT_BINARY, type, val, cur )) == NULL ) {
+ perror( "ldif_type_and_value" );
+ return EXIT_FAILURE;
}
fputs( out, stdout );
- free( out );
+ ber_memfree( out );
free( val );
- exit( 0 );
+ return EXIT_SUCCESS;
}
/* not binary: one value per line... */
- while ( gets( buf ) != NULL ) {
- if (( out = ldif_type_and_value( type, buf, strlen( buf ) ))
+ while ( fgets( buf, sizeof(buf), stdin ) != NULL ) {
+ if( buf[len=strlen(buf)] == '\n') buf[len] = '\0';
+
+ if (( out = ldif_put( LDIF_PUT_VALUE, type, buf, strlen( buf ) ))
== NULL ) {
perror( "ldif_type_and_value" );
- exit( 1 );
+ return EXIT_FAILURE;
}
fputs( out, stdout );
- free( out );
+ ber_memfree( out );
}
- exit( 0 );
+ return EXIT_SUCCESS;
}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="ldif" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=ldif - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ldif.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ldif.mak" CFG="ldif - Win32 Single Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ldif - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "ldif - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "ldif - Win32 Single Debug" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "ldif - Win32 Single Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ldif - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release"
+# PROP Intermediate_Dir "..\Release\ldif"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
+
+!ELSEIF "$(CFG)" == "ldif - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ldif___W"
+# PROP BASE Intermediate_Dir "ldif___W"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug"
+# PROP Intermediate_Dir "..\Debug\ldif"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libraries\Debug"
+
+!ELSEIF "$(CFG)" == "ldif - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ldif___W"
+# PROP BASE Intermediate_Dir "ldif___W"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\SDebug"
+# PROP Intermediate_Dir "..\SDebug\ldif"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 oldif32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libraries\Debug"
+# ADD LINK32 hs_regex.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libraries\Debug"
+
+!ELSEIF "$(CFG)" == "ldif - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ldif___0"
+# PROP BASE Intermediate_Dir "ldif___0"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\SRelease"
+# PROP Intermediate_Dir "..\SRelease\ldif"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 oldif32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
+# ADD LINK32 hs_regex.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
+
+!ENDIF
+
+# Begin Target
+
+# Name "ldif - Win32 Release"
+# Name "ldif - Win32 Debug"
+# Name "ldif - Win32 Single Debug"
+# Name "ldif - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\ldif.c
+# End Source File
+# End Target
+# End Project
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "../slap.h"
-#include "../back-ldbm/back-ldbm.h"
-
-#define DEFAULT_CONFIGFILE "/usr/local/etc/slapd.conf"
-#define MAXARGS 100
-
-extern struct dbcache *ldbm_cache_open();
-extern void attr_index_config();
-extern char *str_getline();
-extern char *dn_parent();
-extern char *dn_normalize_case();
-extern int strcasecmp();
-extern int nbackends;
-extern Backend *backends;
-extern int ldap_debug;
-
-int lineno;
-int ldap_debug;
-int ldap_syslog;
-int ldap_syslog_level;
-int global_schemacheck;
-int num_entries_sent;
-int num_bytes_sent;
-int active_threads;
-char *default_referral;
-struct objclass *global_oc;
-time_t currenttime;
-pthread_t listener_tid;
-pthread_mutex_t num_sent_mutex;
-pthread_mutex_t entry2str_mutex;
-pthread_mutex_t active_threads_mutex;
-pthread_mutex_t new_conn_mutex;
-pthread_mutex_t currenttime_mutex;
-pthread_mutex_t replog_mutex;
-pthread_mutex_t ops_mutex;
-pthread_mutex_t regex_mutex;
-
-static int make_index();
-
-static char *tailorfile;
-static char *inputfile;
-
-static void
-usage( char *name )
-{
- fprintf( stderr, "usage: %s -i inputfile [-d debuglevel] [-f configfile] [-n databasenumber]\n", name );
- exit( 1 );
-}
-
-main( int argc, char **argv )
-{
- int i, cargc, indb, stop, status;
- char *cargv[MAXARGS];
- char *defargv[MAXARGS];
- char *linep, *buf;
- char line[BUFSIZ];
- int lineno, elineno;
- int lmax, lcur;
- int dbnum;
- ID id;
- struct dbcache *db, *db2;
- Backend *be;
- struct berval bv;
- struct berval *vals[2];
- Avlnode *avltypes = NULL;
- extern char *optarg;
-
- tailorfile = DEFAULT_CONFIGFILE;
- dbnum = -1;
- while ( (i = getopt( argc, argv, "d:f:i:n:" )) != EOF ) {
- switch ( i ) {
- case 'd': /* turn on debugging */
- ldap_debug = atoi( optarg );
- break;
-
- case 'f': /* specify a tailor file */
- tailorfile = strdup( optarg );
- break;
-
- case 'i': /* input file */
- inputfile = strdup( optarg );
- break;
-
- case 'n': /* which config file db to index */
- dbnum = atoi( optarg ) - 1;
- break;
-
- default:
- usage( argv[0] );
- break;
- }
- }
- if ( inputfile == NULL ) {
- usage( argv[0] );
- } else {
- if ( freopen( inputfile, "r", stdin ) == NULL ) {
- perror( inputfile );
- exit( 1 );
- }
- }
-
- /*
- * initialize stuff and figure out which backend we're dealing with
- */
-
- init();
- read_config( tailorfile, &be, NULL );
-
- if ( dbnum == -1 ) {
- for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
- if ( strcasecmp( backends[dbnum].be_type, "ldbm" )
- == 0 ) {
- break;
- }
- }
- if ( dbnum == nbackends ) {
- fprintf( stderr, "No ldbm database found in config file\n" );
- exit( 1 );
- }
- } else if ( dbnum < 1 || dbnum > nbackends ) {
- fprintf( stderr, "Database number selected via -n is out of range\n" );
- fprintf( stderr, "Must be in the range 1 to %d (number of databases in the config file)\n", nbackends );
- exit( 1 );
- } else if ( strcasecmp( backends[dbnum].be_type, "ldbm" ) != 0 ) {
- fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
- exit( 1 );
- }
- be = &backends[dbnum];
-
- /*
- * first, make the dn2id index
- */
-
- if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_NEWDB ))
- == NULL ) {
- perror( "dn2id file" );
- exit( 1 );
- }
-
- id = 0;
- stop = 0;
- lineno = 0;
- buf = NULL;
- lcur = lmax = 0;
- vals[0] = &bv;
- vals[1] = NULL;
- while ( ! stop ) {
- char *type, *val, *s;
- int vlen;
- Datum key, data;
-
- if ( fgets( line, sizeof(line), stdin ) != NULL ) {
- int len;
-
- lineno++;
- len = strlen( line );
- while ( lcur + len + 1 > lmax ) {
- lmax += BUFSIZ;
- buf = (char *) ch_realloc( buf, lmax );
- }
- strcpy( buf + lcur, line );
- lcur += len;
- } else {
- stop = 1;
- }
- if ( line[0] == '\n' || stop && buf && *buf ) {
- if ( *buf != '\n' ) {
- id++;
- s = buf;
- elineno = 0;
- while ( (linep = str_getline( &s )) != NULL ) {
- elineno++;
- if ( str_parse_line( linep, &type, &val,
- &vlen ) != 0 ) {
- Debug( LDAP_DEBUG_PARSE,
- "bad line %d in entry ending at line %d ignored\n",
- elineno, lineno, 0 );
- continue;
- }
-
- if ( strcmp( type, "dn" ) == 0 )
- break;
- }
-
- if ( linep == NULL ) {
- fprintf( stderr, "entry %d has no dn\n",
- id );
- } else {
- key.dptr = dn_normalize_case( val );
- key.dsize = strlen( val ) + 1;
- data.dptr = (char *) &id;
- data.dsize = sizeof(ID);
- if ( ldbm_store( db->dbc_db, key, data,
- LDBM_REPLACE ) != 0 ) {
- perror( "dn2id ldbm_store" );
- exit( 1 );
- }
- }
- }
- *buf = '\0';
- lcur = 0;
- line[0] = '\0';
- }
- }
-
- /*
- * next, make the id2children index
- */
-
- if ( (db2 = ldbm_cache_open( be, "id2children", LDBM_SUFFIX,
- LDBM_NEWDB )) == NULL ) {
- perror( "id2children file" );
- exit( 1 );
- }
-
- rewind( stdin );
- id = 0;
- stop = 0;
- buf = NULL;
- lineno = 0;
- lcur = lmax = 0;
- vals[0] = &bv;
- vals[1] = NULL;
- while ( ! stop ) {
- char *type, *val, *s, *dn;
- int vlen;
- ID pid;
- char buf2[20];
- Datum key, data;
-
- if ( fgets( line, sizeof(line), stdin ) != NULL ) {
- int len;
-
- len = strlen( line );
- while ( lcur + len + 1 > lmax ) {
- lmax += BUFSIZ;
- buf = (char *) ch_realloc( buf, lmax );
- }
- strcpy( buf + lcur, line );
- lcur += len;
- } else {
- stop = 1;
- }
- if ( line[0] == '\n' || stop && buf && *buf ) {
- if ( * buf != '\n' ) {
- id++;
- s = buf;
- while ( (linep = str_getline( &s )) != NULL ) {
- if ( str_parse_line( linep, &type, &val,
- &vlen ) != 0 ) {
- Debug( LDAP_DEBUG_PARSE,
- "bad line %d ignored\n",
- lineno, 0, 0 );
- continue;
- }
-
- if ( strcmp( type, "dn" ) == 0 )
- break;
- }
-
- if ( linep == NULL ) {
- fprintf( stderr, "entry %d has no dn\n",
- id );
- } else {
- if ( (dn = dn_parent( be, val ))
- == NULL ) {
- pid = 0;
- } else {
- key.dptr =
- dn_normalize_case( dn );
- key.dsize = strlen( dn ) + 1;
-
- data = ldbm_fetch( db->dbc_db,
- key );
- if ( data.dptr == NULL ) {
- dn_normalize( val );
- if ( ! be_issuffix( be,
- val ) ) {
- Debug( LDAP_DEBUG_PARSE, "no parent \"%s\" of \"%s\"\n", dn, val, 0 );
- }
- *buf = '\0';
- lcur = 0;
- line[0] = '\0';
- continue;
- }
- (void) memcpy( (char *) &pid,
- data.dptr, sizeof(ID) );
- }
-
- sprintf( buf2, "%c%d", EQ_PREFIX, pid );
- key.dptr = buf2;
- key.dsize = strlen( buf2 ) + 1;
- if ( idl_insert_key( be, db2, key, id )
- != 0 ) {
- perror( "idl_insert_key" );
- exit( 1 );
- }
- }
- }
- *buf = '\0';
- lcur = 0;
- line[0] = '\0';
- }
- }
- (*be->be_close)( be );
-
- exit( 0 );
-}
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "../slap.h"
-#include "../back-ldbm/back-ldbm.h"
-
-#define DEFAULT_CONFIGFILE "/usr/local/etc/slapd.conf"
-#define MAXARGS 100
-
-extern struct dbcache *ldbm_cache_open();
-extern void attr_index_config();
-extern int strcasecmp();
-extern int nbackends;
-extern Backend *backends;
-extern int ldap_debug;
-
-int ldap_debug;
-int ldap_syslog;
-int ldap_syslog_level;
-int global_schemacheck;
-int num_entries_sent;
-int num_bytes_sent;
-int active_threads;
-char *default_referral;
-struct objclass *global_oc;
-time_t currenttime;
-pthread_t listener_tid;
-pthread_mutex_t num_sent_mutex;
-pthread_mutex_t entry2str_mutex;
-pthread_mutex_t active_threads_mutex;
-pthread_mutex_t new_conn_mutex;
-pthread_mutex_t currenttime_mutex;
-pthread_mutex_t replog_mutex;
-pthread_mutex_t ops_mutex;
-pthread_mutex_t regex_mutex;
-
-static int make_index();
-
-static char *tailorfile;
-static char *inputfile;
-
-static void
-usage( char *name )
-{
- fprintf( stderr, "usage: %s -i inputfile [-d debuglevel] [-f configfile] [-n databasenumber]\n", name );
- exit( 1 );
-}
-
-main( int argc, char **argv )
-{
- int i, cargc, indb, stop, status;
- char *cargv[MAXARGS];
- char *defargv[MAXARGS];
- char *linep, *buf;
- char line[BUFSIZ], idbuf[BUFSIZ];
- int lmax, lcur;
- int dbnum;
- ID id;
- struct dbcache *db;
- Backend *be;
- struct berval bv;
- struct berval *vals[2];
- Avlnode *avltypes = NULL;
- FILE *fp;
- extern char *optarg;
-
- tailorfile = DEFAULT_CONFIGFILE;
- dbnum = -1;
- while ( (i = getopt( argc, argv, "d:f:i:n:" )) != EOF ) {
- switch ( i ) {
- case 'd': /* turn on debugging */
- ldap_debug = atoi( optarg );
- break;
-
- case 'f': /* specify a tailor file */
- tailorfile = strdup( optarg );
- break;
-
- case 'i': /* input file */
- inputfile = strdup( optarg );
- break;
-
- case 'n': /* which config file db to index */
- dbnum = atoi( optarg ) - 1;
- break;
-
- default:
- usage( argv[0] );
- break;
- }
- }
- if ( inputfile == NULL ) {
- usage( argv[0] );
- } else {
- if ( freopen( inputfile, "r", stdin ) == NULL ) {
- perror( inputfile );
- exit( 1 );
- }
- }
-
- /*
- * initialize stuff and figure out which backend we're dealing with
- */
-
- init();
- read_config( tailorfile, &be, NULL );
-
- if ( dbnum == -1 ) {
- for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
- if ( strcasecmp( backends[dbnum].be_type, "ldbm" )
- == 0 ) {
- break;
- }
- }
- if ( dbnum == nbackends ) {
- fprintf( stderr, "No ldbm database found in config file\n" );
- exit( 1 );
- }
- } else if ( dbnum < 1 || dbnum > nbackends ) {
- fprintf( stderr, "Database number selected via -n is out of range\n" );
- fprintf( stderr, "Must be in the range 1 to %d (number of databases in the config file)\n", nbackends );
- exit( 1 );
- } else if ( strcasecmp( backends[dbnum].be_type, "ldbm" ) != 0 ) {
- fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
- exit( 1 );
- }
- be = &backends[dbnum];
-
- if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_NEWDB ))
- == NULL ) {
- perror( "id2entry file" );
- exit( 1 );
- }
-
- id = 0;
- stop = 0;
- buf = NULL;
- lcur = lmax = 0;
- vals[0] = &bv;
- vals[1] = NULL;
- while ( ! stop ) {
- char *type, *val, *s;
- int vlen;
- Datum key, data;
-
- if ( fgets( line, sizeof(line), stdin ) != NULL ) {
- int len, idlen;
-
- len = strlen( line );
- if ( buf == NULL || *buf == '\0' ) {
- sprintf( idbuf, "%d\n", id + 1 );
- idlen = strlen( idbuf );
- } else {
- idlen = 0;
- }
-
- while ( lcur + len + idlen + 1 > lmax ) {
- lmax += BUFSIZ;
- buf = (char *) ch_realloc( buf, lmax );
- }
-
- if ( idlen > 0 ) {
- strcpy( buf + lcur, idbuf );
- lcur += idlen;
- }
- strcpy( buf + lcur, line );
- lcur += len;
- } else {
- stop = 1;
- }
- if ( line[0] == '\n' || stop && buf && *buf ) {
- if ( *buf != '\n' ) {
- id++;
- key.dptr = (char *) &id;
- key.dsize = sizeof(ID);
- data.dptr = buf;
- data.dsize = strlen( buf ) + 1;
- if ( ldbm_store( db->dbc_db, key, data,
- LDBM_INSERT ) != 0 ) {
- perror( "id2entry ldbm_store" );
- exit( 1 );
- }
- }
- *buf = '\0';
- lcur = 0;
- line[0] = '\0';
- }
- }
- (*be->be_close)( be );
-
- id++;
- sprintf( line, "%s/NEXTID",
- ((struct ldbminfo *) be->be_private)->li_directory );
- if ( (fp = fopen( line, "w" )) == NULL ) {
- perror( line );
- fprintf( stderr, "Could not write next id %ld\n", id );
- } else {
- fprintf( fp, "%ld\n", id );
- fclose( fp );
- }
-
- exit( 0 );
-}
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "../slap.h"
-
-#define DEFAULT_CONFIGFILE "/usr/local/etc/slapd.conf"
-#define MAXARGS 100
-
-extern void attr_index_config();
-extern char *str_getline();
-extern char *attr_normalize();
-extern int nbackends;
-extern Backend *backends;
-extern int ldap_debug;
-
-int ldap_debug;
-int ldap_syslog;
-int ldap_syslog_level;
-int global_schemacheck;
-int num_entries_sent;
-int num_bytes_sent;
-int active_threads;
-char *default_referral;
-struct objclass *global_oc;
-time_t currenttime;
-pthread_t listener_tid;
-pthread_mutex_t num_sent_mutex;
-pthread_mutex_t entry2str_mutex;
-pthread_mutex_t active_threads_mutex;
-pthread_mutex_t new_conn_mutex;
-pthread_mutex_t currenttime_mutex;
-pthread_mutex_t replog_mutex;
-pthread_mutex_t ops_mutex;
-pthread_mutex_t regex_mutex;
-
-static void
-usage( char *name )
-{
- fprintf( stderr, "usage: %s -i inputfile [-d debuglevel] [-f configfile] [-n databasenumber] attr\n", name );
- exit( 1 );
-}
-
-main( int argc, char **argv )
-{
- int i, cargc, indb, stop;
- char *cargv[MAXARGS];
- char *defargv[MAXARGS];
- char *tailorfile, *inputfile;
- char *linep, *buf, *attr;
- char line[BUFSIZ];
- int lineno, elineno;
- int lmax, lcur, indexmask, syntaxmask;
- int dbnum;
- unsigned long id;
- Backend *be;
- struct berval bv;
- struct berval *vals[2];
- extern char *optarg;
-
- inputfile = NULL;
- tailorfile = DEFAULT_CONFIGFILE;
- dbnum = -1;
- while ( (i = getopt( argc, argv, "d:f:i:n:" )) != EOF ) {
- switch ( i ) {
- case 'd': /* turn on debugging */
- ldap_debug = atoi( optarg );
- break;
-
- case 'f': /* specify a tailor file */
- tailorfile = strdup( optarg );
- break;
-
- case 'i': /* input file */
- inputfile = strdup( optarg );
- break;
-
- case 'n': /* which config file db to index */
- dbnum = atoi( optarg ) - 1;
- break;
-
- default:
- usage( argv[0] );
- break;
- }
- }
- attr = attr_normalize( argv[argc - 1] );
- if ( inputfile == NULL ) {
- usage( argv[0] );
- } else {
- if ( freopen( inputfile, "r", stdin ) == NULL ) {
- perror( inputfile );
- exit( 1 );
- }
- }
-
- init();
- read_config( tailorfile, &be, NULL );
-
- if ( dbnum == -1 ) {
- for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
- if ( strcasecmp( backends[dbnum].be_type, "ldbm" )
- == 0 ) {
- break;
- }
- }
- if ( dbnum == nbackends ) {
- fprintf( stderr, "No ldbm database found in config file\n" );
- exit( 1 );
- }
- } else if ( dbnum < 1 || dbnum > nbackends ) {
- fprintf( stderr, "Database number selected via -n is out of range\n" );
- fprintf( stderr, "Must be in the range 1 to %d (number of databases in the config file)\n", nbackends );
- exit( 1 );
- } else if ( strcasecmp( backends[dbnum].be_type, "ldbm" ) != 0 ) {
- fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
- exit( 1 );
- }
- be = &backends[dbnum];
-
- attr_masks( be->be_private, attr, &indexmask, &syntaxmask );
- if ( indexmask == 0 ) {
- exit( 0 );
- }
-
- id = 0;
- stop = 0;
- lineno = 0;
- buf = NULL;
- lcur = lmax = 0;
- vals[0] = &bv;
- vals[1] = NULL;
- while ( ! stop ) {
- char *type, *val, *s;
- int vlen;
-
- if ( fgets( line, sizeof(line), stdin ) != NULL ) {
- int len;
-
- lineno++;
- len = strlen( line );
- while ( lcur + len + 1 > lmax ) {
- lmax += BUFSIZ;
- buf = (char *) ch_realloc( buf, lmax );
- }
- strcpy( buf + lcur, line );
- lcur += len;
- } else {
- stop = 1;
- }
- if ( line[0] == '\n' || stop && buf && *buf ) {
- if ( *buf != '\n' ) {
- id++;
- s = buf;
- elineno = 0;
- while ( (linep = str_getline( &s )) != NULL ) {
- elineno++;
- if ( str_parse_line( linep, &type, &val,
- &vlen ) != 0 ) {
- Debug( LDAP_DEBUG_PARSE,
- "bad line %d in entry ending at line %d ignored\n",
- elineno, elineno, 0 );
- continue;
- }
-
- if ( strcasecmp( type, attr ) == 0 ) {
- bv.bv_val = val;
- bv.bv_len = vlen;
- index_add_values( be, attr,
- vals, id );
- }
- }
- }
- *buf = '\0';
- lcur = 0;
- }
- }
- (*be->be_close)( be );
-
- exit( 0 );
-}
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/param.h>
-#include "../slap.h"
-#include "../back-ldbm/back-ldbm.h"
-
-#define DEFAULT_CONFIGFILE "%ETCDIR%/slapd.conf"
-#define DEFAULT_ETCDIR "%ETCDIR%"
-#define INDEXCMD "ldif2index"
-#define ID2ENTRYCMD "ldif2id2entry"
-#define ID2CHILDRENCMD "ldif2id2children"
-#define MAXARGS 100
-
-extern void attr_index_config();
-extern char *str_getline();
-extern int strcasecmp();
-extern int nbackends;
-extern Backend *backends;
-extern int ldap_debug;
-
-int ldap_debug;
-int ldap_syslog;
-int ldap_syslog_level;
-int global_schemacheck;
-int num_entries_sent;
-int num_bytes_sent;
-int active_threads;
-char *default_referral;
-struct objclass *global_oc;
-time_t currenttime;
-pthread_t listener_tid;
-pthread_mutex_t num_sent_mutex;
-pthread_mutex_t entry2str_mutex;
-pthread_mutex_t active_threads_mutex;
-pthread_mutex_t new_conn_mutex;
-pthread_mutex_t currenttime_mutex;
-pthread_mutex_t replog_mutex;
-pthread_mutex_t ops_mutex;
-pthread_mutex_t regex_mutex;
-
-static void fork_child();
-static void wait4kids();
-
-static char *indexcmd;
-static char *tailorfile;
-static char *inputfile;
-static int maxkids = 1;
-static int nkids;
-
-static void
-usage( char *name )
-{
- fprintf( stderr, "usage: %s -i inputfile [-d debuglevel] [-f configfile] [-j #jobs] [-n databasenumber] [-e etcdir]\n", name );
- exit( 1 );
-}
-
-main( int argc, char **argv )
-{
- int i, stop, status;
- char *linep, *buf, *etcdir;
- char *args[10];
- char buf2[20], buf3[20];
- char line[BUFSIZ];
- char cmd[MAXPATHLEN];
- int lineno, elineno;
- int lmax, lcur;
- int dbnum;
- ID id;
- Backend *be = NULL;
- struct berval bv;
- struct berval *vals[2];
- Avlnode *avltypes = NULL;
- extern char *optarg;
-
- etcdir = DEFAULT_ETCDIR;
- tailorfile = DEFAULT_CONFIGFILE;
- dbnum = -1;
- while ( (i = getopt( argc, argv, "d:e:f:i:j:n:" )) != EOF ) {
- switch ( i ) {
- case 'd': /* turn on debugging */
- ldap_debug = atoi( optarg );
- break;
-
- case 'e': /* alternate etcdir (index cmd location) */
- etcdir = strdup( optarg );
- break;
-
- case 'f': /* specify a tailor file */
- tailorfile = strdup( optarg );
- break;
-
- case 'i': /* input file */
- inputfile = strdup( optarg );
- break;
-
- case 'j': /* number of parallel index procs */
- maxkids = atoi( optarg );
- break;
-
- case 'n': /* which config file db to index */
- dbnum = atoi( optarg ) - 1;
- break;
-
- default:
- usage( argv[0] );
- break;
- }
- }
- if ( inputfile == NULL ) {
- usage( argv[0] );
- } else {
- if ( freopen( inputfile, "r", stdin ) == NULL ) {
- perror( inputfile );
- exit( 1 );
- }
- }
-
- /*
- * initialize stuff and figure out which backend we're dealing with
- */
-
- init();
- read_config( tailorfile, &be, NULL );
-
- if ( dbnum == -1 ) {
- for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
- if ( strcasecmp( backends[dbnum].be_type, "ldbm" )
- == 0 ) {
- break;
- }
- }
- if ( dbnum == nbackends ) {
- fprintf( stderr, "No ldbm database found in config file\n" );
- exit( 1 );
- }
- } else if ( dbnum < 0 || dbnum > nbackends ) {
- fprintf( stderr, "Database number selected via -n is out of range\n" );
- fprintf( stderr, "Must be in the range 1 to %d (number of databases in the config file)\n", nbackends );
- exit( 1 );
- } else if ( strcasecmp( backends[dbnum].be_type, "ldbm" ) != 0 ) {
- fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
- exit( 1 );
- }
- be = &backends[dbnum];
-
- /*
- * generate the id2entry index
- */
-
- i = 0;
- sprintf( cmd, "%s/%s", etcdir, ID2ENTRYCMD );
- args[i++] = cmd;
- args[i++] = "-i";
- args[i++] = inputfile;
- args[i++] = "-f";
- args[i++] = tailorfile;
- args[i++] = "-n";
- sprintf( buf2, "%d", dbnum );
- args[i++] = buf2;
- if ( ldap_debug ) {
- sprintf( buf3, "%d", ldap_debug );
- args[i++] = "-d";
- args[i++] = buf3;
- }
- args[i++] = NULL;
- fork_child( cmd, args );
-
- /*
- * generate the dn2id and id2children indexes
- */
-
- i = 0;
- sprintf( cmd, "%s/%s", etcdir, ID2CHILDRENCMD );
- args[i++] = cmd;
- args[i++] = "-i";
- args[i++] = inputfile;
- args[i++] = "-f";
- args[i++] = tailorfile;
- args[i++] = "-n";
- sprintf( buf2, "%d", dbnum );
- args[i++] = buf2;
- if ( ldap_debug ) {
- sprintf( buf3, "%d", ldap_debug );
- args[i++] = "-d";
- args[i++] = buf3;
- }
- args[i++] = NULL;
- fork_child( cmd, args );
-
- /*
- * generate the attribute indexes
- */
-
- i = 0;
- sprintf( cmd, "%s/%s", etcdir, INDEXCMD );
- args[i++] = cmd;
- args[i++] = "-i";
- args[i++] = inputfile;
- args[i++] = "-f";
- args[i++] = tailorfile;
- args[i++] = "-n";
- sprintf( buf2, "%d", dbnum );
- args[i++] = buf2;
- if ( ldap_debug ) {
- sprintf( buf3, "%d", ldap_debug );
- args[i++] = "-d";
- args[i++] = buf3;
- }
- args[i++] = NULL; /* will hold the attribute name */
- args[i++] = NULL;
-
- id = 0;
- stop = 0;
- buf = NULL;
- lineno = 0;
- lcur = lmax = 0;
- vals[0] = &bv;
- vals[1] = NULL;
- while ( ! stop ) {
- char *type, *val, *s;
- int vlen, indexmask, syntaxmask;
- Datum key, data;
-
- if ( fgets( line, sizeof(line), stdin ) != NULL ) {
- int len;
-
- lineno++;
- len = strlen( line );
- while ( lcur + len + 1 > lmax ) {
- lmax += BUFSIZ;
- buf = (char *) ch_realloc( buf, lmax );
- }
- strcpy( buf + lcur, line );
- lcur += len;
- } else {
- stop = 1;
- }
- if ( line[0] == '\n' || stop && buf && *buf ) {
- id++;
- s = buf;
- elineno = 0;
- while ( (linep = str_getline( &s )) != NULL ) {
- elineno++;
- if ( str_parse_line( linep, &type, &val, &vlen )
- != 0 ) {
- Debug( LDAP_DEBUG_PARSE,
- "bad line %d in entry ending at line %d ignored\n",
- elineno, lineno, 0 );
- continue;
- }
-
- if ( !isascii( *type ) || isdigit( *type ) )
- continue;
-
- type = strdup( type );
- if ( avl_insert( &avltypes, type, strcasecmp,
- avl_dup_error ) != 0 ) {
- free( type );
- } else {
- attr_masks( be->be_private, type,
- &indexmask, &syntaxmask );
- if ( indexmask ) {
- args[i - 2] = type;
- fork_child( cmd, args );
- }
- }
- }
- *buf = '\0';
- lcur = 0;
- }
- }
- (*be->be_close)( be );
-
- wait4kids( -1 );
-
- exit( 0 );
-}
-
-static void
-fork_child( char *prog, char *args[] )
-{
- int status, pid;
-
- wait4kids( maxkids );
-
- switch ( pid = fork() ) {
- case 0: /* child */
- execvp( prog, args );
- fprintf( stderr, "%s: ", prog );
- perror( "execv" );
- exit( -1 );
- break;
-
- case -1: /* trouble */
- fprintf( stderr, "Could not fork to run %s\n", prog );
- perror( "fork" );
- break;
-
- default: /* parent */
- nkids++;
- break;
- }
-}
-
-static void
-wait4kids( int nkidval )
-{
- int status;
- unsigned char *p;
-
- while ( nkids >= nkidval ) {
- wait( &status );
- p = (unsigned char *) &status;
- if ( p[sizeof(int) - 1] == 0177 ) {
- fprintf( stderr,
- "stopping: child stopped with signal %d\n",
- p[sizeof(int) - 2] );
- } else if ( p[sizeof(int) - 1] != 0 ) {
- fprintf( stderr,
- "stopping: child terminated with signal %d\n",
- p[sizeof(int) - 1] );
- exit( p[sizeof(int) - 1] );
- } else if ( p[sizeof(int) - 2] != 0 ) {
- fprintf( stderr,
- "stopping: child exited with status %d\n",
- p[sizeof(int) - 2] );
- exit( p[sizeof(int) - 2] );
- } else {
- nkids--;
- }
- }
-}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * Mimic unused interfaces of slapd...
+ * needed for linking.
+ */
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "../slap.h"
+
+#ifdef WIN32
+time_t starttime;
+#endif
+
+/* bogus ../results.c */
+int str2result(
+ char* s,
+ int *code,
+ char **matched,
+ char **info )
+{
+ assert(0);
+ return 0;
+}
+
+void
+send_ldap_disconnect(
+ Connection *conn,
+ Operation *op,
+ ber_int_t err,
+ char *text
+)
+{
+ assert(0);
+}
+
+void
+send_ldap_result(
+ Connection *conn,
+ Operation *op,
+ int err,
+ char *matched,
+ char *text,
+ struct berval **refs,
+ LDAPControl **ctrls
+)
+{
+ assert(0);
+}
+
+void
+send_search_result(
+ Connection *conn,
+ Operation *op,
+ int err,
+ char *matched,
+ char *text,
+ struct berval **refs,
+ LDAPControl **ctrls,
+ int nentries
+)
+{
+ assert(0);
+}
+
+int
+send_search_entry(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ char **attrs,
+ int attrsonly,
+ LDAPControl **ctrls
+)
+{
+ assert(0);
+ return -1;
+}
+
+int send_search_reference(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ struct berval **refs,
+ int scope,
+ LDAPControl **ctrls,
+ struct berval ***v2refs
+)
+{
+ assert(0);
+ return -1;
+}
+
+struct berval **get_entry_referrals(
+ Backend *be, Connection *conn, Operation *op, Entry *e )
+{
+ assert(0);
+ return NULL;
+}
+
+int sasl_init(void) {
+ return 0;
+}
+
+int sasl_destroy(void) {
+ return 0;
+}
+#include "portable.h"
+
#include <stdio.h>
-#include <ldbm.h>
-#include <lber.h>
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
#include <ldap.h>
-#include "portable.h"
+#include <ldbm.h>
#define CACHE_SIZE 1000000
#define MODE 0600
#define DB_FLAGS (LDBM_WRCREAT|LDBM_NEWDB)
#define SUBLEN 3
-extern char *first_word();
-extern char *next_word();
-extern char *word_dup();
-extern char *phonetic();
+extern char *first_word(char *);
+extern char *next_word(char *);
+extern char *word_dup(char *);
+extern char *phonetic(char *);
extern int ldap_debug;
-extern int lber_debug;
+int slap_debug;
int ldap_syslog;
int ldap_syslog_level;
-static void add();
+static void add(LDBM ldbm, char *s, int *count, int *size, int freeit);
-main( argc, argv )
- int argc;
- char **argv;
+int
+main( int argc, char **argv )
{
LDAP *ld;
LDAPMessage *res, *e;
/*
ldap_debug = 255;
- lber_debug = 255;
*/
- if ( (ld = ldap_open( "vertigo:5555", LDAP_PORT )) == NULL ) {
- perror( "ldap_open" );
- exit( 1 );
+ if ( (ld = ldap_init( "vertigo:5555", 0 )) == NULL ) {
+ perror( "ldap_init" );
+ exit( EXIT_FAILURE );
}
if ( ldap_search( ld, "cn=index", LDAP_SCOPE_ONELEVEL, "(objectclass=*)",
attrs, 0 ) == -1 ) {
ldap_perror( ld, "ldap_search" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
printf( "attr\tdn\tnentries\tvcount\tvsize\twcount\twsize\tpcount\tpsize\tscount\tssize\n" );
DB_FLAGS, MODE, CACHE_SIZE )) == NULL || (sldbm = ldbm_open(
"scount.ldbm", DB_FLAGS, MODE, CACHE_SIZE )) == NULL ) {
perror( "ldbm_open" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
vcount = 0; vsize = 0;
wcount = 0; wsize = 0;
Datum key, data;
char *w;
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
/* update value count */
vcount++;
vsize += bvals[j]->bv_len;
(void) unlink( "pcount.ldbm" );
(void) unlink( "scount.ldbm" );
- exit( 0 );
+ exit( EXIT_SUCCESS );
}
static void
{
Datum key, data;
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
key.dptr = s;
key.dsize = strlen( key.dptr ) + 1;
data.dptr = "";
(*count)++;
(*size) += strlen( key.dptr );
}
- if ( freeit )
+ if ( freeit && ( key.dptr != NULL ) )
ldbm_datum_free( ldbm, key );
}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#include "slapcommon.h"
+
+int
+main( int argc, char **argv )
+{
+ char *buf;
+ int lineno;
+ int lmax;
+ int rc = EXIT_SUCCESS;
+
+ slap_tool_init( "slapadd", SLAPADD, argc, argv );
+
+ if( !be->be_entry_open &&
+ !be->be_entry_close &&
+ !be->be_entry_put )
+ {
+ fprintf( stderr, "%s: database doesn't support necessary operations.\n",
+ progname );
+ exit( EXIT_FAILURE );
+ }
+
+ buf = NULL;
+ lmax = 0;
+
+ if( be->be_entry_open( be, 1 ) != 0 ) {
+ fprintf( stderr, "%s: could not open database.\n",
+ progname );
+ exit( EXIT_FAILURE );
+ }
+
+ while( ldif_read_record( ldiffp, &lineno, &buf, &lmax ) ) {
+ ID id;
+ Entry *e = str2entry( buf );
+
+ if( e == NULL ) {
+ fprintf( stderr, "%s: could not parse entry (line=%d)\n",
+ progname, lineno );
+ rc = EXIT_FAILURE;
+ if( continuemode ) continue;
+ break;
+ }
+
+ if( !noschemacheck ) {
+ /* make sure the DN is valid */
+ if( dn_normalize_case( e->e_ndn ) == NULL ) {
+ fprintf( stderr, "%s: bad dn=\"%s\" (line=%d)\n",
+ progname, e->e_dn, lineno );
+ rc = EXIT_FAILURE;
+ entry_free( e );
+ if( continuemode ) continue;
+ break;
+ }
+
+ /* check schema */
+ if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
+ fprintf( stderr, "%s: entry dn=\"%s\" violates schema violation (line=%d)\n",
+ progname, e->e_dn, lineno );
+ rc = EXIT_FAILURE;
+ entry_free( e );
+ if( continuemode ) continue;
+ break;
+ }
+
+ /* check backend */
+ if( select_backend( e->e_ndn ) != be ) {
+ fprintf( stderr, "%s: database not configured to hold dn=\"%s\" (line=%d)\n",
+ progname, e->e_dn, lineno );
+ rc = EXIT_FAILURE;
+ entry_free( e );
+ if( continuemode ) continue;
+ break;
+ }
+ }
+
+ id = be->be_entry_put( be, e );
+
+ if( id == NOID ) {
+ fprintf( stderr, "%s: could not add entry dn=\"%s\" (line=%d)\n",
+ progname, e->e_dn, lineno );
+ rc = EXIT_FAILURE;
+ entry_free( e );
+ if( continuemode ) continue;
+ break;
+
+ } else if ( verbose ) {
+ fprintf( stderr, "added: \"%s\" (%08lx)\n",
+ e->e_dn, (long) id );
+ }
+
+ entry_free( e );
+ }
+
+ free( buf );
+
+ be->be_entry_close( be );
+
+ if( be->be_sync ) {
+ be->be_sync( be );
+ }
+
+ slap_tool_destroy();
+ return rc;
+}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="slapadd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=slapadd - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "slapadd.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "slapadd.mak" CFG="slapadd - Win32 Single Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "slapadd - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "slapadd - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "slapadd - Win32 Single Debug" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "slapadd - Win32 Single Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "slapadd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release"
+# PROP Intermediate_Dir "..\Release\slapadd"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "slapadd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ldif2"
+# PROP BASE Intermediate_Dir "ldif2"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug"
+# PROP Intermediate_Dir "..\Debug\slapadd"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "slapadd - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ldif2"
+# PROP BASE Intermediate_Dir "ldif2"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\SDebug"
+# PROP Intermediate_Dir "..\SDebug\slapadd"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib hs_regexd.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regexd.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "slapadd - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ldif2id0"
+# PROP BASE Intermediate_Dir "ldif2id0"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\SRelease"
+# PROP Intermediate_Dir "..\SRelease\slapadd"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "slapadd - Win32 Release"
+# Name "slapadd - Win32 Debug"
+# Name "slapadd - Win32 Single Debug"
+# Name "slapadd - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\mimic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapadd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapcommon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapcommon.h
+# End Source File
+# End Target
+# End Project
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slapcommon.h"
+
+int
+main( int argc, char **argv )
+{
+ ID id;
+ int rc = EXIT_SUCCESS;
+
+ slap_tool_init( "slapcat", SLAPCAT, argc, argv );
+
+ if( !be->be_entry_open &&
+ !be->be_entry_close &&
+ !be->be_entry_first &&
+ !be->be_entry_next &&
+ !be->be_entry_get )
+ {
+ fprintf( stderr, "%s: database doesn't support necessary operations.\n",
+ progname );
+ exit( EXIT_FAILURE );
+ }
+
+ if( be->be_entry_open( be, 0 ) != 0 ) {
+ fprintf( stderr, "%s: could not open database.\n",
+ progname );
+ exit( EXIT_FAILURE );
+ }
+
+ for ( id = be->be_entry_first( be );
+ id != NOID;
+ id = be->be_entry_next( be ) )
+ {
+ char *data;
+ int len;
+ Entry* e = be->be_entry_get( be, id );
+
+ if( verbose ) {
+ printf( "# id=%08lx\n", (long) id );
+ }
+
+ if ( e == NULL ) {
+ printf("# no data for entry id=%08lx\n\n", (long) id );
+ rc = EXIT_FAILURE;
+ if( continuemode ) continue;
+ break;
+ }
+
+ data = entry2str( e, &len );
+ entry_free( e );
+
+ if ( data == NULL ) {
+ printf("# bad data for entry id=%08lx\n\n", (long) id );
+ rc = EXIT_FAILURE;
+ if( continuemode ) continue;
+ break;
+ }
+
+ fputs( data, ldiffp );
+ fputs( "\n", ldiffp );
+ }
+
+ be->be_entry_close( be );
+
+ slap_tool_destroy();
+ return rc;
+}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="slapcat" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=slapcat - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "slapcat.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "slapcat.mak" CFG="slapcat - Win32 Single Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "slapcat - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "slapcat - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "slapcat - Win32 Single Debug" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "slapcat - Win32 Single Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "slapcat - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release"
+# PROP Intermediate_Dir "..\Release\slapcat"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
+
+!ELSEIF "$(CFG)" == "slapcat - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "slapcat"
+# PROP BASE Intermediate_Dir "slapcat"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug"
+# PROP Intermediate_Dir "..\Debug\slapcat"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libraries\Debug"
+
+!ELSEIF "$(CFG)" == "slapcat - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "slapcat"
+# PROP BASE Intermediate_Dir "slapcat"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Sdebug"
+# PROP Intermediate_Dir "..\SDebug\slapcat"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 oldbm32.lib libdb.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libraries\Debug"
+# ADD LINK32 hs_regex.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libraries\Debug"
+
+!ELSEIF "$(CFG)" == "slapcat - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "slapcat"
+# PROP BASE Intermediate_Dir "slapcat"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\SRelease"
+# PROP Intermediate_Dir "..\SRelease\slapcat"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libdb.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
+# ADD LINK32 hs_regex.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
+
+!ENDIF
+
+# Begin Target
+
+# Name "slapcat - Win32 Release"
+# Name "slapcat - Win32 Debug"
+# Name "slapcat - Win32 Single Debug"
+# Name "slapcat - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\mimic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapcat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapcommon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapcommon.h
+# End Source File
+# End Target
+# End Project
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* slapcommon.c - common routine for the slap tools */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#include "slapcommon.h"
+#include "lutil.h"
+
+
+char *progname = NULL;
+char *conffile = SLAPD_DEFAULT_CONFIGFILE;
+int truncatemode = 0;
+int verbose = 0;
+int noschemacheck = 0;
+int continuemode = 0;
+
+char *ldiffile = NULL;
+FILE *ldiffp = NULL;
+
+#ifdef CSRIMALLOC
+ char *leakfilename;
+ FILE *leakfile;
+#endif
+
+Backend *be = NULL;
+
+static void
+usage( int tool )
+{
+ char *options = NULL;
+ fprintf( stderr,
+ "usage: %s [-v] [-c] [-d debuglevel] [-f configfile]\n"
+ "\t[-n databasenumber | -b suffix]", progname );
+
+ switch( tool ) {
+ case SLAPADD:
+ options = "\t[-s] [-l ldiffile]\n";
+ break;
+
+ case SLAPCAT:
+ options = "\t[-l ldiffile]\n";
+ break;
+
+ case SLAPINDEX:
+ options = "\tattributetype\n";
+ break;
+ }
+
+ if( options != NULL ) {
+ fputs( options, stderr );
+ }
+ exit( EXIT_FAILURE );
+}
+
+
+/*
+ * slap_tool_init - initialize slap utility, handle program options.
+ * arguments:
+ * name program name
+ * tool tool code
+ * argc, argv command line arguments
+ */
+
+void
+slap_tool_init(
+ const char* name,
+ int tool,
+ int argc, char **argv )
+{
+ char *options;
+ char *base = NULL;
+ int rc, i, dbnum;
+ int mode = SLAP_TOOL_MODE;
+
+ progname = lutil_progname( name, argc, argv );
+
+#ifdef CSRIMALLOC
+ leakfilename = malloc( strlen( progname ) + sizeof(".leak") );
+ sprintf( leakfilename, "%s.leak", progname );
+ if( ( leakfile = fopen( leakfilename, "w" )) == NULL ) {
+ leakfile = stderr;
+ }
+ free( leakfilename );
+#endif
+
+ switch( tool ) {
+ case SLAPADD:
+ options = "b:cd:f:l:n:stv";
+ break;
+
+ case SLAPINDEX:
+ options = "b:cd:f:n:v";
+ break;
+
+ case SLAPCAT:
+ options = "b:cd:f:l:n:v";
+ break;
+
+ default:
+ fprintf( stderr, "%s: unknown tool mode (%d)\n",
+ progname, tool );
+ exit( EXIT_FAILURE );
+ }
+
+ ldiffile = NULL;
+ conffile = SLAPD_DEFAULT_CONFIGFILE;
+ dbnum = -1;
+ while ( (i = getopt( argc, argv, options )) != EOF ) {
+ switch ( i ) {
+ case 'b':
+ base = strdup( optarg );
+
+ case 'c': /* enable continue mode */
+ continuemode++;
+ break;
+
+ case 'd': /* turn on debugging */
+ ldap_debug += atoi( optarg );
+ break;
+
+ case 'f': /* specify a conf file */
+ conffile = strdup( optarg );
+ break;
+
+ case 'l': /* LDIF file */
+ ldiffile = strdup( optarg );
+ break;
+
+ case 'n': /* which config file db to index */
+ dbnum = atoi( optarg ) - 1;
+ break;
+
+ case 's': /* disable schema checking */
+ noschemacheck++;
+ break;
+
+ case 't': /* turn on truncate */
+ truncatemode++;
+ mode |= SLAP_TRUNCATE_MODE;
+ break;
+
+ case 'v': /* turn on verbose */
+ verbose++;
+ break;
+
+ default:
+ usage( tool );
+ break;
+ }
+ }
+
+ if ( ( argc != optind + (tool == SLAPINDEX ? 1 : 0) )
+ || (dbnum >= 0 && base != NULL ) )
+ {
+ usage( tool );
+ }
+
+ if ( ldiffile == NULL ) {
+ ldiffp = tool == SLAPCAT ? stdout : stdin;
+
+ } else if( (ldiffp = fopen( ldiffile, tool == SLAPCAT ? "w" : "r" ))
+ == NULL )
+ {
+ perror( ldiffile );
+ exit( EXIT_FAILURE );
+ }
+
+ /*
+ * initialize stuff and figure out which backend we're dealing with
+ */
+
+ rc = slap_init( mode, progname );
+
+ if (rc != 0 ) {
+ fprintf( stderr, "%s: slap_init failed!\n", progname );
+ exit( EXIT_FAILURE );
+ }
+
+ read_config( conffile );
+
+ if ( !nbackends ) {
+ fprintf( stderr, "No databases found in config file\n" );
+ exit( EXIT_FAILURE );
+ }
+
+ if( base != NULL ) {
+ char *tbase = ch_strdup( base );
+
+ if( dn_normalize_case( tbase ) == NULL ) {
+ fprintf( stderr, "%s: slap_init invalid suffix (\"%s\")\n",
+ progname, base );
+ exit( EXIT_FAILURE );
+ }
+
+ be = select_backend( tbase );
+ free( tbase );
+
+ if( be == NULL ) {
+ fprintf( stderr, "%s: slap_init no backend for \"%s\"\n",
+ progname, base );
+ exit( EXIT_FAILURE );
+ }
+
+ } else if ( dbnum == -1 ) {
+ be = &backends[dbnum=0];
+
+ } else if ( dbnum < 0 || dbnum > (nbackends-1) ) {
+ fprintf( stderr,
+ "Database number selected via -n is out of range\n"
+ "Must be in the range 1 to %d (number of databases in the config file)\n",
+ nbackends );
+ exit( EXIT_FAILURE );
+
+ } else {
+ be = &backends[dbnum];
+ }
+
+#ifdef CSRIMALLOC
+ mal_leaktrace(1);
+#endif
+
+ slap_startup( be );
+}
+
+void slap_tool_destroy( void )
+{
+ slap_shutdown( be );
+ slap_destroy();
+
+#ifdef CSRIMALLOC
+ mal_dumpleaktrace( leakfile );
+#endif
+}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* slapcommon.h - common definitions for the slap tools */
+
+#ifndef SLAPCOMMON_H_
+#define SLAPCOMMON_H_ 1
+
+#define SLAPD_TOOLS 1
+#include "ldap_defaults.h"
+#include "../slap.h"
+
+enum slaptool {
+ SLAPCAT=1, /* database -> LDIF tool */
+ SLAPADD, /* LDIF -> database tool */
+ SLAPINDEX, /* database index tool */
+ SLAPTEST /* database testing tool */
+};
+
+
+extern char *progname;
+extern char *conffile;
+extern Backend *be;
+extern int appendmode;
+extern int verbose;
+extern int noschemacheck;
+extern int continuemode;
+
+extern char *ldiffile;
+extern FILE *ldiffp;
+
+void slap_tool_init LDAP_P((
+ const char* name,
+ int tool,
+ int argc, char **argv ));
+
+void slap_tool_destroy LDAP_P((void));
+
+#endif /* SLAPCOMMON_H_ */
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#include "slapcommon.h"
+
+int
+main( int argc, char **argv )
+{
+ char *type;
+ ID id;
+ int rc = EXIT_SUCCESS;
+
+ slap_tool_init( "slapindex", SLAPINDEX, argc, argv );
+
+ if( !be->be_entry_open &&
+ !be->be_entry_close &&
+ !be->be_entry_first &&
+ !be->be_entry_next &&
+ !be->be_entry_get &&
+ !be->be_index_attr &&
+ !be->be_index_change )
+ {
+ fprintf( stderr, "%s: database doesn't support necessary operations.\n",
+ progname );
+ exit( EXIT_FAILURE );
+ }
+
+ type = attr_normalize( argv[argc - 1] );
+
+ if ( !be->be_index_attr( be, type ) ) {
+ fprintf( stderr, "attribute type \"%s\": no indices to generate\n",
+ type );
+ exit( EXIT_FAILURE );
+ }
+
+ if( be->be_entry_open( be, 0 ) != 0 ) {
+ fprintf( stderr, "%s: could not open database.\n",
+ progname );
+ exit( EXIT_FAILURE );
+ }
+
+ for ( id = be->be_entry_first( be );
+ id != NOID;
+ id = be->be_entry_next( be ) )
+ {
+ Attribute *attr;
+ struct berval **values;
+ Entry* e = be->be_entry_get( be, id );
+ struct berval bv;
+ struct berval *bvals[2];
+
+ if ( e == NULL ) {
+ fprintf( stderr,
+ "entry id=%08lx: no data\n", (long) id );
+ rc = EXIT_FAILURE;
+ if( continuemode ) continue;
+ break;
+ }
+
+ if( verbose ) {
+ printf("indexing id=%08lx dn=\"%s\"\n",
+ id, e->e_dn );
+ }
+
+ if( strcasecmp( type, "dn" ) == 0 ) {
+ attr = attr_find( e->e_attrs, type );
+
+ if( attr == NULL ) {
+ entry_free( e );
+ continue;
+ }
+
+ values = attr->a_vals;
+
+ } else {
+ bv.bv_val = e->e_ndn;
+ bv.bv_len = strlen( bv.bv_val );
+ bvals[0] = &bv;
+ bvals[1] = NULL;
+
+ values = bvals;
+ }
+
+ if ( be->be_index_change( be,
+ type, attr->a_vals, id, SLAP_INDEX_ADD_OP ) )
+ {
+ rc = EXIT_FAILURE;
+
+ if( !continuemode ) {
+ entry_free( e );
+ break;
+ }
+ }
+
+ entry_free( e );
+ }
+
+ (void) be->be_entry_close( be );
+
+ slap_tool_destroy();
+
+ return( rc );
+}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="slapindex" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=slapindex - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "slapindex.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "slapindex.mak" CFG="slapindex - Win32 Single Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "slapindex - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "slapindex - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "slapindex - Win32 Single Debug" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "slapindex - Win32 Single Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "slapindex - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release"
+# PROP Intermediate_Dir "..\Release\slapindex"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "slapindex - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ldif2ind"
+# PROP BASE Intermediate_Dir "ldif2ind"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug"
+# PROP Intermediate_Dir "..\Debug\slapindex"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "slapindex - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ldif2ind"
+# PROP BASE Intermediate_Dir "ldif2ind"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\SDebug"
+# PROP Intermediate_Dir "..\SDebug\slapindex"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib shell32.lib hs_regexd.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regex.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "slapindex - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ldif2in0"
+# PROP BASE Intermediate_Dir "ldif2in0"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\SRelease"
+# PROP Intermediate_Dir "..\SRelease\slapindex"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdbs.lib ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "slapindex - Win32 Release"
+# Name "slapindex - Win32 Debug"
+# Name "slapindex - Win32 Single Debug"
+# Name "slapindex - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\mimic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapcommon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapcommon.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapindex.c
+# End Source File
+# End Target
+# End Project
/* unbind.c - decode an ldap unbind operation and pass it to a backend db */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
/*
* Copyright (c) 1995 Regents of the University of Michigan.
*
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
-extern void be_unbind();
+#include <ac/socket.h>
+
+#include "slap.h"
-extern char *default_referral;
-extern pthread_mutex_t new_conn_mutex;
-void
+int
do_unbind(
Connection *conn,
Operation *op
* UnBindRequest ::= NULL
*/
- Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d UNBIND\n", conn->c_connid,
+ Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d UNBIND\n", op->o_connid,
op->o_opid, 0, 0, 0 );
/* pass the unbind to all backends */
- be_unbind( conn, op );
-
- /* close the connection to the client */
- close_connection( conn, op->o_connid, op->o_opid );
+ backend_unbind( conn, op );
+
+ return 0;
}
--- /dev/null
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* user.c - set user id, group id and group access list
+ *
+ * Copyright 1999 by PM Lashley.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+*/
+
+#include "portable.h"
+
+#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
+#include <ac/ctype.h>
+#include <ac/unistd.h>
+
+#include "slap.h"
+
+
+/*
+ * Set real and effective user id and group id, and group access list
+ * The user and group arguments are freed.
+ */
+
+void
+slap_init_user( char *user, char *group )
+{
+ uid_t uid;
+ gid_t gid;
+ int got_uid = 0, got_gid = 0;
+
+ if ( user ) {
+ struct passwd *pwd;
+ if ( isdigit( (unsigned char) *user )) {
+ got_uid = 1;
+ uid = atoi( user );
+#ifdef HAVE_GETPWUID
+ pwd = getpwuid( uid );
+ goto did_getpw;
+#else
+ free( user );
+ user = NULL;
+#endif
+ } else {
+ pwd = getpwnam( user );
+ did_getpw:
+ if ( pwd == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "No passwd entry for user %s\n",
+ user, 0, 0 );
+ exit( EXIT_FAILURE );
+ }
+ if ( got_uid ) {
+ free( user );
+ user = (pwd != NULL ? ch_strdup( pwd->pw_name ) : NULL);
+ } else {
+ got_uid = 1;
+ uid = pwd->pw_uid;
+ }
+ got_gid = 1;
+ gid = pwd->pw_gid;
+#ifdef HAVE_ENDPWENT
+ endpwent();
+#endif
+ }
+ }
+
+ if ( group ) {
+ struct group *grp;
+ if ( isdigit( (unsigned char) *group )) {
+ gid = atoi( group );
+#ifdef HAVE_GETGRGID
+ grp = getgrgid( gid );
+ goto did_group;
+#endif
+ } else {
+ grp = getgrnam( group );
+ if ( grp != NULL )
+ gid = grp->gr_gid;
+ did_group:
+ if ( grp == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "No group entry for group %s\n",
+ group, 0, 0 );
+ exit( EXIT_FAILURE );
+ }
+ }
+ free( group );
+ got_gid = 1;
+ }
+
+ if ( user ) {
+ if ( getuid() == 0 && initgroups( user, gid ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "Could not set the group access (gid) list\n", 0, 0, 0 );
+ exit( EXIT_FAILURE );
+ }
+ free( user );
+ }
+
+#ifdef HAVE_ENDGRENT
+ endgrent();
+#endif
+
+ if ( got_gid ) {
+ if ( setgid( gid ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "Could not set real group id to %d\n",
+ gid, 0, 0 );
+ exit( EXIT_FAILURE );
+ }
+#ifdef HAVE_SETEGID
+ if ( setegid( gid ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "Could not set effective group id to %d\n",
+ gid, 0, 0 );
+ exit( EXIT_FAILURE );
+ }
+#endif
+ }
+
+ if ( got_uid ) {
+ if ( setuid( uid ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "Could not set real user id to %d\n",
+ uid, 0, 0 );
+ exit( EXIT_FAILURE );
+ }
+#ifdef HAVE_SETEUID
+ if ( seteuid( uid ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "Could not set effective user id to %d\n",
+ uid, 0, 0 );
+ exit( EXIT_FAILURE );
+ }
+#endif
+ }
+}
+
+#endif /* HAVE_PWD_H && HAVE_GRP_H */
/* value.c - routines for dealing with values */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include <sys/stat.h>
-#include "portable.h"
+
#include "slap.h"
int
if ( (syntax & SYNTAX_TEL) && (*s == ' ' || *s == '-') ) {
continue;
}
- *d++ = TOUPPER( *s );
+ *d++ = TOUPPER( (unsigned char) *s );
}
*d = '\0';
}
-#define MIN( a, b ) (a < b ? a : b )
-
int
value_cmp(
struct berval *v1,
)
{
int rc;
- struct stat st1, st2;
if ( normalize & 1 ) {
v1 = ber_bvdup( v1 );
break;
case SYNTAX_BIN:
- rc = memcmp( v1->bv_val, v2->bv_val, MIN( v1->bv_len,
- v2->bv_len ) );
+ rc = (v1->bv_len == v2->bv_len
+ ? memcmp( v1->bv_val, v2->bv_val, v1->bv_len )
+ : v1->bv_len > v2->bv_len ? 1 : -1);
break;
}
return( rc );
}
-int
-value_ncmp(
- struct berval *v1,
- struct berval *v2,
- int syntax,
- int len,
- int normalize
-)
-{
- int rc;
-
- if ( normalize & 1 ) {
- v1 = ber_bvdup( v1 );
- value_normalize( v1->bv_val, syntax );
- }
- if ( normalize & 2 ) {
- v2 = ber_bvdup( v2 );
- value_normalize( v2->bv_val, syntax );
- }
-
- switch ( syntax ) {
- case SYNTAX_CIS:
- case (SYNTAX_CIS | SYNTAX_TEL):
- rc = strncasecmp( v1->bv_val, v2->bv_val, len );
- break;
-
- case SYNTAX_CES:
- rc = strncmp( v1->bv_val, v2->bv_val, len );
- break;
-
- case SYNTAX_BIN:
- rc = memcmp( v1->bv_val, v2->bv_val, len );
- }
-
- if ( normalize & 1 ) {
- ber_bvfree( v1 );
- }
- if ( normalize & 2 ) {
- ber_bvfree( v2 );
- }
-
- return( rc );
-}
-
int
value_find(
struct berval **vals,
--- /dev/null
+##
+## Makefile.in for slurpd
+##
+
+PROGRAMS = slurpd
+XPROGRAMS = sslurpd
+
+XSRCS = version.c
+
+SRCS = admin.c args.c ch_malloc.c config.c \
+ fm.c globals.c ldap_op.c lock.c main.c re.c \
+ reject.c replica.c replog.c ri.c rq.c sanity.c st.c
+OBJS = admin.o args.o ch_malloc.o config.o \
+ fm.o globals.o ldap_op.o lock.o main.o re.o \
+ reject.o replica.o replog.o ri.o rq.o sanity.o st.o
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+BUILD_OPT = "--enable-slurpd"
+BUILD_SRV = @BUILD_SLURPD@
+
+all-local-srv: slurpd
+
+# $(LTHREAD_LIBS) must be last!
+XLIBS = -lldif -lldap_r -llber -llutil
+XXLIBS = $(SLURPD_LIBS) $(SECURITY_LIBS) \
+ $(LDIF_LIBS) $(LUTIL_LIBS)
+XXXLIBS = $(LTHREAD_LIBS)
+
+slurpd: version.o
+ $(LTLINK) -o $@ $(OBJS) version.o $(LIBS)
+
+sslurpd: version.o
+ $(LTLINK) -static -o $@ $(OBJS) version.o $(LIBS)
+
+version.c: $(OBJS) $(LDAP_LIBDEPEND) $(LDAP_LIBTHREAD_DEPEND)
+ @-$(RM) $@
+ $(MKVERSION) slurpd > $@
+
+install-local-srv: FORCE
+ @-$(MKDIR) $(libexecdir)
+ $(LTINSTALL) $(INSTALLFLAGS) -m 755 slurpd $(libexecdir)
* is provided ``as is'' without express or implied warranty.
*/
+#define CH_FREE 1
+
/*
* ch_malloc.c - malloc() and friends, with check for NULL return.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/stdlib.h>
+#include <ac/socket.h>
+
#include "../slapd/slap.h"
+#ifndef CSRIMALLOC
/*
* Just like malloc, except we check the returned value and exit
* if anything goes wrong.
*/
-char *
+void *
ch_malloc(
- unsigned long size
+ ber_len_t size
)
{
- char *new;
+ void *new;
- if ( (new = (char *) malloc( size )) == NULL ) {
- fprintf( stderr, "malloc of %d bytes failed\n", size );
- exit( 1 );
+ if ( (new = (void *) ber_memalloc( size )) == NULL ) {
+ fprintf( stderr, "malloc of %lu bytes failed\n",
+ (long) size );
+ exit( EXIT_FAILURE );
}
return( new );
* Just like realloc, except we check the returned value and exit
* if anything goes wrong.
*/
-char *
+void *
ch_realloc(
- char *block,
- unsigned long size
+ void *block,
+ ber_len_t size
)
{
- char *new;
+ void *new;
if ( block == NULL ) {
return( ch_malloc( size ) );
}
- if ( (new = (char *) realloc( block, size )) == NULL ) {
- fprintf( stderr, "realloc of %d bytes failed\n", size );
- exit( 1 );
+ if ( size == 0 ) {
+ ch_free( block );
+ }
+
+ if ( (new = (void *) ber_memrealloc( block, size )) == NULL ) {
+ fprintf( stderr, "realloc of %lu bytes failed\n",
+ (long) size );
+ exit( EXIT_FAILURE );
}
return( new );
* Just like calloc, except we check the returned value and exit
* if anything goes wrong.
*/
-char *
+void *
ch_calloc(
- unsigned long nelem,
- unsigned long size
+ ber_len_t nelem,
+ ber_len_t size
)
{
- char *new;
+ void *new;
- if ( (new = (char *) calloc( nelem, size )) == NULL ) {
- fprintf( stderr, "calloc of %d elems of %d bytes failed\n",
- nelem, size );
- exit( 1 );
+ if ( (new = (void *) ber_memcalloc( nelem, size )) == NULL ) {
+ fprintf( stderr, "calloc of %lu elems of %lu bytes failed\n",
+ (long) nelem, (long) size );
+ exit( EXIT_FAILURE );
}
return( new );
*/
void
ch_free(
- char *p
+ void *p
)
{
if ( p != NULL ) {
- free( p );
+ ber_memfree( p );
}
return;
}
-
+
+#endif
* config.c - configuration file handling routines
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/ctype.h>
#include <lber.h>
#include <ldap.h>
#define MAXARGS 100
/* Forward declarations */
-#ifdef NEEDPROTOS
-static void add_replica( char **, int );
-static int parse_replica_line( char **, int, Ri *);
-static void parse_line( char *, int *, char ** );
-static char *getline( FILE * );
-static char *strtok_quote( char *, char * );
-#else /* NEEDPROTOS */
-static void add_replica();
-static int parse_replica_line();
-static void parse_line();
-static char *getline();
-static char *strtok_quote();
-#endif /* NEEDPROTOS */
+static void add_replica LDAP_P(( char **, int ));
+static int parse_replica_line LDAP_P(( char **, int, Ri *));
+static void parse_line LDAP_P(( char *, int *, char ** ));
+static char *getline LDAP_P(( FILE * ));
+static char *strtok_quote LDAP_P(( char *, char * ));
/* current config file line # */
static int lineno;
)
{
FILE *fp;
- char buf[BUFSIZ];
- char *line, *p;
+ char *line;
int cargc;
char *cargv[MAXARGS];
if ( (fp = fopen( fname, "r" )) == NULL ) {
perror( fname );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
lineno = 0;
"line %d: missing filename in \"replogfile ",
lineno );
fprintf( stderr, "<filename>\" line\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
} else if ( cargc > 2 && *cargv[2] != '#' ) {
fprintf( stderr,
"line %d: extra cruft at the end of \"replogfile %s\"",
} else {
inquote = 1;
}
- strcpy( next, next + 1 );
+ SAFEMEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
break;
case '\\':
- strcpy( next, next + 1 );
+ if ( next[1] )
+ SAFEMEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
+ next++; /* dont parse the escaped character */
break;
default:
*p = '\0';
}
lineno++;
- if ( ! isspace( buf[0] ) ) {
+ if ( ! isspace( (unsigned char) buf[0] ) ) {
return( line );
}
( nr + 1 ) * sizeof( Re * ));
if ( sglob->replicas == NULL ) {
fprintf( stderr, "out of memory, add_replica\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
sglob->replicas[ nr ] = NULL;
if ( Ri_init( &(sglob->replicas[ nr - 1 ])) < 0 ) {
fprintf( stderr, "out of memory, Ri_init\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
if ( parse_replica_line( cargv, cargc,
sglob->replicas[ nr - 1] ) < 0 ) {
sglob->replicas[ nr - 1 ] );
if ( sglob->replicas[ nr - 1]->ri_stel == NULL ) {
fprintf( stderr, "Failed to add status element structure\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
}
}
ri->ri_port = atoi( hp );
}
if ( ri->ri_port <= 0 ) {
- ri->ri_port = LDAP_PORT;
+ ri->ri_port = 0;
}
ri->ri_hostname = strdup( val );
gots |= GOT_HOST;
strlen( BINDMETHSTR ))) {
val = cargv[ i ] + strlen( BINDMETHSTR ) + 1;
if ( !strcasecmp( val, KERBEROSSTR )) {
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
ri->ri_bind_method = AUTH_KERBEROS;
if ( ri->ri_srvtab == NULL ) {
ri->ri_srvtab = strdup( sglob->default_srvtab );
}
gots |= GOT_METHOD;
-#else /* KERBEROS */
+#else /* HAVE_KERBEROS */
fprintf( stderr, "Error: a bind method of \"kerberos\" was\n" );
fprintf( stderr, "specified in the slapd configuration file,\n" );
fprintf( stderr, "but slurpd was not built with kerberos.\n" );
fprintf( stderr, "You must rebuild the LDAP release with\n" );
fprintf( stderr, "kerberos support if you wish to use\n" );
fprintf( stderr, "bindmethod=kerberos\n" );
- exit( 1 );
-#endif /* KERBEROS */
+ exit( EXIT_FAILURE );
+#endif /* HAVE_KERBEROS */
} else if ( !strcasecmp( val, SIMPLESTR )) {
ri->ri_bind_method = AUTH_SIMPLE;
gots |= GOT_METHOD;
* globals.c - initialization code for global data
*/
+#include "portable.h"
+
#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+
#include "slurp.h"
#include "globals.h"
/*
* Initialize the globals
*/
-Globals *init_globals()
+Globals *
+init_globals( void )
{
Globals *g;
g->srpos = 0L;
if ( St_init( &(g->st)) < 0 ) {
fprintf( stderr, "Cannot initialize status data\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
- pthread_mutex_init( &(g->rej_mutex), pthread_mutexattr_default );
+ ldap_pvt_thread_mutex_init( &(g->rej_mutex) );
if ( Rq_init( &(g->rq)) < 0 ) {
fprintf( stderr, "Cannot initialize queue\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
g->default_srvtab = SRVTAB;
-#endif /* KERBEROS */
-#if defined( THREAD_SUNOS4_LWP )
- g->tsl_list = NULL;
- mon_create( &g->tsl_mon );
-#endif /* THREAD_SUNOS4_LWP */
+#endif /* HAVE_KERBEROS */
return g;
}
* ldap_op.c - routines to perform LDAP operations
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#ifdef KERBEROS
-#include <krb.h>
-#endif /* KERBEROS */
+#include <ac/stdlib.h>
+
+#include <ac/errno.h>
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+#include <ac/krb.h>
+
+#if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET )
+/* Get LDAP->ld_lberoptions. Must precede slurp.h, both define ldap_debug. */
+#include "../../libraries/libldap/ldap-int.h"
+#endif
#include <lber.h>
#include <ldap.h>
-#include "portable.h"
#include "slurp.h"
/* Forward references */
-static int get_changetype( char * );
-static struct berval **make_singlevalued_berval( char *, int );
-static int op_ldap_add( Ri *, Re *, char ** );
-static int op_ldap_modify( Ri *, Re *, char ** );
-static int op_ldap_delete( Ri *, Re *, char ** );
-static int op_ldap_modrdn( Ri *, Re *, char ** );
-static LDAPMod *alloc_ldapmod();
-static void free_ldapmod( LDAPMod * );
-static void free_ldmarr( LDAPMod ** );
-static int getmodtype( char * );
-static void dump_ldm_array( LDAPMod ** );
-static char **read_krbnames( Ri * );
-static void upcase( char * );
-static int do_bind( Ri *, int * );
-static int do_unbind( Ri * );
-
-
-/* External references */
-#ifndef SYSERRLIST_IN_STDIO
-extern char *sys_errlist[];
-#endif /* SYSERRLIST_IN_STDIO */
-
-extern char *ch_malloc( unsigned long );
+static struct berval **make_singlevalued_berval LDAP_P(( char *, int ));
+static int op_ldap_add LDAP_P(( Ri *, Re *, char ** ));
+static int op_ldap_modify LDAP_P(( Ri *, Re *, char ** ));
+static int op_ldap_delete LDAP_P(( Ri *, Re *, char ** ));
+static int op_ldap_modrdn LDAP_P(( Ri *, Re *, char ** ));
+static LDAPMod *alloc_ldapmod LDAP_P(( void ));
+static void free_ldapmod LDAP_P(( LDAPMod * ));
+static void free_ldmarr LDAP_P(( LDAPMod ** ));
+static int getmodtype LDAP_P(( char * ));
+static void dump_ldm_array LDAP_P(( LDAPMod ** ));
+static char **read_krbnames LDAP_P(( Ri * ));
+static void upcase LDAP_P(( char * ));
+static int do_bind LDAP_P(( Ri *, int * ));
+static int do_unbind LDAP_P(( Ri * ));
+
static char *kattrs[] = {"kerberosName", NULL };
static struct timeval kst = {30L, 0L};
int rc = 0;
int lderr = LDAP_SUCCESS;
int retry = 2;
- char *msg;
*errmsg = NULL;
Debug( LDAP_DEBUG_ARGS, "replica %s:%d - add dn \"%s\"\n",
ri->ri_hostname, ri->ri_port, re->re_dn );
rc = ldap_add_s( ri->ri_ldp, re->re_dn, ldmarr );
- lderr = ri->ri_ldp->ld_errno;
+
+ ldap_get_option( ri->ri_ldp, LDAP_OPT_ERROR_NUMBER, &lderr);
+
} else {
*errmsg = "No modifications to do";
Debug( LDAP_DEBUG_ANY,
- "Error: op_ldap_add: no mods to do (%s)!", re->re_dn, 0, 0 );
+ "Error: op_ldap_add: no mods to do (%s)!\n", re->re_dn, 0, 0 );
}
free_ldmarr( ldmarr );
return( lderr );
int state; /* This code is a simple-minded state machine */
int nvals; /* Number of values we're modifying */
int nops; /* Number of LDAPMod structs in ldmarr */
- LDAPMod *ldm, *nldm, **ldmarr;
+ LDAPMod *ldm, **ldmarr;
int i, len;
char *type, *value;
int rc = 0;
/*
* Perform an ldap modrdn operation.
*/
-#define GOT_NEWRDN 1
-#define GOT_DRDNFLAGSTR 2
-#define GOT_ALLNEWRDNFLAGS ( GOT_NEWRDN | GOT_DRDNFLAGSTR )
+#define GOT_NEWRDN 0x1
+#define GOT_DELOLDRDN 0x2
+#define GOT_NEWSUP 0x4
+
+#define GOT_MODDN_REQ (GOT_NEWRDN|GOT_DELOLDRDN)
+#define GOT_ALL_MODDN(f) (((f) & GOT_MODDN_REQ) == GOT_MODDN_REQ)
static int
op_ldap_modrdn(
Ri *ri,
int rc = 0;
Mi *mi;
int i;
+ int lderr = 0;
int state = 0;
int drdnflag = -1;
char *newrdn;
+ char *newsup = NULL;
if ( re->re_mods == NULL ) {
*errmsg = "No arguments given";
*/
for ( mi = re->re_mods, i = 0; mi[ i ].mi_type != NULL; i++ ) {
if ( !strcmp( mi[ i ].mi_type, T_NEWRDNSTR )) {
+ if( state & GOT_NEWRDN ) {
+ Debug( LDAP_DEBUG_ANY,
+ "Error: op_ldap_modrdn: multiple newrdn arg \"%s\"\n",
+ mi[ i ].mi_val, 0, 0 );
+ *errmsg = "Multiple newrdn argument";
+ return -1;
+ }
+
newrdn = mi[ i ].mi_val;
state |= GOT_NEWRDN;
- } else if ( !strcmp( mi[ i ].mi_type, T_DRDNFLAGSTR )) {
- state |= GOT_DRDNFLAGSTR;
+
+ } else if ( !strcmp( mi[ i ].mi_type, T_DELOLDRDNSTR )) {
+ if( state & GOT_DELOLDRDN ) {
+ Debug( LDAP_DEBUG_ANY,
+ "Error: op_ldap_modrdn: multiple deleteoldrdn arg \"%s\"\n",
+ mi[ i ].mi_val, 0, 0 );
+ *errmsg = "Multiple newrdn argument";
+ return -1;
+ }
+
+ state |= GOT_DELOLDRDN;
if ( !strcmp( mi[ i ].mi_val, "0" )) {
drdnflag = 0;
} else if ( !strcmp( mi[ i ].mi_val, "1" )) {
*errmsg = "Incorrect argument to deleteoldrdn";
return -1;
}
+
+ } else if ( !strcmp( mi[ i ].mi_type, T_NEWSUPSTR )) {
+ if( state & GOT_NEWSUP ) {
+ Debug( LDAP_DEBUG_ANY,
+ "Error: op_ldap_modrdn: multiple newsuperior arg \"%s\"\n",
+ mi[ i ].mi_val, 0, 0 );
+ *errmsg = "Multiple newrdn argument";
+ return -1;
+ }
+
+ newrdn = mi[ i ].mi_val;
+ state |= GOT_NEWSUP;
+
} else {
Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: bad type \"%s\"\n",
mi[ i ].mi_type, 0, 0 );
/*
* Punt if we don't have all the args.
*/
- if ( state != GOT_ALLNEWRDNFLAGS ) {
+ if ( GOT_ALL_MODDN(state) ) {
Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: missing arguments\n",
0, 0, 0 );
*errmsg = "Missing argument: requires \"newrdn\" and \"deleteoldrdn\"";
#endif /* LDAP_DEBUG */
/* Do the modrdn */
- rc = ldap_modrdn2_s( ri->ri_ldp, re->re_dn, mi->mi_val, drdnflag );
+ rc = ldap_rename2_s( ri->ri_ldp, re->re_dn, mi->mi_val, drdnflag, newsup );
- return( ri->ri_ldp->ld_errno );
+ ldap_get_option( ri->ri_ldp, LDAP_OPT_ERROR_NUMBER, &lderr);
+ return( lderr );
}
* Allocate and initialize an ldapmod struct.
*/
static LDAPMod *
-alloc_ldapmod()
+alloc_ldapmod( void )
{
LDAPMod *ldm;
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
"Error: do_unbind: ldap_unbind failed for %s:%d: %s\n",
- ldap_err2string( rc ), ri->ri_hostname, ri->ri_port );
+ ri->ri_hostname, ri->ri_port, ldap_err2string( rc ) );
}
ri->ri_ldp = NULL;
}
int *lderr
)
{
- int rc;
int ldrc;
- char msgbuf[ 1024];
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
+ int rc;
int retval = 0;
int kni, got_tgt;
char **krbnames;
char realm[ REALM_SZ ];
char name[ ANAME_SZ ];
char instance[ INST_SZ ];
-#endif /* KERBEROS */
+#endif /* HAVE_KERBEROS */
*lderr = 0;
ri->ri_ldp = NULL;
}
- Debug( LDAP_DEBUG_ARGS, "Open connection to %s:%d\n",
+ Debug( LDAP_DEBUG_ARGS, "Initializing session to %s:%d\n",
ri->ri_hostname, ri->ri_port, 0 );
- ri->ri_ldp = ldap_open( ri->ri_hostname, ri->ri_port );
+ ri->ri_ldp = ldap_init( ri->ri_hostname, ri->ri_port );
if ( ri->ri_ldp == NULL ) {
- Debug( LDAP_DEBUG_ANY, "Error: ldap_open(%s, %d) failed: %s\n",
+ Debug( LDAP_DEBUG_ANY, "Error: ldap_init(%s, %d) failed: %s\n",
ri->ri_hostname, ri->ri_port, sys_errlist[ errno ] );
return( BIND_ERR_OPEN );
}
+ /*
+ * Disable string translation if enabled by default.
+ * The replication log is written in the internal format,
+ * so this would do another translation, breaking havoc.
+ */
+#if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET )
+ ri->ri_ldp->ld_lberoptions &= ~LBER_TRANSLATE_STRINGS;
+#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */
+
/*
* Set ldap library options to (1) not follow referrals, and
* (2) restart the select() system call.
*/
-#ifdef LDAP_REFERRALS
- ri->ri_ldp->ld_options &= ~LDAP_OPT_REFERRALS;
-#endif /* LDAP_REFERRALS */
- ri->ri_ldp->ld_options |= LDAP_OPT_RESTART;
+ ldap_set_option(ri->ri_ldp, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
+ ldap_set_option(ri->ri_ldp, LDAP_OPT_RESTART, LDAP_OPT_ON);
switch ( ri->ri_bind_method ) {
case AUTH_KERBEROS:
-#ifndef KERBEROS
+#ifndef HAVE_KERBEROS
Debug( LDAP_DEBUG_ANY,
"Error: Kerberos bind for %s:%d, but not compiled w/kerberos\n",
ri->ri_hostname, ri->ri_port, 0 );
return( BIND_ERR_KERBEROS_FAILED );
-#else /* KERBEROS */
+#else /* HAVE_KERBEROS */
/*
* Bind using kerberos.
* If "bindprincipal" was given in the config file, then attempt
}
return( retval);
break;
-#endif /* KERBEROS */
+#endif /* HAVE_KERBEROS */
case AUTH_SIMPLE:
/*
* Bind with a plaintext password.
*/
static void
dump_ldm_array(
-LDAPMod **ldmarr )
+ LDAPMod **ldmarr
+)
{
int i, j;
LDAPMod *ldm;
for ( i = 0; ldmarr[ i ] != NULL; i++ ) {
ldm = ldmarr[ i ];
Debug( LDAP_DEBUG_TRACE,
- "Trace (%d): *** ldmarr[ %d ] contents:\n",
- getpid(), i, 0 );
+ "Trace (%ld): *** ldmarr[ %d ] contents:\n",
+ (long) getpid(), i, 0 );
Debug( LDAP_DEBUG_TRACE,
- "Trace (%d): *** ldm->mod_op: %d\n",
- getpid(), ldm->mod_op, 0 );
+ "Trace (%ld): *** ldm->mod_op: %d\n",
+ (long) getpid(), ldm->mod_op, 0 );
Debug( LDAP_DEBUG_TRACE,
- "Trace (%d): *** ldm->mod_type: %s\n",
- getpid(), ldm->mod_type, 0 );
+ "Trace (%ld): *** ldm->mod_type: %s\n",
+ (long) getpid(), ldm->mod_type, 0 );
if ( ldm->mod_bvalues != NULL ) {
for ( j = 0; ( b = ldm->mod_bvalues[ j ] ) != NULL; j++ ) {
msgbuf = ch_malloc( b->bv_len + 512 );
- sprintf( msgbuf, "***** bv[ %d ] len = %d, val = <%s>",
+ sprintf( msgbuf, "***** bv[ %d ] len = %ld, val = <%s>",
j, b->bv_len, b->bv_val );
Debug( LDAP_DEBUG_TRACE,
- "Trace (%d):%s\n", getpid(), msgbuf, 0 );
+ "Trace (%ld):%s\n", (long) getpid(), msgbuf, 0 );
free( msgbuf );
}
}
*/
static void
upcase(
-char *s )
+ char *s
+)
{
char *p;
for ( p = s; ( p != NULL ) && ( *p != '\0' ); p++ ) {
- if ( islower( *p )) {
- *p = toupper( *p );
- }
+ *p = TOUPPER( (unsigned char) *p );
}
}
* main.c - main routine for slurpd.
*/
+#include "portable.h"
+
+#include <ac/stdlib.h>
+
#include <stdio.h>
#include "slurp.h"
#include "globals.h"
+#include "lutil.h"
-extern int doargs( int, char **, Globals * );
-extern void fm();
-extern int start_replica_thread( Ri * );
-extern Globals *init_globals();
-extern int sanity();
-#if defined( THREAD_SUNOS4_LWP )
-extern void start_lwp_scheduler();
-#endif /* THREAD_SUNOS4_LWP */
-
+int
main(
int argc,
char **argv
)
{
- pthread_attr_t attr;
- int status;
+#ifdef NO_THREADS
+ /* Haven't yet written the non-threaded version */
+ fputs( "slurpd currently requires threads support\n", stderr );
+ return( 1 );
+#else
+
int i;
-#ifndef _THREAD
- /* Haven't yet written the non-threaded version */
- fprintf( stderr, "slurpd currently requires threads support\n" );
- exit( 1 );
-#endif /* !_THREAD */
+ /* initialize thread package */
+ ldap_pvt_thread_initialize();
/*
* Create and initialize globals. init_globals() also initializes
*/
if (( sglob = init_globals()) == NULL ) {
fprintf( stderr, "Out of memory initializing globals\n" );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/*
* Process command-line args and fill in globals.
*/
if ( doargs( argc, argv, sglob ) < 0 ) {
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/*
fprintf( stderr,
"Errors encountered while processing config file \"%s\"\n",
sglob->slapd_configfile );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/*
if ( sglob->st->st_read( sglob->st )) {
fprintf( stderr, "Malformed slurpd status file \"%s\"\n",
sglob->slurpd_status_file, 0, 0 );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/*
* Check for any fatal error conditions before we get started
*/
if ( sanity() < 0 ) {
- exit( 1 );
+ exit( EXIT_FAILURE );
}
/*
* and if not in one-shot mode.
*/
#ifdef LDAP_DEBUG
- if (( ldap_debug == 0 ) && !sglob->one_shot_mode ) {
+ if (( ldap_debug == 0 ) && !sglob->one_shot_mode )
#else /* LDAP_DEBUG */
- if ( !sglob->one_shot_mode ) {
+ if ( !sglob->one_shot_mode )
#endif /* LDAP_DEBUG */
- detach();
- }
-
-#ifdef _THREAD
-
-#if defined( THREAD_SUNOS4_LWP )
- /*
- * Need to start a scheduler thread under SunOS 4
- */
- start_lwp_scheduler();
-#endif /* THREAD_SUNOS4_LWP */
-
+ lutil_detach( 0, 0 );
/*
* Start threads - one thread for each replica
/*
* Start the main file manager thread (in fm.c).
*/
- pthread_attr_init( &attr );
- if ( pthread_create( &(sglob->fm_tid), attr, (void *) fm, (void *) NULL )
- != 0 ) {
- Debug( LDAP_DEBUG_ANY, "file manager pthread_create failed\n",
+ if ( ldap_pvt_thread_create( &(sglob->fm_tid),
+ 0, fm, (void *) NULL ) != 0 )
+ {
+ Debug( LDAP_DEBUG_ANY, "file manager ldap_pvt_thread_create failed\n",
0, 0, 0 );
- exit( 1 );
+ exit( EXIT_FAILURE );
}
- pthread_attr_destroy( &attr );
/*
* Wait for the fm thread to finish.
*/
- pthread_join( sglob->fm_tid, (void *) &status );
+ ldap_pvt_thread_join( sglob->fm_tid, (void *) NULL );
+
/*
* Wait for the replica threads to finish.
*/
for ( i = 0; sglob->replicas[ i ] != NULL; i++ ) {
- pthread_join( sglob->replicas[ i ]->ri_tid, (void *) &status );
+ ldap_pvt_thread_join( sglob->replicas[ i ]->ri_tid, (void *) NULL );
}
- Debug( LDAP_DEBUG_ANY, "slurpd: terminating normally\n", 0, 0, 0 );
- sglob->slurpd_shutdown = 1;
- pthread_exit( 0 );
-#else /* !_THREAD */
- /*
- * Non-threaded case.
- */
- exit( 0 );
+ /* destroy the thread package */
+ ldap_pvt_thread_destroy();
-#endif /* !_THREAD */
-
+ Debug( LDAP_DEBUG_ANY, "slurpd: terminated.\n", 0, 0, 0 );
+ return 0;
+#endif /* !NO_THREADS */
}
--- /dev/null
+#ifndef _PROTO_SLURP
+#define _PROTO_SLURP
+
+#include <ldap_cdefs.h>
+
+struct globals;
+
+/* admin.c */
+RETSIGTYPE do_admin LDAP_P((int sig));
+
+/* args.c */
+int doargs LDAP_P((int argc, char **argv, struct globals *g));
+
+/* ch_malloc.c */
+#ifdef CSRIMALLOC
+#define ch_malloc malloc
+#define ch_realloc realloc
+#define ch_calloc calloc
+#define ch_free free
+#else
+void *ch_malloc LDAP_P((ber_len_t size));
+void *ch_realloc LDAP_P((void *block, ber_len_t size));
+void *ch_calloc LDAP_P((ber_len_t nelem, ber_len_t size));
+void ch_free LDAP_P((void *p));
+#endif
+
+/* config.c */
+int slurpd_read_config LDAP_P((char *fname));
+
+/* ch_malloc.c */
+void ch_free LDAP_P(( void *p ));
+
+/* fm.c */
+void *fm LDAP_P((void *arg));
+RETSIGTYPE do_nothing LDAP_P((int i));
+
+/* globals.c */
+extern struct globals *sglob;
+extern int ldap_syslog;
+extern int ldap_syslog_level;
+extern int ldap_debug;
+extern struct globals *init_globals LDAP_P((void));
+
+/* ldap_op.c */
+int do_ldap LDAP_P((Ri *ri, Re *re, char **errmsg));
+
+/* lock.c */
+FILE *lock_fopen LDAP_P((char *fname, char *type, FILE **lfp));
+int lock_fclose LDAP_P((FILE *fp, FILE *lfp));
+int acquire_lock LDAP_P((char *file, FILE **rfp, FILE **lfp));
+int relinquish_lock LDAP_P((char *file, FILE *rfp, FILE *lfp));
+
+/* reject.c */
+void write_reject LDAP_P((Ri *ri, Re *re, int lderr, char *errmsg));
+
+/* replica.c */
+int start_replica_thread LDAP_P((Ri *ri));
+
+/* replog.c */
+int copy_replog LDAP_P((char *src, char *dst));
+int file_nonempty LDAP_P((char *filename));
+
+/* sanity.c */
+int sanity LDAP_P((void));
+
+/* st.c */
+int St_init LDAP_P((St **st));
+
+/* tsleep.c */
+int tsleep LDAP_P((time_t interval));
+#if defined( HAVE_LWP )
+void start_lwp_scheduler LDAP_P(( void ));
+#endif
+
+#endif /* _PROTO_SLURP */
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "../slapd/slap.h"
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/ctype.h>
+
#include "slurp.h"
#include "globals.h"
-/* externs */
-extern char *str_getline( char **next );
-extern void ch_free( char *p );
-
-extern char *sys_errlist[];
+#include "../slapd/slap.h"
/* Forward references */
-static Rh *get_repl_hosts( char *, int *, char ** );
-static int gettype( char * );
-static int getchangetype( char *);
-static int Re_parse( Re *re, char *replbuf );
-static void Re_dump( Re *re, FILE *fp );
-static void warn_unknown_replica( char *, int port );
+static Rh *get_repl_hosts LDAP_P(( char *, int *, char ** ));
+static int gettype LDAP_P(( char * ));
+static int getchangetype LDAP_P(( char * ));
+static int Re_parse LDAP_P(( Re *re, char *replbuf ));
+static void Re_dump LDAP_P(( Re *re, FILE *fp ));
+static void warn_unknown_replica LDAP_P(( char *, int port ));
/* Globals, scoped within this file */
static int nur = 0; /* Number of unknown replicas */
/*
* Free an Re
+ * ??? Something should apparently return nonzero here, but I dont know what.
*/
static int
Re_free(
"Warning: freeing re (dn: %s) with nonzero refcnt\n",
re->re_dn, 0, 0 );
}
-#if !defined( THREAD_SUNOS4_LWP )
- /* This seems to have problems under SunOS lwp */
- pthread_mutex_destroy( &re->re_mutex );
-#endif /* THREAD_SUNOS4_LWP */
+
+ ldap_pvt_thread_mutex_destroy( &re->re_mutex );
+
ch_free( re->re_timestamp );
if (( rh = re->re_replicas ) != NULL ) {
for ( i = 0; rh[ i ].rh_hostname != NULL; i++ ) {
free( mi );
}
free( re );
+ return 0;
}
int state;
int nml;
char *buf, *rp, *p;
- long buflen;
+ size_t buflen;
char *type, *value;
- int len;
+ ber_len_t len;
int nreplicas;
if ( re == NULL ) {
re->re_refcnt = sglob->num_replicas;
for (;;) {
- if (( state == GOT_ALL ) || ( buf = str_getline( &rp )) == NULL ) {
+ if (( state == GOT_ALL ) || ( buf = ldif_getline( &rp )) == NULL ) {
break;
}
/*
if ( strncmp( buf, ERROR_STR, strlen( ERROR_STR )) == 0 ) {
continue;
}
- buflen = ( long ) strlen( buf );
- if ( str_parse_line( buf, &type, &value, &len ) < 0 ) {
+ buflen = strlen( buf );
+ if ( ldif_parse_line( buf, &type, &value, &len ) < 0 ) {
Debug( LDAP_DEBUG_ANY,
"Error: Re_parse: malformed replog file\n",
0, 0, 0 );
*p++ = '\0';
}
re->re_timestamp = strdup( value );
- if ( p != NULL && isdigit( *p )) {
+ if ( p != NULL && isdigit( (unsigned char) *p )) {
re->re_seq = atoi( p );
}
state |= GOT_TIME;
break;
case T_DN:
- re->re_dn = strdup( value );
+ re->re_dn = ch_malloc( len + 1 );
+ memcpy( re->re_dn, value, len );
+ re->re_dn[ len ]='\0';
state |= GOT_DN;
break;
default:
}
for (;;) {
- if (( buf = str_getline( &rp )) == NULL ) {
+ if (( buf = ldif_getline( &rp )) == NULL ) {
break;
}
- buflen = ( long ) strlen( buf );
+ buflen = strlen( buf );
if (( buflen == 1 ) && ( buf[ 0 ] == '-' )) {
type = "-";
value = NULL;
} else {
- if ( str_parse_line( buf, &type, &value, &len ) < 0 ) {
+ if ( ldif_parse_line( buf, &type, &value, &len ) < 0 ) {
Debug( LDAP_DEBUG_ANY,
"Error: malformed replog line \"%s\"\n",
buf, 0, 0 );
sizeof( Mi ) * ( nml + 2 ));
re->re_mods[ nml ].mi_type = strdup( type );
if ( value != NULL ) {
- re->re_mods[ nml ].mi_val = strdup( value );
+ re->re_mods[ nml ].mi_val = ch_malloc( len + 1 );
+ memcpy( re->re_mods[ nml ].mi_val, value, len );
+ re->re_mods[ nml ].mi_val[ len ] = '\0';
re->re_mods[ nml ].mi_len = len;
} else {
re->re_mods[ nml ].mi_val = NULL;
char **r_rp
)
{
- char buf[ LINE_WIDTH + 1 ];
+ char buf[ LDIF_LINE_WIDTH + 1 ];
char *type, *value, *line, *p;
Rh *rh = NULL;
- int nreplicas, len;
+ int nreplicas;
+ ber_len_t len;
int port;
int repl_ok;
int i;
for (;;) {
/* If this is a reject log, we need to skip over the ERROR: line */
if ( !strncmp( *r_rp, ERROR_STR, strlen( ERROR_STR ))) {
- line = str_getline( r_rp );
+ line = ldif_getline( r_rp );
if ( line == NULL ) {
break;
}
if ( strncasecmp( *r_rp, "replica:", 7 )) {
break;
}
- line = str_getline( r_rp );
+ line = ldif_getline( r_rp );
if ( line == NULL ) {
break;
}
- if ( str_parse_line( line, &type, &value, &len ) < 0 ) {
+ if ( ldif_parse_line( line, &type, &value, &len ) < 0 ) {
return( NULL );
}
- port = LDAP_PORT;
+ port = 0;
if (( p = strchr( value, ':' )) != NULL ) {
*p = '\0';
p++;
int i;
char *s;
int rc = 0;
- Rh *rh;
if ( re == NULL || fp == NULL ) {
Debug( LDAP_DEBUG_ANY, "Internal error: Re_write: NULL argument\n",
}
} else {
char *obuf;
- obuf = ldif_type_and_value( re->re_mods[ i ].mi_type,
+ obuf = ldif_put( LDIF_PUT_VALUE,
+ re->re_mods[ i ].mi_type,
re->re_mods[ i ].mi_val ? re->re_mods[ i ].mi_val : "",
re->re_mods[ i ].mi_len );
if ( fputs( obuf, fp ) < 0 ) {
free( obuf );
goto bad;
} else {
- free( obuf );
+ ber_memfree( obuf );
}
}
}
Re *re
)
{
- return( pthread_mutex_lock( &re->re_mutex ));
+ return( ldap_pvt_thread_mutex_lock( &re->re_mutex ));
}
Re *re
)
{
- return( pthread_mutex_unlock( &re->re_mutex ));
+ return( ldap_pvt_thread_mutex_unlock( &re->re_mutex ));
}
(*re)->re_mods = NULL;
(*re)->re_next = NULL;
- pthread_mutex_init( &((*re)->re_mutex), pthread_mutexattr_default );
+ ldap_pvt_thread_mutex_init( &((*re)->re_mutex) );
return 0;
}
#ifndef _SLURPD_H_
#define _SLURPD_H_
-#define LDAP_SYSLOG
+#ifndef LDAP_SYSLOG
+#define LDAP_SYSLOG 1
+#endif
-#include <syslog.h>
-#include <errno.h>
-#include <sys/types.h>
+#include <ac/errno.h>
+#include <ac/signal.h>
+#include <ac/syslog.h>
+#include <ac/time.h>
+
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
-#include "lber.h"
-#include "ldap.h"
-#include "lthread.h"
-#include "portable.h"
-#include "ldapconfig.h"
+#endif
+#include <sys/types.h>
+
+#include <ldap.h>
+
+#undef ldap_debug
+#define ldap_debug slurp_debug
+#include "ldap_log.h"
+
+#include "ldap_pvt_thread.h"
+#include "ldap_defaults.h"
#include "ldif.h"
#define T_DELETECTSTR "delete"
#define T_DELETECT 6
#define T_MODRDNCTSTR "modrdn"
+#define T_MODDNCTSTR "moddn"
+#define T_RENAMECTSTR "rename"
#define T_MODRDNCT 7
#define T_MODOPADDSTR "add"
#define T_MODSEP 11
#define T_NEWRDNSTR "newrdn"
-#define T_DRDNFLAGSTR "deleteoldrdn"
+#define T_DELOLDRDNSTR "deleteoldrdn"
+#define T_NEWSUPSTR "newsuperior"
#define T_ERR -1
#define RETRY_SLEEP_TIME 60
+LDAP_BEGIN_DECL
/*
* ****************************************************************************
* Notes:
* - Private data should not be manipulated expect by Ri member functions.
*/
-typedef struct ri {
+typedef struct ri Ri;
+struct ri {
/* Private data */
char *ri_hostname; /* canonical hostname of replica */
struct stel *ri_stel; /* pointer to Stel for this replica */
unsigned long
ri_seq; /* seq number of last repl */
- pthread_t ri_tid; /* ID of thread for this replica */
+ ldap_pvt_thread_t ri_tid; /* ID of thread for this replica */
/* Member functions */
- int (*ri_process)(); /* process the next repl entry */
- void (*ri_wake)(); /* wake up a sleeping thread */
-} Ri;
+ int (*ri_process) LDAP_P(( Ri * )); /* process the next repl entry */
+ void (*ri_wake) LDAP_P(( Ri * )); /* wake up a sleeping thread */
+};
-
/*
* Information about one particular replication entry. Only routines in
* re.c and rq.c should touch the private data. Other routines should
* only use member functions.
*/
-typedef struct re {
+typedef struct re Re;
+struct re {
/* Private data */
- pthread_mutex_t
+ ldap_pvt_thread_mutex_t
re_mutex; /* mutex for this Re */
int re_refcnt; /* ref count, 0 = done */
char *re_timestamp; /* timestamp of this re */
struct re *re_next; /* pointer to next element */
/* Public functions */
- int (*re_free)(); /* free an re struct */
- struct re *(*re_getnext)(); /* return next Re in linked list */
- int (*re_parse)(); /* parse a replication log entry */
- int (*re_write)(); /* write a replication log entry */
- void (*re_dump)(); /* debugging - print contents */
- int (*re_lock)(); /* lock this re */
- int (*re_unlock)(); /* unlock this re */
- int (*re_decrefcnt)(); /* decrement the refcnt */
- int (*re_getrefcnt)(); /* get the refcnt */
-} Re;
+ int (*re_free) LDAP_P(( Re * )); /* free an re struct */
+ Re *(*re_getnext) LDAP_P(( Re * )); /* return next Re in linked list */
+ int (*re_parse) LDAP_P(( Re *, char * )); /* parse replication log entry */
+ int (*re_write) LDAP_P(( Ri *, Re *, FILE * )); /* write repl. log entry */
+ void (*re_dump) LDAP_P(( Re *, FILE * )); /* debugging - print contents */
+ int (*re_lock) LDAP_P(( Re * )); /* lock this re */
+ int (*re_unlock) LDAP_P(( Re * )); /* unlock this re */
+ int (*re_decrefcnt) LDAP_P(( Re * )); /* decrement the refcnt */
+ int (*re_getrefcnt) LDAP_P(( Re * )); /* get the refcnt */
+};
* variable so routines in ri.c can use it as a mutex for the
* rq_more condition variable.
*/
-typedef struct rq {
+typedef struct rq Rq;
+struct rq {
/* Private data */
Re *rq_head; /* pointer to head */
time_t rq_lasttrim; /* Last time we trimmed file */
/* Public data */
- pthread_mutex_t
+ ldap_pvt_thread_mutex_t
rq_mutex; /* mutex for whole queue */
- pthread_cond_t
+ ldap_pvt_thread_cond_t
rq_more; /* condition var - more work added */
/* Member functions */
- Re *(*rq_gethead)(); /* get the element at head */
- Re *(*rq_getnext)(); /* get the next element */
- int (*rq_delhead)(); /* delete the element at head */
- int (*rq_add)(); /* add at tail */
- void (*rq_gc)(); /* garbage-collect queue */
- int (*rq_lock)(); /* lock the queue */
- int (*rq_unlock)(); /* unlock the queue */
- int (*rq_needtrim)(); /* see if queue needs trimming */
- int (*rq_write)(); /* write Rq contents to a file */
- int (*rq_getcount)(); /* return queue counts */
- void (*rq_dump)(); /* debugging - print contents */
-} Rq;
-
+ Re * (*rq_gethead) LDAP_P(( Rq * )); /* get the element at head */
+ Re * (*rq_getnext) LDAP_P(( Re * )); /* get the next element */
+ int (*rq_delhead) LDAP_P(( Rq * )); /* delete the element at head */
+ int (*rq_add) LDAP_P(( Rq *, char * )); /* add at tail */
+ void (*rq_gc) LDAP_P(( Rq * )); /* garbage-collect queue */
+ int (*rq_lock) LDAP_P(( Rq * )); /* lock the queue */
+ int (*rq_unlock) LDAP_P(( Rq * )); /* unlock the queue */
+ int (*rq_needtrim) LDAP_P(( Rq * )); /* see if queue needs trimming */
+ int (*rq_write) LDAP_P(( Rq *, FILE * )); /*write Rq contents to file*/
+ int (*rq_getcount) LDAP_P(( Rq *, int )); /* return queue counts */
+ void (*rq_dump) LDAP_P(( Rq * )); /* debugging - print contents */
+};
/*
* if present, uses the timestamps to avoid "replaying" replications
* which have already been sent to a given replica.
*/
-typedef struct st {
-
+typedef struct st St;
+struct st {
/* Private data */
- pthread_mutex_t
+ ldap_pvt_thread_mutex_t
st_mutex; /* mutex to serialize access */
Stel **st_data; /* array of pointers to Stel structs */
int st_nreplicas; /* number of repl hosts */
FILE *st_lfp; /* lockfile fp */
/* Public member functions */
- int (*st_update)(); /* update the entry for a host */
- Stel *(*st_add)(); /* add a new repl host */
- int (*st_write)(); /* write status to disk */
- int (*st_read)(); /* read status info from disk */
- int (*st_lock)(); /* read status info from disk */
- int (*st_unlock)(); /* read status info from disk */
-} St;
-
-#if defined( THREAD_SUNOS4_LWP )
+ int (*st_update) LDAP_P(( St *, Stel*, Re* ));/*update entry for a host*/
+ Stel*(*st_add) LDAP_P(( St *, Ri * )); /*add a new repl host*/
+ int (*st_write) LDAP_P(( St * )); /* write status to disk */
+ int (*st_read) LDAP_P(( St * )); /* read status info from disk */
+ int (*st_lock) LDAP_P(( St * )); /* read status info from disk */
+ int (*st_unlock) LDAP_P(( St * )); /* read status info from disk */
+};
+
+#if defined( HAVE_LWP )
typedef struct tl {
thread_t tl_tid; /* thread being managed */
time_t tl_wake; /* time thread should be resumed */
tl_t *tsl_list;
mon_t tsl_mon;
} tsl_t;
-#endif /* THREAD_SUNOS4_LWP */
-
-
+#endif /* HAVE_LWP */
/*
* Public functions used to instantiate and initialize queue objects.
*/
-#ifdef NEEDPROTOS
-extern int Ri_init( Ri **ri );
-extern int Rq_init( Rq **rq );
-extern int Re_init( Re **re );
-#else /* NEEDPROTOS */
-extern int Ri_init();
-extern int Rq_init();
-extern int Re_init();
-#endif /* NEEDPROTOS */
+extern int Ri_init LDAP_P(( Ri **ri ));
+extern int Rq_init LDAP_P(( Rq **rq ));
+extern int Re_init LDAP_P(( Re **re ));
-#endif /* _SLURPD_H_ */
+#include "proto-slurp.h"
+
+LDAP_END_DECL
+#endif /* _SLURPD_H_ */
--- /dev/null
+## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+##
+## tests Makefile.in for OpenLDAP
+SUBDIRS= progs
+
+BUILD_BDB2 = @BUILD_BDB2@
+
+test: tests
+tests: bdb2 ldbm
+
+bdb2: test-bdb2
+test-bdb2: FORCE
+ @-$(LN_S) $(srcdir)/data .
+ @if test "$(BUILD_BDB2)" = "yes" ; then \
+ echo "Initiating LDAP tests..." ; \
+ $(MKDIR) test-db test-repl || true; \
+ $(srcdir)/scripts/all $(srcdir) bdb2 ; \
+ else \
+ echo "run configure with --enable-bdb2" ; \
+ fi
+
+ldbm: test-ldbm
+test-ldbm: FORCE
+ @-$(LN_S) $(srcdir)/data .
+ @echo "Initiating LDAP tests..."
+ @-$(MKDIR) test-db test-repl || true
+ @$(srcdir)/scripts/all $(srcdir) ldbm
+
+passwd: test-passwd
+test-passwd: FORCE
+ @-$(LN_S) $(srcdir)/data .
+ @echo "Initiating LDAP tests..."
+ @-$(MKDIR) test-db test-repl || true
+ @$(srcdir)/scripts/passwd-search $(srcdir) passwd
+
+test-nis-schema: test-nis-schema-ldbm
+test-nis-schema-ldbm:
+ @-$(LN_S) $(srcdir)/data .
+ @echo "Initiating LDAP server with NIS schema & ldbm backend..."; \
+ $(MKDIR) test-db test-repl ; \
+ $(srcdir)/scripts/startup_nis_ldap_server.sh $(srcdir) ldbm
+
+test-nis-schema-bdb2:
+ @-$(LN_S) $(srcdir)/data .
+ @echo "Initiating LDAP server with NIS schema & DB2 backend..."; \
+ @if test "$(BUILD_BDB2)" = "yes" ; then \
+ echo "Initiating LDAP tests..." ; \
+ $(MKDIR) test-db test-repl ; \
+ $(srcdir)/scripts/startup_nis_ldap_server.sh $(srcdir) bdb2 ; \
+ else \
+ echo "run configure with --enable-bdb2" ; \
+ fi
+
+clean-local: FORCE
+ -$(RM) test-db/[!C]* test-repl/[!C]* *leak *gmon *core
+
+veryclean-local: FORCE
+ @-$(RM) data
+ $(RM) -r test-db test-repl
+
title: Mad Cow Researcher, UM Alumni Association
pager: +1 313 555 3923
mail: jaj@mail.alumni.umich.edu
-modifytimestamp: 960404171231Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
facsimiletelephonenumber: +1 313 555 4332
telephonenumber: +1 313 555 0895
dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US
mail: bjensen@mailgw.umich.edu
homepostaladdress: 123 Wesley $ Ann Arbor, MI 48103
krbname: bjensen@umich.edu
-multilinedescription: Mythical manager of the rsdd unix project
+multilinedescription: Mythical manager of the rsdd unix project
nobatchupdates: TRUE
notice: Off sailing this month.
onvacation: FALSE
labeledurl: http://www.umich.edu/ U-M Home Page
drink: water
-lastmodifiedtime: 960404035839Z
-lastmodifiedby: cn=Barbara Jensen, ou=Information Technology Division, ou=Peop
- le, o=University of Michigan, c=US
homephone: +1 313 555 2333
pager: +1 313 555 3233
facsimiletelephonenumber: +1 313 555 2274
objectclass: quipuObject
objectclass: quipuNonLeafObject
ou: Groups
-lastmodifiedtime: 950120182331Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
dn: ou=Information Technology Division, ou=People, o=University of Michigan, c
=US
member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of
Michigan, c=US
labeledurl: http://www.itd.umich.edu ITD Home Page
- University of Michigan,c=US
telephonenumber: +1 810 555 1212
dn: cn=James A Jones 2, ou=Information Technology Division, ou=People, o=Unive
cn: Dir Man
sn: Manager
description: Manager of the directory
-lastmodifiedtime: 951212214144Z
-lastmodifiedby: cn=Manager, o=University of Michigan, c=US
krbname: bjensen@umich.edu
dn: ou=People, o=University of Michigan, c=US
o: U of M
description: The University of Michigan at Ann Arbor
postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
- 09 $ USpostalcode: 48109
+ 09 $ US
telephonenumber: +1 313 764-1817
-lastmodifiedtime: 930106182800Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
associateddomain: umich.edu
--- /dev/null
+cn=James A Jones 2, ou=Alumni Association, ou=People, o=University of Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: James A Jones 2
+cn: James Jones
+cn: Jim Jones
+sn: Jones
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jaj
+krbname: jaj@umich.edu
+userpassword:: amFq
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
+homephone: +1 313 555 4772
+multilinedescription: Outstanding
+title: Mad Cow Researcher, UM Alumni Association
+pager: +1 313 555 3923
+mail: jaj@mail.alumni.umich.edu
+facsimiletelephonenumber: +1 313 555 4332
+telephonenumber: +1 313 555 0895
+
joinable: FALSE
multilinedescription: Everyone in the sample data
objectclass: rfc822mailgroup
-modifiersname: cn=Manager,o=University of Michigan,c=US
dn: cn=Alumni Assoc Staff,ou=Groups,o=University of Michigan,c=US
member: cn=Manager, o=University of Michigan, c=US
Arbor, MI 48103-4943
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: bjensen
-userpassword: bjensen
+userpassword:: YmplbnNlbg==
mail: bjensen@mailgw.umich.edu
homepostaladdress: 123 Wesley $ Ann Arbor, MI 48103
krbname: bjensen@umich.edu
-multilinedescription: Mythical manager of the rsdd unix project
+multilinedescription: Mythical manager of the rsdd unix project
nobatchupdates: TRUE
notice: Off sailing this month.
onvacation: FALSE
labeledurl: http://www.umich.edu/ U-M Home Page
drink: water
-lastmodifiedtime: 960404035839Z
-lastmodifiedby: cn=Barbara Jensen, ou=Information Technology Division, ou=Peop
- le, o=University of Michigan, c=US
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 2333
pager: +1 313 555 3233
facsimiletelephonenumber: +1 313 555 2274
sn: Jensen
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: bjorn
-userpassword: bjorn
+userpassword:: Ympvcm4=
krbname: jdoe@umich.edu
nobatchupdates: TRUE
onvacation: FALSE
pager: +1 313 555 4474
facsimiletelephonenumber: +1 313 555 2177
telephonenumber: +1 313 555 0355
-modifiersname: cn=Manager,o=University of Michigan,c=US
multilinedescription: The replaced multiLineDescription $ Blah Woof.
drink: Iced Tea
drink: Mad Dog 20/20
facsimiletelephonenumber: +1 313 555 3223
telephonenumber: +1 313 555 3664
mail: dots@mail.alumni.umich.edu
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 0454
dn: cn=Gern Jensen, ou=Information Technology Division, ou=People, o=Universit
telephonenumber: +1 313 555 8343
mail: gjensen@mailgw.umich.edu
homephone: +1 313 555 8844
-creatorsname: cn=Manager,o=University of Michigan,c=US
dn: ou=Groups, o=University of Michigan, c=US
objectclass: top
objectclass: quipuObject
objectclass: quipuNonLeafObject
ou: Groups
-lastmodifiedtime: 950120182331Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
dn: ou=Information Technology Division, ou=People, o=University of Michigan, c
=US
member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of
Michigan, c=US
labeledurl: http://www.itd.umich.edu ITD Home Page
-modifiersname: cn=Manager,o=University of Michigan,c=US
dn: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Mich
igan, c=US
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: jaj
krbname: jaj@umich.edu
-userpassword: jaj
+userpassword:: amFq
nobatchupdates: TRUE
onvacation: FALSE
homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
mail: jaj@mail.alumni.umich.edu
facsimiletelephonenumber: +1 313 555 4332
telephonenumber: +1 313 555 0895
-modifiersname: cn=Manager,o=University of Michigan,c=US
drink: Orange Juice
dn: cn=Jane Doe, ou=Alumni Association, ou=People, o=University of Michigan, c
drink: diet coke
multilinedescription: Enthusiastic
mail: jdoe@woof.net
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 5445
pager: +1 313 555 1220
facsimiletelephonenumber: +1 313 555 2311
homepostaladdress: 1000 Maple #44 $ Ann Arbor, MI 48103
title: Telemarketer, UM Alumni Association
mail: jen@mail.alumni.umich.edu
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 2333
pager: +1 313 555 6442
facsimiletelephonenumber: +1 313 555 2756
title: System Administrator, Information Technology Division
multilinedescription: overworked!
mail: johnd@mailgw.umich.edu
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 3774
pager: +1 313 555 6573
facsimiletelephonenumber: +1 313 555 4544
cn: Dir Man
sn: Manager
description: Manager of the directory
-userpassword: secret
-lastmodifiedtime: 951212214144Z
-lastmodifiedby: cn=Manager, o=University of Michigan, c=US
+userpassword:: c2VjcmV0
krbname: bjensen@umich.edu
dn: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Michigan
drink: Gasoline
title: Director, UM Alumni Association
mail: melliot@mail.alumni.umich.edu
-modifiersname: cn=Manager,o=University of Michigan,c=US
pager: +1 313 555 7671
facsimiletelephonenumber: +1 313 555 7762
telephonenumber: +1 313 555 4177
o: U of M
description: The University of Michigan at Ann Arbor
postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
- 09 $ USpostalcode: 48109
+ 09 $ US
telephonenumber: +1 313 764-1817
-lastmodifiedtime: 930106182800Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
associateddomain: umich.edu
dn: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of Mich
nobatchupdates: TRUE
onvacation: FALSE
mail: uham@mail.alumni.umich.edu
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 8421
pager: +1 313 555 2844
facsimiletelephonenumber: +1 313 555 9700
--- /dev/null
+dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+member: cn=Manager, o=University of Michigan, c=US
+member: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=Un
+ iversity of Michigan, c=US
+member: cn=Jane Doe, ou=Alumni Association, ou=People, o=University of Michiga
+ n, c=US
+member: cn=John Doe, ou=Information Technology Division, ou=People, o=Universi
+ ty of Michigan, c=US
+member: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Mich
+ igan, c=US
+member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=James A Jones 2, ou=Information Technology Division, ou=People, o=U
+ niversity of Michigan, c=US
+member: cn=Jennifer Smith, ou=Alumni Association, ou=People, o=University of M
+ ichigan, c=US
+member: cn=Dorothy Stevens, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=Univ
+ ersity of Michigan, c=US
+associateddomain: umich.edu
+requeststo: cn=Manager, o=University of Michigan, c=US
+errorsto: cn=Manager, o=University of Michigan, c=US
+owner: cn=Manager, o=University of Michigan, c=US
+cn: All Staff
+joinable: FALSE
+multilinedescription: Everyone in the sample data
+objectclass: rfc822mailgroup
+
+dn: cn=Alumni Assoc Staff,ou=Groups,o=University of Michigan,c=US
+member: cn=Manager, o=University of Michigan, c=US
+member: cn=Dorothy Stevens, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=Jane Doe, ou=Alumni Association, ou=People, o=University of Michiga
+ n, c=US
+member: cn=Jennifer Smith, ou=Alumni Association, ou=People, o=University of M
+ ichigan, c=US
+member: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Mich
+ igan, c=US
+member: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+associateddomain: umich.edu
+requeststo: cn=Manager, o=University of Michigan, c=US
+errorsto: cn=Manager, o=University of Michigan, c=US
+owner: cn=Manager, o=University of Michigan, c=US
+multilinedescription: All Alumni Assoc Staff
+cn: Alumni Assoc Staff
+joinable: FALSE
+objectclass: rfc822mailgroup
+
+dn: ou=Alumni Association, ou=People, o=University of Michigan, c=US
+objectclass: top
+objectclass: organizationalUnit
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+ou: Alumni Association
+
+dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=Univer
+ sity of Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Barbara Jensen
+cn: Babs Jensen
+sn: Jensen
+title: Mythical Manager, Research Systems
+postaladdress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Ann
+ Arbor, MI 48103-4943
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: bjensen
+userpassword:: YmplbnNlbg==
+mail: bjensen@mailgw.umich.edu
+homepostaladdress: 123 Wesley $ Ann Arbor, MI 48103
+krbname: bjensen@umich.edu
+multilinedescription: Mythical manager of the rsdd unix project
+nobatchupdates: TRUE
+notice: Off sailing this month.
+onvacation: FALSE
+labeledurl: http://www.umich.edu/ U-M Home Page
+drink: water
+homephone: +1 313 555 2333
+pager: +1 313 555 3233
+facsimiletelephonenumber: +1 313 555 2274
+telephonenumber: +1 313 555 9022
+
+dn: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=Universi
+ ty of Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Bjorn Jensen
+cn: Biiff Jensen
+sn: Jensen
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: bjorn
+userpassword:: Ympvcm4=
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
+drink: Iced Tea
+multilinedescription: Hiker, biker
+title: Director, Embedded Systems
+postaladdress: Info Tech Division $ 535 W. William St. $ Ann Arbor, MI 48103
+mail: bjorn@mailgw.umich.edu
+homephone: +1 313 555 5444
+pager: +1 313 555 4474
+facsimiletelephonenumber: +1 313 555 2177
+telephonenumber: +1 313 555 0355
+
+dn: cn=Dorothy Stevens, ou=Alumni Association, ou=People, o=University of Mich
+ igan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Dorothy Stevens
+cn: Dot Stevens
+sn: Stevens
+title: Secretary, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: dots
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+drink: Lemonade
+homepostaladdress: 377 White St. Apt. 3 $ Ann Arbor, MI 48104
+multilinedescription: Very tall
+facsimiletelephonenumber: +1 313 555 3223
+telephonenumber: +1 313 555 3664
+mail: dots@mail.alumni.umich.edu
+homephone: +1 313 555 0454
+
+dn: ou=Groups, o=University of Michigan, c=US
+objectclass: top
+objectclass: organizationalUnit
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+ou: Groups
+
+dn: ou=Information Technology Division, ou=People, o=University of Michigan, c
+ =US
+objectclass: top
+objectclass: organizationalUnit
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+ou: Information Technology Divisio
+
+dn: cn=ITD Staff,ou=Groups,o=University of Michigan,c=US
+associateddomain: umich.edu
+requeststo: cn=Manager, o=University of Michigan, c=US
+errorsto: cn=Manager, o=University of Michigan, c=US
+owner: cn=Manager, o=University of Michigan, c=US
+multilinedescription: All ITD Staff
+cn: ITD Staff
+joinable: FALSE
+objectclass: rfc822mailgroup
+member: cn=Manager, o=University of Michigan, c=US
+member: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=Univ
+ ersity of Michigan, c=US
+member: cn=James A Jones 2, ou=Information Technology Division, ou=People, o=U
+ niversity of Michigan, c=US
+member: cn=John Doe, ou=Information Technology Division, ou=People, o=Universi
+ ty of Michigan, c=US
+labeledurl: http://www.itd.umich.edu ITD Home Page
+
+dn: cn=James A Jones II, ou=Information Technology Division, ou=People, o=Univ
+ ersity of Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: James Jones
+cn: Jim Jones
+cn: James A Jones II
+sn: Doe
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jjones
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 933 Brooks $ Ann Arbor, MI 48104
+homephone: +1 313 555 8838
+title: Senior Manager, Information Technology Division
+multilinedescription: Not around very much
+mail: jjones@mailgw.umich.edu
+postaladdress: Info Tech Division $ 535 W William $ Ann Arbor, MI 48103
+pager: +1 313 555 2833
+facsimiletelephonenumber: +1 313 555 8688
+telephonenumber: +1 313 555 7334
+
+dn: cn=James A Jones III, ou=Alumni Association, ou=People, o=University of Mi
+ chigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: James A Jones 1
+cn: James Jones
+cn: Jim Jones
+cn: James A Jones III
+sn: Jones
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jaj
+krbname: jaj@umich.edu
+userpassword:: amFq
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
+homephone: +1 313 555 4772
+multilinedescription: Outstanding
+title: Mad Cow Researcher, UM Alumni Association
+pager: +1 313 555 3923
+mail: jaj@mail.alumni.umich.edu
+facsimiletelephonenumber: +1 313 555 4332
+telephonenumber: +1 313 555 0895
+
+dn: cn=Jane Doe, ou=Alumni Association, ou=People, o=University of Michigan, c
+ =US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Jane Doe
+cn: Jane Alverson
+sn: Doe
+title: Programmer Analyst, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jdoe
+homepostaladdress: 123 Anystreet $ Ann Arbor, MI 48104
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+drink: diet coke
+multilinedescription: Enthusiastic
+mail: jdoe@woof.net
+homephone: +1 313 555 5445
+pager: +1 313 555 1220
+facsimiletelephonenumber: +1 313 555 2311
+telephonenumber: +1 313 555 4774
+
+dn: cn=Jennifer Smith, ou=Alumni Association, ou=People, o=University of Michi
+ gan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Jennifer Smith
+cn: Jen Smith
+sn: Smith
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jen
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+drink: Sam Adams
+homepostaladdress: 1000 Maple #44 $ Ann Arbor, MI 48103
+title: Telemarketer, UM Alumni Association
+mail: jen@mail.alumni.umich.edu
+homephone: +1 313 555 2333
+pager: +1 313 555 6442
+facsimiletelephonenumber: +1 313 555 2756
+telephonenumber: +1 313 555 8232
+
+dn: cn=John Doe, ou=Information Technology Division, ou=People, o=University o
+ f Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: John Doe
+cn: Jonathon Doe
+sn: Doe
+postaladdress: ITD $ 535 W. William $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: johnd
+krbname: johnd@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 912 East Bllvd $ Ann Arbor, MI 48104
+title: System Administrator, Information Technology Division
+multilinedescription: overworked!
+mail: johnd@mailgw.umich.edu
+homephone: +1 313 555 3774
+pager: +1 313 555 6573
+facsimiletelephonenumber: +1 313 555 4544
+telephonenumber: +1 313 555 9394
+
+dn: cn=Manager, o=University of Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: quipuObject
+objectclass: kerberosSecurityObject
+cn: Manager
+cn: Directory Manager
+cn: Dir Man
+sn: Manager
+description: Manager of the directory
+userpassword:: c2VjcmV0
+krbname: bjensen@umich.edu
+
+dn: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Michigan
+ , c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Mark Elliot
+cn: Mark A Elliot
+sn: Elliot
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: melliot
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 199 Outer Drive $ Ypsilanti, MI 48198
+homephone: +1 313 555 0388
+drink: Gasoline
+title: Director, UM Alumni Association
+mail: melliot@mail.alumni.umich.edu
+pager: +1 313 555 7671
+facsimiletelephonenumber: +1 313 555 7762
+telephonenumber: +1 313 555 4177
+
+dn: ou=People, o=University of Michigan, c=US
+objectclass: top
+objectclass: organizationalUnit
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+ou: People
+
+dn: o=University of Michigan, c=US
+objectclass: top
+objectclass: organization
+objectclass: domainRelatedObject
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+l: Ann Arbor, Michigan
+st: Michigan
+streetaddress: 535 West William St.
+o: University of Michigan
+o: UMICH
+o: UM
+o: U-M
+o: U of M
+description: The University of Michigan at Ann Arbor
+postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
+ 09 $ US
+telephonenumber: +1 313 764-1817
+associateddomain: umich.edu
+
+dn: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of Mich
+ igan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Ursula Hampster
+sn: Hampster
+title: Secretary, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: uham
+homepostaladdress: 123 Anystreet $ Ann Arbor, MI 48104
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+mail: uham@mail.alumni.umich.edu
+homephone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimiletelephonenumber: +1 313 555 9700
+telephonenumber: +1 313 555 5331
--- /dev/null
+dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+member: cn=Manager, o=University of Michigan, c=US
+member: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=Un
+ iversity of Michigan, c=US
+member: cn=Jane Doe, ou=Alumni Association, ou=People, o=University of Michiga
+ n, c=US
+member: cn=John Doe, ou=Information Technology Division, ou=People, o=Universi
+ ty of Michigan, c=US
+member: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Mich
+ igan, c=US
+member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=James A Jones 2, ou=Information Technology Division, ou=People, o=U
+ niversity of Michigan, c=US
+member: cn=Jennifer Smith, ou=Alumni Association, ou=People, o=University of M
+ ichigan, c=US
+member: cn=Dorothy Stevens, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=Univ
+ ersity of Michigan, c=US
+associateddomain: umich.edu
+requeststo: cn=Manager, o=University of Michigan, c=US
+errorsto: cn=Manager, o=University of Michigan, c=US
+owner: cn=Manager, o=University of Michigan, c=US
+cn: All Staff
+joinable: FALSE
+multilinedescription: Everyone in the sample data
+objectclass: rfc822mailgroup
+
+dn: cn=Alumni Assoc Staff,ou=Groups,o=University of Michigan,c=US
+member: cn=Manager, o=University of Michigan, c=US
+member: cn=Dorothy Stevens, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+member: cn=Jane Doe, ou=Alumni Association, ou=People, o=University of Michiga
+ n, c=US
+member: cn=Jennifer Smith, ou=Alumni Association, ou=People, o=University of M
+ ichigan, c=US
+member: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Mich
+ igan, c=US
+member: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of
+ Michigan, c=US
+associateddomain: umich.edu
+requeststo: cn=Manager, o=University of Michigan, c=US
+errorsto: cn=Manager, o=University of Michigan, c=US
+owner: cn=Manager, o=University of Michigan, c=US
+multilinedescription: All Alumni Assoc Staff
+cn: Alumni Assoc Staff
+joinable: FALSE
+objectclass: rfc822mailgroup
+
+dn: ou=Alumni Association, ou=People, o=University of Michigan, c=US
+objectclass: top
+objectclass: organizationalUnit
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+ou: Alumni Association
+
+dn: cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=Univer
+ sity of Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Barbara Jensen
+cn: Babs Jensen
+sn: Jensen
+title: Mythical Manager, Research Systems
+postaladdress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Ann
+ Arbor, MI 48103-4943
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: bjensen
+userpassword:: YmplbnNlbg==
+mail: bjensen@mailgw.umich.edu
+homepostaladdress: 123 Wesley $ Ann Arbor, MI 48103
+krbname: bjensen@umich.edu
+multilinedescription: Mythical manager of the rsdd unix project
+nobatchupdates: TRUE
+notice: Off sailing this month.
+onvacation: FALSE
+labeledurl: http://www.umich.edu/ U-M Home Page
+drink: water
+homephone: +1 313 555 2333
+pager: +1 313 555 3233
+facsimiletelephonenumber: +1 313 555 2274
+telephonenumber: +1 313 555 9022
+
+dn: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=Universi
+ ty of Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Bjorn Jensen
+cn: Biiff Jensen
+sn: Jensen
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: bjorn
+userpassword:: Ympvcm4=
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
+drink: Iced Tea
+multilinedescription: Hiker, biker
+title: Director, Embedded Systems
+postaladdress: Info Tech Division $ 535 W. William St. $ Ann Arbor, MI 48103
+mail: bjorn@mailgw.umich.edu
+homephone: +1 313 555 5444
+pager: +1 313 555 4474
+facsimiletelephonenumber: +1 313 555 2177
+telephonenumber: +1 313 555 0355
+
+dn: cn=Dorothy Stevens, ou=Alumni Association, ou=People, o=University of Mich
+ igan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Dorothy Stevens
+cn: Dot Stevens
+sn: Stevens
+title: Secretary, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: dots
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+drink: Lemonade
+homepostaladdress: 377 White St. Apt. 3 $ Ann Arbor, MI 48104
+multilinedescription: Very tall
+facsimiletelephonenumber: +1 313 555 3223
+telephonenumber: +1 313 555 3664
+mail: dots@mail.alumni.umich.edu
+homephone: +1 313 555 0454
+
+dn: ou=Groups, o=University of Michigan, c=US
+objectclass: top
+objectclass: organizationalUnit
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+ou: Groups
+
+dn: ou=Information Technology Division, ou=People, o=University of Michigan, c
+ =US
+objectclass: top
+objectclass: organizationalUnit
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+ou: Information Technology Divisio
+
+dn: cn=ITD Staff,ou=Groups,o=University of Michigan,c=US
+associateddomain: umich.edu
+requeststo: cn=Manager, o=University of Michigan, c=US
+errorsto: cn=Manager, o=University of Michigan, c=US
+owner: cn=Manager, o=University of Michigan, c=US
+multilinedescription: All ITD Staff
+cn: ITD Staff
+joinable: FALSE
+objectclass: rfc822mailgroup
+member: cn=Manager, o=University of Michigan, c=US
+member: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=Univ
+ ersity of Michigan, c=US
+member: cn=James A Jones 2, ou=Information Technology Division, ou=People, o=U
+ niversity of Michigan, c=US
+member: cn=John Doe, ou=Information Technology Division, ou=People, o=Universi
+ ty of Michigan, c=US
+labeledurl: http://www.itd.umich.edu ITD Home Page
+
+dn: cn=James A Jones II, ou=Information Technology Division, ou=People, o=Univ
+ ersity of Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: James Jones
+cn: Jim Jones
+cn: James A Jones II
+sn: Doe
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jjones
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 933 Brooks $ Ann Arbor, MI 48104
+homephone: +1 313 555 8838
+title: Senior Manager, Information Technology Division
+multilinedescription: Not around very much
+mail: jjones@mailgw.umich.edu
+postaladdress: Info Tech Division $ 535 W William $ Ann Arbor, MI 48103
+pager: +1 313 555 2833
+facsimiletelephonenumber: +1 313 555 8688
+telephonenumber: +1 313 555 7334
+
+dn: cn=James A Jones III, ou=Alumni Association, ou=People, o=University of Mi
+ chigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: James A Jones 1
+cn: James Jones
+cn: Jim Jones
+cn: James A Jones III
+sn: Jones
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jaj
+krbname: jaj@umich.edu
+userpassword:: amFq
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
+homephone: +1 313 555 4772
+multilinedescription: Outstanding
+title: Mad Cow Researcher, UM Alumni Association
+pager: +1 313 555 3923
+mail: jaj@mail.alumni.umich.edu
+facsimiletelephonenumber: +1 313 555 4332
+telephonenumber: +1 313 555 0895
+
+dn: cn=Jane Doe, ou=Alumni Association, ou=People, o=University of Michigan, c
+ =US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Jane Doe
+cn: Jane Alverson
+sn: Doe
+title: Programmer Analyst, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jdoe
+homepostaladdress: 123 Anystreet $ Ann Arbor, MI 48104
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+drink: diet coke
+multilinedescription: Enthusiastic
+mail: jdoe@woof.net
+homephone: +1 313 555 5445
+pager: +1 313 555 1220
+facsimiletelephonenumber: +1 313 555 2311
+telephonenumber: +1 313 555 4774
+
+dn: cn=Jennifer Smith, ou=Alumni Association, ou=People, o=University of Michi
+ gan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Jennifer Smith
+cn: Jen Smith
+sn: Smith
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jen
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+drink: Sam Adams
+homepostaladdress: 1000 Maple #44 $ Ann Arbor, MI 48103
+title: Telemarketer, UM Alumni Association
+mail: jen@mail.alumni.umich.edu
+homephone: +1 313 555 2333
+pager: +1 313 555 6442
+facsimiletelephonenumber: +1 313 555 2756
+telephonenumber: +1 313 555 8232
+
+dn: cn=John Doe, ou=Information Technology Division, ou=People, o=University o
+ f Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: John Doe
+cn: Jonathon Doe
+sn: Doe
+postaladdress: ITD $ 535 W. William $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: johnd
+krbname: johnd@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 912 East Bllvd $ Ann Arbor, MI 48104
+title: System Administrator, Information Technology Division
+multilinedescription: overworked!
+mail: johnd@mailgw.umich.edu
+homephone: +1 313 555 3774
+pager: +1 313 555 6573
+facsimiletelephonenumber: +1 313 555 4544
+telephonenumber: +1 313 555 9394
+
+dn: cn=Manager, o=University of Michigan, c=US
+objectclass: top
+objectclass: person
+objectclass: quipuObject
+objectclass: kerberosSecurityObject
+cn: Manager
+cn: Directory Manager
+cn: Dir Man
+sn: Manager
+description: Manager of the directory
+userpassword:: c2VjcmV0
+krbname: bjensen@umich.edu
+
+dn: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Michigan
+ , c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Mark Elliot
+cn: Mark A Elliot
+sn: Elliot
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: melliot
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 199 Outer Drive $ Ypsilanti, MI 48198
+homephone: +1 313 555 0388
+drink: Gasoline
+title: Director, UM Alumni Association
+mail: melliot@mail.alumni.umich.edu
+pager: +1 313 555 7671
+facsimiletelephonenumber: +1 313 555 7762
+telephonenumber: +1 313 555 4177
+
+dn: ou=People, o=University of Michigan, c=US
+objectclass: top
+objectclass: organizationalUnit
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+ou: People
+
+dn: o=University of Michigan, c=US
+objectclass: top
+objectclass: organization
+objectclass: domainRelatedObject
+objectclass: quipuObject
+objectclass: quipuNonLeafObject
+l: Ann Arbor, Michigan
+st: Michigan
+streetaddress: 535 West William St.
+o: University of Michigan
+o: UMICH
+o: UM
+o: U-M
+o: U of M
+description: The University of Michigan at Ann Arbor
+postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
+ 09 $ US
+telephonenumber: +1 313 764-1817
+associateddomain: umich.edu
+
+dn: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of Mich
+ igan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: Ursula Hampster
+sn: Hampster
+title: Secretary, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: uham
+homepostaladdress: 123 Anystreet $ Ann Arbor, MI 48104
+krbname: jdoe@umich.edu
+nobatchupdates: TRUE
+onvacation: FALSE
+mail: uham@mail.alumni.umich.edu
+homephone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimiletelephonenumber: +1 313 555 9700
+telephonenumber: +1 313 555 5331
--- /dev/null
+dn: cn=James A Jones III, ou=Alumni Association, ou=People, o=University of Mi
+ chigan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: James A Jones 1
+cn: James Jones
+cn: Jim Jones
+cn: James A Jones III
+sn: Jones
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jaj
+krbname: jaj@umich.edu
+userpassword:: amFq
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
+homephone: +1 313 555 4772
+multilinedescription: Outstanding
+title: Mad Cow Researcher, UM Alumni Association
+pager: +1 313 555 3923
+mail: jaj@mail.alumni.umich.edu
+facsimiletelephonenumber: +1 313 555 4332
+telephonenumber: +1 313 555 0895
--- /dev/null
+dn: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Mich
+ igan, c=US
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: newPilotPerson
+objectclass: umichPerson
+cn: James A Jones 1
+cn: James Jones
+cn: Jim Jones
+sn: Jones
+postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
+uid: jaj
+krbname: jaj@umich.edu
+userpassword:: amFq
+nobatchupdates: TRUE
+onvacation: FALSE
+homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
+homephone: +1 313 555 4772
+multilinedescription: Outstanding
+title: Mad Cow Researcher, UM Alumni Association
+pager: +1 313 555 3923
+mail: jaj@mail.alumni.umich.edu
+facsimiletelephonenumber: +1 313 555 4332
+telephonenumber: +1 313 555 0895
--- /dev/null
+dn: c=US
+c: US
+objectclass: country
+
+dn: o=ABC, c=US
+o: ABC
+ref: ldap//hostA/o=abc,c=us HostA
+ref: ldap//hostB/o=abc,c=us HostB
+objectclass: referral
+objectclass: extensibleObject
+
+dn: o=XYZ, c=US
+o: XYZ
+ref: ldap//hostC/o=xyz,c=us HostC
+objectclass: referral
+objectclass: extensibleObject
+
+dn: o=Alias, c=US
+o: Alias
+aliasedObjectName: o=University of Michigan, c=US
+objectclass: alias
+objectclass: extensibleObject
+
+dn: o=University of Michigan, c=US
+o: University of Michigan
+objectclass: organization
+
+dn: cn=Manager, o=University of Michigan, c=US
+cn: Manager
+cn: Directory Manager
+cn: Dir Man
+sn: Manager
+description: Manager of the directory
+userpassword:: c2VjcmV0
+objectclass: person
+
+dn: cn=Alias, o=University of Michigan, c=US
+cn: Alias
+aliasedobjectname: cn=Manager, o=University of Michigan, c=US
+objectclass: extensibleObject
+
+dn: cn=Circular, o=University of Michigan, c=US
+cn: Circular
+aliasedobjectname: cn=Circular, o=University of Michigan, c=US
+objectclass: extensibleObject
+
+dn: cn=Subordinate, o=University of Michigan, c=US
+cn: Subordinate
+aliasedobjectname: cn=Subordinate, cn=Alias, o=University of Michigan, c=US
+objectclass: extensibleObject
Arbor, MI 48103-4943
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: bjensen
-userpassword: bjensen
+userpassword:: YmplbnNlbg==
mail: bjensen@mailgw.umich.edu
homepostaladdress: 123 Wesley $ Ann Arbor, MI 48103
krbname: bjensen@umich.edu
-multilinedescription: Mythical manager of the rsdd unix project
+multilinedescription: Mythical manager of the rsdd unix project
nobatchupdates: TRUE
notice: Off sailing this month.
onvacation: FALSE
labeledurl: http://www.umich.edu/ U-M Home Page
drink: water
-lastmodifiedtime: 960404035839Z
-lastmodifiedby: cn=Barbara Jensen, ou=Information Technology Division, ou=Peop
- le, o=University of Michigan, c=US
-modifytimestamp: 960404171405Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 2333
pager: +1 313 555 3233
facsimiletelephonenumber: +1 313 555 2274
sn: Jensen
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: bjorn
-userpassword: bjorn
+userpassword:: Ympvcm4=
krbname: jdoe@umich.edu
nobatchupdates: TRUE
onvacation: FALSE
title: Director, Embedded Systems
postaladdress: Info Tech Division $ 535 W. William St. $ Ann Arbor, MI 48103
mail: bjorn@mailgw.umich.edu
-modifytimestamp: 960404171424Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 5444
pager: +1 313 555 4474
facsimiletelephonenumber: +1 313 555 2177
niversity of Michigan, c=US
member: cn=John Doe, ou=Information Technology Division, ou=People, o=Universi
ty of Michigan, c=US
-modifytimestamp: 960404171730Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
labeledurl: http://www.itd.umich.edu ITD Home Page
dn: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Mich
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: jaj
krbname: jaj@umich.edu
-userpassword: jaj
+userpassword:: amFq
nobatchupdates: TRUE
onvacation: FALSE
homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
title: Mad Cow Researcher, UM Alumni Association
pager: +1 313 555 3923
mail: jaj@mail.alumni.umich.edu
-modifytimestamp: 960404171231Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
facsimiletelephonenumber: +1 313 555 4332
telephonenumber: +1 313 555 0895
dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US
objectclass: quipuObject
objectclass: quipuNonLeafObject
ou: Groups
-lastmodifiedtime: 950120182331Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
dn: ou=Information Technology Division, ou=People, o=University of Michigan, c
=US
niversity of Michigan, c=US
member: cn=John Doe, ou=Information Technology Division, ou=People, o=Universi
ty of Michigan, c=US
-modifiersname: cn=Manager,o=University of Michigan,c=US
labeledurl: http://www.itd.umich.edu ITD Home Page
dn: ou=People, o=University of Michigan, c=US
o: U of M
description: The University of Michigan at Ann Arbor
postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
- 09 $ USpostalcode: 48109
+ 09 $ US
telephonenumber: +1 313 764-1817
-lastmodifiedtime: 930106182800Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
associateddomain: umich.edu
o: U of M
description: The University of Michigan at Ann Arbor
postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
- 09 $ USpostalcode: 48109
+ 09 $ US
telephonenumber: +1 313 764-1817
-lastmodifiedtime: 930106182800Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
associateddomain: umich.edu
dn: ou=People, o=University of Michigan, c=US
objectclass: quipuObject
objectclass: quipuNonLeafObject
ou: Groups
-lastmodifiedtime: 950120182331Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
dn: ou=Alumni Association, ou=People, o=University of Michigan, c=US
objectclass: top
Arbor, MI 48103-4943
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: bjensen
-userpassword: bjensen
+userpassword:: YmplbnNlbg==
mail: bjensen@mailgw.umich.edu
homepostaladdress: 123 Wesley $ Ann Arbor, MI 48103
krbname: bjensen@umich.edu
-multilinedescription: Mythical manager of the rsdd unix project
+multilinedescription: Mythical manager of the rsdd unix project
nobatchupdates: TRUE
notice: Off sailing this month.
onvacation: FALSE
labeledurl: http://www.umich.edu/ U-M Home Page
drink: water
-lastmodifiedtime: 960404035839Z
-lastmodifiedby: cn=Barbara Jensen, ou=Information Technology Division, ou=Peop
- le, o=University of Michigan, c=US
-modifytimestamp: 960404171405Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 2333
pager: +1 313 555 3233
facsimiletelephonenumber: +1 313 555 2274
sn: Jensen
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: bjorn
-userpassword: bjorn
+userpassword:: Ympvcm4=
krbname: jdoe@umich.edu
nobatchupdates: TRUE
onvacation: FALSE
title: Director, Embedded Systems
postaladdress: Info Tech Division $ 535 W. William St. $ Ann Arbor, MI 48103
mail: bjorn@mailgw.umich.edu
-modifytimestamp: 960404171424Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 5444
pager: +1 313 555 4474
facsimiletelephonenumber: +1 313 555 2177
facsimiletelephonenumber: +1 313 555 3223
telephonenumber: +1 313 555 3664
mail: dots@mail.alumni.umich.edu
-modifytimestamp: 960404171218Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 0454
dn: cn=ITD Staff,ou=Groups,o=University of Michigan,c=US
niversity of Michigan, c=US
member: cn=John Doe, ou=Information Technology Division, ou=People, o=Universi
ty of Michigan, c=US
-modifytimestamp: 960404171730Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
labeledurl: http://www.itd.umich.edu ITD Home Page
dn: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Mich
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: jaj
krbname: jaj@umich.edu
-userpassword: jaj
+userpassword:: amFq
nobatchupdates: TRUE
onvacation: FALSE
homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
title: Mad Cow Researcher, UM Alumni Association
pager: +1 313 555 3923
mail: jaj@mail.alumni.umich.edu
-modifytimestamp: 960404171231Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
facsimiletelephonenumber: +1 313 555 4332
telephonenumber: +1 313 555 0895
multilinedescription: Not around very much
mail: jjones@mailgw.umich.edu
postaladdress: Info Tech Division $ 535 W William $ Ann Arbor, MI 48103
-modifytimestamp: 960404171442Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
pager: +1 313 555 2833
facsimiletelephonenumber: +1 313 555 8688
telephonenumber: +1 313 555 7334
drink: diet coke
multilinedescription: Enthusiastic
mail: jdoe@woof.net
-modifytimestamp: 960404171249Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 5445
pager: +1 313 555 1220
facsimiletelephonenumber: +1 313 555 2311
homepostaladdress: 1000 Maple #44 $ Ann Arbor, MI 48103
title: Telemarketer, UM Alumni Association
mail: jen@mail.alumni.umich.edu
-modifytimestamp: 960404171309Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 2333
pager: +1 313 555 6442
facsimiletelephonenumber: +1 313 555 2756
title: System Administrator, Information Technology Division
multilinedescription: overworked!
mail: johnd@mailgw.umich.edu
-modifytimestamp: 960404171509Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 3774
pager: +1 313 555 6573
facsimiletelephonenumber: +1 313 555 4544
cn: Dir Man
sn: Manager
description: Manager of the directory
-userpassword: secret
-lastmodifiedtime: 951212214144Z
-lastmodifiedby: cn=Manager, o=University of Michigan, c=US
+userpassword:: c2VjcmV0
krbname: bjensen@umich.edu
dn: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Michigan
drink: Gasoline
title: Director, UM Alumni Association
mail: melliot@mail.alumni.umich.edu
-modifytimestamp: 960404171327Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
pager: +1 313 555 7671
facsimiletelephonenumber: +1 313 555 7762
telephonenumber: +1 313 555 4177
nobatchupdates: TRUE
onvacation: FALSE
mail: uham@mail.alumni.umich.edu
-modifytimestamp: 960404171346Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 8421
pager: +1 313 555 2844
facsimiletelephonenumber: +1 313 555 9700
Arbor, MI 48103-4943
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: bjensen
-userpassword: bjensen
+userpassword:: YmplbnNlbg==
mail: bjensen@mailgw.umich.edu
homepostaladdress: 123 Wesley $ Ann Arbor, MI 48103
krbname: bjensen@umich.edu
-multilinedescription: Mythical manager of the rsdd unix project
+multilinedescription: Mythical manager of the rsdd unix project
nobatchupdates: TRUE
notice: Off sailing this month.
onvacation: FALSE
labeledurl: http://www.umich.edu/ U-M Home Page
drink: water
-lastmodifiedtime: 960404035839Z
-lastmodifiedby: cn=Barbara Jensen, ou=Information Technology Division, ou=Peop
- le, o=University of Michigan, c=US
-modifytimestamp: 960404171405Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 2333
pager: +1 313 555 3233
facsimiletelephonenumber: +1 313 555 2274
sn: Jensen
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: bjorn
-userpassword: bjorn
+userpassword:: Ympvcm4=
krbname: jdoe@umich.edu
nobatchupdates: TRUE
onvacation: FALSE
title: Director, Embedded Systems
postaladdress: Info Tech Division $ 535 W. William St. $ Ann Arbor, MI 48103
mail: bjorn@mailgw.umich.edu
-modifytimestamp: 960404171424Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 5444
pager: +1 313 555 4474
facsimiletelephonenumber: +1 313 555 2177
facsimiletelephonenumber: +1 313 555 3223
telephonenumber: +1 313 555 3664
mail: dots@mail.alumni.umich.edu
-modifytimestamp: 960404171218Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 0454
dn: ou=Groups, o=University of Michigan, c=US
objectclass: quipuObject
objectclass: quipuNonLeafObject
ou: Groups
-lastmodifiedtime: 950120182331Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
dn: ou=Information Technology Division, ou=People, o=University of Michigan, c
=US
niversity of Michigan, c=US
member: cn=John Doe, ou=Information Technology Division, ou=People, o=Universi
ty of Michigan, c=US
-modifytimestamp: 960404171730Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
labeledurl: http://www.itd.umich.edu ITD Home Page
dn: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Mich
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: jaj
krbname: jaj@umich.edu
-userpassword: jaj
+userpassword:: amFq
nobatchupdates: TRUE
onvacation: FALSE
homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
title: Mad Cow Researcher, UM Alumni Association
pager: +1 313 555 3923
mail: jaj@mail.alumni.umich.edu
-modifytimestamp: 960404171231Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
facsimiletelephonenumber: +1 313 555 4332
telephonenumber: +1 313 555 0895
multilinedescription: Not around very much
mail: jjones@mailgw.umich.edu
postaladdress: Info Tech Division $ 535 W William $ Ann Arbor, MI 48103
-modifytimestamp: 960404171442Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
pager: +1 313 555 2833
facsimiletelephonenumber: +1 313 555 8688
telephonenumber: +1 313 555 7334
drink: diet coke
multilinedescription: Enthusiastic
mail: jdoe@woof.net
-modifytimestamp: 960404171249Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 5445
pager: +1 313 555 1220
facsimiletelephonenumber: +1 313 555 2311
homepostaladdress: 1000 Maple #44 $ Ann Arbor, MI 48103
title: Telemarketer, UM Alumni Association
mail: jen@mail.alumni.umich.edu
-modifytimestamp: 960404171309Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 2333
pager: +1 313 555 6442
facsimiletelephonenumber: +1 313 555 2756
title: System Administrator, Information Technology Division
multilinedescription: overworked!
mail: johnd@mailgw.umich.edu
-modifytimestamp: 960404171509Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 3774
pager: +1 313 555 6573
facsimiletelephonenumber: +1 313 555 4544
cn: Dir Man
sn: Manager
description: Manager of the directory
-userpassword: secret
-lastmodifiedtime: 951212214144Z
-lastmodifiedby: cn=Manager, o=University of Michigan, c=US
+userpassword:: c2VjcmV0
krbname: bjensen@umich.edu
dn: cn=Mark Elliot, ou=Alumni Association, ou=People, o=University of Michigan
drink: Gasoline
title: Director, UM Alumni Association
mail: melliot@mail.alumni.umich.edu
-modifytimestamp: 960404171327Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
pager: +1 313 555 7671
facsimiletelephonenumber: +1 313 555 7762
telephonenumber: +1 313 555 4177
o: U of M
description: The University of Michigan at Ann Arbor
postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
- 09 $ USpostalcode: 48109
+ 09 $ US
telephonenumber: +1 313 764-1817
-lastmodifiedtime: 930106182800Z
-lastmodifiedby: cn=manager, o=university of michigan, c=US
associateddomain: umich.edu
dn: cn=Ursula Hampster, ou=Alumni Association, ou=People, o=University of Mich
nobatchupdates: TRUE
onvacation: FALSE
mail: uham@mail.alumni.umich.edu
-modifytimestamp: 960404171346Z
-modifiersname: cn=Manager,o=University of Michigan,c=US
homephone: +1 313 555 8421
pager: +1 313 555 2844
facsimiletelephonenumber: +1 313 555 9700
--- /dev/null
+## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+##
+## tests Makefile.in for OpenLDAP
+
+PROGRAMS = slapd-tester slapd-search slapd-read slapd-addel
+SRCS = slapd-tester.c slapd-search.c slapd-read.c slapd-addel.c
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = -lldap -llber
+XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
+
+# build-tools: FORCE
+# $(MAKE) $(MFLAGS) load-tools
+
+# load-tools: $(PROGRAMS)
+
+slapd-tester: slapd-tester.o
+ $(LTLINK) -o $@ slapd-tester.o $(LIBS)
+
+slapd-search: slapd-search.o $(LDAP_LIBLBER_DEPEND) $(LDAP_LIBLDAP_DEPEND)
+ $(LTLINK) -o $@ slapd-search.o $(LIBS)
+
+slapd-read: slapd-read.o $(LDAP_LIBLBER_DEPEND) $(LDAP_LIBLDAP_DEPEND)
+ $(LTLINK) -o $@ slapd-read.o $(LIBS)
+
+slapd-addel: slapd-addel.o $(LDAP_LIBLBER_DEPEND) $(LDAP_LIBLDAP_DEPEND)
+ $(LTLINK) -o $@ slapd-addel.o $(LIBS)
+
+
--- /dev/null
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include <ldap.h>
+
+#define LOOPS 100
+
+static char *
+get_add_entry( char *filename, LDAPMod ***mods );
+
+static void
+do_addel( char *host, int port, char *manager, char *passwd,
+ char *dn, LDAPMod **attrs, int maxloop );
+
+static void
+usage( char *name )
+{
+ fprintf( stderr, "usage: %s [-h <host>] -p port -D <managerDN> -w <passwd> -f <addfile> [-l <loops>]\n",
+ name );
+ exit( EXIT_FAILURE );
+}
+
+int
+main( int argc, char **argv )
+{
+ int i;
+ char *host = "localhost";
+ int port = -1;
+ char *manager = NULL;
+ char *passwd = NULL;
+ char *filename = NULL;
+ char *entry = NULL;
+ int loops = LOOPS;
+ LDAPMod **attrs = NULL;
+
+ while ( (i = getopt( argc, argv, "h:p:D:w:f:l:" )) != EOF ) {
+ switch( i ) {
+ case 'h': /* the servers host */
+ host = strdup( optarg );
+ break;
+
+ case 'p': /* the servers port */
+ port = atoi( optarg );
+ break;
+
+ case 'D': /* the servers manager */
+ manager = strdup( optarg );
+ break;
+
+ case 'w': /* the server managers password */
+ passwd = strdup( optarg );
+ break;
+
+ case 'f': /* file with entry search request */
+ filename = strdup( optarg );
+ break;
+
+ case 'l': /* the number of loops */
+ loops = atoi( optarg );
+ break;
+
+ default:
+ usage( argv[0] );
+ break;
+ }
+ }
+
+ if (( filename == NULL ) || ( port == -1 ) ||
+ ( manager == NULL ) || ( passwd == NULL ))
+ usage( argv[0] );
+
+ entry = get_add_entry( filename, &attrs );
+ if (( entry == NULL ) || ( *entry == '\0' )) {
+
+ fprintf( stderr, "%s: invalid entry DN in file \"%s\".\n",
+ argv[0], filename );
+ exit( EXIT_FAILURE );
+
+ }
+
+ if (( attrs == NULL ) || ( *attrs == '\0' )) {
+
+ fprintf( stderr, "%s: invalid attrs in file \"%s\".\n",
+ argv[0], filename );
+ exit( EXIT_FAILURE );
+
+ }
+
+ do_addel( host, port, manager, passwd, entry, attrs, loops );
+
+ exit( EXIT_SUCCESS );
+}
+
+
+static void
+addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
+{
+ LDAPMod **pmods;
+ int i, j;
+ struct berval *bvp;
+
+ pmods = *pmodsp;
+ modop |= LDAP_MOD_BVALUES;
+
+ i = 0;
+ if ( pmods != NULL ) {
+ for ( ; pmods[ i ] != NULL; ++i ) {
+ if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
+ pmods[ i ]->mod_op == modop ) {
+ break;
+ }
+ }
+ }
+
+ if ( pmods == NULL || pmods[ i ] == NULL ) {
+ if (( pmods = (LDAPMod **)realloc( pmods, (i + 2) *
+ sizeof( LDAPMod * ))) == NULL ) {
+ perror( "realloc" );
+ exit( EXIT_FAILURE );
+ }
+ *pmodsp = pmods;
+ pmods[ i + 1 ] = NULL;
+ if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
+ == NULL ) {
+ perror( "calloc" );
+ exit( EXIT_FAILURE );
+ }
+ pmods[ i ]->mod_op = modop;
+ if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
+ perror( "strdup" );
+ exit( EXIT_FAILURE );
+ }
+ }
+
+ if ( value != NULL ) {
+ j = 0;
+ if ( pmods[ i ]->mod_bvalues != NULL ) {
+ for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
+ ;
+ }
+ }
+ if (( pmods[ i ]->mod_bvalues =
+ (struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
+ (j + 2) * sizeof( struct berval * ))) == NULL ) {
+ perror( "ber_realloc" );
+ exit( EXIT_FAILURE );
+ }
+ pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
+ if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
+ == NULL ) {
+ perror( "malloc" );
+ exit( EXIT_FAILURE );
+ }
+ pmods[ i ]->mod_bvalues[ j ] = bvp;
+
+ bvp->bv_len = vlen;
+ if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
+ perror( "malloc" );
+ exit( EXIT_FAILURE );
+ }
+ SAFEMEMCPY( bvp->bv_val, value, vlen );
+ bvp->bv_val[ vlen ] = '\0';
+ }
+}
+
+
+static char *
+get_add_entry( char *filename, LDAPMod ***mods )
+{
+ FILE *fp;
+ char *entry = NULL;
+
+ if ( (fp = fopen( filename, "r" )) != NULL ) {
+ char line[BUFSIZ];
+
+ if ( fgets( line, BUFSIZ, fp )) {
+ char *nl;
+
+ if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
+ *nl = '\0';
+ entry = strdup( line );
+
+ }
+
+ while ( fgets( line, BUFSIZ, fp )) {
+ char *nl;
+ char *value;
+
+ if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
+ *nl = '\0';
+
+ if ( *line == '\0' ) break;
+ if ( !( value = strchr( line, ':' ))) break;
+
+ *value++ = '\0';
+ while ( *value && isspace( (unsigned char) *value ))
+ value++;
+
+ addmodifyop( mods, LDAP_MOD_ADD, line, value, strlen( value ));
+
+ }
+ fclose( fp );
+ }
+
+ return( entry );
+}
+
+
+static void
+do_addel(
+ char *host,
+ int port,
+ char *manager,
+ char *passwd,
+ char *entry,
+ LDAPMod **attrs,
+ int maxloop
+)
+{
+ LDAP *ld;
+ int i;
+ pid_t pid = getpid();
+
+ if (( ld = ldap_init( host, port )) == NULL ) {
+ perror( "ldap_init" );
+ exit( EXIT_FAILURE );
+ }
+
+ if ( ldap_bind_s( ld, manager, passwd, LDAP_AUTH_SIMPLE )
+ != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_bind" );
+ exit( EXIT_FAILURE );
+ }
+
+
+ fprintf( stderr, "PID=%ld - Add/Delete(%d): entry=\"%s\".\n",
+ (long) pid, maxloop, entry );
+
+ for ( i = 0; i < maxloop; i++ ) {
+
+ /* add the entry */
+ if ( ldap_add_s( ld, entry, attrs ) != LDAP_SUCCESS ) {
+
+ ldap_perror( ld, "ldap_add" );
+ break;
+
+ }
+
+ /* wait a second for the add to really complete */
+ sleep( 1 );
+
+ /* now delete the entry again */
+ if ( ldap_delete_s( ld, entry ) != LDAP_SUCCESS ) {
+
+ ldap_perror( ld, "ldap_delete" );
+ break;
+
+ }
+
+ }
+
+ fprintf( stderr, " PID=%ld - Add/Delete done.\n", (long) pid );
+
+ ldap_unbind( ld );
+}
+
+
--- /dev/null
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include <ldap.h>
+
+#define LOOPS 100
+
+static void
+do_read( char *host, int port, char *entry, int maxloop );
+
+static void
+usage( char *name )
+{
+ fprintf( stderr, "usage: %s [-h <host>] -p port -e <entry> [-l <loops>]\n",
+ name );
+ exit( EXIT_FAILURE );
+}
+
+int
+main( int argc, char **argv )
+{
+ int i;
+ char *host = "localhost";
+ int port = -1;
+ char *entry = NULL;
+ int loops = LOOPS;
+
+ while ( (i = getopt( argc, argv, "h:p:e:l:" )) != EOF ) {
+ switch( i ) {
+ case 'h': /* the servers host */
+ host = strdup( optarg );
+ break;
+
+ case 'p': /* the servers port */
+ port = atoi( optarg );
+ break;
+
+ case 'e': /* file with entry search request */
+ entry = strdup( optarg );
+ break;
+
+ case 'l': /* the number of loops */
+ loops = atoi( optarg );
+ break;
+
+ default:
+ usage( argv[0] );
+ break;
+ }
+ }
+
+ if (( entry == NULL ) || ( port == -1 ))
+ usage( argv[0] );
+
+ if ( *entry == '\0' ) {
+
+ fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
+ argv[0] );
+ exit( EXIT_FAILURE );
+
+ }
+
+ do_read( host, port, entry, ( 4 * loops ));
+
+ exit( EXIT_SUCCESS );
+}
+
+
+static void
+do_read( char *host, int port, char *entry, int maxloop )
+{
+ LDAP *ld;
+ int i;
+ char *attrs[] = { "cn", "sn", NULL };
+ char *filter = "(objectclass=*)";
+ pid_t pid = getpid();
+
+ if (( ld = ldap_init( host, port )) == NULL ) {
+ perror( "ldap_init" );
+ exit( EXIT_FAILURE );
+ }
+
+ if ( ldap_bind_s( ld, NULL, NULL, LDAP_AUTH_SIMPLE ) != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_bind" );
+ exit( EXIT_FAILURE );
+ }
+
+
+ fprintf( stderr, "PID=%ld - Read(%d): entry=\"%s\".\n",
+ (long) pid, maxloop, entry );
+
+ for ( i = 0; i < maxloop; i++ ) {
+ LDAPMessage *res;
+ int rc;
+
+ if (( rc = ldap_search_s( ld, entry, LDAP_SCOPE_BASE,
+ filter, attrs, 0, &res )) != LDAP_SUCCESS ) {
+
+ ldap_perror( ld, "ldap_read" );
+ if ( rc != LDAP_NO_SUCH_OBJECT ) break;
+ continue;
+
+ }
+
+ ldap_msgfree( res );
+ }
+
+ fprintf( stderr, " PID=%ld - Read done.\n", (long) pid );
+
+ ldap_unbind( ld );
+}
+
+
--- /dev/null
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include <ldap.h>
+
+#define LOOPS 100
+
+static void
+do_search( char *host, int port, char *sbase, char *filter, int maxloop );
+
+static void
+usage( char *name )
+{
+ fprintf( stderr, "usage: %s [-h <host>] -p port -b <searchbase> -f <searchfiter> [-l <loops>]\n",
+ name );
+ exit( EXIT_FAILURE );
+}
+
+int
+main( int argc, char **argv )
+{
+ int i;
+ char *host = "localhost";
+ int port = -1;
+ char *sbase = NULL;
+ char *filter = NULL;
+ int loops = LOOPS;
+
+ while ( (i = getopt( argc, argv, "h:p:b:f:l:" )) != EOF ) {
+ switch( i ) {
+ case 'h': /* the servers host */
+ host = strdup( optarg );
+ break;
+
+ case 'p': /* the servers port */
+ port = atoi( optarg );
+ break;
+
+ case 'b': /* file with search base */
+ sbase = strdup( optarg );
+ break;
+
+ case 'f': /* the search request */
+ filter = strdup( optarg );
+ break;
+
+ case 'l': /* number of loops */
+ loops = atoi( optarg );
+ break;
+
+ default:
+ usage( argv[0] );
+ break;
+ }
+ }
+
+ if (( sbase == NULL ) || ( filter == NULL ) || ( port == -1 ))
+ usage( argv[0] );
+
+ if ( *filter == '\0' ) {
+
+ fprintf( stderr, "%s: invalid EMPTY search filter.\n",
+ argv[0] );
+ exit( EXIT_FAILURE );
+
+ }
+
+ do_search( host, port, sbase, filter, ( 4 * loops ));
+
+ exit( EXIT_SUCCESS );
+}
+
+
+static void
+do_search( char *host, int port, char *sbase, char *filter, int maxloop )
+{
+ LDAP *ld;
+ int i;
+ char *attrs[] = { "cn", "sn", NULL };
+ pid_t pid = getpid();
+
+ if (( ld = ldap_init( host, port )) == NULL ) {
+ perror( "ldap_init" );
+ exit( EXIT_FAILURE );
+ }
+
+ if ( ldap_bind_s( ld, NULL, NULL, LDAP_AUTH_SIMPLE ) != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_bind" );
+ exit( EXIT_FAILURE );
+ }
+
+
+ fprintf( stderr, "PID=%ld - Search(%d): base=\"%s\", filter=\"%s\".\n",
+ (long) pid, maxloop, sbase, filter );
+
+ for ( i = 0; i < maxloop; i++ ) {
+ LDAPMessage *res;
+ int rc;
+
+ if (( rc = ldap_search_s( ld, sbase, LDAP_SCOPE_SUBTREE,
+ filter, attrs, 0, &res )) != LDAP_SUCCESS ) {
+
+ ldap_perror( ld, "ldap_search" );
+ if ( rc != LDAP_NO_SUCH_OBJECT ) break;
+ continue;
+
+ }
+
+ ldap_msgfree( res );
+ }
+
+ fprintf( stderr, " PID=%ld - Search done.\n", (long) pid );
+
+ ldap_unbind( ld );
+}
+
+
--- /dev/null
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/ctype.h>
+#include <ac/dirent.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+#include <ac/wait.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "ldap_defaults.h"
+
+
+#define SEARCHCMD "slapd-search"
+#define READCMD "slapd-read"
+#define ADDCMD "slapd-addel"
+#define MAXARGS 100
+#define MAXREQS 20
+#define LOOPS "100"
+
+#define TSEARCHFILE "do_search.0"
+#define TREADFILE "do_read.0"
+#define TADDFILE "do_add."
+
+static char *get_file_name( char *dirname, char *filename );
+static int get_search_filters( char *filename, char *filters[] );
+static int get_read_entries( char *filename, char *entries[] );
+static void fork_child( char *prog, char *args[] );
+static void wait4kids( int nkidval );
+
+static int maxkids = 20;
+static int nkids;
+
+static void
+usage( char *name )
+{
+ fprintf( stderr, "usage: %s [-h <host>] -p <port> -D <manager> -w <passwd> -d <datadir> -b <baseDN> [-j <maxchild>] [-l <loops>] -P <progdir>\n", name );
+ exit( EXIT_FAILURE );
+}
+
+int
+main( int argc, char **argv )
+{
+ int i, j;
+ char *host = "localhost";
+ char *port = NULL;
+ char *manager = NULL;
+ char *passwd = NULL;
+ char *dirname = NULL;
+ char *sbase = NULL;
+ char *progdir = NULL;
+ char *loops = LOOPS;
+ DIR *datadir;
+ struct dirent *file;
+ char *sfile = NULL;
+ char *sreqs[MAXREQS];
+ int snum = 0;
+ char *rfile = NULL;
+ char *rreqs[MAXREQS];
+ int rnum = 0;
+ char *afiles[MAXREQS];
+ int anum = 0;
+ char *sargs[MAXARGS];
+ int sanum;
+ char scmd[MAXPATHLEN];
+ char *rargs[MAXARGS];
+ int ranum;
+ char rcmd[MAXPATHLEN];
+ char *aargs[MAXARGS];
+ int aanum;
+ char acmd[MAXPATHLEN];
+
+ while ( (i = getopt( argc, argv, "h:p:D:w:b:d:j:l:P:" )) != EOF ) {
+ switch( i ) {
+ case 'h': /* slapd host */
+ host = strdup( optarg );
+ break;
+
+ case 'p': /* the servers port number */
+ port = strdup( optarg );
+ break;
+
+ case 'D': /* slapd manager */
+ manager = strdup( optarg );
+ break;
+
+ case 'w': /* the managers passwd */
+ passwd = strdup( optarg );
+ break;
+
+ case 'b': /* the base DN */
+ sbase = strdup( optarg );
+ break;
+
+ case 'd': /* data directory */
+ dirname = strdup( optarg );
+ break;
+
+ case 'P': /* prog directory */
+ progdir = strdup( optarg );
+ break;
+
+ case 'j': /* the number of parallel clients */
+ maxkids = atoi( optarg );
+ break;
+
+ case 'l': /* the number of loops per client */
+ loops = strdup( optarg );
+ break;
+
+ default:
+ usage( argv[0] );
+ break;
+ }
+ }
+
+ if (( dirname == NULL ) || ( sbase == NULL ) || ( port == NULL ) ||
+ ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
+ usage( argv[0] );
+
+ /* get the file list */
+ if ( ( datadir = opendir( dirname )) == NULL ) {
+
+ fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
+ argv[0], dirname );
+ exit( EXIT_FAILURE );
+
+ }
+
+ /* look for search, read, and add/delete files */
+ for ( file = readdir( datadir ); file; file = readdir( datadir )) {
+
+ if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
+ sfile = get_file_name( dirname, file->d_name );
+ continue;
+ } else if ( !strcasecmp( file->d_name, TREADFILE )) {
+ rfile = get_file_name( dirname, file->d_name );
+ continue;
+ } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
+ && ( anum < MAXREQS )) {
+ afiles[anum++] = get_file_name( dirname, file->d_name );
+ continue;
+ }
+ }
+
+ closedir( datadir );
+
+ /* look for search requests */
+ if ( sfile ) {
+ snum = get_search_filters( sfile, sreqs );
+ }
+
+ /* look for read requests */
+ if ( rfile ) {
+ rnum = get_read_entries( rfile, rreqs );
+ }
+
+ /*
+ * generate the search clients
+ */
+
+ sanum = 0;
+ sprintf( scmd, "%s%s%s", progdir, LDAP_DIRSEP, SEARCHCMD );
+ sargs[sanum++] = scmd;
+ sargs[sanum++] = "-h";
+ sargs[sanum++] = host;
+ sargs[sanum++] = "-p";
+ sargs[sanum++] = port;
+ sargs[sanum++] = "-b";
+ sargs[sanum++] = sbase;
+ sargs[sanum++] = "-l";
+ sargs[sanum++] = loops;
+ sargs[sanum++] = "-f";
+ sargs[sanum++] = NULL; /* will hold the search request */
+ sargs[sanum++] = NULL;
+
+ /*
+ * generate the read clients
+ */
+
+ ranum = 0;
+ sprintf( rcmd, "%s%s%s", progdir, LDAP_DIRSEP, READCMD );
+ rargs[ranum++] = rcmd;
+ rargs[ranum++] = "-h";
+ rargs[ranum++] = host;
+ rargs[ranum++] = "-p";
+ rargs[ranum++] = port;
+ rargs[ranum++] = "-l";
+ rargs[ranum++] = loops;
+ rargs[ranum++] = "-e";
+ rargs[ranum++] = NULL; /* will hold the read entry */
+ rargs[ranum++] = NULL;
+
+ /*
+ * generate the add/delete clients
+ */
+
+ aanum = 0;
+ sprintf( acmd, "%s%s%s", progdir, LDAP_DIRSEP, ADDCMD );
+ aargs[aanum++] = acmd;
+ aargs[aanum++] = "-h";
+ aargs[aanum++] = host;
+ aargs[aanum++] = "-p";
+ aargs[aanum++] = port;
+ aargs[aanum++] = "-D";
+ aargs[aanum++] = manager;
+ aargs[aanum++] = "-w";
+ aargs[aanum++] = passwd;
+ aargs[aanum++] = "-l";
+ aargs[aanum++] = loops;
+ aargs[aanum++] = "-f";
+ aargs[aanum++] = NULL; /* will hold the add data file */
+ aargs[aanum++] = NULL;
+
+ for ( j = 0; j < MAXREQS; j++ ) {
+
+ if ( j < snum ) {
+
+ sargs[sanum - 2] = sreqs[j];
+ fork_child( scmd, sargs );
+
+ }
+
+ if ( j < rnum ) {
+
+ rargs[ranum - 2] = rreqs[j];
+ fork_child( rcmd, rargs );
+
+ }
+
+ if ( j < anum ) {
+
+ aargs[aanum - 2] = afiles[j];
+ fork_child( acmd, aargs );
+
+ }
+
+ }
+
+ wait4kids( -1 );
+
+ exit( EXIT_SUCCESS );
+}
+
+static char *
+get_file_name( char *dirname, char *filename )
+{
+ char buf[MAXPATHLEN];
+
+ sprintf( buf, "%s%s%s", dirname, LDAP_DIRSEP, filename );
+ return( strdup( buf ));
+}
+
+
+static int
+get_search_filters( char *filename, char *filters[] )
+{
+ FILE *fp;
+ int filter = 0;
+
+ if ( (fp = fopen( filename, "r" )) != NULL ) {
+ char line[BUFSIZ];
+
+ while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
+ char *nl;
+
+ if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
+ *nl = '\0';
+ filters[filter++] = strdup( line );
+
+ }
+ fclose( fp );
+ }
+
+ return( filter );
+}
+
+
+static int
+get_read_entries( char *filename, char *entries[] )
+{
+ FILE *fp;
+ int entry = 0;
+
+ if ( (fp = fopen( filename, "r" )) != NULL ) {
+ char line[BUFSIZ];
+
+ while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
+ char *nl;
+
+ if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
+ *nl = '\0';
+ entries[entry++] = strdup( line );
+
+ }
+ fclose( fp );
+ }
+
+ return( entry );
+}
+
+
+static void
+fork_child( char *prog, char *args[] )
+{
+ pid_t pid;
+
+ wait4kids( maxkids );
+
+ switch ( pid = fork() ) {
+ case 0: /* child */
+ execvp( prog, args );
+ fprintf( stderr, "%s: ", prog );
+ perror( "execv" );
+ exit( EXIT_FAILURE );
+ break;
+
+ case -1: /* trouble */
+ fprintf( stderr, "Could not fork to run %s\n", prog );
+ perror( "fork" );
+ break;
+
+ default: /* parent */
+ nkids++;
+ break;
+ }
+}
+
+static void
+wait4kids( int nkidval )
+{
+ int status;
+
+ while ( nkids >= nkidval ) {
+ wait( &status );
+
+ if ( WIFSTOPPED(status) ) {
+ fprintf( stderr,
+ "stopping: child stopped with signal %d\n",
+ (int) WSTOPSIG(status) );
+
+ } else if ( WIFSIGNALED(status) ) {
+ fprintf( stderr,
+ "stopping: child terminated with signal %d%s\n",
+ (int) WTERMSIG(status),
+#ifdef WCOREDUMP
+ WCOREDUMP(status) ? ", core dumped" : ""
+#else
+ ""
+#endif
+ );
+ exit( WEXITSTATUS(status) );
+
+ } else if ( WEXITSTATUS(status) != 0 ) {
+ fprintf( stderr,
+ "stopping: child exited with status %d\n",
+ (int) WEXITSTATUS(status) );
+ exit( WEXITSTATUS(status) );
+
+ } else {
+ nkids--;
+ }
+ }
+}
-#!/bin/sh
+#! /bin/sh
+
+# disable LDAP initialization
+LDAPNOINIT=true; export LDAPNOINIT
echo ">>>>> Executing all LDAP tests..."
-if [ $# -eq 0 ]; then
- SCRIPTDIR="."
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+
+echo ">>>>> Test Directory: $SRCDIR"
+
+if test $# -eq 0 ; then
+ BACKEND=ldbm
else
- SCRIPTDIR=$1; shift
+ BACKEND=$1; shift
fi
-for i in $SCRIPTDIR/test*; do
- CMD=$i $*
- echo ">>>>> Starting $CMD ..."
- $CMD
+echo ">>>>> Backend: $BACKEND"
+
+for CMD in $SRCDIR/scripts/test*; do
+ echo ">>>>> Starting `basename $CMD` ..."
+ $CMD $SRCDIR $BACKEND
RC=$?
- if [ $RC -eq 0 ]; then
+ if test $RC -eq 0 ; then
echo ">>>>> $CMD completed OK."
else
echo ">>>>> $CMD failed (exit $RC)"
exit $RC
fi
+ echo ">>>>> waiting 10 seconds for things to exit"
+ sleep 10
echo
done
-LDIF2LDBM=../servers/slapd/tools/ldif2ldbm
+
+DATADIR=$SRCDIR/data
+PROGDIR=./progs
+
+if test "$BACKEND" = "bdb2" ; then
+ CONF=$DATADIR/slapd-bdb2-master.conf
+ ACLCONF=$DATADIR/slapd-bdb2-acl.conf
+ MASTERCONF=$DATADIR/slapd-bdb2-repl-master.conf
+ SLAVECONF=$DATADIR/slapd-bdb2-repl-slave.conf
+ REFSLAVECONF=$DATADIR/slapd-bdb2-ref-slave.conf
+ TIMING="-t"
+else
+ CONF=$DATADIR/slapd-master.conf
+ ACLCONF=$DATADIR/slapd-acl.conf
+ MASTERCONF=$DATADIR/slapd-repl-master.conf
+ SLAVECONF=$DATADIR/slapd-repl-slave.conf
+ REFSLAVECONF=$DATADIR/slapd-ref-slave.conf
+fi
+
+if test "$LDAP_PROTO" ; then
+ PROTO="-P $LDAP_PROTO"
+fi
+
+PASSWDCONF=$DATADIR/slapd-passwd.conf
+
+CLIENTDIR=../clients/tools
+#CLIENTDIR=/usr/local/bin
+
+LDIF2LDBM="../servers/slapd/tools/slapadd $LDAP_VERBOSE"
+
SLAPD=../servers/slapd/slapd
SLURPD=../servers/slurpd/slurpd
-LDAPSEARCH=../clients/tools/ldapsearch
-LDAPMODIFY=../clients/tools/ldapmodify
-LDAPADD=../clients/tools/ldapadd
+LDAPSEARCH="$CLIENTDIR/ldapsearch $PROTO -LLL"
+LDAPMODIFY="$CLIENTDIR/ldapmodify $PROTO"
+LDAPADD="$CLIENTDIR/ldapadd $PROTO"
+LDAPMODRDN="$CLIENTDIR/ldapmodrdn $PROTO"
+SLAPDTESTER=$PROGDIR/slapd-tester
+LVL=${SLAPD_DEBUG-5}
+ADDR=127.0.0.1
PORT=9009
SLAVEPORT=9010
DBDIR=./test-db
REPLDIR=./test-repl
-CONF=./data/slapd-master.conf
-ACLCONF=./data/slapd-acl.conf
-MASTERCONF=./data/slapd-repl-master.conf
-SLAVECONF=./data/slapd-repl-slave.conf
-LDIF=./data/test.ldif
-LDIFORDERED=./data/test-ordered.ldif
+LDIF=$DATADIR/test.ldif
+LDIFORDERED=$DATADIR/test-ordered.ldif
+MONITOR="cn=monitor"
BASEDN="o=University of Michigan, c=US"
MANAGERDN="cn=Manager, o=University of Michigan, c=US"
+UPDATEDN="cn=Replica, o=University of Michigan, c=US"
PASSWD=secret
BABSDN="cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US"
BJORNSDN="cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US"
JAJDN="cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US"
+MASTERLOG=$DBDIR/master.log
+SLAVELOG=$DBDIR/slave.log
+SLURPLOG=$DBDIR/slurp.log
SEARCHOUT=$DBDIR/ldapsearch.out
+SEARCHFLT=$DBDIR/ldapsearch.flt
+LDIFFLT=$DBDIR/ldif.flt
MASTEROUT=$DBDIR/master.out
SLAVEOUT=$DBDIR/slave.out
-TESTOUT=$DBDIR/ldapsearch.out
-SEARCHOUTMASTER=./data/search.out.master
-MODIFYOUTMASTER=./data/modify.out.master
-ADDDELOUTMASTER=./data/adddel.out.master
-MODRDNOUTMASTER=./data/modrdn.out.master
-ACLOUTMASTER=./data/acl.out.master
-REPLOUTMASTER=./data/repl.out.master
-MODSRCHFILTERS=./data/modify.search.filters
+TESTOUT=$DBDIR/test.out
+SEARCHOUTMASTER=$DATADIR/search.out.master
+MODIFYOUTMASTER=$DATADIR/modify.out.master
+ADDDELOUTMASTER=$DATADIR/adddel.out.master
+MODRDNOUTMASTER0=$DATADIR/modrdn.out.master.0
+MODRDNOUTMASTER1=$DATADIR/modrdn.out.master.1
+MODRDNOUTMASTER2=$DATADIR/modrdn.out.master.2
+MODRDNOUTMASTER3=$DATADIR/modrdn.out.master.3
+ACLOUTMASTER=$DATADIR/acl.out.master
+REPLOUTMASTER=$DATADIR/repl.out.master
+MODSRCHFILTERS=$DATADIR/modify.search.filters
-#!/bin/sh
+#! /bin/sh
. scripts/defines.sh
echo "Cleaning up in $DBDIR..."
-rm -f $DBDIR/*
+rm -f $DBDIR/[!C]*
echo "Running ldif2ldbm to build slapd database..."
-$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
+$LDIF2LDBM -f $CONF -l $LDIF
RC=$?
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldif2ldbm failed!"
exit $RC
fi
--- /dev/null
+#!/bin/sh
+
+
+if [ $# -eq 0 ]; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if [ $# -eq 1 ]; then
+ BDB2=$1; shift
+fi
+
+. $SRCDIR/scripts/defines.sh $SRCDIR $BDB2
+
+# Sample NIS database in LDIF format
+NIS_LDIF=$SRCDIR/data/nis_sample.ldif
+
+# Sample configuration file for your LDAP server
+if test "$BACKEND" = "bdb2" ; then
+ NIS_CONF=$DATADIR/slapd-bdb2-nis-master.conf
+else
+ NIS_CONF=$DATADIR/slapd-nis-master.conf
+fi
+
+echo "Cleaning up in $DBDIR..."
+
+rm -f $DBDIR/[!C]*
+
+echo "Running ldif2ldbm to build slapd database..."
+$LDIF2LDBM -f $NIS_CONF -l $NIS_LDIF
+RC=$?
+if [ $RC != 0 ]; then
+ echo "ldif2ldbm failed!"
+ exit $RC
+fi
+
+echo "Starting slapd on TCP/IP port $PORT..."
+$SLAPD -f $NIS_CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
+PID=$!
+
+echo ">>>>> LDAP server with NIS schema is up! PID=$PID"
+
+
+exit 0
-#!/bin/sh
+#! /bin/sh
-. scripts/defines.sh
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
+
+echo "Datadir is $DATADIR"
echo "Cleaning up in $DBDIR..."
-rm -f $DBDIR/*
+rm -f $DBDIR/[!C]*
echo "Running ldif2ldbm to build slapd database..."
-$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
+$LDIF2LDBM -f $CONF -l $LDIF
RC=$?
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldif2ldbm failed!"
exit $RC
fi
echo "Starting slapd on TCP/IP port $PORT..."
-$SLAPD -f $CONF -p $PORT -d 1 > /dev/null 2>&1 &
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
PID=$!
echo "Using ldapsearch to retrieve all the entries..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
+ $LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
'objectClass=*' > $SEARCHOUT 2>&1
RC=$?
- if [ $RC = 1 ]; then
+ if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
sleep 5
fi
kill -HUP $PID
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapsearch failed!"
exit $RC
fi
-echo "Comparing retrieved entries to LDIF file used to create database"
-cmp $SEARCHOUT $LDIF
-if [ $? != 0 ]; then
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
echo "comparison failed - database was not created correctly"
exit 1
fi
-#!/bin/sh
+#! /bin/sh
-. scripts/defines.sh
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
echo "Cleaning up in $DBDIR..."
-rm -f $DBDIR/*
+rm -f $DBDIR/[!C]*
echo "Starting slapd on TCP/IP port $PORT..."
-$SLAPD -f $CONF -p $PORT -d 1 > /dev/null 2>&1 &
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
PID=$!
echo "Using ldapsearch to check that slapd is running..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Monitor' > /dev/null 2>&1
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
- if [ $RC = 1 ]; then
+ if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
sleep 5
fi
done
-echo "Using ldapmodify to populate the database..."
-$LDAPMODIFY -a -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD < \
- $LDIFORDERED > /dev/null 2>&1
+echo "Using ldapadd to populate the database..."
+$LDAPADD -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD < \
+ $LDIFORDERED > $TESTOUT 2>&1
RC=$?
-if [ $RC != 0 ]; then
- echo "ldapmodify failed!"
+if test $RC != 0 ; then
+ echo "ldapadd failed!"
kill -HUP $PID
exit $RC
fi
echo "Using ldapsearch to read all the entries..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'objectclass=*' | egrep -iv '^creatorsname:|^createtimestamp:' > \
- $SEARCHOUT 2>&1
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'objectclass=*' > $SEARCHOUT 2>&1
kill -HUP $PID
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapsearch failed!"
exit $RC
fi
-echo "Comparing retrieved entries to LDIF file used to create database"
-cmp $SEARCHOUT $LDIF
-if [ $? != 0 ]; then
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
echo "comparison failed - database was not created correctly"
exit 1
fi
-#!/bin/sh
+#! /bin/sh
-. scripts/defines.sh
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
echo "Cleaning up in $DBDIR..."
-rm -f $DBDIR/*
+rm -f $DBDIR/[!C]*
echo "Running ldif2ldbm to build slapd database..."
-$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
+$LDIF2LDBM -f $CONF -l $LDIF
RC=$?
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldif2ldbm failed!"
exit $RC
fi
echo "Starting slapd on TCP/IP port $PORT..."
-$SLAPD -f $CONF -p $PORT -d 1 > /dev/null 2>&1 &
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
PID=$!
echo "Testing slapd searching..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Manager' > /dev/null 2>&1
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
- if [ $RC = 1 ]; then
+ if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
sleep 5
fi
done
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapsearch failed!"
kill -HUP $PID
exit $RC
fi
-cat /dev/null > $TESTOUT
+cat /dev/null > $SEARCHOUT
echo "Testing exact searching..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'sn=jensen' >> $TESTOUT 2>&1
-if [ $RC != 0 ]; then
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'sn=jensen' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
echo "ldapsearch failed!"
kill -HUP $PID
exit $RC
fi
echo "Testing OR searching..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- '(|(objectclass=rfc822mailgroup)(sn=jones))' >> $TESTOUT 2>&1
-if [ $RC != 0 ]; then
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ '(|(objectclass=rfc822mailgroup)(sn=jones))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
echo "ldapsearch failed!"
kill -HUP $PID
exit $RC
fi
echo "Testing AND matching and ends-with searching..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- '(&(objectclass=rfc822mailgroup)(cn=A*))' >> $TESTOUT 2>&1
-if [ $RC != 0 ]; then
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ '(&(objectclass=rfc822mailgroup)(cn=A*))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
echo "ldapsearch failed!"
kill -HUP $PID
exit $RC
fi
echo "Testing NOT searching..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- '(!(objectclass=person))' | grep -v "^modifytimestamp:" \
- >> $TESTOUT 2>&1
-if [ $RC != 0 ]; then
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ '(!(objectclass=person))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
echo "ldapsearch failed!"
kill -HUP $PID
exit $RC
kill -HUP $PID
-echo "Comparing results"
-cmp $TESTOUT $SEARCHOUTMASTER
-if [ $? != 0 ]; then
+LDIF=$SEARCHOUTMASTER
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
echo "Comparison failed"
exit 1
fi
-#!/bin/sh
+#! /bin/sh
-. scripts/defines.sh
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
echo "Cleaning up in $DBDIR..."
-rm -f $DBDIR/*
+rm -f $DBDIR/[!C]*
echo "Running ldif2ldbm to build slapd database..."
-$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
+$LDIF2LDBM -f $CONF -l $LDIF
RC=$?
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldif2ldbm failed!"
exit $RC
fi
echo "Starting slapd on TCP/IP port $PORT..."
-$SLAPD -f $CONF -p $PORT -d 1 > /dev/null 2>&1 &
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
PID=$!
echo "Testing slapd modify operations..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Manager' > /dev/null 2>&1
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
- if [ $RC = 1 ]; then
+ if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
sleep 5
fi
done
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapsearch failed!"
kill -HUP $PID
exit $RC
fi
-cat /dev/null > $TESTOUT
-
echo "Testing modify, add, and delete..."
$LDAPMODIFY -v -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD > \
- /dev/null 2>&1 << EOMODS
+ $TESTOUT 2>&1 << EOMODS
+version: 1
+
+# LEADING COMMENT AND WHITE SPACE
+
dn: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US
+# EMBEDDED COMMENT
changetype: modify
add: drink
drink: Orange Juice
dn: cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US
changetype: modify
+# EMBEDDED COMMENT
+ CONTINUED
replace: multilinedescription
multilinedescription: The replaced multiLineDescription $ Blah Woof.
-
dn: cn=James A Jones 2, ou=Information Technology Division, ou=People, o=University of Michigan, c=US
changetype: delete
+# TRAILING COMMENT AND WHITE SPACE
EOMODS
RC=$?
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapmodify failed!"
kill -HUP $PID
exit $RC
fi
echo "Using ldapsearch to retrieve all the entries..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'objectClass=*' | egrep -iv '^createtimestamp:|^modifytimestamp:' \
- > $SEARCHOUT 2>&1
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'objectClass=*' > $SEARCHOUT 2>&1
RC=$?
kill -HUP $PID
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapsearch failed!"
exit $RC
fi
-echo "Comparing database to reference file"
-cmp $SEARCHOUT $MODIFYOUTMASTER
-if [ $? != 0 ]; then
+LDIF=$MODIFYOUTMASTER
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
echo "comparison failed - modify operations did not complete correctly"
exit 1
fi
echo ">>>>> Test succeeded"
-
exit 0
-#!/bin/sh
+#! /bin/sh
-echo "modrdn test not yet written"
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
+
+echo "Cleaning up in $DBDIR..."
+
+rm -f $DBDIR/[!C]*
+
+echo "Running ldif2ldbm to build slapd database..."
+$LDIF2LDBM -f $CONF -l $LDIF
+RC=$?
+if test $RC != 0 ; then
+ echo "ldif2ldbm failed!"
+ exit $RC
+fi
+
+echo "Starting slapd on TCP/IP port $PORT..."
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
+PID=$!
+echo "Testing slapd modrdn operations..."
+
+# Make sure we can search the database
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 1 ; then
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+ fi
+done
+
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+# -r used to do remove of old rdn
+
+echo "Testing modrdn(deleteoldrdn=0)..."
+$LDAPMODRDN -v -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD > \
+ $TESTOUT 2>&1 'cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US' 'cn=James A Jones III'
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodrdn failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+echo "Testing modrdn(deleteoldrdn=1)..."
+$LDAPMODRDN -v -D "$MANAGERDN" -r -h localhost -p $PORT -w $PASSWD >> \
+ $TESTOUT 2>&1 'cn=James A Jones 2, ou=Information Technology Division, ou=People, o=University of Michigan, c=US' 'cn=James A Jones II'
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodrdn failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+# Ensure the new rdn's can be found
+
+echo "Using ldapsearch to retrieve entries using new rdn (cn=James A Jones III)..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'cn=James A Jones III' | egrep -iv '^createtimestamp:|^modifytimestamp:' \
+ > $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+
+LDIF=$MODRDNOUTMASTER1
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
+ echo "comparison failed - modrdn operations did not complete correctly"
+ kill -HUP $PID
+ exit 1
+fi
+
+
+echo "Using ldapsearch to retrieve entries using new rdn (cn=James A Jones II)..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'cn=James A Jones II' | egrep -iv '^createtimestamp:|^modifytimestamp:' \
+ > $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+
+LDIF=$MODRDNOUTMASTER2
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
+ echo "comparison failed - modrdn operations did not complete correctly"
+ kill -HUP $PID
+ exit 1
+fi
+
+# Ensure that you cannot find the entry for which the rdn was deleted as
+# an attribute.
+
+echo "Using ldapsearch to retrieve entries using removed rdn (cn=James A Jones 2)..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'cn=James A Jones 2' | egrep -iv '^createtimestamp:|^modifytimestamp:' \
+ > /dev/null 2>&1
+RC=$?
+if test $RC = 0 ; then
+ echo "failure: ldapsearch found attribute that was to be removed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+echo "Using ldapsearch to retrieve all the entries..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'objectClass=*' > $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ kill -HUP $PID
+ echo "ldapsearch failed!"
+ exit $RC
+fi
+
+LDIF=$MODRDNOUTMASTER0
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
+ echo "comparison failed - modrdn operations did not complete correctly"
+ kill -HUP $PID
+ exit 1
+fi
+
+
+echo "Testing modrdn(deleteoldrdn=1), modrdn with new rdn already an att val..."
+$LDAPMODRDN -v -D "$MANAGERDN" -r -h localhost -p $PORT -w $PASSWD > \
+ /dev/null 2>&1 'cn=James A Jones III, ou=Alumni Association, ou=People, o=University of Michigan, c=US' 'cn=James A Jones 1'
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodrdn failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+# Test that you can use modrdn with an attribute value which was previously
+# present
+
+echo "Using ldapsearch to retrieve entries using new rdn (cn=James A Jones 1)..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'cn=James A Jones 1' | egrep -iv '^createtimestamp:|^modifytimestamp:' \
+ > $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+
+LDIF=$MODRDNOUTMASTER3
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+kill -HUP $PID
+if test $? != 0 ; then
+ echo "comparison failed - modrdn operations did not complete correctly"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+
+
+# echo "modrdn test not yet written"
exit 0
-#!/bin/sh
+#! /bin/sh
-. scripts/defines.sh
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
echo "Cleaning up in $DBDIR..."
-rm -f $DBDIR/*
+rm -f $DBDIR/[!C]*
echo "Running ldif2ldbm to build slapd database..."
-$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
+$LDIF2LDBM -f $CONF -l $LDIF
RC=$?
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldif2ldbm failed!"
exit $RC
fi
echo "Starting slapd on TCP/IP port $PORT..."
-$SLAPD -f $ACLCONF -p $PORT -d 1 > /dev/null 2>&1 &
+$SLAPD -f $ACLCONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
PID=$!
echo "Testing slapd access control..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Monitor' > /dev/null 2>&1
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
- if [ $RC = 1 ]; then
+ if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
sleep 5
fi
done
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapsearch failed!"
kill -HUP $PID
exit $RC
# give us nothing if we're not bound, and should return all attributes
# if we're bound as anyone under UM.
#
-$LDAPSEARCH -L -b "$JAJDN" -h localhost -p $PORT "objectclass=*" \
+$LDAPSEARCH -b "$JAJDN" -h localhost -p $PORT "objectclass=*" \
>> $SEARCHOUT 2>&1
-$LDAPSEARCH -L -b "$JAJDN" -h localhost -p $PORT \
+$LDAPSEARCH -b "$JAJDN" -h localhost -p $PORT \
-D "$BABSDN" -w bjensen "objectclass=*" >> $SEARCHOUT 2>&1
# we add our own DN.
# bjensen
$LDAPMODIFY -D "$JAJDN" -h localhost -p $PORT -w jaj > \
- /dev/null 2>&1 << EOMODS1
+ $TESTOUT 2>&1 << EOMODS1
+version: 1
dn: cn=ITD Staff, ou=Groups, o=University of Michigan, c=US
changetype: modify
add: member
EOMODS1
-$LDAPMODIFY -D "$JAJDN" -h localhost -p $PORT -w jaj > \
- /dev/null 2>&1 << EOMODS2
+$LDAPMODIFY -D "$JAJDN" -h localhost -p $PORT -w jaj >> \
+ $TESTOUT 2>&1 << EOMODS2
+version: 1
+
dn: cn=ITD Staff, ou=Groups, o=University of Michigan, c=US
changetype: modify
add: member
member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US
-
EOMODS2
#
# 1) bound as "James A Jones 1" - should fail
# 2) bound as "Barbara Jensen" - should succeed
#
-$LDAPMODIFY -D "$JAJDN" -h localhost -p $PORT -w jaj > \
- /dev/null 2>&1 << EOMODS3
+$LDAPMODIFY -D "$JAJDN" -h localhost -p $PORT -w jaj >> \
+ $TESTOUT 2>&1 << EOMODS3
+
dn: cn=ITD Staff, ou=Groups, o=University of Michigan, c=US
changetype: modify
delete: member
EOMODS3
-$LDAPMODIFY -D "$BJORNSDN" -h localhost -p $PORT -w bjorn > \
- /dev/null 2>&1 << EOMODS4
+$LDAPMODIFY -D "$BJORNSDN" -h localhost -p $PORT -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS4
+# COMMENT
+version: 1
+# comment
dn: cn=ITD Staff, ou=Groups, o=University of Michigan, c=US
+# comment
changetype: modify
+# comment
add: telephonenumber
+# comment
telephonenumber: +1 810 555 1212
-
+# comment
EOMODS4
echo "Using ldapsearch to retrieve all the entries..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'objectClass=*' | egrep -iv '^modifytimestamp|^modifiersname' \
- >> $SEARCHOUT 2>&1
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'objectClass=*' | . $SRCDIR/scripts/acfilter.sh >> $SEARCHOUT 2>&1
RC=$?
kill -HUP $PID
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapsearch failed!"
exit $RC
fi
-echo "Comparing database to reference file"
-cmp $SEARCHOUT $ACLOUTMASTER
-if [ $? != 0 ]; then
+LDIF=$ACLOUTMASTER
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
echo "comparison failed - modify operations did not complete correctly"
exit 1
fi
-#!/bin/sh
+#! /bin/sh
#
# Test replication:
# - retrieve database over ldap and compare against expected results
#
-. scripts/defines.sh
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
+
+if test ! -x $SLURPD ; then
+ echo ">>>>> $SLURPD is not executable or do not exist."
+ echo ">>>>> Test skipped."
+ exit 0
+fi
echo "Cleaning up in $DBDIR..."
-rm -f $DBDIR/*
+rm -f $DBDIR/[!C]*
echo "Cleaning up in $REPLDIR..."
-rm -f $REPLDIR/*
+rm -f $REPLDIR/[!C]*
echo "Starting master slapd on TCP/IP port $PORT..."
-$SLAPD -f $MASTERCONF -p $PORT -d 1 > /dev/null 2>&1 &
+$SLAPD -f $MASTERCONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
PID=$!
echo "Starting slave slapd on TCP/IP port $SLAVEPORT..."
-$SLAPD -f $SLAVECONF -p $SLAVEPORT -d 1 > /dev/null 2>&1 &
+$SLAPD -f $SLAVECONF -p $SLAVEPORT -d $LVL $TIMING > $SLAVELOG 2>&1 &
SLAVEPID=$!
echo "Using ldapsearch to check that master slapd is running..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Monitor' > /dev/null 2>&1
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
- if [ $RC = 1 ]; then
+ if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
sleep 5
fi
echo "Using ldapsearch to check that slave slapd is running..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -b "$BASEDN" -h localhost -p $SLAVEPORT \
- 'cn=Monitor' > /dev/null 2>&1
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
- if [ $RC = 1 ]; then
+ if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
sleep 5
fi
done
echo "Starting slurpd..."
-$SLURPD -f $MASTERCONF -d 4 -t $REPLDIR > /dev/null 2>&1 &
+$SLURPD -f $MASTERCONF -d ${SLURPD_DEBUG-4} -t $REPLDIR > $SLURPLOG 2>&1 &
SLURPPID=$!
-echo "Using ldapmodify to populate the database..."
-$LDAPMODIFY -a -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD < \
+echo "Using ldapadd to populate the master directory..."
+$LDAPADD -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD < \
$LDIFORDERED > /dev/null 2>&1
RC=$?
-if [ $RC != 0 ]; then
- echo "ldapmodify failed!"
+if test $RC != 0 ; then
+ echo "ldapadd failed!"
kill -HUP $PID $SLAVEPID $SLURPPID
exit $RC
fi
-echo "Using ldapmodify to modify the database..."
+echo "Waiting 15 seconds for slurpd to send changes..."
+sleep 15
+
+echo "Using ldapmodify to modify slave directory..."
+
#
# Do some modifications
#
-$LDAPMODIFY -v -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD > \
- /dev/null 2>&1 << EOMODS
+$LDAPMODIFY -v -D "$MANAGERDN" -h localhost -p $SLAVEPORT -w $PASSWD > \
+ $TESTOUT 2>&1 << EOMODS
dn: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US
changetype: modify
add: drink
EOMODS
-echo "Waiting 10 seconds for slurpd to send changes..."
-sleep 10
+echo "Waiting 15 seconds for slurpd to send changes..."
+sleep 15
echo "Using ldapsearch to read all the entries from the master..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
'objectclass=*' > $MASTEROUT 2>&1
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapsearch failed!"
kill -HUP $PID $SLAVEPID $SLURPPID
exit $RC
fi
echo "Using ldapsearch to read all the entries from the slave..."
-$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
'objectclass=*' > $SLAVEOUT 2>&1
-if [ $RC != 0 ]; then
+if test $RC != 0 ; then
echo "ldapsearch failed!"
kill -HUP $PID $SLAVEPID $SLURPPID
exit $RC
kill -HUP $PID $SLAVEPID $SLURPPID
+SEARCHOUT=$MASTEROUT
+LDIF=$SLAVEOUT
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+
echo "Comparing retrieved entries from master and slave..."
-cmp $MASTEROUT $SLAVEOUT
-if [ $? != 0 ]; then
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
echo "test failed - master and slave databases differ"
exit 1
fi
--- /dev/null
+#! /bin/sh
+
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+
+. $SRCDIR/scripts/defines.sh
+
+echo "Datadir is $DATADIR"
+
+echo "Cleaning up in $DBDIR..."
+
+rm -f $DBDIR/[!C]*
+
+echo "Running ldif2ldbm to build slapd database..."
+$LDIF2LDBM -f $CONF -l $LDIF
+RC=$?
+if test $RC != 0 ; then
+ echo "ldif2ldbm failed!"
+ exit $RC
+fi
+
+echo "Waiting 5 seconds for ldif2ldbm to build slapd database..."
+sleep 5
+
+echo "Starting slapd on TCP/IP port $PORT..."
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
+PID=$!
+
+echo "Using ldapsearch to check that slapd is running..."
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 1 ; then
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+ fi
+done
+
+echo "Using tester for concurrent server access..."
+$SLAPDTESTER -b "$BASEDN" -P "$PROGDIR" -d "$DATADIR" -h localhost -p $PORT -D "$MANAGERDN" -w $PASSWD -l 50
+RC=$?
+
+if test $RC != 0 ; then
+ echo "slapd-tester failed!"
+ exit $RC
+fi
+
+echo "Using ldapsearch to retrieve all the entries..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $PORT \
+ 'objectClass=*' > $SEARCHOUT 2>&1
+RC=$?
+
+kill -HUP $PID
+
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ exit $RC
+fi
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
+ echo "comparison failed - database was not created correctly"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+
+exit 0
--- /dev/null
+#! /bin/sh
+
+#
+# Test default referral
+#
+
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
+
+echo "Cleaning up in $DBDIR and $REPLDIR ..."
+
+rm -f $DBDIR/[!C]*
+rm -f $REPLDIR/[!C]*
+
+echo "Running ldif2ldbm to build slapd database..."
+$LDIF2LDBM -f $CONF -l $LDIF
+RC=$?
+if test $RC != 0 ; then
+ echo "ldif2ldbm failed!"
+ exit $RC
+fi
+
+echo "Starting master slapd on TCP/IP port $PORT..."
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
+PID=$!
+
+echo "Starting slave slapd on TCP/IP port $SLAVEPORT..."
+$SLAPD -f $REFSLAVECONF -p $SLAVEPORT -d $LVL $TIMING > $SLAVELOG 2>&1 &
+SLAVEPID=$!
+
+echo "Testing for master slapd..."
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 1 ; then
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+ fi
+done
+
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+echo "Testing for slave slapd..."
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "$MONITOR" -h localhost -p $SLAVEPORT \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 1 ; then
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+ fi
+done
+
+cat /dev/null > $SEARCHOUT
+
+echo "Testing exact searching..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+ 'sn=jensen' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID $SLAVEPID
+ exit $RC
+fi
+
+echo "Testing OR searching..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+ '(|(objectclass=rfc822mailgroup)(sn=jones))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID $SLAVEPID
+ exit $RC
+fi
+
+echo "Testing AND matching and ends-with searching..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+ '(&(objectclass=rfc822mailgroup)(cn=A*))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID $SLAVEPID
+ exit $RC
+fi
+
+echo "Testing NOT searching..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+ '(!(objectclass=person))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID $SLAVEPID
+ exit $RC
+fi
+
+kill -HUP $PID $SLAVEPID
+
+LDIF=$SEARCHOUTMASTER
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+
+exit 0