smime.c 18.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
/* smime.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
 * project 1999.
 */
/* ====================================================================
 * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    licensing@OpenSSL.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */

/* S/MIME utility function */

#include <stdio.h>
#include <string.h>
63
#include "apps.h"
64
#include <openssl/crypto.h>
65 66 67 68 69 70
#include <openssl/pem.h>
#include <openssl/err.h>

#undef PROG
#define PROG smime_main
static X509 *load_cert(char *file);
71
static EVP_PKEY *load_key(char *file, char *pass);
72 73
static STACK_OF(X509) *load_certs(char *file);
static X509_STORE *setup_verify(char *CAfile, char *CApath);
74
static int save_certs(char *signerfile, STACK_OF(X509) *signers);
75 76 77 78 79 80 81 82

#define SMIME_OP	0x10
#define SMIME_ENCRYPT	(1 | SMIME_OP)
#define SMIME_DECRYPT	2
#define SMIME_SIGN	(3 | SMIME_OP)
#define SMIME_VERIFY	4
#define SMIME_PK7OUT	5

83 84
int MAIN(int, char **);

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
int MAIN(int argc, char **argv)
{
	int operation = 0;
	int ret = 0;
	char **args;
	char *inmode = "r", *outmode = "w";
	char *infile = NULL, *outfile = NULL;
	char *signerfile = NULL, *recipfile = NULL;
	char *certfile = NULL, *keyfile = NULL;
	EVP_CIPHER *cipher = NULL;
	PKCS7 *p7 = NULL;
	X509_STORE *store = NULL;
	X509 *cert = NULL, *recip = NULL, *signer = NULL;
	EVP_PKEY *key = NULL;
	STACK_OF(X509) *encerts = NULL, *other = NULL;
	BIO *in = NULL, *out = NULL, *indata = NULL;
	int badarg = 0;
	int flags = PKCS7_DETACHED;
	char *to = NULL, *from = NULL, *subject = NULL;
104
	char *CAfile = NULL, *CApath = NULL, *passin = NULL;
105 106
	char *inrand = NULL;
	int need_rand = 0;
107 108 109 110 111 112 113 114 115 116
	args = argv + 1;

	ret = 1;

	while (!badarg && *args && *args[0] == '-') {
		if (!strcmp (*args, "-encrypt")) operation = SMIME_ENCRYPT;
		else if (!strcmp (*args, "-decrypt")) operation = SMIME_DECRYPT;
		else if (!strcmp (*args, "-sign")) operation = SMIME_SIGN;
		else if (!strcmp (*args, "-verify")) operation = SMIME_VERIFY;
		else if (!strcmp (*args, "-pk7out")) operation = SMIME_PK7OUT;
B
Bodo Möller 已提交
117
#ifndef NO_DES
118 119 120 121
		else if (!strcmp (*args, "-des3")) 
				cipher = EVP_des_ede3_cbc();
		else if (!strcmp (*args, "-des")) 
				cipher = EVP_des_cbc();
B
Bodo Möller 已提交
122 123
#endif
#ifndef NO_RC2
124 125 126 127 128 129
		else if (!strcmp (*args, "-rc2-40")) 
				cipher = EVP_rc2_40_cbc();
		else if (!strcmp (*args, "-rc2-128")) 
				cipher = EVP_rc2_cbc();
		else if (!strcmp (*args, "-rc2-64")) 
				cipher = EVP_rc2_64_cbc();
B
Bodo Möller 已提交
130
#endif
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
		else if (!strcmp (*args, "-text")) 
				flags |= PKCS7_TEXT;
		else if (!strcmp (*args, "-nointern")) 
				flags |= PKCS7_NOINTERN;
		else if (!strcmp (*args, "-noverify")) 
				flags |= PKCS7_NOVERIFY;
		else if (!strcmp (*args, "-nochain")) 
				flags |= PKCS7_NOCHAIN;
		else if (!strcmp (*args, "-nocerts")) 
				flags |= PKCS7_NOCERTS;
		else if (!strcmp (*args, "-noattr")) 
				flags |= PKCS7_NOATTR;
		else if (!strcmp (*args, "-nodetach")) 
				flags &= ~PKCS7_DETACHED;
		else if (!strcmp (*args, "-binary"))
				flags |= PKCS7_BINARY;
147 148
		else if (!strcmp (*args, "-nosigs"))
				flags |= PKCS7_NOSIGS;
149 150 151 152 153 154 155 156 157 158 159
		else if (!strcmp(*args,"-rand")) {
			if (args[1]) {
				args++;
				inrand = *args;
			} else badarg = 1;
			need_rand = 1;
		} else if (!strcmp(*args,"-passin")) {
			if (args[1]) {
				args++;
				passin = *args;
			} else badarg = 1;
160
		} else if (!strcmp(*argv,"-envpassin")) {
161 162 163 164 165 166 167 168 169
			if (args[1]) {
				args++;
				if(!(passin= getenv(*args))) {
					BIO_printf(bio_err,
					 "Can't read environment variable %s\n",
								*args);
					badarg = 1;
				}
			} else badarg = 1;
170
		} else if (!strcmp (*args, "-to")) {
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
			if (args[1]) {
				args++;
				to = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-from")) {
			if (args[1]) {
				args++;
				from = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-subject")) {
			if (args[1]) {
				args++;
				subject = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-signer")) {
			if (args[1]) {
				args++;
				signerfile = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-recip")) {
			if (args[1]) {
				args++;
				recipfile = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-inkey")) {
			if (args[1]) {
				args++;
				keyfile = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-certfile")) {
			if (args[1]) {
				args++;
				certfile = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-CAfile")) {
			if (args[1]) {
				args++;
				CAfile = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-CApath")) {
			if (args[1]) {
				args++;
				CApath = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-in")) {
			if (args[1]) {
				args++;
				infile = *args;
			} else badarg = 1;
		} else if (!strcmp (*args, "-out")) {
			if (args[1]) {
				args++;
				outfile = *args;
			} else badarg = 1;
		} else badarg = 1;
		args++;
	}

	if(operation == SMIME_SIGN) {
		if(!signerfile) {
			BIO_printf(bio_err, "No signer certificate specified\n");
			badarg = 1;
		}
234
		need_rand = 1;
235 236 237 238 239 240 241 242 243 244
	} else if(operation == SMIME_DECRYPT) {
		if(!recipfile) {
			BIO_printf(bio_err, "No recipient certificate and key specified\n");
			badarg = 1;
		}
	} else if(operation == SMIME_ENCRYPT) {
		if(!*args) {
			BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
			badarg = 1;
		}
245
		need_rand = 1;
246 247 248 249 250 251 252 253 254 255
	} else if(!operation) badarg = 1;

	if (badarg) {
		BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n");
		BIO_printf (bio_err, "where options are\n");
		BIO_printf (bio_err, "-encrypt       encrypt message\n");
		BIO_printf (bio_err, "-decrypt       decrypt encrypted message\n");
		BIO_printf (bio_err, "-sign          sign message\n");
		BIO_printf (bio_err, "-verify        verify signed message\n");
		BIO_printf (bio_err, "-pk7out        output PKCS#7 structure\n");
B
Bodo Möller 已提交
256
#ifndef NO_DES
257
		BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
B
Bodo Möller 已提交
258 259 260 261
		BIO_printf (bio_err, "-des           encrypt with DES\n");
#endif
#ifndef NO_RC2
		BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
262 263
		BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
		BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
B
Bodo Möller 已提交
264
#endif
265 266 267 268 269 270 271
		BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
		BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
		BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
		BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
		BIO_printf (bio_err, "-nodetach      use opaque signing\n");
		BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
		BIO_printf (bio_err, "-binary        don't translate message to text\n");
272 273
		BIO_printf (bio_err, "-certfile file other certificates file\n");
		BIO_printf (bio_err, "-signer file   signer certificate file\n");
B
Bodo Möller 已提交
274
		BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
275 276 277 278 279 280 281
		BIO_printf (bio_err, "-in file       input file\n");
		BIO_printf (bio_err, "-inkey file    input private key (if not signer or recipient)\n");
		BIO_printf (bio_err, "-out file      output file\n");
		BIO_printf (bio_err, "-to addr       to address\n");
		BIO_printf (bio_err, "-from ad       from address\n");
		BIO_printf (bio_err, "-subject s     subject\n");
		BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
282 283
		BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
		BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
284 285 286
		BIO_printf(bio_err,  "-rand file:file:...\n");
		BIO_printf(bio_err,  "               load the file (or the files in the directory) into\n");
		BIO_printf(bio_err,  "               the random number generator\n");
B
Bodo Möller 已提交
287
		BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
288 289 290
		goto end;
	}

291 292 293 294 295 296 297
	if (need_rand) {
		app_RAND_load_file(NULL, bio_err, (inrand != NULL));
		if (inrand != NULL)
			BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
				app_RAND_load_files(inrand));
	}

298 299 300 301 302 303 304 305 306 307
	ret = 2;

	if(operation != SMIME_SIGN) flags &= ~PKCS7_DETACHED;

	if(flags & PKCS7_BINARY) {
		if(operation & SMIME_OP) inmode = "rb";
		else outmode = "rb";
	}

	if(operation == SMIME_ENCRYPT) {
B
Bodo Möller 已提交
308 309 310 311 312 313 314 315
		if (!cipher) {
#ifndef NO_RC2			
			cipher = EVP_rc2_40_cbc();
#else
			BIO_printf(bio_err, "No cipher selected\n");
			goto end;
#endif
		}
316 317 318
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load encryption certificates");
#endif		
319
		encerts = sk_X509_new_null();
320 321
		while (*args) {
			if(!(cert = load_cert(*args))) {
U
Ulf Möller 已提交
322
				BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args);
323 324
				goto end;
			}
325
			sk_X509_push(encerts, cert);
326 327 328
			cert = NULL;
			args++;
		}
329 330 331
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
332 333
	}

334
	if(signerfile && (operation == SMIME_SIGN)) {
335 336 337
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load signer certificate");
#endif		
338 339 340 341
		if(!(signer = load_cert(signerfile))) {
			BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile);
			goto end;
		}
342 343 344
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
345 346 347
	}

	if(certfile) {
348 349 350
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load other certfiles");
#endif		
351 352 353 354 355
		if(!(other = load_certs(certfile))) {
			BIO_printf(bio_err, "Can't read certificate file %s\n", certfile);
			ERR_print_errors(bio_err);
			goto end;
		}
356 357 358
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
359 360
	}

361
	if(recipfile && (operation == SMIME_DECRYPT)) {
362 363 364
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load recipient certificate");
#endif		
365 366 367 368 369
		if(!(recip = load_cert(recipfile))) {
			BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile);
			ERR_print_errors(bio_err);
			goto end;
		}
370 371 372
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
373 374 375 376 377 378 379 380 381
	}

	if(operation == SMIME_DECRYPT) {
		if(!keyfile) keyfile = recipfile;
	} else if(operation == SMIME_SIGN) {
		if(!keyfile) keyfile = signerfile;
	} else keyfile = NULL;

	if(keyfile) {
382 383 384
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load keyfile");
#endif		
385
		if(!(key = load_key(keyfile, passin))) {
386 387 388 389
			BIO_printf(bio_err, "Can't read recipient certificate file %s\n", keyfile);
			ERR_print_errors(bio_err);
			goto end;
		}
390 391 392
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
393 394
	}

395 396 397
#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("open input files");
#endif		
398 399 400 401 402 403 404
	if (infile) {
		if (!(in = BIO_new_file(infile, inmode))) {
			BIO_printf (bio_err,
				 "Can't open input file %s\n", infile);
			goto end;
		}
	} else in = BIO_new_fp(stdin, BIO_NOCLOSE);
405 406 407
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif		
408

409 410 411
#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("open output files");
#endif		
412 413 414 415 416 417 418
	if (outfile) {
		if (!(out = BIO_new_file(outfile, outmode))) {
			BIO_printf (bio_err,
				 "Can't open output file %s\n", outfile);
			goto end;
		}
	} else out = BIO_new_fp(stdout, BIO_NOCLOSE);
419 420 421 422 423 424 425 426
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif		

	if(operation == SMIME_VERIFY) {
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("setup_verify");
#endif		
427
		if(!(store = setup_verify(CAfile, CApath))) goto end;
428 429 430 431
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
	}
432 433

	ret = 3;
434

435
	if(operation == SMIME_ENCRYPT) {
436 437 438
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("PKCS7_encrypt");
#endif		
439
		p7 = PKCS7_encrypt(encerts, in, cipher, flags);
440 441 442
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
443
	} else if(operation == SMIME_SIGN) {
444 445 446
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("PKCS7_sign");
#endif		
447 448
		p7 = PKCS7_sign(signer, key, other, in, flags);
		BIO_reset(in);
449 450 451
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
452
	} else {
453 454 455
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("SMIME_read_PKCS7");
#endif		
456 457 458 459
		if(!(p7 = SMIME_read_PKCS7(in, &indata))) {
			BIO_printf(bio_err, "Error reading S/MIME message\n");
			goto end;
		}
460 461 462
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
463
	}
464

465 466 467 468 469
	if(!p7) {
		BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
		goto end;
	}

470
	ret = 4;
471
	if(operation == SMIME_DECRYPT) {
472 473 474
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("PKCS7_decrypt");
#endif		
475
		if(!PKCS7_decrypt(p7, key, recip, out, flags)) {
476
			BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
477 478
			goto end;
		}
479 480 481
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
482
	} else if(operation == SMIME_VERIFY) {
483
		STACK_OF(X509) *signers;
484 485 486
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("PKCS7_verify");
#endif		
487 488 489 490
		if(PKCS7_verify(p7, other, store, indata, out, flags)) {
			BIO_printf(bio_err, "Verification Successful\n");
		} else {
			BIO_printf(bio_err, "Verification Failure\n");
491
			goto end;
492
		}
493 494 495 496
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
		CRYPTO_push_info("PKCS7_iget_signers");
#endif		
497
		signers = PKCS7_iget_signers(p7, other, flags);
498 499 500 501
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
		CRYPTO_push_info("save_certs");
#endif		
502 503 504
		if(!save_certs(signerfile, signers)) {
			BIO_printf(bio_err, "Error writing signers to %s\n",
								signerfile);
505 506
			ret = 5;
			goto end;
507
		}
508 509 510
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
511
		sk_X509_free(signers);
512 513 514 515 516 517 518 519
	} else if(operation == SMIME_PK7OUT) {
		PEM_write_bio_PKCS7(out, p7);
	} else {
		if(to) BIO_printf(out, "To: %s\n", to);
		if(from) BIO_printf(out, "From: %s\n", from);
		if(subject) BIO_printf(out, "Subject: %s\n", subject);
		SMIME_write_PKCS7(out, p7, in, flags);
	}
520
	ret = 0;
521
end:
522 523 524
#ifdef CRYPTO_MDEBUG
	CRYPTO_remove_all_info();
#endif
525 526
	if (need_rand)
		app_RAND_write_file(NULL, bio_err);
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
	if(ret) ERR_print_errors(bio_err);
	sk_X509_pop_free(encerts, X509_free);
	sk_X509_pop_free(other, X509_free);
	X509_STORE_free(store);
	X509_free(cert);
	X509_free(recip);
	X509_free(signer);
	EVP_PKEY_free(key);
	PKCS7_free(p7);
	BIO_free(in);
	BIO_free(indata);
	BIO_free(out);
	return (ret);
}

static X509 *load_cert(char *file)
{
	BIO *in;
	X509 *cert;
	if(!(in = BIO_new_file(file, "r"))) return NULL;
	cert = PEM_read_bio_X509(in, NULL, NULL,NULL);
	BIO_free(in);
	return cert;
}

552
static EVP_PKEY *load_key(char *file, char *pass)
553 554 555 556
{
	BIO *in;
	EVP_PKEY *key;
	if(!(in = BIO_new_file(file, "r"))) return NULL;
557
	key = PEM_read_bio_PrivateKey(in, NULL,PEM_cb,pass);
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
	BIO_free(in);
	return key;
}

static STACK_OF(X509) *load_certs(char *file)
{
	BIO *in;
	int i;
	STACK_OF(X509) *othercerts;
	STACK_OF(X509_INFO) *allcerts;
	X509_INFO *xi;
	if(!(in = BIO_new_file(file, "r"))) return NULL;
	othercerts = sk_X509_new(NULL);
	if(!othercerts) return NULL;
	allcerts = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
	for(i = 0; i < sk_X509_INFO_num(allcerts); i++) {
		xi = sk_X509_INFO_value (allcerts, i);
		if (xi->x509) {
			sk_X509_push(othercerts, xi->x509);
			xi->x509 = NULL;
		}
	}
	sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
	BIO_free(in);
	return othercerts;
}

static X509_STORE *setup_verify(char *CAfile, char *CApath)
{
	X509_STORE *store;
	X509_LOOKUP *lookup;
589 590 591
#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("X509_STORE_new");
#endif	
592
	if(!(store = X509_STORE_new())) goto end;
593 594 595 596
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_STORE_add_lookup(...file)");
#endif	
597 598
	lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
	if (lookup == NULL) goto end;
599 600 601 602
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_LOOKUP_load_file");
#endif	
603 604 605 606 607 608 609
	if (CAfile) {
		if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
			BIO_printf(bio_err, "Error loading file %s\n", CAfile);
			goto end;
		}
	} else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
		
610 611 612 613
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_STORE_add_lookup(...hash_dir)");
#endif	
614 615
	lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
	if (lookup == NULL) goto end;
616 617 618 619
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_LOOKUP_add_dir");
#endif	
620 621 622 623 624 625
	if (CApath) {
		if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
			BIO_printf(bio_err, "Error loading directory %s\n", CApath);
			goto end;
		}
	} else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
626 627 628
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif	
629 630 631 632 633 634 635

	ERR_clear_error();
	return store;
	end:
	X509_STORE_free(store);
	return NULL;
}
636 637 638 639 640 641 642 643 644 645 646 647 648 649

int save_certs(char *signerfile, STACK_OF(X509) *signers)
{
	int i;
	BIO *tmp;
	if(!signerfile) return 1;
	tmp = BIO_new_file(signerfile, "w");
	if(!tmp) return 0;
	for(i = 0; i < sk_X509_num(signers); i++)
		PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
	BIO_free(tmp);
	return 1;
}