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