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