1 /* decode.c - ber input decoding routines */ 2 /* $OpenLDAP: pkg/ldap/libraries/liblber/decode.c,v 1.105.2.4 2008/02/11 23:26:41 kurt Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2008 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 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>. 15 */ 16 /* Portions Copyright (c) 1990 Regents of the University of Michigan. 17 * All rights reserved. 18 * 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 University 22 * may not be used to endorse or promote products derived from this 23 * software without specific prior written permission. This software 24 * is provided ``as is'' without express or implied warranty. 25 */ 26 /* ACKNOWLEDGEMENTS: 27 * This work was originally developed by the University of Michigan 28 * (as part of U-MICH LDAP). 29 */ 30 31 #include "portable.h" 32 33 #include <stdio.h> 34 35 #include <ac/stdlib.h> 36 37 #include <ac/stdarg.h> 38 #include <ac/string.h> 39 #include <ac/socket.h> 40 41 #include "lber-int.h" 42 43 static ber_len_t ber_getnint LDAP_P(( 44 BerElement *ber, 45 ber_int_t *num, 46 ber_len_t len )); 47 48 /* out->bv_len should be the buffer size on input */ 49 int 50 ber_decode_oid( BerValue *in, BerValue *out ) 51 { 52 const unsigned char *der; 53 unsigned long val; 54 unsigned val1; 55 ber_len_t i; 56 char *ptr; 57 58 assert( in != NULL ); 59 assert( out != NULL ); 60 61 /* need 4 chars/inbyte + \0 for input={7f 7f 7f...} */ 62 if ( !out->bv_val || (out->bv_len+3)/4 <= in->bv_len ) 63 return -1; 64 65 ptr = NULL; 66 der = (unsigned char *) in->bv_val; 67 val = 0; 68 for ( i=0; i < in->bv_len; i++ ) { 69 val |= der[i] & 0x7f; 70 if ( !( der[i] & 0x80 )) { 71 if ( ptr == NULL ) { 72 /* Initial "x.y": val=x*40+y, x<=2, y<40 if x=2 */ 73 ptr = out->bv_val; 74 val1 = (val < 80 ? val/40 : 2); 75 val -= val1*40; 76 ptr += sprintf( ptr, "%u", val1 ); 77 } 78 ptr += sprintf( ptr, ".%lu", val ); 79 val = 0; 80 } else if ( val - 1UL < LBER_OID_COMPONENT_MAX >> 7 ) { 81 val <<= 7; 82 } else { 83 /* val would overflow, or is 0 from invalid initial 0x80 octet */ 84 return -1; 85 } 86 } 87 if ( ptr == NULL || val != 0 ) 88 return -1; 89 90 out->bv_len = ptr - out->bv_val; 91 return 0; 92 } 93 94 /* return the tag - LBER_DEFAULT returned means trouble */ 95 ber_tag_t 96 ber_get_tag( BerElement *ber ) 97 { 98 unsigned char xbyte; 99 ber_tag_t tag; 100 unsigned int i; 101 102 assert( ber != NULL ); 103 assert( LBER_VALID( ber ) ); 104 105 if ( ber_pvt_ber_remaining( ber ) < 1 ) { 106 return LBER_DEFAULT; 107 } 108 109 if ( ber->ber_ptr == ber->ber_buf ) { 110 tag = *(unsigned char *)ber->ber_ptr; 111 } else { 112 tag = ber->ber_tag; 113 } 114 ber->ber_ptr++; 115 116 if ( (tag & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { 117 return tag; 118 } 119 120 for ( i = 1; i < sizeof(ber_tag_t); i++ ) { 121 if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) { 122 return LBER_DEFAULT; 123 } 124 125 tag <<= 8; 126 tag |= 0x00ffUL & (ber_tag_t) xbyte; 127 128 if ( ! (xbyte & LBER_MORE_TAG_MASK) ) { 129 break; 130 } 131 } 132 133 /* tag too big! */ 134 if ( i == sizeof(ber_tag_t) ) { 135 return LBER_DEFAULT; 136 } 137 138 return tag; 139 } 140 141 ber_tag_t 142 ber_skip_tag( BerElement *ber, ber_len_t *len ) 143 { 144 ber_tag_t tag; 145 unsigned char lc; 146 ber_len_t i, noctets; 147 unsigned char netlen[sizeof(ber_len_t)]; 148 149 assert( ber != NULL ); 150 assert( len != NULL ); 151 assert( LBER_VALID( ber ) ); 152 153 /* 154 * Any ber element looks like this: tag length contents. 155 * Assuming everything's ok, we return the tag byte (we 156 * can assume a single byte), and return the length in len. 157 * 158 * Assumptions: 159 * 1) definite lengths 160 * 2) primitive encodings used whenever possible 161 */ 162 163 *len = 0; 164 165 /* 166 * First, we read the tag. 167 */ 168 169 if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT ) { 170 return LBER_DEFAULT; 171 } 172 173 /* 174 * Next, read the length. The first byte contains the length of 175 * the length. If bit 8 is set, the length is the long form, 176 * otherwise it's the short form. We don't allow a length that's 177 * greater than what we can hold in a ber_len_t. 178 */ 179 180 if ( ber_read( ber, (char *) &lc, 1 ) != 1 ) { 181 return LBER_DEFAULT; 182 } 183 184 if ( lc & 0x80U ) { 185 noctets = (lc & 0x7fU); 186 187 if ( noctets > sizeof(ber_len_t) ) { 188 return LBER_DEFAULT; 189 } 190 191 if( (unsigned) ber_read( ber, (char *) netlen, noctets ) != noctets ) { 192 return LBER_DEFAULT; 193 } 194 195 for( i = 0; i < noctets; i++ ) { 196 *len <<= 8; 197 *len |= netlen[i]; 198 } 199 200 } else { 201 *len = lc; 202 } 203 204 /* BER element should have enough data left */ 205 if( *len > (ber_len_t) ber_pvt_ber_remaining( ber ) ) { 206 return LBER_DEFAULT; 207 } 208 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 209 210 return tag; 211 } 212 213 ber_tag_t 214 ber_peek_tag( 215 BerElement *ber, 216 ber_len_t *len ) 217 { 218 /* 219 * This implementation assumes ber_skip_tag() only 220 * modifies ber_ptr field of the BerElement. 221 */ 222 223 char *save; 224 ber_tag_t tag, old; 225 226 old = ber->ber_tag; 227 save = ber->ber_ptr; 228 tag = ber_skip_tag( ber, len ); 229 ber->ber_ptr = save; 230 ber->ber_tag = old; 231 232 return tag; 233 } 234 235 static ber_len_t 236 ber_getnint( 237 BerElement *ber, 238 ber_int_t *num, 239 ber_len_t len ) 240 { 241 unsigned char buf[sizeof(ber_int_t)]; 242 243 assert( ber != NULL ); 244 assert( num != NULL ); 245 assert( LBER_VALID( ber ) ); 246 247 /* 248 * The tag and length have already been stripped off. We should 249 * be sitting right before len bytes of 2's complement integer, 250 * ready to be read straight into an int. We may have to sign 251 * extend after we read it in. 252 */ 253 254 if ( len > sizeof(ber_int_t) ) { 255 return -1; 256 } 257 258 /* read into the low-order bytes of our buffer */ 259 if ( (ber_len_t) ber_read( ber, (char *) buf, len ) != len ) { 260 return -1; 261 } 262 263 if( len ) { 264 /* sign extend if necessary */ 265 ber_len_t i; 266 ber_int_t netnum = 0x80 & buf[0] ? -1 : 0; 267 268 /* shift in the bytes */ 269 for( i=0 ; i<len; i++ ) { 270 netnum = (netnum << 8 ) | buf[i]; 271 } 272 273 *num = netnum; 274 275 } else { 276 *num = 0; 277 } 278 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 279 280 return len; 281 } 282 283 ber_tag_t 284 ber_get_int( 285 BerElement *ber, 286 ber_int_t *num ) 287 { 288 ber_tag_t tag; 289 ber_len_t len; 290 291 assert( ber != NULL ); 292 assert( LBER_VALID( ber ) ); 293 294 if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) { 295 return LBER_DEFAULT; 296 } 297 298 if ( ber_getnint( ber, num, len ) != len ) { 299 return LBER_DEFAULT; 300 } 301 302 return tag; 303 } 304 305 ber_tag_t 306 ber_get_enum( 307 BerElement *ber, 308 ber_int_t *num ) 309 { 310 return ber_get_int( ber, num ); 311 } 312 313 ber_tag_t 314 ber_get_stringb( 315 BerElement *ber, 316 char *buf, 317 ber_len_t *len ) 318 { 319 ber_len_t datalen; 320 ber_tag_t tag; 321 322 assert( ber != NULL ); 323 assert( LBER_VALID( ber ) ); 324 325 if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) { 326 return LBER_DEFAULT; 327 } 328 329 /* must fit within allocated space with termination */ 330 if ( datalen >= *len ) { 331 return LBER_DEFAULT; 332 } 333 334 if ( (ber_len_t) ber_read( ber, buf, datalen ) != datalen ) { 335 return LBER_DEFAULT; 336 } 337 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 338 339 buf[datalen] = '\0'; 340 341 *len = datalen; 342 return tag; 343 } 344 345 /* Definitions for get_string vector 346 * 347 * ChArray, BvArray, and BvVec are self-explanatory. 348 * BvOff is a struct berval embedded in an array of larger structures 349 * of siz bytes at off bytes from the beginning of the struct. 350 */ 351 enum bgbvc { ChArray, BvArray, BvVec, BvOff }; 352 353 /* Use this single cookie for state, to keep actual 354 * stack use to the absolute minimum. 355 */ 356 typedef struct bgbvr { 357 enum bgbvc choice; 358 BerElement *ber; 359 int alloc; 360 ber_len_t siz; 361 ber_len_t off; 362 union { 363 char ***c; 364 BerVarray *ba; 365 struct berval ***bv; 366 } res; 367 } bgbvr; 368 369 static ber_tag_t 370 ber_get_stringbvl( bgbvr *b, ber_len_t *rlen ) 371 { 372 int i = 0, n; 373 ber_tag_t tag; 374 ber_len_t len; 375 char *last, *orig; 376 struct berval bv, *bvp = NULL; 377 378 /* For rewinding, just like ber_peek_tag() */ 379 orig = b->ber->ber_ptr; 380 tag = b->ber->ber_tag; 381 382 if ( ber_first_element( b->ber, &len, &last ) != LBER_DEFAULT ) { 383 for ( ; b->ber->ber_ptr < last; i++ ) { 384 if (ber_skip_tag( b->ber, &len ) == LBER_DEFAULT) break; 385 b->ber->ber_ptr += len; 386 b->ber->ber_tag = *(unsigned char *)b->ber->ber_ptr; 387 } 388 } 389 390 if ( rlen ) *rlen = i; 391 392 if ( i == 0 ) { 393 *b->res.c = NULL; 394 return 0; 395 } 396 397 n = i; 398 399 /* Allocate the result vector */ 400 switch (b->choice) { 401 case ChArray: 402 *b->res.c = ber_memalloc_x( (n+1)*sizeof( char * ), 403 b->ber->ber_memctx); 404 if ( *b->res.c == NULL ) return LBER_DEFAULT; 405 (*b->res.c)[n] = NULL; 406 break; 407 case BvArray: 408 *b->res.ba = ber_memalloc_x( (n+1)*sizeof( struct berval ), 409 b->ber->ber_memctx); 410 if ( *b->res.ba == NULL ) return LBER_DEFAULT; 411 (*b->res.ba)[n].bv_val = NULL; 412 break; 413 case BvVec: 414 *b->res.bv = ber_memalloc_x( (n+1)*sizeof( struct berval *), 415 b->ber->ber_memctx); 416 if ( *b->res.bv == NULL ) return LBER_DEFAULT; 417 (*b->res.bv)[n] = NULL; 418 break; 419 case BvOff: 420 *b->res.ba = ber_memalloc_x( (n+1) * b->siz, b->ber->ber_memctx ); 421 if ( *b->res.ba == NULL ) return LBER_DEFAULT; 422 ((struct berval *)((char *)(*b->res.ba) + n*b->siz + 423 b->off))->bv_val = NULL; 424 break; 425 } 426 b->ber->ber_ptr = orig; 427 b->ber->ber_tag = tag; 428 ber_skip_tag( b->ber, &len ); 429 430 for (n=0; n<i; n++) 431 { 432 tag = ber_next_element( b->ber, &len, last ); 433 if ( ber_get_stringbv( b->ber, &bv, b->alloc ) == LBER_DEFAULT ) { 434 goto nomem; 435 } 436 437 /* store my result */ 438 switch (b->choice) { 439 case ChArray: 440 (*b->res.c)[n] = bv.bv_val; 441 break; 442 case BvArray: 443 (*b->res.ba)[n] = bv; 444 break; 445 case BvVec: 446 bvp = ber_memalloc_x( sizeof( struct berval ), b->ber->ber_memctx); 447 if ( !bvp ) { 448 LBER_FREE(bv.bv_val); 449 goto nomem; 450 } 451 (*b->res.bv)[n] = bvp; 452 *bvp = bv; 453 break; 454 case BvOff: 455 *(BerVarray)((char *)(*b->res.ba)+n*b->siz+b->off) = bv; 456 break; 457 } 458 } 459 return tag; 460 461 nomem: 462 if (b->alloc || b->choice == BvVec) { 463 for (--n; n>=0; n--) { 464 switch(b->choice) { 465 case ChArray: 466 LBER_FREE((*b->res.c)[n]); 467 break; 468 case BvArray: 469 LBER_FREE((*b->res.ba)[n].bv_val); 470 break; 471 case BvVec: 472 LBER_FREE((*b->res.bv)[n]->bv_val); 473 LBER_FREE((*b->res.bv)[n]); 474 break; 475 default: 476 break; 477 } 478 } 479 } 480 LBER_FREE(*b->res.c); 481 *b->res.c = NULL; 482 return LBER_DEFAULT; 483 } 484 485 ber_tag_t 486 ber_get_stringbv( BerElement *ber, struct berval *bv, int option ) 487 { 488 ber_tag_t tag; 489 490 assert( ber != NULL ); 491 assert( bv != NULL ); 492 493 assert( LBER_VALID( ber ) ); 494 495 if ( (tag = ber_skip_tag( ber, &bv->bv_len )) == LBER_DEFAULT ) { 496 bv->bv_val = NULL; 497 return LBER_DEFAULT; 498 } 499 500 if ( (ber_len_t) ber_pvt_ber_remaining( ber ) < bv->bv_len ) { 501 return LBER_DEFAULT; 502 } 503 504 if ( option & LBER_BV_ALLOC ) { 505 bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1, 506 ber->ber_memctx ); 507 if ( bv->bv_val == NULL ) { 508 return LBER_DEFAULT; 509 } 510 511 if ( bv->bv_len > 0 && (ber_len_t) ber_read( ber, bv->bv_val, 512 bv->bv_len ) != bv->bv_len ) 513 { 514 LBER_FREE( bv->bv_val ); 515 bv->bv_val = NULL; 516 return LBER_DEFAULT; 517 } 518 } else { 519 bv->bv_val = ber->ber_ptr; 520 ber->ber_ptr += bv->bv_len; 521 } 522 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 523 if ( !( option & LBER_BV_NOTERM )) 524 bv->bv_val[bv->bv_len] = '\0'; 525 526 return tag; 527 } 528 529 ber_tag_t 530 ber_get_stringbv_null( BerElement *ber, struct berval *bv, int option ) 531 { 532 ber_tag_t tag; 533 534 assert( ber != NULL ); 535 assert( bv != NULL ); 536 537 assert( LBER_VALID( ber ) ); 538 539 if ( (tag = ber_skip_tag( ber, &bv->bv_len )) == LBER_DEFAULT ) { 540 bv->bv_val = NULL; 541 return LBER_DEFAULT; 542 } 543 544 if ( (ber_len_t) ber_pvt_ber_remaining( ber ) < bv->bv_len ) { 545 return LBER_DEFAULT; 546 } 547 548 if ( bv->bv_len == 0 ) { 549 bv->bv_val = NULL; 550 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 551 return tag; 552 } 553 554 if ( option & LBER_BV_ALLOC ) { 555 bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1, 556 ber->ber_memctx ); 557 if ( bv->bv_val == NULL ) { 558 return LBER_DEFAULT; 559 } 560 561 if ( bv->bv_len > 0 && (ber_len_t) ber_read( ber, bv->bv_val, 562 bv->bv_len ) != bv->bv_len ) 563 { 564 LBER_FREE( bv->bv_val ); 565 bv->bv_val = NULL; 566 return LBER_DEFAULT; 567 } 568 } else { 569 bv->bv_val = ber->ber_ptr; 570 ber->ber_ptr += bv->bv_len; 571 } 572 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 573 if ( !( option & LBER_BV_NOTERM )) 574 bv->bv_val[bv->bv_len] = '\0'; 575 576 return tag; 577 } 578 579 ber_tag_t 580 ber_get_stringa( BerElement *ber, char **buf ) 581 { 582 BerValue bv; 583 ber_tag_t tag; 584 585 assert( buf != NULL ); 586 587 tag = ber_get_stringbv( ber, &bv, LBER_BV_ALLOC ); 588 *buf = bv.bv_val; 589 590 return tag; 591 } 592 593 ber_tag_t 594 ber_get_stringa_null( BerElement *ber, char **buf ) 595 { 596 BerValue bv; 597 ber_tag_t tag; 598 599 assert( buf != NULL ); 600 601 tag = ber_get_stringbv_null( ber, &bv, LBER_BV_ALLOC ); 602 *buf = bv.bv_val; 603 604 return tag; 605 } 606 607 ber_tag_t 608 ber_get_stringal( BerElement *ber, struct berval **bv ) 609 { 610 ber_tag_t tag; 611 612 assert( ber != NULL ); 613 assert( bv != NULL ); 614 615 *bv = (struct berval *) ber_memalloc_x( sizeof(struct berval), 616 ber->ber_memctx ); 617 if ( *bv == NULL ) { 618 return LBER_DEFAULT; 619 } 620 621 tag = ber_get_stringbv( ber, *bv, LBER_BV_ALLOC ); 622 if ( tag == LBER_DEFAULT ) { 623 LBER_FREE( *bv ); 624 *bv = NULL; 625 } 626 return tag; 627 } 628 629 ber_tag_t 630 ber_get_bitstringa( 631 BerElement *ber, 632 char **buf, 633 ber_len_t *blen ) 634 { 635 ber_len_t datalen; 636 ber_tag_t tag; 637 unsigned char unusedbits; 638 639 assert( ber != NULL ); 640 assert( buf != NULL ); 641 assert( blen != NULL ); 642 643 assert( LBER_VALID( ber ) ); 644 645 if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) { 646 *buf = NULL; 647 return LBER_DEFAULT; 648 } 649 --datalen; 650 651 *buf = (char *) ber_memalloc_x( datalen, ber->ber_memctx ); 652 if ( *buf == NULL ) { 653 return LBER_DEFAULT; 654 } 655 656 if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 ) { 657 LBER_FREE( buf ); 658 *buf = NULL; 659 return LBER_DEFAULT; 660 } 661 662 if ( (ber_len_t) ber_read( ber, *buf, datalen ) != datalen ) { 663 LBER_FREE( buf ); 664 *buf = NULL; 665 return LBER_DEFAULT; 666 } 667 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 668 669 *blen = datalen * 8 - unusedbits; 670 return tag; 671 } 672 673 ber_tag_t 674 ber_get_null( BerElement *ber ) 675 { 676 ber_len_t len; 677 ber_tag_t tag; 678 679 assert( ber != NULL ); 680 assert( LBER_VALID( ber ) ); 681 682 if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) { 683 return LBER_DEFAULT; 684 } 685 686 if ( len != 0 ) { 687 return LBER_DEFAULT; 688 } 689 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 690 691 return( tag ); 692 } 693 694 ber_tag_t 695 ber_get_boolean( 696 BerElement *ber, 697 ber_int_t *boolval ) 698 { 699 ber_int_t longbool; 700 ber_tag_t rc; 701 702 assert( ber != NULL ); 703 assert( boolval != NULL ); 704 705 assert( LBER_VALID( ber ) ); 706 707 rc = ber_get_int( ber, &longbool ); 708 *boolval = longbool; 709 710 return rc; 711 } 712 713 ber_tag_t 714 ber_first_element( 715 BerElement *ber, 716 ber_len_t *len, 717 char **last ) 718 { 719 assert( ber != NULL ); 720 assert( len != NULL ); 721 assert( last != NULL ); 722 723 /* skip the sequence header, use the len to mark where to stop */ 724 if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) { 725 *last = NULL; 726 return LBER_DEFAULT; 727 } 728 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 729 730 *last = ber->ber_ptr + *len; 731 732 if ( *last == ber->ber_ptr ) { 733 return LBER_DEFAULT; 734 } 735 736 return ber_peek_tag( ber, len ); 737 } 738 739 ber_tag_t 740 ber_next_element( 741 BerElement *ber, 742 ber_len_t *len, 743 LDAP_CONST char *last ) 744 { 745 assert( ber != NULL ); 746 assert( len != NULL ); 747 assert( last != NULL ); 748 749 assert( LBER_VALID( ber ) ); 750 751 if ( ber->ber_ptr >= last ) { 752 return LBER_DEFAULT; 753 } 754 755 return ber_peek_tag( ber, len ); 756 } 757 758 /* VARARGS */ 759 ber_tag_t 760 ber_scanf ( BerElement *ber, 761 LDAP_CONST char *fmt, 762 ... ) 763 { 764 va_list ap; 765 LDAP_CONST char *fmt_reset; 766 char *s, **ss; 767 struct berval **bvp, *bval; 768 ber_int_t *i; 769 ber_len_t *l; 770 ber_tag_t *t; 771 ber_tag_t rc; 772 ber_len_t len; 773 774 va_start( ap, fmt ); 775 776 assert( ber != NULL ); 777 assert( fmt != NULL ); 778 779 assert( LBER_VALID( ber ) ); 780 781 fmt_reset = fmt; 782 783 if ( ber->ber_debug & (LDAP_DEBUG_TRACE|LDAP_DEBUG_BER)) { 784 ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, 785 "ber_scanf fmt (%s) ber:\n", fmt ); 786 ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 ); 787 } 788 789 for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) { 790 /* When this is modified, remember to update 791 * the error-cleanup code below accordingly. */ 792 switch ( *fmt ) { 793 case '!': { /* Hook */ 794 BERDecodeCallback *f; 795 void *p; 796 797 f = va_arg( ap, BERDecodeCallback * ); 798 p = va_arg( ap, void * ); 799 800 rc = (*f)( ber, p, 0 ); 801 } break; 802 803 case 'a': /* octet string - allocate storage as needed */ 804 ss = va_arg( ap, char ** ); 805 rc = ber_get_stringa( ber, ss ); 806 break; 807 808 case 'A': /* octet string - allocate storage as needed, 809 * but return NULL if len == 0 */ 810 ss = va_arg( ap, char ** ); 811 rc = ber_get_stringa_null( ber, ss ); 812 break; 813 814 case 'b': /* boolean */ 815 i = va_arg( ap, ber_int_t * ); 816 rc = ber_get_boolean( ber, i ); 817 break; 818 819 case 'B': /* bit string - allocate storage as needed */ 820 ss = va_arg( ap, char ** ); 821 l = va_arg( ap, ber_len_t * ); /* for length, in bits */ 822 rc = ber_get_bitstringa( ber, ss, l ); 823 break; 824 825 case 'e': /* enumerated */ 826 case 'i': /* int */ 827 i = va_arg( ap, ber_int_t * ); 828 rc = ber_get_int( ber, i ); 829 break; 830 831 case 'l': /* length of next item */ 832 l = va_arg( ap, ber_len_t * ); 833 rc = ber_peek_tag( ber, l ); 834 break; 835 836 case 'm': /* octet string in berval, in-place */ 837 bval = va_arg( ap, struct berval * ); 838 rc = ber_get_stringbv( ber, bval, 0 ); 839 break; 840 841 case 'M': /* bvoffarray - must include address of 842 * a record len, and record offset. 843 * number of records will be returned thru 844 * len ptr on finish. parsed in-place. 845 */ 846 { 847 bgbvr cookie = { BvOff }; 848 cookie.ber = ber; 849 cookie.res.ba = va_arg( ap, struct berval ** ); 850 cookie.alloc = 0; 851 l = va_arg( ap, ber_len_t * ); 852 cookie.siz = *l; 853 cookie.off = va_arg( ap, ber_len_t ); 854 rc = ber_get_stringbvl( &cookie, l ); 855 break; 856 } 857 858 case 'n': /* null */ 859 rc = ber_get_null( ber ); 860 break; 861 862 case 'o': /* octet string in a supplied berval */ 863 bval = va_arg( ap, struct berval * ); 864 rc = ber_get_stringbv( ber, bval, LBER_BV_ALLOC ); 865 break; 866 867 case 'O': /* octet string - allocate & include length */ 868 bvp = va_arg( ap, struct berval ** ); 869 rc = ber_get_stringal( ber, bvp ); 870 break; 871 872 case 's': /* octet string - in a buffer */ 873 s = va_arg( ap, char * ); 874 l = va_arg( ap, ber_len_t * ); 875 rc = ber_get_stringb( ber, s, l ); 876 break; 877 878 case 't': /* tag of next item */ 879 t = va_arg( ap, ber_tag_t * ); 880 *t = rc = ber_peek_tag( ber, &len ); 881 break; 882 883 case 'T': /* skip tag of next item */ 884 t = va_arg( ap, ber_tag_t * ); 885 *t = rc = ber_skip_tag( ber, &len ); 886 break; 887 888 case 'v': /* sequence of strings */ 889 { 890 bgbvr cookie = { ChArray }; 891 cookie.ber = ber; 892 cookie.res.c = va_arg( ap, char *** ); 893 cookie.alloc = LBER_BV_ALLOC; 894 rc = ber_get_stringbvl( &cookie, NULL ); 895 break; 896 } 897 898 case 'V': /* sequence of strings + lengths */ 899 { 900 bgbvr cookie = { BvVec }; 901 cookie.ber = ber; 902 cookie.res.bv = va_arg( ap, struct berval *** ); 903 cookie.alloc = LBER_BV_ALLOC; 904 rc = ber_get_stringbvl( &cookie, NULL ); 905 break; 906 } 907 908 case 'W': /* bvarray */ 909 { 910 bgbvr cookie = { BvArray }; 911 cookie.ber = ber; 912 cookie.res.ba = va_arg( ap, struct berval ** ); 913 cookie.alloc = LBER_BV_ALLOC; 914 rc = ber_get_stringbvl( &cookie, NULL ); 915 break; 916 } 917 918 case 'x': /* skip the next element - whatever it is */ 919 if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) 920 break; 921 ber->ber_ptr += len; 922 ber->ber_tag = *(unsigned char *)ber->ber_ptr; 923 break; 924 925 case '{': /* begin sequence */ 926 case '[': /* begin set */ 927 if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V' 928 && *(fmt + 1) != 'W' && *(fmt + 1) != 'M' ) 929 rc = ber_skip_tag( ber, &len ); 930 break; 931 932 case '}': /* end sequence */ 933 case ']': /* end set */ 934 break; 935 936 default: 937 if( ber->ber_debug ) { 938 ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, 939 "ber_scanf: unknown fmt %c\n", *fmt ); 940 } 941 rc = LBER_DEFAULT; 942 break; 943 } 944 } 945 946 va_end( ap ); 947 if ( rc == LBER_DEFAULT ) { 948 /* 949 * Error. Reclaim malloced memory that was given to the caller. 950 * Set allocated pointers to NULL, "data length" outvalues to 0. 951 */ 952 va_start( ap, fmt ); 953 954 for ( ; fmt_reset < fmt; fmt_reset++ ) { 955 switch ( *fmt_reset ) { 956 case '!': { /* Hook */ 957 BERDecodeCallback *f; 958 void *p; 959 960 f = va_arg( ap, BERDecodeCallback * ); 961 p = va_arg( ap, void * ); 962 963 (void) (*f)( ber, p, 1 ); 964 } break; 965 966 case 'a': /* octet string - allocate storage as needed */ 967 case 'A': 968 ss = va_arg( ap, char ** ); 969 if ( *ss ) { 970 LBER_FREE( *ss ); 971 *ss = NULL; 972 } 973 break; 974 975 case 'b': /* boolean */ 976 case 'e': /* enumerated */ 977 case 'i': /* int */ 978 (void) va_arg( ap, int * ); 979 break; 980 981 case 'l': /* length of next item */ 982 (void) va_arg( ap, ber_len_t * ); 983 break; 984 985 case 'o': /* octet string in a supplied berval */ 986 bval = va_arg( ap, struct berval * ); 987 if ( bval->bv_val != NULL ) { 988 LBER_FREE( bval->bv_val ); 989 bval->bv_val = NULL; 990 } 991 bval->bv_len = 0; 992 break; 993 994 case 'O': /* octet string - allocate & include length */ 995 bvp = va_arg( ap, struct berval ** ); 996 if ( *bvp ) { 997 ber_bvfree( *bvp ); 998 *bvp = NULL; 999 } 1000 break; 1001 1002 case 's': /* octet string - in a buffer */ 1003 (void) va_arg( ap, char * ); 1004 (void) va_arg( ap, ber_len_t * ); 1005 break; 1006 1007 case 't': /* tag of next item */ 1008 case 'T': /* skip tag of next item */ 1009 (void) va_arg( ap, ber_tag_t * ); 1010 break; 1011 1012 case 'B': /* bit string - allocate storage as needed */ 1013 ss = va_arg( ap, char ** ); 1014 if ( *ss ) { 1015 LBER_FREE( *ss ); 1016 *ss = NULL; 1017 } 1018 *(va_arg( ap, ber_len_t * )) = 0; /* for length, in bits */ 1019 break; 1020 1021 case 'm': /* berval in-place */ 1022 case 'M': /* BVoff array in-place */ 1023 case 'n': /* null */ 1024 case 'v': /* sequence of strings */ 1025 case 'V': /* sequence of strings + lengths */ 1026 case 'W': /* BerVarray */ 1027 case 'x': /* skip the next element - whatever it is */ 1028 case '{': /* begin sequence */ 1029 case '[': /* begin set */ 1030 case '}': /* end sequence */ 1031 case ']': /* end set */ 1032 break; 1033 1034 default: 1035 /* format should be good */ 1036 assert( 0 ); 1037 } 1038 } 1039 1040 va_end( ap ); 1041 } 1042 1043 return rc; 1044 } 1045