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