Merge in all -devel changes made since branch was created.

This commit is contained in:
Kurt Zeilenga 1999-08-19 21:32:17 +00:00
parent fc88ac148f
commit 31e6b38fa7
345 changed files with 78935 additions and 14855 deletions

View file

@ -1,4 +1,29 @@
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

260
INSTALL
View file

@ -1,101 +1,116 @@
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]
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.
4. Build dependencies
% make depend
5. Build the system
% make
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.
If all goes well, the system will build as configured. If not,
return to step 4 after reviewing the configuration settings.
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:
You may want to consult the doc/install/hints file for your
platform.
% sh
$ make
6. Test the standalone system
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
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:
% cd build/platforms/sunos4-cc
% make
If you want to run some simple tests after the build is complete, you
can do this:
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!
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
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
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.
@ -103,34 +118,111 @@ these steps:
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
3. Configure the build system
% [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.
2. move to the new directory and make as for a single platform. Follow steps
1-4 above to accomplish this. For example:
CONFIGURE OPTIONS
% cd obj-sunos4-cc
% make
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.
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
End of LDAP INSTALL file.
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.
* Use software under installed in /usr/local/{include,lib}
[env] \
CPPFLAGS="-I/usr/local/include" \
LDFLAGS="-L/usr/local/lib" \
./configure
End of OpenLDAP INSTALL file.

50
build/dir.mk Normal file
View file

@ -0,0 +1,50 @@
## 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

3992
build/ltmain.sh Executable file

File diff suppressed because it is too large Load diff

680
build/main.dsw Normal file
View file

@ -0,0 +1,680 @@
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>
{{{
}}}
###############################################################################

46
build/man.mk Normal file
View file

@ -0,0 +1,46 @@
## 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

190
build/missing Executable file
View file

@ -0,0 +1,190 @@
#! /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

View file

@ -25,7 +25,11 @@ if test -e $RELNAME ; then
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"

81
build/mod.mk Normal file
View file

@ -0,0 +1,81 @@
## 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

939
build/openldap.m4 Normal file
View file

@ -0,0 +1,939 @@
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

24
build/rules.mk Normal file
View file

@ -0,0 +1,24 @@
## 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

49
build/srv.mk Normal file
View file

@ -0,0 +1,49 @@
## 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

View file

@ -22,16 +22,17 @@ exec_prefix = @exec_prefix@
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@
@ -94,6 +95,7 @@ LDAP_LIBADIR= $(top_builddir)/libraries
LDAP_LIBPATH= -L$(LDAP_LIBADIR)
LUTIL_LIBS = @LUTIL_LIBS@
LDIF_LIBS = @LDIF_LIBS@
LDBM_LIBS = @LDBM_LIBS@
LTHREAD_LIBS = @LTHREAD_LIBS@
@ -119,9 +121,13 @@ AC_LDFLAGS = @LDFLAGS@
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@

View file

@ -0,0 +1,36 @@
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

View file

@ -10,24 +10,34 @@
* is provided ``as is'' without express or implied warranty.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/time.h>
#include <syslog.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sysexits.h>
#include <ldapconfig.h>
#include "portable.h"
#include "lber.h"
#include "ldap.h"
#include <stdio.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>
#endif
#include <ldap.h>
#include "fax500.h"
#include "ldap_defaults.h"
#define USER 0
#define GROUP_ERRORS 1
@ -43,7 +53,6 @@ char *errorsfrom = NULL;
char *mailfrom = NULL;
char *host = NULL;
int hostlen = 0;
char *faxtotpc();
int identity;
#define MAIL500 1
@ -99,27 +108,33 @@ static char *attrs[] = { "objectClass", "title", "postaladdress",
"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;
@ -127,9 +142,6 @@ char **argv;
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 ) {
@ -172,6 +184,10 @@ char **argv;
identity = MAIL500;
}
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
#ifdef LOG_MAIL
openlog( myname, OPENLOG_OPTIONS, LOG_MAIL );
#else
@ -251,7 +267,7 @@ char **argv;
*/
if ( numerr > 0 && numto > nargs || ngroups > 0 ) {
int fd;
FILE *fp;
char buf[BUFSIZ];
umask( 077 );
@ -299,16 +315,21 @@ char **argv;
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 );
}
@ -317,16 +338,17 @@ connect_to_x500()
}
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;
@ -416,7 +438,7 @@ do_address( name, to, nto, togroups, ngroups, err, nerr, type )
/* 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;
}
@ -568,16 +590,17 @@ do_address( name, to, nto, togroups, ngroups, err, nerr, type )
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
@ -606,16 +629,17 @@ do_group( e, dn, to, nto, togroups, ngroups, err, nerr )
}
/* 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;
@ -676,7 +700,10 @@ do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr )
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,
@ -747,7 +774,7 @@ do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr )
add_error( err, nerr,
E_JOINMEMBERNOFAXNUM, ndn,
NULLMSG );
NULL );
free( ndn );
}
@ -765,7 +792,7 @@ do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr )
add_error( err, nerr,
E_JOINMEMBERNOEMAIL, ndn,
NULLMSG );
NULL );
free( ndn );
}
@ -775,21 +802,26 @@ do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr )
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;
@ -802,7 +834,7 @@ add_member( gdn, dn, to, nto, togroups, ngroups, err, nerr )
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 {
@ -852,7 +884,7 @@ add_member( gdn, dn, to, nto, togroups, ngroups, err, nerr )
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 :
@ -864,7 +896,7 @@ add_member( gdn, dn, to, nto, togroups, ngroups, err, nerr )
/* else generate a bounce */
} else {
add_error( err, nerr, E_MEMBERNOEMAIL, ndn, NULLMSG );
add_error( err, nerr, E_MEMBERNOEMAIL, ndn, NULL );
}
free( ndn );
@ -872,13 +904,15 @@ add_member( gdn, dn, to, nto, togroups, ngroups, err, nerr )
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;
@ -888,19 +922,19 @@ do_group_request( e, dn, to, nto, err, nerr )
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;
@ -910,25 +944,22 @@ do_group_errors( e, dn, to, nto, err, nerr )
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 );
@ -944,16 +975,14 @@ send_message( to )
}
}
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
@ -975,8 +1004,8 @@ send_group( group, ngroup )
/* 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 );
@ -994,10 +1023,8 @@ send_group( group, ngroup )
return;
}
static
send_errors( err, nerr )
Error *err;
int nerr;
static void
send_errors( Error *err, int nerr )
{
int i, namelen;
FILE *fp;
@ -1093,12 +1120,8 @@ send_errors( err, nerr )
}
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;
@ -1123,7 +1146,7 @@ do_noemailorfax( fp, err, namelen, errtype )
!= 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;
}
@ -1161,7 +1184,7 @@ do_noemailorfax( fp, err, namelen, errtype )
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] );
@ -1187,11 +1210,8 @@ do_noemailorfax( fp, err, namelen, errtype )
}
/* 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;
@ -1213,7 +1233,7 @@ do_ambiguous( fp, err, namelen )
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;
}
@ -1242,9 +1262,8 @@ do_ambiguous( fp, err, namelen )
}
}
static
count_values( list )
char **list;
static int
count_values( char **list )
{
int i;
@ -1254,11 +1273,8 @@ count_values( list )
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;
@ -1282,9 +1298,8 @@ add_to( list, nlist, new )
return;
}
static
isgroup( e )
LDAPMessage *e;
static int
isgroup( LDAPMessage *e )
{
int i;
char **oclist;
@ -1302,13 +1317,8 @@ isgroup( e )
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) );
@ -1324,11 +1334,8 @@ add_error( err, nerr, code, addr, msg )
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;
@ -1375,9 +1382,8 @@ add_group( dn, list, nlist )
return;
}
static
unbind_and_exit( rc )
int rc;
static void
unbind_and_exit( int rc )
{
int i;
@ -1388,8 +1394,7 @@ unbind_and_exit( rc )
}
static char *
canonical( s )
char *s;
canonical( char *s )
{
char *saves = s;
@ -1401,9 +1406,8 @@ canonical( s )
return( saves );
}
static
group_loop( dn )
char *dn;
static int
group_loop( char *dn )
{
int i;
static char **groups;
@ -1425,11 +1429,8 @@ group_loop( dn )
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;
@ -1447,10 +1448,7 @@ has_attributes( e, attr1, attr2 )
}
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;

View file

@ -10,49 +10,55 @@
* 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;
@ -62,10 +68,7 @@ main (argc, argv)
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 */
@ -107,14 +110,19 @@ main (argc, argv)
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 );
@ -122,7 +130,8 @@ main (argc, argv)
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 )
@ -174,13 +183,12 @@ main (argc, argv)
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;
}
@ -210,7 +218,7 @@ main (argc, argv)
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 );
@ -219,13 +227,13 @@ main (argc, argv)
}
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 );
@ -235,16 +243,14 @@ main (argc, argv)
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 );
@ -253,9 +259,9 @@ print_entry( ld, e )
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" );

View file

@ -0,0 +1,21 @@
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)

View file

@ -10,65 +10,60 @@
* is provided ``as is'' without express or implied warranty.
*/
#include "lber.h"
#include "ldap.h"
#include "disptmpl.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 <sys/resource.h>
#include <sys/wait.h>
#ifdef aix
#include <sys/select.h>
#endif /* aix */
#include <signal.h>
#include "portable.h"
#include "ldapconfig.h"
#ifdef USE_SYSCONF
#include <unistd.h>
#endif /* USE_SYSCONF */
#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/syslog.h>
#include <ac/time.h>
#include <ac/unistd.h>
#include <ac/wait.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <ldap.h>
#include <disptmpl.h>
#include "ldap_defaults.h"
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 ) {
@ -111,9 +106,8 @@ char **argv;
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
@ -128,6 +122,10 @@ char **argv;
else
myname = strdup( myname + 1 );
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
if ( dosyslog ) {
#ifdef LOG_LOCAL4
openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
@ -136,13 +134,12 @@ char **argv;
#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();
@ -150,7 +147,8 @@ char **argv;
return( 0 );
}
static do_query()
static void
do_query( void )
{
char buf[256];
int len, rc, tblsize;
@ -158,25 +156,39 @@ static do_query()
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;
@ -188,11 +200,11 @@ static do_query()
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 );
@ -220,7 +232,7 @@ static do_query()
p = buf;
}
for ( ; *p && isspace( *p ); p++ )
for ( ; *p && isspace( (unsigned char) *p ); p++ )
; /* NULL */
do_search( ld, p );
@ -228,8 +240,7 @@ static do_query()
}
static void
spaces2dots( s )
char *s;
spaces2dots( char *s )
{
for ( ; *s; s++ ) {
if ( *s == ' ' ) {
@ -238,14 +249,14 @@ spaces2dots( 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",
@ -253,7 +264,6 @@ char *buf;
FINGER_SORT_ATTR,
#endif
0 };
extern int strcasecmp();
ufn = 0;
#ifdef FINGER_UFN
@ -267,23 +277,23 @@ char *buf;
!= 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;
@ -294,7 +304,7 @@ char *buf;
{
fprintf( stderr, FINGER_UNAVAILABLE );
ldap_perror( ld, "ldap_search_st" );
exit( 1 );
exit( EXIT_FAILURE );
}
if ( (matches = ldap_count_entries( ld, result )) != 0 )
@ -318,7 +328,7 @@ char *buf;
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 );
@ -365,7 +375,7 @@ char *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;
}
@ -399,15 +409,14 @@ char *buf;
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 };
@ -420,7 +429,7 @@ LDAPMessage *e;
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 ) {

View file

@ -0,0 +1,36 @@
##
## 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)

View file

@ -4,11 +4,7 @@ This directory contains source for two programs:
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:

View file

@ -10,40 +10,51 @@
* is provided ``as is'' without express or implied warranty.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.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>
#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"
#ifdef USE_SYSCONF
#include <unistd.h>
#endif /* USE_SYSCONF */
#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/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>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <ldap.h>
#include <disptmpl.h>
#include "ldap_defaults.h"
#define ldap_debug debug
#include "ldap_log.h"
#include "lutil.h"
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;
@ -51,24 +62,23 @@ 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;
@ -77,15 +87,13 @@ char **argv;
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 ) {
@ -94,7 +102,7 @@ char **argv;
break;
case 'd': /* debug level */
debug = atoi( optarg );
debug |= atoi( optarg );
break;
case 'f': /* ldap filter file */
@ -136,25 +144,42 @@ char **argv;
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 );
@ -170,7 +195,7 @@ char **argv;
s = set_socket( port );
/* arrange to reap children */
(void) signal( SIGCHLD, (void *) wait4child );
(void) SIGNAL( SIGCHLD, wait4child );
} else {
myport = GO500_PORT;
@ -189,13 +214,15 @@ char **argv;
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 ( ;; ) {
@ -216,7 +243,7 @@ char **argv;
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),
@ -230,7 +257,7 @@ char **argv;
switch( pid = fork() ) {
case 0: /* child */
close( s );
tcp_close( s );
do_queries( ns );
break;
@ -239,7 +266,7 @@ char **argv;
break;
default: /* parent */
close( ns );
tcp_close( ns );
if ( debug )
fprintf( stderr, "forked child %d\n", pid );
break;
@ -248,9 +275,8 @@ char **argv;
/* NOT REACHED */
}
static
set_socket( port )
int port;
static int
set_socket( int port )
{
int s, one;
struct sockaddr_in addr;
@ -261,30 +287,41 @@ int port;
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");
@ -292,25 +329,28 @@ int port;
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;
@ -321,7 +361,7 @@ int s;
LDAP *ld;
if ( (fp = fdopen( s, "a+")) == NULL ) {
exit( 1 );
exit( EXIT_FAILURE );
}
timeout.tv_sec = GO500_TIMEOUT;
@ -330,16 +370,16 @@ int s;
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
}
@ -354,32 +394,34 @@ int s;
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 );
}
}
@ -407,16 +449,17 @@ int s;
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;
@ -428,11 +471,8 @@ char *s;
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;
@ -464,7 +504,7 @@ char *buf;
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;
@ -540,16 +580,13 @@ char *buf;
}
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;
@ -559,7 +596,7 @@ char *dn;
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 ) {

View file

@ -10,40 +10,52 @@
* is provided ``as is'' without express or implied warranty.
*/
#include "lber.h"
#include "ldap.h"
#include "disptmpl.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.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>
#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"
#ifdef USE_SYSCONF
#include <unistd.h>
#endif /* USE_SYSCONF */
#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/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>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <ldap.h>
#include <disptmpl.h>
#define ldap_debug debug
#include "ldap_log.h"
#include "lutil.h"
#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;
@ -51,31 +63,35 @@ char *templatefile = TEMPLATEFILE;
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;
@ -84,15 +100,13 @@ char **argv;
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 ) {
@ -101,12 +115,7 @@ char **argv;
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 */
@ -150,11 +159,21 @@ char **argv;
}
}
#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 );
@ -162,19 +181,28 @@ char **argv;
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 );
@ -190,7 +218,7 @@ char **argv;
s = set_socket( port );
/* arrange to reap children */
(void) signal( SIGCHLD, (void *) wait4child );
(void) SIGNAL( SIGCHLD, wait4child );
}
if ( inetd ) {
@ -209,15 +237,17 @@ char **argv;
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 ( ;; ) {
@ -238,7 +268,7 @@ char **argv;
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),
@ -252,7 +282,7 @@ char **argv;
switch( pid = fork() ) {
case 0: /* child */
close( s );
tcp_close( s );
do_queries( ns );
break;
@ -261,7 +291,7 @@ char **argv;
break;
default: /* parent */
close( ns );
tcp_close( ns );
if ( debug )
fprintf( stderr, "forked child %d\n", pid );
break;
@ -270,8 +300,8 @@ char **argv;
/* NOT REACHED */
}
static set_socket( port )
int port;
static int
set_socket( int port )
{
int s, one;
struct sockaddr_in addr;
@ -282,30 +312,41 @@ int port;
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 )
@ -314,36 +355,41 @@ int port;
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" );
(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;
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;
@ -352,16 +398,16 @@ int s;
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
}
@ -376,7 +422,7 @@ int s;
query = buf;
/* strip off leading white space */
while ( isspace( *query )) {
while ( isspace( (unsigned char) *query )) {
++query;
--len;
}
@ -401,31 +447,33 @@ int s;
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++ ) {
@ -434,7 +482,7 @@ int s;
break;
case 'S': /* search */
do_search( ld, fp, query, 1 );
do_search( ld, fp, query );
break;
case 'M': /* X.500 menu */
@ -449,12 +497,12 @@ int s;
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;
@ -471,10 +519,8 @@ char **oclist;
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;
@ -503,14 +549,16 @@ char *dn;
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 )
@ -523,14 +571,12 @@ char *dn;
#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 );
@ -556,20 +602,21 @@ char *dn;
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 ) {
@ -577,7 +624,9 @@ char *dn;
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;
@ -629,9 +678,8 @@ char *dn;
}
}
static isoc( ocl, oc )
char **ocl;
char *oc;
static int
isoc( char **ocl, char *oc )
{
int i;
@ -643,9 +691,8 @@ char *oc;
return( 0 );
}
static int make_scope( ld, dn )
LDAP *ld;
char *dn;
static int
make_scope( LDAP *ld, char *dn )
{
int scope;
char **oc;
@ -676,11 +723,10 @@ char *dn;
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;
@ -693,7 +739,7 @@ char *query;
if ( (filter = strchr( query, '\t' )) == NULL ) {
fprintf( fp, "3Missing filter!\r\n" );
exit( 1 );
exit( EXIT_FAILURE );
}
*filter++ = '\0';
base = query;
@ -704,7 +750,9 @@ char *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 ) {
@ -719,20 +767,21 @@ char *query;
#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;
@ -745,36 +794,37 @@ char *query;
!= 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 );
}
@ -811,15 +861,13 @@ char *query;
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;
@ -828,9 +876,12 @@ char *dn;
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 ) {
@ -838,8 +889,8 @@ char *dn;
}
}
static do_help( op )
FILE *op;
static void
do_help( FILE *op )
{
FILE *fp;
char line[BUFSIZ];
@ -858,9 +909,8 @@ FILE *op;
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" );
@ -876,9 +926,8 @@ char type;
fprintf( fp, ".\r\n" );
}
static do_error( fp, s )
FILE *fp;
char *s;
static void
do_error( FILE *fp, char *s )
{
int code;

View file

@ -13,5 +13,10 @@ localities and are one-level in scope. At the lower levels of the tree
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/

View file

@ -0,0 +1,22 @@
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)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,24 @@
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)

View file

@ -29,16 +29,12 @@ Query message:
.
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':
@ -98,18 +94,18 @@ The search and display behavior is defined in the ldapfilter.conf and
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/

View file

@ -6,59 +6,56 @@
* All Rights Reserved
*/
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
#include <ctype.h>
#include "portable.h"
#include "ldapconfig.h"
#include <stdio.h>
#include <ac/stdlib.h>
#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"
#ifdef ultrix
extern char *strdup();
#endif
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';
@ -78,11 +75,12 @@ main( argc, argv )
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;
@ -114,9 +112,13 @@ main( argc, argv )
}
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
@ -168,10 +170,8 @@ main( argc, argv )
}
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;
@ -231,30 +231,25 @@ read_msg( fp, msgp )
}
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 ) +
@ -262,7 +257,7 @@ read_hdr( fp, offset, buf, MAXSIZEe, linep )
if ( dosyslog ) {
syslog( LOG_ERR, "realloc: %m" );
}
exit( 1 );
exit( EXIT_FAILURE );
}
strcat( hdr, "\n" );
strcat( hdr, *linep );
@ -272,10 +267,8 @@ read_hdr( fp, offset, buf, MAXSIZEe, 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;
@ -353,10 +346,8 @@ send_reply( msgp, body )
}
int
find_command( text, argp )
char *text;
char **argp;
static int
find_command( char *text, char **argp )
{
int i;
char *s, *p;
@ -364,16 +355,16 @@ find_command( text, argp )
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 );

View file

@ -6,48 +6,41 @@
* All Rights Reserved
*/
#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"
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 <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/syslog.h>
#include <ac/time.h>
#include <stdio.h>
#include <ldap.h>
#include <disptmpl.h>
#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;
@ -77,12 +70,12 @@ query_cmd( msgp, reply )
/*
* 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 );
@ -91,9 +84,9 @@ query_cmd( msgp, reply )
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 );
@ -104,17 +97,17 @@ query_cmd( msgp, reply )
/*
* 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 );
@ -133,12 +126,12 @@ query_cmd( msgp, reply )
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 );
@ -170,8 +163,11 @@ query_cmd( msgp, reply )
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" );
}
@ -217,23 +213,20 @@ query_cmd( msgp, reply )
}
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;
@ -269,7 +262,7 @@ append_entry_list( reply, query, ldp, ldmsgp )
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;
@ -294,23 +287,16 @@ append_entry_list( reply, query, ldp, ldmsgp )
}
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 };
@ -318,30 +304,32 @@ do_read( ldp, dn, reply, tmpll )
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';

View file

@ -35,10 +35,14 @@ including: "whois", "search", "look up", "show." You can also send
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:
to requests or other email sent here.
x500@umich.edu
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.

64
clients/tools/Makefile.in Normal file
View file

@ -0,0 +1,64 @@
##
## 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)

View file

@ -1,52 +1,67 @@
/* 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;
int i, rc, authmethod, want_bindpw, version, debug, manageDSAit;
extern char *optarg;
extern int optind;
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;
@ -59,19 +74,22 @@ main( argc, argv )
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 );
@ -82,9 +100,31 @@ main( argc, argv )
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 );
}
}
@ -94,25 +134,66 @@ main( argc, argv )
}
}
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 );
}
}
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
if (( ld = ldap_init( ldaphost, ldapport )) == NULL ) {
perror( "ldap_init" );
return( EXIT_FAILURE );
}
ld->ld_deref = LDAP_DEREF_NEVER; /* prudent, but probably unnecessary */
{
/* 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 ( !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 );
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 ] );
@ -129,18 +210,19 @@ main( argc, argv )
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;
@ -148,7 +230,7 @@ dodelete( ld, dn )
if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_delete" );
} else if ( verbose ) {
printf( "entry removed\n" );
printf( "\tremoved\n" );
}
}

View file

@ -1,40 +1,47 @@
/*
* 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"
@ -42,61 +49,80 @@ extern int ldap_debug, lber_debug;
#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 */
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 );
}
main( argc, argv )
int argc;
char **argv;
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";
int rc, i, use_ldif, authmethod, version, want_bindpw, debug, manageDSAit;
int count;
extern char *optarg;
extern int optind;
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;
@ -111,10 +137,22 @@ main( argc, argv )
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;
@ -127,14 +165,16 @@ main( argc, argv )
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 );
@ -148,66 +188,128 @@ main( argc, argv )
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 */
if ( !kerberos ) {
authmethod = LDAP_AUTH_SIMPLE;
} else if ( kerberos == 1 ) {
authmethod = LDAP_AUTH_KRBV41;
} else {
authmethod = LDAP_AUTH_KRBV4;
/* 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 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;
}
}
@ -218,11 +320,15 @@ main( argc, argv )
}
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 );
}
@ -230,40 +336,45 @@ main( argc, argv )
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;
@ -273,7 +384,7 @@ process_ldif_rec( char *rbuf )
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 );
@ -282,10 +393,19 @@ process_ldif_rec( char *rbuf )
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;
}
@ -295,7 +415,8 @@ process_ldif_rec( char *rbuf )
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 );
@ -307,13 +428,16 @@ process_ldif_rec( char *rbuf )
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;
}
@ -348,27 +472,41 @@ process_ldif_rec( char *rbuf )
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 {
@ -376,6 +514,14 @@ process_ldif_rec( char *rbuf )
}
}
if( linenum == 0 ) {
return 0;
}
if( version && linenum == 1 ) {
return 0;
}
if ( rc == 0 ) {
if ( delete_entry ) {
rc = dodelete( dn );
@ -397,7 +543,7 @@ process_ldif_rec( char *rbuf )
free( newrdn );
}
if ( pmods != NULL ) {
freepmods( pmods );
ldap_mods_free( pmods, 1 );
}
return( rc );
@ -423,7 +569,7 @@ process_ldapmod_rec( char *rbuf )
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;
}
@ -434,7 +580,7 @@ process_ldapmod_rec( char *rbuf )
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 ) {
@ -445,20 +591,21 @@ process_ldapmod_rec( char *rbuf )
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' ) {
@ -468,7 +615,7 @@ process_ldapmod_rec( char *rbuf )
}
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 {
@ -502,7 +649,7 @@ process_ldapmod_rec( char *rbuf )
}
if ( pmods != NULL ) {
freepmods( pmods );
ldap_mods_free( pmods, 1 );
}
if ( dn != NULL ) {
free( dn );
@ -533,22 +680,22 @@ addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
}
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 );
}
}
@ -560,28 +707,28 @@ addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
}
}
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';
@ -597,7 +744,7 @@ domodify( char *dn, LDAPMod **pmods, int newentry )
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 );
}
@ -612,7 +759,7 @@ domodify( char *dn, LDAPMod **pmods, int newentry )
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;
@ -629,9 +776,9 @@ domodify( char *dn, LDAPMod **pmods, int newentry )
}
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 ) {
@ -660,7 +807,7 @@ dodelete( char *dn )
{
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" );
@ -682,12 +829,12 @@ domodrdn( char *dn, char *newrdn, int deleteoldrdn )
{
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 ) {
@ -705,25 +852,6 @@ domodrdn( char *dn, char *newrdn, int deleteoldrdn )
}
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 )
{
@ -744,7 +872,7 @@ 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 );
@ -753,6 +881,8 @@ fromfile( char *path, struct berval *bv )
if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {
perror( path );
fclose( fp );
ber_memfree( bv->bv_val );
bv->bv_val = NULL;
return( -1 );
}
@ -760,9 +890,10 @@ fromfile( char *path, struct berval *bv )
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 );
}
@ -773,25 +904,35 @@ fromfile( char *path, struct berval *bv )
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 );

View file

@ -0,0 +1,104 @@
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>
{{{
}}}
###############################################################################

View file

@ -1,55 +1,83 @@
/* 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;
@ -60,15 +88,22 @@ main( argc, argv )
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 );
@ -85,60 +120,136 @@ main( argc, argv )
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 );
}
}
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
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 (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 ( !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 );
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 */
@ -146,14 +257,14 @@ main( argc, argv )
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;
}
@ -162,29 +273,32 @@ main( argc, argv )
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" );
}

687
clients/tools/ldappasswd.c Normal file
View file

@ -0,0 +1,687 @@
/*
* 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 );
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,101 @@
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>
{{{
}}}
###############################################################################

25
clients/ud/Makefile.in Normal file
View file

@ -0,0 +1,25 @@
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)

View file

@ -10,45 +10,52 @@
* 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>
#endif
#include <lber.h>
#include <ldap.h>
#include <ldapconfig.h>
#include "ldap_defaults.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 */
#ifdef DEBUG
extern int debug; /* debug flag */
#endif
#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];
@ -58,14 +65,6 @@ int implicit;
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)
@ -77,11 +76,26 @@ int implicit;
* 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 ) {
@ -110,7 +124,6 @@ int implicit;
* 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);
@ -130,7 +143,7 @@ int implicit;
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
@ -155,7 +168,7 @@ int implicit;
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
@ -221,37 +234,39 @@ int implicit;
} 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
@ -274,26 +289,24 @@ int implicit;
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 ];
@ -307,12 +320,12 @@ static valid_tgt( names )
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
@ -333,9 +346,7 @@ static char *kauth_name;
/*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;
@ -345,30 +356,28 @@ krbgetpass( user, inst, realm, pw, key )
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 ];
@ -382,12 +391,12 @@ static kinit( kname )
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 );
@ -407,7 +416,8 @@ static kinit( kname )
return( 0 );
}
destroy_tickets()
void
destroy_tickets( void )
{
if ( *tktpath != '\0' ) {
unlink( tktpath );
@ -415,13 +425,10 @@ destroy_tickets()
}
#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);
}

View file

@ -10,40 +10,47 @@
* 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 "ldap_defaults.h"
#include "ud.h"
extern struct entry Entry;
extern int verbose;
extern LDAP *ld;
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)
@ -88,7 +95,7 @@ char *who;
}
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);
}
@ -97,24 +104,23 @@ char *who;
(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)
@ -164,39 +170,50 @@ static load_editor()
++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",
@ -210,12 +227,10 @@ short flag;
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))
@ -228,7 +243,8 @@ short flag;
return(FALSE);
}
static write_entry()
static void
write_entry( void )
{
int i = 0, j, number_of_values = -1;
@ -238,10 +254,6 @@ static write_entry()
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");
@ -255,8 +267,8 @@ static write_entry()
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 ) {
@ -266,7 +278,7 @@ static write_entry()
continue;
}
/* attribute */
while (isspace(*cp))
while (isspace((unsigned char)*cp))
cp++;
/*
* If the number of values is greater than zero, then we
@ -435,8 +447,8 @@ static write_entry()
return;
}
static ovalues(attr)
char *attr;
static int
ovalues( char *attr )
{
struct attribute *ap;

View file

@ -11,30 +11,32 @@
*
*/
#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>
extern void Free();
#include "ldap_defaults.h"
#include "ud.h"
void add_group(name)
char *name;
static char * bind_and_fetch(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,
@ -42,8 +44,6 @@ char *name;
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) {
@ -157,10 +157,9 @@ char *name;
#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);
@ -175,7 +174,7 @@ char *name;
#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");
@ -199,11 +198,10 @@ char *name;
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) {
@ -225,10 +223,12 @@ char *name;
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");
@ -246,15 +246,13 @@ char *name;
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) {
@ -320,9 +318,11 @@ char *name;
#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);
@ -344,8 +344,8 @@ char *name;
return;
}
void bulk_load(group)
char *group;
void
bulk_load( char *group )
{
register int idx_mail, idx_x500;
register int count_mail, count_x500;
@ -452,7 +452,7 @@ char *group;
}
/*
* Add the X.500 style names.
* Add the LDAP style names.
*/
if (count_x500 > 0) {
mods[0] = &mod;
@ -500,15 +500,13 @@ char *group;
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) {
@ -562,7 +560,7 @@ char *group;
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++) {
@ -654,7 +652,8 @@ ask:
return;
}
void tidy_up()
void
tidy_up( void )
{
register int i = 0;
int found_one = 0;
@ -729,14 +728,11 @@ void tidy_up()
* 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;
@ -805,7 +801,7 @@ int offset;
}
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");
}
@ -875,10 +871,10 @@ int offset;
* "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;
@ -903,9 +899,9 @@ int offset;
#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);
@ -922,7 +918,9 @@ int offset;
#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;
@ -960,9 +958,9 @@ int offset;
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);
@ -981,7 +979,9 @@ int offset;
* 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;
}
@ -998,10 +998,8 @@ int offset;
}
}
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;
@ -1020,8 +1018,8 @@ LDAPMod *mods[];
return(rc);
}
void list_groups(who)
char *who;
void
list_groups( char *who )
{
LDAPMessage *mp;
char name[BUFSIZ], filter[BUFSIZ], *search_attrs[2];
@ -1069,7 +1067,7 @@ char *who;
/* 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,
@ -1099,12 +1097,11 @@ char *who;
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) {
@ -1154,8 +1151,8 @@ char *name;
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];
@ -1203,7 +1200,7 @@ char *who;
/* 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);

View file

@ -10,19 +10,22 @@
* 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 */
@ -72,7 +75,7 @@ char *s;
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 */
@ -88,7 +91,7 @@ char *s;
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);
@ -111,7 +114,7 @@ char *s;
}
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");
@ -125,7 +128,7 @@ char *s;
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");
@ -145,7 +148,7 @@ char *s;
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");
@ -182,7 +185,7 @@ char *s;
}
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);

View file

@ -1,3 +1,7 @@
/*
* 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.
@ -16,40 +20,34 @@
* 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.
@ -57,19 +55,19 @@ char copyright[] =
#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 */
@ -84,16 +82,17 @@ LDAPFiltDesc *lfdp; /* LDAP filter descriptor */
#ifdef DEBUG
int debug; /* debug flag */
#endif
int ldebug; /* library debug flag */
main(argc, argv)
int argc;
char *argv[];
#ifndef HAVE_MKVERSION
char Version[] = OPENLDAP_PACKAGE " " OPENLDAP_VERSION " UserDirectory (ud)";
#endif
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;
@ -101,14 +100,11 @@ char *argv[];
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' :
@ -143,10 +139,10 @@ char *argv[];
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 */
}
}
@ -158,26 +154,28 @@ char *argv[];
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)
@ -199,19 +197,19 @@ do_commands()
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;
@ -262,11 +260,14 @@ do_commands()
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();
@ -278,26 +279,34 @@ do_commands()
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);
@ -310,13 +319,15 @@ status()
}
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 */
@ -330,13 +341,9 @@ char **base, *s;
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)
@ -374,7 +381,7 @@ char **base, *s;
}
/*
* 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.
@ -400,7 +407,7 @@ char **base, *s;
*
* sequence now that 'cp' is pointing to the '='.
*/
while(!isspace(*cp))
while(!isspace((unsigned char)*cp))
cp--;
cp++;
/*
@ -426,8 +433,10 @@ char **base, *s;
* 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");
@ -482,7 +491,7 @@ char **base, *s;
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))
@ -492,7 +501,7 @@ char **base, *s;
printbase(output_string, *base);
(void) ldap_msgfree(mp);
for (i = 0; choices[i] != NULL; i++)
Free(choices[i]);
ldap_memfree(choices[i]);
return;
}
}
@ -500,7 +509,7 @@ char **base, *s;
/* 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);
@ -531,27 +540,33 @@ char **base, *s;
}
}
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 {
@ -566,6 +581,9 @@ initialize_client()
config = config_file;
}
}
#else
config = config_file;
#endif /* getpwduid() */
#ifdef DEBUG
if (debug & D_INITIALIZE)
printf("Using config file %s\n", config);
@ -588,7 +606,17 @@ initialize_client()
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;
@ -596,7 +624,7 @@ initialize_client()
}
else if (!strncasecmp(buffer, "base", 4)) {
cp = buffer + 4;
while (isspace(*cp))
while (isspace((unsigned char)*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
@ -604,7 +632,7 @@ initialize_client()
}
else if (!strncasecmp(buffer, "groupbase", 9)) {
cp = buffer + 9;
while (isspace(*cp))
while (isspace((unsigned char)*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
@ -616,30 +644,32 @@ initialize_client()
}
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);
@ -648,11 +678,7 @@ initialize_client()
}
/* 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) {
@ -665,21 +691,18 @@ initialize_client()
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)
@ -688,37 +711,44 @@ initialize_client()
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

View file

@ -10,33 +10,27 @@
* 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 */
@ -46,11 +40,9 @@ char *who;
#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)
@ -106,10 +98,13 @@ char *who;
*/
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");
@ -153,20 +148,22 @@ char *who;
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;
@ -174,7 +171,6 @@ struct attribute attr; /* attribute to change */
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)
@ -372,18 +368,15 @@ struct attribute attr; /* attribute to change */
#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);
@ -481,7 +474,7 @@ mail_is_good:
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);
@ -491,6 +484,7 @@ mail_is_good:
}
tmp = ldap_get_dn(ld, elmp);
strcpy(buffer, tmp);
ldap_memfree(tmp);
(void) ldap_msgfree(lmp);
break;
}
@ -511,7 +505,7 @@ mail_is_good:
* are done.
*/
if (count++ > 1)
(void) strcat(buffer, "$");
(void) strcat(buffer, " $ ");
(void) strcat(buffer, line);
if (!multiline)
break;
@ -537,12 +531,15 @@ mail_is_good:
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];
@ -578,7 +575,7 @@ struct attribute attr; /* boolean attribute to change */
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)) {
@ -596,11 +593,10 @@ struct attribute attr; /* boolean attribute to change */
#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 };
@ -620,9 +616,9 @@ char *who;
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");
}
@ -644,7 +640,7 @@ char *who;
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"))
@ -666,11 +662,10 @@ char *who;
#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++) {
@ -695,15 +690,11 @@ int group;
#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) {
@ -739,22 +730,14 @@ int group;
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");
@ -782,13 +765,13 @@ static char * get_URL()
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*/
}
@ -797,17 +780,25 @@ char *url;
}
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" );

View file

@ -1,7 +1,9 @@
#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.
@ -24,35 +26,27 @@
* 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>
#include <ac/krb.h>
#if defined( DEBUG ) && defined( HAVE_DES_DEBUG )
#define USE_DES_DEBUG
extern int des_debug;
#endif
extern int des_debug;
extern int des_debug_print();
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;
@ -73,7 +67,7 @@ des_string_to_key(str,key)
/* 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 ",
@ -84,7 +78,7 @@ des_string_to_key(str,key)
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
@ -125,13 +119,16 @@ des_string_to_key(str,key)
/* 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
@ -151,10 +148,12 @@ des_string_to_key(str,key)
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;
@ -190,10 +189,12 @@ static void Andrew_StringToKey (str, cell, key)
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];
@ -219,16 +220,19 @@ static void StringToKey (str, cell, key)
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
@ -243,9 +247,7 @@ ka_StringToKey (str, cell, key)
* 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);

View file

@ -10,158 +10,31 @@
* is provided ``as is'' without express or implied warranty.
*/
#include "portable.h"
#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 <ac/stdlib.h>
#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>
#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 "ldap_defaults.h"
#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");
}
/* 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 /* DOS */
}
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)
@ -187,12 +60,9 @@ char *lead, *s;
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;
@ -209,36 +79,35 @@ FILE *where;
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;
@ -266,14 +135,11 @@ isgroup()
* 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)
@ -297,7 +163,7 @@ int width, lead;
*/
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);
@ -305,10 +171,10 @@ int width, lead;
/*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;
@ -322,14 +188,18 @@ int width, lead;
* 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 = "";
@ -364,7 +234,7 @@ int first_indent, indent, width;
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);
@ -380,7 +250,7 @@ int first_indent, indent, width;
* 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--;
/*
@ -398,12 +268,12 @@ int first_indent, indent, width;
* 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);
@ -411,7 +281,7 @@ int first_indent, indent, width;
/*NOTREACHED*/
}
cp = s + width - indent - strlen(tag);
while (!isspace(*cp) && (cp != s))
while (!isspace((unsigned char)*cp) && (cp != s))
cp--;
c = *cp;
*cp = '\0';
@ -424,15 +294,13 @@ int first_indent, indent, width;
#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)
@ -477,7 +345,8 @@ char *cp;
return(tmp);
}
char * code_to_str(i)
char *
code_to_str( int i )
{
switch(i) {
case LDAP_MOD_ADD : return("ADD");
@ -487,10 +356,10 @@ char * code_to_str(i)
}
}
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);
@ -502,28 +371,27 @@ char *s;
#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))
@ -533,13 +401,13 @@ char *s;
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));
@ -548,11 +416,10 @@ char *s;
}
/* 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))
@ -563,11 +430,10 @@ char *s;
}
/* 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))
@ -577,37 +443,30 @@ char *s;
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);
@ -616,22 +475,18 @@ char *s;
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)
@ -641,8 +496,8 @@ char **ptr, *new_value;
}
confirm_action( msg )
char *msg;
int
confirm_action( char *msg )
{
char tmp[SMALL_BUF_SIZE];
int i;

4159
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -46,14 +46,22 @@ AC_PREFIX_DEFAULT(/usr/local)
top_builddir=`pwd`
AC_SUBST(top_builddir)dnl
ldap_subdir="openldap"
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
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
@ -72,6 +80,10 @@ OL_ARG_ENABLE(x_compile,[ --enable-x-compile enable cross compiling],
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],
@ -91,7 +103,9 @@ OL_ARG_ENABLE(slapd,[ --enable-slapd enable building slapd], yes)dnl
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
@ -170,12 +184,18 @@ if test $ol_enable_slapd = no ; then
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
@ -220,7 +240,9 @@ if test $ol_enable_slapd = no ; then
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
@ -315,6 +337,7 @@ AC_MSG_RESULT(done)
## Initialize vars
LDAP_LIBS=
LDIF_LIBS=
LDBM_LIBS=
LTHREAD_LIBS=
LUTIL_LIBS=
@ -330,28 +353,32 @@ BUILD_LDAP=no
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
@ -414,6 +441,7 @@ dnl The default CFLAGS is empty NOT whatever AC_PROG_CC sets.
dnl (for now, let autoconf sort this out)
dnl CFLAGS=${CFLAGS-""}
AC_LIBTOOL_DLOPEN
AC_PROG_LIBTOOL
dnl AC_PROG_MAKE_SET
@ -496,21 +524,18 @@ dnl Check for module support
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`"
dnl should check glib version
ol_link_modules=yes
fi
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
@ -623,27 +648,43 @@ fi
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" = 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 = 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])
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
@ -836,7 +877,7 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \
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 (?)
@ -846,7 +887,7 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \
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)
@ -864,84 +905,48 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \
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])
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_LINK([-lpthread -lmach -lexc -lc_r],
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,
@ -1024,30 +1029,7 @@ dnl [ol_cv_pthread_lpthread_lexc])
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
@ -1595,6 +1577,47 @@ if test $ol_link_termcap = no ; then
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
@ -1713,6 +1736,8 @@ dnl AM_FUNC_MKTIME dnl checks for sys/time.h and unistd.h
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
@ -1816,6 +1841,9 @@ fi
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
@ -1826,6 +1854,8 @@ 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
@ -1835,7 +1865,9 @@ 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
@ -1846,7 +1878,9 @@ if test "$ol_enable_ldap" != no ; then
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
@ -1857,7 +1891,9 @@ if test "$ol_link_ldbm" != no ; then
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
@ -1868,7 +1904,9 @@ if test "$ol_enable_passwd" != no ; then
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
@ -1879,7 +1917,9 @@ if test "$ol_link_perl" != no ; then
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
@ -1890,7 +1930,9 @@ if test "$ol_enable_shell" != no ; then
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
@ -1901,7 +1943,9 @@ if test "$ol_enable_tcl" != no ; then
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
@ -1918,6 +1962,7 @@ AC_SUBST(BUILD_SLAPD)
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)
@ -1930,6 +1975,7 @@ AC_SUBST(BUILD_SLAPD)
AC_SUBST(BUILD_SLURPD)
AC_SUBST(LDAP_LIBS)
AC_SUBST(LDIF_LIBS)
AC_SUBST(SLAPD_LIBS)
AC_SUBST(SLURPD_LIBS)
AC_SUBST(LDBM_LIBS)
@ -1938,14 +1984,17 @@ AC_SUBST(LUTIL_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
@ -1978,13 +2027,13 @@ libraries/libldif/Makefile:build/top.mk:libraries/libldif/Makefile.in:build/lib.
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 \

6
contrib/Makefile.in Normal file
View file

@ -0,0 +1,6 @@
## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved.
## COPYING RESTRICTIONS APPLY, See COPYRIGHT file
##
## contrib Makefile.in for OpenLDAP
SUBDIRS= saucer web_ldap

11
contrib/ldaptcl/CHANGES Normal file
View file

@ -0,0 +1,11 @@
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.)

196
contrib/ldaptcl/Makefile.in Normal file
View file

@ -0,0 +1,196 @@
#
# 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

1742
contrib/ldaptcl/configure vendored Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,225 @@
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)

View file

@ -0,0 +1,33 @@
#
# 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]
}

1112
contrib/ldaptcl/neoXldap.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,23 @@
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

View file

@ -13,22 +13,37 @@
* '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 {
@ -62,15 +77,25 @@ int cmd_quit(char **cmdargv, int cmdargc);
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]",
@ -98,7 +123,7 @@ int bind_user(void)
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++)
@ -128,7 +153,7 @@ int cmd_list(char **cmdargv, int cmdargc)
char *dn = NULL;
int errflag = 0;
int i;
static char *opts[] = { "absolute" };
static const char *const opts[] = { "absolute" };
int relative = 1;
LDAPMessage *result;
@ -176,7 +201,7 @@ int cmd_moveto(char **cmdargv, int cmdargc)
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++) {
@ -252,11 +277,11 @@ int cmd_search(char **cmdargv, int cmdargc)
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++) {
@ -311,10 +336,14 @@ int cmd_search(char **cmdargv, int cmdargc)
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] == '-') {
@ -322,20 +351,22 @@ int cmd_set(char **cmdargv, int cmdargc)
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:
@ -347,11 +378,16 @@ int cmd_set(char **cmdargv, int cmdargc)
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;
}
@ -359,10 +395,9 @@ int cmd_set(char **cmdargv, int cmdargc)
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;
@ -403,7 +438,7 @@ int cmd_show(char **cmdargv, int cmdargc)
return 0;
}
display_search_results(LDAPMessage *result)
void display_search_results(LDAPMessage *result)
{
BerElement *cookie;
int i;
@ -414,7 +449,7 @@ display_search_results(LDAPMessage *result)
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 */
@ -516,13 +551,39 @@ void do_commands(FILE *file)
{
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;
}
}
@ -532,7 +593,7 @@ int is_whitespace(register char *s)
if (!s)
return 1;
while (*s && isspace(*s))
while (*s && isspace((unsigned char) *s))
++s;
return !*s;
@ -541,6 +602,7 @@ int is_whitespace(register char *s)
int main(int argc, char **argv)
{
int error_flag = 0;
int tmp;
FILE *rc;
progname = argv[0];
@ -551,8 +613,9 @@ int main(int argc, char **argv)
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':
@ -571,15 +634,15 @@ int main(int argc, char **argv)
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())
@ -599,7 +662,6 @@ int main(int argc, char **argv)
char *make_dn(char *dn, int relative)
{
static char dn_buf[DN_MAXLEN];
char *s;
if (!dn)
dn = "";
@ -613,7 +675,7 @@ char *make_dn(char *dn, int relative)
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);
}
@ -634,7 +696,7 @@ char *skip_to_whitespace(register char *s)
if (!s)
return s;
while (*s && !isspace(*s))
while (*s && !isspace((unsigned char) *s))
++s;
return s;
@ -645,13 +707,13 @@ char *skip_whitespace(register char *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;

View file

@ -0,0 +1,18 @@
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. <<"

622
contrib/web_ldap/web_ldap.c Normal file
View file

@ -0,0 +1,622 @@
/* 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;
}

View file

@ -0,0 +1,354 @@
<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>
&gt; 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>
&gt; 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>
&gt; chmod 777 web_ldap*
</pre>
<h3>Running the application:</h3>
Test it in your own directory by entering:
<pre>
&gt; 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>
&lt;p&gt;++ 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>
&gt; web_ldap DEF "cn=j*moller"
&gt; 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.

View file

@ -0,0 +1,344 @@
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.

View file

@ -41,8 +41,7 @@
#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)
@ -139,9 +138,10 @@ EXTERN char *banner;
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);

8
doc/drafts/README Normal file
View file

@ -0,0 +1,8 @@
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."

View file

@ -0,0 +1,324 @@
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

View file

@ -0,0 +1,449 @@
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]
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]
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]
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]
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]
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]
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]
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]

View file

@ -0,0 +1,672 @@
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,632 @@
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]

View file

@ -0,0 +1,784 @@
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
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
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
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
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
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
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
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
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
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
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
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
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
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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,774 @@
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]

View file

@ -0,0 +1,220 @@
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
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
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
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

View file

@ -1,20 +1,38 @@
.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
@ -55,44 +73,57 @@ Continuous operation mode. Errors are reported, but
will continue with deletions. The default is to exit after
reporting an error.
.TP
.B \-d debuglevel
.B \-M[M]
Enable manage DSA IT control.
.B \-MM
makes control critical.
.TP
.BI \-d \ debuglevel
Set the LDAP debugging level to \fIdebuglevel\fP.
.B ldapdelete
must be compiled with LDAP_DEBUG defined for this option to have any effect.
.TP
.B \-f file
.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),
@ -107,3 +138,8 @@ Kille, S.,
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.

View file

@ -1,36 +1,68 @@
.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
@ -94,27 +126,39 @@ lines that begin with
(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
@ -189,16 +233,16 @@ Assuming that the file
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
-
@ -212,7 +256,7 @@ the command:
.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
@ -225,8 +269,8 @@ The same modifications as above can be performed using the older
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
@ -243,13 +287,13 @@ Assuming that the file
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:
@ -267,7 +311,7 @@ Assuming that the file
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:
@ -285,6 +329,7 @@ status and a diagnostic message being written to standard error.
.BR ldapdelete (1),
.BR ldapmodrdn (1),
.BR ldapsearch (1),
.BR ldap.conf (5),
.BR ldap (3),
.BR ldap_add (3),
.BR ldap_delete (3),
@ -299,3 +344,8 @@ Kille, S.,
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.

View file

@ -1,20 +1,40 @@
.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
@ -56,6 +76,11 @@ Continuous operation mode. Errors are reported, but ldapmodify
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
@ -67,9 +92,13 @@ Read the entry modification information from \fIfile\fP instead of from
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
@ -78,6 +107,9 @@ Specify an alternate host on which the ldap server is running.
.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.
@ -99,7 +131,7 @@ Assuming that the file
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
@ -120,6 +152,7 @@ status and a diagnostic message being written to standard error.
.BR ldapdelete (1),
.BR ldapmodify (1),
.BR ldapsearch (1),
.BR ldap.conf (5),
.BR ldap (3),
.BR ldap_modrdn2 (3)
.LP
@ -130,3 +163,8 @@ Kille, S.,
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.

View file

@ -1,32 +1,61 @@
.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
@ -43,7 +72,9 @@ If
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
@ -87,18 +118,23 @@ Display search results in
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
@ -110,61 +146,82 @@ normally prints out entries as it receives them. The use of the
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
.B \-z sizelimit
retrieve at most \fIsizelimit\fP seconds for a search to complete.
.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
.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:
@ -187,45 +244,45 @@ is given, only the "attributename" part is written.
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
@ -233,12 +290,12 @@ jpegPhoto=/tmp/ldapsearch-jpegPhoto-a19924
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
@ -275,6 +332,7 @@ status and a diagnostic message being written to standard error.
.BR ldapdelete (1),
.BR ldapmodify (1),
.BR ldapmodrdn (1),
.BR ldap.conf (5),
.BR ldap (3),
.BR ldap_search (3)
.LP
@ -289,3 +347,8 @@ Howes, T.,
.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.

View file

@ -1,4 +1,4 @@
.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
@ -111,7 +111,7 @@ The next line is the default location under which new entries are created.
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
@ -243,7 +243,7 @@ for display of people entries and one for display of contries.
#
# 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
@ -273,3 +273,8 @@ ETCDIR/ldaptemplates.conf
.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.

View file

@ -1,44 +1,37 @@
.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
@ -51,10 +44,10 @@ Multiple attribute values are specified on separate lines, e.g.,
.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
@ -62,6 +55,16 @@ a space" would be encoded like this:
.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
@ -69,22 +72,20 @@ Here is an example of an LDIF file containing three entries.
.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
@ -100,8 +101,12 @@ Notice that the jpegPhoto in Jennifer Jensen's entry is encoded using
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.

View file

@ -1,4 +1,4 @@
.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
@ -10,12 +10,11 @@ contains configuration information for the
.BR slapd (8)
daemon. This configuration file is also used by the
.BR slurpd (8)
replication daemon and by the 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
@ -103,14 +102,43 @@ distinguished name
.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
@ -169,9 +197,10 @@ used in conjunction with the schemacheck option.
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.
@ -186,6 +215,34 @@ meaningful if you are using Kerberos authentication.
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
@ -205,7 +262,7 @@ Controls whether
.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
@ -238,7 +295,10 @@ Specify the DN of an entry that is not subject to access control
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
@ -252,6 +312,12 @@ It specifies the DN allowed to make changes to the replica (typically,
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
@ -267,6 +333,11 @@ Specify the size in bytes of the in-memory cache associated
with each open index file. If not supported by the underlying database
method, this option is ignored without comment. The default is 100000 bytes.
.TP
.B 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
@ -333,8 +404,17 @@ ETCDIR/slapd.conf
.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.

View file

@ -1,8 +1,8 @@
.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...]
@ -16,7 +16,7 @@ tool is used to convert directory data from EDB file format to the
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).
@ -92,8 +92,13 @@ Specify an attribute that should not be converted. You can include as many
.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.

View file

@ -1,61 +0,0 @@
.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"

View file

@ -1,8 +1,8 @@
.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
@ -42,7 +42,12 @@ containing a single value.
.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.

View file

@ -1,113 +0,0 @@
.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"

View file

@ -1,3 +0,0 @@
ldif2index.8
ldif2id2entry.8
ldif2id2children.8

100
doc/man/man8/slapadd.8 Normal file
View file

@ -0,0 +1,100 @@
.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.

89
doc/man/man8/slapcat.8 Normal file
View file

@ -0,0 +1,89 @@
.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.

619
doc/rfc/rfc1488.txt Normal file
View file

@ -0,0 +1,619 @@
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]

283
doc/rfc/rfc2079.txt Normal file
View file

@ -0,0 +1,283 @@
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]
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 "&aring").
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]
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]
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]
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]

731
doc/rfc/rfc2559.txt Normal file
View file

@ -0,0 +1,731 @@
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]

451
doc/rfc/rfc2587.txt Normal file
View file

@ -0,0 +1,451 @@
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]
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]
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]
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]
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]
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]
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]
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]

675
doc/rfc/rfc2589.txt Normal file
View file

@ -0,0 +1,675 @@
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]

507
doc/rfc/rfc2596.txt Normal file
View file

@ -0,0 +1,507 @@
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]
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]
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]
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]
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]
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]
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]
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]
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]

50
include/Makefile.in Normal file
View file

@ -0,0 +1,50 @@
## 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

52
include/ac/assert.h Normal file
View file

@ -0,0 +1,52 @@
/* 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 */

141
include/ac/socket.h Normal file
View file

@ -0,0 +1,141 @@
/*
* 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_ */

33
include/ac/stdlib.h Normal file
View file

@ -0,0 +1,33 @@
/* 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 */

View file

@ -1,4 +1,13 @@
/*
* 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.
*
@ -13,172 +22,468 @@
#ifndef _LBER_H
#define _LBER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <ldap_cdefs.h>
#include <lber_types.h>
#if !defined( NEEDPROTOS ) && defined(__STDC__)
#define NEEDPROTOS 1
#endif
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;
/* "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 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 0x10L /* w/o constructed bit - broken */
#define OLD_LBER_SET 0x11L /* w/o constructed bit - broken */
#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 */
#ifdef NEEDPROTOS
typedef int (*BERTranslateProc)( char **bufp, unsigned long *buflenp,
int free_input );
#else /* NEEDPROTOS */
typedef int (*BERTranslateProc)();
#endif /* NEEDPROTOS */
typedef int (*BERTranslateProc) LDAP_P((
char **bufp,
ber_len_t *buflenp,
int free_input ));
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;
/* 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;
/* get/set options for BerElement */
#define LBER_OPT_BER_OPTIONS 0x01
#define LBER_OPT_BER_DEBUG 0x02
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 */
#define LBER_OPT_DEBUG_LEVEL LBER_OPT_BER_DEBUG
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
#define LBER_OPT_LOG_PRINT_FN 0x8001
#define LBER_OPT_MEMORY_FNS 0x8002
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)
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;
};
} BerValue;
#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 */
/*
* 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 ));
#define LBER_NTOHL( l ) (((long)ntohl( (l) & 0x00000000FFFFFFFF )) << 32 \
| ntohl( ( (l) & 0xFFFFFFFF00000000 ) >> 32 ))
#endif /* __alpha */
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 ));
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 */
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,
... ));
#ifdef __cplusplus
}
#endif
/*
* 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 */

File diff suppressed because it is too large Load diff

83
include/ldap_pvt.h Normal file
View file

@ -0,0 +1,83 @@
/*
* 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

Some files were not shown because too many files have changed in this diff Show more