diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libldap4 | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libldap4')
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 *)<ag, 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, <ag, 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(¤t_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); +} |
