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