No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / openldap / dist / libraries / liblber / decode.c
blob31652d2845f2c86ab8e9766c01aa0afd0d1521f9
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/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
6 * All rights reserved.
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.
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) 1990 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 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.
26 /* ACKNOWLEDGEMENTS:
27 * This work was originally developed by the University of Michigan
28 * (as part of U-MICH LDAP).
31 #include "portable.h"
33 #include <stdio.h>
35 #include <ac/stdlib.h>
37 #include <ac/stdarg.h>
38 #include <ac/string.h>
39 #include <ac/socket.h>
41 #include "lber-int.h"
43 static ber_len_t ber_getnint LDAP_P((
44 BerElement *ber,
45 ber_int_t *num,
46 ber_len_t len ));
48 /* out->bv_len should be the buffer size on input */
49 int
50 ber_decode_oid( BerValue *in, BerValue *out )
52 const unsigned char *der;
53 unsigned long val;
54 unsigned val1;
55 ber_len_t i;
56 char *ptr;
58 assert( in != NULL );
59 assert( out != NULL );
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;
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 );
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;
87 if ( ptr == NULL || val != 0 )
88 return -1;
90 out->bv_len = ptr - out->bv_val;
91 return 0;
94 /* return the tag - LBER_DEFAULT returned means trouble */
95 ber_tag_t
96 ber_get_tag( BerElement *ber )
98 unsigned char xbyte;
99 ber_tag_t tag;
100 unsigned int i;
102 assert( ber != NULL );
103 assert( LBER_VALID( ber ) );
105 if ( ber_pvt_ber_remaining( ber ) < 1 ) {
106 return LBER_DEFAULT;
109 if ( ber->ber_ptr == ber->ber_buf ) {
110 tag = *(unsigned char *)ber->ber_ptr;
111 } else {
112 tag = ber->ber_tag;
114 ber->ber_ptr++;
116 if ( (tag & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) {
117 return tag;
120 for ( i = 1; i < sizeof(ber_tag_t); i++ ) {
121 if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) {
122 return LBER_DEFAULT;
125 tag <<= 8;
126 tag |= 0x00ffUL & (ber_tag_t) xbyte;
128 if ( ! (xbyte & LBER_MORE_TAG_MASK) ) {
129 break;
133 /* tag too big! */
134 if ( i == sizeof(ber_tag_t) ) {
135 return LBER_DEFAULT;
138 return tag;
141 ber_tag_t
142 ber_skip_tag( BerElement *ber, ber_len_t *len )
144 ber_tag_t tag;
145 unsigned char lc;
146 ber_len_t i, noctets;
147 unsigned char netlen[sizeof(ber_len_t)];
149 assert( ber != NULL );
150 assert( len != NULL );
151 assert( LBER_VALID( ber ) );
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.
158 * Assumptions:
159 * 1) definite lengths
160 * 2) primitive encodings used whenever possible
163 *len = 0;
166 * First, we read the tag.
169 if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT ) {
170 return LBER_DEFAULT;
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.
180 if ( ber_read( ber, (char *) &lc, 1 ) != 1 ) {
181 return LBER_DEFAULT;
184 if ( lc & 0x80U ) {
185 noctets = (lc & 0x7fU);
187 if ( noctets > sizeof(ber_len_t) ) {
188 return LBER_DEFAULT;
191 if( (unsigned) ber_read( ber, (char *) netlen, noctets ) != noctets ) {
192 return LBER_DEFAULT;
195 for( i = 0; i < noctets; i++ ) {
196 *len <<= 8;
197 *len |= netlen[i];
200 } else {
201 *len = lc;
204 /* BER element should have enough data left */
205 if( *len > (ber_len_t) ber_pvt_ber_remaining( ber ) ) {
206 return LBER_DEFAULT;
208 ber->ber_tag = *(unsigned char *)ber->ber_ptr;
210 return tag;
213 ber_tag_t
214 ber_peek_tag(
215 BerElement *ber,
216 ber_len_t *len )
219 * This implementation assumes ber_skip_tag() only
220 * modifies ber_ptr field of the BerElement.
223 char *save;
224 ber_tag_t tag, old;
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;
232 return tag;
235 static ber_len_t
236 ber_getnint(
237 BerElement *ber,
238 ber_int_t *num,
239 ber_len_t len )
241 unsigned char buf[sizeof(ber_int_t)];
243 assert( ber != NULL );
244 assert( num != NULL );
245 assert( LBER_VALID( ber ) );
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.
254 if ( len > sizeof(ber_int_t) ) {
255 return -1;
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;
263 if( len ) {
264 /* sign extend if necessary */
265 ber_len_t i;
266 ber_int_t netnum = 0x80 & buf[0] ? -1 : 0;
268 /* shift in the bytes */
269 for( i=0 ; i<len; i++ ) {
270 netnum = (netnum << 8 ) | buf[i];
273 *num = netnum;
275 } else {
276 *num = 0;
278 ber->ber_tag = *(unsigned char *)ber->ber_ptr;
280 return len;
283 ber_tag_t
284 ber_get_int(
285 BerElement *ber,
286 ber_int_t *num )
288 ber_tag_t tag;
289 ber_len_t len;
291 assert( ber != NULL );
292 assert( LBER_VALID( ber ) );
294 if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) {
295 return LBER_DEFAULT;
298 if ( ber_getnint( ber, num, len ) != len ) {
299 return LBER_DEFAULT;
302 return tag;
305 ber_tag_t
306 ber_get_enum(
307 BerElement *ber,
308 ber_int_t *num )
310 return ber_get_int( ber, num );
313 ber_tag_t
314 ber_get_stringb(
315 BerElement *ber,
316 char *buf,
317 ber_len_t *len )
319 ber_len_t datalen;
320 ber_tag_t tag;
322 assert( ber != NULL );
323 assert( LBER_VALID( ber ) );
325 if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) {
326 return LBER_DEFAULT;
329 /* must fit within allocated space with termination */
330 if ( datalen >= *len ) {
331 return LBER_DEFAULT;
334 if ( (ber_len_t) ber_read( ber, buf, datalen ) != datalen ) {
335 return LBER_DEFAULT;
337 ber->ber_tag = *(unsigned char *)ber->ber_ptr;
339 buf[datalen] = '\0';
341 *len = datalen;
342 return tag;
345 /* Definitions for get_string vector
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.
351 enum bgbvc { ChArray, BvArray, BvVec, BvOff };
353 /* Use this single cookie for state, to keep actual
354 * stack use to the absolute minimum.
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;
369 static ber_tag_t
370 ber_get_stringbvl( bgbvr *b, ber_len_t *rlen )
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;
378 /* For rewinding, just like ber_peek_tag() */
379 orig = b->ber->ber_ptr;
380 tag = b->ber->ber_tag;
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;
390 if ( rlen ) *rlen = i;
392 if ( i == 0 ) {
393 *b->res.c = NULL;
394 return 0;
397 n = i;
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;
426 b->ber->ber_ptr = orig;
427 b->ber->ber_tag = tag;
428 ber_skip_tag( b->ber, &len );
430 for (n=0; n<i; n++)
432 tag = ber_next_element( b->ber, &len, last );
433 if ( ber_get_stringbv( b->ber, &bv, b->alloc ) == LBER_DEFAULT ) {
434 goto nomem;
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;
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;
459 return tag;
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;
480 LBER_FREE(*b->res.c);
481 *b->res.c = NULL;
482 return LBER_DEFAULT;
485 ber_tag_t
486 ber_get_stringbv( BerElement *ber, struct berval *bv, int option )
488 ber_tag_t tag;
490 assert( ber != NULL );
491 assert( bv != NULL );
493 assert( LBER_VALID( ber ) );
495 if ( (tag = ber_skip_tag( ber, &bv->bv_len )) == LBER_DEFAULT ) {
496 bv->bv_val = NULL;
497 return LBER_DEFAULT;
500 if ( (ber_len_t) ber_pvt_ber_remaining( ber ) < bv->bv_len ) {
501 return LBER_DEFAULT;
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;
511 if ( bv->bv_len > 0 && (ber_len_t) ber_read( ber, bv->bv_val,
512 bv->bv_len ) != bv->bv_len )
514 LBER_FREE( bv->bv_val );
515 bv->bv_val = NULL;
516 return LBER_DEFAULT;
518 } else {
519 bv->bv_val = ber->ber_ptr;
520 ber->ber_ptr += bv->bv_len;
522 ber->ber_tag = *(unsigned char *)ber->ber_ptr;
523 if ( !( option & LBER_BV_NOTERM ))
524 bv->bv_val[bv->bv_len] = '\0';
526 return tag;
529 ber_tag_t
530 ber_get_stringbv_null( BerElement *ber, struct berval *bv, int option )
532 ber_tag_t tag;
534 assert( ber != NULL );
535 assert( bv != NULL );
537 assert( LBER_VALID( ber ) );
539 if ( (tag = ber_skip_tag( ber, &bv->bv_len )) == LBER_DEFAULT ) {
540 bv->bv_val = NULL;
541 return LBER_DEFAULT;
544 if ( (ber_len_t) ber_pvt_ber_remaining( ber ) < bv->bv_len ) {
545 return LBER_DEFAULT;
548 if ( bv->bv_len == 0 ) {
549 bv->bv_val = NULL;
550 ber->ber_tag = *(unsigned char *)ber->ber_ptr;
551 return tag;
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;
561 if ( bv->bv_len > 0 && (ber_len_t) ber_read( ber, bv->bv_val,
562 bv->bv_len ) != bv->bv_len )
564 LBER_FREE( bv->bv_val );
565 bv->bv_val = NULL;
566 return LBER_DEFAULT;
568 } else {
569 bv->bv_val = ber->ber_ptr;
570 ber->ber_ptr += bv->bv_len;
572 ber->ber_tag = *(unsigned char *)ber->ber_ptr;
573 if ( !( option & LBER_BV_NOTERM ))
574 bv->bv_val[bv->bv_len] = '\0';
576 return tag;
579 ber_tag_t
580 ber_get_stringa( BerElement *ber, char **buf )
582 BerValue bv;
583 ber_tag_t tag;
585 assert( buf != NULL );
587 tag = ber_get_stringbv( ber, &bv, LBER_BV_ALLOC );
588 *buf = bv.bv_val;
590 return tag;
593 ber_tag_t
594 ber_get_stringa_null( BerElement *ber, char **buf )
596 BerValue bv;
597 ber_tag_t tag;
599 assert( buf != NULL );
601 tag = ber_get_stringbv_null( ber, &bv, LBER_BV_ALLOC );
602 *buf = bv.bv_val;
604 return tag;
607 ber_tag_t
608 ber_get_stringal( BerElement *ber, struct berval **bv )
610 ber_tag_t tag;
612 assert( ber != NULL );
613 assert( bv != NULL );
615 *bv = (struct berval *) ber_memalloc_x( sizeof(struct berval),
616 ber->ber_memctx );
617 if ( *bv == NULL ) {
618 return LBER_DEFAULT;
621 tag = ber_get_stringbv( ber, *bv, LBER_BV_ALLOC );
622 if ( tag == LBER_DEFAULT ) {
623 LBER_FREE( *bv );
624 *bv = NULL;
626 return tag;
629 ber_tag_t
630 ber_get_bitstringa(
631 BerElement *ber,
632 char **buf,
633 ber_len_t *blen )
635 ber_len_t datalen;
636 ber_tag_t tag;
637 unsigned char unusedbits;
639 assert( ber != NULL );
640 assert( buf != NULL );
641 assert( blen != NULL );
643 assert( LBER_VALID( ber ) );
645 if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) {
646 *buf = NULL;
647 return LBER_DEFAULT;
649 --datalen;
651 *buf = (char *) ber_memalloc_x( datalen, ber->ber_memctx );
652 if ( *buf == NULL ) {
653 return LBER_DEFAULT;
656 if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 ) {
657 LBER_FREE( buf );
658 *buf = NULL;
659 return LBER_DEFAULT;
662 if ( (ber_len_t) ber_read( ber, *buf, datalen ) != datalen ) {
663 LBER_FREE( buf );
664 *buf = NULL;
665 return LBER_DEFAULT;
667 ber->ber_tag = *(unsigned char *)ber->ber_ptr;
669 *blen = datalen * 8 - unusedbits;
670 return tag;
673 ber_tag_t
674 ber_get_null( BerElement *ber )
676 ber_len_t len;
677 ber_tag_t tag;
679 assert( ber != NULL );
680 assert( LBER_VALID( ber ) );
682 if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) {
683 return LBER_DEFAULT;
686 if ( len != 0 ) {
687 return LBER_DEFAULT;
689 ber->ber_tag = *(unsigned char *)ber->ber_ptr;
691 return( tag );
694 ber_tag_t
695 ber_get_boolean(
696 BerElement *ber,
697 ber_int_t *boolval )
699 ber_int_t longbool;
700 ber_tag_t rc;
702 assert( ber != NULL );
703 assert( boolval != NULL );
705 assert( LBER_VALID( ber ) );
707 rc = ber_get_int( ber, &longbool );
708 *boolval = longbool;
710 return rc;
713 ber_tag_t
714 ber_first_element(
715 BerElement *ber,
716 ber_len_t *len,
717 char **last )
719 assert( ber != NULL );
720 assert( len != NULL );
721 assert( last != NULL );
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;
728 ber->ber_tag = *(unsigned char *)ber->ber_ptr;
730 *last = ber->ber_ptr + *len;
732 if ( *last == ber->ber_ptr ) {
733 return LBER_DEFAULT;
736 return ber_peek_tag( ber, len );
739 ber_tag_t
740 ber_next_element(
741 BerElement *ber,
742 ber_len_t *len,
743 LDAP_CONST char *last )
745 assert( ber != NULL );
746 assert( len != NULL );
747 assert( last != NULL );
749 assert( LBER_VALID( ber ) );
751 if ( ber->ber_ptr >= last ) {
752 return LBER_DEFAULT;
755 return ber_peek_tag( ber, len );
758 /* VARARGS */
759 ber_tag_t
760 ber_scanf ( BerElement *ber,
761 LDAP_CONST char *fmt,
762 ... )
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;
774 va_start( ap, fmt );
776 assert( ber != NULL );
777 assert( fmt != NULL );
779 assert( LBER_VALID( ber ) );
781 fmt_reset = fmt;
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 );
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;
797 f = va_arg( ap, BERDecodeCallback * );
798 p = va_arg( ap, void * );
800 rc = (*f)( ber, p, 0 );
801 } break;
803 case 'a': /* octet string - allocate storage as needed */
804 ss = va_arg( ap, char ** );
805 rc = ber_get_stringa( ber, ss );
806 break;
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;
814 case 'b': /* boolean */
815 i = va_arg( ap, ber_int_t * );
816 rc = ber_get_boolean( ber, i );
817 break;
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;
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;
831 case 'l': /* length of next item */
832 l = va_arg( ap, ber_len_t * );
833 rc = ber_peek_tag( ber, l );
834 break;
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;
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.
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;
858 case 'n': /* null */
859 rc = ber_get_null( ber );
860 break;
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;
867 case 'O': /* octet string - allocate & include length */
868 bvp = va_arg( ap, struct berval ** );
869 rc = ber_get_stringal( ber, bvp );
870 break;
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;
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;
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;
888 case 'v': /* sequence of strings */
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;
898 case 'V': /* sequence of strings + lengths */
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;
908 case 'W': /* bvarray */
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;
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;
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;
932 case '}': /* end sequence */
933 case ']': /* end set */
934 break;
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 );
941 rc = LBER_DEFAULT;
942 break;
946 va_end( ap );
947 if ( rc == LBER_DEFAULT ) {
949 * Error. Reclaim malloced memory that was given to the caller.
950 * Set allocated pointers to NULL, "data length" outvalues to 0.
952 va_start( ap, fmt );
954 for ( ; fmt_reset < fmt; fmt_reset++ ) {
955 switch ( *fmt_reset ) {
956 case '!': { /* Hook */
957 BERDecodeCallback *f;
958 void *p;
960 f = va_arg( ap, BERDecodeCallback * );
961 p = va_arg( ap, void * );
963 (void) (*f)( ber, p, 1 );
964 } break;
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;
973 break;
975 case 'b': /* boolean */
976 case 'e': /* enumerated */
977 case 'i': /* int */
978 (void) va_arg( ap, int * );
979 break;
981 case 'l': /* length of next item */
982 (void) va_arg( ap, ber_len_t * );
983 break;
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;
991 bval->bv_len = 0;
992 break;
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;
1000 break;
1002 case 's': /* octet string - in a buffer */
1003 (void) va_arg( ap, char * );
1004 (void) va_arg( ap, ber_len_t * );
1005 break;
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;
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;
1018 *(va_arg( ap, ber_len_t * )) = 0; /* for length, in bits */
1019 break;
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;
1034 default:
1035 /* format should be good */
1036 assert( 0 );
1040 va_end( ap );
1043 return rc;