155714Skris/* v3_utl.c */
2280304Sjkim/*
3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4160814Ssimon * project.
555714Skris */
655714Skris/* ====================================================================
7160814Ssimon * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
855714Skris *
955714Skris * Redistribution and use in source and binary forms, with or without
1055714Skris * modification, are permitted provided that the following conditions
1155714Skris * are met:
1255714Skris *
1355714Skris * 1. Redistributions of source code must retain the above copyright
14280304Sjkim *    notice, this list of conditions and the following disclaimer.
1555714Skris *
1655714Skris * 2. Redistributions in binary form must reproduce the above copyright
1755714Skris *    notice, this list of conditions and the following disclaimer in
1855714Skris *    the documentation and/or other materials provided with the
1955714Skris *    distribution.
2055714Skris *
2155714Skris * 3. All advertising materials mentioning features or use of this
2255714Skris *    software must display the following acknowledgment:
2355714Skris *    "This product includes software developed by the OpenSSL Project
2455714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2555714Skris *
2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2755714Skris *    endorse or promote products derived from this software without
2855714Skris *    prior written permission. For written permission, please contact
2955714Skris *    licensing@OpenSSL.org.
3055714Skris *
3155714Skris * 5. Products derived from this software may not be called "OpenSSL"
3255714Skris *    nor may "OpenSSL" appear in their names without prior written
3355714Skris *    permission of the OpenSSL Project.
3455714Skris *
3555714Skris * 6. Redistributions of any form whatsoever must retain the following
3655714Skris *    acknowledgment:
3755714Skris *    "This product includes software developed by the OpenSSL Project
3855714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3955714Skris *
4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4355714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5255714Skris * ====================================================================
5355714Skris *
5455714Skris * This product includes cryptographic software written by Eric Young
5555714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5655714Skris * Hudson (tjh@cryptsoft.com).
5755714Skris *
5855714Skris */
5955714Skris/* X509 v3 extension utilities */
6055714Skris
6155714Skris#include <stdio.h>
6255714Skris#include <ctype.h>
6355714Skris#include "cryptlib.h"
6455714Skris#include <openssl/conf.h>
6555714Skris#include <openssl/x509v3.h>
66160814Ssimon#include <openssl/bn.h>
6755714Skris
6855714Skrisstatic char *strip_spaces(char *name);
69280304Sjkimstatic int sk_strcmp(const char *const *a, const char *const *b);
70280304Sjkimstatic STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
71280304Sjkim                                           GENERAL_NAMES *gens);
72238405Sjkimstatic void str_free(OPENSSL_STRING str);
73238405Sjkimstatic int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
7455714Skris
75160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in);
76160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in);
77160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr);
78160814Ssimonstatic int ipv6_hex(unsigned char *out, const char *in, int inlen);
79160814Ssimon
8055714Skris/* Add a CONF_VALUE name value pair to stack */
8155714Skris
8255714Skrisint X509V3_add_value(const char *name, const char *value,
83280304Sjkim                     STACK_OF(CONF_VALUE) **extlist)
8455714Skris{
85280304Sjkim    CONF_VALUE *vtmp = NULL;
86280304Sjkim    char *tname = NULL, *tvalue = NULL;
87280304Sjkim    if (name && !(tname = BUF_strdup(name)))
88280304Sjkim        goto err;
89280304Sjkim    if (value && !(tvalue = BUF_strdup(value)))
90280304Sjkim        goto err;
91280304Sjkim    if (!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE))))
92280304Sjkim        goto err;
93280304Sjkim    if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null()))
94280304Sjkim        goto err;
95280304Sjkim    vtmp->section = NULL;
96280304Sjkim    vtmp->name = tname;
97280304Sjkim    vtmp->value = tvalue;
98280304Sjkim    if (!sk_CONF_VALUE_push(*extlist, vtmp))
99280304Sjkim        goto err;
100280304Sjkim    return 1;
101280304Sjkim err:
102280304Sjkim    X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE);
103280304Sjkim    if (vtmp)
104280304Sjkim        OPENSSL_free(vtmp);
105280304Sjkim    if (tname)
106280304Sjkim        OPENSSL_free(tname);
107280304Sjkim    if (tvalue)
108280304Sjkim        OPENSSL_free(tvalue);
109280304Sjkim    return 0;
11055714Skris}
11155714Skris
11255714Skrisint X509V3_add_value_uchar(const char *name, const unsigned char *value,
113280304Sjkim                           STACK_OF(CONF_VALUE) **extlist)
114280304Sjkim{
115280304Sjkim    return X509V3_add_value(name, (const char *)value, extlist);
116280304Sjkim}
11755714Skris
11855714Skris/* Free function for STACK_OF(CONF_VALUE) */
11955714Skris
12055714Skrisvoid X509V3_conf_free(CONF_VALUE *conf)
12155714Skris{
122280304Sjkim    if (!conf)
123280304Sjkim        return;
124280304Sjkim    if (conf->name)
125280304Sjkim        OPENSSL_free(conf->name);
126280304Sjkim    if (conf->value)
127280304Sjkim        OPENSSL_free(conf->value);
128280304Sjkim    if (conf->section)
129280304Sjkim        OPENSSL_free(conf->section);
130280304Sjkim    OPENSSL_free(conf);
13155714Skris}
13255714Skris
13355714Skrisint X509V3_add_value_bool(const char *name, int asn1_bool,
134280304Sjkim                          STACK_OF(CONF_VALUE) **extlist)
13555714Skris{
136280304Sjkim    if (asn1_bool)
137280304Sjkim        return X509V3_add_value(name, "TRUE", extlist);
138280304Sjkim    return X509V3_add_value(name, "FALSE", extlist);
13955714Skris}
14055714Skris
14155714Skrisint X509V3_add_value_bool_nf(char *name, int asn1_bool,
142280304Sjkim                             STACK_OF(CONF_VALUE) **extlist)
14355714Skris{
144280304Sjkim    if (asn1_bool)
145280304Sjkim        return X509V3_add_value(name, "TRUE", extlist);
146280304Sjkim    return 1;
14755714Skris}
14855714Skris
14955714Skrischar *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
15055714Skris{
151280304Sjkim    BIGNUM *bntmp = NULL;
152280304Sjkim    char *strtmp = NULL;
153280304Sjkim    if (!a)
154280304Sjkim        return NULL;
155280304Sjkim    if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
156280304Sjkim        !(strtmp = BN_bn2dec(bntmp)))
157280304Sjkim        X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
158280304Sjkim    BN_free(bntmp);
159280304Sjkim    return strtmp;
16055714Skris}
16155714Skris
16255714Skrischar *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
16355714Skris{
164280304Sjkim    BIGNUM *bntmp = NULL;
165280304Sjkim    char *strtmp = NULL;
166280304Sjkim    if (!a)
167280304Sjkim        return NULL;
168280304Sjkim    if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
169280304Sjkim        !(strtmp = BN_bn2dec(bntmp)))
170280304Sjkim        X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
171280304Sjkim    BN_free(bntmp);
172280304Sjkim    return strtmp;
17355714Skris}
17455714Skris
17555714SkrisASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
17655714Skris{
177280304Sjkim    BIGNUM *bn = NULL;
178280304Sjkim    ASN1_INTEGER *aint;
179280304Sjkim    int isneg, ishex;
180280304Sjkim    int ret;
181280304Sjkim    if (!value) {
182280304Sjkim        X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE);
183280304Sjkim        return 0;
184280304Sjkim    }
185280304Sjkim    bn = BN_new();
186280304Sjkim    if (value[0] == '-') {
187280304Sjkim        value++;
188280304Sjkim        isneg = 1;
189280304Sjkim    } else
190280304Sjkim        isneg = 0;
191109998Smarkm
192280304Sjkim    if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
193280304Sjkim        value += 2;
194280304Sjkim        ishex = 1;
195280304Sjkim    } else
196280304Sjkim        ishex = 0;
197109998Smarkm
198280304Sjkim    if (ishex)
199280304Sjkim        ret = BN_hex2bn(&bn, value);
200280304Sjkim    else
201280304Sjkim        ret = BN_dec2bn(&bn, value);
202109998Smarkm
203280304Sjkim    if (!ret || value[ret]) {
204280304Sjkim        BN_free(bn);
205280304Sjkim        X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR);
206280304Sjkim        return 0;
207280304Sjkim    }
20855714Skris
209280304Sjkim    if (isneg && BN_is_zero(bn))
210280304Sjkim        isneg = 0;
211109998Smarkm
212280304Sjkim    aint = BN_to_ASN1_INTEGER(bn, NULL);
213280304Sjkim    BN_free(bn);
214280304Sjkim    if (!aint) {
215280304Sjkim        X509V3err(X509V3_F_S2I_ASN1_INTEGER,
216280304Sjkim                  X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
217280304Sjkim        return 0;
218280304Sjkim    }
219280304Sjkim    if (isneg)
220280304Sjkim        aint->type |= V_ASN1_NEG;
221280304Sjkim    return aint;
22255714Skris}
22355714Skris
22455714Skrisint X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
225280304Sjkim                         STACK_OF(CONF_VALUE) **extlist)
22655714Skris{
227280304Sjkim    char *strtmp;
228280304Sjkim    int ret;
229280304Sjkim    if (!aint)
230280304Sjkim        return 1;
231280304Sjkim    if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
232280304Sjkim        return 0;
233280304Sjkim    ret = X509V3_add_value(name, strtmp, extlist);
234280304Sjkim    OPENSSL_free(strtmp);
235280304Sjkim    return ret;
23655714Skris}
23755714Skris
23855714Skrisint X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
23955714Skris{
240280304Sjkim    char *btmp;
241280304Sjkim    if (!(btmp = value->value))
242280304Sjkim        goto err;
243280304Sjkim    if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
244280304Sjkim        || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
245280304Sjkim        || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
246280304Sjkim        *asn1_bool = 0xff;
247280304Sjkim        return 1;
248280304Sjkim    } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
249280304Sjkim               || !strcmp(btmp, "N") || !strcmp(btmp, "n")
250280304Sjkim               || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
251280304Sjkim        *asn1_bool = 0;
252280304Sjkim        return 1;
253280304Sjkim    }
254280304Sjkim err:
255280304Sjkim    X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,
256280304Sjkim              X509V3_R_INVALID_BOOLEAN_STRING);
257280304Sjkim    X509V3_conf_err(value);
258280304Sjkim    return 0;
25955714Skris}
26055714Skris
26155714Skrisint X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
26255714Skris{
263280304Sjkim    ASN1_INTEGER *itmp;
264280304Sjkim    if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
265280304Sjkim        X509V3_conf_err(value);
266280304Sjkim        return 0;
267280304Sjkim    }
268280304Sjkim    *aint = itmp;
269280304Sjkim    return 1;
27055714Skris}
27155714Skris
272280304Sjkim#define HDR_NAME        1
273280304Sjkim#define HDR_VALUE       2
27455714Skris
275280304Sjkim/*
276280304Sjkim * #define DEBUG
277280304Sjkim */
27855714Skris
279109998SmarkmSTACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
28055714Skris{
281280304Sjkim    char *p, *q, c;
282280304Sjkim    char *ntmp, *vtmp;
283280304Sjkim    STACK_OF(CONF_VALUE) *values = NULL;
284280304Sjkim    char *linebuf;
285280304Sjkim    int state;
286280304Sjkim    /* We are going to modify the line so copy it first */
287280304Sjkim    linebuf = BUF_strdup(line);
288284285Sjkim    if (linebuf == NULL) {
289284285Sjkim        X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE);
290284285Sjkim        goto err;
291284285Sjkim    }
292280304Sjkim    state = HDR_NAME;
293280304Sjkim    ntmp = NULL;
294280304Sjkim    /* Go through all characters */
295280304Sjkim    for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
296280304Sjkim         p++) {
29755714Skris
298280304Sjkim        switch (state) {
299280304Sjkim        case HDR_NAME:
300280304Sjkim            if (c == ':') {
301280304Sjkim                state = HDR_VALUE;
302280304Sjkim                *p = 0;
303280304Sjkim                ntmp = strip_spaces(q);
304280304Sjkim                if (!ntmp) {
305280304Sjkim                    X509V3err(X509V3_F_X509V3_PARSE_LIST,
306280304Sjkim                              X509V3_R_INVALID_NULL_NAME);
307280304Sjkim                    goto err;
308280304Sjkim                }
309280304Sjkim                q = p + 1;
310280304Sjkim            } else if (c == ',') {
311280304Sjkim                *p = 0;
312280304Sjkim                ntmp = strip_spaces(q);
313280304Sjkim                q = p + 1;
314100928Snectar#if 0
315280304Sjkim                printf("%s\n", ntmp);
31655714Skris#endif
317280304Sjkim                if (!ntmp) {
318280304Sjkim                    X509V3err(X509V3_F_X509V3_PARSE_LIST,
319280304Sjkim                              X509V3_R_INVALID_NULL_NAME);
320280304Sjkim                    goto err;
321280304Sjkim                }
322280304Sjkim                X509V3_add_value(ntmp, NULL, &values);
323280304Sjkim            }
324280304Sjkim            break;
32555714Skris
326280304Sjkim        case HDR_VALUE:
327280304Sjkim            if (c == ',') {
328280304Sjkim                state = HDR_NAME;
329280304Sjkim                *p = 0;
330280304Sjkim                vtmp = strip_spaces(q);
331100928Snectar#if 0
332280304Sjkim                printf("%s\n", ntmp);
33355714Skris#endif
334280304Sjkim                if (!vtmp) {
335280304Sjkim                    X509V3err(X509V3_F_X509V3_PARSE_LIST,
336280304Sjkim                              X509V3_R_INVALID_NULL_VALUE);
337280304Sjkim                    goto err;
338280304Sjkim                }
339280304Sjkim                X509V3_add_value(ntmp, vtmp, &values);
340280304Sjkim                ntmp = NULL;
341280304Sjkim                q = p + 1;
342280304Sjkim            }
34355714Skris
344280304Sjkim        }
345280304Sjkim    }
34655714Skris
347280304Sjkim    if (state == HDR_VALUE) {
348280304Sjkim        vtmp = strip_spaces(q);
349100928Snectar#if 0
350280304Sjkim        printf("%s=%s\n", ntmp, vtmp);
35155714Skris#endif
352280304Sjkim        if (!vtmp) {
353280304Sjkim            X509V3err(X509V3_F_X509V3_PARSE_LIST,
354280304Sjkim                      X509V3_R_INVALID_NULL_VALUE);
355280304Sjkim            goto err;
356280304Sjkim        }
357280304Sjkim        X509V3_add_value(ntmp, vtmp, &values);
358280304Sjkim    } else {
359280304Sjkim        ntmp = strip_spaces(q);
360100928Snectar#if 0
361280304Sjkim        printf("%s\n", ntmp);
36255714Skris#endif
363280304Sjkim        if (!ntmp) {
364280304Sjkim            X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
365280304Sjkim            goto err;
366280304Sjkim        }
367280304Sjkim        X509V3_add_value(ntmp, NULL, &values);
368280304Sjkim    }
369280304Sjkim    OPENSSL_free(linebuf);
370280304Sjkim    return values;
37155714Skris
372280304Sjkim err:
373280304Sjkim    OPENSSL_free(linebuf);
374280304Sjkim    sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
375280304Sjkim    return NULL;
37655714Skris
37755714Skris}
37855714Skris
37955714Skris/* Delete leading and trailing spaces from a string */
38055714Skrisstatic char *strip_spaces(char *name)
38155714Skris{
382280304Sjkim    char *p, *q;
383280304Sjkim    /* Skip over leading spaces */
384280304Sjkim    p = name;
385280304Sjkim    while (*p && isspace((unsigned char)*p))
386280304Sjkim        p++;
387280304Sjkim    if (!*p)
388280304Sjkim        return NULL;
389280304Sjkim    q = p + strlen(p) - 1;
390280304Sjkim    while ((q != p) && isspace((unsigned char)*q))
391280304Sjkim        q--;
392280304Sjkim    if (p != q)
393280304Sjkim        q[1] = 0;
394280304Sjkim    if (!*p)
395280304Sjkim        return NULL;
396280304Sjkim    return p;
39755714Skris}
39855714Skris
39955714Skris/* hex string utilities */
40055714Skris
401280304Sjkim/*
402280304Sjkim * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
403280304Sjkim * hex representation @@@ (Contents of buffer are always kept in ASCII, also
404280304Sjkim * on EBCDIC machines)
40555714Skris */
40655714Skris
407238405Sjkimchar *hex_to_string(const unsigned char *buffer, long len)
40855714Skris{
409280304Sjkim    char *tmp, *q;
410280304Sjkim    const unsigned char *p;
411280304Sjkim    int i;
412280304Sjkim    const static char hexdig[] = "0123456789ABCDEF";
413280304Sjkim    if (!buffer || !len)
414280304Sjkim        return NULL;
415280304Sjkim    if (!(tmp = OPENSSL_malloc(len * 3 + 1))) {
416280304Sjkim        X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE);
417280304Sjkim        return NULL;
418280304Sjkim    }
419280304Sjkim    q = tmp;
420280304Sjkim    for (i = 0, p = buffer; i < len; i++, p++) {
421280304Sjkim        *q++ = hexdig[(*p >> 4) & 0xf];
422280304Sjkim        *q++ = hexdig[*p & 0xf];
423280304Sjkim        *q++ = ':';
424280304Sjkim    }
425280304Sjkim    q[-1] = 0;
42668651Skris#ifdef CHARSET_EBCDIC
427280304Sjkim    ebcdic2ascii(tmp, tmp, q - tmp - 1);
42868651Skris#endif
42968651Skris
430280304Sjkim    return tmp;
43155714Skris}
43255714Skris
433280304Sjkim/*
434280304Sjkim * Give a string of hex digits convert to a buffer
43555714Skris */
43655714Skris
437238405Sjkimunsigned char *string_to_hex(const char *str, long *len)
43855714Skris{
439280304Sjkim    unsigned char *hexbuf, *q;
440280304Sjkim    unsigned char ch, cl, *p;
441280304Sjkim    if (!str) {
442280304Sjkim        X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_INVALID_NULL_ARGUMENT);
443280304Sjkim        return NULL;
444280304Sjkim    }
445280304Sjkim    if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1)))
446280304Sjkim        goto err;
447280304Sjkim    for (p = (unsigned char *)str, q = hexbuf; *p;) {
448280304Sjkim        ch = *p++;
44968651Skris#ifdef CHARSET_EBCDIC
450280304Sjkim        ch = os_toebcdic[ch];
45168651Skris#endif
452280304Sjkim        if (ch == ':')
453280304Sjkim            continue;
454280304Sjkim        cl = *p++;
45568651Skris#ifdef CHARSET_EBCDIC
456280304Sjkim        cl = os_toebcdic[cl];
45768651Skris#endif
458280304Sjkim        if (!cl) {
459280304Sjkim            X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ODD_NUMBER_OF_DIGITS);
460280304Sjkim            OPENSSL_free(hexbuf);
461280304Sjkim            return NULL;
462280304Sjkim        }
463280304Sjkim        if (isupper(ch))
464280304Sjkim            ch = tolower(ch);
465280304Sjkim        if (isupper(cl))
466280304Sjkim            cl = tolower(cl);
46755714Skris
468280304Sjkim        if ((ch >= '0') && (ch <= '9'))
469280304Sjkim            ch -= '0';
470280304Sjkim        else if ((ch >= 'a') && (ch <= 'f'))
471280304Sjkim            ch -= 'a' - 10;
472280304Sjkim        else
473280304Sjkim            goto badhex;
47455714Skris
475280304Sjkim        if ((cl >= '0') && (cl <= '9'))
476280304Sjkim            cl -= '0';
477280304Sjkim        else if ((cl >= 'a') && (cl <= 'f'))
478280304Sjkim            cl -= 'a' - 10;
479280304Sjkim        else
480280304Sjkim            goto badhex;
48155714Skris
482280304Sjkim        *q++ = (ch << 4) | cl;
483280304Sjkim    }
48455714Skris
485280304Sjkim    if (len)
486280304Sjkim        *len = q - hexbuf;
48755714Skris
488280304Sjkim    return hexbuf;
48955714Skris
490280304Sjkim err:
491280304Sjkim    if (hexbuf)
492280304Sjkim        OPENSSL_free(hexbuf);
493280304Sjkim    X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE);
494280304Sjkim    return NULL;
49555714Skris
496280304Sjkim badhex:
497280304Sjkim    OPENSSL_free(hexbuf);
498280304Sjkim    X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT);
499280304Sjkim    return NULL;
50055714Skris
50155714Skris}
50255714Skris
503280304Sjkim/*
504280304Sjkim * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
50555714Skris */
50655714Skris
50755714Skrisint name_cmp(const char *name, const char *cmp)
50855714Skris{
509280304Sjkim    int len, ret;
510280304Sjkim    char c;
511280304Sjkim    len = strlen(cmp);
512280304Sjkim    if ((ret = strncmp(name, cmp, len)))
513280304Sjkim        return ret;
514280304Sjkim    c = name[len];
515280304Sjkim    if (!c || (c == '.'))
516280304Sjkim        return 0;
517280304Sjkim    return 1;
51855714Skris}
51968651Skris
520280304Sjkimstatic int sk_strcmp(const char *const *a, const char *const *b)
52168651Skris{
522280304Sjkim    return strcmp(*a, *b);
52368651Skris}
52468651Skris
525238405SjkimSTACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
52668651Skris{
527280304Sjkim    GENERAL_NAMES *gens;
528280304Sjkim    STACK_OF(OPENSSL_STRING) *ret;
529238405Sjkim
530280304Sjkim    gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
531280304Sjkim    ret = get_email(X509_get_subject_name(x), gens);
532280304Sjkim    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
533280304Sjkim    return ret;
53468651Skris}
53568651Skris
536238405SjkimSTACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
537194206Ssimon{
538280304Sjkim    AUTHORITY_INFO_ACCESS *info;
539280304Sjkim    STACK_OF(OPENSSL_STRING) *ret = NULL;
540280304Sjkim    int i;
541238405Sjkim
542280304Sjkim    info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
543280304Sjkim    if (!info)
544280304Sjkim        return NULL;
545280304Sjkim    for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
546280304Sjkim        ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
547280304Sjkim        if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
548280304Sjkim            if (ad->location->type == GEN_URI) {
549280304Sjkim                if (!append_ia5
550280304Sjkim                    (&ret, ad->location->d.uniformResourceIdentifier))
551280304Sjkim                    break;
552280304Sjkim            }
553280304Sjkim        }
554280304Sjkim    }
555280304Sjkim    AUTHORITY_INFO_ACCESS_free(info);
556280304Sjkim    return ret;
557194206Ssimon}
558194206Ssimon
559238405SjkimSTACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
56068651Skris{
561280304Sjkim    GENERAL_NAMES *gens;
562280304Sjkim    STACK_OF(X509_EXTENSION) *exts;
563280304Sjkim    STACK_OF(OPENSSL_STRING) *ret;
564238405Sjkim
565280304Sjkim    exts = X509_REQ_get_extensions(x);
566280304Sjkim    gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
567280304Sjkim    ret = get_email(X509_REQ_get_subject_name(x), gens);
568280304Sjkim    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
569280304Sjkim    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
570280304Sjkim    return ret;
57168651Skris}
57268651Skris
573280304Sjkimstatic STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
574280304Sjkim                                           GENERAL_NAMES *gens)
57568651Skris{
576280304Sjkim    STACK_OF(OPENSSL_STRING) *ret = NULL;
577280304Sjkim    X509_NAME_ENTRY *ne;
578280304Sjkim    ASN1_IA5STRING *email;
579280304Sjkim    GENERAL_NAME *gen;
580280304Sjkim    int i;
581280304Sjkim    /* Now add any email address(es) to STACK */
582280304Sjkim    i = -1;
583280304Sjkim    /* First supplied X509_NAME */
584280304Sjkim    while ((i = X509_NAME_get_index_by_NID(name,
585280304Sjkim                                           NID_pkcs9_emailAddress, i)) >= 0) {
586280304Sjkim        ne = X509_NAME_get_entry(name, i);
587280304Sjkim        email = X509_NAME_ENTRY_get_data(ne);
588280304Sjkim        if (!append_ia5(&ret, email))
589280304Sjkim            return NULL;
590280304Sjkim    }
591280304Sjkim    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
592280304Sjkim        gen = sk_GENERAL_NAME_value(gens, i);
593280304Sjkim        if (gen->type != GEN_EMAIL)
594280304Sjkim            continue;
595280304Sjkim        if (!append_ia5(&ret, gen->d.ia5))
596280304Sjkim            return NULL;
597280304Sjkim    }
598280304Sjkim    return ret;
59968651Skris}
60068651Skris
601238405Sjkimstatic void str_free(OPENSSL_STRING str)
60268651Skris{
603280304Sjkim    OPENSSL_free(str);
60468651Skris}
60568651Skris
606238405Sjkimstatic int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
60768651Skris{
608280304Sjkim    char *emtmp;
609280304Sjkim    /* First some sanity checks */
610280304Sjkim    if (email->type != V_ASN1_IA5STRING)
611280304Sjkim        return 1;
612280304Sjkim    if (!email->data || !email->length)
613280304Sjkim        return 1;
614280304Sjkim    if (!*sk)
615280304Sjkim        *sk = sk_OPENSSL_STRING_new(sk_strcmp);
616280304Sjkim    if (!*sk)
617280304Sjkim        return 0;
618280304Sjkim    /* Don't add duplicates */
619280304Sjkim    if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
620280304Sjkim        return 1;
621280304Sjkim    emtmp = BUF_strdup((char *)email->data);
622280304Sjkim    if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
623280304Sjkim        X509_email_free(*sk);
624280304Sjkim        *sk = NULL;
625280304Sjkim        return 0;
626280304Sjkim    }
627280304Sjkim    return 1;
62868651Skris}
62968651Skris
630238405Sjkimvoid X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
63168651Skris{
632280304Sjkim    sk_OPENSSL_STRING_pop_free(sk, str_free);
63368651Skris}
634160814Ssimon
635280304Sjkim/*
636280304Sjkim * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
637280304Sjkim * with RFC3280.
638160814Ssimon */
639160814Ssimon
640160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
641280304Sjkim{
642280304Sjkim    unsigned char ipout[16];
643280304Sjkim    ASN1_OCTET_STRING *ret;
644280304Sjkim    int iplen;
645160814Ssimon
646280304Sjkim    /* If string contains a ':' assume IPv6 */
647160814Ssimon
648280304Sjkim    iplen = a2i_ipadd(ipout, ipasc);
649160814Ssimon
650280304Sjkim    if (!iplen)
651280304Sjkim        return NULL;
652160814Ssimon
653280304Sjkim    ret = ASN1_OCTET_STRING_new();
654280304Sjkim    if (!ret)
655280304Sjkim        return NULL;
656280304Sjkim    if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
657280304Sjkim        ASN1_OCTET_STRING_free(ret);
658280304Sjkim        return NULL;
659280304Sjkim    }
660280304Sjkim    return ret;
661280304Sjkim}
662160814Ssimon
663160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
664280304Sjkim{
665280304Sjkim    ASN1_OCTET_STRING *ret = NULL;
666280304Sjkim    unsigned char ipout[32];
667280304Sjkim    char *iptmp = NULL, *p;
668280304Sjkim    int iplen1, iplen2;
669280304Sjkim    p = strchr(ipasc, '/');
670280304Sjkim    if (!p)
671280304Sjkim        return NULL;
672280304Sjkim    iptmp = BUF_strdup(ipasc);
673280304Sjkim    if (!iptmp)
674280304Sjkim        return NULL;
675280304Sjkim    p = iptmp + (p - ipasc);
676280304Sjkim    *p++ = 0;
677160814Ssimon
678280304Sjkim    iplen1 = a2i_ipadd(ipout, iptmp);
679160814Ssimon
680280304Sjkim    if (!iplen1)
681280304Sjkim        goto err;
682160814Ssimon
683280304Sjkim    iplen2 = a2i_ipadd(ipout + iplen1, p);
684160814Ssimon
685280304Sjkim    OPENSSL_free(iptmp);
686280304Sjkim    iptmp = NULL;
687160814Ssimon
688280304Sjkim    if (!iplen2 || (iplen1 != iplen2))
689280304Sjkim        goto err;
690160814Ssimon
691280304Sjkim    ret = ASN1_OCTET_STRING_new();
692280304Sjkim    if (!ret)
693280304Sjkim        goto err;
694280304Sjkim    if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
695280304Sjkim        goto err;
696160814Ssimon
697280304Sjkim    return ret;
698160814Ssimon
699280304Sjkim err:
700280304Sjkim    if (iptmp)
701280304Sjkim        OPENSSL_free(iptmp);
702280304Sjkim    if (ret)
703280304Sjkim        ASN1_OCTET_STRING_free(ret);
704280304Sjkim    return NULL;
705280304Sjkim}
706160814Ssimon
707167612Ssimonint a2i_ipadd(unsigned char *ipout, const char *ipasc)
708280304Sjkim{
709280304Sjkim    /* If string contains a ':' assume IPv6 */
710160814Ssimon
711280304Sjkim    if (strchr(ipasc, ':')) {
712280304Sjkim        if (!ipv6_from_asc(ipout, ipasc))
713280304Sjkim            return 0;
714280304Sjkim        return 16;
715280304Sjkim    } else {
716280304Sjkim        if (!ipv4_from_asc(ipout, ipasc))
717280304Sjkim            return 0;
718280304Sjkim        return 4;
719280304Sjkim    }
720280304Sjkim}
721160814Ssimon
722160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in)
723280304Sjkim{
724280304Sjkim    int a0, a1, a2, a3;
725280304Sjkim    if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
726280304Sjkim        return 0;
727280304Sjkim    if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
728280304Sjkim        || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
729280304Sjkim        return 0;
730280304Sjkim    v4[0] = a0;
731280304Sjkim    v4[1] = a1;
732280304Sjkim    v4[2] = a2;
733280304Sjkim    v4[3] = a3;
734280304Sjkim    return 1;
735280304Sjkim}
736160814Ssimon
737160814Ssimontypedef struct {
738280304Sjkim    /* Temporary store for IPV6 output */
739280304Sjkim    unsigned char tmp[16];
740280304Sjkim    /* Total number of bytes in tmp */
741280304Sjkim    int total;
742280304Sjkim    /* The position of a zero (corresponding to '::') */
743280304Sjkim    int zero_pos;
744280304Sjkim    /* Number of zeroes */
745280304Sjkim    int zero_cnt;
746280304Sjkim} IPV6_STAT;
747160814Ssimon
748160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in)
749280304Sjkim{
750280304Sjkim    IPV6_STAT v6stat;
751280304Sjkim    v6stat.total = 0;
752280304Sjkim    v6stat.zero_pos = -1;
753280304Sjkim    v6stat.zero_cnt = 0;
754280304Sjkim    /*
755280304Sjkim     * Treat the IPv6 representation as a list of values separated by ':'.
756280304Sjkim     * The presence of a '::' will parse as one, two or three zero length
757280304Sjkim     * elements.
758280304Sjkim     */
759280304Sjkim    if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
760280304Sjkim        return 0;
761160814Ssimon
762280304Sjkim    /* Now for some sanity checks */
763160814Ssimon
764280304Sjkim    if (v6stat.zero_pos == -1) {
765280304Sjkim        /* If no '::' must have exactly 16 bytes */
766280304Sjkim        if (v6stat.total != 16)
767280304Sjkim            return 0;
768280304Sjkim    } else {
769280304Sjkim        /* If '::' must have less than 16 bytes */
770280304Sjkim        if (v6stat.total == 16)
771280304Sjkim            return 0;
772280304Sjkim        /* More than three zeroes is an error */
773280304Sjkim        if (v6stat.zero_cnt > 3)
774280304Sjkim            return 0;
775280304Sjkim        /* Can only have three zeroes if nothing else present */
776280304Sjkim        else if (v6stat.zero_cnt == 3) {
777280304Sjkim            if (v6stat.total > 0)
778280304Sjkim                return 0;
779280304Sjkim        }
780280304Sjkim        /* Can only have two zeroes if at start or end */
781280304Sjkim        else if (v6stat.zero_cnt == 2) {
782280304Sjkim            if ((v6stat.zero_pos != 0)
783280304Sjkim                && (v6stat.zero_pos != v6stat.total))
784280304Sjkim                return 0;
785280304Sjkim        } else
786280304Sjkim            /* Can only have one zero if *not* start or end */
787280304Sjkim        {
788280304Sjkim            if ((v6stat.zero_pos == 0)
789280304Sjkim                || (v6stat.zero_pos == v6stat.total))
790280304Sjkim                return 0;
791280304Sjkim        }
792280304Sjkim    }
793160814Ssimon
794280304Sjkim    /* Format result */
795160814Ssimon
796280304Sjkim    if (v6stat.zero_pos >= 0) {
797280304Sjkim        /* Copy initial part */
798280304Sjkim        memcpy(v6, v6stat.tmp, v6stat.zero_pos);
799280304Sjkim        /* Zero middle */
800280304Sjkim        memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
801280304Sjkim        /* Copy final part */
802280304Sjkim        if (v6stat.total != v6stat.zero_pos)
803280304Sjkim            memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
804280304Sjkim                   v6stat.tmp + v6stat.zero_pos,
805280304Sjkim                   v6stat.total - v6stat.zero_pos);
806280304Sjkim    } else
807280304Sjkim        memcpy(v6, v6stat.tmp, 16);
808160814Ssimon
809280304Sjkim    return 1;
810280304Sjkim}
811160814Ssimon
812160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr)
813280304Sjkim{
814280304Sjkim    IPV6_STAT *s = usr;
815280304Sjkim    /* Error if 16 bytes written */
816280304Sjkim    if (s->total == 16)
817280304Sjkim        return 0;
818280304Sjkim    if (len == 0) {
819280304Sjkim        /* Zero length element, corresponds to '::' */
820280304Sjkim        if (s->zero_pos == -1)
821280304Sjkim            s->zero_pos = s->total;
822280304Sjkim        /* If we've already got a :: its an error */
823280304Sjkim        else if (s->zero_pos != s->total)
824280304Sjkim            return 0;
825280304Sjkim        s->zero_cnt++;
826280304Sjkim    } else {
827280304Sjkim        /* If more than 4 characters could be final a.b.c.d form */
828280304Sjkim        if (len > 4) {
829280304Sjkim            /* Need at least 4 bytes left */
830280304Sjkim            if (s->total > 12)
831280304Sjkim                return 0;
832280304Sjkim            /* Must be end of string */
833280304Sjkim            if (elem[len])
834280304Sjkim                return 0;
835280304Sjkim            if (!ipv4_from_asc(s->tmp + s->total, elem))
836280304Sjkim                return 0;
837280304Sjkim            s->total += 4;
838280304Sjkim        } else {
839280304Sjkim            if (!ipv6_hex(s->tmp + s->total, elem, len))
840280304Sjkim                return 0;
841280304Sjkim            s->total += 2;
842280304Sjkim        }
843280304Sjkim    }
844280304Sjkim    return 1;
845280304Sjkim}
846160814Ssimon
847280304Sjkim/*
848280304Sjkim * Convert a string of up to 4 hex digits into the corresponding IPv6 form.
849160814Ssimon */
850160814Ssimon
851160814Ssimonstatic int ipv6_hex(unsigned char *out, const char *in, int inlen)
852280304Sjkim{
853280304Sjkim    unsigned char c;
854280304Sjkim    unsigned int num = 0;
855280304Sjkim    if (inlen > 4)
856280304Sjkim        return 0;
857280304Sjkim    while (inlen--) {
858280304Sjkim        c = *in++;
859280304Sjkim        num <<= 4;
860280304Sjkim        if ((c >= '0') && (c <= '9'))
861280304Sjkim            num |= c - '0';
862280304Sjkim        else if ((c >= 'A') && (c <= 'F'))
863280304Sjkim            num |= c - 'A' + 10;
864280304Sjkim        else if ((c >= 'a') && (c <= 'f'))
865280304Sjkim            num |= c - 'a' + 10;
866280304Sjkim        else
867280304Sjkim            return 0;
868280304Sjkim    }
869280304Sjkim    out[0] = num >> 8;
870280304Sjkim    out[1] = num & 0xff;
871280304Sjkim    return 1;
872280304Sjkim}
873160814Ssimon
874280304Sjkimint X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
875280304Sjkim                             unsigned long chtype)
876280304Sjkim{
877280304Sjkim    CONF_VALUE *v;
878280304Sjkim    int i, mval;
879280304Sjkim    char *p, *type;
880280304Sjkim    if (!nm)
881280304Sjkim        return 0;
882160814Ssimon
883280304Sjkim    for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
884280304Sjkim        v = sk_CONF_VALUE_value(dn_sk, i);
885280304Sjkim        type = v->name;
886280304Sjkim        /*
887280304Sjkim         * Skip past any leading X. X: X, etc to allow for multiple instances
888280304Sjkim         */
889280304Sjkim        for (p = type; *p; p++)
890160814Ssimon#ifndef CHARSET_EBCDIC
891280304Sjkim            if ((*p == ':') || (*p == ',') || (*p == '.'))
892160814Ssimon#else
893280304Sjkim            if ((*p == os_toascii[':']) || (*p == os_toascii[','])
894280304Sjkim                || (*p == os_toascii['.']))
895160814Ssimon#endif
896280304Sjkim            {
897280304Sjkim                p++;
898280304Sjkim                if (*p)
899280304Sjkim                    type = p;
900280304Sjkim                break;
901280304Sjkim            }
902160814Ssimon#ifndef CHARSET_EBCDIC
903280304Sjkim        if (*type == '+')
904160814Ssimon#else
905280304Sjkim        if (*type == os_toascii['+'])
906160814Ssimon#endif
907280304Sjkim        {
908280304Sjkim            mval = -1;
909280304Sjkim            type++;
910280304Sjkim        } else
911280304Sjkim            mval = 0;
912280304Sjkim        if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
913280304Sjkim                                        (unsigned char *)v->value, -1, -1,
914280304Sjkim                                        mval))
915280304Sjkim            return 0;
916160814Ssimon
917280304Sjkim    }
918280304Sjkim    return 1;
919280304Sjkim}
920