]>
Commit | Line | Data |
---|---|---|
9aeaf1b4 DSH |
1 | /* v3_utl.c */ |
2 | /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL | |
3 | * project 1999. | |
4 | */ | |
5 | /* ==================================================================== | |
6 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * | |
12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | |
14 | * | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in | |
17 | * the documentation and/or other materials provided with the | |
18 | * distribution. | |
19 | * | |
20 | * 3. All advertising materials mentioning features or use of this | |
21 | * software must display the following acknowledgment: | |
22 | * "This product includes software developed by the OpenSSL Project | |
23 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
24 | * | |
25 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
26 | * endorse or promote products derived from this software without | |
27 | * prior written permission. For written permission, please contact | |
28 | * licensing@OpenSSL.org. | |
29 | * | |
30 | * 5. Products derived from this software may not be called "OpenSSL" | |
31 | * nor may "OpenSSL" appear in their names without prior written | |
32 | * permission of the OpenSSL Project. | |
33 | * | |
34 | * 6. Redistributions of any form whatsoever must retain the following | |
35 | * acknowledgment: | |
36 | * "This product includes software developed by the OpenSSL Project | |
37 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
38 | * | |
39 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
40 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
41 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
42 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
43 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
44 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
45 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
46 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
48 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
49 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
50 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
51 | * ==================================================================== | |
52 | * | |
53 | * This product includes cryptographic software written by Eric Young | |
54 | * (eay@cryptsoft.com). This product includes software written by Tim | |
55 | * Hudson (tjh@cryptsoft.com). | |
56 | * | |
57 | */ | |
58 | /* X509 v3 extension utilities */ | |
59 | ||
e527ba09 DSH |
60 | |
61 | #include <stdio.h> | |
9aeaf1b4 | 62 | #include <ctype.h> |
e527ba09 DSH |
63 | #include "cryptlib.h" |
64 | #include "conf.h" | |
9aeaf1b4 DSH |
65 | #include "x509v3.h" |
66 | ||
9aeaf1b4 DSH |
67 | static char *strip_spaces(char *name); |
68 | ||
9aeaf1b4 DSH |
69 | /* Add a CONF_VALUE name value pair to stack */ |
70 | ||
6b691a5c | 71 | int X509V3_add_value(const char *name, const char *value, STACK **extlist) |
9aeaf1b4 DSH |
72 | { |
73 | CONF_VALUE *vtmp = NULL; | |
74 | char *tname = NULL, *tvalue = NULL; | |
9985bed3 DSH |
75 | if(name && !(tname = BUF_strdup(name))) goto err; |
76 | if(value && !(tvalue = BUF_strdup(value))) goto err;; | |
9aeaf1b4 DSH |
77 | if(!(vtmp = (CONF_VALUE *)Malloc(sizeof(CONF_VALUE)))) goto err; |
78 | if(!*extlist && !(*extlist = sk_new(NULL))) goto err; | |
79 | vtmp->section = NULL; | |
80 | vtmp->name = tname; | |
81 | vtmp->value = tvalue; | |
82 | if(!sk_push(*extlist, (char *)vtmp)) goto err; | |
83 | return 1; | |
84 | err: | |
85 | X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE); | |
86 | if(vtmp) Free(vtmp); | |
87 | if(tname) Free(tname); | |
88 | if(tvalue) Free(tvalue); | |
89 | return 0; | |
90 | } | |
91 | ||
61f5b6f3 BL |
92 | int X509V3_add_value_uchar(const char *name, const unsigned char *value, |
93 | STACK **extlist) | |
94 | { | |
95 | return X509V3_add_value(name,(const char *)value,extlist); | |
96 | } | |
97 | ||
9aeaf1b4 DSH |
98 | /* Free function for STACK of CONF_VALUE */ |
99 | ||
6b691a5c | 100 | void X509V3_conf_free(CONF_VALUE *conf) |
9aeaf1b4 DSH |
101 | { |
102 | if(!conf) return; | |
103 | if(conf->name) Free(conf->name); | |
104 | if(conf->value) Free(conf->value); | |
105 | if(conf->section) Free(conf->section); | |
106 | Free((char *)conf); | |
107 | } | |
108 | ||
6b691a5c | 109 | int X509V3_add_value_bool(const char *name, int asn1_bool, STACK **extlist) |
9aeaf1b4 DSH |
110 | { |
111 | if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist); | |
112 | return X509V3_add_value(name, "FALSE", extlist); | |
113 | } | |
114 | ||
6b691a5c | 115 | int X509V3_add_value_bool_nf(char *name, int asn1_bool, STACK **extlist) |
9aeaf1b4 DSH |
116 | { |
117 | if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist); | |
118 | return 1; | |
119 | } | |
120 | ||
c74f1eb9 | 121 | |
6b691a5c | 122 | char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) |
c74f1eb9 DSH |
123 | { |
124 | BIGNUM *bntmp = NULL; | |
125 | char *strtmp = NULL; | |
126 | if(!a) return NULL; | |
127 | if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || | |
128 | !(strtmp = BN_bn2dec(bntmp)) ) | |
129 | X509V3err(X509V3_F_I2S_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE); | |
130 | BN_free(bntmp); | |
131 | return strtmp; | |
132 | } | |
133 | ||
6b691a5c | 134 | char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) |
0ca5f8b1 DSH |
135 | { |
136 | BIGNUM *bntmp = NULL; | |
137 | char *strtmp = NULL; | |
138 | if(!a) return NULL; | |
139 | if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || | |
140 | !(strtmp = BN_bn2dec(bntmp)) ) | |
141 | X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE); | |
142 | BN_free(bntmp); | |
143 | return strtmp; | |
144 | } | |
145 | ||
6b691a5c | 146 | ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) |
28a98809 DSH |
147 | { |
148 | BIGNUM *bn = NULL; | |
149 | ASN1_INTEGER *aint; | |
150 | bn = BN_new(); | |
151 | if(!value) { | |
152 | X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE); | |
153 | return 0; | |
154 | } | |
155 | if(!BN_dec2bn(&bn, value)) { | |
156 | X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR); | |
157 | return 0; | |
158 | } | |
159 | ||
160 | if(!(aint = BN_to_ASN1_INTEGER(bn, NULL))) { | |
161 | X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR); | |
162 | return 0; | |
163 | } | |
164 | BN_free(bn); | |
165 | return aint; | |
166 | } | |
167 | ||
6b691a5c UM |
168 | int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, |
169 | STACK **extlist) | |
9aeaf1b4 | 170 | { |
9aeaf1b4 DSH |
171 | char *strtmp; |
172 | int ret; | |
173 | if(!aint) return 1; | |
0ca5f8b1 | 174 | if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0; |
9aeaf1b4 | 175 | ret = X509V3_add_value(name, strtmp, extlist); |
9aeaf1b4 DSH |
176 | Free(strtmp); |
177 | return ret; | |
178 | } | |
179 | ||
6b691a5c | 180 | int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) |
9aeaf1b4 DSH |
181 | { |
182 | char *btmp; | |
183 | if(!(btmp = value->value)) goto err; | |
184 | if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") | |
185 | || !strcmp(btmp, "Y") || !strcmp(btmp, "y") | |
186 | || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { | |
187 | *asn1_bool = 0xff; | |
188 | return 1; | |
189 | } else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") | |
190 | || !strcmp(btmp, "N") || !strcmp(btmp, "n") | |
191 | || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { | |
192 | *asn1_bool = 0; | |
193 | return 1; | |
194 | } | |
195 | err: | |
28a98809 | 196 | X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,X509V3_R_INVALID_BOOLEAN_STRING); |
9aeaf1b4 DSH |
197 | X509V3_conf_err(value); |
198 | return 0; | |
199 | } | |
200 | ||
6b691a5c | 201 | int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) |
9aeaf1b4 | 202 | { |
28a98809 DSH |
203 | ASN1_INTEGER *itmp; |
204 | if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { | |
9aeaf1b4 DSH |
205 | X509V3_conf_err(value); |
206 | return 0; | |
207 | } | |
28a98809 | 208 | *aint = itmp; |
9aeaf1b4 DSH |
209 | return 1; |
210 | } | |
211 | ||
212 | #define HDR_NAME 1 | |
213 | #define HDR_VALUE 2 | |
214 | ||
215 | /*#define DEBUG*/ | |
216 | ||
6b691a5c | 217 | STACK *X509V3_parse_list(char *line) |
9aeaf1b4 DSH |
218 | { |
219 | char *p, *q, c; | |
220 | char *ntmp, *vtmp; | |
221 | STACK *values = NULL; | |
222 | char *linebuf; | |
223 | int state; | |
224 | /* We are going to modify the line so copy it first */ | |
9985bed3 | 225 | linebuf = BUF_strdup(line); |
9aeaf1b4 DSH |
226 | state = HDR_NAME; |
227 | ntmp = NULL; | |
228 | /* Go through all characters */ | |
229 | for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) { | |
230 | ||
231 | switch(state) { | |
232 | case HDR_NAME: | |
233 | if(c == ':') { | |
234 | state = HDR_VALUE; | |
235 | *p = 0; | |
236 | ntmp = strip_spaces(q); | |
237 | if(!ntmp) { | |
238 | X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); | |
239 | goto err; | |
240 | } | |
241 | q = p + 1; | |
242 | } else if(c == ',') { | |
243 | *p = 0; | |
244 | ntmp = strip_spaces(q); | |
245 | q = p + 1; | |
246 | #ifdef DEBUG | |
247 | printf("%s\n", ntmp); | |
248 | #endif | |
249 | if(!ntmp) { | |
250 | X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); | |
251 | goto err; | |
252 | } | |
253 | X509V3_add_value(ntmp, NULL, &values); | |
254 | } | |
255 | break ; | |
256 | ||
257 | case HDR_VALUE: | |
258 | if(c == ',') { | |
259 | state = HDR_NAME; | |
260 | *p = 0; | |
261 | vtmp = strip_spaces(q); | |
262 | #ifdef DEBUG | |
263 | printf("%s\n", ntmp); | |
264 | #endif | |
265 | if(!vtmp) { | |
266 | X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE); | |
267 | goto err; | |
268 | } | |
269 | X509V3_add_value(ntmp, vtmp, &values); | |
270 | ntmp = NULL; | |
271 | q = p + 1; | |
272 | } | |
273 | ||
274 | } | |
275 | } | |
276 | ||
277 | if(state == HDR_VALUE) { | |
278 | vtmp = strip_spaces(q); | |
279 | #ifdef DEBUG | |
280 | printf("%s=%s\n", ntmp, vtmp); | |
281 | #endif | |
282 | if(!vtmp) { | |
283 | X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE); | |
284 | goto err; | |
285 | } | |
286 | X509V3_add_value(ntmp, vtmp, &values); | |
287 | } else { | |
288 | ntmp = strip_spaces(q); | |
289 | #ifdef DEBUG | |
290 | printf("%s\n", ntmp); | |
291 | #endif | |
292 | if(!ntmp) { | |
293 | X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); | |
294 | goto err; | |
295 | } | |
296 | X509V3_add_value(ntmp, NULL, &values); | |
297 | } | |
298 | Free(linebuf); | |
299 | return values; | |
300 | ||
301 | err: | |
302 | Free(linebuf); | |
303 | sk_pop_free(values, X509V3_conf_free); | |
304 | return NULL; | |
305 | ||
306 | } | |
307 | ||
308 | /* Delete leading and trailing spaces from a string */ | |
6b691a5c | 309 | static char *strip_spaces(char *name) |
9aeaf1b4 DSH |
310 | { |
311 | char *p, *q; | |
312 | /* Skip over leading spaces */ | |
313 | p = name; | |
314 | while(*p && isspace(*p)) p++; | |
315 | if(!*p) return NULL; | |
316 | q = p + strlen(p) - 1; | |
317 | while((q != p) && isspace(*q)) q--; | |
318 | if(p != q) q[1] = 0; | |
319 | if(!*p) return NULL; | |
320 | return p; | |
321 | } | |
175b0942 DSH |
322 | |
323 | /* hex string utilities */ | |
324 | ||
325 | /* Given a buffer of length 'len' return a Malloc'ed string with its | |
326 | * hex representation | |
327 | */ | |
328 | ||
6b691a5c | 329 | char *hex_to_string(unsigned char *buffer, long len) |
175b0942 DSH |
330 | { |
331 | char *tmp, *q; | |
332 | unsigned char *p; | |
333 | int i; | |
334 | static char hexdig[] = "0123456789ABCDEF"; | |
335 | if(!buffer || !len) return NULL; | |
336 | if(!(tmp = Malloc(len * 3 + 1))) { | |
337 | X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE); | |
338 | return NULL; | |
339 | } | |
340 | q = tmp; | |
341 | for(i = 0, p = buffer; i < len; i++,p++) { | |
342 | *q++ = hexdig[(*p >> 4) & 0xf]; | |
343 | *q++ = hexdig[*p & 0xf]; | |
344 | *q++ = ':'; | |
345 | } | |
346 | q[-1] = 0; | |
347 | return tmp; | |
348 | } | |
349 | ||
350 | /* Give a string of hex digits convert to | |
351 | * a buffer | |
352 | */ | |
353 | ||
6b691a5c | 354 | unsigned char *string_to_hex(char *str, long *len) |
175b0942 DSH |
355 | { |
356 | unsigned char *hexbuf, *q; | |
357 | unsigned char ch, cl, *p; | |
358 | if(!str) { | |
359 | X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT); | |
360 | return NULL; | |
361 | } | |
362 | if(!(hexbuf = Malloc(strlen(str) >> 1))) goto err; | |
363 | for(p = (unsigned char *)str, q = hexbuf; *p;) { | |
364 | ch = *p++; | |
365 | if(ch == ':') continue; | |
366 | cl = *p++; | |
367 | if(!cl) { | |
368 | X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS); | |
369 | Free(hexbuf); | |
370 | return NULL; | |
371 | } | |
372 | if(isupper(ch)) ch = tolower(ch); | |
373 | if(isupper(cl)) cl = tolower(cl); | |
374 | ||
375 | if((ch >= '0') && (ch <= '9')) ch -= '0'; | |
376 | else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10; | |
377 | else goto badhex; | |
378 | ||
379 | if((cl >= '0') && (cl <= '9')) cl -= '0'; | |
380 | else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10; | |
381 | else goto badhex; | |
382 | ||
383 | *q++ = (ch << 4) | cl; | |
384 | } | |
385 | ||
386 | if(len) *len = q - hexbuf; | |
387 | ||
388 | return hexbuf; | |
389 | ||
390 | err: | |
391 | if(hexbuf) Free(hexbuf); | |
392 | X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE); | |
393 | return NULL; | |
394 | ||
395 | badhex: | |
396 | Free(hexbuf); | |
397 | X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT); | |
398 | return NULL; | |
399 | ||
400 | } | |
d08d8da4 DSH |
401 | |
402 | /* V2I name comparison function: returns zero if 'name' matches | |
403 | * cmp or cmp.* | |
404 | */ | |
405 | ||
6b691a5c | 406 | int name_cmp(const char *name, const char *cmp) |
d08d8da4 DSH |
407 | { |
408 | int len, ret; | |
409 | char c; | |
410 | len = strlen(cmp); | |
411 | if((ret = strncmp(name, cmp, len))) return ret; | |
412 | c = name[len]; | |
413 | if(!c || (c=='.')) return 0; | |
414 | return 1; | |
415 | } |