VirtualBox

source: vbox/trunk/src/libs/openssl-3.0.2/crypto/x509/v3_utl.c@ 94404

Last change on this file since 94404 was 94404, checked in by vboxsync, 3 years ago

libs/openssl: Update to 3.0.2 and switch to it, bugref:10128

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette