1 /* ldif.c - routines for dealing with LDIF files */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2018 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
16 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
17 * All rights reserved.
19 * Redistribution and use in source and binary forms are permitted
20 * provided that this notice is preserved and that due credit is given
21 * to the University of Michigan at Ann Arbor. The name of the
22 * University may not be used to endorse or promote products derived
23 * from this software without specific prior written permission. This
24 * software is provided ``as is'' without express or implied warranty.
26 /* This work was originally developed by the University of Michigan
27 * and distributed as part of U-MICH LDAP.
34 #include <ac/stdlib.h>
37 #include <ac/string.h>
38 #include <ac/socket.h>
46 #define CONTINUED_LINE_MARKER '\r'
49 #define ber_memalloc malloc
50 #define ber_memcalloc calloc
51 #define ber_memrealloc realloc
52 #define ber_strdup strdup
55 static const char nib2b64[0x40] =
56 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
59 * ldif_parse_line - takes a line of the form "type:[:] value" and splits it
60 * into components "type" and "value". if a double colon separates type from
61 * value, then value is encoded in base 64, and parse_line un-decodes it
62 * (in place) before returning. The type and value are stored in malloc'd
63 * memory which must be freed by the caller.
65 * ldif_parse_line2 - operates in-place on input buffer, returning type
66 * in-place. Will return value in-place if possible, (must malloc for
67 * fetched URLs). If freeval is NULL, all return data will be malloc'd
68 * and the input line will be unmodified. Otherwise freeval is set to
69 * True if the value was malloc'd.
74 LDAP_CONST char *line,
80 struct berval type, value;
81 int rc = ldif_parse_line2( (char *)line, &type, &value, NULL );
84 *valuep = value.bv_val;
85 *vlenp = value.bv_len;
103 /* skip any leading space */
104 while ( isspace( (unsigned char) *line ) ) {
111 line = ber_strdup( line );
114 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
115 _("ldif_parse_line: line malloc failed\n"));
122 s = strchr( type->bv_val, ':' );
125 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
126 _("ldif_parse_line: missing ':' after %s\n"),
128 if ( !freeval ) ber_memfree( line );
132 /* trim any space between type and : */
133 for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) {
137 type->bv_len = s - type->bv_val - 1;
146 } else if ( *s == ':' ) {
147 /* base 64 encoded value */
152 /* skip space between : and value */
153 while ( isspace( (unsigned char) *s ) ) {
157 /* check for continued line markers that should be deleted */
158 for ( p = s, d = s; *p; p++ ) {
159 if ( *p != CONTINUED_LINE_MARKER )
168 /* no value is present, error out */
169 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
170 _("ldif_parse_line: %s missing base64 value\n"),
172 if ( !freeval ) ber_memfree( line );
177 value->bv_len = d - s;
178 if ( ldap_int_decode_b64_inplace( value ) != LDAP_SUCCESS ) {
179 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
180 _("ldif_parse_line: %s base64 decode failed\n"),
182 if ( !freeval ) ber_memfree( line );
187 /* no value is present, error out */
188 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
189 _("ldif_parse_line: %s missing URL value\n"),
191 if ( !freeval ) ber_memfree( line );
195 if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) {
196 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
197 _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"),
199 if ( !freeval ) ber_memfree( line );
202 if ( freeval ) *freeval = 1;
206 value->bv_len = (int) (d - s);
210 struct berval bv = *type;
212 ber_dupbv( type, &bv );
214 if( BER_BVISNULL( type )) {
215 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
216 _("ldif_parse_line: type malloc failed\n"));
217 if( url ) ber_memfree( value->bv_val );
224 ber_dupbv( value, &bv );
225 if( BER_BVISNULL( value )) {
226 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
227 _("ldif_parse_line: value malloc failed\n"));
228 ber_memfree( type->bv_val );
241 * ldif_getline - return the next "line" (minus newline) of input from a
242 * string buffer of lines separated by newlines, terminated by \n\n
243 * or \0. this routine handles continued lines, bundling them into
244 * a single big line before returning. if a line begins with a white
245 * space character, it is a continuation of the previous line. the white
246 * space character (nb: only one char), and preceeding newline are changed
247 * into CONTINUED_LINE_MARKER chars, to be deleted later by the
248 * ldif_parse_line() routine above.
250 * ldif_getline will skip over any line which starts '#'.
252 * ldif_getline takes a pointer to a pointer to the buffer on the first call,
253 * which it updates and must be supplied on subsequent calls.
257 ldif_countlines( LDAP_CONST char *buf )
262 if ( !buf ) return ret;
264 for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) {
266 if ( *nl != ' ' ) ret++;
272 ldif_getline( char **next )
277 if ( *next == NULL || **next == '\n' || **next == '\0' ) {
283 while ( (*next = strchr( *next, '\n' )) != NULL ) {
284 #if CONTINUED_LINE_MARKER != '\r'
285 if ( (*next)[-1] == '\r' ) {
286 (*next)[-1] = CONTINUED_LINE_MARKER;
290 if ( (*next)[1] != ' ' ) {
291 if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) {
298 **next = CONTINUED_LINE_MARKER;
299 (*next)[1] = CONTINUED_LINE_MARKER;
302 } while( *line == '#' );
308 * name and OID of attributeTypes that must be base64 encoded in any case
310 typedef struct must_b64_encode_s {
315 static must_b64_encode_s default_must_b64_encode[] = {
316 { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) },
317 { BER_BVNULL, BER_BVNULL }
320 static must_b64_encode_s *must_b64_encode = default_must_b64_encode;
323 * register name and OID of attributeTypes that must always be base64
326 * NOTE: this routine mallocs memory in a static struct which must
327 * be explicitly freed when no longer required
330 ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid )
335 assert( must_b64_encode != NULL );
336 assert( name != NULL );
337 assert( oid != NULL );
339 len = strlen( name );
341 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
342 if ( len != must_b64_encode[i].name.bv_len ) {
346 if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) {
351 if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) {
355 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ )
358 if ( must_b64_encode == default_must_b64_encode ) {
359 must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) );
361 for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) {
362 ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name );
363 ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid );
367 must_b64_encode_s *tmp;
369 tmp = ber_memrealloc( must_b64_encode,
370 sizeof( must_b64_encode_s ) * ( i + 2 ) );
374 must_b64_encode = tmp;
377 ber_str2bv( name, len, 1, &must_b64_encode[i].name );
378 ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid );
380 BER_BVZERO( &must_b64_encode[i + 1].name );
386 ldif_must_b64_encode_release( void )
390 assert( must_b64_encode != NULL );
392 if ( must_b64_encode == default_must_b64_encode ) {
396 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
397 ber_memfree( must_b64_encode[i].name.bv_val );
398 ber_memfree( must_b64_encode[i].oid.bv_val );
401 ber_memfree( must_b64_encode );
403 must_b64_encode = default_must_b64_encode;
407 * returns 1 iff the string corresponds to the name or the OID of any
408 * of the attributeTypes listed in must_b64_encode
411 ldif_must_b64_encode( LDAP_CONST char *s )
416 assert( must_b64_encode != NULL );
419 ber_str2bv( s, 0, 0, &bv );
421 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
422 if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0
423 || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 )
432 /* compatibility with U-Mich off by two bug */
433 #define LDIF_KLUDGE 2
435 /* NOTE: only preserved for binary compatibility */
440 LDAP_CONST char *name,
441 LDAP_CONST char *val,
444 ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH+LDIF_KLUDGE );
451 LDAP_CONST char *name,
452 LDAP_CONST char *val,
456 const unsigned char *byte, *stop;
457 unsigned char buf[3];
468 wrap = LDIF_LINE_WIDTH+LDIF_KLUDGE;
472 case LDIF_PUT_COMMENT:
488 /* name (attribute type) */
490 /* put the name + ":" */
491 namelen = strlen(name);
496 if( type != LDIF_PUT_COMMENT ) {
504 assert( type == LDIF_PUT_COMMENT );
514 case LDIF_PUT_NOVALUE:
518 case LDIF_PUT_URL: /* url value */
523 case LDIF_PUT_B64: /* base64 value */
537 case LDIF_PUT_COMMENT:
538 /* pre-encoded names */
539 for ( i=0; i < vlen; i++ ) {
559 stop = (const unsigned char *) (val + vlen);
561 if ( type == LDIF_PUT_VALUE
562 && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<'
563 && isgraph( (unsigned char) val[vlen-1] )
564 #ifndef LDAP_BINARY_DEBUG
565 && strstr( name, ";binary" ) == NULL
567 #ifndef LDAP_PASSWD_DEBUG
568 && !ldif_must_b64_encode( name )
573 for ( byte = (const unsigned char *) val; byte < stop;
576 if ( !isascii( *byte ) || !isprint( *byte ) ) {
599 /* convert to base 64 (3 bytes => 4 base 64 digits) */
600 for ( byte = (const unsigned char *) val;
604 bits = (byte[0] & 0xff) << 16;
605 bits |= (byte[1] & 0xff) << 8;
606 bits |= (byte[2] & 0xff);
608 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
615 /* get b64 digit from high order 6 bits */
616 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
620 /* add padding if necessary */
622 for ( i = 0; byte + i < stop; i++ ) {
625 for ( pad = 0; i < 3; i++, pad++ ) {
629 bits = (byte[0] & 0xff) << 16;
630 bits |= (byte[1] & 0xff) << 8;
631 bits |= (byte[2] & 0xff);
633 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
641 /* get b64 digit from low order 6 bits */
642 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
653 * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
656 /* NOTE: only preserved for binary compatibility */
660 LDAP_CONST char *name,
661 LDAP_CONST char *val,
664 return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH );
670 LDAP_CONST char *name,
671 LDAP_CONST char *val,
678 nlen = ( name != NULL ) ? strlen( name ) : 0;
680 buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 );
683 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
684 _("ldif_type_and_value: malloc failed!"));
689 ldif_sput_wrap( &p, type, name, val, vlen, wrap );
695 int ldif_is_not_printable(
696 LDAP_CONST char *val,
699 if( vlen == 0 || val == NULL ) {
703 if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
704 isgraph( (unsigned char) val[vlen-1] ) )
708 for ( i = 0; val[i]; i++ ) {
709 if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) {
722 LDAP_CONST char *file,
723 LDAP_CONST char *mode
726 FILE *fp = fopen( file, mode );
730 lfp = ber_memalloc( sizeof( LDIFFP ));
752 #define LDIF_MAXLINE 4096
755 * ldif_read_record - read an ldif record. Return 1 for success, 0 for EOF,
761 unsigned long *lno, /* ptr to line number counter */
762 char **bufp, /* ptr to malloced output buffer */
763 int *buflenp ) /* ptr to length of *bufp */
765 char line[LDIF_MAXLINE], *nbufp;
766 ber_len_t lcur = 0, len;
767 int last_ch = '\n', found_entry = 0, stop, top_comment = 0;
769 for ( stop = 0; !stop; last_ch = line[len-1] ) {
770 /* If we're at the end of this file, see if we should pop
771 * back to a previous file. (return from an include)
773 while ( feof( lfp->fp )) {
775 LDIFFP *tmp = lfp->prev;
785 if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) {
789 len = strlen( line );
794 /* Add \n in case the file does not end with newline */
795 if (last_ch != '\n') {
804 /* Squash \r\n to \n */
805 if ( len > 1 && line[len-2] == '\r' ) {
810 if ( last_ch == '\n' ) {
813 if ( line[0] == '\n' ) {
814 if ( !found_entry ) {
822 if ( !found_entry ) {
823 if ( line[0] == '#' ) {
825 } else if ( ! ( top_comment && line[0] == ' ' ) ) {
826 /* Found a new entry */
829 if ( isdigit( (unsigned char) line[0] ) ) {
833 if ( !strncasecmp( line, "include:",
834 STRLENOF("include:"))) {
839 if ( line[len-1] == '\n' ) {
844 ptr = line + STRLENOF("include:");
845 while (isspace((unsigned char) *ptr)) ptr++;
846 fp2 = ldif_open_url( ptr );
848 LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP ));
849 if ( lnew == NULL ) {
853 lnew->prev = lfp->prev;
861 /* We failed to open the file, this should
862 * be reported as an error somehow.
864 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
865 _("ldif_read_record: include %s failed\n"), ptr );
874 if ( *buflenp - lcur <= len ) {
875 *buflenp += len + LDIF_MAXLINE;
876 nbufp = ber_memrealloc( *bufp, *buflenp );
877 if( nbufp == NULL ) {
882 strcpy( *bufp + lcur, line );
886 return( found_entry );