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