1 /* $OpenBSD: x509_utl.c,v 1.26 2025/01/26 13:51:41 tb 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
59 #include <ctype.h>
60 #include <limits.h>
61 #include <stdio.h>
62 #include <string.h>
63
64 #include <openssl/asn1.h>
65 #include <openssl/bn.h>
66 #include <openssl/conf.h>
67 #include <openssl/err.h>
68 #include <openssl/x509v3.h>
69
70 #include "bytestring.h"
71 #include "conf_local.h"
72
73 /*
74 * Match reference identifiers starting with "." to any sub-domain. This
75 * flag is set implicitly when the subject reference identity is a DNS name.
76 */
77 #define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000
78
79 static char *bn_to_string(const BIGNUM *bn);
80 static char *strip_spaces(char *name);
81 static int sk_strcmp(const char * const *a, const char * const *b);
82 static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
83 GENERAL_NAMES *gens);
84 static void str_free(OPENSSL_STRING str);
85 static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
86
87 static int ipv4_from_asc(unsigned char *v4, const char *in);
88 static int ipv6_from_asc(unsigned char *v6, const char *in);
89 static int ipv6_cb(const char *elem, int len, void *usr);
90 static int ipv6_hex(unsigned char *out, const char *in, int inlen);
91
92 /* Add a CONF_VALUE name-value pair to stack. */
93 int
X509V3_add_value(const char * name,const char * value,STACK_OF (CONF_VALUE)** out_extlist)94 X509V3_add_value(const char *name, const char *value,
95 STACK_OF(CONF_VALUE) **out_extlist)
96 {
97 STACK_OF(CONF_VALUE) *extlist = NULL;
98 CONF_VALUE *conf_value = NULL;
99 int ret = 0;
100
101 if ((conf_value = calloc(1, sizeof(*conf_value))) == NULL) {
102 X509V3error(ERR_R_MALLOC_FAILURE);
103 goto err;
104 }
105 if (name != NULL) {
106 if ((conf_value->name = strdup(name)) == NULL) {
107 X509V3error(ERR_R_MALLOC_FAILURE);
108 goto err;
109 }
110 }
111 if (value != NULL) {
112 if ((conf_value->value = strdup(value)) == NULL) {
113 X509V3error(ERR_R_MALLOC_FAILURE);
114 goto err;
115 }
116 }
117
118 if ((extlist = *out_extlist) == NULL)
119 extlist = sk_CONF_VALUE_new_null();
120 if (extlist == NULL) {
121 X509V3error(ERR_R_MALLOC_FAILURE);
122 goto err;
123 }
124
125 if (!sk_CONF_VALUE_push(extlist, conf_value)) {
126 X509V3error(ERR_R_MALLOC_FAILURE);
127 goto err;
128 }
129 conf_value = NULL;
130
131 *out_extlist = extlist;
132 extlist = NULL;
133
134 ret = 1;
135
136 err:
137 if (extlist != *out_extlist)
138 sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free);
139 X509V3_conf_free(conf_value);
140
141 return ret;
142 }
143
144 int
X509V3_add_value_uchar(const char * name,const unsigned char * value,STACK_OF (CONF_VALUE)** extlist)145 X509V3_add_value_uchar(const char *name, const unsigned char *value,
146 STACK_OF(CONF_VALUE) **extlist)
147 {
148 return X509V3_add_value(name, (const char *)value, extlist);
149 }
150
151 /* Free function for STACK_OF(CONF_VALUE) */
152
153 void
X509V3_conf_free(CONF_VALUE * conf)154 X509V3_conf_free(CONF_VALUE *conf)
155 {
156 if (!conf)
157 return;
158 free(conf->name);
159 free(conf->value);
160 free(conf->section);
161 free(conf);
162 }
163 LCRYPTO_ALIAS(X509V3_conf_free);
164
165 int
X509V3_add_value_bool(const char * name,int asn1_bool,STACK_OF (CONF_VALUE)** extlist)166 X509V3_add_value_bool(const char *name, int asn1_bool,
167 STACK_OF(CONF_VALUE) **extlist)
168 {
169 if (asn1_bool)
170 return X509V3_add_value(name, "TRUE", extlist);
171 return X509V3_add_value(name, "FALSE", extlist);
172 }
173
174 static char *
bn_to_string(const BIGNUM * bn)175 bn_to_string(const BIGNUM *bn)
176 {
177 const char *sign = "";
178 char *bnstr, *hex;
179 char *ret = NULL;
180
181 /* Only display small numbers in decimal, as conversion is quadratic. */
182 if (BN_num_bits(bn) < 128)
183 return BN_bn2dec(bn);
184
185 if ((hex = bnstr = BN_bn2hex(bn)) == NULL)
186 goto err;
187
188 if (BN_is_negative(bn)) {
189 sign = "-";
190 hex++;
191 }
192
193 if (asprintf(&ret, "%s0x%s", sign, hex) == -1)
194 ret = NULL;
195
196 err:
197 free(bnstr);
198 return ret;
199 }
200
201 char *
i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD * method,const ASN1_ENUMERATED * a)202 i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a)
203 {
204 BIGNUM *bntmp;
205 char *strtmp = NULL;
206
207 if (a == NULL)
208 return NULL;
209 if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL ||
210 (strtmp = bn_to_string(bntmp)) == NULL)
211 X509V3error(ERR_R_MALLOC_FAILURE);
212 BN_free(bntmp);
213 return strtmp;
214 }
215 LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED);
216
217 char *
i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD * method,const ASN1_ENUMERATED * e)218 i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *e)
219 {
220 const BIT_STRING_BITNAME *enam;
221 long strval;
222
223 strval = ASN1_ENUMERATED_get(e);
224 for (enam = method->usr_data; enam->lname; enam++) {
225 if (strval == enam->bitnum)
226 return strdup(enam->lname);
227 }
228 return i2s_ASN1_ENUMERATED(method, e);
229 }
230 LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED_TABLE);
231
232 char *
i2s_ASN1_INTEGER(X509V3_EXT_METHOD * method,const ASN1_INTEGER * a)233 i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a)
234 {
235 BIGNUM *bntmp;
236 char *strtmp = NULL;
237
238 if (a == NULL)
239 return NULL;
240 if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL ||
241 (strtmp = bn_to_string(bntmp)) == NULL)
242 X509V3error(ERR_R_MALLOC_FAILURE);
243 BN_free(bntmp);
244 return strtmp;
245 }
246 LCRYPTO_ALIAS(i2s_ASN1_INTEGER);
247
248 ASN1_INTEGER *
s2i_ASN1_INTEGER(X509V3_EXT_METHOD * method,const char * value)249 s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
250 {
251 BIGNUM *bn = NULL;
252 ASN1_INTEGER *aint;
253 int isneg = 0, ishex = 0;
254 int ret;
255
256 if (!value) {
257 X509V3error(X509V3_R_INVALID_NULL_VALUE);
258 return NULL;
259 }
260 if ((bn = BN_new()) == NULL) {
261 X509V3error(ERR_R_MALLOC_FAILURE);
262 return NULL;
263 }
264 if (value[0] == '-') {
265 value++;
266 isneg = 1;
267 }
268
269 if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
270 value += 2;
271 ishex = 1;
272 }
273
274 if (ishex)
275 ret = BN_hex2bn(&bn, value);
276 else
277 ret = BN_dec2bn(&bn, value);
278
279 if (!ret || value[ret]) {
280 BN_free(bn);
281 X509V3error(X509V3_R_BN_DEC2BN_ERROR);
282 return NULL;
283 }
284
285 if (BN_is_zero(bn))
286 isneg = 0;
287
288 aint = BN_to_ASN1_INTEGER(bn, NULL);
289 BN_free(bn);
290 if (!aint) {
291 X509V3error(X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
292 return NULL;
293 }
294 if (isneg)
295 aint->type |= V_ASN1_NEG;
296 return aint;
297 }
298 LCRYPTO_ALIAS(s2i_ASN1_INTEGER);
299
300 int
X509V3_add_value_int(const char * name,const ASN1_INTEGER * aint,STACK_OF (CONF_VALUE)** extlist)301 X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint,
302 STACK_OF(CONF_VALUE) **extlist)
303 {
304 char *strtmp;
305 int ret;
306
307 if (!aint)
308 return 1;
309 if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
310 return 0;
311 ret = X509V3_add_value(name, strtmp, extlist);
312 free(strtmp);
313 return ret;
314 }
315
316 int
X509V3_get_value_bool(const CONF_VALUE * value,int * asn1_bool)317 X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool)
318 {
319 char *btmp;
320
321 if (!(btmp = value->value))
322 goto err;
323 if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") ||
324 !strcmp(btmp, "Y") || !strcmp(btmp, "y") ||
325 !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
326 *asn1_bool = 0xff;
327 return 1;
328 } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") ||
329 !strcmp(btmp, "N") || !strcmp(btmp, "n") ||
330 !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
331 *asn1_bool = 0;
332 return 1;
333 }
334
335 err:
336 X509V3error(X509V3_R_INVALID_BOOLEAN_STRING);
337 X509V3_conf_err(value);
338 return 0;
339 }
340
341 int
X509V3_get_value_int(const CONF_VALUE * value,ASN1_INTEGER ** aint)342 X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint)
343 {
344 ASN1_INTEGER *itmp;
345
346 if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
347 X509V3_conf_err(value);
348 return 0;
349 }
350 *aint = itmp;
351 return 1;
352 }
353
354 #define HDR_NAME 1
355 #define HDR_VALUE 2
356
357 /*#define DEBUG*/
358
STACK_OF(CONF_VALUE)359 STACK_OF(CONF_VALUE) *
360 X509V3_parse_list(const char *line)
361 {
362 char *p, *q, c;
363 char *ntmp, *vtmp;
364 STACK_OF(CONF_VALUE) *values = NULL;
365 char *linebuf;
366 int state;
367
368 /* We are going to modify the line so copy it first */
369 if ((linebuf = strdup(line)) == NULL) {
370 X509V3error(ERR_R_MALLOC_FAILURE);
371 goto err;
372 }
373 state = HDR_NAME;
374 ntmp = NULL;
375
376 /* Go through all characters */
377 for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') &&
378 (c != '\n'); p++) {
379
380 switch (state) {
381 case HDR_NAME:
382 if (c == ':') {
383 state = HDR_VALUE;
384 *p = 0;
385 ntmp = strip_spaces(q);
386 if (!ntmp) {
387 X509V3error(X509V3_R_INVALID_NULL_NAME);
388 goto err;
389 }
390 q = p + 1;
391 } else if (c == ',') {
392 *p = 0;
393 ntmp = strip_spaces(q);
394 q = p + 1;
395 if (!ntmp) {
396 X509V3error(X509V3_R_INVALID_NULL_NAME);
397 goto err;
398 }
399 if (!X509V3_add_value(ntmp, NULL, &values))
400 goto err;
401 }
402 break;
403
404 case HDR_VALUE:
405 if (c == ',') {
406 state = HDR_NAME;
407 *p = 0;
408 vtmp = strip_spaces(q);
409 if (!vtmp) {
410 X509V3error(X509V3_R_INVALID_NULL_VALUE);
411 goto err;
412 }
413 if (!X509V3_add_value(ntmp, vtmp, &values))
414 goto err;
415 ntmp = NULL;
416 q = p + 1;
417 }
418
419 }
420 }
421
422 if (state == HDR_VALUE) {
423 vtmp = strip_spaces(q);
424 if (!vtmp) {
425 X509V3error(X509V3_R_INVALID_NULL_VALUE);
426 goto err;
427 }
428 if (!X509V3_add_value(ntmp, vtmp, &values))
429 goto err;
430 } else {
431 ntmp = strip_spaces(q);
432 if (!ntmp) {
433 X509V3error(X509V3_R_INVALID_NULL_NAME);
434 goto err;
435 }
436 if (!X509V3_add_value(ntmp, NULL, &values))
437 goto err;
438 }
439 free(linebuf);
440 return values;
441
442 err:
443 free(linebuf);
444 sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
445 return NULL;
446 }
447 LCRYPTO_ALIAS(X509V3_parse_list);
448
449 /* Delete leading and trailing spaces from a string */
450 static char *
strip_spaces(char * name)451 strip_spaces(char *name)
452 {
453 char *p, *q;
454
455 /* Skip over leading spaces */
456 p = name;
457 while (*p && isspace((unsigned char)*p))
458 p++;
459 if (!*p)
460 return NULL;
461 q = p + strlen(p) - 1;
462 while ((q != p) && isspace((unsigned char)*q))
463 q--;
464 if (p != q)
465 q[1] = 0;
466 if (!*p)
467 return NULL;
468 return p;
469 }
470
471 static const char hex_digits[] = "0123456789ABCDEF";
472
473 char *
hex_to_string(const unsigned char * buffer,long len)474 hex_to_string(const unsigned char *buffer, long len)
475 {
476 CBB cbb;
477 CBS cbs;
478 uint8_t *out = NULL;
479 uint8_t c;
480 size_t out_len;
481
482 if (!CBB_init(&cbb, 0))
483 goto err;
484
485 if (len < 0)
486 goto err;
487
488 CBS_init(&cbs, buffer, len);
489 while (CBS_len(&cbs) > 0) {
490 if (!CBS_get_u8(&cbs, &c))
491 goto err;
492 if (!CBB_add_u8(&cbb, hex_digits[c >> 4]))
493 goto err;
494 if (!CBB_add_u8(&cbb, hex_digits[c & 0xf]))
495 goto err;
496 if (CBS_len(&cbs) > 0) {
497 if (!CBB_add_u8(&cbb, ':'))
498 goto err;
499 }
500 }
501
502 if (!CBB_add_u8(&cbb, '\0'))
503 goto err;
504
505 if (!CBB_finish(&cbb, &out, &out_len))
506 goto err;
507
508 err:
509 CBB_cleanup(&cbb);
510
511 return out;
512 }
513 LCRYPTO_ALIAS(hex_to_string);
514
515 static int
x509_skip_colons_cbs(CBS * cbs)516 x509_skip_colons_cbs(CBS *cbs)
517 {
518 uint8_t c;
519
520 while (CBS_len(cbs) > 0) {
521 if (!CBS_peek_u8(cbs, &c))
522 return 0;
523 if (c != ':')
524 return 1;
525 if (!CBS_get_u8(cbs, &c))
526 return 0;
527 }
528
529 return 1;
530 }
531
532 static int
x509_get_xdigit_nibble_cbs(CBS * cbs,uint8_t * out_nibble)533 x509_get_xdigit_nibble_cbs(CBS *cbs, uint8_t *out_nibble)
534 {
535 uint8_t c;
536
537 if (!CBS_get_u8(cbs, &c))
538 return 0;
539
540 if (c >= '0' && c <= '9') {
541 *out_nibble = c - '0';
542 return 1;
543 }
544 if (c >= 'a' && c <= 'f') {
545 *out_nibble = c - 'a' + 10;
546 return 1;
547 }
548 if (c >= 'A' && c <= 'F') {
549 *out_nibble = c - 'A' + 10;
550 return 1;
551 }
552
553 X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT);
554 return 0;
555 }
556
557 unsigned char *
string_to_hex(const char * str,long * len)558 string_to_hex(const char *str, long *len)
559 {
560 CBB cbb;
561 CBS cbs;
562 uint8_t *out = NULL;
563 size_t out_len;
564 uint8_t hi, lo;
565
566 *len = 0;
567
568 if (!CBB_init(&cbb, 0))
569 goto err;
570
571 if (str == NULL) {
572 X509V3error(X509V3_R_INVALID_NULL_ARGUMENT);
573 goto err;
574 }
575
576 CBS_init(&cbs, str, strlen(str));
577 while (CBS_len(&cbs) > 0) {
578 /*
579 * Skipping only a single colon between two pairs of digits
580 * would make more sense - history...
581 */
582 if (!x509_skip_colons_cbs(&cbs))
583 goto err;
584 /* Another historic idiocy. */
585 if (CBS_len(&cbs) == 0)
586 break;
587 if (!x509_get_xdigit_nibble_cbs(&cbs, &hi))
588 goto err;
589 if (CBS_len(&cbs) == 0) {
590 X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS);
591 goto err;
592 }
593 if (!x509_get_xdigit_nibble_cbs(&cbs, &lo))
594 goto err;
595 if (!CBB_add_u8(&cbb, hi << 4 | lo))
596 goto err;
597 }
598
599 if (!CBB_finish(&cbb, &out, &out_len))
600 goto err;
601 if (out_len > LONG_MAX) {
602 freezero(out, out_len);
603 out = NULL;
604 goto err;
605 }
606
607 *len = out_len;
608
609 err:
610 CBB_cleanup(&cbb);
611
612 return out;
613 }
614 LCRYPTO_ALIAS(string_to_hex);
615
616 /* V2I name comparison function: returns zero if 'name' matches
617 * cmp or cmp.*
618 */
619
620 int
name_cmp(const char * name,const char * cmp)621 name_cmp(const char *name, const char *cmp)
622 {
623 int len, ret;
624 char c;
625
626 len = strlen(cmp);
627 if ((ret = strncmp(name, cmp, len)))
628 return ret;
629 c = name[len];
630 if (!c || (c=='.'))
631 return 0;
632 return 1;
633 }
634
635 static int
sk_strcmp(const char * const * a,const char * const * b)636 sk_strcmp(const char * const *a, const char * const *b)
637 {
638 return strcmp(*a, *b);
639 }
640
STACK_OF(OPENSSL_STRING)641 STACK_OF(OPENSSL_STRING) *
642 X509_get1_email(X509 *x)
643 {
644 GENERAL_NAMES *gens;
645 STACK_OF(OPENSSL_STRING) *ret;
646
647 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
648 ret = get_email(X509_get_subject_name(x), gens);
649 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
650 return ret;
651 }
652 LCRYPTO_ALIAS(X509_get1_email);
653
STACK_OF(OPENSSL_STRING)654 STACK_OF(OPENSSL_STRING) *
655 X509_get1_ocsp(X509 *x)
656 {
657 AUTHORITY_INFO_ACCESS *info;
658 STACK_OF(OPENSSL_STRING) *ret = NULL;
659 int i;
660
661 info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
662 if (!info)
663 return NULL;
664 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
665 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
666 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
667 if (ad->location->type == GEN_URI) {
668 if (!append_ia5(&ret,
669 ad->location->d.uniformResourceIdentifier))
670 break;
671 }
672 }
673 }
674 AUTHORITY_INFO_ACCESS_free(info);
675 return ret;
676 }
677 LCRYPTO_ALIAS(X509_get1_ocsp);
678
STACK_OF(OPENSSL_STRING)679 STACK_OF(OPENSSL_STRING) *
680 X509_REQ_get1_email(X509_REQ *x)
681 {
682 GENERAL_NAMES *gens;
683 STACK_OF(X509_EXTENSION) *exts;
684 STACK_OF(OPENSSL_STRING) *ret;
685
686 exts = X509_REQ_get_extensions(x);
687 gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
688 ret = get_email(X509_REQ_get_subject_name(x), gens);
689 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
690 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
691 return ret;
692 }
693 LCRYPTO_ALIAS(X509_REQ_get1_email);
694
695
STACK_OF(OPENSSL_STRING)696 static STACK_OF(OPENSSL_STRING) *
697 get_email(X509_NAME *name, GENERAL_NAMES *gens)
698 {
699 STACK_OF(OPENSSL_STRING) *ret = NULL;
700 X509_NAME_ENTRY *ne;
701 ASN1_IA5STRING *email;
702 GENERAL_NAME *gen;
703 int i;
704
705 /* Now add any email address(es) to STACK */
706 i = -1;
707
708 /* First supplied X509_NAME */
709 while ((i = X509_NAME_get_index_by_NID(name,
710 NID_pkcs9_emailAddress, i)) >= 0) {
711 ne = X509_NAME_get_entry(name, i);
712 email = X509_NAME_ENTRY_get_data(ne);
713 if (!append_ia5(&ret, email))
714 return NULL;
715 }
716 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
717 gen = sk_GENERAL_NAME_value(gens, i);
718 if (gen->type != GEN_EMAIL)
719 continue;
720 if (!append_ia5(&ret, gen->d.ia5))
721 return NULL;
722 }
723 return ret;
724 }
725
726 static void
str_free(OPENSSL_STRING str)727 str_free(OPENSSL_STRING str)
728 {
729 free(str);
730 }
731
732 static int
append_ia5(STACK_OF (OPENSSL_STRING)** sk,ASN1_IA5STRING * email)733 append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
734 {
735 char *emtmp;
736
737 /* First some sanity checks */
738 if (email->type != V_ASN1_IA5STRING)
739 return 1;
740 if (!email->data || !email->length)
741 return 1;
742 if (!*sk)
743 *sk = sk_OPENSSL_STRING_new(sk_strcmp);
744 if (!*sk)
745 return 0;
746 /* Don't add duplicates */
747 if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
748 return 1;
749 emtmp = strdup((char *)email->data);
750 if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
751 X509_email_free(*sk);
752 *sk = NULL;
753 return 0;
754 }
755 return 1;
756 }
757
758 void
X509_email_free(STACK_OF (OPENSSL_STRING)* sk)759 X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
760 {
761 sk_OPENSSL_STRING_pop_free(sk, str_free);
762 }
763 LCRYPTO_ALIAS(X509_email_free);
764
765 typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len,
766 const unsigned char *subject, size_t subject_len, unsigned int flags);
767
768 /* Skip pattern prefix to match "wildcard" subject */
769 static void
skip_prefix(const unsigned char ** p,size_t * plen,const unsigned char * subject,size_t subject_len,unsigned int flags)770 skip_prefix(const unsigned char **p, size_t *plen, const unsigned char *subject,
771 size_t subject_len, unsigned int flags)
772 {
773 const unsigned char *pattern = *p;
774 size_t pattern_len = *plen;
775
776 /*
777 * If subject starts with a leading '.' followed by more octets, and
778 * pattern is longer, compare just an equal-length suffix with the
779 * full subject (starting at the '.'), provided the prefix contains
780 * no NULs.
781 */
782 if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
783 return;
784
785 while (pattern_len > subject_len && *pattern) {
786 if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
787 *pattern == '.')
788 break;
789 ++pattern;
790 --pattern_len;
791 }
792
793 /* Skip if entire prefix acceptable */
794 if (pattern_len == subject_len) {
795 *p = pattern;
796 *plen = pattern_len;
797 }
798 }
799
800 /*
801 * Open/BoringSSL uses memcmp for "equal_case" while their
802 * "equal_nocase" function is a hand-rolled strncasecmp that does not
803 * allow \0 in the pattern. Since an embedded \0 is likely a sign of
804 * problems, we simply don't allow it in either case, and then we use
805 * standard libc functions.
806 */
807
808 /* Compare using strncasecmp */
809 static int
equal_nocase(const unsigned char * pattern,size_t pattern_len,const unsigned char * subject,size_t subject_len,unsigned int flags)810 equal_nocase(const unsigned char *pattern, size_t pattern_len,
811 const unsigned char *subject, size_t subject_len, unsigned int flags)
812 {
813 if (memchr(pattern, '\0', pattern_len) != NULL)
814 return 0;
815 if (memchr(subject, '\0', subject_len) != NULL)
816 return 0;
817 skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
818 if (pattern_len != subject_len)
819 return 0;
820 return (strncasecmp(pattern, subject, pattern_len) == 0);
821 }
822
823 /* Compare using strncmp. */
824 static int
equal_case(const unsigned char * pattern,size_t pattern_len,const unsigned char * subject,size_t subject_len,unsigned int flags)825 equal_case(const unsigned char *pattern, size_t pattern_len,
826 const unsigned char *subject, size_t subject_len, unsigned int flags)
827 {
828 if (memchr(pattern, 0, pattern_len) != NULL)
829 return 0;
830 if (memchr(subject, 0, subject_len) != NULL)
831 return 0;
832 skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
833 if (pattern_len != subject_len)
834 return 0;
835 return (strncmp(pattern, subject, pattern_len) == 0);
836 }
837
838 /*
839 * RFC 5280, section 7.5, requires that only the domain is compared in a
840 * case-insensitive manner.
841 */
842 static int
equal_email(const unsigned char * a,size_t a_len,const unsigned char * b,size_t b_len,unsigned int unused_flags)843 equal_email(const unsigned char *a, size_t a_len, const unsigned char *b,
844 size_t b_len, unsigned int unused_flags)
845 {
846 size_t pos = a_len;
847 if (a_len != b_len)
848 return 0;
849 /*
850 * We search backwards for the '@' character, so that we do not have to
851 * deal with quoted local-parts. The domain part is compared in a
852 * case-insensitive manner.
853 */
854 while (pos > 0) {
855 pos--;
856 if (a[pos] == '@' || b[pos] == '@') {
857 if (!equal_nocase(a + pos, a_len - pos, b + pos,
858 a_len - pos, 0))
859 return 0;
860 break;
861 }
862 }
863 if (pos == 0)
864 pos = a_len;
865 return equal_case(a, pos, b, pos, 0);
866 }
867
868 /*
869 * Compare the prefix and suffix with the subject, and check that the
870 * characters in-between are valid.
871 */
872 static int
wildcard_match(const unsigned char * prefix,size_t prefix_len,const unsigned char * suffix,size_t suffix_len,const unsigned char * subject,size_t subject_len,unsigned int flags)873 wildcard_match(const unsigned char *prefix, size_t prefix_len,
874 const unsigned char *suffix, size_t suffix_len,
875 const unsigned char *subject, size_t subject_len, unsigned int flags)
876 {
877 const unsigned char *wildcard_start;
878 const unsigned char *wildcard_end;
879 const unsigned char *p;
880 int allow_multi = 0;
881 int allow_idna = 0;
882
883 if (subject_len < prefix_len + suffix_len)
884 return 0;
885 if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
886 return 0;
887 wildcard_start = subject + prefix_len;
888 wildcard_end = subject + (subject_len - suffix_len);
889 if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
890 return 0;
891 /*
892 * If the wildcard makes up the entire first label, it must match at
893 * least one character.
894 */
895 if (prefix_len == 0 && *suffix == '.') {
896 if (wildcard_start == wildcard_end)
897 return 0;
898 allow_idna = 1;
899 if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
900 allow_multi = 1;
901 }
902 /* IDNA labels cannot match partial wildcards */
903 if (!allow_idna &&
904 subject_len >= 4
905 && strncasecmp((char *)subject, "xn--", 4) == 0)
906 return 0;
907 /* The wildcard may match a literal '*' */
908 if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
909 return 1;
910 /*
911 * Check that the part matched by the wildcard contains only
912 * permitted characters and only matches a single label unless
913 * allow_multi is set.
914 */
915 for (p = wildcard_start; p != wildcard_end; ++p)
916 if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') ||
917 ('a' <= *p && *p <= 'z') || *p == '-' ||
918 (allow_multi && *p == '.')))
919 return 0;
920 return 1;
921 }
922
923 #define LABEL_START (1 << 0)
924 #define LABEL_END (1 << 1)
925 #define LABEL_HYPHEN (1 << 2)
926 #define LABEL_IDNA (1 << 3)
927
928 static const unsigned char *
valid_star(const unsigned char * p,size_t len,unsigned int flags)929 valid_star(const unsigned char *p, size_t len, unsigned int flags)
930 {
931 const unsigned char *star = 0;
932 size_t i;
933 int state = LABEL_START;
934 int dots = 0;
935 for (i = 0; i < len; ++i) {
936 /*
937 * Locate first and only legal wildcard, either at the start
938 * or end of a non-IDNA first and not final label.
939 */
940 if (p[i] == '*') {
941 int atstart = (state & LABEL_START);
942 int atend = (i == len - 1 || p[i + 1] == '.');
943 /*
944 * At most one wildcard per pattern.
945 * No wildcards in IDNA labels.
946 * No wildcards after the first label.
947 */
948 if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
949 return NULL;
950 /* Only full-label '*.example.com' wildcards? */
951 if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
952 && (!atstart || !atend))
953 return NULL;
954 /* No 'foo*bar' wildcards */
955 if (!atstart && !atend)
956 return NULL;
957 star = &p[i];
958 state &= ~LABEL_START;
959 } else if ((state & LABEL_START) != 0) {
960 /*
961 * At the start of a label, skip any "xn--" and
962 * remain in the LABEL_START state, but set the
963 * IDNA label state
964 */
965 if ((state & LABEL_IDNA) == 0 && len - i >= 4
966 && strncasecmp((char *)&p[i], "xn--", 4) == 0) {
967 i += 3;
968 state |= LABEL_IDNA;
969 continue;
970 }
971 /* Labels must start with a letter or digit */
972 state &= ~LABEL_START;
973 if (('a' <= p[i] && p[i] <= 'z')
974 || ('A' <= p[i] && p[i] <= 'Z')
975 || ('0' <= p[i] && p[i] <= '9'))
976 continue;
977 return NULL;
978 } else if (('a' <= p[i] && p[i] <= 'z')
979 || ('A' <= p[i] && p[i] <= 'Z')
980 || ('0' <= p[i] && p[i] <= '9')) {
981 state &= LABEL_IDNA;
982 continue;
983 } else if (p[i] == '.') {
984 if (state & (LABEL_HYPHEN | LABEL_START))
985 return NULL;
986 state = LABEL_START;
987 ++dots;
988 } else if (p[i] == '-') {
989 /* no domain/subdomain starts with '-' */
990 if ((state & LABEL_START) != 0)
991 return NULL;
992 state |= LABEL_HYPHEN;
993 } else
994 return NULL;
995 }
996
997 /*
998 * The final label must not end in a hyphen or ".", and
999 * there must be at least two dots after the star.
1000 */
1001 if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
1002 return NULL;
1003 return star;
1004 }
1005
1006 /* Compare using wildcards. */
1007 static int
equal_wildcard(const unsigned char * pattern,size_t pattern_len,const unsigned char * subject,size_t subject_len,unsigned int flags)1008 equal_wildcard(const unsigned char *pattern, size_t pattern_len,
1009 const unsigned char *subject, size_t subject_len, unsigned int flags)
1010 {
1011 const unsigned char *star = NULL;
1012
1013 /*
1014 * Subject names starting with '.' can only match a wildcard pattern
1015 * via a subject sub-domain pattern suffix match.
1016 */
1017 if (!(subject_len > 1 && subject[0] == '.'))
1018 star = valid_star(pattern, pattern_len, flags);
1019 if (star == NULL)
1020 return equal_nocase(pattern, pattern_len,
1021 subject, subject_len, flags);
1022 return wildcard_match(pattern, star - pattern,
1023 star + 1, (pattern + pattern_len) - star - 1,
1024 subject, subject_len, flags);
1025 }
1026
1027 /*
1028 * Compare an ASN1_STRING to a supplied string. If they match return 1. If
1029 * cmp_type > 0 only compare if string matches the type, otherwise convert it
1030 * to UTF8.
1031 */
1032
1033 static int
do_check_string(ASN1_STRING * a,int cmp_type,equal_fn equal,unsigned int flags,const char * b,size_t blen,char ** peername)1034 do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
1035 unsigned int flags, const char *b, size_t blen, char **peername)
1036 {
1037 int rv = 0;
1038
1039 if (!a->data || !a->length)
1040 return 0;
1041 if (cmp_type > 0) {
1042 if (cmp_type != a->type)
1043 return 0;
1044 if (cmp_type == V_ASN1_IA5STRING)
1045 rv = equal(a->data, a->length, (unsigned char *)b,
1046 blen, flags);
1047 else if (a->length == (int)blen && !memcmp(a->data, b, blen))
1048 rv = 1;
1049 if (rv > 0 && peername &&
1050 (*peername = strndup((char *)a->data, a->length)) == NULL)
1051 rv = -1;
1052 } else {
1053 int astrlen;
1054 unsigned char *astr = NULL;
1055 astrlen = ASN1_STRING_to_UTF8(&astr, a);
1056 if (astrlen < 0)
1057 return -1;
1058 rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
1059 if (rv > 0 && peername &&
1060 (*peername = strndup((char *)astr, astrlen)) == NULL)
1061 rv = -1;
1062 free(astr);
1063 }
1064 return rv;
1065 }
1066
1067 static int
do_x509_check(X509 * x,const char * chk,size_t chklen,unsigned int flags,int check_type,char ** peername)1068 do_x509_check(X509 *x, const char *chk, size_t chklen, unsigned int flags,
1069 int check_type, char **peername)
1070 {
1071 GENERAL_NAMES *gens = NULL;
1072 X509_NAME *name = NULL;
1073 size_t i;
1074 int j;
1075 int cnid = NID_undef;
1076 int alt_type;
1077 int san_present = 0;
1078 int rv = 0;
1079 equal_fn equal;
1080
1081 /* See below, this flag is internal-only */
1082 flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
1083 if (check_type == GEN_EMAIL) {
1084 cnid = NID_pkcs9_emailAddress;
1085 alt_type = V_ASN1_IA5STRING;
1086 equal = equal_email;
1087 } else if (check_type == GEN_DNS) {
1088 if (!(flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT))
1089 cnid = NID_commonName;
1090 /* Implicit client-side DNS sub-domain pattern */
1091 if (chklen > 1 && chk[0] == '.')
1092 flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
1093 alt_type = V_ASN1_IA5STRING;
1094 if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
1095 equal = equal_nocase;
1096 else
1097 equal = equal_wildcard;
1098 } else {
1099 alt_type = V_ASN1_OCTET_STRING;
1100 equal = equal_case;
1101 }
1102
1103 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
1104 if (gens != NULL) {
1105 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
1106 GENERAL_NAME *gen;
1107 ASN1_STRING *cstr;
1108 gen = sk_GENERAL_NAME_value(gens, i);
1109 if (gen->type != check_type)
1110 continue;
1111 san_present = 1;
1112 if (check_type == GEN_EMAIL)
1113 cstr = gen->d.rfc822Name;
1114 else if (check_type == GEN_DNS)
1115 cstr = gen->d.dNSName;
1116 else
1117 cstr = gen->d.iPAddress;
1118 /* Positive on success, negative on error! */
1119 if ((rv = do_check_string(cstr, alt_type, equal, flags,
1120 chk, chklen, peername)) != 0)
1121 break;
1122 }
1123 GENERAL_NAMES_free(gens);
1124 if (rv != 0)
1125 return rv;
1126 if (cnid == NID_undef ||
1127 (san_present &&
1128 !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
1129 return 0;
1130 }
1131
1132 /* We're done if CN-ID is not pertinent */
1133 if (cnid == NID_undef)
1134 return 0;
1135
1136 j = -1;
1137 name = X509_get_subject_name(x);
1138 while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) {
1139 X509_NAME_ENTRY *ne;
1140 ASN1_STRING *str;
1141 if ((ne = X509_NAME_get_entry(name, j)) == NULL)
1142 return -1;
1143 if ((str = X509_NAME_ENTRY_get_data(ne)) == NULL)
1144 return -1;
1145 /* Positive on success, negative on error! */
1146 if ((rv = do_check_string(str, -1, equal, flags,
1147 chk, chklen, peername)) != 0)
1148 return rv;
1149 }
1150 return 0;
1151 }
1152
1153 int
X509_check_host(X509 * x,const char * chk,size_t chklen,unsigned int flags,char ** peername)1154 X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags,
1155 char **peername)
1156 {
1157 if (chk == NULL)
1158 return -2;
1159 if (chklen == 0)
1160 chklen = strlen(chk);
1161 else if (memchr(chk, '\0', chklen))
1162 return -2;
1163 return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
1164 }
1165 LCRYPTO_ALIAS(X509_check_host);
1166
1167 int
X509_check_email(X509 * x,const char * chk,size_t chklen,unsigned int flags)1168 X509_check_email(X509 *x, const char *chk, size_t chklen, unsigned int flags)
1169 {
1170 if (chk == NULL)
1171 return -2;
1172 if (chklen == 0)
1173 chklen = strlen(chk);
1174 else if (memchr(chk, '\0', chklen))
1175 return -2;
1176 return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
1177 }
1178 LCRYPTO_ALIAS(X509_check_email);
1179
1180 int
X509_check_ip(X509 * x,const unsigned char * chk,size_t chklen,unsigned int flags)1181 X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
1182 unsigned int flags)
1183 {
1184 if (chk == NULL)
1185 return -2;
1186 return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
1187 }
1188 LCRYPTO_ALIAS(X509_check_ip);
1189
1190 int
X509_check_ip_asc(X509 * x,const char * ipasc,unsigned int flags)1191 X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
1192 {
1193 unsigned char ipout[16];
1194 size_t iplen;
1195
1196 if (ipasc == NULL)
1197 return -2;
1198 iplen = (size_t)a2i_ipadd(ipout, ipasc);
1199 if (iplen == 0)
1200 return -2;
1201 return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
1202 }
1203 LCRYPTO_ALIAS(X509_check_ip_asc);
1204
1205 /* Convert IP addresses both IPv4 and IPv6 into an
1206 * OCTET STRING compatible with RFC3280.
1207 */
1208
1209 ASN1_OCTET_STRING *
a2i_IPADDRESS(const char * ipasc)1210 a2i_IPADDRESS(const char *ipasc)
1211 {
1212 unsigned char ipout[16];
1213 ASN1_OCTET_STRING *ret;
1214 int iplen;
1215
1216 /* If string contains a ':' assume IPv6 */
1217
1218 iplen = a2i_ipadd(ipout, ipasc);
1219
1220 if (!iplen)
1221 return NULL;
1222
1223 ret = ASN1_OCTET_STRING_new();
1224 if (!ret)
1225 return NULL;
1226 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
1227 ASN1_OCTET_STRING_free(ret);
1228 return NULL;
1229 }
1230 return ret;
1231 }
1232 LCRYPTO_ALIAS(a2i_IPADDRESS);
1233
1234 ASN1_OCTET_STRING *
a2i_IPADDRESS_NC(const char * ipasc)1235 a2i_IPADDRESS_NC(const char *ipasc)
1236 {
1237 ASN1_OCTET_STRING *ret = NULL;
1238 unsigned char ipout[32];
1239 char *iptmp = NULL, *p;
1240 int iplen1, iplen2;
1241
1242 p = strchr(ipasc, '/');
1243 if (!p)
1244 return NULL;
1245 iptmp = strdup(ipasc);
1246 if (!iptmp)
1247 return NULL;
1248 p = iptmp + (p - ipasc);
1249 *p++ = 0;
1250
1251 iplen1 = a2i_ipadd(ipout, iptmp);
1252
1253 if (!iplen1)
1254 goto err;
1255
1256 iplen2 = a2i_ipadd(ipout + iplen1, p);
1257
1258 free(iptmp);
1259 iptmp = NULL;
1260
1261 if (!iplen2 || (iplen1 != iplen2))
1262 goto err;
1263
1264 ret = ASN1_OCTET_STRING_new();
1265 if (!ret)
1266 goto err;
1267 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
1268 goto err;
1269
1270 return ret;
1271
1272 err:
1273 free(iptmp);
1274 if (ret)
1275 ASN1_OCTET_STRING_free(ret);
1276 return NULL;
1277 }
1278 LCRYPTO_ALIAS(a2i_IPADDRESS_NC);
1279
1280
1281 int
a2i_ipadd(unsigned char * ipout,const char * ipasc)1282 a2i_ipadd(unsigned char *ipout, const char *ipasc)
1283 {
1284 /* If string contains a ':' assume IPv6 */
1285
1286 if (strchr(ipasc, ':')) {
1287 if (!ipv6_from_asc(ipout, ipasc))
1288 return 0;
1289 return 16;
1290 } else {
1291 if (!ipv4_from_asc(ipout, ipasc))
1292 return 0;
1293 return 4;
1294 }
1295 }
1296 LCRYPTO_ALIAS(a2i_ipadd);
1297
1298 static int
ipv4_from_asc(unsigned char * v4,const char * in)1299 ipv4_from_asc(unsigned char *v4, const char *in)
1300 {
1301 int a0, a1, a2, a3;
1302 if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
1303 return 0;
1304 if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) ||
1305 (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
1306 return 0;
1307 v4[0] = a0;
1308 v4[1] = a1;
1309 v4[2] = a2;
1310 v4[3] = a3;
1311 return 1;
1312 }
1313
1314 typedef struct {
1315 /* Temporary store for IPV6 output */
1316 unsigned char tmp[16];
1317 /* Total number of bytes in tmp */
1318 int total;
1319 /* The position of a zero (corresponding to '::') */
1320 int zero_pos;
1321 /* Number of zeroes */
1322 int zero_cnt;
1323 } IPV6_STAT;
1324
1325
1326 static int
ipv6_from_asc(unsigned char * v6,const char * in)1327 ipv6_from_asc(unsigned char *v6, const char *in)
1328 {
1329 IPV6_STAT v6stat;
1330
1331 v6stat.total = 0;
1332 v6stat.zero_pos = -1;
1333 v6stat.zero_cnt = 0;
1334
1335 /*
1336 * Treat the IPv6 representation as a list of values separated by ':'.
1337 * The presence of a '::' will parse as one (e.g., "2001:db8::1"),
1338 * two (e.g., "2001:db8::") or three (e.g., "::") zero length elements.
1339 */
1340 if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
1341 return 0;
1342
1343 /* Now for some sanity checks */
1344
1345 if (v6stat.zero_pos == -1) {
1346 /* If no '::' must have exactly 16 bytes */
1347 if (v6stat.total != 16)
1348 return 0;
1349 } else {
1350 /* If '::' must have less than 16 bytes */
1351 if (v6stat.total == 16)
1352 return 0;
1353 /* More than three zeroes is an error */
1354 if (v6stat.zero_cnt > 3)
1355 return 0;
1356 /* Can only have three zeroes if nothing else present */
1357 else if (v6stat.zero_cnt == 3) {
1358 if (v6stat.total > 0)
1359 return 0;
1360 }
1361 /* Can only have two zeroes if at start or end */
1362 else if (v6stat.zero_cnt == 2) {
1363 if ((v6stat.zero_pos != 0) &&
1364 (v6stat.zero_pos != v6stat.total))
1365 return 0;
1366 } else
1367 /* Can only have one zero if *not* start or end */
1368 {
1369 if ((v6stat.zero_pos == 0) ||
1370 (v6stat.zero_pos == v6stat.total))
1371 return 0;
1372 }
1373 }
1374
1375 /* Format result */
1376
1377 if (v6stat.zero_pos >= 0) {
1378 /* Copy initial part */
1379 memcpy(v6, v6stat.tmp, v6stat.zero_pos);
1380 /* Zero middle */
1381 memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
1382 /* Copy final part */
1383 if (v6stat.total != v6stat.zero_pos)
1384 memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
1385 v6stat.tmp + v6stat.zero_pos,
1386 v6stat.total - v6stat.zero_pos);
1387 } else
1388 memcpy(v6, v6stat.tmp, 16);
1389
1390 return 1;
1391 }
1392
1393 static int
ipv6_cb(const char * elem,int len,void * usr)1394 ipv6_cb(const char *elem, int len, void *usr)
1395 {
1396 IPV6_STAT *s = usr;
1397
1398 /* Error if 16 bytes written */
1399 if (s->total == 16)
1400 return 0;
1401 if (len == 0) {
1402 /* Zero length element, corresponds to '::' */
1403 if (s->zero_pos == -1)
1404 s->zero_pos = s->total;
1405 /* If we've already got a :: its an error */
1406 else if (s->zero_pos != s->total)
1407 return 0;
1408 s->zero_cnt++;
1409 } else {
1410 /* If more than 4 characters could be final a.b.c.d form */
1411 if (len > 4) {
1412 /* Need at least 4 bytes left */
1413 if (s->total > 12)
1414 return 0;
1415 /* Must be end of string */
1416 if (elem[len])
1417 return 0;
1418 if (!ipv4_from_asc(s->tmp + s->total, elem))
1419 return 0;
1420 s->total += 4;
1421 } else {
1422 if (!ipv6_hex(s->tmp + s->total, elem, len))
1423 return 0;
1424 s->total += 2;
1425 }
1426 }
1427 return 1;
1428 }
1429
1430 /* Convert a string of up to 4 hex digits into the corresponding
1431 * IPv6 form.
1432 */
1433
1434 static int
ipv6_hex(unsigned char * out,const char * in,int inlen)1435 ipv6_hex(unsigned char *out, const char *in, int inlen)
1436 {
1437 unsigned char c;
1438 unsigned int num = 0;
1439
1440 if (inlen > 4)
1441 return 0;
1442 while (inlen--) {
1443 c = *in++;
1444 num <<= 4;
1445 if ((c >= '0') && (c <= '9'))
1446 num |= c - '0';
1447 else if ((c >= 'A') && (c <= 'F'))
1448 num |= c - 'A' + 10;
1449 else if ((c >= 'a') && (c <= 'f'))
1450 num |= c - 'a' + 10;
1451 else
1452 return 0;
1453 }
1454 out[0] = num >> 8;
1455 out[1] = num & 0xff;
1456 return 1;
1457 }
1458
1459 int
X509V3_NAME_from_section(X509_NAME * nm,STACK_OF (CONF_VALUE)* dn_sk,unsigned long chtype)1460 X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
1461 unsigned long chtype)
1462 {
1463 CONF_VALUE *v;
1464 int i, mval;
1465 char *p, *type;
1466
1467 if (!nm)
1468 return 0;
1469
1470 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1471 v = sk_CONF_VALUE_value(dn_sk, i);
1472 type = v->name;
1473 /* Skip past any leading X. X: X, etc to allow for
1474 * multiple instances
1475 */
1476 for (p = type; *p; p++)
1477 if ((*p == ':') || (*p == ',') || (*p == '.')) {
1478 p++;
1479 if (*p)
1480 type = p;
1481 break;
1482 }
1483 if (*type == '+') {
1484 mval = -1;
1485 type++;
1486 } else
1487 mval = 0;
1488 if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
1489 (unsigned char *) v->value, -1, -1, mval))
1490 return 0;
1491 }
1492 return 1;
1493 }
1494 LCRYPTO_ALIAS(X509V3_NAME_from_section);
1495