1 /* $NetBSD: ldif.c,v 1.2 2020/08/11 13:15:37 christos Exp $ */ 2 3 /* ldif.c - routines for dealing with LDIF files */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2020 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms are permitted 22 * provided that this notice is preserved and that due credit is given 23 * to the University of Michigan at Ann Arbor. The name of the 24 * University may not be used to endorse or promote products derived 25 * from this software without specific prior written permission. This 26 * software is provided ``as is'' without express or implied warranty. 27 */ 28 /* This work was originally developed by the University of Michigan 29 * and distributed as part of U-MICH LDAP. 30 */ 31 32 #include <sys/cdefs.h> 33 __RCSID("$NetBSD: ldif.c,v 1.2 2020/08/11 13:15:37 christos Exp $"); 34 35 #include "portable.h" 36 37 #include <stdio.h> 38 39 #include <ac/stdlib.h> 40 #include <ac/ctype.h> 41 42 #include <ac/string.h> 43 #include <ac/socket.h> 44 #include <ac/time.h> 45 46 int ldif_debug = 0; 47 48 #include "ldap_log.h" 49 #include "lber_pvt.h" 50 #include "ldif.h" 51 52 #define RIGHT2 0x03 53 #define RIGHT4 0x0f 54 #define CONTINUED_LINE_MARKER '\r' 55 56 #ifdef CSRIMALLOC 57 #define ber_memalloc malloc 58 #define ber_memcalloc calloc 59 #define ber_memrealloc realloc 60 #define ber_strdup strdup 61 #endif 62 63 static const char nib2b64[0x40] = 64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 65 66 static const unsigned char b642nib[0x80] = { 67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 69 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 70 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 72 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 73 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 74 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 75 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 76 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 77 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 78 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 79 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 80 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 81 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 82 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff 83 }; 84 85 /* 86 * ldif_parse_line - takes a line of the form "type:[:] value" and splits it 87 * into components "type" and "value". if a double colon separates type from 88 * value, then value is encoded in base 64, and parse_line un-decodes it 89 * (in place) before returning. The type and value are stored in malloc'd 90 * memory which must be freed by the caller. 91 * 92 * ldif_parse_line2 - operates in-place on input buffer, returning type 93 * in-place. Will return value in-place if possible, (must malloc for 94 * fetched URLs). If freeval is NULL, all return data will be malloc'd 95 * and the input line will be unmodified. Otherwise freeval is set to 96 * True if the value was malloc'd. 97 */ 98 99 int 100 ldif_parse_line( 101 LDAP_CONST char *line, 102 char **typep, 103 char **valuep, 104 ber_len_t *vlenp 105 ) 106 { 107 struct berval type, value; 108 int rc = ldif_parse_line2( (char *)line, &type, &value, NULL ); 109 110 *typep = type.bv_val; 111 *valuep = value.bv_val; 112 *vlenp = value.bv_len; 113 return rc; 114 } 115 116 int 117 ldif_parse_line2( 118 char *line, 119 struct berval *type, 120 struct berval *value, 121 int *freeval 122 ) 123 { 124 char *s, *p, *d; 125 char nib; 126 int b64, url; 127 128 BER_BVZERO( type ); 129 BER_BVZERO( value ); 130 131 /* skip any leading space */ 132 while ( isspace( (unsigned char) *line ) ) { 133 line++; 134 } 135 136 if ( freeval ) { 137 *freeval = 0; 138 } else { 139 line = ber_strdup( line ); 140 141 if( line == NULL ) { 142 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 143 _("ldif_parse_line: line malloc failed\n")); 144 return( -1 ); 145 } 146 } 147 148 type->bv_val = line; 149 150 s = strchr( type->bv_val, ':' ); 151 152 if ( s == NULL ) { 153 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, 154 _("ldif_parse_line: missing ':' after %s\n"), 155 type->bv_val ); 156 if ( !freeval ) ber_memfree( line ); 157 return( -1 ); 158 } 159 160 /* trim any space between type and : */ 161 for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) { 162 *p = '\0'; 163 } 164 *s++ = '\0'; 165 type->bv_len = s - type->bv_val - 1; 166 167 url = 0; 168 b64 = 0; 169 170 if ( *s == '<' ) { 171 s++; 172 url = 1; 173 174 } else if ( *s == ':' ) { 175 /* base 64 encoded value */ 176 s++; 177 b64 = 1; 178 } 179 180 /* skip space between : and value */ 181 while ( isspace( (unsigned char) *s ) ) { 182 s++; 183 } 184 185 /* check for continued line markers that should be deleted */ 186 for ( p = s, d = s; *p; p++ ) { 187 if ( *p != CONTINUED_LINE_MARKER ) 188 *d++ = *p; 189 } 190 *d = '\0'; 191 192 if ( b64 ) { 193 char *byte = s; 194 195 if ( *s == '\0' ) { 196 /* no value is present, error out */ 197 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, 198 _("ldif_parse_line: %s missing base64 value\n"), 199 type->bv_val ); 200 if ( !freeval ) ber_memfree( line ); 201 return( -1 ); 202 } 203 204 byte = value->bv_val = s; 205 206 for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) { 207 int i; 208 for ( i = 0; i < 4; i++ ) { 209 if ( p[i] != '=' && (p[i] & 0x80 || 210 b642nib[ p[i] & 0x7f ] > 0x3f) ) { 211 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 212 _("ldif_parse_line: %s: invalid base64 encoding" 213 " char (%c) 0x%x\n"), 214 type->bv_val, p[i], p[i] ); 215 if ( !freeval ) ber_memfree( line ); 216 return( -1 ); 217 } 218 } 219 220 /* first digit */ 221 nib = b642nib[ p[0] & 0x7f ]; 222 byte[0] = nib << 2; 223 /* second digit */ 224 nib = b642nib[ p[1] & 0x7f ]; 225 byte[0] |= nib >> 4; 226 byte[1] = (nib & RIGHT4) << 4; 227 /* third digit */ 228 if ( p[2] == '=' ) { 229 value->bv_len += 1; 230 break; 231 } 232 nib = b642nib[ p[2] & 0x7f ]; 233 byte[1] |= nib >> 2; 234 byte[2] = (nib & RIGHT2) << 6; 235 /* fourth digit */ 236 if ( p[3] == '=' ) { 237 value->bv_len += 2; 238 break; 239 } 240 nib = b642nib[ p[3] & 0x7f ]; 241 byte[2] |= nib; 242 243 byte += 3; 244 } 245 s[ value->bv_len ] = '\0'; 246 247 } else if ( url ) { 248 if ( *s == '\0' ) { 249 /* no value is present, error out */ 250 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, 251 _("ldif_parse_line: %s missing URL value\n"), 252 type->bv_val ); 253 if ( !freeval ) ber_memfree( line ); 254 return( -1 ); 255 } 256 257 if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) { 258 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 259 _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"), 260 type->bv_val, s ); 261 if ( !freeval ) ber_memfree( line ); 262 return( -1 ); 263 } 264 if ( freeval ) *freeval = 1; 265 266 } else { 267 value->bv_val = s; 268 value->bv_len = (int) (d - s); 269 } 270 271 if ( !freeval ) { 272 struct berval bv = *type; 273 274 ber_dupbv( type, &bv ); 275 276 if( BER_BVISNULL( type )) { 277 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 278 _("ldif_parse_line: type malloc failed\n")); 279 if( url ) ber_memfree( value->bv_val ); 280 ber_memfree( line ); 281 return( -1 ); 282 } 283 284 if( !url ) { 285 bv = *value; 286 ber_dupbv( value, &bv ); 287 if( BER_BVISNULL( value )) { 288 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 289 _("ldif_parse_line: value malloc failed\n")); 290 ber_memfree( type->bv_val ); 291 ber_memfree( line ); 292 return( -1 ); 293 } 294 } 295 296 ber_memfree( line ); 297 } 298 299 return( 0 ); 300 } 301 302 /* 303 * ldif_getline - return the next "line" (minus newline) of input from a 304 * string buffer of lines separated by newlines, terminated by \n\n 305 * or \0. this routine handles continued lines, bundling them into 306 * a single big line before returning. if a line begins with a white 307 * space character, it is a continuation of the previous line. the white 308 * space character (nb: only one char), and preceeding newline are changed 309 * into CONTINUED_LINE_MARKER chars, to be deleted later by the 310 * ldif_parse_line() routine above. 311 * 312 * ldif_getline will skip over any line which starts '#'. 313 * 314 * ldif_getline takes a pointer to a pointer to the buffer on the first call, 315 * which it updates and must be supplied on subsequent calls. 316 */ 317 318 int 319 ldif_countlines( LDAP_CONST char *buf ) 320 { 321 char *nl; 322 int ret = 0; 323 324 if ( !buf ) return ret; 325 326 for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) { 327 nl++; 328 if ( *nl != ' ' ) ret++; 329 } 330 return ret; 331 } 332 333 char * 334 ldif_getline( char **next ) 335 { 336 char *line; 337 338 do { 339 if ( *next == NULL || **next == '\n' || **next == '\0' ) { 340 return( NULL ); 341 } 342 343 line = *next; 344 345 while ( (*next = strchr( *next, '\n' )) != NULL ) { 346 #if CONTINUED_LINE_MARKER != '\r' 347 if ( (*next)[-1] == '\r' ) { 348 (*next)[-1] = CONTINUED_LINE_MARKER; 349 } 350 #endif 351 352 if ( (*next)[1] != ' ' ) { 353 if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) { 354 *(*next)++ = '\0'; 355 } 356 *(*next)++ = '\0'; 357 break; 358 } 359 360 **next = CONTINUED_LINE_MARKER; 361 (*next)[1] = CONTINUED_LINE_MARKER; 362 (*next)++; 363 } 364 } while( *line == '#' ); 365 366 return( line ); 367 } 368 369 /* 370 * name and OID of attributeTypes that must be base64 encoded in any case 371 */ 372 typedef struct must_b64_encode_s { 373 struct berval name; 374 struct berval oid; 375 } must_b64_encode_s; 376 377 static must_b64_encode_s default_must_b64_encode[] = { 378 { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) }, 379 { BER_BVNULL, BER_BVNULL } 380 }; 381 382 static must_b64_encode_s *must_b64_encode = default_must_b64_encode; 383 384 /* 385 * register name and OID of attributeTypes that must always be base64 386 * encoded 387 * 388 * NOTE: this routine mallocs memory in a static struct which must 389 * be explicitly freed when no longer required 390 */ 391 int 392 ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid ) 393 { 394 int i; 395 ber_len_t len; 396 397 assert( must_b64_encode != NULL ); 398 assert( name != NULL ); 399 assert( oid != NULL ); 400 401 len = strlen( name ); 402 403 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { 404 if ( len != must_b64_encode[i].name.bv_len ) { 405 continue; 406 } 407 408 if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) { 409 break; 410 } 411 } 412 413 if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) { 414 return 1; 415 } 416 417 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) 418 /* just count */ ; 419 420 if ( must_b64_encode == default_must_b64_encode ) { 421 must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) ); 422 423 for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) { 424 ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name ); 425 ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid ); 426 } 427 428 } else { 429 must_b64_encode_s *tmp; 430 431 tmp = ber_memrealloc( must_b64_encode, 432 sizeof( must_b64_encode_s ) * ( i + 2 ) ); 433 if ( tmp == NULL ) { 434 return 1; 435 } 436 must_b64_encode = tmp; 437 } 438 439 ber_str2bv( name, len, 1, &must_b64_encode[i].name ); 440 ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid ); 441 442 BER_BVZERO( &must_b64_encode[i + 1].name ); 443 444 return 0; 445 } 446 447 void 448 ldif_must_b64_encode_release( void ) 449 { 450 int i; 451 452 assert( must_b64_encode != NULL ); 453 454 if ( must_b64_encode == default_must_b64_encode ) { 455 return; 456 } 457 458 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { 459 ber_memfree( must_b64_encode[i].name.bv_val ); 460 ber_memfree( must_b64_encode[i].oid.bv_val ); 461 } 462 463 ber_memfree( must_b64_encode ); 464 465 must_b64_encode = default_must_b64_encode; 466 } 467 468 /* 469 * returns 1 iff the string corresponds to the name or the OID of any 470 * of the attributeTypes listed in must_b64_encode 471 */ 472 static int 473 ldif_must_b64_encode( LDAP_CONST char *s ) 474 { 475 int i; 476 struct berval bv; 477 478 assert( must_b64_encode != NULL ); 479 assert( s != NULL ); 480 481 ber_str2bv( s, 0, 0, &bv ); 482 483 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { 484 if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0 485 || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 ) 486 { 487 return 1; 488 } 489 } 490 491 return 0; 492 } 493 494 /* compatibility with U-Mich off by two bug */ 495 #define LDIF_KLUDGE 2 496 497 /* NOTE: only preserved for binary compatibility */ 498 void 499 ldif_sput( 500 char **out, 501 int type, 502 LDAP_CONST char *name, 503 LDAP_CONST char *val, 504 ber_len_t vlen ) 505 { 506 ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH+LDIF_KLUDGE ); 507 } 508 509 void 510 ldif_sput_wrap( 511 char **out, 512 int type, 513 LDAP_CONST char *name, 514 LDAP_CONST char *val, 515 ber_len_t vlen, 516 ber_len_t wrap ) 517 { 518 const unsigned char *byte, *stop; 519 unsigned char buf[3]; 520 unsigned long bits; 521 char *save; 522 int pad; 523 int namelen = 0; 524 525 ber_len_t savelen; 526 ber_len_t len=0; 527 ber_len_t i; 528 529 if ( !wrap ) 530 wrap = LDIF_LINE_WIDTH+LDIF_KLUDGE; 531 532 /* prefix */ 533 switch( type ) { 534 case LDIF_PUT_COMMENT: 535 *(*out)++ = '#'; 536 len++; 537 538 if( vlen ) { 539 *(*out)++ = ' '; 540 len++; 541 } 542 543 break; 544 545 case LDIF_PUT_SEP: 546 *(*out)++ = '\n'; 547 return; 548 } 549 550 /* name (attribute type) */ 551 if( name != NULL ) { 552 /* put the name + ":" */ 553 namelen = strlen(name); 554 strcpy(*out, name); 555 *out += namelen; 556 len += namelen; 557 558 if( type != LDIF_PUT_COMMENT ) { 559 *(*out)++ = ':'; 560 len++; 561 } 562 563 } 564 #ifdef LDAP_DEBUG 565 else { 566 assert( type == LDIF_PUT_COMMENT ); 567 } 568 #endif 569 570 if( vlen == 0 ) { 571 *(*out)++ = '\n'; 572 return; 573 } 574 575 switch( type ) { 576 case LDIF_PUT_NOVALUE: 577 *(*out)++ = '\n'; 578 return; 579 580 case LDIF_PUT_URL: /* url value */ 581 *(*out)++ = '<'; 582 len++; 583 break; 584 585 case LDIF_PUT_B64: /* base64 value */ 586 *(*out)++ = ':'; 587 len++; 588 break; 589 } 590 591 switch( type ) { 592 case LDIF_PUT_TEXT: 593 case LDIF_PUT_URL: 594 case LDIF_PUT_B64: 595 *(*out)++ = ' '; 596 len++; 597 /* fall-thru */ 598 599 case LDIF_PUT_COMMENT: 600 /* pre-encoded names */ 601 for ( i=0; i < vlen; i++ ) { 602 if ( len > wrap ) { 603 *(*out)++ = '\n'; 604 *(*out)++ = ' '; 605 len = 1; 606 } 607 608 *(*out)++ = val[i]; 609 len++; 610 } 611 *(*out)++ = '\n'; 612 return; 613 } 614 615 save = *out; 616 savelen = len; 617 618 *(*out)++ = ' '; 619 len++; 620 621 stop = (const unsigned char *) (val + vlen); 622 623 if ( type == LDIF_PUT_VALUE 624 && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' 625 && isgraph( (unsigned char) val[vlen-1] ) 626 #ifndef LDAP_BINARY_DEBUG 627 && strstr( name, ";binary" ) == NULL 628 #endif 629 #ifndef LDAP_PASSWD_DEBUG 630 && !ldif_must_b64_encode( name ) 631 #endif 632 ) { 633 int b64 = 0; 634 635 for ( byte = (const unsigned char *) val; byte < stop; 636 byte++, len++ ) 637 { 638 if ( !isascii( *byte ) || !isprint( *byte ) ) { 639 b64 = 1; 640 break; 641 } 642 if ( len >= wrap ) { 643 *(*out)++ = '\n'; 644 *(*out)++ = ' '; 645 len = 1; 646 } 647 *(*out)++ = *byte; 648 } 649 650 if( !b64 ) { 651 *(*out)++ = '\n'; 652 return; 653 } 654 } 655 656 *out = save; 657 *(*out)++ = ':'; 658 *(*out)++ = ' '; 659 len = savelen + 2; 660 661 /* convert to base 64 (3 bytes => 4 base 64 digits) */ 662 for ( byte = (const unsigned char *) val; 663 byte < stop - 2; 664 byte += 3 ) 665 { 666 bits = (byte[0] & 0xff) << 16; 667 bits |= (byte[1] & 0xff) << 8; 668 bits |= (byte[2] & 0xff); 669 670 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { 671 if ( len >= wrap ) { 672 *(*out)++ = '\n'; 673 *(*out)++ = ' '; 674 len = 1; 675 } 676 677 /* get b64 digit from high order 6 bits */ 678 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; 679 } 680 } 681 682 /* add padding if necessary */ 683 if ( byte < stop ) { 684 for ( i = 0; byte + i < stop; i++ ) { 685 buf[i] = byte[i]; 686 } 687 for ( pad = 0; i < 3; i++, pad++ ) { 688 buf[i] = '\0'; 689 } 690 byte = buf; 691 bits = (byte[0] & 0xff) << 16; 692 bits |= (byte[1] & 0xff) << 8; 693 bits |= (byte[2] & 0xff); 694 695 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { 696 if ( len >= wrap ) { 697 *(*out)++ = '\n'; 698 *(*out)++ = ' '; 699 len = 1; 700 } 701 702 if( i + pad < 4 ) { 703 /* get b64 digit from low order 6 bits */ 704 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; 705 } else { 706 *(*out)++ = '='; 707 } 708 } 709 } 710 *(*out)++ = '\n'; 711 } 712 713 714 /* 715 * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line 716 */ 717 718 /* NOTE: only preserved for binary compatibility */ 719 char * 720 ldif_put( 721 int type, 722 LDAP_CONST char *name, 723 LDAP_CONST char *val, 724 ber_len_t vlen ) 725 { 726 return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH ); 727 } 728 729 char * 730 ldif_put_wrap( 731 int type, 732 LDAP_CONST char *name, 733 LDAP_CONST char *val, 734 ber_len_t vlen, 735 ber_len_t wrap ) 736 { 737 char *buf, *p; 738 ber_len_t nlen; 739 740 nlen = ( name != NULL ) ? strlen( name ) : 0; 741 742 buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 ); 743 744 if ( buf == NULL ) { 745 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 746 _("ldif_type_and_value: malloc failed!")); 747 return NULL; 748 } 749 750 p = buf; 751 ldif_sput_wrap( &p, type, name, val, vlen, wrap ); 752 *p = '\0'; 753 754 return( buf ); 755 } 756 757 int ldif_is_not_printable( 758 LDAP_CONST char *val, 759 ber_len_t vlen ) 760 { 761 if( vlen == 0 || val == NULL ) { 762 return -1; 763 } 764 765 if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' && 766 isgraph( (unsigned char) val[vlen-1] ) ) 767 { 768 ber_len_t i; 769 770 for ( i = 0; val[i]; i++ ) { 771 if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) { 772 return 1; 773 } 774 } 775 776 return 0; 777 } 778 779 return 1; 780 } 781 782 LDIFFP * 783 ldif_open( 784 LDAP_CONST char *file, 785 LDAP_CONST char *mode 786 ) 787 { 788 FILE *fp = fopen( file, mode ); 789 LDIFFP *lfp = NULL; 790 791 if ( fp ) { 792 lfp = ber_memalloc( sizeof( LDIFFP )); 793 lfp->fp = fp; 794 lfp->prev = NULL; 795 } 796 return lfp; 797 } 798 799 void 800 ldif_close( 801 LDIFFP *lfp 802 ) 803 { 804 LDIFFP *prev; 805 806 while ( lfp ) { 807 fclose( lfp->fp ); 808 prev = lfp->prev; 809 ber_memfree( lfp ); 810 lfp = prev; 811 } 812 } 813 814 #define LDIF_MAXLINE 4096 815 816 /* 817 * ldif_read_record - read an ldif record. Return 1 for success, 0 for EOF, 818 * -1 for error. 819 */ 820 int 821 ldif_read_record( 822 LDIFFP *lfp, 823 unsigned long *lno, /* ptr to line number counter */ 824 char **bufp, /* ptr to malloced output buffer */ 825 int *buflenp ) /* ptr to length of *bufp */ 826 { 827 char line[LDIF_MAXLINE], *nbufp; 828 ber_len_t lcur = 0, len; 829 int last_ch = '\n', found_entry = 0, stop, top_comment = 0; 830 831 for ( stop = 0; !stop; last_ch = line[len-1] ) { 832 /* If we're at the end of this file, see if we should pop 833 * back to a previous file. (return from an include) 834 */ 835 while ( feof( lfp->fp )) { 836 if ( lfp->prev ) { 837 LDIFFP *tmp = lfp->prev; 838 fclose( lfp->fp ); 839 *lfp = *tmp; 840 ber_memfree( tmp ); 841 } else { 842 stop = 1; 843 break; 844 } 845 } 846 if ( !stop ) { 847 if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) { 848 stop = 1; 849 len = 0; 850 } else { 851 len = strlen( line ); 852 } 853 } 854 855 if ( stop ) { 856 /* Add \n in case the file does not end with newline */ 857 if (last_ch != '\n') { 858 len = 1; 859 line[0] = '\n'; 860 line[1] = '\0'; 861 goto last; 862 } 863 break; 864 } 865 866 /* Squash \r\n to \n */ 867 if ( len > 1 && line[len-2] == '\r' ) { 868 len--; 869 line[len-1] = '\n'; 870 } 871 872 if ( last_ch == '\n' ) { 873 (*lno)++; 874 875 if ( line[0] == '\n' ) { 876 if ( !found_entry ) { 877 lcur = 0; 878 top_comment = 0; 879 continue; 880 } 881 break; 882 } 883 884 if ( !found_entry ) { 885 if ( line[0] == '#' ) { 886 top_comment = 1; 887 } else if ( ! ( top_comment && line[0] == ' ' ) ) { 888 /* Found a new entry */ 889 found_entry = 1; 890 891 if ( isdigit( (unsigned char) line[0] ) ) { 892 /* skip index */ 893 continue; 894 } 895 if ( !strncasecmp( line, "include:", 896 STRLENOF("include:"))) { 897 FILE *fp2; 898 char *ptr; 899 found_entry = 0; 900 901 if ( line[len-1] == '\n' ) { 902 len--; 903 line[len] = '\0'; 904 } 905 906 ptr = line + STRLENOF("include:"); 907 while (isspace((unsigned char) *ptr)) ptr++; 908 fp2 = ldif_open_url( ptr ); 909 if ( fp2 ) { 910 LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP )); 911 if ( lnew == NULL ) { 912 fclose( fp2 ); 913 return 0; 914 } 915 lnew->prev = lfp->prev; 916 lnew->fp = lfp->fp; 917 lfp->prev = lnew; 918 lfp->fp = fp2; 919 line[len] = '\n'; 920 len++; 921 continue; 922 } else { 923 /* We failed to open the file, this should 924 * be reported as an error somehow. 925 */ 926 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 927 _("ldif_read_record: include %s failed\n"), ptr ); 928 return -1; 929 } 930 } 931 } 932 } 933 } 934 935 last: 936 if ( *buflenp - lcur <= len ) { 937 *buflenp += len + LDIF_MAXLINE; 938 nbufp = ber_memrealloc( *bufp, *buflenp ); 939 if( nbufp == NULL ) { 940 return 0; 941 } 942 *bufp = nbufp; 943 } 944 strcpy( *bufp + lcur, line ); 945 lcur += len; 946 } 947 948 return( found_entry ); 949 } 950