155714Skris/* v3_utl.c */
2296465Sdelphij/*
3296465Sdelphij * 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
14296465Sdelphij *    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);
69296465Sdelphijstatic int sk_strcmp(const char *const *a, const char *const *b);
70109998Smarkmstatic STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens);
7168651Skrisstatic void str_free(void *str);
72296465Sdelphijstatic int append_ia5(STACK ** sk, ASN1_IA5STRING *email);
7355714Skris
74160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in);
75160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in);
76160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr);
77160814Ssimonstatic int ipv6_hex(unsigned char *out, const char *in, int inlen);
78160814Ssimon
7955714Skris/* Add a CONF_VALUE name value pair to stack */
8055714Skris
8155714Skrisint X509V3_add_value(const char *name, const char *value,
82296465Sdelphij                     STACK_OF(CONF_VALUE) **extlist)
8355714Skris{
84296465Sdelphij    CONF_VALUE *vtmp = NULL;
85296465Sdelphij    char *tname = NULL, *tvalue = NULL;
86296465Sdelphij    if (name && !(tname = BUF_strdup(name)))
87296465Sdelphij        goto err;
88296465Sdelphij    if (value && !(tvalue = BUF_strdup(value)))
89296465Sdelphij        goto err;
90296465Sdelphij    if (!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE))))
91296465Sdelphij        goto err;
92296465Sdelphij    if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null()))
93296465Sdelphij        goto err;
94296465Sdelphij    vtmp->section = NULL;
95296465Sdelphij    vtmp->name = tname;
96296465Sdelphij    vtmp->value = tvalue;
97296465Sdelphij    if (!sk_CONF_VALUE_push(*extlist, vtmp))
98296465Sdelphij        goto err;
99296465Sdelphij    return 1;
100296465Sdelphij err:
101296465Sdelphij    X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE);
102296465Sdelphij    if (vtmp)
103296465Sdelphij        OPENSSL_free(vtmp);
104296465Sdelphij    if (tname)
105296465Sdelphij        OPENSSL_free(tname);
106296465Sdelphij    if (tvalue)
107296465Sdelphij        OPENSSL_free(tvalue);
108296465Sdelphij    return 0;
10955714Skris}
11055714Skris
11155714Skrisint X509V3_add_value_uchar(const char *name, const unsigned char *value,
112296465Sdelphij                           STACK_OF(CONF_VALUE) **extlist)
113296465Sdelphij{
114296465Sdelphij    return X509V3_add_value(name, (const char *)value, extlist);
115296465Sdelphij}
11655714Skris
11755714Skris/* Free function for STACK_OF(CONF_VALUE) */
11855714Skris
11955714Skrisvoid X509V3_conf_free(CONF_VALUE *conf)
12055714Skris{
121296465Sdelphij    if (!conf)
122296465Sdelphij        return;
123296465Sdelphij    if (conf->name)
124296465Sdelphij        OPENSSL_free(conf->name);
125296465Sdelphij    if (conf->value)
126296465Sdelphij        OPENSSL_free(conf->value);
127296465Sdelphij    if (conf->section)
128296465Sdelphij        OPENSSL_free(conf->section);
129296465Sdelphij    OPENSSL_free(conf);
13055714Skris}
13155714Skris
13255714Skrisint X509V3_add_value_bool(const char *name, int asn1_bool,
133296465Sdelphij                          STACK_OF(CONF_VALUE) **extlist)
13455714Skris{
135296465Sdelphij    if (asn1_bool)
136296465Sdelphij        return X509V3_add_value(name, "TRUE", extlist);
137296465Sdelphij    return X509V3_add_value(name, "FALSE", extlist);
13855714Skris}
13955714Skris
14055714Skrisint X509V3_add_value_bool_nf(char *name, int asn1_bool,
141296465Sdelphij                             STACK_OF(CONF_VALUE) **extlist)
14255714Skris{
143296465Sdelphij    if (asn1_bool)
144296465Sdelphij        return X509V3_add_value(name, "TRUE", extlist);
145296465Sdelphij    return 1;
14655714Skris}
14755714Skris
14855714Skrischar *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
14955714Skris{
150296465Sdelphij    BIGNUM *bntmp = NULL;
151296465Sdelphij    char *strtmp = NULL;
152296465Sdelphij    if (!a)
153296465Sdelphij        return NULL;
154296465Sdelphij    if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
155296465Sdelphij        !(strtmp = BN_bn2dec(bntmp)))
156296465Sdelphij        X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
157296465Sdelphij    BN_free(bntmp);
158296465Sdelphij    return strtmp;
15955714Skris}
16055714Skris
16155714Skrischar *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
16255714Skris{
163296465Sdelphij    BIGNUM *bntmp = NULL;
164296465Sdelphij    char *strtmp = NULL;
165296465Sdelphij    if (!a)
166296465Sdelphij        return NULL;
167296465Sdelphij    if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
168296465Sdelphij        !(strtmp = BN_bn2dec(bntmp)))
169296465Sdelphij        X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
170296465Sdelphij    BN_free(bntmp);
171296465Sdelphij    return strtmp;
17255714Skris}
17355714Skris
17455714SkrisASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
17555714Skris{
176296465Sdelphij    BIGNUM *bn = NULL;
177296465Sdelphij    ASN1_INTEGER *aint;
178296465Sdelphij    int isneg, ishex;
179296465Sdelphij    int ret;
180296465Sdelphij    if (!value) {
181296465Sdelphij        X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE);
182296465Sdelphij        return 0;
183296465Sdelphij    }
184296465Sdelphij    bn = BN_new();
185296465Sdelphij    if (value[0] == '-') {
186296465Sdelphij        value++;
187296465Sdelphij        isneg = 1;
188296465Sdelphij    } else
189296465Sdelphij        isneg = 0;
190109998Smarkm
191296465Sdelphij    if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
192296465Sdelphij        value += 2;
193296465Sdelphij        ishex = 1;
194296465Sdelphij    } else
195296465Sdelphij        ishex = 0;
196109998Smarkm
197296465Sdelphij    if (ishex)
198296465Sdelphij        ret = BN_hex2bn(&bn, value);
199296465Sdelphij    else
200296465Sdelphij        ret = BN_dec2bn(&bn, value);
201109998Smarkm
202296465Sdelphij    if (!ret || value[ret]) {
203296465Sdelphij        BN_free(bn);
204296465Sdelphij        X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR);
205296465Sdelphij        return 0;
206296465Sdelphij    }
20755714Skris
208296465Sdelphij    if (isneg && BN_is_zero(bn))
209296465Sdelphij        isneg = 0;
210109998Smarkm
211296465Sdelphij    aint = BN_to_ASN1_INTEGER(bn, NULL);
212296465Sdelphij    BN_free(bn);
213296465Sdelphij    if (!aint) {
214296465Sdelphij        X509V3err(X509V3_F_S2I_ASN1_INTEGER,
215296465Sdelphij                  X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
216296465Sdelphij        return 0;
217296465Sdelphij    }
218296465Sdelphij    if (isneg)
219296465Sdelphij        aint->type |= V_ASN1_NEG;
220296465Sdelphij    return aint;
22155714Skris}
22255714Skris
22355714Skrisint X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
224296465Sdelphij                         STACK_OF(CONF_VALUE) **extlist)
22555714Skris{
226296465Sdelphij    char *strtmp;
227296465Sdelphij    int ret;
228296465Sdelphij    if (!aint)
229296465Sdelphij        return 1;
230296465Sdelphij    if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
231296465Sdelphij        return 0;
232296465Sdelphij    ret = X509V3_add_value(name, strtmp, extlist);
233296465Sdelphij    OPENSSL_free(strtmp);
234296465Sdelphij    return ret;
23555714Skris}
23655714Skris
23755714Skrisint X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
23855714Skris{
239296465Sdelphij    char *btmp;
240296465Sdelphij    if (!(btmp = value->value))
241296465Sdelphij        goto err;
242296465Sdelphij    if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
243296465Sdelphij        || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
244296465Sdelphij        || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
245296465Sdelphij        *asn1_bool = 0xff;
246296465Sdelphij        return 1;
247296465Sdelphij    } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
248296465Sdelphij               || !strcmp(btmp, "N") || !strcmp(btmp, "n")
249296465Sdelphij               || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
250296465Sdelphij        *asn1_bool = 0;
251296465Sdelphij        return 1;
252296465Sdelphij    }
253296465Sdelphij err:
254296465Sdelphij    X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,
255296465Sdelphij              X509V3_R_INVALID_BOOLEAN_STRING);
256296465Sdelphij    X509V3_conf_err(value);
257296465Sdelphij    return 0;
25855714Skris}
25955714Skris
26055714Skrisint X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
26155714Skris{
262296465Sdelphij    ASN1_INTEGER *itmp;
263296465Sdelphij    if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
264296465Sdelphij        X509V3_conf_err(value);
265296465Sdelphij        return 0;
266296465Sdelphij    }
267296465Sdelphij    *aint = itmp;
268296465Sdelphij    return 1;
26955714Skris}
27055714Skris
271296465Sdelphij#define HDR_NAME        1
272296465Sdelphij#define HDR_VALUE       2
27355714Skris
274296465Sdelphij/*
275296465Sdelphij * #define DEBUG
276296465Sdelphij */
27755714Skris
278109998SmarkmSTACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
27955714Skris{
280296465Sdelphij    char *p, *q, c;
281296465Sdelphij    char *ntmp, *vtmp;
282296465Sdelphij    STACK_OF(CONF_VALUE) *values = NULL;
283296465Sdelphij    char *linebuf;
284296465Sdelphij    int state;
285296465Sdelphij    /* We are going to modify the line so copy it first */
286296465Sdelphij    linebuf = BUF_strdup(line);
287296465Sdelphij    state = HDR_NAME;
288296465Sdelphij    ntmp = NULL;
289296465Sdelphij    /* Go through all characters */
290296465Sdelphij    for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
291296465Sdelphij         p++) {
29255714Skris
293296465Sdelphij        switch (state) {
294296465Sdelphij        case HDR_NAME:
295296465Sdelphij            if (c == ':') {
296296465Sdelphij                state = HDR_VALUE;
297296465Sdelphij                *p = 0;
298296465Sdelphij                ntmp = strip_spaces(q);
299296465Sdelphij                if (!ntmp) {
300296465Sdelphij                    X509V3err(X509V3_F_X509V3_PARSE_LIST,
301296465Sdelphij                              X509V3_R_INVALID_NULL_NAME);
302296465Sdelphij                    goto err;
303296465Sdelphij                }
304296465Sdelphij                q = p + 1;
305296465Sdelphij            } else if (c == ',') {
306296465Sdelphij                *p = 0;
307296465Sdelphij                ntmp = strip_spaces(q);
308296465Sdelphij                q = p + 1;
309100928Snectar#if 0
310296465Sdelphij                printf("%s\n", ntmp);
31155714Skris#endif
312296465Sdelphij                if (!ntmp) {
313296465Sdelphij                    X509V3err(X509V3_F_X509V3_PARSE_LIST,
314296465Sdelphij                              X509V3_R_INVALID_NULL_NAME);
315296465Sdelphij                    goto err;
316296465Sdelphij                }
317296465Sdelphij                X509V3_add_value(ntmp, NULL, &values);
318296465Sdelphij            }
319296465Sdelphij            break;
32055714Skris
321296465Sdelphij        case HDR_VALUE:
322296465Sdelphij            if (c == ',') {
323296465Sdelphij                state = HDR_NAME;
324296465Sdelphij                *p = 0;
325296465Sdelphij                vtmp = strip_spaces(q);
326100928Snectar#if 0
327296465Sdelphij                printf("%s\n", ntmp);
32855714Skris#endif
329296465Sdelphij                if (!vtmp) {
330296465Sdelphij                    X509V3err(X509V3_F_X509V3_PARSE_LIST,
331296465Sdelphij                              X509V3_R_INVALID_NULL_VALUE);
332296465Sdelphij                    goto err;
333296465Sdelphij                }
334296465Sdelphij                X509V3_add_value(ntmp, vtmp, &values);
335296465Sdelphij                ntmp = NULL;
336296465Sdelphij                q = p + 1;
337296465Sdelphij            }
33855714Skris
339296465Sdelphij        }
340296465Sdelphij    }
34155714Skris
342296465Sdelphij    if (state == HDR_VALUE) {
343296465Sdelphij        vtmp = strip_spaces(q);
344100928Snectar#if 0
345296465Sdelphij        printf("%s=%s\n", ntmp, vtmp);
34655714Skris#endif
347296465Sdelphij        if (!vtmp) {
348296465Sdelphij            X509V3err(X509V3_F_X509V3_PARSE_LIST,
349296465Sdelphij                      X509V3_R_INVALID_NULL_VALUE);
350296465Sdelphij            goto err;
351296465Sdelphij        }
352296465Sdelphij        X509V3_add_value(ntmp, vtmp, &values);
353296465Sdelphij    } else {
354296465Sdelphij        ntmp = strip_spaces(q);
355100928Snectar#if 0
356296465Sdelphij        printf("%s\n", ntmp);
35755714Skris#endif
358296465Sdelphij        if (!ntmp) {
359296465Sdelphij            X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
360296465Sdelphij            goto err;
361296465Sdelphij        }
362296465Sdelphij        X509V3_add_value(ntmp, NULL, &values);
363296465Sdelphij    }
364296465Sdelphij    OPENSSL_free(linebuf);
365296465Sdelphij    return values;
36655714Skris
367296465Sdelphij err:
368296465Sdelphij    OPENSSL_free(linebuf);
369296465Sdelphij    sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
370296465Sdelphij    return NULL;
37155714Skris
37255714Skris}
37355714Skris
37455714Skris/* Delete leading and trailing spaces from a string */
37555714Skrisstatic char *strip_spaces(char *name)
37655714Skris{
377296465Sdelphij    char *p, *q;
378296465Sdelphij    /* Skip over leading spaces */
379296465Sdelphij    p = name;
380296465Sdelphij    while (*p && isspace((unsigned char)*p))
381296465Sdelphij        p++;
382296465Sdelphij    if (!*p)
383296465Sdelphij        return NULL;
384296465Sdelphij    q = p + strlen(p) - 1;
385296465Sdelphij    while ((q != p) && isspace((unsigned char)*q))
386296465Sdelphij        q--;
387296465Sdelphij    if (p != q)
388296465Sdelphij        q[1] = 0;
389296465Sdelphij    if (!*p)
390296465Sdelphij        return NULL;
391296465Sdelphij    return p;
39255714Skris}
39355714Skris
39455714Skris/* hex string utilities */
39555714Skris
396296465Sdelphij/*
397296465Sdelphij * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
398296465Sdelphij * hex representation @@@ (Contents of buffer are always kept in ASCII, also
399296465Sdelphij * on EBCDIC machines)
40055714Skris */
40155714Skris
40255714Skrischar *hex_to_string(unsigned char *buffer, long len)
40355714Skris{
404296465Sdelphij    char *tmp, *q;
405296465Sdelphij    unsigned char *p;
406296465Sdelphij    int i;
407296465Sdelphij    const static char hexdig[] = "0123456789ABCDEF";
408296465Sdelphij    if (!buffer || !len)
409296465Sdelphij        return NULL;
410296465Sdelphij    if (!(tmp = OPENSSL_malloc(len * 3 + 1))) {
411296465Sdelphij        X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE);
412296465Sdelphij        return NULL;
413296465Sdelphij    }
414296465Sdelphij    q = tmp;
415296465Sdelphij    for (i = 0, p = buffer; i < len; i++, p++) {
416296465Sdelphij        *q++ = hexdig[(*p >> 4) & 0xf];
417296465Sdelphij        *q++ = hexdig[*p & 0xf];
418296465Sdelphij        *q++ = ':';
419296465Sdelphij    }
420296465Sdelphij    q[-1] = 0;
42168651Skris#ifdef CHARSET_EBCDIC
422296465Sdelphij    ebcdic2ascii(tmp, tmp, q - tmp - 1);
42368651Skris#endif
42468651Skris
425296465Sdelphij    return tmp;
42655714Skris}
42755714Skris
428296465Sdelphij/*
429296465Sdelphij * Give a string of hex digits convert to a buffer
43055714Skris */
43155714Skris
43255714Skrisunsigned char *string_to_hex(char *str, long *len)
43355714Skris{
434296465Sdelphij    unsigned char *hexbuf, *q;
435296465Sdelphij    unsigned char ch, cl, *p;
436296465Sdelphij    if (!str) {
437296465Sdelphij        X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_INVALID_NULL_ARGUMENT);
438296465Sdelphij        return NULL;
439296465Sdelphij    }
440296465Sdelphij    if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1)))
441296465Sdelphij        goto err;
442296465Sdelphij    for (p = (unsigned char *)str, q = hexbuf; *p;) {
443296465Sdelphij        ch = *p++;
44468651Skris#ifdef CHARSET_EBCDIC
445296465Sdelphij        ch = os_toebcdic[ch];
44668651Skris#endif
447296465Sdelphij        if (ch == ':')
448296465Sdelphij            continue;
449296465Sdelphij        cl = *p++;
45068651Skris#ifdef CHARSET_EBCDIC
451296465Sdelphij        cl = os_toebcdic[cl];
45268651Skris#endif
453296465Sdelphij        if (!cl) {
454296465Sdelphij            X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ODD_NUMBER_OF_DIGITS);
455296465Sdelphij            OPENSSL_free(hexbuf);
456296465Sdelphij            return NULL;
457296465Sdelphij        }
458296465Sdelphij        if (isupper(ch))
459296465Sdelphij            ch = tolower(ch);
460296465Sdelphij        if (isupper(cl))
461296465Sdelphij            cl = tolower(cl);
46255714Skris
463296465Sdelphij        if ((ch >= '0') && (ch <= '9'))
464296465Sdelphij            ch -= '0';
465296465Sdelphij        else if ((ch >= 'a') && (ch <= 'f'))
466296465Sdelphij            ch -= 'a' - 10;
467296465Sdelphij        else
468296465Sdelphij            goto badhex;
46955714Skris
470296465Sdelphij        if ((cl >= '0') && (cl <= '9'))
471296465Sdelphij            cl -= '0';
472296465Sdelphij        else if ((cl >= 'a') && (cl <= 'f'))
473296465Sdelphij            cl -= 'a' - 10;
474296465Sdelphij        else
475296465Sdelphij            goto badhex;
47655714Skris
477296465Sdelphij        *q++ = (ch << 4) | cl;
478296465Sdelphij    }
47955714Skris
480296465Sdelphij    if (len)
481296465Sdelphij        *len = q - hexbuf;
48255714Skris
483296465Sdelphij    return hexbuf;
48455714Skris
485296465Sdelphij err:
486296465Sdelphij    if (hexbuf)
487296465Sdelphij        OPENSSL_free(hexbuf);
488296465Sdelphij    X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE);
489296465Sdelphij    return NULL;
49055714Skris
491296465Sdelphij badhex:
492296465Sdelphij    OPENSSL_free(hexbuf);
493296465Sdelphij    X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT);
494296465Sdelphij    return NULL;
49555714Skris
49655714Skris}
49755714Skris
498296465Sdelphij/*
499296465Sdelphij * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
50055714Skris */
50155714Skris
50255714Skrisint name_cmp(const char *name, const char *cmp)
50355714Skris{
504296465Sdelphij    int len, ret;
505296465Sdelphij    char c;
506296465Sdelphij    len = strlen(cmp);
507296465Sdelphij    if ((ret = strncmp(name, cmp, len)))
508296465Sdelphij        return ret;
509296465Sdelphij    c = name[len];
510296465Sdelphij    if (!c || (c == '.'))
511296465Sdelphij        return 0;
512296465Sdelphij    return 1;
51355714Skris}
51468651Skris
515296465Sdelphijstatic int sk_strcmp(const char *const *a, const char *const *b)
51668651Skris{
517296465Sdelphij    return strcmp(*a, *b);
51868651Skris}
51968651Skris
52068651SkrisSTACK *X509_get1_email(X509 *x)
52168651Skris{
522296465Sdelphij    GENERAL_NAMES *gens;
523296465Sdelphij    STACK *ret;
524296465Sdelphij    gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
525296465Sdelphij    ret = get_email(X509_get_subject_name(x), gens);
526296465Sdelphij    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
527296465Sdelphij    return ret;
52868651Skris}
52968651Skris
530194206SsimonSTACK *X509_get1_ocsp(X509 *x)
531194206Ssimon{
532296465Sdelphij    AUTHORITY_INFO_ACCESS *info;
533296465Sdelphij    STACK *ret = NULL;
534296465Sdelphij    int i;
535296465Sdelphij    info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
536296465Sdelphij    if (!info)
537296465Sdelphij        return NULL;
538296465Sdelphij    for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
539296465Sdelphij        ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
540296465Sdelphij        if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
541296465Sdelphij            if (ad->location->type == GEN_URI) {
542296465Sdelphij                if (!append_ia5
543296465Sdelphij                    (&ret, ad->location->d.uniformResourceIdentifier))
544296465Sdelphij                    break;
545296465Sdelphij            }
546296465Sdelphij        }
547296465Sdelphij    }
548296465Sdelphij    AUTHORITY_INFO_ACCESS_free(info);
549296465Sdelphij    return ret;
550194206Ssimon}
551194206Ssimon
55268651SkrisSTACK *X509_REQ_get1_email(X509_REQ *x)
55368651Skris{
554296465Sdelphij    GENERAL_NAMES *gens;
555296465Sdelphij    STACK_OF(X509_EXTENSION) *exts;
556296465Sdelphij    STACK *ret;
557296465Sdelphij    exts = X509_REQ_get_extensions(x);
558296465Sdelphij    gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
559296465Sdelphij    ret = get_email(X509_REQ_get_subject_name(x), gens);
560296465Sdelphij    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
561296465Sdelphij    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
562296465Sdelphij    return ret;
56368651Skris}
56468651Skris
565109998Smarkmstatic STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens)
56668651Skris{
567296465Sdelphij    STACK *ret = NULL;
568296465Sdelphij    X509_NAME_ENTRY *ne;
569296465Sdelphij    ASN1_IA5STRING *email;
570296465Sdelphij    GENERAL_NAME *gen;
571296465Sdelphij    int i;
572296465Sdelphij    /* Now add any email address(es) to STACK */
573296465Sdelphij    i = -1;
574296465Sdelphij    /* First supplied X509_NAME */
575296465Sdelphij    while ((i = X509_NAME_get_index_by_NID(name,
576296465Sdelphij                                           NID_pkcs9_emailAddress, i)) >= 0) {
577296465Sdelphij        ne = X509_NAME_get_entry(name, i);
578296465Sdelphij        email = X509_NAME_ENTRY_get_data(ne);
579296465Sdelphij        if (!append_ia5(&ret, email))
580296465Sdelphij            return NULL;
581296465Sdelphij    }
582296465Sdelphij    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
583296465Sdelphij        gen = sk_GENERAL_NAME_value(gens, i);
584296465Sdelphij        if (gen->type != GEN_EMAIL)
585296465Sdelphij            continue;
586296465Sdelphij        if (!append_ia5(&ret, gen->d.ia5))
587296465Sdelphij            return NULL;
588296465Sdelphij    }
589296465Sdelphij    return ret;
59068651Skris}
59168651Skris
59268651Skrisstatic void str_free(void *str)
59368651Skris{
594296465Sdelphij    OPENSSL_free(str);
59568651Skris}
59668651Skris
597296465Sdelphijstatic int append_ia5(STACK ** sk, ASN1_IA5STRING *email)
59868651Skris{
599296465Sdelphij    char *emtmp;
600296465Sdelphij    /* First some sanity checks */
601296465Sdelphij    if (email->type != V_ASN1_IA5STRING)
602296465Sdelphij        return 1;
603296465Sdelphij    if (!email->data || !email->length)
604296465Sdelphij        return 1;
605296465Sdelphij    if (!*sk)
606296465Sdelphij        *sk = sk_new(sk_strcmp);
607296465Sdelphij    if (!*sk)
608296465Sdelphij        return 0;
609296465Sdelphij    /* Don't add duplicates */
610296465Sdelphij    if (sk_find(*sk, (char *)email->data) != -1)
611296465Sdelphij        return 1;
612296465Sdelphij    emtmp = BUF_strdup((char *)email->data);
613296465Sdelphij    if (!emtmp || !sk_push(*sk, emtmp)) {
614296465Sdelphij        X509_email_free(*sk);
615296465Sdelphij        *sk = NULL;
616296465Sdelphij        return 0;
617296465Sdelphij    }
618296465Sdelphij    return 1;
61968651Skris}
62068651Skris
621296465Sdelphijvoid X509_email_free(STACK * sk)
62268651Skris{
623296465Sdelphij    sk_pop_free(sk, str_free);
62468651Skris}
625160814Ssimon
626296465Sdelphij/*
627296465Sdelphij * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
628296465Sdelphij * with RFC3280.
629160814Ssimon */
630160814Ssimon
631160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
632296465Sdelphij{
633296465Sdelphij    unsigned char ipout[16];
634296465Sdelphij    ASN1_OCTET_STRING *ret;
635296465Sdelphij    int iplen;
636160814Ssimon
637296465Sdelphij    /* If string contains a ':' assume IPv6 */
638160814Ssimon
639296465Sdelphij    iplen = a2i_ipadd(ipout, ipasc);
640160814Ssimon
641296465Sdelphij    if (!iplen)
642296465Sdelphij        return NULL;
643160814Ssimon
644296465Sdelphij    ret = ASN1_OCTET_STRING_new();
645296465Sdelphij    if (!ret)
646296465Sdelphij        return NULL;
647296465Sdelphij    if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
648296465Sdelphij        ASN1_OCTET_STRING_free(ret);
649296465Sdelphij        return NULL;
650296465Sdelphij    }
651296465Sdelphij    return ret;
652296465Sdelphij}
653160814Ssimon
654160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
655296465Sdelphij{
656296465Sdelphij    ASN1_OCTET_STRING *ret = NULL;
657296465Sdelphij    unsigned char ipout[32];
658296465Sdelphij    char *iptmp = NULL, *p;
659296465Sdelphij    int iplen1, iplen2;
660296465Sdelphij    p = strchr(ipasc, '/');
661296465Sdelphij    if (!p)
662296465Sdelphij        return NULL;
663296465Sdelphij    iptmp = BUF_strdup(ipasc);
664296465Sdelphij    if (!iptmp)
665296465Sdelphij        return NULL;
666296465Sdelphij    p = iptmp + (p - ipasc);
667296465Sdelphij    *p++ = 0;
668160814Ssimon
669296465Sdelphij    iplen1 = a2i_ipadd(ipout, iptmp);
670160814Ssimon
671296465Sdelphij    if (!iplen1)
672296465Sdelphij        goto err;
673160814Ssimon
674296465Sdelphij    iplen2 = a2i_ipadd(ipout + iplen1, p);
675160814Ssimon
676296465Sdelphij    OPENSSL_free(iptmp);
677296465Sdelphij    iptmp = NULL;
678160814Ssimon
679296465Sdelphij    if (!iplen2 || (iplen1 != iplen2))
680296465Sdelphij        goto err;
681160814Ssimon
682296465Sdelphij    ret = ASN1_OCTET_STRING_new();
683296465Sdelphij    if (!ret)
684296465Sdelphij        goto err;
685296465Sdelphij    if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
686296465Sdelphij        goto err;
687160814Ssimon
688296465Sdelphij    return ret;
689160814Ssimon
690296465Sdelphij err:
691296465Sdelphij    if (iptmp)
692296465Sdelphij        OPENSSL_free(iptmp);
693296465Sdelphij    if (ret)
694296465Sdelphij        ASN1_OCTET_STRING_free(ret);
695296465Sdelphij    return NULL;
696296465Sdelphij}
697160814Ssimon
698167612Ssimonint a2i_ipadd(unsigned char *ipout, const char *ipasc)
699296465Sdelphij{
700296465Sdelphij    /* If string contains a ':' assume IPv6 */
701160814Ssimon
702296465Sdelphij    if (strchr(ipasc, ':')) {
703296465Sdelphij        if (!ipv6_from_asc(ipout, ipasc))
704296465Sdelphij            return 0;
705296465Sdelphij        return 16;
706296465Sdelphij    } else {
707296465Sdelphij        if (!ipv4_from_asc(ipout, ipasc))
708296465Sdelphij            return 0;
709296465Sdelphij        return 4;
710296465Sdelphij    }
711296465Sdelphij}
712160814Ssimon
713160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in)
714296465Sdelphij{
715296465Sdelphij    int a0, a1, a2, a3;
716296465Sdelphij    if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
717296465Sdelphij        return 0;
718296465Sdelphij    if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
719296465Sdelphij        || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
720296465Sdelphij        return 0;
721296465Sdelphij    v4[0] = a0;
722296465Sdelphij    v4[1] = a1;
723296465Sdelphij    v4[2] = a2;
724296465Sdelphij    v4[3] = a3;
725296465Sdelphij    return 1;
726296465Sdelphij}
727160814Ssimon
728160814Ssimontypedef struct {
729296465Sdelphij    /* Temporary store for IPV6 output */
730296465Sdelphij    unsigned char tmp[16];
731296465Sdelphij    /* Total number of bytes in tmp */
732296465Sdelphij    int total;
733296465Sdelphij    /* The position of a zero (corresponding to '::') */
734296465Sdelphij    int zero_pos;
735296465Sdelphij    /* Number of zeroes */
736296465Sdelphij    int zero_cnt;
737296465Sdelphij} IPV6_STAT;
738160814Ssimon
739160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in)
740296465Sdelphij{
741296465Sdelphij    IPV6_STAT v6stat;
742296465Sdelphij    v6stat.total = 0;
743296465Sdelphij    v6stat.zero_pos = -1;
744296465Sdelphij    v6stat.zero_cnt = 0;
745296465Sdelphij    /*
746296465Sdelphij     * Treat the IPv6 representation as a list of values separated by ':'.
747296465Sdelphij     * The presence of a '::' will parse as one, two or three zero length
748296465Sdelphij     * elements.
749296465Sdelphij     */
750296465Sdelphij    if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
751296465Sdelphij        return 0;
752160814Ssimon
753296465Sdelphij    /* Now for some sanity checks */
754160814Ssimon
755296465Sdelphij    if (v6stat.zero_pos == -1) {
756296465Sdelphij        /* If no '::' must have exactly 16 bytes */
757296465Sdelphij        if (v6stat.total != 16)
758296465Sdelphij            return 0;
759296465Sdelphij    } else {
760296465Sdelphij        /* If '::' must have less than 16 bytes */
761296465Sdelphij        if (v6stat.total == 16)
762296465Sdelphij            return 0;
763296465Sdelphij        /* More than three zeroes is an error */
764296465Sdelphij        if (v6stat.zero_cnt > 3)
765296465Sdelphij            return 0;
766296465Sdelphij        /* Can only have three zeroes if nothing else present */
767296465Sdelphij        else if (v6stat.zero_cnt == 3) {
768296465Sdelphij            if (v6stat.total > 0)
769296465Sdelphij                return 0;
770296465Sdelphij        }
771296465Sdelphij        /* Can only have two zeroes if at start or end */
772296465Sdelphij        else if (v6stat.zero_cnt == 2) {
773296465Sdelphij            if ((v6stat.zero_pos != 0)
774296465Sdelphij                && (v6stat.zero_pos != v6stat.total))
775296465Sdelphij                return 0;
776296465Sdelphij        } else
777296465Sdelphij            /* Can only have one zero if *not* start or end */
778296465Sdelphij        {
779296465Sdelphij            if ((v6stat.zero_pos == 0)
780296465Sdelphij                || (v6stat.zero_pos == v6stat.total))
781296465Sdelphij                return 0;
782296465Sdelphij        }
783296465Sdelphij    }
784160814Ssimon
785296465Sdelphij    /* Format result */
786160814Ssimon
787296465Sdelphij    if (v6stat.zero_pos >= 0) {
788296465Sdelphij        /* Copy initial part */
789296465Sdelphij        memcpy(v6, v6stat.tmp, v6stat.zero_pos);
790296465Sdelphij        /* Zero middle */
791296465Sdelphij        memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
792296465Sdelphij        /* Copy final part */
793296465Sdelphij        if (v6stat.total != v6stat.zero_pos)
794296465Sdelphij            memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
795296465Sdelphij                   v6stat.tmp + v6stat.zero_pos,
796296465Sdelphij                   v6stat.total - v6stat.zero_pos);
797296465Sdelphij    } else
798296465Sdelphij        memcpy(v6, v6stat.tmp, 16);
799160814Ssimon
800296465Sdelphij    return 1;
801296465Sdelphij}
802160814Ssimon
803160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr)
804296465Sdelphij{
805296465Sdelphij    IPV6_STAT *s = usr;
806296465Sdelphij    /* Error if 16 bytes written */
807296465Sdelphij    if (s->total == 16)
808296465Sdelphij        return 0;
809296465Sdelphij    if (len == 0) {
810296465Sdelphij        /* Zero length element, corresponds to '::' */
811296465Sdelphij        if (s->zero_pos == -1)
812296465Sdelphij            s->zero_pos = s->total;
813296465Sdelphij        /* If we've already got a :: its an error */
814296465Sdelphij        else if (s->zero_pos != s->total)
815296465Sdelphij            return 0;
816296465Sdelphij        s->zero_cnt++;
817296465Sdelphij    } else {
818296465Sdelphij        /* If more than 4 characters could be final a.b.c.d form */
819296465Sdelphij        if (len > 4) {
820296465Sdelphij            /* Need at least 4 bytes left */
821296465Sdelphij            if (s->total > 12)
822296465Sdelphij                return 0;
823296465Sdelphij            /* Must be end of string */
824296465Sdelphij            if (elem[len])
825296465Sdelphij                return 0;
826296465Sdelphij            if (!ipv4_from_asc(s->tmp + s->total, elem))
827296465Sdelphij                return 0;
828296465Sdelphij            s->total += 4;
829296465Sdelphij        } else {
830296465Sdelphij            if (!ipv6_hex(s->tmp + s->total, elem, len))
831296465Sdelphij                return 0;
832296465Sdelphij            s->total += 2;
833296465Sdelphij        }
834296465Sdelphij    }
835296465Sdelphij    return 1;
836296465Sdelphij}
837160814Ssimon
838296465Sdelphij/*
839296465Sdelphij * Convert a string of up to 4 hex digits into the corresponding IPv6 form.
840160814Ssimon */
841160814Ssimon
842160814Ssimonstatic int ipv6_hex(unsigned char *out, const char *in, int inlen)
843296465Sdelphij{
844296465Sdelphij    unsigned char c;
845296465Sdelphij    unsigned int num = 0;
846296465Sdelphij    if (inlen > 4)
847296465Sdelphij        return 0;
848296465Sdelphij    while (inlen--) {
849296465Sdelphij        c = *in++;
850296465Sdelphij        num <<= 4;
851296465Sdelphij        if ((c >= '0') && (c <= '9'))
852296465Sdelphij            num |= c - '0';
853296465Sdelphij        else if ((c >= 'A') && (c <= 'F'))
854296465Sdelphij            num |= c - 'A' + 10;
855296465Sdelphij        else if ((c >= 'a') && (c <= 'f'))
856296465Sdelphij            num |= c - 'a' + 10;
857296465Sdelphij        else
858296465Sdelphij            return 0;
859296465Sdelphij    }
860296465Sdelphij    out[0] = num >> 8;
861296465Sdelphij    out[1] = num & 0xff;
862296465Sdelphij    return 1;
863296465Sdelphij}
864160814Ssimon
865296465Sdelphijint X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
866296465Sdelphij                             unsigned long chtype)
867296465Sdelphij{
868296465Sdelphij    CONF_VALUE *v;
869296465Sdelphij    int i, mval;
870296465Sdelphij    char *p, *type;
871296465Sdelphij    if (!nm)
872296465Sdelphij        return 0;
873160814Ssimon
874296465Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
875296465Sdelphij        v = sk_CONF_VALUE_value(dn_sk, i);
876296465Sdelphij        type = v->name;
877296465Sdelphij        /*
878296465Sdelphij         * Skip past any leading X. X: X, etc to allow for multiple instances
879296465Sdelphij         */
880296465Sdelphij        for (p = type; *p; p++)
881160814Ssimon#ifndef CHARSET_EBCDIC
882296465Sdelphij            if ((*p == ':') || (*p == ',') || (*p == '.'))
883160814Ssimon#else
884296465Sdelphij            if ((*p == os_toascii[':']) || (*p == os_toascii[','])
885296465Sdelphij                || (*p == os_toascii['.']))
886160814Ssimon#endif
887296465Sdelphij            {
888296465Sdelphij                p++;
889296465Sdelphij                if (*p)
890296465Sdelphij                    type = p;
891296465Sdelphij                break;
892296465Sdelphij            }
893160814Ssimon#ifndef CHARSET_EBCDIC
894296465Sdelphij        if (*type == '+')
895160814Ssimon#else
896296465Sdelphij        if (*type == os_toascii['+'])
897160814Ssimon#endif
898296465Sdelphij        {
899296465Sdelphij            mval = -1;
900296465Sdelphij            type++;
901296465Sdelphij        } else
902296465Sdelphij            mval = 0;
903296465Sdelphij        if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
904296465Sdelphij                                        (unsigned char *)v->value, -1, -1,
905296465Sdelphij                                        mval))
906296465Sdelphij            return 0;
907160814Ssimon
908296465Sdelphij    }
909296465Sdelphij    return 1;
910296465Sdelphij}
911