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