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