]> git.sur5r.net Git - openldap/blob - libraries/liblber/decode.c
f6b32848a9963d051bc490a1c8224bb372fe01a8
[openldap] / libraries / liblber / decode.c
1 /* decode.c - ber input decoding routines */
2 /*
3  * Copyright (c) 1990 Regents of the University of Michigan.
4  * All rights reserved.
5  *
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.
12  */
13
14 #include "portable.h"
15
16 #include <stdio.h>
17 #include <stdlib.h>
18
19 #include <ac/stdarg.h>
20
21 #include <ac/string.h>
22 #include <ac/socket.h>
23
24 #include "lber-int.h"
25
26 static int ber_getnint LDAP_P(( BerElement *ber, long *num, int len ));
27
28 /* return the tag - LBER_DEFAULT returned means trouble */
29 unsigned long
30 ber_get_tag( BerElement *ber )
31 {
32         unsigned char   xbyte;
33         unsigned long   tag;
34         char            *tagp;
35         unsigned int    i;
36
37         if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
38                 return( LBER_DEFAULT );
39
40         if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
41                 return( (unsigned long) xbyte );
42
43         tagp = (char *) &tag;
44         tagp[0] = xbyte;
45         for ( i = 1; i < sizeof(long); i++ ) {
46                 if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
47                         return( LBER_DEFAULT );
48
49                 tagp[i] = xbyte;
50
51                 if ( ! (xbyte & LBER_MORE_TAG_MASK) )
52                         break;
53         }
54
55         /* tag too big! */
56         if ( i == sizeof(long) )
57                 return( LBER_DEFAULT );
58
59         /* want leading, not trailing 0's */
60         return( tag >> (sizeof(long) - i - 1) );
61 }
62
63 unsigned long
64 ber_skip_tag( BerElement *ber, unsigned long *len )
65 {
66         unsigned long   tag;
67         unsigned char   lc;
68         int             noctets, diff;
69         unsigned long   netlen;
70
71         /*
72          * Any ber element looks like this: tag length contents.
73          * Assuming everything's ok, we return the tag byte (we
74          * can assume a single byte), and return the length in len.
75          *
76          * Assumptions:
77          *      1) definite lengths
78          *      2) primitive encodings used whenever possible
79          */
80
81         /*
82          * First, we read the tag.
83          */
84
85         if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT )
86                 return( LBER_DEFAULT );
87
88         /*
89          * Next, read the length.  The first byte contains the length of
90          * the length.  If bit 8 is set, the length is the long form,
91          * otherwise it's the short form.  We don't allow a length that's
92          * greater than what we can hold in an unsigned long.
93          */
94
95         *len = netlen = 0;
96         if ( ber_read( ber, (char *) &lc, 1 ) != 1 )
97                 return( LBER_DEFAULT );
98         if ( lc & 0x80 ) {
99                 noctets = (lc & 0x7f);
100                 if ( noctets > sizeof(unsigned long) )
101                         return( LBER_DEFAULT );
102                 diff = sizeof(unsigned long) - noctets;
103                 if ( ber_read( ber, (char *) &netlen + diff, noctets )
104                     != noctets )
105                         return( LBER_DEFAULT );
106                 *len = AC_NTOHL( netlen );
107         } else {
108                 *len = lc;
109         }
110
111         return( tag );
112 }
113
114 unsigned long
115 ber_peek_tag( BerElement *ber, unsigned long *len )
116 {
117         char            *save;
118         unsigned long   tag;
119
120         save = ber->ber_ptr;
121         tag = ber_skip_tag( ber, len );
122         ber->ber_ptr = save;
123
124         return( tag );
125 }
126
127 static int
128 ber_getnint( BerElement *ber, long *num, int len )
129 {
130         int     diff, sign, i;
131         long    netnum;
132         char    *p;
133
134         /*
135          * The tag and length have already been stripped off.  We should
136          * be sitting right before len bytes of 2's complement integer,
137          * ready to be read straight into an int.  We may have to sign
138          * extend after we read it in.
139          */
140
141         if ( len > sizeof(long) )
142                 return( -1 );
143
144         netnum = 0;
145         diff = sizeof(long) - len;
146         /* read into the low-order bytes of netnum */
147         if ( ber_read( ber, ((char *) &netnum) + diff, len ) != len )
148                 return( -1 );
149
150         /* sign extend if necessary */
151         p = (char *) &netnum;
152         sign = (0x80 & *(p+diff) );
153         if ( sign && len < sizeof(long) ) {
154                 for ( i = 0; i < diff; i++ ) {
155                         *(p+i) = (unsigned char) 0xff;
156                 }
157         }
158         *num = AC_NTOHL( netnum );
159
160         return( len );
161 }
162
163 unsigned long
164 ber_get_int( BerElement *ber, long *num )
165 {
166         unsigned long   tag, len;
167
168         if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
169                 return( LBER_DEFAULT );
170
171         if ( (unsigned long) ber_getnint( ber, num, (int)len ) != len )
172                 return( LBER_DEFAULT );
173         else
174                 return( tag );
175 }
176
177 unsigned long
178 ber_get_stringb( BerElement *ber, char *buf, unsigned long *len )
179 {
180         unsigned long   datalen, tag;
181 #ifdef STR_TRANSLATION
182         char            *transbuf;
183 #endif /* STR_TRANSLATION */
184
185         if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
186                 return( LBER_DEFAULT );
187         if ( datalen > (*len - 1) )
188                 return( LBER_DEFAULT );
189
190         if ( (unsigned long) ber_read( ber, buf, datalen ) != datalen )
191                 return( LBER_DEFAULT );
192
193         buf[datalen] = '\0';
194
195 #ifdef STR_TRANSLATION
196         if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
197             && ber->ber_decode_translate_proc != NULL ) {
198                 transbuf = buf;
199                 ++datalen;
200                 if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen,
201                     0 ) != 0 ) {
202                         return( LBER_DEFAULT );
203                 }
204                 if ( datalen > *len ) {
205                         free( transbuf );
206                         return( LBER_DEFAULT );
207                 }
208                 SAFEMEMCPY( buf, transbuf, datalen );
209                 free( transbuf );
210                 --datalen;
211         }
212 #endif /* STR_TRANSLATION */
213
214         *len = datalen;
215         return( tag );
216 }
217
218 unsigned long
219 ber_get_stringa( BerElement *ber, char **buf )
220 {
221         unsigned long   datalen, tag;
222
223         if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) {
224                 *buf = NULL;
225                 return( LBER_DEFAULT );
226         }
227
228         if ( (*buf = (char *) malloc( (size_t)datalen + 1 )) == NULL )
229                 return( LBER_DEFAULT );
230
231         if ( (unsigned long) ber_read( ber, *buf, datalen ) != datalen ) {
232                 free( *buf );
233                 *buf = NULL;
234                 return( LBER_DEFAULT );
235         }
236         (*buf)[datalen] = '\0';
237
238 #ifdef STR_TRANSLATION
239         if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
240             && ber->ber_decode_translate_proc != NULL ) {
241                 ++datalen;
242                 if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 )
243                     != 0 ) {
244                         free( *buf );
245                         *buf = NULL;
246                         return( LBER_DEFAULT );
247                 }
248         }
249 #endif /* STR_TRANSLATION */
250
251         return( tag );
252 }
253
254 unsigned long
255 ber_get_stringal( BerElement *ber, struct berval **bv )
256 {
257         unsigned long   len, tag;
258
259         if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) {
260                 *bv = NULL;
261                 return( LBER_DEFAULT );
262         }
263
264         if ( (*bv = (struct berval *) malloc( sizeof(struct berval) )) == NULL )
265                 return( LBER_DEFAULT );
266
267         if ( ((*bv)->bv_val = (char *) malloc( (size_t)len + 1 )) == NULL ) {
268                 free( *bv );
269                 *bv = NULL;
270                 return( LBER_DEFAULT );
271         }
272
273         if ( (unsigned long) ber_read( ber, (*bv)->bv_val, len ) != len ) {
274                 ber_bvfree( *bv );
275                 *bv = NULL;
276                 return( LBER_DEFAULT );
277         }
278         ((*bv)->bv_val)[len] = '\0';
279         (*bv)->bv_len = len;
280
281 #ifdef STR_TRANSLATION
282         if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
283             && ber->ber_decode_translate_proc != NULL ) {
284                 ++len;
285                 if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val),
286                     &len, 1 ) != 0 ) {
287                         ber_bvfree( *bv );
288                         *bv = NULL;
289                         return( LBER_DEFAULT );
290                 }
291                 (*bv)->bv_len = len - 1;
292         }
293 #endif /* STR_TRANSLATION */
294
295         return( tag );
296 }
297
298 unsigned long
299 ber_get_bitstringa( BerElement *ber, char **buf, unsigned long *blen )
300 {
301         unsigned long   datalen, tag;
302         unsigned char   unusedbits;
303
304         if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) {
305                 *buf = NULL;
306                 return( LBER_DEFAULT );
307         }
308         --datalen;
309
310         if ( (*buf = (char *) malloc( (size_t)datalen )) == NULL )
311                 return( LBER_DEFAULT );
312
313         if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 ) {
314                 free( buf );
315                 *buf = NULL;
316                 return( LBER_DEFAULT );
317         }
318
319         if ( (unsigned long) ber_read( ber, *buf, datalen ) != datalen ) {
320                 free( buf );
321                 *buf = NULL;
322                 return( LBER_DEFAULT );
323         }
324
325         *blen = datalen * 8 - unusedbits;
326         return( tag );
327 }
328
329 unsigned long
330 ber_get_null( BerElement *ber )
331 {
332         unsigned long   len, tag;
333
334         if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
335                 return( LBER_DEFAULT );
336
337         if ( len != 0 )
338                 return( LBER_DEFAULT );
339
340         return( tag );
341 }
342
343 unsigned long
344 ber_get_boolean( BerElement *ber, int *boolval )
345 {
346         long    longbool;
347         int     rc;
348
349         rc = ber_get_int( ber, &longbool );
350         *boolval = longbool;
351
352         return( rc );
353 }
354
355 unsigned long
356 ber_first_element( BerElement *ber, unsigned long *len, char **last )
357 {
358         /* skip the sequence header, use the len to mark where to stop */
359         if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) {
360                 *last = NULL;
361                 return( LBER_DEFAULT );
362         }
363
364         *last = ber->ber_ptr + *len;
365
366         if ( *last == ber->ber_ptr ) {
367 #ifdef LBER_END_SEQORSET 
368                 return( LBER_END_SEQORSET );
369 #else
370                 return( LBER_DEFAULT );
371 #endif
372         }
373
374         return( ber_peek_tag( ber, len ) );
375 }
376
377 unsigned long
378 ber_next_element( BerElement *ber, unsigned long *len, char *last )
379 {
380         if ( ber->ber_ptr == last ) {
381 #ifdef LBER_END_SEQORSET 
382                 return( LBER_END_SEQORSET );
383 #else
384                 return( LBER_DEFAULT );
385 #endif
386         }
387
388         return( ber_peek_tag( ber, len ) );
389 }
390
391 /* VARARGS */
392 unsigned long
393 ber_scanf
394 #if HAVE_STDARG
395         ( BerElement *ber, char *fmt, ... )
396 #else
397         ( va_alist )
398 va_dcl
399 #endif
400 {
401         va_list         ap;
402 #ifndef HAVE_STDARG
403         BerElement      *ber;
404         char            *fmt;
405 #endif
406         char            *fmt_reset;
407         char            *last;
408         char            *s, **ss, ***sss;
409         struct berval   ***bv, **bvp, *bval;
410         int             *i, j;
411         long            *l;
412         unsigned long   rc, tag, len;
413
414 #ifdef HAVE_STDARG
415         va_start( ap, fmt );
416 #else
417         va_start( ap );
418         ber = va_arg( ap, BerElement * );
419         fmt = va_arg( ap, char * );
420 #endif
421         fmt_reset = fmt;
422
423         if ( ber->ber_debug ) {
424                 lber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
425                         "ber_scanf fmt (%s) ber:\n", fmt );
426                 lber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 );
427         }
428
429         for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) {
430                 /* When this is modified, remember to update
431                  * the error-cleanup code below accordingly. */
432                 switch ( *fmt ) {
433                 case 'a':       /* octet string - allocate storage as needed */
434                         ss = va_arg( ap, char ** );
435                         rc = ber_get_stringa( ber, ss );
436                         break;
437
438                 case 'b':       /* boolean */
439                         i = va_arg( ap, int * );
440                         rc = ber_get_boolean( ber, i );
441                         break;
442
443                 case 'e':       /* enumerated */
444                 case 'i':       /* int */
445                         l = va_arg( ap, long * );
446                         rc = ber_get_int( ber, l );
447                         break;
448
449                 case 'l':       /* length of next item */
450                         l = va_arg( ap, long * );
451                         rc = ber_peek_tag( ber, (unsigned long *)l );
452                         break;
453
454                 case 'n':       /* null */
455                         rc = ber_get_null( ber );
456                         break;
457
458                 case 's':       /* octet string - in a buffer */
459                         s = va_arg( ap, char * );
460                         l = va_arg( ap, long * );
461                         rc = ber_get_stringb( ber, s, (unsigned long *)l );
462                         break;
463
464                 case 'o':       /* octet string in a supplied berval */
465                         bval = va_arg( ap, struct berval * );
466                         ber_peek_tag( ber, &bval->bv_len );
467                         rc = ber_get_stringa( ber, &bval->bv_val );
468                         break;
469
470                 case 'O':       /* octet string - allocate & include length */
471                         bvp = va_arg( ap, struct berval ** );
472                         rc = ber_get_stringal( ber, bvp );
473                         break;
474
475                 case 'B':       /* bit string - allocate storage as needed */
476                         ss = va_arg( ap, char ** );
477                         l = va_arg( ap, long * ); /* for length, in bits */
478                         rc = ber_get_bitstringa( ber, ss, (unsigned long *)l );
479                         break;
480
481                 case 't':       /* tag of next item */
482                         i = va_arg( ap, int * );
483                         *i = rc = ber_peek_tag( ber, &len );
484                         break;
485
486                 case 'T':       /* skip tag of next item */
487                         i = va_arg( ap, int * );
488                         *i = rc = ber_skip_tag( ber, &len );
489                         break;
490
491                 case 'v':       /* sequence of strings */
492                         sss = va_arg( ap, char *** );
493                         *sss = NULL;
494                         j = 0;
495                         for ( tag = ber_first_element( ber, &len, &last );
496                             tag != LBER_DEFAULT && 
497 #ifdef LDAP_END_SEQORSET
498                                         tag != LBER_END_SEQORSET &&
499 #endif
500                                         rc != LBER_DEFAULT;
501                             tag = ber_next_element( ber, &len, last ) )
502                         {
503                                 if ( *sss == NULL ) {
504                                         *sss = (char **) malloc(
505                                             2 * sizeof(char *) );
506                                 } else {
507                                         *sss = (char **) realloc( *sss,
508                                             (j + 2) * sizeof(char *) );
509                                 }
510                                 rc = ber_get_stringa( ber, &((*sss)[j]) );
511                                 j++;
512                         }
513 #ifdef LDAP_END_SEQORSET
514                         if (rc != LBER_DEFAULT && 
515                                 tag != LBER_END_SEQORSET )
516                         {
517                                 rc = LBER_DEFAULT;
518                         }
519 #endif
520                         if ( j > 0 )
521                                 (*sss)[j] = NULL;
522                         break;
523
524                 case 'V':       /* sequence of strings + lengths */
525                         bv = va_arg( ap, struct berval *** );
526                         *bv = NULL;
527                         j = 0;
528                         for ( tag = ber_first_element( ber, &len, &last );
529                             tag != LBER_DEFAULT && 
530 #ifdef LDAP_END_SEQORSET
531                                         tag != LBER_END_SEQORSET &&
532 #endif
533                                         rc != LBER_DEFAULT;
534                             tag = ber_next_element( ber, &len, last ) )
535                         {
536                                 if ( *bv == NULL ) {
537                                         *bv = (struct berval **) malloc(
538                                             2 * sizeof(struct berval *) );
539                                 } else {
540                                         *bv = (struct berval **) realloc( *bv,
541                                             (j + 2) * sizeof(struct berval *) );
542                                 }
543                                 rc = ber_get_stringal( ber, &((*bv)[j]) );
544                                 j++;
545                         }
546 #ifdef LDAP_END_SEQORSET
547                         if (rc != LBER_DEFAULT && 
548                                 tag != LBER_END_SEQORSET )
549                         {
550                                 rc = LBER_DEFAULT;
551                         }
552 #endif
553                         if ( j > 0 )
554                                 (*bv)[j] = NULL;
555                         break;
556
557                 case 'x':       /* skip the next element - whatever it is */
558                         if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
559                                 break;
560                         ber->ber_ptr += len;
561                         break;
562
563                 case '{':       /* begin sequence */
564                 case '[':       /* begin set */
565                         if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V' )
566                                 rc = ber_skip_tag( ber, &len );
567                         break;
568
569                 case '}':       /* end sequence */
570                 case ']':       /* end set */
571                         break;
572
573                 default:
574                         if( ber->ber_debug ) {
575                                 lber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug,
576                                         "ber_scanf: unknown fmt %c\n", *fmt );
577                         }
578                         rc = LBER_DEFAULT;
579                         break;
580                 }
581         }
582
583         va_end( ap );
584
585         if ( rc == LBER_DEFAULT ) {
586             /*
587              * Error.  Reclaim malloced memory that was given to the caller.
588              * Set allocated pointers to NULL, "data length" outvalues to 0.
589              */
590 #ifdef HAVE_STDARG
591             va_start( ap, fmt );
592 #else
593             va_start( ap );
594             (void) va_arg( ap, BerElement * );
595             (void) va_arg( ap, char * );
596 #endif
597
598             for ( ; fmt_reset < fmt; fmt_reset++ ) {
599                 switch ( *fmt_reset ) {
600                 case 'a':       /* octet string - allocate storage as needed */
601                         ss = va_arg( ap, char ** );
602                         if ( *ss ) {
603                                 free( *ss );
604                                 *ss = NULL;
605                         }
606                         break;
607
608                 case 'b':       /* boolean */
609                 case 't':       /* tag of next item */
610                 case 'T':       /* skip tag of next item */
611                         (void) va_arg( ap, int * );
612                         break;
613
614                 case 's':       /* octet string - in a buffer */
615                         (void) va_arg( ap, char * );
616                         /* Fall through */
617                 case 'e':       /* enumerated */
618                 case 'i':       /* int */
619                 case 'l':       /* length of next item */
620                         (void) va_arg( ap, long * );
621                         break;
622
623                 case 'o':       /* octet string in a supplied berval */
624                         bval = va_arg( ap, struct berval * );
625                         if ( bval->bv_val ) {
626                                 free( bval->bv_val );
627                                 bval->bv_val = NULL;
628                         }
629                         bval->bv_len = 0;
630                         break;
631
632                 case 'O':       /* octet string - allocate & include length */
633                         bvp = va_arg( ap, struct berval ** );
634                         if ( *bvp ) {
635                                 ber_bvfree( *bvp );
636                                 *bvp = NULL;
637                         }
638                         break;
639
640                 case 'B':       /* bit string - allocate storage as needed */
641                         ss = va_arg( ap, char ** );
642                         if ( *ss ) {
643                                 free( *ss );
644                                 *ss = NULL;
645                         }
646                         *(va_arg( ap, long * )) = 0; /* for length, in bits */
647                         break;
648
649                 case 'v':       /* sequence of strings */
650                         sss = va_arg( ap, char *** );
651                         if ( *sss ) {
652                                 for (j = 0;  (*sss)[j];  j++)
653                                         free( (*sss)[j] );
654                                 free( *sss );
655                                 *sss = NULL;
656                         }
657                         break;
658
659                 case 'V':       /* sequence of strings + lengths */
660                         bv = va_arg( ap, struct berval *** );
661                         if ( *bv ) {
662                                 ber_bvecfree( *bv );
663                                 *bv = NULL;
664                         }
665                         break;
666
667 #if 0           /* No action for these format characters */
668                 case 'n':       /* null */
669                 case 'x':       /* skip the next element - whatever it is */
670                 case '{':       /* begin sequence */
671                 case '[':       /* begin set */
672                 case '}':       /* end sequence */
673                 case ']':       /* end set */
674 #endif
675
676                 }
677             }
678
679             va_end( ap );
680         }
681
682         return( rc );
683 }
684
685 void
686 ber_bvfree( struct berval *bv )
687 {
688 #ifdef LBER_ASSERT
689         assert(bv != NULL);                     /* bv damn better point to something */
690 #endif
691         if ( bv->bv_val != NULL )
692                 free( bv->bv_val );
693         free( (char *) bv );
694 }
695
696 void
697 ber_bvecfree( struct berval **bv )
698 {
699         int     i;
700
701 #ifdef LBER_ASSERT
702         assert(bv != NULL);                     /* bv damn better point to something */
703 #endif
704         for ( i = 0; bv[i] != NULL; i++ )
705                 ber_bvfree( bv[i] );
706         free( (char *) bv );
707 }
708
709 struct berval *
710 ber_bvdup( struct berval *bv )
711 {
712         struct berval   *new;
713
714         if ( (new = (struct berval *) malloc( sizeof(struct berval) ))
715             == NULL ) {
716                 return( NULL );
717         }
718
719         if ( bv->bv_val == NULL ) {
720                 new->bv_val = NULL;
721                 new->bv_len = 0;
722                 return ( new );
723         }
724
725         if ( (new->bv_val = (char *) malloc( bv->bv_len + 1 )) == NULL ) {
726                 free( new );
727                 return( NULL );
728         }
729
730         SAFEMEMCPY( new->bv_val, bv->bv_val, (size_t) bv->bv_len );
731         new->bv_val[bv->bv_len] = '\0';
732         new->bv_len = bv->bv_len;
733
734         return( new );
735 }
736
737
738 #ifdef STR_TRANSLATION
739 void
740 ber_set_string_translators( BerElement *ber, BERTranslateProc encode_proc,
741         BERTranslateProc decode_proc )
742 {
743     ber->ber_encode_translate_proc = encode_proc;
744     ber->ber_decode_translate_proc = decode_proc;
745 }
746 #endif /* STR_TRANSLATION */