From: Howard Chu Date: Thu, 24 Mar 2011 06:49:04 +0000 (+0000) Subject: ITS#6870 move ldif.c and fetch.c from liblutil to libldap X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=f8a5ce4a6e91953d6965f4571f562d85881f39c8;p=openldap ITS#6870 move ldif.c and fetch.c from liblutil to libldap --- diff --git a/libraries/libldap/Makefile.in b/libraries/libldap/Makefile.in index 4b71ddd800..782101d992 100644 --- a/libraries/libldap/Makefile.in +++ b/libraries/libldap/Makefile.in @@ -28,7 +28,7 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \ charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ tls2.c tls_o.c tls_g.c tls_m.c \ turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \ - assertion.c deref.c ldifutil.c + assertion.c deref.c ldifutil.c ldif.c fetch.c OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ controls.lo messages.lo references.lo extended.lo cyrus.lo \ @@ -41,7 +41,7 @@ OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ tls2.lo tls_o.lo tls_g.lo tls_m.lo \ turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \ - assertion.lo deref.lo ldifutil.lo + assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries diff --git a/libraries/libldap/fetch.c b/libraries/libldap/fetch.c new file mode 100644 index 0000000000..fe734295c7 --- /dev/null +++ b/libraries/libldap/fetch.c @@ -0,0 +1,133 @@ +/* fetch.c - routines for fetching data at URLs */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 1999-2011 The OpenLDAP Foundation. + * Portions Copyright 1999-2003 Kurt D. Zeilenga. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* This work was initially developed by Kurt D. Zeilenga for + * inclusion in OpenLDAP Software. + */ + +#include "portable.h" + +#include + +#include + +#include +#include +#include + +#ifdef HAVE_FETCH +#include +#endif + +#include "lber_pvt.h" +#include "ldap_pvt.h" +#include "ldap_config.h" +#include "ldif.h" + +FILE * +ldif_open_url( + LDAP_CONST char *urlstr ) +{ + FILE *url; + + if( strncasecmp( "file:", urlstr, sizeof("file:")-1 ) == 0 ) { + char *p; + urlstr += sizeof("file:")-1; + + /* we don't check for LDAP_DIRSEP since URLs should contain '/' */ + if ( urlstr[0] == '/' && urlstr[1] == '/' ) { + urlstr += 2; + /* path must be absolute if authority is present */ + if ( urlstr[0] != '/' ) + return NULL; + } + + p = ber_strdup( urlstr ); + + /* But we should convert to LDAP_DIRSEP before use */ + if ( LDAP_DIRSEP[0] != '/' ) { + char *s = p; + while (( s = strchr( s, '/' ))) + *s++ = LDAP_DIRSEP[0]; + } + + ldap_pvt_hex_unescape( p ); + + url = fopen( p, "rb" ); + + ber_memfree( p ); + } else { +#ifdef HAVE_FETCH + url = fetchGetURL( (char*) urlstr, "" ); +#else + url = NULL; +#endif + } + return url; +} + +int +ldif_fetch_url( + LDAP_CONST char *urlstr, + char **valuep, + ber_len_t *vlenp ) +{ + FILE *url; + char buffer[1024]; + char *p = NULL; + size_t total; + size_t bytes; + + *valuep = NULL; + *vlenp = 0; + + url = ldif_open_url( urlstr ); + + if( url == NULL ) { + return -1; + } + + total = 0; + + while( (bytes = fread( buffer, 1, sizeof(buffer), url )) != 0 ) { + char *newp = ber_memrealloc( p, total + bytes + 1 ); + if( newp == NULL ) { + ber_memfree( p ); + fclose( url ); + return -1; + } + p = newp; + AC_MEMCPY( &p[total], buffer, bytes ); + total += bytes; + } + + fclose( url ); + + if( total == 0 ) { + char *newp = ber_memrealloc( p, 1 ); + if( newp == NULL ) { + ber_memfree( p ); + return -1; + } + p = newp; + } + + p[total] = '\0'; + *valuep = p; + *vlenp = total; + + return 0; +} diff --git a/libraries/libldap/ldif.c b/libraries/libldap/ldif.c new file mode 100644 index 0000000000..0ee7849f16 --- /dev/null +++ b/libraries/libldap/ldif.c @@ -0,0 +1,932 @@ +/* ldif.c - routines for dealing with LDIF files */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2011 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. This + * software is provided ``as is'' without express or implied warranty. + */ +/* This work was originally developed by the University of Michigan + * and distributed as part of U-MICH LDAP. + */ + +#include "portable.h" + +#include + +#include +#include + +#include +#include +#include + +int ldif_debug = 0; + +#include "ldap_log.h" +#include "lber_pvt.h" +#include "ldif.h" + +#define RIGHT2 0x03 +#define RIGHT4 0x0f +#define CONTINUED_LINE_MARKER '\r' + +#ifdef CSRIMALLOC +#define ber_memalloc malloc +#define ber_memcalloc calloc +#define ber_memrealloc realloc +#define ber_strdup strdup +#endif + +static const char nib2b64[0x40] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const unsigned char b642nib[0x80] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +/* + * ldif_parse_line - takes a line of the form "type:[:] value" and splits it + * into components "type" and "value". if a double colon separates type from + * value, then value is encoded in base 64, and parse_line un-decodes it + * (in place) before returning. The type and value are stored in malloc'd + * memory which must be freed by the caller. + * + * ldif_parse_line2 - operates in-place on input buffer, returning type + * in-place. Will return value in-place if possible, (must malloc for + * fetched URLs). If freeval is NULL, all return data will be malloc'd + * and the input line will be unmodified. Otherwise freeval is set to + * True if the value was malloc'd. + */ + +int +ldif_parse_line( + LDAP_CONST char *line, + char **typep, + char **valuep, + ber_len_t *vlenp +) +{ + struct berval type, value; + int rc = ldif_parse_line2( (char *)line, &type, &value, NULL ); + + *typep = type.bv_val; + *valuep = value.bv_val; + *vlenp = value.bv_len; + return rc; +} + +int +ldif_parse_line2( + char *line, + struct berval *type, + struct berval *value, + int *freeval +) +{ + char *s, *p, *d; + char nib; + int b64, url; + + BER_BVZERO( type ); + BER_BVZERO( value ); + + /* skip any leading space */ + while ( isspace( (unsigned char) *line ) ) { + line++; + } + + if ( freeval ) { + *freeval = 0; + } else { + line = ber_strdup( line ); + + if( line == NULL ) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_parse_line: line malloc failed\n")); + return( -1 ); + } + } + + type->bv_val = line; + + s = strchr( type->bv_val, ':' ); + + if ( s == NULL ) { + ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, + _("ldif_parse_line: missing ':' after %s\n"), + type->bv_val ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + + /* trim any space between type and : */ + for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) { + *p = '\0'; + } + *s++ = '\0'; + type->bv_len = s - type->bv_val - 1; + + url = 0; + b64 = 0; + + if ( *s == '<' ) { + s++; + url = 1; + + } else if ( *s == ':' ) { + /* base 64 encoded value */ + s++; + b64 = 1; + } + + /* skip space between : and value */ + while ( isspace( (unsigned char) *s ) ) { + s++; + } + + /* check for continued line markers that should be deleted */ + for ( p = s, d = s; *p; p++ ) { + if ( *p != CONTINUED_LINE_MARKER ) + *d++ = *p; + } + *d = '\0'; + + if ( b64 ) { + char *byte = s; + + if ( *s == '\0' ) { + /* no value is present, error out */ + ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, + _("ldif_parse_line: %s missing base64 value\n"), + type->bv_val ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + + byte = value->bv_val = s; + + for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) { + int i; + for ( i = 0; i < 4; i++ ) { + if ( p[i] != '=' && (p[i] & 0x80 || + b642nib[ p[i] & 0x7f ] > 0x3f) ) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_parse_line: %s: invalid base64 encoding" + " char (%c) 0x%x\n"), + type->bv_val, p[i], p[i] ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + } + + /* first digit */ + nib = b642nib[ p[0] & 0x7f ]; + byte[0] = nib << 2; + /* second digit */ + nib = b642nib[ p[1] & 0x7f ]; + byte[0] |= nib >> 4; + byte[1] = (nib & RIGHT4) << 4; + /* third digit */ + if ( p[2] == '=' ) { + value->bv_len += 1; + break; + } + nib = b642nib[ p[2] & 0x7f ]; + byte[1] |= nib >> 2; + byte[2] = (nib & RIGHT2) << 6; + /* fourth digit */ + if ( p[3] == '=' ) { + value->bv_len += 2; + break; + } + nib = b642nib[ p[3] & 0x7f ]; + byte[2] |= nib; + + byte += 3; + } + s[ value->bv_len ] = '\0'; + + } else if ( url ) { + if ( *s == '\0' ) { + /* no value is present, error out */ + ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, + _("ldif_parse_line: %s missing URL value\n"), + type->bv_val ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + + if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"), + type->bv_val, s ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + if ( freeval ) *freeval = 1; + + } else { + value->bv_val = s; + value->bv_len = (int) (d - s); + } + + if ( !freeval ) { + struct berval bv = *type; + + ber_dupbv( type, &bv ); + + if( BER_BVISNULL( type )) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_parse_line: type malloc failed\n")); + if( url ) ber_memfree( value->bv_val ); + ber_memfree( line ); + return( -1 ); + } + + if( !url ) { + bv = *value; + ber_dupbv( value, &bv ); + if( BER_BVISNULL( value )) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_parse_line: value malloc failed\n")); + ber_memfree( type->bv_val ); + ber_memfree( line ); + return( -1 ); + } + } + + ber_memfree( line ); + } + + return( 0 ); +} + +/* + * ldif_getline - return the next "line" (minus newline) of input from a + * string buffer of lines separated by newlines, terminated by \n\n + * or \0. this routine handles continued lines, bundling them into + * a single big line before returning. if a line begins with a white + * space character, it is a continuation of the previous line. the white + * space character (nb: only one char), and preceeding newline are changed + * into CONTINUED_LINE_MARKER chars, to be deleted later by the + * ldif_parse_line() routine above. + * + * ldif_getline will skip over any line which starts '#'. + * + * ldif_getline takes a pointer to a pointer to the buffer on the first call, + * which it updates and must be supplied on subsequent calls. + */ + +int +ldif_countlines( LDAP_CONST char *buf ) +{ + char *nl; + int ret = 0; + + if ( !buf ) return ret; + + for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) { + nl++; + if ( *nl != ' ' ) ret++; + } + return ret; +} + +char * +ldif_getline( char **next ) +{ + char *line; + + do { + if ( *next == NULL || **next == '\n' || **next == '\0' ) { + return( NULL ); + } + + line = *next; + + while ( (*next = strchr( *next, '\n' )) != NULL ) { +#if CONTINUED_LINE_MARKER != '\r' + if ( (*next)[-1] == '\r' ) { + (*next)[-1] = CONTINUED_LINE_MARKER; + } +#endif + + if ( (*next)[1] != ' ' ) { + if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) { + *(*next)++ = '\0'; + } + *(*next)++ = '\0'; + break; + } + + **next = CONTINUED_LINE_MARKER; + (*next)[1] = CONTINUED_LINE_MARKER; + (*next)++; + } + } while( *line == '#' ); + + return( line ); +} + +/* + * name and OID of attributeTypes that must be base64 encoded in any case + */ +typedef struct must_b64_encode_s { + struct berval name; + struct berval oid; +} must_b64_encode_s; + +static must_b64_encode_s default_must_b64_encode[] = { + { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) }, + { BER_BVNULL, BER_BVNULL } +}; + +static must_b64_encode_s *must_b64_encode = default_must_b64_encode; + +/* + * register name and OID of attributeTypes that must always be base64 + * encoded + * + * NOTE: this routine mallocs memory in a static struct which must + * be explicitly freed when no longer required + */ +int +ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid ) +{ + int i; + ber_len_t len; + + assert( must_b64_encode != NULL ); + assert( name != NULL ); + assert( oid != NULL ); + + len = strlen( name ); + + for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { + if ( len != must_b64_encode[i].name.bv_len ) { + continue; + } + + if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) { + break; + } + } + + if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) { + return 1; + } + + for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) + /* just count */ ; + + if ( must_b64_encode == default_must_b64_encode ) { + must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) ); + + for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) { + ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name ); + ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid ); + } + + } else { + must_b64_encode_s *tmp; + + tmp = ber_memrealloc( must_b64_encode, + sizeof( must_b64_encode_s ) * ( i + 2 ) ); + if ( tmp == NULL ) { + return 1; + } + must_b64_encode = tmp; + } + + ber_str2bv( name, len, 1, &must_b64_encode[i].name ); + ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid ); + + BER_BVZERO( &must_b64_encode[i + 1].name ); + + return 0; +} + +void +ldif_must_b64_encode_release( void ) +{ + int i; + + assert( must_b64_encode != NULL ); + + if ( must_b64_encode == default_must_b64_encode ) { + return; + } + + for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { + ber_memfree( must_b64_encode[i].name.bv_val ); + ber_memfree( must_b64_encode[i].oid.bv_val ); + } + + ber_memfree( must_b64_encode ); + + must_b64_encode = default_must_b64_encode; +} + +/* + * returns 1 iff the string corresponds to the name or the OID of any + * of the attributeTypes listed in must_b64_encode + */ +static int +ldif_must_b64_encode( LDAP_CONST char *s ) +{ + int i; + struct berval bv; + + assert( must_b64_encode != NULL ); + assert( s != NULL ); + + ber_str2bv( s, 0, 0, &bv ); + + for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { + if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0 + || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 ) + { + return 1; + } + } + + return 0; +} + +/* compatibility with U-Mich off by one bug */ +#define LDIF_KLUDGE 1 + +/* NOTE: only preserved for binary compatibility */ +void +ldif_sput( + char **out, + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen ) +{ + ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH ); +} + +void +ldif_sput_wrap( + char **out, + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen, + ber_len_t wrap ) +{ + const unsigned char *byte, *stop; + unsigned char buf[3]; + unsigned long bits; + char *save; + int pad; + int namelen = 0; + + ber_len_t savelen; + ber_len_t len=0; + ber_len_t i; + + wrap = LDIF_LINE_WIDTH_WRAP( wrap ); + + /* prefix */ + switch( type ) { + case LDIF_PUT_COMMENT: + *(*out)++ = '#'; + len++; + + if( vlen ) { + *(*out)++ = ' '; + len++; + } + + break; + + case LDIF_PUT_SEP: + *(*out)++ = '\n'; + return; + } + + /* name (attribute type) */ + if( name != NULL ) { + /* put the name + ":" */ + namelen = strlen(name); + strcpy(*out, name); + *out += namelen; + len += namelen; + + if( type != LDIF_PUT_COMMENT ) { + *(*out)++ = ':'; + len++; + } + + } +#ifdef LDAP_DEBUG + else { + assert( type == LDIF_PUT_COMMENT ); + } +#endif + + if( vlen == 0 ) { + *(*out)++ = '\n'; + return; + } + + switch( type ) { + case LDIF_PUT_NOVALUE: + *(*out)++ = '\n'; + return; + + case LDIF_PUT_URL: /* url value */ + *(*out)++ = '<'; + len++; + break; + + case LDIF_PUT_B64: /* base64 value */ + *(*out)++ = ':'; + len++; + break; + } + + switch( type ) { + case LDIF_PUT_TEXT: + case LDIF_PUT_URL: + case LDIF_PUT_B64: + *(*out)++ = ' '; + len++; + /* fall-thru */ + + case LDIF_PUT_COMMENT: + /* pre-encoded names */ + for ( i=0; i < vlen; i++ ) { + if ( len > wrap ) { + *(*out)++ = '\n'; + *(*out)++ = ' '; + len = 1; + } + + *(*out)++ = val[i]; + len++; + } + *(*out)++ = '\n'; + return; + } + + save = *out; + savelen = len; + + *(*out)++ = ' '; + len++; + + stop = (const unsigned char *) (val + vlen); + + if ( type == LDIF_PUT_VALUE + && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' + && isgraph( (unsigned char) val[vlen-1] ) +#ifndef LDAP_BINARY_DEBUG + && strstr( name, ";binary" ) == NULL +#endif +#ifndef LDAP_PASSWD_DEBUG + && !ldif_must_b64_encode( name ) +#endif + ) { + int b64 = 0; + + for ( byte = (const unsigned char *) val; byte < stop; + byte++, len++ ) + { + if ( !isascii( *byte ) || !isprint( *byte ) ) { + b64 = 1; + break; + } + if ( len - LDIF_KLUDGE > wrap ) { + *(*out)++ = '\n'; + *(*out)++ = ' '; + len = 1; + } + *(*out)++ = *byte; + } + + if( !b64 ) { + *(*out)++ = '\n'; + return; + } + } + + *out = save; + *(*out)++ = ':'; + *(*out)++ = ' '; + len = savelen + 2; + + /* convert to base 64 (3 bytes => 4 base 64 digits) */ + for ( byte = (const unsigned char *) val; + byte < stop - 2; + byte += 3 ) + { + bits = (byte[0] & 0xff) << 16; + bits |= (byte[1] & 0xff) << 8; + bits |= (byte[2] & 0xff); + + for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { + if ( len - LDIF_KLUDGE > wrap ) { + *(*out)++ = '\n'; + *(*out)++ = ' '; + len = 1; + } + + /* get b64 digit from high order 6 bits */ + *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; + } + } + + /* add padding if necessary */ + if ( byte < stop ) { + for ( i = 0; byte + i < stop; i++ ) { + buf[i] = byte[i]; + } + for ( pad = 0; i < 3; i++, pad++ ) { + buf[i] = '\0'; + } + byte = buf; + bits = (byte[0] & 0xff) << 16; + bits |= (byte[1] & 0xff) << 8; + bits |= (byte[2] & 0xff); + + for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { + if ( len - LDIF_KLUDGE > wrap ) { + *(*out)++ = '\n'; + *(*out)++ = ' '; + len = 1; + } + + if( i + pad < 4 ) { + /* get b64 digit from low order 6 bits */ + *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; + } else { + *(*out)++ = '='; + } + } + } + *(*out)++ = '\n'; +} + + +/* + * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line + */ + +/* NOTE: only preserved for binary compatibility */ +char * +ldif_put( + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen ) +{ + return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH ); +} + +char * +ldif_put_wrap( + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen, + ber_len_t wrap ) +{ + char *buf, *p; + ber_len_t nlen; + + nlen = ( name != NULL ) ? strlen( name ) : 0; + + buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 ); + + if ( buf == NULL ) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_type_and_value: malloc failed!")); + return NULL; + } + + p = buf; + ldif_sput_wrap( &p, type, name, val, vlen, wrap ); + *p = '\0'; + + return( buf ); +} + +int ldif_is_not_printable( + LDAP_CONST char *val, + ber_len_t vlen ) +{ + if( vlen == 0 || val == NULL ) { + return -1; + } + + if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' && + isgraph( (unsigned char) val[vlen-1] ) ) + { + ber_len_t i; + + for ( i = 0; val[i]; i++ ) { + if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) { + return 1; + } + } + + return 0; + } + + return 1; +} + +LDIFFP * +ldif_open( + LDAP_CONST char *file, + LDAP_CONST char *mode +) +{ + FILE *fp = fopen( file, mode ); + LDIFFP *lfp = NULL; + + if ( fp ) { + lfp = ber_memalloc( sizeof( LDIFFP )); + lfp->fp = fp; + lfp->prev = NULL; + } + return lfp; +} + +void +ldif_close( + LDIFFP *lfp +) +{ + LDIFFP *prev; + + while ( lfp ) { + fclose( lfp->fp ); + prev = lfp->prev; + ber_memfree( lfp ); + lfp = prev; + } +} + +#define LDIF_MAXLINE 4096 + +/* + * ldif_read_record - read an ldif record. Return 1 for success, 0 for EOF, + * -1 for error. + */ +int +ldif_read_record( + LDIFFP *lfp, + int *lno, /* ptr to line number counter */ + char **bufp, /* ptr to malloced output buffer */ + int *buflenp ) /* ptr to length of *bufp */ +{ + char line[LDIF_MAXLINE], *nbufp; + ber_len_t lcur = 0, len; + int last_ch = '\n', found_entry = 0, stop, top_comment = 0; + + for ( stop = 0; !stop; last_ch = line[len-1] ) { + /* If we're at the end of this file, see if we should pop + * back to a previous file. (return from an include) + */ + while ( feof( lfp->fp )) { + if ( lfp->prev ) { + LDIFFP *tmp = lfp->prev; + fclose( lfp->fp ); + *lfp = *tmp; + ber_memfree( tmp ); + } else { + stop = 1; + break; + } + } + if ( stop ) + break; + + if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) { + stop = 1; + /* Add \n in case the file does not end with newline */ + line[0] = '\n'; + line[1] = '\0'; + } + len = strlen( line ); + + if ( last_ch == '\n' ) { + (*lno)++; + + if ( line[0] == '\n' || + ( line[0] == '\r' && line[1] == '\n' )) { + if ( !found_entry ) { + lcur = 0; + top_comment = 0; + continue; + } + break; + } + + if ( !found_entry ) { + if ( line[0] == '#' ) { + top_comment = 1; + } else if ( ! ( top_comment && line[0] == ' ' ) ) { + /* Found a new entry */ + found_entry = 1; + + if ( isdigit( (unsigned char) line[0] ) ) { + /* skip index */ + continue; + } + if ( !strncasecmp( line, "include:", + STRLENOF("include:"))) { + FILE *fp2; + char *ptr; + found_entry = 0; + + if ( line[len-1] == '\n' ) { + len--; + line[len] = '\0'; + } + if ( line[len-1] == '\r' ) { + len--; + line[len] = '\0'; + } + + ptr = line + STRLENOF("include:"); + while (isspace((unsigned char) *ptr)) ptr++; + fp2 = ldif_open_url( ptr ); + if ( fp2 ) { + LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP )); + if ( lnew == NULL ) { + fclose( fp2 ); + return 0; + } + lnew->prev = lfp->prev; + lnew->fp = lfp->fp; + lfp->prev = lnew; + lfp->fp = fp2; + line[len] = '\n'; + len++; + continue; + } else { + /* We failed to open the file, this should + * be reported as an error somehow. + */ + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_read_record: include %s failed\n"), ptr ); + return -1; + } + } + } + } + } + + if ( *buflenp - lcur <= len ) { + *buflenp += len + LDIF_MAXLINE; + nbufp = ber_memrealloc( *bufp, *buflenp ); + if( nbufp == NULL ) { + return 0; + } + *bufp = nbufp; + } + strcpy( *bufp + lcur, line ); + lcur += len; + } + + return( found_entry ); +} diff --git a/libraries/libldap_r/Makefile.in b/libraries/libldap_r/Makefile.in index f5e9e8963b..de0d67b6f3 100644 --- a/libraries/libldap_r/Makefile.in +++ b/libraries/libldap_r/Makefile.in @@ -30,7 +30,7 @@ XXSRCS = apitest.c test.c \ charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ tls2.c tls_o.c tls_g.c tls_m.c \ turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \ - assertion.c deref.c ldifutil.c + assertion.c deref.c ldifutil.c ldif.c fetch.c SRCS = threads.c rdwr.c rmutex.c tpool.c rq.c \ thr_posix.c thr_cthreads.c thr_thr.c thr_nt.c \ thr_pth.c thr_stub.c thr_debug.c @@ -48,7 +48,7 @@ OBJS = threads.lo rdwr.lo rmutex.lo tpool.lo rq.lo \ charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ tls2.lo tls_o.lo tls_g.lo tls_m.lo \ turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \ - assertion.lo deref.lo ldifutil.lo + assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries diff --git a/libraries/liblutil/Makefile.in b/libraries/liblutil/Makefile.in index ff7bc3a880..06da05c951 100644 --- a/libraries/liblutil/Makefile.in +++ b/libraries/liblutil/Makefile.in @@ -14,9 +14,6 @@ ## . LIBRARY = liblutil.a - -SHAREDLIB = libldif.la - PROGRAM = testavl LDAP_INCDIR= ../../include @@ -32,19 +29,17 @@ XLIBS = $(LIBRARY) $(LDAP_LIBLBER_LA) SRCS = base64.c entropy.c sasl.c signal.c hash.c passfile.c \ md5.c passwd.c sha1.c getpass.c lockf.c utils.c uuid.c sockpair.c \ - avl.c tavl.c ldif.c fetch.c \ + avl.c tavl.c \ testavl.c \ meter.c \ @LIBSRCS@ $(@PLAT@_SRCS) OBJS = base64.o entropy.o sasl.o signal.o hash.o passfile.o \ md5.o passwd.o sha1.o getpass.o lockf.o utils.o uuid.o sockpair.o \ - avl.o tavl.o ldif.o fetch.o \ + avl.o tavl.o \ meter.o \ @LIBOBJS@ $(@PLAT@_OBJS) -SHAREDLIBOBJS = ldif.lo fetch.lo - testavl: $(XLIBS) testavl.o (LTLINK) -o $@ testavl.o $(LIBS) @@ -64,19 +59,3 @@ slapdmsg.res: slapdmsg.rc slapdmsg.bin clean-local: $(RM) *.res -all-local: $(SHAREDLIB) - -.SUFFIXES: .c .o .lo - -.c.lo: - $(LTCOMPILE_LIB) $< - -$(LIBRARY): $(SHAREDLIBOBJS) version.lo - -$(SHAREDLIB): $(SHAREDLIBOBJS) version.lo - $(LTLINK_LIB) -o $(SHAREDLIB) $(SHAREDLIBOBJS) version.lo $(LINK_LIBS) - -install-local: FORCE - -$(MKDIR) $(DESTDIR)$(libdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(SHAREDLIB) $(DESTDIR)$(libdir) - $(LTFINISH) $(DESTDIR)$(libdir) diff --git a/libraries/liblutil/fetch.c b/libraries/liblutil/fetch.c deleted file mode 100644 index fe734295c7..0000000000 --- a/libraries/liblutil/fetch.c +++ /dev/null @@ -1,133 +0,0 @@ -/* fetch.c - routines for fetching data at URLs */ -/* $OpenLDAP$ */ -/* This work is part of OpenLDAP Software . - * - * Copyright 1999-2011 The OpenLDAP Foundation. - * Portions Copyright 1999-2003 Kurt D. Zeilenga. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ -/* This work was initially developed by Kurt D. Zeilenga for - * inclusion in OpenLDAP Software. - */ - -#include "portable.h" - -#include - -#include - -#include -#include -#include - -#ifdef HAVE_FETCH -#include -#endif - -#include "lber_pvt.h" -#include "ldap_pvt.h" -#include "ldap_config.h" -#include "ldif.h" - -FILE * -ldif_open_url( - LDAP_CONST char *urlstr ) -{ - FILE *url; - - if( strncasecmp( "file:", urlstr, sizeof("file:")-1 ) == 0 ) { - char *p; - urlstr += sizeof("file:")-1; - - /* we don't check for LDAP_DIRSEP since URLs should contain '/' */ - if ( urlstr[0] == '/' && urlstr[1] == '/' ) { - urlstr += 2; - /* path must be absolute if authority is present */ - if ( urlstr[0] != '/' ) - return NULL; - } - - p = ber_strdup( urlstr ); - - /* But we should convert to LDAP_DIRSEP before use */ - if ( LDAP_DIRSEP[0] != '/' ) { - char *s = p; - while (( s = strchr( s, '/' ))) - *s++ = LDAP_DIRSEP[0]; - } - - ldap_pvt_hex_unescape( p ); - - url = fopen( p, "rb" ); - - ber_memfree( p ); - } else { -#ifdef HAVE_FETCH - url = fetchGetURL( (char*) urlstr, "" ); -#else - url = NULL; -#endif - } - return url; -} - -int -ldif_fetch_url( - LDAP_CONST char *urlstr, - char **valuep, - ber_len_t *vlenp ) -{ - FILE *url; - char buffer[1024]; - char *p = NULL; - size_t total; - size_t bytes; - - *valuep = NULL; - *vlenp = 0; - - url = ldif_open_url( urlstr ); - - if( url == NULL ) { - return -1; - } - - total = 0; - - while( (bytes = fread( buffer, 1, sizeof(buffer), url )) != 0 ) { - char *newp = ber_memrealloc( p, total + bytes + 1 ); - if( newp == NULL ) { - ber_memfree( p ); - fclose( url ); - return -1; - } - p = newp; - AC_MEMCPY( &p[total], buffer, bytes ); - total += bytes; - } - - fclose( url ); - - if( total == 0 ) { - char *newp = ber_memrealloc( p, 1 ); - if( newp == NULL ) { - ber_memfree( p ); - return -1; - } - p = newp; - } - - p[total] = '\0'; - *valuep = p; - *vlenp = total; - - return 0; -} diff --git a/libraries/liblutil/ldif.c b/libraries/liblutil/ldif.c deleted file mode 100644 index 0ee7849f16..0000000000 --- a/libraries/liblutil/ldif.c +++ /dev/null @@ -1,932 +0,0 @@ -/* ldif.c - routines for dealing with LDIF files */ -/* $OpenLDAP$ */ -/* This work is part of OpenLDAP Software . - * - * Copyright 1998-2011 The OpenLDAP Foundation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ -/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and that due credit is given - * to the University of Michigan at Ann Arbor. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. This - * software is provided ``as is'' without express or implied warranty. - */ -/* This work was originally developed by the University of Michigan - * and distributed as part of U-MICH LDAP. - */ - -#include "portable.h" - -#include - -#include -#include - -#include -#include -#include - -int ldif_debug = 0; - -#include "ldap_log.h" -#include "lber_pvt.h" -#include "ldif.h" - -#define RIGHT2 0x03 -#define RIGHT4 0x0f -#define CONTINUED_LINE_MARKER '\r' - -#ifdef CSRIMALLOC -#define ber_memalloc malloc -#define ber_memcalloc calloc -#define ber_memrealloc realloc -#define ber_strdup strdup -#endif - -static const char nib2b64[0x40] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static const unsigned char b642nib[0x80] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff -}; - -/* - * ldif_parse_line - takes a line of the form "type:[:] value" and splits it - * into components "type" and "value". if a double colon separates type from - * value, then value is encoded in base 64, and parse_line un-decodes it - * (in place) before returning. The type and value are stored in malloc'd - * memory which must be freed by the caller. - * - * ldif_parse_line2 - operates in-place on input buffer, returning type - * in-place. Will return value in-place if possible, (must malloc for - * fetched URLs). If freeval is NULL, all return data will be malloc'd - * and the input line will be unmodified. Otherwise freeval is set to - * True if the value was malloc'd. - */ - -int -ldif_parse_line( - LDAP_CONST char *line, - char **typep, - char **valuep, - ber_len_t *vlenp -) -{ - struct berval type, value; - int rc = ldif_parse_line2( (char *)line, &type, &value, NULL ); - - *typep = type.bv_val; - *valuep = value.bv_val; - *vlenp = value.bv_len; - return rc; -} - -int -ldif_parse_line2( - char *line, - struct berval *type, - struct berval *value, - int *freeval -) -{ - char *s, *p, *d; - char nib; - int b64, url; - - BER_BVZERO( type ); - BER_BVZERO( value ); - - /* skip any leading space */ - while ( isspace( (unsigned char) *line ) ) { - line++; - } - - if ( freeval ) { - *freeval = 0; - } else { - line = ber_strdup( line ); - - if( line == NULL ) { - ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, - _("ldif_parse_line: line malloc failed\n")); - return( -1 ); - } - } - - type->bv_val = line; - - s = strchr( type->bv_val, ':' ); - - if ( s == NULL ) { - ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, - _("ldif_parse_line: missing ':' after %s\n"), - type->bv_val ); - if ( !freeval ) ber_memfree( line ); - return( -1 ); - } - - /* trim any space between type and : */ - for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) { - *p = '\0'; - } - *s++ = '\0'; - type->bv_len = s - type->bv_val - 1; - - url = 0; - b64 = 0; - - if ( *s == '<' ) { - s++; - url = 1; - - } else if ( *s == ':' ) { - /* base 64 encoded value */ - s++; - b64 = 1; - } - - /* skip space between : and value */ - while ( isspace( (unsigned char) *s ) ) { - s++; - } - - /* check for continued line markers that should be deleted */ - for ( p = s, d = s; *p; p++ ) { - if ( *p != CONTINUED_LINE_MARKER ) - *d++ = *p; - } - *d = '\0'; - - if ( b64 ) { - char *byte = s; - - if ( *s == '\0' ) { - /* no value is present, error out */ - ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, - _("ldif_parse_line: %s missing base64 value\n"), - type->bv_val ); - if ( !freeval ) ber_memfree( line ); - return( -1 ); - } - - byte = value->bv_val = s; - - for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) { - int i; - for ( i = 0; i < 4; i++ ) { - if ( p[i] != '=' && (p[i] & 0x80 || - b642nib[ p[i] & 0x7f ] > 0x3f) ) { - ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, - _("ldif_parse_line: %s: invalid base64 encoding" - " char (%c) 0x%x\n"), - type->bv_val, p[i], p[i] ); - if ( !freeval ) ber_memfree( line ); - return( -1 ); - } - } - - /* first digit */ - nib = b642nib[ p[0] & 0x7f ]; - byte[0] = nib << 2; - /* second digit */ - nib = b642nib[ p[1] & 0x7f ]; - byte[0] |= nib >> 4; - byte[1] = (nib & RIGHT4) << 4; - /* third digit */ - if ( p[2] == '=' ) { - value->bv_len += 1; - break; - } - nib = b642nib[ p[2] & 0x7f ]; - byte[1] |= nib >> 2; - byte[2] = (nib & RIGHT2) << 6; - /* fourth digit */ - if ( p[3] == '=' ) { - value->bv_len += 2; - break; - } - nib = b642nib[ p[3] & 0x7f ]; - byte[2] |= nib; - - byte += 3; - } - s[ value->bv_len ] = '\0'; - - } else if ( url ) { - if ( *s == '\0' ) { - /* no value is present, error out */ - ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, - _("ldif_parse_line: %s missing URL value\n"), - type->bv_val ); - if ( !freeval ) ber_memfree( line ); - return( -1 ); - } - - if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) { - ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, - _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"), - type->bv_val, s ); - if ( !freeval ) ber_memfree( line ); - return( -1 ); - } - if ( freeval ) *freeval = 1; - - } else { - value->bv_val = s; - value->bv_len = (int) (d - s); - } - - if ( !freeval ) { - struct berval bv = *type; - - ber_dupbv( type, &bv ); - - if( BER_BVISNULL( type )) { - ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, - _("ldif_parse_line: type malloc failed\n")); - if( url ) ber_memfree( value->bv_val ); - ber_memfree( line ); - return( -1 ); - } - - if( !url ) { - bv = *value; - ber_dupbv( value, &bv ); - if( BER_BVISNULL( value )) { - ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, - _("ldif_parse_line: value malloc failed\n")); - ber_memfree( type->bv_val ); - ber_memfree( line ); - return( -1 ); - } - } - - ber_memfree( line ); - } - - return( 0 ); -} - -/* - * ldif_getline - return the next "line" (minus newline) of input from a - * string buffer of lines separated by newlines, terminated by \n\n - * or \0. this routine handles continued lines, bundling them into - * a single big line before returning. if a line begins with a white - * space character, it is a continuation of the previous line. the white - * space character (nb: only one char), and preceeding newline are changed - * into CONTINUED_LINE_MARKER chars, to be deleted later by the - * ldif_parse_line() routine above. - * - * ldif_getline will skip over any line which starts '#'. - * - * ldif_getline takes a pointer to a pointer to the buffer on the first call, - * which it updates and must be supplied on subsequent calls. - */ - -int -ldif_countlines( LDAP_CONST char *buf ) -{ - char *nl; - int ret = 0; - - if ( !buf ) return ret; - - for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) { - nl++; - if ( *nl != ' ' ) ret++; - } - return ret; -} - -char * -ldif_getline( char **next ) -{ - char *line; - - do { - if ( *next == NULL || **next == '\n' || **next == '\0' ) { - return( NULL ); - } - - line = *next; - - while ( (*next = strchr( *next, '\n' )) != NULL ) { -#if CONTINUED_LINE_MARKER != '\r' - if ( (*next)[-1] == '\r' ) { - (*next)[-1] = CONTINUED_LINE_MARKER; - } -#endif - - if ( (*next)[1] != ' ' ) { - if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) { - *(*next)++ = '\0'; - } - *(*next)++ = '\0'; - break; - } - - **next = CONTINUED_LINE_MARKER; - (*next)[1] = CONTINUED_LINE_MARKER; - (*next)++; - } - } while( *line == '#' ); - - return( line ); -} - -/* - * name and OID of attributeTypes that must be base64 encoded in any case - */ -typedef struct must_b64_encode_s { - struct berval name; - struct berval oid; -} must_b64_encode_s; - -static must_b64_encode_s default_must_b64_encode[] = { - { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) }, - { BER_BVNULL, BER_BVNULL } -}; - -static must_b64_encode_s *must_b64_encode = default_must_b64_encode; - -/* - * register name and OID of attributeTypes that must always be base64 - * encoded - * - * NOTE: this routine mallocs memory in a static struct which must - * be explicitly freed when no longer required - */ -int -ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid ) -{ - int i; - ber_len_t len; - - assert( must_b64_encode != NULL ); - assert( name != NULL ); - assert( oid != NULL ); - - len = strlen( name ); - - for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { - if ( len != must_b64_encode[i].name.bv_len ) { - continue; - } - - if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) { - break; - } - } - - if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) { - return 1; - } - - for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) - /* just count */ ; - - if ( must_b64_encode == default_must_b64_encode ) { - must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) ); - - for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) { - ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name ); - ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid ); - } - - } else { - must_b64_encode_s *tmp; - - tmp = ber_memrealloc( must_b64_encode, - sizeof( must_b64_encode_s ) * ( i + 2 ) ); - if ( tmp == NULL ) { - return 1; - } - must_b64_encode = tmp; - } - - ber_str2bv( name, len, 1, &must_b64_encode[i].name ); - ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid ); - - BER_BVZERO( &must_b64_encode[i + 1].name ); - - return 0; -} - -void -ldif_must_b64_encode_release( void ) -{ - int i; - - assert( must_b64_encode != NULL ); - - if ( must_b64_encode == default_must_b64_encode ) { - return; - } - - for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { - ber_memfree( must_b64_encode[i].name.bv_val ); - ber_memfree( must_b64_encode[i].oid.bv_val ); - } - - ber_memfree( must_b64_encode ); - - must_b64_encode = default_must_b64_encode; -} - -/* - * returns 1 iff the string corresponds to the name or the OID of any - * of the attributeTypes listed in must_b64_encode - */ -static int -ldif_must_b64_encode( LDAP_CONST char *s ) -{ - int i; - struct berval bv; - - assert( must_b64_encode != NULL ); - assert( s != NULL ); - - ber_str2bv( s, 0, 0, &bv ); - - for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { - if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0 - || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 ) - { - return 1; - } - } - - return 0; -} - -/* compatibility with U-Mich off by one bug */ -#define LDIF_KLUDGE 1 - -/* NOTE: only preserved for binary compatibility */ -void -ldif_sput( - char **out, - int type, - LDAP_CONST char *name, - LDAP_CONST char *val, - ber_len_t vlen ) -{ - ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH ); -} - -void -ldif_sput_wrap( - char **out, - int type, - LDAP_CONST char *name, - LDAP_CONST char *val, - ber_len_t vlen, - ber_len_t wrap ) -{ - const unsigned char *byte, *stop; - unsigned char buf[3]; - unsigned long bits; - char *save; - int pad; - int namelen = 0; - - ber_len_t savelen; - ber_len_t len=0; - ber_len_t i; - - wrap = LDIF_LINE_WIDTH_WRAP( wrap ); - - /* prefix */ - switch( type ) { - case LDIF_PUT_COMMENT: - *(*out)++ = '#'; - len++; - - if( vlen ) { - *(*out)++ = ' '; - len++; - } - - break; - - case LDIF_PUT_SEP: - *(*out)++ = '\n'; - return; - } - - /* name (attribute type) */ - if( name != NULL ) { - /* put the name + ":" */ - namelen = strlen(name); - strcpy(*out, name); - *out += namelen; - len += namelen; - - if( type != LDIF_PUT_COMMENT ) { - *(*out)++ = ':'; - len++; - } - - } -#ifdef LDAP_DEBUG - else { - assert( type == LDIF_PUT_COMMENT ); - } -#endif - - if( vlen == 0 ) { - *(*out)++ = '\n'; - return; - } - - switch( type ) { - case LDIF_PUT_NOVALUE: - *(*out)++ = '\n'; - return; - - case LDIF_PUT_URL: /* url value */ - *(*out)++ = '<'; - len++; - break; - - case LDIF_PUT_B64: /* base64 value */ - *(*out)++ = ':'; - len++; - break; - } - - switch( type ) { - case LDIF_PUT_TEXT: - case LDIF_PUT_URL: - case LDIF_PUT_B64: - *(*out)++ = ' '; - len++; - /* fall-thru */ - - case LDIF_PUT_COMMENT: - /* pre-encoded names */ - for ( i=0; i < vlen; i++ ) { - if ( len > wrap ) { - *(*out)++ = '\n'; - *(*out)++ = ' '; - len = 1; - } - - *(*out)++ = val[i]; - len++; - } - *(*out)++ = '\n'; - return; - } - - save = *out; - savelen = len; - - *(*out)++ = ' '; - len++; - - stop = (const unsigned char *) (val + vlen); - - if ( type == LDIF_PUT_VALUE - && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' - && isgraph( (unsigned char) val[vlen-1] ) -#ifndef LDAP_BINARY_DEBUG - && strstr( name, ";binary" ) == NULL -#endif -#ifndef LDAP_PASSWD_DEBUG - && !ldif_must_b64_encode( name ) -#endif - ) { - int b64 = 0; - - for ( byte = (const unsigned char *) val; byte < stop; - byte++, len++ ) - { - if ( !isascii( *byte ) || !isprint( *byte ) ) { - b64 = 1; - break; - } - if ( len - LDIF_KLUDGE > wrap ) { - *(*out)++ = '\n'; - *(*out)++ = ' '; - len = 1; - } - *(*out)++ = *byte; - } - - if( !b64 ) { - *(*out)++ = '\n'; - return; - } - } - - *out = save; - *(*out)++ = ':'; - *(*out)++ = ' '; - len = savelen + 2; - - /* convert to base 64 (3 bytes => 4 base 64 digits) */ - for ( byte = (const unsigned char *) val; - byte < stop - 2; - byte += 3 ) - { - bits = (byte[0] & 0xff) << 16; - bits |= (byte[1] & 0xff) << 8; - bits |= (byte[2] & 0xff); - - for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { - if ( len - LDIF_KLUDGE > wrap ) { - *(*out)++ = '\n'; - *(*out)++ = ' '; - len = 1; - } - - /* get b64 digit from high order 6 bits */ - *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; - } - } - - /* add padding if necessary */ - if ( byte < stop ) { - for ( i = 0; byte + i < stop; i++ ) { - buf[i] = byte[i]; - } - for ( pad = 0; i < 3; i++, pad++ ) { - buf[i] = '\0'; - } - byte = buf; - bits = (byte[0] & 0xff) << 16; - bits |= (byte[1] & 0xff) << 8; - bits |= (byte[2] & 0xff); - - for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { - if ( len - LDIF_KLUDGE > wrap ) { - *(*out)++ = '\n'; - *(*out)++ = ' '; - len = 1; - } - - if( i + pad < 4 ) { - /* get b64 digit from low order 6 bits */ - *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; - } else { - *(*out)++ = '='; - } - } - } - *(*out)++ = '\n'; -} - - -/* - * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line - */ - -/* NOTE: only preserved for binary compatibility */ -char * -ldif_put( - int type, - LDAP_CONST char *name, - LDAP_CONST char *val, - ber_len_t vlen ) -{ - return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH ); -} - -char * -ldif_put_wrap( - int type, - LDAP_CONST char *name, - LDAP_CONST char *val, - ber_len_t vlen, - ber_len_t wrap ) -{ - char *buf, *p; - ber_len_t nlen; - - nlen = ( name != NULL ) ? strlen( name ) : 0; - - buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 ); - - if ( buf == NULL ) { - ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, - _("ldif_type_and_value: malloc failed!")); - return NULL; - } - - p = buf; - ldif_sput_wrap( &p, type, name, val, vlen, wrap ); - *p = '\0'; - - return( buf ); -} - -int ldif_is_not_printable( - LDAP_CONST char *val, - ber_len_t vlen ) -{ - if( vlen == 0 || val == NULL ) { - return -1; - } - - if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' && - isgraph( (unsigned char) val[vlen-1] ) ) - { - ber_len_t i; - - for ( i = 0; val[i]; i++ ) { - if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) { - return 1; - } - } - - return 0; - } - - return 1; -} - -LDIFFP * -ldif_open( - LDAP_CONST char *file, - LDAP_CONST char *mode -) -{ - FILE *fp = fopen( file, mode ); - LDIFFP *lfp = NULL; - - if ( fp ) { - lfp = ber_memalloc( sizeof( LDIFFP )); - lfp->fp = fp; - lfp->prev = NULL; - } - return lfp; -} - -void -ldif_close( - LDIFFP *lfp -) -{ - LDIFFP *prev; - - while ( lfp ) { - fclose( lfp->fp ); - prev = lfp->prev; - ber_memfree( lfp ); - lfp = prev; - } -} - -#define LDIF_MAXLINE 4096 - -/* - * ldif_read_record - read an ldif record. Return 1 for success, 0 for EOF, - * -1 for error. - */ -int -ldif_read_record( - LDIFFP *lfp, - int *lno, /* ptr to line number counter */ - char **bufp, /* ptr to malloced output buffer */ - int *buflenp ) /* ptr to length of *bufp */ -{ - char line[LDIF_MAXLINE], *nbufp; - ber_len_t lcur = 0, len; - int last_ch = '\n', found_entry = 0, stop, top_comment = 0; - - for ( stop = 0; !stop; last_ch = line[len-1] ) { - /* If we're at the end of this file, see if we should pop - * back to a previous file. (return from an include) - */ - while ( feof( lfp->fp )) { - if ( lfp->prev ) { - LDIFFP *tmp = lfp->prev; - fclose( lfp->fp ); - *lfp = *tmp; - ber_memfree( tmp ); - } else { - stop = 1; - break; - } - } - if ( stop ) - break; - - if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) { - stop = 1; - /* Add \n in case the file does not end with newline */ - line[0] = '\n'; - line[1] = '\0'; - } - len = strlen( line ); - - if ( last_ch == '\n' ) { - (*lno)++; - - if ( line[0] == '\n' || - ( line[0] == '\r' && line[1] == '\n' )) { - if ( !found_entry ) { - lcur = 0; - top_comment = 0; - continue; - } - break; - } - - if ( !found_entry ) { - if ( line[0] == '#' ) { - top_comment = 1; - } else if ( ! ( top_comment && line[0] == ' ' ) ) { - /* Found a new entry */ - found_entry = 1; - - if ( isdigit( (unsigned char) line[0] ) ) { - /* skip index */ - continue; - } - if ( !strncasecmp( line, "include:", - STRLENOF("include:"))) { - FILE *fp2; - char *ptr; - found_entry = 0; - - if ( line[len-1] == '\n' ) { - len--; - line[len] = '\0'; - } - if ( line[len-1] == '\r' ) { - len--; - line[len] = '\0'; - } - - ptr = line + STRLENOF("include:"); - while (isspace((unsigned char) *ptr)) ptr++; - fp2 = ldif_open_url( ptr ); - if ( fp2 ) { - LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP )); - if ( lnew == NULL ) { - fclose( fp2 ); - return 0; - } - lnew->prev = lfp->prev; - lnew->fp = lfp->fp; - lfp->prev = lnew; - lfp->fp = fp2; - line[len] = '\n'; - len++; - continue; - } else { - /* We failed to open the file, this should - * be reported as an error somehow. - */ - ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, - _("ldif_read_record: include %s failed\n"), ptr ); - return -1; - } - } - } - } - } - - if ( *buflenp - lcur <= len ) { - *buflenp += len + LDIF_MAXLINE; - nbufp = ber_memrealloc( *bufp, *buflenp ); - if( nbufp == NULL ) { - return 0; - } - *bufp = nbufp; - } - strcpy( *bufp + lcur, line ); - lcur += len; - } - - return( found_entry ); -}