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