os/ossrv/ssl/libcrypto/src/crypto/x509v3/v3_utl.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/* v3_utl.c */
sl@0
     2
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
sl@0
     3
 * project.
sl@0
     4
 */
sl@0
     5
/* ====================================================================
sl@0
     6
 * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
sl@0
     7
 *
sl@0
     8
 * Redistribution and use in source and binary forms, with or without
sl@0
     9
 * modification, are permitted provided that the following conditions
sl@0
    10
 * are met:
sl@0
    11
 *
sl@0
    12
 * 1. Redistributions of source code must retain the above copyright
sl@0
    13
 *    notice, this list of conditions and the following disclaimer. 
sl@0
    14
 *
sl@0
    15
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    16
 *    notice, this list of conditions and the following disclaimer in
sl@0
    17
 *    the documentation and/or other materials provided with the
sl@0
    18
 *    distribution.
sl@0
    19
 *
sl@0
    20
 * 3. All advertising materials mentioning features or use of this
sl@0
    21
 *    software must display the following acknowledgment:
sl@0
    22
 *    "This product includes software developed by the OpenSSL Project
sl@0
    23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
sl@0
    24
 *
sl@0
    25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
sl@0
    26
 *    endorse or promote products derived from this software without
sl@0
    27
 *    prior written permission. For written permission, please contact
sl@0
    28
 *    licensing@OpenSSL.org.
sl@0
    29
 *
sl@0
    30
 * 5. Products derived from this software may not be called "OpenSSL"
sl@0
    31
 *    nor may "OpenSSL" appear in their names without prior written
sl@0
    32
 *    permission of the OpenSSL Project.
sl@0
    33
 *
sl@0
    34
 * 6. Redistributions of any form whatsoever must retain the following
sl@0
    35
 *    acknowledgment:
sl@0
    36
 *    "This product includes software developed by the OpenSSL Project
sl@0
    37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
sl@0
    38
 *
sl@0
    39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
sl@0
    40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
sl@0
    42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
sl@0
    43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
sl@0
    44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
sl@0
    45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sl@0
    46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sl@0
    48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
sl@0
    49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
sl@0
    50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
sl@0
    51
 * ====================================================================
sl@0
    52
 *
sl@0
    53
 * This product includes cryptographic software written by Eric Young
sl@0
    54
 * (eay@cryptsoft.com).  This product includes software written by Tim
sl@0
    55
 * Hudson (tjh@cryptsoft.com).
sl@0
    56
 *
sl@0
    57
 */
sl@0
    58
 /*
sl@0
    59
 © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
sl@0
    60
 */
sl@0
    61
sl@0
    62
sl@0
    63
/* X509 v3 extension utilities */
sl@0
    64
sl@0
    65
sl@0
    66
#include <stdio.h>
sl@0
    67
#include <ctype.h>
sl@0
    68
#include "cryptlib.h"
sl@0
    69
#include <openssl/conf.h>
sl@0
    70
#include <openssl/x509v3.h>
sl@0
    71
#include <openssl/bn.h>
sl@0
    72
#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
sl@0
    73
#include "libcrypto_wsd_macros.h"
sl@0
    74
#include "libcrypto_wsd.h"
sl@0
    75
#endif
sl@0
    76
sl@0
    77
static char *strip_spaces(char *name);
sl@0
    78
static int sk_strcmp(const char * const *a, const char * const *b);
sl@0
    79
static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens);
sl@0
    80
static void str_free(void *str);
sl@0
    81
static int append_ia5(STACK **sk, ASN1_IA5STRING *email);
sl@0
    82
sl@0
    83
static int ipv4_from_asc(unsigned char *v4, const char *in);
sl@0
    84
static int ipv6_from_asc(unsigned char *v6, const char *in);
sl@0
    85
static int ipv6_cb(const char *elem, int len, void *usr);
sl@0
    86
static int ipv6_hex(unsigned char *out, const char *in, int inlen);
sl@0
    87
sl@0
    88
/* Add a CONF_VALUE name value pair to stack */
sl@0
    89
sl@0
    90
EXPORT_C int X509V3_add_value(const char *name, const char *value,
sl@0
    91
						STACK_OF(CONF_VALUE) **extlist)
sl@0
    92
{
sl@0
    93
	CONF_VALUE *vtmp = NULL;
sl@0
    94
	char *tname = NULL, *tvalue = NULL;
sl@0
    95
	if(name && !(tname = BUF_strdup(name))) goto err;
sl@0
    96
	if(value && !(tvalue = BUF_strdup(value))) goto err;;
sl@0
    97
	if(!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) goto err;
sl@0
    98
	if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err;
sl@0
    99
	vtmp->section = NULL;
sl@0
   100
	vtmp->name = tname;
sl@0
   101
	vtmp->value = tvalue;
sl@0
   102
	if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err;
sl@0
   103
	return 1;
sl@0
   104
	err:
sl@0
   105
	X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE);
sl@0
   106
	if(vtmp) OPENSSL_free(vtmp);
sl@0
   107
	if(tname) OPENSSL_free(tname);
sl@0
   108
	if(tvalue) OPENSSL_free(tvalue);
sl@0
   109
	return 0;
sl@0
   110
}
sl@0
   111
sl@0
   112
EXPORT_C int X509V3_add_value_uchar(const char *name, const unsigned char *value,
sl@0
   113
			   STACK_OF(CONF_VALUE) **extlist)
sl@0
   114
    {
sl@0
   115
    return X509V3_add_value(name,(const char *)value,extlist);
sl@0
   116
    }
sl@0
   117
sl@0
   118
/* Free function for STACK_OF(CONF_VALUE) */
sl@0
   119
sl@0
   120
EXPORT_C void X509V3_conf_free(CONF_VALUE *conf)
sl@0
   121
{
sl@0
   122
	if(!conf) return;
sl@0
   123
	if(conf->name) OPENSSL_free(conf->name);
sl@0
   124
	if(conf->value) OPENSSL_free(conf->value);
sl@0
   125
	if(conf->section) OPENSSL_free(conf->section);
sl@0
   126
	OPENSSL_free(conf);
sl@0
   127
}
sl@0
   128
sl@0
   129
EXPORT_C int X509V3_add_value_bool(const char *name, int asn1_bool,
sl@0
   130
						STACK_OF(CONF_VALUE) **extlist)
sl@0
   131
{
sl@0
   132
	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
sl@0
   133
	return X509V3_add_value(name, "FALSE", extlist);
sl@0
   134
}
sl@0
   135
sl@0
   136
EXPORT_C int X509V3_add_value_bool_nf(char *name, int asn1_bool,
sl@0
   137
						STACK_OF(CONF_VALUE) **extlist)
sl@0
   138
{
sl@0
   139
	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
sl@0
   140
	return 1;
sl@0
   141
}
sl@0
   142
sl@0
   143
sl@0
   144
EXPORT_C char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
sl@0
   145
{
sl@0
   146
	BIGNUM *bntmp = NULL;
sl@0
   147
	char *strtmp = NULL;
sl@0
   148
	if(!a) return NULL;
sl@0
   149
	if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
sl@0
   150
	    !(strtmp = BN_bn2dec(bntmp)) )
sl@0
   151
		X509V3err(X509V3_F_I2S_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE);
sl@0
   152
	BN_free(bntmp);
sl@0
   153
	return strtmp;
sl@0
   154
}
sl@0
   155
sl@0
   156
EXPORT_C char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
sl@0
   157
{
sl@0
   158
	BIGNUM *bntmp = NULL;
sl@0
   159
	char *strtmp = NULL;
sl@0
   160
	if(!a) return NULL;
sl@0
   161
	if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
sl@0
   162
	    !(strtmp = BN_bn2dec(bntmp)) )
sl@0
   163
		X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE);
sl@0
   164
	BN_free(bntmp);
sl@0
   165
	return strtmp;
sl@0
   166
}
sl@0
   167
sl@0
   168
EXPORT_C ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
sl@0
   169
{
sl@0
   170
	BIGNUM *bn = NULL;
sl@0
   171
	ASN1_INTEGER *aint;
sl@0
   172
	int isneg, ishex;
sl@0
   173
	int ret;
sl@0
   174
	if (!value) {
sl@0
   175
		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE);
sl@0
   176
		return 0;
sl@0
   177
	}
sl@0
   178
	bn = BN_new();
sl@0
   179
	if (value[0] == '-') {
sl@0
   180
		value++;
sl@0
   181
		isneg = 1;
sl@0
   182
	} else isneg = 0;
sl@0
   183
sl@0
   184
	if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
sl@0
   185
		value += 2;
sl@0
   186
		ishex = 1;
sl@0
   187
	} else ishex = 0;
sl@0
   188
sl@0
   189
	if (ishex) ret = BN_hex2bn(&bn, value);
sl@0
   190
	else ret = BN_dec2bn(&bn, value);
sl@0
   191
sl@0
   192
	if (!ret || value[ret]) {
sl@0
   193
		BN_free(bn);
sl@0
   194
		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR);
sl@0
   195
		return 0;
sl@0
   196
	}
sl@0
   197
sl@0
   198
	if (isneg && BN_is_zero(bn)) isneg = 0;
sl@0
   199
sl@0
   200
	aint = BN_to_ASN1_INTEGER(bn, NULL);
sl@0
   201
	BN_free(bn);
sl@0
   202
	if (!aint) {
sl@0
   203
		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
sl@0
   204
		return 0;
sl@0
   205
	}
sl@0
   206
	if (isneg) aint->type |= V_ASN1_NEG;
sl@0
   207
	return aint;
sl@0
   208
}
sl@0
   209
sl@0
   210
EXPORT_C int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
sl@0
   211
	     STACK_OF(CONF_VALUE) **extlist)
sl@0
   212
{
sl@0
   213
	char *strtmp;
sl@0
   214
	int ret;
sl@0
   215
	if(!aint) return 1;
sl@0
   216
	if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0;
sl@0
   217
	ret = X509V3_add_value(name, strtmp, extlist);
sl@0
   218
	OPENSSL_free(strtmp);
sl@0
   219
	return ret;
sl@0
   220
}
sl@0
   221
sl@0
   222
EXPORT_C int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
sl@0
   223
{
sl@0
   224
	char *btmp;
sl@0
   225
	if(!(btmp = value->value)) goto err;
sl@0
   226
	if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
sl@0
   227
		 || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
sl@0
   228
		|| !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
sl@0
   229
		*asn1_bool = 0xff;
sl@0
   230
		return 1;
sl@0
   231
	} else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
sl@0
   232
		 || !strcmp(btmp, "N") || !strcmp(btmp, "n")
sl@0
   233
		|| !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
sl@0
   234
		*asn1_bool = 0;
sl@0
   235
		return 1;
sl@0
   236
	}
sl@0
   237
	err:
sl@0
   238
	X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,X509V3_R_INVALID_BOOLEAN_STRING);
sl@0
   239
	X509V3_conf_err(value);
sl@0
   240
	return 0;
sl@0
   241
}
sl@0
   242
sl@0
   243
EXPORT_C int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
sl@0
   244
{
sl@0
   245
	ASN1_INTEGER *itmp;
sl@0
   246
	if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
sl@0
   247
		X509V3_conf_err(value);
sl@0
   248
		return 0;
sl@0
   249
	}
sl@0
   250
	*aint = itmp;
sl@0
   251
	return 1;
sl@0
   252
}
sl@0
   253
sl@0
   254
#define HDR_NAME	1
sl@0
   255
#define HDR_VALUE	2
sl@0
   256
sl@0
   257
/*#define DEBUG*/
sl@0
   258
sl@0
   259
EXPORT_C STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
sl@0
   260
{
sl@0
   261
	char *p, *q, c;
sl@0
   262
	char *ntmp, *vtmp;
sl@0
   263
	STACK_OF(CONF_VALUE) *values = NULL;
sl@0
   264
	char *linebuf;
sl@0
   265
	int state;
sl@0
   266
	/* We are going to modify the line so copy it first */
sl@0
   267
	linebuf = BUF_strdup(line);
sl@0
   268
	state = HDR_NAME;
sl@0
   269
	ntmp = NULL;
sl@0
   270
	/* Go through all characters */
sl@0
   271
	for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
sl@0
   272
sl@0
   273
		switch(state) {
sl@0
   274
			case HDR_NAME:
sl@0
   275
			if(c == ':') {
sl@0
   276
				state = HDR_VALUE;
sl@0
   277
				*p = 0;
sl@0
   278
				ntmp = strip_spaces(q);
sl@0
   279
				if(!ntmp) {
sl@0
   280
					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
sl@0
   281
					goto err;
sl@0
   282
				}
sl@0
   283
				q = p + 1;
sl@0
   284
			} else if(c == ',') {
sl@0
   285
				*p = 0;
sl@0
   286
				ntmp = strip_spaces(q);
sl@0
   287
				q = p + 1;
sl@0
   288
#if 0
sl@0
   289
				printf("%s\n", ntmp);
sl@0
   290
#endif
sl@0
   291
				if(!ntmp) {
sl@0
   292
					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
sl@0
   293
					goto err;
sl@0
   294
				}
sl@0
   295
				X509V3_add_value(ntmp, NULL, &values);
sl@0
   296
			}
sl@0
   297
			break ;
sl@0
   298
sl@0
   299
			case HDR_VALUE:
sl@0
   300
			if(c == ',') {
sl@0
   301
				state = HDR_NAME;
sl@0
   302
				*p = 0;
sl@0
   303
				vtmp = strip_spaces(q);
sl@0
   304
#if 0
sl@0
   305
				printf("%s\n", ntmp);
sl@0
   306
#endif
sl@0
   307
				if(!vtmp) {
sl@0
   308
					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
sl@0
   309
					goto err;
sl@0
   310
				}
sl@0
   311
				X509V3_add_value(ntmp, vtmp, &values);
sl@0
   312
				ntmp = NULL;
sl@0
   313
				q = p + 1;
sl@0
   314
			}
sl@0
   315
sl@0
   316
		}
sl@0
   317
	}
sl@0
   318
sl@0
   319
	if(state == HDR_VALUE) {
sl@0
   320
		vtmp = strip_spaces(q);
sl@0
   321
#if 0
sl@0
   322
		printf("%s=%s\n", ntmp, vtmp);
sl@0
   323
#endif
sl@0
   324
		if(!vtmp) {
sl@0
   325
			X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
sl@0
   326
			goto err;
sl@0
   327
		}
sl@0
   328
		X509V3_add_value(ntmp, vtmp, &values);
sl@0
   329
	} else {
sl@0
   330
		ntmp = strip_spaces(q);
sl@0
   331
#if 0
sl@0
   332
		printf("%s\n", ntmp);
sl@0
   333
#endif
sl@0
   334
		if(!ntmp) {
sl@0
   335
			X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
sl@0
   336
			goto err;
sl@0
   337
		}
sl@0
   338
		X509V3_add_value(ntmp, NULL, &values);
sl@0
   339
	}
sl@0
   340
OPENSSL_free(linebuf);
sl@0
   341
return values;
sl@0
   342
sl@0
   343
err:
sl@0
   344
OPENSSL_free(linebuf);
sl@0
   345
sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
sl@0
   346
return NULL;
sl@0
   347
sl@0
   348
}
sl@0
   349
sl@0
   350
/* Delete leading and trailing spaces from a string */
sl@0
   351
static char *strip_spaces(char *name)
sl@0
   352
{
sl@0
   353
	char *p, *q;
sl@0
   354
	/* Skip over leading spaces */
sl@0
   355
	p = name;
sl@0
   356
	while(*p && isspace((unsigned char)*p)) p++;
sl@0
   357
	if(!*p) return NULL;
sl@0
   358
	q = p + strlen(p) - 1;
sl@0
   359
	while((q != p) && isspace((unsigned char)*q)) q--;
sl@0
   360
	if(p != q) q[1] = 0;
sl@0
   361
	if(!*p) return NULL;
sl@0
   362
	return p;
sl@0
   363
}
sl@0
   364
sl@0
   365
/* hex string utilities */
sl@0
   366
sl@0
   367
/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
sl@0
   368
 * hex representation
sl@0
   369
 * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
sl@0
   370
 */
sl@0
   371
 
sl@0
   372
sl@0
   373
EXPORT_C char *hex_to_string(unsigned char *buffer, long len)
sl@0
   374
{
sl@0
   375
	char *tmp, *q;
sl@0
   376
	unsigned char *p;
sl@0
   377
	int i;
sl@0
   378
#ifndef EMULATOR	
sl@0
   379
	static char hexdig[] = "0123456789ABCDEF";
sl@0
   380
#else
sl@0
   381
    static const char hexdig[] = "0123456789ABCDEF";
sl@0
   382
#endif	
sl@0
   383
	if(!buffer || !len) return NULL;
sl@0
   384
	if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
sl@0
   385
		X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE);
sl@0
   386
		return NULL;
sl@0
   387
	}
sl@0
   388
	q = tmp;
sl@0
   389
	for(i = 0, p = buffer; i < len; i++,p++) {
sl@0
   390
		*q++ = hexdig[(*p >> 4) & 0xf];
sl@0
   391
		*q++ = hexdig[*p & 0xf];
sl@0
   392
		*q++ = ':';
sl@0
   393
	}
sl@0
   394
	q[-1] = 0;
sl@0
   395
#ifdef CHARSET_EBCDIC
sl@0
   396
	ebcdic2ascii(tmp, tmp, q - tmp - 1);
sl@0
   397
#endif
sl@0
   398
sl@0
   399
	return tmp;
sl@0
   400
}
sl@0
   401
sl@0
   402
/* Give a string of hex digits convert to
sl@0
   403
 * a buffer
sl@0
   404
 */
sl@0
   405
sl@0
   406
EXPORT_C unsigned char *string_to_hex(char *str, long *len)
sl@0
   407
{
sl@0
   408
	unsigned char *hexbuf, *q;
sl@0
   409
	unsigned char ch, cl, *p;
sl@0
   410
	if(!str) {
sl@0
   411
		X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT);
sl@0
   412
		return NULL;
sl@0
   413
	}
sl@0
   414
	if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
sl@0
   415
	for(p = (unsigned char *)str, q = hexbuf; *p;) {
sl@0
   416
		ch = *p++;
sl@0
   417
#ifdef CHARSET_EBCDIC
sl@0
   418
		ch = os_toebcdic[ch];
sl@0
   419
#endif
sl@0
   420
		if(ch == ':') continue;
sl@0
   421
		cl = *p++;
sl@0
   422
#ifdef CHARSET_EBCDIC
sl@0
   423
		cl = os_toebcdic[cl];
sl@0
   424
#endif
sl@0
   425
		if(!cl) {
sl@0
   426
			X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS);
sl@0
   427
			OPENSSL_free(hexbuf);
sl@0
   428
			return NULL;
sl@0
   429
		}
sl@0
   430
		if(isupper(ch)) ch = tolower(ch);
sl@0
   431
		if(isupper(cl)) cl = tolower(cl);
sl@0
   432
sl@0
   433
		if((ch >= '0') && (ch <= '9')) ch -= '0';
sl@0
   434
		else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
sl@0
   435
		else goto badhex;
sl@0
   436
sl@0
   437
		if((cl >= '0') && (cl <= '9')) cl -= '0';
sl@0
   438
		else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
sl@0
   439
		else goto badhex;
sl@0
   440
sl@0
   441
		*q++ = (ch << 4) | cl;
sl@0
   442
	}
sl@0
   443
sl@0
   444
	if(len) *len = q - hexbuf;
sl@0
   445
sl@0
   446
	return hexbuf;
sl@0
   447
sl@0
   448
	err:
sl@0
   449
	if(hexbuf) OPENSSL_free(hexbuf);
sl@0
   450
	X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE);
sl@0
   451
	return NULL;
sl@0
   452
sl@0
   453
	badhex:
sl@0
   454
	OPENSSL_free(hexbuf);
sl@0
   455
	X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT);
sl@0
   456
	return NULL;
sl@0
   457
sl@0
   458
}
sl@0
   459
sl@0
   460
/* V2I name comparison function: returns zero if 'name' matches
sl@0
   461
 * cmp or cmp.*
sl@0
   462
 */
sl@0
   463
sl@0
   464
EXPORT_C int name_cmp(const char *name, const char *cmp)
sl@0
   465
{
sl@0
   466
	int len, ret;
sl@0
   467
	char c;
sl@0
   468
	len = strlen(cmp);
sl@0
   469
	if((ret = strncmp(name, cmp, len))) return ret;
sl@0
   470
	c = name[len];
sl@0
   471
	if(!c || (c=='.')) return 0;
sl@0
   472
	return 1;
sl@0
   473
}
sl@0
   474
sl@0
   475
static int sk_strcmp(const char * const *a, const char * const *b)
sl@0
   476
{
sl@0
   477
	return strcmp(*a, *b);
sl@0
   478
}
sl@0
   479
sl@0
   480
EXPORT_C STACK *X509_get1_email(X509 *x)
sl@0
   481
{
sl@0
   482
	GENERAL_NAMES *gens;
sl@0
   483
	STACK *ret;
sl@0
   484
	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
sl@0
   485
	ret = get_email(X509_get_subject_name(x), gens);
sl@0
   486
	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
sl@0
   487
	return ret;
sl@0
   488
}
sl@0
   489
sl@0
   490
EXPORT_C STACK *X509_REQ_get1_email(X509_REQ *x)
sl@0
   491
{
sl@0
   492
	GENERAL_NAMES *gens;
sl@0
   493
	STACK_OF(X509_EXTENSION) *exts;
sl@0
   494
	STACK *ret;
sl@0
   495
	exts = X509_REQ_get_extensions(x);
sl@0
   496
	gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
sl@0
   497
	ret = get_email(X509_REQ_get_subject_name(x), gens);
sl@0
   498
	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
sl@0
   499
	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
sl@0
   500
	return ret;
sl@0
   501
}
sl@0
   502
sl@0
   503
sl@0
   504
static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens)
sl@0
   505
{
sl@0
   506
	STACK *ret = NULL;
sl@0
   507
	X509_NAME_ENTRY *ne;
sl@0
   508
	ASN1_IA5STRING *email;
sl@0
   509
	GENERAL_NAME *gen;
sl@0
   510
	int i;
sl@0
   511
	/* Now add any email address(es) to STACK */
sl@0
   512
	i = -1;
sl@0
   513
	/* First supplied X509_NAME */
sl@0
   514
	while((i = X509_NAME_get_index_by_NID(name,
sl@0
   515
					 NID_pkcs9_emailAddress, i)) >= 0) {
sl@0
   516
		ne = X509_NAME_get_entry(name, i);
sl@0
   517
		email = X509_NAME_ENTRY_get_data(ne);
sl@0
   518
		if(!append_ia5(&ret, email)) return NULL;
sl@0
   519
	}
sl@0
   520
	for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
sl@0
   521
	{
sl@0
   522
		gen = sk_GENERAL_NAME_value(gens, i);
sl@0
   523
		if(gen->type != GEN_EMAIL) continue;
sl@0
   524
		if(!append_ia5(&ret, gen->d.ia5)) return NULL;
sl@0
   525
	}
sl@0
   526
	return ret;
sl@0
   527
}
sl@0
   528
sl@0
   529
static void str_free(void *str)
sl@0
   530
{
sl@0
   531
	OPENSSL_free(str);
sl@0
   532
}
sl@0
   533
sl@0
   534
static int append_ia5(STACK **sk, ASN1_IA5STRING *email)
sl@0
   535
{
sl@0
   536
	char *emtmp;
sl@0
   537
	/* First some sanity checks */
sl@0
   538
	if(email->type != V_ASN1_IA5STRING) return 1;
sl@0
   539
	if(!email->data || !email->length) return 1;
sl@0
   540
	if(!*sk) *sk = sk_new(sk_strcmp);
sl@0
   541
	if(!*sk) return 0;
sl@0
   542
	/* Don't add duplicates */
sl@0
   543
	if(sk_find(*sk, (char *)email->data) != -1) return 1;
sl@0
   544
	emtmp = BUF_strdup((char *)email->data);
sl@0
   545
	if(!emtmp || !sk_push(*sk, emtmp)) {
sl@0
   546
		X509_email_free(*sk);
sl@0
   547
		*sk = NULL;
sl@0
   548
		return 0;
sl@0
   549
	}
sl@0
   550
	return 1;
sl@0
   551
}
sl@0
   552
sl@0
   553
EXPORT_C void X509_email_free(STACK *sk)
sl@0
   554
{
sl@0
   555
	sk_pop_free(sk, str_free);
sl@0
   556
}
sl@0
   557
sl@0
   558
/* Convert IP addresses both IPv4 and IPv6 into an 
sl@0
   559
 * OCTET STRING compatible with RFC3280.
sl@0
   560
 */
sl@0
   561
sl@0
   562
EXPORT_C ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
sl@0
   563
	{
sl@0
   564
	unsigned char ipout[16];
sl@0
   565
	ASN1_OCTET_STRING *ret;
sl@0
   566
	int iplen;
sl@0
   567
sl@0
   568
	/* If string contains a ':' assume IPv6 */
sl@0
   569
sl@0
   570
	iplen = a2i_ipadd(ipout, ipasc);
sl@0
   571
sl@0
   572
	if (!iplen)
sl@0
   573
		return NULL;
sl@0
   574
sl@0
   575
	ret = ASN1_OCTET_STRING_new();
sl@0
   576
	if (!ret)
sl@0
   577
		return NULL;
sl@0
   578
	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen))
sl@0
   579
		{
sl@0
   580
		ASN1_OCTET_STRING_free(ret);
sl@0
   581
		return NULL;
sl@0
   582
		}
sl@0
   583
	return ret;
sl@0
   584
	}
sl@0
   585
sl@0
   586
EXPORT_C ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
sl@0
   587
	{
sl@0
   588
	ASN1_OCTET_STRING *ret = NULL;
sl@0
   589
	unsigned char ipout[32];
sl@0
   590
	char *iptmp = NULL, *p;
sl@0
   591
	int iplen1, iplen2;
sl@0
   592
	p = strchr(ipasc,'/');
sl@0
   593
	if (!p)
sl@0
   594
		return NULL;
sl@0
   595
	iptmp = BUF_strdup(ipasc);
sl@0
   596
	if (!iptmp)
sl@0
   597
		return NULL;
sl@0
   598
	p = iptmp + (p - ipasc);
sl@0
   599
	*p++ = 0;
sl@0
   600
sl@0
   601
	iplen1 = a2i_ipadd(ipout, iptmp);
sl@0
   602
sl@0
   603
	if (!iplen1)
sl@0
   604
		goto err;
sl@0
   605
sl@0
   606
	iplen2 = a2i_ipadd(ipout + iplen1, p);
sl@0
   607
sl@0
   608
	OPENSSL_free(iptmp);
sl@0
   609
	iptmp = NULL;
sl@0
   610
sl@0
   611
	if (!iplen2 || (iplen1 != iplen2))
sl@0
   612
		goto err;
sl@0
   613
sl@0
   614
	ret = ASN1_OCTET_STRING_new();
sl@0
   615
	if (!ret)
sl@0
   616
		goto err;
sl@0
   617
	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
sl@0
   618
		goto err;
sl@0
   619
sl@0
   620
	return ret;
sl@0
   621
sl@0
   622
	err:
sl@0
   623
	if (iptmp)
sl@0
   624
		OPENSSL_free(iptmp);
sl@0
   625
	if (ret)
sl@0
   626
		ASN1_OCTET_STRING_free(ret);
sl@0
   627
	return NULL;
sl@0
   628
	}
sl@0
   629
	
sl@0
   630
sl@0
   631
EXPORT_C int a2i_ipadd(unsigned char *ipout, const char *ipasc)
sl@0
   632
	{
sl@0
   633
	/* If string contains a ':' assume IPv6 */
sl@0
   634
sl@0
   635
	if (strchr(ipasc, ':'))
sl@0
   636
		{
sl@0
   637
		if (!ipv6_from_asc(ipout, ipasc))
sl@0
   638
			return 0;
sl@0
   639
		return 16;
sl@0
   640
		}
sl@0
   641
	else
sl@0
   642
		{
sl@0
   643
		if (!ipv4_from_asc(ipout, ipasc))
sl@0
   644
			return 0;
sl@0
   645
		return 4;
sl@0
   646
		}
sl@0
   647
	}
sl@0
   648
sl@0
   649
static int ipv4_from_asc(unsigned char *v4, const char *in)
sl@0
   650
	{
sl@0
   651
	int a0, a1, a2, a3;
sl@0
   652
	if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
sl@0
   653
		return 0;
sl@0
   654
	if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
sl@0
   655
		|| (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
sl@0
   656
		return 0;
sl@0
   657
	v4[0] = a0;
sl@0
   658
	v4[1] = a1;
sl@0
   659
	v4[2] = a2;
sl@0
   660
	v4[3] = a3;
sl@0
   661
	return 1;
sl@0
   662
	}
sl@0
   663
sl@0
   664
typedef struct {
sl@0
   665
		/* Temporary store for IPV6 output */
sl@0
   666
		unsigned char tmp[16];
sl@0
   667
		/* Total number of bytes in tmp */
sl@0
   668
		int total;
sl@0
   669
		/* The position of a zero (corresponding to '::') */
sl@0
   670
		int zero_pos;
sl@0
   671
		/* Number of zeroes */
sl@0
   672
		int zero_cnt;
sl@0
   673
	} IPV6_STAT;
sl@0
   674
sl@0
   675
sl@0
   676
static int ipv6_from_asc(unsigned char *v6, const char *in)
sl@0
   677
	{
sl@0
   678
	IPV6_STAT v6stat;
sl@0
   679
	v6stat.total = 0;
sl@0
   680
	v6stat.zero_pos = -1;
sl@0
   681
	v6stat.zero_cnt = 0;
sl@0
   682
	/* Treat the IPv6 representation as a list of values
sl@0
   683
	 * separated by ':'. The presence of a '::' will parse
sl@0
   684
 	 * as one, two or three zero length elements.
sl@0
   685
	 */
sl@0
   686
	if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
sl@0
   687
		return 0;
sl@0
   688
sl@0
   689
	/* Now for some sanity checks */
sl@0
   690
sl@0
   691
	if (v6stat.zero_pos == -1)
sl@0
   692
		{
sl@0
   693
		/* If no '::' must have exactly 16 bytes */
sl@0
   694
		if (v6stat.total != 16)
sl@0
   695
			return 0;
sl@0
   696
		}
sl@0
   697
	else 
sl@0
   698
		{
sl@0
   699
		/* If '::' must have less than 16 bytes */
sl@0
   700
		if (v6stat.total == 16)
sl@0
   701
			return 0;
sl@0
   702
		/* More than three zeroes is an error */
sl@0
   703
		if (v6stat.zero_cnt > 3)
sl@0
   704
			return 0;
sl@0
   705
		/* Can only have three zeroes if nothing else present */
sl@0
   706
		else if (v6stat.zero_cnt == 3)
sl@0
   707
			{
sl@0
   708
			if (v6stat.total > 0)
sl@0
   709
				return 0;
sl@0
   710
			}
sl@0
   711
		/* Can only have two zeroes if at start or end */
sl@0
   712
		else if (v6stat.zero_cnt == 2)
sl@0
   713
			{
sl@0
   714
			if ((v6stat.zero_pos != 0)
sl@0
   715
				&& (v6stat.zero_pos != v6stat.total))
sl@0
   716
				return 0;
sl@0
   717
			}
sl@0
   718
		else 
sl@0
   719
		/* Can only have one zero if *not* start or end */
sl@0
   720
			{
sl@0
   721
			if ((v6stat.zero_pos == 0)
sl@0
   722
				|| (v6stat.zero_pos == v6stat.total))
sl@0
   723
				return 0;
sl@0
   724
			}
sl@0
   725
		}
sl@0
   726
sl@0
   727
	/* Format result */
sl@0
   728
sl@0
   729
	/* Copy initial part */
sl@0
   730
	if (v6stat.zero_pos > 0)
sl@0
   731
		memcpy(v6, v6stat.tmp, v6stat.zero_pos);
sl@0
   732
	/* Zero middle */
sl@0
   733
	if (v6stat.total != 16)
sl@0
   734
		memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
sl@0
   735
	/* Copy final part */
sl@0
   736
	if (v6stat.total != v6stat.zero_pos)
sl@0
   737
		memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
sl@0
   738
			v6stat.tmp + v6stat.zero_pos,
sl@0
   739
			v6stat.total - v6stat.zero_pos);
sl@0
   740
sl@0
   741
	return 1;
sl@0
   742
	}
sl@0
   743
sl@0
   744
static int ipv6_cb(const char *elem, int len, void *usr)
sl@0
   745
	{
sl@0
   746
	IPV6_STAT *s = usr;
sl@0
   747
	/* Error if 16 bytes written */
sl@0
   748
	if (s->total == 16)
sl@0
   749
		return 0;
sl@0
   750
	if (len == 0)
sl@0
   751
		{
sl@0
   752
		/* Zero length element, corresponds to '::' */
sl@0
   753
		if (s->zero_pos == -1)
sl@0
   754
			s->zero_pos = s->total;
sl@0
   755
		/* If we've already got a :: its an error */
sl@0
   756
		else if (s->zero_pos != s->total)
sl@0
   757
			return 0;
sl@0
   758
		s->zero_cnt++;
sl@0
   759
		}
sl@0
   760
	else 
sl@0
   761
		{
sl@0
   762
		/* If more than 4 characters could be final a.b.c.d form */
sl@0
   763
		if (len > 4)
sl@0
   764
			{
sl@0
   765
			/* Need at least 4 bytes left */
sl@0
   766
			if (s->total > 12)
sl@0
   767
				return 0;
sl@0
   768
			/* Must be end of string */
sl@0
   769
			if (elem[len])
sl@0
   770
				return 0;
sl@0
   771
			if (!ipv4_from_asc(s->tmp + s->total, elem))
sl@0
   772
				return 0;
sl@0
   773
			s->total += 4;
sl@0
   774
			}
sl@0
   775
		else
sl@0
   776
			{
sl@0
   777
			if (!ipv6_hex(s->tmp + s->total, elem, len))
sl@0
   778
				return 0;
sl@0
   779
			s->total += 2;
sl@0
   780
			}
sl@0
   781
		}
sl@0
   782
	return 1;
sl@0
   783
	}
sl@0
   784
sl@0
   785
/* Convert a string of up to 4 hex digits into the corresponding
sl@0
   786
 * IPv6 form.
sl@0
   787
 */
sl@0
   788
sl@0
   789
static int ipv6_hex(unsigned char *out, const char *in, int inlen)
sl@0
   790
	{
sl@0
   791
	unsigned char c;
sl@0
   792
	unsigned int num = 0;
sl@0
   793
	if (inlen > 4)
sl@0
   794
		return 0;
sl@0
   795
	while(inlen--)
sl@0
   796
		{
sl@0
   797
		c = *in++;
sl@0
   798
		num <<= 4;
sl@0
   799
		if ((c >= '0') && (c <= '9'))
sl@0
   800
			num |= c - '0';
sl@0
   801
		else if ((c >= 'A') && (c <= 'F'))
sl@0
   802
			num |= c - 'A' + 10;
sl@0
   803
		else if ((c >= 'a') && (c <= 'f'))
sl@0
   804
			num |=  c - 'a' + 10;
sl@0
   805
		else
sl@0
   806
			return 0;
sl@0
   807
		}
sl@0
   808
	out[0] = num >> 8;
sl@0
   809
	out[1] = num & 0xff;
sl@0
   810
	return 1;
sl@0
   811
	}
sl@0
   812
sl@0
   813
sl@0
   814
EXPORT_C int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
sl@0
   815
						unsigned long chtype)
sl@0
   816
	{
sl@0
   817
	CONF_VALUE *v;
sl@0
   818
	int i, mval;
sl@0
   819
	char *p, *type;
sl@0
   820
	if (!nm)
sl@0
   821
		return 0;
sl@0
   822
sl@0
   823
	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
sl@0
   824
		{
sl@0
   825
		v=sk_CONF_VALUE_value(dn_sk,i);
sl@0
   826
		type=v->name;
sl@0
   827
		/* Skip past any leading X. X: X, etc to allow for
sl@0
   828
		 * multiple instances 
sl@0
   829
		 */
sl@0
   830
		for(p = type; *p ; p++) 
sl@0
   831
#ifndef CHARSET_EBCDIC
sl@0
   832
			if ((*p == ':') || (*p == ',') || (*p == '.'))
sl@0
   833
#else
sl@0
   834
			if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.']))
sl@0
   835
#endif
sl@0
   836
				{
sl@0
   837
				p++;
sl@0
   838
				if(*p) type = p;
sl@0
   839
				break;
sl@0
   840
				}
sl@0
   841
#ifndef CHARSET_EBCDIC
sl@0
   842
		if (*type == '+')
sl@0
   843
#else
sl@0
   844
		if (*type == os_toascii['+'])
sl@0
   845
#endif
sl@0
   846
			{
sl@0
   847
			mval = -1;
sl@0
   848
			type++;
sl@0
   849
			}
sl@0
   850
		else
sl@0
   851
			mval = 0;
sl@0
   852
		if (!X509_NAME_add_entry_by_txt(nm,type, chtype,
sl@0
   853
				(unsigned char *) v->value,-1,-1,mval))
sl@0
   854
					return 0;
sl@0
   855
sl@0
   856
		}
sl@0
   857
	return 1;
sl@0
   858
	}