summaryrefslogtreecommitdiff
path: root/usr/src/lib/libldap4
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libldap4
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libldap4')
-rw-r--r--usr/src/lib/libldap4/Makefile38
-rw-r--r--usr/src/lib/libldap4/Makefile.com103
-rw-r--r--usr/src/lib/libldap4/amd64/Makefile19
-rw-r--r--usr/src/lib/libldap4/ber/Version.c22
-rw-r--r--usr/src/lib/libldap4/ber/bprint.c69
-rw-r--r--usr/src/lib/libldap4/ber/decode.c630
-rw-r--r--usr/src/lib/libldap4/ber/encode.c658
-rw-r--r--usr/src/lib/libldap4/ber/i18n.c27
-rw-r--r--usr/src/lib/libldap4/ber/io.c683
-rw-r--r--usr/src/lib/libldap4/common/Version.c22
-rw-r--r--usr/src/lib/libldap4/common/abandon.c268
-rw-r--r--usr/src/lib/libldap4/common/add.c272
-rw-r--r--usr/src/lib/libldap4/common/addentry.c65
-rw-r--r--usr/src/lib/libldap4/common/bind.c147
-rw-r--r--usr/src/lib/libldap4/common/cache.c716
-rw-r--r--usr/src/lib/libldap4/common/charset.c1871
-rw-r--r--usr/src/lib/libldap4/common/cldap.c599
-rw-r--r--usr/src/lib/libldap4/common/compare.c261
-rw-r--r--usr/src/lib/libldap4/common/controls.c291
-rw-r--r--usr/src/lib/libldap4/common/delete.c205
-rw-r--r--usr/src/lib/libldap4/common/disptmpl.c753
-rw-r--r--usr/src/lib/libldap4/common/dsparse.c216
-rw-r--r--usr/src/lib/libldap4/common/error.c347
-rw-r--r--usr/src/lib/libldap4/common/extensions.c79
-rw-r--r--usr/src/lib/libldap4/common/extop.c156
-rw-r--r--usr/src/lib/libldap4/common/free.c106
-rw-r--r--usr/src/lib/libldap4/common/friendly.c142
-rw-r--r--usr/src/lib/libldap4/common/getattr.c109
-rw-r--r--usr/src/lib/libldap4/common/getdn.c414
-rw-r--r--usr/src/lib/libldap4/common/getdxbyname.c227
-rw-r--r--usr/src/lib/libldap4/common/getentry.c84
-rw-r--r--usr/src/lib/libldap4/common/getfilter.c447
-rw-r--r--usr/src/lib/libldap4/common/getmsg.c40
-rw-r--r--usr/src/lib/libldap4/common/getref.c79
-rw-r--r--usr/src/lib/libldap4/common/getvalues.c183
-rw-r--r--usr/src/lib/libldap4/common/kbind.c351
-rw-r--r--usr/src/lib/libldap4/common/llib-lldap317
-rw-r--r--usr/src/lib/libldap4/common/modify.c248
-rw-r--r--usr/src/lib/libldap4/common/modrdn.c120
-rw-r--r--usr/src/lib/libldap4/common/notif.c106
-rw-r--r--usr/src/lib/libldap4/common/open.c433
-rw-r--r--usr/src/lib/libldap4/common/option.c243
-rw-r--r--usr/src/lib/libldap4/common/os-ip.c614
-rw-r--r--usr/src/lib/libldap4/common/referral.c510
-rw-r--r--usr/src/lib/libldap4/common/regex.c922
-rw-r--r--usr/src/lib/libldap4/common/rename.c176
-rw-r--r--usr/src/lib/libldap4/common/request.c779
-rw-r--r--usr/src/lib/libldap4/common/result.c1657
-rw-r--r--usr/src/lib/libldap4/common/saslbind.c340
-rw-r--r--usr/src/lib/libldap4/common/sbind.c171
-rw-r--r--usr/src/lib/libldap4/common/search.c939
-rw-r--r--usr/src/lib/libldap4/common/sort.c180
-rw-r--r--usr/src/lib/libldap4/common/sortctrl.c426
-rw-r--r--usr/src/lib/libldap4/common/srchpref.c430
-rw-r--r--usr/src/lib/libldap4/common/tmplout.c1176
-rw-r--r--usr/src/lib/libldap4/common/ufn.c594
-rw-r--r--usr/src/lib/libldap4/common/unbind.c216
-rw-r--r--usr/src/lib/libldap4/common/url.c836
-rw-r--r--usr/src/lib/libldap4/common/utils.c27
-rw-r--r--usr/src/lib/libldap4/common/version.c22
-rw-r--r--usr/src/lib/libldap4/common/vlistctrl.c124
-rw-r--r--usr/src/lib/libldap4/i386/Makefile17
-rw-r--r--usr/src/lib/libldap4/include/avl.h65
-rw-r--r--usr/src/lib/libldap4/include/cdefs.h131
-rw-r--r--usr/src/lib/libldap4/include/ch_malloc.h13
-rw-r--r--usr/src/lib/libldap4/include/charray.h24
-rw-r--r--usr/src/lib/libldap4/include/client_door.h15
-rw-r--r--usr/src/lib/libldap4/include/entry.h271
-rw-r--r--usr/src/lib/libldap4/include/fe.h420
-rw-r--r--usr/src/lib/libldap4/include/hsearch.h55
-rw-r--r--usr/src/lib/libldap4/include/lber.h240
-rw-r--r--usr/src/lib/libldap4/include/ldap-int.h343
-rw-r--r--usr/src/lib/libldap4/include/ldap-private.h360
-rw-r--r--usr/src/lib/libldap4/include/ldap.h1375
-rw-r--r--usr/src/lib/libldap4/include/ldapconfig.h280
-rw-r--r--usr/src/lib/libldap4/include/ldif.h65
-rw-r--r--usr/src/lib/libldap4/include/log.h65
-rw-r--r--usr/src/lib/libldap4/include/lthread.h187
-rw-r--r--usr/src/lib/libldap4/include/portable.h224
-rw-r--r--usr/src/lib/libldap4/include/regex.h52
-rw-r--r--usr/src/lib/libldap4/include/sec.h25
-rw-r--r--usr/src/lib/libldap4/include/ssl.h41
-rw-r--r--usr/src/lib/libldap4/include/sysexits-compat.h111
-rw-r--r--usr/src/lib/libldap4/include/thq.h75
-rw-r--r--usr/src/lib/libldap4/misc/ldapfilter.conf111
-rw-r--r--usr/src/lib/libldap4/misc/ldapfriendly248
-rw-r--r--usr/src/lib/libldap4/misc/ldapsearchprefs.conf159
-rw-r--r--usr/src/lib/libldap4/misc/ldaptemplates.conf683
-rw-r--r--usr/src/lib/libldap4/sec/cram_md5.c62
-rw-r--r--usr/src/lib/libldap4/sec/secutil.c63
-rw-r--r--usr/src/lib/libldap4/sparc/Makefile17
-rw-r--r--usr/src/lib/libldap4/sparcv9/Makefile20
-rw-r--r--usr/src/lib/libldap4/spec/Makefile8
-rw-r--r--usr/src/lib/libldap4/spec/Makefile.targ13
-rw-r--r--usr/src/lib/libldap4/spec/amd64/Makefile26
-rw-r--r--usr/src/lib/libldap4/spec/i386/Makefile26
-rw-r--r--usr/src/lib/libldap4/spec/ldap.spec1288
-rw-r--r--usr/src/lib/libldap4/spec/sparc/Makefile26
-rw-r--r--usr/src/lib/libldap4/spec/sparcv9/Makefile27
-rw-r--r--usr/src/lib/libldap4/spec/versions27
-rw-r--r--usr/src/lib/libldap4/util/line64.c388
-rw-r--r--usr/src/lib/libldap4/util/log.c168
102 files changed, 30119 insertions, 0 deletions
diff --git a/usr/src/lib/libldap4/Makefile b/usr/src/lib/libldap4/Makefile
new file mode 100644
index 0000000000..1d83af4be5
--- /dev/null
+++ b/usr/src/lib/libldap4/Makefile
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 1997-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libldap4/Makefile
+
+include ../Makefile.lib
+
+
+SUBDIRS= spec .WAIT $(MACH) $(BUILD64) $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+delete := TARGET= delete
+install := TARGET= install
+lint := TARGET= lint
+catalog := TARGET= catalog
+package := TARGET= package
+
+.KEEP_STATE:
+
+all clean clobber delete install lint catalog package: $(SUBDIRS)
+
+# install rule for install_h target
+$(ROOTHDRDIR)/%: %
+ $(INS.file)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(MACH) $(MACH64) spec: FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/libldap4/Makefile.com b/usr/src/lib/libldap4/Makefile.com
new file mode 100644
index 0000000000..d663656758
--- /dev/null
+++ b/usr/src/lib/libldap4/Makefile.com
@@ -0,0 +1,103 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libldap4/Makefile.com
+#
+
+LIBRARY= libldap.a
+VERS= .4
+
+LDAPOBJS= abandon.o getentry.o referral.o \
+ add.o getfilter.o regex.o \
+ addentry.o getmsg.o rename.o \
+ bind.o getref.o request.o \
+ cache.o getvalues.o result.o \
+ charset.o kbind.o saslbind.o \
+ cldap.o sbind.o compare.o \
+ search.o controls.o sort.o \
+ delete.o srchpref.o disptmpl.o \
+ tmplout.o dsparse.o \
+ error.o ufn.o \
+ extensions.o unbind.o extop.o \
+ url.o \
+ free.o modify.o utils.o \
+ friendly.o modrdn.o notif.o Version.o \
+ getattr.o open.o \
+ getdn.o option.o \
+ getdxbyname.o os-ip.o sortctrl.o \
+ vlistctrl.o
+
+BEROBJS= bprint.o decode.o \
+ encode.o \
+ io.o i18n.o
+
+UTILOBJS= line64.o log.o
+
+
+SECOBJS= cram_md5.o secutil.o
+
+OBJECTS= $(LDAPOBJS) $(BEROBJS) $(UTILOBJS) $(SECOBJS)
+
+include ../../Makefile.lib
+
+LDAPINC= $(SRC)/lib/libldap4/include
+LDAP_FLAGS= -DLDAP_REFERRALS -DCLDAP -DLDAP_DNS -DSUN
+
+MAPFILE= $(MAPDIR)/mapfile
+
+SRCS= $(LDAPOBJS:%.o=../common/%.c) $(BEROBJS:%.o=../ber/%.c) \
+ $(UTILOBJS:%.o=../util/%.c) $(SECOBJS:%.o=../sec/%.c)
+
+LIBS = $(DYNLIB)
+
+$(LINTLIB):= SRCS=../common/llib-lldap
+
+LINTSRC= $(LINTLIB:%.ln=%)
+ROOTLINTDIR= $(ROOTLIBDIR)
+ROOTLINT= $(LINTSRC:%=$(ROOTLINTDIR)/%)
+
+
+CLEANFILES += $(LINTOUT) $(LINTLIB)
+CLOBBERFILES += $(MAPFILE)
+
+# Local Libldap definitions
+
+LOCFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \
+ -DTHREAD_SUNOS5_LWP -DSOUNDEX -DSTR_TRANSLATION \
+ $(LDAP_FLAGS) -I$(LDAPINC)
+
+CPPFLAGS = $(LOCFLAGS) $(CPPFLAGS.master)
+CFLAGS += $(CCVERBOSE)
+DYNFLAGS += -M $(MAPFILE)
+LDLIBS += -lsocket -lnsl -lresolv -lc -lmd5
+
+.KEEP_STATE:
+
+lint: lintcheck
+
+$(DYNLIB): $(MAPFILE)
+
+$(MAPFILE):
+ @cd $(MAPDIR); $(MAKE) mapfile
+
+# include library targets
+include ../../Makefile.targ
+
+objs/%.o pics/%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+objs/%.o pics/%.o: ../ber/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+objs/%.o pics/%.o: ../util/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+objs/%.o pics/%.o: ../sec/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/lib/libldap4/amd64/Makefile b/usr/src/lib/libldap4/amd64/Makefile
new file mode 100644
index 0000000000..f6dbac60d2
--- /dev/null
+++ b/usr/src/lib/libldap4/amd64/Makefile
@@ -0,0 +1,19 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+MAPDIR= ../spec/amd64
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+LIBS = $(DYNLIB)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64)
diff --git a/usr/src/lib/libldap4/ber/Version.c b/usr/src/lib/libldap4/ber/Version.c
new file mode 100644
index 0000000000..ef2e13b7b8
--- /dev/null
+++ b/usr/src/lib/libldap4/ber/Version.c
@@ -0,0 +1,22 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1991 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+static char Version[] = " liblber.a v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";
diff --git a/usr/src/lib/libldap4/ber/bprint.c b/usr/src/lib/libldap4/ber/bprint.c
new file mode 100644
index 0000000000..08edc423a1
--- /dev/null
+++ b/usr/src/lib/libldap4/ber/bprint.c
@@ -0,0 +1,69 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "lber.h"
+
+/*
+ * Print arbitrary stuff, for debugging.
+ */
+
+#ifdef LDAP_DEBUG
+
+#ifndef NO_USERINTERFACE
+#define BPLEN 48
+
+void
+lber_bprint( char *data, int len )
+{
+ static char hexdig[] = "0123456789abcdef";
+ char out[ BPLEN ];
+ int i = 0;
+
+ (void) memset( out, 0, BPLEN );
+ for ( ;; ) {
+ if ( len < 1 ) {
+ (void) fprintf( stderr, "\t%s\n", ( i == 0 ) ? catgets(slapdcat, 1, 72, "(end)") : out );
+ break;
+ }
+
+#ifndef HEX
+ if ( isgraph( (unsigned char)*data )) {
+ out[ i ] = ' ';
+ out[ i+1 ] = *data;
+ } else {
+#endif
+ out[ i ] = hexdig[ ( *data & 0xf0 ) >> 4 ];
+ out[ i+1 ] = hexdig[ *data & 0x0f ];
+#ifndef HEX
+ }
+#endif
+ i += 2;
+ len--;
+ data++;
+
+ if ( i > BPLEN - 2 ) {
+ (void) fprintf( stderr, "\t%s\n", out );
+ (void) memset( out, 0, BPLEN );
+ i = 0;
+ continue;
+ }
+ out[ i++ ] = ' ';
+ }
+}
+#else /* NO_USERINTERFACE */
+void
+lber_bprint( char *data, int len )
+{
+}
+#endif /* NO_USERINTERFACE */
+
+#endif
diff --git a/usr/src/lib/libldap4/ber/decode.c b/usr/src/lib/libldap4/ber/decode.c
new file mode 100644
index 0000000000..5117b3249a
--- /dev/null
+++ b/usr/src/lib/libldap4/ber/decode.c
@@ -0,0 +1,630 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* decode.c - ber input decoding routines */
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#include <stdio.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include <stdarg.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined(NeXT) || defined(VMS)
+#include <stdlib.h>
+#else /* next || vms */
+#include <malloc.h>
+#endif /* next || vms */
+#if defined(BC31) || defined(_WIN32) || defined(__sun)
+#include <stdarg.h>
+#else /* BC31 || _WIN32 */
+#include <varargs.h>
+#endif /* BC31 || _WIN32 */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifdef PCNFS
+#include <tklib.h>
+#endif /* PCNFS */
+#endif /* MACOS */
+
+#if defined( DOS ) || defined( _WIN32 )
+#include "msdos.h"
+#endif /* DOS */
+
+#include <string.h>
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifdef LDAP_DEBUG
+int lber_debug;
+#endif
+
+#ifdef NEEDPROTOS
+static int ber_getnint( BerElement *ber, int *num, int len );
+#endif /* NEEDPROTOS */
+
+
+/* return the tag - LBER_DEFAULT returned means trouble */
+unsigned int
+ber_get_tag( BerElement *ber )
+{
+ unsigned char xbyte;
+ unsigned int tag;
+ char *tagp;
+ int i;
+
+ if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
+ return( LBER_DEFAULT );
+
+ if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
+ return( (unsigned int) xbyte );
+
+ tagp = (char *) &tag;
+ tagp[0] = xbyte;
+ for ( i = 1; i < sizeof(int); i++ ) {
+ if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
+ return( LBER_DEFAULT );
+
+ tagp[i] = xbyte;
+
+ if ( ! (xbyte & LBER_MORE_TAG_MASK) )
+ break;
+ }
+
+ /* tag too big! */
+ if ( i == sizeof(int) )
+ return( LBER_DEFAULT );
+
+ /* want leading, not trailing 0's */
+ return( tag >> (sizeof(int) - i - 1) );
+}
+
+unsigned int
+ber_skip_tag( BerElement *ber, unsigned int *len )
+{
+ unsigned int tag;
+ unsigned char lc;
+ int noctets, diff;
+ unsigned int netlen;
+
+ /*
+ * Any ber element looks like this: tag length contents.
+ * Assuming everything's ok, we return the tag byte (we
+ * can assume a single byte), and return the length in len.
+ *
+ * Assumptions:
+ * 1) definite lengths
+ * 2) primitive encodings used whenever possible
+ */
+
+ /*
+ * First, we read the tag.
+ */
+
+ if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT )
+ return( LBER_DEFAULT );
+
+ /*
+ * Next, read the length. The first byte contains the length of
+ * the length. If bit 8 is set, the length is the int form,
+ * otherwise it's the short form. We don't allow a length that's
+ * greater than what we can hold in an unsigned int.
+ */
+
+ *len = netlen = 0;
+ if ( ber_read( ber, (char *) &lc, 1 ) != 1 )
+ return( LBER_DEFAULT );
+ if ( lc & 0x80 ) {
+ noctets = (lc & 0x7f);
+ if ( noctets > sizeof(unsigned int) )
+ return( LBER_DEFAULT );
+ diff = (int)sizeof(unsigned int) - noctets;
+ if ( ber_read( ber, (char *) &netlen + diff, noctets )
+ != noctets )
+ return( LBER_DEFAULT );
+ *len = LBER_NTOHL( netlen );
+ } else {
+ *len = lc;
+ }
+
+ return( tag );
+}
+
+unsigned int
+ber_peek_tag( BerElement *ber, unsigned int *len )
+{
+ char *save;
+ unsigned int tag;
+
+ save = ber->ber_ptr;
+ tag = ber_skip_tag( ber, len );
+ ber->ber_ptr = save;
+
+ return( tag );
+}
+
+static int
+ber_getnint( BerElement *ber, int *num, int len )
+{ /* New patch much cleaner, from David Wilson, Isode. Old code not kept*/
+ int i;
+ unsigned char buffer[sizeof(int)];
+ int value;
+
+ /*
+ * The tag and length have already been stripped off. We should
+ * be sitting right before len bytes of 2's complement integer,
+ * ready to be read straight into an int.
+ */
+
+ if ( len > sizeof(int) )
+ return( -1 );
+
+ if ( ber_read( ber, (char *) buffer, len ) != len )
+ return( -1 );
+
+ /* This sets the required sign extension */
+ value = 0x80 & buffer[0] ? (-1) : 0;
+
+ for ( i = 0; i < len; i++ )
+ value = (value << 8) | buffer[i];
+
+ *num = value;
+
+ return( len );
+}
+
+unsigned int
+ber_get_int( BerElement *ber, int *num )
+{
+ unsigned int tag, len;
+
+ if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
+ return( LBER_DEFAULT );
+
+ if ( ber_getnint( ber, num, (int)len ) != len )
+ return( LBER_DEFAULT );
+ else
+ return( tag );
+}
+
+unsigned int
+ber_get_stringb( BerElement *ber, char *buf, unsigned int *len )
+{
+ unsigned int datalen, tag;
+#ifdef STR_TRANSLATION
+ char *transbuf;
+#endif /* STR_TRANSLATION */
+
+ if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
+ return( LBER_DEFAULT );
+ if ( datalen > (*len - 1) )
+ return( LBER_DEFAULT );
+
+ if ( ber_read( ber, buf, datalen ) != datalen )
+ return( LBER_DEFAULT );
+
+ buf[datalen] = '\0';
+
+#ifdef STR_TRANSLATION
+ if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
+ && ber->ber_decode_translate_proc != NULL ) {
+ transbuf = buf;
+ ++datalen;
+ if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen,
+ 0 ) != 0 ) {
+ return( LBER_DEFAULT );
+ }
+ if ( datalen > *len ) {
+ free( transbuf );
+ return( LBER_DEFAULT );
+ }
+ (void) SAFEMEMCPY( buf, transbuf, datalen );
+ free( transbuf );
+ --datalen;
+ }
+#endif /* STR_TRANSLATION */
+
+ *len = datalen;
+ return( tag );
+}
+
+unsigned int
+ber_get_stringa( BerElement *ber, char **buf )
+{
+ unsigned int datalen, tag;
+
+ if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
+ return( LBER_DEFAULT );
+
+ if ( (*buf = (char *) malloc( (size_t)datalen + 1 )) == NULL )
+ return( LBER_DEFAULT );
+
+ if ( ber_read( ber, *buf, datalen ) != datalen )
+ return( LBER_DEFAULT );
+ (*buf)[datalen] = '\0';
+
+#ifdef STR_TRANSLATION
+ if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
+ && ber->ber_decode_translate_proc != NULL ) {
+ ++datalen;
+ if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 )
+ != 0 ) {
+ free( *buf );
+ return( LBER_DEFAULT );
+ }
+ }
+#endif /* STR_TRANSLATION */
+
+ return( tag );
+}
+
+unsigned int
+ber_get_stringal( BerElement *ber, struct berval **bv )
+{
+ unsigned int len, tag;
+
+ if ( (*bv = (struct berval *) malloc( sizeof(struct berval) )) == NULL )
+ return( LBER_DEFAULT );
+
+ if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
+ return( LBER_DEFAULT );
+
+ if ( ((*bv)->bv_val = (char *) malloc( (size_t)len + 1 )) == NULL )
+ return( LBER_DEFAULT );
+
+ if ( ber_read( ber, (*bv)->bv_val, len ) != len )
+ return( LBER_DEFAULT );
+ ((*bv)->bv_val)[len] = '\0';
+ (*bv)->bv_len = len;
+
+#ifdef STR_TRANSLATION
+ if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
+ && ber->ber_decode_translate_proc != NULL ) {
+ ++len;
+ if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val),
+ &len, 1 ) != 0 ) {
+ free( (*bv)->bv_val );
+ return( LBER_DEFAULT );
+ }
+ (*bv)->bv_len = len - 1;
+ }
+#endif /* STR_TRANSLATION */
+
+ return( tag );
+}
+
+unsigned int
+ber_get_bitstringa( BerElement *ber, char **buf, unsigned int *blen )
+{
+ unsigned int datalen, tag;
+ unsigned char unusedbits;
+
+ if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
+ return( LBER_DEFAULT );
+ --datalen;
+
+ if ( (*buf = (char *) malloc( (size_t)datalen )) == NULL )
+ return( LBER_DEFAULT );
+
+ if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 )
+ return( LBER_DEFAULT );
+
+ if ( ber_read( ber, *buf, datalen ) != datalen )
+ return( LBER_DEFAULT );
+
+ *blen = datalen * 8 - unusedbits;
+ return( tag );
+}
+
+unsigned int
+ber_get_null( BerElement *ber )
+{
+ unsigned int len, tag;
+
+ if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
+ return( LBER_DEFAULT );
+
+ if ( len != 0 )
+ return( LBER_DEFAULT );
+
+ return( tag );
+}
+
+unsigned int
+ber_get_boolean( BerElement *ber, int *boolval )
+{
+ int longbool;
+ int rc;
+
+ rc = ber_get_int( ber, &longbool );
+ *boolval = longbool;
+
+ return( rc );
+}
+
+unsigned int
+ber_first_element( BerElement *ber, unsigned int *len, char **last )
+{
+ /* skip the sequence header, use the len to mark where to stop */
+ if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) {
+ return( LBER_DEFAULT );
+ }
+
+ *last = ber->ber_ptr + *len;
+
+ if ( *last == ber->ber_ptr ) {
+ return( LBER_DEFAULT );
+ }
+
+ return( ber_peek_tag( ber, len ) );
+}
+
+unsigned int
+ber_next_element( BerElement *ber, unsigned int *len, char *last )
+{
+ if ( ber->ber_ptr == last ) {
+ return( LBER_DEFAULT );
+ }
+
+ return( ber_peek_tag( ber, len ) );
+}
+
+/* VARARGS */
+unsigned int
+ber_scanf(
+#if defined(MACOS) || defined(BC31) || defined(_WIN32) || defined(__sun)
+ BerElement *ber, char *fmt, ... )
+#else
+ va_alist )
+va_dcl
+#endif
+{
+ va_list ap;
+#if !defined(MACOS) && !defined(BC31) && !defined(_WIN32) && !defined(__sun)
+ BerElement *ber;
+ char *fmt;
+#endif
+ char *last;
+ char *s, **ss, ***sss;
+ struct berval ***bv, **bvp, *bval;
+ int *i, j;
+ int *l, rc, tag;
+ unsigned int len;
+
+#if defined(MACOS) || defined(BC31) || defined(_WIN32) || defined(__sun)
+ va_start( ap, fmt );
+#else
+ va_start( ap );
+ ber = va_arg( ap, BerElement * );
+ fmt = va_arg( ap, char * );
+#endif
+
+#ifdef LDAP_DEBUG
+ if ( lber_debug & 64 ) {
+ (void) fprintf( stderr, catgets(slapdcat, 1, 73, "ber_scanf fmt (%s) ber:\n"), fmt );
+ ber_dump( ber, 1 );
+ }
+#endif
+
+ for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) {
+ switch ( *fmt ) {
+ case 'a': /* octet string - allocate storage as needed */
+ ss = va_arg( ap, char ** );
+ rc = ber_get_stringa( ber, ss );
+ break;
+
+ case 'b': /* boolean */
+ i = va_arg( ap, int * );
+ rc = ber_get_boolean( ber, i );
+ break;
+
+ case 'e': /* enumerated */
+ case 'i': /* int */
+ l = va_arg( ap, int * );
+ rc = ber_get_int( ber, l );
+ break;
+
+ case 'l': /* length of next item */
+ l = va_arg( ap, int * );
+ rc = ber_peek_tag( ber, (unsigned int *)l );
+ break;
+
+ case 'n': /* null */
+ rc = ber_get_null( ber );
+ break;
+
+ case 's': /* octet string - in a buffer */
+ s = va_arg( ap, char * );
+ l = va_arg( ap, int * );
+ rc = ber_get_stringb( ber, s, (unsigned int *)l );
+ break;
+
+ case 'o': /* octet string in a supplied berval */
+ bval = va_arg( ap, struct berval * );
+ ber_peek_tag( ber, &bval->bv_len );
+ rc = ber_get_stringa( ber, &bval->bv_val );
+ break;
+
+ case 'O': /* octet string - allocate & include length */
+ bvp = va_arg( ap, struct berval ** );
+ rc = ber_get_stringal( ber, bvp );
+ break;
+
+ case 'B': /* bit string - allocate storage as needed */
+ ss = va_arg( ap, char ** );
+ l = va_arg( ap, int * ); /* for length, in bits */
+ rc = ber_get_bitstringa( ber, ss, (unsigned int *)l );
+ break;
+
+ case 't': /* tag of next item */
+ i = va_arg( ap, int * );
+ *i = rc = ber_peek_tag( ber, &len );
+ break;
+
+ case 'T': /* skip tag of next item */
+ i = va_arg( ap, int * );
+ *i = rc = ber_skip_tag( ber, &len );
+ break;
+
+ case 'v': /* sequence of strings */
+ sss = va_arg( ap, char *** );
+ *sss = NULL;
+ j = 0;
+ for ( tag = ber_first_element( ber, &len, &last );
+ tag != LBER_DEFAULT && rc != LBER_DEFAULT;
+ tag = ber_next_element( ber, &len, last ) ) {
+ if ( *sss == NULL ) {
+ *sss = (char **) malloc(
+ 2 * sizeof(char *) );
+ } else {
+ *sss = (char **) realloc( *sss,
+ (j + 2) * sizeof(char *) );
+ }
+ rc = ber_get_stringa( ber, &((*sss)[j]) );
+ j++;
+ }
+ if ( j > 0 )
+ (*sss)[j] = NULL;
+ break;
+
+ case 'V': /* sequence of strings + lengths */
+ bv = va_arg( ap, struct berval *** );
+ *bv = NULL;
+ j = 0;
+ for ( tag = ber_first_element( ber, &len, &last );
+ tag != LBER_DEFAULT && rc != LBER_DEFAULT;
+ tag = ber_next_element( ber, &len, last ) ) {
+ if ( *bv == NULL ) {
+ *bv = (struct berval **) malloc(
+ 2 * sizeof(struct berval *) );
+ } else {
+ *bv = (struct berval **) realloc( *bv,
+ (j + 2) * sizeof(struct berval *) );
+ }
+ rc = ber_get_stringal( ber, &((*bv)[j]) );
+ j++;
+ }
+ if ( j > 0 )
+ (*bv)[j] = NULL;
+ break;
+
+ case 'x': /* skip the next element - whatever it is */
+ if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
+ break;
+ ber->ber_ptr += len;
+ break;
+
+ case '{': /* begin sequence */
+ case '[': /* begin set */
+ if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V' )
+ rc = ber_skip_tag( ber, &len );
+ break;
+
+ case '}': /* end sequence */
+ case ']': /* end set */
+ break;
+
+ default:
+#ifndef NO_USERINTERFACE
+ (void) fprintf( stderr, catgets(slapdcat, 1, 74, "unknown fmt %c\n"), *fmt );
+#endif /* NO_USERINTERFACE */
+ rc = (int) LBER_DEFAULT;
+ break;
+ }
+ }
+
+ va_end( ap );
+
+ return( rc );
+}
+
+void
+ber_bvfree( struct berval *bv )
+{
+ if ( bv->bv_val != NULL )
+ free( bv->bv_val );
+ free( (char *) bv );
+}
+
+void
+ber_bvecfree( struct berval **bv )
+{
+ int i;
+
+ for ( i = 0; bv[i] != NULL; i++ )
+ ber_bvfree( bv[i] );
+ free( (char *) bv );
+}
+
+struct berval *
+ber_bvdup( struct berval *bv )
+{
+ struct berval *new;
+
+ if ( (new = (struct berval *) malloc( sizeof(struct berval) ))
+ == NULL ) {
+ return( NULL );
+ }
+ if ( (new->bv_val = (char *) malloc( bv->bv_len + 1 )) == NULL ) {
+ free(new);
+ return( NULL );
+ }
+ SAFEMEMCPY( new->bv_val, bv->bv_val, (size_t) bv->bv_len );
+ new->bv_val[bv->bv_len] = '\0';
+ new->bv_len = bv->bv_len;
+
+ return( new );
+}
+
+
+#ifdef STR_TRANSLATION
+void
+ber_set_string_translators( BerElement *ber, BERTranslateProc encode_proc,
+ BERTranslateProc decode_proc )
+{
+ ber->ber_encode_translate_proc = encode_proc;
+ ber->ber_decode_translate_proc = decode_proc;
+}
+#endif /* STR_TRANSLATION */
+
+int ber_flatten(BerElement *ber, struct berval **bvPtr)
+{
+ struct berval * bv;
+ int len;
+
+ if ((ber == NULL) || (ber->ber_buf == NULL))
+ return (-1);
+
+ len = ber->ber_ptr - ber->ber_buf;
+
+ if ((bv = (struct berval *)malloc(sizeof(struct berval))) == NULL)
+ return (-1);
+ if ((bv->bv_val = (char *) malloc(len + 1)) == NULL) {
+ free(bv);
+ return (-1);
+ }
+
+ SAFEMEMCPY(bv->bv_val, ber->ber_buf, (size_t)len);
+ bv->bv_val[len] = '\0';
+ bv->bv_len = len;
+
+ *bvPtr = bv;
+ return (0);
+}
diff --git a/usr/src/lib/libldap4/ber/encode.c b/usr/src/lib/libldap4/ber/encode.c
new file mode 100644
index 0000000000..f296d52053
--- /dev/null
+++ b/usr/src/lib/libldap4/ber/encode.c
@@ -0,0 +1,658 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* encode.c - ber output encoding routines */
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#include <stdio.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include <stdarg.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined(NeXT) || defined(VMS)
+#include <stdlib.h>
+#else /* next || vms */
+#include <malloc.h>
+#endif /* next || vms */
+#if defined( BC31 ) || defined( _WIN32 ) || defined(__sun)
+#include <stdarg.h>
+#else /* BC31 || _WIN32 */
+#include <varargs.h>
+#endif /* BC31 || _WIN32 */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifdef PCNFS
+#include <tklib.h>
+#endif /* PCNFS */
+#endif /* MACOS */
+#ifndef VMS
+#include <memory.h>
+#endif
+#include <string.h>
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#if defined( DOS ) || defined( _WIN32 )
+#include "msdos.h"
+#endif /* DOS */
+
+#ifdef NEEDPROTOS
+static int ber_put_len( BerElement *ber, unsigned int len, int nosos );
+static int ber_start_seqorset( BerElement *ber, unsigned int tag );
+static int ber_put_seqorset( BerElement *ber );
+static int ber_put_int_or_enum( BerElement *ber, int num, unsigned int tag );
+#endif /* NEEDPROTOS */
+
+extern int ber_realloc(BerElement *ber, unsigned int len);
+
+static int
+ber_calc_taglen( unsigned int tag )
+{
+ int i;
+ int mask;
+
+ /* find the first non-all-zero byte in the tag */
+ for ( i = sizeof(int) - 1; i > 0; i-- ) {
+ mask = (0xffL << (i * 8));
+ /* not all zero */
+ if ( tag & mask )
+ break;
+ }
+
+ return( i + 1 );
+}
+
+static int
+ber_put_tag( BerElement *ber, unsigned int tag, int nosos )
+{
+ int taglen;
+ unsigned int ntag;
+
+ taglen = ber_calc_taglen( tag );
+
+ ntag = LBER_HTONL( tag );
+
+ return( ber_write( ber, ((char *) &ntag) + sizeof(int) - taglen,
+ taglen, nosos ) );
+}
+
+static int
+ber_calc_lenlen( unsigned int len )
+{
+ /*
+ * short len if it's less than 128 - one byte giving the len,
+ * with bit 8 0.
+ */
+
+ if ( len <= 0x7F )
+ return( 1 );
+
+ /*
+ * int len otherwise - one byte with bit 8 set, giving the
+ * length of the length, followed by the length itself.
+ */
+
+ if ( len <= 0xFF )
+ return( 2 );
+ if ( len <= 0xFFFF )
+ return( 3 );
+ if ( len <= 0xFFFFFF )
+ return( 4 );
+
+ return( 5 );
+}
+
+static int
+ber_put_len( BerElement *ber, unsigned int len, int nosos )
+{
+ int i;
+ char lenlen;
+ int mask;
+ unsigned int netlen;
+
+ /*
+ * short len if it's less than 128 - one byte giving the len,
+ * with bit 8 0.
+ */
+
+ if ( len <= 127 ) {
+ netlen = LBER_HTONL( len );
+ return( ber_write( ber, (char *) &netlen + sizeof(int) - 1,
+ 1, nosos ) );
+ }
+
+ /*
+ * int len otherwise - one byte with bit 8 set, giving the
+ * length of the length, followed by the length itself.
+ */
+
+ /* find the first non-all-zero byte */
+ for ( i = sizeof(int) - 1; i > 0; i-- ) {
+ mask = (0xff << (i * 8));
+ /* not all zero */
+ if ( len & mask )
+ break;
+ }
+ lenlen = ++i;
+ if ( lenlen > 4 )
+ return( -1 );
+ lenlen |= 0x80;
+
+ /* write the length of the length */
+ if ( ber_write( ber, &lenlen, 1, nosos ) != 1 )
+ return( -1 );
+
+ /* write the length itself */
+ netlen = LBER_HTONL( len );
+ if ( ber_write( ber, (char *) &netlen + (sizeof(int) - i), i, nosos )
+ != i )
+ return( -1 );
+
+ return( i + 1 );
+}
+
+static int
+ber_put_int_or_enum( BerElement *ber, int num, unsigned int tag )
+{
+ int i, sign, taglen;
+ int len, lenlen;
+ int netnum, mask;
+
+ sign = (num < 0);
+
+ /*
+ * high bit is set - look for first non-all-one byte
+ * high bit is clear - look for first non-all-zero byte
+ */
+ for ( i = sizeof(int) - 1; i > 0; i-- ) {
+ mask = (0xff << (i * 8));
+
+ if ( sign ) {
+ /* not all ones */
+ if ( (num & mask) != mask )
+ break;
+ } else {
+ /* not all zero */
+ if ( num & mask )
+ break;
+ }
+ }
+
+ /*
+ * we now have the "leading byte". if the high bit on this
+ * byte matches the sign bit, we need to "back up" a byte.
+ */
+ mask = (num & (0x80 << (i * 8)));
+ if ( (mask && !sign) || (sign && !mask) )
+ i++;
+
+ len = i + 1;
+
+ if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
+ return( -1 );
+
+ if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 )
+ return( -1 );
+ i++;
+ netnum = LBER_HTONL( num );
+ if ( ber_write( ber, (char *) &netnum + (sizeof(int) - i), i, 0 )
+ != i )
+ return( -1 );
+
+ /* length of tag + length + contents */
+ return( taglen + lenlen + i );
+}
+
+int
+ber_put_enum( BerElement *ber, int num, unsigned int tag )
+{
+ if ( tag == LBER_DEFAULT )
+ tag = LBER_ENUMERATED;
+
+ return( ber_put_int_or_enum( ber, num, tag ) );
+}
+
+int
+ber_put_int( BerElement *ber, int num, unsigned int tag )
+{
+ if ( tag == LBER_DEFAULT )
+ tag = LBER_INTEGER;
+
+ return( ber_put_int_or_enum( ber, num, tag ) );
+}
+
+int
+ber_put_ostring( BerElement *ber, char *str, unsigned int len,
+ unsigned int tag )
+{
+ int taglen, lenlen, rc;
+#ifdef STR_TRANSLATION
+ int free_str;
+#endif /* STR_TRANSLATION */
+
+ if ( tag == LBER_DEFAULT )
+ tag = LBER_OCTETSTRING;
+
+ if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
+ return( -1 );
+
+#ifdef STR_TRANSLATION
+ if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0 &&
+ ber->ber_encode_translate_proc != NULL ) {
+ if ( (*(ber->ber_encode_translate_proc))( &str, &len, 0 )
+ != 0 ) {
+ return( -1 );
+ }
+ free_str = 1;
+ } else {
+ free_str = 0;
+ }
+#endif /* STR_TRANSLATION */
+
+ if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ||
+ ber_write( ber, str, len, 0 ) != len ) {
+ rc = -1;
+ } else {
+ /* return length of tag + length + contents */
+ rc = taglen + lenlen + len;
+ }
+
+#ifdef STR_TRANSLATION
+ if ( free_str ) {
+ free( str );
+ }
+#endif /* STR_TRANSLATION */
+
+ return( rc );
+}
+
+int
+ber_put_string( BerElement *ber, char *str, unsigned int tag )
+{
+ return( ber_put_ostring( ber, str, (unsigned int)strlen( str ), tag ));
+}
+
+int
+ber_put_bitstring( BerElement *ber, char *str,
+ unsigned int blen /* in bits */, unsigned int tag )
+{
+ int taglen, lenlen, len;
+ unsigned char unusedbits;
+
+ if ( tag == LBER_DEFAULT )
+ tag = LBER_BITSTRING;
+
+ if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
+ return( -1 );
+
+ len = ( blen + 7 ) / 8;
+ unusedbits = len * 8 - blen;
+ if ( (lenlen = ber_put_len( ber, len + 1, 0 )) == -1 )
+ return( -1 );
+
+ if ( ber_write( ber, (char *)&unusedbits, 1, 0 ) != 1 )
+ return( -1 );
+
+ if ( ber_write( ber, str, len, 0 ) != len )
+ return( -1 );
+
+ /* return length of tag + length + unused bit count + contents */
+ return( taglen + 1 + lenlen + len );
+}
+
+int
+ber_put_null( BerElement *ber, unsigned int tag )
+{
+ int taglen;
+
+ if ( tag == LBER_DEFAULT )
+ tag = LBER_NULL;
+
+ if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
+ return( -1 );
+
+ if ( ber_put_len( ber, 0, 0 ) != 1 )
+ return( -1 );
+
+ return( taglen + 1 );
+}
+
+int
+ber_put_boolean( BerElement *ber, int boolval, unsigned int tag )
+{
+ int taglen;
+ unsigned char trueval = 0xff;
+ unsigned char falseval = 0x00;
+
+ if ( tag == LBER_DEFAULT )
+ tag = LBER_BOOLEAN;
+
+ if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
+ return( -1 );
+
+ if ( ber_put_len( ber, 1, 0 ) != 1 )
+ return( -1 );
+
+ if ( ber_write( ber, (char *)(boolval ? &trueval : &falseval), 1, 0 )
+ != 1 )
+ return( -1 );
+
+ return( taglen + 2 );
+}
+
+#define FOUR_BYTE_LEN 5
+
+static int
+ber_start_seqorset( BerElement *ber, unsigned int tag )
+{
+ Seqorset *new;
+
+ if ( (new = (Seqorset *) calloc( sizeof(Seqorset), 1 ))
+ == NULLSEQORSET )
+ return( -1 );
+ new->sos_ber = ber;
+ if ( ber->ber_sos == NULLSEQORSET )
+ new->sos_first = ber->ber_ptr;
+ else
+ new->sos_first = ber->ber_sos->sos_ptr;
+
+ /* Set aside room for a 4 byte length field */
+ new->sos_ptr = new->sos_first + ber_calc_taglen( tag ) + FOUR_BYTE_LEN;
+ new->sos_tag = tag;
+
+ new->sos_next = ber->ber_sos;
+ ber->ber_sos = new;
+ if (ber->ber_sos->sos_ptr > ber->ber_end)
+ ber_realloc(ber, ber->ber_sos->sos_ptr - ber->ber_end);
+
+ return( 0 );
+}
+
+int
+ber_start_seq( BerElement *ber, unsigned int tag )
+{
+ if ( tag == LBER_DEFAULT )
+ tag = LBER_SEQUENCE;
+
+ return( ber_start_seqorset( ber, tag ) );
+}
+
+int
+ber_start_set( BerElement *ber, unsigned int tag )
+{
+ if ( tag == LBER_DEFAULT )
+ tag = LBER_SET;
+
+ return( ber_start_seqorset( ber, tag ) );
+}
+
+static int
+ber_put_seqorset( BerElement *ber )
+{
+ unsigned int len, netlen;
+ int taglen, lenlen;
+ unsigned char ltag = 0x80 + FOUR_BYTE_LEN - 1;
+ Seqorset *next;
+ Seqorset **sos = &ber->ber_sos;
+
+ /*
+ * If this is the toplevel sequence or set, we need to actually
+ * write the stuff out. Otherwise, it's already been put in
+ * the appropriate buffer and will be written when the toplevel
+ * one is written. In this case all we need to do is update the
+ * length and tag.
+ */
+
+ len = (*sos)->sos_clen;
+ netlen = LBER_HTONL( len );
+ /* CONSTCOND */
+ if ( sizeof(int) > 4 && len > 0xFFFFFFFF )
+ return( -1 );
+
+ if ( ber->ber_options & LBER_USE_DER ) {
+ lenlen = ber_calc_lenlen( len );
+ } else {
+ lenlen = FOUR_BYTE_LEN;
+ }
+
+ if ( (next = (*sos)->sos_next) == NULLSEQORSET ) {
+ /* write the tag */
+ if ( (taglen = ber_put_tag( ber, (*sos)->sos_tag, 1 )) == -1 )
+ return( -1 );
+
+ if ( ber->ber_options & LBER_USE_DER ) {
+ /* Write the length in the minimum # of octets */
+ if ( ber_put_len( ber, len, 1 ) == -1 )
+ return( -1 );
+
+ if (lenlen != FOUR_BYTE_LEN) {
+ /*
+ * We set aside FOUR_BYTE_LEN bytes for
+ * the length field. Move the data if
+ * we don't actually need that much
+ */
+ (void) SAFEMEMCPY( (*sos)->sos_first + taglen +
+ lenlen, (*sos)->sos_first + taglen +
+ FOUR_BYTE_LEN, len );
+ }
+ } else {
+ /* Fill FOUR_BYTE_LEN bytes for length field */
+ /* one byte of length length */
+ if ( ber_write( ber, (char *)&ltag, 1, 1 ) != 1 )
+ return( -1 );
+
+ /* the length itself */
+ if ( ber_write( ber, (char *) &netlen + sizeof(int)
+ - (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1, 1 )
+ != FOUR_BYTE_LEN - 1 )
+ return( -1 );
+ }
+ /* The ber_ptr is at the set/seq start - move it to the end */
+ (*sos)->sos_ber->ber_ptr += len;
+ } else {
+ unsigned int ntag;
+
+ /* the tag */
+ taglen = ber_calc_taglen( (*sos)->sos_tag );
+ ntag = LBER_HTONL( (*sos)->sos_tag );
+ (void) SAFEMEMCPY( (*sos)->sos_first, (char *) &ntag +
+ sizeof(int) - taglen, taglen );
+
+ if ( ber->ber_options & LBER_USE_DER ) {
+ ltag = (lenlen == 1) ? len : 0x80 + (lenlen - 1);
+ }
+
+ /* one byte of length length */
+ (void) SAFEMEMCPY( (*sos)->sos_first + 1, &ltag, 1 );
+
+ if ( ber->ber_options & LBER_USE_DER ) {
+ if (lenlen > 1) {
+ /* Write the length itself */
+ (void) SAFEMEMCPY( (*sos)->sos_first + 2,
+ (char *)&netlen + sizeof(unsigned int) -
+ (lenlen - 1),
+ lenlen - 1 );
+ }
+ if (lenlen != FOUR_BYTE_LEN) {
+ /*
+ * We set aside FOUR_BYTE_LEN bytes for
+ * the length field. Move the data if
+ * we don't actually need that much
+ */
+ (void) SAFEMEMCPY( (*sos)->sos_first + taglen +
+ lenlen, (*sos)->sos_first + taglen +
+ FOUR_BYTE_LEN, len );
+ }
+ } else {
+ /* the length itself */
+ (void) SAFEMEMCPY( (*sos)->sos_first + taglen + 1,
+ (char *) &netlen + sizeof(int) -
+ (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1 );
+ }
+
+ next->sos_clen += (taglen + lenlen + len);
+ next->sos_ptr += (taglen + lenlen + len);
+ }
+
+ /* we're done with this seqorset, so free it up */
+ free( (char *) (*sos) );
+ *sos = next;
+
+ return( taglen + lenlen + len );
+}
+
+int
+ber_put_seq( BerElement *ber )
+{
+ return( ber_put_seqorset( ber ) );
+}
+
+int
+ber_put_set( BerElement *ber )
+{
+ return( ber_put_seqorset( ber ) );
+}
+
+/* VARARGS */
+int
+ber_printf(
+#if defined(MACOS) || defined(_WIN32) || defined(BC31) || defined(__sun)
+ BerElement *ber, char *fmt, ... )
+#else /* MACOS || _WIN32 || BC31 */
+ va_alist )
+va_dcl
+#endif /* MACOS || _WIN32 || BC31 */
+{
+ va_list ap;
+#if !defined(MACOS) && !defined(_WIN32) && !defined(BC31) && !defined(__sun)
+ BerElement *ber;
+ char *fmt;
+#endif /* !MACOS && !_WIN32 && !BC31 */
+ char *s, **ss;
+ struct berval **bv;
+ int rc, i;
+ unsigned int len;
+
+#if defined(MACOS) || defined(_WIN32) || defined(BC31) || defined(__sun)
+ va_start( ap, fmt );
+#else /* MACOS || _WIN32 || BC31 */
+ va_start( ap );
+ ber = va_arg( ap, BerElement * );
+ fmt = va_arg( ap, char * );
+#endif /* MACOS || _WIN32 || BC31 */
+
+ for ( rc = 0; *fmt && rc != -1; fmt++ ) {
+ switch ( *fmt ) {
+ case 'b': /* boolean */
+ i = va_arg( ap, int );
+ rc = ber_put_boolean( ber, i, ber->ber_tag );
+ break;
+
+ case 'i': /* int */
+ i = va_arg( ap, int );
+ rc = ber_put_int( ber, i, ber->ber_tag );
+ break;
+
+ case 'e': /* enumeration */
+ i = va_arg( ap, int );
+ rc = ber_put_enum( ber, i, ber->ber_tag );
+ break;
+
+ case 'n': /* null */
+ rc = ber_put_null( ber, ber->ber_tag );
+ break;
+
+ case 'o': /* octet string (non-null terminated) */
+ s = va_arg( ap, char * );
+ len = va_arg( ap, int );
+ rc = ber_put_ostring( ber, s, len, ber->ber_tag );
+ break;
+
+ case 's': /* string */
+ s = va_arg( ap, char * );
+ rc = ber_put_string( ber, s, ber->ber_tag );
+ break;
+
+ case 'B': /* bit string */
+ s = va_arg( ap, char * );
+ len = va_arg( ap, int ); /* in bits */
+ rc = ber_put_bitstring( ber, s, len, ber->ber_tag );
+ break;
+
+ case 't': /* tag for the next element */
+ ber->ber_tag = va_arg( ap, unsigned int );
+ ber->ber_usertag = 1;
+ break;
+
+ case 'v': /* vector of strings */
+ if ( (ss = va_arg( ap, char ** )) == NULL )
+ break;
+ for ( i = 0; ss[i] != NULL; i++ ) {
+ if ( (rc = ber_put_string( ber, ss[i],
+ ber->ber_tag )) == -1 )
+ break;
+ }
+ break;
+
+ case 'V': /* sequences of strings + lengths */
+ if ( (bv = va_arg( ap, struct berval ** )) == NULL )
+ break;
+ for ( i = 0; bv[i] != NULL; i++ ) {
+ if ( (rc = ber_put_ostring( ber, bv[i]->bv_val,
+ bv[i]->bv_len, ber->ber_tag )) == -1 )
+ break;
+ }
+ break;
+
+ case '{': /* begin sequence */
+ rc = ber_start_seq( ber, ber->ber_tag );
+ break;
+
+ case '}': /* end sequence */
+ rc = ber_put_seqorset( ber );
+ break;
+
+ case '[': /* begin set */
+ rc = ber_start_set( ber, ber->ber_tag );
+ break;
+
+ case ']': /* end set */
+ rc = ber_put_seqorset( ber );
+ break;
+
+ default:
+#ifndef NO_USERINTERFACE
+ (void) fprintf( stderr, catgets(slapdcat, 1, 74, "unknown fmt %c\n"), *fmt );
+#endif /* NO_USERINTERFACE */
+ rc = -1;
+ break;
+ }
+
+ if ( ber->ber_usertag == 0 )
+ ber->ber_tag = LBER_DEFAULT;
+ else
+ ber->ber_usertag = 0;
+ }
+
+ va_end( ap );
+
+ return( rc );
+}
diff --git a/usr/src/lib/libldap4/ber/i18n.c b/usr/src/lib/libldap4/ber/i18n.c
new file mode 100644
index 0000000000..0f57fe06f6
--- /dev/null
+++ b/usr/src/lib/libldap4/ber/i18n.c
@@ -0,0 +1,27 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <nl_types.h>
+/* #include <lthread.h> */
+#include <pthread.h>
+#include <thread.h>
+
+nl_catd slapdcat = 0;
+int notdone = 1;
+static pthread_mutex_t log_mutex;
+pthread_mutex_t systime_mutex;
+
+void i18n_catopen(char * name)
+{
+ if ( notdone ) {
+ notdone = 0;
+ slapdcat = catopen(name, NL_CAT_LOCALE);
+ } /* end if */
+}
+
diff --git a/usr/src/lib/libldap4/ber/io.c b/usr/src/lib/libldap4/ber/io.c
new file mode 100644
index 0000000000..5b7338e08e
--- /dev/null
+++ b/usr/src/lib/libldap4/ber/io.c
@@ -0,0 +1,683 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* io.c - ber general i/o routines */
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <poll.h>
+
+#if defined( DOS ) || defined( _WIN32 )
+#include "msdos.h"
+#endif /* DOS || _WIN32 */
+
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined(NeXT) || defined(VMS)
+#include <stdlib.h>
+#else /* next || vms */
+#include <malloc.h>
+#endif /* next || vms */
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifdef PCNFS
+#include <tklib.h>
+#endif /* PCNFS */
+#endif /* MACOS */
+
+#ifdef SUN
+#include <unistd.h>
+#endif
+
+#ifndef VMS
+#include <memory.h>
+#endif
+#include <string.h>
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifdef _WIN32
+#include <winsock.h>
+#include <io.h>
+#endif /* _WIN32 */
+
+#ifdef NEEDPROTOS
+int ber_realloc(BerElement *ber, unsigned int len);
+static int ber_filbuf(Sockbuf *sb, int len);
+static int BerRead(Sockbuf *sb, char *buf, int len);
+#ifdef PCNFS
+static int BerWrite( Sockbuf *sb, char *buf, int len );
+#endif /* PCNFS */
+#else
+int ber_filbuf();
+int BerRead();
+int ber_realloc();
+#endif /* NEEDPROTOS */
+
+#define bergetc( sb, len ) ( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \
+ (unsigned char)*sb->sb_ber.ber_ptr++ : \
+ ber_filbuf( sb, len ))
+
+#ifdef MACOS
+/*
+ * MacTCP/OpenTransport
+ */
+#define read( s, b, l ) tcpread( s, 0, (unsigned char *)b, l, NULL )
+#define MAX_WRITE 65535
+#define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (l<MAX_WRITE)? l : MAX_WRITE )
+#else /* MACOS */
+#ifdef DOS
+#ifdef PCNFS
+/*
+ * PCNFS (under DOS)
+ */
+#define read( s, b, l ) recv( s, b, l, 0 )
+#define BerWrite( s, b, l ) send( s->sb_sd, b, (int) l, 0 )
+#endif /* PCNFS */
+#ifdef NCSA
+/*
+ * NCSA Telnet TCP/IP stack (under DOS)
+ */
+#define read( s, b, l ) nread( s, b, l )
+#define BerWrite( s, b, l ) netwrite( s->sb_sd, b, l )
+#endif /* NCSA */
+#ifdef WINSOCK
+/*
+ * Windows Socket API (under DOS/Windows 3.x)
+ */
+#define read( s, b, l ) recv( s, b, l, 0 )
+#define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 )
+#endif /* WINSOCK */
+#else /* DOS */
+#ifdef _WIN32
+/*
+ * 32-bit Windows Socket API (under Windows NT or Windows 95)
+ */
+#define read( s, b, l ) recv( s, b, l, 0 )
+#define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 )
+#else /* _WIN32 */
+#ifdef VMS
+/*
+ * VMS -- each write must be 64K or smaller
+ */
+#define MAX_WRITE 65535
+#define BerWrite( sb, b, l ) write( sb->sb_sd, b, (l<MAX_WRITE)? l : MAX_WRITE)
+#else /* VMS */
+/*
+ * everything else (Unix/BSD 4.3 socket API)
+ */
+#define BerWrite( sb, b, l ) write( sb->sb_sd, b, l )
+#endif /* VMS */
+#define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \
+ (struct sockaddr *)sb->sb_fromaddr, \
+ (al = sizeof(struct sockaddr), &al))
+#define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \
+ (struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr))
+#endif /* _WIN32 */
+#endif /* DOS */
+#endif /* MACOS */
+
+#ifndef udp_read
+#define udp_read( sb, b, l, al ) CLDAP NOT SUPPORTED
+#define udp_write( sb, b, l ) CLDAP NOT SUPPORTED
+#endif /* udp_read */
+
+#define EXBUFSIZ 1024
+
+int
+ber_filbuf( Sockbuf *sb, int len )
+{
+ ssize_t rc;
+#ifdef CLDAP
+ int addrlen;
+#endif /* CLDAP */
+
+ if ( sb->sb_ber.ber_buf == NULL ) {
+ if ( (sb->sb_ber.ber_buf = (char *) malloc( READBUFSIZ )) ==
+ NULL )
+ return( -1 );
+ sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf;
+ sb->sb_ber.ber_end = sb->sb_ber.ber_buf;
+ }
+
+ if ( sb->sb_naddr > 0 ) {
+#ifdef CLDAP
+ rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen );
+#ifdef LDAP_DEBUG
+ if ( lber_debug ) {
+ (void) fprintf( stderr, catgets(slapdcat, 1, 75, "ber_filbuf udp_read %d bytes\n"),
+ (int)rc );
+ if ( lber_debug > 1 && rc > 0 )
+ lber_bprint( sb->sb_ber.ber_buf, (int)rc );
+ }
+#endif /* LDAP_DEBUG */
+#else /* CLDAP */
+ rc = -1;
+#endif /* CLDAP */
+#ifdef LDAP_SSL
+ } else if ( sb->sb_ssl != NULL ) {
+ rc = SSL_read(sb->sb_ssl,(u_char *)sb->sb_ber.ber_buf,
+ ((sb->sb_options & LBER_NO_READ_AHEAD) &&
+ (len < READBUFSIZ)) ?
+ len : READBUFSIZ );
+#endif /* LDAP_SSL */
+ } else {
+ int loop=2;
+ while (loop>0) {
+ --loop;
+ rc = read( sb->sb_sd, sb->sb_ber.ber_buf,
+ ((sb->sb_options & LBER_NO_READ_AHEAD) &&
+ (len < READBUFSIZ)) ?
+ len : READBUFSIZ );
+ /*
+ * if packet not here yet, wait 10 seconds to let it arrive
+ */
+ if ( rc <= 0 && (errno==EWOULDBLOCK || errno==EAGAIN) ) {
+ struct pollfd poll_tab[1];
+ poll_tab[0].fd = sb->sb_sd;
+ poll_tab[0].events = POLLIN;
+ poll_tab[0].revents = 0;
+ if ( poll(poll_tab, 1, 10000) <= 0) {
+ /* nothing received or error, just abandon the read */
+ break;
+ } /* end if */
+ } else {
+ break;
+ } /* end if */
+ } /* end while */
+ }
+
+ if ( rc > 0 ) {
+ sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1;
+ sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc;
+ return( (unsigned char)*sb->sb_ber.ber_buf );
+ }
+
+ return( -1 );
+}
+
+
+int
+BerRead( Sockbuf *sb, char *buf, int len )
+{
+ int c;
+ int nread = 0;
+
+ while ( len > 0 ) {
+ if ( (c = bergetc( sb, len )) < 0 ) {
+ if ( nread > 0 )
+ break;
+ return( c );
+ }
+ *buf++ = (char)c;
+ nread++;
+ len--;
+ }
+
+ return( nread );
+}
+
+
+int
+ber_read( BerElement *ber, char *buf, unsigned int len )
+{
+ unsigned int actuallen, nleft;
+
+ nleft = (int)(ber->ber_end - ber->ber_ptr);
+ actuallen = nleft < len ? nleft : len;
+
+ SAFEMEMCPY( buf, ber->ber_ptr, (size_t)actuallen );
+
+ ber->ber_ptr += actuallen;
+
+ return( (int)actuallen );
+}
+
+int
+ber_write( BerElement *ber, char *buf, unsigned int len, int nosos )
+{
+ if ( nosos || ber->ber_sos == NULL ) {
+ if ( ber->ber_ptr + len > ber->ber_end ) {
+ if ( ber_realloc( ber, len ) != 0 )
+ return( -1 );
+ }
+ (void) SAFEMEMCPY( ber->ber_ptr, buf, (size_t)len );
+ ber->ber_ptr += len;
+ return( len );
+ } else {
+ if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) {
+ if ( ber_realloc( ber, len ) != 0 )
+ return( -1 );
+ }
+ (void) SAFEMEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len );
+ ber->ber_sos->sos_ptr += len;
+ ber->ber_sos->sos_clen += len;
+ return( len );
+ }
+}
+
+int
+ber_realloc(BerElement *ber, unsigned int len)
+{
+ size_t need, have, total;
+ Seqorset *s;
+ ssize_t off;
+ char *oldbuf;
+
+ have = (ber->ber_end - ber->ber_buf) / EXBUFSIZ;
+ need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ);
+ total = have * EXBUFSIZ + need * EXBUFSIZ;
+
+ oldbuf = ber->ber_buf;
+
+ if ( ber->ber_buf == NULL ) {
+ if ( (ber->ber_buf = (char *) malloc( (size_t)total )) == NULL )
+ return( -1 );
+ } else if ( (ber->ber_buf = (char *) realloc( ber->ber_buf,
+ (size_t)total )) == NULL )
+ return( -1 );
+
+ ber->ber_end = ber->ber_buf + total;
+
+ /*
+ * If the stinking thing was moved, we need to go through and
+ * reset all the sos and ber pointers. Offsets would've been
+ * a better idea... oh well.
+ */
+
+ if ( ber->ber_buf != oldbuf ) {
+ ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf);
+
+ for ( s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next ) {
+ off = s->sos_first - oldbuf;
+ s->sos_first = ber->ber_buf + off;
+
+ off = s->sos_ptr - oldbuf;
+ s->sos_ptr = ber->ber_buf + off;
+ }
+ }
+
+ return( 0 );
+}
+
+void
+ber_free(BerElement *ber, int freebuf)
+{
+ if (NULL != ber) {
+ if (freebuf && ber->ber_buf != NULL)
+ free(ber->ber_buf);
+ free((char *)ber);
+ }
+}
+
+int
+ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
+{
+ ssize_t nwritten, towrite, rc;
+
+ if ( ber->ber_rwptr == NULL ) {
+ ber->ber_rwptr = ber->ber_buf;
+ }
+ towrite = ber->ber_ptr - ber->ber_rwptr;
+
+#ifdef LDAP_DEBUG
+ if ( lber_debug ) {
+ (void) fprintf( stderr, catgets(slapdcat, 1, 76, "ber_flush: %1$ld bytes to sd %2$ld%s\n"), towrite,
+ sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)"
+ : "" );
+ if ( lber_debug > 1 )
+ lber_bprint( ber->ber_rwptr, towrite );
+ }
+#endif
+#if !defined(MACOS) && !defined(DOS)
+ if ( sb->sb_options & (LBER_TO_FILE | LBER_TO_FILE_ONLY) ) {
+#ifdef LDAP_SSL
+ if (sb->sb_ssl) {
+ rc = SSL_write( sb->sb_ssl, (u_char *)ber->ber_buf, towrite );
+ if ( rc < 0 ) {
+ fprintf( stderr, SSL_strerr(SSL_errno(sb->sb_ssl)));
+ }
+ } else {
+#endif /* LDAP_SSL */
+ rc = write( sb->sb_fd, ber->ber_buf, towrite );
+ if ( sb->sb_options & LBER_TO_FILE_ONLY ) {
+ return( (int)rc );
+ }
+#ifdef LDAP_SSL
+ }
+#endif /* LDAP_SSL */
+ }
+#endif
+
+ nwritten = 0;
+ do {
+ if (sb->sb_naddr > 0) {
+#ifdef CLDAP
+ rc = udp_write( sb, ber->ber_buf + nwritten,
+ (size_t)towrite );
+#else /* CLDAP */
+ rc = -1;
+#endif /* CLDAP */
+ if ( rc <= 0 )
+ return( -1 );
+ /* fake error if write was not atomic */
+ if (rc < towrite) {
+#if !defined( MACOS ) && !defined( DOS )
+ errno = EMSGSIZE;
+#endif
+ return( -1 );
+ }
+ } else {
+#ifdef LDAP_SSL
+ if (sb->sb_ssl) {
+ if ( (rc = SSL_write( sb->sb_ssl, (u_char *)ber->ber_rwptr,
+ (size_t) towrite )) <= 0 ) {
+ return( -1 );
+ }
+ } else
+#endif /* LDAP_SSL */
+ if ( (rc = BerWrite( sb, ber->ber_rwptr,
+ (size_t) towrite )) <= 0 ) {
+ return( -1 );
+ }
+ }
+ towrite -= rc;
+ nwritten += rc;
+ ber->ber_rwptr += rc;
+ } while ( towrite > 0 );
+
+ if ( freeit )
+ ber_free( ber, 1 );
+
+ return( 0 );
+}
+
+BerElement *
+ber_alloc_t( int options )
+{
+ BerElement *ber;
+
+ if ( (ber = (BerElement *) calloc( (size_t) 1, sizeof(BerElement) )) == NULLBER )
+ return( NULLBER );
+ ber->ber_tag = LBER_DEFAULT;
+ ber->ber_options = (char) options;
+
+ return( ber );
+}
+
+BerElement *
+ber_alloc()
+{
+ return( ber_alloc_t( 0 ) );
+}
+
+BerElement *
+der_alloc()
+{
+ return( ber_alloc_t( LBER_USE_DER ) );
+}
+
+BerElement *
+ber_dup( BerElement *ber )
+{
+ BerElement *new;
+
+ if ( (new = ber_alloc()) == NULLBER )
+ return( NULLBER );
+
+ *new = *ber;
+
+ return( new );
+}
+
+BerElement *ber_init(struct berval *bv)
+{
+ BerElement *new;
+
+ if (bv == NULL)
+ return (NULLBER);
+
+ if ((new = ber_alloc()) == NULLBER)
+ return (NULLBER);
+ if ((new->ber_buf = (char *)malloc(bv->bv_len + 1)) == NULL){
+ free(new);
+ return (NULLBER);
+ }
+ SAFEMEMCPY(new->ber_buf, bv->bv_val, bv->bv_len);
+ new->ber_end = new->ber_buf + bv->bv_len;
+ new->ber_ptr = new->ber_buf;
+ new->ber_len = bv->bv_len;
+ return (new);
+}
+
+void
+ber_zero_init( BerElement *ber, int options )
+{
+ (void) memset( (char *)ber, '\0', sizeof( BerElement ));
+ ber->ber_tag = LBER_DEFAULT;
+ ber->ber_options = options;
+}
+
+
+void
+ber_reset( BerElement *ber, int was_writing )
+{
+ if ( was_writing ) {
+ ber->ber_end = ber->ber_ptr;
+ ber->ber_ptr = ber->ber_buf;
+ } else {
+ ber->ber_ptr = ber->ber_end;
+ }
+
+ ber->ber_rwptr = NULL;
+}
+
+
+#ifdef LDAP_DEBUG
+
+void
+ber_dump( BerElement *ber, int inout )
+{
+ (void) fprintf( stderr, catgets(slapdcat, 1, 77, "ber_dump: buf 0x%1$lx, ptr 0x%2$lx, end 0x%3$lx\n"),
+ ber->ber_buf, ber->ber_ptr, ber->ber_end );
+ if ( inout == 1 ) {
+ (void) fprintf( stderr, catgets(slapdcat, 1, 78, " current len %ld, contents:\n"),
+ ber->ber_end - ber->ber_ptr );
+ lber_bprint( ber->ber_ptr, ber->ber_end - ber->ber_ptr );
+ } else {
+ (void) fprintf( stderr, catgets(slapdcat, 1, 78, " current len %ld, contents:\n"),
+ ber->ber_ptr - ber->ber_buf );
+ lber_bprint( ber->ber_buf, ber->ber_ptr - ber->ber_buf );
+ }
+}
+
+void
+ber_sos_dump( Seqorset *sos )
+{
+ (void) fprintf( stderr, catgets(slapdcat, 1, 79, "*** sos dump ***\n") );
+ while ( sos != NULLSEQORSET ) {
+ (void) fprintf( stderr, catgets(slapdcat, 1, 80, "ber_sos_dump: clen %1$ld first 0x%2$lx ptr 0x%3$lx\n"),
+ sos->sos_clen, sos->sos_first, sos->sos_ptr );
+ (void) fprintf( stderr, catgets(slapdcat, 1, 81, " current len %ld contents:\n"),
+ sos->sos_ptr - sos->sos_first );
+ lber_bprint( sos->sos_first, sos->sos_ptr - sos->sos_first );
+
+ sos = sos->sos_next;
+ }
+ (void) fprintf( stderr, catgets(slapdcat, 1, 82, "*** end dump ***\n") );
+}
+
+#endif
+
+/* return the tag - LBER_DEFAULT returned means trouble */
+static unsigned int
+get_tag( Sockbuf *sb )
+{
+ unsigned char xbyte;
+ unsigned int tag;
+ char *tagp;
+ int i;
+
+ if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 )
+ return( LBER_DEFAULT );
+
+ if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
+ return( (unsigned int) xbyte );
+
+ tagp = (char *) &tag;
+ tagp[0] = xbyte;
+ for ( i = 1; i < sizeof(int); i++ ) {
+ if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 )
+ return( LBER_DEFAULT );
+
+ tagp[i] = xbyte;
+
+ if ( ! (xbyte & LBER_MORE_TAG_MASK) )
+ break;
+ }
+
+ /* tag too big! */
+ if ( i == sizeof(int) )
+ return( LBER_DEFAULT );
+
+ /* want leading, not trailing 0's */
+ return( tag >> (sizeof(int) - i - 1) );
+}
+
+unsigned int
+ber_get_next( Sockbuf *sb, unsigned int *len, BerElement *ber )
+{
+ unsigned int tag, netlen, toread;
+ unsigned char lc;
+ int rc;
+ int noctets, diff;
+
+#ifdef LDAP_DEBUG
+ if ( lber_debug )
+ (void) fprintf( stderr, catgets(slapdcat, 1, 83, "ber_get_next\n") );
+#endif
+
+ /*
+ * Any ber element looks like this: tag length contents.
+ * Assuming everything's ok, we return the tag byte (we
+ * can assume a single byte), return the length in len,
+ * and the rest of the undecoded element in buf.
+ *
+ * Assumptions:
+ * 1) small tags (less than 128)
+ * 2) definite lengths
+ * 3) primitive encodings used whenever possible
+ */
+
+ /*
+ * first time through - malloc the buffer, set up ptrs, and
+ * read the tag and the length and as much of the rest as we can
+ */
+
+ if ( ber->ber_rwptr == NULL ) {
+ /*
+ * First, we read the tag.
+ */
+
+ if ( (tag = get_tag( sb )) == LBER_DEFAULT ) {
+ return( LBER_DEFAULT );
+ }
+ ber->ber_tag = tag;
+
+ /*
+ * Next, read the length. The first byte contains the length
+ * of the length. If bit 8 is set, the length is the int
+ * form, otherwise it's the short form. We don't allow a
+ * length that's greater than what we can hold in an unsigned
+ * int.
+ */
+
+ *len = netlen = 0;
+ if ( BerRead( sb, (char *) &lc, 1 ) != 1 ) {
+ return( LBER_DEFAULT );
+ }
+ if ( lc & 0x80 ) {
+ noctets = (lc & 0x7f);
+ if ( noctets > sizeof(unsigned int) )
+ return( LBER_DEFAULT );
+ diff = sizeof(unsigned int) - noctets;
+ if ( BerRead( sb, (char *) &netlen + diff, noctets ) !=
+ noctets ) {
+ return( LBER_DEFAULT );
+ }
+ *len = LBER_NTOHL( netlen );
+ } else {
+ *len = lc;
+ }
+ ber->ber_len = *len;
+
+ /*
+ * Finally, malloc a buffer for the contents and read it in.
+ * It's this buffer that's passed to all the other ber decoding
+ * routines.
+ */
+
+#if defined( DOS ) && !defined( _WIN32 )
+ if ( *len > 65535 ) { /* DOS can't allocate > 64K */
+ return( LBER_DEFAULT );
+ }
+#endif /* DOS && !_WIN32 */
+
+ if ( ( sb->sb_options & LBER_MAX_INCOMING_SIZE ) &&
+ *len > sb->sb_max_incoming ) {
+ return( LBER_DEFAULT );
+ }
+
+ if ( (ber->ber_buf = (char *) malloc( (size_t)*len )) == NULL ) {
+ return( LBER_DEFAULT );
+ }
+ ber->ber_ptr = ber->ber_buf;
+ ber->ber_end = ber->ber_buf + *len;
+ ber->ber_rwptr = ber->ber_buf;
+ }
+
+ toread = (uintptr_t)ber->ber_end - (uintptr_t)ber->ber_rwptr;
+ do {
+ if ( (rc = BerRead( sb, ber->ber_rwptr, (int)toread )) <= 0 ) {
+ return( LBER_DEFAULT );
+ }
+
+ toread -= rc;
+ ber->ber_rwptr += rc;
+ } while ( toread != 0 ); /* DF SUN for LINT */
+
+#ifdef LDAP_DEBUG
+ if ( lber_debug ) {
+ (void) fprintf( stderr, catgets(slapdcat, 1, 84, "ber_get_next: tag 0x%1$lx len %2$ld contents:\n"),
+ tag, ber->ber_len );
+ if ( lber_debug > 1 )
+ ber_dump( ber, 1 );
+ }
+#endif
+
+ *len = ber->ber_len;
+ ber->ber_rwptr = NULL;
+ return( ber->ber_tag );
+}
diff --git a/usr/src/lib/libldap4/common/Version.c b/usr/src/lib/libldap4/common/Version.c
new file mode 100644
index 0000000000..e55944caec
--- /dev/null
+++ b/usr/src/lib/libldap4/common/Version.c
@@ -0,0 +1,22 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1991 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+static char Version[] = " libldap.a v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";
diff --git a/usr/src/lib/libldap4/common/abandon.c b/usr/src/lib/libldap4/common/abandon.c
new file mode 100644
index 0000000000..63a1660dd7
--- /dev/null
+++ b/usr/src/lib/libldap4/common/abandon.c
@@ -0,0 +1,268 @@
+
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+ *
+*/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * abandon.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#endif /* DOS */
+
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifdef NEEDPROTOS
+static int do_abandon( LDAP *ld, int origid, int msgid, LDAPControl **serverctrls );
+#else /* NEEDPROTOS */
+static int do_abandon();
+#endif /* NEEDPROTOS */
+
+BerElement * ldap_build_abandon_req( LDAP *ld, int msgid, LDAPControl ** serverctrls)
+{
+ BerElement *ber;
+ int rc;
+
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ rc = -1;
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return (NULLBER);
+ }
+#ifdef CLDAP
+ if ( ld->ld_sb.sb_naddr > 0 ) {
+ rc = ber_printf( ber, "{isti",
+ ++ld->ld_msgid, ld->ld_cldapdn,
+ LDAP_REQ_ABANDON, msgid );
+ } else {
+#endif /* CLDAP */
+ rc = ber_printf( ber, "{iti", ++ld->ld_msgid,
+ LDAP_REQ_ABANDON, msgid );
+#ifdef CLDAP
+ }
+#endif /* CLDAP */
+
+ if ( rc == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return (NULLBER);
+ }
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ return (ber);
+}
+
+
+/*
+ * ldap_abandon - perform an ldap (and X.500) abandon operation. Parameters:
+ *
+ * ld LDAP descriptor
+ * msgid The message id of the operation to abandon
+ *
+ * ldap_abandon returns 0 if everything went ok, -1 otherwise.
+ *
+ * Example:
+ * ldap_abandon( ld, msgid );
+ */
+int
+ldap_abandon( LDAP *ld, int msgid )
+{
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP( ld );
+#endif
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 85, "ldap_abandon %d\n"), msgid, 0, 0 );
+
+ rv = do_abandon( ld, msgid, msgid , NULL);
+#ifdef _REENTRANT
+ UNLOCK_LDAP( ld );
+#endif
+ return (rv);
+}
+
+/* ldapv3 API extensions */
+
+int ldap_abandon_ext(LDAP *ld, int msgid, LDAPControl **serverctrls, LDAPControl **clientctrls)
+{
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP( ld );
+#endif
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 85, "ldap_abandon %d\n"), msgid, 0, 0 );
+
+ rv = do_abandon( ld, msgid, msgid , NULL);
+ if (rv == -1) {
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS)
+ rv = LDAP_OTHER;
+#ifdef _REENTRANT
+ UNLOCK_LDAP( ld );
+#endif
+ return (rv);
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP( ld );
+#endif
+ return (LDAP_SUCCESS);
+}
+
+
+static int
+do_abandon( LDAP *ld, int origid, int msgid , LDAPControl **serverctrls)
+{
+ BerElement *ber;
+ int i, err, sendabandon;
+ Sockbuf *sb;
+#ifdef LDAP_REFERRALS
+ LDAPRequest *lr;
+#endif /* LDAP_REFERRALS */
+
+ /*
+ * An abandon request looks like this:
+ * AbandonRequest ::= MessageID
+ */
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 86, "do_abandon origid %1$d, msgid %2$d\n"),
+ origid, msgid, 0 );
+
+ sendabandon = 1;
+
+#ifdef LDAP_REFERRALS
+ /* find the request that we are abandoning */
+ for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
+ if ( lr->lr_msgid == msgid ) { /* this message */
+ break;
+ }
+ if ( lr->lr_origid == msgid ) { /* child: abandon it */
+ do_abandon( ld, msgid, lr->lr_msgid , serverctrls);
+ }
+ }
+
+ if ( lr != NULL ) {
+ if ( origid == msgid && lr->lr_parent != NULL ) {
+ /* don't let caller abandon child requests! */
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return( -1 );
+ }
+ if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
+ /* no need to send abandon message */
+ sendabandon = 0;
+ }
+ }
+#endif /* LDAP_REFERRALS */
+
+ if ( ldap_msgdelete( ld, msgid ) == 0 ) {
+ ld->ld_errno = LDAP_SUCCESS;
+ return( 0 );
+ }
+
+ err = 0;
+ if ( sendabandon ) {
+ if ((ber = ldap_build_abandon_req(ld, msgid, serverctrls)) == NULLBER){
+ return (-1);
+ }
+
+#ifdef LDAP_REFERRALS
+ if ( lr != NULL ) {
+ sb = lr->lr_conn->lconn_sb;
+ } else {
+ sb = &ld->ld_sb;
+ }
+#else /* LDAP_REFERRALS */
+ sb = &ld->ld_sb;
+#endif /* LDAP_REFERRALS */
+ if ( ber_flush( sb, ber, 1 ) != 0 ) {
+ ld->ld_errno = LDAP_SERVER_DOWN;
+ err = -1;
+ } else {
+ err = 0;
+ }
+ }
+#ifdef LDAP_REFERRALS
+ if ( lr != NULL ) {
+ if ( sendabandon ) {
+ free_connection( ld, lr->lr_conn, 0, 1 );
+ }
+ if ( origid == msgid ) {
+ free_request( ld, lr );
+ }
+ }
+#endif /* LDAP_REFERRALS */
+
+
+ if ( ld->ld_abandoned == NULL ) {
+ if ( (ld->ld_abandoned = (int *) malloc( 2 * sizeof(int) ))
+ == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( -1 );
+ }
+ i = 0;
+ } else {
+ for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
+ ; /* NULL */
+ if ( (ld->ld_abandoned = (int *) realloc( (char *)
+ ld->ld_abandoned, (i + 2) * sizeof(int) )) == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( -1 );
+ }
+ }
+ ld->ld_abandoned[i] = msgid;
+ ld->ld_abandoned[i + 1] = -1;
+
+ if ( err != -1 ) {
+ ld->ld_errno = LDAP_SUCCESS;
+ }
+ return( err );
+}
+
diff --git a/usr/src/lib/libldap4/common/add.c b/usr/src/lib/libldap4/common/add.c
new file mode 100644
index 0000000000..5cb1c67c51
--- /dev/null
+++ b/usr/src/lib/libldap4/common/add.c
@@ -0,0 +1,272 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * add.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include "macos.h"
+#endif /* MACOS */
+
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#endif /* DOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* !MACOS && !DOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+
+BerElement * ldap_build_add_req(LDAP *ld, char *dn, LDAPMod **attrs,
+ LDAPControl ** serverctrls)
+{
+ BerElement * ber;
+ int rc, i;
+
+ /*
+ * An add request looks like this:
+ * AddRequest ::= [APPLICATION 8] SEQUENCE {
+ * entry DistinguishedName,
+ * attrs SEQUENCE OF SEQUENCE {
+ * type AttributeType,
+ * values SET OF AttributeValue
+ * }
+ * }
+ */
+
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( NULLBER );
+ }
+
+ if ( ber_printf( ber, "{it{s{", ++ld->ld_msgid, LDAP_REQ_ADD, dn )
+ == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ /* for each attribute in the entry... */
+ for ( i = 0; attrs[i] != NULL; i++ ) {
+ if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
+ rc = ber_printf( ber, "{s[V]}", attrs[i]->mod_type,
+ attrs[i]->mod_values );
+ } else {
+ rc = ber_printf( ber, "{s[v]}", attrs[i]->mod_type,
+ attrs[i]->mod_values );
+ }
+ if ( rc == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return(NULLBER);
+ }
+ }
+
+ if ( ber_printf( ber, "}}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+/* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ return (ber);
+}
+
+
+/*
+ * ldap_add - initiate an ldap (and X.500) add operation. Parameters:
+ *
+ * ld LDAP descriptor
+ * dn DN of the entry to add
+ * mods List of attributes for the entry. This is a null-
+ * terminated array of pointers to LDAPMod structures.
+ * only the type and values in the structures need be
+ * filled in.
+ *
+ * Example:
+ * LDAPMod *attrs[] = {
+ * { 0, "cn", { "babs jensen", "babs", 0 } },
+ * { 0, "sn", { "jensen", 0 } },
+ * { 0, "objectClass", { "person", 0 } },
+ * 0
+ * }
+ * msgid = ldap_add( ld, dn, attrs );
+ */
+int ldap_add( LDAP *ld, char *dn, LDAPMod **attrs )
+{
+ BerElement *ber;
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 87, "ldap_add\n"), 0, 0, 0 );
+
+ if ((ber = ldap_build_add_req(ld, dn, attrs, NULL)) == NULLBER){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_ADD, dn, ber );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+}
+
+int
+ldap_add_s( LDAP *ld, char *dn, LDAPMod **attrs )
+{
+ int msgid;
+ LDAPMessage *res;
+
+ if ( (msgid = ldap_add( ld, dn, attrs )) == -1 )
+ return( ld->ld_errno );
+
+ if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
+ return( ld->ld_errno );
+
+ return( ldap_result2error( ld, res, 1 ) );
+}
+
+
+/* ldapv3 API extensions */
+/*
+ * ldap_add_ext - initiate an ldap (and X.500) add operation. Parameters:
+ *
+ * ld LDAP descriptor
+ * dn DN of the entry to add
+ * attrs List of attributes for the entry. This is a null-
+ * terminated array of pointers to LDAPMod structures.
+ * only the type and values in the structures need be
+ * filled in.
+ * serverctrls List of server controls. This is a null-terminated
+ * array of pointers to LDAPControl structures.
+ * clientctrls List of client controls.
+ *
+ * Example:
+ * LDAPMod *attrs[] = {
+ * { 0, "cn", { "babs jensen", "babs", 0 } },
+ * { 0, "sn", { "jensen", 0 } },
+ * { 0, "objectClass", { "person", 0 } },
+ * 0
+ * }
+ *
+ * retcode = ldap_add_ext( ld, dn, attrs, srvctrls, cltctrls, &msgid );
+ */
+
+int ldap_add_ext(LDAP *ld, char *dn, LDAPMod **attrs,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp)
+{
+ BerElement *ber;
+ int i, rc;
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 87, "ldap_add\n"), 0, 0, 0 );
+
+ if ((ber = ldap_build_add_req(ld, dn, attrs, serverctrls)) == NULLBER){
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS)
+ rv = LDAP_OTHER;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_ADD, dn, ber );
+ if (rv == -1) {
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS){
+ rv = LDAP_OTHER;
+ }
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+ *msgidp = rv;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_SUCCESS);
+}
+
+int ldap_add_ext_s(LDAP *ld, char *dn, LDAPMod **attrs,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls)
+{
+ int msgid;
+ int retcode = LDAP_SUCCESS;
+ LDAPMessage *res;
+
+ if ((retcode = ldap_add_ext(ld, dn, attrs, serverctrls, clientctrls, &msgid)) != LDAP_SUCCESS)
+ return (retcode);
+ if (ldap_result(ld, msgid, 1, (struct timeval *)NULL, &res ) == -1)
+ return (ld->ld_errno );
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ retcode = ldap_parse_result(ld, res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
+ &ld->ld_referrals, &ld->ld_ret_ctrls, 1);
+ if (retcode == LDAP_SUCCESS)
+ retcode = ld->ld_errno;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (retcode);
+}
diff --git a/usr/src/lib/libldap4/common/addentry.c b/usr/src/lib/libldap4/common/addentry.c
new file mode 100644
index 0000000000..1c946c7971
--- /dev/null
+++ b/usr/src/lib/libldap4/common/addentry.c
@@ -0,0 +1,65 @@
+
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * addentry.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+
+LDAPMessage *
+ldap_delete_result_entry( LDAPMessage **list, LDAPMessage *e )
+{
+ LDAPMessage *tmp, *prev = NULL;
+
+ for ( tmp = *list; tmp != NULL && tmp != e; tmp = tmp->lm_chain )
+ prev = tmp;
+
+ if ( tmp == NULL )
+ return( NULL );
+
+ if ( prev == NULL )
+ *list = tmp->lm_chain;
+ else
+ prev->lm_chain = tmp->lm_chain;
+ tmp->lm_chain = NULL;
+
+ return( tmp );
+}
+
+void
+ldap_add_result_entry( LDAPMessage **list, LDAPMessage *e )
+{
+ e->lm_chain = *list;
+ *list = e;
+}
diff --git a/usr/src/lib/libldap4/common/bind.c b/usr/src/lib/libldap4/common/bind.c
new file mode 100644
index 0000000000..c51cddeb1c
--- /dev/null
+++ b/usr/src/lib/libldap4/common/bind.c
@@ -0,0 +1,147 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * bind.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include "msdos.h"
+#ifdef NCSA
+#include "externs.h"
+#endif /* NCSA */
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+
+/*
+ * ldap_bind - bind to the ldap server (and X.500). The dn and password
+ * of the entry to which to bind are supplied, along with the authentication
+ * method to use. The msgid of the bind request is returned on success,
+ * -1 if there's trouble. Note, the kerberos support assumes the user already
+ * has a valid tgt for now. ldap_result() should be called to find out the
+ * outcome of the bind request.
+ *
+ * Example:
+ * ldap_bind( ld, "cn=manager, o=university of michigan, c=us", "secret",
+ * LDAP_AUTH_SIMPLE )
+ */
+
+int
+ldap_bind( LDAP *ld, char *dn, char *passwd, int authmethod )
+{
+ /*
+ * The bind request looks like this:
+ * BindRequest ::= SEQUENCE {
+ * version INTEGER,
+ * name DistinguishedName, -- who
+ * authentication CHOICE {
+ * simple [0] OCTET STRING -- passwd
+#ifdef KERBEROS
+ * krbv42ldap [1] OCTET STRING
+ * krbv42dsa [2] OCTET STRING
+#endif
+ * }
+ * }
+ * all wrapped up in an LDAPMessage sequence.
+ */
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 88, "ldap_bind\n"), 0, 0, 0 );
+
+ switch ( authmethod ) {
+ case LDAP_AUTH_SIMPLE:
+ return( ldap_simple_bind( ld, dn, passwd ) );
+
+#ifdef KERBEROS
+ case LDAP_AUTH_KRBV41:
+ return( ldap_kerberos_bind1( ld, dn ) );
+
+ case LDAP_AUTH_KRBV42:
+ return( ldap_kerberos_bind2( ld, dn ) );
+#endif
+
+ default:
+ ld->ld_errno = LDAP_AUTH_UNKNOWN;
+ return( -1 );
+ }
+}
+
+/*
+ * ldap_bind_s - bind to the ldap server (and X.500). The dn and password
+ * of the entry to which to bind are supplied, along with the authentication
+ * method to use. This routine just calls whichever bind routine is
+ * appropriate and returns the result of the bind (e.g. LDAP_SUCCESS or
+ * some other error indication). Note, the kerberos support assumes the
+ * user already has a valid tgt for now.
+ *
+ * Examples:
+ * ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us",
+ * "secret", LDAP_AUTH_SIMPLE )
+ * ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us",
+ * NULL, LDAP_AUTH_KRBV4 )
+ */
+int
+ldap_bind_s( LDAP *ld, char *dn, char *passwd, int authmethod )
+{
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 89, "ldap_bind_s\n"), 0, 0, 0 );
+
+ switch ( authmethod ) {
+ case LDAP_AUTH_SIMPLE:
+ return( ldap_simple_bind_s( ld, dn, passwd ) );
+
+#ifdef KERBEROS
+ case LDAP_AUTH_KRBV4:
+ return( ldap_kerberos_bind_s( ld, dn ) );
+
+ case LDAP_AUTH_KRBV41:
+ return( ldap_kerberos_bind1_s( ld, dn ) );
+
+ case LDAP_AUTH_KRBV42:
+ return( ldap_kerberos_bind2_s( ld, dn ) );
+#endif
+
+ default:
+ return( ld->ld_errno = LDAP_AUTH_UNKNOWN );
+ }
+}
+
+
+void
+ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_FUNCTION *rebindproc, void *extra_arg )
+{
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ ld->ld_rebindproc = rebindproc;
+ ld->ld_rebind_extra_arg = extra_arg;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+}
diff --git a/usr/src/lib/libldap4/common/cache.c b/usr/src/lib/libldap4/common/cache.c
new file mode 100644
index 0000000000..5fc2b33561
--- /dev/null
+++ b/usr/src/lib/libldap4/common/cache.c
@@ -0,0 +1,716 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 1993 The Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * cache.c - local caching support for LDAP
+ */
+
+#ifndef NO_CACHE
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1993 The Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include <time.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#ifdef NCSA
+#include "externs.h"
+#endif /* NCSA */
+#ifdef WINSOCK
+#include <time.h>
+#endif /* WINSOCK */
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* DOS */
+#endif /* MACOS */
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifdef NEEDPROTOS
+static int cache_hash( BerElement *ber );
+static LDAPMessage *msg_dup( LDAPMessage *msg );
+static int request_cmp( BerElement *req1, BerElement *req2 );
+static int chain_contains_dn( LDAPMessage *msg, char *dn );
+static ssize_t msg_size( LDAPMessage *msg );
+static void check_cache_memused( LDAPCache *lc );
+static void uncache_entry_or_req( LDAP *ld, char *dn, int msgid );
+#else /* NEEDPROTOS */
+static int cache_hash();
+static LDAPMessage *msg_dup();
+static int request_cmp();
+static int chain_contains_dn();
+static ssize_t msg_size();
+static void check_cache_memused();
+static void uncache_entry_or_req();
+#endif /* NEEDPROTOS */
+
+
+int
+ldap_enable_cache( LDAP *ld, time_t timeout, ssize_t maxmem )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_cache == NULLLDCACHE ) {
+ if (( ld->ld_cache = (LDAPCache *)malloc( sizeof( LDAPCache )))
+ == NULLLDCACHE ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+ (void) memset( ld->ld_cache, 0, sizeof( LDAPCache ));
+ ld->ld_cache->lc_memused = sizeof( LDAPCache );
+ }
+
+ ld->ld_cache->lc_timeout = timeout;
+ ld->ld_cache->lc_maxmem = maxmem;
+ check_cache_memused( ld->ld_cache );
+ ld->ld_cache->lc_enabled = 1;
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( 0 );
+}
+
+
+void
+ldap_disable_cache( LDAP *ld )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_cache != NULLLDCACHE ) {
+ ld->ld_cache->lc_enabled = 0;
+ }
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+
+
+void
+ldap_set_cache_options( LDAP *ld, unsigned int opts )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_cache != NULLLDCACHE ) {
+ ld->ld_cache->lc_options = opts;
+ }
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+
+void
+ldap_destroy_cache( LDAP *ld )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_cache != NULLLDCACHE ) {
+ ldap_flush_cache( ld );
+ free( (char *)ld->ld_cache );
+ ld->ld_cache = NULLLDCACHE;
+ }
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+
+void
+ldap_flush_cache( LDAP *ld )
+{
+ int i;
+ LDAPMessage *m, *next;
+
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 90, "ldap_flush_cache\n"), 0, 0, 0 );
+
+ if ( ld->ld_cache != NULLLDCACHE ) {
+ /* delete all requests in the queue */
+ for ( m = ld->ld_cache->lc_requests; m != NULLMSG; m = next ) {
+ next = m->lm_next;
+ ldap_msgfree( m );
+ }
+ ld->ld_cache->lc_requests = NULLMSG;
+
+ /* delete all messages in the cache */
+ for ( i = 0; i < LDAP_CACHE_BUCKETS; ++i ) {
+ for ( m = ld->ld_cache->lc_buckets[ i ];
+ m != NULLMSG; m = next ) {
+ next = m->lm_next;
+ ldap_msgfree( m );
+ }
+ ld->ld_cache->lc_buckets[ i ] = NULLMSG;
+ }
+ ld->ld_cache->lc_memused = sizeof( LDAPCache );
+ }
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+
+void
+ldap_uncache_request( LDAP *ld, int msgid )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 91, "ldap_uncache_request %1$d ld_cache %2$x\n"),
+ msgid, ld->ld_cache, 0 );
+
+ uncache_entry_or_req( ld, NULL, msgid );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+
+void
+ldap_uncache_entry( LDAP *ld, char *dn )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 92, "ldap_uncache_entry %1$s ld_cache %2$x\n"),
+ dn, ld->ld_cache, 0 );
+
+ uncache_entry_or_req( ld, dn, 0 );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+
+static void
+uncache_entry_or_req( LDAP *ld,
+ char *dn, /* if non-NULL, uncache entry */
+ int msgid ) /* request to uncache (if dn == NULL) */
+{
+ int i;
+ LDAPMessage *m, *prev, *next;
+
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 93, "ldap_uncache_entry_or_req dn %1$s msgid %2$d ld_cache %3$x\n"),
+ dn, msgid, ld->ld_cache );
+
+ if ( ld->ld_cache == NULLLDCACHE ) {
+ return;
+ }
+
+ /* first check the request queue */
+ prev = NULLMSG;
+ for ( m = ld->ld_cache->lc_requests; m != NULLMSG; m = next ) {
+ next = m->lm_next;
+ if (( dn != NULL && chain_contains_dn( m, dn )) ||
+ ( dn == NULL && m->lm_msgid == msgid )) {
+ if ( prev == NULLMSG ) {
+ ld->ld_cache->lc_requests = next;
+ } else {
+ prev->lm_next = next;
+ }
+ ld->ld_cache->lc_memused -= msg_size( m );
+ ldap_msgfree( m );
+ } else {
+ prev = m;
+ }
+ }
+
+ /* now check the rest of the cache */
+ for ( i = 0; i < LDAP_CACHE_BUCKETS; ++i ) {
+ prev = NULLMSG;
+ for ( m = ld->ld_cache->lc_buckets[ i ]; m != NULLMSG;
+ m = next ) {
+ next = m->lm_next;
+ if (( dn != NULL && chain_contains_dn( m, dn )) ||
+ ( dn == NULL && m->lm_msgid == msgid )) {
+ if ( prev == NULLMSG ) {
+ ld->ld_cache->lc_buckets[ i ] = next;
+ } else {
+ prev->lm_next = next;
+ }
+ ld->ld_cache->lc_memused -= msg_size( m );
+ ldap_msgfree( m );
+ } else {
+ prev = m;
+ }
+ }
+ }
+}
+
+
+void
+add_request_to_cache( LDAP *ld, unsigned int msgtype, BerElement *request )
+{
+ LDAPMessage *new;
+ size_t len;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 94, "add_request_to_cache\n"), 0, 0, 0 );
+
+ ld->ld_errno = LDAP_SUCCESS;
+ if ( ld->ld_cache == NULLLDCACHE ||
+ ( ld->ld_cache->lc_enabled == 0 )) {
+ return;
+ }
+
+ if (( new = (LDAPMessage *) calloc( 1, sizeof(LDAPMessage) ))
+ != NULL ) {
+ if (( new->lm_ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ free( (char *)new );
+ return;
+ }
+ len = request->ber_ptr - request->ber_buf;
+ if (( new->lm_ber->ber_buf = (char *) malloc( len ))
+ == NULL ) {
+ ber_free( new->lm_ber, 0 );
+ free( (char *)new );
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return;
+ }
+ SAFEMEMCPY( new->lm_ber->ber_buf, request->ber_buf, len );
+ new->lm_ber->ber_ptr = new->lm_ber->ber_buf;
+ new->lm_ber->ber_end = new->lm_ber->ber_buf + len;
+ new->lm_msgid = ld->ld_msgid;
+ new->lm_msgtype = (int) msgtype;;
+ new->lm_next = ld->ld_cache->lc_requests;
+ ld->ld_cache->lc_requests = new;
+ } else {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ }
+}
+
+
+void
+add_result_to_cache( LDAP *ld, LDAPMessage *result )
+{
+ LDAPMessage *m, **mp, *req, *new, *prev;
+ int err, keep;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 95, "add_result_to_cache: id %1$d, type %2$d\n"),
+ result->lm_msgid, result->lm_msgtype, 0 );
+
+ if ( ld->ld_cache == NULLLDCACHE ||
+ ( ld->ld_cache->lc_enabled == 0 )) {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 96, "artc: cache disabled\n"), 0, 0, 0 );
+ return;
+ }
+
+ if ( result->lm_msgtype != LDAP_RES_SEARCH_ENTRY &&
+ result->lm_msgtype != LDAP_RES_SEARCH_RESULT &&
+ result->lm_msgtype != LDAP_RES_SEARCH_REFERENCE &&
+ result->lm_msgtype != LDAP_RES_COMPARE ) {
+ /*
+ * only cache search and compare operations
+ */
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 97, "artc: only caching search & compare operations\n"), 0, 0, 0 );
+ return;
+ }
+
+ /*
+ * if corresponding request is in the lc_requests list, add this
+ * result to it. if this result completes the results for the
+ * request, add the request/result chain to the cache proper.
+ */
+ prev = NULLMSG;
+ for ( m = ld->ld_cache->lc_requests; m != NULL; m = m->lm_next ) {
+ if ( m->lm_msgid == result->lm_msgid ) {
+ break;
+ }
+ prev = m;
+ }
+
+ if ( m != NULLMSG ) { /* found request; add to end of chain */
+ req = m;
+ for ( ; m->lm_chain != NULLMSG; m = m->lm_chain )
+ ;
+ if (( new = msg_dup( result )) != NULLMSG ) {
+ new->lm_chain = NULLMSG;
+ m->lm_chain = new;
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 98, "artc: result added to cache request chain\n"),
+ 0, 0, 0 );
+ }
+ if ( result->lm_msgtype == LDAP_RES_SEARCH_RESULT ||
+ result->lm_msgtype == LDAP_RES_COMPARE ) {
+ /*
+ * this result completes the chain of results
+ * add to cache proper if appropriate
+ */
+ keep = 0; /* pessimistic */
+ err = ldap_result2error( ld, result, 0 );
+ if ( err == LDAP_SUCCESS ||
+ ( result->lm_msgtype == LDAP_RES_COMPARE &&
+ ( err == LDAP_COMPARE_FALSE ||
+ err == LDAP_COMPARE_TRUE ||
+ err == LDAP_NO_SUCH_ATTRIBUTE ))) {
+ keep = 1;
+ }
+
+ if ( ld->ld_cache->lc_options == 0 ) {
+ if ( err == LDAP_SIZELIMIT_EXCEEDED ) {
+ keep = 1;
+ }
+ } else if (( ld->ld_cache->lc_options &
+ LDAP_CACHE_OPT_CACHEALLERRS ) != 0 ) {
+ keep = 1;
+ }
+
+ if ( prev == NULLMSG ) {
+ ld->ld_cache->lc_requests = req->lm_next;
+ } else {
+ prev->lm_next = req->lm_next;
+ }
+
+ if ( !keep ) {
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 99, "artc: not caching result with error %d\n"),
+ err, 0, 0 );
+ ldap_msgfree( req );
+ } else {
+ mp = &ld->ld_cache->lc_buckets[
+ cache_hash( req->lm_ber ) ];
+ req->lm_next = *mp;
+ *mp = req;
+ req->lm_time = time( NULL );
+ ld->ld_cache->lc_memused += msg_size( req );
+ check_cache_memused( ld->ld_cache );
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 100, "artc: cached result with error %d\n"),
+ err, 0, 0 );
+ }
+ }
+ } else {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 101, "artc: msgid not in request list\n"),
+ 0, 0, 0 );
+ }
+}
+
+
+/*
+ * look in the cache for this request
+ * return 0 if found, -1 if not
+ * if found, the corresponding result messages are added to the incoming
+ * queue with the correct (new) msgid so that subsequent ldap_result calls
+ * will find them.
+ */
+int
+check_cache( LDAP *ld, unsigned int msgtype, BerElement *request )
+{
+ LDAPMessage *m, *new, *prev, *next;
+ BerElement reqber;
+ int first, hash;
+ unsigned long validtime;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 102, "check_cache\n"), 0, 0, 0 );
+
+ if ( ld->ld_cache == NULLLDCACHE ||
+ ( ld->ld_cache->lc_enabled == 0 )) {
+ return( -1 );
+ }
+
+ reqber.ber_buf = reqber.ber_ptr = request->ber_buf;
+ reqber.ber_end = request->ber_ptr;
+
+ validtime = time( NULL ) - ld->ld_cache->lc_timeout;
+
+ prev = NULLMSG;
+ hash = cache_hash( &reqber );
+ for ( m = ld->ld_cache->lc_buckets[ hash ]; m != NULLMSG; m = next ) {
+ Debug( LDAP_DEBUG_TRACE,catgets(slapdcat, 1, 103, "cc: examining id %1$d,type %2$d\n"),
+ m->lm_msgid, m->lm_msgtype, 0 );
+ if ( m->lm_time < validtime ) {
+ /* delete expired message */
+ next = m->lm_next;
+ if ( prev == NULL ) {
+ ld->ld_cache->lc_buckets[ hash ] = next;
+ } else {
+ prev->lm_next = next;
+ }
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 104, "cc: expired id %d\n"),
+ m->lm_msgid, 0, 0 );
+ ld->ld_cache->lc_memused -= msg_size( m );
+ ldap_msgfree( m );
+ } else {
+ if ( m->lm_msgtype == msgtype &&
+ request_cmp( m->lm_ber, &reqber ) == 0 ) {
+ break;
+ }
+ next = m->lm_next;
+ prev = m;
+ }
+ }
+
+ if ( m == NULLMSG ) {
+ return( -1 );
+ }
+
+ /*
+ * add duplicates of responses to incoming queue
+ */
+ first = 1;
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_RESPONSE(ld);
+#endif
+ for ( m = m->lm_chain; m != NULLMSG; m = m->lm_chain ) {
+ if (( new = msg_dup( m )) == NULLMSG ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_RESPONSE(ld);
+#endif
+ return( -1 );
+ }
+
+ new->lm_msgid = ld->ld_msgid;
+ new->lm_chain = NULLMSG;
+ if ( first ) {
+ new->lm_next = ld->ld_responses;
+ ld->ld_responses = new;
+ first = 0;
+ } else {
+ prev->lm_chain = new;
+ }
+ prev = new;
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 105, "cc: added type %d\n"),
+ new->lm_msgtype, 0, 0 );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 106, "cc: result returned from cache\n"), 0, 0, 0 );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_RESPONSE(ld);
+#endif
+ return( 0 );
+}
+
+
+static int
+cache_hash( BerElement *ber )
+{
+ BerElement bercpy;
+ unsigned int len;
+
+ /*
+ * just take the length of the packet and mod with # of buckets
+ */
+ bercpy = *ber;
+ if ( ber_skip_tag( &bercpy, &len ) == LBER_ERROR
+ || ber_scanf( &bercpy, "x" ) == LBER_ERROR ) {
+ len = 0; /* punt: just return zero */
+ } else {
+ len = (int) ( bercpy.ber_end - bercpy.ber_ptr );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 107, "cache_hash: len is %1$ld, returning %2$ld\n"),
+ len, len % LDAP_CACHE_BUCKETS, 0 );
+ return ( len % LDAP_CACHE_BUCKETS );
+}
+
+
+static LDAPMessage *
+msg_dup( LDAPMessage *msg )
+{
+ LDAPMessage *new;
+ size_t len;
+
+ if (( new = (LDAPMessage *)malloc( sizeof(LDAPMessage))) != NULL ) {
+ *new = *msg; /* struct copy */
+ if (( new->lm_ber = ber_dup( msg->lm_ber )) == NULLBER ) {
+ free( (char *)new );
+ return( NULLMSG );
+ }
+ len = msg->lm_ber->ber_end - msg->lm_ber->ber_buf;
+ if (( new->lm_ber->ber_buf = (char *) malloc( len )) == NULL ) {
+ ber_free( new->lm_ber, 0 );
+ free( (char *)new );
+ return( NULLMSG );
+ }
+ SAFEMEMCPY( new->lm_ber->ber_buf, msg->lm_ber->ber_buf, len );
+
+ new->lm_ber->ber_ptr = new->lm_ber->ber_buf +
+ ( msg->lm_ber->ber_ptr - msg->lm_ber->ber_buf );
+ new->lm_ber->ber_end = new->lm_ber->ber_buf + len;
+ }
+
+ return( new );
+}
+
+
+static int
+request_cmp( BerElement *req1, BerElement *req2 )
+{
+ unsigned int len;
+ size_t slen;
+ BerElement r1, r2;
+
+ r1 = *req1; /* struct copies */
+ r2 = *req2;
+
+ /*
+ * skip the enclosing tags (sequence markers) and the msg ids
+ */
+ if ( ber_skip_tag( &r1, &len ) == LBER_ERROR || ber_scanf( &r1, "x" )
+ == LBER_ERROR ) {
+ return( -1 );
+ }
+ if ( ber_skip_tag( &r2, &len ) == LBER_ERROR || ber_scanf( &r2, "x" )
+ == LBER_ERROR ) {
+ return( -1 );
+ }
+
+ /*
+ * check remaining length and bytes if necessary
+ */
+ if (( slen = r1.ber_end - r1.ber_ptr ) != r2.ber_end - r2.ber_ptr ) {
+ return( -1 ); /* different lengths */
+ }
+ return( memcmp( r1.ber_ptr, r2.ber_ptr, slen ));
+}
+
+
+static int
+chain_contains_dn( LDAPMessage *msg, char *dn )
+{
+ LDAPMessage *m;
+ BerElement ber;
+ int msgid;
+ char *s;
+ int rc;
+
+
+ /*
+ * first check the base or dn of the request
+ */
+ ber = *msg->lm_ber; /* struct copy */
+ if ( ber_scanf( &ber, "{i{a", &msgid, &s ) != LBER_ERROR ) {
+ rc = ( strcasecmp( dn, s ) == 0 ) ? 1 : 0;
+ free( s );
+ if ( rc != 0 ) {
+ return( rc );
+ }
+ }
+
+ if ( msg->lm_msgtype == LDAP_REQ_COMPARE ) {
+ return( 0 );
+ }
+
+ /*
+ * now check the dn of each search result
+ */
+ rc = 0;
+ for ( m = msg->lm_chain; m != NULLMSG && rc == 0 ; m = m->lm_chain ) {
+ if ( m->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) {
+ continue;
+ }
+ ber = *m->lm_ber; /* struct copy */
+ if ( ber_scanf( &ber, "{a", &s ) != LBER_ERROR ) {
+ rc = ( strcasecmp( dn, s ) == 0 ) ? 1 : 0;
+ free( s );
+ }
+ }
+
+ return( rc );
+}
+
+
+static ssize_t
+msg_size( LDAPMessage *msg )
+{
+ LDAPMessage *m;
+ ssize_t size;
+
+ size = 0;
+ for ( m = msg; m != NULLMSG; m = m->lm_chain ) {
+ size += sizeof( LDAPMessage ) + m->lm_ber->ber_end -
+ m->lm_ber->ber_buf;
+ }
+
+ return( size );
+}
+
+
+#define THRESHOLD_FACTOR 3 / 4
+#define SIZE_FACTOR 2 / 3
+
+static void
+check_cache_memused( LDAPCache *lc )
+{
+/*
+ * this routine is called to check if the cache is too big (lc_maxmem >
+ * minimum cache size and lc_memused > lc_maxmem). If too big, it reduces
+ * the cache size to < SIZE_FACTOR * lc_maxmem. The algorithm is as follows:
+ * remove_threshold = lc_timeout seconds;
+ * do {
+ * remove everything older than remove_threshold seconds;
+ * remove_threshold = remove_threshold * THRESHOLD_FACTOR;
+ * } while ( cache size is > SIZE_FACTOR * lc_maxmem )
+ */
+ int i;
+ unsigned long remove_threshold, validtime;
+ LDAPMessage *m, *prev, *next;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 108, "check_cache_memused: %1$ld bytes in use (%2$ld max)\n"),
+ lc->lc_memused, lc->lc_maxmem, 0 );
+
+ if ( lc->lc_maxmem <= sizeof( LDAPCache )
+ || lc->lc_memused <= lc->lc_maxmem * SIZE_FACTOR ) {
+ return;
+ }
+
+ remove_threshold = lc->lc_timeout;
+ while ( lc->lc_memused > lc->lc_maxmem * SIZE_FACTOR ) {
+ validtime = time( NULL ) - remove_threshold;
+ for ( i = 0; i < LDAP_CACHE_BUCKETS; ++i ) {
+ prev = NULLMSG;
+ for ( m = lc->lc_buckets[ i ]; m != NULLMSG;
+ m = next ) {
+ next = m->lm_next;
+ if ( m->lm_time < validtime ) {
+ if ( prev == NULLMSG ) {
+ lc->lc_buckets[ i ] = next;
+ } else {
+ prev->lm_next = next;
+ }
+ lc->lc_memused -= msg_size( m );
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 109, "ccm: removed %d\n"),
+ m->lm_msgid, 0, 0 );
+ ldap_msgfree( m );
+ } else {
+ prev = m;
+ }
+ }
+ }
+ remove_threshold *= THRESHOLD_FACTOR;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 110, "ccm: reduced usage to %ld bytes\n"),
+ lc->lc_memused, 0, 0 );
+}
+
+#endif /* !NO_CACHE */
diff --git a/usr/src/lib/libldap4/common/charset.c b/usr/src/lib/libldap4/common/charset.c
new file mode 100644
index 0000000000..d2866746af
--- /dev/null
+++ b/usr/src/lib/libldap4/common/charset.c
@@ -0,0 +1,1871 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * charset.c
+ */
+
+#if defined( DOS ) || defined( _WIN32 )
+/*
+ * This MUST precede "#ifdef STR_TRANSLATION"
+ * because STR_TRANSLATION and friends are defined in msdos.h.
+ */
+#include "msdos.h"
+#endif /* DOS */
+
+#ifdef STR_TRANSLATION
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#endif /* MACOS */
+
+#if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 ) && !defined(VMS)
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#endif
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+
+void
+ldap_set_string_translators( LDAP *ld, BERTranslateProc encode_proc,
+ BERTranslateProc decode_proc )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ ld->ld_lber_encode_translate_proc = encode_proc;
+ ld->ld_lber_decode_translate_proc = decode_proc;
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+
+void
+ldap_enable_translation( LDAP *ld, LDAPMessage *entry, int enable )
+{
+ char *optionsp;
+
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ optionsp = ( entry == NULLMSG ) ? &ld->ld_lberoptions :
+ &entry->lm_ber->ber_options;
+
+ if ( enable ) {
+ *optionsp |= LBER_TRANSLATE_STRINGS;
+ } else {
+ *optionsp &= ~LBER_TRANSLATE_STRINGS;
+ }
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+
+int
+ldap_translate_from_t61( LDAP *ld, char **bufp, unsigned int *lenp,
+ int free_input )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ BERTranslateProc decode_proc;
+
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_lber_decode_translate_proc == NULL ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( LDAP_SUCCESS );
+ }
+#if defined( SUN ) && defined( _REENTRANT )
+ decode_proc = ld->ld_lber_decode_translate_proc;
+ UNLOCK_LDAP(ld);
+
+ return( (*decode_proc)( bufp, lenp, free_input ));
+#else
+ return( (*ld->ld_lber_decode_translate_proc)( bufp, lenp, free_input ));
+#endif
+}
+
+
+int
+ldap_translate_to_t61( LDAP *ld, char **bufp, unsigned int *lenp,
+ int free_input )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ BERTranslateProc encode_proc;
+
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_lber_encode_translate_proc == NULL ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( LDAP_SUCCESS );
+ }
+
+#if defined( SUN ) && defined( _REENTRANT )
+ encode_proc = ld->ld_lber_encode_translate_proc;
+ UNLOCK_LDAP(ld);
+ return( (*encode_proc)( bufp, lenp, free_input ));
+#else
+ return( (*ld->ld_lber_encode_translate_proc)( bufp, lenp, free_input ));
+#endif
+}
+
+
+/*
+ ** Character translation routine notes:
+ *
+ * On entry: bufp points to a "string" to be converted (not necessarily
+ * zero-terminated) and buflenp points to the length of the buffer.
+ *
+ * On exit: bufp should point to a malloc'd result. If free_input is
+ * non-zero then the original bufp will be freed. *buflenp should be
+ * set to the new length. Zero bytes in the input buffer must be left
+ * as zero bytes.
+ *
+ * Return values: any ldap error code (LDAP_SUCCESS if all goes well).
+ */
+
+
+#ifdef LDAP_CHARSET_8859
+
+#if LDAP_CHARSET_8859 == 88591
+#define ISO_8859 1
+#elif LDAP_CHARSET_8859 == 88592
+#define ISO_8859 2
+#elif LDAP_CHARSET_8859 == 88593
+#define ISO_8859 3
+#elif LDAP_CHARSET_8859 == 88594
+#define ISO_8859 4
+#elif LDAP_CHARSET_8859 == 88595
+#define ISO_8859 5
+#elif LDAP_CHARSET_8859 == 88596
+#define ISO_8859 6
+#elif LDAP_CHARSET_8859 == 88597
+#define ISO_8859 7
+#elif LDAP_CHARSET_8859 == 88598
+#define ISO_8859 8
+#elif LDAP_CHARSET_8859 == 88599
+#define ISO_8859 9
+#elif LDAP_CHARSET_8859 == 885910
+#define ISO_8859 10
+#else
+#define ISO_8859 0
+#endif
+
+/*
+ * the following ISO_8859 to/afrom T.61 character set translation code is
+ * based on the code found in Enrique Silvestre Mora's iso-t61.c, found
+ * as part of this package:
+ * ftp://pereiii.uji.es/pub/uji-ftp/unix/ldap/iso-t61.translation.tar.Z
+ * Enrique is now (10/95) at this address: enrique.silvestre@uv.es
+ *
+ * changes made by mcs@umich.edu 12 October 1995:
+ * Change calling conventions of iso8859_t61() and t61_iso8859() to
+ * match libldap conventions; rename to ldap_8859_to_t61() and
+ * ldap_t61_to_8859().
+ * Change conversion routines to deal with non-zero terminated strings.
+ * ANSI-ize functions and include prototypes.
+ */
+
+/* iso-t61.c - ISO-T61 translation routines (version: 0.2.1, July-1994) */
+/*
+ * Copyright (c) 1994 Enrique Silvestre Mora, Universitat Jaume I, Spain.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the Universitat Jaume I. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Character set used: ISO 8859-1, ISO 8859-2, ISO 8859-3, ... */
+/* #define ISO_8859 1 */
+
+#ifndef ISO_8859
+# define ISO_8859 0
+#endif
+
+typedef unsigned char Byte;
+typedef struct { Byte a, b; } Couple;
+
+#ifdef NEEDPROTOS
+static Byte *c_to_hh( Byte *o, Byte c );
+static Byte *c_to_cc( Byte *o, Couple *cc, Byte c );
+static int hh_to_c( Byte *h );
+static Byte *cc_to_t61( Byte *o, Byte *s );
+#else /* NEEDPROTOS */
+static Byte *c_to_hh();
+static Byte *c_to_cc();
+static int hh_to_c();
+static Byte *cc_to_t61();
+#endif /* NEEDPROTOS */
+
+/*
+ Character choosed as base in diacritics alone: NO-BREAK SPACE.
+ (The standard say it must be a blank space, 0x20.)
+*/
+#define ALONE 0xA0
+
+static Couple diacritic[16] = {
+#if (ISO_8859 == 1) || (ISO_8859 == 9)
+ {0,0}, {'`',0}, {0xb4,0}, {'^',0},
+ {'~',0}, {0xaf,0}, {'(',ALONE}, {'.',ALONE},
+ {0xa8,0}, {0,0}, {'0',ALONE}, {0xb8,0},
+ {0,0}, {'"',ALONE}, {';',ALONE}, {'<',ALONE},
+#elif (ISO_8859 == 2)
+ {0,0}, {'`',0}, {0xb4,0}, {'^',0},
+ {'~',0}, {'-',ALONE}, {0xa2,0}, {0xff,0},
+ {0xa8,0}, {0,0}, {'0',ALONE}, {0xb8,0},
+ {0,0}, {0xbd,0}, {0xb2,0}, {0xb7,0}
+#elif (ISO_8859 == 3)
+ {0,0}, {'`',0}, {0xb4,0}, {'^',0},
+ {'~',0}, {'-',ALONE}, {0xa2,0}, {0xff,0},
+ {0xa8,0}, {0,0}, {'0',ALONE}, {0xb8,0},
+ {0,0}, {'"',ALONE}, {';',ALONE}, {'<',ALONE}
+#elif (ISO_8859 == 4)
+ {0,0}, {'`',0}, {0xb4,0}, {'^',0},
+ {'~',0}, {0xaf,0}, {'(',ALONE}, {0xff,0},
+ {0xa8,0}, {0,0}, {'0',ALONE}, {0xb8,0},
+ {0,0}, {'"',ALONE}, {0xb2,0}, {0xb7,0}
+#else
+ {0,0}, {'`',0}, {'\'',ALONE}, {'^',0},
+ {'~',0}, {'-',ALONE}, {'(',ALONE}, {'.',ALONE},
+ {':',ALONE}, {0,0}, {'0',ALONE}, {',',ALONE},
+ {0,0}, {'"',ALONE}, {';',ALONE}, {'<',ALONE}
+#endif
+};
+
+/*
+ --- T.61 (T.51) letters with diacritics: conversion to ISO 8859-n -----
+ A, C, D, E, G, H, I, J, K,
+ L, N, O, R, S, T, U, W, Y, Z.
+ -----------------------------------------------------------------------
+*/
+static int letter_w_diacritic[16][38] = {
+#if (ISO_8859 == 1)
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xc0,0, 0, 0xc8,0, 0, 0xcc,0, 0,
+ 0, 0, 0xd2,0, 0, 0, 0xd9,0, 0, 0,
+ 0xe0,0, 0, 0xe8,0, 0, 0xec,0, 0,
+ 0, 0, 0xf2,0, 0, 0, 0xf9,0, 0, 0,
+ 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0,
+ -1, -1, 0xd3,-1, -1, 0, 0xda,0, 0xdd,-1,
+ 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0,
+ -1, -1, 0xf3,-1, -1, 0, 0xfa,0, 0xfd,-1,
+ 0xc2,-1, 0, 0xca,-1, -1, 0xce,-1, 0,
+ 0, 0, 0xd4,0, -1, 0, 0xdb,-1, -1, 0,
+ 0xe2,-1, 0, 0xea,-1, -1, 0xee,-1, 0,
+ 0, 0, 0xf4,0, -1, 0, 0xfb,-1, -1, 0,
+ 0xc3,0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0xd1,0xd5,0, 0, 0, -1, 0, 0, 0,
+ 0xe3,0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0xf1,0xf5,0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, 0, -1, -1, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0, -1, 0, -1, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0xc4,0, 0, 0xcb,0, 0, 0xcf,0, 0,
+ 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0,
+ 0xe4,0, 0, 0xeb,0, 0, 0xef,0, 0,
+ 0, 0, 0xf6,0, 0, 0, 0xfc,0, 0xff,0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xc5,0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0xe5,0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0xc7,0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, 0,
+ 0, 0xe7,0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, -1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, -1,
+ 0, -1, -1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, -1
+#elif (ISO_8859 == 2)
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0xc1,0xc6,0, 0xc9,0, 0, 0xcd,0, 0,
+ 0xc5,0xd1,0xd3,0xc0,0xa6,0, 0xda,0, 0xdd,0xac,
+ 0xe1,0xe6,0, 0xe9,0, 0, 0xed,0, 0,
+ 0xe5,0xf1,0xf3,0xe0,0xb6,0, 0xfa,0, 0xfd,0xbc,
+ 0xc2,-1, 0, -1, -1, -1, 0xce,-1, 0,
+ 0, 0, 0xd4,0, -1, 0, -1, -1, -1, 0,
+ 0xe2,-1, 0, -1, -1, -1, 0xee,-1, 0,
+ 0, 0, 0xf4,0, -1, 0, -1, -1, -1, 0,
+ -1, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, -1, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, -1, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0xc3,0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0xe3,0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, 0, -1, -1, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xaf,
+ 0, -1, 0, -1, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbf,
+ 0xc4,0, 0, 0xcb,0, 0, -1, 0, 0,
+ 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0,
+ 0xe4,0, 0, 0xeb,0, 0, -1, 0, 0,
+ 0, 0, 0xf6,0, 0, 0, 0xfc,0, -1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xd9,0, 0, 0,
+ -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xf9,0, 0, 0,
+ 0, 0xc7,0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, 0xaa,0xde,0, 0, 0, 0,
+ 0, 0xe7,0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, 0xba,0xfe,0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xd5,0, 0, 0, 0xdb,0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xf5,0, 0, 0, 0xfb,0, 0, 0,
+ 0xa1,0, 0, 0xca,0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0xb1,0, 0, 0xea,0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0xc8,0xcf,0xcc,0, 0, 0, 0, 0,
+ 0xa5,0xd2,0, 0xd8,0xa9,0xab,0, 0, 0, 0xae,
+ 0, 0xe8,0xef,0xec,0, 0, 0, 0, 0,
+ 0xb5,0xf2,0, 0xf8,0xb9,0xbb,0, 0, 0, 0xbe
+#elif (ISO_8859 == 3)
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xc0,0, 0, 0xc8,0, 0, 0xcc,0, 0,
+ 0, 0, 0xd2,0, 0, 0, 0xd9,0, 0, 0,
+ 0xe0,0, 0, 0xe8,0, 0, 0xec,0, 0,
+ 0, 0, 0xf2,0, 0, 0, 0xf9,0, 0, 0,
+ 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0,
+ -1, -1, 0xd3,-1, -1, 0, 0xda,0, -1, -1,
+ 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0,
+ -1, -1, 0xf3,-1, -1, 0, 0xfa,0, -1, -1,
+ 0xc2,0xc6,0, 0xca,0xd8,0xa6,0xce,0xac,0,
+ 0, 0, 0xd4,0, 0xde,0, 0xdb,-1, -1, 0,
+ 0xe2,0xe6,0, 0xea,0xf8,0xb6,0xee,0xbc,0,
+ 0, 0, 0xf4,0, 0xfe,0, 0xfb,-1, -1, 0,
+ -1, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0xd1,-1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0xf1,-1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, 0xab,0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xdd,0, 0, 0,
+ -1, 0, 0, 0, 0xbb,0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xfd,0, 0, 0,
+ 0, 0xc5,0, -1, 0xd5,0, 0xa9,0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xaf,
+ 0, 0xe5,0, -1, 0xf5,0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbf,
+ 0xc4,0, 0, 0xcb,0, 0, 0xcf,0, 0,
+ 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0,
+ 0xe4,0, 0, 0xeb,0, 0, 0xef,0, 0,
+ 0, 0, 0xf6,0, 0, 0, 0xfc,0, -1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0xc7,0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, 0xaa,-1, 0, 0, 0, 0,
+ 0, 0xe7,0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, 0xba,-1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, -1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, -1,
+ 0, -1, -1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, -1
+#elif (ISO_8859 == 4)
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0,
+ -1, -1, -1, -1, -1, 0, 0xda,0, -1, -1,
+ 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0,
+ -1, -1, -1, -1, -1, 0, 0xfa,0, -1, -1,
+ 0xc2,-1, 0, -1, -1, -1, 0xce,-1, 0,
+ 0, 0, 0xd4,0, -1, 0, 0xdb,-1, -1, 0,
+ 0xe2,-1, 0, -1, -1, -1, 0xee,-1, 0,
+ 0, 0, 0xf4,0, -1, 0, 0xfb,-1, -1, 0,
+ 0xc3,0, 0, 0, 0, 0, 0xa5,0, 0,
+ 0, -1, 0xd5,0, 0, 0, 0xdd,0, 0, 0,
+ 0xe3,0, 0, 0, 0, 0, 0xb5,0, 0,
+ 0, -1, 0xf5,0, 0, 0, 0xfd,0, 0, 0,
+ 0xc0,0, 0, 0xaa,0, 0, 0xcf,0, 0,
+ 0, 0, 0xd2,0, 0, 0, 0xde,0, 0, 0,
+ 0xe0,0, 0, 0xba,0, 0, 0xef,0, 0,
+ 0, 0, 0xf2,0, 0, 0, 0xfe,0, 0, 0,
+ -1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, 0, 0xcc,-1, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0, -1, 0, 0xec,-1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0xc4,0, 0, 0xcb,0, 0, -1, 0, 0,
+ 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0,
+ 0xe4,0, 0, 0xeb,0, 0, -1, 0, 0,
+ 0, 0, 0xf6,0, 0, 0, 0xfc,0, -1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xc5,0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0xe5,0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, 0, 0, 0xab,0, 0, 0, 0xd3,
+ 0xa6,0xd1,0, 0xa3,-1, -1, 0, 0, 0, 0,
+ 0, -1, 0, 0, 0xbb,0, 0, 0, 0xf3,
+ 0xb6,0xf1,0, 0xb3,-1, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0xa1,0, 0, 0xca,0, 0, 0xc7,0, 0,
+ 0, 0, 0, 0, 0, 0, 0xd9,0, 0, 0,
+ 0xb1,0, 0, 0xea,0, 0, 0xe7,0, 0,
+ 0, 0, 0, 0, 0, 0, 0xf9,0, 0, 0,
+ 0, 0xc8,-1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, 0xa9,-1, 0, 0, 0, 0xae,
+ 0, 0xe8,-1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, 0xb9,-1, 0, 0, 0, 0xbe
+#elif (ISO_8859 == 9)
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xc0,0, 0, 0xc8,0, 0, 0xcc,0, 0,
+ 0, 0, 0xd2,0, 0, 0, 0xd9,0, 0, 0,
+ 0xe0,0, 0, 0xe8,0, 0, -1, 0, 0,
+ 0, 0, 0xf2,0, 0, 0, 0xf9,0, 0, 0,
+ 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0,
+ -1, -1, 0xd3,-1, -1, 0, 0xda,0, -1, -1,
+ 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0,
+ -1, -1, 0xf3,-1, -1, 0, 0xfa,0, -1, -1,
+ 0xc2,-1, 0, 0xca,-1, -1, 0xce,-1, 0,
+ 0, 0, 0xd4,0, -1, 0, 0xdb,-1, -1, 0,
+ 0xe2,-1, 0, -1, -1, -1, 0xee,-1, 0,
+ 0, 0, 0xf4,0, -1, 0, 0xfb,-1, -1, 0,
+ 0xc3,0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0xd1,0xd5,0, 0, 0, -1, 0, 0, 0,
+ 0xe3,0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0xf1,0xf5,0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, 0xef,0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, 0xd0,0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, 0xf0,0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, 0, -1, -1, 0, 0xdd,0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0, -1, 0, 0xec,-1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0xc4,0, 0, 0xcb,0, 0, 0xcf,0, 0,
+ 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0,
+ 0xe4,0, 0, 0xeb,0, 0, -1, 0, 0,
+ 0, 0, 0xf6,0, 0, 0, 0xfc,0, 0xff,0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xc5,0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0xe5,0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0xc7,0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, 0xde,-1, 0, 0, 0, 0,
+ 0, 0xe7,0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, 0xfe,-1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0xea,0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, -1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, -1,
+ 0, -1, -1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, -1
+#elif (ISO_8859 == 10)
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0,
+ -1, -1, 0xd3,-1, -1, 0, 0xda,0, 0xdd,-1,
+ 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0,
+ -1, -1, 0xf3,-1, -1, 0, 0xfa,0, 0xfd,-1,
+ 0xc2,-1, 0, -1, -1, -1, 0xce,-1, 0,
+ 0, 0, 0xd4,0, -1, 0, 0xdb,-1, -1, 0,
+ 0xe2,-1, 0, -1, -1, -1, 0xee,-1, 0,
+ 0, 0, 0xf4,0, -1, 0, 0xfb,-1, -1, 0,
+ 0xc3,0, 0, 0, 0, 0, 0xa5,0, 0,
+ 0, -1, 0xd5,0, 0, 0, 0xd7,0, 0, 0,
+ 0xe3,0, 0, 0, 0, 0, 0xb5,0, 0,
+ 0, -1, 0xf5,0, 0, 0, 0xf7,0, 0, 0,
+ 0xc0,0, 0, 0xa2,0, 0, 0xa4,0, 0,
+ 0, 0, 0xd2,0, 0, 0, 0xae,0, 0, 0,
+ 0xe0,0, 0, 0xb2,0, 0, 0xb4,0, 0,
+ 0, 0, 0xf2,0, 0, 0, 0xbe,0, 0, 0,
+ -1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, 0, 0xcc,-1, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0, -1, 0, 0xec,-1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0xc4,0, 0, 0xcb,0, 0, 0xcf,0, 0,
+ 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0,
+ 0xe4,0, 0, 0xeb,0, 0, 0xef,0, 0,
+ 0, 0, 0xf6,0, 0, 0, 0xfc,0, -1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xc5,0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0xe5,0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, 0, 0, 0xa3,0, 0, 0, 0xa6,
+ 0xa8,0xd1,0, -1, -1, -1, 0, 0, 0, 0,
+ 0, -1, 0, 0, 0xb3,0, 0, 0, 0xb6,
+ 0xb8,0xf1,0, -1, -1, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0xa1,0, 0, 0xca,0, 0, 0xc7,0, 0,
+ 0, 0, 0, 0, 0, 0, 0xd9,0, 0, 0,
+ 0xb1,0, 0, 0xea,0, 0, 0xe7,0, 0,
+ 0, 0, 0, 0, 0, 0, 0xf9,0, 0, 0,
+ 0, 0xc8,-1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, 0xaa,-1, 0, 0, 0, 0xac,
+ 0, 0xe8,-1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, 0xba,-1, 0, 0, 0, 0xbc
+#else
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, -1, 0, -1, 0, 0, -1, 0, 0,
+ -1, -1, -1, -1, -1, 0, -1, 0, -1, -1,
+ -1, -1, 0, -1, 0, 0, -1, 0, 0,
+ -1, -1, -1, -1, -1, 0, -1, 0, -1, -1,
+ -1, -1, 0, -1, -1, -1, -1, -1, 0,
+ 0, 0, -1, 0, -1, 0, -1, -1, -1, 0,
+ -1, -1, 0, -1, -1, -1, -1, -1, 0,
+ 0, 0, -1, 0, -1, 0, -1, -1, -1, 0,
+ -1, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, -1, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, -1, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, 0, -1, -1, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0, -1, 0, -1, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, -1, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, -1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, 0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, 0,
+ 0, -1, 0, 0, -1, 0, 0, 0, -1,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ -1, 0, 0, -1, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, -1, -1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, -1,
+ 0, -1, -1, -1, 0, 0, 0, 0, 0,
+ -1, -1, 0, -1, -1, -1, 0, 0, 0, -1
+#endif
+};
+
+/*
+--- T.61 characters [0xA0 .. 0xBF] -----------------
+*/
+static Couple trans_t61a_iso8859[32] = {
+#if (ISO_8859 == 1) || (ISO_8859 == 9)
+ {'N','S'}, {0xa1,0}, {0xa2,0}, {0xa3,0},
+ {'D','O'}, {0xa5,0}, {'C','u'}, {0xa7,0},
+ {0xa4,0}, {'\'','6'},{'"','6'}, {0xab,0},
+ {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
+ {0xb0,0}, {0xb1,0}, {0xb2,0}, {0xb3,0},
+ {0xd7,0}, {0xb5,0}, {0xb6,0}, {0xb7,0},
+ {0xf7,0}, {'\'','9'},{'"','9'}, {0xbb,0},
+ {0xbc,0}, {0xbd,0}, {0xbe,0}, {0xbf,0}
+#elif (ISO_8859 == 2) || (ISO_8859 == 4)
+ {'N','S'}, {'!','I'}, {'C','t'}, {'P','d'},
+ {'D','O'}, {'Y','e'}, {'C','u'}, {0xa7,0},
+ {0xa4,0}, {'\'','6'},{'"','6'}, {'<','<'},
+ {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
+ {0xb0,0}, {'+','-'}, {'2','S'}, {'3','S'},
+ {0xd7,0}, {'M','y'}, {'P','I'}, {'.','M'},
+ {0xf7,0}, {'\'','9'},{'"','9'}, {'>','>'},
+ {'1','4'}, {'1','2'}, {'3','4'}, {'?','I'},
+#elif (ISO_8859 == 3)
+ {'N','S'}, {'!','I'}, {'C','t'}, {0xa3,0},
+ {'D','O'}, {'Y','e'}, {'C','u'}, {0xa7,0},
+ {0xa4,0}, {'\'','6'},{'"','6'}, {'<','<'},
+ {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
+ {0xb0,0}, {'+','-'}, {0xb2,0}, {0xb3,0},
+ {0xd7,0}, {0xb5,0}, {'P','I'}, {0xb7,0},
+ {0xf7,0}, {'\'','9'},{'"','9'}, {'>','>'},
+ {'1','4'}, {0xbd,0}, {'3','4'}, {'?','I'}
+#elif (ISO_8859 == 10)
+ {'N','S'}, {'!','I'}, {'C','t'}, {'P','d'},
+ {'D','O'}, {'Y','e'}, {'C','u'}, {0xa7,0},
+ {'C','u'}, {'\'','6'},{'"','6'}, {'<','<'},
+ {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
+ {0xb0,0}, {'+','-'}, {'2','S'}, {'3','S'},
+ {'*','X'}, {'M','y'}, {'P','I'}, {0xb7,0},
+ {'-',':'}, {'\'','9'},{'"','9'}, {'>','>'},
+ {'1','4'}, {'1','2'}, {'3','4'}, {'?','I'}
+#else
+ {'N','S'}, {'!','I'}, {'C','t'}, {'P','d'},
+ {'D','O'}, {'Y','e'}, {'C','u'}, {'S','E'},
+ {'X','O'}, {'\'','6'},{'"','6'}, {'<','<'},
+ {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
+ {'D','G'}, {'+','-'}, {'2','S'}, {'3','S'},
+ {'*','X'}, {'M','y'}, {'P','I'}, {'.','M'},
+ {'-',':'}, {'\'','9'},{'"','9'}, {'>','>'},
+ {'1','4'}, {'1','2'}, {'3','4'}, {'?','I'}
+#endif
+};
+
+/*
+--- T.61 characters [0xE0 .. 0xFF] -----------------
+*/
+static Couple trans_t61b_iso8859[48] = {
+#if (ISO_8859 == 1)
+ {'-','M'}, {0xb9,0}, {0xae,0}, {0xa9,0},
+ {'T','M'}, {'M','8'}, {0xac,0}, {0xa6,0},
+ {0,0}, {0,0}, {0,0}, {0,0},
+ {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
+ {'O','m'}, {0xc6,0}, {0xd0,0}, {0xaa,0},
+ {'H','/'}, {0,0}, {'I','J'}, {'L','.'},
+ {'L','/'}, {0xd8,0}, {'O','E'}, {0xba,0},
+ {0xde,0}, {'T','/'}, {'N','G'}, {'\'','n'},
+ {'k','k'}, {0xe6,0}, {'d','/'}, {0xf0,0},
+ {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
+ {'l','/'}, {0xf8,0}, {'o','e'}, {0xdf,0},
+ {0xfe,0}, {'t','/'}, {'n','g'}, {'-','-'}
+#elif (ISO_8859 == 2)
+ {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'},
+ {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
+ {0,0}, {0,0}, {0,0}, {0,0},
+ {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
+ {'O','m'}, {'A','E'}, {0xd0,0}, {'-','a'},
+ {'H','/'}, {0,0}, {'I','J'}, {'L','.'},
+ {0xa3,0}, {'O','/'}, {'O','E'}, {'-','o'},
+ {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'},
+ {'k','k'}, {'a','e'}, {0xf0,0}, {'d','-'},
+ {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
+ {0xb3,0}, {'o','/'}, {'o','e'}, {0xdf,0},
+ {'t','h'}, {'t','/'}, {'n','g'}, {'-','-'}
+#elif (ISO_8859 == 3)
+ {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'},
+ {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
+ {0,0}, {0,0}, {0,0}, {0,0},
+ {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
+ {'O','m'}, {'A','E'}, {'D','/'}, {'-','a'},
+ {0xa1,0}, {0,0}, {'I','J'}, {'L','.'},
+ {'L','/'}, {'O','/'}, {'O','E'}, {'-','o'},
+ {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'},
+ {'k','k'}, {'a','e'}, {'d','/'}, {'d','-'},
+ {0xb1,0}, {0xb9,0}, {'i','j'}, {'l','.'},
+ {'l','/'}, {'o','/'}, {'o','e'}, {0xdf,0},
+ {'t','h'}, {'t','/'}, {'n','g'}, {'-','-'}
+#elif (ISO_8859 == 4)
+ {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'},
+ {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
+ {0,0}, {0,0}, {0,0}, {0,0},
+ {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
+ {'O','m'}, {0xc6,0}, {0xd0,0}, {'-','a'},
+ {'H','/'}, {0,0}, {'I','J'}, {'L','.'},
+ {'L','/'}, {0xd8,0}, {'O','E'}, {'-','o'},
+ {'T','H'}, {0xac,0}, {0xbd,0}, {'\'','n'},
+ {0xa2,0}, {0xe6,0}, {0xf0,0}, {'d','-'},
+ {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
+ {'l','/'}, {0xf8,0}, {'o','e'}, {0xdf,0},
+ {'t','h'}, {0xbc,0}, {0xbf,0}, {'-','-'}
+#elif (ISO_8859 == 9)
+ {'-','M'}, {0xb9,0}, {0xae,0}, {0xa9,0},
+ {'T','M'}, {'M','8'}, {0xac,0}, {0xa6,0},
+ {0,0}, {0,0}, {0,0}, {0,0},
+ {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
+ {'O','m'}, {0xc6,0}, {'D','/'}, {0xaa,0},
+ {'H','/'}, {0,0}, {'I','J'}, {'L','.'},
+ {'L','/'}, {0xd8,0}, {'O','E'}, {0xba,0},
+ {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'},
+ {'k','k'}, {0xe6,0}, {'d','/'}, {'d','-'},
+ {'h','/'}, {0xfd,0}, {'i','j'}, {'l','.'},
+ {'l','/'}, {0xf8,0}, {'o','e'}, {0xdf,0},
+ {'t','h'}, {'t','/'}, {'n','g'}, {'-','-'}
+#elif (ISO_8859 == 10)
+ {0xbd,0}, {'1','S'}, {'R','g'}, {'C','o'},
+ {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
+ {0,0}, {0,0}, {0,0}, {0,0},
+ {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
+ {'O','m'}, {0xc6,0}, {0xa9,0}, {'-','a'},
+ {'H','/'}, {0,0}, {'I','J'}, {'L','.'},
+ {'L','/'}, {0xd8,0}, {'O','E'}, {'-','o'},
+ {0xde,0}, {0xab,0}, {0xaf,0}, {'\'','n'},
+ {0xff,0}, {0xe6,0}, {0xb9,0}, {0xf0,0},
+ {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
+ {'l','/'}, {0xf8,0}, {'o','e'}, {0xdf,0},
+ {0xfe,0}, {0xbb,0}, {0xbf,0}, {'-','-'}
+#else
+ {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'},
+ {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
+ {0,0}, {0,0}, {0,0}, {0,0},
+ {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
+ {'O','m'}, {'A','E'}, {'D','/'}, {'-','a'},
+ {'H','/'}, {0,0}, {'I','J'}, {'L','.'},
+ {'L','/'}, {'O','/'}, {'O','E'}, {'-','o'},
+ {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'},
+ {'k','k'}, {'a','e'}, {'d','/'}, {'d','-'},
+ {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
+ {'l','/'}, {'o','/'}, {'o','e'}, {'s','s'},
+ {'t','h'}, {'t','-'}, {'n','g'}, {'-','-'}
+#endif
+};
+
+/*
+--- ISO 8859-n characters <0xA0 .. 0xFF> -------------------
+*/
+#if (ISO_8859 == 1)
+static Couple trans_iso8859_t61[96] = {
+ {0xa0,0}, {0xa1,0}, {0xa2,0}, {0xa3,0},
+ {0xa8,0}, {0xa5,0}, {0xd7,0}, {0xa7,0},
+ {0xc8,ALONE}, {0xd3,0}, {0xe3,0}, {0xab,0},
+ {0xd6,0}, {0xff,0}, {0xd2,0}, {0xc5,ALONE},
+ {0xb0,0}, {0xb1,0}, {0xb2,0}, {0xb3,0},
+ {0xc2,ALONE}, {0xb5,0}, {0xb6,0}, {0xb7,0},
+ {0xcb,ALONE}, {0xd1,0}, {0xeb,0}, {0xbb,0},
+ {0xbc,0}, {0xbd,0}, {0xbe,0}, {0xbf,0},
+ {0xc1,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0xc4,'A'},
+ {0xc8,'A'}, {0xca,'A'}, {0xe1,0}, {0xcb,'C'},
+ {0xc1,'E'}, {0xc2,'E'}, {0xc3,'E'}, {0xc8,'E'},
+ {0xc1,'I'}, {0xc2,'I'}, {0xc3,'I'}, {0xc8,'I'},
+ {0xe2,0}, {0xc4,'N'}, {0xc1,'O'}, {0xc2,'O'},
+ {0xc3,'O'}, {0xc4,'O'}, {0xc8,'O'}, {0xb4,0},
+ {0xe9,0}, {0xc1,'U'}, {0xc2,'U'}, {0xc3,'U'},
+ {0xc8,'U'}, {0xc2,'Y'}, {0xec,0}, {0xfb,0},
+ {0xc1,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0xc4,'a'},
+ {0xc8,'a'}, {0xca,'a'}, {0xf1,0}, {0xcb,'c'},
+ {0xc1,'e'}, {0xc2,'e'}, {0xc3,'e'}, {0xc8,'e'},
+ {0xc1,'i'}, {0xc2,'i'}, {0xc3,'i'}, {0xc8,'i'},
+ {0xf3,0}, {0xc4,'n'}, {0xc1,'o'}, {0xc2,'o'},
+ {0xc3,'o'}, {0xc4,'o'}, {0xc8,'o'}, {0xb8,0},
+ {0xf9,0}, {0xc1,'u'}, {0xc2,'u'}, {0xc3,'u'},
+ {0xc8,'u'}, {0xc2,'y'}, {0xfc,0}, {0xc8,'y'}
+};
+#elif (ISO_8859 == 2)
+static Couple trans_iso8859_t61[96] = {
+ {0xa0,0}, {0xce,'A'}, {0xc6,ALONE}, {0xe8,0},
+ {0xa8,0}, {0xcf,'L'}, {0xc2,'S'}, {0xa7,0},
+ {0xc8,ALONE}, {0xcf,'S'}, {0xcb,'S'}, {0xcf,'T'},
+ {0xc2,'Z'}, {0xff,0}, {0xcf,'Z'}, {0xc7,'Z'},
+ {0xb0,0}, {0xce,'a'}, {0xce,ALONE}, {0xf8,0},
+ {0xc2,ALONE}, {0xcf,'l'}, {0xc2,'s'}, {0xcf,ALONE},
+ {0xcb,ALONE}, {0xcf,'s'}, {0xcb,'s'}, {0xcf,'t'},
+ {0xc2,'z'}, {0xcd,ALONE}, {0xcf,'z'}, {0xc7,'z'},
+ {0xc2,'R'}, {0xc2,'A'}, {0xc3,'A'}, {0xc6,'A'},
+ {0xc8,'A'}, {0xc2,'L'}, {0xc2,'C'}, {0xcb,'C'},
+ {0xcf,'C'}, {0xc2,'E'}, {0xce,'E'}, {0xc8,'E'},
+ {0xcf,'E'}, {0xc2,'I'}, {0xc3,'I'}, {0xcf,'D'},
+ {0xe2,0}, {0xc2,'N'}, {0xcf,'N'}, {0xc2,'O'},
+ {0xc3,'O'}, {0xcd,'O'}, {0xc8,'O'}, {0xb4,0},
+ {0xcf,'R'}, {0xca,'U'}, {0xc2,'U'}, {0xcd,'U'},
+ {0xc8,'U'}, {0xc2,'Y'}, {0xcb,'T'}, {0xfb,0},
+ {0xc2,'r'}, {0xc2,'a'}, {0xc3,'a'}, {0xc6,'a'},
+ {0xc8,'a'}, {0xc2,'l'}, {0xc2,'c'}, {0xcb,'c'},
+ {0xcf,'c'}, {0xc2,'e'}, {0xce,'e'}, {0xc8,'e'},
+ {0xcf,'e'}, {0xc2,'i'}, {0xc3,'i'}, {0xcf,'d'},
+ {0xf2,0}, {0xc2,'n'}, {0xcf,'n'}, {0xc2,'o'},
+ {0xc3,'o'}, {0xcd,'o'}, {0xc8,'o'}, {0xb8,0},
+ {0xcf,'r'}, {0xca,'u'}, {0xc2,'u'}, {0xcd,'u'},
+ {0xc8,'u'}, {0xc2,'y'}, {0xcb,'t'}, {0xc7,ALONE}
+};
+#elif (ISO_8859 == 3)
+static Couple trans_iso8859_t61[96] = {
+ {0xa0,0}, {0xe4,0}, {0xc6,ALONE}, {0xa3,0},
+ {0xa8,0}, {0,0}, {0xc3,'H'}, {0xa7,0},
+ {0xc8,ALONE}, {0xc7,'I'}, {0xcb,'S'}, {0xc6,'G'},
+ {0xc3,'J'}, {0xff,0}, {0,0}, {0xc7,'Z'},
+ {0xb0,0}, {0xf4,0}, {0xb2,0}, {0xb3,0},
+ {0xc2,ALONE}, {0xb5,0}, {0xc3,'h'}, {0xb7,0},
+ {0xcb,ALONE}, {0xf5,0}, {0xcb,'s'}, {0xc6,'g'},
+ {0xc3,'j'}, {0xbd,0}, {0,0}, {0xc7,'z'},
+ {0xc1,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0,0},
+ {0xc8,'A'}, {0xc7,'C'}, {0xc3,'C'}, {0xcb,'C'},
+ {0xc1,'E'}, {0xc2,'E'}, {0xc3,'E'}, {0xc8,'E'},
+ {0xc1,'I'}, {0xc2,'I'}, {0xc3,'I'}, {0xc8,'I'},
+ {0,0}, {0xc4,'N'}, {0xc1,'O'}, {0xc2,'O'},
+ {0xc3,'O'}, {0xc7,'G'}, {0xc8,'O'}, {0xb4,0},
+ {0xc3,'G'}, {0xc1,'U'}, {0xc2,'U'}, {0xc3,'U'},
+ {0xc8,'U'}, {0xc6,'U'}, {0xc3,'S'}, {0xfb,0},
+ {0xc1,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0,0},
+ {0xc8,'a'}, {0xc7,'c'}, {0xc3,'c'}, {0xcb,'c'},
+ {0xc1,'e'}, {0xc2,'e'}, {0xc3,'e'}, {0xc8,'e'},
+ {0xc1,'i'}, {0xc2,'i'}, {0xc3,'i'}, {0xc8,'i'},
+ {0,0}, {0xc4,'n'}, {0xc1,'o'}, {0xc2,'o'},
+ {0xc3,'o'}, {0xc7,'g'}, {0xc8,'o'}, {0xb8,0},
+ {0xc3,'g'}, {0xc1,'u'}, {0xc2,'u'}, {0xc3,'u'},
+ {0xc8,'u'}, {0xc6,'u'}, {0xc3,'s'}, {0xc7,ALONE}
+};
+#elif (ISO_8859 == 4)
+static Couple trans_iso8859_t61[96] = {
+ {0xa0,0}, {0xce,'A'}, {0xf0,0}, {0xcb,'R'},
+ {0xa8,0}, {0xc4,'I'}, {0xcb,'L'}, {0xa7,0},
+ {0xc8,ALONE}, {0xcf,'S'}, {0xc5,'E'}, {0xcb,'G'},
+ {0xed,0}, {0xff,0}, {0xcf,'Z'}, {0xc5,ALONE},
+ {0xb0,0}, {0xce,'a'}, {0xce,ALONE}, {0xcb,'r'},
+ {0xc2,ALONE}, {0xc4,'i'}, {0xcb,'l'}, {0xcf,ALONE},
+ {0xcb,ALONE}, {0xcf,'s'}, {0xc5,'e'}, {0xcb,'g'},
+ {0xfd,0}, {0xee,0}, {0xcf,'z'}, {0xfe,0},
+ {0xc5,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0xc4,'A'},
+ {0xc8,'A'}, {0xca,'A'}, {0xe1,0}, {0xce,'I'},
+ {0xcf,'C'}, {0xc2,'E'}, {0xce,'E'}, {0xc8,'E'},
+ {0xc7,'E'}, {0xc2,'I'}, {0xc3,'I'}, {0xc5,'I'},
+ {0xe2,0}, {0xcb,'N'}, {0xc5,'O'}, {0xcb,'K'},
+ {0xc3,'O'}, {0xc4,'O'}, {0xc8,'O'}, {0xb4,0},
+ {0xe9,0}, {0xce,'U'}, {0xc2,'U'}, {0xc3,'U'},
+ {0xc8,'U'}, {0xc4,'U'}, {0xc5,'U'}, {0xfb,0},
+ {0xc5,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0xc4,'a'},
+ {0xc8,'a'}, {0xca,'a'}, {0xf1,0}, {0xce,'i'},
+ {0xcf,'c'}, {0xc2,'e'}, {0xce,'e'}, {0xc8,'e'},
+ {0xc7,'e'}, {0xc2,'i'}, {0xc3,'i'}, {0xc5,'i'},
+ {0xf2,0}, {0xcb,'n'}, {0xc5,'o'}, {0xcb,'k'},
+ {0xc3,'o'}, {0xc4,'o'}, {0xc8,'o'}, {0xb8,0},
+ {0xf9,0}, {0xce,'u'}, {0xc2,'u'}, {0xc3,'u'},
+ {0xc8,'u'}, {0xc4,'u'}, {0xc5,'u'}, {0xc7,ALONE}
+};
+#elif (ISO_8859 == 9)
+static Couple trans_iso8859_t61[96] = {
+ {0xa0,0}, {0xa1,0}, {0xa2,0}, {0xa3,0},
+ {0xa8,0}, {0xa5,0}, {0xd7,0}, {0xa7,0},
+ {0xc8,ALONE}, {0xd3,0}, {0xe3,0}, {0xab,0},
+ {0xd6,0}, {0xff,0}, {0xd2,0}, {0xc5,ALONE},
+ {0xb0,0}, {0xb1,0}, {0xb2,0}, {0xb3,0},
+ {0xc2,ALONE}, {0xb5,0}, {0xb6,0}, {0xb7,0},
+ {0xcb,ALONE}, {0xd1,0}, {0xeb,0}, {0xbb,0},
+ {0xbc,0}, {0xbd,0}, {0xbe,0}, {0xbf,0},
+ {0xc1,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0xc4,'A'},
+ {0xc8,'A'}, {0xca,'A'}, {0xe1,0}, {0xcb,'C'},
+ {0xc1,'E'}, {0xc2,'E'}, {0xc3,'E'}, {0xc8,'E'},
+ {0xc1,'I'}, {0xc2,'I'}, {0xc3,'I'}, {0xc8,'I'},
+ {0xc6,'G'}, {0xc4,'N'}, {0xc1,'O'}, {0xc2,'O'},
+ {0xc3,'O'}, {0xc4,'O'}, {0xc8,'O'}, {0xb4,0},
+ {0xe9,0}, {0xc1,'U'}, {0xc2,'U'}, {0xc3,'U'},
+ {0xc8,'U'}, {0xc7,'I'}, {0xcb,'S'}, {0xfb,0},
+ {0xc1,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0xc4,'a'},
+ {0xc8,'a'}, {0xca,'a'}, {0xf1,0}, {0xcb,'c'},
+ {0xc1,'e'}, {0xc2,'e'}, {0xce,'e'}, {0xc8,'e'},
+ {0xc7,'e'}, {0xc2,'i'}, {0xc3,'i'}, {0xc5,'i'},
+ {0xc6,'g'}, {0xc4,'n'}, {0xc1,'o'}, {0xc2,'o'},
+ {0xc3,'o'}, {0xc4,'o'}, {0xc8,'o'}, {0xb8,0},
+ {0xf9,0}, {0xc1,'u'}, {0xc2,'u'}, {0xc3,'u'},
+ {0xc8,'u'}, {0xf5,0}, {0xcb,'s'}, {0xc8,'y'}
+};
+#elif (ISO_8859 == 10)
+static Couple trans_iso8859_t61[96] = {
+ {0xa0,0}, {0xce,'A'}, {0xc5,'E'}, {0xcb,'G'},
+ {0xc5,'I'}, {0xc4,'I'}, {0xcb,'K'}, {0xa7,0},
+ {0xcb,'L'}, {0xe2,0}, {0xcf,'S'}, {0xed,0},
+ {0xcf,'Z'}, {0xff,0}, {0xc5,'U'}, {0xee,0},
+ {0xb0,0}, {0xce,'a'}, {0xc5,'e'}, {0xcb,'g'},
+ {0xc5,'i'}, {0xc4,'i'}, {0xcb,'k'}, {0xb7,0},
+ {0xcb,'l'}, {0xf2,0}, {0xcf,'s'}, {0xfd,0},
+ {0xcf,'z'}, {0xd0,0}, {0xc5,'u'}, {0xfe,0},
+ {0xc5,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0xc4,'A'},
+ {0xc8,'A'}, {0xca,'A'}, {0xe1,0}, {0xce,'I'},
+ {0xcf,'C'}, {0xc2,'E'}, {0xce,'E'}, {0xc8,'E'},
+ {0xc7,'E'}, {0xc2,'I'}, {0xc3,'I'}, {0xc8,'I'},
+ {0,0}, {0xcb,'N'}, {0xc5,'O'}, {0xc2,'O'},
+ {0xc3,'O'}, {0xc4,'O'}, {0xc8,'O'}, {0xc4,'U'},
+ {0xe9,0}, {0xce,'U'}, {0xc2,'U'}, {0xc3,'U'},
+ {0xc8,'U'}, {0xc2,'Y'}, {0xec,0}, {0xfb,0},
+ {0xc5,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0xc4,'a'},
+ {0xc8,'a'}, {0xca,'a'}, {0xf1,0}, {0xce,'i'},
+ {0xcf,'c'}, {0xc2,'e'}, {0xce,'e'}, {0xc8,'e'},
+ {0xc7,'e'}, {0xc2,'i'}, {0xc3,'i'}, {0xc8,'i'},
+ {0xf3,0}, {0xcb,'n'}, {0xc5,'o'}, {0xc2,'o'},
+ {0xc3,'o'}, {0xc4,'o'}, {0xc8,'o'}, {0xc4,'u'},
+ {0xf9,0}, {0xce,'u'}, {0xc2,'u'}, {0xc3,'u'},
+ {0xc8,'u'}, {0xc2,'y'}, {0xfc,0}, {0xf0,0}
+};
+#endif
+
+
+static Byte *
+c_to_hh( Byte *o, Byte c )
+{
+ Byte n;
+
+ *o++ = '{'; *o++ = 'x';
+ n = c >> 4;
+ *o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n;
+ n = c & 0x0F;
+ *o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n;
+ *o++ = '}';
+ return o;
+}
+
+
+static Byte *
+c_to_cc( Byte *o, Couple *cc, Byte c )
+{
+ if ( (*cc).a != 0 ) {
+ if ( (*cc).b == 0 )
+ *o++ = (*cc).a;
+ else {
+ *o++ = '{';
+ *o++ = (*cc).a;
+ *o++ = (*cc).b;
+ *o++ = '}';
+ }
+ return o;
+ }
+ else
+ return c_to_hh( o, c );
+}
+
+/* --- routine to convert from T.61 to ISO 8859-n --- */
+
+int
+ldap_t61_to_8859( char **bufp, unsigned int *buflenp, int free_input )
+{
+ Byte *s, *oo, *o;
+ unsigned int n;
+ int c;
+ unsigned int len;
+ Couple *cc;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 111, "ldap_t61_to_8859 input length: %ld\n"),
+ *buflenp, 0, 0 );
+
+ len = *buflenp;
+ s = (Byte *) *bufp;
+
+ if ( (o = oo = (Byte *)malloc( 2 * len + 64 )) == NULL ) {
+ return( 1 );
+ }
+
+ while ( (char *)s - *(char **)bufp < len ) {
+ switch ( *s >> 4 ) {
+
+ case 0xA: case 0xB:
+ o = c_to_cc( o, &trans_t61a_iso8859[ *s - 0xA0 ], *s );
+ s++;
+ break;
+
+ case 0xD: case 0xE: case 0xF:
+ o = c_to_cc( o, &trans_t61b_iso8859[ *s - 0xD0 ], *s );
+ s++;
+ break;
+
+ case 0xC:
+ if ( (*s == 0xC0) || (*s == 0xC9) || (*s == 0xCC) ) {
+ o = c_to_hh( o, *s++ );
+ break;
+ }
+
+ n = (*s++) - 0xC0;
+ switch ( *s ) {
+
+ case 'A': c = letter_w_diacritic[n][0]; break;
+ case 'C': c = letter_w_diacritic[n][1]; break;
+ case 'D': c = letter_w_diacritic[n][2]; break;
+ case 'E': c = letter_w_diacritic[n][3]; break;
+ case 'G': c = letter_w_diacritic[n][4]; break;
+ case 'H': c = letter_w_diacritic[n][5]; break;
+ case 'I': c = letter_w_diacritic[n][6]; break;
+ case 'J': c = letter_w_diacritic[n][7]; break;
+ case 'K': c = letter_w_diacritic[n][8]; break;
+ case 'L': c = letter_w_diacritic[n][9]; break;
+ case 'N': c = letter_w_diacritic[n][10]; break;
+ case 'O': c = letter_w_diacritic[n][11]; break;
+ case 'R': c = letter_w_diacritic[n][12]; break;
+ case 'S': c = letter_w_diacritic[n][13]; break;
+ case 'T': c = letter_w_diacritic[n][14]; break;
+ case 'U': c = letter_w_diacritic[n][15]; break;
+ case 'W': c = letter_w_diacritic[n][16]; break;
+ case 'Y': c = letter_w_diacritic[n][17]; break;
+ case 'Z': c = letter_w_diacritic[n][18]; break;
+
+ case 'a': c = letter_w_diacritic[n][19]; break;
+ case 'c': c = letter_w_diacritic[n][20]; break;
+ case 'd': c = letter_w_diacritic[n][21]; break;
+ case 'e': c = letter_w_diacritic[n][22]; break;
+ case 'g': c = letter_w_diacritic[n][23]; break;
+ case 'h': c = letter_w_diacritic[n][24]; break;
+ case 'i': c = letter_w_diacritic[n][25]; break;
+ case 'j': c = letter_w_diacritic[n][26]; break;
+ case 'k': c = letter_w_diacritic[n][27]; break;
+ case 'l': c = letter_w_diacritic[n][28]; break;
+ case 'n': c = letter_w_diacritic[n][29]; break;
+ case 'o': c = letter_w_diacritic[n][30]; break;
+ case 'r': c = letter_w_diacritic[n][31]; break;
+ case 's': c = letter_w_diacritic[n][32]; break;
+ case 't': c = letter_w_diacritic[n][33]; break;
+ case 'u': c = letter_w_diacritic[n][34]; break;
+ case 'w': c = letter_w_diacritic[n][35]; break;
+ case 'y': c = letter_w_diacritic[n][36]; break;
+ case 'z': c = letter_w_diacritic[n][37]; break;
+
+ case ALONE: c = (( !diacritic[n].b ) ? diacritic[n].a : -1);
+ break;
+
+ default: c = 0;
+ }
+
+ if ( c > 0 ) {
+ *o++ = c; s++;
+ } else {
+ *o++ = '{';
+ if ( c == -1 ) {
+ *o++ = ( ( *s == ALONE ) ? ' ' : *s );
+ s++;
+ } else {
+ *o++ = '"';
+ }
+ *o++ = diacritic[n].a;
+ *o++ = '}';
+ }
+ break;
+
+#if (ISO_8859 == 0)
+ case 0x8: case 0x9:
+ *o++ = 0x1B; /* <ESC> */
+ *o++ = *s++ - 0x40;
+ break;
+#endif
+
+ default:
+ *o++ = *s++;
+ }
+ }
+
+ len = o - oo;
+ o = oo;
+
+ if ( (oo = (Byte *)realloc( o, len )) == NULL ) {
+ free( o );
+ return( 1 );
+ }
+
+ if ( free_input ) {
+ free( *bufp );
+ }
+ *bufp = (char *) oo;
+ *buflenp = len;
+ return( 0 );
+}
+
+
+static int
+hh_to_c( Byte *h )
+{
+ Byte c;
+
+ if ( (*h >= '0') && (*h <= '9') ) c = *h++ - '0';
+ else if ( (*h >= 'A') && (*h <= 'F') ) c = *h++ - 'A' + 10;
+ else if ( (*h >= 'a') && (*h <= 'f') ) c = *h++ - 'a' + 10;
+ else return -1;
+
+ c <<= 4;
+
+ if ( (*h >= '0') && (*h <= '9') ) c |= *h - '0';
+ else if ( (*h >= 'A') && (*h <= 'F') ) c |= *h - 'A' + 10;
+ else if ( (*h >= 'a') && (*h <= 'f') ) c |= *h - 'a' + 10;
+ else return -1;
+
+ return c;
+}
+
+
+static Byte *
+cc_to_t61( Byte *o, Byte *s )
+{
+ int n, c = 0;
+
+ switch ( *(s + 1) ) {
+
+ case '`': c = -1; break; /* <grave-accent> */
+
+ case '!':
+ switch ( *s ) {
+ case '!': c = 0x7C; break; /* <vertical-line> */
+ case '(': c = 0x7B; break; /* <left-curly-bracket> */
+ case '-': c = 0xAD; break; /* <upwards-arrow> */
+ default: c = -1; /* <grave-accent> */
+ }
+ break;
+
+#if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
+ (ISO_8859 == 4) || (ISO_8859 == 9)
+ case 0xB4:
+#endif
+ case '\'': c = -2; break; /* <acute-accent> */
+
+ case '^': c = -3; break; /* <circumflex-acent> */
+
+ case '>':
+ switch ( *s ) {
+ case ')': c = 0x5D; break; /* <right-square-bracket> */
+ case '>': c = 0xBB; break; /* <right-angle-quotation> */
+ case '-': c = 0xAE; break; /* <rightwards-arrow> */
+ default: c = -3; /* <circumflex-acent> */
+ }
+ break;
+
+ case '~':
+ case '?': c = -4; break; /* <tilde> */
+
+#if (ISO_8859 == 1) || (ISO_8859 == 4) || (ISO_8859 == 9)
+ case 0xAF: c = -5; break; /* <macron> */
+#endif
+
+ case '-':
+ switch ( *s ) {
+ case '-': c = 0xFF; break; /* <soft-hyphen> */
+ case '<': c = 0xAC; break; /* <leftwards arrow> */
+ case '+': c = 0xB1; break; /* <plus-minus> */
+ case 'd': c = 0xF3; break; /* <eth> */
+ default: c = -5; /* <macron> */
+ }
+ break;
+
+#if (ISO_8859 == 2) || (ISO_8859 == 3)
+ case 0xA2: c = -6; break; /* <breve> */
+#endif
+
+ case '(':
+ if ( *s == '<' ) c = 0x5B; /* <left-square-bracket> */
+ else c = -6; /* <breve> */
+ break;
+
+#if (ISO_8859 == 2) || (ISO_8859 == 3) || (ISO_8859 == 4)
+ case 0xFF: c = -7; break; /* <dot-accent> */
+#endif
+
+ case '.':
+ switch ( *s ) {
+ case 'i': c = 0xF5; break; /* <dotless-i> */
+ case 'L': c = 0xE7; break; /* <L-middle-dot> */
+ case 'l': c = 0xF7; break; /* <l-middle-dot> */
+ default: c = -7; /* <dot-accent> */
+ }
+ break;
+
+#if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
+ (ISO_8859 == 4) || (ISO_8859 == 9)
+ case 0xA8: c = -8; break; /* <diaeresis> */
+#endif
+
+ case ':':
+ if ( *s == '-') c = 0xB8; /* <division-sign> */
+ else c = -8; /* <diaeresis> */
+ break;
+
+#if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
+ (ISO_8859 == 4) || (ISO_8859 == 9) || (ISO_8859 == 10)
+ case 0xB0:
+#endif
+ case '0': c = -10; break; /* <ring-above> */
+
+#if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
+ (ISO_8859 == 4) || (ISO_8859 == 9)
+ case 0xB8:
+#endif
+ case ',': c = -11; break; /* <cedilla> */
+
+#if (ISO_8859 == 2)
+ case 0xBD:
+#endif
+ case '"': c = -13; break; /* <double-acute-accent> */
+
+#if (ISO_8859 == 2) || (ISO_8859 == 4)
+ case 0xB2:
+#endif
+ case ';': c = -14; break; /* <ogonek> */
+
+#if (ISO_8859 == 2) || (ISO_8859 == 4)
+ case 0xB7: c = -15; break; /* <caron> */
+#endif
+
+ case ')':
+ if ( *s == '!' ) c = 0x7D; /* <left-curly-bracket> */
+ break;
+
+ case '<':
+ if ( *s == '<' ) c = 0xAB; /* <left-angle-quotation> */
+ else c = -15; /* <caron> */
+ break;
+
+ case '/':
+ switch ( *s ) {
+ case '/': c = 0x5C; break; /* <reverse-solidus> */
+ case 'D': c = 0xE2; break; /* <D-stroke> */
+ case 'd': c = 0xF2; break; /* <d-stroke> */
+ case 'H': c = 0xE4; break; /* <H-stroke> */
+ case 'h': c = 0xF4; break; /* <h-stroke> */
+ case 'L': c = 0xE8; break; /* <L-stroke> */
+ case 'l': c = 0xF8; break; /* <l-stroke> */
+ case 'O': c = 0xE9; break; /* <O-stroke> */
+ case 'o': c = 0xF9; break; /* <o-stroke> */
+ case 'T': c = 0xED; break; /* <T-stroke> */
+ case 't': c = 0xFD; break; /* <t-stroke> */
+ }
+ break;
+
+ case '2':
+ if ( *s == '1' ) c = 0xBD; /* <one-half> */
+ break;
+
+ case '4':
+ switch ( *s ) {
+ case '1': c = 0xBC; break; /* <one-quarter> */
+ case '3': c = 0xBE; break; /* <three-quarters> */
+ }
+ break;
+
+ case '6':
+ switch ( *s ) {
+ case '\'': c = 0xA9; break; /* <left-single-quotation> */
+ case '"': c = 0xAA; break; /* <left-double-quotation> */
+ }
+ break;
+
+ case '8':
+ switch ( *s ) {
+ case '1': c = 0xDC; break; /* <one-eighth> */
+ case '3': c = 0xDD; break; /* <three-eighths> */
+ case '5': c = 0xDE; break; /* <five-eighths> */
+ case '7': c = 0xDF; break; /* <seven-eighths> */
+ case 'M': c = 0xD5; break; /* <eighth-note> */
+ }
+ break;
+
+ case '9':
+ switch ( *s ) {
+ case '\'': c = 0xB9; break; /* <right-single-quotation> */
+ case '"': c = 0xBA; break; /* <right-double-quotation> */
+ }
+ break;
+
+ case 'A':
+ if ( *s == 'A' ) c = -10; /* <ring-above> + <A> */
+ break;
+
+ case 'a':
+ switch ( *s ) {
+ case '-': c = 0xE3; break; /* <femenine-ordinal-a> */
+ case 'a': c = -10; break; /* <ring-above> + <a> */
+ }
+ break;
+
+ case 'B':
+ if ( *s == 'B' ) c = 0xD7; /* <broken-bar> */
+ break;
+
+ case 'b':
+ if ( *s == 'N' ) c = 0xA6; /* <number-sign> */
+ break;
+
+ case 'd':
+ if ( *s == 'P' ) c = 0xA3; /* <pound-sign> */
+ break;
+
+ case 'E':
+ switch ( *s ) {
+ case 'S': c = 0xA7; break; /* <section-sign> */
+ case 'A': c = 0xE1; break; /* <AE> */
+ case 'O': c = 0xEA; break; /* <OE> */
+ }
+ break;
+
+ case 'e':
+ switch ( *s ) {
+ case 'a': c = 0xF1; break; /* <ae> */
+ case 'o': c = 0xFA; break; /* <oe> */
+ case 'Y': c = 0xA5; break; /* <yen-sign> */
+ }
+ break;
+
+ case 'G':
+ switch ( *s ) {
+ case 'D': c = 0xB0; break; /* <degree-sign> */
+ case 'N': c = 0xEE; break; /* <Eng> */
+ }
+ break;
+
+ case 'g':
+ switch ( *s ) {
+ case 'R': c = 0xD2; break; /* <registered-sign> */
+ case 'n': c = 0xFE; break; /* <eng> */
+ }
+ break;
+
+ case 'H':
+ if ( *s == 'T' ) c = 0xEC; /* <Thorn> */
+ break;
+
+ case 'h':
+ if ( *s == 't' ) c = 0xFC; /* <thorn> */
+ break;
+
+ case 'I':
+ switch ( *s ) {
+ case 'P': c = 0xB6; break; /* <pilcrow-sign> */
+ case '!': c = 0xA1; break; /* <inverted-exclamation> */
+ case '?': c = 0xBF; break; /* <inverted-question> */
+ }
+ break;
+
+ case 'J':
+ if ( *s == 'I' ) c = 0xE6; /* <IJ> */
+ break;
+
+ case 'j':
+ if ( *s == 'i' ) c = 0xF6; /* <ij> */
+ break;
+
+ case 'k':
+ if ( *s == 'k' ) c = 0xF0; /* <kra> */
+ break;
+
+ case 'M':
+ switch ( *s ) {
+ case '.': c = 0xB7; break; /* <middle-dot> */
+ case '-': c = 0xD0; break; /* <em-dash> */
+ case 'T': c = 0xD4; break; /* <trade-mark-sign> */
+ }
+ break;
+
+ case 'm':
+ switch ( *s ) {
+ case '\'': /* <macron> RFC 1345 */
+ case ' ': c = -5; break; /* <macron> */
+ case 'O': c = 0xE0; break; /* <Ohm sign> */
+ }
+ break;
+
+ case 'n':
+ if ( *s == '\'' ) c = 0xEF; /* <n-preceded-by-apostrophe> */
+ break;
+
+ case 'O':
+ switch ( *s ) {
+ case 'D': c = 0xA4; break; /* <dollar-sign> */
+ case 'N': c = 0xD6; break; /* <not-sign> */
+ }
+ break;
+
+ case 'o':
+ switch ( *s ) {
+ case 'C': c = 0xD3; break; /* <copyright-sign> */
+ case '-': c = 0xEB; break; /* <masculine-ordinal-o> */
+ }
+ break;
+
+ case 'S':
+ switch ( *s ) {
+ case '1': c = 0xD1; break; /* <superscript-1> */
+ case '2': c = 0xB2; break; /* <superscript-2> */
+ case '3': c = 0xB3; break; /* <superscript-3> */
+ case 'N': c = 0xA0; break; /* <no-break-space> */
+ }
+ break;
+
+ case 's':
+ if ( *s == 's' ) c = 0xFB; /* <sharp-s> */
+ break;
+
+ case 't':
+ if ( *s == 'C' ) c = 0xA2; /* <cent-sign> */
+ break;
+
+ case 'u':
+ if ( *s == 'C' ) c = 0xA8; /* <currency-sign> */
+ break;
+
+ case 'v':
+ if ( *s == '-' ) c = 0xAF; /* <downwards-arrow> */
+ break;
+
+ case 'X':
+ if ( *s == '*' ) c = 0xB4; /* <multiplication-sign> */
+ break;
+
+ case 'y':
+ if ( *s == 'M' ) c = 0xB5; /* <micro-sign> */
+ break;
+ }
+
+ if ( c > 0 ) {
+ *o++ = c;
+ return o;
+ } else if ( !c )
+ return NULL;
+
+ /* else: c < 0 */
+ n = -c;
+ switch ( *s ) {
+
+ case 'A': c = letter_w_diacritic[n][0]; break;
+ case 'C': c = letter_w_diacritic[n][1]; break;
+ case 'D': c = letter_w_diacritic[n][2]; break;
+ case 'E': c = letter_w_diacritic[n][3]; break;
+ case 'G': c = letter_w_diacritic[n][4]; break;
+ case 'H': c = letter_w_diacritic[n][5]; break;
+ case 'I': c = letter_w_diacritic[n][6]; break;
+ case 'J': c = letter_w_diacritic[n][7]; break;
+ case 'K': c = letter_w_diacritic[n][8]; break;
+ case 'L': c = letter_w_diacritic[n][9]; break;
+ case 'N': c = letter_w_diacritic[n][10]; break;
+ case 'O': c = letter_w_diacritic[n][11]; break;
+ case 'R': c = letter_w_diacritic[n][12]; break;
+ case 'S': c = letter_w_diacritic[n][13]; break;
+ case 'T': c = letter_w_diacritic[n][14]; break;
+ case 'U': c = letter_w_diacritic[n][15]; break;
+ case 'W': c = letter_w_diacritic[n][16]; break;
+ case 'Y': c = letter_w_diacritic[n][17]; break;
+ case 'Z': c = letter_w_diacritic[n][18]; break;
+
+ case 'a': c = letter_w_diacritic[n][19]; break;
+ case 'c': c = letter_w_diacritic[n][20]; break;
+ case 'd': c = letter_w_diacritic[n][21]; break;
+ case 'e': c = letter_w_diacritic[n][22]; break;
+ case 'g': c = letter_w_diacritic[n][23]; break;
+ case 'h': c = letter_w_diacritic[n][24]; break;
+ case 'i': c = letter_w_diacritic[n][25]; break;
+ case 'j': c = letter_w_diacritic[n][26]; break;
+ case 'k': c = letter_w_diacritic[n][27]; break;
+ case 'l': c = letter_w_diacritic[n][28]; break;
+ case 'n': c = letter_w_diacritic[n][29]; break;
+ case 'o': c = letter_w_diacritic[n][30]; break;
+ case 'r': c = letter_w_diacritic[n][31]; break;
+ case 's': c = letter_w_diacritic[n][32]; break;
+ case 't': c = letter_w_diacritic[n][33]; break;
+ case 'u': c = letter_w_diacritic[n][34]; break;
+ case 'w': c = letter_w_diacritic[n][35]; break;
+ case 'y': c = letter_w_diacritic[n][36]; break;
+ case 'z': c = letter_w_diacritic[n][37]; break;
+
+ case '\'':
+ case ' ': c = -1; break;
+
+ default: c = 0;
+ }
+
+ if ( !c )
+ return NULL;
+
+ *o++ = n + 0xC0;
+ *o++ = ( ( (*s == ' ') || (*s == '\'') ) ? ALONE : *s );
+ return o;
+}
+
+
+/* --- routine to convert from ISO 8859-n to T.61 --- */
+
+int
+ldap_8859_to_t61( char **bufp, unsigned int *buflenp, int free_input )
+{
+ Byte *s, *oo, *o, *aux;
+ int c;
+ unsigned int len;
+ Couple *cc;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 112, "ldap_8859_to_t61 input length: %ld\n"),
+ *buflenp, 0, 0 );
+
+ len = *buflenp;
+ s = (Byte *) *bufp;
+
+ if ( (o = oo = (Byte *)malloc( 2 * len + 64 )) == NULL ) {
+ return( 1 );
+ }
+
+ while ( (char *)s - *(char **)bufp < len ) {
+ switch( *s >> 5 ) {
+
+ case 2:
+ switch ( *s ) {
+
+ case '^': *o++ = 0xC3; *o++ = ALONE; s++; break;
+
+ case '\\':
+ s++;
+ if ( (c = hh_to_c( s )) != -1 ) {
+ *o++ = c;
+ s += 2;
+ } else
+ *o++ = '\\';
+ break;
+
+ default: *o++ = *s++;
+ }
+ break;
+
+ case 3:
+ switch ( *s ) {
+
+ case '`': *o++ = 0xC1; *o++ = ALONE; s++; break;
+ case '~': *o++ = 0xC4; *o++ = ALONE; s++; break;
+
+ case '{':
+ s++;
+ if ( *(s + 2) == '}' ) {
+ if ( (aux = cc_to_t61( o, s )) != NULL ) {
+ o = aux;
+ s += 3;
+ } else {
+ *o++ = '{';
+ }
+ } else if ( (*(s + 3) == '}') && ( (*s == 'x') || (*s == 'X') ) &&
+ ( (c = hh_to_c( s + 1 )) != -1 ) ) {
+ *o++ = c;
+ s += 4;
+ } else {
+ *o++ = '{';
+ }
+ break;
+
+ default:
+ *o++ = *s++;
+ }
+ break;
+
+#if (ISO_8859 == 0)
+ case 4: case 5: case 6: case 7:
+ s++;
+ break;
+#else
+ case 5: case 6: case 7:
+# if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
+ (ISO_8859 == 4) || (ISO_8859 == 9) || (ISO_8859 == 10)
+ if ( (*(cc = &trans_iso8859_t61[ *s - 0xA0 ])).a ) {
+ *o++ = (*cc).a;
+ if ( (*cc).b ) *o++ = (*cc).b;
+ }
+# endif
+ s++;
+ break;
+#endif
+
+ default:
+ *o++ = *s++;
+ }
+ }
+
+ len = o - oo;
+ o = oo;
+
+ if ( (oo = (Byte *)realloc( o, len )) == NULL ) {
+ free( o );
+ return( 1 );
+ }
+
+ if ( free_input ) {
+ free( *bufp );
+ }
+ *bufp = (char *) oo;
+ *buflenp = len;
+ return( 0 );
+}
+
+
+#ifdef NOT_NEEDED_IN_LIBLDAP /* mcs@umich.edu 12 Oct 1995 */
+/* --- routine to convert "escaped" (\hh) characters to 8bits --- */
+
+void convert_escaped_to_8bit( s )
+char *s;
+{
+ char *o = s;
+ int c;
+
+ while ( *s ) {
+ if ( *s == '\\' ) {
+ if ( (c = hh_to_c( ++s )) != -1 ) {
+ *o++ = c;
+ s += 2;
+ } else
+ *o++ = '\\';
+ } else
+ *o++ = *s++;
+ }
+ *o = '\0';
+}
+
+/* --- routine to convert 8bits characters to the "escaped" (\hh) form --- */
+
+char *convert_8bit_to_escaped( s )
+Byte *s;
+{
+ Byte *o, *oo;
+ Byte n;
+
+ if ( (o = oo = (Byte *)malloc( 2 * strlen( s ) + 64 )) == NULL ) {
+ return( NULL );
+ }
+
+ while ( *s ) {
+ if ( *s < 0x80 )
+ *o++ = *s++;
+ else {
+ *o++ = '\\';
+ n = *s >> 4;
+ *o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n;
+ n = *s++ & 0x0F;
+ *o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n;
+ }
+ }
+ *o = '\0';
+
+ o = oo;
+
+ if ( (oo = (Byte *)realloc( o, strlen( o ) + 1 )) == NULL ) {
+ free( o );
+ return( NULL );
+ }
+
+ return( (char *)oo );
+}
+
+/* --- routine to convert from T.61 to printable characters --- */
+
+/*
+ printable characters [RFC 1488]: 'A'..'Z', 'a'..'z', '0'..'9',
+ '\'', '(', ')', '+', ',', '-', '.', '/', ':', '?, ' '.
+
+ that conversion is language dependent.
+*/
+
+static Couple last_t61_printabled[32] = {
+ {0,0}, {'A','E'}, {'D',0}, {0,0},
+ {'H',0}, {0,0}, {'I','J'}, {'L',0},
+ {'L',0}, {'O',0}, {'O','E'}, {0,0},
+ {'T','H'}, {'T',0}, {'N','G'}, {'n',0},
+ {'k',0}, {'a','e'}, {'d',0}, {'d',0},
+ {'h',0}, {'i',0}, {'i','j'}, {'l',0},
+ {'l',0}, {'o',0}, {'o','e'}, {'s','s'},
+ {'t','h'}, {'t',0}, {'n','g'}, {0,0}
+};
+
+char *t61_printable( s )
+Byte *s;
+{
+ Byte *o, *oo;
+ Byte n;
+ Couple *cc;
+
+ if ( (o = oo = (Byte *)malloc( 2 * strlen( s ) + 64 )) == NULL ) {
+ return( NULL );
+ }
+
+ while ( *s ) {
+ if ( ( (*s >= 'A') && (*s <= 'Z') ) ||
+ ( (*s >= 'a') && (*s <= 'z') ) ||
+ ( (*s >= '0') && (*s <= '9') ) ||
+ ( (*s >= '\'') && (*s <= ')') ) ||
+ ( (*s >= '+') && (*s <= '/') ) ||
+ ( *s == '?' ) || ( *s == ' ' ) )
+ *o++ = *s++;
+ else {
+ if ( *s >= 0xE0 ) {
+ if ( (*(cc = &last_t61_printabled[ *s - 0xE0 ])).a ) {
+ *o++ = (*cc).a;
+ if ( (*cc).b ) *o++ = (*cc).b;
+ }
+ }
+ else if ( (*s >> 4) == 0xC ) {
+ switch ( *s ) {
+ case 0xCA: /* ring */
+ switch ( *(s + 1) ) {
+ case 'A': *o++ = 'A'; *o++ = 'A'; s++; break; /* Swedish */
+ case 'a': *o++ = 'a'; *o++ = 'a'; s++; break; /* Swedish */
+ }
+ break;
+
+ case 0xC8: /* diaeresis */
+ switch ( *(s + 1) ) {
+ case 'Y': *o++ = 'I'; *o++ = 'J'; s++; break; /* Dutch */
+ case 'y': *o++ = 'i'; *o++ = 'j'; s++; break; /* Dutch */
+ }
+ break;
+ }
+ }
+ s++;
+ }
+ }
+ *o = '\0';
+
+ o = oo;
+
+ if ( (oo = (Byte *)realloc( o, strlen( o ) + 1 )) == NULL ) {
+ free( o );
+ return( NULL );
+ }
+
+ return( (char *)oo );
+}
+#endif /* NOT_NEEDED_IN_LIBLDAP */ /* mcs@umich.edu 12 Oct 1995 */
+
+#endif /* LDAP_CHARSET_8859 */
+#endif /* STR_TRANSLATION */
diff --git a/usr/src/lib/libldap4/common/cldap.c b/usr/src/lib/libldap4/common/cldap.c
new file mode 100644
index 0000000000..4dc4402111
--- /dev/null
+++ b/usr/src/lib/libldap4/common/cldap.c
@@ -0,0 +1,599 @@
+ /*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990, 1994 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * cldap.c - synchronous, retrying interface to the cldap protocol
+ */
+
+
+#ifdef CLDAP
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990, 1994 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include "msdos.h"
+#else /* DOS */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif /* DOS */
+#endif /* MACOS */
+#ifdef SUN
+#include <nss_dbdefs.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#define DEF_CLDAP_TIMEOUT 3
+#define DEF_CLDAP_TRIES 4
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK ((in_addr_t) 0x7f000001)
+#endif
+
+
+struct cldap_retinfo {
+ int cri_maxtries;
+ int cri_try;
+ int cri_useaddr;
+ time_t cri_timeout;
+};
+
+#ifdef NEEDPROTOS
+static int add_addr( LDAP *ld, struct sockaddr *sap );
+static int cldap_result( LDAP *ld, int msgid, LDAPMessage **res,
+ struct cldap_retinfo *crip, char *base );
+static int cldap_parsemsg( LDAP *ld, int msgid, BerElement *ber,
+ LDAPMessage **res, char *base );
+#else /* NEEDPROTOS */
+static int add_addr();
+static int cldap_result();
+static int cldap_parsemsg();
+#endif /* NEEDPROTOS */
+
+/*
+ * cldap_open - initialize and connect to an ldap server. A magic cookie to
+ * be used for future communication is returned on success, NULL on failure.
+ *
+ * Example:
+ * LDAP *ld;
+ * ld = cldap_open( hostname, port );
+ */
+
+LDAP *
+cldap_open( char *host, int port )
+{
+ int s;
+ in_addr_t address;
+ struct sockaddr_in sock;
+ struct hostent *hp;
+ LDAP *ld;
+ char *p;
+ int i;
+#ifdef SUN
+ struct hostent hpret;
+ char hpbuf[NSS_BUFLEN_HOSTS];
+ int hperrno;
+#endif
+ in_addr_t inet_addr(const char *);
+ int close(int);
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 113, "ldap_open\n"), 0, 0, 0 );
+
+ if ( port == 0 ) {
+ port = LDAP_PORT;
+ }
+
+ if ( (s = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) {
+ return( NULL );
+ }
+
+ sock.sin_addr.s_addr = 0;
+ sock.sin_family = AF_INET;
+ sock.sin_port = 0;
+ if ( bind(s, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
+ close( s );
+ return( NULL );
+ }
+
+ if (( ld = ldap_init( host, port )) == NULL ) {
+ close( s );
+ return( NULL );
+ }
+ if ( (ld->ld_sb.sb_fromaddr = (void *) calloc( 1,
+ sizeof( struct sockaddr ))) == NULL ) {
+ free( ld );
+ close( s );
+ return( NULL );
+ }
+ ld->ld_sb.sb_sd = s;
+ ld->ld_sb.sb_naddr = 0;
+ ld->ld_version = LDAP_VERSION;
+
+ sock.sin_family = AF_INET;
+ sock.sin_port = htons( port );
+
+ /*
+ * 'host' may be a space-separated list.
+ */
+ if ( host != NULL ) {
+ for ( ; host != NULL; host = p ) {
+ if (( p = strchr( host, ' ' )) != NULL ) {
+ for (*p++ = '\0'; *p == ' '; p++) {
+ ;
+ }
+ }
+
+ if ( (address = inet_addr( host )) == -1 ) {
+#ifdef SUN
+ if ( (hp = gethostbyname_r( host, &hpret, hpbuf, NSS_BUFLEN_HOSTS, &hperrno)) == NULL ) {
+ errno = EHOSTUNREACH;
+ continue;
+ }
+#else
+ if ( (hp = gethostbyname( host )) == NULL ) {
+ errno = EHOSTUNREACH;
+ continue;
+ }
+#endif
+
+ for ( i = 0; hp->h_addr_list[ i ] != 0; ++i ) {
+ SAFEMEMCPY( (char *)&sock.sin_addr.s_addr,
+ (char *)hp->h_addr_list[ i ],
+ sizeof(sock.sin_addr.s_addr));
+ if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
+ close( s );
+ free( ld );
+ return( NULL );
+ }
+ }
+
+ } else {
+ sock.sin_addr.s_addr = address;
+ if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
+ close( s );
+ free( ld );
+ return( NULL );
+ }
+ }
+
+ if ( ld->ld_host == NULL ) {
+ ld->ld_host = strdup( host );
+ }
+ }
+
+ } else {
+ address = INADDR_LOOPBACK;
+ sock.sin_addr.s_addr = htonl( address );
+ if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
+ close( s );
+ free( ld );
+ return( NULL );
+ }
+ }
+
+ if ( ld->ld_sb.sb_addrs == NULL
+#ifdef LDAP_REFERRALS
+ || ( ld->ld_defconn = new_connection( ld, NULL, 1,0,0 )) == NULL
+#endif /* LDAP_REFERRALS */
+ ) {
+ free( ld );
+ return( NULL );
+ }
+
+ ld->ld_sb.sb_useaddr = ld->ld_sb.sb_addrs[ 0 ];
+ cldap_setretryinfo( ld, 0, 0 );
+
+#ifdef LDAP_DEBUG
+ putchar( '\n' );
+ for ( i = 0; i < ld->ld_sb.sb_naddr; ++i ) {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 114, "end of cldap_open address %1$d is %2$s\n"),
+ i, inet_ntoa( ((struct sockaddr_in *)
+ ld->ld_sb.sb_addrs[ i ])->sin_addr ), 0 );
+ }
+#endif
+
+ return( ld );
+}
+
+
+
+void
+cldap_close( LDAP *ld )
+{
+ ldap_ld_free( ld, 0 );
+}
+
+
+void
+cldap_setretryinfo( LDAP *ld, int tries, time_t timeout )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ ld->ld_cldaptries = ( tries <= 0 ) ? DEF_CLDAP_TRIES : tries;
+ ld->ld_cldaptimeout = ( timeout <= 0 ) ? DEF_CLDAP_TIMEOUT : timeout;
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+
+int
+cldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs,
+ int attrsonly, LDAPMessage **res, char *logdn )
+{
+ int ret, msgid;
+ struct cldap_retinfo cri;
+
+ *res = NULLMSG;
+
+ (void) memset( &cri, 0, sizeof( cri ));
+
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+
+ if ( logdn != NULL ) {
+ ld->ld_cldapdn = logdn;
+ } else if ( ld->ld_cldapdn == NULL ) {
+ ld->ld_cldapdn = "";
+ }
+
+ do {
+ if ( cri.cri_try != 0 ) {
+ --ld->ld_msgid; /* use same id as before */
+ }
+ ld->ld_sb.sb_useaddr = ld->ld_sb.sb_addrs[ cri.cri_useaddr ];
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 115, "cldap_search_s try %1$d (to %2$s)\n"),
+ cri.cri_try, inet_ntoa( ((struct sockaddr_in *)
+ ld->ld_sb.sb_useaddr)->sin_addr ), 0 );
+
+ if ( (msgid = ldap_search( ld, base, scope, filter, attrs,
+ attrsonly )) == -1 ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno );
+ }
+#ifndef NO_CACHE
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_RESPONSE(ld);
+#endif
+ if ( ld->ld_cache != NULL && ld->ld_responses != NULL ) {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 116, "cldap_search_s res from cache\n"),
+ 0, 0, 0 );
+ *res = ld->ld_responses;
+ ld->ld_responses = ld->ld_responses->lm_next;
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+ ret = ldap_result2error( ld, *res, 0 );
+ UNLOCK_RESPONSE(ld);
+ return( ret );
+#else
+ return( ldap_result2error( ld, *res, 0 ));
+#endif
+ }
+#endif /* NO_CACHE */
+ ret = cldap_result( ld, msgid, res, &cri, base );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_RESPONSE(ld);
+#endif
+ } while (ret == -1);
+
+ return( ret );
+}
+
+
+static int
+add_addr( LDAP *ld, struct sockaddr *sap )
+{
+ struct sockaddr *newsap, **addrs;
+
+ if (( newsap = (struct sockaddr *)malloc( sizeof( struct sockaddr )))
+ == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( -1 );
+ }
+
+ if ( ld->ld_sb.sb_naddr == 0 ) {
+ addrs = (struct sockaddr **)malloc( sizeof(struct sockaddr *));
+ } else {
+ addrs = (struct sockaddr **)realloc( ld->ld_sb.sb_addrs,
+ ( ld->ld_sb.sb_naddr + 1 ) * sizeof(struct sockaddr *));
+ }
+
+ if ( addrs == NULL ) {
+ free( newsap );
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( -1 );
+ }
+
+ SAFEMEMCPY( (char *)newsap, (char *)sap, sizeof( struct sockaddr ));
+ addrs[ ld->ld_sb.sb_naddr++ ] = newsap;
+ ld->ld_sb.sb_addrs = (void **)addrs;
+ return( 0 );
+}
+
+
+static int
+cldap_result( LDAP *ld, int msgid, LDAPMessage **res,
+ struct cldap_retinfo *crip, char *base )
+{
+ Sockbuf *sb;
+ BerElement ber;
+ char *logdn;
+ int ret, id, fromaddr, i;
+ struct timeval tv;
+
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+
+ sb = &ld->ld_sb;
+ fromaddr = -1;
+
+ if ( crip->cri_try == 0 ) {
+ crip->cri_maxtries = ld->ld_cldaptries * sb->sb_naddr;
+ crip->cri_timeout = ld->ld_cldaptimeout;
+ crip->cri_useaddr = 0;
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 117, "cldap_result tries %1$d timeout %2$d\n"),
+ ld->ld_cldaptries, ld->ld_cldaptimeout, 0 );
+ }
+
+ if ((tv.tv_sec = crip->cri_timeout / sb->sb_naddr) < 1 ) {
+ tv.tv_sec = 1;
+ }
+ tv.tv_usec = 0;
+
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 118, "cldap_result waiting up to %d seconds for a response\n"),
+ tv.tv_sec, 0, 0 );
+ ber_zero_init( &ber, 0 );
+ set_ber_options( ld, &ber );
+
+ if ( cldap_getmsg( ld, &tv, &ber ) == -1 ) {
+ ret = ld->ld_errno;
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 119, "cldap_getmsg returned -1 (%d)\n"),
+ ret, 0, 0 );
+ } else if ( ld->ld_errno == LDAP_TIMEOUT ) {
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 120, "cldap_result timed out\n"), 0, 0, 0 );
+ /*
+ * It timed out; is it time to give up?
+ */
+ if ( ++crip->cri_try >= crip->cri_maxtries ) {
+ ret = LDAP_TIMEOUT;
+ --crip->cri_try;
+ } else {
+ if ( ++crip->cri_useaddr >= sb->sb_naddr ) {
+ /*
+ * new round: reset address to first one and
+ * double the timeout
+ */
+ crip->cri_useaddr = 0;
+ crip->cri_timeout <<= 1;
+ }
+ ret = -1;
+ }
+
+ } else {
+ /*
+ * Got a response. It should look like:
+ * { msgid, logdn, { searchresponse...}}
+ */
+ logdn = NULL;
+
+ if ( ber_scanf( &ber, "ia", &id, &logdn ) == LBER_ERROR ) {
+ free( ber.ber_buf ); /* gack! */
+ ret = LDAP_DECODING_ERROR;
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 121, "cldap_result: ber_scanf returned LBER_ERROR (%d)\n"),
+ ret, 0, 0 );
+ } else if ( id != msgid ) {
+ free( ber.ber_buf ); /* gack! */
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 122, "cldap_result: looking for msgid %1$d; got %2$d\n"),
+ msgid, id, 0 );
+ ret = -1; /* ignore and keep looking */
+ } else {
+ /*
+ * got a result: determine which server it came from
+ * decode into ldap message chain
+ */
+ for ( fromaddr = 0; fromaddr < sb->sb_naddr; ++fromaddr ) {
+ if ( memcmp( &((struct sockaddr_in *)
+ sb->sb_addrs[ fromaddr ])->sin_addr,
+ &((struct sockaddr_in *)sb->sb_fromaddr)->sin_addr,
+ sizeof( struct in_addr )) == 0 ) {
+ break;
+ }
+ }
+ ret = cldap_parsemsg( ld, msgid, &ber, res, base );
+ free( ber.ber_buf ); /* gack! */
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 123, "cldap_result got result (%d)\n"), ret, 0, 0 );
+ }
+
+ if ( logdn != NULL ) {
+ free( logdn );
+ }
+ }
+
+
+ /*
+ * If we are giving up (successfully or otherwise) then
+ * abandon any outstanding requests.
+ */
+ if ( ret != -1 ) {
+ i = crip->cri_try;
+ if ( i >= sb->sb_naddr ) {
+ i = sb->sb_naddr - 1;
+ }
+
+ for ( ; i >= 0; --i ) {
+ if ( i == fromaddr ) {
+ continue;
+ }
+ sb->sb_useaddr = sb->sb_addrs[ i ];
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 124, "cldap_result abandoning id %1$d (to %2$s)\n"),
+ msgid, inet_ntoa( ((struct sockaddr_in *)
+ sb->sb_useaddr)->sin_addr ), 0 );
+ (void) ldap_abandon( ld, msgid );
+ }
+ }
+
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno = ret );
+}
+
+
+static int
+cldap_parsemsg( LDAP *ld, int msgid, BerElement *ber,
+ LDAPMessage **res, char *base )
+{
+ unsigned int tag, len;
+ int rc;
+ size_t baselen, slen;
+ char *dn, *p, *cookie;
+ LDAPMessage *chain, *prev, *ldm;
+ struct berval *bv;
+
+ rc = LDAP_DECODING_ERROR; /* pessimistic */
+ ldm = chain = prev = NULLMSG;
+ baselen = ( base == NULL ) ? 0 : strlen( base );
+ bv = NULL;
+
+ for ( tag = ber_first_element( ber, &len, &cookie );
+ tag != LBER_DEFAULT && rc != LDAP_SUCCESS;
+ tag = ber_next_element( ber, &len, cookie )) {
+ if (( ldm = (LDAPMessage *)calloc( 1, sizeof(LDAPMessage)))
+ == NULL || ( ldm->lm_ber = alloc_ber_with_options( ld ))
+ == NULLBER ) {
+ rc = LDAP_NO_MEMORY;
+ break; /* return w/error*/
+ }
+ ldm->lm_msgid = msgid;
+ ldm->lm_msgtype = tag;
+
+ if ( tag == LDAP_RES_SEARCH_RESULT ) {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 125, "cldap_parsemsg got search result\n"),
+ 0, 0, 0 );
+
+ if ( ber_get_stringal( ber, &bv ) == LBER_DEFAULT ) {
+ break; /* return w/error */
+ }
+
+ if ( ber_printf( ldm->lm_ber, "to", tag, bv->bv_val,
+ bv->bv_len ) == -1 ) {
+ break; /* return w/error */
+ }
+ ber_bvfree( bv );
+ bv = NULL;
+ rc = LDAP_SUCCESS;
+
+ } else if ( tag == LDAP_RES_SEARCH_ENTRY ) {
+ if ( ber_scanf( ber, "{aO", &dn, &bv ) == LBER_ERROR ) {
+ break; /* return w/error */
+ }
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 126, "cldap_parsemsg entry %s\n"), dn, 0, 0 );
+ if ( dn != NULL && *(dn + ( slen = strlen(dn)) - 1) == '*' &&
+ baselen > 0 ) {
+ /*
+ * substitute original searchbase for trailing '*'
+ */
+ if (( p = (char *)malloc( slen + baselen )) == NULL ) {
+ rc = LDAP_NO_MEMORY;
+ free( dn );
+ break; /* return w/error */
+ }
+ strcpy( p, dn );
+ strcpy( p + slen - 1, base );
+ free( dn );
+ dn = p;
+ }
+
+ if ( ber_printf( ldm->lm_ber, "t{so}", tag, dn, bv->bv_val,
+ bv->bv_len ) == -1 ) {
+ break; /* return w/error */
+ }
+ free( dn );
+ ber_bvfree( bv );
+ bv = NULL;
+
+ } else {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 127, "cldap_parsemsg got unknown tag %d\n"),
+ tag, 0, 0 );
+ rc = LDAP_PROTOCOL_ERROR;
+ break; /* return w/error */
+ }
+
+ /* Reset message ber so we can read from it later. Gack! */
+ ldm->lm_ber->ber_end = ldm->lm_ber->ber_ptr;
+ ldm->lm_ber->ber_ptr = ldm->lm_ber->ber_buf;
+
+#ifdef LDAP_DEBUG
+ if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
+ fprintf( stderr, "cldap_parsemsg add message id %d type %d:\n",
+ ldm->lm_msgid, ldm->lm_msgtype );
+ ber_dump( ldm->lm_ber, 1 );
+ }
+#endif /* LDAP_DEBUG */
+
+#ifndef NO_CACHE
+ if ( ld->ld_cache != NULL ) {
+ add_result_to_cache( ld, ldm );
+ }
+#endif /* NO_CACHE */
+
+ if ( chain == NULL ) {
+ chain = ldm;
+ } else {
+ prev->lm_chain = ldm;
+ }
+ prev = ldm;
+ ldm = NULL;
+ }
+
+ /* dispose of any leftovers */
+ if ( ldm != NULL ) {
+ if ( ldm->lm_ber != NULLBER ) {
+ ber_free( ldm->lm_ber, 1 );
+ }
+ free( ldm );
+ }
+ if ( bv != NULL ) {
+ ber_bvfree( bv );
+ }
+
+ /* return chain, calling result2error if we got anything at all */
+ *res = chain;
+ return(( *res == NULLMSG ) ? rc : ldap_result2error( ld, *res, 0 ));
+}
+#endif /* CLDAP */
diff --git a/usr/src/lib/libldap4/common/compare.c b/usr/src/lib/libldap4/common/compare.c
new file mode 100644
index 0000000000..49a05a5feb
--- /dev/null
+++ b/usr/src/lib/libldap4/common/compare.c
@@ -0,0 +1,261 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * compare.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include "macos.h"
+#endif /* MACOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+BerElement * ldap_build_compare_req(LDAP *ld, char *dn, char *attr,
+ struct berval *bvalue, LDAPControl **serverctrls)
+{
+ BerElement *ber;
+ int rc, rv;
+
+ /* The compare request looks like this:
+ * CompareRequest ::= SEQUENCE {
+ * entry DistinguishedName,
+ * ava SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue
+ * }
+ * }
+ * and must be wrapped in an LDAPMessage.
+ */
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( NULLBER );
+ }
+
+ if ( ber_printf( ber, "{it{s{so}}", ++ld->ld_msgid, LDAP_REQ_COMPARE,
+ dn, attr, bvalue->bv_val, bvalue->bv_len ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ return( NULLBER );
+ }
+ }
+ if (ber_printf(ber, "}") == -1) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+
+ return (ber);
+}
+
+/*
+ * ldap_compare - perform an ldap (and X.500) compare operation. The dn
+ * of the entry to compare to and the attribute and value to compare (in
+ * attr and value) are supplied. The msgid of the response is returned.
+ *
+ * Example:
+ * ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" )
+ */
+int
+ldap_compare( LDAP *ld, char *dn, char *attr, char *value )
+{
+ BerElement *ber;
+ struct berval bv;
+ int rv;
+
+ /* The compare request looks like this:
+ * CompareRequest ::= SEQUENCE {
+ * entry DistinguishedName,
+ * ava SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue
+ * }
+ * }
+ * and must be wrapped in an LDAPMessage.
+ */
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 128, "ldap_compare\n"), 0, 0, 0 );
+
+ bv.bv_val = value;
+ bv.bv_len = strlen(value);
+
+ if ((ber = ldap_build_compare_req(ld, dn, attr, &bv, NULL)) == NULLBER) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+
+#ifndef NO_CACHE
+ if ( ld->ld_cache != NULL ) {
+ if ( check_cache( ld, LDAP_REQ_COMPARE, ber ) == 0 ) {
+ ber_free( ber, 1 );
+ ld->ld_errno = LDAP_SUCCESS;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_msgid );
+ }
+ add_request_to_cache( ld, LDAP_REQ_COMPARE, ber );
+ }
+#endif /* NO_CACHE */
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+}
+
+int
+ldap_compare_s( LDAP *ld, char *dn, char *attr, char *value )
+{
+ int msgid;
+ LDAPMessage *res;
+
+ if ( (msgid = ldap_compare( ld, dn, attr, value )) == -1 )
+ return( ld->ld_errno );
+
+ if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
+ return( ld->ld_errno );
+
+ return( ldap_result2error( ld, res, 1 ) );
+}
+
+/* LDAPv3 API extensions */
+int ldap_compare_ext(LDAP *ld, char *dn, char *attr, struct berval *bvalue,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp)
+{
+ BerElement *ber;
+ struct berval bv;
+ int rv;
+
+ /* The compare request looks like this:
+ * CompareRequest ::= SEQUENCE {
+ * entry DistinguishedName,
+ * ava SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue
+ * }
+ * }
+ * and must be wrapped in an LDAPMessage.
+ */
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 128, "ldap_compare\n"), 0, 0, 0 );
+
+ if ((ber = ldap_build_compare_req(ld, dn, attr, bvalue, NULL)) == NULLBER) {
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS)
+ rv = LDAP_OTHER;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+#ifndef NO_CACHE
+ if ( ld->ld_cache != NULL ) {
+ if ( check_cache( ld, LDAP_REQ_COMPARE, ber ) == 0 ) {
+ ber_free( ber, 1 );
+ ld->ld_errno = LDAP_SUCCESS;
+ *msgidp = ld->ld_msgid;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( LDAP_SUCCESS );
+ }
+ add_request_to_cache( ld, LDAP_REQ_COMPARE, ber );
+ }
+#endif /* NO_CACHE */
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber );
+ if (rv == -1) {
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS){
+ rv = LDAP_OTHER;
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+ *msgidp = rv;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_SUCCESS);
+}
+
+int ldap_compare_ext_s(LDAP *ld, char *dn, char *attr, struct berval *bvalue,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls)
+{
+ int msgid, retcode = LDAP_SUCCESS;
+ LDAPMessage *res;
+
+ if ( (retcode = ldap_compare_ext( ld, dn, attr, bvalue, serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS )
+ return( retcode );
+
+ if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
+ return( ld->ld_errno );
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ retcode = ldap_parse_result( ld, res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
+ &ld->ld_referrals, &ld->ld_ret_ctrls, 1);
+ if (retcode == LDAP_SUCCESS)
+ retcode = ld->ld_errno;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (retcode);
+}
+
diff --git a/usr/src/lib/libldap4/common/controls.c b/usr/src/lib/libldap4/common/controls.c
new file mode 100644
index 0000000000..bd95409eeb
--- /dev/null
+++ b/usr/src/lib/libldap4/common/controls.c
@@ -0,0 +1,291 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+static int ldap_control_copy_contents(LDAPControl *, LDAPControl *);
+
+void ldap_control_free (LDAPControl *ctrl)
+{
+ if (ctrl != NULL){
+ if (ctrl->ldctl_oid)
+ free (ctrl->ldctl_oid);
+ if (ctrl->ldctl_value.bv_val != NULL)
+ free (ctrl->ldctl_value.bv_val);
+ free ((char *)ctrl);
+ }
+ return;
+}
+
+void ldap_controls_free (LDAPControl **ctrls)
+{
+ int i;
+
+ if (ctrls == NULL)
+ return;
+
+ for (i = 0; ctrls[i] != NULL; i++){
+ ldap_control_free(ctrls[i]);
+ }
+ free((char *)ctrls);
+}
+
+LDAPControl * ldap_control_dup(LDAPControl *ctrl)
+{
+ LDAPControl *newctrl;
+
+ if ((newctrl = (LDAPControl *)calloc(1, sizeof(LDAPControl))) == NULL)
+ return (NULL);
+
+ if (ldap_control_copy_contents(newctrl, ctrl) != LDAP_SUCCESS) {
+ free(newctrl);
+ return (NULL);
+ }
+
+ return(newctrl);
+}
+
+
+static int ldap_control_copy_contents(LDAPControl *ctrl_dst,
+LDAPControl *ctrl_src)
+{
+ size_t len;
+
+ if (NULL == ctrl_dst || NULL == ctrl_src) {
+ return (LDAP_PARAM_ERROR);
+ }
+
+ ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical;
+
+ /* fill in the fields of this new control */
+ if ((ctrl_dst->ldctl_oid = strdup(ctrl_src->ldctl_oid)) == NULL) {
+ return (LDAP_NO_MEMORY);
+ }
+
+ len = (size_t)(ctrl_src->ldctl_value).bv_len;
+ if (ctrl_src->ldctl_value.bv_val == NULL || len <= 0) {
+ ctrl_dst->ldctl_value.bv_len = 0;
+ ctrl_dst->ldctl_value.bv_val = NULL;
+ } else {
+ ctrl_dst->ldctl_value.bv_len = len;
+ if ((ctrl_dst->ldctl_value.bv_val = malloc(len))
+ == NULL) {
+ free(ctrl_dst->ldctl_oid);
+ return (LDAP_NO_MEMORY);
+ }
+ SAFEMEMCPY(ctrl_dst->ldctl_value.bv_val,
+ ctrl_src->ldctl_value.bv_val, len);
+ }
+
+ return (LDAP_SUCCESS);
+}
+
+
+LDAPControl ** ldap_controls_dup(LDAPControl ** ctrls)
+{
+ int i;
+ LDAPControl **newctrls;
+
+ for (i = 0; ctrls[i] != NULL; i++);
+ newctrls = (LDAPControl **)calloc(i+1, sizeof(LDAPControl*));
+ if (newctrls == NULL) {
+ return (NULL);
+ }
+
+ for (i = 0; ctrls[i] != NULL; i++) {
+ newctrls[i] = ldap_control_dup(ctrls[i]);
+ if (newctrls[i] == NULL) {
+ ldap_controls_free(newctrls);
+ return (NULL);
+ }
+ }
+ return (newctrls);
+}
+
+int ldap_controls_code (BerElement *ber, LDAPControl **ctrls)
+{
+ int i, rc;
+
+ if (ctrls && ctrls[0]){
+ rc = ber_printf(ber, "t{", LDAP_TAG_CONTROL_LIST);
+ if (rc == -1){
+ ber_free(ber, 1);
+ return(LDAP_ENCODING_ERROR);
+ }
+
+ for (i = 0; ctrls[i] != NULL; i++){
+ rc = ber_printf(ber, "{s", ctrls[i]->ldctl_oid);
+ if (rc == -1){
+ ber_free(ber, 1);
+ return(LDAP_ENCODING_ERROR);
+ }
+ if (ctrls[i]->ldctl_iscritical){
+ rc = ber_printf(ber, "b", ctrls[i]->ldctl_iscritical);
+ if (rc == -1){
+ ber_free(ber, 1);
+ return(LDAP_ENCODING_ERROR);
+ }
+ }
+
+ if (ctrls[i]->ldctl_value.bv_val)
+ rc = ber_printf(ber, "o}", ctrls[i]->ldctl_value.bv_val, ctrls[i]->ldctl_value.bv_len);
+ else
+ rc = ber_printf(ber, "}");
+ if (rc == -1){
+ ber_free(ber, 1);
+ return(LDAP_ENCODING_ERROR);
+ }
+ }
+
+ rc = ber_printf(ber, "}");
+ if (rc == -1){
+ ber_free(ber, 1);
+ return(LDAP_ENCODING_ERROR);
+ }
+ }
+ return (LDAP_SUCCESS);
+}
+
+/* Decode the sequence of control from the ber, return a NULL terminated list of LDAPControl* */
+LDAPControl ** ldap_controls_decode(BerElement *ber, int *errcode)
+{
+ LDAPControl ** ctrls = NULL;
+
+ char *opaque;
+ unsigned int tag, len;
+ int i = 0, count = 0;
+
+ BerElement tmpber = *ber;
+
+ for (tag = ber_first_element(&tmpber, &len, &opaque);
+ tag != LBER_DEFAULT;
+ tag = ber_next_element(&tmpber, &len, opaque )) {
+ count ++;
+ ber_skip_tag(&tmpber, &len);
+ }
+
+
+ if ((ctrls = (LDAPControl **)calloc(count + 1, sizeof(LDAPControl *))) == NULL){
+ *errcode = LDAP_NO_MEMORY;
+ return(NULL);
+ }
+
+ for (tag = ber_first_element(ber, &len, &opaque );
+ tag != LBER_DEFAULT;
+ tag = ber_next_element (ber, &len, opaque )) {
+ LDAPControl *aCtrl;
+ unsigned int ttag, tlen;
+
+ if ((aCtrl = (LDAPControl *)calloc(1, sizeof(LDAPControl))) == NULL) {
+ *errcode = LDAP_NO_MEMORY;
+ ldap_controls_free(ctrls);
+ return (NULL);
+ }
+ if (ber_scanf(ber, "{a", &aCtrl->ldctl_oid) == LBER_ERROR){
+ *errcode = LDAP_PROTOCOL_ERROR;
+ free(aCtrl);
+ ldap_controls_free(ctrls);
+ return (NULL);
+ }
+ aCtrl->ldctl_iscritical = 0;
+ ttag = ber_peek_tag(ber, &tlen);
+ if (ttag == 0x01) { /* Boolean : criticality */
+ if (ber_scanf(ber, "b", &aCtrl->ldctl_iscritical) == LBER_ERROR){
+ *errcode = LDAP_PROTOCOL_ERROR;
+ free(aCtrl);
+ ldap_controls_free(ctrls);
+ return (NULL);
+ }
+ ttag = ber_peek_tag(ber, &tlen);
+ }
+ if (ttag == 0x04) { /* Octet string : value (it's optional)*/
+ if (ber_scanf(ber, "o", &aCtrl->ldctl_value) == LBER_ERROR){
+ *errcode = LDAP_PROTOCOL_ERROR;
+ free(aCtrl);
+ ldap_controls_free(ctrls);
+ return (NULL);
+ }
+
+ } else if (ttag != LBER_DEFAULT){
+ *errcode = LDAP_PROTOCOL_ERROR;
+ free(aCtrl);
+ ldap_controls_free(ctrls);
+ return (NULL);
+ }
+
+ if (ber_scanf(ber, "}") == LBER_ERROR){
+ *errcode = LDAP_PROTOCOL_ERROR;
+ free(aCtrl);
+ ldap_controls_free(ctrls);
+ return (NULL);
+ }
+ /* add aCtrl in ctrls */
+ ctrls[i++] = aCtrl;
+ }
+ return (ctrls);
+}
+
+/* build an allocated LDAPv3 control. Returns an LDAP error code. */
+int ldap_build_control(char *oid, BerElement *ber, int freeber,
+char iscritical, LDAPControl **ctrlp)
+{
+ int rc;
+ struct berval *bvp;
+
+ if (ber == NULL) {
+ bvp = NULL;
+ } else {
+ /* allocate struct berval with contents of the BER encoding */
+ rc = ber_flatten(ber, &bvp);
+ if (freeber) {
+ ber_free(ber, 1);
+ }
+ if (rc == -1) {
+ return (LDAP_NO_MEMORY);
+ }
+ }
+
+ /* allocate the new control structure */
+ if ((*ctrlp = (LDAPControl *)calloc(1, sizeof (LDAPControl)))
+ == NULL) {
+ if (bvp != NULL) {
+ ber_bvfree(bvp);
+ }
+ return (LDAP_NO_MEMORY);
+ }
+
+ /* fill in the fields of this new control */
+ (*ctrlp)->ldctl_iscritical = iscritical;
+ if (((*ctrlp)->ldctl_oid = strdup(oid)) == NULL) {
+ free(*ctrlp);
+ *ctrlp = NULL;
+ if (bvp != NULL) {
+ ber_bvfree(bvp);
+ }
+ return (LDAP_NO_MEMORY);
+ }
+
+ if (bvp == NULL) {
+ (*ctrlp)->ldctl_value.bv_len = 0;
+ (*ctrlp)->ldctl_value.bv_val = NULL;
+ } else {
+ (*ctrlp)->ldctl_value = *bvp; /* struct copy */
+ free(bvp); /* free container, not contents! */
+ }
+
+ return (LDAP_SUCCESS);
+}
diff --git a/usr/src/lib/libldap4/common/delete.c b/usr/src/lib/libldap4/common/delete.c
new file mode 100644
index 0000000000..107151d0a3
--- /dev/null
+++ b/usr/src/lib/libldap4/common/delete.c
@@ -0,0 +1,205 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * delete.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include "macos.h"
+#endif /* MACOS */
+
+#if defined( DOS ) || defined( _WIN32 )
+#include "msdos.h"
+#endif /* DOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+BerElement * ldap_build_delete_req(LDAP *ld, char *dn, LDAPControl **serverctrls)
+{
+ BerElement *ber;
+ int rv;
+
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return(NULLBER );
+ }
+
+ if ( ber_printf( ber, "{its", ++ld->ld_msgid, LDAP_REQ_DELETE, dn ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return(NULLBER );
+ }
+
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ return (ber);
+}
+
+/*
+ * ldap_delete - initiate an ldap (and X.500) delete operation. Parameters:
+ *
+ * ld LDAP descriptor
+ * dn DN of the object to delete
+ *
+ * Example:
+ * msgid = ldap_delete( ld, dn );
+ */
+int
+ldap_delete( LDAP *ld, char *dn )
+{
+ BerElement *ber;
+ int rv;
+
+ /*
+ * A delete request looks like this:
+ * DelRequet ::= DistinguishedName,
+ */
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 129, "ldap_delete\n"), 0, 0, 0 );
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+
+ if (( ber = ldap_build_delete_req(ld, dn, NULL)) == NULLBER) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_DELETE, dn, ber );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return ( rv );
+}
+
+
+int
+ldap_delete_s( LDAP *ld, char *dn )
+{
+ int msgid;
+ LDAPMessage *res;
+
+ if ( (msgid = ldap_delete( ld, dn )) == -1 )
+ return( ld->ld_errno );
+
+ if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
+ return( ld->ld_errno );
+
+ return( ldap_result2error( ld, res, 1 ) );
+}
+
+/* ldapv3 API extensions */
+
+int ldap_delete_ext(LDAP *ld, char *dn, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp)
+{
+ BerElement *ber;
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 192, "ldap_modify\n"), 0, 0, 0 );
+
+ if ((ber = ldap_build_delete_req(ld, dn, serverctrls)) == NULLBER){
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS)
+ rv = LDAP_OTHER;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_DELETE, dn, ber );
+ if (rv == -1){
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS){
+ rv = LDAP_OTHER;
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+ *msgidp = rv;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return ( LDAP_SUCCESS );
+}
+
+int ldap_delete_ext_s(LDAP *ld, char *dn, LDAPControl **serverctrls, LDAPControl **clientctrls)
+{
+ int msgid;
+ int retcode = LDAP_SUCCESS;
+ LDAPMessage *res;
+
+ if ((retcode = ldap_delete_ext(ld, dn, serverctrls, clientctrls, &msgid)) != LDAP_SUCCESS)
+ return (retcode);
+ if (ldap_result(ld, msgid, 1, (struct timeval *)NULL, &res ) == -1)
+ return (ld->ld_errno );
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ retcode = ldap_parse_result( ld, res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
+ &ld->ld_referrals, &ld->ld_ret_ctrls, 1);
+ if (retcode == LDAP_SUCCESS)
+ retcode = ld->ld_errno;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (retcode);
+}
diff --git a/usr/src/lib/libldap4/common/disptmpl.c b/usr/src/lib/libldap4/common/disptmpl.c
new file mode 100644
index 0000000000..ce5cb6e3b4
--- /dev/null
+++ b/usr/src/lib/libldap4/common/disptmpl.c
@@ -0,0 +1,753 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 1993, 1994 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ *
+ * disptmpl.c: display template library routines for LDAP clients
+ * 7 March 1994 by Mark C Smith
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef MACOS
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/file.h>
+#ifndef VMS
+#include <unistd.h>
+#endif /* VMS */
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifndef NEEDPROTOS
+static void free_disptmpl();
+static int read_next_tmpl();
+int next_line_tokens();
+#else /* !NEEDPROTOS */
+static void free_disptmpl( struct ldap_disptmpl *tmpl );
+static int read_next_tmpl( char **bufp, ssize_t *blenp,
+ struct ldap_disptmpl **tmplp, int dtversion );
+int next_line_tokens( char **bufp, ssize_t *blenp, char ***toksp );
+#endif /* !NEEDPROTOS */
+
+static char *tmploptions[] = {
+ "addable", "modrdn",
+ "altview",
+ NULL
+};
+
+
+static unsigned int tmploptvals[] = {
+ LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN,
+ LDAP_DTMPL_OPT_ALTVIEW,
+};
+
+
+static char *itemtypes[] = {
+ "cis", "mls", "dn",
+ "bool", "jpeg", "jpegbtn",
+ "fax", "faxbtn", "audiobtn",
+ "time", "date", "url",
+ "searchact", "linkact", "adddnact",
+ "addact", "verifyact", "mail",
+#ifdef SUN
+ "protected",
+#endif
+ NULL
+};
+
+static unsigned int itemsynids[] = {
+ LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN,
+ LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON,
+ LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON,
+ LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL,
+ LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION,
+ LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR,
+#ifdef SUN
+ LDAP_SYN_PROTECTED,
+#endif
+};
+
+
+static char *itemoptions[] = {
+ "ro", "sort",
+ "1val", "hide",
+ "required", "hideiffalse",
+ NULL
+};
+
+
+static unsigned int itemoptvals[] = {
+ LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES,
+ LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY,
+ LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE,
+};
+
+
+#define ADDEF_CONSTANT "constant"
+#define ADDEF_ADDERSDN "addersdn"
+
+#ifdef SUN
+/* LP@Sun : right_trim */
+static void right_trim(char *aStr)
+{
+ char * theEnd = aStr + strlen(aStr);
+ while ((theEnd > aStr) && isspace(*(theEnd - 1)))
+ theEnd--;
+ theEnd;
+ *theEnd= '\0';
+}
+#endif
+
+int
+ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp )
+{
+ FILE *fp;
+ char *buf;
+ ssize_t rlen, len;
+ int rc, eof;
+
+ *tmpllistp = NULLDISPTMPL;
+
+ if (( fp = fopen( file, "r" )) == NULL ) {
+ return( LDAP_TMPL_ERR_FILE );
+ }
+
+ if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
+ fclose( fp );
+ return( LDAP_TMPL_ERR_FILE );
+ }
+
+ len = ftell( fp );
+
+ if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
+ fclose( fp );
+ return( LDAP_TMPL_ERR_FILE );
+ }
+
+ if (( buf = malloc( len )) == NULL ) {
+ fclose( fp );
+ return( LDAP_TMPL_ERR_MEM );
+ }
+
+ rlen = fread( buf, (size_t) 1, len, fp );
+ eof = feof( fp );
+ fclose( fp );
+
+ if ( rlen != len && !eof ) { /* error: didn't get the whole file */
+ free( buf );
+ return( LDAP_TMPL_ERR_FILE );
+ }
+
+ rc = ldap_init_templates_buf( buf, rlen, tmpllistp );
+ free( buf );
+
+ return( rc );
+}
+
+
+int
+ldap_init_templates_buf( char *buf, ssize_t buflen,
+ struct ldap_disptmpl **tmpllistp )
+{
+ int rc, version;
+ char **toks;
+ struct ldap_disptmpl *prevtmpl, *tmpl;
+
+ *tmpllistp = prevtmpl = NULLDISPTMPL;
+
+ if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
+ strcasecmp( toks[ 0 ], "version" ) != 0 ) {
+ free_strarray( toks );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+ version = atoi( toks[ 1 ] );
+ free_strarray( toks );
+ if ( version != LDAP_TEMPLATE_VERSION ) {
+ return( LDAP_TMPL_ERR_VERSION );
+ }
+
+ while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl,
+ version )) == 0 && tmpl != NULLDISPTMPL ) {
+ if ( prevtmpl == NULLDISPTMPL ) {
+ *tmpllistp = tmpl;
+ } else {
+ prevtmpl->dt_next = tmpl;
+ }
+ prevtmpl = tmpl;
+ }
+
+ if ( rc != 0 ) {
+ ldap_free_templates( *tmpllistp );
+ }
+
+ return( rc );
+}
+
+
+
+void
+ldap_free_templates( struct ldap_disptmpl *tmpllist )
+{
+ struct ldap_disptmpl *tp, *nexttp;
+
+ if ( tmpllist != NULL ) {
+ for ( tp = tmpllist; tp != NULL; tp = nexttp ) {
+ nexttp = tp->dt_next;
+ free_disptmpl( tp );
+ }
+ }
+}
+
+
+static void
+free_disptmpl( struct ldap_disptmpl *tmpl )
+{
+ if ( tmpl != NULL ) {
+ if ( tmpl->dt_name != NULL ) {
+ free( tmpl->dt_name );
+ }
+
+ if ( tmpl->dt_pluralname != NULL ) {
+ free( tmpl->dt_pluralname );
+ }
+
+ if ( tmpl->dt_iconname != NULL ) {
+ free( tmpl->dt_iconname );
+ }
+
+ if ( tmpl->dt_authattrname != NULL ) {
+ free( tmpl->dt_authattrname );
+ }
+
+ if ( tmpl->dt_defrdnattrname != NULL ) {
+ free( tmpl->dt_defrdnattrname );
+ }
+
+ if ( tmpl->dt_defaddlocation != NULL ) {
+ free( tmpl->dt_defaddlocation );
+ }
+
+ if ( tmpl->dt_oclist != NULL ) {
+ struct ldap_oclist *ocp, *nextocp;
+
+ for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) {
+ nextocp = ocp->oc_next;
+ free_strarray( ocp->oc_objclasses );
+ free( ocp );
+ }
+ }
+
+ if ( tmpl->dt_adddeflist != NULL ) {
+ struct ldap_adddeflist *adp, *nextadp;
+
+ for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) {
+ nextadp = adp->ad_next;
+ if( adp->ad_attrname != NULL ) {
+ free( adp->ad_attrname );
+ }
+ if( adp->ad_value != NULL ) {
+ free( adp->ad_value );
+ }
+ free( adp );
+ }
+ }
+
+ if ( tmpl->dt_items != NULL ) {
+ struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp;
+
+ for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) {
+ nextrowp = rowp->ti_next_in_col;
+ for ( colp = rowp; colp != NULL; colp = nextcolp ) {
+ nextcolp = colp->ti_next_in_row;
+ if ( colp->ti_attrname != NULL ) {
+ free( colp->ti_attrname );
+ }
+ if ( colp->ti_label != NULL ) {
+ free( colp->ti_label );
+ }
+ if ( colp->ti_args != NULL ) {
+ free_strarray( colp->ti_args );
+ }
+ free( colp );
+ }
+ }
+ }
+
+ free( tmpl );
+ }
+}
+
+
+struct ldap_disptmpl *
+ldap_first_disptmpl( struct ldap_disptmpl *tmpllist )
+{
+ return( tmpllist );
+}
+
+
+struct ldap_disptmpl *
+ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
+ struct ldap_disptmpl *tmpl )
+{
+ return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next );
+}
+
+
+struct ldap_disptmpl *
+ldap_name2template( char *name, struct ldap_disptmpl *tmpllist )
+{
+ struct ldap_disptmpl *dtp;
+
+ for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
+ dtp = ldap_next_disptmpl( tmpllist, dtp )) {
+ if ( strcasecmp( name, dtp->dt_name ) == 0 ) {
+ return( dtp );
+ }
+ }
+
+ return( NULLDISPTMPL );
+}
+
+
+struct ldap_disptmpl *
+ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist )
+{
+ struct ldap_disptmpl *dtp;
+ struct ldap_oclist *oclp;
+ int i, j, needcnt, matchcnt;
+
+ if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) {
+ return( NULLDISPTMPL );
+ }
+
+ for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
+ dtp = ldap_next_disptmpl( tmpllist, dtp )) {
+ for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST;
+ oclp = oclp->oc_next ) {
+ needcnt = matchcnt = 0;
+ for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) {
+ for ( j = 0; oclist[ j ] != NULL; ++j ) {
+#ifdef SUN
+ /* LP@Sun : remove ending space from objectclass */
+ right_trim(oclist[j]);
+#endif
+ if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] )
+ == 0 ) {
+ ++matchcnt;
+ }
+ }
+ ++needcnt;
+ }
+
+ if ( matchcnt == needcnt ) {
+ return( dtp );
+ }
+ }
+ }
+
+ return( NULLDISPTMPL );
+}
+
+
+struct ldap_tmplitem *
+ldap_first_tmplrow( struct ldap_disptmpl *tmpl )
+{
+ return( tmpl->dt_items );
+}
+
+
+struct ldap_tmplitem *
+ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
+{
+ return( row == NULLTMPLITEM ? row : row->ti_next_in_col );
+}
+
+
+struct ldap_tmplitem *
+ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
+{
+ return( row );
+}
+
+
+struct ldap_tmplitem *
+ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
+ struct ldap_tmplitem *col )
+{
+ return( col == NULLTMPLITEM ? col : col->ti_next_in_row );
+}
+
+
+char **
+ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
+ int exclude, unsigned int syntaxmask )
+{
+/*
+ * this routine should filter out duplicate attributes...
+ */
+ struct ldap_tmplitem *tirowp, *ticolp;
+ int i, attrcnt, memerr;
+ char **attrs;
+
+ attrcnt = 0;
+ memerr = 0;
+
+ if (( attrs = (char **)malloc( sizeof( char * ))) == NULL ) {
+ return( NULL );
+ }
+
+ if ( includeattrs != NULL ) {
+ for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) {
+ if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
+ sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
+ strdup( includeattrs[ i ] )) == NULL ) {
+ memerr = 1;
+ } else {
+ attrs[ attrcnt ] = NULL;
+ }
+ }
+ }
+
+ for ( tirowp = ldap_first_tmplrow( tmpl );
+ !memerr && tirowp != NULLTMPLITEM;
+ tirowp = ldap_next_tmplrow( tmpl, tirowp )) {
+ for ( ticolp = ldap_first_tmplcol( tmpl, tirowp );
+ ticolp != NULLTMPLITEM;
+ ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) {
+
+ if ( syntaxmask != 0 ) {
+ if (( exclude &&
+ ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) ||
+ ( !exclude &&
+ ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) {
+ continue;
+ }
+ }
+
+ if ( ticolp->ti_attrname != NULL ) {
+ if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
+ sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
+ strdup( ticolp->ti_attrname )) == NULL ) {
+ memerr = 1;
+ } else {
+ attrs[ attrcnt ] = NULL;
+ }
+ }
+ }
+ }
+
+ if ( memerr || attrcnt == 0 ) {
+ for ( i = 0; i < attrcnt; ++i ) {
+ if ( attrs[ i ] != NULL ) {
+ free( attrs[ i ] );
+ }
+ }
+
+ free( (char *)attrs );
+ return( NULL );
+ }
+
+ return( attrs );
+}
+
+
+static int
+read_next_tmpl( char **bufp, ssize_t *blenp, struct ldap_disptmpl **tmplp,
+ int dtversion )
+{
+ int i, j, tokcnt, samerow, adsource;
+ char **toks, *itemopts;
+ struct ldap_disptmpl *tmpl;
+ struct ldap_oclist *ocp, *prevocp;
+ struct ldap_adddeflist *adp, *prevadp;
+ struct ldap_tmplitem *rowp, *ip, *previp;
+
+ *tmplp = NULL;
+
+ /*
+ * template name comes first
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX );
+ }
+
+ if (( tmpl = (struct ldap_disptmpl *)calloc( (size_t) 1,
+ sizeof( struct ldap_disptmpl ))) == NULL ) {
+ free_strarray( toks );
+ return( LDAP_TMPL_ERR_MEM );
+ }
+ tmpl->dt_name = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * template plural name comes next
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+ tmpl->dt_pluralname = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * template icon name is next
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+ tmpl->dt_iconname = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * template options come next
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+ for ( i = 0; toks[ i ] != NULL; ++i ) {
+ for ( j = 0; tmploptions[ j ] != NULL; ++j ) {
+ if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) {
+ tmpl->dt_options |= tmploptvals[ j ];
+ }
+ }
+ }
+ free_strarray( toks );
+
+ /*
+ * object class list is next
+ */
+ while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
+ if (( ocp = (struct ldap_oclist *)calloc( (size_t) 1,
+ sizeof( struct ldap_oclist ))) == NULL ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_MEM );
+ }
+ ocp->oc_objclasses = toks;
+ if ( tmpl->dt_oclist == NULL ) {
+ tmpl->dt_oclist = ocp;
+ } else {
+ prevocp->oc_next = ocp;
+ }
+ prevocp = ocp;
+ }
+ if ( tokcnt < 0 ) {
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+
+ /*
+ * read name of attribute to authenticate as
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+ if ( toks[ 0 ][ 0 ] != '\0' ) {
+ tmpl->dt_authattrname = toks[ 0 ];
+ } else {
+ free( toks[ 0 ] );
+ }
+ free( (char *)toks );
+
+ /*
+ * read default attribute to use for RDN
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+ tmpl->dt_defrdnattrname = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * read default location for new entries
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+ if ( toks[ 0 ][ 0 ] != '\0' ) {
+ tmpl->dt_defaddlocation = toks[ 0 ];
+ } else {
+ free( toks[ 0 ] );
+ }
+ free( (char *)toks );
+
+ /*
+ * read list of rules used to define default values for new entries
+ */
+ while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
+ if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) {
+ adsource = LDAP_ADSRC_CONSTANTVALUE;
+ } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) {
+ adsource = LDAP_ADSRC_ADDERSDN;
+ } else {
+ adsource = 0;
+ }
+ if ( adsource == 0 || tokcnt < 2 ||
+ ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) ||
+ ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+
+ if (( adp = (struct ldap_adddeflist *)calloc( (size_t) 1,
+ sizeof( struct ldap_adddeflist ))) == NULL ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_MEM );
+ }
+ adp->ad_source = adsource;
+ adp->ad_attrname = toks[ 1 ];
+ if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) {
+ adp->ad_value = toks[ 2 ];
+ }
+ free( toks[ 0 ] );
+ free( (char *)toks );
+
+ if ( tmpl->dt_adddeflist == NULL ) {
+ tmpl->dt_adddeflist = adp;
+ } else {
+ prevadp->ad_next = adp;
+ }
+ prevadp = adp;
+ }
+
+ /*
+ * item list is next
+ */
+ samerow = 0;
+ while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
+ if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) {
+ if ( tokcnt < 4 ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+
+ if (( ip = (struct ldap_tmplitem *)calloc( (size_t) 1,
+ sizeof( struct ldap_tmplitem ))) == NULL ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_MEM );
+ }
+
+ /*
+ * find syntaxid from config file string
+ */
+ while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) {
+ *itemopts++ = '\0';
+ for ( i = 0; itemoptions[ i ] != NULL; ++i ) {
+ if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) {
+ break;
+ }
+ }
+ if ( itemoptions[ i ] == NULL ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+ ip->ti_options |= itemoptvals[ i ];
+ }
+
+ for ( i = 0; itemtypes[ i ] != NULL; ++i ) {
+ if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) {
+ break;
+ }
+ }
+ if ( itemtypes[ i ] == NULL ) {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+
+ free( toks[ 0 ] );
+ free( toks[ 1 ] );
+ ip->ti_syntaxid = itemsynids[ i ];
+ ip->ti_label = toks[ 2 ];
+ if ( toks[ 3 ][ 0 ] == '\0' ) {
+ ip->ti_attrname = NULL;
+ free( toks[ 3 ] );
+ } else {
+ ip->ti_attrname = toks[ 3 ];
+ }
+ if ( toks[ 4 ] != NULL ) { /* extra args. */
+ for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
+ ;
+ }
+ if (( ip->ti_args = (char **) calloc( (size_t) (i + 1), sizeof( char * )))
+ == NULL ) {
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_MEM );
+ }
+ for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
+ ip->ti_args[ i ] = toks[ i + 4 ];
+ }
+ }
+ free( (char *)toks );
+
+ if ( tmpl->dt_items == NULL ) {
+ tmpl->dt_items = rowp = ip;
+ } else if ( samerow ) {
+ previp->ti_next_in_row = ip;
+ } else {
+ rowp->ti_next_in_col = ip;
+ rowp = ip;
+ }
+ previp = ip;
+ samerow = 0;
+ } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) {
+ free_strarray( toks );
+ samerow = 1;
+ } else {
+ free_strarray( toks );
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+ }
+ if ( tokcnt < 0 ) {
+ free_disptmpl( tmpl );
+ return( LDAP_TMPL_ERR_SYNTAX );
+ }
+
+ *tmplp = tmpl;
+ return( 0 );
+}
diff --git a/usr/src/lib/libldap4/common/dsparse.c b/usr/src/lib/libldap4/common/dsparse.c
new file mode 100644
index 0000000000..ab0aeefb36
--- /dev/null
+++ b/usr/src/lib/libldap4/common/dsparse.c
@@ -0,0 +1,216 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1993, 1994 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ *
+ * dsparse.c: parsing routines used by display template and search
+ * preference file library routines for LDAP clients.
+ *
+ * 7 March 1994 by Mark C Smith
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdlib.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifndef NEEDPROTOS
+int next_line_tokens();
+static ssize_t next_line();
+static char *next_token();
+#else /* !NEEDPROTOS */
+int next_line_tokens( char **bufp, ssize_t *blenp, char ***toksp );
+static ssize_t next_line( char **bufp, ssize_t *blenp, char **linep );
+static char *next_token( char ** sp );
+#endif /* !NEEDPROTOS */
+
+
+
+int
+next_line_tokens( char **bufp, ssize_t *blenp, char ***toksp )
+{
+ char *p, *line, *token, **toks;
+ ssize_t rc;
+ int tokcnt;
+
+ *toksp = NULL;
+
+ if (( rc = next_line( bufp, blenp, &line )) <= 0 ) {
+ return( (int)rc );
+ }
+
+ if (( toks = (char **)calloc( (size_t) 1, sizeof( char * ))) == NULL ) {
+ free( line );
+ return( -1 );
+ }
+ tokcnt = 0;
+
+ p = line;
+ while (( token = next_token( &p )) != NULL ) {
+ if (( toks = (char **)realloc( toks, ( tokcnt + 2 ) *
+ sizeof( char * ))) == NULL ) {
+ free( (char *)toks );
+ free( line );
+ return( -1 );
+ }
+ toks[ tokcnt ] = token;
+ toks[ ++tokcnt ] = NULL;
+ }
+
+ if ( tokcnt == 1 && strcasecmp( toks[ 0 ], "END" ) == 0 ) {
+ tokcnt = 0;
+ free_strarray( toks );
+ toks = NULL;
+ }
+
+ free( line );
+
+ if ( tokcnt == 0 ) {
+ if ( toks != NULL ) {
+ free( (char *)toks );
+ }
+ } else {
+ *toksp = toks;
+ }
+
+ return( tokcnt );
+}
+
+
+static ssize_t
+next_line( char **bufp, ssize_t *blenp, char **linep )
+{
+ char *linestart, *line, *p;
+ ssize_t plen;
+
+ linestart = *bufp;
+ p = *bufp;
+ plen = *blenp;
+
+ do {
+ for ( linestart = p; plen > 0; ++p, --plen ) {
+ if ( *p == '\r' ) {
+ if ( plen > 1 && *(p+1) == '\n' ) {
+ ++p;
+ --plen;
+ }
+ break;
+ }
+
+ if ( *p == '\n' ) {
+ if ( plen > 1 && *(p+1) == '\r' ) {
+ ++p;
+ --plen;
+ }
+ break;
+ }
+ }
+ ++p;
+ --plen;
+ } while ( plen > 0 && ( *linestart == '#' || linestart + 1 == p ));
+
+
+ *bufp = p;
+ *blenp = plen;
+
+
+ if ( plen <= 0 ) {
+ *linep = NULL;
+ return( 0 ); /* end of file */
+ }
+
+ if (( line = malloc( p - linestart )) == NULL ) {
+ *linep = NULL;
+ return( -1 ); /* fatal error */
+ }
+
+ (void) memcpy( line, linestart, p - linestart );
+ line[ p - linestart - 1 ] = '\0';
+ *linep = line;
+ return( strlen( line ));
+}
+
+
+static char *
+next_token( char **sp )
+{
+ int in_quote = 0;
+ char *p, *tokstart, *t;
+
+ if ( **sp == '\0' ) {
+ return( NULL );
+ }
+
+ p = *sp;
+
+ while ( isspace( *p )) { /* skip leading white space */
+ ++p;
+ }
+
+ if ( *p == '\0' ) {
+ return( NULL );
+ }
+
+ if ( *p == '\"' ) {
+ in_quote = 1;
+ ++p;
+ }
+ t = tokstart = p;
+
+ for ( ;; ) {
+ if ( *p == '\0' || ( isspace( *p ) && !in_quote )) {
+ if ( *p != '\0' ) {
+ ++p;
+ }
+ *t++ = '\0'; /* end of token */
+ break;
+ }
+
+ if ( *p == '\"' ) {
+ in_quote = !in_quote;
+ ++p;
+ } else {
+ *t++ = *p++;
+ }
+ }
+
+ *sp = p;
+
+ if ( t == tokstart ) {
+ return( NULL );
+ }
+
+ return( strdup( tokstart ));
+}
diff --git a/usr/src/lib/libldap4/common/error.c b/usr/src/lib/libldap4/common/error.c
new file mode 100644
index 0000000000..804b9b1637
--- /dev/null
+++ b/usr/src/lib/libldap4/common/error.c
@@ -0,0 +1,347 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* free() for Solaris */
+#ifdef MACOS
+#include <stdlib.h>
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* DOS */
+#endif /* MACOS */
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+struct ldaperror {
+ int e_code;
+ char *e_reason;
+};
+
+static struct ldaperror ldap_errlist[] = {
+#ifdef SUN
+ LDAP_SUCCESS, 0,
+ LDAP_OPERATIONS_ERROR, 0,
+ LDAP_PROTOCOL_ERROR, 0,
+ LDAP_TIMELIMIT_EXCEEDED, 0,
+ LDAP_SIZELIMIT_EXCEEDED, 0,
+ LDAP_COMPARE_FALSE, 0,
+ LDAP_COMPARE_TRUE, 0,
+ LDAP_AUTH_METHOD_NOT_SUPPORTED, 0,
+ LDAP_STRONG_AUTH_REQUIRED, 0,
+ LDAP_PARTIAL_RESULTS, 0,
+/* new with ldapv3 */
+ LDAP_REFERRAL, 0,
+ LDAP_ADMINLIMIT_EXCEEDED, 0,
+ LDAP_UNAVAILABLE_CRITICAL_EXTENSION, 0,
+ LDAP_CONFIDENTIALITY_REQUIRED, 0,
+/* end of new */
+ LDAP_NO_SUCH_ATTRIBUTE, 0,
+ LDAP_UNDEFINED_TYPE, 0,
+ LDAP_INAPPROPRIATE_MATCHING, 0,
+ LDAP_CONSTRAINT_VIOLATION, 0,
+ LDAP_TYPE_OR_VALUE_EXISTS, 0,
+ LDAP_INVALID_SYNTAX, 0,
+ LDAP_NO_SUCH_OBJECT, 0,
+ LDAP_ALIAS_PROBLEM, 0,
+ LDAP_INVALID_DN_SYNTAX, 0,
+ LDAP_IS_LEAF, 0,
+ LDAP_ALIAS_DEREF_PROBLEM, 0,
+ LDAP_INAPPROPRIATE_AUTH, 0,
+ LDAP_INVALID_CREDENTIALS, 0,
+ LDAP_INSUFFICIENT_ACCESS, 0,
+ LDAP_BUSY, 0,
+ LDAP_UNAVAILABLE, 0,
+ LDAP_UNWILLING_TO_PERFORM, 0,
+ LDAP_LOOP_DETECT, 0,
+ LDAP_NAMING_VIOLATION, 0,
+ LDAP_OBJECT_CLASS_VIOLATION, 0,
+ LDAP_NOT_ALLOWED_ON_NONLEAF, 0,
+ LDAP_NOT_ALLOWED_ON_RDN, 0,
+ LDAP_ALREADY_EXISTS, 0,
+ LDAP_NO_OBJECT_CLASS_MODS, 0,
+ LDAP_RESULTS_TOO_LARGE, 0,
+/* new with ldapv3 */
+ LDAP_AFFECTS_MULTIPLE_DSAS, 0,
+/* end of new */
+ LDAP_OTHER, 0,
+ LDAP_SERVER_DOWN, 0,
+ LDAP_LOCAL_ERROR, 0,
+ LDAP_ENCODING_ERROR, 0,
+ LDAP_DECODING_ERROR, 0,
+ LDAP_TIMEOUT, 0,
+ LDAP_AUTH_UNKNOWN, 0,
+ LDAP_FILTER_ERROR, 0,
+ LDAP_USER_CANCELLED, 0,
+ LDAP_PARAM_ERROR, 0,
+ LDAP_NO_MEMORY, 0,
+/* new with ldapv3 */
+ LDAP_CONNECT_ERROR, 0,
+ LDAP_NOT_SUPPORTED, 0,
+ LDAP_CONTROL_NOT_FOUND, 0,
+ LDAP_NO_RESULTS_RETURNED, 0,
+ LDAP_MORE_RESULTS_TO_RETURN, 0,
+ LDAP_CLIENT_LOOP, 0,
+ LDAP_REFERRAL_LIMIT_EXCEEDED, 0,
+/* end of new */
+#else
+ LDAP_SUCCESS, "Success",
+ LDAP_OPERATIONS_ERROR, "Operations error",
+ LDAP_PROTOCOL_ERROR, "Protocol error",
+ LDAP_TIMELIMIT_EXCEEDED, "Timelimit exceeded",
+ LDAP_SIZELIMIT_EXCEEDED, "Sizelimit exceeded",
+ LDAP_COMPARE_FALSE, "Compare false",
+ LDAP_COMPARE_TRUE, "Compare true",
+ LDAP_AUTH_METHOD_NOT_SUPPORTED, "Authentication method not supported",
+ LDAP_STRONG_AUTH_REQUIRED, "Strong authentication required",
+ LDAP_PARTIAL_RESULTS, "Partial results and referral received",
+/* new with ldapv3 */
+ LDAP_REFERRAL, "Referral received",
+ LDAP_ADMINLIMIT_EXCEEDED, "Admin. limit exceeded",
+ LDAP_UNAVAILABLE_CRITICAL_EXTENSION, "Unavailable critical extension",
+ LDAP_CONFIDENTIALITY_REQUIRED, "Confidentiality required",
+/* end of new */
+ LDAP_NO_SUCH_ATTRIBUTE, "No such attribute",
+ LDAP_UNDEFINED_TYPE, "Undefined attribute type",
+ LDAP_INAPPROPRIATE_MATCHING, "Inappropriate matching",
+ LDAP_CONSTRAINT_VIOLATION, "Constraint violation",
+ LDAP_TYPE_OR_VALUE_EXISTS, "Type or value exists",
+ LDAP_INVALID_SYNTAX, "Invalid syntax",
+ LDAP_NO_SUCH_OBJECT, "No such object",
+ LDAP_ALIAS_PROBLEM, "Alias problem",
+ LDAP_INVALID_DN_SYNTAX, "Invalid DN syntax",
+ LDAP_IS_LEAF, "Object is a leaf",
+ LDAP_ALIAS_DEREF_PROBLEM, "Alias dereferencing problem",
+ LDAP_INAPPROPRIATE_AUTH, "Inappropriate authentication",
+ LDAP_INVALID_CREDENTIALS, "Invalid credentials",
+ LDAP_INSUFFICIENT_ACCESS, "Insufficient access",
+ LDAP_BUSY, "DSA is busy",
+ LDAP_UNAVAILABLE, "DSA is unavailable",
+ LDAP_UNWILLING_TO_PERFORM, "DSA is unwilling to perform",
+ LDAP_LOOP_DETECT, "Loop detected",
+ LDAP_NAMING_VIOLATION, "Naming violation",
+ LDAP_OBJECT_CLASS_VIOLATION, "Object class violation",
+ LDAP_NOT_ALLOWED_ON_NONLEAF, "Operation not allowed on nonleaf",
+ LDAP_NOT_ALLOWED_ON_RDN, "Operation not allowed on RDN",
+ LDAP_ALREADY_EXISTS, "Already exists",
+ LDAP_NO_OBJECT_CLASS_MODS, "Cannot modify object class",
+ LDAP_RESULTS_TOO_LARGE, "Results too large",
+/* new with ldapv3 */
+ LDAP_AFFECTS_MULTIPLE_DSAS, "Affects multiple DSAs",
+/* end of new */
+ LDAP_OTHER, "Unknown error",
+ LDAP_SERVER_DOWN, "Can't contact LDAP server",
+ LDAP_LOCAL_ERROR, "Local error",
+ LDAP_ENCODING_ERROR, "Encoding error",
+ LDAP_DECODING_ERROR, "Decoding error",
+ LDAP_TIMEOUT, "Timed out",
+ LDAP_AUTH_UNKNOWN, "Unknown authentication method",
+ LDAP_FILTER_ERROR, "Bad search filter",
+ LDAP_USER_CANCELLED, "User cancelled operation",
+ LDAP_PARAM_ERROR, "Bad parameter to an ldap routine",
+ LDAP_NO_MEMORY, "Out of memory",
+/* new with ldapv3 */
+ LDAP_CONNECT_ERROR, "Connection error",
+ LDAP_NOT_SUPPORTED, "Not supported",
+ LDAP_CONTROL_NOT_FOUND, "Control not found",
+ LDAP_NO_RESULTS_RETURNED, "No results have been returned",
+ LDAP_MORE_RESULTS_TO_RETURN, "More results to return",
+ LDAP_CLIENT_LOOP, "Loop detected in referrals",
+ LDAP_REFERRAL_LIMIT_EXCEEDED, "Too many referrals followed",
+/* end of new */
+#endif
+ -1, 0
+};
+
+#ifdef SUN
+#pragma init (fill_ldap_errlist)
+
+static void fill_ldap_errlist()
+{
+ int i=0;
+ Debug(LDAP_DEBUG_TRACE, "fill_ldap_errlist\n", 0, 0, 0 );
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 130, "Success");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 131, "Operations error");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 132, "Protocol error");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 133, "Timelimit exceeded");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 134, "Sizelimit exceeded");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 135, "Compare false");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 136, "Compare true");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 137, "Strong authentication not supported");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 138, "Strong authentication required");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 139, "Partial results and referral received");
+/* new with ldapv3 */
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1262, "Referral received");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1263, "Admin. limit exceeded");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1264, "Unavailable critical extension");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1265, "Confidentiality required");
+/* end of new */
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 140, "No such attribute");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 141, "Undefined attribute type");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 142, "Inappropriate matching");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 143, "Constraint violation");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 144, "Type or value exists");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 145, "Invalid syntax");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 146, "No such object");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 147, "Alias problem");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 148, "Invalid DN syntax");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 149, "Object is a leaf");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 150, "Alias dereferencing problem");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 151, "Inappropriate authentication");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 152, "Invalid credentials");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 153, "Insufficient access");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 154, "DSA is busy");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 155, "DSA is unavailable");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 156, "DSA is unwilling to perform");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 157, "Loop detected");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 158, "Naming violation");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 159, "Object class violation");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 160, "Operation not allowed on nonleaf");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 161, "Operation not allowed on RDN");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 162, "Already exists");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 163, "Cannot modify object class");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 164, "Results too large");
+/* new with ldapv3 */
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1266, "Affects multiple DSAs");
+/* end of new */
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 165, "Unknown error");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 166, "Can't contact LDAP server");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 167, "Local error");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 168, "Encoding error");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 169, "Decoding error");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 170, "Timed out");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 171, "Unknown authentication method");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 172, "Bad search filter");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 173, "User cancelled operation");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 174, "Bad parameter to an ldap routine");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 175, "Out of memory");
+
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1267, "Connection error");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1268, "Not supported");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1269, "Control not found");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1270, "No results have been returned");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1271, "More results to return");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1272, "Loop detected in referrals");
+ ldap_errlist[i++].e_reason = catgets(slapdcat, 1, 1273, "Too many referrals followed");
+}
+#endif
+
+char *
+ldap_err2string( int err )
+{
+ int i;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 );
+
+ for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) {
+ if ( err == ldap_errlist[i].e_code )
+ return( ldap_errlist[i].e_reason );
+ }
+
+ return( catgets(slapdcat, 1 , 165, "Unknown error") );
+}
+
+#ifndef NO_USERINTERFACE
+void
+ldap_perror( LDAP *ld, char *s )
+{
+ int i;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_perror\n", 0, 0, 0 );
+
+ if ( ld == NULL ) {
+ perror( s );
+ return;
+ }
+#ifdef SUN
+ /* for I18N */
+ if ( ldap_errlist[0].e_reason == NULL ) {
+ fill_ldap_errlist();
+ } /* end if */
+#endif
+
+ for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) {
+ if ( ld->ld_errno == ldap_errlist[i].e_code ) {
+ (void) fprintf( stderr, "%s: %s\n", s,
+ ldap_errlist[i].e_reason );
+ if ( ld->ld_matched != NULL && *ld->ld_matched != '\0' )
+ (void) fprintf( stderr, catgets(slapdcat, 1, 176, "%1$s: matched: %2$s\n"), s,
+ ld->ld_matched );
+ if ( ld->ld_error != NULL && *ld->ld_error != '\0' )
+ (void) fprintf( stderr, catgets(slapdcat, 1, 177, "%1$s: additional info: %2$s\n"),
+ s, ld->ld_error );
+ (void) fflush( stderr );
+ return;
+ }
+ }
+
+ (void) fprintf( stderr, catgets(slapdcat, 1, 178, "%1$s: Not an LDAP errno %2$d\n"), s, ld->ld_errno );
+ (void) fflush( stderr );
+}
+
+#else
+
+void
+ldap_perror( LDAP *ld, char *s )
+{
+}
+
+#endif /* NO_USERINTERFACE */
+
+
+int
+ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit )
+{
+ LDAPMessage *lm;
+ BerElement ber;
+ int along;
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_result2error\n", 0, 0, 0 );
+
+ if ( r == NULLMSG )
+ return( LDAP_PARAM_ERROR );
+
+ for ( lm = r; lm->lm_chain != NULL; lm = lm->lm_chain )
+ ; /* NULL */
+
+ if ( ld->ld_error ) {
+ free( ld->ld_error );
+ ld->ld_error = NULL;
+ }
+ if ( ld->ld_matched ) {
+ free( ld->ld_matched );
+ ld->ld_matched = NULL;
+ }
+
+ ber = *(lm->lm_ber);
+ if ( ld->ld_version == LDAP_VERSION2 ) {
+ rc = ber_scanf( &ber, "{iaa}", &along, &ld->ld_matched,
+ &ld->ld_error );
+ } else {
+ rc = ber_scanf( &ber, "{ia}", &along, &ld->ld_error );
+ }
+ if ( rc == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ } else {
+ ld->ld_errno = along;
+ }
+
+ if ( freeit )
+ ldap_msgfree( r );
+
+ return( ld->ld_errno );
+}
diff --git a/usr/src/lib/libldap4/common/extensions.c b/usr/src/lib/libldap4/common/extensions.c
new file mode 100644
index 0000000000..c04bed0e26
--- /dev/null
+++ b/usr/src/lib/libldap4/common/extensions.c
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include "macos.h"
+#endif /* MACOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+int ldap_create_page_control(LDAP *ld, unsigned int pagesize, struct berval *cookie, char isCritical, LDAPControl **output)
+{
+ BerElement *ber;
+ int rc;
+
+ if (NULL == ld || NULL == output)
+ return (LDAP_PARAM_ERROR);
+
+ if ((ber = ber_alloc_t(LBER_USE_DER)) == NULLBER){
+ return (LDAP_NO_MEMORY);
+ }
+
+ if (ber_printf(ber, "{io}", pagesize,
+ (cookie && cookie->bv_val) ? cookie->bv_val : "",
+ (cookie && cookie->bv_val) ? cookie->bv_len : 0)
+ == LBER_ERROR) {
+ ber_free(ber, 1);
+ return (LDAP_ENCODING_ERROR);
+ }
+
+ rc = ldap_build_control(LDAP_CONTROL_SIMPLE_PAGE, ber, 1, isCritical,
+ output);
+
+ ld->ld_errno = rc;
+ return (rc);
+}
+
+int ldap_parse_page_control(LDAP *ld, LDAPControl **controls, unsigned int *totalcount, struct berval **cookie)
+{
+ int i, rc;
+ BerElement *theBer;
+ LDAPControl *listCtrlp;
+
+ for (i = 0; controls[i] != NULL; i++){
+ if (strcmp(controls[i]->ldctl_oid, "1.2.840.113556.1.4.319") == 0) {
+ listCtrlp = controls[i];
+ if ((theBer = ber_init(&listCtrlp->ldctl_value)) == NULLBER){
+ return (LDAP_NO_MEMORY);
+ }
+ if ((rc = ber_scanf(theBer, "{iO}", totalcount, cookie)) == LBER_ERROR){
+ ber_free(theBer, 1);
+ return (LDAP_DECODING_ERROR);
+ }
+ ber_free(theBer, 1);
+ return (LDAP_SUCCESS);
+ }
+ }
+ return (LDAP_CONTROL_NOT_FOUND);
+}
+
diff --git a/usr/src/lib/libldap4/common/extop.c b/usr/src/lib/libldap4/common/extop.c
new file mode 100644
index 0000000000..9cc61d0705
--- /dev/null
+++ b/usr/src/lib/libldap4/common/extop.c
@@ -0,0 +1,156 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include "macos.h"
+#endif /* MACOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+BerElement * ldap_build_extended_operation_req(LDAP *ld, char *exoid, struct berval *exdata, LDAPControl ** serverctrls)
+{
+ BerElement *ber;
+ int rv;
+
+ /* an extended operation request looks like this:
+ * ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+ * requestName [0] LDAPOID,
+ * requestValue [1] OCTECT STRING OPTIONAL
+ * }
+ */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( NULLBER );
+ }
+
+ if ( ber_printf( ber, "{it{ts", ++ld->ld_msgid, LDAP_REQ_EXTENDED, LDAP_TAG_EXT_NAME, exoid ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ if (exdata && (ber_printf(ber, "to", LDAP_TAG_EXT_VAL, exdata->bv_val, exdata->bv_len) == -1 )) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ return (ber);
+}
+
+/* ldap_extended_operation - initiate an ldap extended operation.
+ * Parameters :
+ * ld : LDAP descriptor.
+ * exoid : OID of the request.
+ * exdata : Arbitrary data required by the operation.
+ * serverctrls : List of server controls.
+ * clientctrls : List of client controls.
+ * msgidp : msg id returned if operation succeeded.
+ * Returns LDAP_SUCCESS or error code.
+ */
+
+int ldap_extended_operation(LDAP *ld, char *exoid, struct berval *exdata,
+ LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp)
+{
+ BerElement *ber;
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 242, "ldap_extended_operation\n"), 0, 0, 0 );
+
+ if (( ber = ldap_build_extended_operation_req( ld, exoid, exdata, serverctrls)) == NULLBER ) {
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS)
+ rv = LDAP_OTHER;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( rv);
+ }
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber );
+ if (rv == -1) {
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS){
+ rv = LDAP_OTHER;
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+ *msgidp = rv;
+#if _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return ( LDAP_SUCCESS );
+}
+
+
+int ldap_extended_operation_s(LDAP *ld, char *exoid, struct berval *exdata,
+ LDAPControl **serverctrls, LDAPControl **clientctrls,
+ char **retoidp, struct berval **retdatap)
+{
+ int msgid;
+ int retcode;
+ LDAPMessage *res = NULL;
+
+ if ((retcode = ldap_extended_operation(ld, exoid, exdata, serverctrls, clientctrls, &msgid)) != LDAP_SUCCESS)
+ return (retcode);
+ if (ldap_result(ld, msgid, 1, (struct timeval *)NULL, &res ) == -1)
+ return (ld->ld_errno );
+
+ return (ldap_parse_extended_result(ld, res, retoidp, retdatap, 1));
+}
diff --git a/usr/src/lib/libldap4/common/free.c b/usr/src/lib/libldap4/common/free.c
new file mode 100644
index 0000000000..e85db6b3e9
--- /dev/null
+++ b/usr/src/lib/libldap4/common/free.c
@@ -0,0 +1,106 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1994 The Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * free.c - some free routines are included here to avoid having to
+ * link in lots of extra code when not using certain features
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1994 The Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <stdlib.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+
+void
+ldap_getfilter_free( LDAPFiltDesc *lfdp )
+{
+ LDAPFiltList *flp, *nextflp;
+ LDAPFiltInfo *fip, *nextfip;
+
+ for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = nextflp ) {
+ for ( fip = flp->lfl_ilist; fip != NULL; fip = nextfip ) {
+ nextfip = fip->lfi_next;
+ free( fip->lfi_filter );
+ free( fip->lfi_desc );
+ free( fip );
+ }
+ nextflp = flp->lfl_next;
+ free( flp->lfl_pattern );
+ free( flp->lfl_delims );
+ free( flp->lfl_tag );
+ free( flp );
+ }
+
+ if ( lfdp->lfd_curvalcopy != NULL ) {
+ free( lfdp->lfd_curvalcopy );
+ }
+ if ( lfdp->lfd_curvalwords != NULL ) {
+ free( lfdp->lfd_curvalwords );
+ }
+ if ( lfdp->lfd_filtprefix != NULL ) {
+ free( lfdp->lfd_filtprefix );
+ }
+ if ( lfdp->lfd_filtsuffix != NULL ) {
+ free( lfdp->lfd_filtsuffix );
+ }
+
+ free( lfdp );
+}
+
+/*
+ * free a null-terminated array of pointers to mod structures. the
+ * structures are freed, not the array itself, unless the freemods
+ * flag is set.
+ */
+
+void
+ldap_mods_free( LDAPMod **mods, int freemods )
+{
+ int i;
+
+ if ( mods == NULL )
+ return;
+
+ for ( i = 0; mods[i] != NULL; i++ ) {
+ if ( mods[i]->mod_op & LDAP_MOD_BVALUES ) {
+ ber_bvecfree( mods[i]->mod_bvalues );
+ } else {
+ ldap_value_free( mods[i]->mod_values );
+ }
+ if (mods[i]->mod_type)
+ free(mods[i]->mod_type);
+ free( (char *) mods[i] );
+ }
+
+ if ( freemods )
+ free( (char *) mods );
+}
diff --git a/usr/src/lib/libldap4/common/friendly.c b/usr/src/lib/libldap4/common/friendly.c
new file mode 100644
index 0000000000..70b76902c8
--- /dev/null
+++ b/usr/src/lib/libldap4/common/friendly.c
@@ -0,0 +1,142 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * friendly.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h> /* malloc(), free() for Solaris */
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#endif /* MACOS */
+
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#endif /* DOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+char *
+ldap_friendly_name( char *filename, char *uname, FriendlyMap **map )
+{
+ int i, entries;
+ FILE *fp;
+ char *s;
+ char buf[BUFSIZ];
+
+ if ( map == NULL ) {
+#if !defined( MACOS ) && !defined( DOS )
+ errno = EINVAL;
+#endif
+ return( uname );
+ }
+
+ if ( *map == NULL ) {
+ if ( (fp = fopen( filename, "r" )) == NULL )
+ return( uname );
+
+ entries = 0;
+ while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
+ if ( buf[0] != '#' )
+ entries++;
+ }
+ rewind( fp );
+
+ if ( (*map = (FriendlyMap *) malloc( (entries + 1) *
+ sizeof(FriendlyMap) )) == NULL ) {
+ (void) fclose( fp );
+ return( uname );
+ }
+
+ i = 0;
+ while ( fgets( buf, sizeof(buf), fp ) != NULL && i < entries ) {
+ if ( buf[0] == '#' )
+ continue;
+
+ if ( (s = strchr( buf, '\n' )) != NULL )
+ *s = '\0';
+
+ if ( (s = strchr( buf, '\t' )) == NULL )
+ continue;
+ *s++ = '\0';
+
+ if ( *s == '"' ) {
+ int esc = 0, found = 0;
+
+ for ( ++s; *s && !found; s++ ) {
+ switch ( *s ) {
+ case '\\':
+ esc = 1;
+ break;
+ case '"':
+ if ( !esc )
+ found = 1;
+ /* FALL */
+ default:
+ esc = 0;
+ break;
+ }
+ }
+ }
+
+ (*map)[i].f_unfriendly = strdup( buf );
+ (*map)[i].f_friendly = strdup( s );
+ i++;
+ }
+
+ (void) fclose( fp );
+ (*map)[i].f_unfriendly = NULL;
+ }
+
+ for ( i = 0; (*map)[i].f_unfriendly != NULL; i++ ) {
+ if ( strcasecmp( uname, (*map)[i].f_unfriendly ) == 0 )
+ return( (*map)[i].f_friendly );
+ }
+ return( uname );
+}
+
+
+void
+ldap_free_friendlymap( FriendlyMap **map )
+{
+ struct friendly* pF = *map;
+
+ if ( pF == NULL )
+ return;
+
+ while ( pF->f_unfriendly )
+ {
+ free( pF->f_unfriendly );
+ free( pF->f_friendly );
+ pF++;
+ }
+ free( *map );
+ *map = NULL;
+}
diff --git a/usr/src/lib/libldap4/common/getattr.c b/usr/src/lib/libldap4/common/getattr.c
new file mode 100644
index 0000000000..dee90abda1
--- /dev/null
+++ b/usr/src/lib/libldap4/common/getattr.c
@@ -0,0 +1,109 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * getattr.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+char *
+ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **ber )
+{
+ int len;
+ char *attrbuffer;
+
+ if ((attrbuffer = (char *)malloc(LDAP_MAX_ATTR_LEN)) == NULL) {
+ return (NULL);
+ }
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 179, "ldap_first_attribute\n"), 0, 0, 0 );
+
+ if ( (*ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ free(attrbuffer);
+ return( NULL );
+ }
+
+ **ber = *entry->lm_ber;
+
+ /*
+ * Skip past the sequence, dn, sequence of sequence, snarf the
+ * attribute type, and skip the set of values, leaving us
+ * positioned right before the next attribute type/value sequence.
+ */
+
+ len = LDAP_MAX_ATTR_LEN;
+ if ( ber_scanf( *ber, "{x{{sx}", attrbuffer, &len )
+ == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ ber_free( *ber, 0 );
+ *ber = NULL;
+ free(attrbuffer);
+ return( NULL );
+ }
+
+ return( attrbuffer );
+}
+
+/* ARGSUSED */
+char *
+ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber )
+{
+ int len;
+ char *attrbuffer;
+
+ if ((attrbuffer = (char *)malloc(LDAP_MAX_ATTR_LEN)) == NULL) {
+ return (NULL);
+ }
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 180, "ldap_next_attribute\n"), 0, 0, 0 );
+
+ /* skip sequence, snarf attribute type, skip values */
+ len = LDAP_MAX_ATTR_LEN;
+ if ( ber_scanf( ber, "{sx}", attrbuffer, &len )
+ == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ free(attrbuffer);
+ return( NULL );
+ }
+ ld->ld_errno = LDAP_SUCCESS;
+ return( attrbuffer );
+}
+
+void ldap_memfree(char *mem)
+{
+ free(mem);
+}
+
diff --git a/usr/src/lib/libldap4/common/getdn.c b/usr/src/lib/libldap4/common/getdn.c
new file mode 100644
index 0000000000..0c64236a6a
--- /dev/null
+++ b/usr/src/lib/libldap4/common/getdn.c
@@ -0,0 +1,414 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1994 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * getdn.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h> /* malloc(), realloc(), calloc() for Solaris */
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+char *
+ldap_get_dn( LDAP *ld, LDAPMessage *entry )
+{
+ char *dn;
+ BerElement tmp;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 181, "ldap_get_dn\n"), 0, 0, 0 );
+
+ if ( entry == NULL ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return( NULL );
+ }
+
+ tmp = *entry->lm_ber; /* struct copy */
+ if ( ber_scanf( &tmp, "{a", &dn ) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( NULL );
+ }
+
+ return( dn );
+}
+
+char *
+ldap_dn2ufn( char *dn )
+{
+ char *p, *ufn, *r;
+ int state;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 182, "ldap_dn2ufn\n"), 0, 0, 0 );
+
+ if ( ldap_is_dns_dn( dn ) || ( p = strchr( dn, '=' )) == NULL )
+ return( strdup( dn ));
+
+ ufn = strdup( ++p );
+
+#define INQUOTE 1
+#define OUTQUOTE 2
+ state = OUTQUOTE;
+ for ( p = ufn, r = ufn; *p; p++ ) {
+ switch ( *p ) {
+ case '\\':
+ if ( *++p == '\0' )
+ p--;
+ else {
+ *r++ = '\\';
+ *r++ = *p;
+ }
+ break;
+ case '"':
+ if ( state == INQUOTE )
+ state = OUTQUOTE;
+ else
+ state = INQUOTE;
+ *r++ = *p;
+ break;
+ case ';':
+ case ',':
+ if ( state == OUTQUOTE )
+ *r++ = ',';
+ else
+ *r++ = *p;
+ break;
+ case '=':
+ if ( state == INQUOTE )
+ *r++ = *p;
+ else {
+ char *rsave = r;
+
+ *r-- = '\0';
+ while ( !isspace( *r ) && *r != ';'
+ && *r != ',' && r > ufn )
+ r--;
+ r++;
+
+ if ( strcasecmp( r, "c" )
+ && strcasecmp( r, "o" )
+ && strcasecmp( r, "ou" )
+ && strcasecmp( r, "st" )
+ && strcasecmp( r, "l" )
+ && strcasecmp( r, "cn" ) ) {
+ r = rsave;
+ *r++ = '=';
+ }
+ }
+ break;
+ default:
+ *r++ = *p;
+ break;
+ }
+ }
+ *r = '\0';
+
+ return( ufn );
+}
+
+char **
+ldap_explode_dns( char *dn )
+{
+ int ncomps, maxcomps;
+ char *s;
+ char **rdns;
+
+ if ( (rdns = (char **) malloc( 8 * sizeof(char *) )) == NULL ) {
+ return( NULL );
+ }
+
+ maxcomps = 8;
+ ncomps = 0;
+ for ( s = strtok( dn, "@." ); s != NULL; s = strtok( NULL, "@." ) ) {
+ if ( ncomps == maxcomps ) {
+ maxcomps *= 2;
+ if ( (rdns = (char **) realloc( rdns, maxcomps *
+ sizeof(char *) )) == NULL ) {
+ return( NULL );
+ }
+ }
+ rdns[ncomps++] = strdup( s );
+ }
+ rdns[ncomps] = NULL;
+
+ return( rdns );
+}
+
+char **
+ldap_explode_dn( char *dn, int notypes )
+{
+ char *p, *q, *rdnstart, **rdns = NULL;
+ int state, count = 0, endquote;
+ ssize_t len;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 183, "ldap_explode_dn\n"), 0, 0, 0 );
+
+ if ( ldap_is_dns_dn( dn ) ) {
+ return( ldap_explode_dns( dn ) );
+ }
+
+ rdnstart = dn;
+ p = dn-1;
+ state = OUTQUOTE;
+
+ do {
+
+ ++p;
+ switch ( *p ) {
+ case '\\':
+ if ( *++p == '\0' )
+ p--;
+ break;
+ case '"':
+ if ( state == INQUOTE )
+ state = OUTQUOTE;
+ else
+ state = INQUOTE;
+ break;
+ case ';':
+ case ',':
+ case '\0':
+ if ( state == OUTQUOTE ) {
+ ++count;
+ if ( rdns == NULL ) {
+ if (( rdns = (char **)malloc( 8
+ * sizeof( char *))) == NULL )
+ return( NULL );
+ } else if ( count >= 8 ) {
+ if (( rdns = (char **)realloc( rdns,
+ (count+1) * sizeof( char *)))
+ == NULL )
+ return( NULL );
+ }
+ rdns[ count ] = NULL;
+ endquote = 0;
+ if ( notypes ) {
+ for ( q = rdnstart;
+ q < p && *q != '='; ++q ) {
+ ;
+ }
+ if ( q < p ) {
+ rdnstart = ++q;
+ }
+ if ( *rdnstart == '"' ) {
+ ++rdnstart;
+ }
+
+ if ( *(p-1) == '"' ) {
+ endquote = 1;
+ --p;
+ }
+ }
+
+ len = p - rdnstart;
+ if (( rdns[ count-1 ] = (char *)calloc( 1,
+ len + 1 )) != NULL ) {
+ (void) SAFEMEMCPY( rdns[ count-1 ], rdnstart,
+ len );
+ rdns[ count-1 ][ len ] = '\0';
+ }
+
+ /*
+ * Don't forget to increment 'p' back to where
+ * it should be. If we don't, then we will
+ * never get past an "end quote."
+ */
+ if ( endquote == 1 )
+ p++;
+
+ rdnstart = *p ? p + 1 : p;
+ while ( isspace( *rdnstart ))
+ ++rdnstart;
+ }
+ break;
+ }
+ } while ( *p );
+
+ return( rdns );
+}
+
+
+int
+ldap_is_dns_dn( char *dn )
+{
+ return( dn[ 0 ] != '\0' && strchr( dn, '=' ) == NULL &&
+ strchr( dn, ',' ) == NULL );
+}
+
+
+#if defined( ultrix ) || defined( NeXT )
+
+char *strdup( char *s )
+{
+ char *p;
+
+ if ( (p = (char *) malloc( strlen( s ) + 1 )) == NULL )
+ return( NULL );
+
+ strcpy( p, s );
+
+ return( p );
+}
+
+#endif /* ultrix */
+
+
+/*
+ * Convert a DNS domain name into an X.500 distinguished name.
+ * For example, "sales.wiz.com" -> "dc=sales,dc=wiz,dc=com"
+ *
+ * If an error is encountered zero is returned, otherwise a string
+ * distinguished name and the number of nameparts is returned.
+ * The caller should free the returned string if it is non-zero.
+ */
+
+char *
+ldap_dns_to_dn(
+ char *dns_name,
+ int *nameparts
+)
+{
+ size_t dns_len;
+ char *dn = 0;
+ char *cp;
+
+ /* check for NULL string, empty name and name ending in '.' */
+ if (dns_name && (dns_len = strlen(dns_name)) &&
+ (dns_name[dns_len - 1] != '.')) {
+ if (dn = (char *)malloc(dns_len * 3 + 1)) {
+ *nameparts = 0;
+ cp = dn;
+ while (*dns_name) {
+ *cp++ = 'd';
+ *cp++ = 'c';
+ *cp++ = '=';
+
+ while (*dns_name && (*dns_name != '.')) {
+ *cp++ = *dns_name++;
+ }
+ if (*dns_name == '.') {
+ dns_name++;
+ *cp++ = ',';
+ }
+ (*nameparts)++;
+ }
+ *cp = '\0';
+ }
+ }
+ return (dn);
+}
+
+char **
+ldap_explode_rdn( char *rdn, int notypes )
+{
+ char *p, *q, *rdnstart, **rdncomps = NULL;
+ int state, count = 0, endquote;
+ size_t len;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 183, "ldap_explode_rdn\n"), 0, 0, 0 );
+
+ rdnstart = rdn;
+ p = rdn-1;
+ state = OUTQUOTE;
+
+ do {
+
+ ++p;
+ switch ( *p ) {
+ case '\\':
+ if ( *++p == '\0' )
+ p--;
+ break;
+ case '"':
+ if ( state == INQUOTE )
+ state = OUTQUOTE;
+ else
+ state = INQUOTE;
+ break;
+ case '+':
+ case '\0':
+ if ( state == OUTQUOTE ) {
+ ++count;
+ if ( rdncomps == NULL ) {
+ if (( rdncomps = (char **)malloc( 8 * sizeof( char *))) == NULL )
+ return( NULL );
+ } else if ( count >= 8 ) {
+ if (( rdncomps = (char **)realloc( rdncomps,
+ (count+1) * sizeof( char *)))
+ == NULL )
+ return( NULL );
+ }
+ rdncomps[ count ] = NULL;
+ endquote = 0;
+ if ( notypes ) {
+ for ( q = rdnstart;
+ q < p && *q != '='; ++q ) {
+ ;
+ }
+ if ( q < p ) {
+ rdnstart = ++q;
+ }
+ if ( *rdnstart == '"' ) {
+ ++rdnstart;
+ }
+
+ if ( *(p-1) == '"' ) {
+ endquote = 1;
+ --p;
+ }
+ }
+
+ len = p - rdnstart;
+ if (( rdncomps[ count-1 ] = (char *)calloc( 1, len + 1 )) != NULL ) {
+ SAFEMEMCPY( rdncomps[ count-1 ], rdnstart,
+ len );
+ rdncomps[ count-1 ][ len ] = '\0';
+ }
+
+ /*
+ * Don't forget to increment 'p' back to where
+ * it should be. If we don't, then we will
+ * never get past an "end quote."
+ */
+ if ( endquote == 1 )
+ p++;
+
+ rdnstart = *p ? p + 1 : p;
+ while ( isspace( *rdnstart ))
+ ++rdnstart;
+ }
+ break;
+ }
+ } while ( *p );
+
+ return( rdncomps );
+}
diff --git a/usr/src/lib/libldap4/common/getdxbyname.c b/usr/src/lib/libldap4/common/getdxbyname.c
new file mode 100644
index 0000000000..e6316e0436
--- /dev/null
+++ b/usr/src/lib/libldap4/common/getdxbyname.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef LDAP_DNS
+/*
+ * Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * getdxbyname - retrieve DX records from the DNS (from TXT records for now)
+ */
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#endif /* MACOS */
+
+#if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <resolv.h>
+#endif
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#if defined( DOS ) || defined( _WIN32 )
+#include "msdos.h"
+#endif /* DOS */
+
+
+#ifdef NEEDPROTOS
+static char ** decode_answer( unsigned char *answer, int len );
+#else /* NEEDPROTOS */
+static char **decode_answer();
+#endif /* NEEDPROTOS */
+
+extern int h_errno;
+extern char *h_errlist[];
+
+
+#define MAX_TO_SORT 32
+
+
+/*
+ * getdxbyname - lookup DNS DX records for domain and return an ordered
+ * array.
+ */
+char **
+getdxbyname( char *domain )
+{
+ unsigned char buf[ PACKETSZ ];
+ char **dxs;
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE, "getdxbyname( %s )\n", domain, 0, 0 );
+
+ memset( buf, 0, sizeof( buf ));
+
+ if (( rc = res_search( domain, C_IN, T_TXT, buf, sizeof( buf ))) < 0
+ || ( dxs = decode_answer( buf, rc )) == NULL ) {
+ /*
+ * punt: return list conisting of the original domain name only
+ */
+ if (( dxs = (char **)malloc( 2 * sizeof( char * ))) == NULL ||
+ ( dxs[ 0 ] = strdup( domain )) == NULL ) {
+ if ( dxs != NULL ) {
+ free( dxs );
+ }
+ dxs = NULL;
+ } else {
+ dxs[ 1 ] = NULL;
+ }
+ }
+
+ return( dxs );
+}
+
+
+static char **
+decode_answer( unsigned char *answer, int len )
+{
+ HEADER *hp;
+ char buf[ 256 ], **dxs;
+ unsigned char *eom, *p;
+ int ancount, err, rc, type, class, dx_count, rr_len;
+ int dx_pref[ MAX_TO_SORT ];
+
+ int _getshort( unsigned char * );
+#ifdef LDAP_DEBUG
+ if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
+/* __p_query( answer ); */
+ }
+#endif /* LDAP_DEBUG */
+
+ dxs = NULL;
+ hp = (HEADER *)answer;
+ eom = answer + len;
+
+ if ( ntohs( hp->qdcount ) != 1 ) {
+ h_errno = NO_RECOVERY;
+ return( NULL );
+ }
+
+ ancount = ntohs( hp->ancount );
+ if ( ancount < 1 ) {
+ h_errno = NO_DATA;
+ return( NULL );
+ }
+
+ /*
+ * skip over the query
+ */
+ p = answer + HFIXEDSZ;
+ if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) {
+ h_errno = NO_RECOVERY;
+ return( NULL );
+ }
+ p += ( rc + QFIXEDSZ );
+
+ /*
+ * pull out the answers we are interested in
+ */
+ err = dx_count = 0;
+ while ( ancount > 0 && err == 0 && p < eom ) {
+ if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) {
+ err = NO_RECOVERY;
+ continue;
+ }
+ p += rc; /* skip over name */
+ type = _getshort( p );
+ p += INT16SZ;
+ class = _getshort( p );
+ p += INT16SZ;
+ p += INT32SZ; /* skip over TTL */
+ rr_len = _getshort( p );
+ p += INT16SZ;
+ if ( class == C_IN && type == T_TXT ) {
+ int i, n, pref, txt_len;
+ char *q, *r;
+
+ q = (char *)p;
+ while ( q < (char *)p + rr_len && err == 0 ) {
+ if ( *q >= 3 && strncasecmp( q + 1, "dx:", 3 ) == 0 ) {
+ txt_len = *q - 3;
+ r = q + 4;
+ while ( isspace( *r )) {
+ ++r;
+ --txt_len;
+ }
+ pref = 0;
+ while ( isdigit( *r )) {
+ pref *= 10;
+ pref += ( *r - '0' );
+ ++r;
+ --txt_len;
+ }
+ if ( dx_count < MAX_TO_SORT - 1 ) {
+ dx_pref[ dx_count ] = pref;
+ }
+ while ( isspace( *r )) {
+ ++r;
+ --txt_len;
+ }
+ if ( dx_count == 0 ) {
+ dxs = (char **)malloc( 2 * sizeof( char * ));
+ } else {
+ dxs = (char **)realloc( dxs,
+ ( dx_count + 2 ) * sizeof( char * ));
+ }
+ if ( dxs == NULL || ( dxs[ dx_count ] =
+ (char *)calloc( 1, txt_len + 1 )) == NULL ) {
+ err = NO_RECOVERY;
+ continue;
+ }
+ memcpy( dxs[ dx_count ], r, txt_len );
+ dxs[ ++dx_count ] = NULL;
+ }
+ q += ( *q + 1 ); /* move past last TXT record */
+ }
+ }
+ p += rr_len;
+ }
+
+ if ( err == 0 ) {
+ if ( dx_count == 0 ) {
+ err = NO_DATA;
+ } else {
+ /*
+ * sort records based on associated preference value
+ */
+ int i, j, sort_count, tmp_pref;
+ char *tmp_dx;
+
+ sort_count = ( dx_count < MAX_TO_SORT ) ? dx_count : MAX_TO_SORT;
+ for ( i = 0; i < sort_count; ++i ) {
+ for ( j = i + 1; j < sort_count; ++j ) {
+ if ( dx_pref[ i ] > dx_pref[ j ] ) {
+ tmp_pref = dx_pref[ i ];
+ dx_pref[ i ] = dx_pref[ j ];
+ dx_pref[ j ] = tmp_pref;
+ tmp_dx = dxs[ i ];
+ dxs[ i ] = dxs[ j ];
+ dxs[ j ] = tmp_dx;
+ }
+ }
+ }
+ }
+ }
+
+ h_errno = err;
+ return( dxs );
+}
+
+#endif /* LDAP_DNS */
diff --git a/usr/src/lib/libldap4/common/getentry.c b/usr/src/lib/libldap4/common/getentry.c
new file mode 100644
index 0000000000..078e8aaa80
--- /dev/null
+++ b/usr/src/lib/libldap4/common/getentry.c
@@ -0,0 +1,84 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * getentry.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+
+/* ARGSUSED */
+LDAPMessage *
+ldap_first_entry( LDAP *ld, LDAPMessage *res )
+{
+ LDAPMessage *msg = res;
+
+ while ( msg != NULLMSG) {
+ if (msg->lm_msgtype == LDAP_RES_SEARCH_ENTRY)
+ break;
+ msg = msg->lm_chain;
+ }
+ return (msg);
+}
+
+/* ARGSUSED */
+LDAPMessage *ldap_next_entry( LDAP *ld, LDAPMessage *entry )
+{
+ LDAPMessage *msg;
+
+ if ( entry == NULLMSG)
+ return( NULLMSG );
+
+ msg = entry->lm_chain;
+ while(msg != NULLMSG){
+ if (msg->lm_msgtype == LDAP_RES_SEARCH_ENTRY)
+ break;
+ msg = msg->lm_chain;
+ }
+
+ return( msg );
+}
+
+/* ARGSUSED */
+int
+ldap_count_entries( LDAP *ld, LDAPMessage *res )
+{
+ int i;
+
+ for ( i = 0; res != NULL; res = res->lm_chain )
+ if (res->lm_msgtype == LDAP_RES_SEARCH_ENTRY)
+ i++;
+
+ return( i );
+}
diff --git a/usr/src/lib/libldap4/common/getfilter.c b/usr/src/lib/libldap4/common/getfilter.c
new file mode 100644
index 0000000000..57ae904801
--- /dev/null
+++ b/usr/src/lib/libldap4/common/getfilter.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1993 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * getfilter.c -- optional add-on to libldap
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#if defined(NeXT)
+#include <regex.h>
+#endif
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifndef VMS
+#include <unistd.h>
+#endif /* VMS */
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+#include "regex.h"
+
+#ifdef NEEDPROTOS
+static int break_into_words( char *str, char *delims, char ***wordsp );
+int next_line_tokens( char **bufp, ssize_t *blenp, char ***toksp );
+void free_strarray( char **sap );
+#else /* NEEDPROTOS */
+static int break_into_words();
+int next_line_tokens();
+void free_strarray();
+#endif /* NEEDPROTOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+extern int errno;
+extern char *re_comp();
+#endif
+
+#define FILT_MAX_LINE_LEN 1024
+
+LDAPFiltDesc *
+ldap_init_getfilter( char *fname )
+{
+ FILE *fp;
+ char *buf;
+ ssize_t rlen, len;
+ int eof;
+ LDAPFiltDesc *lfdp;
+
+ if (( fp = fopen( fname, "r" )) == NULL ) {
+ return( NULL );
+ }
+
+ if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
+ fclose( fp );
+ return( NULL );
+ }
+
+ len = ftell( fp );
+
+ if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
+ fclose( fp );
+ return( NULL );
+ }
+
+ if (( buf = malloc( len )) == NULL ) {
+ fclose( fp );
+ return( NULL );
+ }
+
+ rlen = fread( buf, (size_t) 1, len, fp );
+ eof = feof( fp );
+ fclose( fp );
+
+ if ( rlen != len && !eof ) { /* error: didn't get the whole file */
+ free( buf );
+ return( NULL );
+ }
+
+
+ lfdp = ldap_init_getfilter_buf( buf, rlen );
+ free( buf );
+
+ return( lfdp );
+}
+
+
+LDAPFiltDesc *
+ldap_init_getfilter_buf( char *buf, ssize_t buflen )
+{
+ LDAPFiltDesc *lfdp;
+ LDAPFiltList *flp, *nextflp;
+ LDAPFiltInfo *fip, *nextfip;
+ char *tag, **tok;
+ int tokcnt, i;
+
+ if (( lfdp = (LDAPFiltDesc *)calloc( (size_t) 1, sizeof( LDAPFiltDesc))) == NULL ) {
+ return( NULL );
+ }
+
+ flp = nextflp = NULL;
+ fip = NULL;
+ tag = NULL;
+
+ while ( buflen > 0 && ( tokcnt = next_line_tokens( &buf, &buflen, &tok ))
+ > 0 ) {
+
+ switch( tokcnt ) {
+ case 1: /* tag line */
+ if ( tag != NULL ) {
+ free( tag );
+ }
+ tag = tok[ 0 ];
+ free( tok );
+ break;
+ case 4:
+ case 5: /* start of filter info. list */
+ if (( nextflp = (LDAPFiltList *)calloc( (size_t) 1, sizeof( LDAPFiltList )))
+ == NULL ) {
+ ldap_getfilter_free( lfdp );
+ return( NULL );
+ }
+ nextflp->lfl_tag = strdup( tag );
+ nextflp->lfl_pattern = tok[ 0 ];
+ if ( re_comp( nextflp->lfl_pattern ) != NULL ) {
+#ifndef NO_USERINTERFACE
+ ldap_getfilter_free( lfdp );
+ fprintf( stderr, "bad regular expresssion %s\n",
+ nextflp->lfl_pattern );
+#if !defined( MACOS ) && !defined( DOS )
+ errno = EINVAL;
+#endif
+#endif /* NO_USERINTERFACE */
+ free_strarray( tok );
+ return( NULL );
+ }
+
+ nextflp->lfl_delims = tok[ 1 ];
+ nextflp->lfl_ilist = NULL;
+ nextflp->lfl_next = NULL;
+ if ( flp == NULL ) { /* first one */
+ lfdp->lfd_filtlist = nextflp;
+ } else {
+ flp->lfl_next = nextflp;
+ }
+ flp = nextflp;
+ fip = NULL;
+ for ( i = 2; i < 5; ++i ) {
+ tok[ i - 2 ] = tok[ i ];
+ }
+ /* fall through */
+
+ case 2:
+ case 3: /* filter, desc, and optional search scope */
+ if ( nextflp != NULL ) { /* add to info list */
+ if (( nextfip = (LDAPFiltInfo *)calloc( (size_t) 1,
+ sizeof( LDAPFiltInfo ))) == NULL ) {
+ ldap_getfilter_free( lfdp );
+ free_strarray( tok );
+ return( NULL );
+ }
+ if ( fip == NULL ) { /* first one */
+ nextflp->lfl_ilist = nextfip;
+ } else {
+ fip->lfi_next = nextfip;
+ }
+ fip = nextfip;
+ nextfip->lfi_next = NULL;
+ nextfip->lfi_filter = tok[ 0 ];
+ nextfip->lfi_desc = tok[ 1 ];
+ if ( tok[ 2 ] != NULL ) {
+ if ( strcasecmp( tok[ 2 ], "subtree" ) == 0 ) {
+ nextfip->lfi_scope = LDAP_SCOPE_SUBTREE;
+ } else if ( strcasecmp( tok[ 2 ], "onelevel" ) == 0 ) {
+ nextfip->lfi_scope = LDAP_SCOPE_ONELEVEL;
+ } else if ( strcasecmp( tok[ 2 ], "base" ) == 0 ) {
+ nextfip->lfi_scope = LDAP_SCOPE_BASE;
+ } else {
+ free_strarray( tok );
+ ldap_getfilter_free( lfdp );
+#if !defined( MACOS ) && !defined( DOS )
+ errno = EINVAL;
+#endif
+ return( NULL );
+ }
+ free( tok[ 2 ] );
+ tok[ 2 ] = NULL;
+ } else {
+ nextfip->lfi_scope = LDAP_SCOPE_SUBTREE; /* default */
+ }
+ nextfip->lfi_isexact = ( strchr( tok[ 0 ], '*' ) == NULL &&
+ strchr( tok[ 0 ], '~' ) == NULL );
+ free( tok );
+ }
+ break;
+
+ default:
+ free_strarray( tok );
+ ldap_getfilter_free( lfdp );
+#if !defined( MACOS ) && !defined( DOS )
+ errno = EINVAL;
+#endif
+ return( NULL );
+ }
+ }
+
+ if ( tag != NULL ) {
+ free( tag );
+ }
+
+ return( lfdp );
+}
+
+
+void
+ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix, char *suffix )
+{
+ if ( lfdp->lfd_filtprefix != NULL ) {
+ free( lfdp->lfd_filtprefix );
+ }
+ lfdp->lfd_filtprefix = ( prefix == NULL ) ? NULL : strdup( prefix );
+
+ if ( lfdp->lfd_filtsuffix != NULL ) {
+ free( lfdp->lfd_filtsuffix );
+ }
+ lfdp->lfd_filtsuffix = ( suffix == NULL ) ? NULL : strdup( suffix );
+}
+
+
+LDAPFiltInfo *
+ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value )
+{
+ LDAPFiltList *flp;
+
+ if ( lfdp->lfd_curvalcopy != NULL ) {
+ free( lfdp->lfd_curvalcopy );
+ free( lfdp->lfd_curvalwords );
+ }
+
+ lfdp->lfd_curval = value;
+ lfdp->lfd_curfip = NULL;
+
+ for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
+ if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1
+ && re_comp( flp->lfl_pattern ) == NULL
+ && re_exec( lfdp->lfd_curval ) == 1 ) {
+ lfdp->lfd_curfip = flp->lfl_ilist;
+ break;
+ }
+ }
+
+ if ( lfdp->lfd_curfip == NULL ) {
+ return( NULL );
+ }
+
+ if (( lfdp->lfd_curvalcopy = strdup( value )) == NULL ) {
+ return( NULL );
+ }
+
+ if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims,
+ &lfdp->lfd_curvalwords ) < 0 ) {
+ free( lfdp->lfd_curvalcopy );
+ lfdp->lfd_curvalcopy = NULL;
+ return( NULL );
+ }
+
+ return( ldap_getnextfilter( lfdp ));
+}
+
+
+LDAPFiltInfo *
+ldap_getnextfilter( LDAPFiltDesc *lfdp )
+{
+ LDAPFiltInfo *fip;
+
+ fip = lfdp->lfd_curfip;
+
+ if ( fip == NULL ) {
+ return( NULL );
+ }
+
+ lfdp->lfd_curfip = fip->lfi_next;
+
+ ldap_build_filter( lfdp->lfd_filter, (size_t) LDAP_FILT_MAXSIZ, fip->lfi_filter,
+ lfdp->lfd_filtprefix, lfdp->lfd_filtsuffix, NULL,
+ lfdp->lfd_curval, lfdp->lfd_curvalwords );
+ lfdp->lfd_retfi.lfi_filter = lfdp->lfd_filter;
+ lfdp->lfd_retfi.lfi_desc = fip->lfi_desc;
+ lfdp->lfd_retfi.lfi_scope = fip->lfi_scope;
+ lfdp->lfd_retfi.lfi_isexact = fip->lfi_isexact;
+
+ return( &lfdp->lfd_retfi );
+}
+
+
+void
+ldap_build_filter( char *filtbuf, size_t buflen, char *pattern,
+ char *prefix, char *suffix, char *attr, char *value, char **valwords )
+{
+ char *p, *f;
+ size_t slen;
+ int i, wordcount, wordnum, endwordnum;
+
+ if ( valwords == NULL ) {
+ wordcount = 0;
+ } else {
+ for ( wordcount = 0; valwords[ wordcount ] != NULL; ++wordcount ) {
+ ;
+ }
+ }
+
+ f = filtbuf;
+
+ if ( prefix != NULL ) {
+ strcpy( f, prefix );
+ f += strlen( prefix );
+ }
+
+ for ( p = pattern; *p != '\0'; ++p ) {
+ if ( *p == '%' ) {
+ ++p;
+ if ( *p == 'v' ) {
+ if ( isdigit( *(p+1))) {
+ ++p;
+ wordnum = *p - '1';
+ if ( *(p+1) == '-' ) {
+ ++p;
+ if ( isdigit( *(p+1))) {
+ ++p;
+ endwordnum = *p - '1'; /* e.g., "%v2-4" */
+#ifndef SUN /* Patch from innosoft Craig.Watkins 08.Jul.97 */
+ if ( endwordnum > wordcount - 1 ) {
+ endwordnum = wordcount - 1;
+ }
+#endif
+ } else {
+ endwordnum = wordcount - 1; /* e.g., "%v2-" */
+ }
+ } else {
+ endwordnum = wordnum; /* e.g., "%v2" */
+ }
+#ifdef SUN /* Patch from innosoft Craig.Watkins 08.Jul.97 */
+ if ( endwordnum > wordcount - 1 ) {
+ endwordnum = wordcount - 1;
+ }
+#endif
+ if ( wordcount > 0 ) {
+ for ( i = wordnum; i <= endwordnum; ++i ) {
+ if ( i > wordnum ) { /* add blank btw words */
+ *f++ = ' ';
+ }
+ slen = strlen( valwords[ i ] );
+ SAFEMEMCPY( f, valwords[ i ], slen );
+ f += slen;
+ }
+ }
+ } else if ( *(p+1) == '$' ) {
+ ++p;
+ if ( wordcount > 0 ) {
+ wordnum = wordcount - 1;
+ slen = strlen( valwords[ wordnum ] );
+ SAFEMEMCPY( f, valwords[ wordnum ], slen );
+ f += slen;
+ }
+ } else if ( value != NULL ) {
+ slen = strlen( value );
+ SAFEMEMCPY( f, value, slen );
+ f += slen;
+ }
+ } else if ( *p == 'a' && attr != NULL ) {
+ slen = strlen( attr );
+ SAFEMEMCPY( f, attr, slen );
+ f += slen;
+ } else {
+ *f++ = *p;
+ }
+ } else {
+ *f++ = *p;
+ }
+
+ if ( f - filtbuf > buflen ) {
+ /* sanity check */
+ --f;
+ break;
+ }
+ }
+
+ if ( suffix != NULL && ( f - filtbuf ) < buflen ) {
+ strcpy( f, suffix );
+ } else {
+ *f = '\0';
+ }
+}
+
+
+static int
+break_into_words( char *str, char *delims, char ***wordsp )
+{
+ char *word, **words;
+ int count;
+
+ if (( words = (char **)calloc( (size_t) 1, sizeof( char * ))) == NULL ) {
+ return( -1 );
+ }
+ count = 0;
+ words[ count ] = NULL;
+
+ word = strtok( str, delims );
+ while ( word != NULL ) {
+ if (( words = (char **)realloc( words,
+ ( count + 2 ) * sizeof( char * ))) == NULL ) {
+ return( -1 );
+ }
+
+ words[ count ] = word;
+ words[ ++count ] = NULL;
+ word = strtok( NULL, delims );
+ }
+
+ *wordsp = words;
+ return( count );
+}
diff --git a/usr/src/lib/libldap4/common/getmsg.c b/usr/src/lib/libldap4/common/getmsg.c
new file mode 100644
index 0000000000..01c524688e
--- /dev/null
+++ b/usr/src/lib/libldap4/common/getmsg.c
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+
+LDAPMessage * ldap_first_message(LDAP *ld, LDAPMessage *res)
+{
+ return (res == NULLMSG ? NULLMSG : res);
+}
+
+LDAPMessage * ldap_next_message(LDAP *ld, LDAPMessage *msg)
+{
+ if (msg == NULLMSG || msg->lm_chain == NULLMSG)
+ return (NULLMSG);
+ return (msg->lm_chain);
+}
+
+int ldap_count_messages( LDAP *ld, LDAPMessage *res)
+{
+ int i;
+
+ for ( i =0; res != NULL; res = res->lm_chain)
+ i++;
+
+ return (i);
+}
diff --git a/usr/src/lib/libldap4/common/getref.c b/usr/src/lib/libldap4/common/getref.c
new file mode 100644
index 0000000000..25600cda24
--- /dev/null
+++ b/usr/src/lib/libldap4/common/getref.c
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+LDAPMessage * ldap_first_reference(LDAP *ld, LDAPMessage *res)
+{
+ LDAPMessage *msg = res;
+
+ while ( msg != NULLMSG) {
+ if (msg->lm_msgtype == LDAP_RES_SEARCH_REFERENCE)
+ break;
+ msg = msg->lm_chain;
+ }
+ return (msg);
+}
+
+LDAPMessage * ldap_next_reference(LDAP *ld, LDAPMessage *entry)
+{
+ LDAPMessage *msg;
+
+ if ( entry == NULLMSG)
+ return( NULLMSG );
+
+ msg = entry->lm_chain;
+ while(msg != NULLMSG){
+ if (msg->lm_msgtype == LDAP_RES_SEARCH_REFERENCE)
+ break;
+ msg = msg->lm_chain;
+ }
+
+ return( msg );
+}
+
+int
+ldap_count_references( LDAP *ld, LDAPMessage *res )
+{
+ int i;
+
+ for ( i = 0; res != NULL; res = res->lm_chain )
+ if (res->lm_msgtype == LDAP_RES_SEARCH_REFERENCE)
+ i++;
+
+ return( i );
+}
+
+char ** ldap_get_reference_urls(LDAP *ld, LDAPMessage *res)
+{
+ BerElement tmp;
+ char **urls = NULL;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1274, "ldap_get_reference_urls\n"), 0, 0, 0 );
+
+ if (res == NULL){
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return (NULL);
+ }
+ tmp = *res->lm_ber; /* struct copy */
+ if ( ber_scanf( &tmp, "{v}", &urls) == LBER_ERROR){
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return (NULL);
+ }
+ return (urls);
+}
diff --git a/usr/src/lib/libldap4/common/getvalues.c b/usr/src/lib/libldap4/common/getvalues.c
new file mode 100644
index 0000000000..cd7da43926
--- /dev/null
+++ b/usr/src/lib/libldap4/common/getvalues.c
@@ -0,0 +1,183 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * getvalues.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h> /* free() for Solaris */
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+char **
+ldap_get_values( LDAP *ld, LDAPMessage *entry, char *target )
+{
+ BerElement ber;
+ char attr[LDAP_MAX_ATTR_LEN];
+ int found = 0;
+ int len;
+ char **vals;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 184, "ldap_get_values\n"), 0, 0, 0 );
+
+ ber = *entry->lm_ber;
+
+ /* skip sequence, dn, sequence of, and snag the first attr */
+ len = sizeof(attr);
+ if ( ber_scanf( &ber, "{x{{s", attr, &len ) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( NULL );
+ }
+
+ if ( strcasecmp( target, attr ) == 0 )
+ found = 1;
+
+ /* break out on success, return out on error */
+ while ( ! found ) {
+ len = sizeof(attr);
+ if ( ber_scanf( &ber, "x}{s", attr, &len ) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( NULL );
+ }
+
+ if ( strcasecmp( target, attr ) == 0 )
+ break;
+ }
+
+ /*
+ * if we get this far, we've found the attribute and are sitting
+ * just before the set of values.
+ */
+
+ if ( ber_scanf( &ber, "[v]", &vals ) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( NULL );
+ }
+
+ return( vals );
+}
+
+struct berval **
+ldap_get_values_len( LDAP *ld, LDAPMessage *entry, char *target )
+{
+ BerElement ber;
+ char attr[LDAP_MAX_ATTR_LEN];
+ int found = 0;
+ int len;
+ struct berval **vals;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 185, "ldap_get_values_len\n"), 0, 0, 0 );
+
+ ber = *entry->lm_ber;
+
+ /* skip sequence, dn, sequence of, and snag the first attr */
+ len = sizeof(attr);
+ if ( ber_scanf( &ber, "{x{{s", attr, &len ) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( NULL );
+ }
+
+ if ( strcasecmp( target, attr ) == 0 )
+ found = 1;
+
+ /* break out on success, return out on error */
+ while ( ! found ) {
+ len = sizeof(attr);
+ if ( ber_scanf( &ber, "x}{s", attr, &len ) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( NULL );
+ }
+
+ if ( strcasecmp( target, attr ) == 0 )
+ break;
+ }
+
+ /*
+ * if we get this far, we've found the attribute and are sitting
+ * just before the set of values.
+ */
+
+ if ( ber_scanf( &ber, "[V]", &vals ) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( NULL );
+ }
+
+ return( vals );
+}
+
+int
+ldap_count_values( char **vals )
+{
+ int i;
+
+ if ( vals == NULL )
+ return( 0 );
+
+ for ( i = 0; vals[i] != NULL; i++ )
+ ; /* NULL */
+
+ return( i );
+}
+
+int
+ldap_count_values_len( struct berval **vals )
+{
+ return( ldap_count_values( (char **) vals ) );
+}
+
+void
+ldap_value_free( char **vals )
+{
+ int i;
+
+ if ( vals == NULL )
+ return;
+ for ( i = 0; vals[i] != NULL; i++ )
+ free( vals[i] );
+ free( (char *) vals );
+}
+
+void
+ldap_value_free_len( struct berval **vals )
+{
+ int i;
+
+ if ( vals == NULL )
+ return;
+ for ( i = 0; vals[i] != NULL; i++ ) {
+ free( vals[i]->bv_val );
+ free( vals[i] );
+ }
+ free( (char *) vals );
+}
diff --git a/usr/src/lib/libldap4/common/kbind.c b/usr/src/lib/libldap4/common/kbind.c
new file mode 100644
index 0000000000..167eab8d58
--- /dev/null
+++ b/usr/src/lib/libldap4/common/kbind.c
@@ -0,0 +1,351 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1993 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * kbind.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#ifdef KERBEROS
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include "msdos.h"
+#endif /* DOS */
+#include <krb.h>
+#include <stdlib.h>
+#if !defined(DOS) && !defined( _WIN32 )
+#include <sys/types.h>
+#endif /* !DOS && !_WIN32 */
+#include <sys/time.h>
+#include <sys/socket.h>
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+
+
+/*
+ * ldap_kerberos_bind1 - initiate a bind to the ldap server using
+ * kerberos authentication. The dn is supplied. It is assumed the user
+ * already has a valid ticket granting ticket. The msgid of the
+ * request is returned on success (suitable for passing to ldap_result()),
+ * -1 is returned if there's trouble.
+ *
+ * Example:
+ * ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" )
+ */
+int
+ldap_kerberos_bind1( LDAP *ld, char *dn )
+{
+ BerElement *ber;
+ char *cred;
+ int rc, credlen;
+ char *get_kerberosv4_credentials();
+#ifdef STR_TRANSLATION
+ int str_translation_on;
+#endif /* STR_TRANSLATION */
+
+ /*
+ * The bind request looks like this:
+ * BindRequest ::= SEQUENCE {
+ * version INTEGER,
+ * name DistinguishedName,
+ * authentication CHOICE {
+ * krbv42ldap [1] OCTET STRING
+ * krbv42dsa [2] OCTET STRING
+ * }
+ * }
+ * all wrapped up in an LDAPMessage sequence.
+ */
+
+#if defined( SUN ) && defined( _REENTRANT )
+ int rv;
+
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 186, "ldap_kerberos_bind1\n"), 0, 0, 0 );
+
+ if ( dn == NULL )
+ dn = "";
+
+ if ( (cred = get_kerberosv4_credentials( ld, dn, "ldapserver",
+ &credlen )) == NULL ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 ); /* ld_errno should already be set */
+ }
+
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ free( cred );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+#ifdef STR_TRANSLATION
+ if (( str_translation_on = (( ber->ber_options &
+ LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
+ ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
+ }
+#endif /* STR_TRANSLATION */
+
+ /* fill it in */
+ rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
+ ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen );
+
+#ifdef STR_TRANSLATION
+ if ( str_translation_on ) { /* restore translation */
+ ber->ber_options |= LBER_TRANSLATE_STRINGS;
+ }
+#endif /* STR_TRANSLATION */
+
+ if ( rc == -1 ) {
+ free( cred );
+ ber_free( ber, 1 );
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+ free( cred );
+
+#ifndef NO_CACHE
+ if ( ld->ld_cache != NULL ) {
+ ldap_flush_cache( ld );
+ }
+#endif /* !NO_CACHE */
+
+ /* send the message */
+#if defined( SUN ) && defined( _REENTRANT )
+ rv = send_initial_request( ld, LDAP_REQ_BIND, dn, ber );
+ UNLOCK_LDAP(ld);
+ return ( rv );
+#else
+ return ( send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
+#endif
+}
+
+int
+ldap_kerberos_bind1_s( LDAP *ld, char *dn )
+{
+ int msgid;
+ LDAPMessage *res;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 187, "ldap_kerberos_bind1_s\n"), 0, 0, 0 );
+
+ /* initiate the bind */
+ if ( (msgid = ldap_kerberos_bind1( ld, dn )) == -1 )
+ return( ld->ld_errno );
+
+ /* wait for a result */
+ if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
+ == -1 ) {
+ return( ld->ld_errno ); /* ldap_result sets ld_errno */
+ }
+
+ return( ldap_result2error( ld, res, 1 ) );
+}
+
+/*
+ * ldap_kerberos_bind2 - initiate a bind to the X.500 server using
+ * kerberos authentication. The dn is supplied. It is assumed the user
+ * already has a valid ticket granting ticket. The msgid of the
+ * request is returned on success (suitable for passing to ldap_result()),
+ * -1 is returned if there's trouble.
+ *
+ * Example:
+ * ldap_kerberos_bind2( ld, "cn=manager, o=university of michigan, c=us" )
+ */
+int
+ldap_kerberos_bind2( LDAP *ld, char *dn )
+{
+ BerElement *ber;
+ char *cred;
+ int rc, credlen;
+ char *get_kerberosv4_credentials();
+#ifdef STR_TRANSLATION
+ int str_translation_on;
+#endif /* STR_TRANSLATION */
+
+#if defined( SUN ) && defined( _REENTRANT )
+ int rv;
+
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 188, "ldap_kerberos_bind2\n"), 0, 0, 0 );
+
+ if ( dn == NULL )
+ dn = "";
+
+ if ( (cred = get_kerberosv4_credentials( ld, dn, "x500dsa", &credlen ))
+ == NULL ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 ); /* ld_errno should already be set */
+ }
+
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ free( cred );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+#ifdef STR_TRANSLATION
+ if (( str_translation_on = (( ber->ber_options &
+ LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
+ ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
+ }
+#endif /* STR_TRANSLATION */
+
+ /* fill it in */
+ rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
+ ld->ld_version, dn, LDAP_AUTH_KRBV42, cred, credlen );
+
+
+#ifdef STR_TRANSLATION
+ if ( str_translation_on ) { /* restore translation */
+ ber->ber_options |= LBER_TRANSLATE_STRINGS;
+ }
+#endif /* STR_TRANSLATION */
+
+ free( cred );
+
+ if ( rc == -1 ) {
+ ber_free( ber, 1 );
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+ /* send the message */
+#if defined( SUN ) && defined( _REENTRANT )
+ rv = send_initial_request( ld, LDAP_REQ_BIND, dn, ber );
+ UNLOCK_LDAP(ld);
+ return ( rv );
+#endif
+ return ( send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
+}
+
+/* synchronous bind to DSA using kerberos */
+int
+ldap_kerberos_bind2_s( LDAP *ld, char *dn )
+{
+ int msgid;
+ LDAPMessage *res;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 189, "ldap_kerberos_bind2_s\n"), 0, 0, 0 );
+
+ /* initiate the bind */
+ if ( (msgid = ldap_kerberos_bind2( ld, dn )) == -1 )
+ return( ld->ld_errno );
+
+ /* wait for a result */
+ if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
+ == -1 ) {
+ return( ld->ld_errno ); /* ldap_result sets ld_errno */
+ }
+
+ return( ldap_result2error( ld, res, 1 ) );
+}
+
+/* synchronous bind to ldap and DSA using kerberos */
+int
+ldap_kerberos_bind_s( LDAP *ld, char *dn )
+{
+ int err;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 190, "ldap_kerberos_bind_s\n"), 0, 0, 0 );
+
+ if ( (err = ldap_kerberos_bind1_s( ld, dn )) != LDAP_SUCCESS )
+ return( err );
+
+ return( ldap_kerberos_bind2_s( ld, dn ) );
+}
+
+
+#ifndef AUTHMAN
+/*
+ * get_kerberosv4_credentials - obtain kerberos v4 credentials for ldap.
+ * The dn of the entry to which to bind is supplied. It's assumed the
+ * user already has a tgt.
+ */
+
+char *
+get_kerberosv4_credentials( LDAP *ld, char *who, char *service, int *len )
+{
+ KTEXT_ST ktxt;
+ int err;
+ char realm[REALM_SZ], *cred, *krbinstance;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 191, "get_kerberosv4_credentials\n"), 0, 0, 0 );
+
+ if ( (err = krb_get_tf_realm( tkt_string(), realm )) != KSUCCESS ) {
+#ifndef NO_USERINTERFACE
+ fprintf( stderr, "krb_get_tf_realm failed (%s)\n",
+ krb_err_txt[err] );
+#endif /* NO_USERINTERFACE */
+ ld->ld_errno = LDAP_INVALID_CREDENTIALS;
+ return( NULL );
+ }
+
+#ifdef LDAP_REFERRALS
+ krbinstance = ld->ld_defconn->lconn_krbinstance;
+#else /* LDAP_REFERRALS */
+ krbinstance = ld->ld_host;
+#endif /* LDAP_REFERRALS */
+
+ if ( (err = krb_mk_req( &ktxt, service, krbinstance, realm, 0 ))
+ != KSUCCESS ) {
+#ifndef NO_USERINTERFACE
+ fprintf( stderr, "krb_mk_req failed (%s)\n", krb_err_txt[err] );
+#endif /* NO_USERINTERFACE */
+ ld->ld_errno = LDAP_INVALID_CREDENTIALS;
+ return( NULL );
+ }
+
+ if ( ( cred = malloc( ktxt.length )) == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( NULL );
+ }
+
+ *len = ktxt.length;
+ memcpy( cred, ktxt.dat, ktxt.length );
+
+ return( cred );
+}
+
+#endif /* !AUTHMAN */
+#endif /* KERBEROS */
diff --git a/usr/src/lib/libldap4/common/llib-lldap b/usr/src/lib/libldap4/common/llib-lldap
new file mode 100644
index 0000000000..2d0b9e947c
--- /dev/null
+++ b/usr/src/lib/libldap4/common/llib-lldap
@@ -0,0 +1,317 @@
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+/*
+ * Copyright (c) 1997 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <lber.h>
+#include <ldap.h>
+
+/*
+ * /usr/src/lib/libldap routines
+ */
+
+
+/*
+ * in abandon.c:
+ */
+int ldap_abandon_ext(LDAP *ld, int msgid, LDAPControl **serverctrls, LDAPControl ** clientctrls);
+int ldap_abandon( LDAP *ld, int msgid );
+
+/*
+ * in add.c:
+ */
+int ldap_add_ext( LDAP *ld, char *dn, LDAPMod **attrs, LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_add_ext_s( LDAP *ld, char *dn, LDAPMod **attrs, LDAPControl ** serverctrls, LDAPControl **clientctrls);
+int ldap_add( LDAP *ld, char *dn, LDAPMod **attrs );
+int ldap_add_s( LDAP *ld, char *dn, LDAPMod **attrs );
+
+/*
+ * in bind.c:
+ */
+
+/*
+ * in sbind.c:
+ */
+int ldap_simple_bind( LDAP *ld, char *who, char *passwd );
+int ldap_simple_bind_s( LDAP *ld, char *who, char *passwd );
+
+/*
+ * in saslbind.c:
+ */
+int ldap_sasl_bind(LDAP *ld, char *dn, char *mechanism, struct berval *cred, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_sasl_bind_s(LDAP *ld, char *dn, char *mechanism, struct berval *cred, LDAPControl **serverctrls, LDAPControl **clientctrls, struct berval **servercredp);
+
+/*
+ * in kbind.c:
+ */
+
+#ifndef NO_CACHE
+/*
+ * in cache.c
+ */
+int ldap_enable_cache( LDAP *ld, time_t timeout, ssize_t maxmem );
+void ldap_disable_cache( LDAP *ld );
+void ldap_set_cache_options( LDAP *ld, unsigned int opts );
+void ldap_destroy_cache( LDAP *ld );
+void ldap_flush_cache( LDAP *ld );
+void ldap_uncache_entry( LDAP *ld, char *dn );
+void ldap_uncache_request( LDAP *ld, int msgid );
+#endif /* !NO_CACHE */
+
+/*
+ * in compare.c:
+ */
+int ldap_compare_ext(LDAP *ld, char *dn, char *attr, struct berval *bvalue, LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_compare_ext_s(LDAP *ld, char *dn, char *attr, struct berval *bvalue, LDAPControl ** serverctrls, LDAPControl **clientctrls) ;
+int ldap_compare( LDAP *ld, char *dn, char *attr, char *value );
+int ldap_compare_s( LDAP *ld, char *dn, char *attr, char *value );
+
+/*
+ * in delete.c:
+ */
+int ldap_delete_ext(LDAP *ld, char *dn, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_delete_ext_s(LDAP *ld, char *dn, LDAPControl **serverctrls, LDAPControl **clientctrls);
+int ldap_delete( LDAP *ld, char *dn );
+int ldap_delete_s( LDAP *ld, char *dn );
+
+/*
+ * in error.c:
+ */
+char *ldap_err2string( int err );
+
+
+/*
+ * in modify.c:
+ */
+int ldap_modify_ext(LDAP *ld, char *dn, LDAPMod **mods, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_modify_ext_s(LDAP *ld, char *dn, LDAPMod **mods, LDAPControl **serverctrls, LDAPControl **clientctrls) ;
+int ldap_modify( LDAP *ld, char *dn, LDAPMod **mods );
+int ldap_modify_s( LDAP *ld, char *dn, LDAPMod **mods );
+
+/*
+ * in modrdn.c:
+ */
+
+/*
+ * in rename.c:
+ */
+int ldap_rename(LDAP *ld, char *dn, char *newrdn, char *newparent, int deleteoldrdn, LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_rename_s(LDAP *ld, char *dn, char *newrdn, char *newparent, int deleteoldrdn, LDAPControl ** serverctrls, LDAPControl **clientctrls);
+
+/*
+ * in open.c:
+ */
+LDAP *ldap_init( char *defhost, int defport );
+
+
+#ifdef LDAP_SSL
+LDAP *ldap_ssl_init(char *defhost, int defport, char *keyname );
+#endif
+
+/*
+ * in getentry.c:
+ */
+LDAPMessage *ldap_first_entry( LDAP *ld, LDAPMessage *res );
+LDAPMessage *ldap_next_entry( LDAP *ld, LDAPMessage *entry );
+int ldap_count_entries( LDAP *ld, LDAPMessage *res );
+
+/*
+ * in getmsg.c:
+ */
+LDAPMessage *ldap_first_message( LDAP *ld, LDAPMessage *res );
+LDAPMessage *ldap_next_message( LDAP *ld, LDAPMessage *msg );
+int ldap_count_messages( LDAP *ld, LDAPMessage *res );
+
+/*
+ * in getref.c:
+ */
+LDAPMessage *ldap_first_reference( LDAP *ld, LDAPMessage *res );
+LDAPMessage *ldap_next_reference( LDAP *ld, LDAPMessage *msg );
+int ldap_count_references( LDAP *ld, LDAPMessage *res );
+char ** ldap_get_reference_urls( LDAP *ld, LDAPMessage *res );
+
+/*
+ * in addentry.c
+ */
+LDAPMessage *ldap_delete_result_entry( LDAPMessage **list,
+ LDAPMessage *e );
+void ldap_add_result_entry( LDAPMessage **list, LDAPMessage *e );
+
+/*
+ * in getdn.c
+ */
+char *ldap_get_dn( LDAP *ld, LDAPMessage *entry );
+char **ldap_explode_dn( char *dn, int notypes );
+char ** ldap_explode_rdn( char *rdn, int notypes );
+char *ldap_dn2ufn( char *dn );
+
+char **ldap_explode_dns( char *dn );
+int ldap_is_dns_dn( char *dn );
+char *ldap_dns_to_dn(char *dns_name, int *nameparts);
+
+/*
+ * in getattr.c
+ */
+char *ldap_first_attribute( LDAP *ld, LDAPMessage *entry,
+ BerElement **ber );
+char *ldap_next_attribute( LDAP *ld, LDAPMessage *entry,
+ BerElement *ber );
+void ldap_memfree(char *mem);
+
+/*
+ * in getvalues.c
+ */
+char **ldap_get_values( LDAP *ld, LDAPMessage *entry, char *target );
+struct berval **ldap_get_values_len( LDAP *ld, LDAPMessage *entry,
+ char *target );
+int ldap_count_values( char **vals );
+int ldap_count_values_len( struct berval **vals );
+void ldap_value_free( char **vals );
+void ldap_value_free_len( struct berval **vals );
+
+/*
+ * in result.c:
+ */
+int ldap_result( LDAP *ld, int msgid, int all,
+ struct timeval *timeout, LDAPMessage **result );
+int ldap_msgdelete( LDAP *ld, int msgid );
+int ldap_msgfree( LDAPMessage *lm );
+int ldap_msgtype( LDAPMessage *res );
+int ldap_msgid( LDAPMessage *res );
+int ldap_parse_result(LDAP *ld, LDAPMessage *res, int *errcodep, char **matcheddnp, char **errmsgp, char ***referralsp, LDAPControl ***serverctrlsp, int freeit) ;
+int ldap_parse_sasl_bind_result(LDAP *ld, LDAPMessage *res, struct berval **servercredp, int freeit);
+int ldap_parse_extended_result(LDAP *ld, LDAPMessage *res, char **resultoidp, struct berval **resultdata, int freeit);
+
+/*
+ * in search.c:
+ */
+int ldap_search_ext(LDAP *ld, char *base, int scope, char *filter, char **attrs, int attrsonly, LDAPControl **serverctrls, LDAPControl **clientctrls, struct timeval *timeoutp, int sizelimit, int *msgidp);
+int ldap_search_ext_s(LDAP *ld, char *base, int scope, char *filter, char **attrs, int attrsonly, LDAPControl **serverctrls, LDAPControl **clientctrls, struct timeval *timeoutp, int sizelimit, LDAPMessage **res);
+
+int ldap_search( LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly );
+int ldap_search_s( LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, LDAPMessage **res );
+int ldap_search_st( LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, struct timeval *timeout, LDAPMessage **res );
+
+/*
+ * in ufn.c
+ */
+int ldap_ufn_search_c( LDAP *ld, char *ufn, char **attrs,
+ int attrsonly, LDAPMessage **res, int (*cancelproc)( void *cl ),
+ void *cancelparm );
+int ldap_ufn_search_ct( LDAP *ld, char *ufn, char **attrs,
+ int attrsonly, LDAPMessage **res, int (*cancelproc)( void *cl ),
+ void *cancelparm, char *tag1, char *tag2, char *tag3 );
+int ldap_ufn_search_s( LDAP *ld, char *ufn, char **attrs,
+ int attrsonly, LDAPMessage **res );
+LDAPFiltDesc *ldap_ufn_setfilter( LDAP *ld, char *fname );
+void ldap_ufn_setprefix( LDAP *ld, char *prefix );
+int ldap_ufn_timeout( void *tvparam );
+
+
+/*
+ * in unbind.c
+ */
+int ldap_unbind( LDAP *ld );
+int ldap_unbind_s( LDAP *ld );
+
+
+/*
+ * in getfilter.c
+ */
+LDAPFiltDesc *ldap_init_getfilter( char *fname );
+LDAPFiltDesc *ldap_init_getfilter_buf( char *buf, ssize_t buflen );
+LDAPFiltInfo *ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat,
+ char *value );
+LDAPFiltInfo *ldap_getnextfilter( LDAPFiltDesc *lfdp );
+void ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix, char *suffix );
+void ldap_build_filter( char *buf, size_t buflen,
+ char *pattern, char *prefix, char *suffix, char *attr,
+ char *value, char **valwords );
+
+/*
+ * in free.c
+ */
+void ldap_getfilter_free( LDAPFiltDesc *lfdp );
+void ldap_mods_free( LDAPMod **mods, int freemods );
+
+/*
+ * in friendly.c
+ */
+char *ldap_friendly_name( char *filename, char *uname,
+ FriendlyMap **map );
+void ldap_free_friendlymap( FriendlyMap **map );
+
+
+/*
+ * in cldap.c
+ */
+LDAP *cldap_open( char *host, int port );
+void cldap_close( LDAP *ld );
+int cldap_search_s( LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, LDAPMessage **res, char *logdn );
+void cldap_setretryinfo( LDAP *ld, int tries, time_t timeout );
+
+
+/*
+ * in sort.c
+ */
+int ldap_sort_entries( LDAP *ld, LDAPMessage **chain, char *attr,
+ int (*cmp)() );
+int ldap_sort_values( LDAP *ld, char **vals, int (*cmp)() );
+int ldap_sort_strcasecmp( char **a, char **b );
+
+
+/*
+ * in url.c
+ */
+int ldap_is_ldap_url( char *url );
+int ldap_url_parse( char *url, LDAPURLDesc **ludpp );
+void ldap_free_urlexts( LDAPURLExt **lues );
+void ldap_free_urldesc( LDAPURLDesc *ludp );
+int ldap_url_search( LDAP *ld, char *url, int attrsonly );
+int ldap_url_search_s( LDAP *ld, char *url, int attrsonly,
+ LDAPMessage **res );
+int ldap_url_search_st( LDAP *ld, char *url, int attrsonly,
+ struct timeval *timeout, LDAPMessage **res );
+char *ldap_dns_to_url(LDAP *ld, char *dns_name, char *attrs,
+char *scope, char *filter);
+char *ldap_dn_to_url(LDAP *ld, char *dn, int nameparts);
+
+
+/*
+ * in charset.c
+ */
+#ifdef STR_TRANSLATION
+void ldap_set_string_translators( LDAP *ld,
+ BERTranslateProc encode_proc, BERTranslateProc decode_proc );
+int ldap_translate_from_t61( LDAP *ld, char **bufp,
+ unsigned int *lenp, int free_input );
+int ldap_translate_to_t61( LDAP *ld, char **bufp,
+ unsigned int *lenp, int free_input );
+void ldap_enable_translation( LDAP *ld, LDAPMessage *entry,
+ int enable );
+
+#ifdef LDAP_CHARSET_8859
+int ldap_t61_to_8859( char **bufp, unsigned int *buflenp,
+ int free_input );
+int ldap_8859_to_t61( char **bufp, unsigned int *buflenp,
+ int free_input );
+#endif /* LDAP_CHARSET_8859 */
+#endif /* STR_TRANSLATION */
+
+
+#ifdef WINSOCK
+/*
+ * in msdos/winsock/wsa.c
+ */
+void ldap_memfree( void *p );
+#endif /* WINSOCK */
diff --git a/usr/src/lib/libldap4/common/modify.c b/usr/src/lib/libldap4/common/modify.c
new file mode 100644
index 0000000000..44fa519efb
--- /dev/null
+++ b/usr/src/lib/libldap4/common/modify.c
@@ -0,0 +1,248 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * modify.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include "macos.h"
+#endif /* MACOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+BerElement * ldap_build_modify_req(LDAP *ld, char *dn, LDAPMod ** mods, LDAPControl **serverctrls)
+{
+ BerElement *ber;
+ int i, rc;
+
+ /*
+ * A modify request looks like this:
+ * ModifyRequest ::= SEQUENCE {
+ * object DistinguishedName,
+ * modifications SEQUENCE OF SEQUENCE {
+ * operation ENUMERATED {
+ * add (0),
+ * delete (1),
+ * replace (2)
+ * },
+ * modification SEQUENCE {
+ * type AttributeType,
+ * values SET OF AttributeValue
+ * }
+ * }
+ * }
+ */
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ return( NULLBER );
+ }
+ if ( ber_printf( ber, "{it{s{", ++ld->ld_msgid, LDAP_REQ_MODIFY, dn )
+ == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ /* for each modification to be performed... */
+ for ( i = 0; mods[i] != NULL; i++ ) {
+ if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
+ rc = ber_printf( ber, "{e{s[V]}}",
+ mods[i]->mod_op & ~LDAP_MOD_BVALUES,
+ mods[i]->mod_type, mods[i]->mod_bvalues );
+ } else {
+ rc = ber_printf( ber, "{e{s[v]}}", mods[i]->mod_op,
+ mods[i]->mod_type, mods[i]->mod_values );
+ }
+
+ if ( rc == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ return (ber);
+}
+
+/*
+ * ldap_modify - initiate an ldap (and X.500) modify operation. Parameters:
+ *
+ * ld LDAP descriptor
+ * dn DN of the object to modify
+ * mods List of modifications to make. This is null-terminated
+ * array of struct ldapmod's, specifying the modifications
+ * to perform.
+ *
+ * Example:
+ * LDAPMod *mods[] = {
+ * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
+ * { LDAP_MOD_REPLACE, "sn", { "jensen", 0 } },
+ * 0
+ * }
+ * msgid = ldap_modify( ld, dn, mods );
+ */
+int
+ldap_modify( LDAP *ld, char *dn, LDAPMod **mods )
+{
+ BerElement *ber;
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 192, "ldap_modify\n"), 0, 0, 0 );
+
+ if ((ber = ldap_build_modify_req(ld, dn, mods, NULL)) == NULLBER){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return ( rv );
+}
+
+int
+ldap_modify_s( LDAP *ld, char *dn, LDAPMod **mods )
+{
+ int msgid;
+ LDAPMessage *res;
+
+ if ( (msgid = ldap_modify( ld, dn, mods )) == -1 )
+ return( ld->ld_errno );
+
+ if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
+ return( ld->ld_errno );
+
+ return( ldap_result2error( ld, res, 1 ) );
+}
+
+/* ldapv3 API extensions */
+
+int ldap_modify_ext(LDAP *ld, char *dn, LDAPMod **mods,
+ LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp)
+{
+ BerElement *ber;
+ int i, rc;
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 192, "ldap_modify\n"), 0, 0, 0 );
+
+ if ((ber = ldap_build_modify_req(ld, dn, mods, serverctrls)) == NULLBER){
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS)
+ rv = LDAP_OTHER;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber );
+ if (rv == -1){
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS){
+ rv = LDAP_OTHER;
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+ *msgidp = rv;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return ( LDAP_SUCCESS );
+}
+
+
+int ldap_modify_ext_s(LDAP *ld, char *dn, LDAPMod **mods,
+ LDAPControl **serverctrls, LDAPControl **clientctrls)
+{
+ int msgid;
+ int retcode = LDAP_SUCCESS;
+ LDAPMessage *res;
+
+ if ((retcode = ldap_modify_ext(ld, dn, mods, serverctrls, clientctrls, &msgid)) != LDAP_SUCCESS)
+ return (retcode);
+ if (ldap_result(ld, msgid, 1, (struct timeval *)NULL, &res ) == -1)
+ return (ld->ld_errno );
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ retcode = ldap_parse_result(ld, res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
+ &ld->ld_referrals, &ld->ld_ret_ctrls, 1);
+ if (retcode == LDAP_SUCCESS)
+ retcode = ld->ld_errno;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (retcode);
+}
+
diff --git a/usr/src/lib/libldap4/common/modrdn.c b/usr/src/lib/libldap4/common/modrdn.c
new file mode 100644
index 0000000000..b1ec5a93ac
--- /dev/null
+++ b/usr/src/lib/libldap4/common/modrdn.c
@@ -0,0 +1,120 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * modrdn.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include "macos.h"
+#endif /* MACOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+/*
+ * ldap_modrdn - initiate an ldap (and X.500) modifyRDN operation. Parameters:
+ *
+ * ld LDAP descriptor
+ * dn DN of the object to modify
+ * newrdn RDN to give the object
+ * deleteoldrdn nonzero means to delete old rdn values from the entry
+ *
+ * Example:
+ * msgid = ldap_modrdn( ld, dn, newrdn );
+ */
+int
+ldap_modrdn( LDAP *ld, char *dn, char *newrdn, int deleteoldrdn )
+{
+ BerElement *ber;
+ int rv;
+
+ /*
+ * A modify rdn request looks like this:
+ * ModifyRDNRequest ::= SEQUENCE {
+ * entry DistinguishedName,
+ * newrdn RelativeDistinguishedName,
+ * deleteoldrdn BOOLEAN
+ * }
+ */
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 193, "ldap_modrdn\n"), 0, 0, 0 );
+
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+ if ( ber_printf( ber, "{it{ssb}}", ++ld->ld_msgid, LDAP_REQ_MODRDN, dn,
+ newrdn, deleteoldrdn ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return ( rv );
+}
+
+int
+ldap_modrdn0( LDAP *ld, char *dn, char *newrdn )
+{
+ return( ldap_modrdn( ld, dn, newrdn, 1 ) );
+}
+
+int
+ldap_modrdn_s( LDAP *ld, char *dn, char *newrdn, int deleteoldrdn )
+{
+ int msgid;
+ LDAPMessage *res;
+
+ if ( (msgid = ldap_modrdn( ld, dn, newrdn, deleteoldrdn )) == -1 )
+ return( ld->ld_errno );
+
+ if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
+ return( ld->ld_errno );
+
+ return( ldap_result2error( ld, res, 1 ) );
+}
+
+int
+ldap_modrdn0_s( LDAP *ld, char *dn, char *newrdn )
+{
+ return( ldap_modrdn_s( ld, dn, newrdn, 1 ) );
+}
diff --git a/usr/src/lib/libldap4/common/notif.c b/usr/src/lib/libldap4/common/notif.c
new file mode 100644
index 0000000000..f52cd56734
--- /dev/null
+++ b/usr/src/lib/libldap4/common/notif.c
@@ -0,0 +1,106 @@
+/*
+ *
+ * Copyright 13/01/98 Sun Microsystems, Inc. All Rights Reserved
+ * Comments:
+ *
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+LDAPMessage *ldap_first_notif(LDAP *ld)
+{
+ return ld->ld_notifs;
+}
+
+LDAPMessage *ldap_next_notif(LDAP *ld, LDAPMessage *current)
+{
+ if ( current == NULLMSG )
+ return NULLMSG;
+ else
+ return current->lm_next;
+}
+
+int ldap_reset_notif(LDAP *ld, int freeit)
+{
+ LDAPMessage *L_n=NULLMSG;
+ LDAPMessage *L_q=NULLMSG;
+
+ if ( freeit )
+ {
+ for (L_n=ld->ld_notifs; L_n!=NULLMSG; L_n=L_n->lm_next)
+ {
+ if ( L_n->lm_next != NULLMSG )
+ {
+ L_q = L_n->lm_next;
+ ldap_msgfree(L_n);
+ L_n = L_q;
+ }
+ else
+ {
+ ldap_msgfree(L_n);
+ break;
+ }
+ }
+ }
+ ld->ld_notifs = NULLMSG;
+
+ return (LDAP_SUCCESS);
+}
+
+int ldap_remove_notif(LDAP *ld, LDAPMessage *notif, int freeit)
+{
+ LDAPMessage *L_n=NULLMSG, *L_q=NULLMSG;
+
+ for ( L_n=ld->ld_notifs; L_n!=NULLMSG; L_n=L_n->lm_next)
+ {
+ if ( L_n == notif)
+ {
+ if ( L_q == NULLMSG )
+ ld->ld_notifs = L_n->lm_next;
+ else
+ L_q->lm_next = L_n->lm_next;
+
+ L_n->lm_next = NULLMSG;
+ if ( freeit )
+ ldap_msgfree(L_n);
+
+ break;
+ }
+ L_q = L_n;
+ }
+ return (LDAP_SUCCESS);
+}
+
+/* Add in tail */
+int ldap_add_notif(LDAP *ld, LDAPMessage *notif)
+{
+ LDAPMessage *L_n=NULLMSG, *L_q=NULLMSG;
+
+ for ( L_n=ld->ld_notifs; L_n!=NULLMSG; L_n=L_n->lm_next)
+ L_q = L_n;
+
+ notif->lm_next = NULLMSG;
+ if ( L_q == NULLMSG )
+ ld->ld_notifs = notif;
+ else
+ L_q->lm_next = notif;
+
+ return (LDAP_SUCCESS);
+}
+
+/* Add in head */
+int ldap_insert_notif(LDAP *ld, LDAPMessage *notif)
+{
+
+ notif->lm_next = ld->ld_notifs;
+ ld->ld_notifs = notif;
+
+ return (LDAP_SUCCESS);
+}
+
diff --git a/usr/src/lib/libldap4/common/open.c b/usr/src/lib/libldap4/common/open.c
new file mode 100644
index 0000000000..78211659f2
--- /dev/null
+++ b/usr/src/lib/libldap4/common/open.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 1995-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * open.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1995 Regents of the "
+ "University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* calloc(), free(), atoi() for Solaris */
+#include <locale.h>
+#include <thread.h>
+
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#endif /* MACOS */
+
+#if defined(DOS) || defined(_WIN32)
+#include "msdos.h"
+#include <stdlib.h>
+#endif /* DOS */
+
+#if !defined(MACOS) && !defined(DOS) && !defined(_WIN32)
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifndef VMS
+#include <sys/param.h>
+#endif
+#include <netinet/in.h>
+#endif
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifdef LDAP_DEBUG
+int ldap_debug;
+#endif
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK ((unsigned int) 0x7f000001)
+#endif
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+extern int thr_kill(thread_t, int);
+
+/*
+ * ldap_open - initialize and connect to an ldap server. A magic cookie to
+ * be used for future communication is returned on success, NULL on failure.
+ * "host" may be a space-separated list of hosts or IP addresses
+ *
+ * Example:
+ * LDAP *ld;
+ * ld = ldap_open( hostname, port );
+ */
+
+LDAP *
+ldap_open(char *host, int port)
+{
+ LDAP *ld;
+ int err;
+
+ if ((ld = ldap_init(host, port)) == NULL) {
+ return (NULL);
+ }
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 113,
+ "ldap_open (after ldap_init)\n"), 0, 0, 0);
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ if ((err = open_default_ldap_connection(ld)) != LDAP_SUCCESS) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ ldap_ld_free(ld, 0);
+ Debug(LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1275,
+ "ldap_open failed, %s\n"),
+ ldap_err2string(err), 0, 0);
+ return (NULL);
+ }
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 194,
+ "ldap_open successful, ld_host is %s\n"),
+ (ld->ld_host == NULL) ? "(null)" : ld->ld_host, 0, 0);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (ld);
+
+}
+
+/*
+ * Open the default connection
+ * ld->ld_defconn MUST be null when calling this function,
+ * ie the connection was never established
+ * ld should be LOCKed before calling this function
+ */
+int
+open_default_ldap_connection(LDAP *ld)
+{
+ LDAPServer *srv;
+ int err;
+
+ if ((srv = (LDAPServer *)calloc(1, sizeof (LDAPServer))) ==
+ NULL || (ld->ld_defhost != NULL && (srv->lsrv_host =
+ strdup(ld->ld_defhost)) == NULL)) {
+ return (LDAP_NO_MEMORY);
+ }
+ srv->lsrv_port = ld->ld_defport;
+
+ if ((ld->ld_defconn = new_connection(ld, &srv, 1, 1, 0)) ==
+ NULL) {
+ err = ld->ld_errno;
+ Debug(LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1276,
+ "Default connection to ldap server %s couldn't be "
+ "opened (%d)\n"), ld->ld_defhost, err, 0);
+
+ if (ld->ld_defhost != NULL)
+ free(srv->lsrv_host);
+ free((char *)srv);
+ return (err);
+ }
+
+ /* so it never gets closed/freed */
+ ++ld->ld_defconn->lconn_refcnt;
+
+ return (LDAP_SUCCESS);
+}
+
+static pthread_mutex_t ldap_thr_index_mutex = {0};
+static pthread_t ldap_thr_table[MAX_THREAD_ID] = {0};
+
+int
+ldap_thr_index()
+{
+ int i = 0;
+ int free = 0;
+ pthread_t cur = thr_self();
+ for (i = 1; i < MAX_THREAD_ID; ++i) {
+ if (ldap_thr_table[i] == cur) {
+ return (i);
+ } /* end if */
+ } /* end for */
+ /*
+ * not in the table, allocate a new entry
+ */
+ pthread_mutex_lock(&ldap_thr_index_mutex);
+ for (i = 1; i < MAX_THREAD_ID; ++i) {
+ if (ldap_thr_table[i] == 0 ||
+ thr_kill(ldap_thr_table[i], 0) != 0) {
+ ldap_thr_table[i] = cur;
+ pthread_mutex_unlock(&ldap_thr_index_mutex);
+ return (i);
+ } /* end if */
+ } /* end for */
+ pthread_mutex_unlock(&ldap_thr_index_mutex);
+ /* if table is full, return the first entry, so that it */
+ /* doesn't core dump */
+ return (0);
+}
+
+/*
+ * ldap_init - initialize the LDAP library. A magic cookie to be used for
+ * future communication is returned on success, NULL on failure.
+ * "defhost" may be a space-separated list of hosts or IP addresses
+ *
+ * Example:
+ * LDAP *ld;
+ * ld = ldap_init( default_hostname, default_port );
+ */
+LDAP *
+ldap_init(char *defhost, int defport)
+{
+ LDAP *ld;
+ char *locale;
+
+ locale = setlocale(LC_ALL, "");
+ i18n_catopen("sdserver");
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 195,
+ "ldap_init\n"), 0, 0, 0);
+
+
+ if ((ld = (LDAP *) calloc(1, sizeof (LDAP))) == NULL) {
+ return (NULL);
+ }
+
+#ifdef _REENTRANT
+ pthread_mutex_init(&ld->ld_ldap_mutex, DEFAULT_TYPE);
+ pthread_mutex_init(&ld->ld_response_mutex, DEFAULT_TYPE);
+ pthread_mutex_init(&ld->ld_poll_mutex, DEFAULT_TYPE);
+ ld->ld_lockthread = 0;
+#endif
+
+ if ((ld->ld_selectinfo = new_select_info()) == NULL) {
+ free((char *)ld);
+ return (NULL);
+ }
+ ld->ld_follow_referral = 1;
+
+ /*
+ * default to localhost when hostname is not specified
+ * or if null string is passed as hostname
+ */
+
+ if ((defhost != NULL) && (*defhost != NULL) &&
+ (ld->ld_defhost = strdup(defhost)) == NULL) {
+ free_select_info(ld->ld_selectinfo);
+ free((char *)ld);
+ return (NULL);
+ }
+
+ ld->ld_defport = (defport == 0) ? LDAP_PORT : defport;
+ ld->ld_version = LDAP_VERSION;
+ ld->ld_lberoptions = LBER_USE_DER;
+ ld->ld_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT;
+ ld->ld_connect_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT;
+
+#if defined(STR_TRANSLATION) && defined(LDAP_DEFAULT_CHARSET)
+ ld->ld_lberoptions |= LBER_TRANSLATE_STRINGS;
+#if LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET
+ ldap_set_string_translators(ld, ldap_8859_to_t61,
+ ldap_t61_to_8859);
+#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */
+#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */
+
+ return (ld);
+}
+
+
+/* ARGSUSED */
+int
+open_ldap_connection(LDAP *ld, Sockbuf *sb, char *host, int defport,
+ char **krbinstancep, int async)
+{
+ int rc, port;
+ char *p, *q, *r;
+ char *curhost, hostname[ 2*MAXHOSTNAMELEN ];
+ int bindTimeout;
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 196,
+ "open_ldap_connection\n"), 0, 0, 0);
+
+ defport = htons(defport);
+ bindTimeout = ld->ld_connect_timeout;
+
+ if (host != NULL) {
+ for (p = host; p != NULL && *p != '\0'; p = q) {
+ if ((q = strchr(p, ' ')) != NULL) {
+ (void) strncpy(hostname, p, q - p);
+ hostname[ q - p ] = '\0';
+ curhost = hostname;
+ while (*q == ' ') {
+ ++q;
+ }
+ } else {
+ /* avoid copy if possible */
+ curhost = p;
+ q = NULL;
+ }
+
+ if ((r = strchr(curhost, ':')) != NULL) {
+ if (curhost != hostname) {
+ /* now copy */
+ (void) strcpy(hostname, curhost);
+ r = hostname + (r - curhost);
+ curhost = hostname;
+ }
+ *r++ = '\0';
+ port = htons((short)atoi(r));
+ } else {
+ port = defport;
+ }
+
+ if ((rc = connect_to_host(sb, curhost, 0,
+ port, async, bindTimeout)) != -1) {
+ break;
+ }
+ }
+ } else {
+ rc = connect_to_host(sb, NULL, htonl(INADDR_LOOPBACK),
+ defport, async, bindTimeout);
+ }
+
+ if (rc == -1) {
+ return (rc);
+ }
+
+ if (krbinstancep != NULL) {
+#ifdef KERBEROS
+ if ((*krbinstancep = host_connected_to(sb)) != NULL &&
+ (p = strchr(*krbinstancep, '.')) != NULL) {
+ *p = '\0';
+ }
+#else /* KERBEROS */
+ krbinstancep = NULL;
+#endif /* KERBEROS */
+ }
+
+ return (0);
+}
+
+/*
+ * ldap_ssl_open - initialize and connect to an ssl secured ldap
+ * server. First ldap_open() is called and then ssl is layered on top
+ * of the socket. A magic cookie to be used for future communication
+ * is returned on success, NULL on failure. "host" may be a
+ * space-separated list of hosts or IP addresses. CAfile and CApath
+ * are used first time through, subsequent calls are ignored and can
+ * be NULL.
+ *
+ * Example:
+ * LDAP *ld;
+ * ld = ldap_ssl_open( hostname, port, key );
+ */
+
+#ifdef LDAP_SSL
+
+#include "security/ssl.h"
+
+int
+establish_ssl_connection(LDAP *ld)
+{
+ SSL *ssl = NULL; /* The Client's SSL connection */
+
+ /*
+ * Creates a new SSL connection. This holds information
+ * pertinent to this
+ * connection.
+ */
+ if ((ssl = SSL_new()) == NULL) {
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 198,
+ "SSL_new() failed: %s\n"),
+ SSL_strerr(SSL_errno(ssl)), 0, 0);
+ return (-1);
+ }
+
+ /* if keyname is non-null, set ssl keypackage name from it */
+ if (ld->ld_ssl_key != NULL) {
+ if (SSL_set_userid(ssl, ld->ld_ssl_key, 0) == NULL) {
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1,
+ 199, "SSL_set_userid() failed: %s\n"),
+ SSL_strerr(SSL_errno(ssl)), 0, 0);
+ return (-1);
+ }
+ }
+
+ /* Start the SSL connection */
+ if (SSL_connect(ssl, ld->ld_sb.sb_sd) < 1) {
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 200,
+ "SSL_connect() failed: %s\n"),
+ SSL_strerr(SSL_errno(ssl)), 0, 0);
+ return (-1);
+ }
+
+ ld->ld_sb.sb_ssl = ssl;
+ return (0);
+}
+
+
+LDAP *
+ldap_ssl_open(char *host, int port, char *keyname)
+{
+ LDAP *ld;
+ int rval;
+
+
+ if (port == 0)
+ port = SSL_LDAP_PORT;
+
+ ld = ldap_open(host, port);
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 197,
+ "ldap_ssl_open (after ldap_open)\n"), 0, 0, 0);
+
+ if (ld == NULL)
+ return (NULL);
+
+ ld->ld_use_ssl = 1;
+ if (keyname)
+ ld->ld_ssl_key = strdup(keyname);
+
+ if (establish_ssl_connection(ld) != 0) {
+ ldap_ld_free(ld, 1);
+ return (NULL);
+ }
+
+ return (ld);
+}
+
+LDAP *
+ldap_ssl_init(char *defhost, int defport, char *keyname)
+{
+ LDAP *ld;
+ int rval;
+
+
+ if (defport == 0)
+ defport = SSL_LDAP_PORT;
+
+ ld = ldap_init(defhost, defport);
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 197,
+ "ldap_ssl_open (after ldap_open)\n"), 0, 0, 0);
+
+ if (ld == NULL)
+ return (NULL);
+ ld->ld_use_ssl = 1;
+ ld->ld_ssl_key = strdup(keyname);
+
+ return (ld);
+}
+
+#endif /* LDAP_SSL */
diff --git a/usr/src/lib/libldap4/common/option.c b/usr/src/lib/libldap4/common/option.c
new file mode 100644
index 0000000000..b80d6a609c
--- /dev/null
+++ b/usr/src/lib/libldap4/common/option.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 1995-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+extern LDAPControl ** ldap_controls_dup(LDAPControl **ctrls);
+
+/*
+ * ldap_get_option()
+ */
+int
+ldap_get_option(LDAP *ld, int option, void *outvalue)
+{
+ if (ld == NULL)
+ return (-1);
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ switch (option) {
+ case LDAP_OPT_API_INFO:
+ ((LDAPAPIInfo *)outvalue)->ldapai_api_version =
+ LDAP_API_VERSION;
+ if (((LDAPAPIInfo *)outvalue)->ldapai_info_version !=
+ LDAP_API_INFO_VERSION) {
+ ((LDAPAPIInfo *)outvalue)->ldapai_info_version =
+ LDAP_API_INFO_VERSION;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+ ((LDAPAPIInfo *)outvalue)->ldapai_protocol_version =
+ LDAP_VERSION_MAX;
+ /* No extensions are currently supported */
+ ((LDAPAPIInfo *)outvalue)->ldapai_extensions = NULL;
+ ((LDAPAPIInfo *)outvalue)->ldapai_vendor_name =
+ strdup(LDAP_VENDOR_NAME);
+ ((LDAPAPIInfo *)outvalue)->ldapai_vendor_version =
+ LDAP_VENDOR_VERSION;
+ break;
+ case LDAP_OPT_DESC: /* depricated option */
+ *(int *)outvalue = ld->ld_sb.sb_sd;
+ break;
+ case LDAP_OPT_DEREF:
+ *(int *)outvalue = ld->ld_deref;
+ break;
+ case LDAP_OPT_SIZELIMIT:
+ *(int *)outvalue = ld->ld_sizelimit;
+ break;
+ case LDAP_OPT_TIMELIMIT:
+ *(int *)outvalue = ld->ld_timelimit;
+ break;
+ case LDAP_OPT_REBIND_FN: /* depricated option */
+ outvalue = (void *)ld->ld_rebindproc;
+ break;
+ case LDAP_OPT_REBIND_ARG: /* depricated option */
+ outvalue = ld->ld_rebind_extra_arg;
+ break;
+ case LDAP_OPT_REFERRALS:
+ *(int *)outvalue = ld->ld_follow_referral;
+ break;
+ case LDAP_OPT_RESTART:
+ *(int *)outvalue = ld->ld_restart;
+ break;
+ case LDAP_OPT_PROTOCOL_VERSION:
+ *(int *)outvalue = ld->ld_version;
+ break;
+ case LDAP_OPT_SERVER_CONTROLS:
+ outvalue = ld->ld_srvctrls;
+ break;
+ case LDAP_OPT_CLIENT_CONTROLS:
+ outvalue = ld->ld_cltctrls;
+ break;
+ case LDAP_OPT_API_FEATURE_INFO:
+ if ((((LDAPAPIFeatureInfo *)outvalue)->ldapaif_info_version !=
+ LDAP_FEATURE_INFO_VERSION) ||
+ (((LDAPAPIFeatureInfo *)outvalue)->ldapaif_name ==
+ NULL)) {
+ ((LDAPAPIFeatureInfo *)outvalue)->ldapaif_info_version =
+ LDAP_FEATURE_INFO_VERSION;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+ /*
+ * This option must be completed when optional api's (or
+ * (extensions) are supported by this library. Right now
+ * there are none, and therefore this section can not be
+ * completed.
+ */
+ break;
+ case LDAP_OPT_HOST_NAME:
+ *(char **)outvalue = ld->ld_host;
+ break;
+ case LDAP_OPT_ERROR_NUMBER:
+ *(int *)outvalue = ld->ld_errno;
+ break;
+ case LDAP_OPT_ERROR_STRING:
+ *(char **)outvalue = ld->ld_error;
+ break;
+ case LDAP_OPT_MATCHED_DN:
+/* case LDAP_OPT_ERROR_MATCHED: depricated option */
+ *(char **)outvalue = ld->ld_matched;
+ break;
+ case LDAP_X_OPT_CONNECT_TIMEOUT:
+ *((int *)outvalue) = ld->ld_connect_timeout;
+ break;
+ default:
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (0);
+}
+
+int
+ldap_set_option(LDAP *ld, int option, void *invalue)
+{
+ if (ld == NULL)
+ return (-1);
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ switch (option) {
+ case LDAP_OPT_DESC:
+ break;
+ case LDAP_OPT_DEREF:
+ if (*(int *)invalue != LDAP_DEREF_NEVER &&
+ *(int *)invalue != LDAP_DEREF_SEARCHING &&
+ *(int *)invalue != LDAP_DEREF_FINDING &&
+ *(int *)invalue != LDAP_DEREF_ALWAYS) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+ ld->ld_deref = *(int *)invalue;
+ break;
+ case LDAP_OPT_SIZELIMIT:
+ ld->ld_sizelimit = *(int *)invalue;
+ break;
+ case LDAP_OPT_TIMELIMIT:
+ ld->ld_timelimit = *(int *)invalue;
+ break;
+ case LDAP_OPT_REBIND_FN:
+ /* cast needs to be updated when ldap.h gets updated */
+ ld->ld_rebindproc = (LDAP_REBIND_FUNCTION *)invalue;
+ break;
+ case LDAP_OPT_REBIND_ARG:
+ ld->ld_rebind_extra_arg = invalue;
+ break;
+ case LDAP_OPT_REFERRALS:
+ if (invalue != LDAP_OPT_ON && invalue != LDAP_OPT_OFF) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+ ld->ld_follow_referral = invalue ? 1 : 0;
+ break;
+ case LDAP_OPT_RESTART:
+ if (invalue != LDAP_OPT_ON && invalue != LDAP_OPT_OFF) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+ ld->ld_restart = invalue ? 1 : 0;
+ break;
+ case LDAP_OPT_PROTOCOL_VERSION:
+ if (*(int *)invalue < LDAP_VERSION1 ||
+ *(int *)invalue > LDAP_VERSION3) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+ ld->ld_version = *(int *)invalue;
+ break;
+ case LDAP_OPT_SERVER_CONTROLS:
+ if (ld->ld_srvctrls != NULL) {
+ ldap_controls_free(ld->ld_srvctrls);
+ }
+ ld->ld_srvctrls = NULL;
+ if (invalue != NULL)
+ ld->ld_srvctrls = ldap_controls_dup(invalue);
+ break;
+ case LDAP_OPT_CLIENT_CONTROLS:
+ if (ld->ld_cltctrls != NULL) {
+ ldap_controls_free(ld->ld_cltctrls);
+ }
+ ld->ld_cltctrls = NULL;
+ if (invalue != NULL)
+ ld->ld_cltctrls = ldap_controls_dup(invalue);
+ break;
+ case LDAP_OPT_HOST_NAME:
+ if (ld->ld_host != NULL) {
+ free(ld->ld_host);
+ }
+ ld->ld_host = NULL;
+ if ((char *)invalue != NULL)
+ ld->ld_host = strdup((char *)invalue);
+ break;
+ case LDAP_OPT_ERROR_NUMBER:
+ break;
+ case LDAP_OPT_ERROR_STRING:
+ break;
+ case LDAP_OPT_MATCHED_DN:
+ if (ld->ld_matched)
+ free(ld->ld_matched);
+ ld->ld_matched = NULL;
+ if ((char *)invalue != NULL)
+ ld->ld_matched = strdup((char *)invalue);
+ break;
+ case LDAP_X_OPT_CONNECT_TIMEOUT:
+ ld->ld_connect_timeout = *((int *)invalue);
+ break;
+ default:
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (0);
+}
diff --git a/usr/src/lib/libldap4/common/os-ip.c b/usr/src/lib/libldap4/common/os-ip.c
new file mode 100644
index 0000000000..5f025ee548
--- /dev/null
+++ b/usr/src/lib/libldap4/common/os-ip.c
@@ -0,0 +1,614 @@
+/*
+ * Copyright (c) 1995-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * os-ip.c -- platform-specific TCP & UDP related code
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#ifdef _WIN32
+#include <io.h>
+#include "msdos.h"
+#else /* _WIN32 */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif /* _WIN32 */
+#ifdef _AIX
+#include <sys/select.h>
+#endif /* _AIX */
+#ifdef VMS
+#include "ucx_select.h"
+#endif /* VMS */
+#include "portable.h"
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifdef LDAP_REFERRALS
+#ifdef USE_SYSCONF
+#include <unistd.h>
+#endif /* USE_SYSCONF */
+#ifdef notyet
+#ifdef NEED_FILIO
+#include <sys/filio.h>
+#else /* NEED_FILIO */
+#include <sys/ioctl.h>
+#endif /* NEED_FILIO */
+#endif /* notyet */
+#endif /* LDAP_REFERRALS */
+
+#ifdef MACOS
+#define tcp_close(s) tcpclose(s)
+#else /* MACOS */
+#ifdef DOS
+#ifdef PCNFS
+#define tcp_close(s) close(s)
+#endif /* PCNFS */
+#ifdef NCSA
+#define tcp_close(s) netclose(s); netshut()
+#endif /* NCSA */
+#ifdef WINSOCK
+#define tcp_close(s) closesocket(s); WSACleanup();
+#endif /* WINSOCK */
+#else /* DOS */
+#define tcp_close(s) close(s)
+#endif /* DOS */
+#endif /* MACOS */
+#ifdef SUN
+#include <nss_dbdefs.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/poll.h>
+
+
+/*
+ * Do an async connect or blocking connect depending on the timeout
+ * value. LDAP_X_IO_TIMEOUT_NO_TIMEOUT means do a blocking connect.
+ * Otherwise wait for timeout milliseconds for the connection.
+ * Returns 0 on success and -1 on failure.
+ */
+static int
+do_connect(int s, struct sockaddr *sin, int timeout)
+{
+ int flags, connected = 0;
+ int retval, error, n;
+ fd_set wfds;
+ struct timeval waittime, *sel_timeout;
+
+ /* set the socket to do non-blocking i/o */
+ flags = fcntl(s, F_GETFL, 0);
+ fcntl(s, F_SETFL, flags | O_NONBLOCK);
+
+ if (connect(s, sin, sizeof (struct sockaddr_in)) == 0) {
+ connected = 1;
+ } else if (errno == EINPROGRESS) {
+ /* if NO_TIMEOUT is specified do a blocking connect */
+ if (timeout <= LDAP_X_IO_TIMEOUT_NO_TIMEOUT) {
+ sel_timeout = NULL;
+ } else {
+ /* set the timeout to the specified value */
+ waittime.tv_sec = timeout / MILLISEC;
+ waittime.tv_usec = (timeout % MILLISEC) * 1000;
+ sel_timeout = &waittime;
+ }
+
+ FD_ZERO(&wfds);
+ FD_SET(s, &wfds);
+ n = sizeof (error);
+ if (select(s+1, NULL, &wfds, NULL, sel_timeout) > 0 &&
+ FD_ISSET(s, &wfds) &&
+ getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &n) == 0 &&
+ error == 0) {
+ connected = 1;
+ }
+ }
+
+ /* if we are connected restore the flags for the socket */
+ if (connected) {
+ fcntl(s, F_SETFL, flags);
+ }
+
+ return (connected ? 0 : -1);
+}
+
+
+int
+connect_to_host(Sockbuf *sb, char *host, in_addr_t address,
+ int port, int async, int timeout)
+/*
+ * if host == NULL, connect using address
+ * "address" and "port" must be in network byte order
+ * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
+ * async is only used ifdef LDAP_REFERRALS (non-0 means don't wait for connect)
+ * XXX async is not used yet!
+ */
+{
+ int rc, i, s, connected, use_hp;
+ struct sockaddr_in sin;
+ struct hostent *hp;
+#ifdef notyet
+#ifdef LDAP_REFERRALS
+ int status; /* for ioctl call */
+#endif /* LDAP_REFERRALS */
+#endif /* notyet */
+#ifdef SUN
+ struct hostent hpret;
+ char hpbuf[NSS_BUFLEN_HOSTS];
+ int hperrno;
+#endif
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 201, "connect_to_host: "
+ "%1$s:%2$d\n"), (host == NULL) ? catgets(slapdcat, 1, 202,
+ "(by address)") : host, ntohs(port), 0);
+
+ connected = use_hp = 0;
+
+ if (host != NULL && (address = inet_addr(host)) == -1) {
+#ifdef SUN
+ if ((hp = gethostbyname_r(host, &hpret, hpbuf,
+ NSS_BUFLEN_HOSTS, &hperrno)) == NULL) {
+#else
+ if ((hp = gethostbyname(host)) == NULL) {
+#endif
+ errno = EHOSTUNREACH; /* not exactly right, but... */
+ return (-1);
+ }
+ use_hp = 1;
+ }
+
+ rc = -1;
+ for (i = 0; !use_hp || (hp->h_addr_list[i] != 0); i++) {
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ return (-1);
+ }
+#ifdef notyet
+#ifdef LDAP_REFERRALS
+ status = 1;
+ if (async && ioctl(s, FIONBIO, (caddr_t)&status) == -1) {
+ Debug(LDAP_DEBUG_ANY, catgets(slapdcat, 1, 203,
+ "FIONBIO ioctl failed on %d\n"), s, 0, 0);
+ }
+#endif /* LDAP_REFERRALS */
+#endif /* notyet */
+ (void) memset((char *)&sin, 0, sizeof (struct sockaddr_in));
+ sin.sin_family = AF_INET;
+ sin.sin_port = port;
+ SAFEMEMCPY((char *) &sin.sin_addr.s_addr,
+ (use_hp ? (char *) hp->h_addr_list[i] :
+ (char *)&address), sizeof (sin.sin_addr.s_addr));
+
+ if (do_connect(s, (struct sockaddr *)&sin, timeout) == 0) {
+ connected = 1;
+ break;
+ }
+
+#ifdef notyet
+#ifdef LDAP_REFERRALS
+#ifdef EAGAIN
+ if (errno == EINPROGRESS || errno == EAGAIN) {
+#else /* EAGAIN */
+ if (errno == EINPROGRESS) {
+#endif /* EAGAIN */
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 204,
+ "connect would block...\n"), 0, 0, 0);
+ rc = -2;
+ break;
+ }
+#endif /* LDAP_REFERRALS */
+#endif /* notyet */
+
+#ifdef LDAP_DEBUG
+ if (ldap_debug & LDAP_DEBUG_TRACE) {
+ perror((char *)inet_ntoa(sin.sin_addr));
+ }
+#endif
+ close(s);
+ if (!use_hp) {
+ break;
+ }
+ }
+
+ if (connected) {
+ rc = 0;
+ sb->sb_sd = s;
+#ifdef notyet
+#ifdef LDAP_REFERRALS
+ status = 0;
+ if (!async && ioctl(s, FIONBIO, (caddr_t)&on) == -1) {
+ Debug(LDAP_DEBUG_ANY, catgets(slapdcat, 1, 203,
+ "FIONBIO ioctl failed on %d\n"), s, 0, 0);
+ }
+#endif /* LDAP_REFERRALS */
+#endif /* notyet */
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 205,
+ "sd %1$d connected to: %2$s\n"), s,
+ inet_ntoa(sin.sin_addr), 0);
+ }
+
+ return (rc);
+}
+
+
+void
+close_ldap_connection( Sockbuf *sb )
+{
+#ifdef LDAP_SSL
+ if (sb->sb_ssl){
+ SSL_close(sb->sb_ssl);
+ SSL_delete(sb->sb_ssl);
+ }
+ sb->sb_ssl = NULL;
+ sb->sb_ssl_tls = 0;
+#endif
+ tcp_close( sb->sb_sd );
+}
+
+
+#ifdef KERBEROS
+char *
+host_connected_to( Sockbuf *sb )
+{
+ struct hostent *hp;
+ char *p;
+ int len;
+ struct sockaddr_in sin;
+#ifdef SUN
+ struct hostent hpret;
+ char hpbuf[NSS_BUFLEN_HOSTS];
+ int hperrno;
+#endif
+
+ (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
+ len = sizeof( sin );
+ if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
+ return( NULL );
+ }
+
+ /*
+ * do a reverse lookup on the addr to get the official hostname.
+ * this is necessary for kerberos to work right, since the official
+ * hostname is used as the kerberos instance.
+ */
+#ifdef SUN
+ if (( hp = gethostbyaddr_r((char *) &sin.sin_addr,
+ sizeof( sin.sin_addr ), AF_INET,
+ &hpret, hpbuf, NSS_BUFLEN_HOSTS, &hperrno)) != NULL ) {
+#else
+ if (( hp = gethostbyaddr( (char *) &sin.sin_addr,
+ sizeof( sin.sin_addr ), AF_INET )) != NULL ) {
+#endif
+ if ( hp->h_name != NULL ) {
+ return( strdup( hp->h_name ));
+ }
+ }
+
+ return( NULL );
+}
+#endif /* KERBEROS */
+
+
+#ifdef LDAP_REFERRALS
+#ifdef SUN
+/* for UNIX */
+#include <stropts.h>
+#include <poll.h>
+
+struct selectinfo {
+ struct pollfd fds[LDAP_DEFAULT_REFHOPLIMIT];
+ int nbfds;
+};
+
+
+void
+mark_select_write( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+ int i;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ /* find if sb is in fds */
+ for (i=0; i< sip->nbfds; i++) {
+ if (sip->fds[i].fd == sb->sb_sd){
+ sip->fds[i].events |= POLLOUT;
+ return;
+ }
+ }
+ if (sip->nbfds < LDAP_DEFAULT_REFHOPLIMIT) {
+ sip->fds[sip->nbfds].fd = sb->sb_sd;
+ sip->fds[sip->nbfds].events |= POLLOUT;
+ sip->nbfds++;
+ }
+ else {
+ /* Should not happen */
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 206, "Mark for poll : Too many descriptors\n"), 0, 0, 0 );
+ }
+}
+
+
+void
+mark_select_read( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+ int i;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ /* find if sb is in fds */
+ for (i=0; i< sip->nbfds; i++) {
+ if (sip->fds[i].fd == sb->sb_sd) {
+ sip->fds[i].events |= POLLIN;
+ return;
+ }
+ }
+
+ if (sip->nbfds < LDAP_DEFAULT_REFHOPLIMIT) {
+ sip->fds[sip->nbfds].fd = sb->sb_sd;
+ sip->fds[sip->nbfds].events |= POLLIN;
+ sip->nbfds++;
+ }
+ else {
+ /* Should not happen */
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 206, "Mark for poll : Too many descriptors\n"), 0, 0, 0 );
+ }
+}
+
+
+void
+mark_select_clear( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+ int i;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ for (i = 0; i< sip->nbfds; i++) {
+ if (sip->fds[i].fd == sb->sb_sd){
+ i++;
+ for (; i < sip->nbfds; i ++) {
+ sip->fds[ i - 1] = sip->fds[i];
+ }
+ sip->fds[i].fd = -1;
+ sip->fds[i].events = -1;
+ sip->nbfds--;
+ return;
+ }
+ }
+ /* If we reach here, there's a pb. */
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 207, "Clear poll : descriptor not found\n"), 0, 0, 0 );
+}
+
+
+long
+is_write_ready( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+ int i;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ for (i=0; i< sip->nbfds; i++) {
+ if (sip->fds[i].fd == sb->sb_sd) {
+ if ( sip->fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) {
+ return (-1);
+ }
+ return( sip->fds[i].revents & POLLOUT );
+ }
+ }
+ return(0);
+}
+
+
+long
+is_read_ready( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+ int i;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ for (i=0; i< sip->nbfds; i++) {
+ if (sip->fds[i].fd == sb->sb_sd) {
+ if (sip->fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) {
+ return (-1);
+ }
+ return( sip->fds[i].revents & POLLIN );
+ }
+ }
+ return(0);
+}
+
+void *
+new_select_info()
+{
+ struct selectinfo *sip;
+
+ sip = (struct selectinfo *)calloc( 1, sizeof( struct selectinfo ));
+
+ return( (void *)sip );
+}
+
+
+void
+free_select_info( void *sip )
+{
+ free( sip );
+}
+
+
+int
+do_ldap_select( LDAP *ld, struct timeval *timeout )
+{
+ struct selectinfo *sip;
+ int tim;
+#if defined( SUN ) && defined( _REENTRANT )
+ int rv;
+#endif
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 208, "do_ldap_select\n"), 0, 0, 0 );
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+/* sip->fds[0].revents = 0; */
+
+ if ( timeout ) {
+ tim = (timeout->tv_sec*1000)+(timeout->tv_usec/1000);
+ } else {
+ tim = INFTIM;
+ } /* end if */
+ errno=0;
+#if defined( SUN ) && defined( _REENTRANT )
+/* UNLOCK_LDAP(ld); */
+ LOCK_POLL(ld);
+ rv = poll(sip->fds,sip->nbfds,tim);
+/* LOCK_LDAP(ld); */
+ UNLOCK_POLL(ld);
+ return(rv);
+#else
+ return( poll(sip->fds,sip->nbfds,tim) );
+#endif
+}
+#else
+/* for UNIX */
+struct selectinfo {
+ fd_set si_readfds;
+ fd_set si_writefds;
+ fd_set si_use_readfds;
+ fd_set si_use_writefds;
+};
+
+
+void
+mark_select_write( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ if ( !FD_ISSET( sb->sb_sd, &sip->si_writefds )) {
+ FD_SET( sb->sb_sd, &sip->si_writefds );
+ }
+}
+
+
+void
+mark_select_read( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ if ( !FD_ISSET( sb->sb_sd, &sip->si_readfds )) {
+ FD_SET( sb->sb_sd, &sip->si_readfds );
+ }
+}
+
+
+void
+mark_select_clear( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ FD_CLR( sb->sb_sd, &sip->si_writefds );
+ FD_CLR( sb->sb_sd, &sip->si_readfds );
+}
+
+
+long
+is_write_ready( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ return( FD_ISSET( sb->sb_sd, &sip->si_use_writefds ));
+}
+
+
+long
+is_read_ready( LDAP *ld, Sockbuf *sb )
+{
+ struct selectinfo *sip;
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+
+ return( FD_ISSET( sb->sb_sd, &sip->si_use_readfds ));
+}
+
+
+void *
+new_select_info()
+{
+ struct selectinfo *sip;
+
+ if (( sip = (struct selectinfo *)calloc( 1,
+ sizeof( struct selectinfo ))) != NULL ) {
+ FD_ZERO( &sip->si_readfds );
+ FD_ZERO( &sip->si_writefds );
+ }
+
+ return( (void *)sip );
+}
+
+
+void
+free_select_info( void *sip )
+{
+ free( sip );
+}
+
+
+int
+do_ldap_select( LDAP *ld, struct timeval *timeout )
+{
+ struct selectinfo *sip;
+ static int tblsize;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 208, "do_ldap_select\n"), 0, 0, 0 );
+
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ if ( tblsize == 0 ) {
+#ifdef USE_SYSCONF
+ tblsize = (int)sysconf( _SC_OPEN_MAX );
+#else /* USE_SYSCONF */
+ tblsize = getdtablesize();
+#endif /* USE_SYSCONF */
+ }
+
+ sip = (struct selectinfo *)ld->ld_selectinfo;
+ sip->si_use_readfds = sip->si_readfds;
+ sip->si_use_writefds = sip->si_writefds;
+
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( select( tblsize, &sip->si_use_readfds, &sip->si_use_writefds,
+ NULL, timeout ));
+}
+#endif /* SUN */
+#endif /* LDAP_REFERRALS */
diff --git a/usr/src/lib/libldap4/common/referral.c b/usr/src/lib/libldap4/common/referral.c
new file mode 100644
index 0000000000..80b2444526
--- /dev/null
+++ b/usr/src/lib/libldap4/common/referral.c
@@ -0,0 +1,510 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include "portable.h"
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+static BerElement *
+re_encode_request( LDAP *ld, BerElement *origber, int msgid, LDAPURLDesc *urldesc );
+static void addFollowedRef(LDAPRequest *lr, char *ref);
+static void addToFollowRef(LDAPRequest *lr, char *ref);
+static int addUnFollowedRef(LDAP *ld, LDAPRequest *lr, char *ref);
+
+char ** ldap_errormsg2referrals(char *errmsg) {
+ char ** refs;
+ int count;
+ size_t len;
+ char *p, *ref;
+
+ if (errmsg == NULL){
+ return (NULL);
+ }
+ len = strlen( errmsg );
+ for ( p = errmsg; len >= LDAP_REF_STR_LEN; ++p, --len ) {
+ if (( *p == 'R' || *p == 'r' ) && strncasecmp( p,
+ LDAP_REF_STR, LDAP_REF_STR_LEN ) == 0 ) {
+ *p = '\0';
+ p += LDAP_REF_STR_LEN;
+ break;
+ }
+ }
+
+ if ( len < LDAP_REF_STR_LEN ) {
+ return( NULL);
+ }
+ count = 1;
+ ref = p;
+ while ((ref = strchr(ref, '\n')) != NULL)
+ count++;
+
+ if ((refs = (char **)calloc(count + 1, sizeof(char *))) == NULL){
+ return (NULL);
+ }
+
+ count = 0;
+ for (ref = p; ref != NULL; ref= p){
+ if ((p = strchr(ref, '\n')) != NULL){
+ *p = '\0';
+ }
+ refs[count++] = strdup(ref);
+ if (p != NULL)
+ *p++ = '\n';
+ }
+ return (refs);
+}
+
+char *ldap_referral2error_msg(char ** refs)
+{
+ int i;
+ size_t len = 0;
+ char *msg = NULL;
+
+ if (refs == NULL)
+ return (msg);
+
+ for (i = 0; refs[i] != NULL; i++){
+ len += strlen (refs[i]) + 1;
+ }
+
+ if ((len > 0) && ((msg = (char *)malloc(len + LDAP_REF_STR_LEN + 2)) != NULL)) {
+ strncpy(msg, LDAP_REF_STR, LDAP_REF_STR_LEN);
+ for (i = 0; refs[i] != NULL; i++) {
+ strcat(msg, refs[i]);
+ strcat(msg, "\n");
+ }
+ }
+ return (msg);
+}
+
+
+int
+chase_referrals( LDAP *ld, LDAPRequest *lr, char **refs, int *count, int samerequest )
+{
+ int rc, len, newdn, i, j, refcnt, errCode;
+ char *p, *ports, *ref, *tmpref, *refdn;
+ LDAPRequest *origreq;
+ LDAPServer *srv;
+ BerElement *ber;
+ LDAPURLDesc *ludp;
+
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 215, "=> chase_referrals\n"), 0, 0, 0 );
+
+ ld->ld_errno = LDAP_SUCCESS; /* optimistic */
+ *count = 0;
+ if ( refs == NULL ) {
+ return( LDAP_SUCCESS );
+ }
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+
+ if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) {
+ Debug( LDAP_DEBUG_ANY,
+ catgets(slapdcat, 1, 216, "more than %d referral hops (dropping)\n"),
+ ld->ld_refhoplimit, 0, 0 );
+ /* XXX report as error in ld->ld_errno? */
+ rc = ld->ld_errno = (ld->ld_version >= LDAP_VERSION3) ? LDAP_REFERRAL_LIMIT_EXCEEDED : LDAP_OTHER;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( rc );
+ }
+
+ /* find original request */
+ for ( origreq = lr; origreq->lr_parent != NULL;
+ origreq = origreq->lr_parent ) {
+ ;
+ }
+
+ for (refcnt = 0; refs[refcnt] != NULL; refcnt++)
+ ; /* Count number of referrals */
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1277, "%d possible referrals to chase\n"), refcnt, 0,0);
+
+ rc = 0;
+ /* parse out & follow referrals */
+ for (i = 0; rc == 0 && refs[i] != NULL; i++) {
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Try to chase %s\n"), refs[i], 0,0);
+
+ /* Parse URL */
+ if (ldap_url_parse(refs[i], &ludp) != 0){
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Bad URL for referral %s\n"), refs[i], 0,0);
+ errCode = LDAP_PARAM_ERROR;
+ addUnFollowedRef(ld, lr, refs[i]);
+ /* try next URL */
+ continue;
+ }
+
+ /* Encode previous request with new URL */
+ if (( ber = re_encode_request( ld, origreq->lr_ber, ++ld->ld_msgid, ludp )) == NULL ) {
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Error while encoding request for referral\n"), 0, 0,0);
+ ldap_free_urldesc(ludp);
+ errCode = ld->ld_errno;
+ addUnFollowedRef(ld, lr, refs[i]);
+ /* try next URL */
+ continue;
+ }
+
+ if (( srv = (LDAPServer *)calloc( 1, sizeof( LDAPServer ))) == NULL ) {
+ ldap_free_urldesc(ludp);
+ ber_free( ber, 1 );
+ rc = ld->ld_errno = LDAP_NO_MEMORY;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( rc );
+ }
+
+ if (( srv->lsrv_host = strdup( ludp->lud_host ? ludp->lud_host : ld->ld_defhost)) == NULL ) {
+ ldap_free_urldesc(ludp);
+ free( (char *)srv );
+ ber_free( ber, 1 );
+ rc = ld->ld_errno = LDAP_NO_MEMORY;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( rc );
+ }
+
+ srv->lsrv_port = ludp->lud_port ? ludp->lud_port : LDAP_PORT;
+
+ if ( srv != NULL && send_server_request( ld, ber, ld->ld_msgid,
+ lr, srv, NULL, 1 ) >= 0 ) {
+ ++*count;
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Request has been forwarded to %s\n"), refs[i], 0,0);
+ addFollowedRef(lr, refs[i]);
+ for (j = i+1; refs[j] != NULL; j++){
+ addToFollowRef(lr, refs[j]);
+ }
+ ldap_free_urldesc(ludp);
+ break;
+ } else {
+ Debug( LDAP_DEBUG_ANY,
+ catgets(slapdcat, 1, 220, "Unable to chase referral (%s)\n"),
+ ldap_err2string( ld->ld_errno ), 0, 0 );
+ addUnFollowedRef(ld, lr, refs[i]);
+ errCode = ld->ld_errno;
+ }
+ ldap_free_urldesc(ludp); /* So far spawn all requests */
+ }
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ if (refs[i] != NULL) {
+ rc = LDAP_SUCCESS;
+ } else {
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "No referral was successfully chased (last error %d)\n"), errCode, 0, 0);
+ rc = errCode;
+ }
+ Debug ( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1278, "<= chase_referrals --- \n"), 0,0,0);
+
+ return( rc );
+}
+
+static void addFollowedRef(LDAPRequest *lr, char *ref)
+{
+ int i;
+
+ if (lr->lr_ref_followed == NULL){
+ if ((lr->lr_ref_followed = (char **)calloc(2, sizeof(char*))) == NULL)
+ return;
+ i = 0;
+ } else {
+ for (i = 0; lr->lr_ref_followed[i] != NULL; i++);
+ if ((lr->lr_ref_followed = (char **)realloc((char *)lr->lr_ref_followed, (i+2) * sizeof(char *))) == NULL){
+ return;
+ }
+ }
+ lr->lr_ref_followed[i++] = strdup(ref);
+ lr->lr_ref_followed[i] = NULL;
+ return;
+}
+
+static void addToFollowRef(LDAPRequest *lr, char *ref)
+{
+ int i;
+
+ if (lr->lr_ref_tofollow == NULL){
+ if ((lr->lr_ref_tofollow = (char **)calloc(2, sizeof(char*))) == NULL)
+ return;
+ i = 0;
+ } else {
+ for (i = 0; lr->lr_ref_tofollow[i] != NULL; i++);
+ if ((lr->lr_ref_tofollow = (char **)realloc((char *)lr->lr_ref_tofollow, (i+2) * sizeof(char *))) == NULL){
+ return;
+ }
+ }
+ lr->lr_ref_tofollow[i++] = strdup(ref);
+ lr->lr_ref_tofollow[i] = NULL;
+ return;
+}
+
+static int addUnFollowedRef(LDAP *ld, LDAPRequest *lr, char *ref)
+{
+ int i;
+
+ if (lr->lr_ref_unfollowed == NULL){
+ if ((lr->lr_ref_unfollowed = (char **)calloc(2, sizeof(char*))) == NULL){
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return (-1);
+ }
+ i = 0;
+ } else {
+ for (i = 0; lr->lr_ref_unfollowed[i] != NULL; i++);
+ if ((lr->lr_ref_unfollowed = (char **)realloc((char *)lr->lr_ref_unfollowed, (i+2) * sizeof(char *))) == NULL){
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return (-1);
+ }
+ }
+ lr->lr_ref_unfollowed[i++] = strdup(ref);
+ lr->lr_ref_unfollowed[i] = NULL;
+ return (0);
+}
+
+
+int
+append_referral( LDAP *ld, char **referralsp, char *s )
+{
+ int first;
+
+ if ( *referralsp == NULL ) {
+ first = 1;
+ *referralsp = (char *)malloc( strlen( s ) + LDAP_REF_STR_LEN
+ + 1 );
+ } else {
+ first = 0;
+ *referralsp = (char *)realloc( *referralsp,
+ strlen( *referralsp ) + strlen( s ) + 2 );
+ }
+
+ if ( *referralsp == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( -1 );
+ }
+
+ if ( first ) {
+ strcpy( *referralsp, LDAP_REF_STR );
+ } else {
+ strcat( *referralsp, "\n" );
+ }
+ strcat( *referralsp, s );
+
+ return( 0 );
+}
+
+
+
+static BerElement *
+re_encode_request( LDAP *ld, BerElement *origber, int msgid, LDAPURLDesc *urldesc )
+{
+/*
+ * XXX this routine knows way too much about how the lber library works!
+ */
+ unsigned int along, tag, len;
+ int ver, scope, deref, sizelimit, timelimit, attrsonly;
+ int rc, hasCtrls;
+ BerElement tmpber, *ber;
+ char *dn, *seqstart;
+
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 221, "re_encode_request: new msgid %1$d, new dn <%2$s>\n"),
+ msgid, ( urldesc->lud_dn == NULL ) ? "NONE" : urldesc->lud_dn, 0 );
+
+ tmpber = *origber;
+
+ /*
+ * all LDAP requests are sequences that start with a message id,
+ * followed by a sequence that is tagged with the operation code
+ */
+ /* Bad assumption : delete op is not a sequence.
+ * So we have a special processing for it : it's much simpler
+ */
+ if ( ber_scanf( &tmpber, "{i", &along ) != LDAP_TAG_MSGID ||
+ ( tag = ber_peek_tag( &tmpber, &along )) == LBER_DEFAULT ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( NULL );
+ }
+
+ /* Special case : delete request is not a sequence of... */
+ if (tag == LDAP_REQ_EXTENDED){
+ /* return error, I don't know how to do it automatically */
+ ld->ld_errno = LDAP_NOT_SUPPORTED;
+ return (NULL);
+ }
+
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ return (NULL);
+ }
+
+ if (tag == LDAP_REQ_DELETE) {
+ if ( ber_get_stringa( &tmpber, &dn ) == LBER_DEFAULT ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ Debug(LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 1279,"Error in decoding delete DN"),0,0,0);
+ ber_free( ber, 1);
+ return( NULL );
+ }
+ /* Check if controls */
+ hasCtrls = 0;
+ if (ber_peek_tag(&tmpber, &len) == LDAP_TAG_CONTROL_LIST){
+ hasCtrls = 1;
+ }
+
+ if ( urldesc->lud_dn && *urldesc->lud_dn ) {
+ free( dn );
+ dn = urldesc->lud_dn;
+ }
+ if ( ber_printf( ber, "{its", msgid, tag, dn ) == -1 ) {
+ Debug(LDAP_DEBUG_TRACE, "Error in re_encoding delete request",0,0,0);
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return (NULL);
+ }
+ /* Now add controls if any */
+ if (hasCtrls && ber_write( ber, tmpber.ber_ptr, len, 0 ) != len ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+ if (ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+
+#ifdef LDAP_DEBUG
+ if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
+ Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 222, "re_encode_request new request is:\n"),
+ 0, 0, 0 );
+ ber_dump( ber, 0 );
+ }
+#endif /* LDAP_DEBUG */
+ return (ber);
+ }
+
+ if (( tag = ber_skip_tag( &tmpber, &along )) == LBER_DEFAULT ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( NULL );
+ }
+ /* Keep length and pointer */
+ seqstart = tmpber.ber_ptr;
+
+ /* bind requests have a version number before the DN & other stuff */
+ if ( tag == LDAP_REQ_BIND && ber_get_int( &tmpber, &ver ) ==
+ LBER_DEFAULT ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+
+ /* the rest of the request is the DN followed by other stuff */
+ if ( ber_get_stringa( &tmpber, &dn ) == LBER_DEFAULT ) {
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+ if ( urldesc->lud_dn != NULL ) {
+ free( dn );
+ dn = urldesc->lud_dn;
+ }
+
+ /* see what to do with CONTROLS */
+
+ if ( tag == LDAP_REQ_BIND ) {
+ rc = ber_printf( ber, "{it{is", msgid, tag, ver, dn );
+ } else {
+ rc = ber_printf( ber, "{it{s", msgid, tag, dn );
+ }
+
+ if ( rc == -1 ) {
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+
+ if (tag == LDAP_REQ_SEARCH) {
+ /* Now for SEARCH, decode more of the request */
+ if (ber_scanf(&tmpber, "iiiib", &scope, &deref, &sizelimit, &timelimit, &attrsonly) == LBER_DEFAULT){
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+ if (ber_printf(ber, "iiiib", urldesc->lud_scope == LDAP_SCOPE_UNKNOWN ? scope : urldesc->lud_scope,
+ deref, sizelimit, timelimit, attrsonly) == -1) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+ /* We should then decode and check the filter as opposed to ludp->lud_filter */
+ /* Same for attributes */
+ /* Later */
+ }
+ /* The rest is the same for all requests */
+
+ /* Copy Buffer from tmpber.ber_ptr for along - (tmpber.ber_ptr - seqstart) */
+ /* It's the rest of the request */
+ len = along - ( tmpber.ber_ptr - seqstart);
+ if ( ber_write( ber, tmpber.ber_ptr, len, 0) != len ||
+ ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+
+ if (seqstart + along < tmpber.ber_end){ /* there's probably some controls, copy them also */
+ len = tmpber.ber_end - seqstart - along;
+ if ( ber_write( ber, seqstart + along, len, 0) != len ){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+ }
+
+ if ( ber_printf(ber, "}") == -1) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULL );
+ }
+
+#ifdef LDAP_DEBUG
+ if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
+ Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 222, "re_encode_request new request is:\n"),
+ 0, 0, 0 );
+ ber_dump( ber, 0 );
+ }
+#endif /* LDAP_DEBUG */
+
+ return( ber );
+}
+
+
+LDAPRequest *
+find_request_by_msgid( LDAP *ld, int msgid )
+{
+ LDAPRequest *lr;
+
+ for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
+ if ( msgid == lr->lr_msgid ) {
+ break;
+ }
+ }
+
+ return( lr );
+}
diff --git a/usr/src/lib/libldap4/common/regex.c b/usr/src/lib/libldap4/common/regex.c
new file mode 100644
index 0000000000..a8e247bf40
--- /dev/null
+++ b/usr/src/lib/libldap4/common/regex.c
@@ -0,0 +1,922 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "portable.h"
+#include "stdio.h"
+#include "stdlib.h"
+
+#if defined( MACOS ) || defined( DOS ) || defined( _WIN32 ) || defined( NEED_BSDREGEX )
+#include "regex.h"
+
+/*
+ * regex - Regular expression pattern matching and replacement
+ *
+ * By: Ozan S. Yigit (oz)
+ * Dept. of Computer Science
+ * York University
+ *
+ * These routines are the PUBLIC DOMAIN equivalents of regex
+ * routines as found in 4.nBSD UN*X, with minor extensions.
+ *
+ * These routines are derived from various implementations found
+ * in software tools books, and Conroy's grep. They are NOT derived
+ * from licensed/restricted software.
+ * For more interesting/academic/complicated implementations,
+ * see Henry Spencer's regexp routines, or GNU Emacs pattern
+ * matching module.
+ *
+ * Modification history:
+ *
+ * $Log: regex.c,v $
+ * Revision 1.12 1996/04/25 16:20:59 mcs
+ * make re_exec() match "" with ".*" and similar patterns
+ * hopefully this change doesn't break anything else!
+ *
+ * Revision 1.11 1994/12/14 21:33:45 mcs
+ * use new NEED_BSDREGEX
+ * fix pmatch() prototype
+ *
+ * Revision 1.10 1994/12/12 18:16:39 mcs
+ * use on NetBSD
+ *
+ * Revision 1.9 1994/11/15 19:16:35 mcs
+ * add (CHAR) cast to make VisualC++ happy
+ *
+ * Revision 1.8 1994/11/08 21:14:32 mcs
+ * WIN32 changes
+ *
+ * Revision 1.7 1994/07/23 19:51:24 mcs
+ * use ANSI-style inline function parameters
+ *
+ * Revision 1.6 1993/10/18 01:52:32 tim
+ * include for VMS
+ *
+ * Revision 1.5 1993/09/28 21:37:54 mcs
+ * HP/UX needs the regex we include (not in its libc)
+ *
+ * Revision 1.4 1993/08/27 15:59:52 mcs
+ * use CHAR for deftab
+ *
+ * Revision 1.3 1993/08/27 15:49:47 mcs
+ * added missing 0 to octal constants
+ * use unsigned char for CHAR under DOS
+ *
+ * Revision 1.2 1993/08/27 14:57:48 mcs
+ * add proto. for pmatch
+ *
+ * Revision 1.1 1993/08/18 21:20:02 mcs
+ * Initial revision
+ *
+ * Revision 1.4 1991/10/17 03:56:42 oz
+ * miscellaneous changes, small cleanups etc.
+ *
+ * Revision 1.3 1989/04/01 14:18:09 oz
+ * Change all references to a dfa: this is actually an nfa.
+ *
+ * Revision 1.2 88/08/28 15:36:04 oz
+ * Use a complement bitmap to represent NCL.
+ * This removes the need to have seperate
+ * code in the pmatch case block - it is
+ * just CCL code now.
+ *
+ * Use the actual CCL code in the CLO
+ * section of pmatch. No need for a recursive
+ * pmatch call.
+ *
+ * Use a bitmap table to set char bits in an
+ * 8-bit chunk.
+ *
+ * Interfaces:
+ * re_comp: compile a regular expression into a NFA.
+ *
+ * char *re_comp(s)
+ * char *s;
+ *
+ * re_exec: execute the NFA to match a pattern.
+ *
+ * int re_exec(s)
+ * char *s;
+ *
+ * re_modw change re_exec's understanding of what a "word"
+ * looks like (for \< and \>) by adding into the
+ * hidden word-syntax table.
+ *
+ * void re_modw(s)
+ * char *s;
+ *
+ * re_subs: substitute the matched portions in a new string.
+ *
+ * int re_subs(src, dst)
+ * char *src;
+ * char *dst;
+ *
+ * re_fail: failure routine for re_exec.
+ *
+ * void re_fail(msg, op)
+ * char *msg;
+ * char op;
+ *
+ * Regular Expressions:
+ *
+ * [1] char matches itself, unless it is a special
+ * character (metachar): . \ [ ] * + ^ $
+ *
+ * [2] . matches any character.
+ *
+ * [3] \ matches the character following it, except
+ * when followed by a left or right round bracket,
+ * a digit 1 to 9 or a left or right angle bracket.
+ * (see [7], [8] and [9])
+ * It is used as an escape character for all
+ * other meta-characters, and itself. When used
+ * in a set ([4]), it is treated as an ordinary
+ * character.
+ *
+ * [4] [set] matches one of the characters in the set.
+ * If the first character in the set is "^",
+ * it matches a character NOT in the set, i.e.
+ * complements the set. A shorthand S-E is
+ * used to specify a set of characters S upto
+ * E, inclusive. The special characters "]" and
+ * "-" have no special meaning if they appear
+ * as the first chars in the set.
+ * examples: match:
+ *
+ * [a-z] any lowercase alpha
+ *
+ * [^]-] any char except ] and -
+ *
+ * [^A-Z] any char except uppercase
+ * alpha
+ *
+ * [a-zA-Z] any alpha
+ *
+ * [5] * any regular expression form [1] to [4], followed by
+ * closure char (*) matches zero or more matches of
+ * that form.
+ *
+ * [6] + same as [5], except it matches one or more.
+ *
+ * [7] a regular expression in the form [1] to [10], enclosed
+ * as \(form\) matches what form matches. The enclosure
+ * creates a set of tags, used for [8] and for
+ * pattern substution. The tagged forms are numbered
+ * starting from 1.
+ *
+ * [8] a \ followed by a digit 1 to 9 matches whatever a
+ * previously tagged regular expression ([7]) matched.
+ *
+ * [9] \< a regular expression starting with a \< construct
+ * \> and/or ending with a \> construct, restricts the
+ * pattern matching to the beginning of a word, and/or
+ * the end of a word. A word is defined to be a character
+ * string beginning and/or ending with the characters
+ * A-Z a-z 0-9 and _. It must also be preceded and/or
+ * followed by any character outside those mentioned.
+ *
+ * [10] a composite regular expression xy where x and y
+ * are in the form [1] to [10] matches the longest
+ * match of x followed by a match for y.
+ *
+ * [11] ^ a regular expression starting with a ^ character
+ * $ and/or ending with a $ character, restricts the
+ * pattern matching to the beginning of the line,
+ * or the end of line. [anchors] Elsewhere in the
+ * pattern, ^ and $ are treated as ordinary characters.
+ *
+ *
+ * Acknowledgements:
+ *
+ * HCR's Hugh Redelmeier has been most helpful in various
+ * stages of development. He convinced me to include BOW
+ * and EOW constructs, originally invented by Rob Pike at
+ * the University of Toronto.
+ *
+ * References:
+ * Software tools Kernighan & Plauger
+ * Software tools in Pascal Kernighan & Plauger
+ * Grep [rsx-11 C dist] David Conroy
+ * ed - text editor Un*x Programmer's Manual
+ * Advanced editing on Un*x B. W. Kernighan
+ * RegExp routines Henry Spencer
+ *
+ * Notes:
+ *
+ * This implementation uses a bit-set representation for character
+ * classes for speed and compactness. Each character is represented
+ * by one bit in a 128-bit block. Thus, CCL always takes a
+ * constant 16 bytes in the internal nfa, and re_exec does a single
+ * bit comparison to locate the character in the set.
+ *
+ * Examples:
+ *
+ * pattern: foo*.*
+ * compile: CHR f CHR o CLO CHR o END CLO ANY END END
+ * matches: fo foo fooo foobar fobar foxx ...
+ *
+ * pattern: fo[ob]a[rz]
+ * compile: CHR f CHR o CCL bitset CHR a CCL bitset END
+ * matches: fobar fooar fobaz fooaz
+ *
+ * pattern: foo\\+
+ * compile: CHR f CHR o CHR o CHR \ CLO CHR \ END END
+ * matches: foo\ foo\\ foo\\\ ...
+ *
+ * pattern: \(foo\)[1-3]\1 (same as foo[1-3]foo)
+ * compile: BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
+ * matches: foo1foo foo2foo foo3foo
+ *
+ * pattern: \(fo.*\)-\1
+ * compile: BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
+ * matches: foo-foo fo-fo fob-fob foobar-foobar ...
+ */
+
+#define MAXNFA 1024
+#define MAXTAG 10
+
+#define OKP 1
+#define NOP 0
+
+#define CHR 1
+#define ANY 2
+#define CCL 3
+#define BOL 4
+#define EOL 5
+#define BOT 6
+#define EOT 7
+#define BOW 8
+#define EOW 9
+#define REF 10
+#define CLO 11
+
+#define END 0
+
+/*
+ * The following defines are not meant to be changeable.
+ * They are for readability only.
+ */
+#define MAXCHR 128
+#define CHRBIT 8
+#define BITBLK MAXCHR/CHRBIT
+#define BLKIND 0170
+#define BITIND 07
+
+#define ASCIIB 0177
+
+#if defined( DOS ) || defined( _WIN32 ) || defined(SUN)
+typedef unsigned char CHAR;
+#else /* DOS */
+typedef /*unsigned*/ char CHAR;
+#endif /* DOS */
+
+static int tagstk[MAXTAG]; /* subpat tag stack..*/
+static CHAR nfa[MAXNFA]; /* automaton.. */
+static int sta = NOP; /* status of lastpat */
+
+static CHAR bittab[BITBLK]; /* bit table for CCL */
+ /* pre-set bits... */
+static CHAR bitarr[] = {1,2,4,8,16,32,64,128};
+
+#ifdef DEBUG
+static void nfadump(CHAR *);
+void symbolic(char *);
+#endif
+
+static void
+chset(CHAR c)
+{
+ bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
+}
+
+#define badpat(x) (*nfa = END, x)
+#define store(x) *mp++ = x
+
+char *
+re_comp( char *pat )
+{
+ register char *p; /* pattern pointer */
+ register CHAR *mp=nfa; /* nfa pointer */
+ register CHAR *lp; /* saved pointer.. */
+ register CHAR *sp=nfa; /* another one.. */
+
+ register int tagi = 0; /* tag stack index */
+ register int tagc = 1; /* actual tag count */
+
+ register int n;
+ register CHAR mask; /* xor mask -CCL/NCL */
+ int c1, c2;
+
+ if (!pat || !*pat)
+ if (sta)
+ return 0;
+ else
+ return badpat("No previous regular expression");
+ sta = NOP;
+
+ for (p = pat; *p; p++) {
+ lp = mp;
+ switch(*p) {
+
+ case '.': /* match any char.. */
+ store(ANY);
+ break;
+
+ case '^': /* match beginning.. */
+ if (p == pat)
+ store(BOL);
+ else {
+ store(CHR);
+ store(*p);
+ }
+ break;
+
+ case '$': /* match endofline.. */
+ if (!*(p+1))
+ store(EOL);
+ else {
+ store(CHR);
+ store(*p);
+ }
+ break;
+
+ case '[': /* match char class..*/
+ store(CCL);
+
+ if (*++p == '^') {
+ mask = 0377;
+ p++;
+ }
+ else
+ mask = 0;
+
+ if (*p == '-') /* real dash */
+ chset(*p++);
+ if (*p == ']') /* real brac */
+ chset(*p++);
+ while (*p && *p != ']') {
+ if (*p == '-' && *(p+1) && *(p+1) != ']') {
+ p++;
+ c1 = *(p-2) + 1;
+ c2 = *p++;
+ while (c1 <= c2)
+ chset((CHAR)c1++);
+ }
+#ifdef EXTEND
+ else if (*p == '\\' && *(p+1)) {
+ p++;
+ chset(*p++);
+ }
+#endif
+ else
+ chset(*p++);
+ }
+ if (!*p)
+ return badpat("Missing ]");
+
+ for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
+ store(mask ^ bittab[n]);
+
+ break;
+
+ case '*': /* match 0 or more.. */
+ case '+': /* match 1 or more.. */
+ if (p == pat)
+ return badpat("Empty closure");
+ lp = sp; /* previous opcode */
+ if (*lp == CLO) /* equivalence.. */
+ break;
+ switch(*lp) {
+
+ case BOL:
+ case BOT:
+ case EOT:
+ case BOW:
+ case EOW:
+ case REF:
+ return badpat("Illegal closure");
+ default:
+ break;
+ }
+
+ if (*p == '+')
+ for (sp = mp; lp < sp; lp++)
+ store(*lp);
+
+ store(END);
+ store(END);
+ sp = mp;
+ while (--mp > lp)
+ *mp = mp[-1];
+ store(CLO);
+ mp = sp;
+ break;
+
+ case '\\': /* tags, backrefs .. */
+ switch(*++p) {
+
+ case '(':
+ if (tagc < MAXTAG) {
+ tagstk[++tagi] = tagc;
+ store(BOT);
+ store(tagc++);
+ }
+ else
+ return badpat("Too many \\(\\) pairs");
+ break;
+ case ')':
+ if (*sp == BOT)
+ return badpat("Null pattern inside \\(\\)");
+ if (tagi > 0) {
+ store(EOT);
+ store(tagstk[tagi--]);
+ }
+ else
+ return badpat("Unmatched \\)");
+ break;
+ case '<':
+ store(BOW);
+ break;
+ case '>':
+ if (*sp == BOW)
+ return badpat("Null pattern inside \\<\\>");
+ store(EOW);
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = *p-'0';
+ if (tagi > 0 && tagstk[tagi] == n)
+ return badpat("Cyclical reference");
+ if (tagc > n) {
+ store(REF);
+ store(n);
+ }
+ else
+ return badpat("Undetermined reference");
+ break;
+#ifdef EXTEND
+ case 'b':
+ store(CHR);
+ store('\b');
+ break;
+ case 'n':
+ store(CHR);
+ store('\n');
+ break;
+ case 'f':
+ store(CHR);
+ store('\f');
+ break;
+ case 'r':
+ store(CHR);
+ store('\r');
+ break;
+ case 't':
+ store(CHR);
+ store('\t');
+ break;
+#endif
+ default:
+ store(CHR);
+ store(*p);
+ }
+ break;
+
+ default : /* an ordinary char */
+ store(CHR);
+ store(*p);
+ break;
+ }
+ sp = lp;
+ }
+ if (tagi > 0)
+ return badpat("Unmatched \\(");
+ store(END);
+ sta = OKP;
+ return 0;
+}
+
+
+static char *bol;
+char *bopat[MAXTAG];
+char *eopat[MAXTAG];
+#ifdef NEEDPROTOS
+static char *pmatch( char *lp, CHAR *ap );
+#else /* NEEDPROTOS */
+static char *pmatch();
+#endif /* NEEDPROTOS */
+
+/*
+ * re_exec:
+ * execute nfa to find a match.
+ *
+ * special cases: (nfa[0])
+ * BOL
+ * Match only once, starting from the
+ * beginning.
+ * CHR
+ * First locate the character without
+ * calling pmatch, and if found, call
+ * pmatch for the remaining string.
+ * END
+ * re_comp failed, poor luser did not
+ * check for it. Fail fast.
+ *
+ * If a match is found, bopat[0] and eopat[0] are set
+ * to the beginning and the end of the matched fragment,
+ * respectively.
+ *
+ */
+
+int
+re_exec( char *lp )
+{
+ register char c;
+ register char *ep = 0;
+ register CHAR *ap = nfa;
+
+ bol = lp;
+
+ bopat[0] = 0;
+ bopat[1] = 0;
+ bopat[2] = 0;
+ bopat[3] = 0;
+ bopat[4] = 0;
+ bopat[5] = 0;
+ bopat[6] = 0;
+ bopat[7] = 0;
+ bopat[8] = 0;
+ bopat[9] = 0;
+
+ switch(*ap) {
+
+ case BOL: /* anchored: match from BOL only */
+ ep = pmatch(lp,ap);
+ break;
+ case CHR: /* ordinary char: locate it fast */
+ c = *(ap+1);
+ while (*lp && *lp != c)
+ lp++;
+ if (!*lp) /* if EOS, fail, else fall thru. */
+ return 0;
+ default: /* regular matching all the way. */
+ do {
+ if ((ep = pmatch(lp,ap)))
+ break;
+ lp++;
+ } while (*lp);
+
+ break;
+ case END: /* munged automaton. fail always */
+ return 0;
+ }
+ if (!ep)
+ return 0;
+
+ bopat[0] = lp;
+ eopat[0] = ep;
+ return 1;
+}
+
+/*
+ * pmatch: internal routine for the hard part
+ *
+ * This code is partly snarfed from an early grep written by
+ * David Conroy. The backref and tag stuff, and various other
+ * innovations are by oz.
+ *
+ * special case optimizations: (nfa[n], nfa[n+1])
+ * CLO ANY
+ * We KNOW .* will match everything upto the
+ * end of line. Thus, directly go to the end of
+ * line, without recursive pmatch calls. As in
+ * the other closure cases, the remaining pattern
+ * must be matched by moving backwards on the
+ * string recursively, to find a match for xy
+ * (x is ".*" and y is the remaining pattern)
+ * where the match satisfies the LONGEST match for
+ * x followed by a match for y.
+ * CLO CHR
+ * We can again scan the string forward for the
+ * single char and at the point of failure, we
+ * execute the remaining nfa recursively, same as
+ * above.
+ *
+ * At the end of a successful match, bopat[n] and eopat[n]
+ * are set to the beginning and end of subpatterns matched
+ * by tagged expressions (n = 1 to 9).
+ *
+ */
+
+#ifndef re_fail
+extern void re_fail();
+#endif /* re_fail */
+
+/*
+ * character classification table for word boundary operators BOW
+ * and EOW. the reason for not using ctype macros is that we can
+ * let the user add into our own table. see re_modw. This table
+ * is not in the bitset form, since we may wish to extend it in the
+ * future for other character classifications.
+ *
+ * TRUE for 0-9 A-Z a-z _
+ */
+static char chrtyp[MAXCHR] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 0
+ };
+
+#define inascii(x) (0177&(x))
+#define iswordc(x) chrtyp[inascii(x)]
+#define isinset(x,y) ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
+
+/*
+ * skip values for CLO XXX to skip past the closure
+ */
+
+#define ANYSKIP 2 /* [CLO] ANY END ... */
+#define CHRSKIP 3 /* [CLO] CHR chr END ... */
+#define CCLSKIP 18 /* [CLO] CCL 16bytes END ... */
+
+static char *
+pmatch( char *lp, CHAR *ap)
+{
+ register int op, c, n;
+ register char *e; /* extra pointer for CLO */
+ register char *bp; /* beginning of subpat.. */
+ register char *ep; /* ending of subpat.. */
+ char *are; /* to save the line ptr. */
+
+ while ((op = *ap++) != END)
+ switch(op) {
+
+ case CHR:
+ if (*lp++ != *ap++)
+ return 0;
+ break;
+ case ANY:
+ if (!*lp++)
+ return 0;
+ break;
+ case CCL:
+ c = *lp++;
+ if (!isinset(ap,c))
+ return 0;
+ ap += BITBLK;
+ break;
+ case BOL:
+ if (lp != bol)
+ return 0;
+ break;
+ case EOL:
+ if (*lp)
+ return 0;
+ break;
+ case BOT:
+ bopat[*ap++] = lp;
+ break;
+ case EOT:
+ eopat[*ap++] = lp;
+ break;
+ case BOW:
+ if (lp!=bol && iswordc(lp[-1]) || !iswordc(*lp))
+ return 0;
+ break;
+ case EOW:
+ if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp))
+ return 0;
+ break;
+ case REF:
+ n = *ap++;
+ bp = bopat[n];
+ ep = eopat[n];
+ while (bp < ep)
+ if (*bp++ != *lp++)
+ return 0;
+ break;
+ case CLO:
+ are = lp;
+ switch(*ap) {
+
+ case ANY:
+ while (*lp)
+ lp++;
+ n = ANYSKIP;
+ break;
+ case CHR:
+ c = *(ap+1);
+ while (*lp && c == *lp)
+ lp++;
+ n = CHRSKIP;
+ break;
+ case CCL:
+ while ((c = *lp) && isinset(ap+1,c))
+ lp++;
+ n = CCLSKIP;
+ break;
+ default:
+ re_fail("closure: bad nfa.", *ap);
+ return 0;
+ }
+
+ ap += n;
+
+ while (lp >= are) {
+ if (e = pmatch(lp, ap))
+ return e;
+ --lp;
+ }
+ return 0;
+ default:
+ re_fail("re_exec: bad nfa.", op);
+ return 0;
+ }
+ return lp;
+}
+
+/*
+ * re_modw:
+ * add new characters into the word table to change re_exec's
+ * understanding of what a word should look like. Note that we
+ * only accept additions into the word definition.
+ *
+ * If the string parameter is 0 or null string, the table is
+ * reset back to the default containing A-Z a-z 0-9 _. [We use
+ * the compact bitset representation for the default table]
+ */
+
+static CHAR deftab[16] = {
+ 0, 0, 0, 0, 0, 0, 0377, 003, 0376, 0377, 0377, 0207,
+ 0376, 0377, 0377, 007
+};
+
+void
+re_modw( char *s )
+{
+ register int i;
+
+ if (!s || !*s) {
+ for (i = 0; i < MAXCHR; i++)
+ if (!isinset(deftab,i))
+ iswordc(i) = 0;
+ }
+ else
+ while(*s)
+ iswordc(*s++) = 1;
+}
+
+/*
+ * re_subs:
+ * substitute the matched portions of the src in dst.
+ *
+ * & substitute the entire matched pattern.
+ *
+ * \digit substitute a subpattern, with the given tag number.
+ * Tags are numbered from 1 to 9. If the particular
+ * tagged subpattern does not exist, null is substituted.
+ */
+int
+re_subs( char *src, char *dst)
+{
+ register char c;
+ register int pin;
+ register char *bp;
+ register char *ep;
+
+ if (!*src || !bopat[0])
+ return 0;
+
+ while (c = *src++) {
+ switch(c) {
+
+ case '&':
+ pin = 0;
+ break;
+
+ case '\\':
+ c = *src++;
+ if (c >= '0' && c <= '9') {
+ pin = c - '0';
+ break;
+ }
+
+ default:
+ *dst++ = c;
+ continue;
+ }
+
+ if ((bp = bopat[pin]) && (ep = eopat[pin])) {
+ while (*bp && bp < ep)
+ *dst++ = *bp++;
+ if (bp < ep)
+ return 0;
+ }
+ }
+ *dst = (char) 0;
+ return 1;
+}
+
+#ifdef DEBUG
+/*
+ * symbolic - produce a symbolic dump of the nfa
+ */
+void
+symbolic( char *s )
+{
+ (void) printf("pattern: %s\n", s);
+ (void) printf("nfacode:\n");
+ nfadump(nfa);
+}
+
+static void
+nfadump( CHAR *ap)
+{
+ register int n;
+
+ while (*ap != END)
+ switch(*ap++) {
+ case CLO:
+ (void) printf("CLOSURE");
+ nfadump(ap);
+ switch(*ap) {
+ case CHR:
+ n = CHRSKIP;
+ break;
+ case ANY:
+ n = ANYSKIP;
+ break;
+ case CCL:
+ n = CCLSKIP;
+ break;
+ }
+ ap += n;
+ break;
+ case CHR:
+ (void) printf("\tCHR %c\n",*ap++);
+ break;
+ case ANY:
+ (void) printf("\tANY .\n");
+ break;
+ case BOL:
+ (void) printf("\tBOL -\n");
+ break;
+ case EOL:
+ (void) printf("\tEOL -\n");
+ break;
+ case BOT:
+ (void) printf("BOT: %d\n",*ap++);
+ break;
+ case EOT:
+ (void) printf("EOT: %d\n",*ap++);
+ break;
+ case BOW:
+ (void) printf("BOW\n");
+ break;
+ case EOW:
+ (void) printf("EOW\n");
+ break;
+ case REF:
+ (void) printf("REF: %d\n",*ap++);
+ break;
+ case CCL:
+ (void) printf("\tCCL [");
+ for (n = 0; n < MAXCHR; n++)
+ if (isinset(ap,(CHAR)n)) {
+ if (n < ' ')
+ (void) printf("^%c", n ^ 0x040);
+ else
+ (void) printf("%c", n);
+ }
+ (void) printf("]\n");
+ ap += BITBLK;
+ break;
+ default:
+ (void) printf("bad nfa. opcode %o\n", ap[-1]);
+ exit(1);
+ break;
+ }
+}
+#endif
+#endif /* MACOS or DOS or NEED_BSDREGEX */
diff --git a/usr/src/lib/libldap4/common/rename.c b/usr/src/lib/libldap4/common/rename.c
new file mode 100644
index 0000000000..b7f530adb5
--- /dev/null
+++ b/usr/src/lib/libldap4/common/rename.c
@@ -0,0 +1,176 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include "macos.h"
+#endif /* MACOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+BerElement * ldap_build_rename_req ( LDAP *ld, char *dn, char *newrdn, char *newparent,
+ int deleteoldrdn, LDAPControl **serverctrls)
+{
+ BerElement *ber;
+ int rc;
+
+ /*
+ * A modify rdn request looks like this:
+ * ModifyRDNRequest ::= SEQUENCE {
+ * entry LDAPDN,
+ * newrdn RelativeLDAPDN,
+ * deleteoldrdn BOOLEAN
+ * newSuperior [0] LDAPDN OPTIONAL
+ * }
+ */
+
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ return( NULLBER );
+ }
+
+ if ( ber_printf( ber, "{it{ssb", ++ld->ld_msgid, LDAP_REQ_MODRDN, dn,
+ newrdn, deleteoldrdn ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ if (newparent) {
+ if ( ber_printf( ber, "ts}", LDAP_TAG_NEWPARENT, newparent) == -1){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ } else if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ return (ber);
+}
+
+/* ldap_rename - Modify the name of an entry.
+ * Parameters :
+ * ld : LDAP descriptor.
+ * dn : DN of the object to rename.
+ * newrdn : New RDN to give to the entry.
+ * newparent : the parent or superior entry. If NULL only RDN is changed.
+ * "" means the root DN.
+ * deleteoldrdn : Boolean to indicate wether or not to remove the old RDN value.
+ * serverctrls : List of Server controls.
+ * clientctrls : List of client controls.
+ * msgidp : the msg id return if renamed succeded.
+ */
+
+int ldap_rename(LDAP *ld, char *dn, char *newrdn, char *newparent, int deleteoldrdn,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp)
+{
+ BerElement *ber;
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 87, "ldap_rename\n"), 0, 0, 0 );
+
+ if ((ber = ldap_build_rename_req(ld, dn, newrdn, newparent, deleteoldrdn, serverctrls)) == NULLBER){
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS)
+ rv = LDAP_OTHER;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber );
+ if (rv == -1) {
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS){
+ rv = LDAP_OTHER;
+ }
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+ *msgidp = rv;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_SUCCESS);
+
+}
+
+
+int ldap_rename_s(LDAP *ld, char *dn, char *newrdn, char *newparent, int deleteoldrdn,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls)
+{
+ int msgid;
+ int retcode = LDAP_SUCCESS;
+ LDAPMessage *res;
+
+ if ((retcode = ldap_rename(ld, dn, newrdn, newparent, deleteoldrdn, serverctrls, clientctrls, &msgid)) != LDAP_SUCCESS)
+ return (retcode);
+ if (ldap_result(ld, msgid, 1, (struct timeval *)NULL, &res ) == -1)
+ return (ld->ld_errno );
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ retcode = ldap_parse_result( ld, res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
+ &ld->ld_referrals, &ld->ld_ret_ctrls, 1);
+ if (retcode == LDAP_SUCCESS)
+ retcode = ld->ld_errno;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (retcode);
+}
diff --git a/usr/src/lib/libldap4/common/request.c b/usr/src/lib/libldap4/common/request.c
new file mode 100644
index 0000000000..7b0af4c0f7
--- /dev/null
+++ b/usr/src/lib/libldap4/common/request.c
@@ -0,0 +1,779 @@
+/*
+ * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * request.c - sending of ldap requests; handling of referrals
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include <time.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include "msdos.h"
+#include <time.h>
+#include <stdlib.h>
+#ifdef PCNFS
+#include <tklib.h>
+#include <tk_errno.h>
+#include <bios.h>
+#endif /* PCNFS */
+#ifdef NCSA
+#include "externs.h"
+#endif /* NCSA */
+#else /* DOS */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#ifdef _AIX
+#include <sys/select.h>
+#endif /* _AIX */
+#include "portable.h"
+#endif /* DOS */
+#endif /* MACOS */
+#ifdef VMS
+#include "ucx_select.h"
+#endif
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifdef USE_SYSCONF
+#include <unistd.h>
+#endif /* USE_SYSCONF */
+
+#ifdef NEEDPROTOS
+static LDAPConn *find_connection( LDAP *ld, LDAPServer *srv, int any );
+static void use_connection( LDAP *ld, LDAPConn *lc );
+static void free_servers( LDAPServer *srvlist );
+#else /* NEEDPROTOS */
+static LDAPConn *find_connection();
+static void use_connection();
+static void free_servers();
+#endif /* NEEDPROTOS */
+
+
+#ifdef LDAP_DNS
+#ifdef NEEDPROTOS
+static LDAPServer *dn2servers( LDAP *ld, char *dn );
+#else /* NEEDPROTOS */
+static LDAPServer *dn2servers();
+#endif /* NEEDPROTOS */
+#endif /* LDAP_DNS */
+
+
+BerElement *
+alloc_ber_with_options( LDAP *ld )
+{
+ BerElement *ber;
+
+ if (( ber = ber_alloc_t( ld->ld_lberoptions )) == NULLBER ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+#ifdef STR_TRANSLATION
+ } else {
+ set_ber_options( ld, ber );
+#endif /* STR_TRANSLATION */
+ }
+
+ return( ber );
+}
+
+
+void
+set_ber_options( LDAP *ld, BerElement *ber )
+{
+ ber->ber_options = ld->ld_lberoptions;
+#ifdef STR_TRANSLATION
+ if (( ld->ld_lberoptions & LBER_TRANSLATE_STRINGS ) != 0 ) {
+ ber_set_string_translators( ber,
+ ld->ld_lber_encode_translate_proc,
+ ld->ld_lber_decode_translate_proc );
+ }
+#endif /* STR_TRANSLATION */
+}
+
+
+int
+send_initial_request( LDAP *ld, unsigned int msgtype, char *dn,
+ BerElement *ber )
+{
+ LDAPServer *servers;
+ int rv;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 209, "send_initial_request\n"), 0, 0, 0 );
+
+#ifdef LDAP_DNS
+ if (( ld->ld_options & LDAP_OPT_DNS ) != 0 && ldap_is_dns_dn( dn )) {
+ if (( servers = dn2servers( ld, dn )) == NULL ) {
+ ber_free( ber, 1 );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+#ifdef LDAP_DEBUG
+ if ( ldap_debug & LDAP_DEBUG_TRACE ) {
+ LDAPServer *srv;
+
+ for ( srv = servers; srv != NULL;
+ srv = srv->lsrv_next ) {
+ fprintf( stderr,
+ "LDAP server %s: dn %s, port %d\n",
+ srv->lsrv_host, ( srv->lsrv_dn == NULL ) ?
+ "(default)" : srv->lsrv_dn,
+ srv->lsrv_port );
+ }
+ }
+#endif /* LDAP_DEBUG */
+ } else {
+#endif /* LDAP_DNS */
+ /*
+ * use of DNS is turned off or this is an X.500 DN...
+ * use our default connection
+ */
+ servers = NULL;
+#ifdef LDAP_DNS
+ }
+#endif /* LDAP_DNS */
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ rv = send_server_request( ld, ber, ld->ld_msgid, NULL, servers,
+ NULL, 0 );
+ return ( rv );
+}
+
+int
+send_server_request( LDAP *ld, BerElement *ber, int msgid, LDAPRequest
+ *parentreq, LDAPServer *srvlist, LDAPConn *lc, int bind )
+{
+ LDAPRequest *lr;
+ int err;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 210, "send_server_request\n"), 0, 0, 0 );
+
+ ld->ld_errno = LDAP_SUCCESS; /* optimistic */
+ /* Be optimistic : increment parentreq initially.
+ If it fails we must decrement it */
+ if (parentreq != NULL){
+ parentreq->lr_outrefcnt++;
+ }
+
+ if ( lc == NULL ) {
+ if ( srvlist == NULL ) {
+ if (ld->ld_defconn == NULL){ /* Not connected yet on the default connection, ie init was called not open */
+ if ((err = open_default_ldap_connection(ld)) != LDAP_SUCCESS){
+ ld->ld_errno = err;
+ ber_free(ber, 1);
+ if (parentreq != NULL){
+ parentreq->lr_outrefcnt--;
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+ }
+
+ lc = ld->ld_defconn;
+ } else {
+ if (( lc = find_connection( ld, srvlist, 1 )) ==
+ NULL ) {
+ lc = new_connection( ld, &srvlist, 0, 1, bind );
+ }
+ free_servers( srvlist );
+ }
+ }
+
+ if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) {
+ ber_free( ber, 1 );
+ if ( ld->ld_errno == LDAP_SUCCESS ) {
+ ld->ld_errno = LDAP_SERVER_DOWN;
+ }
+ if (parentreq != NULL){
+ parentreq->lr_outrefcnt--;
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+ use_connection( ld, lc );
+ if (( lr = (LDAPRequest *)calloc( 1, sizeof( LDAPRequest ))) ==
+ NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ free_connection( ld, lc, 0, 0 );
+ ber_free( ber, 1 );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+ lr->lr_msgid = msgid;
+ lr->lr_status = LDAP_REQST_INPROGRESS;
+ lr->lr_res_errno = LDAP_SUCCESS; /* optimistic */
+ lr->lr_ber = ber;
+ lr->lr_conn = lc;
+ if ( parentreq != NULL ) { /* sub-request */
+/* ++parentreq->lr_outrefcnt; */
+ lr->lr_origid = parentreq->lr_origid;
+ lr->lr_parentcnt = parentreq->lr_parentcnt + 1;
+ lr->lr_parent = parentreq;
+ lr->lr_refnext = parentreq->lr_refnext;
+ parentreq->lr_refnext = lr;
+ } else { /* original request */
+ lr->lr_origid = lr->lr_msgid;
+ }
+
+ if (( lr->lr_next = ld->ld_requests ) != NULL ) {
+ lr->lr_next->lr_prev = lr;
+ }
+ ld->ld_requests = lr;
+ lr->lr_prev = NULL;
+
+ if ( ber_flush( lc->lconn_sb, ber, 0 ) != 0 ) {
+#ifdef notyet
+ extern int errno;
+
+ if ( errno == EWOULDBLOCK ) {
+ /* need to continue write later */
+ lr->lr_status = LDAP_REQST_WRITING;
+ mark_select_write( ld, lc->lconn_sb );
+ } else {
+#else /* notyet */
+ ld->ld_errno = LDAP_SERVER_DOWN;
+ free_request( ld, lr );
+ free_connection( ld, lc, 0, 0 );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+#endif /* notyet */
+#ifdef notyet
+ }
+#endif /* notyet */
+ } else {
+ if ( parentreq == NULL ) {
+ ber->ber_end = ber->ber_ptr;
+ ber->ber_ptr = ber->ber_buf;
+ }
+
+ /* sent -- waiting for a response */
+ mark_select_read( ld, lc->lconn_sb );
+ }
+
+ ld->ld_errno = LDAP_SUCCESS;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( msgid );
+}
+
+
+LDAPConn *
+new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
+ int connect, int bind )
+{
+ LDAPConn *lc;
+ LDAPServer *prevsrv, *srv;
+ Sockbuf *sb;
+
+ /*
+ * make a new LDAP server connection
+ * XXX open connection synchronously for now
+ */
+ if (( lc = (LDAPConn *)calloc( 1, sizeof( LDAPConn ))) == NULL ||
+ ( !use_ldsb && ( sb = (Sockbuf *)calloc( 1, sizeof( Sockbuf )))
+ == NULL )) {
+ if ( lc != NULL ) {
+ free( (char *)lc );
+ }
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( NULL );
+ }
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ lc->lconn_sb = ( use_ldsb ) ? &ld->ld_sb : sb;
+
+ if ( connect ) {
+ prevsrv = NULL;
+
+ for ( srv = *srvlistp; srv != NULL; srv = srv->lsrv_next ) {
+ if ( open_ldap_connection( ld, lc->lconn_sb,
+ srv->lsrv_host, srv->lsrv_port,
+ &lc->lconn_krbinstance, 0 ) != -1 ) {
+ break;
+ }
+ prevsrv = srv;
+ }
+
+ if ( srv == NULL ) {
+ if ( !use_ldsb ) {
+ free( (char *)lc->lconn_sb );
+ }
+ free( (char *)lc );
+ ld->ld_errno = LDAP_SERVER_DOWN;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( NULL );
+ }
+
+ if ( prevsrv == NULL ) {
+ *srvlistp = srv->lsrv_next;
+ } else {
+ prevsrv->lsrv_next = srv->lsrv_next;
+ }
+ lc->lconn_server = srv;
+ }
+
+ lc->lconn_status = LDAP_CONNST_CONNECTED;
+ lc->lconn_next = ld->ld_conns;
+ ld->ld_conns = lc;
+
+ /*
+ * XXX for now, we always do a synchronous bind. This will have
+ * to change in the long run...
+ */
+ if ( bind ) {
+ int err, freepasswd, authmethod;
+ char *binddn, *passwd;
+ LDAPConn *savedefconn;
+
+ freepasswd = err = 0;
+
+ if ( ld->ld_version == LDAP_VERSION3 && ld->ld_rebindproc == NULL){
+ /* Nothing to do */
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1280, "new_connection: bind no needed with ldapv3\n"), 0,0,0);
+ } else {
+ if ( ld->ld_rebindproc == NULL ) {
+ binddn = passwd = "";
+ authmethod = LDAP_AUTH_SIMPLE;
+ } else {
+ if (( err = (*ld->ld_rebindproc)( ld, &binddn, &passwd,
+ &authmethod, 0, ld->ld_rebind_extra_arg )) == LDAP_SUCCESS ) {
+ freepasswd = 1;
+ } else {
+ ld->ld_errno = err;
+ err = -1;
+ }
+ }
+
+ if ( err == 0 ) {
+ savedefconn = ld->ld_defconn;
+ ld->ld_defconn = lc;
+ ++lc->lconn_refcnt; /* avoid premature free */
+
+ if ( ldap_bind_s( ld, binddn, passwd, authmethod ) !=
+ LDAP_SUCCESS ) {
+ err = -1;
+ }
+ --lc->lconn_refcnt;
+ ld->ld_defconn = savedefconn;
+ }
+
+ if ( freepasswd ) {
+ (*ld->ld_rebindproc)( ld, &binddn, &passwd,
+ &authmethod, 1, ld->ld_rebind_extra_arg );
+ }
+
+ if ( err != 0 ) {
+ free_connection( ld, lc, 1, 0 );
+ lc = NULL;
+ }
+ }
+ }
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( lc );
+}
+
+
+static LDAPConn *
+find_connection( LDAP *ld, LDAPServer *srv, int any )
+/*
+ * return an existing connection (if any) to the server srv
+ * if "any" is non-zero, check for any server in the "srv" chain
+ */
+{
+ LDAPConn *lc;
+ LDAPServer *ls;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
+ for ( ls = srv; ls != NULL; ls = ls->lsrv_next ) {
+ if ( lc->lconn_server->lsrv_host != NULL &&
+ ls->lsrv_host != NULL && strcasecmp(
+ ls->lsrv_host, lc->lconn_server->lsrv_host ) == 0
+ && ls->lsrv_port == lc->lconn_server->lsrv_port ) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( lc );
+ }
+ if ( !any ) {
+ break;
+ }
+ }
+ }
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( NULL );
+}
+
+
+
+static void
+use_connection( LDAP *ld, LDAPConn *lc )
+{
+ ++lc->lconn_refcnt;
+ lc->lconn_lastused = time( 0 );
+}
+
+
+void
+free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
+{
+ LDAPConn *tmplc, *prevlc;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 211, "free_connection\n"), 0, 0, 0 );
+
+ if ( force || --lc->lconn_refcnt <= 0 ) {
+ if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
+ mark_select_clear( ld, lc->lconn_sb );
+ if ( unbind ) {
+ send_unbind( ld, lc->lconn_sb );
+ }
+ close_ldap_connection( lc->lconn_sb );
+ if ( lc->lconn_sb->sb_ber.ber_buf != NULL ) {
+ free( lc->lconn_sb->sb_ber.ber_buf );
+ lc->lconn_sb->sb_ber.ber_buf = NULL;
+ }
+ }
+ prevlc = NULL;
+ for ( tmplc = ld->ld_conns; tmplc != NULL;
+ tmplc = tmplc->lconn_next ) {
+ if ( tmplc == lc ) {
+ if ( prevlc == NULL ) {
+ ld->ld_conns = tmplc->lconn_next;
+ } else {
+ prevlc->lconn_next = tmplc->lconn_next;
+ }
+ break;
+ }
+ }
+ free_servers( lc->lconn_server );
+ if ( lc->lconn_krbinstance != NULL ) {
+ free( lc->lconn_krbinstance );
+ }
+ if ( lc->lconn_sb != &ld->ld_sb ) {
+ free( (char *)lc->lconn_sb );
+ }
+ free( lc );
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 212, "free_connection: actually freed\n"),
+ 0, 0, 0 );
+ } else {
+ lc->lconn_lastused = time( 0 );
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 213, "free_connection: refcnt %d\n"),
+ lc->lconn_refcnt, 0, 0 );
+ }
+}
+
+
+#ifdef LDAP_DEBUG
+void
+dump_connection( LDAP *ld, LDAPConn *lconns, int all )
+{
+ LDAPConn *lc;
+
+ fprintf( stderr, "** Connection%s:\n", all ? "s" : "" );
+ for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
+ if ( lc->lconn_server != NULL ) {
+ fprintf( stderr, "* host: %s port: %d%s\n",
+ ( lc->lconn_server->lsrv_host == NULL ) ? "(null)"
+ : lc->lconn_server->lsrv_host,
+ lc->lconn_server->lsrv_port, ( lc->lconn_sb ==
+ &ld->ld_sb ) ? " (default)" : "" );
+ }
+ fprintf( stderr, " refcnt: %d status: %s\n", lc->lconn_refcnt,
+ ( lc->lconn_status == LDAP_CONNST_NEEDSOCKET ) ?
+ "NeedSocket" : ( lc->lconn_status ==
+ LDAP_CONNST_CONNECTING ) ? "Connecting" : "Connected" );
+ fprintf( stderr, " last used: %s\n",
+ ctime( &lc->lconn_lastused ));
+ if ( !all ) {
+ break;
+ }
+ }
+}
+
+
+void
+dump_requests_and_responses( LDAP *ld )
+{
+ LDAPRequest *lr;
+ LDAPMessage *lm, *l;
+
+ fprintf( stderr, "** Outstanding Requests:\n" );
+ if (( lr = ld->ld_requests ) == NULL ) {
+ fprintf( stderr, " Empty\n" );
+ }
+ for ( ; lr != NULL; lr = lr->lr_next ) {
+ fprintf( stderr, " * msgid %d, origid %d, status %s\n",
+ lr->lr_msgid, lr->lr_origid, ( lr->lr_status ==
+ LDAP_REQST_INPROGRESS ) ? "InProgress" :
+ ( lr->lr_status == LDAP_REQST_CHASINGREFS ) ? "ChasingRefs" :
+ ( lr->lr_status == LDAP_REQST_NOTCONNECTED ) ? "NotConnected" :
+ "Writing" );
+ fprintf( stderr, " outstanding referrals %d, parent count %d\n",
+ lr->lr_outrefcnt, lr->lr_parentcnt );
+ }
+
+ fprintf( stderr, "** Response Queue:\n" );
+#ifdef _REENTRANT
+ LOCK_RESPONSE(ld);
+#endif
+ if (( lm = ld->ld_responses ) == NULLMSG ) {
+ fprintf( stderr, " Empty\n" );
+ }
+ for ( ; lm != NULLMSG; lm = lm->lm_next ) {
+ fprintf( stderr, " * msgid %d, type %d\n",
+ lm->lm_msgid, lm->lm_msgtype );
+ if (( l = lm->lm_chain ) != NULL ) {
+ fprintf( stderr, " chained responses:\n" );
+ for ( ; l != NULLMSG; l = l->lm_chain ) {
+ fprintf( stderr,
+ " * msgid %d, type %d\n",
+ l->lm_msgid, l->lm_msgtype );
+ }
+ }
+ }
+#ifdef _REENTRANT
+ UNLOCK_RESPONSE(ld);
+#endif
+}
+#endif /* LDAP_DEBUG */
+
+
+void
+free_request( LDAP *ld, LDAPRequest *lr )
+{
+ LDAPRequest *tmplr, *nextlr;
+ int i;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 214, "free_request (origid %1$d, msgid %2$d)\n"),
+ lr->lr_origid, lr->lr_msgid, 0 );
+
+ if ( lr->lr_parent != NULL ) {
+ --lr->lr_parent->lr_outrefcnt;
+ } else {
+ /* free all referrals (child requests) */
+ for ( tmplr = lr->lr_refnext; tmplr != NULL; tmplr = nextlr ) {
+ nextlr = tmplr->lr_refnext;
+ free_request( ld, tmplr );
+ }
+ }
+
+ if ( lr->lr_prev == NULL ) {
+ ld->ld_requests = lr->lr_next;
+ } else {
+ lr->lr_prev->lr_next = lr->lr_next;
+ }
+
+ if ( lr->lr_next != NULL ) {
+ lr->lr_next->lr_prev = lr->lr_prev;
+ }
+
+ if ( lr->lr_ber != NULL ) {
+ ber_free( lr->lr_ber, 1 );
+ }
+
+ if ( lr->lr_res_error != NULL ) {
+ free( lr->lr_res_error );
+ }
+
+ if ( lr->lr_res_matched != NULL ) {
+ free( lr->lr_res_matched );
+ }
+
+ if ( lr->lr_ref_tofollow != NULL ) {
+ for (i= 0; lr->lr_ref_tofollow[i] != NULL; i++)
+ free(lr->lr_ref_tofollow[i]);
+ free(lr->lr_ref_tofollow);
+ }
+ if ( lr->lr_ref_unfollowed != NULL ) {
+ for (i= 0; lr->lr_ref_unfollowed[i] != NULL; i++)
+ free(lr->lr_ref_unfollowed[i]);
+ free(lr->lr_ref_unfollowed);
+ }
+ if ( lr->lr_ref_followed != NULL ) {
+ for (i= 0; lr->lr_ref_followed[i] != NULL; i++)
+ free(lr->lr_ref_followed[i]);
+ free(lr->lr_ref_followed);
+ }
+
+ free( lr );
+}
+
+
+static void
+free_servers( LDAPServer *srvlist )
+{
+ LDAPServer *nextsrv;
+
+ while ( srvlist != NULL ) {
+ nextsrv = srvlist->lsrv_next;
+ if ( srvlist->lsrv_dn != NULL ) {
+ free( srvlist->lsrv_dn );
+ }
+ if ( srvlist->lsrv_host != NULL ) {
+ free( srvlist->lsrv_host );
+ }
+ free( srvlist );
+ srvlist = nextsrv;
+ }
+}
+
+/*
+ * nsldapi_connection_lost_nolock() resets "ld" to a non-connected, known
+ * state. It should be called whenever a fatal error occurs on the
+ * Sockbuf "sb." sb == NULL means we don't know specifically where
+ * the problem was so we assume all connections are bad.
+ */
+void
+nsldapi_connection_lost_nolock( LDAP *ld, Sockbuf *sb )
+{
+ LDAPRequest *lr;
+
+ /*
+ * change status of all pending requests that are associated with "sb
+ * to "connection dead."
+ * also change the connection status to "dead" and remove it from
+ * the list of sockets we are interested in.
+ */
+ for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
+ if ( sb == NULL ||
+ ( lr->lr_conn != NULL && lr->lr_conn->lconn_sb == sb )) {
+ lr->lr_status = LDAP_REQST_CONNDEAD;
+ if ( lr->lr_conn != NULL ) {
+ lr->lr_conn->lconn_status = LDAP_CONNST_DEAD;
+ }
+ }
+ }
+}
+
+#ifdef LDAP_DNS
+static LDAPServer *
+dn2servers( LDAP *ld, char *dn ) /* dn can also be a domain.... */
+{
+ char *p, *domain, *host, *server_dn, **dxs;
+ int i, port;
+ LDAPServer *srvlist, *prevsrv, *srv;
+
+ if (( domain = strrchr( dn, '@' )) != NULL ) {
+ ++domain;
+ } else {
+ domain = dn;
+ }
+
+ if (( dxs = getdxbyname( domain )) == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( NULL );
+ }
+
+ srvlist = NULL;
+
+ for ( i = 0; dxs[ i ] != NULL; ++i ) {
+ port = LDAP_PORT;
+ server_dn = NULL;
+ if ( strchr( dxs[ i ], ':' ) == NULL ) {
+ host = dxs[ i ];
+ } else if ( strlen( dxs[ i ] ) >= 7 &&
+ strncmp( dxs[ i ], "ldap://", 7 ) == 0 ) {
+ host = dxs[ i ] + 7;
+ if (( p = strchr( host, ':' )) == NULL ) {
+ p = host;
+ } else {
+ *p++ = '\0';
+ port = atoi( p );
+ }
+ if (( p = strchr( p, '/' )) != NULL ) {
+ server_dn = ++p;
+ if ( *server_dn == '\0' ) {
+ server_dn = NULL;
+ }
+ }
+ } else {
+ host = NULL;
+ }
+
+ if ( host != NULL ) { /* found a server we can use */
+ if (( srv = (LDAPServer *)calloc( 1,
+ sizeof( LDAPServer ))) == NULL ) {
+ free_servers( srvlist );
+ srvlist = NULL;
+ break; /* exit loop & return */
+ }
+
+ /* add to end of list of servers */
+ if ( srvlist == NULL ) {
+ srvlist = srv;
+ } else {
+ prevsrv->lsrv_next = srv;
+ }
+ prevsrv = srv;
+
+ /* copy in info. */
+ if (( srv->lsrv_host = strdup( host )) == NULL ||
+ ( server_dn != NULL && ( srv->lsrv_dn =
+ strdup( server_dn )) == NULL )) {
+ free_servers( srvlist );
+ srvlist = NULL;
+ break; /* exit loop & return */
+ }
+ srv->lsrv_port = port;
+ }
+ }
+
+ ldap_value_free( dxs );
+
+ if ( srvlist == NULL ) {
+ ld->ld_errno = LDAP_SERVER_DOWN;
+ }
+
+ return( srvlist );
+}
+#endif /* LDAP_DNS */
diff --git a/usr/src/lib/libldap4/common/result.c b/usr/src/lib/libldap4/common/result.c
new file mode 100644
index 0000000000..07b21483c6
--- /dev/null
+++ b/usr/src/lib/libldap4/common/result.c
@@ -0,0 +1,1657 @@
+/*
+ * Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * result.c - wait for an ldap result
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include <time.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include <time.h>
+#include "msdos.h"
+#ifdef PCNFS
+#include <tklib.h>
+#include <tk_errno.h>
+#include <bios.h>
+#endif /* PCNFS */
+#ifdef NCSA
+#include "externs.h"
+#endif /* NCSA */
+#else /* DOS */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#ifdef _AIX
+#include <sys/select.h>
+#endif /* _AIX */
+#include "portable.h"
+#endif /* DOS */
+#endif /* MACOS */
+#ifdef VMS
+#include "ucx_select.h"
+#endif
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifdef USE_SYSCONF
+#include <unistd.h>
+#endif /* USE_SYSCONF */
+
+#ifdef NEEDPROTOS
+static int ldap_abandoned( LDAP *ld, int msgid );
+static int ldap_mark_abandoned( LDAP *ld, int msgid );
+static int wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout,
+ LDAPMessage **result );
+static int read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn *lc,
+ LDAPMessage **result );
+static int build_result_ber( LDAP *ld, BerElement *ber, LDAPRequest *lr );
+static void merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr );
+#ifdef CLDAP
+static int ldap_select1( LDAP *ld, struct timeval *timeout );
+#endif
+static int Ref_AddToRequest(LDAPRequest *lr, char **refs);
+static void Ref_FreeAll(LDAPRequest *lr);
+#else /* NEEDPROTOS */
+static int ldap_abandoned();
+static int ldap_mark_abandoned();
+static int wait4msg();
+static int read1msg();
+static int build_result_ber();
+static void merge_error_info();
+#ifdef CLDAP
+static int ldap_select1();
+#endif
+#endif /* NEEDPROTOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+extern int errno;
+#endif
+
+/*
+ * ldap_result - wait for an ldap result response to a message from the
+ * ldap server. If msgid is -1, any message will be accepted, otherwise
+ * ldap_result will wait for a response with msgid.
+ * If all is LDAP_MSG_ONE the first message with id msgid will be accepted.
+ * If all is LDAP_MSG_RECEIVED, the received messages with the id msgid will
+ * be accepted.
+ * Otherwise, ldap_result will wait for all responses with id msgid and
+ * then return a pointer to the entire list of messages. This is only
+ * useful for search responses, which can be of 3 message types (zero or
+ * more entries, zero or more references, one or more results). The type
+ * of the first message* received is returned.
+ * When waiting, any messages that have been abandoned are discarded.
+ *
+ * Example:
+ * ldap_result( s, msgid, all, timeout, result )
+ */
+int
+ldap_result( LDAP *ld, int msgid, int all, struct timeval *timeout,
+ LDAPMessage **result )
+{
+ LDAPMessage *lm, *lastlm, *nextlm;
+ int rv;
+
+ /*
+ * First, look through the list of responses we have received on
+ * this association and see if the response we're interested in
+ * is there. If it is, return it. If not, call wait4msg() to
+ * wait until it arrives or timeout occurs.
+ */
+
+#ifdef _REENTRANT
+ LOCK_RESPONSE(ld);
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 223, "ldap_result\n"), 0, 0, 0 );
+
+ *result = NULLMSG;
+ lastlm = NULLMSG;
+
+ /* look in the received responses */
+ for ( lm = ld->ld_responses; lm != NULLMSG; lm = nextlm ) {
+ nextlm = lm->lm_next;
+
+ /* if the msg has been abandonned, free it */
+ if ( ldap_abandoned( ld, lm->lm_msgid ) ) {
+ ldap_mark_abandoned( ld, lm->lm_msgid );
+
+ if ( lastlm == NULLMSG ) {
+ ld->ld_responses = lm->lm_next;
+ } else {
+ lastlm->lm_next = nextlm;
+ }
+
+ ldap_msgfree( lm );
+
+ continue;
+ }
+
+ if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) {
+ LDAPMessage *tmp;
+
+ /* If return ONE or RECEIVED message(s) or not a search result, return lm */
+ if ( all == LDAP_MSG_ONE || all == LDAP_MSG_RECEIVED
+ || (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT
+ && lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY
+ && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE) )
+ break;
+
+ /* Search in the set of messages if one is a search result */
+ for ( tmp = lm; tmp != NULLMSG; tmp = tmp->lm_chain ) {
+ if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT )
+ break;
+ }
+ /* No, well wait for the result message */
+ if ( tmp == NULLMSG ) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ rv = wait4msg( ld, msgid, all, timeout, result );
+#ifdef _REENTRANT
+ UNLOCK_RESPONSE(ld);
+#endif
+ return( rv );
+ }
+ /* Here we have the Search result pointed by tmp */
+ break;
+ }
+ /* Check next response */
+ lastlm = lm;
+ }
+
+ /* No response matching found : Wait for one */
+ if ( lm == NULLMSG ) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ rv = wait4msg( ld, msgid, all, timeout, result );
+#ifdef _REENTRANT
+ UNLOCK_RESPONSE(ld);
+#endif
+ return( rv );
+ }
+
+ /* lm points to the message (chain) to return */
+
+ /* Remove message to return from ld_responses list */
+ if ( lastlm == NULLMSG ) {
+ if (all == LDAP_MSG_ONE && lm->lm_chain != NULLMSG){
+ ld->ld_responses = lm->lm_chain;
+ } else {
+ ld->ld_responses = lm->lm_next;
+ }
+ } else {
+ if (all == LDAP_MSG_ONE && lm->lm_chain != NULLMSG) {
+ lastlm->lm_next = lm->lm_chain;
+ } else {
+ lastlm->lm_next = lm->lm_next;
+ }
+ }
+
+ if ( all == LDAP_MSG_ONE )
+ lm->lm_chain = NULLMSG;
+ /* Otherwise return the whole chain */
+ /* No reponses attached */
+ lm->lm_next = NULLMSG;
+
+ *result = lm;
+ ld->ld_errno = LDAP_SUCCESS;
+ rv = lm->lm_msgtype;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+ UNLOCK_RESPONSE(ld);
+#endif
+ return( rv );
+}
+
+static int
+wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout,
+ LDAPMessage **result )
+{
+ int rc;
+ struct timeval tv, *tvp;
+ time_t start_time, tmp_time;
+ LDAPConn *lc, *nextlc;
+
+#ifdef LDAP_DEBUG
+ if ( timeout == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 224, "wait4msg (infinite timeout)\n"),
+ 0, 0, 0 );
+ } else {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 225, "wait4msg (timeout %1$ld sec, %2$ld usec)\n"),
+ timeout->tv_sec, timeout->tv_usec, 0 );
+ }
+#endif /* LDAP_DEBUG */
+
+ if ( timeout == NULL ) {
+ tvp = NULL;
+ } else {
+ tv = *timeout;
+ tvp = &tv;
+ start_time = time( NULL );
+ }
+
+ rc = -2;
+ while ( rc == -2 ) {
+#ifdef LDAP_DEBUG
+ if ( ldap_debug & LDAP_DEBUG_TRACE ) {
+ dump_connection( ld, ld->ld_conns, 1 );
+ dump_requests_and_responses( ld );
+ }
+#endif /* LDAP_DEBUG */
+ for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
+ if ( lc->lconn_sb->sb_ber.ber_ptr <
+ lc->lconn_sb->sb_ber.ber_end ) {
+ /* A Message is available, decode and process it */
+ rc = read1msg( ld, msgid, all, lc->lconn_sb,
+ lc, result );
+ break;
+ }
+ }
+ /* There was no message available : Wait for one */
+ if ( lc == NULL ) {
+ rc = do_ldap_select( ld, tvp );
+
+
+#if defined( LDAP_DEBUG ) && !defined( MACOS ) && !defined( DOS )
+ if ( rc == -1 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 226, "do_ldap_select returned -1: errno %d\n"),
+ errno, 0, 0 );
+ }
+#endif
+
+#if !defined( MACOS ) && !defined( DOS )
+ if ( rc == 0 || ( rc == -1 && (ld->ld_restart || errno != EINTR ))) {
+#else
+ if ( rc == -1 || rc == 0 ) {
+#endif
+ ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
+ LDAP_TIMEOUT);
+ if ( rc == -1 ) {
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ nsldapi_connection_lost_nolock( ld, NULL);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ }
+ return( rc );
+ }
+
+ if ( rc == -1 ) {
+ rc = -2; /* select interrupted: Continue the loop */
+ } else {
+ rc = -2;
+ for ( lc = ld->ld_conns; rc == -2 && lc != NULL;
+ lc = nextlc ) {
+ nextlc = lc->lconn_next;
+ if ( lc->lconn_status == LDAP_CONNST_CONNECTED) {
+ /* Check on each connection. */
+ long is_ready = is_read_ready( ld, lc->lconn_sb );
+
+ if (is_ready > 0) {
+ /* A Message is available, decode and process it */
+ rc = read1msg( ld, msgid, all,
+ lc->lconn_sb, lc, result );
+ } else if ( is_ready < 0){
+ /* Error in the select : what to do in here ? */
+ /* So far : */
+ rc = -1;
+ }
+ }
+ }
+ }
+ }
+
+ if ( rc == -2 && tvp != NULL ) {
+ tmp_time = time( NULL );
+ if (( tv.tv_sec -= ( tmp_time - start_time )) <= 0 ) {
+ /* At this point if all == LDAP_MSG_RECEIVED, we must
+ return all available messages for the msgid */
+ if (all == LDAP_MSG_RECEIVED) {
+ /* Search in responses if some have the correct id */
+ /* if yes return the chain */
+ /* Otherwise return timeout */
+ break;
+ }
+
+ rc = 0; /* timed out */
+ ld->ld_errno = LDAP_TIMEOUT;
+ break;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 227, "wait4msg: %ld secs to go\n"),
+ tv.tv_sec, 0, 0 );
+ start_time = tmp_time;
+ }
+ }
+
+ return( rc );
+}
+
+
+static int
+read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb,
+ LDAPConn *lc,
+ LDAPMessage **result )
+{
+ BerElement ber;
+ LDAPMessage *new, *L_res, *l, *prev, *tmp;
+ int id;
+ unsigned int tag, atag, len;
+ int foundit = 0;
+ LDAPRequest *lr, *lrparent;
+ LDAPRef *theReferences;
+ BerElement tmpber;
+ int rc, refer_cnt, hadref, simple_request, samereq = 0, total_count;
+ int retcode;
+ int theErrCode = LDAP_SUCCESS;
+ unsigned int lderr;
+ char *msgtypestr;
+ char ** theRefs = NULL;
+ char * theOid = NULL;
+ char *lddn, *lderrmsg;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 228, "read1msg\n"), 0, 0, 0 );
+
+read_from_sb:
+ lderr = LDAP_SUCCESS; /* Be optimistic */
+
+ ber_zero_init( &ber, 0 );
+ set_ber_options( ld, &ber );
+
+ /* get the next message */
+ if ( (tag = ber_get_next( sb, &len, &ber ))
+ != LDAP_TAG_MESSAGE ) {
+ ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN :
+ LDAP_LOCAL_ERROR);
+ if ( tag == LBER_DEFAULT ) {
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ nsldapi_connection_lost_nolock( ld, sb );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ }
+ return( -1 );
+ }
+
+ /* message id */
+ if ( ber_get_int( &ber, &id ) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( -1 );
+ }
+
+ /* if it's been abandoned, toss it */
+ if ( ldap_abandoned( ld, (int)id ) ) {
+ free( ber.ber_buf ); /* gack! */
+ return( -2 ); /* continue looking */
+ }
+
+ /* the message type */
+ if ( (tag = ber_peek_tag( &ber, &len )) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return( -1 );
+ }
+
+ /* KE
+ * Treat unsolicited notification if we got one!
+ * id==0
+ * tag==LDAP_RES_EXTENDED
+ *
+ * resultCode== protocolError
+ * strongAuthRequired
+ * unavailable
+ * tag==LDAP_TAG_EXT_RESPNAME
+ * response name (oid)==1.3.6.1.1.4.1.1466.20036
+ * no response field
+ *
+ * Example:
+ * --------
+ * Ber format: {iaata}
+ * which means: returnCode dn errorMessage LDAP_TAG_EXT_RESPNAME "1.3.6.1.1.4.1.1466.20036"
+ */
+ if ( (id==0) && (tag==LDAP_RES_EXTENDED) )
+ {
+ tmpber = ber;
+ if (ber_scanf( &ber, "{iaa", &lderr, &lddn, &lderrmsg) != LBER_ERROR)
+ {
+ if (ber_peek_tag ( &ber, &atag) == LDAP_TAG_EXT_RESPNAME)
+ {
+ if ( ber_get_stringa( &ber, &theOid) == LBER_ERROR )
+ {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return(-1);
+ }
+ }
+ else
+ {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return(-1);
+ }
+
+ if (ber_peek_tag ( &ber, &atag) == LDAP_TAG_EXT_RESPONSE)
+ {
+ /* this field must be absent */
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return(-1);
+ }
+ if ( ber_scanf(&ber, "}")== LBER_ERROR)
+ {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return(-1);
+ }
+
+ /* make a new ldap message to return the result */
+ if ( (new = (LDAPMessage *) calloc( 1, sizeof(LDAPMessage) )) == NULL )
+ {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return(-1);
+ }
+ new->lm_msgid = 0;
+ new->lm_msgtype = tag;
+ new->lm_ber = ber_dup( &tmpber );
+
+ if ( (strncmp(theOid, "1.3.6.1.1.4.1.1466.20036", 24)==0) &&
+ (lderr==LDAP_PROTOCOL_ERROR) ||
+ (lderr==LDAP_STRONG_AUTH_REQUIRED) ||
+ (lderr==LDAP_UNAVAILABLE) )
+ {
+ /* make a new ldap message to return the result */
+ if ( (L_res = (LDAPMessage *) calloc( 1, sizeof(LDAPMessage) )) == NULL )
+ {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return(-1);
+ }
+ L_res->lm_msgid = 0;
+ L_res->lm_msgtype = tag;
+ L_res->lm_ber = ber_dup( &tmpber );
+ *result = L_res;
+
+ /* It is a notice of disconnection
+ * Return immediatly with an error code to stop
+ * reading any new message and to prevent the use
+ */
+ ld->ld_errno = LDAP_SERVER_DOWN;
+ ldap_insert_notif(ld, new); /* in head */
+ return(-1);
+ }
+ else
+ {
+ /* This is another notification
+ * Keep on the processing of received messages
+ */
+ ldap_add_notif(ld, new); /* in tail */
+ goto read_from_sb;
+ }
+ }
+ else
+ {
+ Debug(LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1673, "Error while decoding Extended Response message"), NULL, NULL, NULL);
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return(-1);
+ }
+ }
+ else if (( lr = find_request_by_msgid( ld, id )) == NULL )
+ {
+ Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 229, "no request for response with msgid %ld (tossing)\n"), id, 0, 0 );
+ free( ber.ber_buf ); /* gack! */
+ return( -2 ); /* continue looking */
+ }
+
+ if (tag == LDAP_RES_SEARCH_ENTRY)
+ msgtypestr = catgets(slapdcat, 1, 1281, "search entry");
+ else if (tag == LDAP_RES_SEARCH_REFERENCE)
+ msgtypestr = catgets(slapdcat, 1, 1282, "search reference");
+ else
+ msgtypestr = catgets(slapdcat, 1, 1283, "result");
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 230, "got %1$s msgid %2$ld, original id %3$d\n"),
+ msgtypestr, id, lr->lr_origid );
+
+ id = lr->lr_origid;
+
+ /* REFERRALS HANDLING*/
+ refer_cnt = 0;
+ simple_request = 0;
+ hadref = 0;
+ rc = -2; /* default is to keep looking (no response found) */
+ lr->lr_res_msgtype = tag;
+
+ if ( tag != LDAP_RES_SEARCH_ENTRY ) { /* If it's not an entry, ie it's a result or a reference */
+ if ( ld->ld_version >= LDAP_VERSION2 &&
+ ( lr->lr_parent != NULL ||
+ ld->ld_follow_referral /* || ClientControl to follow referral present */ )) {
+ tmpber = ber;
+ if (tag == LDAP_RES_SEARCH_REFERENCE){
+ /* LDAP V3 reference. Decode it */
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "LDAP search reference received. Will follow it later\n"),
+ 0, 0,0);
+ if (ber_scanf(&tmpber, "{v}", &theRefs) == LBER_ERROR){
+ Debug ( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1284, "Error while decoding Search Reference Result message\n"),
+ NULL, NULL, NULL);
+ rc = -1;
+ theRefs = NULL;
+ } else {
+ /* Store the referrals in request. We will follow them when the result arrives */
+ Ref_AddToRequest(lr, theRefs);
+ theRefs = NULL;
+ free( ber.ber_buf ); /* gack! */
+ ber.ber_buf = NULL;
+ return (rc);
+ }
+ } else {
+ if (ber_scanf( &tmpber, "{iaa", &lderr, &lr->lr_res_matched, &lr->lr_res_error) != LBER_ERROR){
+ if (lderr == LDAP_PARTIAL_RESULTS){
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "LDAPv2 partial error received\n"), 0, 0,0);
+ /* Ldapv2 referrals */
+ theRefs = ldap_errormsg2referrals(lr->lr_res_error);
+ ber_scanf(&tmpber, "}");
+ } else if (lderr == LDAP_REFERRAL ){
+ /* We have some referrals, decode them */
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "LDAPv3 referral error received\n"), 0, 0,0);
+ if (ber_peek_tag ( &tmpber, &atag) == LDAP_TAG_REFERRAL){
+ if (ber_scanf(&tmpber, "{v}}", &theRefs) == LBER_ERROR){
+ Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1285, "Error while decoding referrals in msg\n"),
+ NULL, NULL, NULL );
+ rc = -1; /* ??? */
+ theRefs = NULL;
+ }
+ } /* else error there should be at least one ref */
+ } else if (((lderr == LDAP_NO_SUCH_OBJECT) ||
+ (lderr == LDAP_BUSY) ||
+ (lderr == LDAP_UNAVAILABLE) ||
+ (lderr == LDAP_SERVER_DOWN) ||
+ (lderr == LDAP_CONNECT_ERROR)) &&
+ (lr->lr_parent != NULL) && /* its subrequest */
+ (lr->lr_ref_tofollow != NULL)) { /* And it has some other referral to try */
+ samereq = 1;
+ theRefs = lr->lr_ref_tofollow;
+ lr->lr_ref_tofollow = NULL;
+ lrparent = lr->lr_parent;
+ /* delete lr */
+ free_request(ld, lr);
+ /* lr now points on parent request */
+ lr = lrparent;
+ /* Follow referrals */
+ } else {
+ /* Here we have a simple result */
+ hadref = lr->lr_outrefcnt;
+ }
+ } else {
+ Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1286, "Error while decoding result for request %$1d\n"),
+ lr->lr_origid, NULL, NULL);
+ rc = -1; /* ??? */
+ }
+ }
+
+ total_count = 0;
+ if (tag != LDAP_RES_SEARCH_REFERENCE && lr->lr_references) {
+ /* Some search references pending... Let's try to chase them */
+ hadref = 1;
+ theReferences = lr->lr_references;
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Now following the search references received\n"),
+ 0, 0,0);
+
+ while (theReferences != NULL){
+ if ((retcode = chase_referrals(ld, lr, theReferences->lref_refs , &refer_cnt, 0)) != LDAP_SUCCESS) {
+ /* think about what to do */
+ Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, -1, "Error while chasing referral (%1$d)\n"),
+ retcode, NULL, NULL);
+ theErrCode = LDAP_REFERRAL;
+ }
+ if (refer_cnt >= 0)
+ total_count += refer_cnt;
+ theReferences = theReferences->lref_next;
+ }
+ Ref_FreeAll(lr);
+ if (theErrCode != LDAP_SUCCESS) {
+ if (ld->ld_error != NULL && *ld->ld_error) {
+ if (lr->lr_res_error)
+ free(lr->lr_res_error);
+ lr->lr_res_error = strdup(ld->ld_error);
+ }
+ }
+ lr->lr_res_errno = theErrCode;
+ }
+ /* if theRefs != NULL we have some referrals to chase, do it */
+ if (theRefs){
+ hadref = 1;
+ if ((retcode = chase_referrals(ld, lr, theRefs, &refer_cnt, samereq)) != LDAP_SUCCESS){
+ /* think about what to do */
+ Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, -1, "Error while chasing referral (%1$d)\n"),
+ retcode, NULL, NULL);
+ }
+
+ if (refer_cnt >= 0)
+ total_count += refer_cnt;
+
+ ldap_value_free(theRefs);
+ if (samereq){ /* Just tried another referral for same request */
+ free(ber.ber_buf);
+ ber.ber_buf = NULL;
+ rc = -2;
+ /* continue */
+ }
+ if (retcode != LDAP_SUCCESS) {
+ if (ld->ld_version == LDAP_VERSION2){
+ if (lr->lr_res_error)
+ free(lr->lr_res_error);
+ lr->lr_res_error = ldap_referral2error_msg(lr->lr_ref_unfollowed);
+ } else if (ld->ld_error != NULL && *ld->ld_error) {
+ if (lr->lr_res_error)
+ free(lr->lr_res_error);
+ lr->lr_res_error = strdup(ld->ld_error);
+ }
+ }
+ lr->lr_res_errno = ld->ld_errno;
+
+ } else if (theErrCode == LDAP_SUCCESS) {
+ /* no referral have been chased */
+ lr->lr_res_errno = (lderr == LDAP_PARTIAL_RESULTS || lderr == LDAP_REFERRAL) ? LDAP_SUCCESS : lderr;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 231, "new result: res_errno: %1$d, res_error: <%2$s>, res_matched: <%3$s>\n"),
+ lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "",
+ lr->lr_res_matched ? lr->lr_res_matched : "" );
+ }
+
+
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 232, "read1msg: %1$d new referrals\n"), total_count, 0, 0 );
+
+ if ( refer_cnt != 0 ) { /* chasing referrals */
+ free( ber.ber_buf ); /* gack! */
+ ber.ber_buf = NULL;
+ if ( refer_cnt < 0 ) {
+ return( -1 ); /* fatal error */
+ }
+ lr->lr_status = LDAP_REQST_CHASINGREFS;
+ } else if (tag == LDAP_RES_SEARCH_REFERENCE && !ld->ld_follow_referral) {
+ /* We had a ref and we don't follow referral : Do nothing there ?! */
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, -1, "read1msg: returning search reference\n"), 0, 0, 0 );
+
+ } else {
+ /* No referral chasing */
+ if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) {
+ /* request without any referrals */
+ simple_request = ( hadref ? 0 : 1 );
+ } else {
+ /* request with referrals or child request */
+ free( ber.ber_buf ); /* gack! */
+ ber.ber_buf = NULL;
+ }
+
+
+ while ( lr->lr_parent != NULL ) {
+ merge_error_info( ld, lr->lr_parent, lr );
+ lr = lr->lr_parent;
+ if ( --lr->lr_outrefcnt > 0 ) {
+ break; /* not completedly done yet */
+ }
+ }
+
+ if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { /* The main request has no more outstanding refs */
+ id = lr->lr_msgid;
+ tag = lr->lr_res_msgtype;
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 233, "request %1$ld done\n"),
+ id, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE,
+ catgets(slapdcat, 1, 234, "res_errno: %1$d, res_error: <%2$s>, res_matched: <%3$s>\n"),
+ lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "",
+ lr->lr_res_matched ? lr->lr_res_matched : "" );
+ if ( !simple_request ) { /* We have to rebuild the result */
+ if ( ber.ber_buf != NULL ) {
+ free( ber.ber_buf ); /* gack! */
+ ber.ber_buf = NULL;
+ }
+ if ( build_result_ber( ld, &ber, lr )
+ == LBER_ERROR ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ rc = -1; /* fatal error */
+ }
+ }
+
+ free_request( ld, lr );
+ }
+
+ if ( lc != NULL ) {
+ free_connection( ld, lc, 0, 1 );
+ }
+ }
+ }
+
+ if ( ber.ber_buf == NULL ) { /* If the buffer has been freed, return */
+ return( rc );
+ }
+ /* End of REFERRALS */
+
+ /* make a new ldap message */
+ if ( (new = (LDAPMessage *) calloc( 1, sizeof(LDAPMessage) ))
+ == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( -1 );
+ }
+ new->lm_msgid = (int)id;
+ new->lm_msgtype = tag;
+ new->lm_ber = ber_dup( &ber );
+
+#ifndef NO_CACHE
+ if ( ld->ld_cache != NULL ) {
+ add_result_to_cache( ld, new );
+ }
+#endif /* NO_CACHE */
+
+ /* is this the one we're looking for? */
+ if ( msgid == LDAP_RES_ANY || id == msgid ) {
+ if ( all == LDAP_MSG_ONE /* all apply only to search, so if not a search,return the val */
+ || (new->lm_msgtype != LDAP_RES_SEARCH_RESULT
+ && new->lm_msgtype != LDAP_RES_SEARCH_ENTRY
+ && new->lm_msgtype != LDAP_RES_SEARCH_REFERENCE) ) {
+ *result = new;
+ ld->ld_errno = LDAP_SUCCESS;
+ return( tag );
+ } else if ( new->lm_msgtype == LDAP_RES_SEARCH_RESULT) {
+ foundit = 1; /* return the chain later */
+ }
+ }
+
+ /*
+ * if not, we must add it to the list of responses. if
+ * the msgid is already there, it must be part of an existing
+ * search response.
+ */
+
+ prev = NULLMSG;
+ for ( l = ld->ld_responses; l != NULLMSG; l = l->lm_next ) {
+ if ( l->lm_msgid == new->lm_msgid )
+ break;
+ prev = l;
+ }
+
+ /* not part of an existing search response */
+ if ( l == NULLMSG ) {
+ if ( foundit ) { /* it a search result anyway, so return it */
+ *result = new;
+ ld->ld_errno = LDAP_SUCCESS;
+ return( tag );
+ }
+
+ new->lm_next = ld->ld_responses;
+ ld->ld_responses = new;
+ return( -2 ); /* continue looking */
+ }
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 235, "adding response id %1$d type %2$d:\n"),
+ new->lm_msgid, new->lm_msgtype, 0 );
+
+ /* part of a search response - add to end of list of entries or references */
+ for ( tmp = l; tmp->lm_chain != NULLMSG &&
+ (tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ||
+ tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE);
+ tmp = tmp->lm_chain )
+ ; /* NULL */
+ tmp->lm_chain = new;
+
+ /* return the whole chain if that's what we were looking for */
+ if ( foundit ) {
+ if ( prev == NULLMSG )
+ ld->ld_responses = l->lm_next;
+ else
+ prev->lm_next = l->lm_next;
+ *result = l;
+ ld->ld_errno = LDAP_SUCCESS;
+ return( l->lm_msgtype ); /* Patch 16 : was return(tag) */
+ }
+
+ return( -2 ); /* continue looking */
+}
+
+
+static int
+build_result_ber( LDAP *ld, BerElement *ber, LDAPRequest *lr )
+{
+ unsigned int len;
+ int along;
+
+ Debug (LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1287, "=> building_ber_error msgid %ld\n"), lr->lr_msgid, 0,0);
+ ber_zero_init( ber, 0 );
+ set_ber_options( ld, ber );
+ if (ld->ld_version == LDAP_VERSION3){
+ if ( ber_printf( ber, "{it{ess",
+ lr->lr_msgid,
+ lr->lr_res_msgtype,
+ lr->lr_res_errno,
+ lr->lr_res_matched ? lr->lr_res_matched : "",
+ lr->lr_res_error ? lr->lr_res_error : "" ) == LBER_ERROR){
+ return (LBER_ERROR);
+ }
+ if (lr->lr_res_errno == LDAP_REFERRAL &&
+ ber_printf(ber, "t{v}", LDAP_TAG_REFERRAL, lr->lr_ref_unfollowed) == LBER_ERROR){
+ return (LBER_ERROR);
+ }
+ if (ber_printf(ber, "}}") == LBER_ERROR){
+ return (LBER_ERROR);
+ }
+ } else {
+ if ( ber_printf( ber, "{it{ess}}",
+ lr->lr_msgid,
+ lr->lr_res_msgtype,
+ lr->lr_res_errno,
+ lr->lr_res_matched ? lr->lr_res_matched : "",
+ lr->lr_res_error ? lr->lr_res_error : "" ) == LBER_ERROR ) {
+ return( LBER_ERROR );
+ }
+ }
+
+ ber_reset( ber, 1 );
+ if ( ber_skip_tag( ber, &len ) == LBER_ERROR ) {
+ return( LBER_ERROR );
+ }
+
+ if ( ber_get_int( ber, &along ) == LBER_ERROR ) {
+ return( LBER_ERROR );
+ }
+
+ return( ber_peek_tag( ber, &len ));
+}
+
+
+static void
+merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr )
+{
+ int i, j;
+/*
+ * Merge error information in "lr" with "parentr" error code and string.
+ */
+ if ( lr->lr_res_errno == LDAP_PARTIAL_RESULTS ) {
+ parentr->lr_res_errno = lr->lr_res_errno;
+ if ( lr->lr_res_error != NULL ) {
+ (void)append_referral( ld, &parentr->lr_res_error,
+ lr->lr_res_error );
+ }
+ } else if ( lr->lr_res_errno != LDAP_SUCCESS &&
+ parentr->lr_res_errno == LDAP_SUCCESS ) {
+ parentr->lr_res_errno = lr->lr_res_errno;
+ if ( parentr->lr_res_error != NULL ) {
+ free( parentr->lr_res_error );
+ }
+ parentr->lr_res_error = lr->lr_res_error;
+ lr->lr_res_error = NULL;
+ if ( NAME_ERROR( lr->lr_res_errno )) {
+ if ( parentr->lr_res_matched != NULL ) {
+ free( parentr->lr_res_matched );
+ }
+ parentr->lr_res_matched = lr->lr_res_matched;
+ lr->lr_res_matched = NULL;
+ }
+ if (lr->lr_ref_unfollowed != NULL){
+ for (i=0;lr->lr_ref_unfollowed[i] != NULL; i++);
+ j = 0;
+ if (parentr->lr_ref_unfollowed != NULL){
+ for (j=0;parentr->lr_ref_unfollowed[j]!= NULL ;j++);
+ j++;
+ }
+ parentr->lr_ref_unfollowed = (char **)realloc (parentr->lr_ref_unfollowed, (j+i+1) * sizeof(char *));
+ if (parentr->lr_ref_unfollowed != NULL){
+ for (i = 0; lr->lr_ref_unfollowed[i] != NULL; i++){
+ parentr->lr_ref_unfollowed[j+i] = lr->lr_ref_unfollowed[i];
+ lr->lr_ref_unfollowed[i] = NULL;
+ }
+ parentr->lr_ref_unfollowed[i+j+1] = NULL;
+ } else {
+ if (parentr->lr_res_errno == LDAP_SUCCESS)
+ parentr->lr_res_errno = LDAP_NO_MEMORY;
+ }
+ }
+ }
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 236, "merged parent (id %1$d) error info: "),
+ parentr->lr_msgid, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 237, "result errno %1$d, error <%2$s>, matched <%3$s>\n"),
+ parentr->lr_res_errno,
+ parentr->lr_res_error ? parentr->lr_res_error : "",
+ parentr->lr_res_matched ? parentr->lr_res_matched : "" );
+}
+
+#ifdef CLDAP
+#if !defined( MACOS ) && !defined( DOS ) && !defined( _WIN32 )
+static int
+ldap_select1( LDAP *ld, struct timeval *timeout )
+{
+ fd_set readfds;
+ static int tblsize;
+
+ if ( tblsize == 0 ) {
+#ifdef USE_SYSCONF
+ tblsize = (int) sysconf( _SC_OPEN_MAX );
+#else /* USE_SYSCONF */
+ tblsize = getdtablesize();
+#endif /* USE_SYSCONF */
+ }
+
+ FD_ZERO( &readfds );
+ FD_SET( ld->ld_sb.sb_sd, &readfds );
+
+ return( select( tblsize, &readfds, 0, 0, timeout ) );
+}
+#endif /* !MACOS */
+
+
+#ifdef MACOS
+static int
+ldap_select1( LDAP *ld, struct timeval *timeout )
+{
+ return( tcpselect( ld->ld_sb.sb_sd, timeout ));
+}
+#endif /* MACOS */
+
+
+#if ( defined( DOS ) && defined( WINSOCK )) || defined( _WIN32 )
+static int
+ldap_select1( LDAP *ld, struct timeval *timeout )
+{
+ fd_set readfds;
+ int rc;
+
+ FD_ZERO( &readfds );
+ FD_SET( ld->ld_sb.sb_sd, &readfds );
+
+ rc = select( 1, &readfds, 0, 0, timeout );
+ return( rc == SOCKET_ERROR ? -1 : rc );
+}
+#endif /* WINSOCK || _WIN32 */
+
+
+#ifdef DOS
+#ifdef PCNFS
+static int
+ldap_select1( LDAP *ld, struct timeval *timeout )
+{
+ fd_set readfds;
+ int res;
+
+ FD_ZERO( &readfds );
+ FD_SET( ld->ld_sb.sb_sd, &readfds );
+
+ res = select( FD_SETSIZE, &readfds, NULL, NULL, timeout );
+ if ( res == -1 && errno == EINTR) {
+ /* We've been CTRL-C'ed at this point. It'd be nice to
+ carry on but PC-NFS currently won't let us! */
+ printf("\n*** CTRL-C ***\n");
+ exit(-1);
+ }
+ return( res );
+}
+#endif /* PCNFS */
+
+#ifdef NCSA
+static int
+ldap_select1( LDAP *ld, struct timeval *timeout )
+{
+ int rc;
+ clock_t endtime;
+
+ if ( timeout != NULL ) {
+ endtime = timeout->tv_sec * CLK_TCK +
+ timeout->tv_usec * CLK_TCK / 1000000 + clock();
+ }
+
+ do {
+ Stask();
+ rc = netqlen( ld->ld_sb.sb_sd );
+ } while ( rc <= 0 && ( timeout == NULL || clock() < endtime ));
+
+ return( rc > 0 ? 1 : 0 );
+}
+#endif /* NCSA */
+#endif /* DOS */
+#endif /* CLDAP */
+
+
+int
+ldap_msgfree( LDAPMessage *lm )
+{
+ LDAPMessage *next;
+ int type = 0;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 238, "ldap_msgfree\n"), 0, 0, 0 );
+
+ for ( ; lm != NULLMSG; lm = next ) {
+ next = lm->lm_chain;
+ type = lm->lm_msgtype;
+ if (lm->lm_ber)
+ ber_free( lm->lm_ber, 1 );
+ free( (char *) lm );
+ }
+
+ return( type );
+}
+
+/*
+ * ldap_msgdelete - delete a message. It returns:
+ * 0 if the entire message was deleted
+ * -1 if the message was not found, or only part of it was found
+ */
+int
+ldap_msgdelete( LDAP *ld, int msgid )
+{
+ LDAPMessage *lm, *prev;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+ LOCK_RESPONSE(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 239, "ldap_msgdelete\n"), 0, 0, 0 );
+
+ prev = NULLMSG;
+ for ( lm = ld->ld_responses; lm != NULLMSG; lm = lm->lm_next ) {
+ if ( lm->lm_msgid == msgid )
+ break;
+ prev = lm;
+ }
+
+ if ( lm == NULLMSG ) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+ UNLOCK_RESPONSE(ld);
+#endif
+ return( -1 );
+ }
+
+ if ( prev == NULLMSG )
+ ld->ld_responses = lm->lm_next;
+ else
+ prev->lm_next = lm->lm_next;
+
+ if ( ldap_msgfree( lm ) == LDAP_RES_SEARCH_ENTRY ) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+ UNLOCK_RESPONSE(ld);
+#endif
+ return( -1 );
+ }
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+ UNLOCK_RESPONSE(ld);
+#endif
+ return( 0 );
+}
+
+
+/*
+ * return 1 if message msgid is waiting to be abandoned, 0 otherwise
+ */
+static int
+ldap_abandoned( LDAP *ld, int msgid )
+{
+ int i;
+
+ if ( ld == NULL ) return(1);
+ if ( ld->ld_abandoned == NULL )
+ return( 0 );
+
+ for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
+ if ( ld->ld_abandoned[i] == msgid )
+ return( 1 );
+
+ return( 0 );
+}
+
+
+static int
+ldap_mark_abandoned( LDAP *ld, int msgid )
+{
+ int i;
+
+ if ( ld->ld_abandoned == NULL )
+ return( -1 );
+
+ for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
+ if ( ld->ld_abandoned[i] == msgid )
+ break;
+
+ if ( ld->ld_abandoned[i] == -1 )
+ return( -1 );
+
+ for ( ; ld->ld_abandoned[i] != -1; i++ ) {
+ ld->ld_abandoned[i] = ld->ld_abandoned[i + 1];
+ }
+
+ return( 0 );
+}
+
+
+#ifdef CLDAP
+int
+cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber )
+{
+ int rc;
+ unsigned int tag, len;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_sb.sb_ber.ber_ptr >= ld->ld_sb.sb_ber.ber_end ) {
+ rc = ldap_select1( ld, timeout );
+ if ( rc == -1 || rc == 0 ) {
+ ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
+ LDAP_TIMEOUT);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( rc );
+ }
+ }
+
+ /* get the next message */
+ if ( (tag = ber_get_next( &ld->ld_sb, &len, ber ))
+ != LDAP_TAG_MESSAGE ) {
+ ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN :
+ LDAP_LOCAL_ERROR);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( tag );
+}
+#endif /* CLDAP */
+
+/* ldapv3 API extensions */
+
+int ldap_msgtype(LDAPMessage *res)
+{
+ if (res == NULL)
+ return (LDAP_RES_ANY);
+ return (res->lm_msgtype);
+}
+
+
+int ldap_msgid(LDAPMessage *res)
+{
+ if (res == NULL)
+ return (LDAP_RES_ANY);
+ return (res->lm_msgid);
+}
+
+int ldap_parse_result(LDAP *ld, LDAPMessage *res, int *errcodep, char **matcheddnp,
+ char **errmsgp, char ***referralsp, LDAPControl ***serverctrlsp,
+ int freeit)
+{
+ LDAPMessage *lm;
+ BerElement ber;
+ unsigned int alen;
+ int along;
+ unsigned int tag;
+ int i;
+ size_t rc;
+ char * acharp = NULL, * a2ndcharp = NULL;
+ char ** arefs = NULL;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 );
+
+ if (res == NULLMSG)
+ return (LDAP_PARAM_ERROR);
+
+ if (matcheddnp && *matcheddnp){
+ free(*matcheddnp);
+ *matcheddnp = NULL;
+ }
+ if (errmsgp && *errmsgp){
+ free(*errmsgp);
+ *errmsgp = NULL;
+ }
+ if (referralsp && *referralsp){
+ free_strarray(*referralsp);
+ *referralsp = NULL;
+ }
+
+ if (serverctrlsp && *serverctrlsp){
+ ldap_controls_free(*serverctrlsp);
+ *serverctrlsp = NULL;
+ }
+
+ for (lm = res; lm->lm_chain != NULL; lm = lm->lm_chain)
+
+ if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY
+ && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE)
+ break;
+
+ ber = *(lm->lm_ber);
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ if (ld->ld_version == LDAP_VERSION3) {
+ rc = ber_scanf( &ber, "{iaa", &along, &acharp, &a2ndcharp);
+ if (rc == LBER_ERROR){
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ if (matcheddnp) {
+ *matcheddnp = acharp;
+ } else {
+ ldap_memfree(acharp);
+ }
+ if (errmsgp) {
+ *errmsgp = a2ndcharp;
+ } else {
+ ldap_memfree(a2ndcharp);
+ }
+
+ if (errcodep) {
+ *errcodep = along;
+ }
+
+ if (along == LDAP_REFERRAL){
+ if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_REFERRAL) {
+ rc = ber_scanf(&ber, "{v}", &arefs);
+ if (rc == LBER_ERROR){
+ /* try to free other stuff */
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ if (referralsp) {
+ *referralsp = arefs;
+ } else {
+ for (i = 0; arefs[i] != NULL; i++)
+ ldap_memfree(arefs[i]);
+ ldap_memfree((char *)arefs);
+ }
+ } else {
+ /* referral errcode without URL is forbiden */
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ }
+ rc = ber_scanf(&ber, "}");
+ if (rc == LBER_ERROR){
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ /* It's the end of the result but the PDU may have controls */
+ if (serverctrlsp && (ber_peek_tag(&ber, &alen) == LDAP_TAG_CONTROL_LIST)) {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 392, "Controls found in result\n"), 0, 0, 0 );
+ *serverctrlsp = ldap_controls_decode(&ber,
+ (int *)&rc);
+ if (*serverctrlsp == NULL) {
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ } else {
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 393, "NO controls found in result\n"), 0, 0, 0 );
+ }
+ }
+ else if (ld->ld_version == LDAP_VERSION2) {
+ rc = ber_scanf( &ber, "{iaa}", &along, &acharp,
+ &a2ndcharp );
+ if (rc == LBER_ERROR){
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ if (matcheddnp) {
+ *matcheddnp = acharp;
+ } else {
+ ldap_memfree(acharp);
+ }
+ if (errmsgp) {
+ *errmsgp = a2ndcharp;
+ } else {
+ ldap_memfree(a2ndcharp);
+ }
+ if (errcodep) {
+ *errcodep = along;
+ }
+ }
+ else {
+ rc = ber_scanf( &ber, "{ia}", &along, &a2ndcharp );
+ if (rc == LBER_ERROR){
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+
+ if (errmsgp) {
+ *errmsgp = a2ndcharp;
+ } else {
+ ldap_memfree(a2ndcharp);
+ }
+ if (errcodep) {
+ *errcodep = along;
+ }
+ }
+
+ if ( freeit )
+ ldap_msgfree(res);
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_SUCCESS);
+}
+
+int ldap_parse_sasl_bind_result(LDAP *ld, LDAPMessage *res, struct berval **servercredp, int freeit)
+{
+ LDAPMessage *lm;
+ BerElement ber;
+ int along;
+ unsigned int tag;
+ int i;
+ size_t rc;
+ char * acharp = NULL, *a2ndcharp = NULL;
+ char ** arefs = NULL;
+ struct berval * creds = NULL;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 );
+
+ if (res == NULLMSG)
+ return (LDAP_PARAM_ERROR);
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ if ((res->lm_msgtype != LDAP_RES_BIND) || (ld->ld_version != LDAP_VERSION3)){
+ ld->ld_errno = LDAP_PARAM_ERROR;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_PARAM_ERROR);
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+
+ ber = *(res->lm_ber);
+ rc = ber_scanf( &ber, "{iaa", &along, &acharp, &a2ndcharp);
+ if (rc == LBER_ERROR){
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ ld->ld_errno = LDAP_DECODING_ERROR;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ ldap_memfree(acharp);
+ ldap_memfree(a2ndcharp);
+ if (along == LDAP_SUCCESS || along == LDAP_SASL_BIND_INPROGRESS){
+ /* Decode the serverSaslCreds if any */
+ if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_SASLCREDS) {
+ rc = ber_get_stringal( &ber, &creds);
+ if (rc == LBER_ERROR ){
+ if (freeit)
+ ldap_msgfree(res);
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ ld->ld_errno = LDAP_DECODING_ERROR;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ if (servercredp) {
+ *servercredp = creds;
+ } else {
+ ber_bvfree( creds );
+ }
+ }
+ } else if (along == LDAP_REFERRAL) {
+ if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_REFERRAL){
+ rc = ber_scanf(&ber, "{v}", &arefs);
+ if (rc == LBER_ERROR){
+ /* try to free other stuff */
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ ld->ld_errno = LDAP_DECODING_ERROR;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ for (i = 0; arefs[i] != NULL; i++)
+ ldap_memfree(arefs[i]);
+ ldap_memfree((char *)arefs);
+ } else {
+ /* There should be at least one ref */
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ ld->ld_errno = LDAP_DECODING_ERROR;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+ }
+
+ rc = ber_scanf(&ber, "}");
+ if (rc == LBER_ERROR){
+ if (freeit)
+ ldap_msgfree( res );
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ ld->ld_errno = LDAP_DECODING_ERROR;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_DECODING_ERROR);
+ }
+
+ if ( freeit )
+ ldap_msgfree(res);
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ ld->ld_errno = along;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (along);
+}
+
+int ldap_parse_extended_result(LDAP *ld, LDAPMessage *res, char **resultoidp,
+ struct berval **resultdata, int freeit)
+{
+ LDAPMessage *lm;
+ BerElement ber;
+ int along;
+ unsigned int tag;
+ int i;
+ size_t rc;
+ char * acharp = NULL, *a2ndcharp = NULL, *anoid = NULL;
+ char **arefs = NULL;
+ struct berval * aresp = NULL;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 );
+
+ if ( res == NULLMSG )
+ return (LDAP_PARAM_ERROR);
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ if ((res->lm_msgtype != LDAP_RES_EXTENDED) || (ld->ld_version != LDAP_VERSION3))
+ {
+ if ( res->lm_msgid != 0 )
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_PARAM_ERROR);
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+
+ ber = *(res->lm_ber);
+ rc = ber_scanf( &ber, "{iaa", &along, &acharp, &a2ndcharp);
+ if (rc == LBER_ERROR){
+ if (freeit)
+ ldap_msgfree( res );
+ return (LDAP_DECODING_ERROR);
+ }
+ ldap_memfree(acharp);
+ ldap_memfree(a2ndcharp);
+
+ if (along == LDAP_REFERRAL) {
+ if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_REFERRAL){
+ rc = ber_scanf(&ber, "{v}", &arefs);
+ if (rc == LBER_ERROR){
+ /* try to free other stuff */
+ if (freeit)
+ ldap_msgfree( res );
+ return (LDAP_DECODING_ERROR);
+ }
+ for (i = 0; arefs[i] != NULL; i++)
+ ldap_memfree(arefs[i]);
+ ldap_memfree((char *)arefs);
+ } else {
+ /* There should be at least one ref */
+ if (freeit)
+ ldap_msgfree( res );
+ return (LDAP_DECODING_ERROR);
+ }
+ }
+
+ if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_EXT_RESPNAME) {
+ rc = ber_get_stringa( &ber, &anoid);
+ if (rc == LBER_ERROR ){
+ if (freeit)
+ ldap_msgfree(res);
+ return (LDAP_DECODING_ERROR);
+ }
+ if (resultoidp) {
+ *resultoidp = anoid;
+ } else {
+ ldap_memfree( anoid );
+ }
+ }
+ if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_EXT_RESPONSE) {
+ rc = ber_get_stringal( &ber, &aresp);
+ if (rc == LBER_ERROR ){
+ if (freeit)
+ ldap_msgfree(res);
+ return (LDAP_DECODING_ERROR);
+ }
+ if (resultdata) {
+ *resultdata = aresp;
+ } else {
+ ber_bvfree( aresp );
+ }
+ }
+
+ rc = ber_scanf(&ber, "}");
+ if (rc == LBER_ERROR){
+ if (freeit)
+ ldap_msgfree( res );
+ return (LDAP_DECODING_ERROR);
+ }
+
+ if ( freeit )
+ ldap_msgfree(res);
+
+ return (along);
+}
+
+
+static int Ref_AddToRequest(LDAPRequest *lr, char **refs) {
+ int count;
+ LDAPRef *lref;
+ LDAPRef *newRef;
+
+ if ((newRef = (LDAPRef *)calloc(1, sizeof (LDAPRef))) == NULL){
+ return LDAP_NO_MEMORY;
+ }
+ newRef->lref_refs = refs;
+ newRef->lref_next = NULL;
+ lref = lr->lr_references;
+ if (lref == NULL){
+ lr->lr_references = newRef;
+ } else {
+ while (lref->lref_next != NULL)
+ lref = lref->lref_next;
+ lref->lref_next = newRef;
+ }
+ return LDAP_SUCCESS;
+}
+
+static void Ref_FreeAll(LDAPRequest *lr)
+{
+ LDAPRef *lref, *next;
+ lref = lr->lr_references;
+ while (lref != NULL){
+ next = lref->lref_next;
+ ldap_value_free(lref->lref_refs);
+ free (lref);
+ lref = next;
+ }
+ lr->lr_references = NULL;
+}
diff --git a/usr/src/lib/libldap4/common/saslbind.c b/usr/src/lib/libldap4/common/saslbind.c
new file mode 100644
index 0000000000..eede4b1599
--- /dev/null
+++ b/usr/src/lib/libldap4/common/saslbind.c
@@ -0,0 +1,340 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+#include "sec.h"
+#include <strings.h>
+
+BerElement * ldap_build_sasl_bind_req( LDAP *ld, char *dn, char *mechanism, struct berval *creds, LDAPControl ** serverctrls)
+{
+ BerElement *ber = NULL;
+ int err;
+
+ /* Create a Bind Request for SASL authentication.
+ * It look like this :
+ * BindRequest := [APPLICATION 0] SEQUENCE {
+ * version INTEGER,
+ * name LDAPDN,
+ * authentication CHOICE {
+ * sasl [3] SEQUENCE {
+ * mechanism LDAPString,
+ * credential OCTET STRING OPTIONAL
+ * }
+ * }
+ * }
+ * all wrapped up in an LDAPMessage sequence.
+ */
+
+ if (dn == NULL || *dn == '\0'){
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return (NULLBER);
+ }
+
+
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ return (NULLBER);
+ }
+ if ( ber_printf( ber, "{it{ist{s", ++ld->ld_msgid, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism) == -1){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+ if (creds != NULL && creds->bv_val != NULL) {
+ if (ber_printf(ber, "o", creds->bv_val, creds->bv_len) == -1){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+ }
+ if (ber_printf(ber, "}}") == -1){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ return (ber);
+}
+
+/*
+ * ldap_sasl_bind - bind to the ldap server (and X.500).
+ * dn, mechanism, cred, serverctrls, and clientctrls are supplied.
+ * the message id of the request is returned in msgid
+ * Returns LDAP_SUCCESS or an error code.
+ */
+
+int ldap_sasl_bind(
+ LDAP *ld,
+ char *dn,
+ char *mechanism,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp)
+{
+ int theErr = LDAP_SUCCESS;
+ int rv;
+ BerElement *ber = NULL;
+
+ Debug ( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1288, "ldap_sasl_bind\n"), 0,0,0);
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ if (strcasecmp(mechanism, LDAP_SASL_SIMPLE) == 0){
+ /* Simple bind */
+ if ( (ber = ldap_build_simple_bind_req(ld, dn, cred->bv_val, serverctrls)) == NULLBER){
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (theErr);
+ }
+ }
+
+ if (strcasecmp(mechanism, LDAP_SASL_CRAM_MD5) == 0){
+ if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_CRAM_MD5, cred, serverctrls)) == NULLBER) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (theErr);
+ }
+ }
+
+ if (strcasecmp(mechanism, LDAP_SASL_EXTERNAL) == 0){
+ if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_EXTERNAL, cred, serverctrls)) == NULLBER) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (theErr);
+ }
+ }
+
+ if (strcasecmp(mechanism, LDAP_SASL_X511_PROTECTED) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (strcasecmp(mechanism, LDAP_SASL_X511_STRONG) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (strcasecmp(mechanism, LDAP_SASL_KERBEROS_V4) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (strcasecmp(mechanism, LDAP_SASL_GSSAPI) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (strcasecmp(mechanism, LDAP_SASL_SKEY) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (ber == NULL){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_PARAM_ERROR);
+ }
+
+#ifndef NO_CACHE
+ if ( ld->ld_cache != NULL ) {
+ ldap_flush_cache( ld );
+ }
+#endif /* !NO_CACHE */
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_BIND, dn, ber );
+ if (rv == -1){
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS){
+ rv = LDAP_OTHER;
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+ *msgidp = rv;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return ( LDAP_SUCCESS );
+}
+
+/*
+ * ldap_sasl_bind_s - bind to the ldap server (and X.500).
+ * dn, mechanism, cred, serverctrls, and clientctrls are supplied.
+ * the message id of the request is returned in msgid
+ * Returns LDAP_SUCCESS or an error code.
+ */
+
+int ldap_sasl_bind_s(
+ LDAP *ld,
+ char *dn,
+ char *mechanism,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct berval **servercredp)
+{
+ int msgid;
+ int retcode;
+ LDAPMessage *res;
+
+ Debug ( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1288, "ldap_sasl_bind\n"), 0,0,0);
+
+ if ((retcode = ldap_sasl_bind(ld, dn, mechanism, cred, serverctrls, clientctrls, &msgid)) != LDAP_SUCCESS)
+ return (retcode);
+ if (ldap_result(ld, msgid, 1, (struct timeval *)NULL, &res ) == -1)
+ return (ld->ld_errno );
+
+ return (ldap_parse_sasl_bind_result(ld, res, servercredp, 1));
+}
+
+int ldap_sasl_cram_md5_bind_s(
+ LDAP *ld,
+ char *dn,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls )
+{
+ int res;
+ struct berval *challenge = NULL;
+ struct berval resp;
+ unsigned char digest[16];
+ char *theHDigest;
+
+ if (dn == NULL){
+ return (LDAP_PARAM_ERROR);
+ }
+
+ bzero(digest, sizeof (digest));
+
+ if ((res = ldap_sasl_bind_s(ld, dn, LDAP_SASL_CRAM_MD5, NULL, serverctrls, clientctrls, &challenge))
+ != LDAP_SASL_BIND_INPROGRESS){
+ return (res);
+ }
+ if (challenge == NULL){
+ return (LDAP_PARAM_ERROR);
+ }
+
+ Debug (LDAP_DEBUG_TRACE, "SASL challenge: %s\n", challenge->bv_val, 0, 0);
+
+ hmac_md5((unsigned char *)challenge->bv_val, challenge->bv_len,
+ (unsigned char *)cred->bv_val, cred->bv_len, digest);
+ ber_bvfree(challenge);
+ challenge = NULL;
+
+ theHDigest = hexa_print(digest, 16);
+ if (theHDigest == NULL){
+ return (LDAP_NO_MEMORY);
+ }
+
+ resp.bv_len = (strlen(dn) + 32 + 1);
+ if ((resp.bv_val = (char *)malloc(resp.bv_len+1)) == NULL) {
+ return(LDAP_NO_MEMORY);
+ }
+
+ sprintf(resp.bv_val, "%s %s", dn, theHDigest);
+ free(theHDigest);
+
+ Debug (LDAP_DEBUG_TRACE, "SASL response: %s\n", resp.bv_val, 0, 0);
+ res = ldap_sasl_bind_s(ld, dn, LDAP_SASL_CRAM_MD5, &resp, serverctrls, clientctrls, &challenge);
+
+ free(resp.bv_val);
+ return (res);
+}
diff --git a/usr/src/lib/libldap4/common/sbind.c b/usr/src/lib/libldap4/common/sbind.c
new file mode 100644
index 0000000000..4ae8b354cc
--- /dev/null
+++ b/usr/src/lib/libldap4/common/sbind.c
@@ -0,0 +1,171 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1993 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * sbind.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MACOS
+#include "macos.h"
+#endif /* MACOS */
+
+#if !defined( MACOS ) && !defined( DOS )
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+BerElement * ldap_build_simple_bind_req(LDAP *ld, char *dn, char *passwd, LDAPControl **serverctrls)
+{
+ /*
+ * The bind request looks like this:
+ * BindRequest ::= SEQUENCE {
+ * version INTEGER,
+ * name DistinguishedName, -- who
+ * authentication CHOICE {
+ * simple [0] OCTET STRING -- passwd
+ * }
+ * }
+ * all wrapped up in an LDAPMessage sequence.
+ */
+
+ BerElement *ber = NULL;
+
+ if ( dn == NULL )
+ dn = "";
+ if ( passwd == NULL )
+ passwd = "";
+
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ return (NULLBER);
+ }
+
+ /* fill it in */
+ if ( ber_printf( ber, "{it{ists}", ++ld->ld_msgid, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SIMPLE, passwd ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ return (ber);
+}
+
+/*
+ * ldap_simple_bind - bind to the ldap server (and X.500). The dn and
+ * password of the entry to which to bind are supplied. The message id
+ * of the request initiated is returned.
+ *
+ * Example:
+ * ldap_simple_bind( ld, "cn=manager, o=university of michigan, c=us",
+ * "secret" )
+ */
+
+int
+ldap_simple_bind( LDAP *ld, char *dn, char *passwd )
+{
+ BerElement *ber;
+ int rv;
+
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 240, "ldap_simple_bind\n"), 0, 0, 0 );
+
+ if ( dn == NULL )
+ dn = "";
+ if ( passwd == NULL )
+ passwd = "";
+
+ /* create a message to send */
+ if ( (ber = ldap_build_simple_bind_req( ld, dn, passwd, NULL )) == NULLBER ) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+#ifndef NO_CACHE
+ if ( ld->ld_cache != NULL ) {
+ ldap_flush_cache( ld );
+ }
+#endif /* !NO_CACHE */
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_BIND, dn, ber );
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return ( rv );
+}
+
+/*
+ * ldap_simple_bind - bind to the ldap server (and X.500) using simple
+ * authentication. The dn and password of the entry to which to bind are
+ * supplied. LDAP_SUCCESS is returned upon success, the ldap error code
+ * otherwise.
+ *
+ * Example:
+ * ldap_simple_bind_s( ld, "cn=manager, o=university of michigan, c=us",
+ * "secret" )
+ */
+
+int
+ldap_simple_bind_s( LDAP *ld, char *dn, char *passwd )
+{
+ int msgid;
+ LDAPMessage *result;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 241, "ldap_simple_bind_s\n"), 0, 0, 0 );
+
+ if ( (msgid = ldap_simple_bind( ld, dn, passwd )) == -1 )
+ return( ld->ld_errno );
+
+ if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 )
+ return( ld->ld_errno ); /* ldap_result sets ld_errno */
+
+ return( ldap_result2error( ld, result, 1 ) );
+}
diff --git a/usr/src/lib/libldap4/common/search.c b/usr/src/lib/libldap4/common/search.c
new file mode 100644
index 0000000000..ca0910aa6d
--- /dev/null
+++ b/usr/src/lib/libldap4/common/search.c
@@ -0,0 +1,939 @@
+/*
+ *
+ * Copyright (c) 1998-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * search.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h> /* free() for Solaris */
+
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#endif /* MACOS */
+
+#if defined(DOS) || defined(_WIN32)
+#include "msdos.h"
+#endif /* DOS */
+
+#if !defined(MACOS) && !defined(DOS) && !defined(_WIN32)
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+#ifdef NEEDPROTOS
+static char *find_right_paren(char *s);
+static char *put_complex_filter(BerElement *ber, char *str,
+ unsigned int tag, int not);
+static int put_filter(BerElement *ber, char *str);
+static int put_simple_filter(BerElement *ber, char *str);
+static int put_substring_filter(BerElement *ber, char *type, char *str);
+static int put_filter_list(BerElement *ber, char *str);
+static char *star_search(char *str);
+static int hex_char2int(char c);
+static int decode_value(char *str);
+#else
+static char *find_right_paren();
+static char *put_complex_filter();
+static int put_filter();
+static int put_simple_filter();
+static int put_substring_filter();
+static int put_filter_list();
+static char *star_search();
+static int hex_char2int();
+static int decode_value();
+#endif /* NEEDPROTOS */
+
+
+BerElement *
+ldap_build_search_req(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, LDAPControl ** serverctrls,
+ struct timeval *timeoutp, int sizelimit)
+{
+ BerElement *ber;
+ int err;
+ int theSizeLimit, theTimeLimit;
+ char *theFilter;
+
+ /*
+ * Create the search request. It looks like this:
+ * SearchRequest := [APPLICATION 3] SEQUENCE {
+ * baseObject DistinguishedName,
+ * scope ENUMERATED {
+ * baseObject (0),
+ * singleLevel (1),
+ * wholeSubtree (2)
+ * },
+ * derefAliases ENUMERATED {
+ * neverDerefaliases (0),
+ * derefInSearching (1),
+ * derefFindingBaseObj (2),
+ * alwaysDerefAliases (3)
+ * },
+ * sizelimit INTEGER (0 .. 65535),
+ * timelimit INTEGER (0 .. 65535),
+ * attrsOnly BOOLEAN,
+ * filter Filter,
+ * attributes SEQUENCE OF AttributeType
+ * }
+ * wrapped in an ldap message.
+ */
+
+ if (filter == NULL || *filter == '\0') {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return (NULLBER);
+ }
+
+ /* create a message to send */
+ if ((ber = alloc_ber_with_options(ld)) == NULLBER) {
+ return (NULLBER);
+ }
+
+ if (base == NULL) {
+ base = "";
+ }
+
+ if (timeoutp != NULL) {
+ if (timeoutp->tv_sec > 0) {
+ theTimeLimit = (int)(timeoutp->tv_sec +
+ (timeoutp->tv_usec / 1000000));
+ } else if (timeoutp->tv_usec > 0) {
+ theTimeLimit = 1; /* minimum we can express in LDAP */
+ } else {
+ theTimeLimit = 0; /* no limit */
+ }
+ } else {
+ theTimeLimit = ld->ld_timelimit;
+ }
+
+#ifdef CLDAP
+ if (ld->ld_sb.sb_naddr > 0) {
+ err = ber_printf(ber, "{ist{seeiib", ++ld->ld_msgid,
+ ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
+ sizelimit == -1 ? ld->ld_sizelimit : sizelimit, theTimeLimit,
+ attrsonly);
+ } else {
+#endif /* CLDAP */
+ err = ber_printf(ber, "{it{seeiib", ++ld->ld_msgid,
+ LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
+ sizelimit == -1 ? ld->ld_sizelimit : sizelimit,
+ theTimeLimit, attrsonly);
+#ifdef CLDAP
+ }
+#endif /* CLDAP */
+
+ if (err == -1) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+
+ theFilter = filter;
+ while (*theFilter == ' ') theFilter++;
+ if ((*theFilter == '&') || (*theFilter == '|') || (*theFilter == '!')) {
+ char *ptr = theFilter;
+ theFilter = (char *)calloc(1, strlen(ptr) + 3);
+ sprintf(theFilter, "(%s)", ptr);
+ } else {
+ theFilter = strdup(filter);
+ }
+ err = put_filter(ber, theFilter);
+ free(theFilter);
+
+ if (err == -1) {
+ ld->ld_errno = LDAP_FILTER_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+
+ if (ber_printf(ber, "{v}}", attrs) == -1) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+ }
+
+ if (ber_printf(ber, "}") == -1) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+
+ return (ber);
+}
+
+/*
+ * ldap_search - initiate an ldap (and X.500) search operation. Parameters:
+ *
+ * ld LDAP descriptor
+ * base DN of the base object
+ * scope the search scope - one of LDAP_SCOPE_BASE,
+ * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
+ * filter a string containing the search filter
+ * (e.g., "(|(cn=bob)(sn=bob))")
+ * attrs list of attribute types to return for matches
+ * attrsonly 1 => attributes only 0 => attributes and values
+ *
+ * Example:
+ * char *attrs[] = { "mail", "title", 0 };
+ * msgid = ldap_search( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob",
+ * attrs, attrsonly );
+ */
+int
+ldap_search(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly)
+{
+ BerElement *ber;
+
+#if defined(SUN) && defined(_REENTRANT)
+ int rv;
+
+ LOCK_LDAP(ld);
+#endif
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 242, "ldap_search\n"),
+ 0, 0, 0);
+
+ if ((ber = ldap_build_search_req(ld, base, scope, filter, attrs,
+ attrsonly, NULL, NULL, -1)) == NULLBER) {
+#if defined(SUN) && defined(_REENTRANT)
+ UNLOCK_LDAP(ld);
+#endif
+ return (-1);
+ }
+
+#ifndef NO_CACHE
+ if (ld->ld_cache != NULL) {
+ if (check_cache(ld, LDAP_REQ_SEARCH, ber) == 0) {
+ ber_free(ber, 1);
+ ld->ld_errno = LDAP_SUCCESS;
+ rv = ld->ld_msgid;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+ add_request_to_cache(ld, LDAP_REQ_SEARCH, ber);
+ }
+#endif /* NO_CACHE */
+
+ /* send the message */
+ rv = send_initial_request(ld, LDAP_REQ_SEARCH, base, ber);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+}
+
+
+static char *
+find_right_paren(char *s)
+{
+ int balance, escape;
+
+ balance = 1;
+ escape = 0;
+ while (*s && balance) {
+ if (escape == 0) {
+ if (*s == '(')
+ balance++;
+ else if (*s == ')')
+ balance--;
+ }
+ if (*s == '\\' && ! escape)
+ escape = 1;
+ else
+ escape = 0;
+ if (balance)
+ s++;
+ }
+
+ return (*s ? s : NULL);
+}
+
+static char *
+put_complex_filter(BerElement *ber, char *str, unsigned int tag, int not)
+{
+ char *next;
+
+ /*
+ * We have (x(filter)...) with str sitting on
+ * the x. We have to find the paren matching
+ * the one before the x and put the intervening
+ * filters by calling put_filter_list().
+ */
+
+ /* put explicit tag */
+ if (ber_printf(ber, "t{", tag) == -1)
+ return (NULL);
+/*
+ if (!not && ber_printf(ber, "{") == -1)
+ return (NULL);
+*/
+
+ str++;
+ if ((next = find_right_paren(str)) == NULL)
+ return (NULL);
+
+ *next = '\0';
+ if (put_filter_list(ber, str) == -1)
+ return (NULL);
+ *next++ = ')';
+
+ /* flush explicit tagged thang */
+ if (ber_printf(ber, "}") == -1)
+ return (NULL);
+/*
+ if (!not && ber_printf(ber, "}") == -1)
+ return (NULL);
+*/
+
+ return (next);
+}
+
+static int
+put_filter(BerElement *ber, char *str)
+{
+ char *next, *tmp, *s, *d;
+ int parens, balance, escape;
+ int multipleparen = 0;
+
+ /*
+ * A Filter looks like this:
+ * Filter ::= CHOICE {
+ * and [0] SET OF Filter,
+ * or [1] SET OF Filter,
+ * not [2] Filter,
+ * equalityMatch [3] AttributeValueAssertion,
+ * substrings [4] SubstringFilter,
+ * greaterOrEqual [5] AttributeValueAssertion,
+ * lessOrEqual [6] AttributeValueAssertion,
+ * present [7] AttributeType,
+ * approxMatch [8] AttributeValueAssertion,
+ * extensibleMatch [9] MatchingRuleAssertion
+ * }
+ *
+ * SubstringFilter ::= SEQUENCE {
+ * type AttributeType,
+ * SEQUENCE OF CHOICE {
+ * initial [0] IA5String,
+ * any [1] IA5String,
+ * final [2] IA5String
+ * }
+ * }
+ * MatchingRuleAssertion ::= SEQUENCE {
+ * matchingRule [1] MatchingRuleId OPTIONAL,
+ * type [2] AttributeDescription OPTIONAL,
+ * matchValue [3] AssertionValue,
+ * dnAttributes [4] BOOLEAN DEFAULT FALSE
+ * }
+ *
+ * Note: tags in a choice are always explicit
+ */
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 243,
+ "put_filter \"%s\"\n"), str, 0, 0);
+
+ parens = 0;
+ while (*str) {
+ switch (*str) {
+ case '(':
+ str++;
+ parens++;
+ switch (*str) {
+ case '&':
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1,
+ 244, "put_filter: AND\n"), 0, 0, 0);
+
+ if ((str = put_complex_filter(ber, str,
+ LDAP_FILTER_AND, 0)) == NULL)
+ return (-1);
+
+ parens--;
+ break;
+
+ case '|':
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1,
+ 245, "put_filter: OR\n"), 0, 0, 0);
+
+ if ((str = put_complex_filter(ber, str,
+ LDAP_FILTER_OR, 0)) == NULL)
+ return (-1);
+
+ parens--;
+ break;
+
+ case '!':
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1,
+ 246, "put_filter: NOT\n"), 0, 0, 0);
+
+ if ((str = put_complex_filter(ber, str,
+ LDAP_FILTER_NOT, 1)) == NULL)
+ return (-1);
+
+ parens--;
+ break;
+
+ case '(':
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1,
+ 402, "put_filter: Double Parentheses\n"),
+ 0, 0, 0);
+ multipleparen++;
+ continue;
+
+ default:
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1,
+ 247, "put_filter: simple\n"), 0, 0, 0);
+
+ balance = 1;
+ escape = 0;
+ next = str;
+ while (*next && balance) {
+ if (escape == 0) {
+ if (*next == '(')
+ balance++;
+ else if (*next == ')')
+ balance--;
+ }
+ if (*next == '\\' && ! escape)
+ escape = 1;
+ else
+ escape = 0;
+ if (balance)
+ next++;
+ }
+ if (balance != 0)
+ return (-1);
+
+ *next = '\0';
+ if (put_simple_filter(ber, str) == -1)
+ return (-1);
+ *next++ = ')';
+ str = next;
+ parens--;
+ break;
+ }
+ break;
+
+ case ')':
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 248,
+ "put_filter: end\n"), 0, 0, 0);
+ if (multipleparen) {
+ multipleparen--;
+ } else {
+ if (ber_printf(ber, "]") == -1)
+ return (-1);
+ }
+
+ str++;
+ parens--;
+ break;
+
+ case ' ':
+ str++;
+ break;
+
+ default: /* assume it's a simple type=value filter */
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 249,
+ "put_filter: default\n"), 0, 0, 0);
+ next = strchr(str, '\0');
+ if (put_simple_filter(ber, str) == -1) {
+ return (-1);
+ }
+ str = next;
+ break;
+ }
+ }
+
+ return (parens ? -1 : 0);
+}
+
+/*
+ * Put a list of filters like this "(filter1)(filter2)..."
+ */
+
+static int
+put_filter_list(BerElement *ber, char *str)
+{
+ char *next;
+ char save;
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 250,
+ "put_filter_list \"%s\"\n"), str, 0, 0);
+
+ while (*str) {
+ while (*str && isspace(*str))
+ str++;
+ if (*str == '\0')
+ break;
+
+ if ((next = find_right_paren(str + 1)) == NULL)
+ return (-1);
+ save = *++next;
+
+ /* now we have "(filter)" with str pointing to it */
+ *next = '\0';
+ if (put_filter(ber, str) == -1)
+ return (-1);
+ *next = save;
+
+ str = next;
+ }
+
+ return (0);
+}
+
+static int
+put_simple_filter(BerElement *ber, char *str)
+{
+ char *s;
+ char *value, savechar;
+ unsigned int ftype;
+ int rc;
+ int len;
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 251,
+ "put_simple_filter \"%s\"\n"), str, 0, 0);
+
+ if ((s = strchr(str, '=')) == NULL)
+ return (-1);
+ value = s + 1;
+ *s-- = '\0';
+ savechar = *s;
+
+ switch (*s) {
+ case '<':
+ ftype = LDAP_FILTER_LE;
+ *s = '\0';
+ break;
+ case '>':
+ ftype = LDAP_FILTER_GE;
+ *s = '\0';
+ break;
+ case '~':
+ ftype = LDAP_FILTER_APPROX;
+ *s = '\0';
+ break;
+ /* LDAP V3 : New extensible matching */
+ case ':':
+ rc = put_extensible_filter(ber, str, value);
+ *(value -1) = '=';
+ return (rc);
+ default:
+ if (star_search(value) == NULL) {
+ ftype = LDAP_FILTER_EQUALITY;
+ } else if (strcmp(value, "*") == 0) {
+ ftype = LDAP_FILTER_PRESENT;
+ } else {
+ rc = put_substring_filter(ber, str, value);
+ *(value-1) = '=';
+ return (rc);
+ }
+ break;
+ }
+
+ if (*(value -1) == '=')
+ return (rc);
+ if (ftype == LDAP_FILTER_PRESENT) {
+ rc = ber_printf(ber, "ts", ftype, str);
+ } else {
+ if ((len = decode_value(value)) >= 0)
+ rc = ber_printf(ber, "t{so}", ftype, str, value, len);
+ }
+
+ *s = savechar;
+ *(value-1) = '=';
+ return (rc == -1 ? rc : 0);
+}
+
+static int
+put_substring_filter(BerElement *ber, char *type, char *val)
+{
+ char *nextstar, gotstar = 0;
+ unsigned int ftype;
+ int len;
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 252,
+ "put_substring_filter \"%1$s=%2$s\"\n"), type, val, 0);
+
+ if (ber_printf(ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type) == -1)
+ return (-1);
+
+ while (val != NULL) {
+ if ((nextstar = star_search(val)) != NULL)
+ *nextstar++ = '\0';
+
+ if (gotstar == 0) {
+ ftype = LDAP_SUBSTRING_INITIAL;
+ } else if (nextstar == NULL) {
+ ftype = LDAP_SUBSTRING_FINAL;
+ } else {
+ ftype = LDAP_SUBSTRING_ANY;
+ }
+ if (*val != '\0') {
+ if ((len = decode_value(val)) == -1 ||
+ ber_printf(ber, "to", ftype, val, len) == -1)
+ return (-1);
+ }
+
+ gotstar = 1;
+ if (nextstar != NULL)
+ *(nextstar-1) = '*';
+ val = nextstar;
+ }
+
+ if (ber_printf(ber, "}}") == -1)
+ return (-1);
+
+ return (0);
+}
+
+static int
+put_extensible_filter(BerElement *ber, char *type, char *val)
+{
+ char *ptr, *ptype;
+ char *dn, *rule;
+ int len;
+
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 252,
+ "put_extensible_filter \"%1$s=%2$s\"\n"), type, val, 0);
+
+ /* type is off form : attr:dn:matchingrule: or :dn:matchingrule: */
+ /* type ends with ':', suppress it */
+ ptr = strdup(type);
+ ptype = ptr;
+ while (*ptype) {
+ *ptype = tolower(*ptype);
+ ptype++;
+ }
+
+ len = strlen(ptr);
+ if (len > 0 && ptr[len -1] == ':')
+ ptr [len - 1] = '\0';
+ else {
+ return (-1);
+ }
+
+ ptype = ptr;
+ /* Search first ':dn' */
+ if ((dn = strstr(ptype, ":dn")) == NULL) {
+ /* No dn */
+ /* if there's a : its separating type and matching rule */
+ rule = strchr(ptype, ':');
+ if (rule == ptype) {
+ ptype = NULL;
+ }
+ } else {
+ if (dn == ptype) {
+ ptype = NULL;
+ } else {
+ *dn = '\0';
+ }
+
+ rule = dn + 3;
+ }
+
+ if (rule && rule[0] == ':') {
+ rule[0] = '\0';
+ rule++;
+ } else {
+ rule = NULL;
+ }
+
+ if ((ptype == NULL || *ptype == '\0') && rule == NULL) {
+ free(ptr);
+ return (-1);
+ }
+
+ if (ber_printf(ber, "t{", LDAP_FILTER_EXTENSIBLE) == -1) {
+ free(ptr);
+ return (-1);
+ }
+
+ if (rule && *rule && (ber_printf(ber, "ts",
+ LDAP_TAG_FEXT_RULE, rule) == -1)) {
+ free(ptr);
+ return (-1);
+ }
+
+ if (ptype && *ptype && (ber_printf(ber, "ts",
+ LDAP_TAG_FEXT_TYPE, ptype) == -1)) {
+ free(ptr);
+ return (-1);
+ }
+
+ /* Code value */
+ if ((len = decode_value(val)) == -1 ||
+ ber_printf(ber, "to", LDAP_TAG_FEXT_VAL, val, len) == -1) {
+ free(ptr);
+ return (-1);
+ }
+
+ if (dn && (ber_printf(ber, "tb", LDAP_TAG_FEXT_DN, 1) == -1)) {
+ free(ptr);
+ return (-1);
+ }
+
+ free(ptr);
+
+ if (ber_printf(ber, "}") == -1)
+ return (-1);
+
+ return (0);
+}
+
+int
+ldap_search_st(LDAP *ld, char *base, int scope, char *filter, char **attrs,
+ int attrsonly, struct timeval *timeout, LDAPMessage **res)
+{
+ int msgid;
+
+ if ((msgid = ldap_search(ld, base, scope, filter, attrs, attrsonly))
+ == -1)
+ return (ld->ld_errno);
+
+ if (ldap_result(ld, msgid, 1, timeout, res) == -1)
+ return (ld->ld_errno);
+
+ if (ld->ld_errno == LDAP_TIMEOUT) {
+ (void) ldap_abandon(ld, msgid);
+ ld->ld_errno = LDAP_TIMEOUT;
+ return (ld->ld_errno);
+ }
+
+ return (ldap_result2error(ld, *res, 0));
+}
+
+int
+ldap_search_s(LDAP *ld, char *base, int scope, char *filter, char **attrs,
+ int attrsonly, LDAPMessage **res)
+{
+ int msgid;
+
+ if ((msgid = ldap_search(ld, base, scope, filter, attrs, attrsonly))
+ == -1)
+ return (ld->ld_errno);
+
+ if (ldap_result(ld, msgid, 1, (struct timeval *)NULL, res) == -1)
+ return (ld->ld_errno);
+
+ return (ldap_result2error(ld, *res, 0));
+}
+
+/* LDAPv3 API EXTENSIONS */
+int ldap_search_ext(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, LDAPControl **serverctrls,
+ LDAPControl **clientctrls, struct timeval *timeoutp, int sizelimit,
+ int *msgidp)
+{
+ BerElement *ber;
+ int rv;
+
+ if (timeoutp != NULL && timeoutp->tv_sec == 0 &&
+ timeoutp->tv_usec == 0) {
+ timeoutp = NULL;
+ }
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 242,
+ "ldap_search\n"), 0, 0, 0);
+
+ if ((ber = ldap_build_search_req(ld, base, scope, filter, attrs,
+ attrsonly, serverctrls, timeoutp, sizelimit)) == NULLBER) {
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS)
+ rv = LDAP_OTHER;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+#ifndef NO_CACHE
+ if (ld->ld_cache != NULL) {
+ if (check_cache(ld, LDAP_REQ_SEARCH, ber) == 0) {
+ ber_free(ber, 1);
+ ld->ld_errno = LDAP_SUCCESS;
+ *msgidp = ld->ld_msgid;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_SUCCESS);
+ }
+ add_request_to_cache(ld, LDAP_REQ_SEARCH, ber);
+ }
+#endif /* NO_CACHE */
+
+ /* send the message */
+ rv = send_initial_request(ld, LDAP_REQ_SEARCH, base, ber);
+ if (rv == -1) {
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS) {
+ rv = LDAP_OTHER;
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+
+ *msgidp = rv;
+#if _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_SUCCESS);
+}
+
+
+int ldap_search_ext_s(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, LDAPControl **serverctrls,
+ LDAPControl **clientctrls, struct timeval *timeoutp, int sizelimit,
+ LDAPMessage **res)
+{
+ int msgid;
+ int retcode = LDAP_SUCCESS;
+
+ if ((retcode = ldap_search_ext(ld, base, scope, filter, attrs,
+ attrsonly, serverctrls, clientctrls, timeoutp, sizelimit,
+ &msgid)) != LDAP_SUCCESS)
+ return (retcode);
+ if (ldap_result(ld, msgid, 1, timeoutp, res) == -1)
+ return (ld->ld_errno);
+
+
+#if _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ retcode = ldap_parse_result(ld, *res, &ld->ld_errno, &ld->ld_matched,
+ &ld->ld_error, &ld->ld_referrals, &ld->ld_ret_ctrls, 0);
+ if (retcode == LDAP_SUCCESS)
+ retcode = ld->ld_errno;
+#if _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (retcode);
+}
+
+/*
+ * Search string for ascii '*' (asterisk) character.
+ * RFC 1960 permits an escaped asterisk to pass through.
+ * RFC 2254 adds the definition of encoded characters:
+ *
+ * Character ASCII value
+ * ---------------------------
+ * * 0x2a
+ * ( 0x28
+ * ) 0x29
+ * \ 0x5c
+ * NUL 0x00
+ *
+ * No distinction of escaped characters is made here.
+ */
+static char *
+star_search(char *str)
+{
+ for (; *str; str++) {
+ switch (*str) {
+ case '*':
+ return (str);
+ case '\\':
+ if (str[1] == '\0')
+ break; /* input string exahausted */
+ ++str; /* Assume RFC 1960 escaped character */
+ /* Check for RFC 2254 hex encoding */
+ if (hex_char2int(str[0]) >= 0 &&
+ hex_char2int(str[1]) >= 0) {
+ str++; /* skip over RFC 2254 hex encoding */
+ }
+ default:
+ break;
+ }
+ }
+ return (NULL);
+}
+
+/*
+ * Return integer value of hexadecimal character or (-1) if character is
+ * not a hexadecimal digit [0-9A-Fa-f].
+ */
+static int
+hex_char2int(char c)
+{
+ if (c >= '0' && c <= '9') {
+ return (c-'0');
+ } else if (c >= 'A' && c <= 'F') {
+ return (c-'A'+10);
+ } else if (c >= 'a' && c <= 'f') {
+ return (c-'a'+10);
+ }
+ return (-1);
+}
+
+/*
+ * Modifys passed string converting escaped hexadecimal characters as
+ * per RFC 2254 and un-escapes escaped characters. Returns length of
+ * modified string as it may contain null characters as per RFC 2254.
+ */
+static int
+decode_value(char *start)
+{
+ char *read, *write;
+ int hn, ln;
+
+ for (read = write = start; *read; *write++ = *read++) {
+ if (*read == '\\') {
+ if (*++read == '\0')
+ break; /* input string exahausted */
+ /*
+ * Assume *read is simple RFC 1960 escaped character.
+ * However check for RFC 2254 hex encoding.
+ */
+ if ((hn = hex_char2int(read[0])) >= 0 &&
+ (ln = hex_char2int(read[1])) >= 0) {
+ read++;
+ *read = (hn<<4)+ln;
+ }
+ }
+ }
+ *write = '\0';
+ return (write-start);
+}
+
diff --git a/usr/src/lib/libldap4/common/sort.c b/usr/src/lib/libldap4/common/sort.c
new file mode 100644
index 0000000000..d26afb5200
--- /dev/null
+++ b/usr/src/lib/libldap4/common/sort.c
@@ -0,0 +1,180 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1994 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ *
+ * sort.c: LDAP library entry and value sort routines
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#ifdef MACOS
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include <malloc.h>
+#include "msdos.h"
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+struct entrything {
+ char **et_vals;
+ LDAPMessage *et_msg;
+};
+
+#ifndef NEEDPROTOS
+static int (*et_cmp_fn)();
+static int et_cmp();
+#else /* !NEEDPROTOS */
+static int (*et_cmp_fn)( char *a, char *b );
+#ifdef SUN
+static int et_cmp( const void *aa, const void *bb);
+#else
+static int et_cmp( void *aa, void *bb);
+#endif
+#endif /* !NEEDPROTOS */
+
+int
+ldap_sort_strcasecmp(
+ char **a,
+ char **b
+)
+{
+ return( strcasecmp( *a, *b ) );
+}
+
+static int
+et_cmp(
+#ifdef SUN
+ const void *aa,
+ const void *bb
+#else
+ void *aa,
+ void *bb
+#endif
+)
+{
+ int i, rc;
+ struct entrything *a = (struct entrything *)aa;
+ struct entrything *b = (struct entrything *)bb;
+
+ if ( a->et_vals == NULL && b->et_vals == NULL )
+ return( 0 );
+ if ( a->et_vals == NULL )
+ return( -1 );
+ if ( b->et_vals == NULL )
+ return( 1 );
+
+ for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) {
+ if ( (rc = (*et_cmp_fn)( a->et_vals[i], b->et_vals[i] ))
+ != 0 ) {
+ return( rc );
+ }
+ }
+
+ if ( a->et_vals[i] == NULL && b->et_vals[i] == NULL )
+ return( 0 );
+ if ( a->et_vals[i] == NULL )
+ return( -1 );
+ return( 1 );
+}
+
+int
+ldap_sort_entries(
+ LDAP *ld,
+ LDAPMessage **chain,
+ char *attr, /* NULL => sort by DN */
+ int (*cmp)()
+)
+{
+ int i;
+ size_t count;
+ struct entrything *et;
+ LDAPMessage *e, *last;
+ LDAPMessage **ep;
+
+ count = ldap_count_entries( ld, *chain );
+
+ if ( (et = (struct entrything *) malloc( count *
+ sizeof(struct entrything) )) == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( -1 );
+ }
+
+ e = *chain;
+ for ( i = 0; i < count; i++ ) {
+ et[i].et_msg = e;
+ if ( attr == NULL ) {
+ char *dn;
+
+ dn = ldap_get_dn( ld, e );
+ et[i].et_vals = ldap_explode_dn( dn, 1 );
+ free( dn );
+ } else {
+ et[i].et_vals = ldap_get_values( ld, e, attr );
+ }
+
+ e = e->lm_chain;
+ }
+ last = e;
+
+ et_cmp_fn = cmp;
+#ifdef SUN
+ qsort( et, count, sizeof(struct entrything), et_cmp );
+#else
+ qsort( et, count, sizeof(struct entrything), (void *) et_cmp );
+#endif
+
+ ep = chain;
+ for ( i = 0; i < count; i++ ) {
+ *ep = et[i].et_msg;
+ ep = &(*ep)->lm_chain;
+
+ ldap_value_free( et[i].et_vals );
+ }
+ *ep = last;
+ free( (char *) et );
+
+ return( 0 );
+}
+
+/* ARGSUSED */
+int
+ldap_sort_values(
+ LDAP *ld,
+ char **vals,
+ int (*cmp)()
+)
+{
+ size_t nel;
+
+ for ( nel = 0; vals[nel] != NULL; nel++ )
+ ; /* NULL */
+
+ qsort( vals, nel, sizeof(char *), cmp );
+
+ return( 0 );
+}
diff --git a/usr/src/lib/libldap4/common/sortctrl.c b/usr/src/lib/libldap4/common/sortctrl.c
new file mode 100644
index 0000000000..22dd53e527
--- /dev/null
+++ b/usr/src/lib/libldap4/common/sortctrl.c
@@ -0,0 +1,426 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+static int count_tokens(char *s);
+static int isattrdescchar(char c);
+static int read_next_token(char **s, LDAPsortkey **key);
+
+
+int ldap_create_sort_control(LDAP *ld, LDAPsortkey **sortKeyList,
+ const char ctl_iscritical, LDAPControl **ctrlp)
+{
+ BerElement *ber;
+ int i, rc;
+
+ if (NULL == ld) {
+ return (LDAP_PARAM_ERROR);
+ }
+
+ if (sortKeyList == NULL || ctrlp == NULL) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return (LDAP_PARAM_ERROR);
+ }
+
+ /* create a ber package to hold the controlValue */
+ if ((ber = alloc_ber_with_options(ld)) == NULLBER) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return (LDAP_NO_MEMORY);
+ }
+
+ /* encode the start of the sequence of sequences into the ber */
+ if (ber_printf(ber, "{") == -1) {
+ goto encoding_error_exit;
+ }
+
+ /*
+ * the sort control value will be encoded as a sequence of sequences
+ * which are each encoded as one of the following: {s} or {sts} or
+ * {stb} or {ststb} since the orderingRule and reverseOrder flag are
+ * both optional
+ */
+ for (i = 0; sortKeyList[i] != NULL; i++) {
+
+ /* encode the attributeType into the ber */
+ if (ber_printf(ber, "{s", (sortKeyList[i])->sk_attrtype)
+ == -1) {
+ goto encoding_error_exit;
+ }
+
+ /* encode the optional orderingRule into the ber */
+ if ((sortKeyList[i])->sk_matchruleoid != NULL) {
+ if (ber_printf(ber, "ts", LDAP_TAG_SK_MATCHRULE,
+ (sortKeyList[i])->sk_matchruleoid)
+ == -1) {
+ goto encoding_error_exit;
+ }
+ }
+
+ /* Encode the optional reverseOrder flag into the ber. */
+ /* If the flag is false, it should be absent. */
+ if ((sortKeyList[i])->sk_reverseorder) {
+ if (ber_printf(ber, "tb}", LDAP_TAG_SK_REVERSE,
+ (sortKeyList[i])->sk_reverseorder) == -1) {
+ goto encoding_error_exit;
+ }
+ } else {
+ if (ber_printf(ber, "}") == -1) {
+ goto encoding_error_exit;
+ }
+ }
+ }
+
+ /* encode the end of the sequence of sequences into the ber */
+ if (ber_printf(ber, "}") == -1) {
+ goto encoding_error_exit;
+ }
+
+ rc = ldap_build_control(LDAP_CONTROL_SORTREQUEST, ber, 1,
+ ctl_iscritical, ctrlp);
+ ld->ld_errno = rc;
+ return (rc);
+
+encoding_error_exit:
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (LDAP_ENCODING_ERROR);
+}
+
+
+int ldap_parse_sort_control(LDAP *ld, LDAPControl **ctrlp,
+ unsigned long *result, char **attribute)
+{
+ BerElement *ber;
+ int i, foundSortControl;
+ LDAPControl *sortCtrlp;
+ unsigned int len;
+ char *attr;
+ int tag;
+
+ if ((NULL == ld) || (result == NULL) ||
+ (attribute == NULL)) {
+ return (LDAP_PARAM_ERROR);
+ }
+
+
+ /* find the sortControl in the list of controls if it exists */
+ if (ctrlp == NULL) {
+ ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
+ return (LDAP_CONTROL_NOT_FOUND);
+ }
+ foundSortControl = 0;
+ for (i = 0; ((ctrlp[i] != NULL) && (!foundSortControl)); i++) {
+ foundSortControl = !(strcmp(ctrlp[i]->ldctl_oid,
+ LDAP_CONTROL_SORTRESPONSE));
+ }
+ if (!foundSortControl) {
+ ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
+ return (LDAP_CONTROL_NOT_FOUND);
+ } else {
+ /* let local var point to the sortControl */
+ sortCtrlp = ctrlp[i-1];
+ }
+
+ /*
+ * allocate a Ber element with the contents of the sort_control's
+ * struct berval
+ */
+ if ((ber = ber_init(&sortCtrlp->ldctl_value)) == NULL) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return (LDAP_NO_MEMORY);
+ }
+
+ /* decode the result from the Berelement */
+ if (ber_scanf(ber, "{i", result) == LBER_ERROR) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ ber_free(ber, 1);
+ return (LDAP_DECODING_ERROR);
+ }
+
+ /*
+ * if the server returned one, decode the attribute from the Ber element
+ */
+ if (ber_peek_tag(ber, &len) == LDAP_TAG_SR_ATTRTYPE) {
+ if (ber_scanf(ber, "ta", &tag, &attr) == LBER_ERROR) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ ber_free(ber, 1);
+ return (LDAP_DECODING_ERROR);
+ }
+ *attribute = attr;
+ } else {
+ *attribute = NULL;
+ }
+
+ if (ber_scanf(ber, "}") == LBER_ERROR) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ ber_free(ber, 1);
+ return (LDAP_DECODING_ERROR);
+ }
+
+ /* the ber encoding is no longer needed */
+ ber_free(ber, 1);
+ return (LDAP_SUCCESS);
+}
+
+
+/*
+ * Routines for the manipulation of string-representations of sort control
+ * keylists
+ */
+static int count_tokens(char *s)
+{
+ int count = 0;
+ char *p = s;
+ int whitespace = 1;
+ /*
+ * Loop along the string counting the number of times we see the
+ * beginning of non-whitespace. This tells us
+ * the number of tokens in the string
+ */
+ while (*p != '\0') {
+ if (whitespace) {
+ if (!isspace(*p)) {
+ whitespace = 0;
+ count++;
+ }
+ } else {
+ if (isspace(*p)) {
+ whitespace = 1;
+ }
+ }
+ p++;
+ }
+ return (count);
+}
+
+
+/* Is this character a valid attribute description character ? */
+static int isattrdescchar(char c)
+{
+ /* Alphanumeric chars are in */
+ if (isalnum(c)) {
+ return (1);
+ }
+ /* As is ';' */
+ if (';' == c) {
+ return (1);
+ }
+ /* Everything else is out */
+ return (0);
+}
+
+
+static int read_next_token(char **s, LDAPsortkey **key)
+{
+ char c = 0;
+ char *pos = *s;
+ int retval = 0;
+ LDAPsortkey *new_key = NULL;
+
+ char *matchrule_source = NULL;
+ int matchrule_size = 0;
+ char *attrdesc_source = NULL;
+ int attrdesc_size = 0;
+ int reverse = 0;
+
+ int state = 0;
+
+ while (((c = *pos++) != '\0') && (state != 4)) {
+ switch (state) {
+ case 0:
+ /* case where we've not seen the beginning of the attr yet */
+ /* If we still see whitespace, nothing to do */
+ if (!isspace(c)) {
+ /* Otherwise, something to look at */
+ /* Is it a minus sign ? */
+ if ('-' == c) {
+ reverse = 1;
+ } else {
+ attrdesc_source = pos - 1;
+ state = 1;
+ }
+ }
+ break;
+ case 1:
+ /*
+ * case where we've seen the beginning of the attr, but not
+ * the end
+ */
+ /* Is this char either whitespace or a ':' ? */
+ if (isspace(c) || (':' == c)) {
+ attrdesc_size = (pos - attrdesc_source) - 1;
+ if (':' == c) {
+ state = 2;
+ } else {
+ state = 4;
+ }
+ }
+ break;
+ case 2:
+ /*
+ * case where we've seen the end of the attr and want the
+ * beginning of match rule
+ */
+ if (!isspace(c)) {
+ matchrule_source = pos - 1;
+ state = 3;
+ } else {
+ state = 4;
+ }
+ break;
+ case 3:
+ /*
+ * case where we've seen the beginning of match rule and
+ * want to find the end
+ */
+ if (isspace(c)) {
+ matchrule_size = (pos - matchrule_source) - 1;
+ state = 4;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (3 == state) {
+ /*
+ * means we fell off the end of the string looking for the
+ * end of the marching rule
+ */
+ matchrule_size = (pos - matchrule_source) - 1;
+ }
+
+ if (1 == state) {
+ /*
+ * means we fell of the end of the string looking for the
+ * end of the attribute
+ */
+ attrdesc_size = (pos - attrdesc_source) - 1;
+ }
+
+ if (NULL == attrdesc_source) {
+ /* Didn't find anything */
+ return (-1);
+ }
+
+ new_key = (LDAPsortkey*)malloc(sizeof (LDAPsortkey));
+ if (0 == new_key) {
+ return (LDAP_NO_MEMORY);
+ }
+
+ /* Allocate the strings */
+ new_key->sk_attrtype = (char *)malloc(attrdesc_size + 1);
+ if (NULL != matchrule_source) {
+ new_key->sk_matchruleoid = (char *)malloc(matchrule_size + 1);
+ } else {
+ new_key->sk_matchruleoid = NULL;
+ }
+ /* Copy over the strings */
+ memcpy(new_key->sk_attrtype, attrdesc_source, attrdesc_size);
+ *(new_key->sk_attrtype + attrdesc_size) = '\0';
+ if (NULL != matchrule_source) {
+ memcpy(new_key->sk_matchruleoid, matchrule_source,
+ matchrule_size);
+ *(new_key->sk_matchruleoid + matchrule_size) = '\0';
+ }
+
+ new_key->sk_reverseorder = reverse;
+
+ *s = pos - 1;
+ *key = new_key;
+ return (retval);
+}
+
+
+int
+ldap_create_sort_keylist(LDAPsortkey ***sortKeyList, char *string_rep)
+{
+ int count = 0;
+ LDAPsortkey **pointer_array = NULL;
+ char *current_position = NULL;
+ char *s = NULL;
+ int retval = 0;
+ int i = 0;
+
+ /* Figure out how many there are */
+ if (NULL == string_rep) {
+ return (LDAP_PARAM_ERROR);
+ }
+ if (NULL == sortKeyList) {
+ return (LDAP_PARAM_ERROR);
+ }
+ count = count_tokens(string_rep);
+ if (0 == count) {
+ *sortKeyList = NULL;
+ return (LDAP_PARAM_ERROR);
+ }
+ /* Allocate enough memory for the pointers */
+ pointer_array = (LDAPsortkey**)malloc(sizeof (LDAPsortkey*)
+ * (count + 1));
+ if (NULL == pointer_array) {
+ return (LDAP_NO_MEMORY);
+ }
+ /*
+ * Now walk along the string, allocating and filling in the
+ * LDAPsearchkey structure
+ */
+ current_position = string_rep;
+
+ for (i = 0; i < count; i++) {
+ if (0 != (retval = read_next_token(&current_position,
+ &(pointer_array[i])))) {
+ pointer_array[count] = NULL;
+ ldap_free_sort_keylist(pointer_array);
+ *sortKeyList = NULL;
+ return (retval);
+ }
+ }
+ pointer_array[count] = NULL;
+ *sortKeyList = pointer_array;
+ return (LDAP_SUCCESS);
+}
+
+
+void
+ldap_free_sort_keylist(LDAPsortkey **sortKeyList)
+{
+ LDAPsortkey *this_one = NULL;
+ int i = 0;
+
+ if (NULL == sortKeyList) {
+ return;
+ }
+
+ /* Walk down the list freeing the LDAPsortkey structures */
+ for (this_one = sortKeyList[0]; this_one;
+ this_one = sortKeyList[++i]) {
+ /* Free the strings, if present */
+ if (NULL != this_one->sk_attrtype) {
+ free(this_one->sk_attrtype);
+ }
+ if (NULL != this_one->sk_matchruleoid) {
+ free(this_one->sk_matchruleoid);
+ }
+ free(this_one);
+ }
+ /* Free the pointer list */
+ free(sortKeyList);
+}
diff --git a/usr/src/lib/libldap4/common/srchpref.c b/usr/src/lib/libldap4/common/srchpref.c
new file mode 100644
index 0000000000..4cdd9e491a
--- /dev/null
+++ b/usr/src/lib/libldap4/common/srchpref.c
@@ -0,0 +1,430 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1993, 1994 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ *
+ * searchpref.c: search preferences library routines for LDAP clients
+ * 17 May 1994 by Gordon Good
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef MACOS
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/file.h>
+#ifndef VMS
+#include <unistd.h>
+#endif /* VMS */
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+
+#ifndef NEEDPROTOS
+int next_line_tokens();
+void free_strarray();
+static void free_searchobj();
+static int read_next_searchobj();
+#else /* !NEEDPROTOS */
+int next_line_tokens( char **bufp, ssize_t *blenp, char ***toksp );
+void free_strarray( char **sap );
+static void free_searchobj( struct ldap_searchobj *so );
+static int read_next_searchobj( char **bufp, ssize_t *blenp,
+ struct ldap_searchobj **sop, int soversion );
+#endif /* !NEEDPROTOS */
+
+
+static char *sobjoptions[] = {
+ "internal",
+ NULL
+};
+
+
+static unsigned int sobjoptvals[] = {
+ LDAP_SEARCHOBJ_OPT_INTERNAL,
+};
+
+
+int
+ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp )
+{
+ FILE *fp;
+ char *buf;
+ ssize_t rlen, len;
+ int rc, eof;
+
+ if (( fp = fopen( file, "r" )) == NULL ) {
+ return( LDAP_SEARCHPREF_ERR_FILE );
+ }
+
+ if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
+ fclose( fp );
+ return( LDAP_SEARCHPREF_ERR_FILE );
+ }
+
+ len = ftell( fp );
+
+ if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
+ fclose( fp );
+ return( LDAP_SEARCHPREF_ERR_FILE );
+ }
+
+ if (( buf = malloc( (size_t)len )) == NULL ) {
+ fclose( fp );
+ return( LDAP_SEARCHPREF_ERR_MEM );
+ }
+
+ rlen = fread( buf, (size_t) 1, (size_t)len, fp );
+ eof = feof( fp );
+ fclose( fp );
+
+ if ( rlen != len && !eof ) { /* error: didn't get the whole file */
+ free( buf );
+ return( LDAP_SEARCHPREF_ERR_FILE );
+ }
+
+ rc = ldap_init_searchprefs_buf( buf, rlen, solistp );
+ free( buf );
+
+ return( rc );
+}
+
+
+int
+ldap_init_searchprefs_buf( char *buf, ssize_t buflen,
+ struct ldap_searchobj **solistp )
+{
+ int rc, version;
+ char **toks;
+ struct ldap_searchobj *prevso, *so;
+
+ *solistp = prevso = NULLSEARCHOBJ;
+
+ if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
+ strcasecmp( toks[ 0 ], "version" ) != 0 ) {
+ free_strarray( toks );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ version = atoi( toks[ 1 ] );
+ free_strarray( toks );
+ if ( version != LDAP_SEARCHPREF_VERSION &&
+ version != LDAP_SEARCHPREF_VERSION_ZERO ) {
+ return( LDAP_SEARCHPREF_ERR_VERSION );
+ }
+
+ while ( buflen > 0 && ( rc = read_next_searchobj( &buf, &buflen, &so,
+ version )) == 0 && so != NULLSEARCHOBJ ) {
+ if ( prevso == NULLSEARCHOBJ ) {
+ *solistp = so;
+ } else {
+ prevso->so_next = so;
+ }
+ prevso = so;
+ }
+
+ if ( rc != 0 ) {
+ ldap_free_searchprefs( *solistp );
+ }
+
+ return( rc );
+}
+
+
+
+void
+ldap_free_searchprefs( struct ldap_searchobj *solist )
+{
+ struct ldap_searchobj *so, *nextso;
+
+ if ( solist != NULL ) {
+ for ( so = solist; so != NULL; so = nextso ) {
+ nextso = so->so_next;
+ free_searchobj( so );
+ }
+ }
+ /* XXX XXX need to do some work here */
+}
+
+
+static void
+free_searchobj( struct ldap_searchobj *so )
+{
+ if ( so != NULL ) {
+ if ( so->so_objtypeprompt != NULL ) {
+ free( so->so_objtypeprompt );
+ }
+ if ( so->so_prompt != NULL ) {
+ free( so->so_prompt );
+ }
+ if ( so->so_filterprefix != NULL ) {
+ free( so->so_filterprefix );
+ }
+ if ( so->so_filtertag != NULL ) {
+ free( so->so_filtertag );
+ }
+ if ( so->so_defaultselectattr != NULL ) {
+ free( so->so_defaultselectattr );
+ }
+ if ( so->so_defaultselecttext != NULL ) {
+ free( so->so_defaultselecttext );
+ }
+ if ( so->so_salist != NULL ) {
+ struct ldap_searchattr *sa, *nextsa;
+ for ( sa = so->so_salist; sa != NULL; sa = nextsa ) {
+ nextsa = sa->sa_next;
+ if ( sa->sa_attrlabel != NULL ) {
+ free( sa->sa_attrlabel );
+ }
+ if ( sa->sa_attr != NULL ) {
+ free( sa->sa_attr );
+ }
+ if ( sa->sa_selectattr != NULL ) {
+ free( sa->sa_selectattr );
+ }
+ if ( sa->sa_selecttext != NULL ) {
+ free( sa->sa_selecttext );
+ }
+ free( sa );
+ }
+ }
+ if ( so->so_smlist != NULL ) {
+ struct ldap_searchmatch *sm, *nextsm;
+ for ( sm = so->so_smlist; sm != NULL; sm = nextsm ) {
+ nextsm = sm->sm_next;
+ if ( sm->sm_matchprompt != NULL ) {
+ free( sm->sm_matchprompt );
+ }
+ if ( sm->sm_filter != NULL ) {
+ free( sm->sm_filter );
+ }
+ free( sm );
+ }
+ }
+ free( so );
+ }
+}
+
+
+
+struct ldap_searchobj *
+ldap_first_searchobj( struct ldap_searchobj *solist )
+{
+ return( solist );
+}
+
+
+struct ldap_searchobj *
+ldap_next_searchobj( struct ldap_searchobj *solist, struct ldap_searchobj *so )
+{
+ return( so == NULLSEARCHOBJ ? so : so->so_next );
+}
+
+
+
+static int
+read_next_searchobj( char **bufp, ssize_t *blenp, struct ldap_searchobj **sop,
+ int soversion )
+{
+ int i, j, tokcnt;
+ char **toks;
+ struct ldap_searchobj *so;
+ struct ldap_searchattr **sa;
+ struct ldap_searchmatch **sm;
+
+ *sop = NULL;
+
+ /*
+ * Object type prompt comes first
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ return( tokcnt == 0 ? 0 : LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+
+ if (( so = (struct ldap_searchobj *)calloc( (size_t) 1,
+ sizeof( struct ldap_searchobj ))) == NULL ) {
+ free_strarray( toks );
+ return( LDAP_SEARCHPREF_ERR_MEM );
+ }
+ so->so_objtypeprompt = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * if this is post-version zero, options come next
+ */
+ if ( soversion > LDAP_SEARCHPREF_VERSION_ZERO ) {
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ for ( i = 0; toks[ i ] != NULL; ++i ) {
+ for ( j = 0; sobjoptions[ j ] != NULL; ++j ) {
+ if ( strcasecmp( toks[ i ], sobjoptions[ j ] ) == 0 ) {
+ so->so_options |= sobjoptvals[ j ];
+ }
+ }
+ }
+ free_strarray( toks );
+ }
+
+ /*
+ * "Fewer choices" prompt is next
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ so->so_prompt = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * Filter prefix for "More Choices" searching is next
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ so->so_filterprefix = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * "Fewer Choices" filter tag comes next
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ so->so_filtertag = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * Selection (disambiguation) attribute comes next
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ so->so_defaultselectattr = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * Label for selection (disambiguation) attribute
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ so->so_defaultselecttext = toks[ 0 ];
+ free( (char *)toks );
+
+ /*
+ * Search scope is next
+ */
+ if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ if ( !strcasecmp(toks[ 0 ], "subtree" )) {
+ so->so_defaultscope = LDAP_SCOPE_SUBTREE;
+ } else if ( !strcasecmp(toks[ 0 ], "onelevel" )) {
+ so->so_defaultscope = LDAP_SCOPE_ONELEVEL;
+ } else if ( !strcasecmp(toks[ 0 ], "base" )) {
+ so->so_defaultscope = LDAP_SCOPE_BASE;
+ } else {
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ free_strarray( toks );
+
+
+ /*
+ * "More Choices" search option list comes next
+ */
+ sa = &( so->so_salist );
+ while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
+ if ( tokcnt < 5 ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ if (( *sa = ( struct ldap_searchattr * ) calloc( (size_t) 1,
+ sizeof( struct ldap_searchattr ))) == NULL ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_MEM );
+ }
+ ( *sa )->sa_attrlabel = toks[ 0 ];
+ ( *sa )->sa_attr = toks[ 1 ];
+ ( *sa )->sa_selectattr = toks[ 3 ];
+ ( *sa )->sa_selecttext = toks[ 4 ];
+ /* Deal with bitmap */
+ ( *sa )->sa_matchtypebitmap = 0;
+ for ( i = (int) strlen( toks[ 2 ] ) - 1, j = 0; i >= 0; i--, j++ ) {
+ if ( toks[ 2 ][ i ] == '1' ) {
+ ( *sa )->sa_matchtypebitmap |= (1 << j);
+ }
+ }
+ free( toks[ 2 ] );
+ free( ( char * ) toks );
+ sa = &(( *sa )->sa_next);
+ }
+ *sa = NULL;
+
+ /*
+ * Match types are last
+ */
+ sm = &( so->so_smlist );
+ while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
+ if ( tokcnt < 2 ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_SYNTAX );
+ }
+ if (( *sm = ( struct ldap_searchmatch * ) calloc( (size_t) 1,
+ sizeof( struct ldap_searchmatch ))) == NULL ) {
+ free_strarray( toks );
+ ldap_free_searchprefs( so );
+ return( LDAP_SEARCHPREF_ERR_MEM );
+ }
+ ( *sm )->sm_matchprompt = toks[ 0 ];
+ ( *sm )->sm_filter = toks[ 1 ];
+ free( ( char * ) toks );
+ sm = &(( *sm )->sm_next );
+ }
+ *sm = NULL;
+
+ *sop = so;
+ return( 0 );
+}
diff --git a/usr/src/lib/libldap4/common/tmplout.c b/usr/src/lib/libldap4/common/tmplout.c
new file mode 100644
index 0000000000..a887efa705
--- /dev/null
+++ b/usr/src/lib/libldap4/common/tmplout.c
@@ -0,0 +1,1176 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * tmplout.c: display template library output routines for LDAP clients
+ * 12 April 1994 by Mark C Smith
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <tzfile.h>
+#include <stdlib.h>
+#ifdef MACOS
+#include "macos.h"
+#else /* MACOS */
+#ifdef DOS
+#include <malloc.h>
+#include "msdos.h"
+#else /* DOS */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#ifdef VMS
+#include <sys/socket.h>
+#endif /* VMS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+#ifdef SUN
+/*
+ * to include definition of FILTERFILE and or TEMPLATEFILE
+ */
+#include "ldapconfig.h"
+#endif
+
+#ifdef NEEDPROTOS
+static int do_entry2text( LDAP *ld, char *buf, char *base, LDAPMessage *entry,
+ struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
+ writeptype writeproc, void *writeparm, char *eol, int rdncount,
+ unsigned int opts, char *urlprefix );
+static int do_entry2text_search( LDAP *ld, char *dn, char *base,
+ LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs,
+ char ***defvals, writeptype writeproc, void *writeparm, char *eol,
+ int rdncount, unsigned int opts, char *urlprefix );
+static int do_vals2text( LDAP *ld, char *buf, char **vals, char *label,
+ int labelwidth, unsigned int syntaxid, writeptype writeproc,
+ void *writeparm, char *eol, int rdncount, char *urlprefix );
+static int max_label_len( struct ldap_disptmpl *tmpl );
+static int output_label( char *buf, char *label, int width,
+ writeptype writeproc, void *writeparm, char *eol, int html );
+static int output_dn( char *buf, char *dn, int width, int rdncount,
+ writeptype writeproc, void *writeparm, char *eol, char *urlprefix );
+static void strcat_escaped( char *s1, char *s2 );
+static char *time2text( char *ldtimestr, int dateonly );
+static time_t gtime( struct tm *tm );
+static int searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry,
+ char *dn, struct ldap_tmplitem *tip, int labelwidth, int rdncount,
+ writeptype writeproc, void *writeparm, char *eol, char *urlprefix );
+#else /* NEEDPROTOS */
+static int do_entry2text();
+static int do_entry2text_search();
+static int do_vals2text();
+static int max_label_len();
+static int output_label();
+static int output_dn();
+static void strcat_escaped();
+static char *time2text();
+static time_t gtime();
+static int searchaction();
+#endif /* NEEDPROTOS */
+
+#define DEF_LABEL_WIDTH 15
+#define SEARCH_TIMEOUT_SECS 120
+#define OCATTRNAME "objectClass"
+
+
+#define NONFATAL_LDAP_ERR( err ) ( err == LDAP_SUCCESS || \
+ err == LDAP_TIMELIMIT_EXCEEDED || err == LDAP_SIZELIMIT_EXCEEDED )
+
+#define DEF_LDAP_URL_PREFIX "ldap:///"
+
+
+int
+ldap_entry2text(
+ LDAP *ld,
+ char *buf, /* NULL for "use internal" */
+ LDAPMessage *entry,
+ struct ldap_disptmpl *tmpl,
+ char **defattrs,
+ char ***defvals,
+ writeptype writeproc,
+ void *writeparm,
+ char *eol,
+ int rdncount,
+ unsigned int opts
+)
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ int rv;
+
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 253, "ldap_entry2text\n"), 0, 0, 0 );
+
+#if defined( SUN ) && defined( _REENTRANT )
+ rv = do_entry2text( ld, buf, NULL, entry, tmpl, defattrs, defvals,
+ writeproc, writeparm, eol, rdncount, opts, NULL );
+ UNLOCK_LDAP(ld);
+ return( rv );
+#else
+ return( do_entry2text( ld, buf, NULL, entry, tmpl, defattrs, defvals,
+ writeproc, writeparm, eol, rdncount, opts, NULL ));
+#endif
+}
+
+
+
+int
+ldap_entry2html(
+ LDAP *ld,
+ char *buf, /* NULL for "use internal" */
+ LDAPMessage *entry,
+ struct ldap_disptmpl *tmpl,
+ char **defattrs,
+ char ***defvals,
+ writeptype writeproc,
+ void *writeparm,
+ char *eol,
+ int rdncount,
+ unsigned int opts,
+ char *base,
+ char *urlprefix
+)
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ int rv;
+
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 254, "ldap_entry2html\n"), 0, 0, 0 );
+
+ if ( urlprefix == NULL ) {
+ urlprefix = DEF_LDAP_URL_PREFIX;
+ }
+
+#if defined( SUN ) && defined( _REENTRANT )
+ rv = do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals,
+ writeproc, writeparm, eol, rdncount, opts, urlprefix );
+ UNLOCK_LDAP(ld);
+ return( rv );
+#else
+ return( do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals,
+ writeproc, writeparm, eol, rdncount, opts, urlprefix ));
+#endif
+}
+
+
+static int
+do_entry2text(
+ LDAP *ld,
+ char *buf, /* NULL for use-internal */
+ char *base, /* used for search actions */
+ LDAPMessage *entry,
+ struct ldap_disptmpl *tmpl,
+ char **defattrs,
+ char ***defvals,
+ writeptype writeproc,
+ void *writeparm,
+ char *eol,
+ int rdncount,
+ unsigned int opts,
+ char *urlprefix /* if non-NULL, do HTML */
+)
+{
+ int i, err, html, show, labelwidth;
+ int freebuf, freevals;
+ char *dn, **vals;
+ struct ldap_tmplitem *rowp, *colp;
+
+ if (( dn = ldap_get_dn( ld, entry )) == NULL ) {
+ return( ld->ld_errno );
+ }
+
+ if ( buf == NULL ) {
+ if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ free( dn );
+ return( ld->ld_errno );
+ }
+ freebuf = 1;
+ } else {
+ freebuf = 0;
+ }
+
+ html = ( urlprefix != NULL );
+
+ if ( html ) {
+ /*
+ * add HTML intro. and title
+ */
+ if (!(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) {
+ sprintf( buf, "<HTML>%s<HEAD>%s<TITLE>%s%s - ", eol, eol, eol,
+ ( tmpl == NULL ) ? "Entry" : tmpl->dt_name );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL );
+ sprintf( buf, "%s</TITLE>%s</HEAD>%s<BODY>%s<H3>%s - ", eol, eol,
+ eol, eol, ( tmpl == NULL ) ? "Entry" : tmpl->dt_name );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL );
+ sprintf( buf, "</H3>%s", eol );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ }
+
+ if (( opts & LDAP_DISP_OPT_NONLEAF ) != 0 &&
+ ( vals = ldap_explode_dn( dn, 0 )) != NULL ) {
+ char *untagged;
+
+ /*
+ * add "Move Up" link
+ */
+ sprintf( buf, "<A HREF=\"%s", urlprefix );
+ for ( i = 1; vals[ i ] != NULL; ++i ) {
+ if ( i > 1 ) {
+ strcat_escaped( buf, ", " );
+ }
+ strcat_escaped( buf, vals[ i ] );
+ }
+ if ( vals[ 1 ] != NULL ) {
+ untagged = strchr( vals[ 1 ], '=' );
+ } else {
+ untagged = "=The World";
+ }
+ sprintf( buf + strlen( buf ),
+ "%s\">Move Up To <EM>%s</EM></A>%s<BR>",
+ ( vals[ 1 ] == NULL ) ? "??one" : "",
+ ( untagged != NULL ) ? untagged + 1 : vals[ 1 ], eol, eol );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+
+ /*
+ * add "Browse" link
+ */
+ untagged = strchr( vals[ 0 ], '=' );
+ sprintf( buf, "<A HREF=\"%s", urlprefix );
+ strcat_escaped( buf, dn );
+ sprintf( buf + strlen( buf ), "??one?(!(objectClass=dsa))\">Browse Below <EM>%s</EM></A>%s%s",
+ ( untagged != NULL ) ? untagged + 1 : vals[ 0 ], eol, eol );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+
+ ldap_value_free( vals );
+ }
+
+ (*writeproc)( writeparm, "<HR>", 4 ); /* horizontal rule */
+ } else {
+ (*writeproc)( writeparm, "\"", 1 );
+ output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL );
+ sprintf( buf, "\"%s", eol );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ }
+
+ if ( tmpl != NULL && ( opts & LDAP_DISP_OPT_AUTOLABELWIDTH ) != 0 ) {
+ labelwidth = max_label_len( tmpl ) + 3;
+ } else {
+ labelwidth = DEF_LABEL_WIDTH;;
+ }
+
+ err = LDAP_SUCCESS;
+
+ if ( tmpl == NULL ) {
+ BerElement *ber;
+ char *attr;
+
+ ber = NULL;
+ for ( attr = ldap_first_attribute( ld, entry, &ber );
+ NONFATAL_LDAP_ERR( err ) && attr != NULL;
+ attr = ldap_next_attribute( ld, entry, ber )) {
+ if (( vals = ldap_get_values( ld, entry, attr )) == NULL ) {
+ freevals = 0;
+ if ( defattrs != NULL ) {
+ for ( i = 0; defattrs[ i ] != NULL; ++i ) {
+ if ( strcasecmp( attr, defattrs[ i ] ) == 0 ) {
+ break;
+ }
+ }
+ if ( defattrs[ i ] != NULL ) {
+ vals = defvals[ i ];
+ }
+ }
+ } else {
+ freevals = 1;
+ }
+
+ if ( islower( *attr )) { /* cosmetic -- upcase attr. name */
+ *attr = toupper( *attr );
+ }
+
+ err = do_vals2text( ld, buf, vals, attr, labelwidth,
+ LDAP_SYN_CASEIGNORESTR, writeproc, writeparm, eol,
+ rdncount, urlprefix );
+ if ( freevals ) {
+ ldap_value_free( vals );
+ }
+ }
+ } else {
+ for ( rowp = ldap_first_tmplrow( tmpl );
+ NONFATAL_LDAP_ERR( err ) && rowp != NULLTMPLITEM;
+ rowp = ldap_next_tmplrow( tmpl, rowp )) {
+ for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM;
+ colp = ldap_next_tmplcol( tmpl, rowp, colp )) {
+ vals = NULL;
+ if ( colp->ti_attrname == NULL || ( vals = ldap_get_values( ld,
+ entry, colp->ti_attrname )) == NULL ) {
+ freevals = 0;
+ if ( !LDAP_IS_TMPLITEM_OPTION_SET( colp,
+ LDAP_DITEM_OPT_HIDEIFEMPTY ) && defattrs != NULL
+ && colp->ti_attrname != NULL ) {
+ for ( i = 0; defattrs[ i ] != NULL; ++i ) {
+ if ( strcasecmp( colp->ti_attrname, defattrs[ i ] )
+ == 0 ) {
+ break;
+ }
+ }
+ if ( defattrs[ i ] != NULL ) {
+ vals = defvals[ i ];
+ }
+ }
+ } else {
+ freevals = 1;
+ if ( LDAP_IS_TMPLITEM_OPTION_SET( colp,
+ LDAP_DITEM_OPT_SORTVALUES ) && vals[ 0 ] != NULL
+ && vals[ 1 ] != NULL ) {
+ ldap_sort_values( ld, vals, ldap_sort_strcasecmp );
+ }
+ }
+
+ /*
+ * don't bother even calling do_vals2text() if no values
+ * or boolean with value false and "hide if false" option set
+ */
+ show = ( vals != NULL && vals[ 0 ] != NULL );
+ if ( show && LDAP_GET_SYN_TYPE( colp->ti_syntaxid )
+ == LDAP_SYN_TYPE_BOOLEAN && LDAP_IS_TMPLITEM_OPTION_SET(
+ colp, LDAP_DITEM_OPT_HIDEIFFALSE ) &&
+ toupper( vals[ 0 ][ 0 ] ) != 'T' ) {
+ show = 0;
+ }
+
+ if ( colp->ti_syntaxid == LDAP_SYN_SEARCHACTION ) {
+ if (( opts & LDAP_DISP_OPT_DOSEARCHACTIONS ) != 0 ) {
+ if ( colp->ti_attrname == NULL || ( show &&
+ toupper( vals[ 0 ][ 0 ] ) == 'T' )) {
+ err = searchaction( ld, buf, base, entry, dn, colp,
+ labelwidth, rdncount, writeproc,
+ writeparm, eol, urlprefix );
+ }
+ }
+ show = 0;
+ }
+
+ if ( show ) {
+ err = do_vals2text( ld, buf, vals, colp->ti_label,
+ labelwidth, colp->ti_syntaxid, writeproc, writeparm,
+ eol, rdncount, urlprefix );
+ }
+
+ if ( freevals ) {
+ ldap_value_free( vals );
+ }
+ }
+ }
+ }
+
+ if ( html && !(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) {
+ sprintf( buf, "</BODY>%s</HTML>%s", eol, eol );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ }
+
+ free( dn );
+ if ( freebuf ) {
+ free( buf );
+ }
+
+ return( err );
+}
+
+
+int
+ldap_entry2text_search(
+ LDAP *ld,
+ char *dn, /* if NULL, use entry */
+ char *base, /* if NULL, no search actions */
+ LDAPMessage *entry, /* if NULL, use dn */
+ struct ldap_disptmpl* tmpllist, /* if NULL, load default file */
+ char **defattrs,
+ char ***defvals,
+ writeptype writeproc,
+ void *writeparm,
+ char *eol,
+ int rdncount, /* if 0, display full DN */
+ unsigned int opts
+)
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ int rv;
+
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 255, "ldap_entry2text_search\n"), 0, 0, 0 );
+
+#if defined( SUN ) && defined( _REENTRANT )
+ rv = do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs,
+ defvals, writeproc, writeparm, eol, rdncount, opts, NULL );
+ UNLOCK_LDAP(ld);
+ return( rv );
+#else
+ return( do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs,
+ defvals, writeproc, writeparm, eol, rdncount, opts, NULL ));
+#endif
+}
+
+
+
+int
+ldap_entry2html_search(
+ LDAP *ld,
+ char *dn, /* if NULL, use entry */
+ char *base, /* if NULL, no search actions */
+ LDAPMessage *entry, /* if NULL, use dn */
+ struct ldap_disptmpl* tmpllist, /* if NULL, load default file */
+ char **defattrs,
+ char ***defvals,
+ writeptype writeproc,
+ void *writeparm,
+ char *eol,
+ int rdncount, /* if 0, display full DN */
+ unsigned int opts,
+ char *urlprefix
+)
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ int rv;
+
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 256, "ldap_entry2html_search\n"), 0, 0, 0 );
+
+#if defined( SUN ) && defined( _REENTRANT )
+ rv = do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs,
+ defvals, writeproc, writeparm, eol, rdncount, opts, urlprefix );
+ UNLOCK_LDAP(ld);
+ return( rv );
+#else
+ return( do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs,
+ defvals, writeproc, writeparm, eol, rdncount, opts, urlprefix ));
+#endif
+}
+
+
+static int
+do_entry2text_search(
+ LDAP *ld,
+ char *dn, /* if NULL, use entry */
+ char *base, /* if NULL, no search actions */
+ LDAPMessage *entry, /* if NULL, use dn */
+ struct ldap_disptmpl* tmpllist, /* if NULL, load default file */
+ char **defattrs,
+ char ***defvals,
+ writeptype writeproc,
+ void *writeparm,
+ char *eol,
+ int rdncount, /* if 0, display full DN */
+ unsigned int opts,
+ char *urlprefix
+)
+{
+ int err, freedn, freetmpls, html;
+ char *buf, **fetchattrs, **vals;
+ LDAPMessage *ldmp;
+ struct ldap_disptmpl *tmpl;
+ struct timeval timeout;
+
+ if ( dn == NULL && entry == NULLMSG ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return( ld->ld_errno );
+ }
+
+ html = ( urlprefix != NULL );
+
+ timeout.tv_sec = SEARCH_TIMEOUT_SECS;
+ timeout.tv_usec = 0;
+
+ if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( ld->ld_errno );
+ }
+
+ freedn = freetmpls = 0;
+ tmpl = NULL;
+
+ if ( tmpllist == NULL ) {
+ if (( err = ldap_init_templates( TEMPLATEFILE, &tmpllist )) != 0 ) {
+ sprintf( buf, "%sUnable to read template file %s (error %d)%s%s",
+ html ? "<!-- " : "", TEMPLATEFILE, err,
+ html ? "-->" : "", eol );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ }
+ freetmpls = 1;
+ }
+
+ if ( dn == NULL ) {
+ if (( dn = ldap_get_dn( ld, entry )) == NULL ) {
+ free( buf );
+ if ( freetmpls ) {
+ ldap_free_templates( tmpllist );
+ }
+ return( ld->ld_errno );
+ }
+ freedn = 1;
+ }
+
+
+ if ( tmpllist != NULL ) {
+ ldmp = NULLMSG;
+
+ if ( entry == NULL ) {
+ char *ocattrs[2];
+
+ ocattrs[0] = OCATTRNAME;
+ ocattrs[1] = NULL;
+#ifdef CLDAP
+ if ( LDAP_IS_CLDAP( ld ))
+ err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE,
+ "objectClass=*", ocattrs, 0, &ldmp, NULL );
+ else
+#endif /* CLDAP */
+ err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE,
+ "objectClass=*", ocattrs, 0, &timeout, &ldmp );
+
+ if ( err == LDAP_SUCCESS ) {
+ entry = ldap_first_entry( ld, ldmp );
+ }
+ }
+
+ if ( entry != NULL ) {
+ vals = ldap_get_values( ld, entry, OCATTRNAME );
+ tmpl = ldap_oc2template( vals, tmpllist );
+ if ( vals != NULL ) {
+ ldap_value_free( vals );
+ }
+ }
+ if ( ldmp != NULL ) {
+ ldap_msgfree( ldmp );
+ }
+ }
+
+ entry = NULL;
+
+ if ( tmpl == NULL ) {
+ fetchattrs = NULL;
+ } else {
+ fetchattrs = ldap_tmplattrs( tmpl, NULL, 1, LDAP_SYN_OPT_DEFER );
+ }
+
+#ifdef CLDAP
+ if ( LDAP_IS_CLDAP( ld ))
+ err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*",
+ fetchattrs, 0, &ldmp, NULL );
+ else
+#endif /* CLDAP */
+ err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*",
+ fetchattrs, 0, &timeout, &ldmp );
+
+ if ( freedn ) {
+ free( dn );
+ }
+ if ( fetchattrs != NULL ) {
+ ldap_value_free( fetchattrs );
+ }
+
+ if ( err != LDAP_SUCCESS ||
+ ( entry = ldap_first_entry( ld, ldmp )) == NULL ) {
+ if ( freetmpls ) {
+ ldap_free_templates( tmpllist );
+ }
+ free( buf );
+ return( ld->ld_errno );
+ }
+
+ err = do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals,
+ writeproc, writeparm, eol, rdncount, opts, urlprefix );
+
+ free( buf );
+ if ( freetmpls ) {
+ ldap_free_templates( tmpllist );
+ }
+ ldap_msgfree( ldmp );
+ return( err );
+}
+
+
+int
+ldap_vals2text(
+ LDAP *ld,
+ char *buf, /* NULL for "use internal" */
+ char **vals,
+ char *label,
+ int labelwidth, /* 0 means use default */
+ unsigned int syntaxid,
+ writeptype writeproc,
+ void *writeparm,
+ char *eol,
+ int rdncount
+)
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ int rv;
+
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 257, "ldap_vals2text\n"), 0, 0, 0 );
+
+#if defined( SUN ) && defined( _REENTRANT )
+ rv = do_vals2text( ld, buf, vals, label, labelwidth, syntaxid,
+ writeproc, writeparm, eol, rdncount, NULL );
+ UNLOCK_LDAP(ld);
+ return( rv );
+#else
+ return( do_vals2text( ld, buf, vals, label, labelwidth, syntaxid,
+ writeproc, writeparm, eol, rdncount, NULL ));
+#endif
+}
+
+
+int
+ldap_vals2html(
+ LDAP *ld,
+ char *buf, /* NULL for "use internal" */
+ char **vals,
+ char *label,
+ int labelwidth, /* 0 means use default */
+ unsigned int syntaxid,
+ writeptype writeproc,
+ void *writeparm,
+ char *eol,
+ int rdncount,
+ char *urlprefix
+)
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ int rv;
+
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 258, "ldap_vals2html\n"), 0, 0, 0 );
+
+ if ( urlprefix == NULL ) {
+ urlprefix = DEF_LDAP_URL_PREFIX;
+ }
+
+#if defined( SUN ) && defined( _REENTRANT )
+ rv = do_vals2text( ld, buf, vals, label, labelwidth, syntaxid,
+ writeproc, writeparm, eol, rdncount, urlprefix );
+ UNLOCK_LDAP(ld);
+ return( rv );
+#else
+ return( do_vals2text( ld, buf, vals, label, labelwidth, syntaxid,
+ writeproc, writeparm, eol, rdncount, urlprefix ));
+#endif
+}
+
+
+static int
+do_vals2text(
+ LDAP *ld,
+ char *buf, /* NULL for "use internal" */
+ char **vals,
+ char *label,
+ int labelwidth, /* 0 means use default */
+ unsigned int syntaxid,
+ writeptype writeproc,
+ void *writeparm,
+ char *eol,
+ int rdncount,
+ char *urlprefix
+)
+{
+ int i, html, writeoutval, freebuf, notascii;
+ char *p, *s, *outval;
+
+
+ if ( vals == NULL ) {
+ return( LDAP_SUCCESS );
+ }
+
+ html = ( urlprefix != NULL );
+
+ switch( LDAP_GET_SYN_TYPE( syntaxid )) {
+ case LDAP_SYN_TYPE_TEXT:
+ case LDAP_SYN_TYPE_BOOLEAN:
+ break; /* we only bother with these two types... */
+ default:
+ return( LDAP_SUCCESS );
+ }
+
+ if ( labelwidth == 0 || labelwidth < 0 ) {
+ labelwidth = DEF_LABEL_WIDTH;
+ }
+
+ if ( buf == NULL ) {
+ if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return( ld->ld_errno );
+ }
+ freebuf = 1;
+ } else {
+ freebuf = 0;
+ }
+
+ output_label( buf, label, labelwidth, writeproc, writeparm, eol, html );
+
+ for ( i = 0; vals[ i ] != NULL; ++i ) {
+ for ( p = vals[ i ]; *p != '\0'; ++p ) {
+ if ( !isascii( *p )) {
+ break;
+ }
+ }
+ notascii = ( *p != '\0' );
+ outval = notascii ? "(unable to display non-ASCII text value)"
+ : vals[ i ];
+
+ writeoutval = 0; /* if non-zero, write outval after switch */
+
+ switch( syntaxid ) {
+ case LDAP_SYN_CASEIGNORESTR:
+ ++writeoutval;
+ break;
+
+ case LDAP_SYN_RFC822ADDR:
+ if ( html ) {
+ strcpy( buf, "<DD><A HREF=\"mailto:" );
+ strcat_escaped( buf, outval );
+ sprintf( buf + strlen( buf ), "\">%s</A><BR>%s", outval, eol );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ } else {
+ ++writeoutval;
+ }
+ break;
+
+ case LDAP_SYN_DN: /* for now */
+ output_dn( buf, outval, labelwidth, rdncount, writeproc,
+ writeparm, eol, urlprefix );
+ break;
+
+ case LDAP_SYN_MULTILINESTR:
+ if ( i > 0 && !html ) {
+ output_label( buf, label, labelwidth, writeproc,
+ writeparm, eol, html );
+ }
+
+ p = s = outval;
+ while (( s = strchr( s, '$' )) != NULL ) {
+ *s++ = '\0';
+ while ( isspace( *s )) {
+ ++s;
+ }
+ if ( html ) {
+ sprintf( buf, "<DD>%s<BR>%s", p, eol );
+ } else {
+ sprintf( buf, "%-*s%s%s", labelwidth, " ", p, eol );
+ }
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ p = s;
+ }
+ outval = p;
+ ++writeoutval;
+ break;
+
+ case LDAP_SYN_BOOLEAN:
+ outval = toupper( outval[ 0 ] ) == 'T' ? "TRUE" : "FALSE";
+ ++writeoutval;
+ break;
+
+ case LDAP_SYN_TIME:
+ case LDAP_SYN_DATE:
+ outval = time2text( outval, syntaxid == LDAP_SYN_DATE );
+ ++writeoutval;
+ break;
+
+ case LDAP_SYN_LABELEDURL:
+ if ( !notascii && ( p = strchr( outval, '$' )) != NULL ) {
+ *p++ = '\0';
+ while ( isspace( *p )) {
+ ++p;
+ }
+ s = outval;
+ } else if ( !notascii && ( s = strchr( outval, ' ' )) != NULL ) {
+ *s++ = '\0';
+ while ( isspace( *s )) {
+ ++s;
+ }
+ p = outval;
+ } else {
+ s = "URL";
+ p = outval;
+ }
+
+ /*
+ * at this point `s' points to the label & `p' to the URL
+ */
+ if ( html ) {
+ sprintf( buf, "<DD><A HREF=\"%s\">%s</A><BR>%s", p, s, eol );
+ } else {
+ sprintf( buf, "%-*s%s%s%-*s%s%s", labelwidth, " ",
+ s, eol, labelwidth + 2, " ",p , eol );
+ }
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ break;
+
+ default:
+ sprintf( buf, " Can't display item type %ld%s",
+ syntaxid, eol );
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ }
+
+ if ( writeoutval ) {
+ if ( html ) {
+ sprintf( buf, "<DD>%s<BR>%s", outval, eol );
+ } else {
+ sprintf( buf, "%-*s%s%s", labelwidth, " ", outval, eol );
+ }
+ (*writeproc)( writeparm, buf, strlen( buf ));
+ }
+ }
+
+ if ( freebuf ) {
+ free( buf );
+ }
+
+ return( LDAP_SUCCESS );
+}
+
+
+static int
+max_label_len( struct ldap_disptmpl *tmpl )
+{
+ struct ldap_tmplitem *rowp, *colp;
+ int len, maxlen;
+
+ maxlen = 0;
+
+ for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULLTMPLITEM;
+ rowp = ldap_next_tmplrow( tmpl, rowp )) {
+ for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM;
+ colp = ldap_next_tmplcol( tmpl, rowp, colp )) {
+ if (( len = strlen( colp->ti_label )) > maxlen ) {
+ maxlen = len;
+ }
+ }
+ }
+
+ return( maxlen );
+}
+
+
+static int
+output_label( char *buf, char *label, int width, writeptype writeproc,
+ void *writeparm, char *eol, int html )
+{
+ char *p;
+
+ if ( html ) {
+ sprintf( buf, "<DT><B>%s</B>", label );
+ } else {
+ sprintf( buf, " %s:", label );
+ p = buf + strlen( buf );
+
+ while ( p - buf < width ) {
+ *p++ = ' ';
+ }
+
+ *p = '\0';
+ strcat( buf, eol );
+ }
+
+ return ((*writeproc)( writeparm, buf, strlen( buf )));
+}
+
+
+static int
+output_dn( char *buf, char *dn, int width, int rdncount,
+ writeptype writeproc, void *writeparm, char *eol, char *urlprefix )
+{
+ char **dnrdns;
+ int i;
+
+ if (( dnrdns = ldap_explode_dn( dn, 1 )) == NULL ) {
+ return( -1 );
+ }
+
+ if ( urlprefix != NULL ) {
+ sprintf( buf, "<DD><A HREF=\"%s", urlprefix );
+ strcat_escaped( buf, dn );
+ strcat( buf, "\">" );
+ } else if ( width > 0 ) {
+ sprintf( buf, "%-*s", width, " " );
+ } else {
+ *buf = '\0';
+ }
+
+ for ( i = 0; dnrdns[ i ] != NULL && ( rdncount == 0 || i < rdncount );
+ ++i ) {
+ if ( i > 0 ) {
+ strcat( buf, ", " );
+ }
+ strcat( buf, dnrdns[ i ] );
+ }
+
+ if ( urlprefix != NULL ) {
+ strcat( buf, "</A><BR>" );
+ }
+
+ ldap_value_free( dnrdns );
+
+ strcat( buf, eol );
+
+ return ((*writeproc)( writeparm, buf, strlen( buf )));
+}
+
+
+
+#define HREF_CHAR_ACCEPTABLE( c ) (( c >= '-' && c <= '9' ) || \
+ ( c >= '@' && c <= 'Z' ) || \
+ ( c == '_' ) || \
+ ( c >= 'a' && c <= 'z' ))
+
+static void
+strcat_escaped( char *s1, char *s2 )
+{
+ char *p, *q;
+ char *hexdig = "0123456789ABCDEF";
+
+ p = s1 + strlen( s1 );
+ for ( q = s2; *q != '\0'; ++q ) {
+ if ( HREF_CHAR_ACCEPTABLE( *q )) {
+ *p++ = *q;
+ } else {
+ *p++ = '%';
+ *p++ = hexdig[ *q >> 4 ];
+ *p++ = hexdig[ *q & 0x0F ];
+ }
+ }
+
+ *p = '\0';
+}
+
+
+#define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
+
+static char *
+time2text( char *ldtimestr, int dateonly )
+{
+ struct tm t;
+ char *p, zone, *fmterr = "badly formatted time";
+ time_t gmttime;
+ int century;
+ static char timestr[128];
+
+ memset( (char *)&t, 0, sizeof( struct tm ));
+ if ( (int) strlen( ldtimestr ) < 13 ) {
+ return( fmterr );
+ }
+
+ for ( p = ldtimestr; p - ldtimestr < 12; ++p ) {
+ if ( !isdigit( *p )) {
+ return( fmterr );
+ }
+ }
+
+ p = ldtimestr;
+ century = GET2BYTENUM( p ) * 100; p += 2;
+ century += GET2BYTENUM( p ); p += 2;
+ /* tm_year is the offset of number of years from TM_YEAR_BASE */
+ t.tm_year = century - TM_YEAR_BASE;
+ t.tm_mon = GET2BYTENUM( p ) - 1; p += 2;
+ t.tm_mday = GET2BYTENUM( p ); p += 2;
+ t.tm_hour = GET2BYTENUM( p ); p += 2;
+ t.tm_min = GET2BYTENUM( p ); p += 2;
+ t.tm_sec = GET2BYTENUM( p ); p += 2;
+
+ /*strftime will return for e.g. Thu Aug 19 2001 */
+ if (strftime(timestr, sizeof(timestr), "%a %b %d %Y", &t) == 0) {
+ return( fmterr );
+ }
+ if (dateonly) {
+ strcpy(timestr + 11, timestr + 20);
+ }
+ return( timestr );
+}
+
+
+
+/* gtime.c - inverse gmtime */
+
+#if !defined( MACOS ) && !defined( _WIN32 ) && !defined( DOS )
+#include <sys/time.h>
+#endif /* !MACOS */
+
+/* gtime(): the inverse of localtime().
+ This routine was supplied by Mike Accetta at CMU many years ago.
+ */
+
+static int dmsize[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+#define dysize(y) \
+ (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
+
+#define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900)
+
+/* */
+
+static time_t gtime ( struct tm *tm )
+{
+ register int i,
+ sec,
+ mins,
+ hour,
+ mday,
+ mon,
+ year;
+ register time_t result;
+
+ if ((sec = tm -> tm_sec) < 0 || sec > 59
+ || (mins = tm -> tm_min) < 0 || mins > 59
+ || (hour = tm -> tm_hour) < 0 || hour > 24
+ || (mday = tm -> tm_mday) < 1 || mday > 31
+ || (mon = tm -> tm_mon + 1) < 1 || mon > 12)
+ return ((time_t) -1);
+ if (hour == 24) {
+ hour = 0;
+ mday++;
+ }
+ year = YEAR (tm -> tm_year);
+
+ result = 0L;
+ for (i = 1970; i < year; i++)
+ result += dysize (i);
+ if (dysize (year) == 366 && mon >= 3)
+ result++;
+ while (--mon)
+ result += dmsize[mon - 1];
+ result += mday - 1;
+ result = 24 * result + hour;
+ result = 60 * result + mins;
+ result = 60 * result + sec;
+
+ return result;
+}
+
+static int
+searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry, char *dn,
+ struct ldap_tmplitem *tip, int labelwidth, int rdncount,
+ writeptype writeproc, void *writeparm, char *eol, char *urlprefix )
+{
+ int err, lderr, i, count, html;
+ char **vals, **members;
+ char *value, *filtpattern, *attr, *selectname;
+ char *retattrs[2], filter[ 256 ];
+ LDAPMessage *ldmp;
+ struct timeval timeout;
+
+ html = ( urlprefix != NULL );
+
+ for ( i = 0; tip->ti_args != NULL && tip->ti_args[ i ] != NULL; ++i ) {
+ ;
+ }
+ if ( i < 3 ) {
+ return( LDAP_PARAM_ERROR );
+ }
+ attr = tip->ti_args[ 0 ];
+ filtpattern = tip->ti_args[ 1 ];
+ retattrs[ 0 ] = tip->ti_args[ 2 ];
+ retattrs[ 1 ] = NULL;
+ selectname = tip->ti_args[ 3 ];
+
+ vals = NULL;
+ if ( attr == NULL ) {
+ value = NULL;
+ } else if ( strcasecmp( attr, "-dnb" ) == 0 ) {
+ return( LDAP_PARAM_ERROR );
+ } else if ( strcasecmp( attr, "-dnt" ) == 0 ) {
+ value = dn;
+ } else if (( vals = ldap_get_values( ld, entry, attr )) != NULL ) {
+ value = vals[ 0 ];
+ } else {
+ value = NULL;
+ }
+
+ ldap_build_filter( filter, sizeof( filter ), filtpattern, NULL, NULL, NULL,
+ value, NULL );
+
+ if ( html ) {
+ /*
+ * if we are generating HTML, we add an HREF link that embodies this
+ * search action as an LDAP URL, instead of actually doing the search
+ * now.
+ */
+ sprintf( buf, "<DT><A HREF=\"%s", urlprefix );
+ if ( base != NULL ) {
+ strcat_escaped( buf, base );
+ }
+ strcat( buf, "??sub?" );
+ strcat_escaped( buf, filter );
+ sprintf( buf + strlen( buf ), "\"><B>%s</B></A><DD><BR>%s",
+ tip->ti_label, eol );
+ if ((*writeproc)( writeparm, buf, strlen( buf )) < 0 ) {
+ return( LDAP_LOCAL_ERROR );
+ }
+ return( LDAP_SUCCESS );
+ }
+
+ timeout.tv_sec = SEARCH_TIMEOUT_SECS;
+ timeout.tv_usec = 0;
+
+#ifdef CLDAP
+ if ( LDAP_IS_CLDAP( ld ))
+ lderr = cldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs,
+ 0, &ldmp, NULL );
+ else
+#endif /* CLDAP */
+ lderr = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs,
+ 0, &timeout, &ldmp );
+
+ if ( lderr == LDAP_SUCCESS || NONFATAL_LDAP_ERR( lderr )) {
+ if (( count = ldap_count_entries( ld, ldmp )) > 0 ) {
+ if (( members = (char **)malloc( (count + 1) * sizeof(char *)))
+ == NULL ) {
+ err = LDAP_NO_MEMORY;
+ } else {
+ for ( i = 0, entry = ldap_first_entry( ld, ldmp );
+ entry != NULL;
+ entry = ldap_next_entry( ld, entry ), ++i ) {
+ members[ i ] = ldap_get_dn( ld, entry );
+ }
+ members[ i ] = NULL;
+
+ ldap_sort_values( ld, members, ldap_sort_strcasecmp );
+
+ err = do_vals2text( ld, NULL, members, tip->ti_label,
+ html ? -1 : 0, LDAP_SYN_DN, writeproc, writeparm,
+ eol, rdncount, urlprefix );
+
+ ldap_value_free( members );
+ }
+ }
+ ldap_msgfree( ldmp );
+ }
+
+
+ if ( vals != NULL ) {
+ ldap_value_free( vals );
+ }
+
+ return(( err == LDAP_SUCCESS ) ? lderr : err );
+}
diff --git a/usr/src/lib/libldap4/common/ufn.c b/usr/src/lib/libldap4/common/ufn.c
new file mode 100644
index 0000000000..b2548d2482
--- /dev/null
+++ b/usr/src/lib/libldap4/common/ufn.c
@@ -0,0 +1,594 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * ufn.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h> /* malloc(), realloc(), free() */
+
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include "msdos.h"
+#else /* DOS */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+#ifdef SUN
+/*
+ * to include definition of FILTERFILE and or TEMPLATEFILE
+ */
+#include "ldapconfig.h"
+#endif
+
+#ifdef NEEDPROTOS
+typedef int (*cancelptype)( void *cancelparm );
+#else /* NEEDPROTOS */
+typedef int (*cancelptype)();
+#endif /* NEEDPROTOS */
+
+#ifdef NEEDPROTOS
+static int ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp,
+ char *prefix, char **attrs, int attrsonly, LDAPMessage **res,
+ cancelptype cancelproc, void *cancelparm, char *tag1, char *tag2,
+ char *tag3 );
+static LDAPMessage *ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b );
+static LDAPMessage *ldap_ufn_expand( LDAP *ld, cancelptype cancelproc,
+ void *cancelparm, char **dns, char *filter, int scope,
+ char **attrs, int aonly, int *err );
+LDAPFiltDesc *ldap_ufn_setfilter( LDAP *ld, char *fname );
+#else /* NEEDPROTOS */
+static LDAPMessage *ldap_msg_merge();
+static LDAPMessage *ldap_ufn_expand();
+LDAPFiltDesc *ldap_ufn_setfilter();
+#endif /* NEEDPROTOS */
+static LDAPMessage *ldap_msg_merge();
+static LDAPMessage *ldap_ufn_expand();
+
+/*
+ * ldap_ufn_search_ctx - do user friendly searching; provide cancel feature;
+ * specify ldapfilter.conf tags for each phase of search
+ *
+ * ld LDAP descriptor
+ * ufncomp the exploded user friendly name to look for
+ * ncomp number of elements in ufncomp
+ * prefix where to start searching
+ * attrs list of attribute types to return for matches
+ * attrsonly 1 => attributes only 0 => attributes and values
+ * res will contain the result of the search
+ * cancelproc routine that returns non-zero if operation should be
+ * cancelled. This can be NULL. If it is non-NULL, the
+ * routine will be called periodically.
+ * cancelparm void * that is passed to cancelproc
+ * tag[123] the ldapfilter.conf tag that will be used in phases
+ * 1, 2, and 3 of the search, respectively
+ *
+ * Example:
+ * char *attrs[] = { "mail", "title", 0 };
+ * char *ufncomp[] = { "howes", "umich", "us", 0 }
+ * LDAPMessage *res;
+ * error = ldap_ufn_search_ctx( ld, ufncomp, 3, NULL, attrs, attrsonly,
+ * &res, acancelproc, along, "ufn first",
+ * "ufn intermediate", "ufn last" );
+ */
+
+static int
+ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, char *prefix,
+ char **attrs, int attrsonly, LDAPMessage **res, cancelptype cancelproc,
+ void *cancelparm, char *tag1, char *tag2, char *tag3 )
+{
+ char *dn, *ftag;
+ char **dns;
+ int max, i, err, scope, phase, tries;
+ LDAPFiltInfo *fi;
+ LDAPMessage *tmpcand;
+ LDAPMessage *candidates;
+ /* LDAPMessage *ldap_msg_merge(), *ldap_ufn_expand(); */
+ static char *objattrs[] = { "objectClass", NULL };
+
+ /*
+ * look up ufn components from most to least significant.
+ * there are 3 phases.
+ * phase 1 search the root for orgs or countries
+ * phase 2 search for orgs
+ * phase 3 search for a person
+ * in phases 1 and 2, we are building a list of candidate DNs,
+ * below which we will search for the final component of the ufn.
+ * for each component we try the filters listed in the
+ * filterconfig file, first one-level (except the last compoment),
+ * then subtree. if any of them produce any results, we go on to
+ * the next component.
+ */
+
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ *res = NULL;
+ candidates = NULL;
+ phase = 1;
+ for ( ncomp--; ncomp != -1; ncomp-- ) {
+ if ( *ufncomp[ncomp] == '"' ) {
+ char *quote;
+
+ if ( (quote = strrchr( ufncomp[ncomp], '"' )) != NULL )
+ *quote = '\0';
+ (void) strcpy( ufncomp[ncomp], ufncomp[ncomp] + 1 );
+ }
+ if ( ncomp == 0 )
+ phase = 3;
+
+ switch ( phase ) {
+ case 1:
+ ftag = tag1;
+ scope = LDAP_SCOPE_ONELEVEL;
+ break;
+ case 2:
+ ftag = tag2;
+ scope = LDAP_SCOPE_ONELEVEL;
+ break;
+ case 3:
+ ftag = tag3;
+ scope = LDAP_SCOPE_SUBTREE;
+ break;
+ }
+
+ /*
+ * construct an array of DN's to search below from the
+ * list of candidates.
+ */
+
+ if ( candidates == NULL ) {
+ if ( prefix != NULL ) {
+ if ( (dns = (char **) malloc( sizeof(char *)
+ * 2 )) == NULL ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno = LDAP_NO_MEMORY );
+ }
+ dns[0] = strdup( prefix );
+ dns[1] = NULL;
+ } else {
+ dns = NULL;
+ }
+ } else {
+ i = 0, max = 0;
+ for ( tmpcand = candidates; tmpcand != NULL &&
+ tmpcand->lm_msgtype != LDAP_RES_SEARCH_RESULT;
+ tmpcand = tmpcand->lm_chain )
+ {
+ if ( (dn = ldap_get_dn( ld, tmpcand )) == NULL )
+ continue;
+
+ if ( dns == NULL ) {
+ if ( (dns = (char **) malloc(
+ sizeof(char *) * 8 )) == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( LDAP_NO_MEMORY );
+ }
+ max = 8;
+ } else if ( i >= max ) {
+ if ( (dns = (char **) realloc( dns,
+ sizeof(char *) * 2 * max ))
+ == NULL )
+ {
+ ld->ld_errno = LDAP_NO_MEMORY;
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( LDAP_NO_MEMORY );
+ }
+ max *= 2;
+ }
+ dns[i++] = dn;
+ dns[i] = NULL;
+ }
+ ldap_msgfree( candidates );
+ candidates = NULL;
+ }
+ tries = 0;
+ tryagain:
+ tries++;
+ for ( fi = ldap_getfirstfilter( ld->ld_filtd, ftag,
+ ufncomp[ncomp] ); fi != NULL;
+ fi = ldap_getnextfilter( ld->ld_filtd ) )
+ {
+ if ( (candidates = ldap_ufn_expand( ld, cancelproc,
+ cancelparm, dns, fi->lfi_filter, scope,
+ phase == 3 ? attrs : objattrs,
+ phase == 3 ? attrsonly : 1, &err )) != NULL )
+ {
+ break;
+ }
+
+ if ( err == -1 || err == LDAP_USER_CANCELLED ) {
+ if ( dns != NULL ) {
+ ldap_value_free( dns );
+ dns = NULL;
+ }
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( err );
+ }
+ }
+
+ if ( candidates == NULL ) {
+ if ( tries < 2 && phase != 3 ) {
+ scope = LDAP_SCOPE_SUBTREE;
+ goto tryagain;
+ } else {
+ if ( dns != NULL ) {
+ ldap_value_free( dns );
+ dns = NULL;
+ }
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( err );
+ }
+ }
+
+ /* go on to the next component */
+ if ( phase == 1 )
+ phase++;
+ if ( dns != NULL ) {
+ ldap_value_free( dns );
+ dns = NULL;
+ }
+ }
+ *res = candidates;
+
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( err );
+}
+
+int
+ldap_ufn_search_ct( LDAP *ld, char *ufn, char **attrs, int attrsonly,
+ LDAPMessage **res, cancelptype cancelproc, void *cancelparm,
+ char *tag1, char *tag2, char *tag3 )
+{
+ char **ufncomp, **prefixcomp;
+ char *pbuf;
+ int ncomp, pcomp, i, err;
+
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ /* initialize the getfilter stuff if it's not already */
+ if ( ld->ld_filtd == NULL && ldap_ufn_setfilter( ld, FILTERFILE )
+ == NULL ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno = LDAP_LOCAL_ERROR );
+ }
+
+ /* call ldap_explode_dn() to break the ufn into its components */
+ if ( (ufncomp = ldap_explode_dn( ufn, 0 )) == NULL ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno = LDAP_LOCAL_ERROR );
+ }
+ for ( ncomp = 0; ufncomp[ncomp] != NULL; ncomp++ )
+ ; /* NULL */
+
+ /* more than two components => try it fully qualified first */
+ if ( ncomp > 2 || ld->ld_ufnprefix == NULL ) {
+ err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, NULL, attrs,
+ attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 );
+
+ if ( ldap_count_entries( ld, *res ) > 0 ) {
+ ldap_value_free( ufncomp );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( err );
+ } else {
+ ldap_msgfree( *res );
+ *res = NULL;
+ }
+ }
+
+ if ( ld->ld_ufnprefix == NULL ) {
+ ldap_value_free( ufncomp );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( err );
+ }
+
+ /* if that failed, or < 2 components, use the prefix */
+ if ( (prefixcomp = ldap_explode_dn( ld->ld_ufnprefix, 0 )) == NULL ) {
+ ldap_value_free( ufncomp );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno = LDAP_LOCAL_ERROR );
+ }
+ for ( pcomp = 0; prefixcomp[pcomp] != NULL; pcomp++ )
+ ; /* NULL */
+ if ( (pbuf = (char *) malloc( strlen( ld->ld_ufnprefix ) + 1 ))
+ == NULL ) {
+ ldap_value_free( ufncomp );
+ ldap_value_free( prefixcomp );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno = LDAP_NO_MEMORY );
+ }
+
+ for ( i = 0; i < pcomp; i++ ) {
+ int j;
+
+ *pbuf = '\0';
+ for ( j = i; j < pcomp; j++ ) {
+ (void) strcat( pbuf, prefixcomp[j] );
+ if ( j + 1 < pcomp )
+ (void) strcat( pbuf, "," );
+ }
+ err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, pbuf, attrs,
+ attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 );
+
+ if ( ldap_count_entries( ld, *res ) > 0 ) {
+ break;
+ } else {
+ ldap_msgfree( *res );
+ *res = NULL;
+ }
+ }
+
+ ldap_value_free( ufncomp );
+ ldap_value_free( prefixcomp );
+ free( pbuf );
+
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( err );
+}
+
+/*
+ * same as ldap_ufn_search_ct, except without the ability to specify
+ * ldapfilter.conf tags.
+ */
+int
+ldap_ufn_search_c( LDAP *ld, char *ufn, char **attrs, int attrsonly,
+ LDAPMessage **res, cancelptype cancelproc, void *cancelparm )
+{
+ return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, cancelproc,
+ cancelparm, "ufn first", "ufn intermediate", "ufn last" ) );
+}
+
+/*
+ * same as ldap_ufn_search_c without the cancel function
+ */
+int
+ldap_ufn_search_s( LDAP *ld, char *ufn, char **attrs, int attrsonly,
+ LDAPMessage **res )
+{
+ struct timeval tv;
+
+ tv.tv_sec = ld->ld_timelimit;
+
+ return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res,
+ ld->ld_timelimit ? ldap_ufn_timeout : NULL,
+ ld->ld_timelimit ? (void *) &tv : NULL,
+ "ufn first", "ufn intermediate", "ufn last" ) );
+}
+
+
+/*
+ * ldap_msg_merge - merge two ldap search result chains. the more
+ * serious of the two error result codes is kept.
+ */
+
+static LDAPMessage *
+ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b )
+{
+ LDAPMessage *end, *aprev, *aend, *bprev, *bend;
+
+ if ( a == NULL )
+ return( b );
+
+ if ( b == NULL )
+ return( a );
+
+ /* find the ends of the a and b chains */
+ aprev = NULL;
+ for ( aend = a; aend->lm_chain != NULL; aend = aend->lm_chain )
+ aprev = aend;
+ bprev = NULL;
+ for ( bend = b; bend->lm_chain != NULL; bend = bend->lm_chain )
+ bprev = bend;
+
+ /* keep result a */
+ if ( ldap_result2error( ld, aend, 0 ) != LDAP_SUCCESS ) {
+ /* remove result b */
+ ldap_msgfree( bend );
+ if ( bprev != NULL )
+ bprev->lm_chain = NULL;
+ else
+ b = NULL;
+ end = aend;
+ if ( aprev != NULL )
+ aprev->lm_chain = NULL;
+ else
+ a = NULL;
+ /* keep result b */
+ } else {
+ /* remove result a */
+ ldap_msgfree( aend );
+ if ( aprev != NULL )
+ aprev->lm_chain = NULL;
+ else
+ a = NULL;
+ end = bend;
+ if ( bprev != NULL )
+ bprev->lm_chain = NULL;
+ else
+ b = NULL;
+ }
+
+ if ( (a == NULL && b == NULL) || (a == NULL && bprev == NULL) ||
+ (b == NULL && aprev == NULL) )
+ return( end );
+
+ if ( a == NULL ) {
+ bprev->lm_chain = end;
+ return( b );
+ } else if ( b == NULL ) {
+ aprev->lm_chain = end;
+ return( a );
+ } else {
+ bprev->lm_chain = end;
+ aprev->lm_chain = b;
+ return( a );
+ }
+}
+
+static LDAPMessage *
+ldap_ufn_expand( LDAP *ld, cancelptype cancelproc, void *cancelparm,
+ char **dns, char *filter, int scope, char **attrs, int aonly,
+ int *err )
+{
+ LDAPMessage *tmpcand, *tmpres;
+ char *dn;
+ int i, msgid;
+ struct timeval tv;
+
+ /* search for this component below the current candidates */
+ tmpcand = NULL;
+ i = 0;
+ do {
+ if ( dns != NULL )
+ dn = dns[i];
+ else
+ dn = "";
+
+ if (( msgid = ldap_search( ld, dn, scope, filter, attrs,
+ aonly )) == -1 ) {
+ ldap_msgfree( tmpcand );
+ *err = ld->ld_errno;
+ return( NULL );
+ }
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000; /* 1/10 of a second */
+
+ do {
+ *err = ldap_result( ld, msgid, 1, &tv, &tmpres );
+ if ( *err == 0 && cancelproc != NULL &&
+ (*cancelproc)( cancelparm ) != 0 ) {
+ ldap_abandon( ld, msgid );
+ *err = LDAP_USER_CANCELLED;
+ ld->ld_errno = LDAP_USER_CANCELLED;
+ }
+ } while ( *err == 0 );
+
+ if ( *err == LDAP_USER_CANCELLED || *err < 0 ||
+ ( *err = ldap_result2error( ld, tmpres, 0 )) == -1 ) {
+ ldap_msgfree( tmpcand );
+ return( NULL );
+ }
+
+ tmpcand = ldap_msg_merge( ld, tmpcand, tmpres );
+
+ i++;
+ } while ( dns != NULL && dns[i] != NULL );
+
+ if ( ldap_count_entries( ld, tmpcand ) > 0 ) {
+ return( tmpcand );
+ } else {
+ ldap_msgfree( tmpcand );
+ return( NULL );
+ }
+}
+
+/*
+ * ldap_ufn_setfilter - set the filter config file used in ufn searching
+ */
+
+LDAPFiltDesc *
+ldap_ufn_setfilter( LDAP *ld, char *fname )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LDAPFiltDesc *rv;
+
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_filtd != NULL )
+ ldap_getfilter_free( ld->ld_filtd );
+
+#if defined( SUN ) && defined( _REENTRANT )
+ ld->ld_filtd = ldap_init_getfilter( fname );
+ rv = ld->ld_filtd;
+ UNLOCK_LDAP(ld);
+ return( rv );
+#else
+ return( ld->ld_filtd = ldap_init_getfilter( fname ) );
+#endif
+}
+
+void
+ldap_ufn_setprefix( LDAP *ld, char *prefix )
+{
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_ufnprefix != NULL )
+ free( ld->ld_ufnprefix );
+
+ ld->ld_ufnprefix = strdup( prefix );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+}
+
+int
+ldap_ufn_timeout( void *tvparam )
+{
+ struct timeval *tv;
+
+ tv = (struct timeval *)tvparam;
+
+ if ( tv->tv_sec != 0 ) {
+ tv->tv_usec = tv->tv_sec * 1000000; /* sec => micro sec */
+ tv->tv_sec = 0;
+ }
+ tv->tv_usec -= 100000; /* 1/10 of a second */
+
+ return( tv->tv_usec <= 0 ? 1 : 0 );
+}
diff --git a/usr/src/lib/libldap4/common/unbind.c b/usr/src/lib/libldap4/common/unbind.c
new file mode 100644
index 0000000000..fc96ab2e37
--- /dev/null
+++ b/usr/src/lib/libldap4/common/unbind.c
@@ -0,0 +1,216 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * unbind.c
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#else /* MACOS */
+#if defined( DOS ) || defined( _WIN32 )
+#include "msdos.h"
+#ifdef NCSA
+#include "externs.h"
+#endif /* NCSA */
+#else /* DOS */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#endif /* DOS */
+#endif /* MACOS */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+
+int
+ldap_unbind( LDAP *ld )
+{
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 259, "ldap_unbind\n"), 0, 0, 0 );
+
+ return( ldap_ld_free( ld, 1 ));
+}
+
+
+int
+ldap_ld_free( LDAP *ld, int close )
+{
+ LDAPMessage *lm, *next;
+ int err = LDAP_SUCCESS;
+ LDAPRequest *lr, *nextlr;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ if ( ld->ld_sb.sb_naddr == 0 ) {
+ /* free LDAP structure and outstanding requests/responses */
+ for ( lr = ld->ld_requests; lr != NULL; lr = nextlr ) {
+ nextlr = lr->lr_next;
+ free_request( ld, lr );
+ }
+
+ /* free and unbind from all open connections */
+ while ( ld->ld_conns != NULL ) {
+ free_connection( ld, ld->ld_conns, 1, close );
+ }
+ } else {
+ int i;
+
+ for ( i = 0; i < ld->ld_sb.sb_naddr; ++i ) {
+ free( ld->ld_sb.sb_addrs[ i ] );
+ }
+ free( ld->ld_sb.sb_addrs );
+ free( ld->ld_sb.sb_fromaddr );
+#ifdef LDAP_SSL
+ if (ld->ld_sb.sb_ssl){
+ SSL_delete(ld->ld_sb.sb_ssl);
+ }
+ ld->ld_sb.sb_ssl = NULL;
+ ld->ld_sb.sb_ssl_tls = 0;
+#endif
+ }
+
+ if (ld->ld_sb.sb_ber.ber_buf) {
+ free(ld->ld_sb.sb_ber.ber_buf);
+ ld->ld_sb.sb_ber.ber_buf = NULL;
+ }
+
+#ifdef _REENTRANT
+ LOCK_RESPONSE(ld);
+#endif
+ for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
+ next = lm->lm_next;
+ ldap_msgfree( lm );
+ }
+
+#ifdef _REENTRANT
+ UNLOCK_RESPONSE(ld);
+#endif
+
+#ifndef NO_CACHE
+ if ( ld->ld_cache != NULL )
+ ldap_destroy_cache( ld );
+#endif /* !NO_CACHE */
+ if ( ld->ld_error != NULL )
+ free( ld->ld_error );
+ if ( ld->ld_matched != NULL )
+ free( ld->ld_matched );
+ if ( ld->ld_host != NULL )
+ free( ld->ld_host );
+ if ( ld->ld_ufnprefix != NULL )
+ free( ld->ld_ufnprefix );
+ if ( ld->ld_filtd != NULL )
+ ldap_getfilter_free( ld->ld_filtd );
+ if ( ld->ld_abandoned != NULL )
+ free( ld->ld_abandoned );
+
+ if ( ld->ld_selectinfo != NULL )
+ free_select_info( ld->ld_selectinfo );
+
+ if ( ld->ld_defhost != NULL )
+ free( ld->ld_defhost );
+
+#ifdef LDAP_SSL
+ if (ld->ld_ssl_key != NULL)
+ free(ld->ld_ssl_key);
+#endif
+
+#undef ld_attrbuffer
+ {
+ /* free thread-specific attr buffers */
+ int i;
+
+ for (i = 0; i < MAX_THREAD_ID; i++)
+ if (ld->ld_attrbuffer[i] != NULL) {
+ free(ld->ld_attrbuffer[i]);
+ ld->ld_attrbuffer[i] = NULL;
+ }
+ }
+/* free ldapv3 stuff */
+ if (ld->ld_srvctrls != NULL)
+ ldap_controls_free(ld->ld_srvctrls);
+ if (ld->ld_cltctrls != NULL)
+ ldap_controls_free(ld->ld_cltctrls);
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+
+ if (ld->ld_lockcount != 0)
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 260, "Mutex problem: ld_lockcount not equal to zero when freeing context\n"), 0, 0, 0 );
+#endif
+
+ free( (char *) ld );
+
+ return( err );
+}
+
+int
+ldap_unbind_s( LDAP *ld )
+{
+ return( ldap_ld_free( ld, 1 ));
+}
+
+
+int
+send_unbind( LDAP *ld, Sockbuf *sb )
+{
+ BerElement *ber;
+
+#if defined( SUN ) && defined( _REENTRANT )
+ LOCK_LDAP(ld);
+#endif
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 261, "send_unbind\n"), 0, 0, 0 );
+
+ /* create a message to send */
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno );
+ }
+
+ /* fill it in */
+ if ( ber_printf( ber, "{itn}", ++ld->ld_msgid,
+ LDAP_REQ_UNBIND ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno );
+ }
+
+ /* send the message */
+ if ( ber_flush( sb, ber, 1 ) == -1 ) {
+ ld->ld_errno = LDAP_SERVER_DOWN;
+ ber_free( ber, 1 );
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( ld->ld_errno );
+ }
+
+#if defined( SUN ) && defined( _REENTRANT )
+ UNLOCK_LDAP(ld);
+#endif
+ return( LDAP_SUCCESS );
+}
diff --git a/usr/src/lib/libldap4/common/url.c b/usr/src/lib/libldap4/common/url.c
new file mode 100644
index 0000000000..dab3cfb258
--- /dev/null
+++ b/usr/src/lib/libldap4/common/url.c
@@ -0,0 +1,836 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1996 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * LIBLDAP url.c -- LDAP URL related routines
+ *
+ * LDAP URLs look like this:
+ * l d a p : / / hostport / dn [ ? attributes [ ? scope [ ? filter [ ? extensions ] ] ] ]
+ *
+ * where:
+ * attributes is a comma separated list
+ * scope is one of these three strings: base one sub (default=base)
+ * filter is an string-represented filter as in RFC 1558
+ * extensions is a comma separated list of extension
+ * and extension is like this: [ ! ] oid/x-oid [ = value ]
+ *
+ * e.g., ldap://ldap.itd.umich.edu/c=US?o,description?one?o=umich
+ *
+ * We also tolerate URLs that look like: <ldapurl> and <URL:ldapurl>
+ */
+
+#ifndef lint
+static char copyright[] = "@(#) Copyright (c) 1996 Regents of the University of Michigan.\nAll rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef MACOS
+#include <stdlib.h>
+#include "macos.h"
+#endif /* MACOS */
+
+#if defined( DOS ) || defined( _WIN32 )
+#include <stdlib.h>
+#include <malloc.h>
+#include "msdos.h"
+#endif /* DOS || _WIN32 */
+
+#if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* !MACOS && !DOS && !_WIN32 */
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+
+#ifdef NEEDPROTOS
+static int skip_url_prefix( char **urlp, int *enclosedp );
+static void hex_unescape( char *s );
+static int unhex( char c );
+#else /* NEEDPROTOS */
+static int skip_url_prefix();
+static void hex_unescape();
+static int unhex();
+#endif /* NEEDPROTOS */
+
+
+int
+ldap_is_ldap_url( char *url )
+{
+ int enclosed;
+
+ return( url != NULL && skip_url_prefix( &url, &enclosed ));
+}
+
+
+static int
+skip_url_prefix( char **urlp, int *enclosedp )
+{
+/*
+ * return non-zero if this looks like a LDAP URL; zero if not
+ * if non-zero returned, *urlp will be moved past "ldap://" part of URL
+ */
+ if ( *urlp == NULL ) {
+ return( 0 );
+ }
+
+ /* skip leading '<' (if any) */
+ if ( **urlp == '<' ) {
+ *enclosedp = 1;
+ ++*urlp;
+ } else {
+ *enclosedp = 0;
+ }
+
+ /* skip leading "URL:" (if any) */
+ if ( strlen( *urlp ) >= LDAP_URL_URLCOLON_LEN && strncasecmp(
+ *urlp, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
+ *urlp += LDAP_URL_URLCOLON_LEN;
+ }
+
+ /* check for missing "ldap://" prefix */
+ if ( strlen( *urlp ) < LDAP_URL_PREFIX_LEN ||
+ strncasecmp( *urlp, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) != 0 ) {
+ return( 0 );
+ }
+
+ /* skip over "ldap://" prefix and return success */
+ *urlp += LDAP_URL_PREFIX_LEN;
+ return( 1 );
+}
+
+int ldap_url_extension_parse( char *exts, LDAPURLExt *** lueppp)
+{
+ /* Pick apart the pieces of an LDAP URL Extensions */
+ /* No copy of exts is made, LDAPURLExt's points to exts string */
+ LDAPURLExt ** lues;
+ LDAPURLExt *luep;
+ int i = 0;
+ char *p = exts;
+ char *ptr, *ptr2;
+
+ *lueppp = NULL;
+
+ /* Count the number of , in extensions */
+ while ( (p = strchr (p, ',')) != NULL){
+ i++;
+ }
+ /* There are at most i+1 extensions */
+ if ((lues = (LDAPURLExt **)calloc(i+2, sizeof(LDAPURLExt *))) == NULL){
+ return (LDAP_URL_ERR_MEM);
+ }
+
+ p = exts;
+ i = 0;
+
+ while ( p ) {
+ if ((ptr = strchr(p, ',')) != NULL)
+ *ptr++ = '\0';
+ else
+ ptr = NULL;
+
+ if ((luep = (LDAPURLExt *)calloc(1, sizeof(LDAPURLExt))) == NULL){
+ ldap_free_urlexts(lues);
+ return (LDAP_URL_ERR_MEM);
+ }
+ lues[i] = luep;
+
+ if (*p == '!'){
+ luep->lue_iscritical = 1;
+ p++;
+ }
+ luep->lue_type = p;
+
+ if (( ptr2 = strchr(p, '=')) != NULL) {
+ *ptr2++ = '\0';
+ luep->lue_value = ptr2;
+ hex_unescape(ptr2);
+ }
+
+ i++;
+ p = ptr;
+ }
+ *lueppp = lues;
+
+ return( 0 );
+}
+
+
+int
+ldap_url_parse( char *url, LDAPURLDesc **ludpp )
+{
+/*
+ * Pick apart the pieces of an LDAP URL.
+ */
+
+ LDAPURLDesc *ludp;
+ char *attrs = NULL;
+ char *p = NULL;
+ char *q = NULL;
+ char *x = NULL;
+ int enclosed, i, nattrs, errcode;
+
+ Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 262, "ldap_url_parse(%s)\n"), url, 0, 0 );
+
+ *ludpp = NULL; /* pessimistic */
+
+ if ( !skip_url_prefix( &url, &enclosed )) {
+ return( LDAP_URL_ERR_NOTLDAP );
+ }
+
+ /* allocate return struct */
+ if (( ludp = (LDAPURLDesc *)calloc( 1, sizeof( LDAPURLDesc )))
+ == NULLLDAPURLDESC ) {
+ return( LDAP_URL_ERR_MEM );
+ }
+
+ ludp->lud_port = LDAP_PORT;
+
+ /* make working copy of the remainder of the URL */
+ if (( url = strdup( url )) == NULL ) {
+ ldap_free_urldesc( ludp );
+ return( LDAP_URL_ERR_MEM );
+ }
+
+ if ( enclosed && *((p = url + strlen( url ) - 1)) == '>' ) {
+ *p = '\0';
+ }
+
+ /* set defaults */
+ /* LP By default don't set them... Then we can check if they are present or not in URL */
+ ludp->lud_scope = LDAP_SCOPE_UNKNOWN;
+ ludp->lud_filter = NULL;
+
+
+ /* lud_string is the only malloc'd string space we use */
+ ludp->lud_string = url;
+
+ /* scan forward for '/' that marks end of hostport and begin. of dn */
+ if (( ludp->lud_dn = strchr( url, '/' )) != NULL ) {
+ *ludp->lud_dn++ = '\0';
+ }
+
+ /* terminate hostport; point to start of dn */
+
+ if (( p = strchr( url, ':' )) != NULL ) {
+ *p++ = '\0';
+ ludp->lud_port = atoi( p );
+ }
+
+ if ( *url == '\0' ) {
+ ludp->lud_host = NULL;
+ } else {
+ ludp->lud_host = url;
+ hex_unescape( ludp->lud_host );
+ }
+
+ if (ludp->lud_dn != NULL){
+ /* scan for '?' that marks end of dn and beginning of attributes */
+ if (( attrs = strchr( ludp->lud_dn, '?' )) != NULL ) {
+ /* terminate dn; point to start of attrs. */
+ *attrs++ = '\0';
+
+ /* scan for '?' that marks end of attrs and begin. of scope */
+ if (( p = strchr( attrs, '?' )) != NULL ) {
+ /*
+ * terminate attrs; point to start of scope and scan for
+ * '?' that marks end of scope and begin. of filter
+ */
+ *p++ = '\0';
+
+ if (( q = strchr( p, '?' )) != NULL ) {
+ /* terminate scope; point to start of filter */
+ *q++ = '\0';
+
+ if (( x = strchr(q, '?')) != NULL ) {
+ /* terminate filter; point to start of extension */
+ *x++ = '\0';
+
+ if (*x != '\0'){
+ /* parse extensions */
+ }
+ }
+
+ if ( *q != '\0' ) {
+ ludp->lud_filter = q;
+ hex_unescape( ludp->lud_filter );
+ }
+ }
+
+ if ( strcasecmp( p, "one" ) == 0 ) {
+ ludp->lud_scope = LDAP_SCOPE_ONELEVEL;
+ } else if ( strcasecmp( p, "base" ) == 0 ) {
+ ludp->lud_scope = LDAP_SCOPE_BASE;
+ } else if ( strcasecmp( p, "sub" ) == 0 ) {
+ ludp->lud_scope = LDAP_SCOPE_SUBTREE;
+ } else if ( *p != '\0' ) {
+ ldap_free_urldesc( ludp );
+ return( LDAP_URL_ERR_BADSCOPE );
+ }
+ }
+ }
+ if ( *ludp->lud_dn == '\0' ) {
+ ludp->lud_dn = NULL;
+ } else {
+ hex_unescape( ludp->lud_dn );
+ }
+
+ /*
+ * if attrs list was included, turn it into a null-terminated array
+ */
+ if ( attrs != NULL && *attrs != '\0' ) {
+ for ( nattrs = 1, p = attrs; *p != '\0'; ++p ) {
+ if ( *p == ',' ) {
+ ++nattrs;
+ }
+ }
+
+ if (( ludp->lud_attrs = (char **)calloc( nattrs + 1,
+ sizeof( char * ))) == NULL ) {
+ ldap_free_urldesc( ludp );
+ return( LDAP_URL_ERR_MEM );
+ }
+
+ for ( i = 0, p = attrs; i < nattrs; ++i ) {
+ ludp->lud_attrs[ i ] = p;
+ if (( p = strchr( p, ',' )) != NULL ) {
+ *p++ ='\0';
+ }
+ hex_unescape( ludp->lud_attrs[ i ] );
+ }
+ }
+
+ if (x != NULL && *x != '\0'){
+ if (errcode = ldap_url_extension_parse(x, &ludp->lud_extensions)){
+ ldap_free_urldesc(ludp);
+ return ( errcode );
+ }
+ }
+ }
+
+ *ludpp = ludp;
+
+ return( 0 );
+}
+
+void ldap_free_urlexts( LDAPURLExt ** lues)
+{
+ int i;
+ for (i = 0; lues[i] != NULL; i++){
+ free(lues[i]);
+ }
+ free(lues);
+}
+
+
+void
+ldap_free_urldesc( LDAPURLDesc *ludp )
+{
+ if ( ludp != NULLLDAPURLDESC ) {
+ if ( ludp->lud_string != NULL ) {
+ free( ludp->lud_string );
+ }
+ if ( ludp->lud_attrs != NULL ) {
+ free( ludp->lud_attrs );
+ }
+ if (ludp->lud_extensions != NULL) {
+ ldap_free_urlexts(ludp->lud_extensions);
+ }
+ free( ludp );
+ }
+}
+
+
+
+int
+ldap_url_search( LDAP *ld, char *url, int attrsonly )
+{
+ int err;
+ LDAPURLDesc *ludp;
+ BerElement *ber;
+ LDAPServer *srv = NULL;
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ if ( ldap_url_parse( url, &ludp ) != 0 ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+ if (( ber = ldap_build_search_req( ld, ludp->lud_dn,
+ ludp->lud_scope == LDAP_SCOPE_UNKNOWN ? LDAP_SCOPE_BASE : ludp->lud_scope,
+ ludp->lud_filter ? ludp->lud_filter : "(objectclass=*)",
+ ludp->lud_attrs, attrsonly, NULL, NULL, -1 )) == NULLBER ) {
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( -1 );
+ }
+
+ err = 0;
+
+ if ( ludp->lud_host != NULL || ludp->lud_port != 0 ) {
+ if (( srv = (LDAPServer *)calloc( 1, sizeof( LDAPServer )))
+ == NULL || ( srv->lsrv_host = strdup( ludp->lud_host ==
+ NULL ? ld->ld_defhost : ludp->lud_host )) == NULL ) {
+ if ( srv != NULL ) {
+ free( srv );
+ }
+ ld->ld_errno = LDAP_NO_MEMORY;
+ err = -1;
+ } else {
+ if ( ludp->lud_port == 0 ) {
+ srv->lsrv_port = LDAP_PORT;
+ } else {
+ srv->lsrv_port = ludp->lud_port;
+ }
+ }
+ }
+
+ if ( err != 0 ) {
+ ber_free( ber, 1 );
+ } else {
+ err = send_server_request( ld, ber, ld->ld_msgid, NULL, srv, NULL, 1 );
+ }
+
+ ldap_free_urldesc( ludp );
+
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return( err );
+}
+
+
+int
+ldap_url_search_st( LDAP *ld, char *url, int attrsonly,
+ struct timeval *timeout, LDAPMessage **res )
+{
+ int msgid;
+ int retcode = LDAP_SUCCESS;
+
+ if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) {
+ return( ld->ld_errno );
+ }
+
+ if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 ) {
+ return( ld->ld_errno );
+ }
+
+ if ( ld->ld_errno == LDAP_TIMEOUT ) {
+ (void) ldap_abandon( ld, msgid );
+ ld->ld_errno = LDAP_TIMEOUT;
+ return( ld->ld_errno );
+ }
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ retcode = ldap_parse_result(ld, *res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
+ &ld->ld_referrals, &ld->ld_ret_ctrls, 0);
+ if (retcode == LDAP_SUCCESS)
+ retcode = ld->ld_errno;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+
+ return (retcode);
+}
+
+
+int
+ldap_url_search_s( LDAP *ld, char *url, int attrsonly, LDAPMessage **res )
+{
+ int msgid;
+ int retcode = LDAP_SUCCESS;
+
+ if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) {
+ return( ld->ld_errno );
+ }
+
+ if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, res ) == -1 ) {
+ return( ld->ld_errno );
+ }
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ retcode = ldap_parse_result(ld, *res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
+ &ld->ld_referrals, &ld->ld_ret_ctrls, 0);
+ if (retcode == LDAP_SUCCESS)
+ retcode = ld->ld_errno;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+
+ return (retcode);
+}
+
+
+static void
+hex_unescape( char *s )
+{
+/*
+ * Remove URL hex escapes from s... done in place. The basic concept for
+ * this routine is borrowed from the WWW library HTUnEscape() routine.
+ */
+ char *p;
+
+ for ( p = s; *s != '\0'; ++s ) {
+ if ( *s == '%' ) {
+ if ( *++s != '\0' ) {
+ *p = unhex( *s ) << 4;
+ }
+ if ( *++s != '\0' ) {
+ *p++ += unhex( *s );
+ }
+ } else {
+ *p++ = *s;
+ }
+ }
+
+ *p = '\0';
+}
+
+
+static int
+unhex( char c )
+{
+ return( c >= '0' && c <= '9' ? c - '0'
+ : c >= 'A' && c <= 'F' ? c - 'A' + 10
+ : c - 'a' + 10 );
+}
+
+
+/*
+ * Locate the LDAP URL associated with a DNS domain name.
+ *
+ * The supplied DNS domain name is converted into a distinguished
+ * name. The directory entry specified by that distinguished name
+ * is searched for a labeledURI attribute. If successful then the
+ * LDAP URL is returned. If unsuccessful then that entry's parent
+ * is searched and so on until the target distinguished name is
+ * reduced to only two nameparts.
+ *
+ * For example, if 'ny.eng.wiz.com' is the DNS domain then the
+ * following entries are searched until one succeeds:
+ * dc=ny,dc=eng,dc=wiz,dc=com
+ * dc=eng,dc=wiz,dc=com
+ * dc=wiz,dc=com
+ *
+ * If dns_name is NULL then the environment variable LOCALDOMAIN is used.
+ * If attrs is not NULL then it is appended to the URL's attribute list.
+ * If scope is not NULL then it overrides the URL's scope.
+ * If filter is not NULL then it is merged with the URL's filter.
+ *
+ * If an error is encountered then zero is returned, otherwise a string
+ * URL is returned. The caller should free the returned string if it is
+ * non-zero.
+ */
+
+char *
+ldap_dns_to_url(
+ LDAP *ld,
+ char *dns_name,
+ char *attrs,
+ char *scope,
+ char *filter
+)
+{
+ char *dn;
+ char *url = 0;
+ char *url2 = 0;
+ LDAPURLDesc *urldesc;
+ char *cp;
+ char *cp2;
+ size_t attrs_len = 0;
+ size_t scope_len = 0;
+ size_t filter_len = 0;
+ int nameparts;
+ int no_attrs = 0;
+ int no_scope = 0;
+
+ if (dns_name == 0) {
+ dns_name = (char *)getenv("LOCALDOMAIN");
+ }
+
+ if ((ld == NULL) || ((dn = ldap_dns_to_dn(dns_name, &nameparts)) ==
+ NULL))
+ return (0);
+
+ if ((url = ldap_dn_to_url(ld, dn, nameparts)) == NULL) {
+ free(dn);
+ return (0);
+ }
+ free(dn);
+
+ /* merge filter and/or scope and/or attributes with URL */
+ if (attrs || scope || filter) {
+
+ if (attrs)
+ attrs_len = strlen(attrs) + 2; /* for comma and NULL */
+
+ if (scope)
+ scope_len = strlen(scope) + 1; /* for NULL */
+
+ if (filter)
+ filter_len = strlen(filter) + 4;
+ /* for ampersand, parentheses and NULL */
+
+ if (ldap_is_ldap_url(url)) {
+
+ if ((url2 = (char *)malloc(attrs_len + scope_len +
+ filter_len + strlen(url) + 1)) == NULL) {
+ return (0);
+ }
+ cp = url;
+ cp2 = url2;
+
+ /* copy URL scheme, hostname, port number and DN */
+ while (*cp && (*cp != '?')) {
+ *cp2++ = *cp++;
+ }
+
+ /* handle URL attributes */
+
+ if (*cp == '?') { /* test first '?' */
+ *cp2++ = *cp++; /* copy first '?' */
+
+ if (*cp == '?') { /* test second '?' */
+
+ /* insert supplied attributes */
+ if (attrs) {
+ while (*attrs) {
+ *cp2++ = *attrs++;
+ }
+ } else {
+ no_attrs = 1;
+ }
+
+ } else {
+
+ /* copy URL attributes */
+ while (*cp && (*cp != '?')) {
+ *cp2++ = *cp++;
+ }
+
+ /* append supplied attributes */
+ if (attrs) {
+ *cp2++ = ',';
+ while (*attrs) {
+ *cp2++ = *attrs++;
+ }
+ }
+ }
+
+ } else {
+ /* append supplied attributes */
+ if (attrs) {
+ *cp2++ = '?';
+ while (*attrs) {
+ *cp2++ = *attrs++;
+ }
+ } else {
+ no_attrs = 1;
+ }
+ }
+
+ /* handle URL scope */
+
+ if (*cp == '?') { /* test second '?' */
+ *cp2++ = *cp++; /* copy second '?' */
+
+ if (*cp == '?') { /* test third '?' */
+
+ /* insert supplied scope */
+ if (scope) {
+ while (*scope) {
+ *cp2++ = *scope++;
+ }
+ } else {
+ no_scope = 1;
+ }
+
+ } else {
+
+ if (scope) {
+ /* skip over URL scope */
+ while (*cp && (*cp != '?')) {
+ *cp++;
+ }
+ /* insert supplied scope */
+ while (*scope) {
+ *cp2++ = *scope++;
+ }
+ } else {
+
+ /* copy URL scope */
+ while (*cp && (*cp != '?')) {
+ *cp2++ = *cp++;
+ }
+ }
+ }
+
+ } else {
+ /* append supplied scope */
+ if (scope) {
+ if (no_attrs) {
+ *cp2++ = '?';
+ }
+ *cp2++ = '?';
+ while (*scope) {
+ *cp2++ = *scope++;
+ }
+ } else {
+ no_scope = 1;
+ }
+ }
+
+ /* handle URL filter */
+
+ if (*cp == '?') { /* test third '?' */
+ *cp2++ = *cp++; /* copy third '?' */
+
+ if (filter) {
+
+ /* merge URL and supplied filters */
+
+ *cp2++ = '(';
+ *cp2++ = '&';
+ /* copy URL filter */
+ while (*cp) {
+ *cp2++ = *cp++;
+ }
+ /* append supplied filter */
+ while (*filter) {
+ *cp2++ = *filter++;
+ }
+ *cp2++ = ')';
+ } else {
+
+ /* copy URL filter */
+ while (*cp) {
+ *cp2++ = *cp++;
+ }
+ }
+
+ } else {
+ /* append supplied filter */
+ if (filter) {
+ if (no_scope) {
+ if (no_attrs) {
+ *cp2++ = '?';
+ }
+ *cp2++ = '?';
+ }
+ *cp2++ = '?';
+ while (*filter) {
+ *cp2++ = *filter++;
+ }
+ }
+ }
+
+ *cp2++ = '\0';
+ free (url);
+ url = url2;
+
+ } else {
+ return (0); /* not an LDAP URL */
+ }
+ }
+ return (url);
+}
+
+
+/*
+ * Locate the LDAP URL associated with a distinguished name.
+ *
+ * The number of nameparts in the supplied distinguished name must be
+ * provided. The specified directory entry is searched for a labeledURI
+ * attribute. If successful then the LDAP URL is returned. If unsuccessful
+ * then that entry's parent is searched and so on until the target
+ * distinguished name is reduced to only two nameparts.
+ *
+ * For example, if 'l=ny,ou=eng,o=wiz,c=us' is the distinguished name
+ * then the following entries are searched until one succeeds:
+ * l=ny,ou=eng,o=wiz,c=us
+ * ou=eng,o=wiz,c=us
+ * o=wiz,c=us
+ *
+ * If an error is encountered then zero is returned, otherwise a string
+ * URL is returned. The caller should free the returned string if it is
+ * non-zero.
+ */
+
+char *
+ldap_dn_to_url(
+ LDAP *ld,
+ char *dn,
+ int nameparts
+)
+{
+ char *next_dn = dn;
+ char *url = 0;
+ char *attrs[2] = {"labeledURI", 0};
+ LDAPMessage *res, *e;
+ char **vals;
+
+ /*
+ * Search for a URL in the named entry or its parent entry.
+ * Continue until only 2 nameparts remain.
+ */
+ while (dn && (nameparts > 1) && (! url)) {
+
+ /* search for the labeledURI attribute */
+ if (ldap_search_s(ld, dn, LDAP_SCOPE_BASE,
+ "(objectClass=*)", attrs, 0, &res) == LDAP_SUCCESS) {
+
+ /* locate the first entry returned */
+ if ((e = ldap_first_entry(ld, res)) != NULL) {
+
+ /* locate the labeledURI attribute */
+ if ((vals =
+ ldap_get_values(ld, e, "labeledURI")) !=
+ NULL) {
+
+ /* copy the attribute value */
+ if ((url = strdup((char *)vals[0])) !=
+ NULL) {
+ ldap_value_free(vals);
+ }
+ }
+ }
+ /* free the search results */
+ ldap_msgfree(res);
+ }
+
+ if (! url) {
+ /* advance along the DN by one namepart */
+ if (next_dn = strchr(dn, ',')) {
+ next_dn++;
+ dn = next_dn;
+ nameparts--;
+ }
+ }
+ }
+
+ return (url);
+}
diff --git a/usr/src/lib/libldap4/common/utils.c b/usr/src/lib/libldap4/common/utils.c
new file mode 100644
index 0000000000..e3652ac275
--- /dev/null
+++ b/usr/src/lib/libldap4/common/utils.c
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+void free_strarray( char **sap )
+{
+ int i;
+
+ if ( sap != NULL ) {
+ for ( i = 0; sap[ i ] != NULL; ++i ) {
+ free( sap[ i ] );
+ }
+ free( (char *)sap );
+ }
+}
diff --git a/usr/src/lib/libldap4/common/version.c b/usr/src/lib/libldap4/common/version.c
new file mode 100644
index 0000000000..bfc8680612
--- /dev/null
+++ b/usr/src/lib/libldap4/common/version.c
@@ -0,0 +1,22 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1991 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+static char Version[] = VERSIONNAME": libldap.a 4.0";
diff --git a/usr/src/lib/libldap4/common/vlistctrl.c b/usr/src/lib/libldap4/common/vlistctrl.c
new file mode 100644
index 0000000000..53335f4490
--- /dev/null
+++ b/usr/src/lib/libldap4/common/vlistctrl.c
@@ -0,0 +1,124 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+
+
+int ldap_create_virtuallist_control(LDAP *ld, LDAPVirtualList *ldvlistp,
+ LDAPControl **ctrlp)
+{
+ BerElement *ber;
+ int rc;
+
+ if (NULL == ld)
+ return (LDAP_PARAM_ERROR);
+
+ if (NULL == ctrlp || NULL == ldvlistp)
+ return (LDAP_PARAM_ERROR);
+
+ if ((ber = alloc_ber_with_options(ld)) == NULLBER) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return (LDAP_NO_MEMORY);
+ }
+
+ if (ber_printf(ber, "{ii", ldvlistp->ldvlist_before_count,
+ ldvlistp->ldvlist_after_count) == -1) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (LDAP_ENCODING_ERROR);
+ }
+
+ if (NULL == ldvlistp->ldvlist_attrvalue) {
+ if (ber_printf(ber, "t{ii}}", LDAP_TAG_VLV_BY_INDEX,
+ ldvlistp->ldvlist_index,
+ ldvlistp->ldvlist_size) == -1) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (LDAP_ENCODING_ERROR);
+ }
+ } else {
+ if (ber_printf(ber, "to}", LDAP_TAG_VLV_BY_VALUE,
+ ldvlistp->ldvlist_attrvalue,
+ strlen(ldvlistp->ldvlist_attrvalue)) == -1) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (LDAP_ENCODING_ERROR);
+ }
+ }
+
+ rc = ldap_build_control(LDAP_CONTROL_VLVREQUEST, ber, 1, 1, ctrlp);
+ ld->ld_errno = rc;
+ return (rc);
+}
+
+
+int ldap_parse_virtuallist_control(LDAP *ld, LDAPControl **ctrls,
+ unsigned long *target_posp, unsigned long *list_sizep, int *errcodep)
+{
+ BerElement *ber;
+ int i, foundListControl;
+ LDAPControl *listCtrlp;
+
+ if (NULL == ld)
+ return (LDAP_PARAM_ERROR);
+
+ /* only ldapv3 or higher can do virtual lists. */
+ if (ld->ld_version != LDAP_VERSION3) {
+ ld->ld_errno = LDAP_NOT_SUPPORTED;
+ return (LDAP_NOT_SUPPORTED);
+ }
+
+ /* find the listControl in the list of controls if it exists */
+ if (ctrls == NULL) {
+ ld->ld_errno = LDAP_NOT_SUPPORTED;
+ return (LDAP_NOT_SUPPORTED);
+ }
+
+ foundListControl = 0;
+ for (i = 0; ((ctrls[i] != NULL) && (!foundListControl)); i++) {
+ foundListControl = !(strcmp(ctrls[i]->ldctl_oid,
+ LDAP_CONTROL_VLVRESPONSE));
+ }
+ if (!foundListControl) {
+ ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
+ return (LDAP_CONTROL_NOT_FOUND);
+ } else {
+ /* let local var point to the listControl */
+ listCtrlp = ctrls[i-1];
+ }
+
+ /* allocate a Ber element with the contents of the list_control's */
+ /* struct berval */
+ if ((ber = ber_init(&listCtrlp->ldctl_value)) == NULL) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return (LDAP_NO_MEMORY);
+ }
+
+ /* decode the result from the Berelement */
+ if (LBER_ERROR == ber_scanf(ber, "{iie}", target_posp, list_sizep,
+ errcodep)) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ ber_free(ber, 1);
+ return (LDAP_DECODING_ERROR);
+ }
+
+ /* the ber encoding is no longer needed */
+ ber_free(ber, 1);
+
+ return (LDAP_SUCCESS);
+}
diff --git a/usr/src/lib/libldap4/i386/Makefile b/usr/src/lib/libldap4/i386/Makefile
new file mode 100644
index 0000000000..10b1c4f5f5
--- /dev/null
+++ b/usr/src/lib/libldap4/i386/Makefile
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 1997-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/liblibldap4/i386/Makefile
+
+MAPDIR= ../spec/i386
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS)
diff --git a/usr/src/lib/libldap4/include/avl.h b/usr/src/lib/libldap4/include/avl.h
new file mode 100644
index 0000000000..c0742f5d9d
--- /dev/null
+++ b/usr/src/lib/libldap4/include/avl.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Portions Portions Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* avl.h - avl tree definitions */
+/*
+ * Copyright (c) 1993 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+
+#ifndef _AVL
+#define _AVL
+
+/*
+ * this structure represents a generic avl tree node.
+ */
+
+typedef struct avlnode {
+ caddr_t avl_data;
+ char avl_bf;
+ struct avlnode *avl_left;
+ struct avlnode *avl_right;
+} Avlnode;
+
+#define NULLAVL ((Avlnode *) NULL)
+
+/* balance factor values */
+#define LH -1
+#define EH 0
+#define RH 1
+
+/* avl routines */
+#define avl_getone(x) (x == 0 ? 0 : (x)->avl_data)
+#define avl_onenode(x) (x == 0 || ((x)->avl_left == 0 && (x)->avl_right == 0))
+extern int avl_insert();
+extern caddr_t avl_delete();
+extern caddr_t avl_find();
+extern caddr_t avl_getfirst();
+extern caddr_t avl_getnext();
+extern int avl_dup_error();
+extern int avl_apply();
+
+/* apply traversal types */
+#define AVL_PREORDER 1
+#define AVL_INORDER 2
+#define AVL_POSTORDER 3
+/* what apply returns if it ran out of nodes */
+#define AVL_NOMORE -6
+
+typedef int (*IFP)();
+
+#endif /* _AVL */
diff --git a/usr/src/lib/libldap4/include/cdefs.h b/usr/src/lib/libldap4/include/cdefs.h
new file mode 100644
index 0000000000..2805136d64
--- /dev/null
+++ b/usr/src/lib/libldap4/include/cdefs.h
@@ -0,0 +1,131 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)cdefs.h 8.7 (Berkeley) 1/21/94
+ */
+
+#ifndef _CDEFS_H_
+#define _CDEFS_H_
+
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS };
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments. __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define __P(protos) protos /* full-blown ANSI C */
+#define __CONCAT(x,y) x ## y
+#define __STRING(x) #x
+
+#define __const const /* define reserved names to standard */
+#define __signed signed
+#define __volatile volatile
+#if defined(__cplusplus)
+#define __inline inline /* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define __inline /* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
+#else /* !(__STDC__ || __cplusplus) */
+#define __P(protos) () /* traditional C preprocessor */
+#define __CONCAT(x,y) x/**/y
+#define __STRING(x) "x"
+
+#ifndef __GNUC__
+#define __const /* delete pseudo-ANSI C keywords */
+#define __inline
+#define __signed
+#define __volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef NO_ANSI_KEYWORDS
+#define const /* delete ANSI C keywords */
+#define inline
+#define signed
+#define volatile
+#endif
+#endif /* !__GNUC__ */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
+ */
+#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
+#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define __dead __volatile
+#define __pure __const
+#endif
+#endif
+
+/* Delete pseudo-keywords wherever they are not available or needed. */
+#ifndef __dead
+#define __dead
+#define __pure
+#endif
+
+#endif /* !_CDEFS_H_ */
diff --git a/usr/src/lib/libldap4/include/ch_malloc.h b/usr/src/lib/libldap4/include/ch_malloc.h
new file mode 100644
index 0000000000..650d4ba856
--- /dev/null
+++ b/usr/src/lib/libldap4/include/ch_malloc.h
@@ -0,0 +1,13 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+char * ch_malloc( unsigned long size );
+char * ch_realloc( char *block, unsigned long size );
+char * ch_calloc( unsigned long nelem, unsigned long size );
+char * ch_strdup( char *s1 );
+void ch_free(void *ptr);
diff --git a/usr/src/lib/libldap4/include/charray.h b/usr/src/lib/libldap4/include/charray.h
new file mode 100644
index 0000000000..b28a91a7f4
--- /dev/null
+++ b/usr/src/lib/libldap4/include/charray.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+extern void charray_add(char ***a, char *s);
+extern void charray_add_uniq(char ***a, char *s);
+extern void charray_add_case_uniq(char ***a, char *s);
+extern void charray_merge(char ***a, char **s);
+extern void charray_free( char **array );
+extern int charray_inlist( char **a, char *s);
+extern char ** charray_dup( char **a );
+extern int charray_count( char **a);
+extern char ** str2charray( char *str, char *brkstr );
+extern char ** str2charray2( char *str, char *brkstr, int *NbItems );
+extern char * ch_strdup( char *s1 );
+extern void charray_sort(char **a, int (*comp_func)(const char *, const char *));
+extern int charray_pos(char **a, char *s);
+
+
+
diff --git a/usr/src/lib/libldap4/include/client_door.h b/usr/src/lib/libldap4/include/client_door.h
new file mode 100644
index 0000000000..2aefe3d7f0
--- /dev/null
+++ b/usr/src/lib/libldap4/include/client_door.h
@@ -0,0 +1,15 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+extern int connect_dsserv(int pid, int cid, void ** scid,
+ struct in_addr * addr);
+extern int disconnect_dsserv(int pid, int cid, void * scid, int reas);
+extern int operation_buf_dsserv(int pid, int cid, void * scid,
+ char * buf,int bufsize, char **rbuf, int * rsize);
+extern int operation_fd_dsserv(int pid, int cid, void * scid, int fd);
diff --git a/usr/src/lib/libldap4/include/entry.h b/usr/src/lib/libldap4/include/entry.h
new file mode 100644
index 0000000000..460b8e9e30
--- /dev/null
+++ b/usr/src/lib/libldap4/include/entry.h
@@ -0,0 +1,271 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * structs for storing and updating entries
+ */
+
+#if !defined(_ENTRY_H_) && !defined(_PROTO_SLAP)
+#define _ENTRY_H_
+
+#ifndef _SLDAPD_H_
+
+/*
+ * represents an attribute (type + values + syntax + oid)
+ */
+typedef struct attr {
+ char *a_type;
+ struct berval **a_vals;
+ int a_syntax;
+ struct attr *a_next;
+} Attribute;
+
+/*
+ * the attr_syntax() routine returns one of these values
+ * telling what kind of syntax an attribute supports.
+ *
+ * NOTE: The syntax may not be available in libentry unless you have
+ * read the slapd.conf config file.
+ */
+#define SYNTAX_CIS 0x01 /* case insensitive string */
+#define SYNTAX_CES 0x02 /* case sensitive string */
+#define SYNTAX_BIN 0x04 /* binary data */
+#define SYNTAX_TEL 0x08 /* telephone number string */
+#define SYNTAX_DN 0x10 /* dn string */
+#define SYNTAX_LONG 0x20 /* integer */
+#define SYNTAX_ULONG 0x40 /* integer */
+#define SYNTAX_CRYPT 0x80 /* crypted password */
+#define SYNTAX_UTCTIME 0x0100 /* Utctime string YYMMDDhhmm[ss]Z */
+#define SYNTAX_GENTIME 0x0200 /* gentime string YYYYMMDDhhmm[ss]Z */
+
+/* These next two are used by libentry. They are overloaded into a_syntax
+ * because there's no extra room and we didn't want to enlarge the structure
+ * because of the performance hit.
+ */
+#define ATTRIBUTE_FOUND 0x1000 /* Set if attribute was found */
+#define ATTRIBUTE_ADD 0x2000 /* Set if values are to be added instead of replaced */
+
+#define DEFAULT_SYNTAX SYNTAX_CIS
+
+typedef struct asyntaxinfo {
+ char **asi_names;
+ char *asi_oid;
+ int asi_options;
+#define ATTR_OPT_SINGLE 0x01 /* Single Valued attr */
+#define ATTR_OPT_OPERATIONAL 0x02 /* Operational attr */
+#define ATTR_OPT_NAMING 0x10 /* Naming Attribute */
+ char *asi_default_oc;
+ int asi_maxlen;
+ int asi_syntax;
+} AttrSyntaxInfo;
+
+/*
+ * the id used in the indexes to refer to an entry
+ */
+typedef unsigned int ID;
+#define NOID ((unsigned int)-1)
+
+/*
+ * represents an entry in core
+ */
+typedef struct entry {
+ char *e_dn; /* DN of this entry */
+ Attribute *e_attrs; /* list of attributes + values */
+
+ ID e_id; /* not used in libentry */
+ char e_state; /* only ENTRY_FOUND is used below */
+#define ENTRY_STATE_DELETED 0x01 /* value not used in libentry */
+#define ENTRY_STATE_CREATING 0x02 /* value not used in libentry */
+ int e_refcnt; /* # threads ref'ing this entry */
+ pthread_mutex_t e_mutex; /* to lock for add/modify */
+ struct entry *e_lrunext;
+ struct entry *e_lruprev; /* not used in libentry, (could be added) */
+} Entry;
+
+/* This next #define is used by libentry. It is overloaded into e_state.
+ * It is used to mark entries as found/not found so that they can be deleted
+ * if they are not found (for example on a remote replica).
+ */
+#define ENTRY_FOUND 0x80
+
+#endif _SLDAPD_H_
+
+/* entry.c */
+
+/* output_ldif takes a modlist structure and prints out ldif. Since there are 3 ways
+ * you can use a modlist structure, you need to tell this routine what you're doing.
+ * The three choices are:
+ * LDAP_MODIFY_ENTRY
+ * LDAP_ADD_ENTRY
+ * LDAP_DELETE_ENTRY
+ * ldif suitable for feeding to ldapmodify will be produced.
+ */
+
+/* op arg to output_ldif() */
+#define LDAP_MODIFY_ENTRY 1
+#define LDAP_ADD_ENTRY 2
+#define LDAP_DELETE_ENTRY 3
+
+void output_ldif(char *dn, int op, LDAPMod **modlist, FILE *out);
+
+/* Checks that base exist. If not, create it.
+ * ld - ldap context, you must supply it because it's used in ldap_search
+ * out - file to output ldif to. If supplied, ldif will be printed here,
+ * if not supplied, ldap_mod will be called for you (using ld).
+ *
+ * returns number of entries created if all is ok, -1 if an error occured.
+ *
+ * mutex locks: if you are outputting to out from other threads, you need
+ * to lock output_mutex. output_ldif locks this mutex before outputting.
+ */
+
+int make_base(LDAP *ld, FILE *out, char *base);
+
+/* Add an entry to ldap. You supply an Entry struct. Will either add entry
+ * to ldap or output ldif to an open file (stdout for example).
+ *
+ * ld - ldap context. Must be valid if you want entry_add to add entries to ldap
+ * for you.
+ * out - open file where to send ldif output. One of ld or out should be valid.
+ * new_entry is an Entry which you want added to ldap
+ *
+ * returns number of entries created or -1 if an error occured in ldap_add()
+ */
+
+int entry_add(LDAP *ld, FILE *out, Entry *new_entry);
+
+/* Compares two entries and issue changes to make old look like new.
+ *
+ * ld - ldap context. Must be valid if you want entry_update to add entries to ldap
+ * for you.
+ * out - open file where to send ldif output. One of ld or out should be valid.
+ * new_entry is an Entry which you want old_entry to look like
+ *
+ * returns number of entries modified or -1 if an error occured in ldap_modify()
+ */
+
+int entry_update(LDAP *ld, FILE *out, Entry *old_entry, Entry *new_entry);
+
+/* Deletes an entry.
+ * ld - ldap context. Must be valid if you want delete_entry to call ldap
+ * for you.
+ * out - open file where to send ldif output. One of ld or out should be valid.
+ * ldap_entry is an Entry which you want to delete
+ *
+ * returns number of entries deleted or -1 if an error occured in ldap_modify()
+ * usually one, but for future it might delete more than one.
+ */
+
+int entry_delete(LDAP *ld, FILE *out, Entry *ldap_entry);
+
+/* attr.c */
+void attr_free( Attribute *a );
+int attr_merge_fast(
+ Entry *e,
+ char *type,
+ struct berval **vals,
+ int nvals,
+ int naddvals,
+ int *maxvals,
+ Attribute ***a
+);
+int attr_merge(
+ Entry *e,
+ char *type,
+ struct berval **vals
+);
+
+Attribute *attr_find(
+ Attribute *a,
+ char *type,
+ int ignoreOpt
+);
+int attr_delete(
+ Attribute **attrs,
+ char *type
+);
+int attr_syntax( char *type );
+int attr_syntax_by_oid( char *oid );
+void attr_syntax_config(
+ char *fname,
+ int lineno,
+ int argc,
+ char **argv
+);
+char * attr_normalize( char *s );
+char * alias_normalize( char *s );
+int type_compare(char * t1, char *t2);
+int type_list_compare(
+ char **a,
+ char *s
+);
+
+int attr_cmp(Attribute *attr1, Attribute *attr2);
+char * get_type_from_list(char **a, char *s);
+int attr_single_valued_check(char *type, struct berval **vals);
+AttrSyntaxInfo *get_attrSyntaxInfo(char *type);
+char * attr_syntax2oid(int aSyntax);
+
+/* value.c */
+int value_add_fast(
+ struct berval ***vals,
+ struct berval **addvals,
+ int nvals,
+ int naddvals,
+ int *maxvals
+);
+int value_delete(
+ struct berval ***vals,
+ struct berval *v,
+ int syntax,
+ int normalize
+);
+int value_add_one(
+ struct berval ***vals,
+ struct berval *v,
+ int syntax,
+ int normalize
+);
+time_t utc2seconds(char * utctime);
+int value_add(
+ struct berval ***vals,
+ struct berval **addvals
+);
+void value_normalize(
+ char *s,
+ int syntax
+);
+int value_cmp(
+ struct berval *v1,
+ struct berval *v2,
+ int syntax,
+ int normalize /* 1 => arg 1; 2 => arg 2; 3 => both */
+);
+int value_ncmp(
+ struct berval *v1,
+ struct berval *v2,
+ int syntax,
+ int len,
+ int normalize
+);
+int value_find(
+ struct berval **vals,
+ struct berval *v,
+ int syntax,
+ int normalize
+);
+int value_cnt(struct berval **vals);
+
+/* dn.c */
+char *dn_normalize( char *dn );
+char *dn_normalize_case( char *dn );
+int dn_issuffix(char *dn, char *suffix);
+char *dn_upcase( char *dn );
+
+#endif _ENTRY_H_
diff --git a/usr/src/lib/libldap4/include/fe.h b/usr/src/lib/libldap4/include/fe.h
new file mode 100644
index 0000000000..4e2772ec14
--- /dev/null
+++ b/usr/src/lib/libldap4/include/fe.h
@@ -0,0 +1,420 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _FE_H
+#define _FE_H
+
+/*
+ * Get context const . Used to retreive info in context : fe_get_ctx
+ * Return values depend on requested info :
+ */
+#define CTX_FENAME 1 /* To get the Front End name */
+ /* return value is (char *) */
+#define CTX_NBTABLE 2 /* To get the number of sub-section */
+ /* return value is (int *) */
+#define CTX_TABLENAME 3 /* To get name(s) of sub section */
+ /* return value is (char **) */
+#define CTX_TABLEPTR 4 /* To get the ptr to a sub section definition */
+ /* return value is (FE_Table *) */
+ /* !! This is not a copy */
+#define CTX_CUSTOMS 5 /* get customs attributes */
+ /* third parameter is the variable name (char *) */
+
+/*
+ * Get Tables const
+ */
+#define TABLE_NAME 1 /* table or subsection name, return value is (char *) */
+ /* third parms is null */
+#define TABLE_OBJ_LST 2 /* object class list, return value is (char **) */
+ /* third parms is null */
+#define TABLE_COM_HLD 3 /* stored ldap, connection return value is (LDAP *) */
+#define TABLE_CUSTOMS 4 /* get customs attributes */
+ /* third parameter is the variable name (char *) */
+ /* return value is an array of string (char **) */
+#define TABLE_FEATTR 5 /* to get the attribute definition. If no attribute name */
+ /* is provided to get the list of attributes */
+ /* third parms is the attribute name */
+ /* return a FE_Attr * if attribute name provided */
+ /* return a char ** (null term) if no attribute name provided */
+
+#define TABLE_SUNDSATTR 6 /* idem TABLE_FEATTR but for SunDS definition */
+
+/*
+ * Tokens/Attributes
+ */
+#define FETABLE 0
+#define SUNDSTABLE 1
+#define SUNDSATTRLIST 2
+#define SUNDSTOKENLIST 3
+#define FEATTRLIST 4
+#define FETOKENLIST 5
+#define FEBUILDLIST 6
+#define SUNDSBUILDLIST 7
+
+/*
+ * Errors consts
+ */
+#define NOERROR 0
+#define INVALID_PARMS 1
+#define VALUE_NOT_FOUND 2
+#define CREATE_FAILED 3
+#define SYNTAX_ERROR 4
+
+/*
+ * SPLIT way
+ */
+#define LEFT2RIGHT 0
+#define RIGHT2LEFT 1
+/*
+ * Data structures
+ */
+
+/*
+ * This struct is used to run regex with "reg_expression"
+ * and assigned values (braelist) with "token" links
+ * Functional schema :
+ * step(input,reg_expression)
+ * => token[0] = braslist[0]..braelist[0]
+ * => token[1] = braslist[1]..braelist[1]
+ * => ...
+ * => token[i] = braslist[i]..braelist[i]
+ */
+typedef struct _reg_mapp {
+ char *reg_expression; /* Compiled regular expression */
+ int Nbra; /* nbra result */
+ int NbToken_Defined; /* Nb tokens defined in reg_expression */
+ int *Token_ID; /* Tokens place (index) in input value */
+} Reg_Map;
+
+/*
+ * Tokens definition, including input attribute and number of expressions
+ * and link to each rule.
+ */
+typedef struct _tokens_def {
+ int attr_ID; /* Attributes ID (in SD or FE Table) */
+ /* Used as input in regular expression */
+ int NbRules; /* Number of expressions seperated by | */
+ Reg_Map **TokenRules; /* Array of tokens rules */
+} Token_Def;
+
+/*
+ * Attribute mapping definition. SD attributes are composed of FE attributes and
+ * SD tokens.
+ */
+typedef struct _attr_mapping {
+ char *AttrName; /* Attribute Name */
+ char *Expr; /* Value expression */
+ int AttrStatus; /* Store several attr's info such as */
+ /* Key || Exist || Frozen */
+ /* Key is used to generate wizard filter */
+ /* Exist is used to generate wizard filter */
+ /* Frozen is used control access on attribute */
+ int NbItem; /* Nb Attributes & Tokens need to build val */
+ int *AttrID; /* Set of attributes including tokens */
+} Attr_Mapping;
+
+/*
+ * Builder_map : defined builder expression
+ */
+typedef struct _builder_map {
+ char *build_exp; /* the sentence to build */
+ int NbInput;
+ int *Input_ID; /* List of attr ID to used as input in semtence */
+}Builder_map;
+
+/*
+ * Data used for split/string2instances/instances2string/exclude functions
+ */
+typedef struct _builder_fct {
+ int Input_ID;
+ char *value; /* input data */
+ char *prefix; /* string2instances and reverse : prefix */
+ /* exclude : val 2 exclude */
+ int Parm_ID; /* only for exclude funct : ID of val 2 exclude */
+ char *suffix;
+ char *separator;
+ int readIndicator;
+} Builder_fct;
+
+/*
+ * Builder tokens : used to build special value (named builder token) from other tokens
+ * or input value. They look like ouput attributes, but they allow to apply rules, if
+ * input value does exist. They also permit to split input sentence into attribute instances
+ */
+typedef struct _builder {
+ char *builder_name;
+ int builder_ID;
+ int NbRules;
+ int BuilderType;
+ Builder_map *Mapp;
+ Builder_fct *Fct;
+} Build_def;
+
+
+/*
+ * Full definition of table mapping.
+ */
+typedef struct _table_mapping {
+ int NbTokens; /* Nb extract tokens defined */
+ int NbAttributes; /* Nb attributes in the entry */
+ int NbBuilder; /* Nb builder tokens defined */
+ Token_Def **Tokens_list; /* Array of tokens needed for translation */
+ Build_def *Build_list; /* Array of builder tokens */
+ Attr_Mapping **Attr_list; /* Array of Attributes defined in an entry */
+} Table_Mapping;
+
+typedef struct _custo_info {
+ char *InfoName;
+ int NbValues;
+ char **Values; /* Null terminated array of instance */
+} Cust_Info;
+
+typedef struct _sds_com {
+ LDAP *lhd; /* LDAP communication handle */
+ char **fe_object_list; /* Array of ObjectClasses (null term list) */
+} SDS_Com;
+
+typedef struct _dynrule {
+ char *ResName; /* Result (or Rule) name */
+ int opType; /* Extrac, Cond, split, str2ins, ins2str, */
+ /* getrdn, exclude */
+ int NbExpr; /* Nb rules found use only in extract & cond */
+ int *NbItems; /* Nb variable in expression, usefull for */
+ /* extract and cond. IT's a null terminated */
+ /* array which contains the Number of var in */
+ char **Expression; /* The sentence (make sense only in cond) */
+ char **ConstVal; /* use when funct parm are const not used for */
+ /* extract and cond cases */
+ char **VarName; /* Var can be 1)DynRule 2)InputData 3)Common */
+} DynRule;
+
+typedef struct _fe_table {
+ char *fe_section; /* Section table name */
+ int nb_fe_attr; /* Nb FE attributes defined */
+ int nb_sds_attr; /* Nb SDS attributes defined */
+ int nb_fe_tokens; /* Nb tokens defined in FE section */
+ int nb_sds_tokens; /* Nb tokens defined in SunDS section */
+ int nb_cust; /* Nb custom attributes in common section */
+ int nb_fe_build; /* Nb tokens build in FE section */
+ int nb_sds_build; /* Nb tokens build in SUNDS section */
+ int nb_dyn_rules; /* Nb dynamic rules in Dynamic section */
+ char **fe_token_list; /* Array of FE token */
+ char **sds_token_list; /* List of SunDS token */
+ char **fe_attr_list; /* Array of attributes (null term list) */
+ char **sds_attr_list; /* Array of attributes (null term list) */
+ char **fe_build_list; /* Array of FE build */
+ char **sds_build_list; /* List of SunDS build */
+ Table_Mapping *sds_schema; /* SDS attributes definition */
+ Table_Mapping *fe_schema; /* FE attributes definition */
+ SDS_Com *comm_items; /* Communication attributes */
+ Cust_Info **custo_info; /* Customs info */
+ DynRule *dyn_rules; /* Ordered dynamic rules */
+} FE_Table;
+
+typedef struct _fe_context {
+ char *fe_name; /* Is it really usefull ?? */
+ int NbSection; /* Nb section */
+ int NbGlobals; /* Nb global customs info */
+ Cust_Info **globals; /* Customs info */
+ FE_Table **fe_section_list; /* All sub-section in mapping file */
+} FE_Context;
+
+/* Entries values definition */
+/* Instance values definition */
+typedef struct _fe_values {
+ int Length;
+ void *Val;
+} FE_Values;
+
+/* Attribute value definition */
+typedef struct _fe_attr {
+ char *AttrType;
+ int NbInstance;
+ FE_Values **ValInstances;
+} FE_Attr;
+
+/* Full entry definition */
+typedef struct _fe_entry {
+ char *DN;
+ int Nb_items;
+ FE_Attr **AttributesArray;
+} FE_Entry;
+
+typedef struct _fe_couple {
+ char *Value2Subst;
+ char *SubstValue;
+} FE_Couple;
+
+/*
+ * libfe.a exported functions
+ */
+
+/*
+ * Read config file and create "fe_name" context
+ * NB : This init read all tables mapping
+ * libldap context use : before all action
+ */
+extern FE_Context *fe_ctx_init(char *config_path, char *fe_name);
+
+/*
+ * Free All fe context all tables ...
+ * libldap context usage : ldap_close
+ */
+extern int fe_ctx_free(FE_Context **Ctx);
+
+/*
+ * Return the pointer to requested item in context
+ * libldap context usage : before all action
+ */
+extern void *fe_ctx_get(FE_Context *Ctx, int FieldID, void *Value);
+
+/*
+ * Search for information from Subsection/Table ?
+ * You can check also Get/Table/Paragraph
+ * libldap context usage : ldap_*
+ */
+extern void *fe_table_get(FE_Table *MapTable, int FieldID, void *Void);
+
+/*
+ * Set tables item is mainly used for communication items. other information
+ * sets will be forbid
+ * libldap context usage : after ldap_open or ldap_bind
+ */
+/*
+extern int fe_table_set(FE_Table *MapTable, int FieldID, void *Void);
+*/
+/*
+ * You have the attribute name ?! fe_ent_get_attr returns pointer to the requested
+ * attributes with instances, status... from a specific entry
+ * libldap context usage : after ldap_search
+ */
+extern FE_Attr *fe_ent_get_attr(FE_Table *MapTable, FE_Entry *fe_item, char *AttrName);
+
+/*
+ * Create the entry according to the "schema" defined in mapping file for a specific table
+ * libladp context usage : before ldap_add
+ */
+extern FE_Entry *fe_ent_create(FE_Table *MapTable, int TableType);
+
+/*
+ * Add new attributes in a new entry
+ * libladp context usage : before ldap_add
+ */
+extern FE_Attr *fe_ent_get_attr(FE_Table *MapTable,FE_Entry *Entry, char *AttrName);
+
+/*
+ * Add new instance value
+ * libladp context usage : before ldap_add
+ */
+extern int fe_ent_add_val(FE_Table *MapTable, FE_Attr *attr, int ValLength, void *Val);
+extern FE_Attr *fe_ent_add_attr_val(FE_Table *MapTable, FE_Entry *Entry, char *AttrName, int ValLength, void *Val);
+
+/*
+ * explode DN into an attributes array
+ * libladp context usage : after ldap_search
+ */
+extern FE_Attr **fe_ent_show_dn(FE_Table *MapTable, FE_Entry *Entry);
+
+/*
+ * free entry (including attributes)
+ */
+extern void fe_ent_free(FE_Entry **Entry);
+
+/*
+ * Substitute all vars defined in inputString (with syntax ${varName}) by values found in
+ * fe_couple array. For errors returned check the errors consts upper
+ */
+extern int fe_subst(char *inputString, char **outputString, FE_Couple **fe_couple);
+
+/*
+ * Split a sentence, add prefix (for each token) and suffix (exept for the last)
+ */
+extern char *fe_split(char *inputData, char *Separator, char *Prefix, char *Suffix, int way );
+
+/*
+ * Dynamic translation, use only definition in dynamic section
+ */
+extern char **fe_dynamic(FE_Table *MapTable, char *Var2stop, char **DynVal);
+
+/*
+ * Return the translated attribute. TableType is the original table of AttrName.
+ * if translation rules is one to one translation, the function return a copy of translated
+ * attribute name.
+ * else the function return a copy of the rules
+ */
+extern char **fe_trans_attrName(FE_Table *MapTable, char *AttrName, int TableType);
+extern int *fe_trans_attrID(FE_Table *MapTable, char *AttrName, int TableType);
+
+/*
+ * Return the translated SD entry
+ * libladp context usage : after ldap_search
+ */
+extern FE_Entry *fe_trans_all_sds2fe(FE_Table *MapTable, LDAP *ld, LDAPMessage *sd_entry);
+
+/*
+ * Return the translated FE entry
+ * libladp context usage : after ldap_search
+ */
+extern LDAPMod **fe_trans_all_fe2sds(FE_Table *MapTable, LDAP *ld, FE_Entry *fe_entry);
+
+/*
+ * Close to "fe_trans_all_sds2fe" but output is Entry pointer as defined in SunDS server
+ */
+extern FE_Entry *fe_trans_all_sunds2fe(FE_Table *MapTable, Entry *sd_entry);
+extern Entry *fe_trans_all_fe2sunds(FE_Table *MapTable, FE_Entry *fe_entry);
+
+/* An example an example ....
+ * Translation from fe to sunds
+ *
+ * FE_Context *MyContext = NULL;
+ * FE_Table *HostTable = NULL;
+ * FE_Entry *fe_entry = NULL;
+ * FE_Attr *fe_attr = NULL;
+ * Entry *lentry = NULL;
+ *
+ * if((MyContext = fe_ctx_init("..../sunds_map.conf","NIS")) == NULL){
+ * ldaplog(LDAP_DEBUG_CONFIG,"Can't load mapping file\n", 0, 0, 0);
+ * exit(1);
+ * }
+ * if((HostTable = fe_ctx_get(MyContext,CTX_TABLEPTR,"dummy")) == NULL)
+ * {
+ * ldaplog(LDAP_DEBUG_CONFIG,"Can't retreive HOSTS table\n", 0, 0, 0);
+ * exit(1);
+ * }
+ * if((fe_entry = fe_ent_create(HostTable, FETABLE))==NULL)
+ * {
+ * ldaplog(LDAP_DEBUG_CONFIG,"Can't create entry\n", 0, 0, 0);
+ * exit(1);
+ * }
+ * if ((fe_attr = fe_ent_add_attr_val(HostTable, fe_entry, "niskey", 16, "109.107.179.131")) == NULL)
+ * {
+ * ldaplog(LDAP_DEBUG_CONFIG,"Can't add attr=%s, val=%s\n", "niskey", "109.107.179.131", 0);
+ * exit(1);
+ * }
+ * if((fe_attr = fe_ent_add_attr_val(HostTable,
+ * fe_entry,
+ * "NISVALUE",
+ * strlen("olivaw OLIVAW oLiVaW # regis Host") +1,
+ * "olivaw OLIVAW oLiVaW # regis Host")) == NULL)
+ * {
+ * ldaplog(...);
+ * exit(1);
+ * }
+ * if((lentry = fe_trans_all_fe2sunds(HostTable, fe_entry)) ==NULL)
+ * {
+ * ldaplog(LDAP_DEBUG_CONFIG,".... \n", 0);
+ * }
+ *
+ */
+
+#endif /* _FE_H */
+
+
+
+
diff --git a/usr/src/lib/libldap4/include/hsearch.h b/usr/src/lib/libldap4/include/hsearch.h
new file mode 100644
index 0000000000..4de0fcfb75
--- /dev/null
+++ b/usr/src/lib/libldap4/include/hsearch.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#ident "@(#)hsearch.h 1.3 07/23/97 SMI"
+typedef struct { /* Hash table entry */
+ char * key;
+ char * data;
+ int dsize;
+ int modified;
+ time_t timestamp;
+} HASH_ENTRY;
+
+typedef struct node { /* Part of the linked list of entries */
+ HASH_ENTRY item;
+ struct node *next;
+} NODE;
+
+typedef enum {
+ FIND, /* Find, if present */
+ ENTER, /* Find; enter if not present */
+ REPLACE, /* replace */
+ DELETE, /* delete */
+} ACTION;
+
+/* define everything that a hash table needs to drag around */
+typedef struct hash_table {
+ NODE **table; /* The address of the hash table */
+ unsigned int length; /* Size of the hash table */
+ unsigned int m; /* Log base 2 of length */
+ unsigned int count; /* nb entries in the hash table */
+ mutex_t table_lock; /* currently not used */
+ int alloc_data; /* true if data is allocated and copied in the hast table */
+ int clean; /* to force cleanup of the hash table */
+ int size; /* Max size of the hast table, defaulted 5000 */
+} HASH_TABLE;
+
+void hdestroy_s(HASH_TABLE **hash_table);
+HASH_ENTRY *hsearch_s(HASH_TABLE *hash_table, HASH_ENTRY item, ACTION action);
+HASH_ENTRY *hlist_s(HASH_TABLE *hash_table, int * i, NODE ** a);
+HASH_TABLE *hcreate_s(size_t size, int alloc_data);
+
+/* convenience functions for adding and find things */
+int hadd_s(HASH_TABLE **hash_table, char *key, void *data, int size);
+int hreplace_s(HASH_TABLE **hash_table, char *key, void *data, int size);
+char *hfind_s(HASH_TABLE *hash_table, char *key);
+int hdelete_s( HASH_TABLE *hash_table, char * key);
diff --git a/usr/src/lib/libldap4/include/lber.h b/usr/src/lib/libldap4/include/lber.h
new file mode 100644
index 0000000000..094c04ab8b
--- /dev/null
+++ b/usr/src/lib/libldap4/include/lber.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#ifndef _LBER_H
+#define _LBER_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(NEEDPROTOS) && defined(__STDC__)
+#define NEEDPROTOS 1
+#endif
+
+/* 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
+
+/* BER encoding type and mask */
+#define LBER_PRIMITIVE 0x00
+#define LBER_CONSTRUCTED 0x20
+#define LBER_ENCODING_MASK 0x20
+
+#define LBER_BIG_TAG_MASK 0x1f
+#define LBER_MORE_TAG_MASK 0x80
+
+/*
+ * 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 0xffffffff
+#define LBER_DEFAULT 0xffffffff
+
+/* general BER types we know about */
+#define LBER_BOOLEAN 0x01
+#define LBER_INTEGER 0x02
+#define LBER_BITSTRING 0x03
+#define LBER_OCTETSTRING 0x04
+#define LBER_NULL 0x05
+#define LBER_ENUMERATED 0x0a
+#define LBER_SEQUENCE 0x30 /* constructed */
+#define LBER_SET 0x31 /* constructed */
+
+#define OLD_LBER_SEQUENCE 0x10 /* w/o constructed bit - broken */
+#define OLD_LBER_SET 0x11 /* w/o constructed bit - broken */
+
+#ifdef NEEDPROTOS
+typedef int (*BERTranslateProc)(char **bufp, unsigned int *buflenp,
+ int free_input);
+#else /* NEEDPROTOS */
+typedef int (*BERTranslateProc)();
+#endif /* NEEDPROTOS */
+
+typedef struct berelement BerElement; /* Opaque BerElement structure */
+#define NULLBER ((BerElement *) 0)
+
+#ifdef LDAP_SSL
+#include <security/ssl.h>
+#endif /* LDAP_SSL */
+
+/*
+ * Structure Sockbuf which used to be defined in this header file, is
+ * removed since the c-api draft does not define the structure and it
+ * is only used internal to the library
+ */
+
+typedef struct seqorset {
+ BerElement *sos_ber;
+ unsigned int sos_clen;
+ unsigned int sos_tag;
+ char *sos_first;
+ char *sos_ptr;
+ struct seqorset *sos_next;
+} Seqorset;
+#define NULLSEQORSET ((Seqorset *) 0)
+
+typedef unsigned int ber_len_t; /* for BER len */
+typedef unsigned int ber_tag_t; /* for BER tags */
+typedef int ber_int_t; /* for BER ints, enums, and Booleans */
+typedef unsigned int ber_uint_t; /* unsigned equivalent of ber_int_t */
+typedef int ber_slen_t; /* signed equivalent of ber_len_t */
+
+/* structure for returning a sequence of octet strings + length */
+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 BerElement *ber_init();
+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_zero_init();
+#else /* NEEDPROTOS */
+
+/*
+ * in bprint.c:
+ */
+void lber_bprint(char *data, int len);
+
+/*
+ * in decode.c:
+ */
+ber_tag_t ber_get_tag(BerElement *ber);
+ber_tag_t ber_skip_tag(BerElement *ber, ber_len_t *len);
+ber_tag_t ber_peek_tag(BerElement *ber, ber_len_t *len);
+unsigned int ber_get_int(BerElement *ber, int *num);
+unsigned int ber_get_stringb(BerElement *ber, char *buf,
+ ber_len_t *len);
+unsigned int ber_get_stringa(BerElement *ber, char **buf);
+unsigned int ber_get_stringal(BerElement *ber, struct berval **bv);
+unsigned int ber_get_bitstringa(BerElement *ber, char **buf,
+ ber_len_t *len);
+unsigned int ber_get_null(BerElement *ber);
+unsigned int ber_get_boolean(BerElement *ber, int *boolval);
+ber_tag_t ber_first_element(BerElement *ber, ber_len_t *len,
+ char **last);
+ber_tag_t ber_next_element(BerElement *ber, ber_len_t *len,
+ char *last);
+#if defined(MACOS) || defined(BC31) || defined(_WIN32) || defined(__sun)
+ber_tag_t ber_scanf(BerElement *ber, char *fmt, ...);
+#else
+ber_tag_t ber_scanf();
+#endif
+void ber_bvfree(struct berval *bv);
+void ber_bvecfree(struct berval **bv);
+struct berval *ber_bvdup(struct berval *bv);
+#ifdef STR_TRANSLATION
+void ber_set_string_translators(BerElement *ber,
+ BERTranslateProc encode_proc, BERTranslateProc decode_proc);
+#endif /* STR_TRANSLATION */
+int ber_flatten(BerElement *ber, struct berval **bvPtr);
+
+/*
+ * in encode.c
+ */
+int ber_put_enum(BerElement *ber, int num, ber_tag_t tag);
+int ber_put_int(BerElement *ber, int num, ber_tag_t tag);
+int ber_put_ostring(BerElement *ber, char *str, ber_len_t len, ber_tag_t tag);
+int ber_put_string(BerElement *ber, char *str, ber_tag_t tag);
+int ber_put_bitstring(BerElement *ber, char *str,
+ unsigned int bitlen, ber_tag_t tag);
+int ber_put_null(BerElement *ber, ber_tag_t tag);
+int ber_put_boolean(BerElement *ber, int boolval, ber_tag_t tag);
+int ber_start_seq(BerElement *ber, ber_tag_t tag);
+int ber_start_set(BerElement *ber, ber_tag_t tag);
+int ber_put_seq(BerElement *ber);
+int ber_put_set(BerElement *ber);
+#if defined(MACOS) || defined(BC31) || defined(_WIN32) || defined(__sun)
+int ber_printf(BerElement *ber, char *fmt, ...);
+#else
+int ber_printf();
+#endif
+
+/*
+ * in io.c:
+ *
+ * ber_flush() and ber_get_next() functions are obsolete and removed
+ * from this library/header file
+ */
+int ber_read(BerElement *ber, char *buf, ber_len_t len);
+int ber_write(BerElement *ber, char *buf, ber_len_t len, int nosos);
+void ber_free(BerElement *ber, int freebuf);
+BerElement *ber_alloc(void);
+BerElement *der_alloc(void);
+BerElement *ber_alloc_t(int options);
+BerElement *ber_dup(BerElement *ber);
+BerElement *ber_init(struct berval *bv);
+void ber_dump(BerElement *ber, int inout);
+void ber_sos_dump(Seqorset *sos);
+void ber_zero_init(BerElement *ber, int options);
+void ber_reset(BerElement *ber, int was_writing);
+
+#ifdef NEEDGETOPT
+/*
+ * in getopt.c
+ */
+int getopt(int nargc, char **nargv, char *ostr);
+#endif /* NEEDGETOPT */
+#endif /* NEEDPROTOS */
+
+#define LBER_HTONL(l) htonl(l)
+#define LBER_NTOHL(l) ntohl(l)
+
+/*
+ * SAFEMEMCPY is an overlap-safe copy from s to d of n bytes
+ */
+#ifdef sunos4
+#define SAFEMEMCPY(d, s, n) bcopy(s, d, n)
+#else /* sunos4 */
+#define SAFEMEMCPY(d, s, n) memmove(d, s, n)
+#endif /* sunos4 */
+
+#ifdef SUN
+
+/* I18N support */
+#include <locale.h>
+#include <nl_types.h>
+
+extern nl_catd slapdcat; /* for I18N support */
+extern void i18n_catopen(char *);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LBER_H */
diff --git a/usr/src/lib/libldap4/include/ldap-int.h b/usr/src/lib/libldap4/include/ldap-int.h
new file mode 100644
index 0000000000..12454463cb
--- /dev/null
+++ b/usr/src/lib/libldap4/include/ldap-int.h
@@ -0,0 +1,343 @@
+/*
+ * Copyright 1995-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * ldap-int.h - defines & prototypes internal to the LDAP library
+ */
+
+#include <stdlib.h> /* rri */
+#include <pthread.h> /* rri */
+#include <netinet/in.h>
+
+#define LDAP_URL_PREFIX "ldap://"
+#define LDAP_URL_PREFIX_LEN 7
+#define LDAP_URL_URLCOLON "URL:"
+#define LDAP_URL_URLCOLON_LEN 4
+
+#ifdef LDAP_REFERRALS
+#define LDAP_REF_STR "Referral:\n"
+#define LDAP_REF_STR_LEN 10
+#define LDAP_LDAP_REF_STR LDAP_URL_PREFIX
+#define LDAP_LDAP_REF_STR_LEN LDAP_URL_PREFIX_LEN
+#ifdef LDAP_DNS
+#define LDAP_DX_REF_STR "dx://"
+#define LDAP_DX_REF_STR_LEN 5
+#endif /* LDAP_DNS */
+#endif /* LDAP_REFERRALS */
+
+
+/*
+ * in cache.c
+ */
+#ifdef NEEDPROTOS
+void add_request_to_cache( LDAP *ld, unsigned int msgtype,
+ BerElement *request );
+void add_result_to_cache( LDAP *ld, LDAPMessage *result );
+int check_cache( LDAP *ld, unsigned int msgtype, BerElement *request );
+#else /* NEEDPROTOS */
+void add_request_to_cache();
+void add_result_to_cache();
+int check_cache();
+#endif /* NEEDPROTOS */
+
+
+#ifdef KERBEROS
+/*
+ * in kerberos.c
+ */
+#ifdef NEEDPROTOS
+char *get_kerberosv4_credentials( LDAP *ld, char *who, char *service,
+ int *len );
+#else /* NEEDPROTOS */
+char *get_kerberosv4_credentials();
+#endif /* NEEDPROTOS */
+
+#endif /* KERBEROS */
+
+/*
+ * in notif.c
+ */
+int ldap_insert_notif(LDAP *ld, LDAPMessage *notif);
+int ldap_add_notif(LDAP *ld, LDAPMessage *notif);
+
+
+/*
+ * in open.c
+ */
+int ldap_thr_index(); /* rri */
+#ifdef NEEDPROTOS
+int open_default_ldap_connection(LDAP *ld);
+int open_ldap_connection( LDAP *ld, Sockbuf *sb, char *host, int defport,
+ char **krbinstancep, int async );
+#else /* NEEDPROTOS */
+int open_default_ldap_connection();
+int open_ldap_connection();
+#endif /* NEEDPROTOS */
+
+/*
+ * in options.c
+ */
+
+int ldap_get_option (LDAP *ld, int option, void *outvalue);
+
+/*
+ * in os-ip.c
+ */
+void close_ldap_connection( Sockbuf *sb ); /* rri */
+#ifdef NEEDPROTOS
+int connect_to_host(Sockbuf *sb, char *host, in_addr_t address, int port,
+ int async, int bindTimeout);
+void close_connection( Sockbuf *sb );
+#else /* NEEDPROTOS */
+int connect_to_host();
+void close_connection();
+#endif /* NEEDPROTOS */
+
+#ifdef KERBEROS
+#ifdef NEEDPROTOS
+char *host_connected_to( Sockbuf *sb );
+#else /* NEEDPROTOS */
+char *host_connected_to();
+#endif /* NEEDPROTOS */
+#endif /* KERBEROS */
+
+#ifdef LDAP_REFERRALS
+#ifdef NEEDPROTOS
+int do_ldap_select( LDAP *ld, struct timeval *timeout );
+void *new_select_info( void );
+void free_select_info( void *sip );
+void mark_select_write( LDAP *ld, Sockbuf *sb );
+void mark_select_read( LDAP *ld, Sockbuf *sb );
+void mark_select_clear( LDAP *ld, Sockbuf *sb );
+long is_read_ready( LDAP *ld, Sockbuf *sb );
+long is_write_ready( LDAP *ld, Sockbuf *sb );
+#else /* NEEDPROTOS */
+int do_ldap_select();
+void *new_select_info();
+void free_select_info();
+void mark_select_write();
+void mark_select_read();
+void mark_select_clear();
+long is_read_ready();
+long is_write_ready();
+#endif /* NEEDPROTOS */
+#endif /* LDAP_REFERRALS */
+
+/*
+ * in regex.c (rri)
+ */
+int re_exec( char *lp );
+
+/*
+ * in request.c
+ */
+#ifdef NEEDPROTOS
+int send_initial_request( LDAP *ld, unsigned int msgtype,
+ char *dn, BerElement *ber );
+BerElement *alloc_ber_with_options( LDAP *ld );
+void set_ber_options( LDAP *ld, BerElement *ber );
+#else /* NEEDPROTOS */
+int send_initial_request();
+BerElement *alloc_ber_with_options();
+void set_ber_options();
+#endif /* NEEDPROTOS */
+
+#if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
+#ifdef NEEDPROTOS
+int send_server_request( LDAP *ld, BerElement *ber, int msgid,
+ LDAPRequest *parentreq, LDAPServer *srvlist, LDAPConn *lc,
+ int bind );
+LDAPConn *new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
+ int connect, int bind );
+LDAPRequest *find_request_by_msgid( LDAP *ld, int msgid );
+void free_request( LDAP *ld, LDAPRequest *lr );
+void free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind );
+void dump_connection( LDAP *ld, LDAPConn *lconns, int all );
+void dump_requests_and_responses( LDAP *ld );
+#else /* NEEDPROTOS */
+int send_server_request();
+LDAPConn *new_connection();
+LDAPRequest *find_request_by_msgid();
+void free_request();
+void free_connection();
+void dump_connection();
+void dump_requests_and_responses();
+#endif /* NEEDPROTOS */
+#endif /* LDAP_REFERRALS || LDAP_DNS */
+
+#ifdef LDAP_REFERRALS
+#ifdef NEEDPROTOS
+int chase_referrals( LDAP *ld, LDAPRequest *lr, char **refs, int *count, int samerequest );
+char ** ldap_errormsg2referrals(char *errmsg);
+char *ldap_referral2error_msg(char ** refs);
+int append_referral( LDAP *ld, char **referralsp, char *s );
+#else /* NEEDPROTOS */
+int chase_referrals();
+char ** ldap_errormsg2referrals();
+char *ldap_referral2error_msg();
+int append_referral();
+#endif /* NEEDPROTOS */
+#endif /* LDAP_REFERRALS */
+
+void nsldapi_connection_lost_nolock( LDAP *ld, Sockbuf *sb );
+
+/*
+ * in search.c
+ */
+#ifdef NEEDPROTOS
+BerElement *ldap_build_search_req( LDAP *ld, char *base, int scope,
+ char *filter, char **attrs, int attrsonly, LDAPControl ** serverctrls,
+ struct timeval *timeoutp, int sizelimit );
+#else /* NEEDPROTOS */
+BerElement *ldap_build_search_req();
+#endif /* NEEDPROTOS */
+
+static int put_extensible_filter( BerElement *ber, char *type, char *val );
+
+/*
+ * in unbind.c
+ */
+#ifdef NEEDPROTOS
+int ldap_ld_free( LDAP *ld, int close );
+int send_unbind( LDAP *ld, Sockbuf *sb );
+#else /* NEEDPROTOS */
+int ldap_ld_free();
+int send_unbind();
+#endif /* NEEDPROTOS */
+
+
+#ifdef LDAP_DNS
+/*
+ * in getdxbyname.c
+ */
+#ifdef NEEDPROTOS
+char **getdxbyname( char *domain );
+#else /* NEEDPROTOS */
+char **getdxbyname();
+#endif /* NEEDPROTOS */
+#endif /* LDAP_DNS */
+
+/*
+ * abandon.c
+ */
+#ifdef NEEDPROTOS
+BerElement * ldap_build_abandon_req( LDAP *ld, int msgid, LDAPControl ** serverctrls);
+#else
+BerElement * ldap_build_abandon_req();
+#endif
+
+/* add.c */
+#ifdef NEEDPROTOS
+BerElement * ldap_build_add_req(LDAP *ld, char *dn, LDAPMod **attrs, LDAPControl ** serverctrls);
+#else
+BerElement * ldap_build_add_req();
+#endif
+
+/*
+ * compare.c
+ */
+#ifdef NEEDPROTOS
+BerElement * ldap_build_compare_req(LDAP *ld, char *dn, char *attr, struct berval *bvalue, LDAPControl **serverctrls);
+#else
+BerElement * ldap_build_compare_req();
+#endif
+
+/*
+ * delete.c
+ */
+#ifdef NEEDPROTOS
+BerElement * ldap_build_delete_req(LDAP *ld, char *dn, LDAPControl **serverctrls);
+#else
+BerElement * ldap_build_delete_req();
+#endif
+
+/*
+ * extop.c
+ */
+#ifdef NEEDPROTOS
+BerElement * ldap_build_extended_operation_req(LDAP *ld, char *exoid, struct berval *exdata, LDAPControl ** serverctrls);
+#else
+BerElement * ldap_build_extended_operation_req();
+#endif
+
+/*
+ * modify.c
+ */
+#ifdef NEEDPROTOS
+BerElement * ldap_build_modify_req(LDAP *ld, char *dn, LDAPMod ** mods, LDAPControl **serverctrls);
+#else
+BerElement * ldap_build_modify_req();
+#endif
+
+/*
+ * rename.c
+ */
+#ifdef NEEDPROTOS
+BerElement * ldap_build_rename_req ( LDAP *ld, char *dn, char *newrdn, char *newparent, int deleteoldrdn, LDAPControl **serverctrls);
+#else
+BerElement * ldap_build_rename_req ();
+#endif
+
+/*
+ * saslbind.c
+ */
+#ifdef NEEDPROTOS
+BerElement * ldap_build_sasl_bind_req( LDAP *ld, char *dn, char *mechanism, struct berval *creds, LDAPControl ** serverctrls);
+#else
+BerElement * ldap_build_sasl_bind_req();
+#endif
+/*
+ * sbind.c
+ */
+#ifdef NEEDPROTOS
+BerElement * ldap_build_simple_bind_req(LDAP *ld, char *dn, char *passwd, LDAPControl **serverctrls);
+#else
+BerElement * ldap_build_simple_bind_req();
+#endif
+
+/*
+ * utils.c
+ */
+
+#ifdef NEEDPROTOS
+void free_strarray(char **sap);
+#else
+void free_strarray();
+#endif
+
+/*
+ * Controls.c
+ */
+#ifdef NEEDPROTOS
+LDAPControl * ldap_control_dup(LDAPControl *ctrl);
+LDAPControl ** ldap_controls_dup(LDAPControl ** ctrls);
+int ldap_controls_code (BerElement *ber, LDAPControl **ctrls);
+LDAPControl ** ldap_controls_decode(BerElement *ber, int *errcode);
+int ldap_build_control(char *oid, BerElement *ber, int freeber,
+ char iscritical, LDAPControl **ctrlp);
+#else
+LDAPControl * ldap_control_dup();
+LDAPControl ** ldap_controls_dup();
+int ldap_controls_code ();
+LDAPControl ** ldap_controls_decode();
+int ldap_build_control();
+#endif
+
+/*
+ * ber/io.c
+ */
+#ifdef NEEDPROTOS
+int ber_flush(Sockbuf *sb, BerElement *ber, int freeit);
+unsigned int ber_get_next(Sockbuf *sb, unsigned int *len, BerElement *ber);
+#else
+int ber_flush();
+unsigned int ber_get_next();
+#endif
+
diff --git a/usr/src/lib/libldap4/include/ldap-private.h b/usr/src/lib/libldap4/include/ldap-private.h
new file mode 100644
index 0000000000..19807f234c
--- /dev/null
+++ b/usr/src/lib/libldap4/include/ldap-private.h
@@ -0,0 +1,360 @@
+/*
+ * Copyright 1995-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _LDAP_PRIVATE_H
+#define _LDAP_PRIVATE_H
+
+#include <signal.h>
+#include <pthread.h> /* rri */
+
+#define pthread_self _thr_self
+#define thr_self _thr_self
+#define pthread_kill _thr_kill
+#define thr_kill _thr_kill
+
+#ifdef _REENTRANT
+#ifndef MAX_THREAD_ID
+#define MAX_THREAD_ID 500
+#endif /* MAX_THREAD_ID */
+#else /* _REENTRANT */
+#ifndef MAX_THREAD_ID
+#define MAX_THREAD_ID 1
+#endif /* MAX_THREAD_ID */
+#endif /* _REENTRANT */
+
+#define COMPAT20
+#define COMPAT30
+#if defined(COMPAT20) || defined(COMPAT30)
+#define COMPAT
+#endif
+
+#ifdef LDAP_DNS
+#define LDAP_OPT_DNS 0x00000001 /* use DN & DNS */
+#endif /* LDAP_DNS */
+
+/*
+#define DBG_LOCK1(st) printf("%d> %s %d:%s\n", _thr_self(), st, __LINE__, __FILE__);
+#define DBG_LOCK2(ld,st) printf("%d> %s ld_lockcount=%d %d:%s\n", _thr_self(), st, (ld)->ld_lockcount, __LINE__, __FILE__);
+*/
+#define DBG_LOCK1(st)
+#define DBG_LOCK2(ld,st)
+
+extern pthread_t _thr_self();
+#define LOCK_RESPONSE(ld) \
+ if ((ld)->ld_response_lockthread != _thr_self()) { \
+ DBG_LOCK1("waiting for response lock") \
+ pthread_mutex_lock( &((ld)->ld_response_mutex) ); \
+ DBG_LOCK1("got response lock") \
+ (ld)->ld_response_lockthread = _thr_self(); \
+ } else { \
+ (ld)->ld_response_lockcount++; \
+ DBG_LOCK2(ld, "fake ldap lock") \
+ }
+
+#define UNLOCK_RESPONSE(ld) \
+ if ((ld)->ld_response_lockcount==0) { \
+ (ld)->ld_response_lockthread = 0; \
+ pthread_mutex_unlock( &((ld)->ld_response_mutex) ); \
+ DBG_LOCK1("freed response lock") \
+ } else { \
+ (ld)->ld_response_lockcount--; \
+ DBG_LOCK2(ld, "fake ldap unlock") \
+ }
+
+#define LOCK_LDAP(ld) \
+ if ((ld)->ld_lockthread != _thr_self()) { \
+ DBG_LOCK1("waiting for ldap lock") \
+ pthread_mutex_lock( &((ld)->ld_ldap_mutex) ); \
+ DBG_LOCK1("got ldap lock") \
+ (ld)->ld_lockthread = _thr_self(); \
+ } else { \
+ (ld)->ld_lockcount++; \
+ DBG_LOCK2(ld, "fake ldap lock") \
+ }
+
+#define UNLOCK_LDAP(ld) \
+ if ((ld)->ld_lockcount==0) { \
+ (ld)->ld_lockthread = 0; \
+ pthread_mutex_unlock( &((ld)->ld_ldap_mutex) ); \
+ DBG_LOCK1("freed ldap lock") \
+ } else { \
+ (ld)->ld_lockcount--; \
+ DBG_LOCK2(ld, "fake ldap unlock") \
+ }
+
+#define LOCK_POLL(ld) pthread_mutex_lock( &ld->ld_poll_mutex )
+#define UNLOCK_POLL(ld) pthread_mutex_unlock( &ld->ld_poll_mutex )
+
+
+/*
+ * structure representing a Ber Element
+ */
+typedef struct berelement {
+ char *ber_buf;
+ char *ber_ptr;
+ char *ber_end;
+ struct seqorset *ber_sos;
+ unsigned int ber_tag;
+ unsigned int ber_len;
+ int ber_usertag;
+ char ber_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;
+} _struct_BerElement;
+
+
+/*
+ * This structure represents both ldap messages and ldap responses.
+ * These are really the same, except in the case of search responses,
+ * where a response has multiple messages.
+ */
+typedef struct ldapmsg {
+ int lm_msgid; /* the message id */
+ int lm_msgtype; /* the message type */
+ BerElement *lm_ber; /* the ber encoded message contents */
+ struct ldapmsg *lm_chain; /* for search - next msg in the resp */
+ struct ldapmsg *lm_next; /* next response */
+ unsigned long lm_time; /* used to maintain cache */
+} _struct_LDAPMessage;
+
+typedef struct ldap_filt_list {
+ char *lfl_tag;
+ char *lfl_pattern;
+ char *lfl_delims;
+ LDAPFiltInfo *lfl_ilist;
+ struct ldap_filt_list *lfl_next;
+} _struct_FiltList;
+
+typedef struct ldap_filt_desc {
+ LDAPFiltList *lfd_filtlist;
+ LDAPFiltInfo *lfd_curfip;
+ LDAPFiltInfo lfd_retfi;
+ char lfd_filter[ LDAP_FILT_MAXSIZ ];
+ char *lfd_curval;
+ char *lfd_curvalcopy;
+ char **lfd_curvalwords;
+ char *lfd_filtprefix;
+ char *lfd_filtsuffix;
+} _struct_FiltDesc;
+
+/*
+ * structure for tracking LDAP server host, ports, DNs, etc.
+ */
+typedef struct ldap_server {
+ char *lsrv_host;
+ char *lsrv_dn; /* if NULL, use default */
+ int lsrv_port;
+ struct ldap_server *lsrv_next;
+} LDAPServer;
+
+
+/*
+ * structure representing a Socket buffer
+ */
+typedef struct sockbuf {
+#ifndef MACOS
+ int sb_sd;
+#else /* MACOS */
+ void *sb_sd;
+#endif /* MACOS */
+ BerElement sb_ber;
+
+ int sb_naddr; /* > 0 implies using CLDAP (UDP) */
+ void *sb_useaddr; /* pointer to sockaddr to use next */
+ void *sb_fromaddr; /* pointer to message source sockaddr */
+ void **sb_addrs; /* actually an array of pointers to */
+ /* sockaddrs */
+
+ int sb_options; /* to support copying ber elements */
+#define LBER_TO_FILE 0x01 /* to a file referenced by sb_fd */
+#define LBER_TO_FILE_ONLY 0x02 /* only write to file, not network */
+#define LBER_MAX_INCOMING_SIZE 0x04 /* impose limit on incoming stuff */
+#define LBER_NO_READ_AHEAD 0x08 /* read only as much as requested */
+ int sb_fd;
+ int sb_max_incoming;
+#ifdef LDAP_SSL
+ int sb_ssl_tls;
+ SSL *sb_ssl; /* to support ldap over ssl */
+#endif /* LDAP_SSL */
+} Sockbuf;
+#define READBUFSIZ 8192
+
+
+/*
+ * structure for representing an LDAP server connection
+ */
+typedef struct ldap_conn {
+ Sockbuf *lconn_sb;
+ int lconn_refcnt;
+ unsigned long lconn_lastused; /* time */
+ int lconn_status;
+#define LDAP_CONNST_NEEDSOCKET 1
+#define LDAP_CONNST_CONNECTING 2
+#define LDAP_CONNST_CONNECTED 3
+#define LDAP_CONNST_DEAD 4
+ LDAPServer *lconn_server;
+ char *lconn_krbinstance;
+ struct ldap_conn *lconn_next;
+} LDAPConn;
+
+/*
+ * Structure used to keep track of search references
+ */
+typedef struct ldap_reference {
+ char ** lref_refs;
+ struct ldap_reference *lref_next;
+} LDAPRef;
+
+
+
+/*
+ * structure used to track outstanding requests
+ */
+typedef struct ldapreq {
+ int lr_msgid; /* the message id */
+ int lr_status; /* status of request */
+#define LDAP_REQST_INPROGRESS 1
+#define LDAP_REQST_CHASINGREFS 2
+#define LDAP_REQST_NOTCONNECTED 3
+#define LDAP_REQST_WRITING 4
+#define LDAP_REQST_CONNDEAD 5
+ int lr_outrefcnt; /* count of outstanding referrals */
+ int lr_origid; /* original request's message id */
+ int lr_parentcnt; /* count of parent requests */
+ int lr_res_msgtype; /* result message type */
+ int lr_res_errno; /* result LDAP errno */
+ char *lr_res_error; /* result error string */
+ char *lr_res_matched;/* result matched DN string */
+ BerElement *lr_ber; /* ber encoded request contents */
+ LDAPConn *lr_conn; /* connection used to send request */
+ LDAPRef *lr_references;
+ char **lr_ref_followed; /* referral being followed */
+ char **lr_ref_unfollowed; /* Not being followed */
+ char **lr_ref_tofollow; /* referral to follow if the one being
+ followed fails. */
+ struct ldapreq *lr_parent; /* request that spawned this referral */
+ struct ldapreq *lr_refnext; /* next referral spawned */
+ struct ldapreq *lr_prev; /* previous request */
+ struct ldapreq *lr_next; /* next request */
+} LDAPRequest;
+
+/*
+ * structure for client cache
+ */
+#define LDAP_CACHE_BUCKETS 31 /* cache hash table size */
+typedef struct ldapcache {
+ LDAPMessage *lc_buckets[LDAP_CACHE_BUCKETS];/* hash table */
+ LDAPMessage *lc_requests; /* unfulfilled reqs */
+ time_t lc_timeout; /* request timeout */
+ ssize_t lc_maxmem; /* memory to use */
+ ssize_t lc_memused; /* memory in use */
+ int lc_enabled; /* enabled? */
+ unsigned int lc_options; /* options */
+#define LDAP_CACHE_OPT_CACHENOERRS 0x00000001
+#define LDAP_CACHE_OPT_CACHEALLERRS 0x00000002
+} LDAPCache;
+#define NULLLDCACHE ((LDAPCache *)NULL)
+
+/*
+ * structure representing an ldap connection
+ */
+typedef struct ldap {
+ Sockbuf ld_sb; /* socket descriptor & buffer */
+ char *ld_host;
+ int ld_version;
+ char ld_lberoptions;
+ int ld_deref;
+
+ int ld_timelimit;
+ int ld_sizelimit;
+
+ LDAPFiltDesc *ld_filtd; /* from getfilter for ufn searches */
+ char *ld_ufnprefix; /* for incomplete ufn's */
+
+ int ld_errno[MAX_THREAD_ID]; /* thread-specific */
+#define ld_errno ld_errno[ldap_thr_index()]
+ char *ld_error[MAX_THREAD_ID]; /* thread-specific */
+#define ld_error ld_error[ldap_thr_index()]
+ char *ld_matched[MAX_THREAD_ID]; /* thread-specific */
+#define ld_matched ld_matched[ldap_thr_index()]
+ char **ld_referrals[MAX_THREAD_ID]; /* thread-specific */
+#define ld_referrals ld_referrals[ldap_thr_index()]
+ LDAPControl **ld_ret_ctrls[MAX_THREAD_ID]; /* thread-specific */
+#define ld_ret_ctrls ld_ret_ctrls[ldap_thr_index()]
+ int ld_msgid;
+
+ int ld_follow_referral; /* flag set to true if lib follow referrals */
+ LDAPRequest *ld_requests; /* list of outstanding requests -- referrals*/
+
+ LDAPMessage *ld_responses; /* list of outstanding responses */
+ int *ld_abandoned; /* array of abandoned requests */
+
+ pthread_mutex_t ld_response_mutex; /* mutex for responses part of structure */
+ pthread_t ld_response_lockthread; /* thread which currently holds the response lock */
+ int ld_response_lockcount; /* response lock depth */
+
+ char *ld_attrbuffer[MAX_THREAD_ID];
+#define ld_attrbuffer ld_attrbuffer[ldap_thr_index()]
+ LDAPCache *ld_cache; /* non-null if cache is initialized */
+ char *ld_cldapdn; /* DN used in connectionless search */
+
+ /* it is OK to change these next four values directly */
+ int ld_cldaptries; /* connectionless search retry count */
+ int ld_cldaptimeout;/* time between retries */
+ int ld_refhoplimit; /* limit on referral nesting */
+/* LP TO CHANGE */
+ char ld_restart;
+#ifdef LDAP_SSL
+ int ld_use_ssl;
+ char *ld_ssl_key;
+#endif
+ unsigned int ld_options; /* boolean options */
+
+ /* do not mess with the rest though */
+ char *ld_defhost; /* full name of default server */
+ int ld_defport; /* port of default server */
+ BERTranslateProc ld_lber_encode_translate_proc;
+ BERTranslateProc ld_lber_decode_translate_proc;
+
+ LDAPConn *ld_defconn; /* default connection */
+ LDAPConn *ld_conns; /* list of server connections */
+ void *ld_selectinfo; /* platform specifics for select */
+
+ LDAP_REBIND_FUNCTION *ld_rebindproc;
+ void *ld_rebind_extra_arg;
+/* int (*ld_rebindproc)( struct ldap *ld, char **dnp, */
+/* char **passwdp, int *authmethodp, int freeit ); */
+ /* routine to get info needed for re-bind */
+
+ pthread_mutex_t ld_ldap_mutex; /* mutex for thread dependent part of struct */
+ pthread_t ld_lockthread; /* thread which currently holds the lock */
+ int ld_lockcount; /* lock depth */
+ pthread_mutex_t ld_poll_mutex; /* a seperate lock for polling */
+
+ LDAPControl **ld_srvctrls; /* Controls used by ldap and server */
+ LDAPControl **ld_cltctrls; /* Client side controls */
+
+/* KE: Lists of unsolicited notifications */
+ LDAPMessage *ld_notifs[MAX_THREAD_ID];
+
+ /* How long to wait for while connecting to a server */
+ int ld_connect_timeout;
+#define ld_notifs ld_notifs[ldap_thr_index()]
+} _struct_LDAP;
+
+
+/*
+ * handy macro to check whether LDAP struct is set up for CLDAP or not
+ */
+#define LDAP_IS_CLDAP( ld ) ( ld->ld_sb.sb_naddr > 0 )
+
+
+#endif /* _LDAP_PRIVATE_H */
diff --git a/usr/src/lib/libldap4/include/ldap.h b/usr/src/lib/libldap4/include/ldap.h
new file mode 100644
index 0000000000..a5a0a61534
--- /dev/null
+++ b/usr/src/lib/libldap4/include/ldap.h
@@ -0,0 +1,1375 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#ifndef _LDAP_H
+#define _LDAP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LDAP_SSL
+#include <security/ssl.h>
+#endif /* LDAP_SSL */
+
+
+#include <pthread.h>
+
+#ifdef LDAP_SSL
+#define SSL_LDAP_PORT 636
+#endif
+
+#if !defined(NEEDPROTOS) && defined(__STDC__)
+#define NEEDPROTOS 1
+#endif
+
+#define LDAP_API_VERSION 2004
+#define LDAP_VERSION_MIN 2
+#define LDAP_VERSION_MAX 3
+#define LDAP_VENDOR_NAME "Sun Microsystems Inc."
+#define LDAP_VENDOR_VERSION 400
+
+#define LDAP_PORT 389
+#define LDAP_VERSION1 1
+#define LDAP_VERSION2 2
+#define LDAP_VERSION3 3
+#define LDAP_VERSION LDAP_VERSION2
+
+/* OPTIONS to use with ldap_set_option and ldap_get_option */
+#define LDAP_OPT_API_INFO 0x00
+#define LDAP_OPT_DESC 0x01 /* Use of this option is depricated */
+/* int, control how aliases are handled during search */
+#define LDAP_OPT_DEREF 0x02
+/* Deref values */
+#define LDAP_DEREF_NEVER 0x00
+#define LDAP_DEREF_SEARCHING 0x01
+#define LDAP_DEREF_FINDING 0x02
+#define LDAP_DEREF_ALWAYS 0x03
+
+#define LDAP_OPT_SIZELIMIT 0x03 /* int, size limit of a search */
+#define LDAP_OPT_TIMELIMIT 0x04 /* int, time limit of a search */
+#define LDAP_OPT_REBIND_FN 0x06 /* Use of this options is depricated */
+#define LDAP_OPT_REBIND_ARG 0x07 /* Use of this options is depricated */
+#define LDAP_OPT_REFERRALS 0x08 /* ON/OFF, chase referrals */
+#define LDAP_OPT_RESTART 0x09 /* ON/OFF, restart if EINTR occurs */
+/* int, protocol version, default 2 */
+#define LDAP_OPT_PROTOCOL_VERSION 0x11
+/* List of ldap controls to be sent with each request */
+#define LDAP_OPT_SERVER_CONTROLS 0x12
+/* List of ldap controls that affect the session */
+#define LDAP_OPT_CLIENT_CONTROLS 0x13
+#define LDAP_OPT_API_FEATURE_INFO 0x15
+/* The hostname of the default ldap server */
+#define LDAP_OPT_HOST_NAME 0x30
+/* The code of the most recent ldap error that occured for this session */
+#define LDAP_OPT_ERROR_NUMBER 0x31
+/* The message returned with the most recent ldap error */
+#define LDAP_OPT_ERROR_STRING 0x32
+/* The Matching DN in case of a naming error */
+#define LDAP_OPT_MATCHED_DN 0x33
+#define LDAP_OPT_ERROR_MATCHED 0x33 /* Use of this options is depricated */
+
+/* The timeout while trying to connect to a server */
+#define LDAP_X_OPT_CONNECT_TIMEOUT 0x4F01
+#define LDAP_X_IO_TIMEOUT_NO_WAIT 0
+#define LDAP_X_IO_TIMEOUT_NO_TIMEOUT -1
+
+/* The Filter List Desc used by UFN functions */
+/* #define LDAP_OPT_FILTERDESC 0x80 */
+/* For on/off options */
+#define LDAP_OPT_ON ((void *)1)
+#define LDAP_OPT_OFF ((void *)0)
+
+/* Used for NO limitation is TIMELIMIT or SIZELIMIT */
+#define LDAP_NO_LIMIT 0
+
+#define LDAP_MAX_ATTR_LEN 100
+#define LDAP_RETURN_NO_ATTR "1.1"
+#define LDAP_RETURN_ALL_ATTR ""
+#define LDAP_RETURN_ALL_ATTR_OPS "*"
+
+/* Begin LDAP Display Template Definitions */
+#define LDAP_TEMPLATE_VERSION 1
+
+/*
+ * general types of items (confined to most significant byte)
+ */
+#define LDAP_SYN_TYPE_TEXT 0x01000000
+#define LDAP_SYN_TYPE_IMAGE 0x02000000
+#define LDAP_SYN_TYPE_BOOLEAN 0x04000000
+#define LDAP_SYN_TYPE_BUTTON 0x08000000
+#define LDAP_SYN_TYPE_ACTION 0x10000000
+
+/*
+ * syntax options (confined to second most significant byte)
+ */
+#define LDAP_SYN_OPT_DEFER 0x00010000
+
+
+/*
+ * display template item syntax ids (defined by common agreement)
+ * these are the valid values for the ti_syntaxid of the tmplitem
+ * struct (defined below). A general type is encoded in the
+ * most-significant 8 bits, and some options are encoded in the next
+ * 8 bits. The lower 16 bits are reserved for the distinct types.
+ */
+#define LDAP_SYN_CASEIGNORESTR (1 | LDAP_SYN_TYPE_TEXT)
+#define LDAP_SYN_MULTILINESTR (2 | LDAP_SYN_TYPE_TEXT)
+#define LDAP_SYN_DN (3 | LDAP_SYN_TYPE_TEXT)
+#define LDAP_SYN_BOOLEAN (4 | LDAP_SYN_TYPE_BOOLEAN)
+#define LDAP_SYN_JPEGIMAGE (5 | LDAP_SYN_TYPE_IMAGE)
+#define LDAP_SYN_JPEGBUTTON (6 | LDAP_SYN_TYPE_BUTTON | \
+ LDAP_SYN_OPT_DEFER)
+#define LDAP_SYN_FAXIMAGE (7 | LDAP_SYN_TYPE_IMAGE)
+#define LDAP_SYN_FAXBUTTON (8 | LDAP_SYN_TYPE_BUTTON | \
+ LDAP_SYN_OPT_DEFER)
+#define LDAP_SYN_AUDIOBUTTON (9 | LDAP_SYN_TYPE_BUTTON | \
+ LDAP_SYN_OPT_DEFER)
+#define LDAP_SYN_TIME (10 | LDAP_SYN_TYPE_TEXT)
+#define LDAP_SYN_DATE (11 | LDAP_SYN_TYPE_TEXT)
+#define LDAP_SYN_LABELEDURL (12 | LDAP_SYN_TYPE_TEXT)
+#define LDAP_SYN_SEARCHACTION (13 | LDAP_SYN_TYPE_ACTION)
+#define LDAP_SYN_LINKACTION (14 | LDAP_SYN_TYPE_ACTION)
+#define LDAP_SYN_ADDDNACTION (15 | LDAP_SYN_TYPE_ACTION)
+#define LDAP_SYN_VERIFYDNACTION (16 | LDAP_SYN_TYPE_ACTION)
+#define LDAP_SYN_RFC822ADDR (17 | LDAP_SYN_TYPE_TEXT)
+#ifdef SUN
+#define LDAP_SYN_PROTECTED (18 | LDAP_SYN_TYPE_TEXT)
+#endif
+
+/*
+ * handy macros
+ */
+#define LDAP_GET_SYN_TYPE(syid) ((syid) & 0xFF000000)
+#define LDAP_GET_SYN_OPTIONS(syid) ((syid) & 0x00FF0000)
+
+/*
+ * display options for output routines (used by entry2text and friends)
+ */
+/*
+ * use calculated label width (based on length of longest label in
+ * template) instead of contant width
+ */
+#define LDAP_DISP_OPT_AUTOLABELWIDTH 0x00000001
+#define LDAP_DISP_OPT_HTMLBODYONLY 0x00000002
+
+/*
+ * perform search actions (applies to ldap_entry2text_search only)
+ */
+#define LDAP_DISP_OPT_DOSEARCHACTIONS 0x00000002
+
+/*
+ * include additional info. relevant to "non leaf" entries only
+ * used by ldap_entry2html and ldap_entry2html_search to include "Browse"
+ * and "Move Up" HREFs
+ */
+#define LDAP_DISP_OPT_NONLEAF 0x00000004
+
+
+/*
+ * display template item options (may not apply to all types)
+ * if this bit is set in ti_options, it applies.
+ */
+#define LDAP_DITEM_OPT_READONLY 0x00000001
+#define LDAP_DITEM_OPT_SORTVALUES 0x00000002
+#define LDAP_DITEM_OPT_SINGLEVALUED 0x00000004
+#define LDAP_DITEM_OPT_HIDEIFEMPTY 0x00000008
+#define LDAP_DITEM_OPT_VALUEREQUIRED 0x00000010
+#define LDAP_DITEM_OPT_HIDEIFFALSE 0x00000020 /* booleans only */
+
+
+/*
+ * LDAP API Information structure
+ */
+typedef struct ldapapiinfo {
+ int ldapai_info_version; /* version of this struct (1) */
+ int ldapai_api_version; /* revision of API supported */
+ int ldapai_protocol_version; /* highest LDAP version supported */
+ char **ldapai_extensions; /* names of API extensions */
+ char *ldapai_vendor_name; /* name of supplier */
+ int ldapai_vendor_version; /* supplier-specific version * 100 */
+} LDAPAPIInfo;
+#define LDAP_API_INFO_VERSION 1
+
+
+/*
+ * LDAP API Feature Information
+ */
+typedef struct ldap_apifeature_info {
+ int ldapaif_info_version; /* version of this struct (1) */
+ char *ldapaif_name; /* name of supported feature */
+ int ldapaif_version; /* revision of supported feature */
+} LDAPAPIFeatureInfo;
+#define LDAP_FEATURE_INFO_VERSION 1
+
+
+/*
+ * display template item structure
+ */
+struct ldap_tmplitem {
+ unsigned int ti_syntaxid;
+ unsigned int ti_options;
+ char *ti_attrname;
+ char *ti_label;
+ char **ti_args;
+ struct ldap_tmplitem *ti_next_in_row;
+ struct ldap_tmplitem *ti_next_in_col;
+ void *ti_appdata;
+};
+
+
+#define NULLTMPLITEM ((struct ldap_tmplitem *)0)
+
+#define LDAP_SET_TMPLITEM_APPDATA(ti, datap) \
+ (ti)->ti_appdata = (void *)(datap)
+
+#define LDAP_GET_TMPLITEM_APPDATA(ti, type) \
+ (type)((ti)->ti_appdata)
+
+
+#define LDAP_IS_TMPLITEM_OPTION_SET(ti, option) \
+ (((ti)->ti_options & option) != 0)
+
+
+/*
+ * object class array structure
+ */
+struct ldap_oclist {
+ char **oc_objclasses;
+ struct ldap_oclist *oc_next;
+};
+
+#define NULLOCLIST ((struct ldap_oclist *)0)
+
+
+/*
+ * add defaults list
+ */
+struct ldap_adddeflist {
+ int ad_source;
+#define LDAP_ADSRC_CONSTANTVALUE 1
+#define LDAP_ADSRC_ADDERSDN 2
+ char *ad_attrname;
+ char *ad_value;
+ struct ldap_adddeflist *ad_next;
+};
+
+#define NULLADLIST ((struct ldap_adddeflist *)0)
+
+
+/*
+ * display template global options
+ * if this bit is set in dt_options, it applies.
+ */
+/*
+ * users should be allowed to try to add objects of these entries
+ */
+#define LDAP_DTMPL_OPT_ADDABLE 0x00000001
+
+/*
+ * users should be allowed to do "modify RDN" operation of these entries
+ */
+#define LDAP_DTMPL_OPT_ALLOWMODRDN 0x00000002
+
+/*
+ * this template is an alternate view, not a primary view
+ */
+#define LDAP_DTMPL_OPT_ALTVIEW 0x00000004
+
+
+/*
+ * display template structure
+ */
+struct ldap_disptmpl {
+ char *dt_name;
+ char *dt_pluralname;
+ char *dt_iconname;
+ unsigned int dt_options;
+ char *dt_authattrname;
+ char *dt_defrdnattrname;
+ char *dt_defaddlocation;
+ struct ldap_oclist *dt_oclist;
+ struct ldap_adddeflist *dt_adddeflist;
+ struct ldap_tmplitem *dt_items;
+ void *dt_appdata;
+ struct ldap_disptmpl *dt_next;
+};
+
+#define NULLDISPTMPL ((struct ldap_disptmpl *)0)
+
+#define LDAP_SET_DISPTMPL_APPDATA(dt, datap) \
+ (dt)->dt_appdata = (void *)(datap)
+
+#define LDAP_GET_DISPTMPL_APPDATA(dt, type) \
+ (type)((dt)->dt_appdata)
+
+#define LDAP_IS_DISPTMPL_OPTION_SET(dt, option) \
+ (((dt)->dt_options & option) != 0)
+
+#define LDAP_TMPL_ERR_VERSION 1
+#define LDAP_TMPL_ERR_MEM 2
+#define LDAP_TMPL_ERR_SYNTAX 3
+#define LDAP_TMPL_ERR_FILE 4
+
+/*
+ * buffer size needed for entry2text and vals2text
+ */
+#define LDAP_DTMPL_BUFSIZ 8192
+
+/* END Display Template Definitions */
+
+/* BEGIN Search Prefrences Definitions */
+
+struct ldap_searchattr {
+ char *sa_attrlabel;
+ char *sa_attr;
+ /* max 32 matchtypes for now */
+ unsigned int sa_matchtypebitmap;
+ char *sa_selectattr;
+ char *sa_selecttext;
+ struct ldap_searchattr *sa_next;
+};
+
+struct ldap_searchmatch {
+ char *sm_matchprompt;
+ char *sm_filter;
+ struct ldap_searchmatch *sm_next;
+};
+
+struct ldap_searchobj {
+ char *so_objtypeprompt;
+ unsigned int so_options;
+ char *so_prompt;
+ short so_defaultscope;
+ char *so_filterprefix;
+ char *so_filtertag;
+ char *so_defaultselectattr;
+ char *so_defaultselecttext;
+ struct ldap_searchattr *so_salist;
+ struct ldap_searchmatch *so_smlist;
+ struct ldap_searchobj *so_next;
+};
+
+#define NULLSEARCHOBJ ((struct ldap_searchobj *)0)
+
+/*
+ * global search object options
+ */
+#define LDAP_SEARCHOBJ_OPT_INTERNAL 0x00000001
+
+#define LDAP_IS_SEARCHOBJ_OPTION_SET(so, option) \
+ (((so)->so_options & option) != 0)
+
+#define LDAP_SEARCHPREF_VERSION_ZERO 0
+#define LDAP_SEARCHPREF_VERSION 1
+
+#define LDAP_SEARCHPREF_ERR_VERSION 1
+#define LDAP_SEARCHPREF_ERR_MEM 2
+#define LDAP_SEARCHPREF_ERR_SYNTAX 3
+#define LDAP_SEARCHPREF_ERR_FILE 4
+
+
+/* END Search Prefrences Definitions */
+
+/*
+ * Structure for LDAP modifications
+ */
+typedef struct ldapmod {
+ int mod_op;
+#define LDAP_MOD_ADD 0x00
+#define LDAP_MOD_DELETE 0x01
+#define LDAP_MOD_REPLACE 0x02
+#define LDAP_MOD_BVALUES 0x80
+ char *mod_type;
+ union {
+ char **modv_strvals;
+ struct berval **modv_bvals;
+ } mod_vals;
+#define mod_values mod_vals.modv_strvals
+#define mod_bvalues mod_vals.modv_bvals
+/*
+ * The following field is commented out since no functions use it in
+ * the library and also not part of c-api draft.
+ */
+/* struct ldapmod *mod_next */
+} LDAPMod;
+
+typedef struct ldap LDAP; /* Opaque LDAP connection handle */
+
+typedef struct ldapmsg LDAPMessage; /* Opaque Result / Entry handle */
+
+#define NULLMSG ((LDAPMessage *) NULL)
+
+/* Call back to get info needed for re-bind */
+typedef int (LDAP_REBIND_FUNCTION)(LDAP *ld, char **dn, char **passwd,
+ int *authmethod, int freeit, void *extraArg);
+
+/*
+ * structures for ldap getfilter routines
+ */
+
+typedef struct ldap_filt_info {
+ char *lfi_filter;
+ char *lfi_desc;
+ int lfi_scope; /* LDAP_SCOPE_BASE, etc */
+ int lfi_isexact; /* exact match filter? */
+ struct ldap_filt_info *lfi_next;
+} LDAPFiltInfo;
+
+
+#define LDAP_FILT_MAXSIZ 1024
+
+typedef struct ldap_filt_list LDAPFiltList;
+typedef struct ldap_filt_desc LDAPFiltDesc;
+
+
+/*
+ * Simple Page control OID
+ */
+#define LDAP_CONTROL_SIMPLE_PAGE "1.2.840.113556.1.4.319"
+
+/*
+ * Server Sort Control
+ */
+#define LDAP_CONTROL_SORTREQUEST "1.2.840.113556.1.4.473"
+#define LDAP_CONTROL_SORTRESPONSE "1.2.840.113556.1.4.474"
+/*
+ * structure for a sort-key
+ */
+typedef struct LDAPsortkey {
+ char *sk_attrtype;
+ char *sk_matchruleoid;
+ int sk_reverseorder;
+} LDAPsortkey;
+
+/*
+ * Virtual List View (vlv) control
+ */
+#define LDAP_CONTROL_VLVREQUEST "2.16.840.1.113730.3.4.9"
+#define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10"
+/*
+ * structure that describes a VirtualListViewRequest control.
+ * note that ldvlist_index and ldvlist_size are only relevant to
+ * ldap_create_virtuallist_control() if ldvlist_attrvalue is NULL.
+ */
+typedef struct ldapvirtuallist {
+ unsigned long ldvlist_before_count; /* # entries before target */
+ unsigned long ldvlist_after_count; /* # entries after target */
+ char *ldvlist_attrvalue; /* jump to this value */
+ unsigned long ldvlist_index; /* list offset */
+ unsigned long ldvlist_size; /* number of items in vlist */
+ void *ldvlist_extradata; /* for use by application */
+} LDAPVirtualList;
+
+/*
+ * ldapv3 LDAPControl
+ */
+typedef struct ldapcontrol
+{
+ char *ldctl_oid;
+/*
+ * the "ldctl_value" field of this structure used to be a pointer to
+ * struct berval. To make this structure compliant to the latest c-api
+ * draft, it is changed to "struct berval ldctl_value"
+ */
+ struct berval ldctl_value;
+ char ldctl_iscritical;
+} LDAPControl, *PLDAPControl;
+
+/*
+ * specific LDAP instantiations of BER types we know about
+ */
+
+/* general stuff */
+#define LDAP_TAG_MESSAGE 0x30 /* tag is 16 + constructed bit */
+#define LDAP_TAG_MSGID 0x02
+#define LDAP_TAG_CONTROL_LIST 0xA0 /* Context 0 + constructed */
+#define LDAP_TAG_REFERRAL 0xA3 /* Context 3 + constructed */
+#define LDAP_TAG_SASLCREDS 0x87 /* Context 7 + primitive */
+#define LDAP_TAG_AUTH_SIMPLE 0x80 /* Context 0 + primitive */
+#define LDAP_TAG_AUTH_SASL 0xA3 /* Context 3 + constructed */
+/* Tag for modrdn request */
+#define LDAP_TAG_NEWPARENT 0x80 /* Context 0 + primitive */
+/* Tags for Extensible filter match */
+#define LDAP_TAG_FEXT_RULE 0x81 /* Context 1 + primitive */
+#define LDAP_TAG_FEXT_TYPE 0x82 /* Context 2 + primitive */
+#define LDAP_TAG_FEXT_VAL 0x83 /* Context 3 + primitive */
+#define LDAP_TAG_FEXT_DN 0x84 /* Context 4 + primitive */
+/* tags for EXTENDED OPERATIONS */
+#define LDAP_TAG_EXT_NAME 0x80 /* Context 0 + primitive */
+#define LDAP_TAG_EXT_VAL 0x81 /* Context 1 + primitive */
+#define LDAP_TAG_EXT_RESPNAME 0x8a /* Context 10 + primitive */
+#define LDAP_TAG_EXT_RESPONSE 0x8b /* Context 11 + primitive */
+/* tags for Virtual List View control */
+#define LDAP_TAG_VLV_BY_INDEX 0xa0 /* context specific + constructed + 0 */
+#define LDAP_TAG_VLV_BY_VALUE 0x81 /* context specific + primitive + 1 */
+/* tag for sort control */
+#define LDAP_TAG_SK_MATCHRULE 0x80L /* context specific + primitive */
+#define LDAP_TAG_SK_REVERSE 0x81L /* context specific + primitive */
+#define LDAP_TAG_SR_ATTRTYPE 0x80L /* context specific + primitive */
+
+/* possible operations a client can invoke */
+#define LDAP_REQ_BIND 0x60 /* application + constructed */
+#define LDAP_REQ_UNBIND 0x42 /* application + primitive */
+#define LDAP_REQ_SEARCH 0x63 /* application + constructed */
+#define LDAP_REQ_MODIFY 0x66 /* application + constructed */
+#define LDAP_REQ_ADD 0x68 /* application + constructed */
+#define LDAP_REQ_DELETE 0x4a /* application + primitive */
+#define LDAP_REQ_MODRDN 0x6c /* application + constructed */
+#define LDAP_REQ_COMPARE 0x6e /* application + constructed */
+#define LDAP_REQ_ABANDON 0x50 /* application + primitive */
+/* New in ldapv3 application + constructed */
+#define LDAP_REQ_EXTENDED 0x77
+/* version 3.0 compatibility stuff */
+#define LDAP_REQ_UNBIND_30 0x62
+#define LDAP_REQ_DELETE_30 0x6a
+#define LDAP_REQ_ABANDON_30 0x70
+
+/* possible result types a server can return */
+#define LDAP_RES_BIND 0x61 /* application + constructed */
+#define LDAP_RES_SEARCH_ENTRY 0x64 /* application + constructed */
+/* new in ldapv3, application + constructed */
+#define LDAP_RES_SEARCH_REFERENCE 0x73
+#define LDAP_RES_SEARCH_RESULT 0x65 /* application + constructed */
+#define LDAP_RES_MODIFY 0x67 /* application + constructed */
+#define LDAP_RES_ADD 0x69 /* application + constructed */
+#define LDAP_RES_DELETE 0x6b /* application + constructed */
+#define LDAP_RES_MODRDN 0x6d /* application + constructed */
+#define LDAP_RES_COMPARE 0x6f /* application + constructed */
+/* new in ldapv3, application + constructed */
+#define LDAP_RES_EXTENDED 0x78
+#define LDAP_RES_ANY (-1)
+
+/* authentication methods available */
+#define LDAP_AUTH_NONE 0x00 /* no authentication */
+#define LDAP_AUTH_SIMPLE 0x80 /* context specific + primitive */
+#define LDAP_AUTH_KRBV4 0xff /* means do both of the following */
+#define LDAP_AUTH_KRBV41 0x81 /* context specific + primitive */
+#define LDAP_AUTH_KRBV42 0x82 /* context specific + primitive */
+/* New with ldapv3 */
+#define LDAP_AUTH_SASL 0xa3 /* context specific + constructed */
+
+/* 3.0 compatibility auth methods */
+#define LDAP_AUTH_SIMPLE_30 0xa0 /* context specific + constructed */
+#define LDAP_AUTH_KRBV41_30 0xa1 /* context specific + constructed */
+#define LDAP_AUTH_KRBV42_30 0xa2 /* context specific + constructed */
+
+/* filter types */
+#define LDAP_FILTER_AND 0xa0 /* context specific + constructed */
+#define LDAP_FILTER_OR 0xa1 /* context specific + constructed */
+#define LDAP_FILTER_NOT 0xa2 /* context specific + constructed */
+#define LDAP_FILTER_EQUALITY 0xa3 /* context specific + constructed */
+#define LDAP_FILTER_SUBSTRINGS 0xa4 /* context specific + constructed */
+#define LDAP_FILTER_GE 0xa5 /* context specific + constructed */
+#define LDAP_FILTER_LE 0xa6 /* context specific + constructed */
+#define LDAP_FILTER_PRESENT 0x87 /* context specific + primitive */
+#define LDAP_FILTER_APPROX 0xa8 /* context specific + constructed */
+#define LDAP_FILTER_EXTENSIBLE 0xa9 /* context specific + constructed */
+
+/* 3.0 compatibility filter types */
+#define LDAP_FILTER_PRESENT_30 0xa7 /* context specific + constructed */
+
+/* substring filter component types */
+#define LDAP_SUBSTRING_INITIAL 0x80 /* context specific */
+#define LDAP_SUBSTRING_ANY 0x81 /* context specific */
+#define LDAP_SUBSTRING_FINAL 0x82 /* context specific */
+
+/* 3.0 compatibility substring filter component types */
+#define LDAP_SUBSTRING_INITIAL_30 0xa0 /* context specific */
+#define LDAP_SUBSTRING_ANY_30 0xa1 /* context specific */
+#define LDAP_SUBSTRING_FINAL_30 0xa2 /* context specific */
+
+/* search scopes */
+#define LDAP_SCOPE_BASE 0x00
+#define LDAP_SCOPE_ONELEVEL 0x01
+#define LDAP_SCOPE_SUBTREE 0x02
+/* Used when parsing URL, if scope not found. *LDAP_SCOPE_BASE is to use then */
+#define LDAP_SCOPE_UNKNOWN 0xFF
+
+/* ldap_result number of messages that should be returned */
+#define LDAP_MSG_ONE 0x00
+#define LDAP_MSG_ALL 0x01
+#define LDAP_MSG_RECEIVED 0x02
+
+
+/* default limit on nesting of referrals */
+#define LDAP_DEFAULT_REFHOPLIMIT 5
+
+
+/* SASL mechanisms */
+#define LDAP_SASL_SIMPLE ""
+#define LDAP_SASL_CRAM_MD5 "CRAM-MD5"
+#define LDAP_SASL_EXTERNAL "EXTERNAL"
+/* Next ones are not supported so far by SunDS 2.0 */
+#define LDAP_SASL_X511_PROTECTED "X.511-Protected"
+#define LDAP_SASL_X511_STRONG "X.511-Strong"
+#define LDAP_SASL_KERBEROS_V4 "KERBEROS_V4"
+#define LDAP_SASL_GSSAPI "GSSAPI"
+#define LDAP_SASL_SKEY "SKEY"
+
+/*
+ * structure for ldap friendly mapping routines
+ */
+
+typedef struct friendly {
+ char *f_unfriendly;
+ char *f_friendly;
+} FriendlyMap;
+
+
+/*
+ * Structures for URL handling
+ */
+typedef struct ldap_url_extension {
+ char *lue_type;
+ char *lue_value;
+ int lue_iscritical;
+} LDAPURLExt;
+
+typedef struct ldap_url_desc {
+ char *lud_host;
+ int lud_port;
+ char *lud_dn;
+ char **lud_attrs;
+ int lud_scope;
+ char *lud_filter;
+ LDAPURLExt **lud_extensions;
+ char *lud_string; /* for internal use only */
+} LDAPURLDesc;
+
+#define NULLLDAPURLDESC ((LDAPURLDesc *)NULL)
+
+#define LDAP_URL_ERR_NOTLDAP 1 /* URL doesn't begin with "ldap://" */
+#define LDAP_URL_ERR_NODN 2 /* URL has no DN (required) */
+#define LDAP_URL_ERR_BADSCOPE 3 /* URL scope string is invalid */
+#define LDAP_URL_ERR_MEM 4 /* can't allocate memory space */
+
+
+/*
+ * possible error codes we can return
+ */
+
+#define LDAP_SUCCESS 0x00
+#define LDAP_OPERATIONS_ERROR 0x01
+#define LDAP_PROTOCOL_ERROR 0x02
+#define LDAP_TIMELIMIT_EXCEEDED 0x03
+#define LDAP_SIZELIMIT_EXCEEDED 0x04
+#define LDAP_COMPARE_FALSE 0x05
+#define LDAP_COMPARE_TRUE 0x06
+#define LDAP_AUTH_METHOD_NOT_SUPPORTED 0x07
+#define LDAP_STRONG_AUTH_REQUIRED 0x08
+/* Not used in ldapv3 */
+#define LDAP_PARTIAL_RESULTS 0x09
+
+/* New in ldapv3 */
+#define LDAP_REFERRAL 0x0a
+#define LDAP_ADMINLIMIT_EXCEEDED 0x0b
+#define LDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c
+#define LDAP_CONFIDENTIALITY_REQUIRED 0x0d
+#define LDAP_SASL_BIND_INPROGRESS 0x0e
+/* End of new */
+
+#define LDAP_NO_SUCH_ATTRIBUTE 0x10
+#define LDAP_UNDEFINED_TYPE 0x11
+#define LDAP_INAPPROPRIATE_MATCHING 0x12
+#define LDAP_CONSTRAINT_VIOLATION 0x13
+#define LDAP_TYPE_OR_VALUE_EXISTS 0x14
+#define LDAP_INVALID_SYNTAX 0x15
+
+#define ATTRIBUTE_ERROR(n) ((n & 0xf0) == 0x10)
+
+#define LDAP_NO_SUCH_OBJECT 0x20
+#define LDAP_ALIAS_PROBLEM 0x21
+#define LDAP_INVALID_DN_SYNTAX 0x22
+/* Following in not used in ldapv3 */
+#define LDAP_IS_LEAF 0x23
+#define LDAP_ALIAS_DEREF_PROBLEM 0x24
+
+#define NAME_ERROR(n) ((n & 0xf0) == 0x20)
+
+#define LDAP_INAPPROPRIATE_AUTH 0x30
+#define LDAP_INVALID_CREDENTIALS 0x31
+#define LDAP_INSUFFICIENT_ACCESS 0x32
+#define LDAP_BUSY 0x33
+#define LDAP_UNAVAILABLE 0x34
+#define LDAP_UNWILLING_TO_PERFORM 0x35
+#define LDAP_LOOP_DETECT 0x36
+
+#define LDAP_SORT_CONTROL_MISSING 0x3C /* 60 */
+#define LDAP_INDEX_RANGE_ERROR 0x3D /* 61 */
+
+#define LDAP_NAMING_VIOLATION 0x40
+#define LDAP_OBJECT_CLASS_VIOLATION 0x41
+#define LDAP_NOT_ALLOWED_ON_NONLEAF 0x42
+#define LDAP_NOT_ALLOWED_ON_RDN 0x43
+#define LDAP_ALREADY_EXISTS 0x44
+#define LDAP_NO_OBJECT_CLASS_MODS 0x45
+#define LDAP_RESULTS_TOO_LARGE 0x46
+/* Following is new in ldapv3 */
+#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47
+#define LDAP_OTHER 0x50
+
+/* Reserved for API */
+#define LDAP_SERVER_DOWN 0x51
+#define LDAP_LOCAL_ERROR 0x52
+#define LDAP_ENCODING_ERROR 0x53
+#define LDAP_DECODING_ERROR 0x54
+#define LDAP_TIMEOUT 0x55
+#define LDAP_AUTH_UNKNOWN 0x56
+#define LDAP_FILTER_ERROR 0x57
+#define LDAP_USER_CANCELLED 0x58
+#define LDAP_PARAM_ERROR 0x59
+#define LDAP_NO_MEMORY 0x5a
+
+/* New code with ldapv3 ? */
+#define LDAP_CONNECT_ERROR 0x5b
+#define LDAP_NOT_SUPPORTED 0x5c
+#define LDAP_CONTROL_NOT_FOUND 0x5d
+#define LDAP_NO_RESULTS_RETURNED 0x5e
+#define LDAP_MORE_RESULTS_TO_RETURN 0x5f
+#define LDAP_CLIENT_LOOP 0x60
+#define LDAP_REFERRAL_LIMIT_EXCEEDED 0x61
+
+/* debugging stuff */
+#ifdef LDAP_DEBUG
+extern int ldap_debug;
+#ifdef LDAP_SYSLOG
+extern int ldap_syslog;
+extern int ldap_syslog_level;
+#endif
+#define LDAP_DEBUG_TRACE 0x001
+#define LDAP_DEBUG_PACKETS 0x002
+#define LDAP_DEBUG_ARGS 0x004
+#define LDAP_DEBUG_CONNS 0x008
+#define LDAP_DEBUG_BER 0x010
+#define LDAP_DEBUG_FILTER 0x020
+#define LDAP_DEBUG_CONFIG 0x040
+#define LDAP_DEBUG_ACL 0x080
+#define LDAP_DEBUG_STATS 0x100
+#define LDAP_DEBUG_STATS2 0x200
+#define LDAP_DEBUG_SHELL 0x400
+#define LDAP_DEBUG_PARSE 0x800
+/* More values for http gateway */
+#define LDAP_DEBUG_GWAY 0x1000
+#define LDAP_DEBUG_GWAYMORE 0x2000
+
+#define LDAP_DEBUG_ANY 0xffff
+
+#ifdef LDAP_SYSLOG
+/* ldaplog is a general logging function that is defined in liblber/i18n.c */
+#define Debug(level, fmt, arg1, arg2, arg3) \
+ { \
+ if (ldap_debug & level) \
+ fprintf(stderr, fmt, arg1, arg2, arg3); \
+ if (ldap_syslog & level) \
+ ldaplog(level, fmt, arg1, arg2, arg3); \
+ }
+#else /* LDAP_SYSLOG */
+#ifndef WINSOCK
+#define Debug(level, fmt, arg1, arg2, arg3) \
+ if (ldap_debug & level) \
+ fprintf(stderr, fmt, arg1, arg2, arg3);
+#else /* !WINSOCK */
+extern void Debug(int level, char *fmt, ...);
+#endif /* !WINSOCK */
+#endif /* LDAP_SYSLOG */
+#else /* LDAP_DEBUG */
+#define Debug(level, fmt, arg1, arg2, arg3)
+#endif /* LDAP_DEBUG */
+
+
+#ifndef NEEDPROTOS
+extern LDAP *ldap_open();
+#ifdef LDAP_SSL
+extern LDAP *ldap_ssl_open();
+#endif /* LDAP_SSL */
+extern LDAP *ldap_init();
+#ifdef STR_TRANSLATION
+extern void ldap_set_string_translators();
+#ifdef LDAP_CHARSET_8859
+extern int ldap_t61_to_8859();
+extern int ldap_8859_to_t61();
+#endif /* LDAP_CHARSET_8859 */
+#endif /* STR_TRANSLATION */
+extern LDAPMessage *ldap_first_entry();
+extern LDAPMessage *ldap_next_entry();
+extern char *ldap_get_dn();
+extern char *ldap_dn2ufn();
+extern char **ldap_explode_dn();
+extern char *ldap_first_attribute();
+extern char *ldap_next_attribute();
+extern char **ldap_get_values();
+extern struct berval **ldap_get_values_len();
+extern void ldap_value_free();
+extern void ldap_value_free_len();
+extern int ldap_count_values();
+extern int ldap_count_values_len();
+extern char *ldap_err2string();
+extern void ldap_getfilter_free();
+extern LDAPFiltDesc *ldap_init_getfilter();
+extern LDAPFiltDesc *ldap_init_getfilter_buf();
+extern LDAPFiltInfo *ldap_getfirstfilter();
+extern LDAPFiltInfo *ldap_getnextfilter();
+extern void ldap_setfilteraffixes();
+extern void ldap_build_filter();
+extern void ldap_flush_cache();
+extern void ldap_set_cache_options();
+extern void ldap_uncache_entry();
+extern void ldap_uncache_request();
+extern char *ldap_friendly_name();
+extern void ldap_free_friendlymap();
+extern LDAP *cldap_open();
+extern void cldap_setretryinfo();
+extern void cldap_close();
+extern LDAPFiltDesc *ldap_ufn_setfilter();
+extern int ldap_ufn_timeout();
+extern int ldap_sort_entries();
+extern int ldap_sort_values();
+extern int ldap_sort_strcasecmp();
+void ldap_free_urldesc();
+void ldap_free_urlexts();
+void ldap_set_rebind_proc();
+void ldap_enable_translation();
+/* Begin Display Template Prototypes */
+typedef int (*writeptype)();
+
+int ldap_init_templates();
+int ldap_init_templates_buf();
+void ldap_free_templates();
+struct ldap_disptmpl *ldap_first_disptmpl();
+struct ldap_disptmpl *ldap_next_disptmpl();
+struct ldap_disptmpl *ldap_name2template();
+struct ldap_disptmpl *ldap_oc2template();
+char **ldap_tmplattrs();
+struct ldap_tmplitem *ldap_first_tmplrow();
+struct ldap_tmplitem *ldap_next_tmplrow();
+struct ldap_tmplitem *ldap_first_tmplcol();
+struct ldap_tmplitem *ldap_next_tmplcol();
+int ldap_entry2text_search();
+int ldap_entry2text();
+int ldap_vals2text();
+int ldap_entry2html_search();
+int ldap_entry2html();
+int ldap_vals2html();
+
+int ldap_init_searchprefs();
+int ldap_init_searchprefs_buf();
+void ldap_free_searchprefs();
+struct ldap_searchobj *ldap_first_searchobj();
+struct ldap_searchobj *ldap_next_searchobj();
+
+#else /* NEEDPROTOS */
+#if !defined(MACOS) && !defined(DOS) && !defined(_WIN32) && !defined(WINSOCK)
+#include <sys/time.h>
+#endif
+
+
+/*
+ * Abandon functions
+ */
+int ldap_abandon_ext(LDAP *ld, int msgid, LDAPControl **serverctrls,
+ LDAPControl ** clientctrls);
+int ldap_abandon(LDAP *ld, int msgid);
+
+/*
+ * Add functions
+ */
+int ldap_add_ext(LDAP *ld, char *dn, LDAPMod **attrs,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_add_ext_s(LDAP *ld, char *dn, LDAPMod **attrs,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls);
+int ldap_add(LDAP *ld, char *dn, LDAPMod **attrs);
+int ldap_add_s(LDAP *ld, char *dn, LDAPMod **attrs);
+
+/*
+ * Bind functions
+ */
+/* DEPRECATED */
+int ldap_bind(LDAP *ld, char *who, char *passwd, int authmethod);
+/* DEPRECATED */
+int ldap_bind_s(LDAP *ld, char *who, char *cred, int method);
+#ifdef LDAP_REFERRALS
+/* DEPRECATED */
+void ldap_set_rebind_proc(LDAP *ld, LDAP_REBIND_FUNCTION *rebindproc,
+ void *extra_arg);
+#endif /* LDAP_REFERRALS */
+
+/*
+ * Simple bind functions
+ */
+int ldap_simple_bind(LDAP *ld, char *who, char *passwd);
+int ldap_simple_bind_s(LDAP *ld, char *who, char *passwd);
+
+/*
+ * SASL functions
+ */
+int ldap_sasl_bind(LDAP *ld, char *dn, char *mechanism, struct berval *cred,
+ LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_sasl_bind_s(LDAP *ld, char *dn, char *mechanism, struct berval *cred,
+ LDAPControl **serverctrls, LDAPControl **clientctrls,
+ struct berval **servercredp);
+
+/*
+ * Kerberos functions
+ */
+/* DEPRECATED */
+int ldap_kerberos_bind_s(LDAP *ld, char *who);
+/* DEPRECATED */
+int ldap_kerberos_bind1(LDAP *ld, char *who);
+/* DEPRECATED */
+int ldap_kerberos_bind1_s(LDAP *ld, char *who);
+/* DEPRECATED */
+int ldap_kerberos_bind2(LDAP *ld, char *who);
+/* DEPRECATED */
+int ldap_kerberos_bind2_s(LDAP *ld, char *who);
+
+#ifndef NO_CACHE
+/*
+ * Cache functions
+ */
+int ldap_enable_cache(LDAP *ld, time_t timeout, ssize_t maxmem);
+void ldap_disable_cache(LDAP *ld);
+void ldap_set_cache_options(LDAP *ld, unsigned int opts);
+void ldap_destroy_cache(LDAP *ld);
+void ldap_flush_cache(LDAP *ld);
+void ldap_uncache_entry(LDAP *ld, char *dn);
+void ldap_uncache_request(LDAP *ld, int msgid);
+#endif /* !NO_CACHE */
+
+/*
+ * Compare functions
+ */
+int ldap_compare_ext(LDAP *ld, char *dn, char *attr, struct berval *bvalue,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_compare_ext_s(LDAP *ld, char *dn, char *attr, struct berval *bvalue,
+ LDAPControl ** serverctrls, LDAPControl **clientctrls);
+int ldap_compare(LDAP *ld, char *dn, char *attr, char *value);
+int ldap_compare_s(LDAP *ld, char *dn, char *attr, char *value);
+
+/*
+ * Delete functions
+ */
+int ldap_delete_ext(LDAP *ld, char *dn, LDAPControl **serverctrls,
+ LDAPControl **clientctrls, int *msgidp);
+int ldap_delete_ext_s(LDAP *ld, char *dn, LDAPControl **serverctrls,
+ LDAPControl **clientctrls);
+int ldap_delete(LDAP *ld, char *dn);
+int ldap_delete_s(LDAP *ld, char *dn);
+
+/*
+ * Error functions
+ */
+char *ldap_err2string(int err);
+
+/* DEPRECATED */
+int ldap_result2error(LDAP *ld, LDAPMessage *r, int freeit);
+/* DEPRECATED */
+void ldap_perror(LDAP *ld, char *s);
+
+/*
+ * Modify functions
+ */
+int ldap_modify_ext(LDAP *ld, char *dn, LDAPMod **mods,
+ LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp);
+int ldap_modify_ext_s(LDAP *ld, char *dn, LDAPMod **mods,
+ LDAPControl **serverctrls, LDAPControl **clientctrls);
+int ldap_modify(LDAP *ld, char *dn, LDAPMod **mods);
+int ldap_modify_s(LDAP *ld, char *dn, LDAPMod **mods);
+
+/*
+ * Modrdn functions
+ */
+
+/* DEPRECATED : use ldap_rename instead */
+int ldap_modrdn0(LDAP *ld, char *dn, char *newrdn);
+/* DEPRECATED : use ldap_rename_s instead */
+int ldap_modrdn0_s(LDAP *ld, char *dn, char *newrdn);
+/* DEPRECATED : use ldap_rename instead */
+int ldap_modrdn(LDAP *ld, char *dn, char *newrdn,
+ int deleteoldrdn);
+/* DEPRECATED : use ldap_rename_s instead */
+int ldap_modrdn_s(LDAP *ld, char *dn, char *newrdn,
+ int deleteoldrdn);
+
+/*
+ * Rename functions
+ */
+int ldap_rename(LDAP *ld, char *dn, char *newrdn, char *newparent,
+ int deleteoldrdn, LDAPControl ** serverctrls,
+ LDAPControl **clientctrls, int *msgidp);
+int ldap_rename_s(LDAP *ld, char *dn, char *newrdn, char *newparent,
+ int deleteoldrdn, LDAPControl ** serverctrls,
+ LDAPControl **clientctrls);
+
+/*
+ * Init/Open functions
+ */
+LDAP *ldap_init(char *defhost, int defport);
+
+/* DEPRECATED : use ldap_init instead */
+LDAP *ldap_open(char *host, int port);
+
+#ifdef LDAP_SSL
+LDAP *ldap_ssl_init(char *defhost, int defport, char *keyname);
+
+/* DEPRECATED : use ldap_ssl_init instead */
+LDAP *ldap_ssl_open(char *host, int port, char *keyname);
+#endif
+
+/*
+ * Entry functions
+ */
+LDAPMessage *ldap_first_entry(LDAP *ld, LDAPMessage *res);
+LDAPMessage *ldap_next_entry(LDAP *ld, LDAPMessage *entry);
+int ldap_count_entries(LDAP *ld, LDAPMessage *res);
+
+/*
+ * Message functions
+ */
+LDAPMessage *ldap_first_message(LDAP *ld, LDAPMessage *res);
+LDAPMessage *ldap_next_message(LDAP *ld, LDAPMessage *msg);
+int ldap_count_messages(LDAP *ld, LDAPMessage *res);
+
+/*
+ * Reference functions
+ */
+LDAPMessage *ldap_first_reference(LDAP *ld, LDAPMessage *res);
+LDAPMessage *ldap_next_reference(LDAP *ld, LDAPMessage *msg);
+int ldap_count_references(LDAP *ld, LDAPMessage *res);
+char ** ldap_get_reference_urls(LDAP *ld, LDAPMessage *res);
+
+/*
+ * Entry functions
+ */
+LDAPMessage *ldap_delete_result_entry(LDAPMessage **list,
+ LDAPMessage *e);
+void ldap_add_result_entry(LDAPMessage **list, LDAPMessage *e);
+
+/*
+ * DN functions
+ */
+char *ldap_get_dn(LDAP *ld, LDAPMessage *entry);
+char **ldap_explode_dn(char *dn, int notypes);
+char ** ldap_explode_rdn(char *rdn, int notypes);
+char *ldap_dn2ufn(char *dn);
+
+char **ldap_explode_dns(char *dn);
+int ldap_is_dns_dn(char *dn);
+char *ldap_dns_to_dn(char *dns_name, int *nameparts);
+
+/*
+ * Attribute parsing functions
+ */
+char *ldap_first_attribute(LDAP *ld, LDAPMessage *entry,
+ BerElement **ber);
+char *ldap_next_attribute(LDAP *ld, LDAPMessage *entry,
+ BerElement *ber);
+void ldap_memfree(char *mem);
+
+/*
+ * Attribute Value functions
+ */
+char **ldap_get_values(LDAP *ld, LDAPMessage *entry, char *target);
+struct berval **ldap_get_values_len(LDAP *ld, LDAPMessage *entry,
+ char *target);
+int ldap_count_values(char **vals);
+int ldap_count_values_len(struct berval **vals);
+void ldap_value_free(char **vals);
+void ldap_value_free_len(struct berval **vals);
+
+/*
+ * Result functions
+ */
+int ldap_result(LDAP *ld, int msgid, int all,
+ struct timeval *timeout, LDAPMessage **result);
+int ldap_msgdelete(LDAP *ld, int msgid);
+int ldap_msgfree(LDAPMessage *lm);
+int ldap_msgtype(LDAPMessage *res);
+int ldap_msgid(LDAPMessage *res);
+int ldap_parse_result(LDAP *ld, LDAPMessage *res, int *errcodep,
+ char **matcheddnp, char **errmsgp, char ***referralsp,
+ LDAPControl ***serverctrlsp, int freeit);
+int ldap_parse_sasl_bind_result(LDAP *ld, LDAPMessage *res,
+ struct berval **servercredp, int freeit);
+int ldap_parse_extended_result(LDAP *ld, LDAPMessage *res,
+ char **resultoidp, struct berval **resultdata, int freeit);
+int cldap_getmsg(LDAP *ld, struct timeval *timeout, BerElement *ber);
+
+
+/*
+ * Search functions
+ */
+int ldap_search_ext(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, LDAPControl **serverctrls,
+ LDAPControl **clientctrls, struct timeval *timeoutp,
+ int sizelimit, int *msgidp);
+int ldap_search_ext_s(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, LDAPControl **serverctrls,
+ LDAPControl **clientctrls, struct timeval *timeoutp, int sizelimit,
+ LDAPMessage **res);
+
+int ldap_search(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly);
+int ldap_search_s(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, LDAPMessage **res);
+int ldap_search_st(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, struct timeval *timeout, LDAPMessage **res);
+
+/*
+ * UFN functions
+ */
+int ldap_ufn_search_c(LDAP *ld, char *ufn, char **attrs,
+ int attrsonly, LDAPMessage **res, int (*cancelproc)(void *cl),
+ void *cancelparm);
+int ldap_ufn_search_ct(LDAP *ld, char *ufn, char **attrs,
+ int attrsonly, LDAPMessage **res, int (*cancelproc)(void *cl),
+ void *cancelparm, char *tag1, char *tag2, char *tag3);
+int ldap_ufn_search_s(LDAP *ld, char *ufn, char **attrs,
+ int attrsonly, LDAPMessage **res);
+LDAPFiltDesc *ldap_ufn_setfilter(LDAP *ld, char *fname);
+void ldap_ufn_setprefix(LDAP *ld, char *prefix);
+int ldap_ufn_timeout(void *tvparam);
+
+
+/*
+ * Unbind functions
+ */
+int ldap_unbind(LDAP *ld);
+int ldap_unbind_s(LDAP *ld);
+
+
+/*
+ * Filter functions
+ */
+LDAPFiltDesc *ldap_init_getfilter(char *fname);
+LDAPFiltDesc *ldap_init_getfilter_buf(char *buf, ssize_t buflen);
+LDAPFiltInfo *ldap_getfirstfilter(LDAPFiltDesc *lfdp, char *tagpat,
+ char *value);
+LDAPFiltInfo *ldap_getnextfilter(LDAPFiltDesc *lfdp);
+void ldap_setfilteraffixes(LDAPFiltDesc *lfdp, char *prefix, char *suffix);
+void ldap_build_filter(char *buf, size_t buflen,
+ char *pattern, char *prefix, char *suffix, char *attr,
+ char *value, char **valwords);
+
+/*
+ * Functions to free LDAPFiltDesc and LDAPmod
+ */
+void ldap_getfilter_free(LDAPFiltDesc *lfdp);
+void ldap_mods_free(LDAPMod **mods, int freemods);
+
+/*
+ * Friendly name functions
+ */
+char *ldap_friendly_name(char *filename, char *uname,
+ FriendlyMap **map);
+void ldap_free_friendlymap(FriendlyMap **map);
+
+
+/*
+ * Connectionless LDAP functions
+ */
+LDAP *cldap_open(char *host, int port);
+void cldap_close(LDAP *ld);
+int cldap_search_s(LDAP *ld, char *base, int scope, char *filter,
+ char **attrs, int attrsonly, LDAPMessage **res, char *logdn);
+void cldap_setretryinfo(LDAP *ld, int tries, time_t timeout);
+
+
+/*
+ * Sort functions
+ */
+int ldap_sort_entries(LDAP *ld, LDAPMessage **chain, char *attr,
+ int (*cmp)());
+int ldap_sort_values(LDAP *ld, char **vals, int (*cmp)());
+int ldap_sort_strcasecmp(char **a, char **b);
+
+
+/*
+ * URL functions
+ */
+int ldap_is_ldap_url(char *url);
+int ldap_url_parse(char *url, LDAPURLDesc **ludpp);
+void ldap_free_urlexts(LDAPURLExt **lues);
+void ldap_free_urldesc(LDAPURLDesc *ludp);
+int ldap_url_search(LDAP *ld, char *url, int attrsonly);
+int ldap_url_search_s(LDAP *ld, char *url, int attrsonly,
+ LDAPMessage **res);
+int ldap_url_search_st(LDAP *ld, char *url, int attrsonly,
+ struct timeval *timeout, LDAPMessage **res);
+char *ldap_dns_to_url(LDAP *ld, char *dns_name, char *attrs,
+char *scope, char *filter);
+char *ldap_dn_to_url(LDAP *ld, char *dn, int nameparts);
+
+
+/*
+ * in Character Set functions
+ */
+#ifdef STR_TRANSLATION
+void ldap_set_string_translators(LDAP *ld,
+ BERTranslateProc encode_proc, BERTranslateProc decode_proc);
+int ldap_translate_from_t61(LDAP *ld, char **bufp,
+ unsigned int *lenp, int free_input);
+int ldap_translate_to_t61(LDAP *ld, char **bufp,
+ unsigned int *lenp, int free_input);
+void ldap_enable_translation(LDAP *ld, LDAPMessage *entry,
+ int enable);
+
+#ifdef LDAP_CHARSET_8859
+int ldap_t61_to_8859(char **bufp, unsigned int *buflenp,
+ int free_input);
+int ldap_8859_to_t61(char **bufp, unsigned int *buflenp,
+ int free_input);
+#endif /* LDAP_CHARSET_8859 */
+#endif /* STR_TRANSLATION */
+
+/*
+ * Diplay Template functions
+ */
+typedef int (*writeptype)(void *writeparm, char *p, int len);
+
+int ldap_init_templates(char *file,
+ struct ldap_disptmpl **tmpllistp);
+
+int ldap_init_templates_buf(char *buf, ssize_t buflen,
+ struct ldap_disptmpl **tmpllistp);
+
+void ldap_free_templates(struct ldap_disptmpl *tmpllist);
+
+struct ldap_disptmpl *ldap_first_disptmpl(
+ struct ldap_disptmpl *tmpllist);
+
+struct ldap_disptmpl *ldap_next_disptmpl(
+ struct ldap_disptmpl *tmpllist, struct ldap_disptmpl *tmpl);
+
+struct ldap_disptmpl *ldap_name2template(char *name,
+ struct ldap_disptmpl *tmpllist);
+
+struct ldap_disptmpl *ldap_oc2template(char **oclist,
+ struct ldap_disptmpl *tmpllist);
+
+char **ldap_tmplattrs(struct ldap_disptmpl *tmpl,
+ char **includeattrs, int exclude, unsigned int syntaxmask);
+
+struct ldap_tmplitem *ldap_first_tmplrow(struct ldap_disptmpl *tmpl);
+
+struct ldap_tmplitem *ldap_next_tmplrow(struct ldap_disptmpl *tmpl,
+ struct ldap_tmplitem *row);
+
+struct ldap_tmplitem *ldap_first_tmplcol(struct ldap_disptmpl *tmpl,
+ struct ldap_tmplitem *row);
+
+struct ldap_tmplitem *ldap_next_tmplcol(struct ldap_disptmpl *tmpl,
+ struct ldap_tmplitem *row, struct ldap_tmplitem *col);
+
+int ldap_entry2text(LDAP *ld, char *buf, LDAPMessage *entry,
+ struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
+ writeptype writeproc, void *writeparm, char *eol,
+ int rdncount, unsigned int opts);
+
+int ldap_vals2text(LDAP *ld, char *buf, char **vals, char *label,
+ int labelwidth, unsigned int syntaxid, writeptype writeproc,
+ void *writeparm, char *eol, int rdncount);
+
+int ldap_entry2text_search(LDAP *ld, char *dn, char *base,
+ LDAPMessage *entry, struct ldap_disptmpl *tmpllist,
+ char **defattrs, char ***defvals, writeptype writeproc,
+ void *writeparm, char *eol, int rdncount, unsigned int opts);
+
+int ldap_entry2html(LDAP *ld, char *buf, LDAPMessage *entry,
+ struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
+ writeptype writeproc, void *writeparm, char *eol,
+ int rdncount, unsigned int opts, char *urlprefix, char *base);
+
+int ldap_vals2html(LDAP *ld, char *buf, char **vals, char *label,
+ int labelwidth, unsigned int syntaxid, writeptype writeproc,
+ void *writeparm, char *eol, int rdncount, char *urlprefix);
+
+int ldap_entry2html_search(LDAP *ld, char *dn, char *base,
+ LDAPMessage *entry, struct ldap_disptmpl *tmpllist,
+ char **defattrs, char ***defvals, writeptype writeproc,
+ void *writeparm, char *eol, int rdncount, unsigned int opts,
+ char *urlprefix);
+
+
+/*
+ * Search Preferences functions
+ */
+int ldap_init_searchprefs(char *file,
+ struct ldap_searchobj **solistp);
+
+int ldap_init_searchprefs_buf(char *buf, ssize_t buflen,
+ struct ldap_searchobj **solistp);
+
+void ldap_free_searchprefs(struct ldap_searchobj *solist);
+
+struct ldap_searchobj *ldap_first_searchobj(
+ struct ldap_searchobj *solist);
+
+struct ldap_searchobj *ldap_next_searchobj(
+ struct ldap_searchobj *sollist, struct ldap_searchobj *so);
+
+
+/*
+ * Option functions
+ */
+int ldap_get_option(LDAP *ld, int option, void *outvalue);
+int ldap_set_option(LDAP *ld, int option, void *invalue);
+
+
+/*
+ * Control functions
+ */
+void ldap_control_free(LDAPControl *ctrl);
+void ldap_controls_free(LDAPControl **ctrls);
+
+
+/*
+ * Simple Page Control functions
+ */
+int ldap_create_page_control(LDAP *ld, unsigned int pagesize,
+ struct berval *cookie, char isCritical, LDAPControl **output);
+int ldap_parse_page_control(LDAP *ld, LDAPControl **controls,
+ unsigned int *totalcount, struct berval **cookie);
+
+/*
+ * Server Side Sort control functions
+ */
+int ldap_create_sort_control(LDAP *ld, LDAPsortkey **sortKeyList,
+ const char ctl_iscritical, LDAPControl **ctrlp);
+int ldap_parse_sort_control(LDAP *ld, LDAPControl **ctrlp,
+ unsigned long *result, char **attribute);
+int ldap_create_sort_keylist(LDAPsortkey ***sortKeyList, char *string_rep);
+void ldap_free_sort_keylist(LDAPsortkey **sortKeyList);
+
+/*
+ * Virtual List View control functions
+ */
+int ldap_create_virtuallist_control(LDAP *ld, LDAPVirtualList *ldvlistp,
+ LDAPControl **ctrlp);
+int ldap_parse_virtuallist_control(LDAP *ld, LDAPControl **ctrls,
+ unsigned long *target_posp, unsigned long *list_sizep,
+ int *errcodep);
+
+#endif /* NEEDPROTOS */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LDAP_H */
diff --git a/usr/src/lib/libldap4/include/ldapconfig.h b/usr/src/lib/libldap4/include/ldapconfig.h
new file mode 100644
index 0000000000..9179d3744b
--- /dev/null
+++ b/usr/src/lib/libldap4/include/ldapconfig.h
@@ -0,0 +1,280 @@
+
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ * File chamged to fit with Sun Standards
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1994 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+/*
+ * config.h for LDAP -- edit this file to customize LDAP client behavior.
+ * NO platform-specific definitions should be placed in this file.
+ * Note that this is NOT used by the LDAP or LBER libraries.
+ */
+
+/*
+ * SHARED DEFINITIONS - things you should change
+ */
+ /* default ldap host */
+#define LDAPHOST "localhost"
+ /* default place to start searching */
+#define DEFAULT_BASE "c=US"
+
+/*********************************************************************
+ * *
+ * You probably do not need to edit anything below this point *
+ * *
+ *********************************************************************/
+
+/*
+ * SHARED DEFINITIONS - other things you can change
+ */
+ /* default attribute to use when sorting entries, NULL => sort by DN */
+#define SORT_ATTR NULL
+ /* default count of DN components to show in entry displays */
+#define DEFAULT_RDNCOUNT 2
+ /* default config file locations */
+#define FILTERFILE "/etc/opt/SUNWconn/ldap/current/ldapfilter.conf"
+#define TEMPLATEFILE "/etc/opt/SUNWconn/ldap/current/ldaptemplates.conf"
+#define SEARCHFILE "/etc/opt/SUNWconn/ldap/current/ldapsearchprefs.conf"
+#define FRIENDLYFILE "/etc/opt/SUNWconn/ldap/current/ldapfriendly"
+
+/*
+ * FINGER DEFINITIONS
+ */
+ /* who to bind as */
+#define FINGER_BINDDN NULL
+ /* where to search */
+#define FINGER_BASE DEFAULT_BASE
+ /* banner to print */
+#define FINGER_BANNER "X.500 Finger Service...\r\n"
+ /* who to report errors to */
+#define FINGER_ERRORS "your local system administrator"
+ /* what to say if no matches are found */
+#define FINGER_NOMATCH "Search failed to find anything.\r\n"
+ /* what to say if the service may be unavailable */
+#define FINGER_UNAVAILABLE \
+"The X.500 service may be temporarily unavailable.\r\n\
+Please try again later.\r\n"
+ /* printed if a match has no email address - for disptmp default */
+#define FINGER_NOEMAIL1 "None registered in this service."
+#define FINGER_NOEMAIL2 NULL
+#define FINGER_NOEMAIL { FINGER_NOEMAIL1, FINGER_NOEMAIL2, NULL }
+ /* maximum number of matches returned */
+#define FINGER_SIZELIMIT 50
+ /* max number of hits displayed in full before a list is presented */
+#define FINGER_LISTLIMIT 1
+ /* what to exec for "finger @host" */
+#define FINGER_CMD "/usr/ucb/finger"
+ /* how to treat aliases when searching */
+#define FINGER_DEREF LDAP_DEREF_FINDING
+ /* attribute to use when sorting results */
+#define FINGER_SORT_ATTR SORT_ATTR
+ /* enable ufn support */
+#define FINGER_UFN
+ /* timeout for searches */
+#define FINGER_TIMEOUT 60
+ /* number of DN components to show in entry displays */
+#define FINGER_RDNCOUNT DEFAULT_RDNCOUNT
+
+/*
+ * GO500 GOPHER GATEWAY DEFINITIONS
+ */
+ /* who to bind as */
+#define GO500_BINDDN NULL
+ /* where to search */
+#define GO500_BASE DEFAULT_BASE
+ /* port on which to listen */
+#define GO500_PORT 5555
+ /* how to handle aliases */
+#define GO500_DEREF LDAP_DEREF_FINDING
+ /* attribute to use when sorting results */
+#define GO500_SORT_ATTR SORT_ATTR
+ /* timeout for searches */
+#define GO500_TIMEOUT 180
+ /* enable ufn support */
+#define GO500_UFN
+ /*
+ * only set and uncomment this if your hostname() does not return
+ * a fully qualified hostname
+ */
+/* #define GO500_HOSTNAME "fully.qualified.hostname.here" */
+ /* number of DN components to show in entry displays */
+#define GO500_RDNCOUNT DEFAULT_RDNCOUNT
+
+/*
+ * GO500GW GOPHER GATEWAY DEFINITIONS
+ */
+ /* who to bind as */
+#define GO500GW_BINDDN NULL
+ /* where the helpfile lives */
+#define GO500GW_HELPFILE "go500gw.help"
+ /* port on which to listen */
+#define GO500GW_PORT 7777
+ /* timeout on all searches */
+#define GO500GW_TIMEOUT 180
+ /* enable ufn support */
+#define GO500GW_UFN
+ /* attribute to use when sorting results */
+#define GO500GW_SORT_ATTR SORT_ATTR
+ /*
+ * only set and uncomment this if your hostname() does not return
+ * a fully qualified hostname
+ */
+/* #define GO500GW_HOSTNAME "fully.qualified.hostname.here" */
+ /* number of DN components to show in entry displays */
+#define GO500GW_RDNCOUNT DEFAULT_RDNCOUNT
+
+/*
+ * RCPT500 MAIL RESPONDER GATEWAY DEFINITIONS
+ */
+ /* who to bind as */
+#define RCPT500_BINDDN NULL
+ /* where the helpfile lives */
+#define RCPT500_HELPFILE "rcpt500.help"
+ /* maximum number of matches returned */
+#define RCPT500_SIZELIMIT 50
+ /* address replies will appear to come from */
+#define RCPT500_FROM "\"X.500 Query Program\" <X500-Query>"
+ /* command that will accept an RFC822 message text on standard
+ input, and send it. sendmail -t does this nicely. */
+#define RCPT500_PIPEMAILCMD "/usr/lib/sendmail -t"
+ /* where to search */
+#define RCPT500_BASE DEFAULT_BASE
+ /* attribute to use when sorting results */
+#define RCPT500_SORT_ATTR SORT_ATTR
+ /* max number of hits displayed in full before a list is presented */
+#define RCPT500_LISTLIMIT 1
+ /* enable ufn support */
+#define RCPT500_UFN
+ /* number of DN components to show in entry displays */
+#define RCPT500_RDNCOUNT DEFAULT_RDNCOUNT
+
+/*
+ * LDAPSEARCH TOOL
+ */
+ /* who to bind as */
+#define LDAPSEARCH_BINDDN NULL
+ /* search base */
+#define LDAPSEARCH_BASE DEFAULT_BASE
+
+/*
+ * LDAPMODIFY TOOL
+ */
+ /* who to bind as */
+#define LDAPMODIFY_BINDDN NULL
+ /* search base */
+#define LDAPMODIFY_BASE DEFAULT_BASE
+
+/*
+ * LDAPDELETE TOOL
+ */
+ /* who to bind as */
+#define LDAPDELETE_BINDDN NULL
+ /* search base */
+#define LDAPDELETE_BASE DEFAULT_BASE
+
+/*
+ * LDAPMODRDN TOOL
+ */
+ /* who to bind as */
+#define LDAPMODRDN_BINDDN NULL
+ /* search base */
+#define LDAPMODRDN_BASE DEFAULT_BASE
+
+/*
+ * MAIL500 MAILER DEFINITIONS
+ */
+ /* who to bind as */
+#define MAIL500_BINDDN NULL
+ /* max number of ambiguous matches reported */
+#define MAIL500_MAXAMBIGUOUS 10
+ /* max subscribers allowed (size limit when searching for them ) */
+#define MAIL500_MAXGROUPMEMBERS LDAP_NO_LIMIT
+ /* timeout for all searches */
+#define MAIL500_TIMEOUT 180
+ /* sendmail location - mail500 needs to exec this */
+#define MAIL500_SENDMAIL "/usr/lib/sendmail"
+
+/*
+ * UD DEFINITIONS
+ */
+ /* ud configuration file */
+#define UD_CONFIG_FILE "/etc/opt/SUNWconn/ldap/current/ud.conf"
+ /* default editor */
+#define UD_DEFAULT_EDITOR "/usr/ucb/vi"
+ /* default bbasename of user config file */
+#define UD_USER_CONFIG_FILE ".udrc"
+ /* default user to bind as */
+#define UD_BINDDN NULL
+ /* default password to bind with */
+#define UD_PASSWD NULL
+ /* default search base */
+#define UD_BASE DEFAULT_BASE
+ /* default base where groups are created */
+#define UD_WHERE_GROUPS_ARE_CREATED ""
+ /* default base below which all groups live */
+#define UD_WHERE_ALL_GROUPS_LIVE ""
+
+/*
+ * FAX500 DEFINITIONS
+ */
+ /* what to bind as */
+#define FAX_BINDDN NULL
+ /* how long to wait for searches */
+#define FAX_TIMEOUT 180
+ /* maximum number of ambiguous matches reported */
+#define FAX_MAXAMBIGUOUS 10
+ /* maximum number of members allowed */
+#define FAX_MAXMEMBERS LDAP_NO_LIMIT
+ /* program to send mail */
+#define FAX_SENDMAIL "/usr/lib/sendmail"
+
+/*
+ * RP500 DEFINITIONS
+ */
+ /* what to bind as */
+#define RP_BINDDN NULL
+ /* prefix to add to non-fully-qualified numbers */
+#define RP_PHONEPREFIX ""
+
+/*
+ * SLAPD DEFINITIONS
+ */
+ /* location of the default slapd config file */
+#define SLAPD_DEFAULT_CONFIGFILE "/etc/opt/SUNWconn/ldap/current/slapd.conf"
+ /* default sizelimit on number of entries from a search */
+#define SLAPD_DEFAULT_SIZELIMIT 10000
+ /* default timelimit to spend on a search */
+#define SLAPD_DEFAULT_TIMELIMIT 3600
+ /* location of the slapd pid file */
+#define SLAPD_PIDFILE "/var/opt/SUNWconn/ldap/log/slapd.pid"
+ /* location of the slapd args file */
+#define SLAPD_ARGSFILE "/var/opt/SUNWconn/ldap/log/slapd.args"
+ /* dn of the special "monitor" entry */
+#define SLAPD_MONITOR_DN "cn=monitor"
+ /* dn of the special "config" entry */
+#define SLAPD_CONFIG_DN "cn=config"
+ /* minimum max ids that a single index entry can map to in ldbm */
+#define SLAPD_LDBM_MIN_MAXIDS 4000
+
+#endif /* _CONFIG_H */
diff --git a/usr/src/lib/libldap4/include/ldif.h b/usr/src/lib/libldap4/include/ldif.h
new file mode 100644
index 0000000000..4b16486440
--- /dev/null
+++ b/usr/src/lib/libldap4/include/ldif.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1996 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#ifndef _LDIF_H
+#define _LDIF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LINE_WIDTH 76 /* maximum length of LDIF lines */
+
+/*
+ * Macro to calculate maximum number of bytes that the base64 equivalent
+ * of an item that is "vlen" bytes long will take up. Base64 encoding
+ * uses one byte for every six bits in the value plus up to two pad bytes.
+ */
+#define LDIF_BASE64_LEN(vlen) (((vlen) * 4 / 3 ) + 3)
+
+/*
+ * Macro to calculate maximum size that an LDIF-encoded type (length
+ * tlen) and value (length vlen) will take up: room for type + ":: " +
+ * first newline + base64 value + continued lines. Each continued line
+ * needs room for a newline and a leading space character.
+ */
+#define LDIF_SIZE_NEEDED(tlen,vlen) \
+ ((tlen) + 4 + LDIF_BASE64_LEN(vlen) \
+ + ((LDIF_BASE64_LEN(vlen) + tlen + 3) / LINE_WIDTH * 2 ))
+
+
+#ifdef NEEDPROTOS
+int str_parse_line( char *line, char **type, char **value, int *vlen);
+char * str_getline( char **next );
+void put_type_and_value( char **out, char *t, char *val, int vlen );
+char *ldif_type_and_value( char *type, char *val, int vlen );
+#else /* NEEDPROTOS */
+int str_parse_line();
+char * str_getline();
+void put_type_and_value();
+char *ldif_type_and_value();
+#endif /* NEEDPROTOS */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LDIF_H */
diff --git a/usr/src/lib/libldap4/include/log.h b/usr/src/lib/libldap4/include/log.h
new file mode 100644
index 0000000000..6936fd99f3
--- /dev/null
+++ b/usr/src/lib/libldap4/include/log.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _LLOG_H
+#define _LLOG_H
+
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <nl_types.h>
+#include <limits.h>
+#include <syslog.h>
+#include <portable.h>
+
+
+
+/* Log levels */
+
+/* slapd values */
+#define LDAP_DEBUG_TRACE 0x001
+#define LDAP_DEBUG_PACKETS 0x002
+#define LDAP_DEBUG_ARGS 0x004
+#define LDAP_DEBUG_CONNS 0x008
+#define LDAP_DEBUG_BER 0x010
+#define LDAP_DEBUG_FILTER 0x020
+#define LDAP_DEBUG_CONFIG 0x040
+#define LDAP_DEBUG_ACL 0x080
+#define LDAP_DEBUG_STATS 0x100
+#define LDAP_DEBUG_STATS2 0x200
+#define LDAP_DEBUG_SHELL 0x400
+#define LDAP_DEBUG_PARSE 0x800
+/* More values for http gateway */
+#define LDAP_DEBUG_GWAY 0x1000
+#define LDAP_DEBUG_GWAYMORE 0x2000
+/* Generic values */
+#define LDAP_DEBUG_ANY 0xffff
+
+nl_catd sundscat;
+extern nl_catd slapdcat;
+extern void ldaplogconfig(char * logf, int size);
+extern void ldaplogconfigf(FILE *fd);
+extern void ldaploginit(char *name,
+ int facility);
+extern void ldaploginitlevel(char *name,
+ int facility,
+ int log_level);
+extern void ldaplog(int level,char *fmt,...);
+
+#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) \
+{ \
+ if ( log_debug & level ) \
+ fprintf( stderr, fmt, connid, opid, arg1, arg2, arg3 );\
+ if ( log_syslog & level ) \
+ ldaplog( level, fmt, connid, opid, arg1, arg2, arg3 ); \
+}
+#endif /* _LLOG_H */
+
+
+
diff --git a/usr/src/lib/libldap4/include/lthread.h b/usr/src/lib/libldap4/include/lthread.h
new file mode 100644
index 0000000000..851e6f1c83
--- /dev/null
+++ b/usr/src/lib/libldap4/include/lthread.h
@@ -0,0 +1,187 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* lthread.h - ldap threads header file */
+
+#ifndef _LTHREAD_H
+#define _LTHREAD_H
+
+#if defined( THREAD_SUNOS4_LWP )
+/***********************************
+ * *
+ * thread definitions for sunos4 *
+ * *
+ ***********************************/
+
+#define _THREAD
+
+#include <lwp/lwp.h>
+#include <lwp/stackdep.h>
+
+typedef void *(*VFP)();
+
+/* thread attributes and thread type */
+typedef int pthread_attr_t;
+typedef thread_t pthread_t;
+
+/* default attr states */
+#define pthread_mutexattr_default NULL
+#define pthread_condattr_default NULL
+
+/* thread state - joinable or not */
+#define PTHREAD_CREATE_JOINABLE 0
+#define PTHREAD_CREATE_DETACHED 1
+/* thread scope - who is in scheduling pool */
+#define PTHREAD_SCOPE_PROCESS 0
+#define PTHREAD_SCOPE_SYSTEM 1
+
+/* mutex attributes and mutex type */
+typedef int pthread_mutexattr_t;
+typedef mon_t pthread_mutex_t;
+
+/* condition variable attributes and condition variable type */
+typedef int pthread_condattr_t;
+typedef struct lwpcv {
+ int lcv_created;
+ cv_t lcv_cv;
+} pthread_cond_t;
+
+/* mutex and condition variable scope - process or system */
+#define PTHREAD_SHARE_PRIVATE 0
+#define PTHREAD_SHARE_PROCESS 1
+
+#else /* end sunos4 */
+
+#if defined( THREAD_SUNOS5_LWP )
+/***********************************
+ * *
+ * thread definitions for sunos5 *
+ * *
+ ***********************************/
+
+#define _THREAD
+
+#include <thread.h>
+#include <synch.h>
+
+typedef void *(*VFP)();
+
+/* sunos5 threads are preemptive */
+#define PTHREAD_PREEMPTIVE 1
+
+#ifndef _PTHREAD_H
+
+/* thread attributes and thread type */
+typedef int pthread_attr_t;
+typedef thread_t pthread_t;
+
+/* thread state - joinable or not */
+#define PTHREAD_CREATE_JOINABLE 0
+#define PTHREAD_CREATE_DETACHED THR_DETACHED
+/* thread scope - who is in scheduling pool */
+#define PTHREAD_SCOPE_PROCESS 0
+#define PTHREAD_SCOPE_SYSTEM THR_BOUND
+
+/* mutex attributes and mutex type */
+typedef int pthread_mutexattr_t;
+typedef mutex_t pthread_mutex_t;
+
+/* condition variable attributes and condition variable type */
+typedef int pthread_condattr_t;
+typedef cond_t pthread_cond_t;
+
+#endif /* _PTHREAD_H */
+
+/* default attr states */
+#define pthread_mutexattr_default NULL
+#define pthread_condattr_default NULL
+
+/* mutex and condition variable scope - process or system */
+#define PTHREAD_SHARE_PRIVATE USYNC_THREAD
+#define PTHREAD_SHARE_PROCESS USYNC_PROCESS
+
+#else /* end sunos5 */
+
+#if defined( THREAD_MIT_PTHREADS )
+/***********************************
+ * *
+ * definitions for mit pthreads *
+ * *
+ ***********************************/
+
+#define _THREAD
+
+#include <pthread.h>
+
+#else /* end mit pthreads */
+
+#if defined( THREAD_DCE_PTHREADS )
+/***********************************
+ * *
+ * definitions for dce pthreads *
+ * *
+ ***********************************/
+
+#define _THREAD
+
+#include <pthread.h>
+
+/* dce threads are preemptive */
+#define PTHREAD_PREEMPTIVE 1
+
+#define pthread_attr_init( a ) pthread_attr_create( a )
+#define pthread_attr_destroy( a ) pthread_attr_delete( a )
+#define pthread_attr_setdetachstate( a, b ) \
+ pthread_attr_setdetach_np( a, b )
+
+#endif /* dce pthreads */
+#endif /* mit pthreads */
+#endif /* sunos5 */
+#endif /* sunos4 */
+
+#ifndef _THREAD
+
+/***********************************
+ * *
+ * thread definitions for no *
+ * underlying library support *
+ * *
+ ***********************************/
+
+typedef void *(*VFP)();
+
+/* thread attributes and thread type */
+typedef int pthread_attr_t;
+typedef int pthread_t;
+
+/* default attr states */
+#define pthread_mutexattr_default NULL
+#define pthread_condattr_default NULL
+
+/* thread state - joinable or not */
+#define PTHREAD_CREATE_JOINABLE 0
+#define PTHREAD_CREATE_DETACHED 0
+/* thread scope - who is in scheduling pool */
+#define PTHREAD_SCOPE_PROCESS 0
+#define PTHREAD_SCOPE_SYSTEM 0
+
+/* mutex attributes and mutex type */
+typedef int pthread_mutexattr_t;
+typedef int pthread_mutex_t;
+
+/* mutex and condition variable scope - process or system */
+#define PTHREAD_SHARE_PRIVATE 0
+#define PTHREAD_SHARE_PROCESS 0
+
+/* condition variable attributes and condition variable type */
+typedef int pthread_condattr_t;
+typedef int pthread_cond_t;
+
+#endif /* no threads support */
+#endif /* _LTHREAD_H */
diff --git a/usr/src/lib/libldap4/include/portable.h b/usr/src/lib/libldap4/include/portable.h
new file mode 100644
index 0000000000..7f11d7892a
--- /dev/null
+++ b/usr/src/lib/libldap4/include/portable.h
@@ -0,0 +1,224 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1994 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#ifndef _PORTABLE_H
+#define _PORTABLE_H
+
+/*
+ * portable.h for LDAP -- this is where we define common stuff to make
+ * life easier on various Unix systems.
+ *
+ * Unless you are porting LDAP to a new platform, you should not need to
+ * edit this file.
+ */
+
+
+#ifndef SYSV
+#if defined( hpux ) || defined( sunos5 ) || defined ( sgi ) || defined( SVR4 )
+#define SYSV
+#endif
+#endif
+
+
+/*
+ * under System V, use sysconf() instead of getdtablesize
+ */
+#if !defined( USE_SYSCONF ) && defined( SYSV )
+#define USE_SYSCONF
+#endif
+
+
+/*
+ * under System V, daemons should use setsid() instead of detaching from their
+ * tty themselves
+ */
+#if !defined( USE_SETSID ) && defined( SYSV )
+#define USE_SETSID
+#endif
+
+
+/*
+ * System V has socket options in filio.h
+ */
+#if !defined( NEED_FILIO ) && defined( SYSV ) && !defined( hpux )
+#define NEED_FILIO
+#endif
+
+/*
+ * use lockf() under System V
+ */
+#if !defined( USE_LOCKF ) && ( defined( SYSV ) || defined( aix ))
+#define USE_LOCKF
+#endif
+
+/*
+ * on many systems, we should use waitpid() instead of waitN()
+ */
+#if !defined( USE_WAITPID ) && ( defined( SYSV ) || defined( sunos4 ) || defined( ultrix ) || defined( aix ))
+#define USE_WAITPID
+#endif
+
+
+/*
+ * define the wait status argument type
+ */
+#if ( defined( SunOS ) && SunOS < 40 ) || defined( nextstep )
+#define WAITSTATUSTYPE union wait
+#else
+#define WAITSTATUSTYPE int
+#endif
+
+/*
+ * define the flags for wait
+ */
+#ifdef sunos5
+#define WAIT_FLAGS ( WNOHANG | WUNTRACED | WCONTINUED )
+#else
+#define WAIT_FLAGS ( WNOHANG | WUNTRACED )
+#endif
+
+
+/*
+ * defined the options for openlog (syslog)
+ */
+#ifdef ultrix
+#define OPENLOG_OPTIONS LOG_PID
+#else
+#define OPENLOG_OPTIONS ( LOG_PID | LOG_NOWAIT )
+#endif
+
+
+/*
+ * some systems don't have the BSD re_comp and re_exec routines
+ */
+#ifndef NEED_BSDREGEX
+#if defined( SYSV ) || defined( VMS ) || defined( netbsd ) || defined( freebsd ) || defined( linux )
+#define NEED_BSDREGEX
+#endif
+#endif
+
+/*
+ * many systems do not have the setpwfile() library routine... we just
+ * enable use for those systems we know have it.
+ */
+#ifndef HAVE_SETPWFILE
+#if defined( sunos4 ) || defined( ultrix ) || defined( __osf__ )
+#define HAVE_SETPWFILE
+#endif
+#endif
+
+/*
+ * Are sys_errlist and sys_nerr declared in stdio.h?
+ */
+#ifndef SYSERRLIST_IN_STDIO
+#if defined( freebsd )
+#define SYSERRLIST_IN_STDIO
+#endif
+#endif
+
+/*
+ * for select()
+ */
+#if !defined(FD_SET) && !defined(WINSOCK)
+#define NFDBITS 32
+#define FD_SETSIZE 32
+#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
+#endif /* FD_SET */
+
+#if defined( hpux ) && defined( __STDC__ )
+/*
+ * Under HP/UX, select seems to want (int *) instead of fd_set. Non-ANSI
+ * compilers don't like recursive macros, so ignore the problem if __STDC__
+ * is not defined.
+ */
+#define select(a,b,c,d,e) select(a, (int *)b, (int *)c, (int *)d, e)
+#endif /* hpux && __STDC__ */
+
+
+/*
+ * for signal() -- what do signal handling functions return?
+ */
+#ifndef SIG_FN
+#ifdef sunos5
+# define SIG_FN void /* signal-catching functions return void */
+#else /* sunos5 */
+# ifdef BSD
+# if (BSD >= 199006) || defined(NeXT) || defined(__osf__) || defined(sun) || defined(ultrix) || defined(apollo) || defined(POSIX_SIGNALS)
+# define SIG_FN void /* signal-catching functions return void */
+# else
+# define SIG_FN int /* signal-catching functions return int */
+# endif
+# else /* BSD */
+# define SIG_FN void /* signal-catching functions return void */
+# endif /* BSD */
+#endif /* sunos5 */
+#endif /* SIG_FN */
+
+/*
+ * call signal or sigset (signal does not block the signal while
+ * in the handler on sys v and sigset does not exist on bsd)
+ */
+#ifdef SYSV
+#define SIGNAL sigset
+#else
+#define SIGNAL signal
+#endif
+
+/*
+ * toupper and tolower macros are different under bsd and sys v
+ */
+#if defined( SYSV ) && !defined( hpux )
+#define TOUPPER(c) (isascii(c) && islower(c) ? _toupper(c) : c)
+#define TOLOWER(c) (isascii(c) && isupper(c) ? _tolower(c) : c)
+#else
+#define TOUPPER(c) (isascii(c) && islower(c) ? toupper(c) : c)
+#define TOLOWER(c) (isascii(c) && isupper(c) ? tolower(c) : c)
+#endif
+
+/*
+ * put a cover on the tty-related ioctl calls we need to use
+ */
+#if defined( NeXT ) || (defined(SunOS) && SunOS < 40)
+#define TERMIO_TYPE struct sgttyb
+#define TERMFLAG_TYPE int
+#define GETATTR( fd, tiop ) ioctl((fd), TIOCGETP, (caddr_t)(tiop))
+#define SETATTR( fd, tiop ) ioctl((fd), TIOCSETP, (caddr_t)(tiop))
+#define GETFLAGS( tio ) (tio).sg_flags
+#define SETFLAGS( tio, flags ) (tio).sg_flags = (flags)
+#else
+#define USE_TERMIOS
+#define TERMIO_TYPE struct termios
+#define TERMFLAG_TYPE tcflag_t
+#define GETATTR( fd, tiop ) tcgetattr((fd), (tiop))
+#define SETATTR( fd, tiop ) tcsetattr((fd), TCSANOW /* 0 */, (tiop))
+#define GETFLAGS( tio ) (tio).c_lflag
+#define SETFLAGS( tio, flags ) (tio).c_lflag = (flags)
+#endif
+
+
+#if defined( ultrix ) || defined( nextstep )
+extern char *strdup();
+#endif /* ultrix || nextstep */
+
+#endif /* _PORTABLE_H */
diff --git a/usr/src/lib/libldap4/include/regex.h b/usr/src/lib/libldap4/include/regex.h
new file mode 100644
index 0000000000..ff6ff2b9ce
--- /dev/null
+++ b/usr/src/lib/libldap4/include/regex.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if defined( MACOS ) || defined( DOS ) || defined( _WIN32 ) || defined( NEED_BSDREGEX )
+/*
+ * Copyright (c) 1993 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/*
+ * regex.h -- includes for regular expression matching routines
+ * 13 August 1993 Mark C Smith
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined( NEEDPROTOS ) && defined( __STDC__ )
+#define NEEDPROTOS
+#endif
+
+#ifdef NEEDPROTOS
+char *re_comp( char *pat );
+int re_exec( char *lp );
+void re_modw( char *s );
+int re_subs( char *src, char *dst );
+#else /* NEEDPROTOS */
+char *re_comp();
+int re_exec();
+void re_modw();
+int re_subs();
+#endif /* NEEDPROTOS */
+
+#define re_fail( m, p )
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* MACOS or DOS or NEED_BSDREGEX */
diff --git a/usr/src/lib/libldap4/include/sec.h b/usr/src/lib/libldap4/include/sec.h
new file mode 100644
index 0000000000..cabf2bfff5
--- /dev/null
+++ b/usr/src/lib/libldap4/include/sec.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _SEC_H_
+#define _SEC_H_
+
+#include <sys/types.h>
+#include <md5.h>
+
+void hmac_md5(unsigned char *text, int text_len, unsigned char *key,
+ int key_len, unsigned char *digest);
+
+char *hexa_print(unsigned char *aString, int aLen);
+char *hexa2str(char *anHexaStr, int *aResLen);
+
+#endif /* _SEC_H_ */
diff --git a/usr/src/lib/libldap4/include/ssl.h b/usr/src/lib/libldap4/include/ssl.h
new file mode 100644
index 0000000000..aa4edcaf2d
--- /dev/null
+++ b/usr/src/lib/libldap4/include/ssl.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * This is a dummy header file for SSL
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _SSL_H
+#define _SSL_H
+
+#include <sys/types.h>
+
+typedef void * SSL;
+
+SSL SSL_new();
+int SSL_connect(SSL s, int filedes);
+int SSL_accept(SSL s, int filedes);
+int SSL_read(SSL s, u_char *buf, u_int len);
+int SSL_write(SSL s, u_char *buf, u_int len);
+int SSL_fread(SSL s, u_char *buf, u_int len);
+int SSL_fwrite(SSL s, u_char *buf, u_int len);
+int SSL_flush(SSL s);
+int SSL_close(SSL s);
+int SSL_delete(SSL s);
+char **SSL_get_supported_ciphers();
+int SSL_get_cipher(SSL s, char **cipher);
+int SSL_set_cipher(SSL s, char **cipher);
+int SSL_set_verification(SSL s, char **root_ca_list, int *certificate_type_list);
+int SSL_set_userid(SSL s, char *name, char *id);
+int SSL_save_session(SSL s, u_char **id, int *len);
+int SSL_set_session(SSL s, u_char *id, int len);
+int SSL_delete_session(u_char *id, int len);
+int SSL_errno(SSL s);
+char *SSL_strerr(int err);
+int SSL_get_fd(SSL s);
+
+#endif _SSL_H
diff --git a/usr/src/lib/libldap4/include/sysexits-compat.h b/usr/src/lib/libldap4/include/sysexits-compat.h
new file mode 100644
index 0000000000..18b11bdca1
--- /dev/null
+++ b/usr/src/lib/libldap4/include/sysexits-compat.h
@@ -0,0 +1,111 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)sysexits.h 4.5 (Berkeley) 7/6/88
+ */
+
+/*
+** SYSEXITS.H -- Exit status codes for system programs.
+**
+** This include file attempts to categorize possible error
+** exit statuses for system programs, notably delivermail
+** and the Berkeley network.
+**
+** Error numbers begin at EX__BASE to reduce the possibility of
+** clashing with other exit statuses that random programs may
+** already return. The meaning of the codes is approximately
+** as follows:
+**
+** EX_USAGE -- The command was used incorrectly, e.g., with
+** the wrong number of arguments, a bad flag, a bad
+** syntax in a parameter, or whatever.
+** EX_DATAERR -- The input data was incorrect in some way.
+** This should only be used for user's data & not
+** system files.
+** EX_NOINPUT -- An input file (not a system file) did not
+** exist or was not readable. This could also include
+** errors like "No message" to a mailer (if it cared
+** to catch it).
+** EX_NOUSER -- The user specified did not exist. This might
+** be used for mail addresses or remote logins.
+** EX_NOHOST -- The host specified did not exist. This is used
+** in mail addresses or network requests.
+** EX_UNAVAILABLE -- A service is unavailable. This can occur
+** if a support program or file does not exist. This
+** can also be used as a catchall message when something
+** you wanted to do doesn't work, but you don't know
+** why.
+** EX_SOFTWARE -- An internal software error has been detected.
+** This should be limited to non-operating system related
+** errors as possible.
+** EX_OSERR -- An operating system error has been detected.
+** This is intended to be used for such things as "cannot
+** fork", "cannot create pipe", or the like. It includes
+** things like getuid returning a user that does not
+** exist in the passwd file.
+** EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
+** etc.) does not exist, cannot be opened, or has some
+** sort of error (e.g., syntax error).
+** EX_CANTCREAT -- A (user specified) output file cannot be
+** created.
+** EX_IOERR -- An error occurred while doing I/O on some file.
+** EX_TEMPFAIL -- temporary failure, indicating something that
+** is not really an error. In sendmail, this means
+** that a mailer (e.g.) could not create a connection,
+** and the request should be reattempted later.
+** EX_PROTOCOL -- the remote system returned something that
+** was "not possible" during a protocol exchange.
+** EX_NOPERM -- You did not have sufficient permission to
+** perform the operation. This is not intended for
+** file system problems, which should use NOINPUT or
+** CANTCREAT, but rather for higher level permissions.
+** For example, kre uses this to restrict who students
+** can send mail to.
+**
+** Maintained by Eric Allman (eric@berkeley, ucbvax!eric) --
+** please mail changes to me.
+**
+** @(#)sysexits.h 4.5 7/6/88
+*/
+
+# define EX_OK 0 /* successful termination */
+
+# define EX__BASE 64 /* base value for error messages */
+
+# define EX_USAGE 64 /* command line usage error */
+# define EX_DATAERR 65 /* data format error */
+# define EX_NOINPUT 66 /* cannot open input */
+# define EX_NOUSER 67 /* addressee unknown */
+# define EX_NOHOST 68 /* host name unknown */
+# define EX_UNAVAILABLE 69 /* service unavailable */
+# define EX_SOFTWARE 70 /* internal software error */
+# define EX_OSERR 71 /* system error (e.g., can't fork) */
+# define EX_OSFILE 72 /* critical OS file missing */
+# define EX_CANTCREAT 73 /* can't create (user) output file */
+# define EX_IOERR 74 /* input/output error */
+# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
+# define EX_PROTOCOL 76 /* remote error in protocol */
+# define EX_NOPERM 77 /* permission denied */
+# define EX_CONFIG 78 /* configuration error */
diff --git a/usr/src/lib/libldap4/include/thq.h b/usr/src/lib/libldap4/include/thq.h
new file mode 100644
index 0000000000..31822c417c
--- /dev/null
+++ b/usr/src/lib/libldap4/include/thq.h
@@ -0,0 +1,75 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <pthread.h>
+
+typedef void * (*PFP)(void *);
+
+typedef void * (*PFP2)(void *, void *);
+
+typedef struct tq_listS {
+ void * arg;
+ struct tq_listS * next;
+} tq_listT, * tq_listTp;
+
+typedef struct {
+ tq_listTp first; /* first element in the queue */
+ tq_listTp last; /* last element in the queue */
+ pthread_mutex_t lock; /* queue mutex */
+ pthread_cond_t cond; /* queue condition to signal new elements */
+ int * shutdown; /* variable to test to see shutdown condition*/
+ int shutalloc; /* is the shutdown variable allocated locally*/
+ int stopping; /* queue is currently stopping */
+ int queue_size; /* current size of the queue */
+ int nb_thr; /* current nb of threads pocessing the queue */
+ int thr_waiting; /* current nb of threads waiting */
+ int max_thr; /* max allowed threads to process the queue */
+ int min_thr; /* min nb of threads to keep alive */
+ PFP doit; /* function to call to process the queue */
+ PFP2 endit; /* function called before to end the thread */
+ void * arg; /* argument to pass to the doit/endit func. */
+ pthread_t * tids; /* array of thread ids for watchdog */
+} tqT, * tqTp;
+
+extern tqTp tq_alloc(PFP process_func, /* function to process the queue */
+ PFP2 shutdown_func, /* function called before to end */
+ void * func_arg, /* arg passed to both functions */
+ int * shutdown, /* shutdown variable to test */
+ int max, /* max allowed threads */
+ int min); /* min allowed threads */
+
+extern int tq_queue(tqTp queue, /* pointer to the queue */
+ void * arg); /* element to be queued */
+
+/* tq_dequeue returns the first "arg" passed to tq_queue */
+extern void * tq_dequeue(tqTp queue, /* pointer to the queue */
+ void * endit_arg); /* pointer to "shutdown" arguments */
+/*
+ * tq_end_thread terminates the current
+ * thread and restarts a new one if necessary
+ */
+extern void tq_end_thread (tqTp queue, /* pointer to the queue */
+ void * endit_arg); /* pointer to "shutdown" arguments */
+
+/*
+ * tq_shutdown, shutdown the queue (alternate way to shutdown if you don't
+ * have a global shutdown integer
+ *
+ * shutdown can be immediate (1) or delayed until there is nothing more
+ * in the queue (immadiate = 0)
+ *
+ * when you call this function, no more argument can be queued using
+ * tq_queue.
+ *
+ * when tq_dequeue returns, the queue pointer is not allocated anymore
+ *
+ */
+extern void tq_shutdown(tqTp queue, /* pointer to the queue */
+ int immediate); /* 1: don't wait, 0: wait for queue */
+ /* to be empty */
diff --git a/usr/src/lib/libldap4/misc/ldapfilter.conf b/usr/src/lib/libldap4/misc/ldapfilter.conf
new file mode 100644
index 0000000000..5daa86d232
--- /dev/null
+++ b/usr/src/lib/libldap4/misc/ldapfilter.conf
@@ -0,0 +1,111 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+ *
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+# ldap filter file
+#
+# lines like this that start with # or empty lines are ignored
+#
+# syntax:
+#
+# <tag>
+# <pattern1> <delimiters> <filter1-1> <desc1-1> [<scope>]
+# <filter1-2> <desc1-2> [<scope>]
+#
+# <pattern2> <delimiters> <filter2-1> <desc2-1> [<scope>] ...
+#
+# The "desc" should describe the filter and it should correctly complete
+# both of the following phrases:
+#
+# One <desc> match was found for...
+# Three <desc> matches were found for...
+#
+# The scope is optional, and should be one of:
+# "base"
+# "onelevel"
+# "subtree"
+# if it is included.
+#
+
+"finger and ud and go500 and go500gw subtree and web500gw subtree and rp500 and rcpt500 and ufn last"
+ "=" " " "%v" "arbitrary filter"
+
+ "^[0-9][0-9-]*$" " " "(telephoneNumber=*%v)" "phone number"
+
+ "@" " " "(mail=%v)" "email address"
+ "(mail=%v*)" "start of email address"
+
+ "^.[. _].*" ". _" "(cn=%v1* %v2-)" "first initial"
+
+ ".*[. _].$" ". _" "(cn=%v1-*)" "last initial"
+
+ "[. _]" ". _" "(|(sn=%v1-)(cn=%v1-))" "exact"
+ "(|(sn~=%v1-)(cn~=%v1-))" "approximate"
+
+ ".*" ". " "(|(cn=%v1)(sn=%v1)(uid=%v1))" "exact"
+ "(|(cn~=%v1)(sn~=%v1))" "approximate"
+
+"go500gw onelevel and web500gw onelevel and ufn first and ufn intermediate"
+ "=" " " "%v" "arbitrary filter"
+
+ "^..$" " " "(|(o=%v)(c=%v)(l=%v)(co=%v))" "exact"
+ "(|(o~=%v)(c~=%v)(l~=%v)(co~=%v))" "approximate"
+
+ " " " " "(|(o=%v)(l=%v)(co=%v)(ou=%v))" "exact"
+ "(|(o~=%v)(l~=%v)(co~=%v)(ou~=%v))" "approximate"
+
+ "\." " " "(associatedDomain=%v)" "exact"
+
+ ".*" " " "(|(o=%v)(l=%v)(co=%v)(ou=%v))" "exact"
+ "(|(o~=%v)(l~=%v)(co~=%v)(ou~=%v))" "approximate"
+
+
+#
+# xax500
+#
+
+"xax500"
+ "=" " " "(%v)" "arbitrary filter"
+
+ "^[0-9][0-9-]*$" " " "(telephoneNumber=*%v)" "phone number"
+
+ "@" " " "(mail=%v)" "email address"
+ "(mail=%v*)" "start of email address"
+
+ "^.[. _].*" ". _" "(cn=%v1* %v2-)" "first initial"
+
+ ".*[. _].$" ". _" "(cn=%v1-*)" "last initial"
+
+ "[. _]" ". _" "(|(sn=%v1-)(cn=%v1-))" "exact"
+ "(|(sn~=%v1-)(cn~=%v1-))" "approximate"
+
+ ".*" ". " "(|(cn=%v1)(sn=%v1)(uid=%v1))" "exact"
+ "(|(cn=%v1)(sn~=%v1))" "approximate"
+
+
+"xax500-auth"
+ "=" " " "(%v)" "arbitrary filter"
+
+ "^[0-9][0-9-]*$" " " "(telephoneNumber=*%v)" "phone number"
+
+ "@" " " "(mail=%v)" "email address"
+ "(mail=%v*)" "start of email address"
+
+ "^.[. _].*" ". _" "(cn=%v1* %v2-)" "first initial"
+
+ ".*[. _].$" ". _" "(cn=%v1-*)" "last initial"
+
+ "[. _]" ". _" "(|(sn=%v1-)(cn=%v1-))" "exact"
+ "(|(sn~=%v1-)(cn~=%v1-))" "approximate"
+
+ ".*" ". " "(|(cn=%v1)(sn=%v1)(uid=%v1))" "exact"
+ "(|(cn=%v1)(sn~=%v1))" "approximate"
+
+"list500"
+ "[. _]" ". _" "(|(sn=%v1-)(cn=%v1-))" "exact"
+ "(|(sn~=%v1-)(cn~=%v1-))" "approximate"
+
+ ".*" ". " "(|(cn=%v1)(sn=%v1)(uid=%v1))" "exact"
+ "(|(cn~=%v1)(sn~=%v1))" "approximate"
diff --git a/usr/src/lib/libldap4/misc/ldapfriendly b/usr/src/lib/libldap4/misc/ldapfriendly
new file mode 100644
index 0000000000..40e9ed5481
--- /dev/null
+++ b/usr/src/lib/libldap4/misc/ldapfriendly
@@ -0,0 +1,248 @@
+#
+#
+# Portions Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+#
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+AD Andorra
+AE United Arab Emirates
+AF Afghanistan
+AG Antigua and Barbuda
+AI Anguilla
+AL Albania
+AM Armenia
+AN Netherlands Antilles
+AO Angola
+AQ Antarctica
+AR Argentina
+AS American Samoa
+AT Austria
+AU Australia
+AW Aruba
+AZ Azerbaijan
+BA Bosnia and Herzegowina
+BB Barbados
+BD Bangladesh
+BE Belgium
+BF Burkina Faso
+BG Bulgaria
+BH Bahrain
+BI Burundi
+BJ Benin
+BM Bermuda
+BN Brunei Darussalam
+BO Bolivia
+BR Brazil
+BS Bahamas
+BT Bhutan
+BV Bouvet Island
+BW Botswana
+BY Belarus
+BZ Belize
+CA Canada
+CC Cocos (Keeling) Islands
+CF Central African Republic
+CG Congo
+CH Switzerland
+CI Cote d'Ivoire
+CK Cook Islands
+CL Chile
+CM Cameroon
+CN China
+CO Colombia
+CR Costa Rica
+CS Former Czechoslovakia
+CU Cuba
+CV Cape Verde
+CX Christmas Island
+CY Cyprus
+CZ Czech Republic
+DE Germany
+DJ Djibouti
+DK Denmark
+DM Dominica
+DO Dominican Republic
+DZ Algeria
+EC Ecuador
+EE Estonia
+EG Egypt
+EH Western Sahara
+ER Eritrea
+ES Spain
+ET Ethiopia
+FI Finland
+FJ Fiji
+FK Falkland Islands (Malvinas)
+FM Micronesia
+FO Faroe Islands
+FR France
+FX France, Metropolitan
+GA Gabon
+GB United Kingdom
+GD Grenada
+GE Georgia
+GF French Guiana
+GH Ghana
+GI Gibraltar
+GL Greenland
+GM Gambia
+GN Guinea
+GP Guadeloupe
+GQ Equatorial Guinea
+GR Greece
+GS South Georgia and the South Sandwich Islands
+GT Guatemala
+GU Guam
+GW Guinea-Bissau
+GY Guyana
+HK Hong Kong
+HM Heard and McDonald Islands
+HN Honduras
+HR Croatia
+HT Haiti
+HU Hungary
+ID Indonesia
+IE Ireland
+IL Israel
+IN India
+IO British Indian Ocean Territory
+IQ Iraq
+IR Iran
+IS Iceland
+IT Italy
+JM Jamaica
+JO Jordan
+JP Japan
+KE Kenya
+KG Kyrgyzstan
+KH Cambodia
+KI Kiribati
+KM Comoros
+KN Saint Kitts and Nevis
+KP Korea, Democratic People's Republic of
+KR Korea, Republic of
+KW Kuwait
+KY Cayman Islands
+KZ Kazakhstan
+LA Laos
+LB Lebanon
+LC Saint Lucia
+LI Liechtenstein
+LK Sri Lanka
+LR Liberia
+LS Lesotho
+LT Lithuania
+LU Luxembourg
+LV Latvia
+LY Libya
+MA Morocco
+MC Monaco
+MD Moldova
+MG Madagascar
+MH Marshall Islands
+MK Macedonia
+ML Mali
+MM Myanmar
+MN Mongolia
+MO Macau
+MP Northern Mariana Islands
+MQ Martinique
+MR Mauritania
+MS Montserrat
+MT Malta
+MU Mauritius
+MV Maldives
+MW Malawi
+MX Mexico
+MY Malaysia
+MZ Mozambique
+NA Namibia
+NC New Caledonia
+NE Niger
+NF Norfolk Island
+NG Nigeria
+NI Nicaragua
+NL Netherlands
+NO Norway
+NP Nepal
+NR Nauru
+NU Niue
+NZ New Zealand
+OM Oman
+PA Panama
+PE Peru
+PF French Polynesia
+PG Papua New Guinea
+PH Philippines
+PK Pakistan
+PL Poland
+PM St. Pierre and Miquelon
+PN Pitcairn
+PR Puerto Rico
+PT Portugal
+PW Palau
+PY Paraguay
+QA Qatar
+RE Reunion
+RO Romania
+RU Russian Federation
+RW Rwanda
+SA Saudi Arabia
+SB Solomon Islands
+SC Seychelles
+SD Sudan
+SE Sweden
+SG Singapore
+SH St. Helena
+SI Slovenia
+SJ Svalbard and Jan Mayen Islands
+SK Slovakia (Slovak Republic)
+SL Sierra Leone
+SM San Marino
+SN Senegal
+SO Somalia
+SR Suriname
+ST Sao Tome and Principe
+SU Former Soviet Union
+SV El Salvador
+SY Syria
+SZ Swaziland
+TC Turks and Caicos Islands
+TD Chad
+TF French Southern Territories
+TG Togo
+TH Thailand
+TJ Tajikistan
+TK Tokelau
+TM Turkmenistan
+TN Tunisia
+TO Tonga
+TP East Timor
+TR Turkey
+TT Trinidad and Tobago
+TV Tuvalu
+TW Taiwan
+TZ Tanzania
+UA Ukraine
+UG Uganda
+UK United Kingdom
+UM United States Minor Outlying Islands
+US United States of America
+UY Uruguay
+UZ Uzbekistan
+VA Vatican City State (Holy See)
+VC Saint Vincent and the Grenadines
+VE Venezuela
+VG Virgin Islands (British)
+VI Virgin Islands (U.S.)
+VN Viet Nam
+VU Vanuatu
+WF Wallis and Futuna Islands
+WS Samoa
+YE Yemen
+YT Mayotte
+YU Yugoslavia
+ZA South Africa
+ZM Zambia
+ZR Zaire
+ZW Zimbabwe
diff --git a/usr/src/lib/libldap4/misc/ldapsearchprefs.conf b/usr/src/lib/libldap4/misc/ldapsearchprefs.conf
new file mode 100644
index 0000000000..2aca07183e
--- /dev/null
+++ b/usr/src/lib/libldap4/misc/ldapsearchprefs.conf
@@ -0,0 +1,159 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+ *
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+# Version should be 1 now
+Version 1
+#
+#
+# Name for this search object
+People
+# options (the only one supported right now is "internal" which means that
+# this search object should not be presented directly to the user)
+# use "" for none
+""
+# Label to place before text box user types in
+"Search For:"
+# Filter prefix to append to all "More Choices" searches
+"(&(objectClass=person)"
+# Tag to use for "Fewer Choices" searches - from ldapfilter.conf file
+"xax500"
+# If a search results in > 1 match, retrieve this attribute to help
+# user disambiguate the entries...
+title
+# ...and label it with this string:
+"Title"
+# Search scope to use when searching
+subtree
+# Follows a list of "More Choices" search options. Format is:
+# Label, attribute, select-bitmap, extra attr display name, extra attr ldap name
+# If last two are null, "Fewer Choices" name/attributes used
+"Common Name" cn 11111 "" ""
+"Surname" sn 11111 "" ""
+"Business Phone" "telephoneNumber" 11101 "" ""
+"E-Mail Address" "mail" 11111 "" ""
+"Uniqname" "uid" 11111 "" ""
+"Title" title 11111 "" ""
+END
+# Match types
+"exactly matches" "(%a=%v))"
+"approximately matches" "(%a~=%v))"
+"starts with" "(%a=%v*))"
+"ends with" "(%a=*%v))"
+"contains" "(%a=*%v*))"
+END
+#
+#
+#
+Groups
+""
+"Search For:"
+"(&(objectClass=rfc822MailGroup)"
+"xax500"
+multilineDescription
+"Description"
+subtree
+"Common Name" cn 11111 "" ""
+"Description" multilineDescription 11101 "" ""
+"Owner" "owner" 00001 "owner" "Owner"
+"X.500 Member" "member" 00001 "" ""
+"E-Mail Member" "mail" 00101 "" ""
+END
+"exactly matches" "(%a=%v))"
+"approximately matches" "(%a~=%v))"
+"starts with" "(%a=%v*))"
+"ends with" "(%a=*%v))"
+"contains" "(%a=*%v*))"
+END
+#
+#
+#
+"Joinable Groups"
+""
+"Search For:"
+"(&(&(objectClass=rfc822MailGroup)(joinable=TRUE))"
+"xax500"
+multilineDescription
+"Description"
+subtree
+"Common Name" cn 11111 "" ""
+"Description" multilineDescription 11101 "" ""
+"Owner" "owner" 00001 "owner" "Owner"
+"X.500 Member" "member" 00001 "" ""
+"E-Mail Member" "mail" 00101 "" ""
+END
+"exactly matches" "(%a=%v))"
+"approximately matches" "(%a~=%v))"
+"starts with" "(%a=%v*))"
+"ends with" "(%a=*%v))"
+"contains" "(%a=*%v*))"
+END
+#
+#
+#
+Services
+""
+"Search For:"
+"(&(objectClass=service)"
+"xax500"
+multilineDescription
+"Description"
+subtree
+"Common Name" cn 11111 "" ""
+"Description" multilineDescription 11101 "" ""
+"Owner" "owner" 00001 "owner" "Owner"
+"Keywords" "keywords" 11111 "" ""
+"Hours" "hoursOfOperation" 11111 "" ""
+END
+"exactly matches" "(%a=%v))"
+"approximately matches" "(%a~=%v))"
+"starts with" "(%a=%v*))"
+"ends with" "(%a=*%v))"
+"contains" "(%a=*%v*))"
+END
+#
+#
+#
+Organizations
+""
+"Search For:"
+"(&(objectClass=organization)"
+"xax500"
+multilineDescription
+"Description"
+subtree
+"Name" organizationName 01111 "" ""
+"Location" localityName 11111 "" ""
+"Phone Number" "telephoneNumber" 10111 "" ""
+"Description" description 10111 "" ""
+END
+"exactly matches" "(%a=%v))"
+"approximately matches" "(%a~=%v))"
+"starts with" "(%a=%v*))"
+"ends with" "(%a=*%v))"
+"contains" "(%a=*%v*))"
+END
+#
+#
+#
+Documents
+""
+"Search For:"
+"(&(objectClass=document)"
+"xax500"
+multilineDescription
+"Description"
+subtree
+"Document Title" cn 11111 "" ""
+"Keyword" "keywords" 11111 "" ""
+"Category" "category" 11111 "" ""
+"Document Number" "documentIdentifier" 11111 "" ""
+END
+"exactly matches" "(%a=%v))"
+"approximately matches" "(%a~=%v))"
+"starts with" "(%a=%v*))"
+"ends with" "(%a=*%v))"
+"contains" "(%a=*%v*))"
+END
diff --git a/usr/src/lib/libldap4/misc/ldaptemplates.conf b/usr/src/lib/libldap4/misc/ldaptemplates.conf
new file mode 100644
index 0000000000..55400b96ff
--- /dev/null
+++ b/usr/src/lib/libldap4/misc/ldaptemplates.conf
@@ -0,0 +1,683 @@
+/*
+ *
+ * Portions Copyright %G% Sun Microsystems, Inc. All Rights Reserved
+ *
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+##########################################################################
+# LDAP display templates
+##########################################################################
+
+#
+# Version must be 1
+#
+Version 1
+
+##########################################################################
+# U-M Person template
+##########################################################################
+#
+# template name and plural name come first
+"U-M Person"
+"U-M People"
+
+# name of the icon that is associated with this template
+"person icon"
+
+# blank-separated list of template options ("" for none)
+# addable - end-user should be allowed to add these types of entries
+# modrdn - end-user can change the name of these entries
+# altview - this template is referred to in another template's
+# "linkact" item
+"addable"
+
+#
+# objectclass list
+umichPerson person
+END
+
+#
+# name of attribute to authenticate as ("" means auth as this entry)
+""
+
+#
+# default attribute name to use when forming RDN of a new entry
+#
+cn
+
+#
+# default location when adding new entries (DN; "" means no default)
+"o=University of Michigan, c=US"
+
+#
+# rules used to define default values for new entries
+END
+
+#
+#
+# list of items for display
+# each line is either:
+# item (type) (attribute) (attr name) (extra args...)
+# to define an item or
+# samerow
+# to keep the next item on the same row as the previous
+#
+# valid types are:
+# cis - case ignore string
+# mls - multiline string
+# dn -
+# mail - case ignore string that contains an RFC822 mail address
+# bool - boolean value
+# jpeg - inlined JPEG image
+# jpegbtn - JPEG image button
+# fax - inlined Fax image
+# faxbtn - Fax image button
+# audiobtn - audio button
+# time - time value
+# date - time value displayed as a date only
+# url - labeled URL for links to items in WWW
+# searchact - search action
+# linkact - link to another template
+#
+# valid options (comma separated list appended to the type) are:
+# ro - attribute is read only; don't let user edit it
+# sort - order the values of this attribute
+# 1val - disallow entry of multiple values
+# required - this attribute should have at least one value
+# hide - don't show this item if attribute has no values
+# hideiffalse - hide item if value is FALSE (for type 'bool' only)
+#
+item jpegbtn "View Photo" jpegPhoto "Next Photo"
+item audiobtn "Play Sound" audio
+item cis,ro,sort "Also Known As" cn
+item mail "E-Mail Address" mail
+item cis "Work Phone" telephoneNumber
+item cis "Fax Number" facsimileTelephoneNumber
+item cis "Pager Number" pager
+item mls "Work Address" postalAddress
+item cis,sort "Title" title
+item cis,ro "Uniqname" uid
+item mls "Description" multiLineDescription
+item cis "Home Phone" homePhone
+item mls "Home Address" homePostalAddress
+item url "More Info (URL)" labeledURL
+item dn,sort "See Also" seeAlso
+item cis "Favorite Beverage" drink
+item cis "Notice" notice
+item bool,hideiffalse "On Vacation" onVacation
+item mls,1val "Vacation Message" vacationMessage
+item bool,hideiffalse "Do Not Allow Updates" noBatchUpdates
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+item searchact "Find Groups Added To" "" "-dnt" "(&(objectclass=rfc822mailgroup)(member=%v))" "multiLineDescription" "Description" ""
+item searchact "List Owned Groups" "" "-dnt" "(&(objectclass=rfc822mailgroup)(owner=%v))" "title" "Title" ""
+item linkact "Other Addresses" "" "other addresses"
+END
+
+
+##########################################################################
+# Person template
+##########################################################################
+"Person"
+"People"
+"person icon"
+
+# template options
+addable
+#
+# objectclass list
+person
+END
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+#
+cn
+
+# default location when adding new entries
+""
+
+#
+# rules used to define default values for new entries
+END
+
+#
+# list of items for display
+item jpegbtn "View Photo" jpegPhoto "Next Photo"
+item audiobtn "Play Sound" audio
+item cis,sort "Also Known As" cn
+item cis,sort "Title" title
+item mls "Work Address" postalAddress
+item cis "Work Phone" telephoneNumber
+item cis "Fax Number" facsimileTelephoneNumber
+item cis "Pager Number" pager
+item mls "Home Address" homePostalAddress
+item cis "Home Phone" homePhone
+item cis "User ID" uid
+item mail "E-Mail Address" mail
+item cis "Description" description
+item cis "Favorite Beverage" drink
+item dn,sort "See Also" seeAlso
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+END
+
+
+##########################################################################
+# Group template
+##########################################################################
+"Group"
+"Groups"
+"group icon"
+
+# template options
+addable modrdn
+
+# objectclass list
+rfc822MailGroup
+END
+
+# name of attribute to authenticate as
+"owner"
+
+# default attribute name to use when forming RDN of a new entry
+#
+cn
+
+# default location when adding new entries
+"ou=User Groups, ou=Groups, o=University of Michigan, c=US"
+
+#
+# rules used to define default values for new entries
+constant "associatedDomain" "umich.edu"
+constant "joinable" "FALSE"
+addersdn "owner"
+addersdn "member"
+addersdn "errorsTo"
+addersdn "requestsTo"
+END
+
+#
+#
+# list of items for display
+# each line is either:
+# item (type) (attribute) (attr name) (extra args...)
+# to define an item or
+# samerow
+#
+# list of items for display
+item cis,sort "Also Known As" cn
+item mls "Description" multiLineDescription
+item cis "Phone Number" telephoneNumber
+item cis "Fax Number" facsimileTelephoneNumber
+item mls "Address" postalAddress
+item dn,required,sort "Owner" owner
+item url "More Info (URL)" labeledURL
+item dn,sort "See Also" seeAlso
+item dn,sort "Errors To" errorsTo
+item dn,sort "Requests To" requestsTo
+item cis "Associated Domain" associatedDomain
+item cis "Moderator" moderator
+item bool "Suppress 'No E-Mail Address' Errors" suppressNoEmailError
+item bool "Others May Join" joinable
+item dn,sort "X.500 Members" member
+item mail,sort "E-Mail Errors To" rfc822ErrorsTo
+item mail,sort "E-Mail Requests To" rfc822RequestsTo
+item mail,sort "E-Mail Members" mail
+item cis "Notice" notice
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+item searchact "Subscribers" "" "-dnt" "memberOfGroup=%v" "title" "Title" "joinable"
+item verifyact "Verify Members" "member" "mail" "E-Mail Address"
+END
+
+##########################################################################
+# Organization template
+##########################################################################
+"Organization"
+"Organizations"
+"organization icon"
+
+# template options
+""
+
+# objectclass list
+organization
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+o
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+constant "o" "foo"
+END
+
+#
+#
+# list of items for display
+# each line is either:
+# item (type) (attribute) (attr name) (extra args...)
+# to define an item or
+# samerow
+#
+# list of items for display
+item cis,sort "Name" o
+item cis "Location" l
+item mls "Address" postalAddress
+item cis "Phone Number" telephoneNumber
+item cis "Fax Number" facsimileTelephoneNumber
+item cis "Description" description
+item dn,sort "See Also" seeAlso
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+END
+
+
+##########################################################################
+# Service template
+##########################################################################
+"Service"
+"Services"
+"service icon"
+
+# template options
+"addable"
+
+# objectclass list
+service
+END
+
+# name of attribute to authenticate as
+"owner"
+
+# default attribute name to use when forming RDN of a new entry
+cn
+
+# default location when adding new entries
+"ou=Services, o=University of Michigan, c=US"
+
+# rules used to define default values for new entries
+addersdn "owner"
+END
+
+#
+#
+# list of items for display
+# each line is either:
+# item (type) (attribute) (attr name) (extra args...)
+# to define an item or
+# samerow
+#
+# list of items for display
+item jpegbtn "View Photo" jpegPhoto
+item cis,sort "Name" cn
+item mls "Description" multilineDescription
+item cis "Provider" provider
+item cis,sort "Service Area" serviceArea
+item mail "E-mail Address" mail
+item cis "Phone" telephoneNumber
+item cis "Fax Number" facsimileTelephoneNumber
+item mls "Postal Address" postalAddress
+item cis "Hours" hoursOfOperation
+item url "More Info (URL)" labeledURL
+item dn,sort "Depends On" dependentUpon
+item dn,sort "See Also" seeAlso
+item cis,sort "Platform" platform
+item cis,sort "Product" product
+item cis,sort "Keywords" keywords
+item cis "FCE Rating" serviceRating
+item date "Date Rated" ratingTime
+item mls "Rating Description" ratingDescription
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+item dn,required,sort "Owner" owner
+END
+
+
+##########################################################################
+# Organizational Role template
+##########################################################################
+"Organizational Role"
+"Organizational Roles"
+"person icon"
+
+# template options
+""
+
+# objectclass list
+organizationalRole
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+cn
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+END
+
+#
+#
+# list of items for display
+# each line is either:
+# item (type) (attribute) (attr name) (extra args...)
+# to define an item or
+# samerow
+#
+# list of items for display
+item cis,sort "Name" cn
+item cis "Description" description
+item dn "Role Occupant" roleOccupant
+item dn,sort "See Also" seeAlso
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+END
+
+
+##########################################################################
+# Organizational Unit template
+##########################################################################
+"Organizational Unit"
+"Organizational Units"
+"organization icon"
+
+# template options
+""
+
+# objectclass list
+organizationalUnit
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+cn
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+END
+
+# Item list
+item cis "Organization Unit Name" ou
+item cis "Title" title
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+END
+
+
+
+##########################################################################
+# Application Entity template
+##########################################################################
+"Application Entity"
+"Application Entities"
+"application icon"
+
+# template options
+""
+
+# objectclass list
+applicationEntity
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+cn
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+END
+
+# Item list
+item cis,sort "Name" cn
+item cis "Location" l
+item cis "Description" description
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+END
+
+##########################################################################
+# Document template
+##########################################################################
+"Document"
+"Documents"
+"document icon"
+
+# template options
+""
+
+# objectclass list
+document
+umichDocument
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+cn
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+END
+
+#
+# Item list
+item cis "Document ID" documentIdentifier
+item cis "Title" documentTitle
+item cis "Series Title" documentSeriesTitle
+item cis "Version" documentVersion
+item cis,sort "Service Area" serviceArea
+item mls "Abstract" multiLineAbstract
+item url "More Info (URL)" labeledURL
+item dn,sort "Availability" documentAvailable
+item dn,sort "See Also" seeAlso
+item cis,sort "Platform" platform
+item cis,sort "Product" product
+item cis,sort "Keyword" keywords
+item dn,sort "Author" documentAuthor
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+item dn,required "Owner" owner
+END
+
+##########################################################################
+# Document description template
+##########################################################################
+"DocumentDescription"
+"DocumentDescriptions"
+"document description icon"
+
+# template options
+""
+
+# objectclass list
+documentDescription
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+cn
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+END
+
+#
+# Item list
+item mls "Description" multilineDescription
+item url "More Info (URL)" labeledURL
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+item dn,required "Owner" owner
+END
+
+##########################################################################
+# Image template
+##########################################################################
+"Image"
+"Images"
+"image icon"
+
+# template options
+""
+
+# objectclass list
+image
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+cn
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+END
+
+#
+# Item list
+item cis "Name" cn
+item mls "Description" multilineDescription
+item jpegbtn "View Photo(s)" jpegPhoto
+item cis "Citation" citation
+item cis "Copyright" copyright
+item cis "Keywords" keywords
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+item dn,required "Owner" owner
+END
+
+
+
+##########################################################################
+# Country template
+##########################################################################
+"Country"
+"Countries"
+"country icon"
+
+# template options
+""
+
+# objectclass list
+friendlyCountry
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+c
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+END
+
+# Item list
+item cis "Country Name" co
+item cis "Country Code" c
+item cis "Description" description
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+END
+
+##########################################################################
+# Locality template
+##########################################################################
+"Locality"
+"Localities"
+"locality icon"
+
+# template options
+""
+
+# objectclass list
+locality
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+l
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+END
+
+#
+# Item list
+item cis "Name" l
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+END
+
+
+##########################################################################
+# "Other Addresses" template
+##########################################################################
+"Others Addresses"
+"Other Addresses"
+"other addr icon"
+
+# template options
+"altview"
+
+# objectclass list
+END
+
+# name of attribute to authenticate as
+""
+
+# default attribute name to use when forming RDN of a new entry
+""
+
+# default location when adding new entries
+""
+
+# rules used to define default values for new entries
+END
+
+# Item list
+item cis "Street Address" streetAddress
+item cis "Locality" l
+item cis "State or Province" st
+item cis "Postal Code" postalCode
+item cis,hide "X.400 Address" mhsORAddresses
+item cis,hide "X.400 Address" textEncodedORAddress
+Item cis "Other Mailbox" otherMailbox
+item time,ro "Last Modified" lastModifiedTime
+item dn,ro "Modified By" lastModifiedBy
+END
diff --git a/usr/src/lib/libldap4/sec/cram_md5.c b/usr/src/lib/libldap4/sec/cram_md5.c
new file mode 100644
index 0000000000..4b92efbfc6
--- /dev/null
+++ b/usr/src/lib/libldap4/sec/cram_md5.c
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <strings.h>
+#include "sec.h"
+
+/* text is the challenge, key is the password, digest is an allocated
+ buffer (min 16 chars) which will contain the resulting digest */
+void hmac_md5(unsigned char *text, int text_len, unsigned char *key,
+ int key_len, unsigned char *digest)
+{
+ MD5_CTX context;
+ unsigned char k_ipad[65];
+ unsigned char k_opad[65];
+ unsigned char tk[16];
+ int i;
+
+ if (key_len > 64){
+ MD5_CTX tctx;
+
+ (void) MD5Init(&tctx);
+ (void) MD5Update(&tctx, key, key_len);
+ (void) MD5Final(tk, &tctx);
+ key = tk;
+ key_len = 16;
+ }
+
+ bzero(k_ipad, sizeof (k_ipad));
+ bzero(k_opad, sizeof (k_opad));
+ bcopy(key, k_ipad, key_len);
+ bcopy(key, k_opad, key_len);
+
+ for (i=0; i<64; i++){
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* Perform inner MD5 */
+ (void) MD5Init(&context);
+ (void) MD5Update(&context, k_ipad, 64);
+ (void) MD5Update(&context, text, text_len);
+ (void) MD5Final(digest, &context);
+
+ /* Perform outer MD5 */
+ (void) MD5Init(&context);
+ (void) MD5Update(&context, k_opad, 64);
+ (void) MD5Update(&context, digest, 16);
+
+ (void) MD5Final(digest, &context);
+
+ return;
+}
diff --git a/usr/src/lib/libldap4/sec/secutil.c b/usr/src/lib/libldap4/sec/secutil.c
new file mode 100644
index 0000000000..7d1658d0f9
--- /dev/null
+++ b/usr/src/lib/libldap4/sec/secutil.c
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+static char hexdig[] = "0123456789abcdef";
+
+char* hexa_print(char *aString, int aLen)
+{
+ char *res;
+ int i =0;
+
+ if ((res = (char *)calloc (aLen*2 + 1, 1 )) == NULL){
+ return (NULL);
+ }
+ for (;;){
+ if (aLen < 1)
+ break;
+ res[i] = hexdig[ ( *aString & 0xf0 ) >> 4 ];
+ res[i + 1] = hexdig[ *aString & 0x0f ];
+ i+= 2;
+ aLen--;
+ aString++;
+ }
+ return (res);
+}
+
+
+static int
+unhex( char c )
+{
+ return( c >= '0' && c <= '9' ? c - '0'
+ : c >= 'A' && c <= 'F' ? c - 'A' + 10
+ : c - 'a' + 10 );
+}
+
+char * hexa2str(char *anHexaStr, int *aResLen) {
+ int theLen = 0;
+ char *theRes = malloc(strlen(anHexaStr) /2 + 1);
+
+ while (isxdigit(*anHexaStr)){
+ theRes[theLen] = unhex(*anHexaStr) << 4;
+ if (++anHexaStr != '\0'){
+ theRes[theLen] += unhex(*anHexaStr);
+ anHexaStr++;
+ }
+ theLen++;
+ }
+ theRes[theLen] = '\0';
+ * aResLen = theLen;
+ return (theRes);
+}
diff --git a/usr/src/lib/libldap4/sparc/Makefile b/usr/src/lib/libldap4/sparc/Makefile
new file mode 100644
index 0000000000..07866abc0c
--- /dev/null
+++ b/usr/src/lib/libldap4/sparc/Makefile
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 1997-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libldap4/sparc/Makefile
+
+MAPDIR= ../spec/sparc
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS)
diff --git a/usr/src/lib/libldap4/sparcv9/Makefile b/usr/src/lib/libldap4/sparcv9/Makefile
new file mode 100644
index 0000000000..9776bf13ec
--- /dev/null
+++ b/usr/src/lib/libldap4/sparcv9/Makefile
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 1997-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libldap4/sparcv9/Makefile
+
+MAPDIR= ../spec/sparcv9
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+LIBS = $(DYNLIB)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64)
diff --git a/usr/src/lib/libldap4/spec/Makefile b/usr/src/lib/libldap4/spec/Makefile
new file mode 100644
index 0000000000..6718d324a0
--- /dev/null
+++ b/usr/src/lib/libldap4/spec/Makefile
@@ -0,0 +1,8 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libadm/spec/Makefile
+
+include $(SRC)/lib/Makefile.spec.arch
diff --git a/usr/src/lib/libldap4/spec/Makefile.targ b/usr/src/lib/libldap4/spec/Makefile.targ
new file mode 100644
index 0000000000..5642e0126f
--- /dev/null
+++ b/usr/src/lib/libldap4/spec/Makefile.targ
@@ -0,0 +1,13 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libldap/spec/Makefile.targ
+
+LIBRARY = libldap.a
+VERS = .4
+
+OBJECTS = ldap.o
+
+SPECCPP = -I..
diff --git a/usr/src/lib/libldap4/spec/amd64/Makefile b/usr/src/lib/libldap4/spec/amd64/Makefile
new file mode 100644
index 0000000000..d9dd978091
--- /dev/null
+++ b/usr/src/lib/libldap4/spec/amd64/Makefile
@@ -0,0 +1,26 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#amd64_C_PICFLAGS = -K PIC
+
+# To make sure the correct header files are located first
+CPPFLAGS= -I$(SRC)/lib/libldap4/include $(CPPFLAGS.master)
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libldap4/spec/i386/Makefile b/usr/src/lib/libldap4/spec/i386/Makefile
new file mode 100644
index 0000000000..56982ab8a4
--- /dev/null
+++ b/usr/src/lib/libldap4/spec/i386/Makefile
@@ -0,0 +1,26 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libldap4/spec/i386/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#i386_C_PICFLAGS = -K PIC
+
+# To make sure the correct header files are located first
+CPPFLAGS= -I$(SRC)/lib/libldap4/include $(CPPFLAGS.master)
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libldap4/spec/ldap.spec b/usr/src/lib/libldap4/spec/ldap.spec
new file mode 100644
index 0000000000..c2c8ff4b89
--- /dev/null
+++ b/usr/src/lib/libldap4/spec/ldap.spec
@@ -0,0 +1,1288 @@
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libldap/spec/ldap.spec
+
+function ber_alloc_t
+include <lber.h>, <ldap.h>
+declaration BerElement *ber_alloc_t(int options)
+version SUNW_1.1
+exception $return == NULLBER
+end
+
+function ber_bvdup
+include <lber.h>, <ldap.h>
+declaration struct berval *ber_bvdup(struct berval *bv)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ber_bvecfree
+include <lber.h>, <ldap.h>
+declaration void ber_bvecfree(struct berval **bv)
+version SUNW_1.1
+end
+
+function ber_bvfree
+include <lber.h>, <ldap.h>
+declaration void ber_bvfree(struct berval *bv)
+version SUNW_1.1
+end
+
+function ber_first_element
+include <lber.h>, <ldap.h>
+declaration unsigned int ber_first_element(BerElement *ber, \
+ unsigned int *len, char **last)
+version SUNW_1.1
+end
+
+function ber_flatten
+include <lber.h>, <ldap.h>
+declaration int ber_flatten(BerElement *ber, struct berval **bvPtr)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ber_free
+include <lber.h>, <ldap.h>
+declaration void ber_free(BerElement *ber, int freebuf)
+version SUNW_1.1
+end
+
+function ber_init
+include <lber.h>, <ldap.h>
+declaration BerElement *ber_init(struct berval *bv)
+version SUNW_1.1
+exception $return == NULLBER
+end
+
+function ber_next_element
+include <lber.h>, <ldap.h>
+declaration unsigned int ber_next_element(BerElement *ber, \
+ unsigned int *len, char *last)
+version SUNW_1.1
+end
+
+function ber_peek_tag
+include <lber.h>, <ldap.h>
+declaration unsigned int ber_peek_tag(BerElement *ber, unsigned int *len)
+version SUNW_1.1
+end
+
+function ber_printf
+include <lber.h>, <ldap.h>
+declaration int ber_printf(BerElement *ber, char *fmt, ...)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ber_scanf
+include <lber.h>, <ldap.h>
+declaration unsigned int ber_scanf(BerElement *ber, char *fmt, ...)
+version SUNW_1.1
+exception $return == LBER_DEFAULT
+end
+
+function ber_skip_tag
+include <lber.h>, <ldap.h>
+declaration unsigned int ber_skip_tag(BerElement *ber, unsigned int *len)
+version SUNW_1.1
+end
+
+function ber_get_int
+include <lber.h>
+declaration unsigned int ber_get_int(BerElement *ber, int *num)
+version SUNW_1.2
+end
+
+function ber_alloc
+include <lber.h>
+declaration BerElement *ber_alloc(void)
+version SUNW_1.2
+end
+
+function cldap_close
+include <lber.h>, <ldap.h>
+declaration void cldap_close(LDAP *ld)
+version SUNW_1.1
+end
+
+function cldap_open
+include <lber.h>, <ldap.h>
+declaration LDAP *cldap_open(char *host, int port)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function cldap_search_s
+include <lber.h>, <ldap.h>
+declaration int cldap_search_s(LDAP *ld, char *base, int scope, \
+ char *filter, char **attrs, int attrsonly, \
+ LDAPMessage **res, char *logdn)
+version SUNW_1.1
+exception $return == -1
+end
+
+function cldap_setretryinfo
+include <lber.h>, <ldap.h>
+declaration void cldap_setretryinfo(LDAP *ld, int tries, time_t timeout)
+version SUNW_1.1
+end
+
+function i18n_catopen
+include <lber.h>, <ldap.h>
+declaration void i18n_catopen(char *name)
+version SUNWprivate_1.1
+end
+
+function ldap_abandon
+include <lber.h>, <ldap.h>
+declaration int ldap_abandon(LDAP *ld, int msgid)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_abandon_ext
+include <lber.h>, <ldap.h>
+declaration int ldap_abandon_ext(LDAP *ld, int msgid, \
+ LDAPControl **serverctrls, LDAPControl **clientctrls)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_add
+include <lber.h>, <ldap.h>
+declaration int ldap_add(LDAP *ld, char *dn, LDAPMod **attrs)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_add_ext
+include <lber.h>, <ldap.h>
+declaration int ldap_add_ext(LDAP *ld, char *dn, LDAPMod **attrs, \
+ LDAPControl **serverctrls, \
+ LDAPControl **clientctrls, int *msgidp)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_add_ext_s
+include <lber.h>, <ldap.h>
+declaration int ldap_add_ext_s(LDAP *ld, char *dn, LDAPMod **attrs, LDAPControl **serverctrls, LDAPControl **clientctrls)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_add_s
+include <lber.h>, <ldap.h>
+declaration int ldap_add_s(LDAP *ld, char *dn, LDAPMod **attrs)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_bind
+include <lber.h>, <ldap.h>
+declaration int ldap_bind(LDAP *ld, char *dn, char *passwd, int authmethod)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_bind_s
+include <lber.h>, <ldap.h>
+declaration int ldap_bind_s(LDAP *ld, char *dn, char *passwd, \
+ int authmethod)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_build_filter
+include <lber.h>, <ldap.h>
+declaration void ldap_build_filter(char *filtbuf, size_t buflen, \
+ char *pattern, char *prefix, char *suffix, \
+ char *attr, char *value, char **valwords)
+version SUNW_1.1
+end
+
+function ldap_compare
+include <lber.h>, <ldap.h>
+declaration int ldap_compare(LDAP *ld, char *dn, char *attr, char *value)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_compare_ext
+include <lber.h>, <ldap.h>
+declaration int ldap_compare_ext(LDAP *ld, char *dn, char *attr, \
+ struct berval *bvalue, LDAPControl **serverctrls, \
+ LDAPControl **clientctrls, int *msgidp)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_compare_ext_s
+include <lber.h>, <ldap.h>
+declaration int ldap_compare_ext_s(LDAP *ld, char *dn, char *attr, \
+ struct berval *bvalue, LDAPControl **serverctrls, \
+ LDAPControl **clientctrls)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_compare_s
+include <lber.h>, <ldap.h>
+declaration int ldap_compare_s(LDAP *ld, char *dn, char *attr, char *value)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_control_free
+include <lber.h>, <ldap.h>
+declaration void ldap_control_free (LDAPControl *ctrl)
+version SUNW_1.1
+end
+
+function ldap_controls_free
+include <lber.h>, <ldap.h>
+declaration void ldap_controls_free (LDAPControl **ctrls)
+version SUNW_1.1
+end
+
+function ldap_count_entries
+include <lber.h>, <ldap.h>
+declaration int ldap_count_entries(LDAP *ld, LDAPMessage *res)
+version SUNW_1.1
+end
+
+function ldap_count_messages
+include <lber.h>, <ldap.h>
+declaration int ldap_count_messages(LDAP *ld, LDAPMessage *res)
+version SUNW_1.1
+end
+
+function ldap_count_references
+include <lber.h>, <ldap.h>
+declaration int ldap_count_references(LDAP *ld, LDAPMessage *res)
+version SUNW_1.1
+end
+
+function ldap_count_values
+include <lber.h>, <ldap.h>
+declaration int ldap_count_values(char **vals)
+version SUNW_1.1
+end
+
+function ldap_count_values_len
+include <lber.h>, <ldap.h>
+declaration int ldap_count_values_len(struct berval **vals)
+version SUNW_1.1
+end
+
+function ldap_create_page_control
+include <lber.h>, <ldap.h>
+declaration int ldap_create_page_control(LDAP *ld, \
+ unsigned int pagesize, struct berval *cookie, \
+ char isCritical, LDAPControl **output)
+version SUNWprivate_1.1
+end
+
+function ldap_delete
+include <lber.h>, <ldap.h>
+declaration int ldap_delete(LDAP *ld, char *dn)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_delete_ext
+include <lber.h>, <ldap.h>
+declaration int ldap_delete_ext(LDAP *ld, char *dn, \
+ LDAPControl **serverctrls, \
+ LDAPControl **clientctrls, int *msgidp)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_delete_ext_s
+include <lber.h>, <ldap.h>
+declaration int ldap_delete_ext_s(LDAP *ld, char *dn, \
+ LDAPControl **serverctrls, LDAPControl **clientctrls)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_delete_s
+include <lber.h>, <ldap.h>
+declaration int ldap_delete_s(LDAP *ld, char *dn)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_destroy_cache
+include <lber.h>, <ldap.h>
+declaration void ldap_destroy_cache(LDAP *ld)
+version SUNW_1.1
+end
+
+function ldap_disable_cache
+include <lber.h>, <ldap.h>
+declaration void ldap_disable_cache(LDAP *ld)
+version SUNW_1.1
+end
+
+function ldap_dn2ufn
+include <lber.h>, <ldap.h>
+declaration char *ldap_dn2ufn(char *dn)
+version SUNW_1.1
+end
+
+function ldap_dn_to_url
+include <lber.h>, <ldap.h>
+declaration char *ldap_dn_to_url(LDAP *ld, char*dn, int nameparts)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_dns_to_dn
+include <lber.h>, <ldap.h>
+declaration char *ldap_dns_to_dn(char *dns_name, int *nameparts)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_dns_to_url
+include <lber.h>, <ldap.h>
+declaration char *ldap_dns_to_url(LDAP *ld, char *dns_name, \
+ char *attrs, char *scope, char *filter)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_enable_cache
+include <lber.h>, <ldap.h>
+declaration int ldap_enable_cache(LDAP *ld, time_t timeout, ssize_t maxmem)
+version SUNW_1.1
+end
+
+function ldap_enable_translation
+include <lber.h>, <ldap.h>
+declaration void ldap_enable_translation(LDAP *ld, LDAPMessage *entry, \
+ int enable)
+version SUNW_1.1
+end
+
+function ldap_entry2html
+include <lber.h>, <ldap.h>
+declaration int ldap_entry2html(LDAP *ld, char *buf, LDAPMessage *entry, \
+ struct ldap_disptmpl *tmpl, char **defattrs, \
+ char ***defvals, writeptype writeproc, \
+ void *writeparm, char *eol, int rdncount, \
+ unsigned int opts, char *base, char *urlprefix)
+version SUNW_1.1
+end
+
+function ldap_entry2html_search
+include <lber.h>, <ldap.h>
+declaration int ldap_entry2html_search(LDAP *ld, char *dn, char *base, \
+ LDAPMessage *entry, struct ldap_disptmpl*tmpllist, \
+ char **defattrs, char ***defvals, \
+ writeptype writeproc, void *writeparm, \
+ char *eol,int rdncount, unsigned int opts, \
+ char *urlprefix)
+version SUNW_1.1
+end
+
+function ldap_entry2text
+include <lber.h>, <ldap.h>
+declaration int ldap_entry2text(LDAP *ld, char *buf, \
+ LDAPMessage *entry, struct ldap_disptmpl *tmpl, \
+ char **defattrs, char ***defvals, \
+ writeptype writeproc, void *writeparm, char *eol, \
+ int rdncount, unsigned int opts)
+version SUNW_1.1
+end
+
+function ldap_entry2text_search
+include <lber.h>, <ldap.h>
+declaration int ldap_entry2text_search(LDAP *ld,char *dn, char *base, \
+ LDAPMessage *entry, struct ldap_disptmpl*tmpllist, \
+ char **defattrs, char ***defvals, \
+ writeptype writeproc, void *writeparm, \
+ char *eol,int rdncount, unsigned int opts)
+version SUNW_1.1
+end
+
+function ldap_err2string
+include <lber.h>, <ldap.h>
+declaration char *ldap_err2string(int err)
+version SUNW_1.1
+end
+
+function ldap_explode_dn
+include <lber.h>, <ldap.h>
+declaration char **ldap_explode_dn(char *dn, int notypes)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_explode_dns
+include <lber.h>, <ldap.h>
+declaration char **ldap_explode_dns(char *dn)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_explode_rdn
+include <lber.h>, <ldap.h>
+declaration char **ldap_explode_rdn(char *rdn, int notypes)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_extended_operation
+include <lber.h>, <ldap.h>
+declaration int ldap_extended_operation(LDAP *ld, char *exoid, \
+ struct berval *exdata, LDAPControl **serverctrls, \
+ LDAPControl**clientctrls, int *msgidp)
+version SUNW_1.1
+end
+
+function ldap_extended_operation_s
+include <lber.h>, <ldap.h>
+declaration int ldap_extended_operation_s(LDAP *ld, char *exoid, \
+ struct berval *exdata, LDAPControl **serverctrls, \
+ LDAPControl **clientctrls, char **retoidp, \
+ struct berval **retdatap)
+version SUNW_1.1
+end
+
+function ldap_first_attribute
+include <lber.h>, <ldap.h>
+declaration char *ldap_first_attribute(LDAP *ld, LDAPMessage *entry, \
+ BerElement **ber)
+version SUNW_1.1
+end
+
+function ldap_first_disptmpl
+include <lber.h>, <ldap.h>
+declaration struct ldap_disptmpl *ldap_first_disptmpl \
+ (struct ldap_disptmpl *tmpllist)
+version SUNW_1.1
+end
+
+function ldap_first_entry
+include <lber.h>, <ldap.h>
+declaration LDAPMessage *ldap_first_entry(LDAP *ld, LDAPMessage *res)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_first_message
+include <lber.h>, <ldap.h>
+declaration LDAPMessage *ldap_first_message(LDAP *ld, LDAPMessage *res)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_first_reference
+include <lber.h>, <ldap.h>
+declaration LDAPMessage *ldap_first_reference(LDAP *ld, LDAPMessage *res)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_first_searchobj
+include <lber.h>, <ldap.h>
+declaration struct ldap_searchobj *ldap_first_searchobj \
+ (struct ldap_searchobj *solist)
+version SUNW_1.1
+end
+
+function ldap_first_tmplcol
+include <lber.h>, <ldap.h>
+declaration struct ldap_tmplitem *ldap_first_tmplcol \
+ (struct ldap_disptmpl *tmpl, \
+ struct ldap_tmplitem *row)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_first_tmplrow
+include <lber.h>, <ldap.h>
+declaration struct ldap_tmplitem *ldap_first_tmplrow \
+ (struct ldap_disptmpl *tmpl)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_flush_cache
+include <lber.h>, <ldap.h>
+declaration void ldap_flush_cache(LDAP *ld)
+version SUNW_1.1
+end
+
+function ldap_free_friendlymap
+include <lber.h>, <ldap.h>
+declaration void ldap_free_friendlymap(FriendlyMap **map)
+version SUNW_1.1
+end
+
+function ldap_free_searchprefs
+include <lber.h>, <ldap.h>
+declaration void ldap_free_searchprefs(struct ldap_searchobj *solist)
+version SUNW_1.1
+end
+
+function ldap_free_templates
+include <lber.h>, <ldap.h>
+declaration void ldap_free_templates(struct ldap_disptmpl *tmpllist)
+version SUNW_1.1
+end
+
+function ldap_free_urldesc
+include <lber.h>, <ldap.h>
+declaration void ldap_free_urldesc(LDAPURLDesc *ludp)
+version SUNW_1.1
+end
+
+function ldap_friendly_name
+include <lber.h>, <ldap.h>
+declaration char *ldap_friendly_name(char *filename, char *uname, \
+ FriendlyMap **map)
+version SUNW_1.1
+end
+
+function ldap_get_dn
+include <lber.h>, <ldap.h>
+declaration char *ldap_get_dn(LDAP *ld, LDAPMessage *entry)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_get_option
+include <lber.h>, <ldap.h>
+declaration int ldap_get_option (LDAP *ld, int option, void *outvalue)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_get_reference_urls
+include <lber.h>, <ldap.h>
+declaration char **ldap_get_reference_urls(LDAP *ld, LDAPMessage *res)
+version SUNWprivate_1.1
+exception $return == NULL
+end
+
+function ldap_get_values
+include <lber.h>, <ldap.h>
+declaration char **ldap_get_values(LDAP *ld, LDAPMessage *entry, \
+ char *target)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_get_values_len
+include <lber.h>, <ldap.h>
+declaration struct berval **ldap_get_values_len(LDAP *ld, \
+ LDAPMessage *entry, char *target)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_getfilter_free
+include <lber.h>, <ldap.h>
+declaration void ldap_getfilter_free(LDAPFiltDesc *lfdp)
+version SUNW_1.1
+end
+
+function ldap_getfirstfilter
+include <lber.h>, <ldap.h>
+declaration LDAPFiltInfo *ldap_getfirstfilter(LDAPFiltDesc *lfdp, \
+ char *tagpat, char *value)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_getnextfilter
+include <lber.h>, <ldap.h>
+declaration LDAPFiltInfo *ldap_getnextfilter(LDAPFiltDesc *lfdp)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_init
+include <lber.h>, <ldap.h>
+declaration LDAP *ldap_init(char *defhost, int defport)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_init_getfilter
+include <lber.h>, <ldap.h>
+declaration LDAPFiltDesc *ldap_init_getfilter(char *fname)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_init_getfilter_buf
+include <lber.h>, <ldap.h>
+declaration LDAPFiltDesc *ldap_init_getfilter_buf(char *buf, \
+ ssize_t buflen)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_init_searchprefs
+include <lber.h>, <ldap.h>
+declaration int ldap_init_searchprefs(char *file, \
+ struct ldap_searchobj **solistp)
+version SUNW_1.1
+exception $return == (int) NULLSEARCHOBJ
+end
+
+function ldap_init_searchprefs_buf
+include <lber.h>, <ldap.h>
+declaration int ldap_init_searchprefs_buf(char *buf, ssize_t buflen, \
+ struct ldap_searchobj **solistp)
+version SUNW_1.1
+exception $return == (int) NULLSEARCHOBJ
+end
+
+function ldap_init_templates
+include <lber.h>, <ldap.h>
+declaration int ldap_init_templates(char *file, \
+ struct ldap_disptmpl **tmpllistp)
+version SUNW_1.1
+end
+
+function ldap_init_templates_buf
+include <lber.h>, <ldap.h>
+declaration int ldap_init_templates_buf(char *buf, ssize_t buflen, \
+ struct ldap_disptmpl **tmpllistp)
+version SUNW_1.1
+end
+
+function ldap_is_dns_dn
+include <lber.h>, <ldap.h>
+declaration int ldap_is_dns_dn(char *dn)
+version SUNW_1.1
+exception $return == 0
+end
+
+function ldap_is_ldap_url
+include <lber.h>, <ldap.h>
+declaration int ldap_is_ldap_url(char *url)
+version SUNW_1.1
+exception $return == 0
+end
+
+function ldap_memfree
+include <lber.h>, <ldap.h>
+declaration void ldap_memfree(char *mem)
+version SUNW_1.1
+end
+
+function ldap_modify
+include <lber.h>, <ldap.h>
+declaration int ldap_modify(LDAP *ld, char *dn, LDAPMod **mods)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_modify_ext
+include <lber.h>, <ldap.h>
+declaration int ldap_modify_ext(LDAP *ld, char *dn, LDAPMod **mods, \
+ LDAPControl **serverctrls, \
+ LDAPControl **clientctrls, int *msgidp)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_modify_ext_s
+include <lber.h>, <ldap.h>
+declaration int ldap_modify_ext_s(LDAP *ld, char *dn, LDAPMod **mods, \
+ LDAPControl **serverctrls, LDAPControl **clientctrls)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_modify_s
+include <lber.h>, <ldap.h>
+declaration int ldap_modify_s(LDAP *ld, char *dn, LDAPMod **mods)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_modrdn
+include <lber.h>, <ldap.h>
+declaration int ldap_modrdn(LDAP *ld, char *dn, char *newrdn, \
+ int deleteoldrdn)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_modrdn_s
+include <lber.h>, <ldap.h>
+declaration int ldap_modrdn_s(LDAP *ld, char *dn, char *newrdn, \
+ int deleteoldrdn)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_mods_free
+include <lber.h>, <ldap.h>
+declaration void ldap_mods_free(LDAPMod **mods, int freemods)
+version SUNW_1.1
+end
+
+function ldap_msgfree
+include <lber.h>, <ldap.h>
+declaration int ldap_msgfree(LDAPMessage *lm)
+version SUNW_1.1
+end
+
+function ldap_msgid
+include <lber.h>, <ldap.h>
+declaration int ldap_msgid(LDAPMessage *res)
+version SUNW_1.1
+exception $return == LDAP_RES_ANY
+end
+
+function ldap_msgtype
+include <lber.h>, <ldap.h>
+declaration int ldap_msgtype(LDAPMessage *res)
+version SUNW_1.1
+exception $return == LDAP_RES_ANY
+end
+
+function ldap_next_attribute
+include <lber.h>, <ldap.h>
+declaration char *ldap_next_attribute(LDAP *ld, LDAPMessage *entry, \
+ BerElement *ber)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_next_disptmpl
+include <lber.h>, <ldap.h>
+declaration struct ldap_disptmpl *ldap_next_disptmpl \
+ (struct ldap_disptmpl *tmpllist, \
+ struct ldap_disptmpl *tmpl)
+version SUNW_1.1
+exception $return == NULLDISPTMPL
+end
+
+function ldap_next_entry
+include <lber.h>, <ldap.h>
+declaration LDAPMessage *ldap_next_entry(LDAP *ld, LDAPMessage *entry)
+version SUNW_1.1
+exception $return == NULLMSG
+end
+
+function ldap_next_message
+include <lber.h>, <ldap.h>
+declaration LDAPMessage *ldap_next_message(LDAP *ld, LDAPMessage *msg)
+version SUNW_1.1
+exception $return == NULLMSG
+end
+
+function ldap_next_reference
+include <lber.h>, <ldap.h>
+declaration LDAPMessage *ldap_next_reference(LDAP *ld, LDAPMessage *entry)
+version SUNW_1.1
+exception $return == NULLMSG
+end
+
+function ldap_next_searchobj
+include <lber.h>, <ldap.h>
+declaration struct ldap_searchobj *ldap_next_searchobj \
+ (struct ldap_searchobj *solist, \
+ struct ldap_searchobj *so)
+version SUNW_1.1
+exception $return == NULLSEARCHOBJ
+end
+
+function ldap_next_tmplcol
+include <lber.h>, <ldap.h>
+declaration struct ldap_tmplitem *ldap_next_tmplcol \
+ (struct ldap_disptmpl *tmpl, \
+ struct ldap_tmplitem *row, \
+ struct ldap_tmplitem *col)
+version SUNW_1.1
+exception $return == NULLTMPLITEM
+end
+
+function ldap_next_tmplrow
+include <lber.h>, <ldap.h>
+declaration struct ldap_tmplitem *ldap_next_tmplrow \
+ (struct ldap_disptmpl *tmpl, \
+ struct ldap_tmplitem *row)
+version SUNW_1.1
+exception $return == NULLTMPLITEM
+end
+
+function ldap_oc2template
+include <lber.h>, <ldap.h>
+declaration struct ldap_disptmpl *ldap_oc2template(char **oclist, \
+ struct ldap_disptmpl *tmpllist)
+version SUNW_1.1
+exception $return == NULLDISPTMPL
+end
+
+function ldap_open
+include <lber.h>, <ldap.h>
+declaration LDAP *ldap_open(char *host, int port)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_parse_extended_result
+include <lber.h>, <ldap.h>
+declaration int ldap_parse_extended_result(LDAP *ld, LDAPMessage *res, \
+ char **resultoidp, struct berval **resultdata, \
+ int freeit)
+version SUNW_1.1
+end
+
+function ldap_parse_page_control
+include <lber.h>, <ldap.h>
+declaration int ldap_parse_page_control(LDAP *ld, \
+ LDAPControl **controls, unsigned int *totalcount, \
+ struct berval **cookie)
+version SUNWprivate_1.1
+end
+
+function ldap_parse_result
+include <lber.h>, <ldap.h>
+declaration int ldap_parse_result(LDAP *ld, LDAPMessage *res, \
+ int *errcodep, char **matcheddnp, char **errmsgp, \
+ char ***referralsp, LDAPControl ***serverctrlsp, \
+ int freeit)
+version SUNW_1.1
+end
+
+function ldap_parse_sasl_bind_result
+include <lber.h>, <ldap.h>
+declaration int ldap_parse_sasl_bind_result(LDAP *ld, LDAPMessage *res, \
+ struct berval **servercredp, int freeit)
+version SUNW_1.1
+end
+
+function ldap_perror
+include <lber.h>, <ldap.h>
+declaration void ldap_perror(LDAP *ld, char *s)
+version SUNW_1.1
+end
+
+function ldap_rename
+include <lber.h>, <ldap.h>
+declaration int ldap_rename(LDAP *ld, char *dn, char *newrdn, \
+ char *newparent, int deleteoldrdn, \
+ LDAPControl **serverctrls, \
+ LDAPControl **clientctrls, int *msgidp)
+version SUNW_1.1
+end
+
+function ldap_rename_s
+include <lber.h>, <ldap.h>
+declaration int ldap_rename_s(LDAP *ld, char *dn, char *newrdn, \
+ char *newparent, int deleteoldrdn, \
+ LDAPControl **serverctrls, LDAPControl **clientctrls)
+version SUNW_1.1
+end
+
+function ldap_result2error
+include <lber.h>, <ldap.h>
+declaration int ldap_result2error(LDAP *ld, LDAPMessage *r, int freeit)
+version SUNW_1.1
+end
+
+function ldap_result
+include <lber.h>, <ldap.h>
+declaration int ldap_result(LDAP *ld, int msgid, int all, \
+ struct timeval *timeout, LDAPMessage **result)
+version SUNW_1.1
+end
+
+function ldap_sasl_bind
+include <lber.h>, <ldap.h>
+declaration int ldap_sasl_bind(LDAP *ld, char *dn, char *mechanism, \
+ struct berval *cred, LDAPControl **serverctrls, \
+ LDAPControl **clientctrls, int *msgidp)
+version SUNW_1.1
+end
+
+function ldap_sasl_bind_s
+include <lber.h>, <ldap.h>
+declaration int ldap_sasl_bind_s(LDAP *ld, char *dn, char *mechanism, \
+ struct berval *cred, LDAPControl **serverctrls, \
+ LDAPControl **clientctrls, struct berval **servercredp)
+version SUNW_1.1
+end
+
+function ldap_sasl_cram_md5_bind_s
+include <lber.h>, <ldap.h>
+declaration int ldap_sasl_cram_md5_bind_s(LDAP *ld, char *dn, \
+ struct berval *cred, LDAPControl **serverctrls, \
+ LDAPControl **clientctrls)
+version SUNW_1.1
+end
+
+function ldap_search
+include <lber.h>, <ldap.h>
+declaration int ldap_search(LDAP *ld, char *base, int scope, \
+ char *filter, char **attrs, int attrsonly)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_search_ext
+include <lber.h>, <ldap.h>
+declaration int ldap_search_ext(LDAP *ld, char *base, int scope, \
+ char *filter, char **attrs, int attrsonly, \
+ LDAPControl **serverctrls, LDAPControl **clientctrls, \
+ struct timeval *timeoutp, int sizelimit, int *msgidp)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_search_ext_s
+include <lber.h>, <ldap.h>
+declaration int ldap_search_ext_s(LDAP *ld, char *base, int scope, \
+ char *filter, char **attrs, int attrsonly, \
+ LDAPControl **serverctrls, \
+ LDAPControl **clientctrls, struct timeval *timeoutp, \
+ int sizelimit, LDAPMessage **res)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_search_s
+include <lber.h>, <ldap.h>
+declaration int ldap_search_s(LDAP *ld, char *base, int scope, \
+ char *filter, char **attrs, int attrsonly, \
+ LDAPMessage **res)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_search_st
+include <lber.h>, <ldap.h>
+declaration int ldap_search_st(LDAP *ld, char *base, int scope, \
+ char *filter, char **attrs, int attrsonly, \
+ struct timeval *timeout, LDAPMessage **res)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_set_cache_options
+include <lber.h>, <ldap.h>
+declaration void ldap_set_cache_options(LDAP *ld, unsigned int opts)
+version SUNW_1.1
+end
+
+function ldap_set_option
+include <lber.h>, <ldap.h>
+declaration int ldap_set_option (LDAP *ld, int option, void *invalue)
+version SUNW_1.1
+end
+
+function ldap_set_rebind_proc
+include <lber.h>, <ldap.h>
+declaration void ldap_set_rebind_proc(LDAP *ld, \
+ LDAP_REBIND_FUNCTION *rebindproc, void *extra_arg)
+version SUNW_1.1
+end
+
+function ldap_set_string_translators
+include <lber.h>, <ldap.h>
+declaration void ldap_set_string_translators(LDAP *ld, \
+ BERTranslateProc encode_proc, \
+ BERTranslateProc decode_proc)
+version SUNW_1.1
+end
+
+function ldap_setfilteraffixes
+include <lber.h>, <ldap.h>
+declaration void ldap_setfilteraffixes(LDAPFiltDesc *lfdp, \
+ char *prefix, char *suffix)
+version SUNW_1.1
+end
+
+function ldap_simple_bind
+include <lber.h>, <ldap.h>
+declaration int ldap_simple_bind(LDAP *ld, char *dn, char *passwd)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_simple_bind_s
+include <lber.h>, <ldap.h>
+declaration int ldap_simple_bind_s(LDAP *ld, char *dn, char *passwd)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_sort_entries
+include <lber.h>, <ldap.h>
+declaration int ldap_sort_entries(LDAP *ld, LDAPMessage **chain, \
+ char *attr, int (*cmp)())
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_sort_strcasecmp
+include <lber.h>, <ldap.h>
+declaration int ldap_sort_strcasecmp(char **a, char **b)
+version SUNW_1.1
+end
+
+function ldap_sort_values
+include <lber.h>, <ldap.h>
+declaration int ldap_sort_values(LDAP *ld, char **vals, int (*cmp)())
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_tmplattrs
+include <lber.h>, <ldap.h>
+declaration char **ldap_tmplattrs(struct ldap_disptmpl *tmpl, \
+ char **includeattrs, int exclude, \
+ unsigned int syntaxmask)
+version SUNW_1.1
+exception $return == NULL
+end
+
+function ldap_translate_from_t61
+include <lber.h>, <ldap.h>
+declaration int ldap_translate_from_t61(LDAP *ld, char **bufp, \
+ unsigned int *lenp, int free_input)
+version SUNW_1.1
+end
+
+function ldap_translate_to_t61
+include <lber.h>, <ldap.h>
+declaration int ldap_translate_to_t61(LDAP *ld, char **bufp, \
+ unsigned int *lenp, int free_input)
+version SUNW_1.1
+end
+
+function ldap_ufn_search_c
+include <lber.h>, <ldap.h>, "ufn.h"
+declaration int ldap_ufn_search_c(LDAP *ld, char *ufn, char **attrs, \
+ int attrsonly, LDAPMessage **res, \
+ cancelptype cancelproc, void *cancelparm)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_ufn_search_ct
+include <lber.h>, <ldap.h>, "ufn.h"
+declaration int ldap_ufn_search_ct(LDAP *ld, char *ufn, char **attrs, \
+ int attrsonly, LDAPMessage **res, \
+ cancelptype cancelproc, void *cancelparm, \
+ char *tag1, char *tag2, char *tag3)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_ufn_search_s
+include <lber.h>, <ldap.h>
+declaration int ldap_ufn_search_s(LDAP *ld, char *ufn, char **attrs, \
+ int attrsonly, LDAPMessage **res)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_ufn_setfilter
+include <lber.h>, <ldap.h>
+declaration LDAPFiltDesc *ldap_ufn_setfilter(LDAP *ld, char *fname)
+version SUNW_1.1
+end
+
+function ldap_ufn_setprefix
+include <lber.h>, <ldap.h>
+declaration void ldap_ufn_setprefix(LDAP *ld, char *prefix)
+version SUNW_1.1
+end
+
+function ldap_ufn_timeout
+include <lber.h>, <ldap.h>
+declaration int ldap_ufn_timeout(void *tvparam)
+version SUNW_1.1
+exception $return == 0
+end
+
+function ldap_unbind
+include <lber.h>, <ldap.h>
+declaration int ldap_unbind(LDAP *ld)
+version SUNW_1.1
+exception $return == 0
+end
+
+function ldap_unbind_s
+include <lber.h>, <ldap.h>
+declaration int ldap_unbind_s(LDAP *ld)
+version SUNW_1.1
+exception $return == 0
+end
+
+function ldap_uncache_entry
+include <lber.h>, <ldap.h>
+declaration void ldap_uncache_entry(LDAP *ld, char *dn)
+version SUNW_1.1
+end
+
+function ldap_uncache_request
+include <lber.h>, <ldap.h>
+declaration void ldap_uncache_request(LDAP *ld, int msgid)
+version SUNW_1.1
+end
+
+function ldap_url_parse
+include <lber.h>, <ldap.h>
+declaration int ldap_url_parse(char *url, LDAPURLDesc **ludpp)
+version SUNW_1.1
+end
+
+function ldap_url_search
+include <lber.h>, <ldap.h>
+declaration int ldap_url_search(LDAP *ld, char *url, int attrsonly)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_url_search_s
+include <lber.h>, <ldap.h>
+declaration int ldap_url_search_s(LDAP *ld, char *url, int attrsonly, \
+ LDAPMessage **res)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_url_search_st
+include <lber.h>, <ldap.h>
+declaration int ldap_url_search_st(LDAP *ld, char *url, int attrsonly, \
+ struct timeval *timeout, LDAPMessage **res)
+version SUNW_1.1
+exception $return == -1
+end
+
+function ldap_vals2html
+include <lber.h>, <ldap.h>
+declaration int ldap_vals2html(LDAP *ld, char *buf, char **vals, \
+ char *label, int labelwidth, unsigned int syntaxid, \
+ writeptype writeproc, void *writeparm, char *eol, \
+ int rdncount, char *urlprefix)
+version SUNW_1.1
+end
+
+function ldap_vals2text
+include <lber.h>, <ldap.h>
+declaration int ldap_vals2text(LDAP *ld, char *buf, char **vals, \
+ char *label, int labelwidth, \
+ unsigned int syntaxid, writeptype writeproc, \
+ void *writeparm, char *eol, int rdncount)
+version SUNW_1.1
+end
+
+function ldap_value_free
+include <lber.h>, <ldap.h>
+declaration void ldap_value_free(char **vals)
+version SUNW_1.1
+end
+
+function ldap_value_free_len
+include <lber.h>, <ldap.h>
+declaration void ldap_value_free_len(struct berval **vals)
+version SUNW_1.1
+end
+
+function ldaplogconfigf
+include <lber.h>, <ldap.h>
+declaration void ldaplogconfigf(FILE *fd)
+version SUNWprivate_1.1
+end
+
+function ldif_type_and_value
+include <lber.h>, <ldap.h>
+declaration char *ldif_type_and_value(char *type, char *val, int vlen)
+version SUNWprivate_1.1
+exception $return == NULL
+end
+
+function open_default_ldap_connection
+include <lber.h>, <ldap.h>
+declaration int open_default_ldap_connection(LDAP *ld)
+version SUNW_1.1
+end
+
+function set_ber_options
+include <lber.h>, <ldap.h>
+declaration void set_ber_options(LDAP *ld, BerElement *ber)
+version SUNW_1.1
+end
+
+data slapdcat
+include <lber.h>, <ldap.h>
+version SUNWprivate_1.1
+end
+
+function str_getline
+include <lber.h>, <ldap.h>
+declaration char *str_getline(char **next)
+version SUNWprivate_1.1
+exception $return == NULL
+end
+
+function str_parse_line
+include <lber.h>, <ldap.h>
+declaration int str_parse_line(char *line, char **type, \
+ char **value, int *vlen)
+version SUNWprivate_1.1
+exception $return == -1
+end
+
+function ldap_create_sort_control
+include <lber.h>, <ldap.h>
+declaration int ldap_create_sort_control (LDAP *ld, \
+ LDAPsortkey **sortKeyList, const char ctl_iscritical, \
+ LDAPControl **ctrlp);
+version SUNW_1.1
+end
+
+function ldap_parse_sort_control
+include <lber.h>, <ldap.h>
+declaration int ldap_parse_sort_control(LDAP *ld, LDAPControl **ctrlp, \
+ unsigned long *result, char **attribute);
+version SUNW_1.1
+end
+
+function ldap_create_sort_keylist
+include <lber.h>, <ldap.h>
+declaration int ldap_create_sort_keylist(LDAPsortkey ***sortKeyList, \
+ char *string_rep);
+version SUNW_1.1
+end
+
+function ldap_free_sort_keylist
+include <lber.h>, <ldap.h>
+declaration void ldap_free_sort_keylist(LDAPsortkey **sortKeyList);
+version SUNW_1.1
+end
+
+function ldap_create_virtuallist_control
+include <lber.h>, <ldap.h>
+declaration int ldap_create_virtuallist_control(LDAP *ld, \
+ LDAPVirtualList *ldvlistp, LDAPControl **ctrlp);
+version SUNW_1.1
+end
+
+function ldap_parse_virtuallist_control
+include <lber.h>, <ldap.h>
+declaration int ldap_parse_virtuallist_control(LDAP *ld, \
+ LDAPControl **ctrls, unsigned long *target_posp, \
+ unsigned long *list_sizep, int *errcodep);
+version SUNW_1.1
+end
diff --git a/usr/src/lib/libldap4/spec/sparc/Makefile b/usr/src/lib/libldap4/spec/sparc/Makefile
new file mode 100644
index 0000000000..3d9a47c524
--- /dev/null
+++ b/usr/src/lib/libldap4/spec/sparc/Makefile
@@ -0,0 +1,26 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libldap4/spec/sparc/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+sparc_C_PICFLAGS = -K PIC
+
+# To make sure the correct header files are located first
+CPPFLAGS= -I$(SRC)/lib/libldap4/include $(CPPFLAGS.master)
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libldap4/spec/sparcv9/Makefile b/usr/src/lib/libldap4/spec/sparcv9/Makefile
new file mode 100644
index 0000000000..29dfe75f94
--- /dev/null
+++ b/usr/src/lib/libldap4/spec/sparcv9/Makefile
@@ -0,0 +1,27 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/libldap4/spec/sparcv9/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+sparcv9_C_PICFLAGS = -K PIC
+
+# To make sure the correct header files are located first
+CPPFLAGS= -I$(SRC)/lib/libldap4/include $(CPPFLAGS.master)
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libldap4/spec/versions b/usr/src/lib/libldap4/spec/versions
new file mode 100644
index 0000000000..04f28e32c1
--- /dev/null
+++ b/usr/src/lib/libldap4/spec/versions
@@ -0,0 +1,27 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+sparc {
+ SUNW_1.2: {SUNW_1.1};
+ SUNW_1.1;
+ SUNWprivate_1.1;
+}
+i386 {
+ SUNW_1.2: {SUNW_1.1};
+ SUNW_1.1;
+ SUNWprivate_1.1;
+}
+sparcv9 {
+ SUNW_1.2: {SUNW_1.1};
+ SUNW_1.1;
+ SUNWprivate_1.1;
+}
+amd64 {
+ SUNW_1.2: {SUNW_1.1};
+ SUNW_1.1;
+ SUNWprivate_1.1;
+}
diff --git a/usr/src/lib/libldap4/util/line64.c b/usr/src/lib/libldap4/util/line64.c
new file mode 100644
index 0000000000..1deb3ef084
--- /dev/null
+++ b/usr/src/lib/libldap4/util/line64.c
@@ -0,0 +1,388 @@
+/*
+ *
+ * Portions Copyright 07/23/97 Sun Microsystems, Inc. All Rights Reserved
+ *
+ */
+/* line64.c - routines for dealing with the slapd line format */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "lber.h"
+#include "ldap.h"
+#include "ldif.h"
+
+#define RIGHT2 0x03
+#define RIGHT4 0x0f
+#define CONTINUED_LINE_MARKER '\001'
+
+static char nib2b64[0x40f] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static unsigned char b642nib[0x80] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+ 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+/*
+ * str_parse_line - takes a line of the form "type:[:] value" and splits it
+ * into components "type" and "value". if a double colon separates type from
+ * value, then value is encoded in base 64, and parse_line un-decodes it
+ * (in place) before returning.
+ */
+
+int
+str_parse_line(
+ char *line,
+ char **type,
+ char **value,
+ int *vlen
+)
+{
+ char *p, *s, *d, *byte, *stop;
+ char nib;
+ int i = 0, b64 = 0;
+
+ int url = 0;
+
+ /* skip any leading space */
+ while ( isspace( *line ) ) {
+ line++;
+ }
+ *type = line;
+
+ for ( s = line; *s && *s != ':'; s++ )
+ ; /* NULL */
+ if ( *s == '\0' ) {
+ Debug( LDAP_DEBUG_PARSE, catgets(slapdcat, 1, 263, "parse_line missing ':'\n"), 0, 0, 0 );
+ return( -1 );
+ }
+
+ /* trim any space between type and : */
+ for ( p = s - 1; p > line && isspace( *p ); p-- ) {
+ *p = '\0';
+ }
+ *s++ = '\0';
+
+ /* check for double : - indicates base 64 encoded value */
+ if ( *s == ':' ) {
+ s++;
+ b64 = 1;
+
+ } else if ( *s == '<' ) { /* the value indicates an url */
+ s++;
+ url = 1;
+
+ } else { /* single : - normally encoded value */
+ b64 = 0;
+ }
+
+ /* skip space between : and value */
+ while ( isspace( *s ) ) {
+ s++;
+ }
+
+ /* if no value is present, error out */
+ if ( *s == '\0' ) {
+ Debug( LDAP_DEBUG_PARSE, catgets(slapdcat, 1, 264, "parse_line missing value\n"), 0,0,0 );
+ return( -1 );
+ }
+
+ /* check for continued line markers that should be deleted */
+ for ( p = s, d = s; *p; p++ ) {
+ if ( *p != CONTINUED_LINE_MARKER )
+ *d++ = *p;
+ }
+ *d = '\0';
+
+ if ( b64 ) {
+ *value = s;
+ stop = strchr( s, '\0' );
+ byte = s;
+ for ( p = s, *vlen = 0; p < stop; p += 4, *vlen += 3 ) {
+ for ( i = 0; i < 3; i++ ) {
+ if ( p[i] != '=' && (p[i] & 0x80 ||
+ b642nib[ p[i] & 0x7f ] > 0x3f) ) {
+ Debug( LDAP_DEBUG_ANY,
+ catgets(slapdcat, 1, 265, "invalid base 64 encoding char (%1$c) 0x%2$x\n"),
+ p[i], p[i], 0 );
+ return( -1 );
+ }
+ }
+
+ /* first digit */
+ nib = b642nib[ p[0] & 0x7f ];
+ byte[0] = nib << 2;
+ /* second digit */
+ nib = b642nib[ p[1] & 0x7f ];
+ byte[0] |= nib >> 4;
+ byte[1] = (nib & RIGHT4) << 4;
+ /* third digit */
+ if ( p[2] == '=' ) {
+ *vlen += 1;
+ break;
+ }
+ nib = b642nib[ p[2] & 0x7f ];
+ byte[1] |= nib >> 2;
+ byte[2] = (nib & RIGHT2) << 6;
+ /* fourth digit */
+ if ( p[3] == '=' ) {
+ *vlen += 2;
+ break;
+ }
+ nib = b642nib[ p[3] & 0x7f ];
+ byte[2] |= nib;
+
+ byte += 3;
+ }
+ s[ *vlen ] = '\0';
+ } else if ( url ) { /* checks that the url is properly formed */
+ /* file://[localhost]/<pathname> */
+ /* value contains the content of the file */
+ char * s2;
+ char * filename;
+
+ FILE *fp;
+ int rlen;
+ int eof;
+
+
+ if ( strncmp(s, "file://localhost", 16) == 0 )
+ {
+ s = s+16;
+ }
+ else if ( strncmp(s, "file://", 7) == 0 )
+ {
+ s = s+7;
+ }
+ else
+ {
+ /* url badly formed */
+ Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1289, "invalid url %s\n"), s, 0, 0);
+ return -1;
+ }
+
+ filename = strdup(s);
+
+ /* now we have the filename, read its content and return the value */
+ if (( fp = fopen( filename, "r" )) == NULL )
+ {
+ perror( filename );
+ return( -1 );
+ }
+
+ if ( fseek( fp, 0, SEEK_END ) != 0 )
+ {
+ perror( filename );
+ fclose( fp );
+ return( -1 );
+ }
+
+ *vlen = ftell(fp);
+ if ( (*value = (char *)malloc(*vlen)) == NULL )
+ {
+ perror("malloc");
+ fclose(fp);
+ return(-1);
+ }
+ if ( fseek( fp, 0, SEEK_SET ) != 0 )
+ {
+ perror( filename );
+ fclose( fp );
+ return( -1 );
+ }
+
+ rlen = fread( *value, 1, *vlen, fp );
+ eof = feof( fp );
+ fclose( fp );
+
+ if ( rlen != *vlen )
+ {
+ perror( filename );
+ return( -1 );
+ }
+
+ } else {
+ *value = s;
+ *vlen = (int) (d - s);
+ }
+
+ return( 0 );
+}
+
+/*
+ * str_getline - return the next "line" (minus newline) of input from a
+ * string buffer of lines separated by newlines, terminated by \n\n
+ * or \0. this routine handles continued lines, bundling them into
+ * a single big line before returning. if a line begins with a white
+ * space character, it is a continuation of the previous line. the white
+ * space character (nb: only one char), and preceeding newline are changed
+ * into CONTINUED_LINE_MARKER chars, to be deleted later by the
+ * str_parse_line() routine above.
+ *
+ * it takes a pointer to a pointer to the buffer on the first call,
+ * which it updates and must be supplied on subsequent calls.
+ */
+
+char *
+str_getline( char **next )
+{
+ char *l;
+ char c;
+
+ if ( *next == NULL || **next == '\n' || **next == '\0' ) {
+ return( NULL );
+ }
+
+ l = *next;
+ while ( (*next = strchr( *next, '\n' )) != NULL ) {
+ c = *(*next + 1);
+ if ( isspace( c ) && c != '\n' ) {
+ **next = CONTINUED_LINE_MARKER;
+ *(*next+1) = CONTINUED_LINE_MARKER;
+ } else {
+ *(*next)++ = '\0';
+ break;
+ }
+ *(*next)++;
+ }
+
+ return( l );
+}
+
+void
+put_type_and_value( char **out, char *t, char *val, int vlen )
+{
+ unsigned char *byte, *p, *stop;
+ unsigned char buf[3];
+ unsigned int bits;
+ char *save;
+ int i, b64, pad, len, savelen;
+ len = 0;
+
+ /* put the type + ": " */
+ for ( p = (unsigned char *) t; *p; p++, len++ ) {
+ *(*out)++ = *p;
+ }
+ *(*out)++ = ':';
+ len++;
+ save = *out;
+ savelen = len;
+ *(*out)++ = ' ';
+ b64 = 0;
+
+ stop = (unsigned char *) (val + vlen);
+ if ( isascii( val[0] ) && isspace( val[0] ) || val[0] == ':' ) {
+ b64 = 1;
+ } else {
+ for ( byte = (unsigned char *) val; byte < stop;
+ byte++, len++ ) {
+ if ( !isascii( *byte ) || !isprint( *byte ) ) {
+ b64 = 1;
+ break;
+ }
+ if ( len > LINE_WIDTH ) {
+ *(*out)++ = '\n';
+ *(*out)++ = ' ';
+ len = 1;
+ }
+ *(*out)++ = *byte;
+ }
+ }
+ if ( b64 ) {
+ *out = save;
+ *(*out)++ = ':';
+ *(*out)++ = ' ';
+ len = savelen + 2;
+ /* convert to base 64 (3 bytes => 4 base 64 digits) */
+ for ( byte = (unsigned char *) val; byte < stop - 2;
+ byte += 3 ) {
+ bits = (byte[0] & 0xff) << 16;
+ bits |= (byte[1] & 0xff) << 8;
+ bits |= (byte[2] & 0xff);
+
+ for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
+ if ( len > LINE_WIDTH ) {
+ *(*out)++ = '\n';
+ *(*out)++ = ' ';
+ len = 1;
+ }
+
+ /* get b64 digit from high order 6 bits */
+ *(*out)++ = nib2b64[ (bits & 0xfc0000) >> 18 ];
+ }
+ }
+
+ /* add padding if necessary */
+ if ( byte < stop ) {
+ for ( i = 0; byte + i < stop; i++ ) {
+ buf[i] = byte[i];
+ }
+ for ( pad = 0; i < 3; i++, pad++ ) {
+ buf[i] = '\0';
+ }
+ byte = buf;
+ bits = (byte[0] & 0xff) << 16;
+ bits |= (byte[1] & 0xff) << 8;
+ bits |= (byte[2] & 0xff);
+
+ for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
+ if ( len > LINE_WIDTH ) {
+ *(*out)++ = '\n';
+ *(*out)++ = ' ';
+ len = 1;
+ }
+
+ /* get b64 digit from low order 6 bits */
+ *(*out)++ = nib2b64[ (bits & 0xfc0000) >> 18 ];
+ }
+
+ for ( ; pad > 0; pad-- ) {
+ *(*out - pad) = '=';
+ }
+ }
+ }
+ *(*out)++ = '\n';
+}
+
+
+char *
+ldif_type_and_value( char *type, char *val, int vlen )
+/*
+ * return malloc'd, zero-terminated LDIF line
+ */
+{
+ char *buf, *p;
+ int tlen;
+
+ buf=NULL;
+ tlen = strlen( type );
+ if (( buf = (char *)malloc( LDIF_SIZE_NEEDED( tlen, vlen ) + 1 )) !=
+ NULL ) {
+
+ p = buf;
+ put_type_and_value( &p, type, val, vlen );
+ *p = '\0';
+ }
+ return( buf );
+}
diff --git a/usr/src/lib/libldap4/util/log.c b/usr/src/lib/libldap4/util/log.c
new file mode 100644
index 0000000000..29ea85a644
--- /dev/null
+++ b/usr/src/lib/libldap4/util/log.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <nl_types.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <syslog.h>
+#include <portable.h>
+/* #include <lthread.h> */
+#include <pthread.h>
+#include <thread.h>
+
+#include "log.h"
+
+#define LDAP_DEBUG_ANY 0xffff
+
+static pthread_mutex_t log_mutex;
+static char logfile[PATH_MAX] =
+ "/var/opt/SUNWconn/ldap/log/slapd.log";
+static int logsize = 512000;
+static int logtime = 1;
+static FILE *logfd = NULL;
+static int syslogopen = 0;
+pthread_mutex_t systime_mutex;
+nl_catd sundscat;
+static int log_debug = LDAP_DEBUG_STATS;
+
+typedef struct _logctx {
+ char *logfile;
+ int syslogopen;
+ int logsize;
+ pthread_mutex_t log_mutex;
+ int log_debug;
+ int log_syslog;
+
+} LogCtx;
+
+void
+ldaplogconfig(char *logf, int size)
+{
+ strcpy(logfile, logf);
+ logsize = size * 1024;
+}
+
+void
+ldaplogconfigf(FILE *fd)
+{
+ logfd = fd;
+ logsize = 0;
+}
+
+void
+ldaploginit(char *name, int facility)
+{
+ openlog(name, OPENLOG_OPTIONS, facility);
+ syslogopen = 1;
+ pthread_mutex_init(&log_mutex, NULL);
+}
+
+void
+ldaploginitlevel(char *name, int facility, int level)
+{
+ ldaploginit(name, facility);
+ log_debug = level;
+}
+
+LogCtx *
+sundsloginit(char *name, int facility, int debug_level, int syslog_level)
+{
+ LogCtx *returnCtx = NULL;
+
+ if ((returnCtx = (LogCtx *)malloc(sizeof (LogCtx))) == NULL)
+ return (NULL);
+ if ((returnCtx->logfile = strdup(name)) == NULL) {
+ free(returnCtx);
+ return (NULL);
+ }
+ openlog(returnCtx->logfile, OPENLOG_OPTIONS, facility);
+ returnCtx->syslogopen = 1;
+ pthread_mutex_init(&(returnCtx->log_mutex), NULL);
+ returnCtx->log_debug = debug_level;
+ returnCtx->log_syslog = syslog_level;
+ return (returnCtx);
+}
+
+static char timestr[128];
+static time_t timelast = 0;
+
+/*VARARGS*/
+void
+ldaplog(int level, char *fmt, ...)
+{
+ va_list ap;
+ struct stat statbuf = {0};
+ char newlog1[PATH_MAX];
+ char newlog2[PATH_MAX];
+ time_t now;
+ int i;
+
+ if (!(log_debug & level))
+ return;
+
+ va_start(ap, fmt);
+
+ if (level == LDAP_DEBUG_ANY) {
+ /*
+ * this message is probably an error message, send it to syslog
+ */
+ if (syslogopen) {
+ vsyslog(LOG_ERR, fmt, ap);
+ } /* end if */
+ /* and sent it also on stderr */
+ vfprintf(stderr, fmt, ap);
+ } /* end if */
+
+ /*
+ * check that the log file is not already too big
+ */
+ pthread_mutex_lock(&log_mutex);
+ if ((logsize > 0) && (stat(logfile, &statbuf) == 0 &&
+ statbuf.st_size > logsize)) {
+ for (i = 9; i > 1; i--) {
+ (void) sprintf(newlog1, "%s.%d", logfile, i-1);
+ (void) sprintf(newlog2, "%s.%d", logfile, i);
+ (void) rename(newlog1, newlog2);
+ } /* end for */
+ if (logfd) {
+ fclose(logfd);
+ logfd = NULL;
+ } /* end if */
+ (void) rename(logfile, newlog1);
+ } /* end if */
+ /*
+ * send the message into a regular log file
+ */
+ if (!logfd) {
+ logfd = fopen(logfile, "a");
+ } /* end if */
+ /*
+ * finally write the message into the log file
+ */
+ if (logfd) {
+ if (logtime) {
+ time(&now);
+ if (now-timelast > 60) {
+ pthread_mutex_lock(&systime_mutex);
+ timelast = now;
+ ctime_r(&now, timestr, 128);
+ pthread_mutex_unlock(&systime_mutex);
+ } /* end if */
+ fprintf(logfd, "%.16s : ", timestr);
+ } /* end if */
+ vfprintf(logfd, fmt, ap);
+ fflush(logfd);
+ } /* end if */
+ pthread_mutex_unlock(&log_mutex);
+ va_end(ap);
+}