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