os/ossrv/ssl/tsrc/topenssl/src/apps.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/ssl/tsrc/topenssl/src/apps.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,2337 @@
     1.4 +/* apps/apps.c */
     1.5 +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
     1.6 + * All rights reserved.
     1.7 + *
     1.8 + * This package is an SSL implementation written
     1.9 + * by Eric Young (eay@cryptsoft.com).
    1.10 + * The implementation was written so as to conform with Netscapes SSL.
    1.11 + * 
    1.12 + * This library is free for commercial and non-commercial use as long as
    1.13 + * the following conditions are aheared to.  The following conditions
    1.14 + * apply to all code found in this distribution, be it the RC4, RSA,
    1.15 + * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
    1.16 + * included with this distribution is covered by the same copyright terms
    1.17 + * except that the holder is Tim Hudson (tjh@cryptsoft.com).
    1.18 + * 
    1.19 + * Copyright remains Eric Young's, and as such any Copyright notices in
    1.20 + * the code are not to be removed.
    1.21 + * If this package is used in a product, Eric Young should be given attribution
    1.22 + * as the author of the parts of the library used.
    1.23 + * This can be in the form of a textual message at program startup or
    1.24 + * in documentation (online or textual) provided with the package.
    1.25 + * 
    1.26 + * Redistribution and use in source and binary forms, with or without
    1.27 + * modification, are permitted provided that the following conditions
    1.28 + * are met:
    1.29 + * 1. Redistributions of source code must retain the copyright
    1.30 + *    notice, this list of conditions and the following disclaimer.
    1.31 + * 2. Redistributions in binary form must reproduce the above copyright
    1.32 + *    notice, this list of conditions and the following disclaimer in the
    1.33 + *    documentation and/or other materials provided with the distribution.
    1.34 + * 3. All advertising materials mentioning features or use of this software
    1.35 + *    must display the following acknowledgement:
    1.36 + *    "This product includes cryptographic software written by
    1.37 + *     Eric Young (eay@cryptsoft.com)"
    1.38 + *    The word 'cryptographic' can be left out if the rouines from the library
    1.39 + *    being used are not cryptographic related :-).
    1.40 + * 4. If you include any Windows specific code (or a derivative thereof) from 
    1.41 + *    the apps directory (application code) you must include an acknowledgement:
    1.42 + *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
    1.43 + * 
    1.44 + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
    1.45 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.46 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.47 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    1.48 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    1.49 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    1.50 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    1.51 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    1.52 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    1.53 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1.54 + * SUCH DAMAGE.
    1.55 + * 
    1.56 + * The licence and distribution terms for any publically available version or
    1.57 + * derivative of this code cannot be changed.  i.e. this code cannot simply be
    1.58 + * copied and put under another distribution licence
    1.59 + * [including the GNU Public Licence.]
    1.60 + */
    1.61 +/* ====================================================================
    1.62 + * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
    1.63 + *
    1.64 + * Redistribution and use in source and binary forms, with or without
    1.65 + * modification, are permitted provided that the following conditions
    1.66 + * are met:
    1.67 + *
    1.68 + * 1. Redistributions of source code must retain the above copyright
    1.69 + *    notice, this list of conditions and the following disclaimer. 
    1.70 + *
    1.71 + * 2. Redistributions in binary form must reproduce the above copyright
    1.72 + *    notice, this list of conditions and the following disclaimer in
    1.73 + *    the documentation and/or other materials provided with the
    1.74 + *    distribution.
    1.75 + *
    1.76 + * 3. All advertising materials mentioning features or use of this
    1.77 + *    software must display the following acknowledgment:
    1.78 + *    "This product includes software developed by the OpenSSL Project
    1.79 + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
    1.80 + *
    1.81 + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
    1.82 + *    endorse or promote products derived from this software without
    1.83 + *    prior written permission. For written permission, please contact
    1.84 + *    openssl-core@openssl.org.
    1.85 + *
    1.86 + * 5. Products derived from this software may not be called "OpenSSL"
    1.87 + *    nor may "OpenSSL" appear in their names without prior written
    1.88 + *    permission of the OpenSSL Project.
    1.89 + *
    1.90 + * 6. Redistributions of any form whatsoever must retain the following
    1.91 + *    acknowledgment:
    1.92 + *    "This product includes software developed by the OpenSSL Project
    1.93 + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
    1.94 + *
    1.95 + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
    1.96 + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.97 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    1.98 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
    1.99 + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   1.100 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   1.101 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   1.102 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   1.103 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   1.104 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   1.105 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   1.106 + * OF THE POSSIBILITY OF SUCH DAMAGE.
   1.107 + * ====================================================================
   1.108 + *
   1.109 + * This product includes cryptographic software written by Eric Young
   1.110 + * (eay@cryptsoft.com).  This product includes software written by Tim
   1.111 + * Hudson (tjh@cryptsoft.com).
   1.112 + *
   1.113 + */
   1.114 +
   1.115 +#include <stdio.h>
   1.116 +#include <stdlib.h>
   1.117 +#include <string.h>
   1.118 +#include <sys/types.h>
   1.119 +#include <sys/stat.h>
   1.120 +#include <ctype.h>
   1.121 +#include <openssl/err.h>
   1.122 +#include <openssl/x509.h>
   1.123 +#include <openssl/x509v3.h>
   1.124 +#include <openssl/pem.h>
   1.125 +#include <openssl/pkcs12.h>
   1.126 +#include <openssl/ui.h>
   1.127 +#include <openssl/safestack.h>
   1.128 +#ifndef OPENSSL_NO_ENGINE
   1.129 +#include <openssl/engine.h>
   1.130 +#endif
   1.131 +#ifndef OPENSSL_NO_RSA
   1.132 +#include <openssl/rsa.h>
   1.133 +#endif
   1.134 +#include <openssl/bn.h>
   1.135 +
   1.136 +#define NON_MAIN
   1.137 +#include "apps.h"
   1.138 +#undef NON_MAIN
   1.139 +
   1.140 +typedef struct {
   1.141 +	const char *name;
   1.142 +	unsigned long flag;
   1.143 +	unsigned long mask;
   1.144 +} NAME_EX_TBL;
   1.145 +
   1.146 +static UI_METHOD *ui_method = NULL;
   1.147 +
   1.148 +static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
   1.149 +static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
   1.150 +
   1.151 +#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
   1.152 +/* Looks like this stuff is worth moving into separate function */
   1.153 +static EVP_PKEY *
   1.154 +load_netscape_key(BIO *err, BIO *key, const char *file,
   1.155 +		const char *key_descrip, int format);
   1.156 +#endif
   1.157 +
   1.158 +int app_init(long mesgwin);
   1.159 +#ifdef undef /* never finished - probably never will be :-) */
   1.160 +int args_from_file(char *file, int *argc, char **argv[])
   1.161 +	{
   1.162 +	FILE *fp;
   1.163 +	int num,i;
   1.164 +	unsigned int len;
   1.165 +	static char *buf=NULL;
   1.166 +	static char **arg=NULL;
   1.167 +	char *p;
   1.168 +	struct stat stbuf;
   1.169 +
   1.170 +	if (stat(file,&stbuf) < 0) return(0);
   1.171 +
   1.172 +	fp=fopen(file,"r");
   1.173 +	if (fp == NULL)
   1.174 +		return(0);
   1.175 +
   1.176 +	*argc=0;
   1.177 +	*argv=NULL;
   1.178 +
   1.179 +	len=(unsigned int)stbuf.st_size;
   1.180 +	if (buf != NULL) OPENSSL_free(buf);
   1.181 +	buf=(char *)OPENSSL_malloc(len+1);
   1.182 +	if (buf == NULL) return(0);
   1.183 +
   1.184 +	len=fread(buf,1,len,fp);
   1.185 +	if (len <= 1) return(0);
   1.186 +	buf[len]='\0';
   1.187 +
   1.188 +	i=0;
   1.189 +	for (p=buf; *p; p++)
   1.190 +		if (*p == '\n') i++;
   1.191 +	if (arg != NULL) OPENSSL_free(arg);
   1.192 +	arg=(char **)OPENSSL_malloc(sizeof(char *)*(i*2));
   1.193 +
   1.194 +	*argv=arg;
   1.195 +	num=0;
   1.196 +	p=buf;
   1.197 +	for (;;)
   1.198 +		{
   1.199 +		if (!*p) break;
   1.200 +		if (*p == '#') /* comment line */
   1.201 +			{
   1.202 +			while (*p && (*p != '\n')) p++;
   1.203 +			continue;
   1.204 +			}
   1.205 +		/* else we have a line */
   1.206 +		*(arg++)=p;
   1.207 +		num++;
   1.208 +		while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n')))
   1.209 +			p++;
   1.210 +		if (!*p) break;
   1.211 +		if (*p == '\n')
   1.212 +			{
   1.213 +			*(p++)='\0';
   1.214 +			continue;
   1.215 +			}
   1.216 +		/* else it is a tab or space */
   1.217 +		p++;
   1.218 +		while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
   1.219 +			p++;
   1.220 +		if (!*p) break;
   1.221 +		if (*p == '\n')
   1.222 +			{
   1.223 +			p++;
   1.224 +			continue;
   1.225 +			}
   1.226 +		*(arg++)=p++;
   1.227 +		num++;
   1.228 +		while (*p && (*p != '\n')) p++;
   1.229 +		if (!*p) break;
   1.230 +		/* else *p == '\n' */
   1.231 +		*(p++)='\0';
   1.232 +		}
   1.233 +	*argc=num;
   1.234 +	return(1);
   1.235 +	}
   1.236 +#endif
   1.237 +
   1.238 +int str2fmt(char *s)
   1.239 +	{
   1.240 +	if 	((*s == 'D') || (*s == 'd'))
   1.241 +		return(FORMAT_ASN1);
   1.242 +	else if ((*s == 'T') || (*s == 't'))
   1.243 +		return(FORMAT_TEXT);
   1.244 +	else if ((*s == 'P') || (*s == 'p'))
   1.245 +		return(FORMAT_PEM);
   1.246 +	else if ((*s == 'N') || (*s == 'n'))
   1.247 +		return(FORMAT_NETSCAPE);
   1.248 +	else if ((*s == 'S') || (*s == 's'))
   1.249 +		return(FORMAT_SMIME);
   1.250 +	else if ((*s == '1')
   1.251 +		|| (strcmp(s,"PKCS12") == 0) || (strcmp(s,"pkcs12") == 0)
   1.252 +		|| (strcmp(s,"P12") == 0) || (strcmp(s,"p12") == 0))
   1.253 +		return(FORMAT_PKCS12);
   1.254 +	else if ((*s == 'E') || (*s == 'e'))
   1.255 +		return(FORMAT_ENGINE);
   1.256 +	else
   1.257 +		return(FORMAT_UNDEF);
   1.258 +	}
   1.259 +
   1.260 +#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_NETWARE)
   1.261 +svoid program_name(char *in, char *out, int size)
   1.262 +	{
   1.263 +	int i,n;
   1.264 +	char *p=NULL;
   1.265 +
   1.266 +	n=strlen(in);
   1.267 +	/* find the last '/', '\' or ':' */
   1.268 +	for (i=n-1; i>0; i--)
   1.269 +		{
   1.270 +		if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':'))
   1.271 +			{
   1.272 +			p= &(in[i+1]);
   1.273 +			break;
   1.274 +			}
   1.275 +		}
   1.276 +	if (p == NULL)
   1.277 +		p=in;
   1.278 +	n=strlen(p);
   1.279 +
   1.280 +#if defined(OPENSSL_SYS_NETWARE)
   1.281 +   /* strip off trailing .nlm if present. */
   1.282 +   if ((n > 4) && (p[n-4] == '.') &&
   1.283 +      ((p[n-3] == 'n') || (p[n-3] == 'N')) &&
   1.284 +      ((p[n-2] == 'l') || (p[n-2] == 'L')) &&
   1.285 +      ((p[n-1] == 'm') || (p[n-1] == 'M')))
   1.286 +      n-=4;
   1.287 +#else
   1.288 +	/* strip off trailing .exe if present. */
   1.289 +	if ((n > 4) && (p[n-4] == '.') &&
   1.290 +		((p[n-3] == 'e') || (p[n-3] == 'E')) &&
   1.291 +		((p[n-2] == 'x') || (p[n-2] == 'X')) &&
   1.292 +		((p[n-1] == 'e') || (p[n-1] == 'E')))
   1.293 +		n-=4;
   1.294 +#endif
   1.295 +
   1.296 +	if (n > size-1)
   1.297 +		n=size-1;
   1.298 +
   1.299 +	for (i=0; i<n; i++)
   1.300 +		{
   1.301 +		if ((p[i] >= 'A') && (p[i] <= 'Z'))
   1.302 +			out[i]=p[i]-'A'+'a';
   1.303 +		else
   1.304 +			out[i]=p[i];
   1.305 +		}
   1.306 +	out[n]='\0';
   1.307 +	}
   1.308 +#else
   1.309 +#ifdef OPENSSL_SYS_VMS
   1.310 +svoid program_name(char *in, char *out, int size)
   1.311 +	{
   1.312 +	char *p=in, *q;
   1.313 +	char *chars=":]>";
   1.314 +
   1.315 +	while(*chars != '\0')
   1.316 +		{
   1.317 +		q=strrchr(p,*chars);
   1.318 +		if (q > p)
   1.319 +			p = q + 1;
   1.320 +		chars++;
   1.321 +		}
   1.322 +
   1.323 +	q=strrchr(p,'.');
   1.324 +	if (q == NULL)
   1.325 +		q = p + strlen(p);
   1.326 +	strncpy(out,p,size-1);
   1.327 +	if (q-p >= size)
   1.328 +		{
   1.329 +		out[size-1]='\0';
   1.330 +		}
   1.331 +	else
   1.332 +		{
   1.333 +		out[q-p]='\0';
   1.334 +		}
   1.335 +	}
   1.336 +#else
   1.337 +void program_name(char *in, char *out, int size)
   1.338 +	{
   1.339 +	char *p;
   1.340 +
   1.341 +	p=strrchr(in,'/');
   1.342 +	if (p != NULL)
   1.343 +		p++;
   1.344 +	else
   1.345 +		p=in;
   1.346 +	BUF_strlcpy(out,p,size);
   1.347 +	}
   1.348 +#endif
   1.349 +#endif
   1.350 +
   1.351 +int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
   1.352 +	{
   1.353 +	int num,len,i;
   1.354 +	char *p;
   1.355 +
   1.356 +	*argc=0;
   1.357 +	*argv=NULL;
   1.358 +
   1.359 +	len=strlen(buf);
   1.360 +	i=0;
   1.361 +	if (arg->count == 0)
   1.362 +		{
   1.363 +		arg->count=20;
   1.364 +		arg->data=(char **)OPENSSL_malloc(sizeof(char *)*arg->count);
   1.365 +		}
   1.366 +	for (i=0; i<arg->count; i++)
   1.367 +		arg->data[i]=NULL;
   1.368 +
   1.369 +	num=0;
   1.370 +	p=buf;
   1.371 +	for (;;)
   1.372 +		{
   1.373 +		/* first scan over white space */
   1.374 +		if (!*p) break;
   1.375 +		while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
   1.376 +			p++;
   1.377 +		if (!*p) break;
   1.378 +
   1.379 +		/* The start of something good :-) */
   1.380 +		if (num >= arg->count)
   1.381 +			{
   1.382 +			char **tmp_p;
   1.383 +			int tlen = arg->count + 20;
   1.384 +			tmp_p = (char **)OPENSSL_realloc(arg->data,
   1.385 +				sizeof(char *)*tlen);
   1.386 +			if (tmp_p == NULL)
   1.387 +				return 0;
   1.388 +			arg->data  = tmp_p;
   1.389 +			arg->count = tlen;
   1.390 +			/* initialize newly allocated data */
   1.391 +			for (i = num; i < arg->count; i++)
   1.392 +				arg->data[i] = NULL;
   1.393 +			}
   1.394 +		arg->data[num++]=p;
   1.395 +
   1.396 +		/* now look for the end of this */
   1.397 +		if ((*p == '\'') || (*p == '\"')) /* scan for closing quote */
   1.398 +			{
   1.399 +			i= *(p++);
   1.400 +			arg->data[num-1]++; /* jump over quote */
   1.401 +			while (*p && (*p != i))
   1.402 +				p++;
   1.403 +			*p='\0';
   1.404 +			}
   1.405 +		else
   1.406 +			{
   1.407 +			while (*p && ((*p != ' ') &&
   1.408 +				(*p != '\t') && (*p != '\n')))
   1.409 +				p++;
   1.410 +
   1.411 +			if (*p == '\0')
   1.412 +				p--;
   1.413 +			else
   1.414 +				*p='\0';
   1.415 +			}
   1.416 +		p++;
   1.417 +		}
   1.418 +	*argc=num;
   1.419 +	*argv=arg->data;
   1.420 +	return(1);
   1.421 +	}
   1.422 +
   1.423 +#ifndef APP_INIT
   1.424 +int app_init(long mesgwin)
   1.425 +	{
   1.426 +	return(1);
   1.427 +	}
   1.428 +#endif
   1.429 +
   1.430 +
   1.431 +int dump_cert_text (BIO *out, X509 *x)
   1.432 +{
   1.433 +	char *p;
   1.434 +
   1.435 +	p=X509_NAME_oneline(X509_get_subject_name(x),NULL,0);
   1.436 +	BIO_puts(out,"subject=");
   1.437 +	BIO_puts(out,p);
   1.438 +	OPENSSL_free(p);
   1.439 +
   1.440 +	p=X509_NAME_oneline(X509_get_issuer_name(x),NULL,0);
   1.441 +	BIO_puts(out,"\nissuer=");
   1.442 +	BIO_puts(out,p);
   1.443 +	BIO_puts(out,"\n");
   1.444 +	OPENSSL_free(p);
   1.445 +
   1.446 +	return 0;
   1.447 +}
   1.448 +
   1.449 +static int ui_open(UI *ui)
   1.450 +	{
   1.451 +	return UI_method_get_opener(UI_OpenSSL())(ui);
   1.452 +	}
   1.453 +static int ui_read(UI *ui, UI_STRING *uis)
   1.454 +	{
   1.455 +	if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
   1.456 +		&& UI_get0_user_data(ui))
   1.457 +		{
   1.458 +		switch(UI_get_string_type(uis))
   1.459 +			{
   1.460 +		case UIT_PROMPT:
   1.461 +		case UIT_VERIFY:
   1.462 +			{
   1.463 +			const char *password =
   1.464 +				((PW_CB_DATA *)UI_get0_user_data(ui))->password;
   1.465 +			if (password && password[0] != '\0')
   1.466 +				{
   1.467 +				UI_set_result(ui, uis, password);
   1.468 +				return 1;
   1.469 +				}
   1.470 +			}
   1.471 +		default:
   1.472 +			break;
   1.473 +			}
   1.474 +		}
   1.475 +	return UI_method_get_reader(UI_OpenSSL())(ui, uis);
   1.476 +	}
   1.477 +static int ui_write(UI *ui, UI_STRING *uis)
   1.478 +	{
   1.479 +	if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
   1.480 +		&& UI_get0_user_data(ui))
   1.481 +		{
   1.482 +		switch(UI_get_string_type(uis))
   1.483 +			{
   1.484 +		case UIT_PROMPT:
   1.485 +		case UIT_VERIFY:
   1.486 +			{
   1.487 +			const char *password =
   1.488 +				((PW_CB_DATA *)UI_get0_user_data(ui))->password;
   1.489 +			if (password && password[0] != '\0')
   1.490 +				return 1;
   1.491 +			}
   1.492 +		default:
   1.493 +			break;
   1.494 +			}
   1.495 +		}
   1.496 +	return UI_method_get_writer(UI_OpenSSL())(ui, uis);
   1.497 +	}
   1.498 +static int ui_close(UI *ui)
   1.499 +	{
   1.500 +	return UI_method_get_closer(UI_OpenSSL())(ui);
   1.501 +	}
   1.502 +int setup_ui_method(void)
   1.503 +	{
   1.504 +	ui_method = UI_create_method("OpenSSL application user interface");
   1.505 +	UI_method_set_opener(ui_method, ui_open);
   1.506 +	UI_method_set_reader(ui_method, ui_read);
   1.507 +	UI_method_set_writer(ui_method, ui_write);
   1.508 +	UI_method_set_closer(ui_method, ui_close);
   1.509 +	return 0;
   1.510 +	}
   1.511 +void destroy_ui_method(void)
   1.512 +	{
   1.513 +	if(ui_method)
   1.514 +		{
   1.515 +		UI_destroy_method(ui_method);
   1.516 +		ui_method = NULL;
   1.517 +		}
   1.518 +	}
   1.519 +int password_callback(char *buf, int bufsiz, int verify,
   1.520 +	PW_CB_DATA *cb_tmp)
   1.521 +	{
   1.522 +	UI *ui = NULL;
   1.523 +	int res = 0;
   1.524 +	const char *prompt_info = NULL;
   1.525 +	const char *password = NULL;
   1.526 +	PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
   1.527 +
   1.528 +	if (cb_data)
   1.529 +		{
   1.530 +		if (cb_data->password)
   1.531 +			password = cb_data->password;
   1.532 +		if (cb_data->prompt_info)
   1.533 +			prompt_info = cb_data->prompt_info;
   1.534 +		}
   1.535 +
   1.536 +	if (password)
   1.537 +		{
   1.538 +		res = strlen(password);
   1.539 +		if (res > bufsiz)
   1.540 +			res = bufsiz;
   1.541 +		memcpy(buf, password, res);
   1.542 +		return res;
   1.543 +		}
   1.544 +
   1.545 +	ui = UI_new_method(ui_method);
   1.546 +	if (ui)
   1.547 +		{
   1.548 +		int ok = 0;
   1.549 +		char *buff = NULL;
   1.550 +		int ui_flags = 0;
   1.551 +		char *prompt = NULL;
   1.552 +
   1.553 +		prompt = UI_construct_prompt(ui, "pass phrase",
   1.554 +			prompt_info);
   1.555 +
   1.556 +		ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
   1.557 +		UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
   1.558 +
   1.559 +		if (ok >= 0)
   1.560 +			ok = UI_add_input_string(ui,prompt,ui_flags,buf,
   1.561 +				PW_MIN_LENGTH,BUFSIZ-1);
   1.562 +		if (ok >= 0 && verify)
   1.563 +			{
   1.564 +			buff = (char *)OPENSSL_malloc(bufsiz);
   1.565 +			ok = UI_add_verify_string(ui,prompt,ui_flags,buff,
   1.566 +				PW_MIN_LENGTH,BUFSIZ-1, buf);
   1.567 +			}
   1.568 +		if (ok >= 0)
   1.569 +			do
   1.570 +				{
   1.571 +				ok = UI_process(ui);
   1.572 +				}
   1.573 +			while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
   1.574 +
   1.575 +		if (buff)
   1.576 +			{
   1.577 +			OPENSSL_cleanse(buff,(unsigned int)bufsiz);
   1.578 +			OPENSSL_free(buff);
   1.579 +			}
   1.580 +
   1.581 +		if (ok >= 0)
   1.582 +			res = strlen(buf);
   1.583 +		if (ok == -1)
   1.584 +			{
   1.585 +			BIO_printf(bio_err, "User interface error\n");
   1.586 +			ERR_print_errors(bio_err);
   1.587 +			OPENSSL_cleanse(buf,(unsigned int)bufsiz);
   1.588 +			res = 0;
   1.589 +			}
   1.590 +		if (ok == -2)
   1.591 +			{
   1.592 +			BIO_printf(bio_err,"aborted!\n");
   1.593 +			OPENSSL_cleanse(buf,(unsigned int)bufsiz);
   1.594 +			res = 0;
   1.595 +			}
   1.596 +		UI_free(ui);
   1.597 +		OPENSSL_free(prompt);
   1.598 +		}
   1.599 +	return res;
   1.600 +	}
   1.601 +
   1.602 +static char *app_get_pass(BIO *err, char *arg, int keepbio);
   1.603 +
   1.604 +int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
   1.605 +{
   1.606 +	int same;
   1.607 +	if(!arg2 || !arg1 || strcmp(arg1, arg2)) same = 0;
   1.608 +	else same = 1;
   1.609 +	if(arg1) {
   1.610 +		*pass1 = app_get_pass(err, arg1, same);
   1.611 +		if(!*pass1) return 0;
   1.612 +	} else if(pass1) *pass1 = NULL;
   1.613 +	if(arg2) {
   1.614 +		*pass2 = app_get_pass(err, arg2, same ? 2 : 0);
   1.615 +		if(!*pass2) return 0;
   1.616 +	} else if(pass2) *pass2 = NULL;
   1.617 +	return 1;
   1.618 +}
   1.619 +
   1.620 +static char *app_get_pass(BIO *err, char *arg, int keepbio)
   1.621 +{
   1.622 +	char *tmp, tpass[APP_PASS_LEN];
   1.623 +	static BIO *pwdbio = NULL;
   1.624 +	int i;
   1.625 +	if(!strncmp(arg, "pass:", 5)) return BUF_strdup(arg + 5);
   1.626 +	if(!strncmp(arg, "env:", 4)) {
   1.627 +		tmp = getenv(arg + 4);
   1.628 +		if(!tmp) {
   1.629 +			BIO_printf(err, "Can't read environment variable %s\n", arg + 4);
   1.630 +			return NULL;
   1.631 +		}
   1.632 +		return BUF_strdup(tmp);
   1.633 +	}
   1.634 +	if(!keepbio || !pwdbio) {
   1.635 +		if(!strncmp(arg, "file:", 5)) {
   1.636 +			pwdbio = BIO_new_file(arg + 5, "r");
   1.637 +			if(!pwdbio) {
   1.638 +				BIO_printf(err, "Can't open file %s\n", arg + 5);
   1.639 +				return NULL;
   1.640 +			}
   1.641 +		} else if(!strncmp(arg, "fd:", 3)) {
   1.642 +			BIO *btmp;
   1.643 +			i = atoi(arg + 3);
   1.644 +			if(i >= 0) pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
   1.645 +			if((i < 0) || !pwdbio) {
   1.646 +				BIO_printf(err, "Can't access file descriptor %s\n", arg + 3);
   1.647 +				return NULL;
   1.648 +			}
   1.649 +			/* Can't do BIO_gets on an fd BIO so add a buffering BIO */
   1.650 +			btmp = BIO_new(BIO_f_buffer());
   1.651 +			pwdbio = BIO_push(btmp, pwdbio);
   1.652 +		} else 
   1.653 +		if(!strcmp(arg, "stdin")) {
   1.654 +			pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE);
   1.655 +			if(!pwdbio) {
   1.656 +				BIO_printf(err, "Can't open BIO for stdin\n");
   1.657 +				return NULL;
   1.658 +			}
   1.659 +
   1.660 +		} else {
   1.661 +			BIO_printf(err, "Invalid password argument \"%s\"\n", arg);
   1.662 +			return NULL;
   1.663 +		}
   1.664 +	}
   1.665 +	i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
   1.666 +	if(keepbio != 1) {
   1.667 +		BIO_free_all(pwdbio);
   1.668 +		pwdbio = NULL;
   1.669 +	}
   1.670 +	if(i <= 0) {
   1.671 +		BIO_printf(err, "Error reading password from BIO\n");
   1.672 +		return NULL;
   1.673 +	}
   1.674 +	tmp = strchr(tpass, '\n');
   1.675 +	if(tmp) *tmp = 0;
   1.676 +	return BUF_strdup(tpass);
   1.677 +}
   1.678 +
   1.679 +int add_oid_section(BIO *err, CONF *conf)
   1.680 +{	
   1.681 +	char *p;
   1.682 +	STACK_OF(CONF_VALUE) *sktmp;
   1.683 +	CONF_VALUE *cnf;
   1.684 +	int i;
   1.685 +	if(!(p=NCONF_get_string(conf,NULL,"oid_section")))
   1.686 +		{
   1.687 +		ERR_clear_error();
   1.688 +		return 1;
   1.689 +		}
   1.690 +	if(!(sktmp = NCONF_get_section(conf, p))) {
   1.691 +		BIO_printf(err, "problem loading oid section %s\n", p);
   1.692 +		return 0;
   1.693 +	}
   1.694 +	for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
   1.695 +		cnf = sk_CONF_VALUE_value(sktmp, i);
   1.696 +		if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
   1.697 +			BIO_printf(err, "problem creating object %s=%s\n",
   1.698 +							 cnf->name, cnf->value);
   1.699 +			return 0;
   1.700 +		}
   1.701 +	}
   1.702 +	return 1;
   1.703 +}
   1.704 +
   1.705 +static int load_pkcs12(BIO *err, BIO *in, const char *desc,
   1.706 +		pem_password_cb *pem_cb,  void *cb_data,
   1.707 +		EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
   1.708 +	{
   1.709 + 	const char *pass;
   1.710 +	char tpass[PEM_BUFSIZE];
   1.711 +	int len, ret = 0;
   1.712 +	PKCS12 *p12;
   1.713 +	p12 = d2i_PKCS12_bio(in, NULL);
   1.714 +	if (p12 == NULL)
   1.715 +		{
   1.716 +		BIO_printf(err, "Error loading PKCS12 file for %s\n", desc);	
   1.717 +		goto die;
   1.718 +		}
   1.719 +	/* See if an empty password will do */
   1.720 +	if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0))
   1.721 +		pass = "";
   1.722 +	else
   1.723 +		{
   1.724 +		if (!pem_cb)
   1.725 +			pem_cb = (pem_password_cb *)password_callback;
   1.726 +		len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
   1.727 +		if (len < 0) 
   1.728 +			{
   1.729 +			BIO_printf(err, "Passpharse callback error for %s\n",
   1.730 +					desc);
   1.731 +			goto die;
   1.732 +			}
   1.733 +		if (len < PEM_BUFSIZE)
   1.734 +			tpass[len] = 0;
   1.735 +		if (!PKCS12_verify_mac(p12, tpass, len))
   1.736 +			{
   1.737 +			BIO_printf(err,
   1.738 +	"Mac verify error (wrong password?) in PKCS12 file for %s\n", desc);	
   1.739 +			goto die;
   1.740 +			}
   1.741 +		pass = tpass;
   1.742 +		}
   1.743 +	ret = PKCS12_parse(p12, pass, pkey, cert, ca);
   1.744 +	die:
   1.745 +	if (p12)
   1.746 +		PKCS12_free(p12);
   1.747 +	return ret;
   1.748 +	}
   1.749 +
   1.750 +X509 *load_cert(BIO *err, const char *file, int format,
   1.751 +	const char *pass, ENGINE *e, const char *cert_descrip)
   1.752 +	{
   1.753 +	ASN1_HEADER *ah=NULL;
   1.754 +	BUF_MEM *buf=NULL;
   1.755 +	X509 *x=NULL;
   1.756 +	BIO *cert;
   1.757 +
   1.758 +	if ((cert=BIO_new(BIO_s_file())) == NULL)
   1.759 +		{
   1.760 +		ERR_print_errors(err);
   1.761 +		goto end;
   1.762 +		}
   1.763 +
   1.764 +	if (file == NULL)
   1.765 +		{
   1.766 +		setvbuf(stdin, NULL, _IONBF, 0);
   1.767 +		BIO_set_fp(cert,stdin,BIO_NOCLOSE);
   1.768 +		}
   1.769 +	else
   1.770 +		{
   1.771 +		if (BIO_read_filename(cert,file) <= 0)
   1.772 +			{
   1.773 +			BIO_printf(err, "Error opening %s %s\n",
   1.774 +				cert_descrip, file);
   1.775 +			ERR_print_errors(err);
   1.776 +			goto end;
   1.777 +			}
   1.778 +		}
   1.779 +
   1.780 +	if 	(format == FORMAT_ASN1)
   1.781 +		x=d2i_X509_bio(cert,NULL);
   1.782 +	else if (format == FORMAT_NETSCAPE)
   1.783 +		{
   1.784 +		const unsigned char *p,*op;
   1.785 +		int size=0,i;
   1.786 +
   1.787 +		/* We sort of have to do it this way because it is sort of nice
   1.788 +		 * to read the header first and check it, then
   1.789 +		 * try to read the certificate */
   1.790 +		buf=BUF_MEM_new();
   1.791 +		for (;;)
   1.792 +			{
   1.793 +			if ((buf == NULL) || (!BUF_MEM_grow(buf,size+1024*10)))
   1.794 +				goto end;
   1.795 +			i=BIO_read(cert,&(buf->data[size]),1024*10);
   1.796 +			size+=i;
   1.797 +			if (i == 0) break;
   1.798 +			if (i < 0)
   1.799 +				{
   1.800 +				perror("reading certificate");
   1.801 +				goto end;
   1.802 +				}
   1.803 +			}
   1.804 +		p=(unsigned char *)buf->data;
   1.805 +		op=p;
   1.806 +
   1.807 +		/* First load the header */
   1.808 +		if ((ah=d2i_ASN1_HEADER(NULL,&p,(long)size)) == NULL)
   1.809 +			goto end;
   1.810 +		if ((ah->header == NULL) || (ah->header->data == NULL) ||
   1.811 +			(strncmp(NETSCAPE_CERT_HDR,(char *)ah->header->data,
   1.812 +			ah->header->length) != 0))
   1.813 +			{
   1.814 +			BIO_printf(err,"Error reading header on certificate\n");
   1.815 +			goto end;
   1.816 +			}
   1.817 +		/* header is ok, so now read the object */
   1.818 +		p=op;
   1.819 +		ah->meth=X509_asn1_meth();
   1.820 +		if ((ah=d2i_ASN1_HEADER(&ah,&p,(long)size)) == NULL)
   1.821 +			goto end;
   1.822 +		x=(X509 *)ah->data;
   1.823 +		ah->data=NULL;
   1.824 +		}
   1.825 +	else if (format == FORMAT_PEM)
   1.826 +		x=PEM_read_bio_X509_AUX(cert,NULL,
   1.827 +			(pem_password_cb *)password_callback, NULL);
   1.828 +	else if (format == FORMAT_PKCS12)
   1.829 +		{
   1.830 +		if (!load_pkcs12(err, cert,cert_descrip, NULL, NULL,
   1.831 +					NULL, &x, NULL))
   1.832 +			goto end;
   1.833 +		}
   1.834 +	else	{
   1.835 +		BIO_printf(err,"bad input format specified for %s\n",
   1.836 +			cert_descrip);
   1.837 +		goto end;
   1.838 +		}
   1.839 +end:
   1.840 +	if (x == NULL)
   1.841 +		{
   1.842 +		BIO_printf(err,"unable to load certificate\n");
   1.843 +		ERR_print_errors(err);
   1.844 +		}
   1.845 +	if (ah != NULL) ASN1_HEADER_free(ah);
   1.846 +	if (cert != NULL) BIO_free(cert);
   1.847 +	if (buf != NULL) BUF_MEM_free(buf);
   1.848 +	return(x);
   1.849 +	}
   1.850 +
   1.851 +EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
   1.852 +	const char *pass, ENGINE *e, const char *key_descrip)
   1.853 +	{
   1.854 +	BIO *key=NULL;
   1.855 +	EVP_PKEY *pkey=NULL;
   1.856 +	PW_CB_DATA cb_data;
   1.857 +
   1.858 +	cb_data.password = pass;
   1.859 +	cb_data.prompt_info = file;
   1.860 +
   1.861 +	if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE))
   1.862 +		{
   1.863 +		BIO_printf(err,"no keyfile specified\n");
   1.864 +		goto end;
   1.865 +		}
   1.866 +#ifndef OPENSSL_NO_ENGINE
   1.867 +	if (format == FORMAT_ENGINE)
   1.868 +		{
   1.869 +		if (!e)
   1.870 +			BIO_printf(bio_err,"no engine specified\n");
   1.871 +		else
   1.872 +			pkey = ENGINE_load_private_key(e, file,
   1.873 +				ui_method, &cb_data);
   1.874 +		goto end;
   1.875 +		}
   1.876 +#endif
   1.877 +	key=BIO_new(BIO_s_file());
   1.878 +	if (key == NULL)
   1.879 +		{
   1.880 +		ERR_print_errors(err);
   1.881 +		goto end;
   1.882 +		}
   1.883 +	if (file == NULL && maybe_stdin)
   1.884 +		{
   1.885 +		setvbuf(stdin, NULL, _IONBF, 0);
   1.886 +		BIO_set_fp(key,stdin,BIO_NOCLOSE);
   1.887 +		}
   1.888 +	else
   1.889 +		if (BIO_read_filename(key,file) <= 0)
   1.890 +			{
   1.891 +			BIO_printf(err, "Error opening %s %s\n",
   1.892 +				key_descrip, file);
   1.893 +			ERR_print_errors(err);
   1.894 +			goto end;
   1.895 +			}
   1.896 +	if (format == FORMAT_ASN1)
   1.897 +		{
   1.898 +		pkey=d2i_PrivateKey_bio(key, NULL);
   1.899 +		}
   1.900 +	else if (format == FORMAT_PEM)
   1.901 +		{
   1.902 +		pkey=PEM_read_bio_PrivateKey(key,NULL,
   1.903 +			(pem_password_cb *)password_callback, &cb_data);
   1.904 +		}
   1.905 +#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
   1.906 +	else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
   1.907 +		pkey = load_netscape_key(err, key, file, key_descrip, format);
   1.908 +#endif
   1.909 +	else if (format == FORMAT_PKCS12)
   1.910 +		{
   1.911 +		if (!load_pkcs12(err, key, key_descrip,
   1.912 +				(pem_password_cb *)password_callback, &cb_data,
   1.913 +				&pkey, NULL, NULL))
   1.914 +			goto end;
   1.915 +		}
   1.916 +	else
   1.917 +		{
   1.918 +		BIO_printf(err,"bad input format specified for key file\n");
   1.919 +		goto end;
   1.920 +		}
   1.921 + end:
   1.922 +	if (key != NULL) BIO_free(key);
   1.923 +	if (pkey == NULL)
   1.924 +		BIO_printf(err,"unable to load %s\n", key_descrip);
   1.925 +	return(pkey);
   1.926 +	}
   1.927 +
   1.928 +EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
   1.929 +	const char *pass, ENGINE *e, const char *key_descrip)
   1.930 +	{
   1.931 +	BIO *key=NULL;
   1.932 +	EVP_PKEY *pkey=NULL;
   1.933 +	PW_CB_DATA cb_data;
   1.934 +
   1.935 +	cb_data.password = pass;
   1.936 +	cb_data.prompt_info = file;
   1.937 +
   1.938 +	if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE))
   1.939 +		{
   1.940 +		BIO_printf(err,"no keyfile specified\n");
   1.941 +		goto end;
   1.942 +		}
   1.943 +#ifndef OPENSSL_NO_ENGINE
   1.944 +	if (format == FORMAT_ENGINE)
   1.945 +		{
   1.946 +		if (!e)
   1.947 +			BIO_printf(bio_err,"no engine specified\n");
   1.948 +		else
   1.949 +			pkey = ENGINE_load_public_key(e, file,
   1.950 +				ui_method, &cb_data);
   1.951 +		goto end;
   1.952 +		}
   1.953 +#endif
   1.954 +	key=BIO_new(BIO_s_file());
   1.955 +	if (key == NULL)
   1.956 +		{
   1.957 +		ERR_print_errors(err);
   1.958 +		goto end;
   1.959 +		}
   1.960 +	if (file == NULL && maybe_stdin)
   1.961 +		{
   1.962 +		setvbuf(stdin, NULL, _IONBF, 0);
   1.963 +		BIO_set_fp(key,stdin,BIO_NOCLOSE);
   1.964 +		}
   1.965 +	else
   1.966 +		if (BIO_read_filename(key,file) <= 0)
   1.967 +			{
   1.968 +			BIO_printf(err, "Error opening %s %s\n",
   1.969 +				key_descrip, file);
   1.970 +			ERR_print_errors(err);
   1.971 +			goto end;
   1.972 +		}
   1.973 +	if (format == FORMAT_ASN1)
   1.974 +		{
   1.975 +		pkey=d2i_PUBKEY_bio(key, NULL);
   1.976 +		}
   1.977 +	else if (format == FORMAT_PEM)
   1.978 +		{
   1.979 +		pkey=PEM_read_bio_PUBKEY(key,NULL,
   1.980 +			(pem_password_cb *)password_callback, &cb_data);
   1.981 +		}
   1.982 +#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
   1.983 +	else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
   1.984 +		pkey = load_netscape_key(err, key, file, key_descrip, format);
   1.985 +#endif
   1.986 +	else
   1.987 +		{
   1.988 +		BIO_printf(err,"bad input format specified for key file\n");
   1.989 +		goto end;
   1.990 +		}
   1.991 + end:
   1.992 +	if (key != NULL) BIO_free(key);
   1.993 +	if (pkey == NULL)
   1.994 +		BIO_printf(err,"unable to load %s\n", key_descrip);
   1.995 +	return(pkey);
   1.996 +	}
   1.997 +
   1.998 +#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
   1.999 +static EVP_PKEY *
  1.1000 +load_netscape_key(BIO *err, BIO *key, const char *file,
  1.1001 +		const char *key_descrip, int format)
  1.1002 +	{
  1.1003 +	EVP_PKEY *pkey;
  1.1004 +	BUF_MEM *buf;
  1.1005 +	RSA	*rsa;
  1.1006 +	const unsigned char *p;
  1.1007 +	int size, i;
  1.1008 +
  1.1009 +	buf=BUF_MEM_new();
  1.1010 +	pkey = EVP_PKEY_new();
  1.1011 +	size = 0;
  1.1012 +	if (buf == NULL || pkey == NULL)
  1.1013 +		goto error;
  1.1014 +	for (;;)
  1.1015 +		{
  1.1016 +		if (!BUF_MEM_grow_clean(buf,size+1024*10))
  1.1017 +			goto error;
  1.1018 +		i = BIO_read(key, &(buf->data[size]), 1024*10);
  1.1019 +		size += i;
  1.1020 +		if (i == 0)
  1.1021 +			break;
  1.1022 +		if (i < 0)
  1.1023 +			{
  1.1024 +				BIO_printf(err, "Error reading %s %s",
  1.1025 +					key_descrip, file);
  1.1026 +				goto error;
  1.1027 +			}
  1.1028 +		}
  1.1029 +	p=(unsigned char *)buf->data;
  1.1030 +	rsa = d2i_RSA_NET(NULL,&p,(long)size,NULL,
  1.1031 +		(format == FORMAT_IISSGC ? 1 : 0));
  1.1032 +	if (rsa == NULL)
  1.1033 +		goto error;
  1.1034 +	BUF_MEM_free(buf);
  1.1035 +	EVP_PKEY_set1_RSA(pkey, rsa);
  1.1036 +	return pkey;
  1.1037 +error:
  1.1038 +	BUF_MEM_free(buf);
  1.1039 +	EVP_PKEY_free(pkey);
  1.1040 +	return NULL;
  1.1041 +	}
  1.1042 +#endif /* ndef OPENSSL_NO_RC4 */
  1.1043 +
  1.1044 +STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
  1.1045 +	const char *pass, ENGINE *e, const char *cert_descrip)
  1.1046 +	{
  1.1047 +	BIO *certs;
  1.1048 +	int i;
  1.1049 +	STACK_OF(X509) *othercerts = NULL;
  1.1050 +	STACK_OF(X509_INFO) *allcerts = NULL;
  1.1051 +	X509_INFO *xi;
  1.1052 +	PW_CB_DATA cb_data;
  1.1053 +
  1.1054 +	cb_data.password = pass;
  1.1055 +	cb_data.prompt_info = file;
  1.1056 +
  1.1057 +	if((certs = BIO_new(BIO_s_file())) == NULL)
  1.1058 +		{
  1.1059 +		ERR_print_errors(err);
  1.1060 +		goto end;
  1.1061 +		}
  1.1062 +
  1.1063 +	if (file == NULL)
  1.1064 +		BIO_set_fp(certs,stdin,BIO_NOCLOSE);
  1.1065 +	else
  1.1066 +		{
  1.1067 +		if (BIO_read_filename(certs,file) <= 0)
  1.1068 +			{
  1.1069 +			BIO_printf(err, "Error opening %s %s\n",
  1.1070 +				cert_descrip, file);
  1.1071 +			ERR_print_errors(err);
  1.1072 +			goto end;
  1.1073 +			}
  1.1074 +		}
  1.1075 +
  1.1076 +	if      (format == FORMAT_PEM)
  1.1077 +		{
  1.1078 +		othercerts = sk_X509_new_null();
  1.1079 +		if(!othercerts)
  1.1080 +			{
  1.1081 +			sk_X509_free(othercerts);
  1.1082 +			othercerts = NULL;
  1.1083 +			goto end;
  1.1084 +			}
  1.1085 +		allcerts = PEM_X509_INFO_read_bio(certs, NULL,
  1.1086 +				(pem_password_cb *)password_callback, &cb_data);
  1.1087 +		for(i = 0; i < sk_X509_INFO_num(allcerts); i++)
  1.1088 +			{
  1.1089 +			xi = sk_X509_INFO_value (allcerts, i);
  1.1090 +			if (xi->x509)
  1.1091 +				{
  1.1092 +				sk_X509_push(othercerts, xi->x509);
  1.1093 +				xi->x509 = NULL;
  1.1094 +				}
  1.1095 +			}
  1.1096 +		goto end;
  1.1097 +		}
  1.1098 +	else	{
  1.1099 +		BIO_printf(err,"bad input format specified for %s\n",
  1.1100 +			cert_descrip);
  1.1101 +		goto end;
  1.1102 +		}
  1.1103 +end:
  1.1104 +	if (othercerts == NULL)
  1.1105 +		{
  1.1106 +		BIO_printf(err,"unable to load certificates\n");
  1.1107 +		ERR_print_errors(err);
  1.1108 +		}
  1.1109 +	if (allcerts) sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
  1.1110 +	if (certs != NULL) BIO_free(certs);
  1.1111 +	return(othercerts);
  1.1112 +	}
  1.1113 +
  1.1114 +
  1.1115 +#define X509V3_EXT_UNKNOWN_MASK		(0xfL << 16)
  1.1116 +/* Return error for unknown extensions */
  1.1117 +#define X509V3_EXT_DEFAULT		0
  1.1118 +/* Print error for unknown extensions */
  1.1119 +#define X509V3_EXT_ERROR_UNKNOWN	(1L << 16)
  1.1120 +/* ASN1 parse unknown extensions */
  1.1121 +#define X509V3_EXT_PARSE_UNKNOWN	(2L << 16)
  1.1122 +/* BIO_dump unknown extensions */
  1.1123 +#define X509V3_EXT_DUMP_UNKNOWN		(3L << 16)
  1.1124 +
  1.1125 +#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
  1.1126 +			 X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
  1.1127 +
  1.1128 +int set_cert_ex(unsigned long *flags, const char *arg)
  1.1129 +{
  1.1130 +	static const NAME_EX_TBL cert_tbl[] = {
  1.1131 +		{ "compatible", X509_FLAG_COMPAT, 0xffffffffl},
  1.1132 +		{ "ca_default", X509_FLAG_CA, 0xffffffffl},
  1.1133 +		{ "no_header", X509_FLAG_NO_HEADER, 0},
  1.1134 +		{ "no_version", X509_FLAG_NO_VERSION, 0},
  1.1135 +		{ "no_serial", X509_FLAG_NO_SERIAL, 0},
  1.1136 +		{ "no_signame", X509_FLAG_NO_SIGNAME, 0},
  1.1137 +		{ "no_validity", X509_FLAG_NO_VALIDITY, 0},
  1.1138 +		{ "no_subject", X509_FLAG_NO_SUBJECT, 0},
  1.1139 +		{ "no_issuer", X509_FLAG_NO_ISSUER, 0},
  1.1140 +		{ "no_pubkey", X509_FLAG_NO_PUBKEY, 0},
  1.1141 +		{ "no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
  1.1142 +		{ "no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
  1.1143 +		{ "no_aux", X509_FLAG_NO_AUX, 0},
  1.1144 +		{ "no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
  1.1145 +		{ "ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
  1.1146 +		{ "ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
  1.1147 +		{ "ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
  1.1148 +		{ "ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
  1.1149 +		{ NULL, 0, 0}
  1.1150 +	};
  1.1151 +	return set_multi_opts(flags, arg, cert_tbl);
  1.1152 +}
  1.1153 +
  1.1154 +int set_name_ex(unsigned long *flags, const char *arg)
  1.1155 +{
  1.1156 +	static const NAME_EX_TBL ex_tbl[] = {
  1.1157 +		{ "esc_2253", ASN1_STRFLGS_ESC_2253, 0},
  1.1158 +		{ "esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
  1.1159 +		{ "esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
  1.1160 +		{ "use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
  1.1161 +		{ "utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
  1.1162 +		{ "ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
  1.1163 +		{ "show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
  1.1164 +		{ "dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
  1.1165 +		{ "dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
  1.1166 +		{ "dump_der", ASN1_STRFLGS_DUMP_DER, 0},
  1.1167 +		{ "compat", XN_FLAG_COMPAT, 0xffffffffL},
  1.1168 +		{ "sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
  1.1169 +		{ "sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
  1.1170 +		{ "sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
  1.1171 +		{ "sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
  1.1172 +		{ "dn_rev", XN_FLAG_DN_REV, 0},
  1.1173 +		{ "nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
  1.1174 +		{ "sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
  1.1175 +		{ "lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
  1.1176 +		{ "align", XN_FLAG_FN_ALIGN, 0},
  1.1177 +		{ "oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
  1.1178 +		{ "space_eq", XN_FLAG_SPC_EQ, 0},
  1.1179 +		{ "dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
  1.1180 +		{ "RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
  1.1181 +		{ "oneline", XN_FLAG_ONELINE, 0xffffffffL},
  1.1182 +		{ "multiline", XN_FLAG_MULTILINE, 0xffffffffL},
  1.1183 +		{ "ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
  1.1184 +		{ NULL, 0, 0}
  1.1185 +	};
  1.1186 +	return set_multi_opts(flags, arg, ex_tbl);
  1.1187 +}
  1.1188 +
  1.1189 +int set_ext_copy(int *copy_type, const char *arg)
  1.1190 +{
  1.1191 +	if (!strcasecmp(arg, "none"))
  1.1192 +		*copy_type = EXT_COPY_NONE;
  1.1193 +	else if (!strcasecmp(arg, "copy"))
  1.1194 +		*copy_type = EXT_COPY_ADD;
  1.1195 +	else if (!strcasecmp(arg, "copyall"))
  1.1196 +		*copy_type = EXT_COPY_ALL;
  1.1197 +	else
  1.1198 +		return 0;
  1.1199 +	return 1;
  1.1200 +}
  1.1201 +
  1.1202 +int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
  1.1203 +{
  1.1204 +	STACK_OF(X509_EXTENSION) *exts = NULL;
  1.1205 +	X509_EXTENSION *ext, *tmpext;
  1.1206 +	ASN1_OBJECT *obj;
  1.1207 +	int i, idx, ret = 0;
  1.1208 +	if (!x || !req || (copy_type == EXT_COPY_NONE))
  1.1209 +		return 1;
  1.1210 +	exts = X509_REQ_get_extensions(req);
  1.1211 +
  1.1212 +	for(i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
  1.1213 +		ext = sk_X509_EXTENSION_value(exts, i);
  1.1214 +		obj = X509_EXTENSION_get_object(ext);
  1.1215 +		idx = X509_get_ext_by_OBJ(x, obj, -1);
  1.1216 +		/* Does extension exist? */
  1.1217 +		if (idx != -1) {
  1.1218 +			/* If normal copy don't override existing extension */
  1.1219 +			if (copy_type == EXT_COPY_ADD)
  1.1220 +				continue;
  1.1221 +			/* Delete all extensions of same type */
  1.1222 +			do {
  1.1223 +				tmpext = X509_get_ext(x, idx);
  1.1224 +				X509_delete_ext(x, idx);
  1.1225 +				X509_EXTENSION_free(tmpext);
  1.1226 +				idx = X509_get_ext_by_OBJ(x, obj, -1);
  1.1227 +			} while (idx != -1);
  1.1228 +		}
  1.1229 +		if (!X509_add_ext(x, ext, -1))
  1.1230 +			goto end;
  1.1231 +	}
  1.1232 +
  1.1233 +	ret = 1;
  1.1234 +
  1.1235 +	end:
  1.1236 +
  1.1237 +	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
  1.1238 +
  1.1239 +	return ret;
  1.1240 +}
  1.1241 +		
  1.1242 +		
  1.1243 +			
  1.1244 +
  1.1245 +static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl)
  1.1246 +{
  1.1247 +	STACK_OF(CONF_VALUE) *vals;
  1.1248 +	CONF_VALUE *val;
  1.1249 +	int i, ret = 1;
  1.1250 +	if(!arg) return 0;
  1.1251 +	vals = X509V3_parse_list(arg);
  1.1252 +	for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
  1.1253 +		val = sk_CONF_VALUE_value(vals, i);
  1.1254 +		if (!set_table_opts(flags, val->name, in_tbl))
  1.1255 +			ret = 0;
  1.1256 +	}
  1.1257 +	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
  1.1258 +	return ret;
  1.1259 +}
  1.1260 +
  1.1261 +static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl)
  1.1262 +{
  1.1263 +	char c;
  1.1264 +	const NAME_EX_TBL *ptbl;
  1.1265 +	c = arg[0];
  1.1266 +
  1.1267 +	if(c == '-') {
  1.1268 +		c = 0;
  1.1269 +		arg++;
  1.1270 +	} else if (c == '+') {
  1.1271 +		c = 1;
  1.1272 +		arg++;
  1.1273 +	} else c = 1;
  1.1274 +
  1.1275 +	for(ptbl = in_tbl; ptbl->name; ptbl++) {
  1.1276 +		if(!strcasecmp(arg, ptbl->name)) {
  1.1277 +			*flags &= ~ptbl->mask;
  1.1278 +			if(c) *flags |= ptbl->flag;
  1.1279 +			else *flags &= ~ptbl->flag;
  1.1280 +			return 1;
  1.1281 +		}
  1.1282 +	}
  1.1283 +	return 0;
  1.1284 +}
  1.1285 +
  1.1286 +void print_name(BIO *out, const char *title, X509_NAME *nm, unsigned long lflags)
  1.1287 +{
  1.1288 +	char *buf;
  1.1289 +	char mline = 0;
  1.1290 +	int indent = 0;
  1.1291 +
  1.1292 +	if(title) BIO_puts(out, title);
  1.1293 +	if((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
  1.1294 +		mline = 1;
  1.1295 +		indent = 4;
  1.1296 +	}
  1.1297 +	if(lflags == XN_FLAG_COMPAT) {
  1.1298 +		buf = X509_NAME_oneline(nm, 0, 0);
  1.1299 +		BIO_puts(out, buf);
  1.1300 +		BIO_puts(out, "\n");
  1.1301 +		OPENSSL_free(buf);
  1.1302 +	} else {
  1.1303 +		if(mline) BIO_puts(out, "\n");
  1.1304 +		X509_NAME_print_ex(out, nm, indent, lflags);
  1.1305 +		BIO_puts(out, "\n");
  1.1306 +	}
  1.1307 +}
  1.1308 +
  1.1309 +X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath)
  1.1310 +{
  1.1311 +	X509_STORE *store;
  1.1312 +	X509_LOOKUP *lookup;
  1.1313 +	if(!(store = X509_STORE_new())) goto end;
  1.1314 +	lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
  1.1315 +	if (lookup == NULL) goto end;
  1.1316 +	if (CAfile) {
  1.1317 +		if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
  1.1318 +			BIO_printf(bp, "Error loading file %s\n", CAfile);
  1.1319 +			goto end;
  1.1320 +		}
  1.1321 +	} else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
  1.1322 +		
  1.1323 +	lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
  1.1324 +	if (lookup == NULL) goto end;
  1.1325 +	if (CApath) {
  1.1326 +		if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
  1.1327 +			BIO_printf(bp, "Error loading directory %s\n", CApath);
  1.1328 +			goto end;
  1.1329 +		}
  1.1330 +	} else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
  1.1331 +
  1.1332 +	ERR_clear_error();
  1.1333 +	return store;
  1.1334 +	end:
  1.1335 +	X509_STORE_free(store);
  1.1336 +	return NULL;
  1.1337 +}
  1.1338 +
  1.1339 +#ifndef OPENSSL_NO_ENGINE
  1.1340 +/* Try to load an engine in a shareable library */
  1.1341 +static ENGINE *try_load_engine(BIO *err, const char *engine, int debug)
  1.1342 +	{
  1.1343 +	ENGINE *e = ENGINE_by_id("dynamic");
  1.1344 +	if (e)
  1.1345 +		{
  1.1346 +		if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
  1.1347 +			|| !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
  1.1348 +			{
  1.1349 +			ENGINE_free(e);
  1.1350 +			e = NULL;
  1.1351 +			}
  1.1352 +		}
  1.1353 +	return e;
  1.1354 +	}
  1.1355 +
  1.1356 +ENGINE *setup_engine(BIO *err, const char *engine, int debug)
  1.1357 +        {
  1.1358 +        ENGINE *e = NULL;
  1.1359 +
  1.1360 +        if (engine)
  1.1361 +                {
  1.1362 +		if(strcmp(engine, "auto") == 0)
  1.1363 +			{
  1.1364 +			BIO_printf(err,"enabling auto ENGINE support\n");
  1.1365 +			ENGINE_register_all_complete();
  1.1366 +			return NULL;
  1.1367 +			}
  1.1368 +		if((e = ENGINE_by_id(engine)) == NULL
  1.1369 +			&& (e = try_load_engine(err, engine, debug)) == NULL)
  1.1370 +			{
  1.1371 +			BIO_printf(err,"invalid engine \"%s\"\n", engine);
  1.1372 +			ERR_print_errors(err);
  1.1373 +			return NULL;
  1.1374 +			}
  1.1375 +		if (debug)
  1.1376 +			{
  1.1377 +			ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM,
  1.1378 +				0, err, 0);
  1.1379 +			}
  1.1380 +                ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1);
  1.1381 +		if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
  1.1382 +			{
  1.1383 +			BIO_printf(err,"can't use that engine\n");
  1.1384 +			ERR_print_errors(err);
  1.1385 +			ENGINE_free(e);
  1.1386 +			return NULL;
  1.1387 +			}
  1.1388 +
  1.1389 +		BIO_printf(err,"engine \"%s\" set.\n", ENGINE_get_id(e));
  1.1390 +
  1.1391 +		/* Free our "structural" reference. */
  1.1392 +		ENGINE_free(e);
  1.1393 +		}
  1.1394 +        return e;
  1.1395 +        }
  1.1396 +#endif
  1.1397 +
  1.1398 +int load_config(BIO *err, CONF *cnf)
  1.1399 +	{
  1.1400 +	if (!cnf)
  1.1401 +		cnf = config;
  1.1402 +	if (!cnf)
  1.1403 +		return 1;
  1.1404 +
  1.1405 +	OPENSSL_load_builtin_modules();
  1.1406 +
  1.1407 +	if (CONF_modules_load(cnf, NULL, 0) <= 0)
  1.1408 +		{
  1.1409 +		BIO_printf(err, "Error configuring OpenSSL\n");
  1.1410 +		ERR_print_errors(err);
  1.1411 +		return 0;
  1.1412 +		}
  1.1413 +	return 1;
  1.1414 +	}
  1.1415 +
  1.1416 +char *make_config_name()
  1.1417 +	{
  1.1418 +	const char *t=X509_get_default_cert_area();
  1.1419 +	size_t len;
  1.1420 +	char *p;
  1.1421 +
  1.1422 +	len=strlen(t)+strlen(OPENSSL_CONF)+2;
  1.1423 +	p=OPENSSL_malloc(len);
  1.1424 +	BUF_strlcpy(p,t,len);
  1.1425 +#ifndef OPENSSL_SYS_VMS
  1.1426 +	BUF_strlcat(p,"/",len);
  1.1427 +#endif
  1.1428 +	BUF_strlcat(p,OPENSSL_CONF,len);
  1.1429 +
  1.1430 +	return p;
  1.1431 +	}
  1.1432 +
  1.1433 +static unsigned long index_serial_hash(const char **a)
  1.1434 +	{
  1.1435 +	const char *n;
  1.1436 +
  1.1437 +	n=a[DB_serial];
  1.1438 +	while (*n == '0') n++;
  1.1439 +	return(lh_strhash(n));
  1.1440 +	}
  1.1441 +
  1.1442 +static int index_serial_cmp(const char **a, const char **b)
  1.1443 +	{
  1.1444 +	const char *aa,*bb;
  1.1445 +
  1.1446 +	for (aa=a[DB_serial]; *aa == '0'; aa++);
  1.1447 +	for (bb=b[DB_serial]; *bb == '0'; bb++);
  1.1448 +	return(strcmp(aa,bb));
  1.1449 +	}
  1.1450 +
  1.1451 +static int index_name_qual(char **a)
  1.1452 +	{ return(a[0][0] == 'V'); }
  1.1453 +
  1.1454 +static unsigned long index_name_hash(const char **a)
  1.1455 +	{ return(lh_strhash(a[DB_name])); }
  1.1456 +
  1.1457 +int index_name_cmp(const char **a, const char **b)
  1.1458 +	{ return(strcmp(a[DB_name],
  1.1459 +	     b[DB_name])); }
  1.1460 +
  1.1461 +static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
  1.1462 +static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
  1.1463 +static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
  1.1464 +static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
  1.1465 +
  1.1466 +#undef BSIZE
  1.1467 +#define BSIZE 256
  1.1468 +
  1.1469 +BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai)
  1.1470 +	{
  1.1471 +	BIO *in=NULL;
  1.1472 +	BIGNUM *ret=NULL;
  1.1473 +	MS_STATIC char buf[1024];
  1.1474 +	ASN1_INTEGER *ai=NULL;
  1.1475 +
  1.1476 +	ai=ASN1_INTEGER_new();
  1.1477 +	if (ai == NULL) goto err;
  1.1478 +
  1.1479 +	if ((in=BIO_new(BIO_s_file())) == NULL)
  1.1480 +		{
  1.1481 +		ERR_print_errors(bio_err);
  1.1482 +		goto err;
  1.1483 +		}
  1.1484 +
  1.1485 +	if (BIO_read_filename(in,serialfile) <= 0)
  1.1486 +		{
  1.1487 +		if (!create)
  1.1488 +			{
  1.1489 +			perror(serialfile);
  1.1490 +			goto err;
  1.1491 +			}
  1.1492 +		else
  1.1493 +			{
  1.1494 +			ret=BN_new();
  1.1495 +			if (ret == NULL || !rand_serial(ret, ai))
  1.1496 +				BIO_printf(bio_err, "Out of memory\n");
  1.1497 +			}
  1.1498 +		}
  1.1499 +	else
  1.1500 +		{
  1.1501 +		if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
  1.1502 +			{
  1.1503 +			BIO_printf(bio_err,"unable to load number from %s\n",
  1.1504 +				serialfile);
  1.1505 +			goto err;
  1.1506 +			}
  1.1507 +		ret=ASN1_INTEGER_to_BN(ai,NULL);
  1.1508 +		if (ret == NULL)
  1.1509 +			{
  1.1510 +			BIO_printf(bio_err,"error converting number from bin to BIGNUM\n");
  1.1511 +			goto err;
  1.1512 +			}
  1.1513 +		}
  1.1514 +
  1.1515 +	if (ret && retai)
  1.1516 +		{
  1.1517 +		*retai = ai;
  1.1518 +		ai = NULL;
  1.1519 +		}
  1.1520 + err:
  1.1521 +	if (in != NULL) BIO_free(in);
  1.1522 +	if (ai != NULL) ASN1_INTEGER_free(ai);
  1.1523 +	return(ret);
  1.1524 +	}
  1.1525 +
  1.1526 +int save_serial(char *serialfile, char *suffix, BIGNUM *serial, ASN1_INTEGER **retai)
  1.1527 +	{
  1.1528 +	char buf[1][BSIZE];
  1.1529 +	BIO *out = NULL;
  1.1530 +	int ret=0;
  1.1531 +	ASN1_INTEGER *ai=NULL;
  1.1532 +	int j;
  1.1533 +
  1.1534 +	if (suffix == NULL)
  1.1535 +		j = strlen(serialfile);
  1.1536 +	else
  1.1537 +		j = strlen(serialfile) + strlen(suffix) + 1;
  1.1538 +	if (j >= BSIZE)
  1.1539 +		{
  1.1540 +		BIO_printf(bio_err,"file name too long\n");
  1.1541 +		goto err;
  1.1542 +		}
  1.1543 +
  1.1544 +	if (suffix == NULL)
  1.1545 +		BUF_strlcpy(buf[0], serialfile, BSIZE);
  1.1546 +	else
  1.1547 +		{
  1.1548 +#ifndef OPENSSL_SYS_VMS
  1.1549 +		j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, suffix);
  1.1550 +#else
  1.1551 +		j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, suffix);
  1.1552 +#endif
  1.1553 +		}
  1.1554 +#ifdef RL_DEBUG
  1.1555 +	BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
  1.1556 +#endif
  1.1557 +	out=BIO_new(BIO_s_file());
  1.1558 +	if (out == NULL)
  1.1559 +		{
  1.1560 +		ERR_print_errors(bio_err);
  1.1561 +		goto err;
  1.1562 +		}
  1.1563 +	if (BIO_write_filename(out,buf[0]) <= 0)
  1.1564 +		{
  1.1565 +		perror(serialfile);
  1.1566 +		goto err;
  1.1567 +		}
  1.1568 +
  1.1569 +	if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
  1.1570 +		{
  1.1571 +		BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
  1.1572 +		goto err;
  1.1573 +		}
  1.1574 +	i2a_ASN1_INTEGER(out,ai);
  1.1575 +	BIO_puts(out,"\n");
  1.1576 +	ret=1;
  1.1577 +	if (retai)
  1.1578 +		{
  1.1579 +		*retai = ai;
  1.1580 +		ai = NULL;
  1.1581 +		}
  1.1582 +err:
  1.1583 +	if (out != NULL) BIO_free_all(out);
  1.1584 +	if (ai != NULL) ASN1_INTEGER_free(ai);
  1.1585 +	return(ret);
  1.1586 +	}
  1.1587 +
  1.1588 +int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix)
  1.1589 +	{
  1.1590 +	char buf[5][BSIZE];
  1.1591 +	int i,j;
  1.1592 +	struct stat sb;
  1.1593 +
  1.1594 +	i = strlen(serialfile) + strlen(old_suffix);
  1.1595 +	j = strlen(serialfile) + strlen(new_suffix);
  1.1596 +	if (i > j) j = i;
  1.1597 +	if (j + 1 >= BSIZE)
  1.1598 +		{
  1.1599 +		BIO_printf(bio_err,"file name too long\n");
  1.1600 +		goto err;
  1.1601 +		}
  1.1602 +
  1.1603 +#ifndef OPENSSL_SYS_VMS
  1.1604 +	j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s",
  1.1605 +		serialfile, new_suffix);
  1.1606 +#else
  1.1607 +	j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s",
  1.1608 +		serialfile, new_suffix);
  1.1609 +#endif
  1.1610 +#ifndef OPENSSL_SYS_VMS
  1.1611 +	j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s",
  1.1612 +		serialfile, old_suffix);
  1.1613 +#else
  1.1614 +	j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s",
  1.1615 +		serialfile, old_suffix);
  1.1616 +#endif
  1.1617 +	if (stat(serialfile,&sb) < 0)
  1.1618 +		{
  1.1619 +		if (errno != ENOENT 
  1.1620 +#ifdef ENOTDIR
  1.1621 +			&& errno != ENOTDIR
  1.1622 +#endif
  1.1623 +		   )
  1.1624 +			goto err;
  1.1625 +		}
  1.1626 +	else
  1.1627 +		{
  1.1628 +#ifdef RL_DEBUG
  1.1629 +		BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
  1.1630 +			serialfile, buf[1]);
  1.1631 +#endif
  1.1632 +		if (rename(serialfile,buf[1]) < 0)
  1.1633 +			{
  1.1634 +			BIO_printf(bio_err,
  1.1635 +				"unable to rename %s to %s\n",
  1.1636 +				serialfile, buf[1]);
  1.1637 +			perror("reason");
  1.1638 +			goto err;
  1.1639 +			}
  1.1640 +		}
  1.1641 +#ifdef RL_DEBUG
  1.1642 +	BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
  1.1643 +		buf[0],serialfile);
  1.1644 +#endif
  1.1645 +	if (rename(buf[0],serialfile) < 0)
  1.1646 +		{
  1.1647 +		BIO_printf(bio_err,
  1.1648 +			"unable to rename %s to %s\n",
  1.1649 +			buf[0],serialfile);
  1.1650 +		perror("reason");
  1.1651 +		rename(buf[1],serialfile);
  1.1652 +		goto err;
  1.1653 +		}
  1.1654 +	return 1;
  1.1655 + err:
  1.1656 +	return 0;
  1.1657 +	}
  1.1658 +
  1.1659 +int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
  1.1660 +	{
  1.1661 +	BIGNUM *btmp;
  1.1662 +	int ret = 0;
  1.1663 +	if (b)
  1.1664 +		btmp = b;
  1.1665 +	else
  1.1666 +		btmp = BN_new();
  1.1667 +
  1.1668 +	if (!btmp)
  1.1669 +		return 0;
  1.1670 +
  1.1671 +	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
  1.1672 +		goto error;
  1.1673 +	if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
  1.1674 +		goto error;
  1.1675 +
  1.1676 +	ret = 1;
  1.1677 +	
  1.1678 +	error:
  1.1679 +
  1.1680 +	if (!b)
  1.1681 +		BN_free(btmp);
  1.1682 +	
  1.1683 +	return ret;
  1.1684 +	}
  1.1685 +
  1.1686 +CA_DB *load_index(char *dbfile, DB_ATTR *db_attr)
  1.1687 +	{
  1.1688 +	CA_DB *retdb = NULL;
  1.1689 +	TXT_DB *tmpdb = NULL;
  1.1690 +	BIO *in = BIO_new(BIO_s_file());
  1.1691 +	CONF *dbattr_conf = NULL;
  1.1692 +	char buf[1][BSIZE];
  1.1693 +	long errorline= -1;
  1.1694 +
  1.1695 +	if (in == NULL)
  1.1696 +		{
  1.1697 +		ERR_print_errors(bio_err);
  1.1698 +		goto err;
  1.1699 +		}
  1.1700 +	if (BIO_read_filename(in,dbfile) <= 0)
  1.1701 +		{
  1.1702 +		perror(dbfile);
  1.1703 +		BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
  1.1704 +		goto err;
  1.1705 +		}
  1.1706 +	if ((tmpdb = TXT_DB_read(in,DB_NUMBER)) == NULL)
  1.1707 +		{
  1.1708 +		if (tmpdb != NULL) TXT_DB_free(tmpdb);
  1.1709 +		goto err;
  1.1710 +		}
  1.1711 +
  1.1712 +#ifndef OPENSSL_SYS_VMS
  1.1713 +	BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile);
  1.1714 +#else
  1.1715 +	BIO_snprintf(buf[0], sizeof buf[0], "%s-attr", dbfile);
  1.1716 +#endif
  1.1717 +	dbattr_conf = NCONF_new(NULL);
  1.1718 +	if (NCONF_load(dbattr_conf,buf[0],&errorline) <= 0)
  1.1719 +		{
  1.1720 +		if (errorline > 0)
  1.1721 +			{
  1.1722 +			BIO_printf(bio_err,
  1.1723 +				"error on line %ld of db attribute file '%s'\n"
  1.1724 +				,errorline,buf[0]);
  1.1725 +			goto err;
  1.1726 +			}
  1.1727 +		else
  1.1728 +			{
  1.1729 +			NCONF_free(dbattr_conf);
  1.1730 +			dbattr_conf = NULL;
  1.1731 +			}
  1.1732 +		}
  1.1733 +
  1.1734 +	if ((retdb = OPENSSL_malloc(sizeof(CA_DB))) == NULL)
  1.1735 +		{
  1.1736 +		fprintf(stderr, "Out of memory\n");
  1.1737 +		goto err;
  1.1738 +		}
  1.1739 +
  1.1740 +	retdb->db = tmpdb;
  1.1741 +	tmpdb = NULL;
  1.1742 +	if (db_attr)
  1.1743 +		retdb->attributes = *db_attr;
  1.1744 +	else
  1.1745 +		{
  1.1746 +		retdb->attributes.unique_subject = 1;
  1.1747 +		}
  1.1748 +
  1.1749 +	if (dbattr_conf)
  1.1750 +		{
  1.1751 +		char *p = NCONF_get_string(dbattr_conf,NULL,"unique_subject");
  1.1752 +		if (p)
  1.1753 +			{
  1.1754 +#ifdef RL_DEBUG
  1.1755 +			BIO_printf(bio_err, "DEBUG[load_index]: unique_subject = \"%s\"\n", p);
  1.1756 +#endif
  1.1757 +			retdb->attributes.unique_subject = parse_yesno(p,1);
  1.1758 +			}
  1.1759 +		}
  1.1760 +
  1.1761 + err:
  1.1762 +	if (dbattr_conf) NCONF_free(dbattr_conf);
  1.1763 +	if (tmpdb) TXT_DB_free(tmpdb);
  1.1764 +	if (in) BIO_free_all(in);
  1.1765 +	return retdb;
  1.1766 +	}
  1.1767 +
  1.1768 +int index_index(CA_DB *db)
  1.1769 +	{
  1.1770 +	if (!TXT_DB_create_index(db->db, DB_serial, NULL,
  1.1771 +				LHASH_HASH_FN(index_serial_hash),
  1.1772 +				LHASH_COMP_FN(index_serial_cmp)))
  1.1773 +		{
  1.1774 +		BIO_printf(bio_err,
  1.1775 +		  "error creating serial number index:(%ld,%ld,%ld)\n",
  1.1776 +		  			db->db->error,db->db->arg1,db->db->arg2);
  1.1777 +			return 0;
  1.1778 +		}
  1.1779 +
  1.1780 +	if (db->attributes.unique_subject
  1.1781 +		&& !TXT_DB_create_index(db->db, DB_name, index_name_qual,
  1.1782 +			LHASH_HASH_FN(index_name_hash),
  1.1783 +			LHASH_COMP_FN(index_name_cmp)))
  1.1784 +		{
  1.1785 +		BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
  1.1786 +			db->db->error,db->db->arg1,db->db->arg2);
  1.1787 +		return 0;
  1.1788 +		}
  1.1789 +	return 1;
  1.1790 +	}
  1.1791 +
  1.1792 +int save_index(const char *dbfile, const char *suffix, CA_DB *db)
  1.1793 +	{
  1.1794 +	char buf[3][BSIZE];
  1.1795 +	BIO *out = BIO_new(BIO_s_file());
  1.1796 +	int j;
  1.1797 +
  1.1798 +	if (out == NULL)
  1.1799 +		{
  1.1800 +		ERR_print_errors(bio_err);
  1.1801 +		goto err;
  1.1802 +		}
  1.1803 +
  1.1804 +	j = strlen(dbfile) + strlen(suffix);
  1.1805 +	if (j + 6 >= BSIZE)
  1.1806 +		{
  1.1807 +		BIO_printf(bio_err,"file name too long\n");
  1.1808 +		goto err;
  1.1809 +		}
  1.1810 +
  1.1811 +#ifndef OPENSSL_SYS_VMS
  1.1812 +	j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr", dbfile);
  1.1813 +#else
  1.1814 +	j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr", dbfile);
  1.1815 +#endif
  1.1816 +#ifndef OPENSSL_SYS_VMS
  1.1817 +	j = BIO_snprintf(buf[1], sizeof buf[1], "%s.attr.%s", dbfile, suffix);
  1.1818 +#else
  1.1819 +	j = BIO_snprintf(buf[1], sizeof buf[1], "%s-attr-%s", dbfile, suffix);
  1.1820 +#endif
  1.1821 +#ifndef OPENSSL_SYS_VMS
  1.1822 +	j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, suffix);
  1.1823 +#else
  1.1824 +	j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, suffix);
  1.1825 +#endif
  1.1826 +#ifdef RL_DEBUG
  1.1827 +	BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
  1.1828 +#endif
  1.1829 +	if (BIO_write_filename(out,buf[0]) <= 0)
  1.1830 +		{
  1.1831 +		perror(dbfile);
  1.1832 +		BIO_printf(bio_err,"unable to open '%s'\n", dbfile);
  1.1833 +		goto err;
  1.1834 +		}
  1.1835 +	j=TXT_DB_write(out,db->db);
  1.1836 +	if (j <= 0) goto err;
  1.1837 +			
  1.1838 +	BIO_free(out);
  1.1839 +
  1.1840 +	out = BIO_new(BIO_s_file());
  1.1841 +#ifdef RL_DEBUG
  1.1842 +	BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[1]);
  1.1843 +#endif
  1.1844 +	if (BIO_write_filename(out,buf[1]) <= 0)
  1.1845 +		{
  1.1846 +		perror(buf[2]);
  1.1847 +		BIO_printf(bio_err,"unable to open '%s'\n", buf[2]);
  1.1848 +		goto err;
  1.1849 +		}
  1.1850 +	BIO_printf(out,"unique_subject = %s\n",
  1.1851 +		db->attributes.unique_subject ? "yes" : "no");
  1.1852 +	BIO_free(out);
  1.1853 +
  1.1854 +	return 1;
  1.1855 + err:
  1.1856 +	return 0;
  1.1857 +	}
  1.1858 +
  1.1859 +int rotate_index(const char *dbfile, const char *new_suffix, const char *old_suffix)
  1.1860 +	{
  1.1861 +	char buf[5][BSIZE];
  1.1862 +	int i,j;
  1.1863 +	struct stat sb;
  1.1864 +
  1.1865 +	i = strlen(dbfile) + strlen(old_suffix);
  1.1866 +	j = strlen(dbfile) + strlen(new_suffix);
  1.1867 +	if (i > j) j = i;
  1.1868 +	if (j + 6 >= BSIZE)
  1.1869 +		{
  1.1870 +		BIO_printf(bio_err,"file name too long\n");
  1.1871 +		goto err;
  1.1872 +		}
  1.1873 +
  1.1874 +#ifndef OPENSSL_SYS_VMS
  1.1875 +	j = BIO_snprintf(buf[4], sizeof buf[4], "%s.attr", dbfile);
  1.1876 +#else
  1.1877 +	j = BIO_snprintf(buf[4], sizeof buf[4], "%s-attr", dbfile);
  1.1878 +#endif
  1.1879 +#ifndef OPENSSL_SYS_VMS
  1.1880 +	j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr.%s",
  1.1881 +		dbfile, new_suffix);
  1.1882 +#else
  1.1883 +	j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr-%s",
  1.1884 +		dbfile, new_suffix);
  1.1885 +#endif
  1.1886 +#ifndef OPENSSL_SYS_VMS
  1.1887 +	j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s",
  1.1888 +		dbfile, new_suffix);
  1.1889 +#else
  1.1890 +	j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s",
  1.1891 +		dbfile, new_suffix);
  1.1892 +#endif
  1.1893 +#ifndef OPENSSL_SYS_VMS
  1.1894 +	j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s",
  1.1895 +		dbfile, old_suffix);
  1.1896 +#else
  1.1897 +	j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s",
  1.1898 +		dbfile, old_suffix);
  1.1899 +#endif
  1.1900 +#ifndef OPENSSL_SYS_VMS
  1.1901 +	j = BIO_snprintf(buf[3], sizeof buf[3], "%s.attr.%s",
  1.1902 +		dbfile, old_suffix);
  1.1903 +#else
  1.1904 +	j = BIO_snprintf(buf[3], sizeof buf[3], "%s-attr-%s",
  1.1905 +		dbfile, old_suffix);
  1.1906 +#endif
  1.1907 +	if (stat(dbfile,&sb) < 0)
  1.1908 +		{
  1.1909 +		if (errno != ENOENT 
  1.1910 +#ifdef ENOTDIR
  1.1911 +			&& errno != ENOTDIR
  1.1912 +#endif
  1.1913 +		   )
  1.1914 +			goto err;
  1.1915 +		}
  1.1916 +	else
  1.1917 +		{
  1.1918 +#ifdef RL_DEBUG
  1.1919 +		BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
  1.1920 +			dbfile, buf[1]);
  1.1921 +#endif
  1.1922 +		if (rename(dbfile,buf[1]) < 0)
  1.1923 +			{
  1.1924 +			BIO_printf(bio_err,
  1.1925 +				"unable to rename %s to %s\n",
  1.1926 +				dbfile, buf[1]);
  1.1927 +			perror("reason");
  1.1928 +			goto err;
  1.1929 +			}
  1.1930 +		}
  1.1931 +#ifdef RL_DEBUG
  1.1932 +	BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
  1.1933 +		buf[0],dbfile);
  1.1934 +#endif
  1.1935 +	if (rename(buf[0],dbfile) < 0)
  1.1936 +		{
  1.1937 +		BIO_printf(bio_err,
  1.1938 +			"unable to rename %s to %s\n",
  1.1939 +			buf[0],dbfile);
  1.1940 +		perror("reason");
  1.1941 +		rename(buf[1],dbfile);
  1.1942 +		goto err;
  1.1943 +		}
  1.1944 +	if (stat(buf[4],&sb) < 0)
  1.1945 +		{
  1.1946 +		if (errno != ENOENT 
  1.1947 +#ifdef ENOTDIR
  1.1948 +			&& errno != ENOTDIR
  1.1949 +#endif
  1.1950 +		   )
  1.1951 +			goto err;
  1.1952 +		}
  1.1953 +	else
  1.1954 +		{
  1.1955 +#ifdef RL_DEBUG
  1.1956 +		BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
  1.1957 +			buf[4],buf[3]);
  1.1958 +#endif
  1.1959 +		if (rename(buf[4],buf[3]) < 0)
  1.1960 +			{
  1.1961 +			BIO_printf(bio_err,
  1.1962 +				"unable to rename %s to %s\n",
  1.1963 +				buf[4], buf[3]);
  1.1964 +			perror("reason");
  1.1965 +			rename(dbfile,buf[0]);
  1.1966 +			rename(buf[1],dbfile);
  1.1967 +			goto err;
  1.1968 +			}
  1.1969 +		}
  1.1970 +#ifdef RL_DEBUG
  1.1971 +	BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
  1.1972 +		buf[2],buf[4]);
  1.1973 +#endif
  1.1974 +	if (rename(buf[2],buf[4]) < 0)
  1.1975 +		{
  1.1976 +		BIO_printf(bio_err,
  1.1977 +			"unable to rename %s to %s\n",
  1.1978 +			buf[2],buf[4]);
  1.1979 +		perror("reason");
  1.1980 +		rename(buf[3],buf[4]);
  1.1981 +		rename(dbfile,buf[0]);
  1.1982 +		rename(buf[1],dbfile);
  1.1983 +		goto err;
  1.1984 +		}
  1.1985 +	return 1;
  1.1986 + err:
  1.1987 +	return 0;
  1.1988 +	}
  1.1989 +
  1.1990 +void free_index(CA_DB *db)
  1.1991 +	{
  1.1992 +	if (db)
  1.1993 +		{
  1.1994 +		if (db->db) TXT_DB_free(db->db);
  1.1995 +		OPENSSL_free(db);
  1.1996 +		}
  1.1997 +	}
  1.1998 +
  1.1999 +int parse_yesno(const char *str, int def)
  1.2000 +	{
  1.2001 +	int ret = def;
  1.2002 +	if (str)
  1.2003 +		{
  1.2004 +		switch (*str)
  1.2005 +			{
  1.2006 +		case 'f': /* false */
  1.2007 +		case 'F': /* FALSE */
  1.2008 +		case 'n': /* no */
  1.2009 +		case 'N': /* NO */
  1.2010 +		case '0': /* 0 */
  1.2011 +			ret = 0;
  1.2012 +			break;
  1.2013 +		case 't': /* true */
  1.2014 +		case 'T': /* TRUE */
  1.2015 +		case 'y': /* yes */
  1.2016 +		case 'Y': /* YES */
  1.2017 +		case '1': /* 1 */
  1.2018 +			ret = 0;
  1.2019 +			break;
  1.2020 +		default:
  1.2021 +			ret = def;
  1.2022 +			break;
  1.2023 +			}
  1.2024 +		}
  1.2025 +	return ret;
  1.2026 +	}
  1.2027 +
  1.2028 +/*
  1.2029 + * subject is expected to be in the format /type0=value0/type1=value1/type2=...
  1.2030 + * where characters may be escaped by \
  1.2031 + */
  1.2032 +X509_NAME *parse_name(char *subject, long chtype, int multirdn)
  1.2033 +	{
  1.2034 +	size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
  1.2035 +	char *buf = OPENSSL_malloc(buflen);
  1.2036 +	size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
  1.2037 +	char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
  1.2038 +	char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
  1.2039 +	int *mval = OPENSSL_malloc (max_ne * sizeof (int));
  1.2040 +
  1.2041 +	char *sp = subject, *bp = buf;
  1.2042 +	int i, ne_num = 0;
  1.2043 +
  1.2044 +	X509_NAME *n = NULL;
  1.2045 +	int nid;
  1.2046 +
  1.2047 +	if (!buf || !ne_types || !ne_values)
  1.2048 +		{
  1.2049 +		BIO_printf(bio_err, "malloc error\n");
  1.2050 +		goto error;
  1.2051 +		}	
  1.2052 +
  1.2053 +	if (*subject != '/')
  1.2054 +		{
  1.2055 +		BIO_printf(bio_err, "Subject does not start with '/'.\n");
  1.2056 +		goto error;
  1.2057 +		}
  1.2058 +	sp++; /* skip leading / */
  1.2059 +
  1.2060 +	/* no multivalued RDN by default */
  1.2061 +	mval[ne_num] = 0;
  1.2062 +
  1.2063 +	while (*sp)
  1.2064 +		{
  1.2065 +		/* collect type */
  1.2066 +		ne_types[ne_num] = bp;
  1.2067 +		while (*sp)
  1.2068 +			{
  1.2069 +			if (*sp == '\\') /* is there anything to escape in the type...? */
  1.2070 +				{
  1.2071 +				if (*++sp)
  1.2072 +					*bp++ = *sp++;
  1.2073 +				else	
  1.2074 +					{
  1.2075 +					BIO_printf(bio_err, "escape character at end of string\n");
  1.2076 +					goto error;
  1.2077 +					}
  1.2078 +				}	
  1.2079 +			else if (*sp == '=')
  1.2080 +				{
  1.2081 +				sp++;
  1.2082 +				*bp++ = '\0';
  1.2083 +				break;
  1.2084 +				}
  1.2085 +			else
  1.2086 +				*bp++ = *sp++;
  1.2087 +			}
  1.2088 +		if (!*sp)
  1.2089 +			{
  1.2090 +			BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
  1.2091 +			goto error;
  1.2092 +			}
  1.2093 +		ne_values[ne_num] = bp;
  1.2094 +		while (*sp)
  1.2095 +			{
  1.2096 +			if (*sp == '\\')
  1.2097 +				{
  1.2098 +				if (*++sp)
  1.2099 +					*bp++ = *sp++;
  1.2100 +				else
  1.2101 +					{
  1.2102 +					BIO_printf(bio_err, "escape character at end of string\n");
  1.2103 +					goto error;
  1.2104 +					}
  1.2105 +				}
  1.2106 +			else if (*sp == '/')
  1.2107 +				{
  1.2108 +				sp++;
  1.2109 +				/* no multivalued RDN by default */
  1.2110 +				mval[ne_num+1] = 0;
  1.2111 +				break;
  1.2112 +				}
  1.2113 +			else if (*sp == '+' && multirdn)
  1.2114 +				{
  1.2115 +				/* a not escaped + signals a mutlivalued RDN */
  1.2116 +				sp++;
  1.2117 +				mval[ne_num+1] = -1;
  1.2118 +				break;
  1.2119 +				}
  1.2120 +			else
  1.2121 +				*bp++ = *sp++;
  1.2122 +			}
  1.2123 +		*bp++ = '\0';
  1.2124 +		ne_num++;
  1.2125 +		}	
  1.2126 +
  1.2127 +	if (!(n = X509_NAME_new()))
  1.2128 +		goto error;
  1.2129 +
  1.2130 +	for (i = 0; i < ne_num; i++)
  1.2131 +		{
  1.2132 +		if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
  1.2133 +			{
  1.2134 +			BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
  1.2135 +			continue;
  1.2136 +			}
  1.2137 +
  1.2138 +		if (!*ne_values[i])
  1.2139 +			{
  1.2140 +			BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
  1.2141 +			continue;
  1.2142 +			}
  1.2143 +
  1.2144 +		if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,mval[i]))
  1.2145 +			goto error;
  1.2146 +		}
  1.2147 +
  1.2148 +	OPENSSL_free(ne_values);
  1.2149 +	OPENSSL_free(ne_types);
  1.2150 +	OPENSSL_free(buf);
  1.2151 +	return n;
  1.2152 +
  1.2153 +error:
  1.2154 +	X509_NAME_free(n);
  1.2155 +	if (ne_values)
  1.2156 +		OPENSSL_free(ne_values);
  1.2157 +	if (ne_types)
  1.2158 +		OPENSSL_free(ne_types);
  1.2159 +	if (buf)
  1.2160 +		OPENSSL_free(buf);
  1.2161 +	return NULL;
  1.2162 +}
  1.2163 +
  1.2164 +/* This code MUST COME AFTER anything that uses rename() */
  1.2165 +#ifdef OPENSSL_SYS_WIN32
  1.2166 +int WIN32_rename(const char *from, const char *to)
  1.2167 +	{
  1.2168 +#ifndef OPENSSL_SYS_WINCE
  1.2169 +	/* Windows rename gives an error if 'to' exists, so delete it
  1.2170 +	 * first and ignore file not found errror
  1.2171 +	 */
  1.2172 +	if((remove(to) != 0) && (errno != ENOENT))
  1.2173 +		return -1;
  1.2174 +#undef rename
  1.2175 +	return rename(from, to);
  1.2176 +#else
  1.2177 +	/* convert strings to UNICODE */
  1.2178 +	{
  1.2179 +	BOOL result = FALSE;
  1.2180 +	WCHAR* wfrom;
  1.2181 +	WCHAR* wto;
  1.2182 +	int i;
  1.2183 +	wfrom = malloc((strlen(from)+1)*2);
  1.2184 +	wto = malloc((strlen(to)+1)*2);
  1.2185 +	if (wfrom != NULL && wto != NULL)
  1.2186 +		{
  1.2187 +		for (i=0; i<(int)strlen(from)+1; i++)
  1.2188 +			wfrom[i] = (short)from[i];
  1.2189 +		for (i=0; i<(int)strlen(to)+1; i++)
  1.2190 +			wto[i] = (short)to[i];
  1.2191 +		result = MoveFile(wfrom, wto);
  1.2192 +		}
  1.2193 +	if (wfrom != NULL)
  1.2194 +		free(wfrom);
  1.2195 +	if (wto != NULL)
  1.2196 +		free(wto);
  1.2197 +	return result;
  1.2198 +	}
  1.2199 +#endif
  1.2200 +	}
  1.2201 +#endif
  1.2202 +
  1.2203 +int args_verify(char ***pargs, int *pargc,
  1.2204 +			int *badarg, BIO *err, X509_VERIFY_PARAM **pm)
  1.2205 +	{
  1.2206 +	ASN1_OBJECT *otmp = NULL;
  1.2207 +	unsigned long flags = 0;
  1.2208 +	int i;
  1.2209 +	int purpose = 0;
  1.2210 +	char **oldargs = *pargs;
  1.2211 +	char *arg = **pargs, *argn = (*pargs)[1];
  1.2212 +	if (!strcmp(arg, "-policy"))
  1.2213 +		{
  1.2214 +		if (!argn)
  1.2215 +			*badarg = 1;
  1.2216 +		else
  1.2217 +			{
  1.2218 +			otmp = OBJ_txt2obj(argn, 0);
  1.2219 +			if (!otmp)
  1.2220 +				{
  1.2221 +				BIO_printf(err, "Invalid Policy \"%s\"\n",
  1.2222 +									argn);
  1.2223 +				*badarg = 1;
  1.2224 +				}
  1.2225 +			}
  1.2226 +		(*pargs)++;
  1.2227 +		}
  1.2228 +	else if (strcmp(arg,"-purpose") == 0)
  1.2229 +		{
  1.2230 +		X509_PURPOSE *xptmp;
  1.2231 +		if (!argn)
  1.2232 +			*badarg = 1;
  1.2233 +		else
  1.2234 +			{
  1.2235 +			i = X509_PURPOSE_get_by_sname(argn);
  1.2236 +			if(i < 0)
  1.2237 +				{
  1.2238 +				BIO_printf(err, "unrecognized purpose\n");
  1.2239 +				*badarg = 1;
  1.2240 +				}
  1.2241 +			else
  1.2242 +				{
  1.2243 +				xptmp = X509_PURPOSE_get0(i);
  1.2244 +				purpose = X509_PURPOSE_get_id(xptmp);
  1.2245 +				}
  1.2246 +			}
  1.2247 +		(*pargs)++;
  1.2248 +		}
  1.2249 +	else if (!strcmp(arg, "-ignore_critical"))
  1.2250 +		flags |= X509_V_FLAG_IGNORE_CRITICAL;
  1.2251 +	else if (!strcmp(arg, "-issuer_checks"))
  1.2252 +		flags |= X509_V_FLAG_CB_ISSUER_CHECK;
  1.2253 +	else if (!strcmp(arg, "-crl_check"))
  1.2254 +		flags |=  X509_V_FLAG_CRL_CHECK;
  1.2255 +	else if (!strcmp(arg, "-crl_check_all"))
  1.2256 +		flags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
  1.2257 +	else if (!strcmp(arg, "-policy_check"))
  1.2258 +		flags |= X509_V_FLAG_POLICY_CHECK;
  1.2259 +	else if (!strcmp(arg, "-explicit_policy"))
  1.2260 +		flags |= X509_V_FLAG_EXPLICIT_POLICY;
  1.2261 +	else if (!strcmp(arg, "-x509_strict"))
  1.2262 +		flags |= X509_V_FLAG_X509_STRICT;
  1.2263 +	else if (!strcmp(arg, "-policy_print"))
  1.2264 +		flags |= X509_V_FLAG_NOTIFY_POLICY;
  1.2265 +	else
  1.2266 +		return 0;
  1.2267 +
  1.2268 +	if (*badarg)
  1.2269 +		{
  1.2270 +		if (*pm)
  1.2271 +			X509_VERIFY_PARAM_free(*pm);
  1.2272 +		*pm = NULL;
  1.2273 +		goto end;
  1.2274 +		}
  1.2275 +
  1.2276 +	if (!*pm && !(*pm = X509_VERIFY_PARAM_new()))
  1.2277 +		{
  1.2278 +		*badarg = 1;
  1.2279 +		goto end;
  1.2280 +		}
  1.2281 +
  1.2282 +	if (otmp)
  1.2283 +		X509_VERIFY_PARAM_add0_policy(*pm, otmp);
  1.2284 +	if (flags)
  1.2285 +		X509_VERIFY_PARAM_set_flags(*pm, flags);
  1.2286 +
  1.2287 +	if (purpose)
  1.2288 +		X509_VERIFY_PARAM_set_purpose(*pm, purpose);
  1.2289 +
  1.2290 +	end:
  1.2291 +
  1.2292 +	(*pargs)++;
  1.2293 +
  1.2294 +	if (pargc)
  1.2295 +		*pargc -= *pargs - oldargs;
  1.2296 +
  1.2297 +	return 1;
  1.2298 +
  1.2299 +	}
  1.2300 +
  1.2301 +static void nodes_print(BIO *out, const char *name,
  1.2302 +	STACK_OF(X509_POLICY_NODE) *nodes)
  1.2303 +	{
  1.2304 +	X509_POLICY_NODE *node;
  1.2305 +	int i;
  1.2306 +	BIO_printf(out, "%s Policies:", name);
  1.2307 +	if (nodes)
  1.2308 +		{
  1.2309 +		BIO_puts(out, "\n");
  1.2310 +		for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++)
  1.2311 +			{
  1.2312 +			node = sk_X509_POLICY_NODE_value(nodes, i);
  1.2313 +			X509_POLICY_NODE_print(out, node, 2);
  1.2314 +			}
  1.2315 +		}
  1.2316 +	else
  1.2317 +		BIO_puts(out, " <empty>\n");
  1.2318 +	}
  1.2319 +
  1.2320 +void policies_print(BIO *out, X509_STORE_CTX *ctx)
  1.2321 +	{
  1.2322 +	X509_POLICY_TREE *tree;
  1.2323 +	int explicit_policy;
  1.2324 +	int free_out = 0;
  1.2325 +	if (out == NULL)
  1.2326 +		{
  1.2327 +		out = BIO_new_fp(stderr, BIO_NOCLOSE);
  1.2328 +		free_out = 1;
  1.2329 +		}
  1.2330 +	tree = X509_STORE_CTX_get0_policy_tree(ctx);
  1.2331 +	explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
  1.2332 +
  1.2333 +	BIO_printf(out, "Require explicit Policy: %s\n",
  1.2334 +				explicit_policy ? "True" : "False");
  1.2335 +
  1.2336 +	nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree));
  1.2337 +	nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree));
  1.2338 +	if (free_out)
  1.2339 +		BIO_free(out);
  1.2340 +	}