diff --git a/contrib/ldapsasl/README b/contrib/ldapsasl/README new file mode 100644 index 0000000000000000000000000000000000000000..36c3f6b9902cb48ac1cd0922b4e595cf01ba9bb4 --- /dev/null +++ b/contrib/ldapsasl/README @@ -0,0 +1,50 @@ +LDAP auxprop plugin for SASL-enabled servers. +Copyright (C) 2002 by Howard Chu, hyc@symas.com + +This software is an experimental proof-of-concept and is not intended for +general use. It is licensed under the terms ofthe OpenLDAP license. + +The file ldapdb.c was written for Cyrus SASL 2.1.3 and OpenLDAP 2.1.3. +It can be compiled by copying into the Cyrus SASL source tree, in the +plugins subdirectory. No configuration or build script is provided. + +To compile, type "make ldapdb.lo". To link, you'll have to copy the +link rule for one of the other plugins. Below is a sample on my Linux +system: + + /bin/sh ./libtool --mode=link gcc -Wall -W -g -O2 -L/usr/local/lib -Wl,-rpath,/usr/local/lib -module -export-dynamic -rpath /usr/lib/sasl2 -o libldapdb.la -version-info 2:4:0 ldapdb.lo -lldap -llber -lssl -lcrypto + +Once installed, you need to add some config items to the SASL server's +config file in /usr/lib/sasl2. For example: + +ldapdb_uri: ldapi:// +ldapdb_id: root +ldapdb_pw: secret +ldapdb_mech: PLAIN + +This config assumes an LDAP server on the same machine as the server +that is using SASL. The LDAP server must be configured to map the SASL +authcId "root" into a DN that has proxy authorization privileges to +every account that is allowed to login to this server. (See the OpenLDAP +Admin Guide for details.) + +Unlike other LDAP-enabled plugins for other services that are common +on the web, this plugin does not require you to configure DN search +patterns to map usernames to LDAP DNs. This plugin requires SASL name +mapping to be configured on the target slapd. This approach keeps the +LDAP-specific configuration details in one place, the slapd.conf, and +makes the configuration of remote services much simpler. + +One additional keyword "ldapdb_rc" may be specified in the config file. +The filename specified here will be put into the server's LDAPRC +environment variable, and libldap-specific config options may be set +in that ldaprc file. The main purpose behind this option is to allow +a client TLS certificate to be configured, so that SASL/EXTERNAL may +be used between the SASL server and the LDAP server. This is the most +optimal way to use this plugin when the servers are on separate machines. + +This plugin likely has very poor performance. You'll need something +better for a real production environment. Please send feedback via the +openldap-software mailing list for now. + + -- Howard Chu, 2002-07-12 diff --git a/contrib/ldapsasl/ldapdb.c b/contrib/ldapsasl/ldapdb.c new file mode 100644 index 0000000000000000000000000000000000000000..0772aeafa20ee33e8e23f7388b05146ff87bc34f --- /dev/null +++ b/contrib/ldapsasl/ldapdb.c @@ -0,0 +1,220 @@ +/* SASL LDAP auxprop implementation + * Copyright (C) 2002 Howard Chu, hyc@symas.com + */ + +#include <config.h> + +#include <stdio.h> + +#include "sasl.h" +#include "saslutil.h" +#include "saslplug.h" + +#include "plugin_common.h" + +#include <ldap.h> + +static char ldapdb[] = "ldapdb"; + +SASL_AUXPROP_PLUG_INIT( ldapdb ) + +typedef struct ldapctx { + const char *uri; /* URI of LDAP server */ + const char *id; /* SASL authcid to bind as */ + const char *pw; /* password for bind */ + const char *mech; /* SASL mech */ +} ldapctx; + +typedef struct gluectx { + ldapctx *lc; + sasl_server_params_t *lp; + const char *user; +} gluectx; + +static int ldapdb_interact(LDAP *ld, unsigned flags __attribute__((unused)), + void *def, void *inter) +{ + sasl_interact_t *in = inter; + gluectx *gc = def; + const char *p; + + for (;in->id != SASL_CB_LIST_END;in++) + { + p = NULL; + switch(in->id) + { + case SASL_CB_GETREALM: + ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &p); + break; + case SASL_CB_AUTHNAME: + p = gc->lc->id; + break; + case SASL_CB_PASS: + p = gc->lc->pw; + break; + case SASL_CB_USER: + p = gc->user; + break; + } + if (p) + { + int l = strlen(p); + in->result = gc->lp->utils->malloc(l+1); + if (!in->result) + return LDAP_NO_MEMORY; + strcpy((char *)in->result, p); + in->len = l; + } + } + return LDAP_SUCCESS; +} + +static void ldapdb_auxprop_lookup(void *glob_context, + sasl_server_params_t *sparams, + unsigned flags, + const char *user, + unsigned ulen) +{ + ldapctx *ctx = glob_context; + int ret, i, n, *aindx; + const struct propval *pr; + LDAP *ld = NULL; + gluectx gc = { ctx, sparams, NULL }; + struct berval *dn = NULL, **bvals; + LDAPMessage *msg, *res; + char **attrs = NULL, *authzid = NULL; + + if(!ctx || !sparams || !user) return; + + pr = sparams->utils->prop_get(sparams->propctx); + if(!pr) return; + + /* count how many attrs to fetch */ + for(i = 0, n = 0; pr[i].name; i++) { + if(pr[i].name[0] == '*' && (flags & SASL_AUXPROP_AUTHZID)) + continue; + if(pr[i].values && !(flags & SASL_AUXPROP_OVERRIDE)) + continue; + n++; + } + /* nothing to do, bail out */ + if (!n) return; + + /* alloc an array of attr names for search, and index to the props */ + attrs = sparams->utils->malloc((n+1)*sizeof(char *)*2); + if (!attrs) return; + + aindx = (int *)(attrs + n + 1); + + /* copy attr list */ + for (i=0, n=0; pr[i].name; i++) { + if(pr[i].name[0] == '*' && (flags & SASL_AUXPROP_AUTHZID)) + continue; + if(pr[i].values && !(flags & SASL_AUXPROP_OVERRIDE)) + continue; + attrs[n] = (char *)pr[i].name; + if (pr[i].name[0] == '*') attrs[n]++; + aindx[n] = i; + n++; + } + attrs[n] = NULL; + + if(ldap_initialize(&ld, ctx->uri)) { + sparams->utils->free(attrs); + return; + } + + authzid = sparams->utils->malloc(ulen + sizeof("u:")); + if (!authzid) goto done; + strcpy(authzid, "u:"); + strcpy(authzid+2, user); + gc.user = authzid; + + i = LDAP_VERSION3; + ret = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &i); + + ret = ldap_sasl_interactive_bind_s(ld, NULL, ctx->mech, NULL, NULL, + LDAP_SASL_QUIET, ldapdb_interact, &gc); + if (ret != LDAP_SUCCESS) goto done; + + ret = ldap_extended_operation_s(ld, LDAP_EXOP_X_WHO_AM_I, NULL, NULL, + NULL, NULL, &dn); + if (ret != LDAP_SUCCESS || !dn) goto done; + + if (dn->bv_val && !strncmp(dn->bv_val, "dn:", 3)) + ret = ldap_search_s(ld, dn->bv_val+3, LDAP_SCOPE_BASE, "(objectclass=*)", + attrs, 0, &res); + ber_bvfree(dn); + + if (ret != LDAP_SUCCESS) goto done; + + for(msg=ldap_first_message(ld, res); msg; msg=ldap_next_message(ld, msg)) + { + if (ldap_msgtype(msg) != LDAP_RES_SEARCH_ENTRY) continue; + for (i=0; i<n; i++) + { + bvals = ldap_get_values_len(ld, msg, attrs[i]); + if (!bvals) continue; + if (pr[aindx[i]].values) + sparams->utils->prop_erase(sparams->propctx, pr[aindx[i]].name); + sparams->utils->prop_set(sparams->propctx, pr[aindx[i]].name, + bvals[0]->bv_val, bvals[0]->bv_len); + ber_bvecfree(bvals); + } + } + ldap_msgfree(res); + + done: + if(authzid) sparams->utils->free(authzid); + if(attrs) sparams->utils->free(attrs); + if(ld) ldap_unbind(ld); +} + +static void ldapdb_auxprop_free(void *glob_ctx, const sasl_utils_t *utils) +{ + utils->free(glob_ctx); +} + +static sasl_auxprop_plug_t ldapdb_auxprop_plugin = { + 0, /* Features */ + 0, /* spare */ + NULL, /* glob_context */ + ldapdb_auxprop_free, /* auxprop_free */ + ldapdb_auxprop_lookup, /* auxprop_lookup */ + ldapdb, /* name */ + NULL /* spare */ +}; + +int ldapdb_auxprop_plug_init(const sasl_utils_t *utils, + int max_version, + int *out_version, + sasl_auxprop_plug_t **plug, + const char *plugname __attribute__((unused))) +{ + ldapctx tmp, *p; + const char *s; + + if(!out_version || !plug) return SASL_BADPARAM; + + if(max_version < SASL_AUXPROP_PLUG_VERSION) return SASL_BADVERS; + + utils->getopt(utils->getopt_context, ldapdb, "ldapdb_uri", &tmp.uri, NULL); + if(!tmp.uri) return SASL_BADPARAM; + + utils->getopt(utils->getopt_context, ldapdb, "ldapdb_id", &tmp.id, NULL); + utils->getopt(utils->getopt_context, ldapdb, "ldapdb_pw", &tmp.pw, NULL); + utils->getopt(utils->getopt_context, ldapdb, "ldapdb_mech", &tmp.mech, NULL); + utils->getopt(utils->getopt_context, ldapdb, "ldapdb_rc", &s, NULL); + if(s && setenv("LDAPRC", s, 1)) return SASL_BADPARAM; + + p = utils->malloc(sizeof(ldapctx)); + if (!p) return SASL_NOMEM; + *p = tmp; + ldapdb_auxprop_plugin.glob_context = p; + + *out_version = SASL_AUXPROP_PLUG_VERSION; + + *plug = &ldapdb_auxprop_plugin; + + return SASL_OK; +} diff --git a/libraries/Makefile.in b/libraries/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..f07cb00fde2967a4160abf09d9a13793b6e10071 --- /dev/null +++ b/libraries/Makefile.in @@ -0,0 +1,10 @@ +# $OpenLDAP$ +## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file +## +## Libraries Makefile for OpenLDAP + +SUBDIRS= liblutil liblunicode libldif \ + liblber libldap libldap_r \ + libavl libldbm librewrite + diff --git a/libraries/libavl/Makefile.in b/libraries/libavl/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..f9c8e4402837a04aefc96ca9162a6889bee9a057 --- /dev/null +++ b/libraries/libavl/Makefile.in @@ -0,0 +1,20 @@ +# $OpenLDAP$ +## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file +## +## LIBAVL +## + +SRCS = avl.c testavl.c +XSRCS = version.c +OBJS = avl.o + +LDAP_INCDIR= ../../include +LDAP_LIBDIR= ../../libraries + +LIBRARY = libavl.a +PROGRAMS = testavl +XLIBS = $(LIBRARY) $(LDAP_LIBLBER_LA) $(LDAP_LIBLUTIL_A) + +testavl: $(XLIBS) testavl.o + $(LTLINK) -o $@ testavl.o $(LIBS) diff --git a/libraries/liblber/Makefile.in b/libraries/liblber/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..87da85611af1df06b5fab412db614d79de313cb6 --- /dev/null +++ b/libraries/liblber/Makefile.in @@ -0,0 +1,40 @@ +# $OpenLDAP$ +## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file +## +## LIBLBER +## + +LIBRARY = liblber.la + +NT_SRCS = nt_err.c +NT_OBJS = nt_err.lo + +LIB_DEFS = -DLBER_LIBRARY + +SRCS= assert.c decode.c encode.c io.c bprint.c debug.c \ + memory.c options.c sockbuf.c $(@PLAT@_SRCS) +OBJS= assert.lo decode.lo encode.lo io.lo bprint.lo debug.lo\ + memory.lo options.lo sockbuf.lo $(@PLAT@_OBJS) +XSRCS= version.c + +PROGRAMS= dtest etest idtest + +LDAP_INCDIR= ../../include +LDAP_LIBDIR= ../../libraries + +XLIBS = $(LIBRARY) $(LDAP_LIBLUTIL_A) +XXLIBS = +NT_LINK_LIBS = $(AC_LIBS) + +dtest: $(XLIBS) dtest.o + $(LTLINK) -o $@ dtest.o $(LIBS) +etest: $(XLIBS) etest.o + $(LTLINK) -o $@ etest.o $(LIBS) +idtest: $(XLIBS) idtest.o + $(LTLINK) -o $@ idtest.o $(LIBS) + +install-local: FORCE + -$(MKDIR) $(DESTDIR)$(libdir) + $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir) + diff --git a/libraries/liblutil/debug.c b/libraries/liblber/debug.c similarity index 61% rename from libraries/liblutil/debug.c rename to libraries/liblber/debug.c index 1d47361d8e53adca94a876b002583d017f21a518..8d182d83f26ded57b6ec693c80fbf901cf9b5991 100644 --- a/libraries/liblutil/debug.c +++ b/libraries/liblber/debug.c @@ -12,6 +12,7 @@ #include <ac/stdlib.h> #include <ac/string.h> #include <ac/time.h> +#include <ac/ctype.h> #ifdef LDAP_SYSLOG #include <ac/syslog.h> @@ -20,6 +21,7 @@ #include "ldap_log.h" #include "ldap_defaults.h" #include "lber.h" +#include "ldap_pvt.h" struct DEBUGLEVEL { @@ -27,7 +29,7 @@ struct DEBUGLEVEL int level; }; -static struct DEBUGLEVEL **levelArray; +int ldap_loglevels[LDAP_SUBSYS_NUM]; static long numLevels = 0; static FILE *log_file = NULL; @@ -56,6 +58,39 @@ static char *lutil_levels[] = {"emergency", "alert", "critical", "results", "detail1", "detail2", NULL}; +static char *lutil_subsys[LDAP_SUBSYS_NUM] = {"global","operation", "transport", + "connection", "filter", "ber", + "config", "acl", "cache", "index", + "ldif", "tools", "slapd", "slurpd", + "backend", "back_bdb", "back_ldbm", + "back_ldap", "back_meta", "back_mon" }; + +int lutil_mnem2subsys( const char *subsys ) +{ + int i; + for( i = 0; i < LDAP_SUBSYS_NUM; i++ ) + { + if ( !strcasecmp( subsys, lutil_subsys[i] ) ) + { + return i; + } + } + return -1; +} + +void lutil_set_all_backends( level ) +{ + int i; + + for( i = 0; i < LDAP_SUBSYS_NUM; i++ ) + { + if ( !strncasecmp( "back_", lutil_subsys[i], strlen("back_") ) ) + { + ldap_loglevels[i] = level; + } + } +} + int lutil_mnem2level( const char *level ) { int i; @@ -66,47 +101,38 @@ int lutil_mnem2level( const char *level ) return i; } } - return 0; + return -1; } -static void addSubsys( const char *subsys, int level ) +static int addSubsys( const char *subsys, int level ) { - int i, j; + int subsys_num; - if ( !strcasecmp( subsys, "global") ) global_level = level; - - for( i = 0; i < numLevels; i++ ) + if ( !strcasecmp( subsys, "backend" ) ) { - if ( levelArray[i] == NULL ) - { - levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) ); - levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 ); - strcpy ( levelArray[i]->subsystem, subsys ); - levelArray[i]->level = level; - return; - } - if( !strcasecmp( subsys, levelArray[i]->subsystem ) ) - { - levelArray[i]->level = level; - return; - } + lutil_set_all_backends( level ); + return level; } - levelArray = (struct DEBUGLEVEL**)ber_memrealloc( levelArray, sizeof( struct DEBUGLEVEL* ) * (numLevels + 10) ); - for( j = numLevels; j < (numLevels + 10); j++ ) + else { - levelArray[j] = NULL; + subsys_num = lutil_mnem2subsys(subsys); + if(subsys_num < 0) + { + fprintf(stderr, "Unknown Subsystem name [ %s ] - Discarded\n", + subsys); + fflush(stderr); + return -1; + } + + ldap_loglevels[subsys_num] = level; + return level; } - numLevels += 10; - levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) ); - levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 ); - strcpy( levelArray[i]->subsystem, subsys ); - levelArray[i]->level = level; - return; + return -1; } -void lutil_set_debug_level( const char* subsys, int level ) +int lutil_set_debug_level( const char* subsys, int level ) { - addSubsys( subsys, level ); + return( addSubsys( subsys, level ) ); } int lutil_debug_file( FILE *file ) @@ -126,33 +152,25 @@ void lutil_log_int( time_t now; struct tm *today; #endif - int i; - - if ( levelArray == NULL ) return; /* logging isn't set up */ + size_t i; + char * t_subsys; + char * tmp; - /* - * Look for the subsystem in the level array. When we find it, - * break out of the loop. - */ - for( i = 0; i < numLevels; i++ ) { - if ( levelArray[i] == NULL ) break; - if ( ! strcasecmp( levelArray[i]->subsystem, subsys ) ) break; - } - - /* - * If we didn't find the subsystem, or the set level is less than - * the requested output level, don't output it. - */ - if ( (level > global_level) && - ((i > numLevels ) || (levelArray[i] == NULL) || ( level > levelArray[i]->level )) ) - { - return; - } + t_subsys = strdup(subsys); + + for(tmp = t_subsys, i = 0; i < strlen(t_subsys); i++, tmp++) + *tmp = TOUPPER( (unsigned char) *tmp ); #ifdef LDAP_SYSLOG /* we're configured to use syslog */ if( use_syslog ) { +#ifdef HAVE_VSYSLOG vsyslog( debug2syslog(level), fmt, vl ); +#else + char data[4096]; + vsnprintf( data, sizeof(data), fmt, vl ); + syslog( debug2syslog(level), data ); +#endif return; } #endif @@ -198,7 +216,10 @@ void lutil_log_int( /* * format the output data. */ + + fprintf(file, "\n%s:: ", t_subsys ); vfprintf( file, fmt, vl ); + fflush( file ); } /* @@ -206,13 +227,13 @@ void lutil_log_int( * level of the log output and the format and data. Send this on to the * internal routine with the print file, if any. */ -void lutil_log( const char *subsys, int level, const char *fmt, ... ) +void lutil_log( const int subsys, int level, const char *fmt, ... ) { FILE* outfile = NULL; va_list vl; va_start( vl, fmt ); ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile ); - lutil_log_int( outfile, subsys, level, fmt, vl ); + lutil_log_int( outfile, lutil_subsys[subsys], level, fmt, vl ); va_end( vl ); } @@ -232,32 +253,38 @@ void lutil_log_initialize(int argc, char **argv) */ for( i = 0; i < argc; i++ ) { - char *next = argv[i]; - if ( i < argc-1 && next[0] == '-' && next[1] == 'd' ) - { - char subsys[64]; - int level; - char *optarg = argv[i+1]; - char *index = strchr( optarg, '=' ); - if ( index != NULL ) - { - *index = 0; - strcpy ( subsys, optarg ); - level = atoi( index+1 ); - if ( level <= 0 ) level = lutil_mnem2level( index + 1 ); - lutil_set_debug_level( subsys, level ); - *index = '='; - } - else - { - global_level = atoi( optarg ); - /* - * if a negative number was used, make the global level the - * maximum sane level. - */ - if ( global_level < 0 ) global_level = 65535; - } - } + char *next = argv[i]; + + if ( i < argc-1 && next[0] == '-' && next[1] == 'd' ) + { + char subsys[64]; + int level; + char *optarg = argv[i+1]; + char *index = strchr( optarg, '=' ); + if ( index != NULL ) + { + *index = 0; + strcpy ( subsys, optarg ); + level = atoi( index+1 ); + if ( level <= 0 ) level = lutil_mnem2level( index + 1 ); + lutil_set_debug_level( subsys, level ); + *index = '='; + } + else + { + global_level = atoi( optarg ); + ldap_loglevels[0] = global_level; + /* + * if a negative number was used, make the global level the + * maximum sane level. + */ + if ( global_level < 0 ) + { + global_level = 65535; + ldap_loglevels[0] = 65535; + } + } + } } } @@ -296,6 +323,6 @@ void (lutil_debug)( int debug, int level, const char *fmt, ... ) fflush( log_file ); } - fputs( buffer, stderr ); + fputs( buffer, stderr ); va_end( vl ); } diff --git a/libraries/liblber/decode.c b/libraries/liblber/decode.c index a722c9eb7a319a12ad027c85310c1d9c6264ccb4..e69bb496fa0673f09e6397519a45dfa8625427dd 100644 --- a/libraries/liblber/decode.c +++ b/libraries/liblber/decode.c @@ -1,5 +1,10 @@ /* decode.c - ber input decoding routines */ +/* $OpenLDAP$ */ /* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* Portions * Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * @@ -11,88 +16,80 @@ * is provided ``as is'' without express or implied warranty. */ +#include "portable.h" + #include <stdio.h> -#ifdef MACOS -#include <stdlib.h> -#include <stdarg.h> -#include "macos.h" -#else /* MACOS */ -#if defined(NeXT) || defined(VMS) -#include <stdlib.h> -#else /* next || vms */ -#include <malloc.h> -#endif /* next || vms */ -#if defined(BC31) || defined(_WIN32) -#include <stdarg.h> -#else /* BC31 || _WIN32 */ -#include <varargs.h> -#endif /* BC31 || _WIN32 */ -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#ifdef PCNFS -#include <tklib.h> -#endif /* PCNFS */ -#endif /* MACOS */ - -#if defined( DOS ) || defined( _WIN32 ) -#include "msdos.h" -#endif /* DOS */ - -#include <string.h> -#include "lber.h" - -#ifdef LDAP_DEBUG -int lber_debug; -#endif -#ifdef NEEDPROTOS -static int ber_getnint( BerElement *ber, long *num, int len ); -#endif /* NEEDPROTOS */ +#include <ac/stdlib.h> + +#include <ac/stdarg.h> +#include <ac/string.h> +#include <ac/socket.h> +#include "lber-int.h" + +static ber_len_t ber_getnint LDAP_P(( + BerElement *ber, + ber_int_t *num, + ber_len_t len )); /* return the tag - LBER_DEFAULT returned means trouble */ -unsigned long +ber_tag_t ber_get_tag( BerElement *ber ) { unsigned char xbyte; - unsigned long tag; - char *tagp; - int i; + ber_tag_t tag; + unsigned int i; - if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) - return( LBER_DEFAULT ); + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); - if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) - return( (unsigned long) xbyte ); + if ( ber_pvt_ber_remaining( ber ) < 1 ) { + return LBER_DEFAULT; + } - tagp = (char *) &tag; - tagp[0] = xbyte; - for ( i = 1; i < sizeof(long); i++ ) { - if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) - return( LBER_DEFAULT ); + if ( ber->ber_ptr == ber->ber_buf ) + tag = *(unsigned char *)ber->ber_ptr; + else + tag = ber->ber_tag; + ber->ber_ptr++; - tagp[i] = xbyte; + if ( (tag & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { + return tag; + } + + for ( i = 1; i < sizeof(ber_tag_t); i++ ) { + if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) { + return LBER_DEFAULT; + } - if ( ! (xbyte & LBER_MORE_TAG_MASK) ) + tag <<= 8; + tag |= 0x00ffUL & (ber_tag_t) xbyte; + + if ( ! (xbyte & LBER_MORE_TAG_MASK) ) { break; + } } /* tag too big! */ - if ( i == sizeof(long) ) - return( LBER_DEFAULT ); + if ( i == sizeof(ber_tag_t) ) { + return LBER_DEFAULT; + } - /* want leading, not trailing 0's */ - return( tag >> (sizeof(long) - i - 1) ); + return tag; } -unsigned long -ber_skip_tag( BerElement *ber, unsigned long *len ) +ber_tag_t +ber_skip_tag( BerElement *ber, ber_len_t *len ) { - unsigned long tag; + ber_tag_t tag; unsigned char lc; - int noctets, diff; - unsigned long netlen; + ber_len_t i, noctets; + unsigned char netlen[sizeof(ber_len_t)]; + + assert( ber != NULL ); + assert( len != NULL ); + assert( LBER_VALID( ber ) ); /* * Any ber element looks like this: tag length contents. @@ -104,57 +101,93 @@ ber_skip_tag( BerElement *ber, unsigned long *len ) * 2) primitive encodings used whenever possible */ + *len = 0; + /* * First, we read the tag. */ - if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); + 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 long form, + * the length. If bit 8 is set, the length is the long form, * otherwise it's the short form. We don't allow a length that's - * greater than what we can hold in an unsigned long. + * greater than what we can hold in a ber_len_t. */ - *len = netlen = 0; if ( ber_read( ber, (char *) &lc, 1 ) != 1 ) - return( LBER_DEFAULT ); - if ( lc & 0x80 ) { - noctets = (lc & 0x7f); - if ( noctets > sizeof(unsigned long) ) - return( LBER_DEFAULT ); - diff = sizeof(unsigned long) - noctets; - if ( ber_read( ber, (char *) &netlen + diff, noctets ) - != noctets ) - return( LBER_DEFAULT ); - *len = LBER_NTOHL( netlen ); + return LBER_DEFAULT; + + if ( lc & 0x80U ) { + noctets = (lc & 0x7fU); + + if ( noctets > sizeof(ber_len_t) ) { + return LBER_DEFAULT; + } + + if( (unsigned) ber_read( ber, netlen, noctets ) != noctets ) { + return LBER_DEFAULT; + } + + for( i = 0; i < noctets; i++ ) { + *len <<= 8; + *len |= netlen[i]; + } + } else { *len = lc; } - return( tag ); + /* BER length should be non-negative */ + if( *len < 0 ) { + return LBER_DEFAULT; + } + + /* BER element should have enough data left */ + if( *len > (ber_len_t) ber_pvt_ber_remaining( ber ) ) { + return LBER_DEFAULT; + } + ber->ber_tag = *(unsigned char *)ber->ber_ptr; + + return tag; } -unsigned long -ber_peek_tag( BerElement *ber, unsigned long *len ) +ber_tag_t +ber_peek_tag( + BerElement *ber, + ber_len_t *len ) { - char *save; - unsigned long tag; + /* + * This implementation assumes ber_skip_tag() only + * modifies ber_ptr field of the BerElement. + */ + + char *save; + ber_tag_t tag, old; + old = ber->ber_tag; save = ber->ber_ptr; tag = ber_skip_tag( ber, len ); ber->ber_ptr = save; + ber->ber_tag = old; - return( tag ); + return tag; } -static int -ber_getnint( BerElement *ber, long *num, int len ) +static ber_len_t +ber_getnint( + BerElement *ber, + ber_int_t *num, + ber_len_t len ) { - int diff, sign, i; - long netnum; + unsigned char buf[sizeof(ber_int_t)]; + + assert( ber != NULL ); + assert( num != NULL ); + assert( LBER_VALID( ber ) ); /* * The tag and length have already been stripped off. We should @@ -163,281 +196,496 @@ ber_getnint( BerElement *ber, long *num, int len ) * extend after we read it in. */ - if ( len > sizeof(long) ) - return( -1 ); + if ( len > sizeof(ber_int_t) ) { + return -1; + } + + /* read into the low-order bytes of our buffer */ + if ( (ber_len_t) ber_read( ber, (char *) buf, len ) != len ) { + return -1; + } - netnum = 0; - diff = sizeof(long) - len; - /* read into the low-order bytes of netnum */ - if ( ber_read( ber, ((char *) &netnum) + diff, len ) != len ) - return( -1 ); + if( len ) { + /* sign extend if necessary */ + ber_len_t i; + ber_int_t netnum = 0x80 & buf[0] ? -1 : 0; - /* sign extend if necessary */ - sign = ((0x80 << ((len - 1) * 8)) & netnum); - if ( sign && len < sizeof(long) ) { - for ( i = sizeof(long) - 1; i > len - 1; i-- ) { - netnum |= (0xffL << (i * 8)); + /* shift in the bytes */ + for( i=0 ; i<len; i++ ) { + netnum = (netnum << 8 ) | buf[i]; } + + *num = netnum; + + } else { + *num = 0; } - *num = LBER_NTOHL( netnum ); + ber->ber_tag = *(unsigned char *)ber->ber_ptr; - return( len ); + return len; } -unsigned long -ber_get_int( BerElement *ber, long *num ) +ber_tag_t +ber_get_int( + BerElement *ber, + ber_int_t *num ) { - unsigned long tag, len; + ber_tag_t tag; + ber_len_t len; - if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); - if ( ber_getnint( ber, num, (int)len ) != len ) - return( LBER_DEFAULT ); - else - return( tag ); + if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) { + return LBER_DEFAULT; + } + + if ( ber_getnint( ber, num, len ) != len ) { + return LBER_DEFAULT; + } + + return tag; } -unsigned long -ber_get_stringb( BerElement *ber, char *buf, unsigned long *len ) +ber_tag_t +ber_get_enum( + BerElement *ber, + ber_int_t *num ) { - unsigned long datalen, tag; -#ifdef STR_TRANSLATION - char *transbuf; -#endif /* STR_TRANSLATION */ + return ber_get_int( ber, num ); +} - if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); - if ( datalen > (*len - 1) ) - return( LBER_DEFAULT ); +ber_tag_t +ber_get_stringb( + BerElement *ber, + char *buf, + ber_len_t *len ) +{ + ber_len_t datalen; + ber_tag_t tag; - if ( ber_read( ber, buf, datalen ) != datalen ) - return( LBER_DEFAULT ); + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) { + return LBER_DEFAULT; + } + + /* must fit within allocated space with termination */ + if ( datalen >= *len ) { + return LBER_DEFAULT; + } + + if ( (ber_len_t) ber_read( ber, buf, datalen ) != datalen ) { + return LBER_DEFAULT; + } + ber->ber_tag = *(unsigned char *)ber->ber_ptr; 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 ); + *len = datalen; + return tag; +} + +/* Definitions for recursive get_string + * + * ChArray, BvArray, and BvVec are self-explanatory. + * BvOff is a struct berval embedded in an array of larger structures + * of siz bytes at off bytes from the beginning of the struct. + */ +enum bgbvc { ChArray, BvArray, BvVec, BvOff }; + +/* Use this single cookie for state, to keep actual + * stack use to the absolute minimum. + */ +typedef struct bgbvr { + enum bgbvc choice; + BerElement *ber; + ber_tag_t tag; + ber_len_t len; + char *last; + int alloc; + ber_len_t siz; + ber_len_t off; + union { + char ***c; + BerVarray *ba; + struct berval ***bv; + } res; +} bgbvr; + +/* Recursive get_string, for decoding a vector of strings. The number + * of elements in the vector is limited only by available stack space. + * Each invocation consumes 24 bytes of stack on a 32-bit machine. + */ +static ber_tag_t +ber_get_stringbvr( bgbvr *b, int n ) +{ + struct berval bv, *bvp = NULL; + + if ( n ) + b->tag = ber_next_element( b->ber, &b->len, b->last ); + else + b->tag = ber_first_element( b->ber, &b->len, &b->last ); + + if ( b->tag == LBER_DEFAULT ) + { + b->len = n; + + if ( n == 0 ) { + *b->res.c = NULL; + return 0; } - if ( datalen > *len ) { - free( transbuf ); - return( LBER_DEFAULT ); + /* Allocate the result vector */ + switch (b->choice) { + case ChArray: + *b->res.c = LBER_MALLOC( (n+1) * sizeof( char * )); + if ( *b->res.c == NULL ) + return LBER_DEFAULT; + (*b->res.c)[n] = NULL; + break; + case BvArray: + *b->res.ba = LBER_MALLOC( (n+1) * sizeof( struct berval )); + if ( *b->res.ba == NULL ) + return LBER_DEFAULT; + (*b->res.ba)[n].bv_val = NULL; + break; + case BvVec: + *b->res.bv = LBER_MALLOC( (n+1) * sizeof( struct berval *)); + if ( *b->res.bv == NULL ) + return LBER_DEFAULT; + (*b->res.bv)[n] = NULL; + break; + case BvOff: + *b->res.ba = LBER_MALLOC( (n+1) * b->siz ); + if ( *b->res.ba == NULL ) + return LBER_DEFAULT; + ((struct berval *)((long)(*b->res.ba) + n*b->siz + + b->off))->bv_val = NULL; + break; } - SAFEMEMCPY( buf, transbuf, datalen ); - free( transbuf ); - --datalen; + return 0; } -#endif /* STR_TRANSLATION */ - *len = datalen; - return( tag ); + /* Do all local allocs before the recursion. Then there + * cannot possibly be any failures on the return trip. + */ + if ( b->choice == BvVec ) + bvp = LBER_MALLOC( sizeof( struct berval )); + + if ( ber_get_stringbv( b->ber, &bv, b->alloc ) == LBER_DEFAULT ) { + if ( bvp ) LBER_FREE( bvp ); + return LBER_DEFAULT; + } + + b->tag = ber_get_stringbvr( b, n+1 ); + + if ( b->tag == 0 ) + { + /* store my result */ + switch (b->choice) { + case ChArray: + (*b->res.c)[n] = bv.bv_val; + break; + case BvArray: + (*b->res.ba)[n] = bv; + break; + case BvVec: + (*b->res.bv)[n] = bvp; + *bvp = bv; + break; + case BvOff: + *(BerVarray)((long)(*b->res.ba)+n*b->siz+b->off) = bv; + } + } else { + /* Failure will propagate up and free in reverse + * order, which is actually ideal. + */ + if ( b->alloc ) LBER_FREE( bv.bv_val ); + if ( bvp ) LBER_FREE( bvp ); + } + return b->tag; } -unsigned long -ber_get_stringa( BerElement *ber, char **buf ) +ber_tag_t +ber_get_stringbv( BerElement *ber, struct berval *bv, int alloc ) { - unsigned long 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 ); + ber_tag_t tag; + + assert( ber != NULL ); + assert( bv != NULL ); + + assert( LBER_VALID( ber ) ); + + if ( (tag = ber_skip_tag( ber, &bv->bv_len )) == LBER_DEFAULT ) { + bv->bv_val = NULL; + return LBER_DEFAULT; + } + + if ( (ber_len_t) ber_pvt_ber_remaining( ber ) < bv->bv_len ) { + return LBER_DEFAULT; + } + + if ( alloc ) { + if ( (bv->bv_val = (char *) LBER_MALLOC( bv->bv_len + 1 )) == NULL ) { + return LBER_DEFAULT; + } + + if ( bv->bv_len > 0 && (ber_len_t) ber_read( ber, bv->bv_val, + bv->bv_len ) != bv->bv_len ) { + LBER_FREE( bv->bv_val ); + bv->bv_val = NULL; + return LBER_DEFAULT; } + } else { + bv->bv_val = ber->ber_ptr; + ber->ber_ptr += bv->bv_len; } -#endif /* STR_TRANSLATION */ + ber->ber_tag = *(unsigned char *)ber->ber_ptr; + bv->bv_val[bv->bv_len] = '\0'; - return( tag ); + return tag; +} + +ber_tag_t +ber_get_stringa( BerElement *ber, char **buf ) +{ + BerValue bv; + ber_tag_t tag; + + assert( buf != NULL ); + + tag = ber_get_stringbv( ber, &bv, 1 ); + *buf = bv.bv_val; + + return tag; } -unsigned long +ber_tag_t ber_get_stringal( BerElement *ber, struct berval **bv ) { - unsigned long 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; + ber_tag_t tag; + + assert( ber != NULL ); + assert( bv != NULL ); + + *bv = (struct berval *) LBER_MALLOC( sizeof(struct berval) ); + if ( *bv == NULL ) { + return LBER_DEFAULT; } -#endif /* STR_TRANSLATION */ - return( tag ); + tag = ber_get_stringbv( ber, *bv, 1 ); + if ( tag == LBER_DEFAULT ) { + LBER_FREE( *bv ); + *bv = NULL; + } + return tag; } -unsigned long -ber_get_bitstringa( BerElement *ber, char **buf, unsigned long *blen ) +ber_tag_t +ber_get_bitstringa( + BerElement *ber, + char **buf, + ber_len_t *blen ) { - unsigned long datalen, tag; + ber_len_t datalen; + ber_tag_t tag; unsigned char unusedbits; - if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); + assert( ber != NULL ); + assert( buf != NULL ); + assert( blen != NULL ); + + assert( LBER_VALID( ber ) ); + + if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) { + *buf = NULL; + return LBER_DEFAULT; + } --datalen; - if ( (*buf = (char *) malloc( (size_t)datalen )) == NULL ) - return( LBER_DEFAULT ); + if ( (*buf = (char *) LBER_MALLOC( datalen )) == NULL ) { + return LBER_DEFAULT; + } - if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 ) - return( LBER_DEFAULT ); + if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 ) { + LBER_FREE( buf ); + *buf = NULL; + return LBER_DEFAULT; + } - if ( ber_read( ber, *buf, datalen ) != datalen ) - return( LBER_DEFAULT ); + if ( (ber_len_t) ber_read( ber, *buf, datalen ) != datalen ) { + LBER_FREE( buf ); + *buf = NULL; + return LBER_DEFAULT; + } + ber->ber_tag = *(unsigned char *)ber->ber_ptr; *blen = datalen * 8 - unusedbits; - return( tag ); + return tag; } -unsigned long +ber_tag_t ber_get_null( BerElement *ber ) { - unsigned long len, tag; + ber_len_t len; + ber_tag_t tag; + + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); - if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); + if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) { + return LBER_DEFAULT; + } - if ( len != 0 ) - return( LBER_DEFAULT ); + if ( len != 0 ) { + return LBER_DEFAULT; + } + ber->ber_tag = *(unsigned char *)ber->ber_ptr; return( tag ); } -unsigned long -ber_get_boolean( BerElement *ber, int *boolval ) +ber_tag_t +ber_get_boolean( + BerElement *ber, + ber_int_t *boolval ) { - long longbool; - int rc; + ber_int_t longbool; + ber_tag_t rc; + + assert( ber != NULL ); + assert( boolval != NULL ); + + assert( LBER_VALID( ber ) ); rc = ber_get_int( ber, &longbool ); *boolval = longbool; - return( rc ); + return rc; } -unsigned long -ber_first_element( BerElement *ber, unsigned long *len, char **last ) +ber_tag_t +ber_first_element( + BerElement *ber, + ber_len_t *len, + char **last ) { + assert( ber != NULL ); + assert( len != NULL ); + assert( last != NULL ); + /* skip the sequence header, use the len to mark where to stop */ if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) { - return( LBER_DEFAULT ); + *last = NULL; + return LBER_DEFAULT; } + ber->ber_tag = *(unsigned char *)ber->ber_ptr; *last = ber->ber_ptr + *len; if ( *last == ber->ber_ptr ) { - return( LBER_DEFAULT ); + return LBER_DEFAULT; } - return( ber_peek_tag( ber, len ) ); + return ber_peek_tag( ber, len ); } -unsigned long -ber_next_element( BerElement *ber, unsigned long *len, char *last ) +ber_tag_t +ber_next_element( + BerElement *ber, + ber_len_t *len, + LDAP_CONST char *last ) { + assert( ber != NULL ); + assert( len != NULL ); + assert( last != NULL ); + + assert( LBER_VALID( ber ) ); + if ( ber->ber_ptr == last ) { - return( LBER_DEFAULT ); + return LBER_DEFAULT; } - return( ber_peek_tag( ber, len ) ); + return ber_peek_tag( ber, len ); } /* VARARGS */ -unsigned long -ber_scanf( -#if defined( MACOS ) || defined( BC31 ) || defined( _WIN32 ) - BerElement *ber, char *fmt, ... ) -#else - va_alist ) -va_dcl -#endif +ber_tag_t +ber_scanf ( BerElement *ber, + LDAP_CONST char *fmt, + ... ) { va_list ap; -#if !defined( MACOS ) && !defined( BC31 ) && !defined( _WIN32 ) - BerElement *ber; - char *fmt; -#endif + LDAP_CONST char *fmt_reset; + char *s, **ss; +#ifdef TMP_SLOTS char *last; - char *s, **ss, ***sss; - struct berval ***bv, **bvp, *bval; - int *i, j; - long *l, rc, tag; - unsigned long len; + char ***sss; + ber_tag_t tag; + struct berval ***bv; + int j; +#endif + struct berval **bvp, *bval; + ber_int_t *i; + ber_len_t *l; + ber_tag_t *t; + ber_tag_t rc; + ber_len_t len; -#if defined( MACOS ) || defined( BC31 ) || defined( _WIN32 ) 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 ) { - fprintf( stderr, "ber_scanf fmt (%s) ber:\n", fmt ); - ber_dump( ber, 1 ); - } + assert( ber != NULL ); + assert( fmt != NULL ); + + assert( LBER_VALID( ber ) ); + + fmt_reset = fmt; + +#ifdef NEW_LOGGING + LDAP_LOG( BER, ENTRY, "ber_scanf fmt (%s) ber:\n", fmt, 0, 0 ); + + if ( LDAP_LOGS_TEST(BER, DETAIL2 )) + BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 )); +#else + ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, + "ber_scanf fmt (%s) ber:\n", fmt ); + ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 ); #endif for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) { + /* When this is modified, remember to update + * the error-cleanup code below accordingly. */ switch ( *fmt ) { + case '!': { /* Hook */ + BERDecodeCallback *f; + void *p; + + f = va_arg( ap, BERDecodeCallback * ); + p = va_arg( ap, void * ); + + rc = (*f)( ber, p, 0 ); + } break; + case 'a': /* octet string - allocate storage as needed */ ss = va_arg( ap, char ** ); rc = ber_get_stringa( ber, ss ); break; case 'b': /* boolean */ - i = va_arg( ap, int * ); + i = va_arg( ap, ber_int_t * ); rc = ber_get_boolean( ber, i ); break; case 'e': /* enumerated */ case 'i': /* int */ - l = va_arg( ap, long * ); - rc = ber_get_int( ber, l ); + i = va_arg( ap, ber_int_t * ); + rc = ber_get_int( ber, i ); break; case 'l': /* length of next item */ - l = va_arg( ap, long * ); - rc = ber_peek_tag( ber, (unsigned long *)l ); + l = va_arg( ap, ber_len_t * ); + rc = ber_peek_tag( ber, l ); break; case 'n': /* null */ @@ -446,14 +694,18 @@ va_dcl case 's': /* octet string - in a buffer */ s = va_arg( ap, char * ); - l = va_arg( ap, long * ); - rc = ber_get_stringb( ber, s, (unsigned long *)l ); + l = va_arg( ap, ber_len_t * ); + rc = ber_get_stringb( ber, s, l ); + break; + + case 'm': /* octet string in berval, in-place */ + bval = va_arg( ap, struct berval * ); + rc = ber_get_stringbv( ber, bval, 0 ); 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 ); + rc = ber_get_stringbv( ber, bval, 1 ); break; case 'O': /* octet string - allocate & include length */ @@ -463,71 +715,79 @@ va_dcl case 'B': /* bit string - allocate storage as needed */ ss = va_arg( ap, char ** ); - l = va_arg( ap, long * ); /* for length, in bits */ - rc = ber_get_bitstringa( ber, ss, (unsigned long *)l ); + l = va_arg( ap, ber_len_t * ); /* for length, in bits */ + rc = ber_get_bitstringa( ber, ss, l ); break; case 't': /* tag of next item */ - i = va_arg( ap, int * ); - *i = rc = ber_peek_tag( ber, &len ); + t = va_arg( ap, ber_tag_t * ); + *t = rc = ber_peek_tag( ber, &len ); break; case 'T': /* skip tag of next item */ - i = va_arg( ap, int * ); - *i = rc = ber_skip_tag( ber, &len ); + t = va_arg( ap, ber_tag_t * ); + *t = rc = ber_skip_tag( ber, &len ); break; case 'v': /* sequence of strings */ - 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; + { + bgbvr cookie = { ChArray }; + cookie.ber = ber; + cookie.res.c = va_arg( ap, char *** ); + cookie.alloc = 1; + rc = ber_get_stringbvr( &cookie, 0 ); 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; + { + bgbvr cookie = { BvVec }; + cookie.ber = ber; + cookie.res.bv = va_arg( ap, struct berval *** ); + cookie.alloc = 1; + rc = ber_get_stringbvr( &cookie, 0 ); + break; + } + + case 'W': /* bvarray */ + { + bgbvr cookie = { BvArray }; + cookie.ber = ber; + cookie.res.ba = va_arg( ap, struct berval ** ); + cookie.alloc = 1; + rc = ber_get_stringbvr( &cookie, 0 ); break; + } + + case 'M': /* bvoffarray - must include address of + * a record len, and record offset. + * number of records will be returned thru + * len ptr on finish. parsed in-place. + */ + { + bgbvr cookie = { BvOff }; + cookie.ber = ber; + cookie.res.ba = va_arg( ap, struct berval ** ); + cookie.alloc = 0; + l = va_arg( ap, ber_len_t * ); + cookie.siz = *l; + cookie.off = va_arg( ap, ber_len_t ); + rc = ber_get_stringbvr( &cookie, 0 ); + *l = cookie.len; + break; + } case 'x': /* skip the next element - whatever it is */ if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) break; ber->ber_ptr += len; + ber->ber_tag = *(unsigned char *)ber->ber_ptr; break; case '{': /* begin sequence */ case '[': /* begin set */ - if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V' ) + if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V' + && *(fmt + 1) != 'W' && *(fmt + 1) != 'M' ) rc = ber_skip_tag( ber, &len ); break; @@ -536,63 +796,115 @@ va_dcl break; default: -#ifndef NO_USERINTERFACE - fprintf( stderr, "unknown fmt %c\n", *fmt ); -#endif /* NO_USERINTERFACE */ + if( ber->ber_debug ) { +#ifdef NEW_LOGGING + LDAP_LOG( BER, ERR, + "ber_scanf: unknown fmt %c\n", *fmt, 0, 0 ); +#else + ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, + "ber_scanf: unknown fmt %c\n", *fmt ); +#endif + } rc = LBER_DEFAULT; break; } } va_end( ap ); + if ( rc == LBER_DEFAULT ) { + /* + * Error. Reclaim malloced memory that was given to the caller. + * Set allocated pointers to NULL, "data length" outvalues to 0. + */ + va_start( ap, fmt ); - return( rc ); -} + for ( ; fmt_reset < fmt; fmt_reset++ ) { + switch ( *fmt_reset ) { + case '!': { /* Hook */ + BERDecodeCallback *f; + void *p; -void -ber_bvfree( struct berval *bv ) -{ - if ( bv->bv_val != NULL ) - free( bv->bv_val ); - free( (char *) bv ); -} + f = va_arg( ap, BERDecodeCallback * ); + p = va_arg( ap, void * ); -void -ber_bvecfree( struct berval **bv ) -{ - int i; + (void) (*f)( ber, p, 1 ); + } break; - for ( i = 0; bv[i] != NULL; i++ ) - ber_bvfree( bv[i] ); - free( (char *) bv ); -} + case 'a': /* octet string - allocate storage as needed */ + ss = va_arg( ap, char ** ); + if ( *ss ) { + LBER_FREE( *ss ); + *ss = NULL; + } + break; -struct berval * -ber_bvdup( struct berval *bv ) -{ - struct berval *new; + case 'b': /* boolean */ + case 'e': /* enumerated */ + case 'i': /* int */ + (void) va_arg( ap, int * ); + break; - if ( (new = (struct berval *) malloc( sizeof(struct berval) )) - == NULL ) { - return( NULL ); - } - if ( (new->bv_val = (char *) malloc( bv->bv_len + 1 )) == NULL ) { - return( NULL ); - } - 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; + case 's': /* octet string - in a buffer */ + (void) va_arg( ap, char * ); + (void) va_arg( ap, ber_len_t * ); + break; - return( new ); -} + case 'l': /* length of next item */ + (void) va_arg( ap, ber_len_t * ); + break; + case 't': /* tag of next item */ + case 'T': /* skip tag of next item */ + (void) va_arg( ap, ber_tag_t * ); + break; -#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; + case 'o': /* octet string in a supplied berval */ + bval = va_arg( ap, struct berval * ); + if ( bval->bv_val != NULL ) { + LBER_FREE( bval->bv_val ); + bval->bv_val = NULL; + } + bval->bv_len = 0; + break; + + case 'O': /* octet string - allocate & include length */ + bvp = va_arg( ap, struct berval ** ); + if ( *bvp ) { + ber_bvfree( *bvp ); + *bvp = NULL; + } + break; + + case 'B': /* bit string - allocate storage as needed */ + ss = va_arg( ap, char ** ); + if ( *ss ) { + LBER_FREE( *ss ); + *ss = NULL; + } + *(va_arg( ap, ber_len_t * )) = 0; /* for length, in bits */ + break; + + case 'v': /* sequence of strings */ + case 'V': /* sequence of strings + lengths */ + case 'W': /* BerVarray */ + case 'm': /* berval in-place */ + case 'M': /* BVoff array in-place */ + case 'n': /* null */ + case 'x': /* skip the next element - whatever it is */ + case '{': /* begin sequence */ + case '[': /* begin set */ + case '}': /* end sequence */ + case ']': /* end set */ + break; + + default: + /* format should be good */ + assert( 0 ); + } + } + + va_end( ap ); + } + + return rc; } -#endif /* STR_TRANSLATION */ diff --git a/libraries/liblber/encode.c b/libraries/liblber/encode.c index 50eb6b5f9234af5e596f6da5ab4a3c084cada359..fefad6d3ecc6061850a2a800153b940e22118032 100644 --- a/libraries/liblber/encode.c +++ b/libraries/liblber/encode.c @@ -812,8 +812,8 @@ ber_printf( BerElement *ber, LDAP_CONST char *fmt, ... ) default: if( ber->ber_debug ) { #ifdef NEW_LOGGING - LDAP_LOG(( "liblber", LDAP_LEVEL_ERR, - "ber_printf: unknown fmt %c\n", *fmt )); + LDAP_LOG( BER, ERR, + "ber_printf: unknown fmt %c\n", *fmt, 0, 0 ); #else ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "ber_printf: unknown fmt %c\n", *fmt ); diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c index 6474acd56d4f3481d0d48882a35a522644b70145..4e3a1cebd84ad07bcf6a9e510b9cd39d2caa16ab 100644 --- a/libraries/liblber/io.c +++ b/libraries/liblber/io.c @@ -33,6 +33,7 @@ #endif #include "lber-int.h" +#include "ldap_log.h" ber_slen_t ber_read( @@ -207,11 +208,14 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) if ( sb->sb_debug ) { #ifdef NEW_LOGGING - LDAP_LOG(( "liblber", LDAP_LEVEL_DETAIL1, + LDAP_LOG( BER, DETAIL1, "ber_flush: %ld bytes to sd %ld%s\n", towrite, (long)sb->sb_fd, - ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" )); - BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 )); + ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" ); + + if(LDAP_LOGS_TEST(BER, DETAIL2)) + BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 )); + #else ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug, "ber_flush: %ld bytes to sd %ld%s\n", @@ -441,7 +445,7 @@ ber_get_next( assert( LBER_VALID( ber ) ); #ifdef NEW_LOGGING - LDAP_LOG(( "liblber", LDAP_LEVEL_ENTRY, "ber_get_next: enter\n" )); + LDAP_LOG( BER, ENTRY, "ber_get_next: enter\n", 0, 0, 0 ); #else ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, "ber_get_next\n" ); @@ -509,6 +513,8 @@ ber_get_next( ber->ber_ptr = (char *)p; } + if (i == 1) continue; + /* Now look for the length */ if (*ber->ber_ptr & 0x80) { /* multi-byte */ int llen = *(unsigned char *)ber->ber_ptr++ & 0x7f; @@ -548,9 +554,9 @@ ber_get_next( return LBER_DEFAULT; } else if ( sb->sb_max_incoming && ber->ber_len > sb->sb_max_incoming ) { #ifdef NEW_LOGGING - LDAP_LOG(( "liblber", LDAP_LEVEL_ERR, + LDAP_LOG( BER, ERR, "ber_get_next: sockbuf_max_incoming limit hit " - "(%d > %d)\n", ber->ber_len, sb->sb_max_incoming )); + "(%d > %d)\n", ber->ber_len, sb->sb_max_incoming, 0 ); #else ber_log_printf( LDAP_DEBUG_CONNS, ber->ber_debug, "ber_get_next: sockbuf_max_incoming limit hit " @@ -616,10 +622,11 @@ done: *len = ber->ber_len; if ( ber->ber_debug ) { #ifdef NEW_LOGGING - LDAP_LOG(( "liblber", LDAP_LEVEL_DETAIL1, - "ber_get_next: tag 0x%lx len %ld\n", - ber->ber_tag, ber->ber_len )); - BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 )); + LDAP_LOG( BER, DETAIL1, + "ber_get_next: tag 0x%lx len %ld\n", + ber->ber_tag, ber->ber_len, 0 ); + if(LDAP_LOGS_TEST(BER, DETAIL2)) + BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 )); #else ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, "ber_get_next: tag 0x%lx len %ld contents:\n", diff --git a/libraries/liblber/lber-int.h b/libraries/liblber/lber-int.h new file mode 100644 index 0000000000000000000000000000000000000000..1d6ad83ba3a2bb841539d4910cd1f5c9b08a2ecb --- /dev/null +++ b/libraries/liblber/lber-int.h @@ -0,0 +1,207 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* Portions + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + */ + +#ifndef _LBER_INT_H +#define _LBER_INT_H + +#include "lber.h" +#include "ldap_log.h" +#include "lber_pvt.h" +#include "ldap_queue.h" + +LDAP_BEGIN_DECL + +typedef void (*BER_LOG_FN)(FILE *file, + const char *subsys, int level, const char *fmt, ... ); + +LBER_V (BER_ERRNO_FN) ber_int_errno_fn; + +struct lber_options { + short lbo_valid; + unsigned short lbo_options; + int lbo_debug; + long lbo_meminuse; +}; + +#ifdef NEW_LOGGING +/* +# ifdef LDAP_DEBUG +# ifdef LDAP_LOG +# undef LDAP_LOG +# endif +# define LDAP_LOG(a) ber_pvt_log_output a + */ +# define BER_DUMP(a) ber_output_dump a +/* +# else +# define LDAP_LOG(a) +# define BER_DUMP(a) +# endif + */ +#endif + +LBER_F( int ) ber_pvt_log_output( + const char *subsystem, + int level, + const char *fmt, ... ); + +#define LBER_UNINITIALIZED 0x0 +#define LBER_INITIALIZED 0x1 +#define LBER_VALID_BERELEMENT 0x2 +#define LBER_VALID_SOCKBUF 0x3 + +LBER_V (struct lber_options) ber_int_options; +#define ber_int_debug ber_int_options.lbo_debug + +struct berelement { + struct lber_options ber_opts; +#define ber_valid ber_opts.lbo_valid +#define ber_options ber_opts.lbo_options +#define ber_debug ber_opts.lbo_debug + + /* Do not change the order of these 3 fields! see ber_get_next */ + ber_tag_t ber_tag; + ber_len_t ber_len; + ber_tag_t ber_usertag; + + char *ber_buf; + char *ber_ptr; + char *ber_end; + + struct seqorset *ber_sos; + char *ber_rwptr; +}; +#define LBER_VALID(ber) ((ber)->ber_valid==LBER_VALID_BERELEMENT) + +#define ber_pvt_ber_remaining(ber) ((ber)->ber_end - (ber)->ber_ptr) +#define ber_pvt_ber_total(ber) ((ber)->ber_end - (ber)->ber_buf) +#define ber_pvt_ber_write(ber) ((ber)->ber_ptr - (ber)->ber_buf) + +struct sockbuf { + struct lber_options sb_opts; + Sockbuf_IO_Desc *sb_iod; /* I/O functions */ +#define sb_valid sb_opts.lbo_valid +#define sb_options sb_opts.lbo_options +#define sb_debug sb_opts.lbo_debug + ber_socket_t sb_fd; + unsigned int sb_trans_needs_read:1; + unsigned int sb_trans_needs_write:1; + ber_len_t sb_max_incoming; +}; + +#define SOCKBUF_VALID( sb ) ( (sb)->sb_valid == LBER_VALID_SOCKBUF ) + +struct seqorset { + BerElement *sos_ber; + ber_len_t sos_clen; + ber_tag_t sos_tag; + char *sos_first; + char *sos_ptr; + struct seqorset *sos_next; +}; + + +/* + * io.c + */ +LBER_F( int ) +ber_realloc LDAP_P(( + BerElement *ber, + ber_len_t len )); + +/* + * bprint.c + */ +#define ber_log_printf ber_pvt_log_printf + +#ifdef NEW_LOGGING +LBER_F( int ) +ber_output_dump LDAP_P(( + const char *subsys, + int level, + BerElement *ber, + int inout )); +#endif + +LBER_F( int ) +ber_log_bprint LDAP_P(( + int errlvl, + int loglvl, + const char *data, + ber_len_t len )); + +LBER_F( int ) +ber_log_dump LDAP_P(( + int errlvl, + int loglvl, + BerElement *ber, + int inout )); + +LBER_F( int ) +ber_log_sos_dump LDAP_P(( + int errlvl, + int loglvl, + Seqorset *sos )); + +LBER_V (BER_LOG_FN) ber_int_log_proc; +LBER_V (FILE *) ber_pvt_err_file; + +/* memory.c */ + /* simple macros to realloc for now */ +LBER_V (BerMemoryFunctions *) ber_int_memory_fns; +LBER_F (char *) ber_strndup( LDAP_CONST char *, ber_len_t ); +LBER_F (char *) ber_strndup__( LDAP_CONST char *, size_t ); + +#ifdef CSRIMALLOC +#define LBER_MALLOC malloc +#define LBER_CALLOC calloc +#define LBER_REALLOC realloc +#define LBER_FREE free +#define LBER_VFREE ber_memvfree +#define LBER_STRDUP strdup +#define LBER_STRNDUP ber_strndup__ + +#else +#define LBER_MALLOC(s) ber_memalloc((s)) +#define LBER_CALLOC(n,s) ber_memcalloc((n),(s)) +#define LBER_REALLOC(p,s) ber_memrealloc((p),(s)) +#define LBER_FREE(p) ber_memfree((p)) +#define LBER_VFREE(v) ber_memvfree((void**)(v)) +#define LBER_STRDUP(s) ber_strdup((s)) +#define LBER_STRNDUP(s,l) ber_strndup((s),(l)) +#endif + +/* sockbuf.c */ + +LBER_F( int ) +ber_int_sb_init LDAP_P(( Sockbuf *sb )); + +LBER_F( int ) +ber_int_sb_close LDAP_P(( Sockbuf *sb )); + +LBER_F( int ) +ber_int_sb_destroy LDAP_P(( Sockbuf *sb )); + +LBER_F( ber_slen_t ) +ber_int_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); + +LBER_F( ber_slen_t ) +ber_int_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); + +LDAP_END_DECL + +#endif /* _LBER_INT_H */ diff --git a/libraries/liblber/liblber.dsp b/libraries/liblber/liblber.dsp new file mode 100644 index 0000000000000000000000000000000000000000..02c82831f9b532ef77b5df85d27acff675c27131 --- /dev/null +++ b/libraries/liblber/liblber.dsp @@ -0,0 +1,229 @@ +# Microsoft Developer Studio Project File - Name="liblber" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=liblber - Win32 DLL Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "liblber.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "liblber.mak" CFG="liblber - Win32 DLL Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "liblber - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 Single Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 Single Release" (based on\ + "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 DLL Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 DLL Release" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "liblber - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Release\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Debug\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "liblber_" +# PROP BASE Intermediate_Dir "liblber_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Sdebug" +# PROP Intermediate_Dir "..\..\SDebug\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Debug\olber32.lib" +# ADD LIB32 /nologo /out:"..\..\SDebug\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "liblber0" +# PROP BASE Intermediate_Dir "liblber0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Release\olber32.lib" +# ADD LIB32 /nologo /out:"..\..\SRelease\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 DLL Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "liblber_" +# PROP BASE Intermediate_Dir "liblber_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\DLLDebug" +# PROP Intermediate_Dir "..\..\DLLDebug\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\..\Debug\olber32.lib" +# ADD LIB32 /nologo /out:"..\..\DLLDebug\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 DLL Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "liblber0" +# PROP BASE Intermediate_Dir "liblber0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "liblber0" +# PROP Intermediate_Dir "liblber0" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\..\Release\olber32.lib" +# ADD LIB32 /nologo /out:"..\..\Release\olber32.lib" + +!ENDIF + +# Begin Target + +# Name "liblber - Win32 Release" +# Name "liblber - Win32 Debug" +# Name "liblber - Win32 Single Debug" +# Name "liblber - Win32 Single Release" +# Name "liblber - Win32 DLL Debug" +# Name "liblber - Win32 DLL Release" +# Begin Source File + +SOURCE=.\bprint.c +# End Source File +# Begin Source File + +SOURCE=.\debug.c +# End Source File +# Begin Source File + +SOURCE=.\decode.c +# End Source File +# Begin Source File + +SOURCE=.\encode.c +# End Source File +# Begin Source File + +SOURCE=.\io.c +# End Source File +# Begin Source File + +SOURCE=".\lber-int.h" +# End Source File +# Begin Source File + +SOURCE=..\..\include\lber.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\lber_pvt.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\lber_types.h +# End Source File +# Begin Source File + +SOURCE=.\memory.c +# End Source File +# Begin Source File + +SOURCE=.\nt_err.c +# End Source File +# Begin Source File + +SOURCE=.\options.c +# End Source File +# Begin Source File + +SOURCE=.\sockbuf.c +# End Source File +# End Target +# End Project diff --git a/libraries/libldap_r/thr_posix.c b/libraries/libldap_r/thr_posix.c new file mode 100644 index 0000000000000000000000000000000000000000..fef18fe9cafc76bcf7c370a6df77d4b657568f7f --- /dev/null +++ b/libraries/libldap_r/thr_posix.c @@ -0,0 +1,317 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, Redwood City, California, USA + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ + +/* thr_posix.c - wrapper around posix and posixish thread implementations. + */ + +#include "portable.h" + +#if defined( HAVE_PTHREADS ) + +#include <ac/errno.h> + +#include "ldap_pvt_thread.h" + + +#if HAVE_PTHREADS_D4 +# define LDAP_INT_THREAD_ATTR_DEFAULT pthread_attr_default +# define LDAP_INT_THREAD_CONDATTR_DEFAULT pthread_condattr_default +# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT pthread_mutexattr_default +#else +# define LDAP_INT_THREAD_ATTR_DEFAULT NULL +# define LDAP_INT_THREAD_CONDATTR_DEFAULT NULL +# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT NULL +#endif + + +int +ldap_int_thread_initialize( void ) +{ + return 0; +} + +int +ldap_int_thread_destroy( void ) +{ +#ifdef HAVE_PTHREAD_KILL_OTHER_THREADS_NP + /* LinuxThreads: kill clones */ + pthread_kill_other_threads_np(); +#endif + return 0; +} + +#ifdef LDAP_THREAD_HAVE_SETCONCURRENCY +int +ldap_pvt_thread_set_concurrency(int n) +{ +#ifdef HAVE_PTHREAD_SETCONCURRENCY + return pthread_setconcurrency( n ); +#elif HAVE_THR_SETCONCURRENCY + return thr_setconcurrency( n ); +#else + return 0; +#endif +} +#endif + +#ifdef LDAP_THREAD_HAVE_GETCONCURRENCY +int +ldap_pvt_thread_get_concurrency(void) +{ +#ifdef HAVE_PTHREAD_GETCONCURRENCY + return pthread_getconcurrency(); +#elif HAVE_THR_GETCONCURRENCY + return thr_getconcurrency(); +#else + return 0; +#endif +} +#endif + +int +ldap_pvt_thread_create( ldap_pvt_thread_t * thread, + int detach, + void *(*start_routine)( void * ), + void *arg) +{ + int rtn; +#if defined( HAVE_PTHREADS_FINAL ) + pthread_attr_t attr; + pthread_attr_init(&attr); + +#if defined( PTHREAD_CREATE_JOINABLE ) || defined( PTHREAD_UNDETACHED ) + if (!detach) { +#if defined( PTHREAD_CREATE_JOINABLE ) + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); +#else + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED); +#endif +#ifdef PTHREAD_CREATE_DETACHED + } else { + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); +#elif HAVE_PTHREADS_OS390 + } else { + int st = __DETACHED; + pthread_attr_setdetachstate(&attr, &st); +#endif + } +#endif + +#if defined(LDAP_PVT_THREAD_STACK_SIZE) && LDAP_PVT_THREAD_STACK_SIZE > 0 + /* this should be tunable */ + pthread_attr_setstacksize( &attr, LDAP_PVT_THREAD_STACK_SIZE ); +#endif + + rtn = pthread_create( thread, &attr, start_routine, arg ); +#ifdef HAVE_PTHREADS_OS390 + if ( rtn == -1 ) rtn = errno; +#endif + +#if !defined( PTHREAD_CREATE_JOINABLE ) && !defined( PTHREAD_UNDETACHED ) + if( detach ) { +#ifdef HAVE_PTHREADS_OS390 + (void) pthread_detach( thread ); +#else + (void) pthread_detach( *thread ); +#endif + } +#endif + pthread_attr_destroy(&attr); + +#else + rtn = pthread_create( thread, LDAP_INT_THREAD_ATTR_DEFAULT, + start_routine, arg ); + + if( detach ) { + pthread_detach( thread ); + } +#endif + + return rtn; +} + +void +ldap_pvt_thread_exit( void *retval ) +{ + pthread_exit( retval ); +} + +int +ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return ) +{ +#if !defined( HAVE_PTHREADS_FINAL ) + void *dummy; + if (thread_return==NULL) + thread_return=&dummy; +#endif +#ifdef HAVE_PTHREADS_OS390 + int st = pthread_join( thread, thread_return ); + if ( st == -1 ) st = errno; + return st; +#else + return pthread_join( thread, thread_return ); +#endif +} + +int +ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) +{ +#ifdef HAVE_PTHREAD_KILL +#ifdef HAVE_PTHREADS_OS390 + int st = pthread_kill( thread, signo ); + if ( st == -1 ) st = errno; + return st; +#else + return pthread_kill( thread, signo ); +#endif +#else + /* pthread package with DCE */ + if (kill( getpid(), signo )<0) + return errno; + return 0; +#endif +} + +int +ldap_pvt_thread_yield( void ) +{ +#ifdef _POSIX_THREAD_IS_GNU_PTH + sched_yield(); + return 0; + +#elif HAVE_SCHED_YIELD + return sched_yield(); + +#elif HAVE_PTHREAD_YIELD +#if HAVE_PTHREADS_OS390 + pthread_yield(NULL); +#else + pthread_yield(); +#endif + return 0; + +#elif HAVE_THR_YIELD + return thr_yield(); + +#else + return 0; +#endif +} + +int +ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) +{ + return pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ); +} + +int +ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond ) +{ + return pthread_cond_destroy( cond ); +} + +int +ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) +{ + return pthread_cond_signal( cond ); +} + +int +ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) +{ + return pthread_cond_broadcast( cond ); +} + +int +ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, + ldap_pvt_thread_mutex_t *mutex ) +{ + return pthread_cond_wait( cond, mutex ); +} + +int +ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) +{ + return pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT ); +} + +int +ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) +{ + return pthread_mutex_destroy( mutex ); +} + +int +ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) +{ + return pthread_mutex_lock( mutex ); +} + +int +ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) +{ + return pthread_mutex_trylock( mutex ); +} + +int +ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) +{ + return pthread_mutex_unlock( mutex ); +} + +#ifdef LDAP_THREAD_HAVE_RDWR +#ifdef HAVE_PTHREAD_RWLOCK_DESTROY +int +ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_init( rw, NULL ); +} + +int +ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_destroy( rw ); +} + +int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_rdlock( rw ); +} + +int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_tryrdlock( rw ); +} + +int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_unlock( rw ); +} + +int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_wrlock( rw ); +} + +int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_trywrlock( rw ); +} + +int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_unlock( rw ); +} + +#endif /* HAVE_PTHREAD_RDLOCK_DESTROY */ +#endif /* LDAP_THREAD_HAVE_RDWR */ +#endif /* HAVE_PTHREADS */ + diff --git a/libraries/libldbm/ldbm.c b/libraries/libldbm/ldbm.c index 6d15e4629e8a3f6881c4893eedc2c9eee6f79b57..112a54a9b43cfa9a4a2e7ca88dcc8f773f456490 100644 --- a/libraries/libldbm/ldbm.c +++ b/libraries/libldbm/ldbm.c @@ -1,52 +1,37 @@ /* ldbm.c - ldap dbm compatibility routines */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ -#include <stdio.h> -#include "ldbm.h" - -#ifdef LDBM_USE_GDBM - -#include <sys/types.h> -#include <sys/stat.h> - -/***************************************************************** - * * - * use gdbm * - * * - *****************************************************************/ +/* Patched for Berkeley DB version 2.0; /KSp; 98/02/23 + * - DB version 2.6.4b ; 1998/12/28, /KSp + * - DB_DBT_MALLOC ; 1998/03/22, /KSp + * - basic implementation; 1998/02/23, /KSp + */ -LDBM -ldbm_open( char *name, int rw, int mode, int dbcachesize ) -{ - LDBM db; - struct stat st; +#include "portable.h" - if ( (db = gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) { - return( NULL ); - } - if ( dbcachesize > 0 && stat( name, &st ) == 0 ) { - dbcachesize = (dbcachesize / st.st_blksize); - gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) ); - } +#ifdef SLAPD_LDBM - return( db ); -} +#include <stdio.h> -void -ldbm_close( LDBM ldbm ) -{ - gdbm_close( ldbm ); -} +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/errno.h> -void -ldbm_sync( LDBM ldbm ) -{ - gdbm_sync( ldbm ); -} +#include "ldbm.h" +#include "ldap_pvt_thread.h" void ldbm_datum_free( LDBM ldbm, Datum data ) { - free( data.dptr ); + if ( data.dptr ) { + free( data.dptr ); + memset( &data, '\0', sizeof( Datum )); + data.dptr = NULL; + } } Datum @@ -54,6 +39,8 @@ ldbm_datum_dup( LDBM ldbm, Datum data ) { Datum dup; + ldbm_datum_init( dup ); + if ( data.dsize == 0 ) { dup.dsize = 0; dup.dptr = NULL; @@ -61,58 +48,250 @@ ldbm_datum_dup( LDBM ldbm, Datum data ) return( dup ); } dup.dsize = data.dsize; - if ( dup.dptr = (char *) malloc( data.dsize ) ) - memcpy( dup.dptr, data.dptr, data.dsize ); + + if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL ) { + AC_MEMCPY( dup.dptr, data.dptr, data.dsize ); + } return( dup ); } -Datum -ldbm_fetch( LDBM ldbm, Datum key ) +static int ldbm_initialized = 0; + +#if defined( USE_BERKELEY_CDB ) + /* not currently supported */ +#define LDBM_RWLOCK_INIT ((void) 0) +#define LDBM_RWLOCK_DESTROY ((void) 0) +#define LDBM_WLOCK ((void) 0) +#define LDBM_WUNLOCK ((void) 0) +#define LDBM_RLOCK ((void) 0) +#define LDBM_RUNLOCK ((void) 0) + +#elif defined( HAVE_BERKELEY_DB_THREAD ) +static ldap_pvt_thread_rdwr_t ldbm_big_rdwr; +#define LDBM_RWLOCK_INIT (ldap_pvt_thread_rdwr_init( &ldbm_big_rdwr )) +#define LDBM_RWLOCK_DESTROY (ldap_pvt_thread_rdwr_destroy( &ldbm_big_rdwr )) +#define LDBM_WLOCK (ldap_pvt_thread_rdwr_wlock(&ldbm_big_rdwr)) +#define LDBM_WUNLOCK (ldap_pvt_thread_rdwr_wunlock(&ldbm_big_rdwr)) +#define LDBM_RLOCK (ldap_pvt_thread_rdwr_rlock(&ldbm_big_rdwr)) +#define LDBM_RUNLOCK (ldap_pvt_thread_rdwr_runlock(&ldbm_big_rdwr)) + +#else +static ldap_pvt_thread_mutex_t ldbm_big_mutex; +#define LDBM_RWLOCK_INIT (ldap_pvt_thread_mutex_init( &ldbm_big_mutex )) +#define LDBM_RWLOCK_DESTROY (ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex )) +#define LDBM_WLOCK (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex)) +#define LDBM_WUNLOCK (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex)) +#define LDBM_RLOCK LDBM_WLOCK +#define LDBM_RUNLOCK LDBM_WUNLOCK +#endif + +#if !defined( HAVE_BERKELEY_DB ) || (DB_VERSION_MAJOR < 3) + /* a dbEnv for BERKELEYv2 */ +DB_ENV *ldbm_Env = NULL; /* real or fake, depending on db and version */ +#endif + +/******************************************************************* + * * + * Create some special functions to initialize Berkeley DB for * + * versions greater than 2. * + * * + *******************************************************************/ +#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 2) + +void * +ldbm_malloc( size_t size ) { - return( gdbm_fetch( ldbm, key ) ); + /* likely should use ber_mem* routines */ + return( calloc( 1, size ) ); } -int -ldbm_store( LDBM ldbm, Datum key, Datum data, int flags ) +#ifdef LDAP_SYSLOG +#include <ac/syslog.h> +#endif + +static void +ldbm_db_errcall( const char *prefix, char *message ) { - int rc; +#ifdef LDAP_SYSLOG + syslog( LOG_INFO, "ldbm: %s %s", prefix, message ); +#endif +} - rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC ); - if ( flags & LDBM_SYNC ) - gdbm_sync( ldbm ); - return( rc ); +int ldbm_initialize( const char* home ) +{ +#if DB_VERSION_MAJOR < 3 + int err; + u_int32_t envFlags; +#endif + + if(ldbm_initialized++) return 1; + + { + char *version; + int major, minor, patch; + version = db_version( &major, &minor, &patch ); + + if( major != DB_VERSION_MAJOR || + minor < DB_VERSION_MINOR ) + { +#ifdef LDAP_SYSLOG + syslog( LOG_INFO, + "ldbm_initialize(): version mismatch\nexpected: %s\ngot: %s\n", + DB_VERSION_STRING, version ); +#endif + return 1; + } + } + +#if DB_VERSION_MAJOR < 3 + ldbm_Env = calloc( 1, sizeof( DB_ENV )); + + if( ldbm_Env == NULL ) return 1; + + ldbm_Env->db_errcall = ldbm_db_errcall; + ldbm_Env->db_errpfx = "==>"; + + envFlags = DB_CREATE | DB_USE_ENVIRON; + + /* add optional flags */ +#ifdef DB_PRIVATE + envFlags |= DB_PRIVATE; +#endif +#ifdef HAVE_BERKELEY_DB_THREAD + envFlags |= DB_THREAD; +#endif + + err = db_appinit( home, NULL, ldbm_Env, envFlags ); + + if ( err ) { +#ifdef LDAP_SYSLOG + syslog( LOG_INFO, "ldbm_initialize(): " + "FATAL error (%d) in db_appinit()\n", err ); +#endif + return( 1 ); + } +#endif + + LDBM_RWLOCK_INIT; + + return 0; } -int -ldbm_delete( LDBM ldbm, Datum key ) +int ldbm_shutdown( void ) { - int rc; + if( !ldbm_initialized ) return 1; - rc = gdbm_delete( ldbm, key ); - gdbm_sync( ldbm ); - return( rc ); +#if DB_VERSION_MAJOR < 3 + db_appexit( ldbm_Env ); +#endif + + LDBM_RWLOCK_DESTROY; + return 0; } -Datum -ldbm_firstkey( LDBM ldbm ) +#else /* some DB other than Berkeley V2 or greater */ + +int ldbm_initialize( const char * home ) { - return( gdbm_firstkey( ldbm ) ); + if(ldbm_initialized++) return 1; + + LDBM_RWLOCK_INIT; + + return 0; } -Datum -ldbm_nextkey( LDBM ldbm, Datum key ) +int ldbm_shutdown( void ) { - return( gdbm_nextkey( ldbm, key ) ); + if( !ldbm_initialized ) return 1; + + LDBM_RWLOCK_DESTROY; + + return 0; } -int -ldbm_errno( LDBM ldbm ) +#endif /* HAVE_BERKELEY_DB */ + +#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 3) + +DB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok) { - return( (int) gdbm_errno ); + DB_ENV *env = NULL; + int err; + u_int32_t envFlags; + + err = db_env_create( &env, 0 ); + + if ( err ) { +#ifdef LDAP_SYSLOG + syslog( LOG_INFO, "ldbm_initialize_env(): " + "FATAL error in db_env_create() : %s (%d)\n", + db_strerror( err ), err ); +#endif + return NULL; + } + +#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR >= 3 + /* This interface appeared in 3.3 */ + env->set_alloc( env, ldbm_malloc, NULL, NULL ); +#endif + + env->set_errcall( env, ldbm_db_errcall ); + env->set_errpfx( env, "==>" ); + if (dbcachesize) { + env->set_cachesize( env, 0, dbcachesize, 0 ); + } + + envFlags = DB_CREATE | DB_INIT_MPOOL | DB_USE_ENVIRON; +#ifdef DB_PRIVATE + envFlags |= DB_PRIVATE; +#endif +#ifdef DB_MPOOL_PRIVATE + envFlags |= DB_MPOOL_PRIVATE; +#endif +#ifdef HAVE_BERKELEY_DB_THREAD + envFlags |= DB_THREAD; +#endif + +#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 0 + err = env->open( env, home, envFlags, 0 ); +#else + /* 3.0.x requires an extra argument */ + err = env->open( env, home, NULL, envFlags, 0 ); +#endif + + if ( err != 0 ) { +#ifdef LDAP_SYSLOG + syslog( LOG_INFO, "ldbm_initialize_env(): " + "FATAL error in dbEnv->open() : %s (%d)\n", + db_strerror( err ), err ); +#endif + env->close( env, 0 ); + return NULL; + } + + *envdirok = 1; + return env; +} + +void ldbm_shutdown_env(DB_ENV *env) +{ + env->close( env, 0 ); } #else + +DB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok) +{ + return ldbm_Env; +} + +void ldbm_shutdown_env(DB_ENV *env) +{ +} + +#endif + #if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE ) /***************************************************************** @@ -122,9 +301,78 @@ ldbm_errno( LDBM ldbm ) *****************************************************************/ LDBM -ldbm_open( char *name, int rw, int mode, int dbcachesize ) +ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize ) { - LDBM ret; + LDBM ret = NULL; +#ifdef HAVE_EBCDIC + char n2[2048]; +#endif + +#if DB_VERSION_MAJOR >= 3 + int err; + + LDBM_WLOCK; + + err = db_create( &ret, env, 0 ); + if ( err != 0 ) { + (void)ret->close(ret, 0); + LDBM_WUNLOCK; + + return NULL; + } + +#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 3 + ret->set_malloc( ret, ldbm_malloc ); +#endif + + ret->set_pagesize( ret, DEFAULT_DB_PAGE_SIZE ); + + /* likely should use ber_mem* routines */ + +#ifdef HAVE_EBCDIC + strncpy(n2, name, sizeof(n2)-1); + n2[sizeof(n2)-1] = '\0'; + __atoe(n2); + name = n2; +#endif + err = ret->open( ret, name, NULL, DB_TYPE, rw, mode); + + if ( err != 0 ) { + int tmp = errno; + (void)ret->close(ret, 0); + errno = tmp; + + LDBM_WUNLOCK; + return NULL; + } + + LDBM_WUNLOCK; + +#elif DB_VERSION_MAJOR >= 2 + DB_INFO dbinfo; + + memset( &dbinfo, '\0', sizeof( dbinfo )); + +#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 4 + /* + * BerkeleyDB 2.4 do not allow db_cachesize + * to be specified if an DB_ENV is. + */ +#else + /* set db_cachesize of MPOOL is NOT being used. */ + if (( ldbm_Env == NULL ) || ( ldbm_Env->mp_info == NULL )) { + dbinfo.db_cachesize = dbcachesize; + } +#endif + + dbinfo.db_pagesize = DEFAULT_DB_PAGE_SIZE; + dbinfo.db_malloc = ldbm_malloc; + + LDBM_WLOCK; + (void) db_open( name, DB_TYPE, rw, mode, ldbm_Env, &dbinfo, &ret ); + LDBM_WUNLOCK; + +#else void *info; BTREEINFO binfo; HASHINFO hinfo; @@ -140,44 +388,33 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize ) } else { info = NULL; } + + LDBM_WLOCK; ret = dbopen( name, rw, mode, DB_TYPE, info ); - return( ret ); + LDBM_WUNLOCK; +#endif + + return ret; } void ldbm_close( LDBM ldbm ) { - (*ldbm->close)( ldbm ); + LDBM_WLOCK; +#if DB_VERSION_MAJOR >= 2 + ldbm->close( ldbm, 0 ); +#else + ldbm->close( ldbm ); +#endif + LDBM_WUNLOCK; } void ldbm_sync( LDBM ldbm ) { + LDBM_WLOCK; (*ldbm->sync)( ldbm, 0 ); -} - -void -ldbm_datum_free( LDBM ldbm, Datum data ) -{ - free( data.dptr ); -} - -Datum -ldbm_datum_dup( LDBM ldbm, Datum data ) -{ - Datum dup; - - if ( data.dsize == 0 ) { - dup.dsize = 0; - dup.dptr = NULL; - - return( dup ); - } - dup.dsize = data.dsize; - if ( dup.dptr = (char *) malloc( data.dsize ) ) - memcpy( dup.dptr, data.dptr, data.dsize ); - - return( dup ); + LDBM_WUNLOCK; } Datum @@ -186,12 +423,30 @@ ldbm_fetch( LDBM ldbm, Datum key ) Datum data; int rc; - if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) { + LDBM_RLOCK; + +#if DB_VERSION_MAJOR >= 2 + ldbm_datum_init( data ); + + data.flags = DB_DBT_MALLOC; + + if ( (rc = ldbm->get( ldbm, NULL, &key, &data, 0 )) != 0 ) { + ldbm_datum_free( ldbm, data ); + data.dptr = NULL; + data.dsize = 0; + } +#else + if ( (rc = ldbm->get( ldbm, &key, &data, 0 )) == 0 ) { + /* Berkeley DB 1.85 don't malloc the data for us */ + /* duplicate it for to ensure reentrancy */ data = ldbm_datum_dup( ldbm, data ); } else { data.dptr = NULL; data.dsize = 0; } +#endif + + LDBM_RUNLOCK; return( data ); } @@ -201,9 +456,20 @@ ldbm_store( LDBM ldbm, Datum key, Datum data, int flags ) { int rc; - rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC ); + LDBM_WLOCK; + +#if DB_VERSION_MAJOR >= 2 + rc = ldbm->put( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC ); + rc = (-1) * rc; +#else + rc = ldbm->put( ldbm, &key, &data, flags & ~LDBM_SYNC ); +#endif + if ( flags & LDBM_SYNC ) - (*ldbm->sync)( ldbm, 0 ); + ldbm->sync( ldbm, 0 ); + + LDBM_WUNLOCK; + return( rc ); } @@ -212,38 +478,107 @@ ldbm_delete( LDBM ldbm, Datum key ) { int rc; - rc = (*ldbm->del)( ldbm, &key, 0 ); - (*ldbm->sync)( ldbm, 0 ); + LDBM_WLOCK; + +#if DB_VERSION_MAJOR >= 2 + rc = ldbm->del( ldbm, NULL, &key, 0 ); + rc = (-1) * rc; +#else + rc = ldbm->del( ldbm, &key, 0 ); +#endif + ldbm->sync( ldbm, 0 ); + + LDBM_WUNLOCK; + return( rc ); } Datum -ldbm_firstkey( LDBM ldbm ) +ldbm_firstkey( LDBM ldbm, LDBMCursor **dbch ) { Datum key, data; int rc; - if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) { +#if DB_VERSION_MAJOR >= 2 + LDBMCursor *dbci; + + ldbm_datum_init( key ); + ldbm_datum_init( data ); + + key.flags = data.flags = DB_DBT_MALLOC; + + LDBM_RLOCK; + + /* acquire a cursor for the DB */ +# if DB_VERSION_MAJOR >= 3 || (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 5) + rc = ldbm->cursor( ldbm, NULL, &dbci, 0 ); +# else + rc = ldbm->cursor( ldbm, NULL, &dbci ); +# endif + + if( rc ) { + key.dptr = NULL; + } else { + *dbch = dbci; + if ( dbci->c_get( dbci, &key, &data, DB_NEXT ) == 0 ) { + ldbm_datum_free( ldbm, data ); + } else { + key.dptr = NULL; + key.dsize = 0; + } + } + + LDBM_RUNLOCK; + +#else + LDBM_RLOCK; + + rc = ldbm->seq( ldbm, &key, &data, R_FIRST ); + + if ( rc == 0 ) { key = ldbm_datum_dup( ldbm, key ); } else { key.dptr = NULL; key.dsize = 0; } + + LDBM_RUNLOCK; +#endif + return( key ); } Datum -ldbm_nextkey( LDBM ldbm, Datum key ) +ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp ) { - Datum data; int rc; + Datum data; + + LDBM_RLOCK; + +#if DB_VERSION_MAJOR >= 2 + ldbm_datum_init( data ); + + ldbm_datum_free( ldbm, key ); + key.flags = data.flags = DB_DBT_MALLOC; - if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) { + rc = dbcp->c_get( dbcp, &key, &data, DB_NEXT ); + if ( rc == 0 ) { + ldbm_datum_free( ldbm, data ); + } else +#else + rc = ldbm->seq( ldbm, &key, &data, R_NEXT ); + + if ( rc == 0 ) { key = ldbm_datum_dup( ldbm, key ); - } else { + } else +#endif + { key.dptr = NULL; key.dsize = 0; } + + LDBM_RUNLOCK; return( key ); } @@ -253,96 +588,576 @@ ldbm_errno( LDBM ldbm ) return( errno ); } -#else +/****************************************************************** + * * + * END Berkeley section * + * * + ******************************************************************/ -#ifdef LDBM_USE_NDBM +#elif defined( HAVE_GDBM ) + +#ifdef HAVE_ST_BLKSIZE +#include <sys/stat.h> +#endif /***************************************************************** * * - * if no gdbm, fall back to using ndbm, the standard unix thing * + * use gdbm * * * *****************************************************************/ -/* ARGSUSED */ LDBM -ldbm_open( char *name, int rw, int mode, int dbcachesize ) +ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize ) { - return( dbm_open( name, rw, mode ) ); + LDBM db; +#ifdef HAVE_ST_BLKSIZE + struct stat st; +#endif +#ifdef HAVE_EBCDIC + char n2[2048]; + + strncpy(n2, name, sizeof(n2)-1); + n2[sizeof(n2)-1] = '\0'; + __atoe(n2); + name = n2; +#endif + + LDBM_WLOCK; + + if ( (db = gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) { + LDBM_WUNLOCK; + return( NULL ); + } + +#ifdef HAVE_ST_BLKSIZE + if ( dbcachesize > 0 && stat( name, &st ) == 0 ) { + dbcachesize /= st.st_blksize; + if( dbcachesize == 0 ) dbcachesize = 1; + gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) ); + } +#else + if ( dbcachesize > 0 ) { + dbcachesize /= 4096; + if( dbcachesize == 0 ) dbcachesize = 1; + gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) ); + } +#endif + + LDBM_WUNLOCK; + + return( db ); } void ldbm_close( LDBM ldbm ) { - dbm_close( ldbm ); + LDBM_WLOCK; + gdbm_close( ldbm ); + LDBM_WUNLOCK; } -/* ARGSUSED */ void ldbm_sync( LDBM ldbm ) { - return; + LDBM_WLOCK; + gdbm_sync( ldbm ); + LDBM_WUNLOCK; +} + +Datum +ldbm_fetch( LDBM ldbm, Datum key ) +{ + Datum d; + + LDBM_RLOCK; + d = gdbm_fetch( ldbm, key ); + LDBM_RUNLOCK; + + return d; +} + +int +ldbm_store( LDBM ldbm, Datum key, Datum data, int flags ) +{ + int rc; + + LDBM_WLOCK; + rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC ); + if ( flags & LDBM_SYNC ) + gdbm_sync( ldbm ); + LDBM_WUNLOCK; + + return( rc ); +} + +int +ldbm_delete( LDBM ldbm, Datum key ) +{ + int rc; + + LDBM_WLOCK; + rc = gdbm_delete( ldbm, key ); + gdbm_sync( ldbm ); + LDBM_WUNLOCK; + + return( rc ); +} + +Datum +ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp ) +{ + Datum d; + + LDBM_RLOCK; + d = gdbm_firstkey( ldbm ); + LDBM_RUNLOCK; + + if ( d.dptr != NULL ) { + *dbcp = (Datum *) malloc( sizeof( Datum ) ); + **dbcp = ldbm_datum_dup( ldbm, d ); + } + + return d; +} + +Datum +ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp ) +{ + Datum d; + + LDBM_RLOCK; + d = gdbm_nextkey( ldbm, *dbcp ); + LDBM_RUNLOCK; + + ldbm_datum_free( ldbm, *dbcp ); + + if ( d.dptr != NULL ) { + *dbcp = ldbm_datum_dup( ldbm, d ); + } else { + free( dbcp ); + } + + return d; +} + +int +ldbm_errno( LDBM ldbm ) +{ + int err; + + LDBM_WLOCK; + err = gdbm_errno; + LDBM_WUNLOCK; + + return( err ); +} + +#elif HAVE_MDBM + +/* MMAPED DBM HASHING DATABASE */ + +#include <ac/string.h> + +/* #define MDBM_DEBUG */ + +#ifdef MDBM_DEBUG +#include <stdio.h> +#endif + +#define NO_NULL_KEY +/* #define MDBM_CHAIN */ + +#ifdef MDBM_CHAIN + +/* Use chaining */ + +#define mdbm_store mdbm_chain_store +#define mdbm_fetch mdbm_chain_fetch +#define mdbm_delete mdbm_chain_delete +#define mdbm_first mdbm_chain_first +#define mdbm_next mdbm_chain_next + +#endif + +#define MDBM_PG_SZ (4*1024) + +/***************************************************************** + * * + * use mdbm * + * * + *****************************************************************/ + +LDBM +ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize ) +{ + LDBM db; + +#ifdef MDBM_DEBUG + fprintf( stdout, + "==>(mdbm)ldbm_open(name=%s,rw=%x,mode=%x,cachesize=%d)\n", + name ? name : "NULL", rw, mode, dbcachesize ); + fflush( stdout ); +#endif + + LDBM_WLOCK; /* We need locking here, this is the only non-thread + * safe function we have. */ + + if ( (db = mdbm_open( name, rw, mode, MDBM_PG_SZ )) == NULL ) { + LDBM_WUNLOCK; +#ifdef MDBM_DEBUG + fprintf( stdout, "<==(mdbm)ldbm_open(db=NULL)\n" ); + fflush( stdout ); +#endif + return( NULL ); + } + +#ifdef MDBM_CHAIN + (void)mdbm_set_chain(db); +#endif + + LDBM_WUNLOCK; + +#ifdef MDBM_DEBUG + fprintf( stdout, "<==(mdbm)ldbm_open(db=%p)\n", db ); + fflush( stdout ); +#endif + + return( db ); } void -ldbm_datum_free( LDBM ldbm, Datum data ) +ldbm_close( LDBM ldbm ) { - return; + /* Open and close are not reentrant so we need to use locks here */ + +#ifdef MDBM_DEBUG + fprintf( stdout, + "==>(mdbm)ldbm_close(db=%p)\n", ldbm ); + fflush( stdout ); +#endif + + LDBM_WLOCK; + mdbm_close( ldbm ); + LDBM_WUNLOCK; + +#ifdef MDBM_DEBUG + fprintf( stdout, "<==(mdbm)ldbm_close()\n" ); + fflush( stdout ); +#endif } +void +ldbm_sync( LDBM ldbm ) +{ + /* XXX: Not sure if this is re-entrant need to check code, if so + * you can leave LOCKS out. + */ + + LDBM_WLOCK; + mdbm_sync( ldbm ); + LDBM_WUNLOCK; +} + +#define MAX_MDBM_RETRY 5 + Datum -ldbm_datum_dup( LDBM ldbm, Datum data ) +ldbm_fetch( LDBM ldbm, Datum key ) { - Datum dup; + Datum d; + kvpair k; + int retry = 0; - if ( data.dsize == 0 ) { - dup.dsize = 0; - dup.dptr = NULL; + /* This hack is needed because MDBM does not take keys + * which begin with NULL when working in the chaining + * mode. + */ - return( dup ); +#ifdef NO_NULL_KEY + k.key.dsize = key.dsize + 1; + k.key.dptr = malloc(k.key.dsize); + *(k.key.dptr) = 'l'; + AC_MEMCPY( (void *)(k.key.dptr + 1), key.dptr, key.dsize ); +#else + k.key = key; +#endif + + k.val.dptr = NULL; + k.val.dsize = 0; + + /* LDBM_RLOCK; */ + do { + d = mdbm_fetch( ldbm, k ); + + if ( d.dsize > 0 ) { + if ( k.val.dptr != NULL ) { + free( k.val.dptr ); + } + + if ( (k.val.dptr = malloc( d.dsize )) != NULL ) { + k.val.dsize = d.dsize; + d = mdbm_fetch( ldbm, k ); + + } else { + d.dsize = 0; + break; + } + }/* if ( d.dsize > 0 ) */ + } while ((d.dsize > k.val.dsize) && (++retry < MAX_MDBM_RETRY)); + /* LDBM_RUNLOCK; */ + +#ifdef NO_NULL_KEY + free(k.key.dptr); +#endif + + return d; +} + +int +ldbm_store( LDBM ldbm, Datum key, Datum data, int flags ) +{ + int rc; + Datum int_key; /* Internal key */ + +#ifdef MDBM_DEBUG + fprintf( stdout, + "==>(mdbm)ldbm_store(db=%p, key(dptr=%p,sz=%d), data(dptr=%p,sz=%d), flags=%x)\n", + ldbm, key.dptr, key.dsize, data.dptr, data.dsize, flags ); + fflush( stdout ); +#endif + + /* LDBM_WLOCK; */ + +#ifdef NO_NULL_KEY + int_key.dsize = key.dsize + 1; + int_key.dptr = malloc( int_key.dsize ); + *(int_key.dptr) = 'l'; /* Must not be NULL !*/ + AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize ); +#else + int_key = key; +#endif + + rc = mdbm_store( ldbm, int_key, data, flags ); + if ( flags & LDBM_SYNC ) { + mdbm_sync( ldbm ); } - dup.dsize = data.dsize; - if ( dup.dptr = (char *) malloc( data.dsize ) ) - memcpy( dup.dptr, data.dptr, data.dsize ); - return( dup ); + /* LDBM_WUNLOCK; */ + +#ifdef MDBM_DEBUG + fprintf( stdout, "<==(mdbm)ldbm_store(rc=%d)\n", rc ); + fflush( stdout ); +#endif + +#ifdef NO_NULL_KEY + free(int_key.dptr); +#endif + + return( rc ); +} + +int +ldbm_delete( LDBM ldbm, Datum key ) +{ + int rc; + Datum int_key; + + /* LDBM_WLOCK; */ + +#ifdef NO_NULL_KEY + int_key.dsize = key.dsize + 1; + int_key.dptr = malloc(int_key.dsize); + *(int_key.dptr) = 'l'; + AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize ); +#else + int_key = key; +#endif + + rc = mdbm_delete( ldbm, int_key ); + + /* LDBM_WUNLOCK; */ +#ifdef NO_NULL_KEY + free(int_key.dptr); +#endif + + return( rc ); +} + +static Datum +ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) ) +{ + kvpair out; + kvpair in; + Datum ret; + size_t sz = MDBM_PAGE_SIZE(ldbm); +#ifdef NO_NULL_KEY + int delta = 1; +#else + int delta = 0; +#endif + + /* LDBM_RLOCK; */ + + in.key.dsize = sz; /* Assume first key in one pg */ + in.key.dptr = malloc(sz); + + in.val.dptr = NULL; /* Don't need data just key */ + in.val.dsize = 0; + + ret.dptr = NULL; + ret.dsize = NULL; + + out = fptr( ldbm, in ); + + if (out.key.dsize > 0) { + ret.dsize = out.key.dsize - delta; + + if ((ret.dptr = (char *)malloc(ret.dsize)) == NULL) { + ret.dsize = 0; + ret.dptr = NULL; + + } else { + AC_MEMCPY(ret.dptr, (void *)(out.key.dptr + delta), + ret.dsize ); + } + } + + /* LDBM_RUNLOCK; */ + + free(in.key.dptr); + return ret; +} + +Datum +ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp ) +{ + return ldbm_get_next( ldbm, mdbm_first ); +} + +Datum +ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp ) +{ + /* XXX: + * don't know if this will affect the LDAP server operation + * but mdbm cannot take and input key. + */ + + return ldbm_get_next( ldbm, mdbm_next ); +} + +int +ldbm_errno( LDBM ldbm ) +{ + /* XXX: best we can do with current mdbm interface */ + return( errno ); +} + +#elif defined( HAVE_NDBM ) + +/***************************************************************** + * * + * if no gdbm or mdbm, fall back to using ndbm, the standard unix thing * + * * + *****************************************************************/ + +/* ARGSUSED */ +LDBM +ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize ) +{ + LDBM ldbm; + + LDBM_WLOCK; + ldbm = dbm_open( name, rw, mode ); + LDBM_WUNLOCK; + + return( ldbm ); +} + +void +ldbm_close( LDBM ldbm ) +{ + LDBM_WLOCK; + dbm_close( ldbm ); + LDBM_WUNLOCK; +} + +/* ARGSUSED */ +void +ldbm_sync( LDBM ldbm ) +{ + return; } Datum ldbm_fetch( LDBM ldbm, Datum key ) { - return( ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) ) ); + Datum d; + + LDBM_RLOCK; + d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) ); + LDBM_RUNLOCK; + + return d; } int ldbm_store( LDBM ldbm, Datum key, Datum data, int flags ) { - return( dbm_store( ldbm, key, data, flags ) ); + int rc; + + LDBM_WLOCK; + rc = dbm_store( ldbm, key, data, flags ); + LDBM_WUNLOCK; + + return rc; } int ldbm_delete( LDBM ldbm, Datum key ) { - return( dbm_delete( ldbm, key ) ); + int rc; + + LDBM_WLOCK; + rc = dbm_delete( ldbm, key ); + LDBM_WUNLOCK; + + return rc; } Datum -ldbm_firstkey( LDBM ldbm ) +ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp ) { - return( dbm_firstkey( ldbm ) ); + Datum d; + + LDBM_RLOCK; + d = dbm_firstkey( ldbm ); + LDBM_RUNLOCK; + + return d; } Datum -ldbm_nextkey( LDBM ldbm, Datum key ) +ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp ) { - return( dbm_nextkey( ldbm ) ); + Datum d; + + LDBM_RLOCK; + d = dbm_nextkey( ldbm ); + LDBM_RUNLOCK; + + return d; } int ldbm_errno( LDBM ldbm ) { - return( dbm_error( ldbm ) ); + int err; + + LDBM_WLOCK; + err = dbm_error( ldbm ); + LDBM_WUNLOCK; + + return err; } #endif /* ndbm */ -#endif /* db */ -#endif /* gdbm */ +#endif /* ldbm */ diff --git a/libraries/liblunicode/Makefile.in b/libraries/liblunicode/Makefile.in index 5316d023aeb252fdbc19b5eb0cae7476039d55d4..ef2e3614a0b31f3ac7d4e1b22059486e376f5791 100644 --- a/libraries/liblunicode/Makefile.in +++ b/libraries/liblunicode/Makefile.in @@ -14,6 +14,7 @@ SRCS = ucstr.c OBJS = ucdata.o ure.o urestubs.o ucstr.o XLIB = $(LIBRARY) +XLIBS = $(LDAP_LIBLUTIL_A) PROGRAMS = ucgendat LDAP_INCDIR= ../../include diff --git a/libraries/liblunicode/ucdata/ucdata.c b/libraries/liblunicode/ucdata/ucdata.c index beb4184f03f55a5339dab12854dda44596018b22..151e0ac1057f3c260aff7b1f42eac2a51a84bc25 100644 --- a/libraries/liblunicode/ucdata/ucdata.c +++ b/libraries/liblunicode/ucdata/ucdata.c @@ -30,6 +30,7 @@ #include "ldap_config.h" #include <stdio.h> +#include <ac/bytes.h> #include <ac/stdlib.h> #include <ac/string.h> #include <ac/unistd.h> @@ -44,11 +45,11 @@ **************************************************************************/ typedef struct { - unsigned short bom; - unsigned short cnt; + ac_uint2 bom; + ac_uint2 cnt; union { - unsigned long bytes; - unsigned short len[2]; + ac_uint4 bytes; + ac_uint2 len[2]; } size; } _ucheader_t; diff --git a/libraries/liblunicode/ucdata/ucgendat.c b/libraries/liblunicode/ucdata/ucgendat.c index 2daee8a4c339656ccbde77a93be410a5e3f55262..11f32f9cb2b1173d21af17b9d48a17d7ee3a1a12 100644 --- a/libraries/liblunicode/ucdata/ucgendat.c +++ b/libraries/liblunicode/ucdata/ucgendat.c @@ -30,6 +30,7 @@ #include "ldap_config.h" #include <stdio.h> +#include <ac/bytes.h> #include <ac/stdlib.h> #include <ac/string.h> #include <ac/unistd.h> @@ -804,8 +805,8 @@ read_cdata(FILE *in) char line[512], *s, *e; lineno = skip = 0; - while (!feof(in)) { - if( fscanf(in, "%[^\n]\n", line) != 1) break; + while (fgets(line, sizeof(line), in)) { + if( (s=strchr(line, '\n')) ) *s = '\0'; lineno++; /* @@ -1163,8 +1164,8 @@ read_compexdata(FILE *in) (void) memset((char *) compexs, 0, sizeof(unsigned long) << 11); - while (!feof(in)) { - if( fscanf(in, "%[^\n]\n", line) != 1) break; + while (fgets(line, sizeof(line), in)) { + if( (s=strchr(line, '\n')) ) *s = '\0'; /* * Skip blank lines and lines that start with a '#'. */ @@ -1216,7 +1217,8 @@ static void write_cdata(char *opath) { FILE *out; - unsigned long i, idx, bytes, nprops; + ac_uint4 bytes; + unsigned long i, idx, nprops; unsigned short casecnt[2]; char path[BUFSIZ]; @@ -1229,7 +1231,7 @@ write_cdata(char *opath) /* * Open the ctype.dat file. */ - sprintf(path, "%s%sctype.dat", opath, LDAP_DIRSEP); + snprintf(path, sizeof path, "%s" LDAP_DIRSEP "ctype.dat", opath); if ((out = fopen(path, "wb")) == 0) return; @@ -1268,7 +1270,7 @@ write_cdata(char *opath) /* * Write the header. */ - fwrite((char *) hdr, sizeof(unsigned short), 2, out); + fwrite((char *) hdr, sizeof(ac_uint2), 2, out); /* * Write the byte count. @@ -1300,7 +1302,7 @@ write_cdata(char *opath) /* * Open the case.dat file. */ - sprintf(path, "%s%scase.dat", opath, LDAP_DIRSEP); + snprintf(path, sizeof path, "%s" LDAP_DIRSEP "case.dat", opath); if ((out = fopen(path, "wb")) == 0) return; @@ -1355,7 +1357,7 @@ write_cdata(char *opath) /* * Open the comp.dat file. */ - sprintf(path, "%s%scomp.dat", opath, LDAP_DIRSEP); + snprintf(path, sizeof path, "%s" LDAP_DIRSEP "comp.dat", opath); if ((out = fopen(path, "wb")) == 0) return; @@ -1393,7 +1395,7 @@ write_cdata(char *opath) /* * Open the decomp.dat file. */ - sprintf(path, "%s%sdecomp.dat", opath, LDAP_DIRSEP); + snprintf(path, sizeof path, "%s" LDAP_DIRSEP "decomp.dat", opath); if ((out = fopen(path, "wb")) == 0) return; @@ -1447,7 +1449,7 @@ write_cdata(char *opath) /* * Open the kdecomp.dat file. */ - sprintf(path, "%s%skdecomp.dat", opath, LDAP_DIRSEP); + snprintf(path, sizeof path, "%s" LDAP_DIRSEP "kdecomp.dat", opath); if ((out = fopen(path, "wb")) == 0) return; @@ -1507,7 +1509,7 @@ write_cdata(char *opath) /* * Open the cmbcl.dat file. */ - sprintf(path, "%s%scmbcl.dat", opath, LDAP_DIRSEP); + snprintf(path, sizeof path, "%s" LDAP_DIRSEP "cmbcl.dat", opath); if ((out = fopen(path, "wb")) == 0) return; @@ -1545,7 +1547,7 @@ write_cdata(char *opath) /* * Open the num.dat file. */ - sprintf(path, "%s%snum.dat", opath, LDAP_DIRSEP); + snprintf(path, sizeof path, "%s" LDAP_DIRSEP "num.dat", opath); if ((out = fopen(path, "wb")) == 0) return; @@ -1598,10 +1600,7 @@ main(int argc, char *argv[]) FILE *in; char *prog, *opath; - if ((prog = strrchr(argv[0], *LDAP_DIRSEP)) != 0) - prog++; - else - prog = argv[0]; + prog = lutil_progname( "ucgendat", argc, argv ); opath = 0; in = stdin; diff --git a/libraries/liblutil/Makefile.in b/libraries/liblutil/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..ba9f3ec5e7737c1e1e128a94a58b22914393aedc --- /dev/null +++ b/libraries/liblutil/Makefile.in @@ -0,0 +1,36 @@ +# $OpenLDAP$ +## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file +## +## Makefile for -llutil +## + +LIBRARY = liblutil.a + +NT_SRCS = ntservice.c +NT_OBJS = ntservice.o slapdmsg.res + +UNIX_SRCS = detach.c +UNIX_OBJS = detach.o + +SRCS = base64.c csn.c entropy.c sasl.c signal.c hash.c \ + md5.c passwd.c sha1.c getpass.c lockf.c utils.c uuid.c sockpair.c \ + @LIBSRCS@ $(@PLAT@_SRCS) + +OBJS = base64.o csn.o entropy.o sasl.o signal.o hash.o \ + md5.o passwd.o sha1.o getpass.o lockf.o utils.o uuid.o sockpair.o \ + @LIBOBJS@ $(@PLAT@_OBJS) + +LDAP_INCDIR= ../../include +LDAP_LIBDIR= ../../libraries + +# These rules are for a Mingw32 build, specifically. +# It's ok for them to be here because the clean rule is harmless, and +# slapdmsg.res won't get built unless it's declared in OBJS. + +slapdmsg.res: slapdmsg.rc slapdmsg.bin + windres $< -O coff -o $@ + +clean-local: + $(RM) *.res + diff --git a/libraries/liblutil/getopt.c b/libraries/liblutil/getopt.c new file mode 100644 index 0000000000000000000000000000000000000000..137944ab6f7d2552305e311af20fadaa53e6bd8a --- /dev/null +++ b/libraries/liblutil/getopt.c @@ -0,0 +1,126 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + getopt.c + + modified public-domain AT&T getopt(3) + modified by Kurt Zeilenga for inclusion into OpenLDAP +*/ + +#include "portable.h" + +#ifndef HAVE_GETOPT + +#include <stdio.h> + +#include <ac/string.h> +#include <ac/unistd.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +#include "lutil.h" + +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif + +int opterr = 1; +int optind = 1; +int optopt; +char * optarg; + +#ifdef HAVE_EBCDIC +extern int _trans_argv; +#endif + +static void ERR (char * const argv[], const char * s, char c) +{ +#ifdef DF_TRACE_DEBUG +printf("DF_TRACE_DEBUG: static void ERR () in getopt.c\n"); +#endif + if (opterr) + { + char *ptr, outbuf[4096]; + + ptr = lutil_strncopy(outbuf, argv[0], sizeof(outbuf) - 2); + ptr = lutil_strncopy(ptr, s, sizeof(outbuf)-2 -(ptr-outbuf)); + *ptr++ = c; + *ptr++ = '\n'; +#ifdef HAVE_EBCDIC + __atoe_l(outbuf, ptr - outbuf); +#endif + (void) write(STDERR_FILENO,outbuf,ptr - outbuf); + } +} + +int getopt (int argc, char * const argv [], const char * opts) +{ + static int sp = 1, error = (int) '?'; + static char sw = '-', eos = '\0', arg = ':'; + register char c, * cp; + +#ifdef DF_TRACE_DEBUG +printf("DF_TRACE_DEBUG: int getopt () in getopt.c\n"); +#endif + +#ifdef HAVE_EBCDIC + if (_trans_argv) { + int i; + for (i=0; i<argc; i++) __etoa(argv[i]); + _trans_argv = 0; + } +#endif + if (sp == 1) + { + if (optind >= argc || argv[optind][0] != sw + || argv[optind][1] == eos) + return EOF; + else if (strcmp(argv[optind],"--") == 0) + { + optind++; + return EOF; + } + } + c = argv[optind][sp]; + optopt = (int) c; + if (c == arg || (cp = strchr(opts,c)) == NULL) + { + ERR(argv,": illegal option--",c); + if (argv[optind][++sp] == eos) + { + optind++; + sp = 1; + } + return error; + } + else if (*++cp == arg) + { + if (argv[optind][sp + 1] != eos) + optarg = &argv[optind++][sp + 1]; + else if (++optind >= argc) + { + ERR(argv,": option requires an argument--",c); + sp = 1; + return error; + } + else + optarg = argv[optind++]; + sp = 1; + } + else + { + if (argv[optind][++sp] == eos) + { + sp = 1; + optind++; + } + optarg = NULL; + } + return (int) c; +} +#endif /* HAVE_GETOPT */ diff --git a/libraries/liblutil/liblutil.dsp b/libraries/liblutil/liblutil.dsp new file mode 100644 index 0000000000000000000000000000000000000000..436a6981bf7aeef502b0301375bfec07d163a915 --- /dev/null +++ b/libraries/liblutil/liblutil.dsp @@ -0,0 +1,297 @@ +# Microsoft Developer Studio Project File - Name="liblutil" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=liblutil - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "liblutil.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "liblutil.mak" CFG="liblutil - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "liblutil - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "liblutil - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "liblutil - Win32 Single Debug" (based on\ + "Win32 (x86) Static Library") +!MESSAGE "liblutil - Win32 Single Release" (based on\ + "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "liblutil - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\liblutil" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Release\olutil32.lib" + +!ELSEIF "$(CFG)" == "liblutil - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\liblutil" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Debug\olutil32.lib" + +!ELSEIF "$(CFG)" == "liblutil - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "liblutil" +# PROP BASE Intermediate_Dir "liblutil" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\liblutil" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Debug\olutil32.lib" +# ADD LIB32 /nologo /out:"..\..\SDebug\olutil32.lib" + +!ELSEIF "$(CFG)" == "liblutil - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "libluti0" +# PROP BASE Intermediate_Dir "libluti0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\liblutil" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Release\olutil32.lib" +# ADD LIB32 /nologo /out:"..\..\SRelease\olutil32.lib" + +!ENDIF + +# Begin Target + +# Name "liblutil - Win32 Release" +# Name "liblutil - Win32 Debug" +# Name "liblutil - Win32 Single Debug" +# Name "liblutil - Win32 Single Release" +# Begin Source File + +SOURCE=.\authpasswd.c +# End Source File +# Begin Source File + +SOURCE=.\base64.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\ac\bytes.h +# End Source File +# Begin Source File + +SOURCE=.\csn.c +# End Source File +# Begin Source File + +SOURCE=.\entropy.c +# End Source File +# Begin Source File + +SOURCE="..\..\include\getopt-compat.h" +# End Source File +# Begin Source File + +SOURCE=.\getopt.c +# End Source File +# Begin Source File + +SOURCE=.\getpass.c +# End Source File +# Begin Source File + +SOURCE=.\hash.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\ldap_cdefs.h +# End Source File +# Begin Source File + +SOURCE=.\lockf.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\lutil.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\lutil_hash.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\lutil_ldap.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\lutil_lockf.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\lutil_md5.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\lutil_sha1.h +# End Source File +# Begin Source File + +SOURCE=.\md5.c +# End Source File +# Begin Source File + +SOURCE=.\ntservice.c +# End Source File +# Begin Source File + +SOURCE=.\passwd.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\portable.h +# End Source File +# Begin Source File + +SOURCE="..\..\include\queue-compat.h" +# End Source File +# Begin Source File + +SOURCE=.\sasl.c +# End Source File +# Begin Source File + +SOURCE=.\sha1.c +# End Source File +# Begin Source File + +SOURCE=.\slapdmsg.mc + +!IF "$(CFG)" == "liblutil - Win32 Release" + +# Begin Custom Build - Building slapd message file +IntDir=.\..\..\Release\liblutil +InputPath=.\slapdmsg.mc + +"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + mkdir $(IntDir) + mc -v slapdmsg.mc -r $(IntDir) + rc /v /r $(IntDir)\slapdmsg.rc + +# End Custom Build + +!ELSEIF "$(CFG)" == "liblutil - Win32 Debug" + +# Begin Custom Build - Building slapd message file +IntDir=.\..\..\Debug\liblutil +InputPath=.\slapdmsg.mc + +"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + mkdir $(IntDir) + mc -v slapdmsg.mc -r $(IntDir) + rc /v /r $(IntDir)\slapdmsg.rc + +# End Custom Build + +!ELSEIF "$(CFG)" == "liblutil - Win32 Single Debug" + +# Begin Custom Build - Building slapd message file +IntDir=.\..\..\SDebug\liblutil +InputPath=.\slapdmsg.mc + +"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + mkdir $(IntDir) + mc -v slapdmsg.mc -r $(IntDir) + rc /v /r $(IntDir)\slapdmsg.rc + +# End Custom Build + +!ELSEIF "$(CFG)" == "liblutil - Win32 Single Release" + +# Begin Custom Build - Building slapd message file +IntDir=.\..\..\SRelease\liblutil +InputPath=.\slapdmsg.mc + +"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + mkdir $(IntDir) + mc -v slapdmsg.mc -r $(IntDir) + rc /v /r $(IntDir)\slapdmsg.rc + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\sockpair.c +# End Source File +# Begin Source File + +SOURCE=.\utils.c +# End Source File +# Begin Source File + +SOURCE=.\uuid.c +# End Source File +# End Target +# End Project diff --git a/libraries/liblutil/ntservice.c b/libraries/liblutil/ntservice.c new file mode 100644 index 0000000000000000000000000000000000000000..9bd27b7065837dfaab261b7564f97324eb8cdaf2 --- /dev/null +++ b/libraries/liblutil/ntservice.c @@ -0,0 +1,513 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +/* + * NT Service manager utilities for OpenLDAP services + * these should NOT be slapd specific, but are + */ + +#include "portable.h" + +#ifdef HAVE_NT_SERVICE_MANAGER + +#include <ac/stdlib.h> +#include <ac/string.h> + +#include <stdio.h> + +#include <windows.h> +#include <winsvc.h> + +#include <ldap.h> + +/* + * The whole debug implementation is a bit of a hack. + * We have to define this LDAP_SLAPD_V macro here since the slap.h + * header file isn't included (and really shouldn't be). + * TODO: re-implement debug functions so that the debug level can + * be passed around instead of having to count on the existence of + * ldap_debug, slap_debug, etc. + */ +#define ldap_debug slap_debug +LDAP_SLAPD_V (int) slap_debug; + +#include "ldap_log.h" +#include "ldap_pvt_thread.h" + + +#include "ldap_defaults.h" + +#include "slapdmsg.h" + +#define SCM_NOTIFICATION_INTERVAL 5000 +#define THIRTY_SECONDS (30 * 1000) + +int is_NT_Service = 1; /* assume this is an NT service until determined that */ + /* startup was from the command line */ + +SERVICE_STATUS SLAPDServiceStatus; +SERVICE_STATUS_HANDLE hSLAPDServiceStatus; + +ldap_pvt_thread_cond_t started_event, stopped_event; +ldap_pvt_thread_t start_status_tid, stop_status_tid; + +void (*stopfunc)(int); + +static char *GetLastErrorString( void ); + +int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszDisplayName, + LPCTSTR lpszBinaryPathName, BOOL auto_start) +{ + HKEY hKey; + DWORD dwValue, dwDisposition; + SC_HANDLE schSCManager, schService; + + fprintf( stderr, "The install path is %s.\n", lpszBinaryPathName ); + if ((schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE ) ) != NULL ) + { + if ((schService = CreateService( + schSCManager, + lpszServiceName, + lpszDisplayName, + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + auto_start ? SERVICE_AUTO_START : SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + lpszBinaryPathName, + NULL, NULL, NULL, NULL, NULL)) != NULL) + { + char regpath[132]; + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + + snprintf( regpath, sizeof regpath, + "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", + lpszServiceName ); + /* Create the registry key for event logging to the Windows NT event log. */ + if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, + regpath, 0, + "REG_SZ", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, + &dwDisposition) != ERROR_SUCCESS) + { + fprintf( stderr, "RegCreateKeyEx() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); + RegCloseKey(hKey); + return(0); + } + if ( RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ, lpszBinaryPathName, strlen(lpszBinaryPathName) + 1) != ERROR_SUCCESS) + { + fprintf( stderr, "RegSetValueEx(EventMessageFile) failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); + RegCloseKey(hKey); + return(0); + } + + dwValue = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; + if ( RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD)) != ERROR_SUCCESS) + { + fprintf( stderr, "RegCreateKeyEx(TypesSupported) failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); + RegCloseKey(hKey); + return(0); + } + RegCloseKey(hKey); + return(1); + } + else + { + fprintf( stderr, "CreateService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); + CloseServiceHandle(schSCManager); + return(0); + } + } + else + fprintf( stderr, "OpenSCManager() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); + return(0); +} + + +int srv_remove(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) +{ + SC_HANDLE schSCManager, schService; + + fprintf( stderr, "The installed path is %s.\n", lpszBinaryPathName ); + if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE)) != NULL ) + { + if ((schService = OpenService(schSCManager, lpszServiceName, DELETE)) != NULL) + { + if ( DeleteService(schService) == TRUE) + { + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return(1); + } else { + fprintf( stderr, "DeleteService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); + fprintf( stderr, "The %s service has not been removed.\n", lpszBinaryPathName); + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return(0); + } + } else { + fprintf( stderr, "OpenService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); + CloseServiceHandle(schSCManager); + return(0); + } + } + else + fprintf( stderr, "OpenSCManager() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); + return(0); +} + + +DWORD +svc_installed (LPTSTR lpszServiceName, LPTSTR lpszBinaryPathName) +{ + char buf[256]; + HKEY key; + DWORD rc; + DWORD type; + long len; + + strcpy(buf, TEXT("SYSTEM\\CurrentControlSet\\Services\\")); + strcat(buf, lpszServiceName); + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) + return(-1); + + rc = 0; + if (lpszBinaryPathName) { + len = sizeof(buf); + if (RegQueryValueEx(key, "ImagePath", NULL, &type, buf, &len) == ERROR_SUCCESS) { + if (strcmp(lpszBinaryPathName, buf)) + rc = -1; + } + } + RegCloseKey(key); + return(rc); +} + + +DWORD +svc_running (LPTSTR lpszServiceName) +{ + SC_HANDLE service; + SC_HANDLE scm; + DWORD rc; + SERVICE_STATUS ss; + + if (!(scm = OpenSCManager(NULL, NULL, GENERIC_READ))) + return(GetLastError()); + + rc = 1; + service = OpenService(scm, lpszServiceName, SERVICE_QUERY_STATUS); + if (service) { + if (!QueryServiceStatus(service, &ss)) + rc = GetLastError(); + else if (ss.dwCurrentState != SERVICE_STOPPED) + rc = 0; + CloseServiceHandle(service); + } + CloseServiceHandle(scm); + return(rc); +} + + +static void *start_status_routine( void *ptr ) +{ + DWORD wait_result; + int done = 0; + + while ( !done ) + { + wait_result = WaitForSingleObject( started_event, SCM_NOTIFICATION_INTERVAL ); + switch ( wait_result ) + { + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + /* the object that we were waiting for has been destroyed (ABANDONED) or + * signalled (TIMEOUT_0). We can assume that the startup process is + * complete and tell the Service Control Manager that we are now runnng */ + SLAPDServiceStatus.dwCurrentState = SERVICE_RUNNING; + SLAPDServiceStatus.dwWin32ExitCode = NO_ERROR; + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = 1000; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + done = 1; + break; + case WAIT_TIMEOUT: + /* We've waited for the required time, so send an update to the Service Control + * Manager saying to wait again. */ + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + break; + case WAIT_FAILED: + /* theres been some problem with WaitForSingleObject so tell the Service + * Control Manager to wait 30 seconds before deploying its assasin and + * then leave the thread. */ + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + done = 1; + break; + } + } + ldap_pvt_thread_exit(NULL); + return NULL; +} + + + +static void *stop_status_routine( void *ptr ) +{ + DWORD wait_result; + int done = 0; + + while ( !done ) + { + wait_result = WaitForSingleObject( stopped_event, SCM_NOTIFICATION_INTERVAL ); + switch ( wait_result ) + { + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + /* the object that we were waiting for has been destroyed (ABANDONED) or + * signalled (TIMEOUT_0). The shutting down process is therefore complete + * and the final SERVICE_STOPPED message will be sent to the service control + * manager prior to the process terminating. */ + done = 1; + break; + case WAIT_TIMEOUT: + /* We've waited for the required time, so send an update to the Service Control + * Manager saying to wait again. */ + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + break; + case WAIT_FAILED: + /* theres been some problem with WaitForSingleObject so tell the Service + * Control Manager to wait 30 seconds before deploying its assasin and + * then leave the thread. */ + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + done = 1; + break; + } + } + ldap_pvt_thread_exit(NULL); + return NULL; +} + + + +void WINAPI SLAPDServiceCtrlHandler( IN DWORD Opcode) +{ + switch (Opcode) + { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + + Debug( LDAP_DEBUG_TRACE, "Service Shutdown ordered\n", 0, 0, 0 ); + SLAPDServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + + ldap_pvt_thread_cond_init( &stopped_event ); + if ( stopped_event == NULL ) + { + /* the event was not created. We will ask the service control manager for 30 + * seconds to shutdown */ + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + } + else + { + /* start a thread to report the progress to the service control manager + * until the stopped_event is fired. */ + if ( ldap_pvt_thread_create( &stop_status_tid, 0, stop_status_routine, NULL ) == 0 ) + { + + } + else { + /* failed to create the thread that tells the Service Control Manager that the + * service stopping is proceeding. + * tell the Service Control Manager to wait another 30 seconds before deploying its + * assasin. */ + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + } + } + stopfunc( -1 ); + break; + + case SERVICE_CONTROL_INTERROGATE: + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + break; + } + return; +} + +void *getRegParam( char *svc, char *value ) +{ + HKEY hkey; + char path[255]; + DWORD vType; + static char vValue[1024]; + DWORD valLen = sizeof( vValue ); + + if ( svc != NULL ) + snprintf ( path, sizeof path, "SOFTWARE\\%s", svc ); + else + snprintf ( path, sizeof path, "SOFTWARE\\OpenLDAP\\Parameters" ); + + if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &hkey ) != ERROR_SUCCESS ) + { + /*Debug( LDAP_DEBUG_ANY, "RegOpenKeyEx() %s\n", GetLastErrorString(), 0, 0); */ + return NULL; + } + + if ( RegQueryValueEx( hkey, value, NULL, &vType, vValue, &valLen ) != ERROR_SUCCESS ) + { + /*Debug( LDAP_DEBUG_ANY, "RegQueryValueEx() %s\n", GetLastErrorString(), 0, 0 );*/ + RegCloseKey( hkey ); + return NULL; + } + RegCloseKey( hkey ); + + switch ( vType ) + { + case REG_BINARY: + case REG_DWORD: + return (void*)&vValue; + case REG_SZ: + return (void*)&vValue; + } + return (void*)NULL; +} + +void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *urls ) +{ + char *Inserts[5]; + WORD i = 0, j; + HANDLE hEventLog; + + hEventLog = RegisterEventSource( NULL, svc ); + + Inserts[i] = (char *)malloc( 20 ); + itoa( slap_debug, Inserts[i++], 10 ); + Inserts[i++] = strdup( configfile ); + Inserts[i++] = strdup( urls ? urls : "ldap:///" ); + Inserts[i++] = strdup( is_NT_Service ? "svc" : "cmd" ); + + ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, + MSG_SLAPD_STARTED, NULL, i, 0, (LPCSTR *) Inserts, NULL ); + + for ( j = 0; j < i; j++ ) + ldap_memfree( Inserts[j] ); + DeregisterEventSource( hEventLog ); +} + + + +void LogSlapdStoppedEvent( char *svc ) +{ + HANDLE hEventLog; + + hEventLog = RegisterEventSource( NULL, svc ); + ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, + MSG_SLAPD_STOPPED, NULL, 0, 0, NULL, NULL ); + DeregisterEventSource( hEventLog ); +} + + +void CommenceStartupProcessing( LPCTSTR lpszServiceName, + void (*stopper)(int) ) +{ + hSLAPDServiceStatus = RegisterServiceCtrlHandler( lpszServiceName, (LPHANDLER_FUNCTION)SLAPDServiceCtrlHandler); + + stopfunc = stopper; + + /* initialize the Service Status structure */ + SLAPDServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + SLAPDServiceStatus.dwCurrentState = SERVICE_START_PENDING; + SLAPDServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + SLAPDServiceStatus.dwWin32ExitCode = NO_ERROR; + SLAPDServiceStatus.dwServiceSpecificExitCode = 0; + SLAPDServiceStatus.dwCheckPoint = 1; + SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; + + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + + /* start up a thread to keep sending SERVICE_START_PENDING to the Service Control Manager + * until the slapd listener is completed and listening. Only then should we send + * SERVICE_RUNNING to the Service Control Manager. */ + ldap_pvt_thread_cond_init( &started_event ); + if ( started_event == NULL) + { + /* failed to create the event to determine when the startup process is complete so + * tell the Service Control Manager to wait another 30 seconds before deploying its + * assasin */ + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + } + else + { + /* start a thread to report the progress to the service control manager + * until the started_event is fired. */ + if ( ldap_pvt_thread_create( &start_status_tid, 0, start_status_routine, NULL ) == 0 ) + { + + } + else { + /* failed to create the thread that tells the Service Control Manager that the + * service startup is proceeding. + * tell the Service Control Manager to wait another 30 seconds before deploying its + * assasin. */ + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + } + } +} + +void ReportSlapdShutdownComplete( ) +{ + if ( is_NT_Service ) + { + /* stop sending SERVICE_STOP_PENDING messages to the Service Control Manager */ + ldap_pvt_thread_cond_signal( &stopped_event ); + ldap_pvt_thread_cond_destroy( &stopped_event ); + + /* wait for the thread sending the SERVICE_STOP_PENDING messages to the Service Control Manager to die. + * if the wait fails then put ourselves to sleep for half the Service Control Manager update interval */ + if (ldap_pvt_thread_join( stop_status_tid, (void *) NULL ) == -1) + ldap_pvt_thread_sleep( SCM_NOTIFICATION_INTERVAL / 2 ); + + SLAPDServiceStatus.dwCurrentState = SERVICE_STOPPED; + SLAPDServiceStatus.dwCheckPoint++; + SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL; + SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + } +} + +static char *GetErrorString( int err ) +{ + static char msgBuf[1024]; + + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + msgBuf, 1024, NULL ); + + return msgBuf; +} + +static char *GetLastErrorString( void ) +{ + return GetErrorString( GetLastError() ); +} +#endif diff --git a/libraries/liblutil/sasl.c b/libraries/liblutil/sasl.c new file mode 100644 index 0000000000000000000000000000000000000000..a1308a8018deb8cd52e6a1a89ad02a14b7f6e8fa --- /dev/null +++ b/libraries/liblutil/sasl.c @@ -0,0 +1,206 @@ +/* $OpenLDAP$ */ +/* + * Copyright 2000-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#ifdef HAVE_CYRUS_SASL + +#include <stdio.h> +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/unistd.h> + +#ifdef HAVE_SASL_SASL_H +#include <sasl/sasl.h> +#else +#include <sasl.h> +#endif + +#include <ldap.h> +#include "lutil_ldap.h" + + +typedef struct lutil_sasl_defaults_s { + char *mech; + char *realm; + char *authcid; + char *passwd; + char *authzid; +} lutilSASLdefaults; + + +void * +lutil_sasl_defaults( + LDAP *ld, + char *mech, + char *realm, + char *authcid, + char *passwd, + char *authzid ) +{ + lutilSASLdefaults *defaults; + + defaults = ber_memalloc( sizeof( lutilSASLdefaults ) ); + + if( defaults == NULL ) return NULL; + + defaults->mech = mech; + defaults->realm = realm; + defaults->authcid = authcid; + defaults->passwd = passwd; + defaults->authzid = authzid; + + if( defaults->mech == NULL ) { + ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech ); + } + if( defaults->realm == NULL ) { + ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm ); + } + if( defaults->authcid == NULL ) { + ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid ); + } + if( defaults->authzid == NULL ) { + ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid ); + } + + return defaults; +} + +static int interaction( + unsigned flags, + sasl_interact_t *interact, + lutilSASLdefaults *defaults ) +{ + const char *dflt = interact->defresult; + char input[1024]; + + int noecho=0; + int challenge=0; + + switch( interact->id ) { + case SASL_CB_GETREALM: + if( defaults ) dflt = defaults->realm; + break; + case SASL_CB_AUTHNAME: + if( defaults ) dflt = defaults->authcid; + break; + case SASL_CB_PASS: + if( defaults ) dflt = defaults->passwd; + noecho = 1; + break; + case SASL_CB_USER: + if( defaults ) dflt = defaults->authzid; + break; + case SASL_CB_NOECHOPROMPT: + noecho = 1; + challenge = 1; + break; + case SASL_CB_ECHOPROMPT: + challenge = 1; + break; + } + + if( dflt && !*dflt ) dflt = NULL; + + if( flags != LDAP_SASL_INTERACTIVE && + ( dflt || interact->id == SASL_CB_USER ) ) + { + goto use_default; + } + + if( flags == LDAP_SASL_QUIET ) { + /* don't prompt */ + return LDAP_OTHER; + } + + if( challenge ) { + if( interact->challenge ) { + fprintf( stderr, "Challenge: %s\n", interact->challenge ); + } + } + + if( dflt ) { + fprintf( stderr, "Default: %s\n", dflt ); + } + + snprintf( input, sizeof input, "%s: ", + interact->prompt ? interact->prompt : "Interact" ); + + if( noecho ) { + interact->result = (char *) getpassphrase( input ); + interact->len = interact->result + ? strlen( interact->result ) : 0; + + } else { + /* prompt user */ + fputs( input, stderr ); + + /* get input */ + interact->result = fgets( input, sizeof(input), stdin ); + + if( interact->result == NULL ) { + interact->len = 0; + return LDAP_UNAVAILABLE; + } + + /* len of input */ + interact->len = strlen(input); + + if( interact->len > 0 && input[interact->len - 1] == '\n' ) { + /* input includes '\n', trim it */ + interact->len--; + input[interact->len] = '\0'; + } + } + + + if( interact->len > 0 ) { + /* duplicate */ + char *p = (char *)interact->result; + interact->result = strdup( p ); + + /* zap */ + memset( p, '\0', interact->len ); + + } else { +use_default: + /* input must be empty */ + interact->result = strdup( (dflt && *dflt) ? dflt : "" ); + interact->len = interact->result + ? strlen( interact->result ) : 0; + } + + if( defaults && defaults->passwd && interact->id == SASL_CB_PASS ) { + /* zap password after first use */ + memset( defaults->passwd, '\0', strlen(defaults->passwd) ); + defaults->passwd = NULL; + } + + return LDAP_SUCCESS; +} + +int lutil_sasl_interact( + LDAP *ld, + unsigned flags, + void *defaults, + void *in ) +{ + sasl_interact_t *interact = in; + + if( flags == LDAP_SASL_INTERACTIVE ) { + fputs( "SASL Interaction\n", stderr ); + } + + while( interact->id != SASL_CB_LIST_END ) { + int rc = interaction( flags, interact, defaults ); + + if( rc ) return rc; + interact++; + } + + return LDAP_SUCCESS; +} +#endif diff --git a/libraries/liblutil/stdio.c b/libraries/liblutil/stdio.c new file mode 100644 index 0000000000000000000000000000000000000000..adf41871851a401e5a7fe9447d9f8138818638ec --- /dev/null +++ b/libraries/liblutil/stdio.c @@ -0,0 +1,228 @@ +/* $OpenLDAP$ */ +/* + * Copyright 2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdarg.h> +#include <ac/string.h> + +#include <lutil.h> + +#ifndef HAVE_VSNPRINTF +/* Write at most n characters to the buffer in str, return the + * number of chars written or -1 if the buffer would have been + * overflowed. + * + * This is portable to any POSIX-compliant system. We use pipe() + * to create a valid file descriptor, and then fdopen() it to get + * a valid FILE pointer. The user's buffer and size are assigned + * to the FILE pointer using setvbuf. Then we close the read side + * of the pipe to invalidate the descriptor. + * + * If the write arguments all fit into size n, the write will + * return successfully. If the write is too large, the stdio + * buffer will need to be flushed to the underlying file descriptor. + * The flush will fail because it is attempting to write to a + * broken pipe, and the write will be terminated. + * -- hyc, 2002-07-19 + */ +#ifndef HAVE_EBCDIC +/* This emulation uses vfprintf; on OS/390 we're also emulating + * that function so it's more efficient just to have a separate + * version of vsnprintf there. + */ +#include <ac/signal.h> +int vsnprintf( char *str, size_t n, const char *fmt, va_list ap ) +{ + int fds[2], res; + FILE *f; + RETSIGTYPE (*sig)(); + + if (pipe( fds )) return -1; + + f = fdopen( fds[1], "w" ); + if ( !f ) { + close( fds[1] ); + close( fds[0] ); + return -1; + } + setvbuf( f, str, _IOFBF, n ); + sig = signal( SIGPIPE, SIG_IGN ); + close( fds[0] ); + + res = vfprintf( f, fmt, ap ); + + fclose( f ); + signal( SIGPIPE, sig ); + return res; +} +#endif + +int snprintf( char *str, size_t n, const char *fmt, ... ) +{ + va_list ap; + int res; + + va_start( ap, fmt ); + res = vsnprintf( str, n, fmt, ap ); + va_end( ap ); + return res; +} +#endif /* !HAVE_VSNPRINTF */ + +#ifdef HAVE_EBCDIC +/* stdio replacements with ASCII/EBCDIC translation for OS/390. + * The OS/390 port depends on the CONVLIT compiler option being + * used to force character and string literals to be compiled in + * ISO8859-1, and the __LIBASCII cpp symbol to be defined to use the + * OS/390 ASCII-compatibility library. This library only supplies + * an ASCII version of sprintf, so other needed functions are + * provided here. + * + * All of the internal character manipulation is done in ASCII, + * but file I/O is EBCDIC, so we catch any stdio reading/writing + * of files here and do the translations. + */ + +#undef fputs +#undef fgets + +char *lutil_fgets( char *s, int n, FILE *fp ) +{ + s = (char *)fgets( s, n, fp ); + if ( s ) __etoa( s ); + return s; +} + +int lutil_fputs( const char *str, FILE *fp ) +{ + char buf[8192]; + + strncpy( buf, str, sizeof(buf) ); + __atoe( buf ); + return fputs( buf, fp ); +} + +/* The __LIBASCII doesn't include a working vsprintf, so we make do + * using just sprintf. This is a very simplistic parser that looks for + * format strings and uses sprintf to process them one at a time. + * Literal text is just copied straight to the destination. + * The result is appended to the destination string. The parser + * recognizes field-width specifiers and the 'l' qualifier; it + * may need to be extended to recognize other qualifiers but so + * far this seems to be enough. + */ +int vsnprintf( char *str, size_t n, const char *fmt, va_list ap ) +{ + char *ptr, *pct, *s2, *f2, *end; + char fm2[64]; + int len, rem; + + ptr = (char *)fmt; + s2 = str; + fm2[0] = '%'; + if (n) + end = str + n; + else + end = NULL; + + for (pct = strchr(ptr, '%'); pct; pct = strchr(ptr, '%')) { + len = pct-ptr; + if (end) { + rem = end-s2; + if (rem < 1) return -1; + if (rem < len) len = rem; + } + s2 = lutil_strncopy( s2, ptr, len ); + /* Did we cheat the length above? If so, bail out */ + if (len < pct-ptr) return -1; + for (pct++, f2 = fm2+1; isdigit(*pct);) *f2++ = *pct++; + if (*pct == 'l') *f2++ = *pct++; + if (*pct == '%') *s2++ = '%'; + else { + *f2++ = *pct; + *f2 = '\0'; + if (*pct == 's') { + char *ss = va_arg(ap, char *); + /* Attempt to limit sprintf output. This + * may be thrown off if field widths were + * specified for this string. + * + * If it looks like the string is too + * long for the remaining buffer, bypass + * sprintf and just copy what fits, then + * quit. + */ + if (end && strlen(ss) > (rem=end-s2)) { + strncpy(s2, ss, rem); + return -1; + } else { + s2 += sprintf(s2, fm2, ss); + } + } else + s2 += sprintf(s2, fm2, va_arg(ap, int)); + } + ptr = pct + 1; + } + if (end) { + rem = end-s2; + if (rem > 0) { + len = strlen(ptr); + s2 = lutil_strncopy( s2, ptr, rem ); + rem -= len; + } + if (rem < 0) return -1; + } else { + s2 = lutil_strcopy( s2, ptr ); + } + return s2 - str; +} + +int lutil_vsprintf( char *str, const char *fmt, va_list ap ) +{ + return vsnprintf( str, 0, fmt, ap ); +} + +/* The fixed buffer size here is a problem, we don't know how + * to flush the buffer and keep printing if the msg is too big. + * Hopefully we never try to write something bigger than this + * in a log msg... + */ +int lutil_vfprintf( FILE *fp, const char *fmt, va_list ap ) +{ + char buf[8192]; + int res; + + vsnprintf( buf, sizeof(buf), fmt, ap ); + __atoe( buf ); + res = fputs( buf, fp ); + if (res == EOF) res = -1; + return res; +} + +int lutil_printf( const char *fmt, ... ) +{ + va_list ap; + int res; + + va_start( ap, fmt ); + res = lutil_vfprintf( stdout, fmt, ap ); + va_end( ap ); + return res; +} + +int lutil_fprintf( FILE *fp, const char *fmt, ... ) +{ + va_list ap; + int res; + + va_start( ap, fmt ); + res = lutil_vfprintf( fp, fmt, ap ); + va_end( ap ); + return res; +} +#endif diff --git a/libraries/liblutil/utils.c b/libraries/liblutil/utils.c new file mode 100644 index 0000000000000000000000000000000000000000..973406f21ebde25448f840517aba226129c7b79b --- /dev/null +++ b/libraries/liblutil/utils.c @@ -0,0 +1,109 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/unistd.h> +#include <ac/time.h> +#ifdef HAVE_IO_H +#include <io.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#include <lutil.h> +#include <ldap_defaults.h> + +#ifdef HAVE_EBCDIC +int _trans_argv = 1; +#endif + +char* lutil_progname( const char* name, int argc, char *argv[] ) +{ + char *progname; + + if(argc == 0) { + return (char *)name; + } + +#ifdef HAVE_EBCDIC + if (_trans_argv) { + int i; + for (i=0; i<argc; i++) __etoa(argv[i]); + _trans_argv = 0; + } +#endif + progname = strrchr ( argv[0], *LDAP_DIRSEP ); + progname = progname ? &progname[1] : argv[0]; + + return progname; +} + +size_t lutil_gentime( char *s, size_t max, const struct tm *tm ) +{ + size_t ret; +#ifdef HAVE_EBCDIC +/* We've been compiling in ASCII so far, but we want EBCDIC now since + * strftime only understands EBCDIC input. + */ +#pragma convlit(suspend) +#endif + ret = strftime( s, max, "%Y%m%d%H%M%SZ", tm ); +#ifdef HAVE_EBCDIC +#pragma convlit(resume) + __etoa( s ); +#endif + return ret; +} + +/* strcopy is like strcpy except it returns a pointer to the trailing NUL of + * the result string. This allows fast construction of catenated strings + * without the overhead of strlen/strcat. + */ +char * +lutil_strcopy( + char *a, + const char *b +) +{ + if (!a || !b) + return a; + + while ((*a++ = *b++)) ; + return a-1; +} + +/* strncopy is like strcpy except it returns a pointer to the trailing NUL of + * the result string. This allows fast construction of catenated strings + * without the overhead of strlen/strcat. + */ +char * +lutil_strncopy( + char *a, + const char *b, + size_t n +) +{ + if (!a || !b || n == 0) + return a; + + while ((*a++ = *b++) && n-- > 0) ; + return a-1; +} + +#ifndef HAVE_MKSTEMP +int mkstemp( char * template ) +{ +#ifdef HAVE_MKTEMP + return open ( mktemp ( template ), O_RDWR|O_CREAT|O_EXCL, 0600 ); +#else + return -1; +#endif +} +#endif diff --git a/libraries/librewrite/map.c b/libraries/librewrite/map.c index 8db54af13711b89701804bb6fdcf5a214cf20012..19389dff45ffa80718476d90d4242bae0487310e 100644 --- a/libraries/librewrite/map.c +++ b/libraries/librewrite/map.c @@ -24,6 +24,8 @@ #include <portable.h> +#include <stdio.h> + #ifdef HAVE_PWD_H #include <pwd.h> #endif @@ -541,6 +543,7 @@ rewrite_xmap_apply( break; } +#ifdef HAVE_PW_GECOS if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) { int l = strlen( pwd->pw_gecos ); @@ -555,7 +558,9 @@ rewrite_xmap_apply( break; } val->bv_len = l; - } else { + } else +#endif /* HAVE_PW_GECOS */ + { val->bv_val = strdup( key->bv_val ); val->bv_len = key->bv_len; } diff --git a/libraries/librewrite/parse.c b/libraries/librewrite/parse.c index bc83e0594e575a6a0cc61c4ce12ec07ef05e0452..42b0180ba38e7740c1db2a31270a71cbb956fcc4 100644 --- a/libraries/librewrite/parse.c +++ b/libraries/librewrite/parse.c @@ -24,6 +24,8 @@ #include <portable.h> +#include <stdio.h> + #include "rewrite-int.h" static int diff --git a/libraries/librewrite/rewrite.c b/libraries/librewrite/rewrite.c new file mode 100644 index 0000000000000000000000000000000000000000..ac301b7a51c0b106f920fb4b410145577d55c95a --- /dev/null +++ b/libraries/librewrite/rewrite.c @@ -0,0 +1,144 @@ +/****************************************************************************** + * + * Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it> + * All rights reserved. + * + * Permission is granted to anyone to use this software for any purpose + * on any computer system, and to alter it and redistribute it, subject + * to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of this + * software, no matter how awful, even if they arise from flaws in it. + * + * 2. The origin of this software must not be misrepresented, either by + * explicit claim or by omission. Since few users ever read sources, + * credits should appear in the documentation. + * + * 3. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software. Since few users + * ever read sources, credits should appear in the documentation. + * + * 4. This notice may not be removed or altered. + * + ******************************************************************************/ + +#include <portable.h> + +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/syslog.h> +#include <ac/regex.h> +#include <ac/socket.h> +#include <ac/unistd.h> +#include <ac/ctype.h> +#include <ac/string.h> +#include <stdio.h> + +#include <rewrite.h> + +int ldap_debug; +int ldap_syslog; +int ldap_syslog_level; + +char * +apply( + FILE *fin, + const char *rewriteContext, + const char *arg +) +{ + struct rewrite_info *info; + char *string, *sep, *result = NULL; + int rc; + void *cookie = &info; + + info = rewrite_info_init(REWRITE_MODE_ERR); + + if ( rewrite_read( fin, info ) != 0 ) { + exit( EXIT_FAILURE ); + } + + rewrite_param_set( info, "prog", "rewrite" ); + + rewrite_session_init( info, cookie ); + + string = strdup( arg ); + for ( sep = strchr( rewriteContext, ',' ); + rewriteContext != NULL; + rewriteContext = sep, + sep ? sep = strchr( rewriteContext, ',' ) : NULL ) { + if ( sep != NULL ) { + sep[ 0 ] = '\0'; + sep++; + } + /* rc = rewrite( info, rewriteContext, string, &result ); */ + rc = rewrite_session( info, rewriteContext, string, + cookie, &result ); + + fprintf( stdout, "%s -> %s\n", string, + ( result ? result : "unwilling to perform" ) ); + if ( result == NULL ) { + break; + } + free( string ); + string = result; + } + + rewrite_session_delete( info, cookie ); + + return result; +} + +int +main( int argc, char *argv[] ) +{ + FILE *fin = NULL; + char *rewriteContext = REWRITE_DEFAULT_CONTEXT; + + while ( 1 ) { + int opt = getopt( argc, argv, "f:hr:" ); + + if ( opt == EOF ) { + break; + } + + switch ( opt ) { + case 'f': + fin = fopen( optarg, "r" ); + if ( fin == NULL ) { + fprintf( stderr, "unable to open file '%s'\n", + optarg ); + exit( EXIT_FAILURE ); + } + break; + + case 'h': + fprintf( stderr, + "usage: rewrite [options] string\n" + "\n" + "\t\t-f file\t\tconfiguration file\n" + "\t\t-r rule[s]\tlist of comma-separated rules\n" + "\n" + "\tsyntax:\n" + "\t\trewriteEngine\t{on|off}\n" + "\t\trewriteContext\tcontextName [alias aliasedContextName]\n" + "\t\trewriteRule\tpattern subst [flags]\n" + "\n" + ); + exit( EXIT_SUCCESS ); + + case 'r': + rewriteContext = strdup( optarg ); + break; + } + } + + if ( optind >= argc ) { + return -1; + } + + apply( ( fin ? fin : stdin ), rewriteContext, argv[ optind ] ); + + return 0; +} +