smime.c 17.5 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 107 108 109 110 111 112 113 114 115

	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 已提交
116
#ifndef NO_DES
117 118 119 120
		else if (!strcmp (*args, "-des3")) 
				cipher = EVP_des_ede3_cbc();
		else if (!strcmp (*args, "-des")) 
				cipher = EVP_des_cbc();
B
Bodo Möller 已提交
121 122
#endif
#ifndef NO_RC2
123 124 125 126 127 128
		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 已提交
129
#endif
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
		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;
146 147
		else if (!strcmp (*args, "-nosigs"))
				flags |= PKCS7_NOSIGS;
148 149 150 151 152 153 154 155 156 157 158 159
		else if (!strcmp(*argv,"-passin")) {
			if (--argc < 1) badarg = 1;
			else passin= *(++argv);
		} else if (!strcmp(*argv,"-envpassin")) {
			if (--argc < 1) badarg = 1;
			else if(!(passin= getenv(*(++argv)))) {
				BIO_printf(bio_err,
				 "Can't read environment variable %s\n",
								*argv);
				badarg = 1;
			}
		} else if (!strcmp (*args, "-to")) {
160 161 162 163 164 165 166 167 168 169 170 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 234 235 236 237 238 239 240 241 242
			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;
		}
	} 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;
		}
	} 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 已提交
243
#ifndef NO_DES
244
		BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
B
Bodo Möller 已提交
245 246 247 248
		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");
249 250
		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 已提交
251
#endif
252 253 254 255 256 257 258
		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");
259 260
		BIO_printf (bio_err, "-certfile file other certificates file\n");
		BIO_printf (bio_err, "-signer file   signer certificate file\n");
B
Bodo Möller 已提交
261
		BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
262 263 264 265 266 267 268
		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");
269 270
		BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
		BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
B
Bodo Möller 已提交
271
		BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
272 273 274 275 276 277 278 279 280 281 282 283 284
		goto end;
	}

	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 已提交
285 286 287 288 289 290 291 292
		if (!cipher) {
#ifndef NO_RC2			
			cipher = EVP_rc2_40_cbc();
#else
			BIO_printf(bio_err, "No cipher selected\n");
			goto end;
#endif
		}
293 294 295
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load encryption certificates");
#endif		
296
		encerts = sk_X509_new_null();
297 298
		while (*args) {
			if(!(cert = load_cert(*args))) {
U
Ulf Möller 已提交
299
				BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args);
300 301
				goto end;
			}
302
			sk_X509_push(encerts, cert);
303 304 305
			cert = NULL;
			args++;
		}
306 307 308
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
309 310
	}

311
	if(signerfile && (operation == SMIME_SIGN)) {
312 313 314
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load signer certificate");
#endif		
315 316 317 318
		if(!(signer = load_cert(signerfile))) {
			BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile);
			goto end;
		}
319 320 321
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
322 323 324
	}

	if(certfile) {
325 326 327
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load other certfiles");
#endif		
328 329 330 331 332
		if(!(other = load_certs(certfile))) {
			BIO_printf(bio_err, "Can't read certificate file %s\n", certfile);
			ERR_print_errors(bio_err);
			goto end;
		}
333 334 335
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
336 337
	}

338
	if(recipfile && (operation == SMIME_DECRYPT)) {
339 340 341
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load recipient certificate");
#endif		
342 343 344 345 346
		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;
		}
347 348 349
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
350 351 352 353 354 355 356 357 358
	}

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

	if(keyfile) {
359 360 361
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load keyfile");
#endif		
362
		if(!(key = load_key(keyfile, passin))) {
363 364 365 366
			BIO_printf(bio_err, "Can't read recipient certificate file %s\n", keyfile);
			ERR_print_errors(bio_err);
			goto end;
		}
367 368 369
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
370 371
	}

372 373 374
#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("open input files");
#endif		
375 376 377 378 379 380 381
	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);
382 383 384
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif		
385

386 387 388
#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("open output files");
#endif		
389 390 391 392 393 394 395
	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);
396 397 398 399 400 401 402 403
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif		

	if(operation == SMIME_VERIFY) {
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("setup_verify");
#endif		
404
		if(!(store = setup_verify(CAfile, CApath))) goto end;
405 406 407 408
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
	}
409 410

	ret = 3;
411

412
	if(operation == SMIME_ENCRYPT) {
413 414 415
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("PKCS7_encrypt");
#endif		
416
		p7 = PKCS7_encrypt(encerts, in, cipher, flags);
417 418 419
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
420
	} else if(operation == SMIME_SIGN) {
421 422 423
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("PKCS7_sign");
#endif		
424 425
		p7 = PKCS7_sign(signer, key, other, in, flags);
		BIO_reset(in);
426 427 428
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
429
	} else {
430 431 432
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("SMIME_read_PKCS7");
#endif		
433 434 435 436
		if(!(p7 = SMIME_read_PKCS7(in, &indata))) {
			BIO_printf(bio_err, "Error reading S/MIME message\n");
			goto end;
		}
437 438 439
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
440
	}
441

442 443 444 445 446
	if(!p7) {
		BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
		goto end;
	}

447
	ret = 4;
448
	if(operation == SMIME_DECRYPT) {
449 450 451
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("PKCS7_decrypt");
#endif		
452
		if(!PKCS7_decrypt(p7, key, recip, out, flags)) {
453
			BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
454 455
			goto end;
		}
456 457 458
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
459
	} else if(operation == SMIME_VERIFY) {
460
		STACK_OF(X509) *signers;
461 462 463
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("PKCS7_verify");
#endif		
464 465 466 467
		if(PKCS7_verify(p7, other, store, indata, out, flags)) {
			BIO_printf(bio_err, "Verification Successful\n");
		} else {
			BIO_printf(bio_err, "Verification Failure\n");
468
			goto end;
469
		}
470 471 472 473
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
		CRYPTO_push_info("PKCS7_iget_signers");
#endif		
474
		signers = PKCS7_iget_signers(p7, other, flags);
475 476 477 478
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
		CRYPTO_push_info("save_certs");
#endif		
479 480 481
		if(!save_certs(signerfile, signers)) {
			BIO_printf(bio_err, "Error writing signers to %s\n",
								signerfile);
482 483
			ret = 5;
			goto end;
484
		}
485 486 487
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
488
		sk_X509_free(signers);
489 490 491 492 493 494 495 496
	} 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);
	}
497
	ret = 0;
498
end:
499 500 501
#ifdef CRYPTO_MDEBUG
	CRYPTO_remove_all_info();
#endif
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
	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;
}

527
static EVP_PKEY *load_key(char *file, char *pass)
528 529 530 531
{
	BIO *in;
	EVP_PKEY *key;
	if(!(in = BIO_new_file(file, "r"))) return NULL;
532
	key = PEM_read_bio_PrivateKey(in, NULL,PEM_cb,pass);
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
	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;
564 565 566
#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("X509_STORE_new");
#endif	
567
	if(!(store = X509_STORE_new())) goto end;
568 569 570 571
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_STORE_add_lookup(...file)");
#endif	
572 573
	lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
	if (lookup == NULL) goto end;
574 575 576 577
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_LOOKUP_load_file");
#endif	
578 579 580 581 582 583 584
	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);
		
585 586 587 588
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_STORE_add_lookup(...hash_dir)");
#endif	
589 590
	lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
	if (lookup == NULL) goto end;
591 592 593 594
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_LOOKUP_add_dir");
#endif	
595 596 597 598 599 600
	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);
601 602 603
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif	
604 605 606 607 608 609 610

	ERR_clear_error();
	return store;
	end:
	X509_STORE_free(store);
	return NULL;
}
611 612 613 614 615 616 617 618 619 620 621 622 623 624

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;
}