Line data Source code
1 : /* v3_utl.c */
2 : /*
3 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 : * project.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in
18 : * the documentation and/or other materials provided with the
19 : * distribution.
20 : *
21 : * 3. All advertising materials mentioning features or use of this
22 : * software must display the following acknowledgment:
23 : * "This product includes software developed by the OpenSSL Project
24 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 : *
26 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 : * endorse or promote products derived from this software without
28 : * prior written permission. For written permission, please contact
29 : * licensing@OpenSSL.org.
30 : *
31 : * 5. Products derived from this software may not be called "OpenSSL"
32 : * nor may "OpenSSL" appear in their names without prior written
33 : * permission of the OpenSSL Project.
34 : *
35 : * 6. Redistributions of any form whatsoever must retain the following
36 : * acknowledgment:
37 : * "This product includes software developed by the OpenSSL Project
38 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 : *
40 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : * ====================================================================
53 : *
54 : * This product includes cryptographic software written by Eric Young
55 : * (eay@cryptsoft.com). This product includes software written by Tim
56 : * Hudson (tjh@cryptsoft.com).
57 : *
58 : */
59 : /* X509 v3 extension utilities */
60 :
61 : #include <stdio.h>
62 : #include <ctype.h>
63 : #include "cryptlib.h"
64 : #include <openssl/conf.h>
65 : #include <openssl/x509v3.h>
66 : #include <openssl/bn.h>
67 :
68 : static char *strip_spaces(char *name);
69 : static int sk_strcmp(const char *const *a, const char *const *b);
70 : static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
71 : GENERAL_NAMES *gens);
72 : static void str_free(OPENSSL_STRING str);
73 : static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
74 :
75 : static int ipv4_from_asc(unsigned char *v4, const char *in);
76 : static int ipv6_from_asc(unsigned char *v6, const char *in);
77 : static int ipv6_cb(const char *elem, int len, void *usr);
78 : static int ipv6_hex(unsigned char *out, const char *in, int inlen);
79 :
80 : /* Add a CONF_VALUE name value pair to stack */
81 :
82 0 : int X509V3_add_value(const char *name, const char *value,
83 : STACK_OF(CONF_VALUE) **extlist)
84 : {
85 : CONF_VALUE *vtmp = NULL;
86 : char *tname = NULL, *tvalue = NULL;
87 0 : if (name && !(tname = BUF_strdup(name)))
88 : goto err;
89 0 : if (value && !(tvalue = BUF_strdup(value)))
90 : goto err;
91 0 : if (!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE))))
92 : goto err;
93 0 : if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null()))
94 : goto err;
95 0 : vtmp->section = NULL;
96 0 : vtmp->name = tname;
97 0 : vtmp->value = tvalue;
98 0 : if (!sk_CONF_VALUE_push(*extlist, vtmp))
99 : goto err;
100 : return 1;
101 : err:
102 0 : X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE);
103 0 : if (vtmp)
104 0 : OPENSSL_free(vtmp);
105 0 : if (tname)
106 0 : OPENSSL_free(tname);
107 0 : if (tvalue)
108 0 : OPENSSL_free(tvalue);
109 : return 0;
110 : }
111 :
112 0 : int X509V3_add_value_uchar(const char *name, const unsigned char *value,
113 : STACK_OF(CONF_VALUE) **extlist)
114 : {
115 0 : return X509V3_add_value(name, (const char *)value, extlist);
116 : }
117 :
118 : /* Free function for STACK_OF(CONF_VALUE) */
119 :
120 0 : void X509V3_conf_free(CONF_VALUE *conf)
121 : {
122 0 : if (!conf)
123 0 : return;
124 0 : if (conf->name)
125 0 : OPENSSL_free(conf->name);
126 0 : if (conf->value)
127 0 : OPENSSL_free(conf->value);
128 0 : if (conf->section)
129 0 : OPENSSL_free(conf->section);
130 0 : OPENSSL_free(conf);
131 : }
132 :
133 0 : int X509V3_add_value_bool(const char *name, int asn1_bool,
134 : STACK_OF(CONF_VALUE) **extlist)
135 : {
136 0 : if (asn1_bool)
137 0 : return X509V3_add_value(name, "TRUE", extlist);
138 0 : return X509V3_add_value(name, "FALSE", extlist);
139 : }
140 :
141 0 : int X509V3_add_value_bool_nf(char *name, int asn1_bool,
142 : STACK_OF(CONF_VALUE) **extlist)
143 : {
144 0 : if (asn1_bool)
145 0 : return X509V3_add_value(name, "TRUE", extlist);
146 : return 1;
147 : }
148 :
149 0 : char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
150 : {
151 : BIGNUM *bntmp = NULL;
152 : char *strtmp = NULL;
153 0 : if (!a)
154 : return NULL;
155 0 : if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
156 : !(strtmp = BN_bn2dec(bntmp)))
157 0 : X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
158 0 : BN_free(bntmp);
159 0 : return strtmp;
160 : }
161 :
162 0 : char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
163 : {
164 : BIGNUM *bntmp = NULL;
165 : char *strtmp = NULL;
166 0 : if (!a)
167 : return NULL;
168 0 : if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
169 : !(strtmp = BN_bn2dec(bntmp)))
170 0 : X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
171 0 : BN_free(bntmp);
172 0 : return strtmp;
173 : }
174 :
175 0 : ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
176 : {
177 0 : BIGNUM *bn = NULL;
178 : ASN1_INTEGER *aint;
179 : int isneg, ishex;
180 : int ret;
181 0 : if (!value) {
182 0 : X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE);
183 0 : return 0;
184 : }
185 0 : bn = BN_new();
186 0 : if (value[0] == '-') {
187 0 : value++;
188 : isneg = 1;
189 : } else
190 : isneg = 0;
191 :
192 0 : if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
193 0 : value += 2;
194 0 : ishex = 1;
195 : } else
196 : ishex = 0;
197 :
198 0 : if (ishex)
199 0 : ret = BN_hex2bn(&bn, value);
200 : else
201 0 : ret = BN_dec2bn(&bn, value);
202 :
203 0 : if (!ret || value[ret]) {
204 0 : BN_free(bn);
205 0 : X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR);
206 0 : return 0;
207 : }
208 :
209 0 : if (isneg && BN_is_zero(bn))
210 : isneg = 0;
211 :
212 0 : aint = BN_to_ASN1_INTEGER(bn, NULL);
213 0 : BN_free(bn);
214 0 : if (!aint) {
215 0 : X509V3err(X509V3_F_S2I_ASN1_INTEGER,
216 : X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
217 0 : return 0;
218 : }
219 0 : if (isneg)
220 0 : aint->type |= V_ASN1_NEG;
221 0 : return aint;
222 : }
223 :
224 0 : int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
225 : STACK_OF(CONF_VALUE) **extlist)
226 : {
227 : char *strtmp;
228 : int ret;
229 0 : if (!aint)
230 : return 1;
231 0 : if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
232 : return 0;
233 0 : ret = X509V3_add_value(name, strtmp, extlist);
234 0 : OPENSSL_free(strtmp);
235 0 : return ret;
236 : }
237 :
238 0 : int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
239 : {
240 : char *btmp;
241 0 : if (!(btmp = value->value))
242 : goto err;
243 0 : if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
244 0 : || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
245 0 : || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
246 0 : *asn1_bool = 0xff;
247 0 : return 1;
248 0 : } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
249 0 : || !strcmp(btmp, "N") || !strcmp(btmp, "n")
250 0 : || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
251 0 : *asn1_bool = 0;
252 0 : return 1;
253 : }
254 : err:
255 0 : X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,
256 : X509V3_R_INVALID_BOOLEAN_STRING);
257 0 : X509V3_conf_err(value);
258 0 : return 0;
259 : }
260 :
261 0 : int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
262 : {
263 : ASN1_INTEGER *itmp;
264 0 : if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
265 0 : X509V3_conf_err(value);
266 0 : return 0;
267 : }
268 0 : *aint = itmp;
269 0 : return 1;
270 : }
271 :
272 : #define HDR_NAME 1
273 : #define HDR_VALUE 2
274 :
275 : /*
276 : * #define DEBUG
277 : */
278 :
279 0 : STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
280 : {
281 : char *p, *q, c;
282 : char *ntmp, *vtmp;
283 0 : STACK_OF(CONF_VALUE) *values = NULL;
284 : char *linebuf;
285 : int state;
286 : /* We are going to modify the line so copy it first */
287 0 : linebuf = BUF_strdup(line);
288 0 : if (linebuf == NULL) {
289 0 : X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE);
290 0 : goto err;
291 : }
292 : state = HDR_NAME;
293 : ntmp = NULL;
294 : /* Go through all characters */
295 0 : for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
296 0 : p++) {
297 :
298 0 : switch (state) {
299 : case HDR_NAME:
300 0 : if (c == ':') {
301 : state = HDR_VALUE;
302 0 : *p = 0;
303 0 : ntmp = strip_spaces(q);
304 0 : if (!ntmp) {
305 0 : X509V3err(X509V3_F_X509V3_PARSE_LIST,
306 : X509V3_R_INVALID_NULL_NAME);
307 0 : goto err;
308 : }
309 0 : q = p + 1;
310 0 : } else if (c == ',') {
311 0 : *p = 0;
312 0 : ntmp = strip_spaces(q);
313 0 : q = p + 1;
314 : #if 0
315 : printf("%s\n", ntmp);
316 : #endif
317 0 : if (!ntmp) {
318 0 : X509V3err(X509V3_F_X509V3_PARSE_LIST,
319 : X509V3_R_INVALID_NULL_NAME);
320 0 : goto err;
321 : }
322 0 : X509V3_add_value(ntmp, NULL, &values);
323 : }
324 : break;
325 :
326 : case HDR_VALUE:
327 0 : if (c == ',') {
328 : state = HDR_NAME;
329 0 : *p = 0;
330 0 : vtmp = strip_spaces(q);
331 : #if 0
332 : printf("%s\n", ntmp);
333 : #endif
334 0 : if (!vtmp) {
335 0 : X509V3err(X509V3_F_X509V3_PARSE_LIST,
336 : X509V3_R_INVALID_NULL_VALUE);
337 0 : goto err;
338 : }
339 0 : X509V3_add_value(ntmp, vtmp, &values);
340 : ntmp = NULL;
341 0 : q = p + 1;
342 : }
343 :
344 : }
345 : }
346 :
347 0 : if (state == HDR_VALUE) {
348 0 : vtmp = strip_spaces(q);
349 : #if 0
350 : printf("%s=%s\n", ntmp, vtmp);
351 : #endif
352 0 : if (!vtmp) {
353 0 : X509V3err(X509V3_F_X509V3_PARSE_LIST,
354 : X509V3_R_INVALID_NULL_VALUE);
355 0 : goto err;
356 : }
357 0 : X509V3_add_value(ntmp, vtmp, &values);
358 : } else {
359 0 : ntmp = strip_spaces(q);
360 : #if 0
361 : printf("%s\n", ntmp);
362 : #endif
363 0 : if (!ntmp) {
364 0 : X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
365 0 : goto err;
366 : }
367 0 : X509V3_add_value(ntmp, NULL, &values);
368 : }
369 0 : OPENSSL_free(linebuf);
370 0 : return values;
371 :
372 : err:
373 0 : OPENSSL_free(linebuf);
374 0 : sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
375 0 : return NULL;
376 :
377 : }
378 :
379 : /* Delete leading and trailing spaces from a string */
380 0 : static char *strip_spaces(char *name)
381 : {
382 : char *p, *q;
383 : /* Skip over leading spaces */
384 : p = name;
385 0 : while (*p && isspace((unsigned char)*p))
386 0 : p++;
387 0 : if (!*p)
388 : return NULL;
389 0 : q = p + strlen(p) - 1;
390 0 : while ((q != p) && isspace((unsigned char)*q))
391 0 : q--;
392 0 : if (p != q)
393 0 : q[1] = 0;
394 0 : if (!*p)
395 : return NULL;
396 0 : return p;
397 : }
398 :
399 : /* hex string utilities */
400 :
401 : /*
402 : * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
403 : * hex representation @@@ (Contents of buffer are always kept in ASCII, also
404 : * on EBCDIC machines)
405 : */
406 :
407 0 : char *hex_to_string(const unsigned char *buffer, long len)
408 : {
409 : char *tmp, *q;
410 : const unsigned char *p;
411 : int i;
412 : const static char hexdig[] = "0123456789ABCDEF";
413 0 : if (!buffer || !len)
414 : return NULL;
415 0 : if (!(tmp = OPENSSL_malloc(len * 3 + 1))) {
416 0 : X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE);
417 0 : return NULL;
418 : }
419 : q = tmp;
420 0 : for (i = 0, p = buffer; i < len; i++, p++) {
421 0 : *q++ = hexdig[(*p >> 4) & 0xf];
422 0 : *q++ = hexdig[*p & 0xf];
423 0 : *q++ = ':';
424 : }
425 0 : q[-1] = 0;
426 : #ifdef CHARSET_EBCDIC
427 : ebcdic2ascii(tmp, tmp, q - tmp - 1);
428 : #endif
429 :
430 0 : return tmp;
431 : }
432 :
433 : /*
434 : * Give a string of hex digits convert to a buffer
435 : */
436 :
437 0 : unsigned char *string_to_hex(const char *str, long *len)
438 : {
439 : unsigned char *hexbuf, *q;
440 : unsigned char ch, cl, *p;
441 0 : if (!str) {
442 0 : X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_INVALID_NULL_ARGUMENT);
443 0 : return NULL;
444 : }
445 0 : if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1)))
446 : goto err;
447 0 : for (p = (unsigned char *)str, q = hexbuf; *p;) {
448 0 : ch = *p++;
449 : #ifdef CHARSET_EBCDIC
450 : ch = os_toebcdic[ch];
451 : #endif
452 0 : if (ch == ':')
453 0 : continue;
454 0 : cl = *p++;
455 : #ifdef CHARSET_EBCDIC
456 : cl = os_toebcdic[cl];
457 : #endif
458 0 : if (!cl) {
459 0 : X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ODD_NUMBER_OF_DIGITS);
460 0 : OPENSSL_free(hexbuf);
461 0 : return NULL;
462 : }
463 0 : if (isupper(ch))
464 0 : ch = tolower(ch);
465 0 : if (isupper(cl))
466 0 : cl = tolower(cl);
467 :
468 0 : if ((ch >= '0') && (ch <= '9'))
469 : ch -= '0';
470 0 : else if ((ch >= 'a') && (ch <= 'f'))
471 0 : ch -= 'a' - 10;
472 : else
473 : goto badhex;
474 :
475 0 : if ((cl >= '0') && (cl <= '9'))
476 : cl -= '0';
477 0 : else if ((cl >= 'a') && (cl <= 'f'))
478 0 : cl -= 'a' - 10;
479 : else
480 : goto badhex;
481 :
482 0 : *q++ = (ch << 4) | cl;
483 : }
484 :
485 0 : if (len)
486 0 : *len = q - hexbuf;
487 :
488 0 : return hexbuf;
489 :
490 : err:
491 0 : if (hexbuf)
492 0 : OPENSSL_free(hexbuf);
493 0 : X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE);
494 0 : return NULL;
495 :
496 : badhex:
497 0 : OPENSSL_free(hexbuf);
498 0 : X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT);
499 0 : return NULL;
500 :
501 : }
502 :
503 : /*
504 : * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
505 : */
506 :
507 0 : int name_cmp(const char *name, const char *cmp)
508 : {
509 : int len, ret;
510 : char c;
511 0 : len = strlen(cmp);
512 0 : if ((ret = strncmp(name, cmp, len)))
513 : return ret;
514 0 : c = name[len];
515 0 : if (!c || (c == '.'))
516 : return 0;
517 0 : return 1;
518 : }
519 :
520 0 : static int sk_strcmp(const char *const *a, const char *const *b)
521 : {
522 0 : return strcmp(*a, *b);
523 : }
524 :
525 0 : STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
526 : {
527 : GENERAL_NAMES *gens;
528 : STACK_OF(OPENSSL_STRING) *ret;
529 :
530 0 : gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
531 0 : ret = get_email(X509_get_subject_name(x), gens);
532 0 : sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
533 0 : return ret;
534 : }
535 :
536 0 : STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
537 : {
538 : AUTHORITY_INFO_ACCESS *info;
539 0 : STACK_OF(OPENSSL_STRING) *ret = NULL;
540 : int i;
541 :
542 0 : info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
543 0 : if (!info)
544 : return NULL;
545 0 : for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
546 0 : ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
547 0 : if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
548 0 : if (ad->location->type == GEN_URI) {
549 0 : if (!append_ia5
550 0 : (&ret, ad->location->d.uniformResourceIdentifier))
551 : break;
552 : }
553 : }
554 : }
555 0 : AUTHORITY_INFO_ACCESS_free(info);
556 0 : return ret;
557 : }
558 :
559 0 : STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
560 : {
561 : GENERAL_NAMES *gens;
562 : STACK_OF(X509_EXTENSION) *exts;
563 : STACK_OF(OPENSSL_STRING) *ret;
564 :
565 0 : exts = X509_REQ_get_extensions(x);
566 0 : gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
567 0 : ret = get_email(X509_REQ_get_subject_name(x), gens);
568 0 : sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
569 0 : sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
570 0 : return ret;
571 : }
572 :
573 0 : static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
574 : GENERAL_NAMES *gens)
575 : {
576 0 : STACK_OF(OPENSSL_STRING) *ret = NULL;
577 : X509_NAME_ENTRY *ne;
578 0 : ASN1_IA5STRING *email;
579 : GENERAL_NAME *gen;
580 : int i;
581 : /* Now add any email address(es) to STACK */
582 : i = -1;
583 : /* First supplied X509_NAME */
584 0 : while ((i = X509_NAME_get_index_by_NID(name,
585 : NID_pkcs9_emailAddress, i)) >= 0) {
586 0 : ne = X509_NAME_get_entry(name, i);
587 0 : email = X509_NAME_ENTRY_get_data(ne);
588 0 : if (!append_ia5(&ret, email))
589 : return NULL;
590 : }
591 0 : for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
592 0 : gen = sk_GENERAL_NAME_value(gens, i);
593 0 : if (gen->type != GEN_EMAIL)
594 0 : continue;
595 0 : if (!append_ia5(&ret, gen->d.ia5))
596 : return NULL;
597 : }
598 0 : return ret;
599 : }
600 :
601 0 : static void str_free(OPENSSL_STRING str)
602 : {
603 0 : OPENSSL_free(str);
604 0 : }
605 :
606 0 : static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
607 : {
608 : char *emtmp;
609 : /* First some sanity checks */
610 0 : if (email->type != V_ASN1_IA5STRING)
611 : return 1;
612 0 : if (!email->data || !email->length)
613 : return 1;
614 0 : if (!*sk)
615 0 : *sk = sk_OPENSSL_STRING_new(sk_strcmp);
616 0 : if (!*sk)
617 : return 0;
618 : /* Don't add duplicates */
619 0 : if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
620 : return 1;
621 0 : emtmp = BUF_strdup((char *)email->data);
622 0 : if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
623 0 : X509_email_free(*sk);
624 0 : *sk = NULL;
625 : return 0;
626 : }
627 : return 1;
628 : }
629 :
630 0 : void X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
631 : {
632 0 : sk_OPENSSL_STRING_pop_free(sk, str_free);
633 0 : }
634 :
635 : typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len,
636 : const unsigned char *subject, size_t subject_len,
637 : unsigned int flags);
638 :
639 : /* Skip pattern prefix to match "wildcard" subject */
640 0 : static void skip_prefix(const unsigned char **p, size_t *plen,
641 : const unsigned char *subject, size_t subject_len,
642 : unsigned int flags)
643 : {
644 0 : const unsigned char *pattern = *p;
645 0 : size_t pattern_len = *plen;
646 :
647 : /*
648 : * If subject starts with a leading '.' followed by more octets, and
649 : * pattern is longer, compare just an equal-length suffix with the
650 : * full subject (starting at the '.'), provided the prefix contains
651 : * no NULs.
652 : */
653 0 : if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
654 0 : return;
655 :
656 0 : while (pattern_len > subject_len && *pattern) {
657 0 : if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
658 : *pattern == '.')
659 : break;
660 0 : ++pattern;
661 0 : --pattern_len;
662 : }
663 :
664 : /* Skip if entire prefix acceptable */
665 0 : if (pattern_len == subject_len) {
666 0 : *p = pattern;
667 0 : *plen = pattern_len;
668 : }
669 : }
670 :
671 : /* Compare while ASCII ignoring case. */
672 0 : static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
673 : const unsigned char *subject, size_t subject_len,
674 : unsigned int flags)
675 : {
676 0 : skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
677 0 : if (pattern_len != subject_len)
678 : return 0;
679 0 : while (pattern_len) {
680 0 : unsigned char l = *pattern;
681 0 : unsigned char r = *subject;
682 : /* The pattern must not contain NUL characters. */
683 0 : if (l == 0)
684 : return 0;
685 0 : if (l != r) {
686 0 : if ('A' <= l && l <= 'Z')
687 0 : l = (l - 'A') + 'a';
688 0 : if ('A' <= r && r <= 'Z')
689 0 : r = (r - 'A') + 'a';
690 0 : if (l != r)
691 : return 0;
692 : }
693 0 : ++pattern;
694 0 : ++subject;
695 0 : --pattern_len;
696 : }
697 : return 1;
698 : }
699 :
700 : /* Compare using memcmp. */
701 0 : static int equal_case(const unsigned char *pattern, size_t pattern_len,
702 : const unsigned char *subject, size_t subject_len,
703 : unsigned int flags)
704 : {
705 0 : skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
706 0 : if (pattern_len != subject_len)
707 : return 0;
708 0 : return !memcmp(pattern, subject, pattern_len);
709 : }
710 :
711 : /*
712 : * RFC 5280, section 7.5, requires that only the domain is compared in a
713 : * case-insensitive manner.
714 : */
715 0 : static int equal_email(const unsigned char *a, size_t a_len,
716 : const unsigned char *b, size_t b_len,
717 : unsigned int unused_flags)
718 : {
719 : size_t i = a_len;
720 0 : if (a_len != b_len)
721 : return 0;
722 : /*
723 : * We search backwards for the '@' character, so that we do not have to
724 : * deal with quoted local-parts. The domain part is compared in a
725 : * case-insensitive manner.
726 : */
727 0 : while (i > 0) {
728 0 : --i;
729 0 : if (a[i] == '@' || b[i] == '@') {
730 0 : if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0))
731 : return 0;
732 : break;
733 : }
734 : }
735 0 : if (i == 0)
736 : i = a_len;
737 0 : return equal_case(a, i, b, i, 0);
738 : }
739 :
740 : /*
741 : * Compare the prefix and suffix with the subject, and check that the
742 : * characters in-between are valid.
743 : */
744 0 : static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
745 : const unsigned char *suffix, size_t suffix_len,
746 : const unsigned char *subject, size_t subject_len,
747 : unsigned int flags)
748 : {
749 : const unsigned char *wildcard_start;
750 : const unsigned char *wildcard_end;
751 : const unsigned char *p;
752 : int allow_multi = 0;
753 : int allow_idna = 0;
754 :
755 0 : if (subject_len < prefix_len + suffix_len)
756 : return 0;
757 0 : if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
758 : return 0;
759 0 : wildcard_start = subject + prefix_len;
760 0 : wildcard_end = subject + (subject_len - suffix_len);
761 0 : if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
762 : return 0;
763 : /*
764 : * If the wildcard makes up the entire first label, it must match at
765 : * least one character.
766 : */
767 0 : if (prefix_len == 0 && *suffix == '.') {
768 0 : if (wildcard_start == wildcard_end)
769 : return 0;
770 : allow_idna = 1;
771 0 : if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
772 : allow_multi = 1;
773 : }
774 : /* IDNA labels cannot match partial wildcards */
775 0 : if (!allow_idna &&
776 0 : subject_len >= 4 && strncasecmp((char *)subject, "xn--", 4) == 0)
777 : return 0;
778 : /* The wildcard may match a literal '*' */
779 0 : if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
780 : return 1;
781 : /*
782 : * Check that the part matched by the wildcard contains only
783 : * permitted characters and only matches a single label unless
784 : * allow_multi is set.
785 : */
786 0 : for (p = wildcard_start; p != wildcard_end; ++p)
787 0 : if (!(('0' <= *p && *p <= '9') ||
788 0 : ('A' <= *p && *p <= 'Z') ||
789 0 : ('a' <= *p && *p <= 'z') ||
790 0 : *p == '-' || (allow_multi && *p == '.')))
791 : return 0;
792 : return 1;
793 : }
794 :
795 : #define LABEL_START (1 << 0)
796 : #define LABEL_END (1 << 1)
797 : #define LABEL_HYPHEN (1 << 2)
798 : #define LABEL_IDNA (1 << 3)
799 :
800 0 : static const unsigned char *valid_star(const unsigned char *p, size_t len,
801 : unsigned int flags)
802 : {
803 : const unsigned char *star = 0;
804 : size_t i;
805 : int state = LABEL_START;
806 : int dots = 0;
807 0 : for (i = 0; i < len; ++i) {
808 : /*
809 : * Locate first and only legal wildcard, either at the start
810 : * or end of a non-IDNA first and not final label.
811 : */
812 0 : if (p[i] == '*') {
813 0 : int atstart = (state & LABEL_START);
814 0 : int atend = (i == len - 1 || p[i + 1] == '.');
815 : /*-
816 : * At most one wildcard per pattern.
817 : * No wildcards in IDNA labels.
818 : * No wildcards after the first label.
819 : */
820 0 : if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
821 : return NULL;
822 : /* Only full-label '*.example.com' wildcards? */
823 0 : if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
824 0 : && (!atstart || !atend))
825 : return NULL;
826 : /* No 'foo*bar' wildcards */
827 0 : if (!atstart && !atend)
828 : return NULL;
829 : star = &p[i];
830 0 : state &= ~LABEL_START;
831 0 : } else if (('a' <= p[i] && p[i] <= 'z')
832 0 : || ('A' <= p[i] && p[i] <= 'Z')
833 0 : || ('0' <= p[i] && p[i] <= '9')) {
834 0 : if ((state & LABEL_START) != 0
835 0 : && len - i >= 4 && strncasecmp((char *)&p[i], "xn--", 4) == 0)
836 0 : state |= LABEL_IDNA;
837 0 : state &= ~(LABEL_HYPHEN | LABEL_START);
838 0 : } else if (p[i] == '.') {
839 0 : if ((state & (LABEL_HYPHEN | LABEL_START)) != 0)
840 : return NULL;
841 : state = LABEL_START;
842 0 : ++dots;
843 0 : } else if (p[i] == '-') {
844 0 : if ((state & LABEL_HYPHEN) != 0)
845 : return NULL;
846 0 : state |= LABEL_HYPHEN;
847 : } else
848 : return NULL;
849 : }
850 :
851 : /*
852 : * The final label must not end in a hyphen or ".", and
853 : * there must be at least two dots after the star.
854 : */
855 0 : if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
856 : return NULL;
857 0 : return star;
858 : }
859 :
860 : /* Compare using wildcards. */
861 0 : static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
862 : const unsigned char *subject, size_t subject_len,
863 : unsigned int flags)
864 : {
865 : const unsigned char *star = NULL;
866 :
867 : /*
868 : * Subject names starting with '.' can only match a wildcard pattern
869 : * via a subject sub-domain pattern suffix match.
870 : */
871 0 : if (!(subject_len > 1 && subject[0] == '.'))
872 0 : star = valid_star(pattern, pattern_len, flags);
873 0 : if (star == NULL)
874 0 : return equal_nocase(pattern, pattern_len,
875 : subject, subject_len, flags);
876 0 : return wildcard_match(pattern, star - pattern,
877 0 : star + 1, (pattern + pattern_len) - star - 1,
878 : subject, subject_len, flags);
879 : }
880 :
881 : /*
882 : * Compare an ASN1_STRING to a supplied string. If they match return 1. If
883 : * cmp_type > 0 only compare if string matches the type, otherwise convert it
884 : * to UTF8.
885 : */
886 :
887 0 : static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
888 : unsigned int flags, const char *b, size_t blen,
889 : char **peername)
890 : {
891 : int rv = 0;
892 :
893 0 : if (!a->data || !a->length)
894 : return 0;
895 0 : if (cmp_type > 0) {
896 0 : if (cmp_type != a->type)
897 : return 0;
898 0 : if (cmp_type == V_ASN1_IA5STRING)
899 0 : rv = equal(a->data, a->length, (unsigned char *)b, blen, flags);
900 0 : else if (a->length == (int)blen && !memcmp(a->data, b, blen))
901 : rv = 1;
902 0 : if (rv > 0 && peername)
903 0 : *peername = BUF_strndup((char *)a->data, a->length);
904 : } else {
905 : int astrlen;
906 : unsigned char *astr;
907 0 : astrlen = ASN1_STRING_to_UTF8(&astr, a);
908 0 : if (astrlen < 0) {
909 : /*
910 : * -1 could be an internal malloc failure or a decoding error from
911 : * malformed input; we can't distinguish.
912 : */
913 0 : return -1;
914 : }
915 0 : rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
916 0 : if (rv > 0 && peername)
917 0 : *peername = BUF_strndup((char *)astr, astrlen);
918 0 : OPENSSL_free(astr);
919 : }
920 0 : return rv;
921 : }
922 :
923 0 : static int do_x509_check(X509 *x, const char *chk, size_t chklen,
924 : unsigned int flags, int check_type, char **peername)
925 : {
926 : GENERAL_NAMES *gens = NULL;
927 : X509_NAME *name = NULL;
928 : int i;
929 : int cnid;
930 : int alt_type;
931 : int san_present = 0;
932 : int rv = 0;
933 : equal_fn equal;
934 :
935 : /* See below, this flag is internal-only */
936 0 : flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
937 0 : if (check_type == GEN_EMAIL) {
938 : cnid = NID_pkcs9_emailAddress;
939 : alt_type = V_ASN1_IA5STRING;
940 : equal = equal_email;
941 0 : } else if (check_type == GEN_DNS) {
942 : cnid = NID_commonName;
943 : /* Implicit client-side DNS sub-domain pattern */
944 0 : if (chklen > 1 && chk[0] == '.')
945 0 : flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
946 : alt_type = V_ASN1_IA5STRING;
947 0 : if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
948 : equal = equal_nocase;
949 : else
950 : equal = equal_wildcard;
951 : } else {
952 : cnid = 0;
953 : alt_type = V_ASN1_OCTET_STRING;
954 : equal = equal_case;
955 : }
956 :
957 0 : if (chklen == 0)
958 0 : chklen = strlen(chk);
959 :
960 0 : gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
961 0 : if (gens) {
962 0 : for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
963 : GENERAL_NAME *gen;
964 : ASN1_STRING *cstr;
965 0 : gen = sk_GENERAL_NAME_value(gens, i);
966 0 : if (gen->type != check_type)
967 0 : continue;
968 : san_present = 1;
969 0 : if (check_type == GEN_EMAIL)
970 0 : cstr = gen->d.rfc822Name;
971 0 : else if (check_type == GEN_DNS)
972 0 : cstr = gen->d.dNSName;
973 : else
974 0 : cstr = gen->d.iPAddress;
975 : /* Positive on success, negative on error! */
976 0 : if ((rv = do_check_string(cstr, alt_type, equal, flags,
977 : chk, chklen, peername)) != 0)
978 : break;
979 : }
980 0 : GENERAL_NAMES_free(gens);
981 0 : if (rv != 0)
982 : return rv;
983 0 : if (!cnid
984 0 : || (san_present
985 0 : && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
986 : return 0;
987 : }
988 : i = -1;
989 0 : name = X509_get_subject_name(x);
990 0 : while ((i = X509_NAME_get_index_by_NID(name, cnid, i)) >= 0) {
991 : X509_NAME_ENTRY *ne;
992 : ASN1_STRING *str;
993 0 : ne = X509_NAME_get_entry(name, i);
994 0 : str = X509_NAME_ENTRY_get_data(ne);
995 : /* Positive on success, negative on error! */
996 0 : if ((rv = do_check_string(str, -1, equal, flags,
997 : chk, chklen, peername)) != 0)
998 : return rv;
999 : }
1000 : return 0;
1001 : }
1002 :
1003 0 : int X509_check_host(X509 *x, const char *chk, size_t chklen,
1004 : unsigned int flags, char **peername)
1005 : {
1006 0 : if (chk == NULL)
1007 : return -2;
1008 : /*
1009 : * Embedded NULs are disallowed, except as the last character of a
1010 : * string of length 2 or more (tolerate caller including terminating
1011 : * NUL in string length).
1012 : */
1013 0 : if (chklen == 0)
1014 0 : chklen = strlen(chk);
1015 0 : else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen))
1016 : return -2;
1017 0 : if (chklen > 1 && chk[chklen - 1] == '\0')
1018 : --chklen;
1019 0 : return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
1020 : }
1021 :
1022 0 : int X509_check_email(X509 *x, const char *chk, size_t chklen,
1023 : unsigned int flags)
1024 : {
1025 0 : if (chk == NULL)
1026 : return -2;
1027 : /*
1028 : * Embedded NULs are disallowed, except as the last character of a
1029 : * string of length 2 or more (tolerate caller including terminating
1030 : * NUL in string length).
1031 : */
1032 0 : if (chklen == 0)
1033 0 : chklen = strlen((char *)chk);
1034 0 : else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen))
1035 : return -2;
1036 0 : if (chklen > 1 && chk[chklen - 1] == '\0')
1037 : --chklen;
1038 0 : return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
1039 : }
1040 :
1041 0 : int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
1042 : unsigned int flags)
1043 : {
1044 0 : if (chk == NULL)
1045 : return -2;
1046 0 : return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
1047 : }
1048 :
1049 0 : int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
1050 : {
1051 : unsigned char ipout[16];
1052 : size_t iplen;
1053 :
1054 0 : if (ipasc == NULL)
1055 : return -2;
1056 0 : iplen = (size_t)a2i_ipadd(ipout, ipasc);
1057 0 : if (iplen == 0)
1058 : return -2;
1059 0 : return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
1060 : }
1061 :
1062 : /*
1063 : * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
1064 : * with RFC3280.
1065 : */
1066 :
1067 0 : ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
1068 : {
1069 : unsigned char ipout[16];
1070 : ASN1_OCTET_STRING *ret;
1071 : int iplen;
1072 :
1073 : /* If string contains a ':' assume IPv6 */
1074 :
1075 0 : iplen = a2i_ipadd(ipout, ipasc);
1076 :
1077 0 : if (!iplen)
1078 : return NULL;
1079 :
1080 0 : ret = ASN1_OCTET_STRING_new();
1081 0 : if (!ret)
1082 : return NULL;
1083 0 : if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
1084 0 : ASN1_OCTET_STRING_free(ret);
1085 0 : return NULL;
1086 : }
1087 : return ret;
1088 : }
1089 :
1090 0 : ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
1091 : {
1092 : ASN1_OCTET_STRING *ret = NULL;
1093 : unsigned char ipout[32];
1094 : char *iptmp = NULL, *p;
1095 : int iplen1, iplen2;
1096 0 : p = strchr(ipasc, '/');
1097 0 : if (!p)
1098 : return NULL;
1099 0 : iptmp = BUF_strdup(ipasc);
1100 0 : if (!iptmp)
1101 : return NULL;
1102 0 : p = iptmp + (p - ipasc);
1103 0 : *p++ = 0;
1104 :
1105 0 : iplen1 = a2i_ipadd(ipout, iptmp);
1106 :
1107 0 : if (!iplen1)
1108 : goto err;
1109 :
1110 0 : iplen2 = a2i_ipadd(ipout + iplen1, p);
1111 :
1112 0 : OPENSSL_free(iptmp);
1113 : iptmp = NULL;
1114 :
1115 0 : if (!iplen2 || (iplen1 != iplen2))
1116 : goto err;
1117 :
1118 0 : ret = ASN1_OCTET_STRING_new();
1119 0 : if (!ret)
1120 : goto err;
1121 0 : if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
1122 : goto err;
1123 :
1124 : return ret;
1125 :
1126 : err:
1127 0 : if (iptmp)
1128 0 : OPENSSL_free(iptmp);
1129 0 : if (ret)
1130 0 : ASN1_OCTET_STRING_free(ret);
1131 : return NULL;
1132 : }
1133 :
1134 0 : int a2i_ipadd(unsigned char *ipout, const char *ipasc)
1135 : {
1136 : /* If string contains a ':' assume IPv6 */
1137 :
1138 0 : if (strchr(ipasc, ':')) {
1139 0 : if (!ipv6_from_asc(ipout, ipasc))
1140 : return 0;
1141 0 : return 16;
1142 : } else {
1143 0 : if (!ipv4_from_asc(ipout, ipasc))
1144 : return 0;
1145 0 : return 4;
1146 : }
1147 : }
1148 :
1149 0 : static int ipv4_from_asc(unsigned char *v4, const char *in)
1150 : {
1151 : int a0, a1, a2, a3;
1152 0 : if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
1153 : return 0;
1154 0 : if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
1155 0 : || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
1156 : return 0;
1157 0 : v4[0] = a0;
1158 0 : v4[1] = a1;
1159 0 : v4[2] = a2;
1160 0 : v4[3] = a3;
1161 0 : return 1;
1162 : }
1163 :
1164 : typedef struct {
1165 : /* Temporary store for IPV6 output */
1166 : unsigned char tmp[16];
1167 : /* Total number of bytes in tmp */
1168 : int total;
1169 : /* The position of a zero (corresponding to '::') */
1170 : int zero_pos;
1171 : /* Number of zeroes */
1172 : int zero_cnt;
1173 : } IPV6_STAT;
1174 :
1175 0 : static int ipv6_from_asc(unsigned char *v6, const char *in)
1176 : {
1177 : IPV6_STAT v6stat;
1178 0 : v6stat.total = 0;
1179 0 : v6stat.zero_pos = -1;
1180 0 : v6stat.zero_cnt = 0;
1181 : /*
1182 : * Treat the IPv6 representation as a list of values separated by ':'.
1183 : * The presence of a '::' will parse as one, two or three zero length
1184 : * elements.
1185 : */
1186 0 : if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
1187 : return 0;
1188 :
1189 : /* Now for some sanity checks */
1190 :
1191 0 : if (v6stat.zero_pos == -1) {
1192 : /* If no '::' must have exactly 16 bytes */
1193 0 : if (v6stat.total != 16)
1194 : return 0;
1195 : } else {
1196 : /* If '::' must have less than 16 bytes */
1197 0 : if (v6stat.total == 16)
1198 : return 0;
1199 : /* More than three zeroes is an error */
1200 0 : if (v6stat.zero_cnt > 3)
1201 : return 0;
1202 : /* Can only have three zeroes if nothing else present */
1203 0 : else if (v6stat.zero_cnt == 3) {
1204 0 : if (v6stat.total > 0)
1205 : return 0;
1206 : }
1207 : /* Can only have two zeroes if at start or end */
1208 0 : else if (v6stat.zero_cnt == 2) {
1209 0 : if ((v6stat.zero_pos != 0)
1210 0 : && (v6stat.zero_pos != v6stat.total))
1211 : return 0;
1212 : } else
1213 : /* Can only have one zero if *not* start or end */
1214 : {
1215 0 : if ((v6stat.zero_pos == 0)
1216 0 : || (v6stat.zero_pos == v6stat.total))
1217 : return 0;
1218 : }
1219 : }
1220 :
1221 : /* Format result */
1222 :
1223 0 : if (v6stat.zero_pos >= 0) {
1224 : /* Copy initial part */
1225 0 : memcpy(v6, v6stat.tmp, v6stat.zero_pos);
1226 : /* Zero middle */
1227 0 : memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
1228 : /* Copy final part */
1229 0 : if (v6stat.total != v6stat.zero_pos)
1230 0 : memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
1231 0 : v6stat.tmp + v6stat.zero_pos,
1232 0 : v6stat.total - v6stat.zero_pos);
1233 : } else
1234 : memcpy(v6, v6stat.tmp, 16);
1235 :
1236 : return 1;
1237 : }
1238 :
1239 0 : static int ipv6_cb(const char *elem, int len, void *usr)
1240 : {
1241 : IPV6_STAT *s = usr;
1242 : /* Error if 16 bytes written */
1243 0 : if (s->total == 16)
1244 : return 0;
1245 0 : if (len == 0) {
1246 : /* Zero length element, corresponds to '::' */
1247 0 : if (s->zero_pos == -1)
1248 0 : s->zero_pos = s->total;
1249 : /* If we've already got a :: its an error */
1250 0 : else if (s->zero_pos != s->total)
1251 : return 0;
1252 0 : s->zero_cnt++;
1253 : } else {
1254 : /* If more than 4 characters could be final a.b.c.d form */
1255 0 : if (len > 4) {
1256 : /* Need at least 4 bytes left */
1257 0 : if (s->total > 12)
1258 : return 0;
1259 : /* Must be end of string */
1260 0 : if (elem[len])
1261 : return 0;
1262 0 : if (!ipv4_from_asc(s->tmp + s->total, elem))
1263 : return 0;
1264 0 : s->total += 4;
1265 : } else {
1266 0 : if (!ipv6_hex(s->tmp + s->total, elem, len))
1267 : return 0;
1268 0 : s->total += 2;
1269 : }
1270 : }
1271 : return 1;
1272 : }
1273 :
1274 : /*
1275 : * Convert a string of up to 4 hex digits into the corresponding IPv6 form.
1276 : */
1277 :
1278 0 : static int ipv6_hex(unsigned char *out, const char *in, int inlen)
1279 : {
1280 : unsigned char c;
1281 : unsigned int num = 0;
1282 0 : if (inlen > 4)
1283 : return 0;
1284 0 : while (inlen--) {
1285 0 : c = *in++;
1286 0 : num <<= 4;
1287 0 : if ((c >= '0') && (c <= '9'))
1288 0 : num |= c - '0';
1289 0 : else if ((c >= 'A') && (c <= 'F'))
1290 0 : num |= c - 'A' + 10;
1291 0 : else if ((c >= 'a') && (c <= 'f'))
1292 0 : num |= c - 'a' + 10;
1293 : else
1294 : return 0;
1295 : }
1296 0 : out[0] = num >> 8;
1297 0 : out[1] = num & 0xff;
1298 0 : return 1;
1299 : }
1300 :
1301 0 : int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
1302 : unsigned long chtype)
1303 : {
1304 : CONF_VALUE *v;
1305 : int i, mval;
1306 : char *p, *type;
1307 0 : if (!nm)
1308 : return 0;
1309 :
1310 0 : for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1311 0 : v = sk_CONF_VALUE_value(dn_sk, i);
1312 0 : type = v->name;
1313 : /*
1314 : * Skip past any leading X. X: X, etc to allow for multiple instances
1315 : */
1316 0 : for (p = type; *p; p++)
1317 : #ifndef CHARSET_EBCDIC
1318 0 : if ((*p == ':') || (*p == ',') || (*p == '.'))
1319 : #else
1320 : if ((*p == os_toascii[':']) || (*p == os_toascii[','])
1321 : || (*p == os_toascii['.']))
1322 : #endif
1323 : {
1324 0 : p++;
1325 0 : if (*p)
1326 : type = p;
1327 : break;
1328 : }
1329 : #ifndef CHARSET_EBCDIC
1330 0 : if (*type == '+')
1331 : #else
1332 : if (*type == os_toascii['+'])
1333 : #endif
1334 : {
1335 : mval = -1;
1336 0 : type++;
1337 : } else
1338 : mval = 0;
1339 0 : if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
1340 0 : (unsigned char *)v->value, -1, -1,
1341 : mval))
1342 : return 0;
1343 :
1344 : }
1345 : return 1;
1346 : }
|