diff options
Diffstat (limited to 'src/lib/libcrypto/x509v3/v3_utl.c')
-rw-r--r-- | src/lib/libcrypto/x509v3/v3_utl.c | 925 |
1 files changed, 0 insertions, 925 deletions
diff --git a/src/lib/libcrypto/x509v3/v3_utl.c b/src/lib/libcrypto/x509v3/v3_utl.c deleted file mode 100644 index ee135a0b52..0000000000 --- a/src/lib/libcrypto/x509v3/v3_utl.c +++ /dev/null | |||
@@ -1,925 +0,0 @@ | |||
1 | /* $OpenBSD: v3_utl.c,v 1.24 2015/02/07 13:19:15 doug Exp $ */ | ||
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | ||
3 | * project. | ||
4 | */ | ||
5 | /* ==================================================================== | ||
6 | * Copyright (c) 1999-2003 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 | |||
60 | #include <ctype.h> | ||
61 | #include <stdio.h> | ||
62 | #include <string.h> | ||
63 | |||
64 | #include <openssl/bn.h> | ||
65 | #include <openssl/conf.h> | ||
66 | #include <openssl/err.h> | ||
67 | #include <openssl/x509v3.h> | ||
68 | |||
69 | static char *strip_spaces(char *name); | ||
70 | static int sk_strcmp(const char * const *a, const char * const *b); | ||
71 | static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, | ||
72 | GENERAL_NAMES *gens); | ||
73 | static void str_free(OPENSSL_STRING str); | ||
74 | static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email); | ||
75 | |||
76 | static int ipv4_from_asc(unsigned char *v4, const char *in); | ||
77 | static int ipv6_from_asc(unsigned char *v6, const char *in); | ||
78 | static int ipv6_cb(const char *elem, int len, void *usr); | ||
79 | static int ipv6_hex(unsigned char *out, const char *in, int inlen); | ||
80 | |||
81 | /* Add a CONF_VALUE name value pair to stack */ | ||
82 | |||
83 | int | ||
84 | X509V3_add_value(const char *name, const char *value, | ||
85 | STACK_OF(CONF_VALUE) **extlist) | ||
86 | { | ||
87 | CONF_VALUE *vtmp = NULL; | ||
88 | char *tname = NULL, *tvalue = NULL; | ||
89 | |||
90 | if (name && !(tname = strdup(name))) | ||
91 | goto err; | ||
92 | if (value && !(tvalue = strdup(value))) | ||
93 | goto err; | ||
94 | if (!(vtmp = malloc(sizeof(CONF_VALUE)))) | ||
95 | goto err; | ||
96 | if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) | ||
97 | goto err; | ||
98 | vtmp->section = NULL; | ||
99 | vtmp->name = tname; | ||
100 | vtmp->value = tvalue; | ||
101 | if (!sk_CONF_VALUE_push(*extlist, vtmp)) | ||
102 | goto err; | ||
103 | return 1; | ||
104 | |||
105 | err: | ||
106 | X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE); | ||
107 | free(vtmp); | ||
108 | free(tname); | ||
109 | free(tvalue); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | int | ||
114 | X509V3_add_value_uchar(const char *name, const unsigned char *value, | ||
115 | STACK_OF(CONF_VALUE) **extlist) | ||
116 | { | ||
117 | return X509V3_add_value(name, (const char *)value, extlist); | ||
118 | } | ||
119 | |||
120 | /* Free function for STACK_OF(CONF_VALUE) */ | ||
121 | |||
122 | void | ||
123 | X509V3_conf_free(CONF_VALUE *conf) | ||
124 | { | ||
125 | if (!conf) | ||
126 | return; | ||
127 | free(conf->name); | ||
128 | free(conf->value); | ||
129 | free(conf->section); | ||
130 | free(conf); | ||
131 | } | ||
132 | |||
133 | int | ||
134 | X509V3_add_value_bool(const char *name, int asn1_bool, | ||
135 | STACK_OF(CONF_VALUE) **extlist) | ||
136 | { | ||
137 | if (asn1_bool) | ||
138 | return X509V3_add_value(name, "TRUE", extlist); | ||
139 | return X509V3_add_value(name, "FALSE", extlist); | ||
140 | } | ||
141 | |||
142 | int | ||
143 | X509V3_add_value_bool_nf(char *name, int asn1_bool, | ||
144 | STACK_OF(CONF_VALUE) **extlist) | ||
145 | { | ||
146 | if (asn1_bool) | ||
147 | return X509V3_add_value(name, "TRUE", extlist); | ||
148 | return 1; | ||
149 | } | ||
150 | |||
151 | |||
152 | char * | ||
153 | i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) | ||
154 | { | ||
155 | BIGNUM *bntmp = NULL; | ||
156 | char *strtmp = NULL; | ||
157 | |||
158 | if (!a) | ||
159 | return NULL; | ||
160 | if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || | ||
161 | !(strtmp = BN_bn2dec(bntmp))) | ||
162 | X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE); | ||
163 | BN_free(bntmp); | ||
164 | return strtmp; | ||
165 | } | ||
166 | |||
167 | char * | ||
168 | i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) | ||
169 | { | ||
170 | BIGNUM *bntmp = NULL; | ||
171 | char *strtmp = NULL; | ||
172 | |||
173 | if (!a) | ||
174 | return NULL; | ||
175 | if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || | ||
176 | !(strtmp = BN_bn2dec(bntmp))) | ||
177 | X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); | ||
178 | BN_free(bntmp); | ||
179 | return strtmp; | ||
180 | } | ||
181 | |||
182 | ASN1_INTEGER * | ||
183 | s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) | ||
184 | { | ||
185 | BIGNUM *bn = NULL; | ||
186 | ASN1_INTEGER *aint; | ||
187 | int isneg, ishex; | ||
188 | int ret; | ||
189 | |||
190 | if (!value) { | ||
191 | X509V3err(X509V3_F_S2I_ASN1_INTEGER, | ||
192 | X509V3_R_INVALID_NULL_VALUE); | ||
193 | return 0; | ||
194 | } | ||
195 | bn = BN_new(); | ||
196 | if (value[0] == '-') { | ||
197 | value++; | ||
198 | isneg = 1; | ||
199 | } else | ||
200 | isneg = 0; | ||
201 | |||
202 | if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { | ||
203 | value += 2; | ||
204 | ishex = 1; | ||
205 | } else | ||
206 | ishex = 0; | ||
207 | |||
208 | if (ishex) | ||
209 | ret = BN_hex2bn(&bn, value); | ||
210 | else | ||
211 | ret = BN_dec2bn(&bn, value); | ||
212 | |||
213 | if (!ret || value[ret]) { | ||
214 | BN_free(bn); | ||
215 | X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | if (isneg && BN_is_zero(bn)) | ||
220 | isneg = 0; | ||
221 | |||
222 | aint = BN_to_ASN1_INTEGER(bn, NULL); | ||
223 | BN_free(bn); | ||
224 | if (!aint) { | ||
225 | X509V3err(X509V3_F_S2I_ASN1_INTEGER, | ||
226 | X509V3_R_BN_TO_ASN1_INTEGER_ERROR); | ||
227 | return 0; | ||
228 | } | ||
229 | if (isneg) | ||
230 | aint->type |= V_ASN1_NEG; | ||
231 | return aint; | ||
232 | } | ||
233 | |||
234 | int | ||
235 | X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, | ||
236 | STACK_OF(CONF_VALUE) **extlist) | ||
237 | { | ||
238 | char *strtmp; | ||
239 | int ret; | ||
240 | |||
241 | if (!aint) | ||
242 | return 1; | ||
243 | if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) | ||
244 | return 0; | ||
245 | ret = X509V3_add_value(name, strtmp, extlist); | ||
246 | free(strtmp); | ||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | int | ||
251 | X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) | ||
252 | { | ||
253 | char *btmp; | ||
254 | |||
255 | if (!(btmp = value->value)) | ||
256 | goto err; | ||
257 | if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") || | ||
258 | !strcmp(btmp, "Y") || !strcmp(btmp, "y") || | ||
259 | !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { | ||
260 | *asn1_bool = 0xff; | ||
261 | return 1; | ||
262 | } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") || | ||
263 | !strcmp(btmp, "N") || !strcmp(btmp, "n") || | ||
264 | !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { | ||
265 | *asn1_bool = 0; | ||
266 | return 1; | ||
267 | } | ||
268 | |||
269 | err: | ||
270 | X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL, | ||
271 | X509V3_R_INVALID_BOOLEAN_STRING); | ||
272 | X509V3_conf_err(value); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | int | ||
277 | X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) | ||
278 | { | ||
279 | ASN1_INTEGER *itmp; | ||
280 | |||
281 | if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { | ||
282 | X509V3_conf_err(value); | ||
283 | return 0; | ||
284 | } | ||
285 | *aint = itmp; | ||
286 | return 1; | ||
287 | } | ||
288 | |||
289 | #define HDR_NAME 1 | ||
290 | #define HDR_VALUE 2 | ||
291 | |||
292 | /*#define DEBUG*/ | ||
293 | |||
294 | STACK_OF(CONF_VALUE) * | ||
295 | X509V3_parse_list(const char *line) | ||
296 | { | ||
297 | char *p, *q, c; | ||
298 | char *ntmp, *vtmp; | ||
299 | STACK_OF(CONF_VALUE) *values = NULL; | ||
300 | char *linebuf; | ||
301 | int state; | ||
302 | |||
303 | /* We are going to modify the line so copy it first */ | ||
304 | if ((linebuf = strdup(line)) == NULL) { | ||
305 | X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE); | ||
306 | goto err; | ||
307 | } | ||
308 | state = HDR_NAME; | ||
309 | ntmp = NULL; | ||
310 | |||
311 | /* Go through all characters */ | ||
312 | for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && | ||
313 | (c != '\n'); p++) { | ||
314 | |||
315 | switch (state) { | ||
316 | case HDR_NAME: | ||
317 | if (c == ':') { | ||
318 | state = HDR_VALUE; | ||
319 | *p = 0; | ||
320 | ntmp = strip_spaces(q); | ||
321 | if (!ntmp) { | ||
322 | X509V3err(X509V3_F_X509V3_PARSE_LIST, | ||
323 | X509V3_R_INVALID_NULL_NAME); | ||
324 | goto err; | ||
325 | } | ||
326 | q = p + 1; | ||
327 | } else if (c == ',') { | ||
328 | *p = 0; | ||
329 | ntmp = strip_spaces(q); | ||
330 | q = p + 1; | ||
331 | if (!ntmp) { | ||
332 | X509V3err(X509V3_F_X509V3_PARSE_LIST, | ||
333 | X509V3_R_INVALID_NULL_NAME); | ||
334 | goto err; | ||
335 | } | ||
336 | X509V3_add_value(ntmp, NULL, &values); | ||
337 | } | ||
338 | break; | ||
339 | |||
340 | case HDR_VALUE: | ||
341 | if (c == ',') { | ||
342 | state = HDR_NAME; | ||
343 | *p = 0; | ||
344 | vtmp = strip_spaces(q); | ||
345 | if (!vtmp) { | ||
346 | X509V3err(X509V3_F_X509V3_PARSE_LIST, | ||
347 | X509V3_R_INVALID_NULL_VALUE); | ||
348 | goto err; | ||
349 | } | ||
350 | X509V3_add_value(ntmp, vtmp, &values); | ||
351 | ntmp = NULL; | ||
352 | q = p + 1; | ||
353 | } | ||
354 | |||
355 | } | ||
356 | } | ||
357 | |||
358 | if (state == HDR_VALUE) { | ||
359 | vtmp = strip_spaces(q); | ||
360 | if (!vtmp) { | ||
361 | X509V3err(X509V3_F_X509V3_PARSE_LIST, | ||
362 | X509V3_R_INVALID_NULL_VALUE); | ||
363 | goto err; | ||
364 | } | ||
365 | X509V3_add_value(ntmp, vtmp, &values); | ||
366 | } else { | ||
367 | ntmp = strip_spaces(q); | ||
368 | if (!ntmp) { | ||
369 | X509V3err(X509V3_F_X509V3_PARSE_LIST, | ||
370 | X509V3_R_INVALID_NULL_NAME); | ||
371 | goto err; | ||
372 | } | ||
373 | X509V3_add_value(ntmp, NULL, &values); | ||
374 | } | ||
375 | free(linebuf); | ||
376 | return values; | ||
377 | |||
378 | err: | ||
379 | free(linebuf); | ||
380 | sk_CONF_VALUE_pop_free(values, X509V3_conf_free); | ||
381 | return NULL; | ||
382 | |||
383 | } | ||
384 | |||
385 | /* Delete leading and trailing spaces from a string */ | ||
386 | static char * | ||
387 | strip_spaces(char *name) | ||
388 | { | ||
389 | char *p, *q; | ||
390 | |||
391 | /* Skip over leading spaces */ | ||
392 | p = name; | ||
393 | while (*p && isspace((unsigned char)*p)) | ||
394 | p++; | ||
395 | if (!*p) | ||
396 | return NULL; | ||
397 | q = p + strlen(p) - 1; | ||
398 | while ((q != p) && isspace((unsigned char)*q)) | ||
399 | q--; | ||
400 | if (p != q) | ||
401 | q[1] = 0; | ||
402 | if (!*p) | ||
403 | return NULL; | ||
404 | return p; | ||
405 | } | ||
406 | |||
407 | /* hex string utilities */ | ||
408 | |||
409 | /* Given a buffer of length 'len' return a malloc'ed string with its | ||
410 | * hex representation | ||
411 | */ | ||
412 | char * | ||
413 | hex_to_string(const unsigned char *buffer, long len) | ||
414 | { | ||
415 | char *tmp, *q; | ||
416 | const unsigned char *p; | ||
417 | int i; | ||
418 | static const char hexdig[] = "0123456789ABCDEF"; | ||
419 | |||
420 | if (!buffer || !len) | ||
421 | return NULL; | ||
422 | if (!(tmp = malloc(len * 3 + 1))) { | ||
423 | X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE); | ||
424 | return NULL; | ||
425 | } | ||
426 | q = tmp; | ||
427 | for (i = 0, p = buffer; i < len; i++, p++) { | ||
428 | *q++ = hexdig[(*p >> 4) & 0xf]; | ||
429 | *q++ = hexdig[*p & 0xf]; | ||
430 | *q++ = ':'; | ||
431 | } | ||
432 | q[-1] = 0; | ||
433 | return tmp; | ||
434 | } | ||
435 | |||
436 | /* Give a string of hex digits convert to | ||
437 | * a buffer | ||
438 | */ | ||
439 | |||
440 | unsigned char * | ||
441 | string_to_hex(const char *str, long *len) | ||
442 | { | ||
443 | unsigned char *hexbuf, *q; | ||
444 | unsigned char ch, cl, *p; | ||
445 | if (!str) { | ||
446 | X509V3err(X509V3_F_STRING_TO_HEX, | ||
447 | X509V3_R_INVALID_NULL_ARGUMENT); | ||
448 | return NULL; | ||
449 | } | ||
450 | if (!(hexbuf = malloc(strlen(str) >> 1))) | ||
451 | goto err; | ||
452 | for (p = (unsigned char *)str, q = hexbuf; *p; ) { | ||
453 | ch = *p++; | ||
454 | if (ch == ':') | ||
455 | continue; | ||
456 | cl = *p++; | ||
457 | if (!cl) { | ||
458 | X509V3err(X509V3_F_STRING_TO_HEX, | ||
459 | X509V3_R_ODD_NUMBER_OF_DIGITS); | ||
460 | free(hexbuf); | ||
461 | return NULL; | ||
462 | } | ||
463 | ch = tolower(ch); | ||
464 | cl = tolower(cl); | ||
465 | |||
466 | if ((ch >= '0') && (ch <= '9')) | ||
467 | ch -= '0'; | ||
468 | else if ((ch >= 'a') && (ch <= 'f')) | ||
469 | ch -= 'a' - 10; | ||
470 | else | ||
471 | goto badhex; | ||
472 | |||
473 | if ((cl >= '0') && (cl <= '9')) | ||
474 | cl -= '0'; | ||
475 | else if ((cl >= 'a') && (cl <= 'f')) | ||
476 | cl -= 'a' - 10; | ||
477 | else | ||
478 | goto badhex; | ||
479 | |||
480 | *q++ = (ch << 4) | cl; | ||
481 | } | ||
482 | |||
483 | if (len) | ||
484 | *len = q - hexbuf; | ||
485 | |||
486 | return hexbuf; | ||
487 | |||
488 | err: | ||
489 | free(hexbuf); | ||
490 | X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE); | ||
491 | return NULL; | ||
492 | |||
493 | badhex: | ||
494 | free(hexbuf); | ||
495 | X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT); | ||
496 | return NULL; | ||
497 | } | ||
498 | |||
499 | /* V2I name comparison function: returns zero if 'name' matches | ||
500 | * cmp or cmp.* | ||
501 | */ | ||
502 | |||
503 | int | ||
504 | name_cmp(const char *name, const char *cmp) | ||
505 | { | ||
506 | int len, ret; | ||
507 | char c; | ||
508 | |||
509 | len = strlen(cmp); | ||
510 | if ((ret = strncmp(name, cmp, len))) | ||
511 | return ret; | ||
512 | c = name[len]; | ||
513 | if (!c || (c=='.')) | ||
514 | return 0; | ||
515 | return 1; | ||
516 | } | ||
517 | |||
518 | static int | ||
519 | sk_strcmp(const char * const *a, const char * const *b) | ||
520 | { | ||
521 | return strcmp(*a, *b); | ||
522 | } | ||
523 | |||
524 | STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x) | ||
525 | { | ||
526 | GENERAL_NAMES *gens; | ||
527 | STACK_OF(OPENSSL_STRING) *ret; | ||
528 | |||
529 | gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); | ||
530 | ret = get_email(X509_get_subject_name(x), gens); | ||
531 | sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); | ||
532 | return ret; | ||
533 | } | ||
534 | |||
535 | STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x) | ||
536 | { | ||
537 | AUTHORITY_INFO_ACCESS *info; | ||
538 | STACK_OF(OPENSSL_STRING) *ret = NULL; | ||
539 | int i; | ||
540 | |||
541 | info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); | ||
542 | if (!info) | ||
543 | return NULL; | ||
544 | for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { | ||
545 | ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); | ||
546 | if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { | ||
547 | if (ad->location->type == GEN_URI) { | ||
548 | if (!append_ia5(&ret, | ||
549 | ad->location->d.uniformResourceIdentifier)) | ||
550 | break; | ||
551 | } | ||
552 | } | ||
553 | } | ||
554 | AUTHORITY_INFO_ACCESS_free(info); | ||
555 | return ret; | ||
556 | } | ||
557 | |||
558 | STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x) | ||
559 | { | ||
560 | GENERAL_NAMES *gens; | ||
561 | STACK_OF(X509_EXTENSION) *exts; | ||
562 | STACK_OF(OPENSSL_STRING) *ret; | ||
563 | |||
564 | exts = X509_REQ_get_extensions(x); | ||
565 | gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); | ||
566 | ret = get_email(X509_REQ_get_subject_name(x), gens); | ||
567 | sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); | ||
568 | sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); | ||
569 | return ret; | ||
570 | } | ||
571 | |||
572 | |||
573 | static | ||
574 | STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens) | ||
575 | { | ||
576 | STACK_OF(OPENSSL_STRING) *ret = NULL; | ||
577 | X509_NAME_ENTRY *ne; | ||
578 | ASN1_IA5STRING *email; | ||
579 | GENERAL_NAME *gen; | ||
580 | int i; | ||
581 | |||
582 | /* Now add any email address(es) to STACK */ | ||
583 | i = -1; | ||
584 | |||
585 | /* First supplied X509_NAME */ | ||
586 | while ((i = X509_NAME_get_index_by_NID(name, | ||
587 | NID_pkcs9_emailAddress, i)) >= 0) { | ||
588 | ne = X509_NAME_get_entry(name, i); | ||
589 | email = X509_NAME_ENTRY_get_data(ne); | ||
590 | if (!append_ia5(&ret, email)) | ||
591 | return NULL; | ||
592 | } | ||
593 | for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { | ||
594 | gen = sk_GENERAL_NAME_value(gens, i); | ||
595 | if (gen->type != GEN_EMAIL) | ||
596 | continue; | ||
597 | if (!append_ia5(&ret, gen->d.ia5)) | ||
598 | return NULL; | ||
599 | } | ||
600 | return ret; | ||
601 | } | ||
602 | |||
603 | static void | ||
604 | str_free(OPENSSL_STRING str) | ||
605 | { | ||
606 | free(str); | ||
607 | } | ||
608 | |||
609 | static int | ||
610 | append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) | ||
611 | { | ||
612 | char *emtmp; | ||
613 | |||
614 | /* First some sanity checks */ | ||
615 | if (email->type != V_ASN1_IA5STRING) | ||
616 | return 1; | ||
617 | if (!email->data || !email->length) | ||
618 | return 1; | ||
619 | if (!*sk) | ||
620 | *sk = sk_OPENSSL_STRING_new(sk_strcmp); | ||
621 | if (!*sk) | ||
622 | return 0; | ||
623 | /* Don't add duplicates */ | ||
624 | if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1) | ||
625 | return 1; | ||
626 | emtmp = strdup((char *)email->data); | ||
627 | if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) { | ||
628 | X509_email_free(*sk); | ||
629 | *sk = NULL; | ||
630 | return 0; | ||
631 | } | ||
632 | return 1; | ||
633 | } | ||
634 | |||
635 | void | ||
636 | X509_email_free(STACK_OF(OPENSSL_STRING) *sk) | ||
637 | { | ||
638 | sk_OPENSSL_STRING_pop_free(sk, str_free); | ||
639 | } | ||
640 | |||
641 | /* Convert IP addresses both IPv4 and IPv6 into an | ||
642 | * OCTET STRING compatible with RFC3280. | ||
643 | */ | ||
644 | |||
645 | ASN1_OCTET_STRING * | ||
646 | a2i_IPADDRESS(const char *ipasc) | ||
647 | { | ||
648 | unsigned char ipout[16]; | ||
649 | ASN1_OCTET_STRING *ret; | ||
650 | int iplen; | ||
651 | |||
652 | /* If string contains a ':' assume IPv6 */ | ||
653 | |||
654 | iplen = a2i_ipadd(ipout, ipasc); | ||
655 | |||
656 | if (!iplen) | ||
657 | return NULL; | ||
658 | |||
659 | ret = ASN1_OCTET_STRING_new(); | ||
660 | if (!ret) | ||
661 | return NULL; | ||
662 | if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { | ||
663 | ASN1_OCTET_STRING_free(ret); | ||
664 | return NULL; | ||
665 | } | ||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | ASN1_OCTET_STRING * | ||
670 | a2i_IPADDRESS_NC(const char *ipasc) | ||
671 | { | ||
672 | ASN1_OCTET_STRING *ret = NULL; | ||
673 | unsigned char ipout[32]; | ||
674 | char *iptmp = NULL, *p; | ||
675 | int iplen1, iplen2; | ||
676 | |||
677 | p = strchr(ipasc, '/'); | ||
678 | if (!p) | ||
679 | return NULL; | ||
680 | iptmp = strdup(ipasc); | ||
681 | if (!iptmp) | ||
682 | return NULL; | ||
683 | p = iptmp + (p - ipasc); | ||
684 | *p++ = 0; | ||
685 | |||
686 | iplen1 = a2i_ipadd(ipout, iptmp); | ||
687 | |||
688 | if (!iplen1) | ||
689 | goto err; | ||
690 | |||
691 | iplen2 = a2i_ipadd(ipout + iplen1, p); | ||
692 | |||
693 | free(iptmp); | ||
694 | iptmp = NULL; | ||
695 | |||
696 | if (!iplen2 || (iplen1 != iplen2)) | ||
697 | goto err; | ||
698 | |||
699 | ret = ASN1_OCTET_STRING_new(); | ||
700 | if (!ret) | ||
701 | goto err; | ||
702 | if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) | ||
703 | goto err; | ||
704 | |||
705 | return ret; | ||
706 | |||
707 | err: | ||
708 | free(iptmp); | ||
709 | if (ret) | ||
710 | ASN1_OCTET_STRING_free(ret); | ||
711 | return NULL; | ||
712 | } | ||
713 | |||
714 | |||
715 | int | ||
716 | a2i_ipadd(unsigned char *ipout, const char *ipasc) | ||
717 | { | ||
718 | /* If string contains a ':' assume IPv6 */ | ||
719 | |||
720 | if (strchr(ipasc, ':')) { | ||
721 | if (!ipv6_from_asc(ipout, ipasc)) | ||
722 | return 0; | ||
723 | return 16; | ||
724 | } else { | ||
725 | if (!ipv4_from_asc(ipout, ipasc)) | ||
726 | return 0; | ||
727 | return 4; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | static int | ||
732 | ipv4_from_asc(unsigned char *v4, const char *in) | ||
733 | { | ||
734 | int a0, a1, a2, a3; | ||
735 | if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) | ||
736 | return 0; | ||
737 | if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) || | ||
738 | (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) | ||
739 | return 0; | ||
740 | v4[0] = a0; | ||
741 | v4[1] = a1; | ||
742 | v4[2] = a2; | ||
743 | v4[3] = a3; | ||
744 | return 1; | ||
745 | } | ||
746 | |||
747 | typedef struct { | ||
748 | /* Temporary store for IPV6 output */ | ||
749 | unsigned char tmp[16]; | ||
750 | /* Total number of bytes in tmp */ | ||
751 | int total; | ||
752 | /* The position of a zero (corresponding to '::') */ | ||
753 | int zero_pos; | ||
754 | /* Number of zeroes */ | ||
755 | int zero_cnt; | ||
756 | } IPV6_STAT; | ||
757 | |||
758 | |||
759 | static int | ||
760 | ipv6_from_asc(unsigned char *v6, const char *in) | ||
761 | { | ||
762 | IPV6_STAT v6stat; | ||
763 | |||
764 | v6stat.total = 0; | ||
765 | v6stat.zero_pos = -1; | ||
766 | v6stat.zero_cnt = 0; | ||
767 | |||
768 | /* Treat the IPv6 representation as a list of values | ||
769 | * separated by ':'. The presence of a '::' will parse | ||
770 | * as one, two or three zero length elements. | ||
771 | */ | ||
772 | if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) | ||
773 | return 0; | ||
774 | |||
775 | /* Now for some sanity checks */ | ||
776 | |||
777 | if (v6stat.zero_pos == -1) { | ||
778 | /* If no '::' must have exactly 16 bytes */ | ||
779 | if (v6stat.total != 16) | ||
780 | return 0; | ||
781 | } else { | ||
782 | /* If '::' must have less than 16 bytes */ | ||
783 | if (v6stat.total == 16) | ||
784 | return 0; | ||
785 | /* More than three zeroes is an error */ | ||
786 | if (v6stat.zero_cnt > 3) | ||
787 | return 0; | ||
788 | /* Can only have three zeroes if nothing else present */ | ||
789 | else if (v6stat.zero_cnt == 3) { | ||
790 | if (v6stat.total > 0) | ||
791 | return 0; | ||
792 | } | ||
793 | /* Can only have two zeroes if at start or end */ | ||
794 | else if (v6stat.zero_cnt == 2) { | ||
795 | if ((v6stat.zero_pos != 0) && | ||
796 | (v6stat.zero_pos != v6stat.total)) | ||
797 | return 0; | ||
798 | } else | ||
799 | /* Can only have one zero if *not* start or end */ | ||
800 | { | ||
801 | if ((v6stat.zero_pos == 0) || | ||
802 | (v6stat.zero_pos == v6stat.total)) | ||
803 | return 0; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | /* Format result */ | ||
808 | |||
809 | if (v6stat.zero_pos >= 0) { | ||
810 | /* Copy initial part */ | ||
811 | memcpy(v6, v6stat.tmp, v6stat.zero_pos); | ||
812 | /* Zero middle */ | ||
813 | memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); | ||
814 | /* Copy final part */ | ||
815 | if (v6stat.total != v6stat.zero_pos) | ||
816 | memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, | ||
817 | v6stat.tmp + v6stat.zero_pos, | ||
818 | v6stat.total - v6stat.zero_pos); | ||
819 | } else | ||
820 | memcpy(v6, v6stat.tmp, 16); | ||
821 | |||
822 | return 1; | ||
823 | } | ||
824 | |||
825 | static int | ||
826 | ipv6_cb(const char *elem, int len, void *usr) | ||
827 | { | ||
828 | IPV6_STAT *s = usr; | ||
829 | |||
830 | /* Error if 16 bytes written */ | ||
831 | if (s->total == 16) | ||
832 | return 0; | ||
833 | if (len == 0) { | ||
834 | /* Zero length element, corresponds to '::' */ | ||
835 | if (s->zero_pos == -1) | ||
836 | s->zero_pos = s->total; | ||
837 | /* If we've already got a :: its an error */ | ||
838 | else if (s->zero_pos != s->total) | ||
839 | return 0; | ||
840 | s->zero_cnt++; | ||
841 | } else { | ||
842 | /* If more than 4 characters could be final a.b.c.d form */ | ||
843 | if (len > 4) { | ||
844 | /* Need at least 4 bytes left */ | ||
845 | if (s->total > 12) | ||
846 | return 0; | ||
847 | /* Must be end of string */ | ||
848 | if (elem[len]) | ||
849 | return 0; | ||
850 | if (!ipv4_from_asc(s->tmp + s->total, elem)) | ||
851 | return 0; | ||
852 | s->total += 4; | ||
853 | } else { | ||
854 | if (!ipv6_hex(s->tmp + s->total, elem, len)) | ||
855 | return 0; | ||
856 | s->total += 2; | ||
857 | } | ||
858 | } | ||
859 | return 1; | ||
860 | } | ||
861 | |||
862 | /* Convert a string of up to 4 hex digits into the corresponding | ||
863 | * IPv6 form. | ||
864 | */ | ||
865 | |||
866 | static int | ||
867 | ipv6_hex(unsigned char *out, const char *in, int inlen) | ||
868 | { | ||
869 | unsigned char c; | ||
870 | unsigned int num = 0; | ||
871 | |||
872 | if (inlen > 4) | ||
873 | return 0; | ||
874 | while (inlen--) { | ||
875 | c = *in++; | ||
876 | num <<= 4; | ||
877 | if ((c >= '0') && (c <= '9')) | ||
878 | num |= c - '0'; | ||
879 | else if ((c >= 'A') && (c <= 'F')) | ||
880 | num |= c - 'A' + 10; | ||
881 | else if ((c >= 'a') && (c <= 'f')) | ||
882 | num |= c - 'a' + 10; | ||
883 | else | ||
884 | return 0; | ||
885 | } | ||
886 | out[0] = num >> 8; | ||
887 | out[1] = num & 0xff; | ||
888 | return 1; | ||
889 | } | ||
890 | |||
891 | int | ||
892 | X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk, | ||
893 | unsigned long chtype) | ||
894 | { | ||
895 | CONF_VALUE *v; | ||
896 | int i, mval; | ||
897 | char *p, *type; | ||
898 | |||
899 | if (!nm) | ||
900 | return 0; | ||
901 | |||
902 | for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { | ||
903 | v = sk_CONF_VALUE_value(dn_sk, i); | ||
904 | type = v->name; | ||
905 | /* Skip past any leading X. X: X, etc to allow for | ||
906 | * multiple instances | ||
907 | */ | ||
908 | for (p = type; *p; p++) | ||
909 | if ((*p == ':') || (*p == ',') || (*p == '.')) { | ||
910 | p++; | ||
911 | if (*p) | ||
912 | type = p; | ||
913 | break; | ||
914 | } | ||
915 | if (*type == '+') { | ||
916 | mval = -1; | ||
917 | type++; | ||
918 | } else | ||
919 | mval = 0; | ||
920 | if (!X509_NAME_add_entry_by_txt(nm, type, chtype, | ||
921 | (unsigned char *) v->value, -1, -1, mval)) | ||
922 | return 0; | ||
923 | } | ||
924 | return 1; | ||
925 | } | ||