2 * -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
4 * The contents of this file are subject to the Netscape Public License
5 * Version 1.0 (the "NPL"); you may not use this file except in
6 * compliance with the NPL. You may obtain a copy of the NPL at
7 * http://www.mozilla.org/NPL/
9 * Software distributed under the NPL is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
11 * for the specific language governing rights and limitations under the
14 * The Initial Developer of this code under the NPL is Netscape
15 * Communications Corporation. Portions created by Netscape are
16 * Copyright (C) 1998 Netscape Communications Corporation. All Rights
21 * Copyright (c) 1990 Regents of the University of Michigan.
22 * All rights reserved.
24 * Redistribution and use in source and binary forms are permitted
25 * provided that this notice is preserved and that due credit is given
26 * to the University of Michigan at Ann Arbor. The name of the University
27 * may not be used to endorse or promote products derived from this
28 * software without specific prior written permission. This software
29 * is provided ``as is'' without express or implied warranty.
32 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
33 * Use is subject to license terms.
38 #include "kmfber_int.h"
43 * Note: kmfber_read() only uses the ber_end and ber_ptr elements of ber.
44 * Functions like kmfber_get_tag(), kmfber_skip_tag, and kmfber_peek_tag()
45 * rely on that fact, so if this code is changed to use any additional
46 * elements of the ber structure, those functions will need to be changed
50 kmfber_read(BerElement
*ber
, char *buf
, ber_len_t len
)
55 nleft
= ber
->ber_end
- ber
->ber_ptr
;
56 actuallen
= nleft
< len
? nleft
: len
;
58 (void) memmove(buf
, ber
->ber_ptr
, (size_t)actuallen
);
60 ber
->ber_ptr
+= actuallen
;
62 return ((ber_int_t
)actuallen
);
66 * enlarge the ber buffer.
67 * return 0 on success, -1 on error.
70 kmfber_realloc(BerElement
*ber
, ber_len_t len
)
72 ber_uint_t need
, have
, total
;
78 have_bytes
= ber
->ber_end
- ber
->ber_buf
;
79 have
= have_bytes
/ EXBUFSIZ
;
80 need
= (len
< EXBUFSIZ
? 1 : (len
+ (EXBUFSIZ
- 1)) / EXBUFSIZ
);
81 total
= have
* EXBUFSIZ
+ need
* EXBUFSIZ
;
83 oldbuf
= ber
->ber_buf
;
85 if (ber
->ber_buf
== NULL
) {
86 if ((ber
->ber_buf
= (char *)malloc((size_t)total
))
90 ber
->ber_flags
&= ~KMFBER_FLAG_NO_FREE_BUFFER
;
92 if (ber
->ber_flags
& KMFBER_FLAG_NO_FREE_BUFFER
) {
93 /* transition to malloc'd buffer */
94 if ((ber
->ber_buf
= (char *)malloc(
95 (size_t)total
)) == NULL
) {
98 ber
->ber_flags
&= ~KMFBER_FLAG_NO_FREE_BUFFER
;
100 /* copy existing data into new malloc'd buffer */
101 (void) memmove(ber
->ber_buf
, oldbuf
, have_bytes
);
103 if ((ber
->ber_buf
= (char *)realloc(
104 oldbuf
, (size_t)total
)) == NULL
) {
111 ber
->ber_end
= ber
->ber_buf
+ total
;
114 * If the stinking thing was moved, we need to go through and
115 * reset all the sos and ber pointers. Offsets would've been
116 * a better idea... oh well.
118 if (ber
->ber_buf
!= oldbuf
) {
119 ber
->ber_ptr
= ber
->ber_buf
+ (ber
->ber_ptr
- oldbuf
);
121 for (s
= ber
->ber_sos
; s
!= NULLSEQORSET
; s
= s
->sos_next
) {
122 off
= s
->sos_first
- oldbuf
;
123 s
->sos_first
= ber
->ber_buf
+ off
;
125 off
= s
->sos_ptr
- oldbuf
;
126 s
->sos_ptr
= ber
->ber_buf
+ off
;
134 * returns "len" on success and -1 on failure.
137 kmfber_write(BerElement
*ber
, char *buf
, ber_len_t len
, int nosos
)
139 if (nosos
|| ber
->ber_sos
== NULL
) {
140 if (ber
->ber_ptr
+ len
> ber
->ber_end
) {
141 if (kmfber_realloc(ber
, len
) != 0)
144 (void) memmove(ber
->ber_ptr
, buf
, (size_t)len
);
148 if (ber
->ber_sos
->sos_ptr
+ len
> ber
->ber_end
) {
149 if (kmfber_realloc(ber
, len
) != 0)
152 (void) memmove(ber
->ber_sos
->sos_ptr
, buf
, (size_t)len
);
153 ber
->ber_sos
->sos_ptr
+= len
;
154 ber
->ber_sos
->sos_clen
+= len
;
160 kmfber_free(BerElement
*ber
, int freebuf
)
164 !(ber
->ber_flags
& KMFBER_FLAG_NO_FREE_BUFFER
))
170 /* we pre-allocate a buffer to save the extra malloc later */
172 kmfber_alloc_t(int options
)
176 if ((ber
= (BerElement
*)calloc(1,
177 sizeof (struct berelement
) + EXBUFSIZ
)) == NULL
) {
181 ber
->ber_tag
= KMFBER_DEFAULT
;
182 ber
->ber_options
= options
;
183 ber
->ber_buf
= (char *)ber
+ sizeof (struct berelement
);
184 ber
->ber_ptr
= ber
->ber_buf
;
185 ber
->ber_end
= ber
->ber_buf
+ EXBUFSIZ
;
186 ber
->ber_flags
= KMFBER_FLAG_NO_FREE_BUFFER
;
195 return (kmfber_alloc_t(0));
201 return (kmfber_alloc_t(KMFBER_OPT_USE_DER
));
205 kmfber_dup(BerElement
*ber
)
209 if ((new = kmfber_alloc()) == NULL
)
219 ber_init_w_nullchar(BerElement
*ber
, int options
)
221 (void) memset((char *)ber
, '\0', sizeof (struct berelement
));
222 ber
->ber_tag
= KMFBER_DEFAULT
;
224 ber
->ber_options
= options
;
229 kmfber_reset(BerElement
*ber
, int was_writing
)
232 ber
->ber_end
= ber
->ber_ptr
;
233 ber
->ber_ptr
= ber
->ber_buf
;
235 ber
->ber_ptr
= ber
->ber_end
;
238 ber
->ber_rwptr
= NULL
;
245 ber_dump(BerElement
*ber
, int inout
)
248 sprintf(msg
, "ber_dump: buf 0x%lx, ptr 0x%lx, rwptr 0x%lx, end 0x%lx\n",
249 ber
->ber_buf
, ber
->ber_ptr
, ber
->ber_rwptr
, ber
->ber_end
);
252 sprintf(msg
, " current len %ld, contents:\n",
253 ber
->ber_end
- ber
->ber_ptr
);
255 lber_bprint(ber
->ber_ptr
, ber
->ber_end
- ber
->ber_ptr
);
257 sprintf(msg
, " current len %ld, contents:\n",
258 ber
->ber_ptr
- ber
->ber_buf
);
260 lber_bprint(ber
->ber_buf
, ber
->ber_ptr
- ber
->ber_buf
);
265 ber_sos_dump(Seqorset
*sos
)
268 ber_err_print("*** sos dump ***\n");
269 while (sos
!= NULLSEQORSET
) {
270 sprintf(msg
, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n",
271 sos
->sos_clen
, sos
->sos_first
, sos
->sos_ptr
);
273 sprintf(msg
, " current len %ld contents:\n",
274 sos
->sos_ptr
- sos
->sos_first
);
276 lber_bprint(sos
->sos_first
, sos
->sos_ptr
- sos
->sos_first
);
280 ber_err_print("*** end dump ***\n");
285 /* new dboreham code below: */
291 typedef struct byte_buffer byte_buffer
;
294 * The kmfber_flatten routine allocates a struct berval whose contents
295 * are a BER encoding taken from the ber argument. The bvPtr pointer
296 * points to the returned berval, which must be freed using
297 * kmfber_bvfree(). This routine returns 0 on success and -1 on error.
298 * The use of kmfber_flatten on a BerElement in which all '{' and '}'
299 * format modifiers have not been properly matched can result in a
300 * berval whose contents are not a valid BER encoding.
301 * Note that the ber_ptr is not modified.
304 kmfber_flatten(BerElement
*ber
, struct berval
**bvPtr
)
309 /* allocate a struct berval */
310 new = (struct berval
*)malloc((size_t)(sizeof (struct berval
)));
314 (void) memset(new, 0, sizeof (struct berval
));
317 * Copy everything from the BerElement's ber_buf to ber_ptr
318 * into the berval structure.
324 len
= ber
->ber_ptr
- ber
->ber_buf
;
325 new->bv_val
= (char *)malloc((size_t)(len
+ 1));
326 if (new->bv_val
== NULL
) {
330 (void) memmove(new->bv_val
, ber
->ber_buf
, (size_t)len
);
331 new->bv_val
[len
] = '\0';
335 /* set bvPtr pointer to point to the returned berval */
342 kmfder_init(const struct berval
*bv
)
346 /* construct BerElement */
347 if ((ber
= kmfber_alloc_t(KMFBER_OPT_USE_DER
)) != NULL
) {
348 /* copy data from the bv argument into BerElement */
349 /* XXXmcs: had to cast unsigned long bv_len to long */
350 if ((kmfber_write(ber
, bv
->bv_val
, bv
->bv_len
, 0)) !=
351 (ber_slen_t
)bv
->bv_len
) {
357 * reset ber_ptr back to the beginning of buffer so that this new
358 * and initialized ber element can be READ
360 kmfber_reset(ber
, 1);
363 * return a ptr to a new BerElement containing a copy of the data
364 * in the bv argument or a null pointer on error
370 kmfber_init(const struct berval
*bv
)
374 /* construct BerElement */
375 if ((ber
= kmfber_alloc_t(0)) != NULL
) {
376 /* copy data from the bv argument into BerElement */
377 /* XXXmcs: had to cast unsigned long bv_len to long */
378 if ((kmfber_write(ber
, bv
->bv_val
, bv
->bv_len
, 0)) !=
379 (ber_slen_t
)bv
->bv_len
) {
385 * reset ber_ptr back to the beginning of buffer so that this new
386 * and initialized ber element can be READ
388 kmfber_reset(ber
, 1);
391 * return a ptr to a new BerElement containing a copy of the data
392 * in the bv argument or a null pointer on error