update libressl to 2.8.2
[unleashed.git] / lib / libcrypto / x509v3 / v3_utl.c
blob4f8d16fd00cb2b62e584f336706ece99cf90e4c8
1 /* $OpenBSD: v3_utl.c,v 1.31 2018/05/19 10:50:08 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.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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/)"
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.
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.
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/)"
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 * ====================================================================
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).
58 /* X509 v3 extension utilities */
60 #include <ctype.h>
61 #include <stdio.h>
62 #include <string.h>
64 #include <openssl/bn.h>
65 #include <openssl/conf.h>
66 #include <openssl/err.h>
67 #include <openssl/x509v3.h>
69 static char *strip_spaces(char *name);
70 static int sk_strcmp(const char * const *a, const char * const *b);
71 static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
72 GENERAL_NAMES *gens);
73 static void str_free(OPENSSL_STRING str);
74 static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
76 static int ipv4_from_asc(unsigned char *v4, const char *in);
77 static int ipv6_from_asc(unsigned char *v6, const char *in);
78 static int ipv6_cb(const char *elem, int len, void *usr);
79 static int ipv6_hex(unsigned char *out, const char *in, int inlen);
81 /* Add a CONF_VALUE name value pair to stack */
83 int
84 X509V3_add_value(const char *name, const char *value,
85 STACK_OF(CONF_VALUE) **extlist)
87 CONF_VALUE *vtmp = NULL;
88 char *tname = NULL, *tvalue = NULL;
90 if (name && !(tname = strdup(name)))
91 goto err;
92 if (value && !(tvalue = strdup(value)))
93 goto err;
94 if (!(vtmp = malloc(sizeof(CONF_VALUE))))
95 goto err;
96 if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null()))
97 goto err;
98 vtmp->section = NULL;
99 vtmp->name = tname;
100 vtmp->value = tvalue;
101 if (!sk_CONF_VALUE_push(*extlist, vtmp))
102 goto err;
103 return 1;
105 err:
106 X509V3error(ERR_R_MALLOC_FAILURE);
107 free(vtmp);
108 free(tname);
109 free(tvalue);
110 return 0;
114 X509V3_add_value_uchar(const char *name, const unsigned char *value,
115 STACK_OF(CONF_VALUE) **extlist)
117 return X509V3_add_value(name, (const char *)value, extlist);
120 /* Free function for STACK_OF(CONF_VALUE) */
122 void
123 X509V3_conf_free(CONF_VALUE *conf)
125 if (!conf)
126 return;
127 free(conf->name);
128 free(conf->value);
129 free(conf->section);
130 free(conf);
134 X509V3_add_value_bool(const char *name, int asn1_bool,
135 STACK_OF(CONF_VALUE) **extlist)
137 if (asn1_bool)
138 return X509V3_add_value(name, "TRUE", extlist);
139 return X509V3_add_value(name, "FALSE", extlist);
143 X509V3_add_value_bool_nf(const char *name, int asn1_bool,
144 STACK_OF(CONF_VALUE) **extlist)
146 if (asn1_bool)
147 return X509V3_add_value(name, "TRUE", extlist);
148 return 1;
152 char *
153 i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a)
155 BIGNUM *bntmp = NULL;
156 char *strtmp = NULL;
158 if (!a)
159 return NULL;
160 if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
161 !(strtmp = BN_bn2dec(bntmp)))
162 X509V3error(ERR_R_MALLOC_FAILURE);
163 BN_free(bntmp);
164 return strtmp;
167 char *
168 i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a)
170 BIGNUM *bntmp = NULL;
171 char *strtmp = NULL;
173 if (!a)
174 return NULL;
175 if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
176 !(strtmp = BN_bn2dec(bntmp)))
177 X509V3error(ERR_R_MALLOC_FAILURE);
178 BN_free(bntmp);
179 return strtmp;
182 ASN1_INTEGER *
183 s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
185 BIGNUM *bn = NULL;
186 ASN1_INTEGER *aint;
187 int isneg, ishex;
188 int ret;
190 if (!value) {
191 X509V3error(X509V3_R_INVALID_NULL_VALUE);
192 return 0;
194 bn = BN_new();
195 if (value[0] == '-') {
196 value++;
197 isneg = 1;
198 } else
199 isneg = 0;
201 if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
202 value += 2;
203 ishex = 1;
204 } else
205 ishex = 0;
207 if (ishex)
208 ret = BN_hex2bn(&bn, value);
209 else
210 ret = BN_dec2bn(&bn, value);
212 if (!ret || value[ret]) {
213 BN_free(bn);
214 X509V3error(X509V3_R_BN_DEC2BN_ERROR);
215 return 0;
218 if (isneg && BN_is_zero(bn))
219 isneg = 0;
221 aint = BN_to_ASN1_INTEGER(bn, NULL);
222 BN_free(bn);
223 if (!aint) {
224 X509V3error(X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
225 return 0;
227 if (isneg)
228 aint->type |= V_ASN1_NEG;
229 return aint;
233 X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint,
234 STACK_OF(CONF_VALUE) **extlist)
236 char *strtmp;
237 int ret;
239 if (!aint)
240 return 1;
241 if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
242 return 0;
243 ret = X509V3_add_value(name, strtmp, extlist);
244 free(strtmp);
245 return ret;
249 X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool)
251 char *btmp;
253 if (!(btmp = value->value))
254 goto err;
255 if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") ||
256 !strcmp(btmp, "Y") || !strcmp(btmp, "y") ||
257 !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
258 *asn1_bool = 0xff;
259 return 1;
260 } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") ||
261 !strcmp(btmp, "N") || !strcmp(btmp, "n") ||
262 !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
263 *asn1_bool = 0;
264 return 1;
267 err:
268 X509V3error(X509V3_R_INVALID_BOOLEAN_STRING);
269 X509V3_conf_err(value);
270 return 0;
274 X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint)
276 ASN1_INTEGER *itmp;
278 if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
279 X509V3_conf_err(value);
280 return 0;
282 *aint = itmp;
283 return 1;
286 #define HDR_NAME 1
287 #define HDR_VALUE 2
289 /*#define DEBUG*/
291 STACK_OF(CONF_VALUE) *
292 X509V3_parse_list(const char *line)
294 char *p, *q, c;
295 char *ntmp, *vtmp;
296 STACK_OF(CONF_VALUE) *values = NULL;
297 char *linebuf;
298 int state;
300 /* We are going to modify the line so copy it first */
301 if ((linebuf = strdup(line)) == NULL) {
302 X509V3error(ERR_R_MALLOC_FAILURE);
303 goto err;
305 state = HDR_NAME;
306 ntmp = NULL;
308 /* Go through all characters */
309 for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') &&
310 (c != '\n'); p++) {
312 switch (state) {
313 case HDR_NAME:
314 if (c == ':') {
315 state = HDR_VALUE;
316 *p = 0;
317 ntmp = strip_spaces(q);
318 if (!ntmp) {
319 X509V3error(X509V3_R_INVALID_NULL_NAME);
320 goto err;
322 q = p + 1;
323 } else if (c == ',') {
324 *p = 0;
325 ntmp = strip_spaces(q);
326 q = p + 1;
327 if (!ntmp) {
328 X509V3error(X509V3_R_INVALID_NULL_NAME);
329 goto err;
331 X509V3_add_value(ntmp, NULL, &values);
333 break;
335 case HDR_VALUE:
336 if (c == ',') {
337 state = HDR_NAME;
338 *p = 0;
339 vtmp = strip_spaces(q);
340 if (!vtmp) {
341 X509V3error(X509V3_R_INVALID_NULL_VALUE);
342 goto err;
344 X509V3_add_value(ntmp, vtmp, &values);
345 ntmp = NULL;
346 q = p + 1;
352 if (state == HDR_VALUE) {
353 vtmp = strip_spaces(q);
354 if (!vtmp) {
355 X509V3error(X509V3_R_INVALID_NULL_VALUE);
356 goto err;
358 X509V3_add_value(ntmp, vtmp, &values);
359 } else {
360 ntmp = strip_spaces(q);
361 if (!ntmp) {
362 X509V3error(X509V3_R_INVALID_NULL_NAME);
363 goto err;
365 X509V3_add_value(ntmp, NULL, &values);
367 free(linebuf);
368 return values;
370 err:
371 free(linebuf);
372 sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
373 return NULL;
377 /* Delete leading and trailing spaces from a string */
378 static char *
379 strip_spaces(char *name)
381 char *p, *q;
383 /* Skip over leading spaces */
384 p = name;
385 while (*p && isspace((unsigned char)*p))
386 p++;
387 if (!*p)
388 return NULL;
389 q = p + strlen(p) - 1;
390 while ((q != p) && isspace((unsigned char)*q))
391 q--;
392 if (p != q)
393 q[1] = 0;
394 if (!*p)
395 return NULL;
396 return p;
399 /* hex string utilities */
401 /* Given a buffer of length 'len' return a malloc'ed string with its
402 * hex representation
404 char *
405 hex_to_string(const unsigned char *buffer, long len)
407 char *tmp, *q;
408 const unsigned char *p;
409 int i;
410 static const char hexdig[] = "0123456789ABCDEF";
412 if (!buffer || !len)
413 return NULL;
414 if (!(tmp = malloc(len * 3 + 1))) {
415 X509V3error(ERR_R_MALLOC_FAILURE);
416 return NULL;
418 q = tmp;
419 for (i = 0, p = buffer; i < len; i++, p++) {
420 *q++ = hexdig[(*p >> 4) & 0xf];
421 *q++ = hexdig[*p & 0xf];
422 *q++ = ':';
424 q[-1] = 0;
425 return tmp;
428 /* Give a string of hex digits convert to
429 * a buffer
432 unsigned char *
433 string_to_hex(const char *str, long *len)
435 unsigned char *hexbuf, *q;
436 unsigned char ch, cl, *p;
437 if (!str) {
438 X509V3error(X509V3_R_INVALID_NULL_ARGUMENT);
439 return NULL;
441 if (!(hexbuf = malloc(strlen(str) >> 1)))
442 goto err;
443 for (p = (unsigned char *)str, q = hexbuf; *p; ) {
444 ch = *p++;
445 if (ch == ':')
446 continue;
447 cl = *p++;
448 if (!cl) {
449 X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS);
450 free(hexbuf);
451 return NULL;
453 ch = tolower(ch);
454 cl = tolower(cl);
456 if ((ch >= '0') && (ch <= '9'))
457 ch -= '0';
458 else if ((ch >= 'a') && (ch <= 'f'))
459 ch -= 'a' - 10;
460 else
461 goto badhex;
463 if ((cl >= '0') && (cl <= '9'))
464 cl -= '0';
465 else if ((cl >= 'a') && (cl <= 'f'))
466 cl -= 'a' - 10;
467 else
468 goto badhex;
470 *q++ = (ch << 4) | cl;
473 if (len)
474 *len = q - hexbuf;
476 return hexbuf;
478 err:
479 free(hexbuf);
480 X509V3error(ERR_R_MALLOC_FAILURE);
481 return NULL;
483 badhex:
484 free(hexbuf);
485 X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT);
486 return NULL;
489 /* V2I name comparison function: returns zero if 'name' matches
490 * cmp or cmp.*
494 name_cmp(const char *name, const char *cmp)
496 int len, ret;
497 char c;
499 len = strlen(cmp);
500 if ((ret = strncmp(name, cmp, len)))
501 return ret;
502 c = name[len];
503 if (!c || (c=='.'))
504 return 0;
505 return 1;
508 static int
509 sk_strcmp(const char * const *a, const char * const *b)
511 return strcmp(*a, *b);
514 STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
516 GENERAL_NAMES *gens;
517 STACK_OF(OPENSSL_STRING) *ret;
519 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
520 ret = get_email(X509_get_subject_name(x), gens);
521 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
522 return ret;
525 STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
527 AUTHORITY_INFO_ACCESS *info;
528 STACK_OF(OPENSSL_STRING) *ret = NULL;
529 int i;
531 info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
532 if (!info)
533 return NULL;
534 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
535 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
536 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
537 if (ad->location->type == GEN_URI) {
538 if (!append_ia5(&ret,
539 ad->location->d.uniformResourceIdentifier))
540 break;
544 AUTHORITY_INFO_ACCESS_free(info);
545 return ret;
548 STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
550 GENERAL_NAMES *gens;
551 STACK_OF(X509_EXTENSION) *exts;
552 STACK_OF(OPENSSL_STRING) *ret;
554 exts = X509_REQ_get_extensions(x);
555 gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
556 ret = get_email(X509_REQ_get_subject_name(x), gens);
557 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
558 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
559 return ret;
563 static
564 STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens)
566 STACK_OF(OPENSSL_STRING) *ret = NULL;
567 X509_NAME_ENTRY *ne;
568 ASN1_IA5STRING *email;
569 GENERAL_NAME *gen;
570 int i;
572 /* Now add any email address(es) to STACK */
573 i = -1;
575 /* First supplied X509_NAME */
576 while ((i = X509_NAME_get_index_by_NID(name,
577 NID_pkcs9_emailAddress, i)) >= 0) {
578 ne = X509_NAME_get_entry(name, i);
579 email = X509_NAME_ENTRY_get_data(ne);
580 if (!append_ia5(&ret, email))
581 return NULL;
583 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
584 gen = sk_GENERAL_NAME_value(gens, i);
585 if (gen->type != GEN_EMAIL)
586 continue;
587 if (!append_ia5(&ret, gen->d.ia5))
588 return NULL;
590 return ret;
593 static void
594 str_free(OPENSSL_STRING str)
596 free(str);
599 static int
600 append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
602 char *emtmp;
604 /* First some sanity checks */
605 if (email->type != V_ASN1_IA5STRING)
606 return 1;
607 if (!email->data || !email->length)
608 return 1;
609 if (!*sk)
610 *sk = sk_OPENSSL_STRING_new(sk_strcmp);
611 if (!*sk)
612 return 0;
613 /* Don't add duplicates */
614 if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
615 return 1;
616 emtmp = strdup((char *)email->data);
617 if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
618 X509_email_free(*sk);
619 *sk = NULL;
620 return 0;
622 return 1;
625 void
626 X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
628 sk_OPENSSL_STRING_pop_free(sk, str_free);
631 typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len,
632 const unsigned char *subject, size_t subject_len, unsigned int flags);
634 /* Skip pattern prefix to match "wildcard" subject */
635 static void skip_prefix(const unsigned char **p, size_t *plen,
636 const unsigned char *subject, size_t subject_len, unsigned int flags)
638 const unsigned char *pattern = *p;
639 size_t pattern_len = *plen;
642 * If subject starts with a leading '.' followed by more octets, and
643 * pattern is longer, compare just an equal-length suffix with the
644 * full subject (starting at the '.'), provided the prefix contains
645 * no NULs.
647 if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
648 return;
650 while (pattern_len > subject_len && *pattern) {
651 if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
652 *pattern == '.')
653 break;
654 ++pattern;
655 --pattern_len;
658 /* Skip if entire prefix acceptable */
659 if (pattern_len == subject_len) {
660 *p = pattern;
661 *plen = pattern_len;
666 * Open/BoringSSL uses memcmp for "equal_case" while their
667 * "equal_nocase" function is a hand-rolled strncasecmp that does not
668 * allow \0 in the pattern. Since an embedded \0 is likely a sign of
669 * problems, we simply don't allow it in either case, and then we use
670 * standard libc funcitons.
673 /* Compare using strncasecmp */
674 static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
675 const unsigned char *subject, size_t subject_len,
676 unsigned int flags)
678 if (memchr(pattern, '\0', pattern_len) != NULL)
679 return 0;
680 if (memchr(subject, '\0', subject_len) != NULL)
681 return 0;
682 skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
683 if (pattern_len != subject_len)
684 return 0;
685 return (strncasecmp(pattern, subject, pattern_len) == 0);
688 /* Compare using strncmp. */
689 static int equal_case(const unsigned char *pattern, size_t pattern_len,
690 const unsigned char *subject, size_t subject_len,
691 unsigned int flags)
693 if (memchr(pattern, 0, pattern_len) != NULL)
694 return 0;
695 if (memchr(subject, 0, subject_len) != NULL)
696 return 0;
697 skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
698 if (pattern_len != subject_len)
699 return 0;
700 return (strncmp(pattern, subject, pattern_len) == 0);
704 * RFC 5280, section 7.5, requires that only the domain is compared in a
705 * case-insensitive manner.
707 static int equal_email(const unsigned char *a, size_t a_len,
708 const unsigned char *b, size_t b_len,
709 unsigned int unused_flags)
711 size_t pos = a_len;
712 if (a_len != b_len)
713 return 0;
715 * We search backwards for the '@' character, so that we do not have to
716 * deal with quoted local-parts. The domain part is compared in a
717 * case-insensitive manner.
719 while (pos > 0) {
720 pos--;
721 if (a[pos] == '@' || b[pos] == '@') {
722 if (!equal_nocase(a + pos, a_len - pos, b + pos, a_len - pos, 0))
723 return 0;
724 break;
727 if (pos == 0)
728 pos = a_len;
729 return equal_case(a, pos, b, pos, 0);
733 * Compare the prefix and suffix with the subject, and check that the
734 * characters in-between are valid.
736 static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
737 const unsigned char *suffix, size_t suffix_len,
738 const unsigned char *subject, size_t subject_len, unsigned int flags)
740 const unsigned char *wildcard_start;
741 const unsigned char *wildcard_end;
742 const unsigned char *p;
743 int allow_multi = 0;
744 int allow_idna = 0;
746 if (subject_len < prefix_len + suffix_len)
747 return 0;
748 if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
749 return 0;
750 wildcard_start = subject + prefix_len;
751 wildcard_end = subject + (subject_len - suffix_len);
752 if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
753 return 0;
755 * If the wildcard makes up the entire first label, it must match at
756 * least one character.
758 if (prefix_len == 0 && *suffix == '.') {
759 if (wildcard_start == wildcard_end)
760 return 0;
761 allow_idna = 1;
762 if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
763 allow_multi = 1;
765 /* IDNA labels cannot match partial wildcards */
766 if (!allow_idna &&
767 subject_len >= 4
768 && strncasecmp((char *)subject, "xn--", 4) == 0)
769 return 0;
770 /* The wildcard may match a literal '*' */
771 if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
772 return 1;
774 * Check that the part matched by the wildcard contains only
775 * permitted characters and only matches a single label unless
776 * allow_multi is set.
778 for (p = wildcard_start; p != wildcard_end; ++p)
779 if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') ||
780 ('a' <= *p && *p <= 'z') || *p == '-' ||
781 (allow_multi && *p == '.')))
782 return 0;
783 return 1;
786 #define LABEL_START (1 << 0)
787 #define LABEL_END (1 << 1)
788 #define LABEL_HYPHEN (1 << 2)
789 #define LABEL_IDNA (1 << 3)
791 static const unsigned char *valid_star(const unsigned char *p, size_t len,
792 unsigned int flags)
794 const unsigned char *star = 0;
795 size_t i;
796 int state = LABEL_START;
797 int dots = 0;
798 for (i = 0; i < len; ++i) {
800 * Locate first and only legal wildcard, either at the start
801 * or end of a non-IDNA first and not final label.
803 if (p[i] == '*') {
804 int atstart = (state & LABEL_START);
805 int atend = (i == len - 1 || p[i + 1] == '.');
807 * At most one wildcard per pattern.
808 * No wildcards in IDNA labels.
809 * No wildcards after the first label.
811 if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
812 return NULL;
813 /* Only full-label '*.example.com' wildcards? */
814 if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
815 && (!atstart || !atend))
816 return NULL;
817 /* No 'foo*bar' wildcards */
818 if (!atstart && !atend)
819 return NULL;
820 star = &p[i];
821 state &= ~LABEL_START;
822 } else if ((state & LABEL_START) != 0) {
824 * At the start of a label, skip any "xn--" and
825 * remain in the LABEL_START state, but set the
826 * IDNA label state
828 if ((state & LABEL_IDNA) == 0 && len - i >= 4
829 && strncasecmp((char *)&p[i], "xn--", 4) == 0) {
830 i += 3;
831 state |= LABEL_IDNA;
832 continue;
834 /* Labels must start with a letter or digit */
835 state &= ~LABEL_START;
836 if (('a' <= p[i] && p[i] <= 'z')
837 || ('A' <= p[i] && p[i] <= 'Z')
838 || ('0' <= p[i] && p[i] <= '9'))
839 continue;
840 return NULL;
841 } else if (('a' <= p[i] && p[i] <= 'z')
842 || ('A' <= p[i] && p[i] <= 'Z')
843 || ('0' <= p[i] && p[i] <= '9')) {
844 state &= LABEL_IDNA;
845 continue;
846 } else if (p[i] == '.') {
847 if (state & (LABEL_HYPHEN | LABEL_START))
848 return NULL;
849 state = LABEL_START;
850 ++dots;
851 } else if (p[i] == '-') {
852 /* no domain/subdomain starts with '-' */
853 if ((state & LABEL_START) != 0)
854 return NULL;
855 state |= LABEL_HYPHEN;
856 } else
857 return NULL;
861 * The final label must not end in a hyphen or ".", and
862 * there must be at least two dots after the star.
864 if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
865 return NULL;
866 return star;
869 /* Compare using wildcards. */
870 static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
871 const unsigned char *subject, size_t subject_len, unsigned int flags)
873 const unsigned char *star = NULL;
876 * Subject names starting with '.' can only match a wildcard pattern
877 * via a subject sub-domain pattern suffix match.
879 if (!(subject_len > 1 && subject[0] == '.'))
880 star = valid_star(pattern, pattern_len, flags);
881 if (star == NULL)
882 return equal_nocase(pattern, pattern_len,
883 subject, subject_len, flags);
884 return wildcard_match(pattern, star - pattern,
885 star + 1, (pattern + pattern_len) - star - 1,
886 subject, subject_len, flags);
890 * Compare an ASN1_STRING to a supplied string. If they match return 1. If
891 * cmp_type > 0 only compare if string matches the type, otherwise convert it
892 * to UTF8.
895 static int
896 do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
897 unsigned int flags, const char *b, size_t blen, char **peername)
899 int rv = 0;
901 if (!a->data || !a->length)
902 return 0;
903 if (cmp_type > 0) {
904 if (cmp_type != a->type)
905 return 0;
906 if (cmp_type == V_ASN1_IA5STRING)
907 rv = equal(a->data, a->length, (unsigned char *)b,
908 blen, flags);
909 else if (a->length == (int)blen && !memcmp(a->data, b, blen))
910 rv = 1;
911 if (rv > 0 && peername &&
912 (*peername = strndup((char *)a->data, a->length)) == NULL)
913 rv = -1;
914 } else {
915 int astrlen;
916 unsigned char *astr;
917 astrlen = ASN1_STRING_to_UTF8(&astr, a);
918 if (astrlen < 0)
919 return -1;
920 rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
921 if (rv > 0 && peername &&
922 (*peername = strndup((char *)astr, astrlen)) == NULL)
923 rv = -1;
924 free(astr);
926 return rv;
929 static int do_x509_check(X509 *x, const char *chk, size_t chklen,
930 unsigned int flags, int check_type, char **peername)
932 GENERAL_NAMES *gens = NULL;
933 X509_NAME *name = NULL;
934 size_t i;
935 int j;
936 int cnid = NID_undef;
937 int alt_type;
938 int san_present = 0;
939 int rv = 0;
940 equal_fn equal;
942 /* See below, this flag is internal-only */
943 flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
944 if (check_type == GEN_EMAIL) {
945 cnid = NID_pkcs9_emailAddress;
946 alt_type = V_ASN1_IA5STRING;
947 equal = equal_email;
948 } else if (check_type == GEN_DNS) {
949 cnid = NID_commonName;
950 /* Implicit client-side DNS sub-domain pattern */
951 if (chklen > 1 && chk[0] == '.')
952 flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
953 alt_type = V_ASN1_IA5STRING;
954 if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
955 equal = equal_nocase;
956 else
957 equal = equal_wildcard;
958 } else {
959 alt_type = V_ASN1_OCTET_STRING;
960 equal = equal_case;
963 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
964 if (gens != NULL) {
965 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
966 GENERAL_NAME *gen;
967 ASN1_STRING *cstr;
968 gen = sk_GENERAL_NAME_value(gens, i);
969 if (gen->type != check_type)
970 continue;
971 san_present = 1;
972 if (check_type == GEN_EMAIL)
973 cstr = gen->d.rfc822Name;
974 else if (check_type == GEN_DNS)
975 cstr = gen->d.dNSName;
976 else
977 cstr = gen->d.iPAddress;
978 /* Positive on success, negative on error! */
979 if ((rv = do_check_string(cstr, alt_type, equal, flags,
980 chk, chklen, peername)) != 0)
981 break;
983 GENERAL_NAMES_free(gens);
984 if (rv != 0)
985 return rv;
986 if (cnid == NID_undef ||
987 (san_present &&
988 !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
989 return 0;
992 /* We're done if CN-ID is not pertinent */
993 if (cnid == NID_undef)
994 return 0;
996 j = -1;
997 name = X509_get_subject_name(x);
998 while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) {
999 X509_NAME_ENTRY *ne;
1000 ASN1_STRING *str;
1001 if ((ne = X509_NAME_get_entry(name, j)) == NULL)
1002 return -1;
1003 if ((str = X509_NAME_ENTRY_get_data(ne)) == NULL)
1004 return -1;
1005 /* Positive on success, negative on error! */
1006 if ((rv = do_check_string(str, -1, equal, flags,
1007 chk, chklen, peername)) != 0)
1008 return rv;
1010 return 0;
1013 int X509_check_host(X509 *x, const char *chk, size_t chklen,
1014 unsigned int flags, char **peername)
1016 if (chk == NULL)
1017 return -2;
1018 if (chklen == 0)
1019 chklen = strlen(chk);
1020 else if (memchr(chk, '\0', chklen))
1021 return -2;
1022 return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
1025 int X509_check_email(X509 *x, const char *chk, size_t chklen,
1026 unsigned int flags)
1028 if (chk == NULL)
1029 return -2;
1030 if (chklen == 0)
1031 chklen = strlen(chk);
1032 else if (memchr(chk, '\0', chklen))
1033 return -2;
1034 return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
1037 int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
1038 unsigned int flags)
1040 if (chk == NULL)
1041 return -2;
1042 return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
1045 int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
1047 unsigned char ipout[16];
1048 size_t iplen;
1050 if (ipasc == NULL)
1051 return -2;
1052 iplen = (size_t)a2i_ipadd(ipout, ipasc);
1053 if (iplen == 0)
1054 return -2;
1055 return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
1058 /* Convert IP addresses both IPv4 and IPv6 into an
1059 * OCTET STRING compatible with RFC3280.
1062 ASN1_OCTET_STRING *
1063 a2i_IPADDRESS(const char *ipasc)
1065 unsigned char ipout[16];
1066 ASN1_OCTET_STRING *ret;
1067 int iplen;
1069 /* If string contains a ':' assume IPv6 */
1071 iplen = a2i_ipadd(ipout, ipasc);
1073 if (!iplen)
1074 return NULL;
1076 ret = ASN1_OCTET_STRING_new();
1077 if (!ret)
1078 return NULL;
1079 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
1080 ASN1_OCTET_STRING_free(ret);
1081 return NULL;
1083 return ret;
1086 ASN1_OCTET_STRING *
1087 a2i_IPADDRESS_NC(const char *ipasc)
1089 ASN1_OCTET_STRING *ret = NULL;
1090 unsigned char ipout[32];
1091 char *iptmp = NULL, *p;
1092 int iplen1, iplen2;
1094 p = strchr(ipasc, '/');
1095 if (!p)
1096 return NULL;
1097 iptmp = strdup(ipasc);
1098 if (!iptmp)
1099 return NULL;
1100 p = iptmp + (p - ipasc);
1101 *p++ = 0;
1103 iplen1 = a2i_ipadd(ipout, iptmp);
1105 if (!iplen1)
1106 goto err;
1108 iplen2 = a2i_ipadd(ipout + iplen1, p);
1110 free(iptmp);
1111 iptmp = NULL;
1113 if (!iplen2 || (iplen1 != iplen2))
1114 goto err;
1116 ret = ASN1_OCTET_STRING_new();
1117 if (!ret)
1118 goto err;
1119 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
1120 goto err;
1122 return ret;
1124 err:
1125 free(iptmp);
1126 if (ret)
1127 ASN1_OCTET_STRING_free(ret);
1128 return NULL;
1133 a2i_ipadd(unsigned char *ipout, const char *ipasc)
1135 /* If string contains a ':' assume IPv6 */
1137 if (strchr(ipasc, ':')) {
1138 if (!ipv6_from_asc(ipout, ipasc))
1139 return 0;
1140 return 16;
1141 } else {
1142 if (!ipv4_from_asc(ipout, ipasc))
1143 return 0;
1144 return 4;
1148 static int
1149 ipv4_from_asc(unsigned char *v4, const char *in)
1151 int a0, a1, a2, a3;
1152 if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
1153 return 0;
1154 if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) ||
1155 (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
1156 return 0;
1157 v4[0] = a0;
1158 v4[1] = a1;
1159 v4[2] = a2;
1160 v4[3] = a3;
1161 return 1;
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;
1176 static int
1177 ipv6_from_asc(unsigned char *v6, const char *in)
1179 IPV6_STAT v6stat;
1181 v6stat.total = 0;
1182 v6stat.zero_pos = -1;
1183 v6stat.zero_cnt = 0;
1185 /* Treat the IPv6 representation as a list of values
1186 * separated by ':'. The presence of a '::' will parse
1187 * as one, two or three zero length elements.
1189 if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
1190 return 0;
1192 /* Now for some sanity checks */
1194 if (v6stat.zero_pos == -1) {
1195 /* If no '::' must have exactly 16 bytes */
1196 if (v6stat.total != 16)
1197 return 0;
1198 } else {
1199 /* If '::' must have less than 16 bytes */
1200 if (v6stat.total == 16)
1201 return 0;
1202 /* More than three zeroes is an error */
1203 if (v6stat.zero_cnt > 3)
1204 return 0;
1205 /* Can only have three zeroes if nothing else present */
1206 else if (v6stat.zero_cnt == 3) {
1207 if (v6stat.total > 0)
1208 return 0;
1210 /* Can only have two zeroes if at start or end */
1211 else if (v6stat.zero_cnt == 2) {
1212 if ((v6stat.zero_pos != 0) &&
1213 (v6stat.zero_pos != v6stat.total))
1214 return 0;
1215 } else
1216 /* Can only have one zero if *not* start or end */
1218 if ((v6stat.zero_pos == 0) ||
1219 (v6stat.zero_pos == v6stat.total))
1220 return 0;
1224 /* Format result */
1226 if (v6stat.zero_pos >= 0) {
1227 /* Copy initial part */
1228 memcpy(v6, v6stat.tmp, v6stat.zero_pos);
1229 /* Zero middle */
1230 memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
1231 /* Copy final part */
1232 if (v6stat.total != v6stat.zero_pos)
1233 memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
1234 v6stat.tmp + v6stat.zero_pos,
1235 v6stat.total - v6stat.zero_pos);
1236 } else
1237 memcpy(v6, v6stat.tmp, 16);
1239 return 1;
1242 static int
1243 ipv6_cb(const char *elem, int len, void *usr)
1245 IPV6_STAT *s = usr;
1247 /* Error if 16 bytes written */
1248 if (s->total == 16)
1249 return 0;
1250 if (len == 0) {
1251 /* Zero length element, corresponds to '::' */
1252 if (s->zero_pos == -1)
1253 s->zero_pos = s->total;
1254 /* If we've already got a :: its an error */
1255 else if (s->zero_pos != s->total)
1256 return 0;
1257 s->zero_cnt++;
1258 } else {
1259 /* If more than 4 characters could be final a.b.c.d form */
1260 if (len > 4) {
1261 /* Need at least 4 bytes left */
1262 if (s->total > 12)
1263 return 0;
1264 /* Must be end of string */
1265 if (elem[len])
1266 return 0;
1267 if (!ipv4_from_asc(s->tmp + s->total, elem))
1268 return 0;
1269 s->total += 4;
1270 } else {
1271 if (!ipv6_hex(s->tmp + s->total, elem, len))
1272 return 0;
1273 s->total += 2;
1276 return 1;
1279 /* Convert a string of up to 4 hex digits into the corresponding
1280 * IPv6 form.
1283 static int
1284 ipv6_hex(unsigned char *out, const char *in, int inlen)
1286 unsigned char c;
1287 unsigned int num = 0;
1289 if (inlen > 4)
1290 return 0;
1291 while (inlen--) {
1292 c = *in++;
1293 num <<= 4;
1294 if ((c >= '0') && (c <= '9'))
1295 num |= c - '0';
1296 else if ((c >= 'A') && (c <= 'F'))
1297 num |= c - 'A' + 10;
1298 else if ((c >= 'a') && (c <= 'f'))
1299 num |= c - 'a' + 10;
1300 else
1301 return 0;
1303 out[0] = num >> 8;
1304 out[1] = num & 0xff;
1305 return 1;
1309 X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
1310 unsigned long chtype)
1312 CONF_VALUE *v;
1313 int i, mval;
1314 char *p, *type;
1316 if (!nm)
1317 return 0;
1319 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1320 v = sk_CONF_VALUE_value(dn_sk, i);
1321 type = v->name;
1322 /* Skip past any leading X. X: X, etc to allow for
1323 * multiple instances
1325 for (p = type; *p; p++)
1326 if ((*p == ':') || (*p == ',') || (*p == '.')) {
1327 p++;
1328 if (*p)
1329 type = p;
1330 break;
1332 if (*type == '+') {
1333 mval = -1;
1334 type++;
1335 } else
1336 mval = 0;
1337 if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
1338 (unsigned char *) v->value, -1, -1, mval))
1339 return 0;
1341 return 1;