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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

#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

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;
102
	char *CAfile = NULL, *CApath = NULL, *passin = NULL;
103 104 105 106 107 108 109 110 111 112 113

	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 已提交
114
#ifndef NO_DES
115 116 117 118
		else if (!strcmp (*args, "-des3")) 
				cipher = EVP_des_ede3_cbc();
		else if (!strcmp (*args, "-des")) 
				cipher = EVP_des_cbc();
B
Bodo Möller 已提交
119 120
#endif
#ifndef NO_RC2
121 122 123 124 125 126
		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 已提交
127
#endif
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
		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;
144 145
		else if (!strcmp (*args, "-nosigs"))
				flags |= PKCS7_NOSIGS;
146 147 148 149 150 151 152 153 154 155 156 157
		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")) {
158 159 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
			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 已提交
241
#ifndef NO_DES
242
		BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
B
Bodo Möller 已提交
243 244 245 246
		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");
247 248
		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 已提交
249
#endif
250 251 252 253 254 255 256
		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");
257 258
		BIO_printf (bio_err, "-certfile file other certificates file\n");
		BIO_printf (bio_err, "-signer file   signer certificate file\n");
B
Bodo Möller 已提交
259
		BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
260 261 262 263 264 265 266
		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");
267 268
		BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
		BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
B
Bodo Möller 已提交
269
		BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
270 271 272 273 274 275 276 277 278 279 280 281 282
		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 已提交
283 284 285 286 287 288 289 290
		if (!cipher) {
#ifndef NO_RC2			
			cipher = EVP_rc2_40_cbc();
#else
			BIO_printf(bio_err, "No cipher selected\n");
			goto end;
#endif
		}
291 292 293
#ifdef CRYPTO_MDEBUG
		CRYPTO_push_info("load encryption certificates");
#endif		
294
		encerts = sk_X509_new_null();
295 296 297 298 299
		while (*args) {
			if(!(cert = load_cert(*args))) {
				BIO_printf(bio_err, "Can't read recipent certificate file %s\n", *args);
				goto end;
			}
300
			sk_X509_push(encerts, cert);
301 302 303
			cert = NULL;
			args++;
		}
304 305 306
#ifdef CRYPTO_MDEBUG
		CRYPTO_pop_info();
#endif		
307 308
	}

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

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

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

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

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

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

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

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

	ret = 3;
409

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

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

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

525
static EVP_PKEY *load_key(char *file, char *pass)
526 527 528 529
{
	BIO *in;
	EVP_PKEY *key;
	if(!(in = BIO_new_file(file, "r"))) return NULL;
530
	key = PEM_read_bio_PrivateKey(in, NULL,PEM_cb,pass);
531 532 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
	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;
562 563 564
#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("X509_STORE_new");
#endif	
565
	if(!(store = X509_STORE_new())) goto end;
566 567 568 569
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_STORE_add_lookup(...file)");
#endif	
570 571
	lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
	if (lookup == NULL) goto end;
572 573 574 575
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_LOOKUP_load_file");
#endif	
576 577 578 579 580 581 582
	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);
		
583 584 585 586
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_STORE_add_lookup(...hash_dir)");
#endif	
587 588
	lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
	if (lookup == NULL) goto end;
589 590 591 592
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("X509_LOOKUP_add_dir");
#endif	
593 594 595 596 597 598
	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);
599 600 601
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif	
602 603 604 605 606 607 608

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

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