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