v3_utl.c revision 167612
155714Skris/* v3_utl.c */
255714Skris/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3160814Ssimon * project.
455714Skris */
555714Skris/* ====================================================================
6160814Ssimon * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
755714Skris *
855714Skris * Redistribution and use in source and binary forms, with or without
955714Skris * modification, are permitted provided that the following conditions
1055714Skris * are met:
1155714Skris *
1255714Skris * 1. Redistributions of source code must retain the above copyright
1355714Skris *    notice, this list of conditions and the following disclaimer.
1455714Skris *
1555714Skris * 2. Redistributions in binary form must reproduce the above copyright
1655714Skris *    notice, this list of conditions and the following disclaimer in
1755714Skris *    the documentation and/or other materials provided with the
1855714Skris *    distribution.
1955714Skris *
2055714Skris * 3. All advertising materials mentioning features or use of this
2155714Skris *    software must display the following acknowledgment:
2255714Skris *    "This product includes software developed by the OpenSSL Project
2355714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2455714Skris *
2555714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2655714Skris *    endorse or promote products derived from this software without
2755714Skris *    prior written permission. For written permission, please contact
2855714Skris *    licensing@OpenSSL.org.
2955714Skris *
3055714Skris * 5. Products derived from this software may not be called "OpenSSL"
3155714Skris *    nor may "OpenSSL" appear in their names without prior written
3255714Skris *    permission of the OpenSSL Project.
3355714Skris *
3455714Skris * 6. Redistributions of any form whatsoever must retain the following
3555714Skris *    acknowledgment:
3655714Skris *    "This product includes software developed by the OpenSSL Project
3755714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3855714Skris *
3955714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4055714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4155714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4255714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4355714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4455714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4555714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4655714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4755714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4855714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4955714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5055714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5155714Skris * ====================================================================
5255714Skris *
5355714Skris * This product includes cryptographic software written by Eric Young
5455714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5555714Skris * Hudson (tjh@cryptsoft.com).
5655714Skris *
5755714Skris */
5855714Skris/* X509 v3 extension utilities */
5955714Skris
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);
6968651Skrisstatic 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);
7268651Skrisstatic 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,
8255714Skris						STACK_OF(CONF_VALUE) **extlist)
8355714Skris{
8455714Skris	CONF_VALUE *vtmp = NULL;
8555714Skris	char *tname = NULL, *tvalue = NULL;
8655714Skris	if(name && !(tname = BUF_strdup(name))) goto err;
8755714Skris	if(value && !(tvalue = BUF_strdup(value))) goto err;;
8868651Skris	if(!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) goto err;
8968651Skris	if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err;
9055714Skris	vtmp->section = NULL;
9155714Skris	vtmp->name = tname;
9255714Skris	vtmp->value = tvalue;
9355714Skris	if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err;
9455714Skris	return 1;
9555714Skris	err:
9655714Skris	X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE);
9768651Skris	if(vtmp) OPENSSL_free(vtmp);
9868651Skris	if(tname) OPENSSL_free(tname);
9968651Skris	if(tvalue) OPENSSL_free(tvalue);
10055714Skris	return 0;
10155714Skris}
10255714Skris
10355714Skrisint X509V3_add_value_uchar(const char *name, const unsigned char *value,
10455714Skris			   STACK_OF(CONF_VALUE) **extlist)
10555714Skris    {
10655714Skris    return X509V3_add_value(name,(const char *)value,extlist);
10755714Skris    }
10855714Skris
10955714Skris/* Free function for STACK_OF(CONF_VALUE) */
11055714Skris
11155714Skrisvoid X509V3_conf_free(CONF_VALUE *conf)
11255714Skris{
11355714Skris	if(!conf) return;
11468651Skris	if(conf->name) OPENSSL_free(conf->name);
11568651Skris	if(conf->value) OPENSSL_free(conf->value);
11668651Skris	if(conf->section) OPENSSL_free(conf->section);
11768651Skris	OPENSSL_free(conf);
11855714Skris}
11955714Skris
12055714Skrisint X509V3_add_value_bool(const char *name, int asn1_bool,
12155714Skris						STACK_OF(CONF_VALUE) **extlist)
12255714Skris{
12355714Skris	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
12455714Skris	return X509V3_add_value(name, "FALSE", extlist);
12555714Skris}
12655714Skris
12755714Skrisint X509V3_add_value_bool_nf(char *name, int asn1_bool,
12855714Skris						STACK_OF(CONF_VALUE) **extlist)
12955714Skris{
13055714Skris	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
13155714Skris	return 1;
13255714Skris}
13355714Skris
13455714Skris
13555714Skrischar *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
13655714Skris{
13755714Skris	BIGNUM *bntmp = NULL;
13855714Skris	char *strtmp = NULL;
13955714Skris	if(!a) return NULL;
14055714Skris	if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
14155714Skris	    !(strtmp = BN_bn2dec(bntmp)) )
14255714Skris		X509V3err(X509V3_F_I2S_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE);
14355714Skris	BN_free(bntmp);
14455714Skris	return strtmp;
14555714Skris}
14655714Skris
14755714Skrischar *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
14855714Skris{
14955714Skris	BIGNUM *bntmp = NULL;
15055714Skris	char *strtmp = NULL;
15155714Skris	if(!a) return NULL;
15255714Skris	if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
15355714Skris	    !(strtmp = BN_bn2dec(bntmp)) )
15455714Skris		X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE);
15555714Skris	BN_free(bntmp);
15655714Skris	return strtmp;
15755714Skris}
15855714Skris
15955714SkrisASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
16055714Skris{
16155714Skris	BIGNUM *bn = NULL;
16255714Skris	ASN1_INTEGER *aint;
163109998Smarkm	int isneg, ishex;
164109998Smarkm	int ret;
165109998Smarkm	if (!value) {
16655714Skris		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE);
16755714Skris		return 0;
16855714Skris	}
169160814Ssimon	bn = BN_new();
170109998Smarkm	if (value[0] == '-') {
171109998Smarkm		value++;
172109998Smarkm		isneg = 1;
173109998Smarkm	} else isneg = 0;
174109998Smarkm
175109998Smarkm	if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
176109998Smarkm		value += 2;
177109998Smarkm		ishex = 1;
178109998Smarkm	} else ishex = 0;
179109998Smarkm
180109998Smarkm	if (ishex) ret = BN_hex2bn(&bn, value);
181109998Smarkm	else ret = BN_dec2bn(&bn, value);
182109998Smarkm
183160814Ssimon	if (!ret || value[ret]) {
184160814Ssimon		BN_free(bn);
18555714Skris		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR);
18655714Skris		return 0;
18755714Skris	}
18855714Skris
189109998Smarkm	if (isneg && BN_is_zero(bn)) isneg = 0;
190109998Smarkm
191109998Smarkm	aint = BN_to_ASN1_INTEGER(bn, NULL);
192109998Smarkm	BN_free(bn);
193109998Smarkm	if (!aint) {
19455714Skris		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
19555714Skris		return 0;
19655714Skris	}
197109998Smarkm	if (isneg) aint->type |= V_ASN1_NEG;
19855714Skris	return aint;
19955714Skris}
20055714Skris
20155714Skrisint X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
20255714Skris	     STACK_OF(CONF_VALUE) **extlist)
20355714Skris{
20455714Skris	char *strtmp;
20555714Skris	int ret;
20655714Skris	if(!aint) return 1;
20755714Skris	if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0;
20855714Skris	ret = X509V3_add_value(name, strtmp, extlist);
20968651Skris	OPENSSL_free(strtmp);
21055714Skris	return ret;
21155714Skris}
21255714Skris
21355714Skrisint X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
21455714Skris{
21555714Skris	char *btmp;
21655714Skris	if(!(btmp = value->value)) goto err;
21755714Skris	if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
21855714Skris		 || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
21955714Skris		|| !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
22055714Skris		*asn1_bool = 0xff;
22155714Skris		return 1;
22255714Skris	} else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
22355714Skris		 || !strcmp(btmp, "N") || !strcmp(btmp, "n")
22455714Skris		|| !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
22555714Skris		*asn1_bool = 0;
22655714Skris		return 1;
22755714Skris	}
22855714Skris	err:
22955714Skris	X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,X509V3_R_INVALID_BOOLEAN_STRING);
23055714Skris	X509V3_conf_err(value);
23155714Skris	return 0;
23255714Skris}
23355714Skris
23455714Skrisint X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
23555714Skris{
23655714Skris	ASN1_INTEGER *itmp;
23755714Skris	if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
23855714Skris		X509V3_conf_err(value);
23955714Skris		return 0;
24055714Skris	}
24155714Skris	*aint = itmp;
24255714Skris	return 1;
24355714Skris}
24455714Skris
24555714Skris#define HDR_NAME	1
24655714Skris#define HDR_VALUE	2
24755714Skris
24855714Skris/*#define DEBUG*/
24955714Skris
250109998SmarkmSTACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
25155714Skris{
25255714Skris	char *p, *q, c;
25355714Skris	char *ntmp, *vtmp;
25455714Skris	STACK_OF(CONF_VALUE) *values = NULL;
25555714Skris	char *linebuf;
25655714Skris	int state;
25755714Skris	/* We are going to modify the line so copy it first */
25855714Skris	linebuf = BUF_strdup(line);
25955714Skris	state = HDR_NAME;
26055714Skris	ntmp = NULL;
26155714Skris	/* Go through all characters */
26255714Skris	for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
26355714Skris
26455714Skris		switch(state) {
26555714Skris			case HDR_NAME:
26655714Skris			if(c == ':') {
26755714Skris				state = HDR_VALUE;
26855714Skris				*p = 0;
26955714Skris				ntmp = strip_spaces(q);
27055714Skris				if(!ntmp) {
27155714Skris					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
27255714Skris					goto err;
27355714Skris				}
27455714Skris				q = p + 1;
27555714Skris			} else if(c == ',') {
27655714Skris				*p = 0;
27755714Skris				ntmp = strip_spaces(q);
27855714Skris				q = p + 1;
279100928Snectar#if 0
28055714Skris				printf("%s\n", ntmp);
28155714Skris#endif
28255714Skris				if(!ntmp) {
28355714Skris					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
28455714Skris					goto err;
28555714Skris				}
28655714Skris				X509V3_add_value(ntmp, NULL, &values);
28755714Skris			}
28855714Skris			break ;
28955714Skris
29055714Skris			case HDR_VALUE:
29155714Skris			if(c == ',') {
29255714Skris				state = HDR_NAME;
29355714Skris				*p = 0;
29455714Skris				vtmp = strip_spaces(q);
295100928Snectar#if 0
29655714Skris				printf("%s\n", ntmp);
29755714Skris#endif
29855714Skris				if(!vtmp) {
29955714Skris					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
30055714Skris					goto err;
30155714Skris				}
30255714Skris				X509V3_add_value(ntmp, vtmp, &values);
30355714Skris				ntmp = NULL;
30455714Skris				q = p + 1;
30555714Skris			}
30655714Skris
30755714Skris		}
30855714Skris	}
30955714Skris
31055714Skris	if(state == HDR_VALUE) {
31155714Skris		vtmp = strip_spaces(q);
312100928Snectar#if 0
31355714Skris		printf("%s=%s\n", ntmp, vtmp);
31455714Skris#endif
31555714Skris		if(!vtmp) {
31655714Skris			X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
31755714Skris			goto err;
31855714Skris		}
31955714Skris		X509V3_add_value(ntmp, vtmp, &values);
32055714Skris	} else {
32155714Skris		ntmp = strip_spaces(q);
322100928Snectar#if 0
32355714Skris		printf("%s\n", ntmp);
32455714Skris#endif
32555714Skris		if(!ntmp) {
32655714Skris			X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
32755714Skris			goto err;
32855714Skris		}
32955714Skris		X509V3_add_value(ntmp, NULL, &values);
33055714Skris	}
33168651SkrisOPENSSL_free(linebuf);
33255714Skrisreturn values;
33355714Skris
33455714Skriserr:
33568651SkrisOPENSSL_free(linebuf);
33655714Skrissk_CONF_VALUE_pop_free(values, X509V3_conf_free);
33755714Skrisreturn NULL;
33855714Skris
33955714Skris}
34055714Skris
34155714Skris/* Delete leading and trailing spaces from a string */
34255714Skrisstatic char *strip_spaces(char *name)
34355714Skris{
34455714Skris	char *p, *q;
34555714Skris	/* Skip over leading spaces */
34655714Skris	p = name;
34755714Skris	while(*p && isspace((unsigned char)*p)) p++;
34855714Skris	if(!*p) return NULL;
34955714Skris	q = p + strlen(p) - 1;
35055714Skris	while((q != p) && isspace((unsigned char)*q)) q--;
35155714Skris	if(p != q) q[1] = 0;
35255714Skris	if(!*p) return NULL;
35355714Skris	return p;
35455714Skris}
35555714Skris
35655714Skris/* hex string utilities */
35755714Skris
35868651Skris/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
35955714Skris * hex representation
36068651Skris * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
36155714Skris */
36255714Skris
36355714Skrischar *hex_to_string(unsigned char *buffer, long len)
36455714Skris{
36555714Skris	char *tmp, *q;
36655714Skris	unsigned char *p;
36755714Skris	int i;
368167612Ssimon	const static char hexdig[] = "0123456789ABCDEF";
36955714Skris	if(!buffer || !len) return NULL;
37068651Skris	if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
37155714Skris		X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE);
37255714Skris		return NULL;
37355714Skris	}
37455714Skris	q = tmp;
37555714Skris	for(i = 0, p = buffer; i < len; i++,p++) {
37655714Skris		*q++ = hexdig[(*p >> 4) & 0xf];
37755714Skris		*q++ = hexdig[*p & 0xf];
37855714Skris		*q++ = ':';
37955714Skris	}
38055714Skris	q[-1] = 0;
38168651Skris#ifdef CHARSET_EBCDIC
38268651Skris	ebcdic2ascii(tmp, tmp, q - tmp - 1);
38368651Skris#endif
38468651Skris
38555714Skris	return tmp;
38655714Skris}
38755714Skris
38855714Skris/* Give a string of hex digits convert to
38955714Skris * a buffer
39055714Skris */
39155714Skris
39255714Skrisunsigned char *string_to_hex(char *str, long *len)
39355714Skris{
39455714Skris	unsigned char *hexbuf, *q;
39555714Skris	unsigned char ch, cl, *p;
39655714Skris	if(!str) {
39755714Skris		X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT);
39855714Skris		return NULL;
39955714Skris	}
40068651Skris	if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
40155714Skris	for(p = (unsigned char *)str, q = hexbuf; *p;) {
40255714Skris		ch = *p++;
40368651Skris#ifdef CHARSET_EBCDIC
40468651Skris		ch = os_toebcdic[ch];
40568651Skris#endif
40655714Skris		if(ch == ':') continue;
40755714Skris		cl = *p++;
40868651Skris#ifdef CHARSET_EBCDIC
40968651Skris		cl = os_toebcdic[cl];
41068651Skris#endif
41155714Skris		if(!cl) {
41255714Skris			X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS);
41368651Skris			OPENSSL_free(hexbuf);
41455714Skris			return NULL;
41555714Skris		}
41655714Skris		if(isupper(ch)) ch = tolower(ch);
41755714Skris		if(isupper(cl)) cl = tolower(cl);
41855714Skris
41955714Skris		if((ch >= '0') && (ch <= '9')) ch -= '0';
42055714Skris		else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
42155714Skris		else goto badhex;
42255714Skris
42355714Skris		if((cl >= '0') && (cl <= '9')) cl -= '0';
42455714Skris		else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
42555714Skris		else goto badhex;
42655714Skris
42755714Skris		*q++ = (ch << 4) | cl;
42855714Skris	}
42955714Skris
43055714Skris	if(len) *len = q - hexbuf;
43155714Skris
43255714Skris	return hexbuf;
43355714Skris
43455714Skris	err:
43568651Skris	if(hexbuf) OPENSSL_free(hexbuf);
43655714Skris	X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE);
43755714Skris	return NULL;
43855714Skris
43955714Skris	badhex:
44068651Skris	OPENSSL_free(hexbuf);
44155714Skris	X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT);
44255714Skris	return NULL;
44355714Skris
44455714Skris}
44555714Skris
44655714Skris/* V2I name comparison function: returns zero if 'name' matches
44755714Skris * cmp or cmp.*
44855714Skris */
44955714Skris
45055714Skrisint name_cmp(const char *name, const char *cmp)
45155714Skris{
45255714Skris	int len, ret;
45355714Skris	char c;
45455714Skris	len = strlen(cmp);
45555714Skris	if((ret = strncmp(name, cmp, len))) return ret;
45655714Skris	c = name[len];
45755714Skris	if(!c || (c=='.')) return 0;
45855714Skris	return 1;
45955714Skris}
46068651Skris
46168651Skrisstatic int sk_strcmp(const char * const *a, const char * const *b)
46268651Skris{
46368651Skris	return strcmp(*a, *b);
46468651Skris}
46568651Skris
46668651SkrisSTACK *X509_get1_email(X509 *x)
46768651Skris{
468109998Smarkm	GENERAL_NAMES *gens;
46968651Skris	STACK *ret;
47068651Skris	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
47168651Skris	ret = get_email(X509_get_subject_name(x), gens);
47268651Skris	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
47368651Skris	return ret;
47468651Skris}
47568651Skris
47668651SkrisSTACK *X509_REQ_get1_email(X509_REQ *x)
47768651Skris{
478109998Smarkm	GENERAL_NAMES *gens;
47968651Skris	STACK_OF(X509_EXTENSION) *exts;
48068651Skris	STACK *ret;
48168651Skris	exts = X509_REQ_get_extensions(x);
48268651Skris	gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
48368651Skris	ret = get_email(X509_REQ_get_subject_name(x), gens);
48468651Skris	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
48568651Skris	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
48668651Skris	return ret;
48768651Skris}
48868651Skris
48968651Skris
490109998Smarkmstatic STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens)
49168651Skris{
49268651Skris	STACK *ret = NULL;
49368651Skris	X509_NAME_ENTRY *ne;
49468651Skris	ASN1_IA5STRING *email;
49568651Skris	GENERAL_NAME *gen;
49668651Skris	int i;
49768651Skris	/* Now add any email address(es) to STACK */
49868651Skris	i = -1;
49968651Skris	/* First supplied X509_NAME */
50068651Skris	while((i = X509_NAME_get_index_by_NID(name,
501109998Smarkm					 NID_pkcs9_emailAddress, i)) >= 0) {
50268651Skris		ne = X509_NAME_get_entry(name, i);
50368651Skris		email = X509_NAME_ENTRY_get_data(ne);
50468651Skris		if(!append_ia5(&ret, email)) return NULL;
50568651Skris	}
50668651Skris	for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
50768651Skris	{
50868651Skris		gen = sk_GENERAL_NAME_value(gens, i);
50968651Skris		if(gen->type != GEN_EMAIL) continue;
51068651Skris		if(!append_ia5(&ret, gen->d.ia5)) return NULL;
51168651Skris	}
51268651Skris	return ret;
51368651Skris}
51468651Skris
51568651Skrisstatic void str_free(void *str)
51668651Skris{
51768651Skris	OPENSSL_free(str);
51868651Skris}
51968651Skris
52068651Skrisstatic int append_ia5(STACK **sk, ASN1_IA5STRING *email)
52168651Skris{
52268651Skris	char *emtmp;
52368651Skris	/* First some sanity checks */
52468651Skris	if(email->type != V_ASN1_IA5STRING) return 1;
52568651Skris	if(!email->data || !email->length) return 1;
52668651Skris	if(!*sk) *sk = sk_new(sk_strcmp);
52768651Skris	if(!*sk) return 0;
52868651Skris	/* Don't add duplicates */
52968651Skris	if(sk_find(*sk, (char *)email->data) != -1) return 1;
53068651Skris	emtmp = BUF_strdup((char *)email->data);
53168651Skris	if(!emtmp || !sk_push(*sk, emtmp)) {
53268651Skris		X509_email_free(*sk);
53368651Skris		*sk = NULL;
53468651Skris		return 0;
53568651Skris	}
53668651Skris	return 1;
53768651Skris}
53868651Skris
53968651Skrisvoid X509_email_free(STACK *sk)
54068651Skris{
54168651Skris	sk_pop_free(sk, str_free);
54268651Skris}
543160814Ssimon
544160814Ssimon/* Convert IP addresses both IPv4 and IPv6 into an
545160814Ssimon * OCTET STRING compatible with RFC3280.
546160814Ssimon */
547160814Ssimon
548160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
549160814Ssimon	{
550160814Ssimon	unsigned char ipout[16];
551160814Ssimon	ASN1_OCTET_STRING *ret;
552160814Ssimon	int iplen;
553160814Ssimon
554160814Ssimon	/* If string contains a ':' assume IPv6 */
555160814Ssimon
556160814Ssimon	iplen = a2i_ipadd(ipout, ipasc);
557160814Ssimon
558160814Ssimon	if (!iplen)
559160814Ssimon		return NULL;
560160814Ssimon
561160814Ssimon	ret = ASN1_OCTET_STRING_new();
562160814Ssimon	if (!ret)
563160814Ssimon		return NULL;
564160814Ssimon	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen))
565160814Ssimon		{
566160814Ssimon		ASN1_OCTET_STRING_free(ret);
567160814Ssimon		return NULL;
568160814Ssimon		}
569160814Ssimon	return ret;
570160814Ssimon	}
571160814Ssimon
572160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
573160814Ssimon	{
574160814Ssimon	ASN1_OCTET_STRING *ret = NULL;
575160814Ssimon	unsigned char ipout[32];
576160814Ssimon	char *iptmp = NULL, *p;
577160814Ssimon	int iplen1, iplen2;
578160814Ssimon	p = strchr(ipasc,'/');
579160814Ssimon	if (!p)
580160814Ssimon		return NULL;
581160814Ssimon	iptmp = BUF_strdup(ipasc);
582160814Ssimon	if (!iptmp)
583160814Ssimon		return NULL;
584160814Ssimon	p = iptmp + (p - ipasc);
585160814Ssimon	*p++ = 0;
586160814Ssimon
587160814Ssimon	iplen1 = a2i_ipadd(ipout, iptmp);
588160814Ssimon
589160814Ssimon	if (!iplen1)
590160814Ssimon		goto err;
591160814Ssimon
592160814Ssimon	iplen2 = a2i_ipadd(ipout + iplen1, p);
593160814Ssimon
594160814Ssimon	OPENSSL_free(iptmp);
595160814Ssimon	iptmp = NULL;
596160814Ssimon
597160814Ssimon	if (!iplen2 || (iplen1 != iplen2))
598160814Ssimon		goto err;
599160814Ssimon
600160814Ssimon	ret = ASN1_OCTET_STRING_new();
601160814Ssimon	if (!ret)
602160814Ssimon		goto err;
603160814Ssimon	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
604160814Ssimon		goto err;
605160814Ssimon
606160814Ssimon	return ret;
607160814Ssimon
608160814Ssimon	err:
609160814Ssimon	if (iptmp)
610160814Ssimon		OPENSSL_free(iptmp);
611160814Ssimon	if (ret)
612160814Ssimon		ASN1_OCTET_STRING_free(ret);
613160814Ssimon	return NULL;
614160814Ssimon	}
615160814Ssimon
616160814Ssimon
617167612Ssimonint a2i_ipadd(unsigned char *ipout, const char *ipasc)
618160814Ssimon	{
619160814Ssimon	/* If string contains a ':' assume IPv6 */
620160814Ssimon
621160814Ssimon	if (strchr(ipasc, ':'))
622160814Ssimon		{
623160814Ssimon		if (!ipv6_from_asc(ipout, ipasc))
624160814Ssimon			return 0;
625160814Ssimon		return 16;
626160814Ssimon		}
627160814Ssimon	else
628160814Ssimon		{
629160814Ssimon		if (!ipv4_from_asc(ipout, ipasc))
630160814Ssimon			return 0;
631160814Ssimon		return 4;
632160814Ssimon		}
633160814Ssimon	}
634160814Ssimon
635160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in)
636160814Ssimon	{
637160814Ssimon	int a0, a1, a2, a3;
638160814Ssimon	if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
639160814Ssimon		return 0;
640160814Ssimon	if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
641160814Ssimon		|| (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
642160814Ssimon		return 0;
643160814Ssimon	v4[0] = a0;
644160814Ssimon	v4[1] = a1;
645160814Ssimon	v4[2] = a2;
646160814Ssimon	v4[3] = a3;
647160814Ssimon	return 1;
648160814Ssimon	}
649160814Ssimon
650160814Ssimontypedef struct {
651160814Ssimon		/* Temporary store for IPV6 output */
652160814Ssimon		unsigned char tmp[16];
653160814Ssimon		/* Total number of bytes in tmp */
654160814Ssimon		int total;
655160814Ssimon		/* The position of a zero (corresponding to '::') */
656160814Ssimon		int zero_pos;
657160814Ssimon		/* Number of zeroes */
658160814Ssimon		int zero_cnt;
659160814Ssimon	} IPV6_STAT;
660160814Ssimon
661160814Ssimon
662160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in)
663160814Ssimon	{
664160814Ssimon	IPV6_STAT v6stat;
665160814Ssimon	v6stat.total = 0;
666160814Ssimon	v6stat.zero_pos = -1;
667160814Ssimon	v6stat.zero_cnt = 0;
668160814Ssimon	/* Treat the IPv6 representation as a list of values
669160814Ssimon	 * separated by ':'. The presence of a '::' will parse
670160814Ssimon 	 * as one, two or three zero length elements.
671160814Ssimon	 */
672160814Ssimon	if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
673160814Ssimon		return 0;
674160814Ssimon
675160814Ssimon	/* Now for some sanity checks */
676160814Ssimon
677160814Ssimon	if (v6stat.zero_pos == -1)
678160814Ssimon		{
679160814Ssimon		/* If no '::' must have exactly 16 bytes */
680160814Ssimon		if (v6stat.total != 16)
681160814Ssimon			return 0;
682160814Ssimon		}
683160814Ssimon	else
684160814Ssimon		{
685160814Ssimon		/* If '::' must have less than 16 bytes */
686160814Ssimon		if (v6stat.total == 16)
687160814Ssimon			return 0;
688160814Ssimon		/* More than three zeroes is an error */
689160814Ssimon		if (v6stat.zero_cnt > 3)
690160814Ssimon			return 0;
691160814Ssimon		/* Can only have three zeroes if nothing else present */
692160814Ssimon		else if (v6stat.zero_cnt == 3)
693160814Ssimon			{
694160814Ssimon			if (v6stat.total > 0)
695160814Ssimon				return 0;
696160814Ssimon			}
697160814Ssimon		/* Can only have two zeroes if at start or end */
698160814Ssimon		else if (v6stat.zero_cnt == 2)
699160814Ssimon			{
700160814Ssimon			if ((v6stat.zero_pos != 0)
701160814Ssimon				&& (v6stat.zero_pos != v6stat.total))
702160814Ssimon				return 0;
703160814Ssimon			}
704160814Ssimon		else
705160814Ssimon		/* Can only have one zero if *not* start or end */
706160814Ssimon			{
707160814Ssimon			if ((v6stat.zero_pos == 0)
708160814Ssimon				|| (v6stat.zero_pos == v6stat.total))
709160814Ssimon				return 0;
710160814Ssimon			}
711160814Ssimon		}
712160814Ssimon
713160814Ssimon	/* Format result */
714160814Ssimon
715160814Ssimon	/* Copy initial part */
716160814Ssimon	if (v6stat.zero_pos > 0)
717160814Ssimon		memcpy(v6, v6stat.tmp, v6stat.zero_pos);
718160814Ssimon	/* Zero middle */
719160814Ssimon	if (v6stat.total != 16)
720160814Ssimon		memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
721160814Ssimon	/* Copy final part */
722160814Ssimon	if (v6stat.total != v6stat.zero_pos)
723160814Ssimon		memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
724160814Ssimon			v6stat.tmp + v6stat.zero_pos,
725160814Ssimon			v6stat.total - v6stat.zero_pos);
726160814Ssimon
727160814Ssimon	return 1;
728160814Ssimon	}
729160814Ssimon
730160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr)
731160814Ssimon	{
732160814Ssimon	IPV6_STAT *s = usr;
733160814Ssimon	/* Error if 16 bytes written */
734160814Ssimon	if (s->total == 16)
735160814Ssimon		return 0;
736160814Ssimon	if (len == 0)
737160814Ssimon		{
738160814Ssimon		/* Zero length element, corresponds to '::' */
739160814Ssimon		if (s->zero_pos == -1)
740160814Ssimon			s->zero_pos = s->total;
741160814Ssimon		/* If we've already got a :: its an error */
742160814Ssimon		else if (s->zero_pos != s->total)
743160814Ssimon			return 0;
744160814Ssimon		s->zero_cnt++;
745160814Ssimon		}
746160814Ssimon	else
747160814Ssimon		{
748160814Ssimon		/* If more than 4 characters could be final a.b.c.d form */
749160814Ssimon		if (len > 4)
750160814Ssimon			{
751160814Ssimon			/* Need at least 4 bytes left */
752160814Ssimon			if (s->total > 12)
753160814Ssimon				return 0;
754160814Ssimon			/* Must be end of string */
755160814Ssimon			if (elem[len])
756160814Ssimon				return 0;
757160814Ssimon			if (!ipv4_from_asc(s->tmp + s->total, elem))
758160814Ssimon				return 0;
759160814Ssimon			s->total += 4;
760160814Ssimon			}
761160814Ssimon		else
762160814Ssimon			{
763160814Ssimon			if (!ipv6_hex(s->tmp + s->total, elem, len))
764160814Ssimon				return 0;
765160814Ssimon			s->total += 2;
766160814Ssimon			}
767160814Ssimon		}
768160814Ssimon	return 1;
769160814Ssimon	}
770160814Ssimon
771160814Ssimon/* Convert a string of up to 4 hex digits into the corresponding
772160814Ssimon * IPv6 form.
773160814Ssimon */
774160814Ssimon
775160814Ssimonstatic int ipv6_hex(unsigned char *out, const char *in, int inlen)
776160814Ssimon	{
777160814Ssimon	unsigned char c;
778160814Ssimon	unsigned int num = 0;
779160814Ssimon	if (inlen > 4)
780160814Ssimon		return 0;
781160814Ssimon	while(inlen--)
782160814Ssimon		{
783160814Ssimon		c = *in++;
784160814Ssimon		num <<= 4;
785160814Ssimon		if ((c >= '0') && (c <= '9'))
786160814Ssimon			num |= c - '0';
787160814Ssimon		else if ((c >= 'A') && (c <= 'F'))
788160814Ssimon			num |= c - 'A' + 10;
789160814Ssimon		else if ((c >= 'a') && (c <= 'f'))
790160814Ssimon			num |=  c - 'a' + 10;
791160814Ssimon		else
792160814Ssimon			return 0;
793160814Ssimon		}
794160814Ssimon	out[0] = num >> 8;
795160814Ssimon	out[1] = num & 0xff;
796160814Ssimon	return 1;
797160814Ssimon	}
798160814Ssimon
799160814Ssimon
800160814Ssimonint X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
801160814Ssimon						unsigned long chtype)
802160814Ssimon	{
803160814Ssimon	CONF_VALUE *v;
804160814Ssimon	int i, mval;
805160814Ssimon	char *p, *type;
806160814Ssimon	if (!nm)
807160814Ssimon		return 0;
808160814Ssimon
809160814Ssimon	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
810160814Ssimon		{
811160814Ssimon		v=sk_CONF_VALUE_value(dn_sk,i);
812160814Ssimon		type=v->name;
813160814Ssimon		/* Skip past any leading X. X: X, etc to allow for
814160814Ssimon		 * multiple instances
815160814Ssimon		 */
816160814Ssimon		for(p = type; *p ; p++)
817160814Ssimon#ifndef CHARSET_EBCDIC
818160814Ssimon			if ((*p == ':') || (*p == ',') || (*p == '.'))
819160814Ssimon#else
820160814Ssimon			if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.']))
821160814Ssimon#endif
822160814Ssimon				{
823160814Ssimon				p++;
824160814Ssimon				if(*p) type = p;
825160814Ssimon				break;
826160814Ssimon				}
827160814Ssimon#ifndef CHARSET_EBCDIC
828160814Ssimon		if (*type == '+')
829160814Ssimon#else
830160814Ssimon		if (*type == os_toascii['+'])
831160814Ssimon#endif
832160814Ssimon			{
833160814Ssimon			mval = -1;
834160814Ssimon			type++;
835160814Ssimon			}
836160814Ssimon		else
837160814Ssimon			mval = 0;
838160814Ssimon		if (!X509_NAME_add_entry_by_txt(nm,type, chtype,
839160814Ssimon				(unsigned char *) v->value,-1,-1,mval))
840160814Ssimon					return 0;
841160814Ssimon
842160814Ssimon		}
843160814Ssimon	return 1;
844160814Ssimon	}
845