155714Skris/* v3_utl.c */
2296341Sdelphij/*
3296341Sdelphij * 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
14296341Sdelphij *    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);
69296341Sdelphijstatic int sk_strcmp(const char *const *a, const char *const *b);
70296341Sdelphijstatic STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
71296341Sdelphij                                           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,
83296341Sdelphij                     STACK_OF(CONF_VALUE) **extlist)
8455714Skris{
85296341Sdelphij    CONF_VALUE *vtmp = NULL;
86296341Sdelphij    char *tname = NULL, *tvalue = NULL;
87296341Sdelphij    if (name && !(tname = BUF_strdup(name)))
88296341Sdelphij        goto err;
89296341Sdelphij    if (value && !(tvalue = BUF_strdup(value)))
90296341Sdelphij        goto err;
91296341Sdelphij    if (!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE))))
92296341Sdelphij        goto err;
93296341Sdelphij    if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null()))
94296341Sdelphij        goto err;
95296341Sdelphij    vtmp->section = NULL;
96296341Sdelphij    vtmp->name = tname;
97296341Sdelphij    vtmp->value = tvalue;
98296341Sdelphij    if (!sk_CONF_VALUE_push(*extlist, vtmp))
99296341Sdelphij        goto err;
100296341Sdelphij    return 1;
101296341Sdelphij err:
102296341Sdelphij    X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE);
103296341Sdelphij    if (vtmp)
104296341Sdelphij        OPENSSL_free(vtmp);
105296341Sdelphij    if (tname)
106296341Sdelphij        OPENSSL_free(tname);
107296341Sdelphij    if (tvalue)
108296341Sdelphij        OPENSSL_free(tvalue);
109296341Sdelphij    return 0;
11055714Skris}
11155714Skris
11255714Skrisint X509V3_add_value_uchar(const char *name, const unsigned char *value,
113296341Sdelphij                           STACK_OF(CONF_VALUE) **extlist)
114296341Sdelphij{
115296341Sdelphij    return X509V3_add_value(name, (const char *)value, extlist);
116296341Sdelphij}
11755714Skris
11855714Skris/* Free function for STACK_OF(CONF_VALUE) */
11955714Skris
12055714Skrisvoid X509V3_conf_free(CONF_VALUE *conf)
12155714Skris{
122296341Sdelphij    if (!conf)
123296341Sdelphij        return;
124296341Sdelphij    if (conf->name)
125296341Sdelphij        OPENSSL_free(conf->name);
126296341Sdelphij    if (conf->value)
127296341Sdelphij        OPENSSL_free(conf->value);
128296341Sdelphij    if (conf->section)
129296341Sdelphij        OPENSSL_free(conf->section);
130296341Sdelphij    OPENSSL_free(conf);
13155714Skris}
13255714Skris
13355714Skrisint X509V3_add_value_bool(const char *name, int asn1_bool,
134296341Sdelphij                          STACK_OF(CONF_VALUE) **extlist)
13555714Skris{
136296341Sdelphij    if (asn1_bool)
137296341Sdelphij        return X509V3_add_value(name, "TRUE", extlist);
138296341Sdelphij    return X509V3_add_value(name, "FALSE", extlist);
13955714Skris}
14055714Skris
14155714Skrisint X509V3_add_value_bool_nf(char *name, int asn1_bool,
142296341Sdelphij                             STACK_OF(CONF_VALUE) **extlist)
14355714Skris{
144296341Sdelphij    if (asn1_bool)
145296341Sdelphij        return X509V3_add_value(name, "TRUE", extlist);
146296341Sdelphij    return 1;
14755714Skris}
14855714Skris
14955714Skrischar *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
15055714Skris{
151296341Sdelphij    BIGNUM *bntmp = NULL;
152296341Sdelphij    char *strtmp = NULL;
153296341Sdelphij    if (!a)
154296341Sdelphij        return NULL;
155296341Sdelphij    if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
156296341Sdelphij        !(strtmp = BN_bn2dec(bntmp)))
157296341Sdelphij        X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
158296341Sdelphij    BN_free(bntmp);
159296341Sdelphij    return strtmp;
16055714Skris}
16155714Skris
16255714Skrischar *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
16355714Skris{
164296341Sdelphij    BIGNUM *bntmp = NULL;
165296341Sdelphij    char *strtmp = NULL;
166296341Sdelphij    if (!a)
167296341Sdelphij        return NULL;
168296341Sdelphij    if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
169296341Sdelphij        !(strtmp = BN_bn2dec(bntmp)))
170296341Sdelphij        X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
171296341Sdelphij    BN_free(bntmp);
172296341Sdelphij    return strtmp;
17355714Skris}
17455714Skris
17555714SkrisASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
17655714Skris{
177296341Sdelphij    BIGNUM *bn = NULL;
178296341Sdelphij    ASN1_INTEGER *aint;
179296341Sdelphij    int isneg, ishex;
180296341Sdelphij    int ret;
181296341Sdelphij    if (!value) {
182296341Sdelphij        X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE);
183296341Sdelphij        return 0;
184296341Sdelphij    }
185296341Sdelphij    bn = BN_new();
186296341Sdelphij    if (value[0] == '-') {
187296341Sdelphij        value++;
188296341Sdelphij        isneg = 1;
189296341Sdelphij    } else
190296341Sdelphij        isneg = 0;
191109998Smarkm
192296341Sdelphij    if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
193296341Sdelphij        value += 2;
194296341Sdelphij        ishex = 1;
195296341Sdelphij    } else
196296341Sdelphij        ishex = 0;
197109998Smarkm
198296341Sdelphij    if (ishex)
199296341Sdelphij        ret = BN_hex2bn(&bn, value);
200296341Sdelphij    else
201296341Sdelphij        ret = BN_dec2bn(&bn, value);
202109998Smarkm
203296341Sdelphij    if (!ret || value[ret]) {
204296341Sdelphij        BN_free(bn);
205296341Sdelphij        X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR);
206296341Sdelphij        return 0;
207296341Sdelphij    }
20855714Skris
209296341Sdelphij    if (isneg && BN_is_zero(bn))
210296341Sdelphij        isneg = 0;
211109998Smarkm
212296341Sdelphij    aint = BN_to_ASN1_INTEGER(bn, NULL);
213296341Sdelphij    BN_free(bn);
214296341Sdelphij    if (!aint) {
215296341Sdelphij        X509V3err(X509V3_F_S2I_ASN1_INTEGER,
216296341Sdelphij                  X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
217296341Sdelphij        return 0;
218296341Sdelphij    }
219296341Sdelphij    if (isneg)
220296341Sdelphij        aint->type |= V_ASN1_NEG;
221296341Sdelphij    return aint;
22255714Skris}
22355714Skris
22455714Skrisint X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
225296341Sdelphij                         STACK_OF(CONF_VALUE) **extlist)
22655714Skris{
227296341Sdelphij    char *strtmp;
228296341Sdelphij    int ret;
229296341Sdelphij    if (!aint)
230296341Sdelphij        return 1;
231296341Sdelphij    if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
232296341Sdelphij        return 0;
233296341Sdelphij    ret = X509V3_add_value(name, strtmp, extlist);
234296341Sdelphij    OPENSSL_free(strtmp);
235296341Sdelphij    return ret;
23655714Skris}
23755714Skris
23855714Skrisint X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
23955714Skris{
240296341Sdelphij    char *btmp;
241296341Sdelphij    if (!(btmp = value->value))
242296341Sdelphij        goto err;
243296341Sdelphij    if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
244296341Sdelphij        || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
245296341Sdelphij        || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
246296341Sdelphij        *asn1_bool = 0xff;
247296341Sdelphij        return 1;
248296341Sdelphij    } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
249296341Sdelphij               || !strcmp(btmp, "N") || !strcmp(btmp, "n")
250296341Sdelphij               || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
251296341Sdelphij        *asn1_bool = 0;
252296341Sdelphij        return 1;
253296341Sdelphij    }
254296341Sdelphij err:
255296341Sdelphij    X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,
256296341Sdelphij              X509V3_R_INVALID_BOOLEAN_STRING);
257296341Sdelphij    X509V3_conf_err(value);
258296341Sdelphij    return 0;
25955714Skris}
26055714Skris
26155714Skrisint X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
26255714Skris{
263296341Sdelphij    ASN1_INTEGER *itmp;
264296341Sdelphij    if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
265296341Sdelphij        X509V3_conf_err(value);
266296341Sdelphij        return 0;
267296341Sdelphij    }
268296341Sdelphij    *aint = itmp;
269296341Sdelphij    return 1;
27055714Skris}
27155714Skris
272296341Sdelphij#define HDR_NAME        1
273296341Sdelphij#define HDR_VALUE       2
27455714Skris
275296341Sdelphij/*
276296341Sdelphij * #define DEBUG
277296341Sdelphij */
27855714Skris
279109998SmarkmSTACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
28055714Skris{
281296341Sdelphij    char *p, *q, c;
282296341Sdelphij    char *ntmp, *vtmp;
283296341Sdelphij    STACK_OF(CONF_VALUE) *values = NULL;
284296341Sdelphij    char *linebuf;
285296341Sdelphij    int state;
286296341Sdelphij    /* We are going to modify the line so copy it first */
287296341Sdelphij    linebuf = BUF_strdup(line);
288296341Sdelphij    if (linebuf == NULL) {
289296341Sdelphij        X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE);
290296341Sdelphij        goto err;
291296341Sdelphij    }
292296341Sdelphij    state = HDR_NAME;
293296341Sdelphij    ntmp = NULL;
294296341Sdelphij    /* Go through all characters */
295296341Sdelphij    for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
296296341Sdelphij         p++) {
29755714Skris
298296341Sdelphij        switch (state) {
299296341Sdelphij        case HDR_NAME:
300296341Sdelphij            if (c == ':') {
301296341Sdelphij                state = HDR_VALUE;
302296341Sdelphij                *p = 0;
303296341Sdelphij                ntmp = strip_spaces(q);
304296341Sdelphij                if (!ntmp) {
305296341Sdelphij                    X509V3err(X509V3_F_X509V3_PARSE_LIST,
306296341Sdelphij                              X509V3_R_INVALID_NULL_NAME);
307296341Sdelphij                    goto err;
308296341Sdelphij                }
309296341Sdelphij                q = p + 1;
310296341Sdelphij            } else if (c == ',') {
311296341Sdelphij                *p = 0;
312296341Sdelphij                ntmp = strip_spaces(q);
313296341Sdelphij                q = p + 1;
314100928Snectar#if 0
315296341Sdelphij                printf("%s\n", ntmp);
31655714Skris#endif
317296341Sdelphij                if (!ntmp) {
318296341Sdelphij                    X509V3err(X509V3_F_X509V3_PARSE_LIST,
319296341Sdelphij                              X509V3_R_INVALID_NULL_NAME);
320296341Sdelphij                    goto err;
321296341Sdelphij                }
322296341Sdelphij                X509V3_add_value(ntmp, NULL, &values);
323296341Sdelphij            }
324296341Sdelphij            break;
32555714Skris
326296341Sdelphij        case HDR_VALUE:
327296341Sdelphij            if (c == ',') {
328296341Sdelphij                state = HDR_NAME;
329296341Sdelphij                *p = 0;
330296341Sdelphij                vtmp = strip_spaces(q);
331100928Snectar#if 0
332296341Sdelphij                printf("%s\n", ntmp);
33355714Skris#endif
334296341Sdelphij                if (!vtmp) {
335296341Sdelphij                    X509V3err(X509V3_F_X509V3_PARSE_LIST,
336296341Sdelphij                              X509V3_R_INVALID_NULL_VALUE);
337296341Sdelphij                    goto err;
338296341Sdelphij                }
339296341Sdelphij                X509V3_add_value(ntmp, vtmp, &values);
340296341Sdelphij                ntmp = NULL;
341296341Sdelphij                q = p + 1;
342296341Sdelphij            }
34355714Skris
344296341Sdelphij        }
345296341Sdelphij    }
34655714Skris
347296341Sdelphij    if (state == HDR_VALUE) {
348296341Sdelphij        vtmp = strip_spaces(q);
349100928Snectar#if 0
350296341Sdelphij        printf("%s=%s\n", ntmp, vtmp);
35155714Skris#endif
352296341Sdelphij        if (!vtmp) {
353296341Sdelphij            X509V3err(X509V3_F_X509V3_PARSE_LIST,
354296341Sdelphij                      X509V3_R_INVALID_NULL_VALUE);
355296341Sdelphij            goto err;
356296341Sdelphij        }
357296341Sdelphij        X509V3_add_value(ntmp, vtmp, &values);
358296341Sdelphij    } else {
359296341Sdelphij        ntmp = strip_spaces(q);
360100928Snectar#if 0
361296341Sdelphij        printf("%s\n", ntmp);
36255714Skris#endif
363296341Sdelphij        if (!ntmp) {
364296341Sdelphij            X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
365296341Sdelphij            goto err;
366296341Sdelphij        }
367296341Sdelphij        X509V3_add_value(ntmp, NULL, &values);
368296341Sdelphij    }
369296341Sdelphij    OPENSSL_free(linebuf);
370296341Sdelphij    return values;
37155714Skris
372296341Sdelphij err:
373296341Sdelphij    OPENSSL_free(linebuf);
374296341Sdelphij    sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
375296341Sdelphij    return NULL;
37655714Skris
37755714Skris}
37855714Skris
37955714Skris/* Delete leading and trailing spaces from a string */
38055714Skrisstatic char *strip_spaces(char *name)
38155714Skris{
382296341Sdelphij    char *p, *q;
383296341Sdelphij    /* Skip over leading spaces */
384296341Sdelphij    p = name;
385296341Sdelphij    while (*p && isspace((unsigned char)*p))
386296341Sdelphij        p++;
387296341Sdelphij    if (!*p)
388296341Sdelphij        return NULL;
389296341Sdelphij    q = p + strlen(p) - 1;
390296341Sdelphij    while ((q != p) && isspace((unsigned char)*q))
391296341Sdelphij        q--;
392296341Sdelphij    if (p != q)
393296341Sdelphij        q[1] = 0;
394296341Sdelphij    if (!*p)
395296341Sdelphij        return NULL;
396296341Sdelphij    return p;
39755714Skris}
39855714Skris
39955714Skris/* hex string utilities */
40055714Skris
401296341Sdelphij/*
402296341Sdelphij * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
403296341Sdelphij * hex representation @@@ (Contents of buffer are always kept in ASCII, also
404296341Sdelphij * on EBCDIC machines)
40555714Skris */
40655714Skris
407238405Sjkimchar *hex_to_string(const unsigned char *buffer, long len)
40855714Skris{
409296341Sdelphij    char *tmp, *q;
410296341Sdelphij    const unsigned char *p;
411296341Sdelphij    int i;
412296341Sdelphij    const static char hexdig[] = "0123456789ABCDEF";
413296341Sdelphij    if (!buffer || !len)
414296341Sdelphij        return NULL;
415296341Sdelphij    if (!(tmp = OPENSSL_malloc(len * 3 + 1))) {
416296341Sdelphij        X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE);
417296341Sdelphij        return NULL;
418296341Sdelphij    }
419296341Sdelphij    q = tmp;
420296341Sdelphij    for (i = 0, p = buffer; i < len; i++, p++) {
421296341Sdelphij        *q++ = hexdig[(*p >> 4) & 0xf];
422296341Sdelphij        *q++ = hexdig[*p & 0xf];
423296341Sdelphij        *q++ = ':';
424296341Sdelphij    }
425296341Sdelphij    q[-1] = 0;
42668651Skris#ifdef CHARSET_EBCDIC
427296341Sdelphij    ebcdic2ascii(tmp, tmp, q - tmp - 1);
42868651Skris#endif
42968651Skris
430296341Sdelphij    return tmp;
43155714Skris}
43255714Skris
433296341Sdelphij/*
434296341Sdelphij * Give a string of hex digits convert to a buffer
43555714Skris */
43655714Skris
437238405Sjkimunsigned char *string_to_hex(const char *str, long *len)
43855714Skris{
439296341Sdelphij    unsigned char *hexbuf, *q;
440296341Sdelphij    unsigned char ch, cl, *p;
441296341Sdelphij    if (!str) {
442296341Sdelphij        X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_INVALID_NULL_ARGUMENT);
443296341Sdelphij        return NULL;
444296341Sdelphij    }
445296341Sdelphij    if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1)))
446296341Sdelphij        goto err;
447296341Sdelphij    for (p = (unsigned char *)str, q = hexbuf; *p;) {
448296341Sdelphij        ch = *p++;
44968651Skris#ifdef CHARSET_EBCDIC
450296341Sdelphij        ch = os_toebcdic[ch];
45168651Skris#endif
452296341Sdelphij        if (ch == ':')
453296341Sdelphij            continue;
454296341Sdelphij        cl = *p++;
45568651Skris#ifdef CHARSET_EBCDIC
456296341Sdelphij        cl = os_toebcdic[cl];
45768651Skris#endif
458296341Sdelphij        if (!cl) {
459296341Sdelphij            X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ODD_NUMBER_OF_DIGITS);
460296341Sdelphij            OPENSSL_free(hexbuf);
461296341Sdelphij            return NULL;
462296341Sdelphij        }
463296341Sdelphij        if (isupper(ch))
464296341Sdelphij            ch = tolower(ch);
465296341Sdelphij        if (isupper(cl))
466296341Sdelphij            cl = tolower(cl);
46755714Skris
468296341Sdelphij        if ((ch >= '0') && (ch <= '9'))
469296341Sdelphij            ch -= '0';
470296341Sdelphij        else if ((ch >= 'a') && (ch <= 'f'))
471296341Sdelphij            ch -= 'a' - 10;
472296341Sdelphij        else
473296341Sdelphij            goto badhex;
47455714Skris
475296341Sdelphij        if ((cl >= '0') && (cl <= '9'))
476296341Sdelphij            cl -= '0';
477296341Sdelphij        else if ((cl >= 'a') && (cl <= 'f'))
478296341Sdelphij            cl -= 'a' - 10;
479296341Sdelphij        else
480296341Sdelphij            goto badhex;
48155714Skris
482296341Sdelphij        *q++ = (ch << 4) | cl;
483296341Sdelphij    }
48455714Skris
485296341Sdelphij    if (len)
486296341Sdelphij        *len = q - hexbuf;
48755714Skris
488296341Sdelphij    return hexbuf;
48955714Skris
490296341Sdelphij err:
491296341Sdelphij    if (hexbuf)
492296341Sdelphij        OPENSSL_free(hexbuf);
493296341Sdelphij    X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE);
494296341Sdelphij    return NULL;
49555714Skris
496296341Sdelphij badhex:
497296341Sdelphij    OPENSSL_free(hexbuf);
498296341Sdelphij    X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT);
499296341Sdelphij    return NULL;
50055714Skris
50155714Skris}
50255714Skris
503296341Sdelphij/*
504296341Sdelphij * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
50555714Skris */
50655714Skris
50755714Skrisint name_cmp(const char *name, const char *cmp)
50855714Skris{
509296341Sdelphij    int len, ret;
510296341Sdelphij    char c;
511296341Sdelphij    len = strlen(cmp);
512296341Sdelphij    if ((ret = strncmp(name, cmp, len)))
513296341Sdelphij        return ret;
514296341Sdelphij    c = name[len];
515296341Sdelphij    if (!c || (c == '.'))
516296341Sdelphij        return 0;
517296341Sdelphij    return 1;
51855714Skris}
51968651Skris
520296341Sdelphijstatic int sk_strcmp(const char *const *a, const char *const *b)
52168651Skris{
522296341Sdelphij    return strcmp(*a, *b);
52368651Skris}
52468651Skris
525238405SjkimSTACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
52668651Skris{
527296341Sdelphij    GENERAL_NAMES *gens;
528296341Sdelphij    STACK_OF(OPENSSL_STRING) *ret;
529238405Sjkim
530296341Sdelphij    gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
531296341Sdelphij    ret = get_email(X509_get_subject_name(x), gens);
532296341Sdelphij    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
533296341Sdelphij    return ret;
53468651Skris}
53568651Skris
536238405SjkimSTACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
537194206Ssimon{
538296341Sdelphij    AUTHORITY_INFO_ACCESS *info;
539296341Sdelphij    STACK_OF(OPENSSL_STRING) *ret = NULL;
540296341Sdelphij    int i;
541238405Sjkim
542296341Sdelphij    info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
543296341Sdelphij    if (!info)
544296341Sdelphij        return NULL;
545296341Sdelphij    for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
546296341Sdelphij        ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
547296341Sdelphij        if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
548296341Sdelphij            if (ad->location->type == GEN_URI) {
549296341Sdelphij                if (!append_ia5
550296341Sdelphij                    (&ret, ad->location->d.uniformResourceIdentifier))
551296341Sdelphij                    break;
552296341Sdelphij            }
553296341Sdelphij        }
554296341Sdelphij    }
555296341Sdelphij    AUTHORITY_INFO_ACCESS_free(info);
556296341Sdelphij    return ret;
557194206Ssimon}
558194206Ssimon
559238405SjkimSTACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
56068651Skris{
561296341Sdelphij    GENERAL_NAMES *gens;
562296341Sdelphij    STACK_OF(X509_EXTENSION) *exts;
563296341Sdelphij    STACK_OF(OPENSSL_STRING) *ret;
564238405Sjkim
565296341Sdelphij    exts = X509_REQ_get_extensions(x);
566296341Sdelphij    gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
567296341Sdelphij    ret = get_email(X509_REQ_get_subject_name(x), gens);
568296341Sdelphij    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
569296341Sdelphij    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
570296341Sdelphij    return ret;
57168651Skris}
57268651Skris
573296341Sdelphijstatic STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
574296341Sdelphij                                           GENERAL_NAMES *gens)
57568651Skris{
576296341Sdelphij    STACK_OF(OPENSSL_STRING) *ret = NULL;
577296341Sdelphij    X509_NAME_ENTRY *ne;
578296341Sdelphij    ASN1_IA5STRING *email;
579296341Sdelphij    GENERAL_NAME *gen;
580296341Sdelphij    int i;
581296341Sdelphij    /* Now add any email address(es) to STACK */
582296341Sdelphij    i = -1;
583296341Sdelphij    /* First supplied X509_NAME */
584296341Sdelphij    while ((i = X509_NAME_get_index_by_NID(name,
585296341Sdelphij                                           NID_pkcs9_emailAddress, i)) >= 0) {
586296341Sdelphij        ne = X509_NAME_get_entry(name, i);
587296341Sdelphij        email = X509_NAME_ENTRY_get_data(ne);
588296341Sdelphij        if (!append_ia5(&ret, email))
589296341Sdelphij            return NULL;
590296341Sdelphij    }
591296341Sdelphij    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
592296341Sdelphij        gen = sk_GENERAL_NAME_value(gens, i);
593296341Sdelphij        if (gen->type != GEN_EMAIL)
594296341Sdelphij            continue;
595296341Sdelphij        if (!append_ia5(&ret, gen->d.ia5))
596296341Sdelphij            return NULL;
597296341Sdelphij    }
598296341Sdelphij    return ret;
59968651Skris}
60068651Skris
601238405Sjkimstatic void str_free(OPENSSL_STRING str)
60268651Skris{
603296341Sdelphij    OPENSSL_free(str);
60468651Skris}
60568651Skris
606238405Sjkimstatic int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
60768651Skris{
608296341Sdelphij    char *emtmp;
609296341Sdelphij    /* First some sanity checks */
610296341Sdelphij    if (email->type != V_ASN1_IA5STRING)
611296341Sdelphij        return 1;
612296341Sdelphij    if (!email->data || !email->length)
613296341Sdelphij        return 1;
614296341Sdelphij    if (!*sk)
615296341Sdelphij        *sk = sk_OPENSSL_STRING_new(sk_strcmp);
616296341Sdelphij    if (!*sk)
617296341Sdelphij        return 0;
618296341Sdelphij    /* Don't add duplicates */
619296341Sdelphij    if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
620296341Sdelphij        return 1;
621296341Sdelphij    emtmp = BUF_strdup((char *)email->data);
622296341Sdelphij    if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
623296341Sdelphij        X509_email_free(*sk);
624296341Sdelphij        *sk = NULL;
625296341Sdelphij        return 0;
626296341Sdelphij    }
627296341Sdelphij    return 1;
62868651Skris}
62968651Skris
630238405Sjkimvoid X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
63168651Skris{
632296341Sdelphij    sk_OPENSSL_STRING_pop_free(sk, str_free);
63368651Skris}
634160814Ssimon
635296341Sdelphij/*
636296341Sdelphij * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
637296341Sdelphij * with RFC3280.
638160814Ssimon */
639160814Ssimon
640160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
641296341Sdelphij{
642296341Sdelphij    unsigned char ipout[16];
643296341Sdelphij    ASN1_OCTET_STRING *ret;
644296341Sdelphij    int iplen;
645160814Ssimon
646296341Sdelphij    /* If string contains a ':' assume IPv6 */
647160814Ssimon
648296341Sdelphij    iplen = a2i_ipadd(ipout, ipasc);
649160814Ssimon
650296341Sdelphij    if (!iplen)
651296341Sdelphij        return NULL;
652160814Ssimon
653296341Sdelphij    ret = ASN1_OCTET_STRING_new();
654296341Sdelphij    if (!ret)
655296341Sdelphij        return NULL;
656296341Sdelphij    if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
657296341Sdelphij        ASN1_OCTET_STRING_free(ret);
658296341Sdelphij        return NULL;
659296341Sdelphij    }
660296341Sdelphij    return ret;
661296341Sdelphij}
662160814Ssimon
663160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
664296341Sdelphij{
665296341Sdelphij    ASN1_OCTET_STRING *ret = NULL;
666296341Sdelphij    unsigned char ipout[32];
667296341Sdelphij    char *iptmp = NULL, *p;
668296341Sdelphij    int iplen1, iplen2;
669296341Sdelphij    p = strchr(ipasc, '/');
670296341Sdelphij    if (!p)
671296341Sdelphij        return NULL;
672296341Sdelphij    iptmp = BUF_strdup(ipasc);
673296341Sdelphij    if (!iptmp)
674296341Sdelphij        return NULL;
675296341Sdelphij    p = iptmp + (p - ipasc);
676296341Sdelphij    *p++ = 0;
677160814Ssimon
678296341Sdelphij    iplen1 = a2i_ipadd(ipout, iptmp);
679160814Ssimon
680296341Sdelphij    if (!iplen1)
681296341Sdelphij        goto err;
682160814Ssimon
683296341Sdelphij    iplen2 = a2i_ipadd(ipout + iplen1, p);
684160814Ssimon
685296341Sdelphij    OPENSSL_free(iptmp);
686296341Sdelphij    iptmp = NULL;
687160814Ssimon
688296341Sdelphij    if (!iplen2 || (iplen1 != iplen2))
689296341Sdelphij        goto err;
690160814Ssimon
691296341Sdelphij    ret = ASN1_OCTET_STRING_new();
692296341Sdelphij    if (!ret)
693296341Sdelphij        goto err;
694296341Sdelphij    if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
695296341Sdelphij        goto err;
696160814Ssimon
697296341Sdelphij    return ret;
698160814Ssimon
699296341Sdelphij err:
700296341Sdelphij    if (iptmp)
701296341Sdelphij        OPENSSL_free(iptmp);
702296341Sdelphij    if (ret)
703296341Sdelphij        ASN1_OCTET_STRING_free(ret);
704296341Sdelphij    return NULL;
705296341Sdelphij}
706160814Ssimon
707167612Ssimonint a2i_ipadd(unsigned char *ipout, const char *ipasc)
708296341Sdelphij{
709296341Sdelphij    /* If string contains a ':' assume IPv6 */
710160814Ssimon
711296341Sdelphij    if (strchr(ipasc, ':')) {
712296341Sdelphij        if (!ipv6_from_asc(ipout, ipasc))
713296341Sdelphij            return 0;
714296341Sdelphij        return 16;
715296341Sdelphij    } else {
716296341Sdelphij        if (!ipv4_from_asc(ipout, ipasc))
717296341Sdelphij            return 0;
718296341Sdelphij        return 4;
719296341Sdelphij    }
720296341Sdelphij}
721160814Ssimon
722160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in)
723296341Sdelphij{
724296341Sdelphij    int a0, a1, a2, a3;
725296341Sdelphij    if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
726296341Sdelphij        return 0;
727296341Sdelphij    if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
728296341Sdelphij        || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
729296341Sdelphij        return 0;
730296341Sdelphij    v4[0] = a0;
731296341Sdelphij    v4[1] = a1;
732296341Sdelphij    v4[2] = a2;
733296341Sdelphij    v4[3] = a3;
734296341Sdelphij    return 1;
735296341Sdelphij}
736160814Ssimon
737160814Ssimontypedef struct {
738296341Sdelphij    /* Temporary store for IPV6 output */
739296341Sdelphij    unsigned char tmp[16];
740296341Sdelphij    /* Total number of bytes in tmp */
741296341Sdelphij    int total;
742296341Sdelphij    /* The position of a zero (corresponding to '::') */
743296341Sdelphij    int zero_pos;
744296341Sdelphij    /* Number of zeroes */
745296341Sdelphij    int zero_cnt;
746296341Sdelphij} IPV6_STAT;
747160814Ssimon
748160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in)
749296341Sdelphij{
750296341Sdelphij    IPV6_STAT v6stat;
751296341Sdelphij    v6stat.total = 0;
752296341Sdelphij    v6stat.zero_pos = -1;
753296341Sdelphij    v6stat.zero_cnt = 0;
754296341Sdelphij    /*
755296341Sdelphij     * Treat the IPv6 representation as a list of values separated by ':'.
756296341Sdelphij     * The presence of a '::' will parse as one, two or three zero length
757296341Sdelphij     * elements.
758296341Sdelphij     */
759296341Sdelphij    if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
760296341Sdelphij        return 0;
761160814Ssimon
762296341Sdelphij    /* Now for some sanity checks */
763160814Ssimon
764296341Sdelphij    if (v6stat.zero_pos == -1) {
765296341Sdelphij        /* If no '::' must have exactly 16 bytes */
766296341Sdelphij        if (v6stat.total != 16)
767296341Sdelphij            return 0;
768296341Sdelphij    } else {
769296341Sdelphij        /* If '::' must have less than 16 bytes */
770296341Sdelphij        if (v6stat.total == 16)
771296341Sdelphij            return 0;
772296341Sdelphij        /* More than three zeroes is an error */
773296341Sdelphij        if (v6stat.zero_cnt > 3)
774296341Sdelphij            return 0;
775296341Sdelphij        /* Can only have three zeroes if nothing else present */
776296341Sdelphij        else if (v6stat.zero_cnt == 3) {
777296341Sdelphij            if (v6stat.total > 0)
778296341Sdelphij                return 0;
779296341Sdelphij        }
780296341Sdelphij        /* Can only have two zeroes if at start or end */
781296341Sdelphij        else if (v6stat.zero_cnt == 2) {
782296341Sdelphij            if ((v6stat.zero_pos != 0)
783296341Sdelphij                && (v6stat.zero_pos != v6stat.total))
784296341Sdelphij                return 0;
785296341Sdelphij        } else
786296341Sdelphij            /* Can only have one zero if *not* start or end */
787296341Sdelphij        {
788296341Sdelphij            if ((v6stat.zero_pos == 0)
789296341Sdelphij                || (v6stat.zero_pos == v6stat.total))
790296341Sdelphij                return 0;
791296341Sdelphij        }
792296341Sdelphij    }
793160814Ssimon
794296341Sdelphij    /* Format result */
795160814Ssimon
796296341Sdelphij    if (v6stat.zero_pos >= 0) {
797296341Sdelphij        /* Copy initial part */
798296341Sdelphij        memcpy(v6, v6stat.tmp, v6stat.zero_pos);
799296341Sdelphij        /* Zero middle */
800296341Sdelphij        memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
801296341Sdelphij        /* Copy final part */
802296341Sdelphij        if (v6stat.total != v6stat.zero_pos)
803296341Sdelphij            memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
804296341Sdelphij                   v6stat.tmp + v6stat.zero_pos,
805296341Sdelphij                   v6stat.total - v6stat.zero_pos);
806296341Sdelphij    } else
807296341Sdelphij        memcpy(v6, v6stat.tmp, 16);
808160814Ssimon
809296341Sdelphij    return 1;
810296341Sdelphij}
811160814Ssimon
812160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr)
813296341Sdelphij{
814296341Sdelphij    IPV6_STAT *s = usr;
815296341Sdelphij    /* Error if 16 bytes written */
816296341Sdelphij    if (s->total == 16)
817296341Sdelphij        return 0;
818296341Sdelphij    if (len == 0) {
819296341Sdelphij        /* Zero length element, corresponds to '::' */
820296341Sdelphij        if (s->zero_pos == -1)
821296341Sdelphij            s->zero_pos = s->total;
822296341Sdelphij        /* If we've already got a :: its an error */
823296341Sdelphij        else if (s->zero_pos != s->total)
824296341Sdelphij            return 0;
825296341Sdelphij        s->zero_cnt++;
826296341Sdelphij    } else {
827296341Sdelphij        /* If more than 4 characters could be final a.b.c.d form */
828296341Sdelphij        if (len > 4) {
829296341Sdelphij            /* Need at least 4 bytes left */
830296341Sdelphij            if (s->total > 12)
831296341Sdelphij                return 0;
832296341Sdelphij            /* Must be end of string */
833296341Sdelphij            if (elem[len])
834296341Sdelphij                return 0;
835296341Sdelphij            if (!ipv4_from_asc(s->tmp + s->total, elem))
836296341Sdelphij                return 0;
837296341Sdelphij            s->total += 4;
838296341Sdelphij        } else {
839296341Sdelphij            if (!ipv6_hex(s->tmp + s->total, elem, len))
840296341Sdelphij                return 0;
841296341Sdelphij            s->total += 2;
842296341Sdelphij        }
843296341Sdelphij    }
844296341Sdelphij    return 1;
845296341Sdelphij}
846160814Ssimon
847296341Sdelphij/*
848296341Sdelphij * 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)
852296341Sdelphij{
853296341Sdelphij    unsigned char c;
854296341Sdelphij    unsigned int num = 0;
855296341Sdelphij    if (inlen > 4)
856296341Sdelphij        return 0;
857296341Sdelphij    while (inlen--) {
858296341Sdelphij        c = *in++;
859296341Sdelphij        num <<= 4;
860296341Sdelphij        if ((c >= '0') && (c <= '9'))
861296341Sdelphij            num |= c - '0';
862296341Sdelphij        else if ((c >= 'A') && (c <= 'F'))
863296341Sdelphij            num |= c - 'A' + 10;
864296341Sdelphij        else if ((c >= 'a') && (c <= 'f'))
865296341Sdelphij            num |= c - 'a' + 10;
866296341Sdelphij        else
867296341Sdelphij            return 0;
868296341Sdelphij    }
869296341Sdelphij    out[0] = num >> 8;
870296341Sdelphij    out[1] = num & 0xff;
871296341Sdelphij    return 1;
872296341Sdelphij}
873160814Ssimon
874296341Sdelphijint X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
875296341Sdelphij                             unsigned long chtype)
876296341Sdelphij{
877296341Sdelphij    CONF_VALUE *v;
878296341Sdelphij    int i, mval;
879296341Sdelphij    char *p, *type;
880296341Sdelphij    if (!nm)
881296341Sdelphij        return 0;
882160814Ssimon
883296341Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
884296341Sdelphij        v = sk_CONF_VALUE_value(dn_sk, i);
885296341Sdelphij        type = v->name;
886296341Sdelphij        /*
887296341Sdelphij         * Skip past any leading X. X: X, etc to allow for multiple instances
888296341Sdelphij         */
889296341Sdelphij        for (p = type; *p; p++)
890160814Ssimon#ifndef CHARSET_EBCDIC
891296341Sdelphij            if ((*p == ':') || (*p == ',') || (*p == '.'))
892160814Ssimon#else
893296341Sdelphij            if ((*p == os_toascii[':']) || (*p == os_toascii[','])
894296341Sdelphij                || (*p == os_toascii['.']))
895160814Ssimon#endif
896296341Sdelphij            {
897296341Sdelphij                p++;
898296341Sdelphij                if (*p)
899296341Sdelphij                    type = p;
900296341Sdelphij                break;
901296341Sdelphij            }
902160814Ssimon#ifndef CHARSET_EBCDIC
903296341Sdelphij        if (*type == '+')
904160814Ssimon#else
905296341Sdelphij        if (*type == os_toascii['+'])
906160814Ssimon#endif
907296341Sdelphij        {
908296341Sdelphij            mval = -1;
909296341Sdelphij            type++;
910296341Sdelphij        } else
911296341Sdelphij            mval = 0;
912296341Sdelphij        if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
913296341Sdelphij                                        (unsigned char *)v->value, -1, -1,
914296341Sdelphij                                        mval))
915296341Sdelphij            return 0;
916160814Ssimon
917296341Sdelphij    }
918296341Sdelphij    return 1;
919296341Sdelphij}
920