]> git.sur5r.net Git - openldap/blob - libraries/liblber/decode.c
6a198599c630d4ede7b25c6df27da588a157d649
[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 #define DISABLE_BRIDGE /* disable LDAP_BRIDGE code */
15 #include "portable.h"
16
17 #include <stdio.h>
18
19 #ifdef MACOS
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include "macos.h"
23 #else /* MACOS */
24
25 #if defined(NeXT) || defined(VMS) || defined(__FreeBSD__)
26 #include <stdlib.h>
27 #else /* next || vms || freebsd */
28 #include <malloc.h>
29 #endif /* next || vms || freebsd */
30 #if defined(BC31) || defined(_WIN32)
31 #include <stdarg.h>
32 #else /* BC31 || _WIN32 */
33 #include <varargs.h>
34 #endif /* BC31 || _WIN32 */
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #ifdef PCNFS
39 #include <tklib.h>
40 #endif /* PCNFS */
41 #endif /* MACOS */
42
43 #if defined( DOS ) || defined( _WIN32 )
44 #include "msdos.h"
45 #endif /* DOS */
46
47 #include <string.h>
48
49 #include "lber.h"
50
51 #ifdef LDAP_DEBUG
52 int     lber_debug;
53 #endif
54
55 static int ber_getnint LDAP_P(( BerElement *ber, long *num, int len ));
56
57 /* return the tag - LBER_DEFAULT returned means trouble */
58 unsigned long
59 ber_get_tag( BerElement *ber )
60 {
61         unsigned char   xbyte;
62         unsigned long   tag;
63         char            *tagp;
64         int             i;
65
66         if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
67                 return( LBER_DEFAULT );
68
69         if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
70                 return( (unsigned long) xbyte );
71
72         tagp = (char *) &tag;
73         tagp[0] = xbyte;
74         for ( i = 1; i < sizeof(long); i++ ) {
75                 if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
76                         return( LBER_DEFAULT );
77
78                 tagp[i] = xbyte;
79
80                 if ( ! (xbyte & LBER_MORE_TAG_MASK) )
81                         break;
82         }
83
84         /* tag too big! */
85         if ( i == sizeof(long) )
86                 return( LBER_DEFAULT );
87
88         /* want leading, not trailing 0's */
89         return( tag >> (sizeof(long) - i - 1) );
90 }
91
92 unsigned long
93 ber_skip_tag( BerElement *ber, unsigned long *len )
94 {
95         unsigned long   tag;
96         unsigned char   lc;
97         int             noctets, diff;
98         unsigned long   netlen;
99
100         /*
101          * Any ber element looks like this: tag length contents.
102          * Assuming everything's ok, we return the tag byte (we
103          * can assume a single byte), and return the length in len.
104          *
105          * Assumptions:
106          *      1) definite lengths
107          *      2) primitive encodings used whenever possible
108          */
109
110         /*
111          * First, we read the tag.
112          */
113
114         if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT )
115                 return( LBER_DEFAULT );
116
117         /*
118          * Next, read the length.  The first byte contains the length of
119          * the length.  If bit 8 is set, the length is the long form,
120          * otherwise it's the short form.  We don't allow a length that's
121          * greater than what we can hold in an unsigned long.
122          */
123
124         *len = netlen = 0;
125         if ( ber_read( ber, (char *) &lc, 1 ) != 1 )
126                 return( LBER_DEFAULT );
127         if ( lc & 0x80 ) {
128                 noctets = (lc & 0x7f);
129                 if ( noctets > sizeof(unsigned long) )
130                         return( LBER_DEFAULT );
131                 diff = sizeof(unsigned long) - noctets;
132                 if ( ber_read( ber, (char *) &netlen + diff, noctets )
133                     != noctets )
134                         return( LBER_DEFAULT );
135                 *len = LBER_NTOHL( netlen );
136         } else {
137                 *len = lc;
138         }
139
140         return( tag );
141 }
142
143 unsigned long
144 ber_peek_tag( BerElement *ber, unsigned long *len )
145 {
146         char            *save;
147         unsigned long   tag;
148
149         save = ber->ber_ptr;
150         tag = ber_skip_tag( ber, len );
151         ber->ber_ptr = save;
152
153         return( tag );
154 }
155
156 static int
157 ber_getnint( BerElement *ber, long *num, int len )
158 {
159         int     diff, sign, i;
160         long    netnum;
161         char    *p;
162
163         /*
164          * The tag and length have already been stripped off.  We should
165          * be sitting right before len bytes of 2's complement integer,
166          * ready to be read straight into an int.  We may have to sign
167          * extend after we read it in.
168          */
169
170         if ( len > sizeof(long) )
171                 return( -1 );
172
173         netnum = 0;
174         diff = sizeof(long) - len;
175         /* read into the low-order bytes of netnum */
176         if ( ber_read( ber, ((char *) &netnum) + diff, len ) != len )
177                 return( -1 );
178
179         /* sign extend if necessary */
180         p = (char *) &netnum;
181         sign = (0x80 & *(p+diff) );
182         if ( sign && len < sizeof(long) ) {
183                 for ( i = 0; i < diff; i++ ) {
184                         *(p+i) = 0xff;
185                 }
186         }
187         *num = LBER_NTOHL( netnum );
188
189         return( len );
190 }
191
192 unsigned long
193 ber_get_int( BerElement *ber, long *num )
194 {
195         unsigned long   tag, len;
196
197         if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
198                 return( LBER_DEFAULT );
199
200         if ( ber_getnint( ber, num, (int)len ) != len )
201                 return( LBER_DEFAULT );
202         else
203                 return( tag );
204 }
205
206 unsigned long
207 ber_get_stringb( BerElement *ber, char *buf, unsigned long *len )
208 {
209         unsigned long   datalen, tag;
210 #ifdef STR_TRANSLATION
211         char            *transbuf;
212 #endif /* STR_TRANSLATION */
213
214         if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
215                 return( LBER_DEFAULT );
216         if ( datalen > (*len - 1) )
217                 return( LBER_DEFAULT );
218
219         if ( ber_read( ber, buf, datalen ) != datalen )
220                 return( LBER_DEFAULT );
221
222         buf[datalen] = '\0';
223
224 #ifdef STR_TRANSLATION
225         if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
226             && ber->ber_decode_translate_proc != NULL ) {
227                 transbuf = buf;
228                 ++datalen;
229                 if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen,
230                     0 ) != 0 ) {
231                         return( LBER_DEFAULT );
232                 }
233                 if ( datalen > *len ) {
234                         free( transbuf );
235                         return( LBER_DEFAULT );
236                 }
237                 SAFEMEMCPY( buf, transbuf, datalen );
238                 free( transbuf );
239                 --datalen;
240         }
241 #endif /* STR_TRANSLATION */
242
243         *len = datalen;
244         return( tag );
245 }
246
247 unsigned long
248 ber_get_stringa( BerElement *ber, char **buf )
249 {
250         unsigned long   datalen, tag;
251
252         if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
253                 return( LBER_DEFAULT );
254
255         if ( (*buf = (char *) malloc( (size_t)datalen + 1 )) == NULL )
256                 return( LBER_DEFAULT );
257
258         if ( ber_read( ber, *buf, datalen ) != datalen )
259                 return( LBER_DEFAULT );
260         (*buf)[datalen] = '\0';
261
262 #ifdef STR_TRANSLATION
263         if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
264             && ber->ber_decode_translate_proc != NULL ) {
265                 ++datalen;
266                 if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 )
267                     != 0 ) {
268                         free( *buf );
269                         return( LBER_DEFAULT );
270                 }
271         }
272 #endif /* STR_TRANSLATION */
273
274         return( tag );
275 }
276
277 unsigned long
278 ber_get_stringal( BerElement *ber, struct berval **bv )
279 {
280         unsigned long   len, tag;
281
282         if ( (*bv = (struct berval *) malloc( sizeof(struct berval) )) == NULL )
283                 return( LBER_DEFAULT );
284
285         if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
286                 return( LBER_DEFAULT );
287
288         if ( ((*bv)->bv_val = (char *) malloc( (size_t)len + 1 )) == NULL )
289                 return( LBER_DEFAULT );
290
291         if ( ber_read( ber, (*bv)->bv_val, len ) != len )
292                 return( LBER_DEFAULT );
293         ((*bv)->bv_val)[len] = '\0';
294         (*bv)->bv_len = len;
295
296 #ifdef STR_TRANSLATION
297         if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
298             && ber->ber_decode_translate_proc != NULL ) {
299                 ++len;
300                 if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val),
301                     &len, 1 ) != 0 ) {
302                         free( (*bv)->bv_val );
303                         return( LBER_DEFAULT );
304                 }
305                 (*bv)->bv_len = len - 1;
306         }
307 #endif /* STR_TRANSLATION */
308
309         return( tag );
310 }
311
312 unsigned long
313 ber_get_bitstringa( BerElement *ber, char **buf, unsigned long *blen )
314 {
315         unsigned long   datalen, tag;
316         unsigned char   unusedbits;
317
318         if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
319                 return( LBER_DEFAULT );
320         --datalen;
321
322         if ( (*buf = (char *) malloc( (size_t)datalen )) == NULL )
323                 return( LBER_DEFAULT );
324
325         if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 )
326                 return( LBER_DEFAULT );
327
328         if ( ber_read( ber, *buf, datalen ) != datalen )
329                 return( LBER_DEFAULT );
330
331         *blen = datalen * 8 - unusedbits;
332         return( tag );
333 }
334
335 unsigned long
336 ber_get_null( BerElement *ber )
337 {
338         unsigned long   len, tag;
339
340         if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
341                 return( LBER_DEFAULT );
342
343         if ( len != 0 )
344                 return( LBER_DEFAULT );
345
346         return( tag );
347 }
348
349 unsigned long
350 ber_get_boolean( BerElement *ber, int *boolval )
351 {
352         long    longbool;
353         int     rc;
354
355         rc = ber_get_int( ber, &longbool );
356         *boolval = longbool;
357
358         return( rc );
359 }
360
361 unsigned long
362 ber_first_element( BerElement *ber, unsigned long *len, char **last )
363 {
364         /* skip the sequence header, use the len to mark where to stop */
365         if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) {
366                 return( LBER_DEFAULT );
367         }
368
369         *last = ber->ber_ptr + *len;
370
371         if ( *last == ber->ber_ptr ) {
372                 return( LBER_DEFAULT );
373         }
374
375         return( ber_peek_tag( ber, len ) );
376 }
377
378 unsigned long
379 ber_next_element( BerElement *ber, unsigned long *len, char *last )
380 {
381         if ( ber->ber_ptr == last ) {
382                 return( LBER_DEFAULT );
383         }
384
385         return( ber_peek_tag( ber, len ) );
386 }
387
388 /* VARARGS */
389 unsigned long
390 ber_scanf(
391 #if defined( MACOS ) || defined( BC31 ) || defined( _WIN32 )
392         BerElement *ber, char *fmt, ... )
393 #else
394         va_alist )
395 va_dcl
396 #endif
397 {
398         va_list         ap;
399 #if !defined( MACOS ) && !defined( BC31 ) && !defined( _WIN32 )
400         BerElement      *ber;
401         char            *fmt;
402 #endif
403         char            *last;
404         char            *s, **ss, ***sss;
405         struct berval   ***bv, **bvp, *bval;
406         int             *i, j;
407         long            *l, rc, tag;
408         unsigned long   len;
409
410 #if defined( MACOS ) || defined( BC31 ) || defined( _WIN32 )
411         va_start( ap, fmt );
412 #else
413         va_start( ap );
414         ber = va_arg( ap, BerElement * );
415         fmt = va_arg( ap, char * );
416 #endif
417
418 #ifdef LDAP_DEBUG
419         if ( lber_debug & 64 ) {
420                 fprintf( stderr, "ber_scanf fmt (%s) ber:\n", fmt );
421                 ber_dump( ber, 1 );
422         }
423 #endif
424
425         for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) {
426                 switch ( *fmt ) {
427                 case 'a':       /* octet string - allocate storage as needed */
428                         ss = va_arg( ap, char ** );
429                         rc = ber_get_stringa( ber, ss );
430                         break;
431
432                 case 'b':       /* boolean */
433                         i = va_arg( ap, int * );
434                         rc = ber_get_boolean( ber, i );
435                         break;
436
437                 case 'e':       /* enumerated */
438                 case 'i':       /* int */
439                         l = va_arg( ap, long * );
440                         rc = ber_get_int( ber, l );
441                         break;
442
443                 case 'l':       /* length of next item */
444                         l = va_arg( ap, long * );
445                         rc = ber_peek_tag( ber, (unsigned long *)l );
446                         break;
447
448                 case 'n':       /* null */
449                         rc = ber_get_null( ber );
450                         break;
451
452                 case 's':       /* octet string - in a buffer */
453                         s = va_arg( ap, char * );
454                         l = va_arg( ap, long * );
455                         rc = ber_get_stringb( ber, s, (unsigned long *)l );
456                         break;
457
458                 case 'o':       /* octet string in a supplied berval */
459                         bval = va_arg( ap, struct berval * );
460                         ber_peek_tag( ber, &bval->bv_len );
461                         rc = ber_get_stringa( ber, &bval->bv_val );
462                         break;
463
464                 case 'O':       /* octet string - allocate & include length */
465                         bvp = va_arg( ap, struct berval ** );
466                         rc = ber_get_stringal( ber, bvp );
467                         break;
468
469                 case 'B':       /* bit string - allocate storage as needed */
470                         ss = va_arg( ap, char ** );
471                         l = va_arg( ap, long * ); /* for length, in bits */
472                         rc = ber_get_bitstringa( ber, ss, (unsigned long *)l );
473                         break;
474
475                 case 't':       /* tag of next item */
476                         i = va_arg( ap, int * );
477                         *i = rc = ber_peek_tag( ber, &len );
478                         break;
479
480                 case 'T':       /* skip tag of next item */
481                         i = va_arg( ap, int * );
482                         *i = rc = ber_skip_tag( ber, &len );
483                         break;
484
485                 case 'v':       /* sequence of strings */
486                         sss = va_arg( ap, char *** );
487                         *sss = NULL;
488                         j = 0;
489                         for ( tag = ber_first_element( ber, &len, &last );
490                             tag != LBER_DEFAULT && rc != LBER_DEFAULT;
491                             tag = ber_next_element( ber, &len, last ) ) {
492                                 if ( *sss == NULL ) {
493                                         *sss = (char **) malloc(
494                                             2 * sizeof(char *) );
495                                 } else {
496                                         *sss = (char **) realloc( *sss,
497                                             (j + 2) * sizeof(char *) );
498                                 }
499                                 rc = ber_get_stringa( ber, &((*sss)[j]) );
500                                 j++;
501                         }
502                         if ( j > 0 )
503                                 (*sss)[j] = NULL;
504                         break;
505
506                 case 'V':       /* sequence of strings + lengths */
507                         bv = va_arg( ap, struct berval *** );
508                         *bv = NULL;
509                         j = 0;
510                         for ( tag = ber_first_element( ber, &len, &last );
511                             tag != LBER_DEFAULT && rc != LBER_DEFAULT;
512                             tag = ber_next_element( ber, &len, last ) ) {
513                                 if ( *bv == NULL ) {
514                                         *bv = (struct berval **) malloc(
515                                             2 * sizeof(struct berval *) );
516                                 } else {
517                                         *bv = (struct berval **) realloc( *bv,
518                                             (j + 2) * sizeof(struct berval *) );
519                                 }
520                                 rc = ber_get_stringal( ber, &((*bv)[j]) );
521                                 j++;
522                         }
523                         if ( j > 0 )
524                                 (*bv)[j] = NULL;
525                         break;
526
527                 case 'x':       /* skip the next element - whatever it is */
528                         if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
529                                 break;
530                         ber->ber_ptr += len;
531                         break;
532
533                 case '{':       /* begin sequence */
534                 case '[':       /* begin set */
535                         if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V' )
536                                 rc = ber_skip_tag( ber, &len );
537                         break;
538
539                 case '}':       /* end sequence */
540                 case ']':       /* end set */
541                         break;
542
543                 default:
544 #ifndef NO_USERINTERFACE
545                         fprintf( stderr, "unknown fmt %c\n", *fmt );
546 #endif /* NO_USERINTERFACE */
547                         rc = LBER_DEFAULT;
548                         break;
549                 }
550         }
551
552         va_end( ap );
553
554         return( rc );
555 }
556
557 void
558 ber_bvfree( struct berval *bv )
559 {
560         if ( bv->bv_val != NULL )
561                 free( bv->bv_val );
562         free( (char *) bv );
563 }
564
565 void
566 ber_bvecfree( struct berval **bv )
567 {
568         int     i;
569
570         for ( i = 0; bv[i] != NULL; i++ )
571                 ber_bvfree( bv[i] );
572         free( (char *) bv );
573 }
574
575 struct berval *
576 ber_bvdup( struct berval *bv )
577 {
578         struct berval   *new;
579
580         if ( (new = (struct berval *) malloc( sizeof(struct berval) ))
581             == NULL ) {
582                 return( NULL );
583         }
584         if ( (new->bv_val = (char *) malloc( bv->bv_len + 1 )) == NULL ) {
585                 return( NULL );
586         }
587         SAFEMEMCPY( new->bv_val, bv->bv_val, (size_t) bv->bv_len );
588         new->bv_val[bv->bv_len] = '\0';
589         new->bv_len = bv->bv_len;
590
591         return( new );
592 }
593
594
595 #ifdef STR_TRANSLATION
596 void
597 ber_set_string_translators( BerElement *ber, BERTranslateProc encode_proc,
598         BERTranslateProc decode_proc )
599 {
600     ber->ber_encode_translate_proc = encode_proc;
601     ber->ber_decode_translate_proc = decode_proc;
602 }
603 #endif /* STR_TRANSLATION */