2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 * -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
8 * The contents of this file are subject to the Netscape Public License
9 * Version 1.0 (the "NPL"); you may not use this file except in
10 * compliance with the NPL. You may obtain a copy of the NPL at
11 * http://www.mozilla.org/NPL/
13 * Software distributed under the NPL is distributed on an "AS IS" basis,
14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
15 * for the specific language governing rights and limitations under the
18 * The Initial Developer of this code under the NPL is Netscape
19 * Communications Corporation. Portions created by Netscape are
20 * Copyright (C) 1998 Netscape Communications Corporation. All Rights
25 * Copyright (c) 1990 Regents of the University of Michigan.
26 * All rights reserved.
28 * Redistribution and use in source and binary forms are permitted
29 * provided that this notice is preserved and that due credit is given
30 * to the University of Michigan at Ann Arbor. The name of the University
31 * may not be used to endorse or promote products derived from this
32 * software without specific prior written permission. This software
33 * is provided ``as is'' without express or implied warranty.
36 /* decode.c - ber input decoding routines */
39 #include <sys/types.h>
40 #include <netinet/in.h>
44 #include "kmfber_int.h"
47 ber_svecfree(char **vals
)
53 for (i
= 0; vals
[i
] != NULL
; i
++)
59 * Note: kmfber_get_tag() only uses the ber_end and ber_ptr elements of ber.
60 * If that changes, the kmfber_peek_tag() and/or
61 * kmfkmfber_skip_tag() implementations will need to be changed.
63 /* return the tag - KMFBER_DEFAULT returned means trouble */
65 kmfber_get_tag(BerElement
*ber
)
72 if (kmfber_read(ber
, (char *)&xbyte
, 1) != 1)
73 return (KMFBER_DEFAULT
);
75 if ((xbyte
& KMFBER_BIG_TAG_MASK
) != KMFBER_BIG_TAG_MASK
)
76 return ((ber_uint_t
)xbyte
);
80 for (i
= 1; i
< sizeof (ber_int_t
); i
++) {
81 if (kmfber_read(ber
, (char *)&xbyte
, 1) != 1)
82 return (KMFBER_DEFAULT
);
86 if (! (xbyte
& KMFBER_MORE_TAG_MASK
))
91 if (i
== sizeof (ber_int_t
))
92 return (KMFBER_DEFAULT
);
94 /* want leading, not trailing 0's */
95 return (tag
>> (sizeof (ber_int_t
)- i
- 1));
99 * Note: kmfber_skip_tag() only uses the ber_end and ber_ptr elements of ber.
100 * If that changes, the implementation of kmfber_peek_tag() will need to
104 kmfber_skip_tag(BerElement
*ber
, ber_len_t
*len
)
112 * Any ber element looks like this: tag length contents.
113 * Assuming everything's ok, we return the tag byte (we
114 * can assume a single byte), and return the length in len.
117 * 1) definite lengths
118 * 2) primitive encodings used whenever possible
122 * First, we read the tag.
125 if ((tag
= kmfber_get_tag(ber
)) == KMFBER_DEFAULT
)
126 return (KMFBER_DEFAULT
);
129 * Next, read the length. The first byte contains the length of
130 * the length. If bit 8 is set, the length is the long form,
131 * otherwise it's the short form. We don't allow a length that's
132 * greater than what we can hold in an unsigned long.
137 if (kmfber_read(ber
, (char *)&lc
, 1) != 1)
138 return (KMFBER_DEFAULT
);
140 noctets
= (lc
& 0x7f);
141 if (noctets
> sizeof (ber_uint_t
))
142 return (KMFBER_DEFAULT
);
143 diff
= sizeof (ber_int_t
) - noctets
;
144 if (kmfber_read(ber
, (char *)&netlen
+ diff
, noctets
)
146 return (KMFBER_DEFAULT
);
147 *len
= ntohl(netlen
);
157 * Note: Previously, we passed the "ber" parameter directly to
158 * kmfber_skip_tag(), saving and restoring the ber_ptr element only.
159 * We now take advantage of the fact that the only ber structure
160 * elements touched by kmfber_skip_tag() are ber_end and ber_ptr.
161 * If that changes, this code must change too.
164 kmfber_peek_tag(BerElement
*ber
, ber_len_t
*len
)
168 bercopy
.ber_end
= ber
->ber_end
;
169 bercopy
.ber_ptr
= ber
->ber_ptr
;
170 return (kmfber_skip_tag(&bercopy
, len
));
174 ber_getnint(BerElement
*ber
, ber_int_t
*num
, ber_slen_t len
)
178 unsigned char buffer
[sizeof (ber_int_t
)];
180 * The tag and length have already been stripped off. We should
181 * be sitting right before len bytes of 2's complement integer,
182 * ready to be read straight into an int. We may have to sign
183 * extend after we read it in.
186 if (len
> sizeof (buffer
))
189 /* read into the low-order bytes of netnum */
190 if (kmfber_read(ber
, (char *)buffer
, len
) != len
)
193 /* This sets the required sign extension */
195 value
= 0x80 & buffer
[0] ? (-1) : 0;
200 for (i
= 0; i
< len
; i
++)
201 value
= (value
<< 8) | buffer
[i
];
209 kmfber_get_int(BerElement
*ber
, ber_int_t
*num
)
214 if ((tag
= kmfber_skip_tag(ber
, &len
)) == KMFBER_DEFAULT
)
215 return (KMFBER_DEFAULT
);
218 * len is being demoted to a long here -- possible conversion error
221 if (ber_getnint(ber
, num
, (int)len
) != (ber_slen_t
)len
)
222 return (KMFBER_DEFAULT
);
228 kmfber_get_stringb(BerElement
*ber
, char *buf
, ber_len_t
*len
)
232 #ifdef STR_TRANSLATION
234 #endif /* STR_TRANSLATION */
236 if ((tag
= kmfber_skip_tag(ber
, &datalen
)) == KMFBER_DEFAULT
)
237 return (KMFBER_DEFAULT
);
238 if (datalen
> (*len
- 1))
239 return (KMFBER_DEFAULT
);
242 * datalen is being demoted to a long here -- possible conversion error
245 if (kmfber_read(ber
, buf
, datalen
) != (ber_slen_t
)datalen
)
246 return (KMFBER_DEFAULT
);
250 #ifdef STR_TRANSLATION
251 if (datalen
> 0 && (ber
->ber_options
& KMFBER_OPT_TRANSLATE_STRINGS
)
252 != 0 && ber
->ber_decode_translate_proc
!= NULL
) {
256 if ((*(ber
->ber_decode_translate_proc
))(&transbuf
, &datalen
,
258 return (KMFBER_DEFAULT
);
260 if (datalen
> *len
) {
262 return (KMFBER_DEFAULT
);
264 (void) memmove(buf
, transbuf
, datalen
);
268 #endif /* STR_TRANSLATION */
275 kmfber_get_stringa(BerElement
*ber
, char **buf
)
280 if ((tag
= kmfber_skip_tag(ber
, &datalen
)) == KMFBER_DEFAULT
)
281 return (KMFBER_DEFAULT
);
283 if ((*buf
= (char *)malloc((size_t)datalen
+ 1)) == NULL
)
284 return (KMFBER_DEFAULT
);
287 * datalen is being demoted to a long here -- possible conversion error
289 if (kmfber_read(ber
, *buf
, datalen
) != (ber_slen_t
)datalen
)
290 return (KMFBER_DEFAULT
);
291 (*buf
)[datalen
] = '\0';
297 ber_get_oid(BerElement
*ber
, struct berval
*oid
)
302 if ((tag
= kmfber_skip_tag(ber
, &len
)) != 0x06) {
303 return (KMFBER_DEFAULT
);
306 if ((oid
->bv_val
= (char *)malloc((size_t)len
+ 1)) == NULL
) {
307 return (KMFBER_DEFAULT
);
311 if (kmfber_read(ber
, oid
->bv_val
, oid
->bv_len
) !=
312 (ber_slen_t
)oid
->bv_len
)
313 return (KMFBER_DEFAULT
);
319 ber_get_bigint(BerElement
*ber
, struct berval
**bv
)
324 if ((*bv
= (struct berval
*)malloc(sizeof (struct berval
)))
326 return (KMFBER_DEFAULT
);
329 (*bv
)->bv_val
= NULL
;
331 if ((tag
= kmfber_skip_tag(ber
, &len
)) != BER_INTEGER
) {
332 return (KMFBER_DEFAULT
);
335 if (((*bv
)->bv_val
= (char *)malloc((size_t)len
+ 1))
337 return (KMFBER_DEFAULT
);
341 * len is being demoted to a long here -- possible conversion error
343 if (kmfber_read(ber
, (*bv
)->bv_val
, len
) != (ber_slen_t
)len
)
344 return (KMFBER_DEFAULT
);
348 /* If DER encoding, strip leading 0's if high-order bit is set */
349 if (ber
->ber_options
& KMFBER_OPT_USE_DER
) {
350 char *p
= (*bv
)->bv_val
;
351 while ((*p
== 0x00) && ((*bv
)->bv_len
> 0) && (p
[1] & 0x80)) {
356 * Shift the buffer to the beginning of the allocated space
357 * so it can be properly freed later.
359 if ((p
> (*bv
)->bv_val
) && ((*bv
)->bv_len
> 0))
360 (void) bcopy(p
, (*bv
)->bv_val
, (*bv
)->bv_len
);
367 kmfber_get_stringal(BerElement
*ber
, struct berval
**bv
)
372 if ((*bv
= (struct berval
*)malloc(sizeof (struct berval
)))
374 return (KMFBER_DEFAULT
);
377 if ((tag
= kmfber_skip_tag(ber
, &len
)) == KMFBER_DEFAULT
) {
378 return (KMFBER_DEFAULT
);
381 if (((*bv
)->bv_val
= (char *)malloc((size_t)len
+ 1))
383 return (KMFBER_DEFAULT
);
387 * len is being demoted to a long here -- possible conversion error
389 if (kmfber_read(ber
, (*bv
)->bv_val
, len
) != (ber_slen_t
)len
)
390 return (KMFBER_DEFAULT
);
391 ((*bv
)->bv_val
)[len
] = '\0';
398 kmfber_get_bitstringa(BerElement
*ber
, char **buf
, ber_len_t
*blen
)
402 unsigned char unusedbits
;
404 if ((tag
= kmfber_skip_tag(ber
, &datalen
)) == KMFBER_DEFAULT
)
405 return (KMFBER_DEFAULT
);
407 if ((*buf
= (char *)malloc((size_t)datalen
- 1)) == NULL
)
408 return (KMFBER_DEFAULT
);
410 if (kmfber_read(ber
, (char *)&unusedbits
, 1) != 1)
411 return (KMFBER_DEFAULT
);
413 /* Subtract 1 for the unused bits */
417 * datalen is being demoted to a long here -- possible conversion error
419 if (kmfber_read(ber
, *buf
, datalen
) != (ber_slen_t
)datalen
)
420 return (KMFBER_DEFAULT
);
422 *blen
= datalen
* 8 - unusedbits
;
427 kmfber_get_null(BerElement
*ber
)
432 if ((tag
= kmfber_skip_tag(ber
, &len
)) == KMFBER_DEFAULT
)
433 return (KMFBER_DEFAULT
);
436 return (KMFBER_DEFAULT
);
442 kmfber_get_boolean(BerElement
*ber
, int *boolval
)
447 rc
= kmfber_get_int(ber
, &longbool
);
454 kmfber_first_element(BerElement
*ber
, ber_len_t
*len
, char **last
)
456 /* skip the sequence header, use the len to mark where to stop */
457 if (kmfber_skip_tag(ber
, len
) == KMFBER_DEFAULT
) {
458 return (KMFBER_ERROR
);
461 *last
= ber
->ber_ptr
+ *len
;
463 if (*last
== ber
->ber_ptr
) {
464 return (KMFBER_END_OF_SEQORSET
);
467 return (kmfber_peek_tag(ber
, len
));
471 kmfber_next_element(BerElement
*ber
, ber_len_t
*len
, char *last
)
473 if (ber
->ber_ptr
== last
) {
474 return (KMFBER_END_OF_SEQORSET
);
477 return (kmfber_peek_tag(ber
, len
));
481 kmfber_bvfree(struct berval
*bv
)
484 if (bv
->bv_val
!= NULL
) {
492 kmfber_bvecfree(struct berval
**bv
)
497 for (i
= 0; bv
[i
] != NULL
; i
++) {
498 kmfber_bvfree(bv
[i
]);
506 kmfber_scanf(BerElement
*ber
, const char *fmt
, ...)
510 char *s
, **ss
, ***sss
;
511 struct berval
***bv
, **bvp
, *bval
;
514 ber_int_t rc
, tag
, *b_int
;
521 for (rc
= 0, p
= (char *)fmt
; *p
&& rc
!= KMFBER_DEFAULT
; p
++) {
523 case 'a': /* octet string - allocate storage as needed */
524 ss
= va_arg(ap
, char **);
525 rc
= kmfber_get_stringa(ber
, ss
);
528 case 'b': /* boolean */
529 i
= va_arg(ap
, int *);
530 rc
= kmfber_get_boolean(ber
, i
);
533 case 'D': /* Object ID */
534 bval
= va_arg(ap
, struct berval
*);
535 rc
= ber_get_oid(ber
, bval
);
537 case 'e': /* enumerated */
539 b_int
= va_arg(ap
, ber_int_t
*);
540 rc
= kmfber_get_int(ber
, b_int
);
543 case 'l': /* length of next item */
544 l
= va_arg(ap
, ber_slen_t
*);
545 rc
= kmfber_peek_tag(ber
, (ber_len_t
*)l
);
549 rc
= kmfber_get_null(ber
);
552 case 's': /* octet string - in a buffer */
553 s
= va_arg(ap
, char *);
554 l
= va_arg(ap
, ber_slen_t
*);
555 rc
= kmfber_get_stringb(ber
, s
, (ber_len_t
*)l
);
558 case 'o': /* octet string in a supplied berval */
559 bval
= va_arg(ap
, struct berval
*);
560 (void) kmfber_peek_tag(ber
, &bval
->bv_len
);
561 rc
= kmfber_get_stringa(ber
, &bval
->bv_val
);
564 case 'I': /* variable length Integer */
565 /* Treat INTEGER same as an OCTET string, but ignore the tag */
566 bvp
= va_arg(ap
, struct berval
**);
567 rc
= ber_get_bigint(ber
, bvp
);
569 case 'O': /* octet string - allocate & include length */
570 bvp
= va_arg(ap
, struct berval
**);
571 rc
= kmfber_get_stringal(ber
, bvp
);
574 case 'B': /* bit string - allocate storage as needed */
575 ss
= va_arg(ap
, char **);
576 l
= va_arg(ap
, ber_slen_t
*); /* for length, in bits */
577 rc
= kmfber_get_bitstringa(ber
, ss
, (ber_len_t
*)l
);
580 case 't': /* tag of next item */
581 t
= va_arg(ap
, ber_tag_t
*);
582 *t
= kmfber_peek_tag(ber
, &len
);
583 rc
= (ber_int_t
)(*t
);
586 case 'T': /* skip tag of next item */
587 t
= va_arg(ap
, ber_tag_t
*);
588 *t
= kmfber_skip_tag(ber
, &len
);
589 rc
= (ber_int_t
)(*t
);
592 case 'v': /* sequence of strings */
593 sss
= va_arg(ap
, char ***);
599 for (tag
= kmfber_first_element(ber
, &len
, &last
);
600 (tag
!= KMFBER_DEFAULT
&&
601 tag
!= KMFBER_END_OF_SEQORSET
&&
602 rc
!= KMFBER_DEFAULT
);
603 tag
= kmfber_next_element(ber
, &len
, last
)) {
605 /* Make room for at least 15 strings */
606 *sss
= (char **)malloc(16 * sizeof (char *));
609 if ((size_t)(j
+2) > array_size
) {
610 /* We'v overflowed our buffer */
611 *sss
= (char **)reallocarray(*sss
,
612 array_size
* 2, sizeof (char *));
613 array_size
= array_size
* 2;
616 rc
= kmfber_get_stringa(ber
, &((*sss
)[j
]));
619 if (rc
!= KMFBER_DEFAULT
&& tag
!= KMFBER_END_OF_SEQORSET
) {
626 case 'V': /* sequence of strings + lengths */
627 bv
= va_arg(ap
, struct berval
***);
630 for (tag
= kmfber_first_element(ber
, &len
, &last
);
631 (tag
!= KMFBER_DEFAULT
&&
632 tag
!= KMFBER_END_OF_SEQORSET
&&
633 rc
!= KMFBER_DEFAULT
);
634 tag
= kmfber_next_element(ber
, &len
, last
)) {
636 *bv
= (struct berval
**)malloc(
637 2 * sizeof (struct berval
*));
639 *bv
= reallocarray(*bv
, j
+ 2,
640 sizeof(struct berval
*));
642 rc
= kmfber_get_stringal(ber
, &((*bv
)[j
]));
645 if (rc
!= KMFBER_DEFAULT
&&
646 tag
!= KMFBER_END_OF_SEQORSET
) {
653 case 'x': /* skip the next element - whatever it is */
654 if ((rc
= kmfber_skip_tag(ber
, &len
)) == KMFBER_DEFAULT
)
659 case '{': /* begin sequence */
660 case '[': /* begin set */
661 if (*(p
+ 1) != 'v' && *(p
+ 1) != 'V')
662 rc
= kmfber_skip_tag(ber
, &len
);
665 case '}': /* end sequence */
666 case ']': /* end set */
677 if (rc
== KMFBER_DEFAULT
) {
679 for (p
--; fmt
< p
&& *fmt
; fmt
++) {
681 case 'a': /* octet string - allocate storage as needed */
682 ss
= va_arg(ap
, char **);
683 if (ss
!= NULL
&& *ss
!= NULL
) {
689 case 'b': /* boolean */
690 i
= va_arg(ap
, int *);
693 case 'e': /* enumerated */
695 l
= va_arg(ap
, ber_slen_t
*);
698 case 'l': /* length of next item */
699 l
= va_arg(ap
, ber_slen_t
*);
705 case 's': /* octet string - in a buffer */
706 s
= va_arg(ap
, char *);
707 l
= va_arg(ap
, ber_slen_t
*);
710 case 'o': /* octet string in a supplied berval */
711 bval
= va_arg(ap
, struct berval
*);
713 (void) memset(bval
, 0, sizeof (struct berval
));
716 case 'O': /* octet string - allocate & include length */
717 bvp
= va_arg(ap
, struct berval
**);
722 case 'B': /* bit string - allocate storage as needed */
723 ss
= va_arg(ap
, char **);
724 l
= va_arg(ap
, ber_slen_t
*); /* for length, in bits */
725 if (ss
!= NULL
&& *ss
!= NULL
) {
731 case 't': /* tag of next item */
732 t
= va_arg(ap
, ber_tag_t
*);
734 case 'T': /* skip tag of next item */
735 t
= va_arg(ap
, ber_tag_t
*);
738 case 'v': /* sequence of strings */
739 sss
= va_arg(ap
, char ***);
740 if (sss
!= NULL
&& *sss
!= NULL
) {
746 case 'V': /* sequence of strings + lengths */
747 bv
= va_arg(ap
, struct berval
***);
748 kmfber_bvecfree(*bv
);
752 case 'x': /* skip the next element - whatever it is */
755 case '{': /* begin sequence */
756 case '[': /* begin set */
759 case '}': /* end sequence */
760 case ']': /* end set */
774 kmfber_bvdup(const struct berval
*bv
)
778 if ((new = (struct berval
*)malloc(sizeof (struct berval
)))
782 if (bv
->bv_val
== NULL
) {
786 if ((new->bv_val
= (char *)malloc(bv
->bv_len
+ 1))
790 (void) memmove(new->bv_val
, bv
->bv_val
, (size_t)bv
->bv_len
);
791 new->bv_val
[bv
->bv_len
] = '\0';
792 new->bv_len
= bv
->bv_len
;