1 /* decode.c - ber input decoding routines */
3 * Copyright (c) 1990 Regents of the University of Michigan.
6 * Redistribution and use in source and binary forms are permitted
7 * provided that this notice is preserved and that due credit is given
8 * to the University of Michigan at Ann Arbor. The name of the University
9 * may not be used to endorse or promote products derived from this
10 * software without specific prior written permission. This software
11 * is provided ``as is'' without express or implied warranty.
25 #include <ac/string.h>
26 #include <ac/socket.h>
34 static int ber_getnint LDAP_P(( BerElement *ber, long *num, int len ));
36 /* return the tag - LBER_DEFAULT returned means trouble */
38 ber_get_tag( BerElement *ber )
45 if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
46 return( LBER_DEFAULT );
48 if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
49 return( (unsigned long) xbyte );
53 for ( i = 1; i < sizeof(long); i++ ) {
54 if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
55 return( LBER_DEFAULT );
59 if ( ! (xbyte & LBER_MORE_TAG_MASK) )
64 if ( i == sizeof(long) )
65 return( LBER_DEFAULT );
67 /* want leading, not trailing 0's */
68 return( tag >> (sizeof(long) - i - 1) );
72 ber_skip_tag( BerElement *ber, unsigned long *len )
80 * Any ber element looks like this: tag length contents.
81 * Assuming everything's ok, we return the tag byte (we
82 * can assume a single byte), and return the length in len.
86 * 2) primitive encodings used whenever possible
90 * First, we read the tag.
93 if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT )
94 return( LBER_DEFAULT );
97 * Next, read the length. The first byte contains the length of
98 * the length. If bit 8 is set, the length is the long form,
99 * otherwise it's the short form. We don't allow a length that's
100 * greater than what we can hold in an unsigned long.
104 if ( ber_read( ber, (char *) &lc, 1 ) != 1 )
105 return( LBER_DEFAULT );
107 noctets = (lc & 0x7f);
108 if ( noctets > sizeof(unsigned long) )
109 return( LBER_DEFAULT );
110 diff = sizeof(unsigned long) - noctets;
111 if ( ber_read( ber, (char *) &netlen + diff, noctets )
113 return( LBER_DEFAULT );
114 *len = AC_NTOHL( netlen );
123 ber_peek_tag( BerElement *ber, unsigned long *len )
129 tag = ber_skip_tag( ber, len );
136 ber_getnint( BerElement *ber, long *num, int len )
143 * The tag and length have already been stripped off. We should
144 * be sitting right before len bytes of 2's complement integer,
145 * ready to be read straight into an int. We may have to sign
146 * extend after we read it in.
149 if ( len > sizeof(long) )
153 diff = sizeof(long) - len;
154 /* read into the low-order bytes of netnum */
155 if ( ber_read( ber, ((char *) &netnum) + diff, len ) != len )
158 /* sign extend if necessary */
159 p = (char *) &netnum;
160 sign = (0x80 & *(p+diff) );
161 if ( sign && len < sizeof(long) ) {
162 for ( i = 0; i < diff; i++ ) {
163 *(p+i) = (char) 0xff;
166 *num = AC_NTOHL( netnum );
172 ber_get_int( BerElement *ber, long *num )
174 unsigned long tag, len;
176 if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
177 return( LBER_DEFAULT );
179 if ( (unsigned long) ber_getnint( ber, num, (int)len ) != len )
180 return( LBER_DEFAULT );
186 ber_get_stringb( BerElement *ber, char *buf, unsigned long *len )
188 unsigned long datalen, tag;
189 #ifdef STR_TRANSLATION
191 #endif /* STR_TRANSLATION */
193 if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
194 return( LBER_DEFAULT );
195 if ( datalen > (*len - 1) )
196 return( LBER_DEFAULT );
198 if ( (unsigned long) ber_read( ber, buf, datalen ) != datalen )
199 return( LBER_DEFAULT );
203 #ifdef STR_TRANSLATION
204 if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
205 && ber->ber_decode_translate_proc != NULL ) {
208 if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen,
210 return( LBER_DEFAULT );
212 if ( datalen > *len ) {
214 return( LBER_DEFAULT );
216 SAFEMEMCPY( buf, transbuf, datalen );
220 #endif /* STR_TRANSLATION */
227 ber_get_stringa( BerElement *ber, char **buf )
229 unsigned long datalen, tag;
231 if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
232 return( LBER_DEFAULT );
234 if ( (*buf = (char *) malloc( (size_t)datalen + 1 )) == NULL )
235 return( LBER_DEFAULT );
237 if ( (unsigned long) ber_read( ber, *buf, datalen ) != datalen )
238 return( LBER_DEFAULT );
239 (*buf)[datalen] = '\0';
241 #ifdef STR_TRANSLATION
242 if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
243 && ber->ber_decode_translate_proc != NULL ) {
245 if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 )
248 return( LBER_DEFAULT );
251 #endif /* STR_TRANSLATION */
257 ber_get_stringal( BerElement *ber, struct berval **bv )
259 unsigned long len, tag;
261 if ( (*bv = (struct berval *) malloc( sizeof(struct berval) )) == NULL )
262 return( LBER_DEFAULT );
264 if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
265 return( LBER_DEFAULT );
267 if ( ((*bv)->bv_val = (char *) malloc( (size_t)len + 1 )) == NULL )
268 return( LBER_DEFAULT );
270 if ( (unsigned long) ber_read( ber, (*bv)->bv_val, len ) != len )
271 return( LBER_DEFAULT );
272 ((*bv)->bv_val)[len] = '\0';
275 #ifdef STR_TRANSLATION
276 if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
277 && ber->ber_decode_translate_proc != NULL ) {
279 if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val),
281 free( (*bv)->bv_val );
282 return( LBER_DEFAULT );
284 (*bv)->bv_len = len - 1;
286 #endif /* STR_TRANSLATION */
292 ber_get_bitstringa( BerElement *ber, char **buf, unsigned long *blen )
294 unsigned long datalen, tag;
295 unsigned char unusedbits;
297 if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
298 return( LBER_DEFAULT );
301 if ( (*buf = (char *) malloc( (size_t)datalen )) == NULL )
302 return( LBER_DEFAULT );
304 if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 )
305 return( LBER_DEFAULT );
307 if ( (unsigned long) ber_read( ber, *buf, datalen ) != datalen )
308 return( LBER_DEFAULT );
310 *blen = datalen * 8 - unusedbits;
315 ber_get_null( BerElement *ber )
317 unsigned long len, tag;
319 if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
320 return( LBER_DEFAULT );
323 return( LBER_DEFAULT );
329 ber_get_boolean( BerElement *ber, int *boolval )
334 rc = ber_get_int( ber, &longbool );
341 ber_first_element( BerElement *ber, unsigned long *len, char **last )
343 /* skip the sequence header, use the len to mark where to stop */
344 if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) {
345 return( LBER_DEFAULT );
348 *last = ber->ber_ptr + *len;
350 if ( *last == ber->ber_ptr ) {
351 return( LBER_DEFAULT );
354 return( ber_peek_tag( ber, len ) );
358 ber_next_element( BerElement *ber, unsigned long *len, char *last )
360 if ( ber->ber_ptr == last ) {
361 return( LBER_DEFAULT );
364 return( ber_peek_tag( ber, len ) );
371 ( BerElement *ber, char *fmt, ... )
383 char *s, **ss, ***sss;
384 struct berval ***bv, **bvp, *bval;
393 ber = va_arg( ap, BerElement * );
394 fmt = va_arg( ap, char * );
398 if ( lber_debug & 64 ) {
399 fprintf( stderr, "ber_scanf fmt (%s) ber:\n", fmt );
404 for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) {
406 case 'a': /* octet string - allocate storage as needed */
407 ss = va_arg( ap, char ** );
408 rc = ber_get_stringa( ber, ss );
411 case 'b': /* boolean */
412 i = va_arg( ap, int * );
413 rc = ber_get_boolean( ber, i );
416 case 'e': /* enumerated */
418 l = va_arg( ap, long * );
419 rc = ber_get_int( ber, l );
422 case 'l': /* length of next item */
423 l = va_arg( ap, long * );
424 rc = ber_peek_tag( ber, (unsigned long *)l );
428 rc = ber_get_null( ber );
431 case 's': /* octet string - in a buffer */
432 s = va_arg( ap, char * );
433 l = va_arg( ap, long * );
434 rc = ber_get_stringb( ber, s, (unsigned long *)l );
437 case 'o': /* octet string in a supplied berval */
438 bval = va_arg( ap, struct berval * );
439 ber_peek_tag( ber, &bval->bv_len );
440 rc = ber_get_stringa( ber, &bval->bv_val );
443 case 'O': /* octet string - allocate & include length */
444 bvp = va_arg( ap, struct berval ** );
445 rc = ber_get_stringal( ber, bvp );
448 case 'B': /* bit string - allocate storage as needed */
449 ss = va_arg( ap, char ** );
450 l = va_arg( ap, long * ); /* for length, in bits */
451 rc = ber_get_bitstringa( ber, ss, (unsigned long *)l );
454 case 't': /* tag of next item */
455 i = va_arg( ap, int * );
456 *i = rc = ber_peek_tag( ber, &len );
459 case 'T': /* skip tag of next item */
460 i = va_arg( ap, int * );
461 *i = rc = ber_skip_tag( ber, &len );
464 case 'v': /* sequence of strings */
465 sss = va_arg( ap, char *** );
468 for ( tag = ber_first_element( ber, &len, &last );
469 tag != LBER_DEFAULT && rc != LBER_DEFAULT;
470 tag = ber_next_element( ber, &len, last ) ) {
471 if ( *sss == NULL ) {
472 *sss = (char **) malloc(
473 2 * sizeof(char *) );
475 *sss = (char **) realloc( *sss,
476 (j + 2) * sizeof(char *) );
478 rc = ber_get_stringa( ber, &((*sss)[j]) );
485 case 'V': /* sequence of strings + lengths */
486 bv = va_arg( ap, struct berval *** );
489 for ( tag = ber_first_element( ber, &len, &last );
490 tag != LBER_DEFAULT && rc != LBER_DEFAULT;
491 tag = ber_next_element( ber, &len, last ) ) {
493 *bv = (struct berval **) malloc(
494 2 * sizeof(struct berval *) );
496 *bv = (struct berval **) realloc( *bv,
497 (j + 2) * sizeof(struct berval *) );
499 rc = ber_get_stringal( ber, &((*bv)[j]) );
506 case 'x': /* skip the next element - whatever it is */
507 if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
512 case '{': /* begin sequence */
513 case '[': /* begin set */
514 if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V' )
515 rc = ber_skip_tag( ber, &len );
518 case '}': /* end sequence */
519 case ']': /* end set */
524 fprintf( stderr, "unknown fmt %c\n", *fmt );
525 #endif /* LDAP_LIBUI */
537 ber_bvfree( struct berval *bv )
539 if ( bv->bv_val != NULL )
545 ber_bvecfree( struct berval **bv )
549 for ( i = 0; bv[i] != NULL; i++ )
555 ber_bvdup( struct berval *bv )
559 if ( (new = (struct berval *) malloc( sizeof(struct berval) ))
563 if ( (new->bv_val = (char *) malloc( bv->bv_len + 1 )) == NULL ) {
566 SAFEMEMCPY( new->bv_val, bv->bv_val, (size_t) bv->bv_len );
567 new->bv_val[bv->bv_len] = '\0';
568 new->bv_len = bv->bv_len;
574 #ifdef STR_TRANSLATION
576 ber_set_string_translators( BerElement *ber, BERTranslateProc encode_proc,
577 BERTranslateProc decode_proc )
579 ber->ber_encode_translate_proc = encode_proc;
580 ber->ber_decode_translate_proc = decode_proc;
582 #endif /* STR_TRANSLATION */