1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 24 * 25 * The contents of this file are subject to the Netscape Public License 26 * Version 1.0 (the "NPL"); you may not use this file except in 27 * compliance with the NPL. You may obtain a copy of the NPL at 28 * http://www.mozilla.org/NPL/ 29 * 30 * Software distributed under the NPL is distributed on an "AS IS" basis, 31 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL 32 * for the specific language governing rights and limitations under the 33 * NPL. 34 * 35 * The Initial Developer of this code under the NPL is Netscape 36 * Communications Corporation. Portions created by Netscape are 37 * Copyright (C) 1998 Netscape Communications Corporation. All Rights 38 * Reserved. 39 */ 40 41 /* 42 * Copyright (c) 1990 Regents of the University of Michigan. 43 * All rights reserved. 44 * 45 * Redistribution and use in source and binary forms are permitted 46 * provided that this notice is preserved and that due credit is given 47 * to the University of Michigan at Ann Arbor. The name of the University 48 * may not be used to endorse or promote products derived from this 49 * software without specific prior written permission. This software 50 * is provided ``as is'' without express or implied warranty. 51 */ 52 /* 53 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 54 * Use is subject to license terms. 55 */ 56 57 #pragma ident "%Z%%M% %I% %E% SMI" 58 59 60 #include <stdlib.h> 61 #include <ber_der.h> 62 #include "kmfber_int.h" 63 64 #define EXBUFSIZ 1024 65 66 /* 67 * Note: kmfber_read() only uses the ber_end and ber_ptr elements of ber. 68 * Functions like kmfber_get_tag(), kmfber_skip_tag, and kmfber_peek_tag() 69 * rely on that fact, so if this code is changed to use any additional 70 * elements of the ber structure, those functions will need to be changed 71 * as well. 72 */ 73 ber_int_t 74 kmfber_read(BerElement *ber, char *buf, ber_len_t len) 75 { 76 size_t actuallen; 77 size_t nleft; 78 79 nleft = ber->ber_end - ber->ber_ptr; 80 actuallen = nleft < len ? nleft : len; 81 82 (void) memmove(buf, ber->ber_ptr, (size_t)actuallen); 83 84 ber->ber_ptr += actuallen; 85 86 return ((ber_int_t)actuallen); 87 } 88 89 /* 90 * enlarge the ber buffer. 91 * return 0 on success, -1 on error. 92 */ 93 static int 94 kmfber_realloc(BerElement *ber, ber_len_t len) 95 { 96 ber_uint_t need, have, total; 97 size_t have_bytes; 98 Seqorset *s; 99 size_t off; 100 char *oldbuf; 101 102 have_bytes = ber->ber_end - ber->ber_buf; 103 have = have_bytes / EXBUFSIZ; 104 need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ); 105 total = have * EXBUFSIZ + need * EXBUFSIZ; 106 107 oldbuf = ber->ber_buf; 108 109 if (ber->ber_buf == NULL) { 110 if ((ber->ber_buf = (char *)malloc((size_t)total)) 111 == NULL) { 112 return (-1); 113 } 114 ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER; 115 } else { 116 if (ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER) { 117 /* transition to malloc'd buffer */ 118 if ((ber->ber_buf = (char *)malloc( 119 (size_t)total)) == NULL) { 120 return (-1); 121 } 122 ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER; 123 /* copy existing data into new malloc'd buffer */ 124 (void) memmove(ber->ber_buf, oldbuf, have_bytes); 125 } else { 126 if ((ber->ber_buf = (char *)realloc( 127 ber->ber_buf, (size_t)total)) == NULL) { 128 return (-1); 129 } 130 } 131 } 132 133 ber->ber_end = ber->ber_buf + total; 134 135 /* 136 * If the stinking thing was moved, we need to go through and 137 * reset all the sos and ber pointers. Offsets would've been 138 * a better idea... oh well. 139 */ 140 141 if (ber->ber_buf != oldbuf) { 142 ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf); 143 144 for (s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next) { 145 off = s->sos_first - oldbuf; 146 s->sos_first = ber->ber_buf + off; 147 148 off = s->sos_ptr - oldbuf; 149 s->sos_ptr = ber->ber_buf + off; 150 } 151 } 152 153 return (0); 154 } 155 156 /* 157 * returns "len" on success and -1 on failure. 158 */ 159 ber_int_t 160 kmfber_write(BerElement *ber, char *buf, ber_len_t len, int nosos) 161 { 162 if (nosos || ber->ber_sos == NULL) { 163 if (ber->ber_ptr + len > ber->ber_end) { 164 if (kmfber_realloc(ber, len) != 0) 165 return (-1); 166 } 167 (void) memmove(ber->ber_ptr, buf, (size_t)len); 168 ber->ber_ptr += len; 169 return (len); 170 } else { 171 if (ber->ber_sos->sos_ptr + len > ber->ber_end) { 172 if (kmfber_realloc(ber, len) != 0) 173 return (-1); 174 } 175 (void) memmove(ber->ber_sos->sos_ptr, buf, (size_t)len); 176 ber->ber_sos->sos_ptr += len; 177 ber->ber_sos->sos_clen += len; 178 return (len); 179 } 180 } 181 182 void 183 kmfber_free(BerElement *ber, int freebuf) 184 { 185 if (ber != NULL) { 186 if (freebuf && 187 !(ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER)) { 188 free(ber->ber_buf); 189 } 190 free((char *)ber); 191 } 192 } 193 194 /* we pre-allocate a buffer to save the extra malloc later */ 195 BerElement * 196 kmfber_alloc_t(int options) 197 { 198 BerElement *ber; 199 200 if ((ber = (BerElement*)calloc(1, 201 sizeof (struct berelement) + EXBUFSIZ)) == NULL) { 202 return (NULL); 203 } 204 205 ber->ber_tag = KMFBER_DEFAULT; 206 ber->ber_options = options; 207 ber->ber_buf = (char *)ber + sizeof (struct berelement); 208 ber->ber_ptr = ber->ber_buf; 209 ber->ber_end = ber->ber_buf + EXBUFSIZ; 210 ber->ber_flags = KMFBER_FLAG_NO_FREE_BUFFER; 211 212 return (ber); 213 } 214 215 216 BerElement * 217 kmfber_alloc() 218 { 219 return (kmfber_alloc_t(0)); 220 } 221 222 BerElement * 223 kmfder_alloc() 224 { 225 return (kmfber_alloc_t(KMFBER_OPT_USE_DER)); 226 } 227 228 BerElement * 229 kmfber_dup(BerElement *ber) 230 { 231 BerElement *new; 232 233 if ((new = kmfber_alloc()) == NULL) 234 return (NULL); 235 236 *new = *ber; 237 238 return (new); 239 } 240 241 242 void 243 ber_init_w_nullchar(BerElement *ber, int options) 244 { 245 (void) memset((char *)ber, '\0', sizeof (struct berelement)); 246 ber->ber_tag = KMFBER_DEFAULT; 247 248 ber->ber_options = options; 249 } 250 251 252 void 253 kmfber_reset(BerElement *ber, int was_writing) 254 { 255 if (was_writing) { 256 ber->ber_end = ber->ber_ptr; 257 ber->ber_ptr = ber->ber_buf; 258 } else { 259 ber->ber_ptr = ber->ber_end; 260 } 261 262 ber->ber_rwptr = NULL; 263 } 264 265 266 #ifdef KMFBER_DEBUG 267 268 void 269 ber_dump(BerElement *ber, int inout) 270 { 271 char msg[128]; 272 sprintf(msg, "ber_dump: buf 0x%lx, ptr 0x%lx, rwptr 0x%lx, end 0x%lx\n", 273 ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end); 274 ber_err_print(msg); 275 if (inout == 1) { 276 sprintf(msg, " current len %ld, contents:\n", 277 ber->ber_end - ber->ber_ptr); 278 ber_err_print(msg); 279 lber_bprint(ber->ber_ptr, ber->ber_end - ber->ber_ptr); 280 } else { 281 sprintf(msg, " current len %ld, contents:\n", 282 ber->ber_ptr - ber->ber_buf); 283 ber_err_print(msg); 284 lber_bprint(ber->ber_buf, ber->ber_ptr - ber->ber_buf); 285 } 286 } 287 288 void 289 ber_sos_dump(Seqorset *sos) 290 { 291 char msg[80]; 292 ber_err_print("*** sos dump ***\n"); 293 while (sos != NULLSEQORSET) { 294 sprintf(msg, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n", 295 sos->sos_clen, sos->sos_first, sos->sos_ptr); 296 ber_err_print(msg); 297 sprintf(msg, " current len %ld contents:\n", 298 sos->sos_ptr - sos->sos_first); 299 ber_err_print(msg); 300 lber_bprint(sos->sos_first, sos->sos_ptr - sos->sos_first); 301 302 sos = sos->sos_next; 303 } 304 ber_err_print("*** end dump ***\n"); 305 } 306 307 #endif 308 309 /* new dboreham code below: */ 310 struct byte_buffer { 311 unsigned char *p; 312 int offset; 313 int length; 314 }; 315 typedef struct byte_buffer byte_buffer; 316 317 /* 318 * The kmfber_flatten routine allocates a struct berval whose contents 319 * are a BER encoding taken from the ber argument. The bvPtr pointer 320 * points to the returned berval, which must be freed using 321 * kmfber_bvfree(). This routine returns 0 on success and -1 on error. 322 * The use of kmfber_flatten on a BerElement in which all '{' and '}' 323 * format modifiers have not been properly matched can result in a 324 * berval whose contents are not a valid BER encoding. 325 * Note that the ber_ptr is not modified. 326 */ 327 int 328 kmfber_flatten(BerElement *ber, struct berval **bvPtr) 329 { 330 struct berval *new; 331 ber_len_t len; 332 333 /* allocate a struct berval */ 334 new = (struct berval *)malloc((size_t)(sizeof (struct berval))); 335 if (new == NULL) { 336 return (-1); 337 } 338 (void) memset(new, 0, sizeof (struct berval)); 339 340 /* 341 * Copy everything from the BerElement's ber_buf to ber_ptr 342 * into the berval structure. 343 */ 344 if (ber == NULL) { 345 new->bv_val = NULL; 346 new->bv_len = 0; 347 } else { 348 len = ber->ber_ptr - ber->ber_buf; 349 new->bv_val = (char *)malloc((size_t)(len + 1)); 350 if (new->bv_val == NULL) { 351 kmfber_bvfree(new); 352 return (-1); 353 } 354 (void) memmove(new->bv_val, ber->ber_buf, (size_t)len); 355 new->bv_val[len] = '\0'; 356 new->bv_len = len; 357 } 358 359 /* set bvPtr pointer to point to the returned berval */ 360 *bvPtr = new; 361 362 return (0); 363 } 364 365 BerElement * 366 kmfder_init(const struct berval *bv) 367 { 368 BerElement *ber; 369 370 /* construct BerElement */ 371 if ((ber = kmfber_alloc_t(KMFBER_OPT_USE_DER)) != NULL) { 372 /* copy data from the bv argument into BerElement */ 373 /* XXXmcs: had to cast unsigned long bv_len to long */ 374 if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) != 375 (ber_slen_t)bv->bv_len) { 376 kmfber_free(ber, 1); 377 return (NULL); 378 } 379 } 380 /* 381 * reset ber_ptr back to the beginning of buffer so that this new 382 * and initialized ber element can be READ 383 */ 384 kmfber_reset(ber, 1); 385 386 /* 387 * return a ptr to a new BerElement containing a copy of the data 388 * in the bv argument or a null pointer on error 389 */ 390 return (ber); 391 } 392 393 BerElement * 394 kmfber_init(const struct berval *bv) 395 { 396 BerElement *ber; 397 398 /* construct BerElement */ 399 if ((ber = kmfber_alloc_t(0)) != NULL) { 400 /* copy data from the bv argument into BerElement */ 401 /* XXXmcs: had to cast unsigned long bv_len to long */ 402 if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) != 403 (ber_slen_t)bv->bv_len) { 404 kmfber_free(ber, 1); 405 return (NULL); 406 } 407 } 408 /* 409 * reset ber_ptr back to the beginning of buffer so that this new 410 * and initialized ber element can be READ 411 */ 412 kmfber_reset(ber, 1); 413 414 /* 415 * return a ptr to a new BerElement containing a copy of the data 416 * in the bv argument or a null pointer on error 417 */ 418 return (ber); 419 } 420