1 /* ldif.c - routines for dealing with LDIF files */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2022 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 preceding 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 ) );
360 if ( must_b64_encode
== NULL
) {
364 for ( i
= 0; !BER_BVISNULL( &default_must_b64_encode
[i
].name
); i
++ ) {
365 ber_dupbv( &must_b64_encode
[i
].name
, &default_must_b64_encode
[i
].name
);
366 ber_dupbv( &must_b64_encode
[i
].oid
, &default_must_b64_encode
[i
].oid
);
370 must_b64_encode_s
*tmp
;
372 tmp
= ber_memrealloc( must_b64_encode
,
373 sizeof( must_b64_encode_s
) * ( i
+ 2 ) );
377 must_b64_encode
= tmp
;
380 ber_str2bv( name
, len
, 1, &must_b64_encode
[i
].name
);
381 ber_str2bv( oid
, 0, 1, &must_b64_encode
[i
].oid
);
383 BER_BVZERO( &must_b64_encode
[i
+ 1].name
);
389 ldif_must_b64_encode_release( void )
393 assert( must_b64_encode
!= NULL
);
395 if ( must_b64_encode
== default_must_b64_encode
) {
399 for ( i
= 0; !BER_BVISNULL( &must_b64_encode
[i
].name
); i
++ ) {
400 ber_memfree( must_b64_encode
[i
].name
.bv_val
);
401 ber_memfree( must_b64_encode
[i
].oid
.bv_val
);
404 ber_memfree( must_b64_encode
);
406 must_b64_encode
= default_must_b64_encode
;
410 * returns 1 iff the string corresponds to the name or the OID of any
411 * of the attributeTypes listed in must_b64_encode
414 ldif_must_b64_encode( LDAP_CONST
char *s
)
419 assert( must_b64_encode
!= NULL
);
422 ber_str2bv( s
, 0, 0, &bv
);
424 for ( i
= 0; !BER_BVISNULL( &must_b64_encode
[i
].name
); i
++ ) {
425 if ( ber_bvstrcasecmp( &must_b64_encode
[i
].name
, &bv
) == 0
426 || ber_bvcmp( &must_b64_encode
[i
].oid
, &bv
) == 0 )
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
, 0 );
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
;
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
, 0 );
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
));
745 LDAP_CONST
char *mode
749 FILE *fp
= fmemopen( ldif
, size
, mode
);
753 lfp
= ber_memalloc( sizeof( LDIFFP
));
758 #else /* !HAVE_FMEMOPEN */
760 #endif /* !HAVE_FMEMOPEN */
778 #define LDIF_MAXLINE 4096
781 * ldif_read_record - read an ldif record. Return 1 for success, 0 for EOF,
787 unsigned long *lno
, /* ptr to line number counter */
788 char **bufp
, /* ptr to malloced output buffer */
789 int *buflenp
) /* ptr to length of *bufp */
791 char line
[LDIF_MAXLINE
], *nbufp
;
792 ber_len_t lcur
= 0, len
;
793 int last_ch
= '\n', found_entry
= 0, stop
, top_comment
= 0;
795 for ( stop
= 0; !stop
; last_ch
= line
[len
-1] ) {
796 /* If we're at the end of this file, see if we should pop
797 * back to a previous file. (return from an include)
799 while ( feof( lfp
->fp
)) {
802 LDIFFP
*tmp
= lfp
->prev
;
812 if ( fgets( line
, sizeof( line
), lfp
->fp
) == NULL
) {
813 if ( !found_entry
&& !ferror( lfp
->fp
) ) {
814 /* ITS#9811 Reached the end looking for an entry, try again */
820 len
= strlen( line
);
825 /* Add \n in case the file does not end with newline */
826 if (last_ch
!= '\n') {
835 /* Squash \r\n to \n */
836 if ( len
> 1 && line
[len
-2] == '\r' ) {
842 if ( last_ch
== '\n' ) {
845 if ( line
[0] == '\n' ) {
846 if ( !found_entry
) {
854 if ( !found_entry
) {
855 if ( line
[0] == '#' ) {
857 } else if ( ! ( top_comment
&& line
[0] == ' ' ) ) {
858 /* Found a new entry */
861 if ( isdigit( (unsigned char) line
[0] ) ) {
865 if ( !strncasecmp( line
, "include:",
866 STRLENOF("include:"))) {
871 if ( line
[len
-1] == '\n' ) {
876 ptr
= line
+ STRLENOF("include:");
877 while (isspace((unsigned char) *ptr
)) ptr
++;
878 fp2
= ldif_open_url( ptr
);
880 LDIFFP
*lnew
= ber_memalloc( sizeof( LDIFFP
));
881 if ( lnew
== NULL
) {
885 lnew
->prev
= lfp
->prev
;
893 /* We failed to open the file, this should
894 * be reported as an error somehow.
896 ber_pvt_log_printf( LDAP_DEBUG_ANY
, ldif_debug
,
897 _("ldif_read_record: include %s failed\n"), ptr
);
906 if ( *buflenp
- lcur
<= len
) {
907 *buflenp
+= len
+ LDIF_MAXLINE
;
908 nbufp
= ber_memrealloc( *bufp
, *buflenp
);
909 if( nbufp
== NULL
) {
914 strcpy( *bufp
+ lcur
, line
);
918 return( found_entry
);