1 /* smime.c */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 /* S/MIME utility function */ 60 61 #include <stdio.h> 62 #include <string.h> 63 #include "apps.h" 64 #include <openssl/crypto.h> 65 #include <openssl/pem.h> 66 #include <openssl/err.h> 67 #include <openssl/x509_vfy.h> 68 #include <openssl/x509v3.h> 69 70 #undef PROG 71 #define PROG smime_main 72 static int save_certs(char *signerfile, STACK_OF(X509) *signers); 73 static int smime_cb(int ok, X509_STORE_CTX *ctx); 74 75 #define SMIME_OP 0x10 76 #define SMIME_ENCRYPT (1 | SMIME_OP) 77 #define SMIME_DECRYPT 2 78 #define SMIME_SIGN (3 | SMIME_OP) 79 #define SMIME_VERIFY 4 80 #define SMIME_PK7OUT 5 81 82 int MAIN(int, char **); 83 84 int MAIN(int argc, char **argv) 85 { 86 ENGINE *e = NULL; 87 int operation = 0; 88 int ret = 0; 89 char **args; 90 const char *inmode = "r", *outmode = "w"; 91 char *infile = NULL, *outfile = NULL; 92 char *signerfile = NULL, *recipfile = NULL; 93 char *certfile = NULL, *keyfile = NULL, *contfile=NULL; 94 const EVP_CIPHER *cipher = NULL; 95 PKCS7 *p7 = NULL; 96 X509_STORE *store = NULL; 97 X509 *cert = NULL, *recip = NULL, *signer = NULL; 98 EVP_PKEY *key = NULL; 99 STACK_OF(X509) *encerts = NULL, *other = NULL; 100 BIO *in = NULL, *out = NULL, *indata = NULL; 101 int badarg = 0; 102 int flags = PKCS7_DETACHED; 103 char *to = NULL, *from = NULL, *subject = NULL; 104 char *CAfile = NULL, *CApath = NULL; 105 char *passargin = NULL, *passin = NULL; 106 char *inrand = NULL; 107 int need_rand = 0; 108 int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; 109 int keyform = FORMAT_PEM; 110 #ifndef OPENSSL_NO_ENGINE 111 char *engine=NULL; 112 #endif 113 114 X509_VERIFY_PARAM *vpm = NULL; 115 116 args = argv + 1; 117 ret = 1; 118 119 apps_startup(); 120 121 if (bio_err == NULL) 122 { 123 if ((bio_err = BIO_new(BIO_s_file())) != NULL) 124 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT); 125 } 126 127 if (!load_config(bio_err, NULL)) 128 goto end; 129 130 while (!badarg && *args && *args[0] == '-') 131 { 132 if (!strcmp (*args, "-encrypt")) 133 operation = SMIME_ENCRYPT; 134 else if (!strcmp (*args, "-decrypt")) 135 operation = SMIME_DECRYPT; 136 else if (!strcmp (*args, "-sign")) 137 operation = SMIME_SIGN; 138 else if (!strcmp (*args, "-verify")) 139 operation = SMIME_VERIFY; 140 else if (!strcmp (*args, "-pk7out")) 141 operation = SMIME_PK7OUT; 142 #ifndef OPENSSL_NO_DES 143 else if (!strcmp (*args, "-des3")) 144 cipher = EVP_des_ede3_cbc(); 145 else if (!strcmp (*args, "-des")) 146 cipher = EVP_des_cbc(); 147 #endif 148 #ifndef OPENSSL_NO_SEED 149 else if (!strcmp (*args, "-seed")) 150 cipher = EVP_seed_cbc(); 151 #endif 152 #ifndef OPENSSL_NO_RC2 153 else if (!strcmp (*args, "-rc2-40")) 154 cipher = EVP_rc2_40_cbc(); 155 else if (!strcmp (*args, "-rc2-128")) 156 cipher = EVP_rc2_cbc(); 157 else if (!strcmp (*args, "-rc2-64")) 158 cipher = EVP_rc2_64_cbc(); 159 #endif 160 #ifndef OPENSSL_NO_AES 161 else if (!strcmp(*args,"-aes128")) 162 cipher = EVP_aes_128_cbc(); 163 else if (!strcmp(*args,"-aes192")) 164 cipher = EVP_aes_192_cbc(); 165 else if (!strcmp(*args,"-aes256")) 166 cipher = EVP_aes_256_cbc(); 167 #endif 168 #ifndef OPENSSL_NO_CAMELLIA 169 else if (!strcmp(*args,"-camellia128")) 170 cipher = EVP_camellia_128_cbc(); 171 else if (!strcmp(*args,"-camellia192")) 172 cipher = EVP_camellia_192_cbc(); 173 else if (!strcmp(*args,"-camellia256")) 174 cipher = EVP_camellia_256_cbc(); 175 #endif 176 else if (!strcmp (*args, "-text")) 177 flags |= PKCS7_TEXT; 178 else if (!strcmp (*args, "-nointern")) 179 flags |= PKCS7_NOINTERN; 180 else if (!strcmp (*args, "-noverify")) 181 flags |= PKCS7_NOVERIFY; 182 else if (!strcmp (*args, "-nochain")) 183 flags |= PKCS7_NOCHAIN; 184 else if (!strcmp (*args, "-nocerts")) 185 flags |= PKCS7_NOCERTS; 186 else if (!strcmp (*args, "-noattr")) 187 flags |= PKCS7_NOATTR; 188 else if (!strcmp (*args, "-nodetach")) 189 flags &= ~PKCS7_DETACHED; 190 else if (!strcmp (*args, "-nosmimecap")) 191 flags |= PKCS7_NOSMIMECAP; 192 else if (!strcmp (*args, "-binary")) 193 flags |= PKCS7_BINARY; 194 else if (!strcmp (*args, "-nosigs")) 195 flags |= PKCS7_NOSIGS; 196 else if (!strcmp (*args, "-nooldmime")) 197 flags |= PKCS7_NOOLDMIMETYPE; 198 else if (!strcmp (*args, "-crlfeol")) 199 flags |= PKCS7_CRLFEOL; 200 else if (!strcmp(*args,"-rand")) 201 { 202 if (args[1]) 203 { 204 args++; 205 inrand = *args; 206 } 207 else 208 badarg = 1; 209 need_rand = 1; 210 } 211 #ifndef OPENSSL_NO_ENGINE 212 else if (!strcmp(*args,"-engine")) 213 { 214 if (args[1]) 215 { 216 args++; 217 engine = *args; 218 } 219 else badarg = 1; 220 } 221 #endif 222 else if (!strcmp(*args,"-passin")) 223 { 224 if (args[1]) 225 { 226 args++; 227 passargin = *args; 228 } 229 else 230 badarg = 1; 231 } 232 else if (!strcmp (*args, "-to")) 233 { 234 if (args[1]) 235 { 236 args++; 237 to = *args; 238 } 239 else 240 badarg = 1; 241 } 242 else if (!strcmp (*args, "-from")) 243 { 244 if (args[1]) 245 { 246 args++; 247 from = *args; 248 } 249 else badarg = 1; 250 } 251 else if (!strcmp (*args, "-subject")) 252 { 253 if (args[1]) 254 { 255 args++; 256 subject = *args; 257 } 258 else 259 badarg = 1; 260 } 261 else if (!strcmp (*args, "-signer")) 262 { 263 if (args[1]) 264 { 265 args++; 266 signerfile = *args; 267 } 268 else 269 badarg = 1; 270 } 271 else if (!strcmp (*args, "-recip")) 272 { 273 if (args[1]) 274 { 275 args++; 276 recipfile = *args; 277 } 278 else badarg = 1; 279 } 280 else if (!strcmp (*args, "-inkey")) 281 { 282 if (args[1]) 283 { 284 args++; 285 keyfile = *args; 286 } 287 else 288 badarg = 1; 289 } 290 else if (!strcmp (*args, "-keyform")) 291 { 292 if (args[1]) 293 { 294 args++; 295 keyform = str2fmt(*args); 296 } 297 else 298 badarg = 1; 299 } 300 else if (!strcmp (*args, "-certfile")) 301 { 302 if (args[1]) 303 { 304 args++; 305 certfile = *args; 306 } 307 else 308 badarg = 1; 309 } 310 else if (!strcmp (*args, "-CAfile")) 311 { 312 if (args[1]) 313 { 314 args++; 315 CAfile = *args; 316 } 317 else 318 badarg = 1; 319 } 320 else if (!strcmp (*args, "-CApath")) 321 { 322 if (args[1]) 323 { 324 args++; 325 CApath = *args; 326 } 327 else 328 badarg = 1; 329 } 330 else if (!strcmp (*args, "-in")) 331 { 332 if (args[1]) 333 { 334 args++; 335 infile = *args; 336 } 337 else 338 badarg = 1; 339 } 340 else if (!strcmp (*args, "-inform")) 341 { 342 if (args[1]) 343 { 344 args++; 345 informat = str2fmt(*args); 346 } 347 else 348 badarg = 1; 349 } 350 else if (!strcmp (*args, "-outform")) 351 { 352 if (args[1]) 353 { 354 args++; 355 outformat = str2fmt(*args); 356 } 357 else 358 badarg = 1; 359 } 360 else if (!strcmp (*args, "-out")) 361 { 362 if (args[1]) 363 { 364 args++; 365 outfile = *args; 366 } 367 else 368 badarg = 1; 369 } 370 else if (!strcmp (*args, "-content")) 371 { 372 if (args[1]) 373 { 374 args++; 375 contfile = *args; 376 } 377 else 378 badarg = 1; 379 } 380 else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) 381 continue; 382 else 383 badarg = 1; 384 args++; 385 } 386 387 388 if (operation == SMIME_SIGN) 389 { 390 if (!signerfile) 391 { 392 BIO_printf(bio_err, "No signer certificate specified\n"); 393 badarg = 1; 394 } 395 need_rand = 1; 396 } 397 else if (operation == SMIME_DECRYPT) 398 { 399 if (!recipfile && !keyfile) 400 { 401 BIO_printf(bio_err, "No recipient certificate or key specified\n"); 402 badarg = 1; 403 } 404 } 405 else if (operation == SMIME_ENCRYPT) 406 { 407 if (!*args) 408 { 409 BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 410 badarg = 1; 411 } 412 need_rand = 1; 413 } 414 else if (!operation) 415 badarg = 1; 416 417 if (badarg) 418 { 419 BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n"); 420 BIO_printf (bio_err, "where options are\n"); 421 BIO_printf (bio_err, "-encrypt encrypt message\n"); 422 BIO_printf (bio_err, "-decrypt decrypt encrypted message\n"); 423 BIO_printf (bio_err, "-sign sign message\n"); 424 BIO_printf (bio_err, "-verify verify signed message\n"); 425 BIO_printf (bio_err, "-pk7out output PKCS#7 structure\n"); 426 #ifndef OPENSSL_NO_DES 427 BIO_printf (bio_err, "-des3 encrypt with triple DES\n"); 428 BIO_printf (bio_err, "-des encrypt with DES\n"); 429 #endif 430 #ifndef OPENSSL_NO_SEED 431 BIO_printf (bio_err, "-seed encrypt with SEED\n"); 432 #endif 433 #ifndef OPENSSL_NO_RC2 434 BIO_printf (bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); 435 BIO_printf (bio_err, "-rc2-64 encrypt with RC2-64\n"); 436 BIO_printf (bio_err, "-rc2-128 encrypt with RC2-128\n"); 437 #endif 438 #ifndef OPENSSL_NO_AES 439 BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); 440 BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); 441 #endif 442 #ifndef OPENSSL_NO_CAMELLIA 443 BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n"); 444 BIO_printf (bio_err, " encrypt PEM output with cbc camellia\n"); 445 #endif 446 BIO_printf (bio_err, "-nointern don't search certificates in message for signer\n"); 447 BIO_printf (bio_err, "-nosigs don't verify message signature\n"); 448 BIO_printf (bio_err, "-noverify don't verify signers certificate\n"); 449 BIO_printf (bio_err, "-nocerts don't include signers certificate when signing\n"); 450 BIO_printf (bio_err, "-nodetach use opaque signing\n"); 451 BIO_printf (bio_err, "-noattr don't include any signed attributes\n"); 452 BIO_printf (bio_err, "-binary don't translate message to text\n"); 453 BIO_printf (bio_err, "-certfile file other certificates file\n"); 454 BIO_printf (bio_err, "-signer file signer certificate file\n"); 455 BIO_printf (bio_err, "-recip file recipient certificate file for decryption\n"); 456 BIO_printf (bio_err, "-in file input file\n"); 457 BIO_printf (bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); 458 BIO_printf (bio_err, "-inkey file input private key (if not signer or recipient)\n"); 459 BIO_printf (bio_err, "-keyform arg input private key format (PEM or ENGINE)\n"); 460 BIO_printf (bio_err, "-out file output file\n"); 461 BIO_printf (bio_err, "-outform arg output format SMIME (default), PEM or DER\n"); 462 BIO_printf (bio_err, "-content file supply or override content for detached signature\n"); 463 BIO_printf (bio_err, "-to addr to address\n"); 464 BIO_printf (bio_err, "-from ad from address\n"); 465 BIO_printf (bio_err, "-subject s subject\n"); 466 BIO_printf (bio_err, "-text include or delete text MIME headers\n"); 467 BIO_printf (bio_err, "-CApath dir trusted certificates directory\n"); 468 BIO_printf (bio_err, "-CAfile file trusted certificates file\n"); 469 BIO_printf (bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); 470 BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); 471 #ifndef OPENSSL_NO_ENGINE 472 BIO_printf (bio_err, "-engine e use engine e, possibly a hardware device.\n"); 473 #endif 474 BIO_printf (bio_err, "-passin arg input file pass phrase source\n"); 475 BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); 476 BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); 477 BIO_printf(bio_err, " the random number generator\n"); 478 BIO_printf (bio_err, "cert.pem recipient certificate(s) for encryption\n"); 479 goto end; 480 } 481 482 #ifndef OPENSSL_NO_ENGINE 483 e = setup_engine(bio_err, engine, 0); 484 #endif 485 486 if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) 487 { 488 BIO_printf(bio_err, "Error getting password\n"); 489 goto end; 490 } 491 492 if (need_rand) 493 { 494 app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 495 if (inrand != NULL) 496 BIO_printf(bio_err,"%ld semi-random bytes loaded\n", 497 app_RAND_load_files(inrand)); 498 } 499 500 ret = 2; 501 502 if (operation != SMIME_SIGN) 503 flags &= ~PKCS7_DETACHED; 504 505 if (operation & SMIME_OP) 506 { 507 if (flags & PKCS7_BINARY) 508 inmode = "rb"; 509 if (outformat == FORMAT_ASN1) 510 outmode = "wb"; 511 } 512 else 513 { 514 if (flags & PKCS7_BINARY) 515 outmode = "wb"; 516 if (informat == FORMAT_ASN1) 517 inmode = "rb"; 518 } 519 520 if (operation == SMIME_ENCRYPT) 521 { 522 if (!cipher) 523 { 524 #ifndef OPENSSL_NO_RC2 525 cipher = EVP_rc2_40_cbc(); 526 #else 527 BIO_printf(bio_err, "No cipher selected\n"); 528 goto end; 529 #endif 530 } 531 encerts = sk_X509_new_null(); 532 while (*args) 533 { 534 if (!(cert = load_cert(bio_err,*args,FORMAT_PEM, 535 NULL, e, "recipient certificate file"))) 536 { 537 #if 0 /* An appropriate message is already printed */ 538 BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args); 539 #endif 540 goto end; 541 } 542 sk_X509_push(encerts, cert); 543 cert = NULL; 544 args++; 545 } 546 } 547 548 if (signerfile && (operation == SMIME_SIGN)) 549 { 550 if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL, 551 e, "signer certificate"))) 552 { 553 #if 0 /* An appropri message has already been printed */ 554 BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile); 555 #endif 556 goto end; 557 } 558 } 559 560 if (certfile) 561 { 562 if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL, 563 e, "certificate file"))) 564 { 565 #if 0 /* An appropriate message has already been printed */ 566 BIO_printf(bio_err, "Can't read certificate file %s\n", certfile); 567 #endif 568 ERR_print_errors(bio_err); 569 goto end; 570 } 571 } 572 573 if (recipfile && (operation == SMIME_DECRYPT)) 574 { 575 if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL, 576 e, "recipient certificate file"))) 577 { 578 #if 0 /* An appropriate message has alrady been printed */ 579 BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile); 580 #endif 581 ERR_print_errors(bio_err); 582 goto end; 583 } 584 } 585 586 if (operation == SMIME_DECRYPT) 587 { 588 if (!keyfile) 589 keyfile = recipfile; 590 } 591 else if (operation == SMIME_SIGN) 592 { 593 if (!keyfile) 594 keyfile = signerfile; 595 } 596 else keyfile = NULL; 597 598 if (keyfile) 599 { 600 key = load_key(bio_err, keyfile, keyform, 0, passin, e, 601 "signing key file"); 602 if (!key) 603 goto end; 604 } 605 606 if (infile) 607 { 608 if (!(in = BIO_new_file(infile, inmode))) 609 { 610 BIO_printf (bio_err, 611 "Can't open input file %s\n", infile); 612 goto end; 613 } 614 } 615 else 616 in = BIO_new_fp(stdin, BIO_NOCLOSE); 617 618 if (outfile) 619 { 620 if (!(out = BIO_new_file(outfile, outmode))) 621 { 622 BIO_printf (bio_err, 623 "Can't open output file %s\n", outfile); 624 goto end; 625 } 626 } 627 else 628 { 629 out = BIO_new_fp(stdout, BIO_NOCLOSE); 630 #ifdef OPENSSL_SYS_VMS 631 { 632 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 633 out = BIO_push(tmpbio, out); 634 } 635 #endif 636 } 637 638 if (operation == SMIME_VERIFY) 639 { 640 if (!(store = setup_verify(bio_err, CAfile, CApath))) 641 goto end; 642 X509_STORE_set_verify_cb_func(store, smime_cb); 643 if (vpm) 644 X509_STORE_set1_param(store, vpm); 645 } 646 647 648 ret = 3; 649 650 if (operation == SMIME_ENCRYPT) 651 p7 = PKCS7_encrypt(encerts, in, cipher, flags); 652 else if (operation == SMIME_SIGN) 653 { 654 /* If detached data and SMIME output enable partial 655 * signing. 656 */ 657 if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME)) 658 flags |= PKCS7_STREAM; 659 p7 = PKCS7_sign(signer, key, other, in, flags); 660 } 661 else 662 { 663 if (informat == FORMAT_SMIME) 664 p7 = SMIME_read_PKCS7(in, &indata); 665 else if (informat == FORMAT_PEM) 666 p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); 667 else if (informat == FORMAT_ASN1) 668 p7 = d2i_PKCS7_bio(in, NULL); 669 else 670 { 671 BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 672 goto end; 673 } 674 675 if (!p7) 676 { 677 BIO_printf(bio_err, "Error reading S/MIME message\n"); 678 goto end; 679 } 680 if (contfile) 681 { 682 BIO_free(indata); 683 if (!(indata = BIO_new_file(contfile, "rb"))) 684 { 685 BIO_printf(bio_err, "Can't read content file %s\n", contfile); 686 goto end; 687 } 688 } 689 } 690 691 if (!p7) 692 { 693 BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 694 goto end; 695 } 696 697 ret = 4; 698 if (operation == SMIME_DECRYPT) 699 { 700 if (!PKCS7_decrypt(p7, key, recip, out, flags)) 701 { 702 BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 703 goto end; 704 } 705 } 706 else if (operation == SMIME_VERIFY) 707 { 708 STACK_OF(X509) *signers; 709 if (PKCS7_verify(p7, other, store, indata, out, flags)) 710 BIO_printf(bio_err, "Verification successful\n"); 711 else 712 { 713 BIO_printf(bio_err, "Verification failure\n"); 714 goto end; 715 } 716 signers = PKCS7_get0_signers(p7, other, flags); 717 if (!save_certs(signerfile, signers)) 718 { 719 BIO_printf(bio_err, "Error writing signers to %s\n", 720 signerfile); 721 ret = 5; 722 goto end; 723 } 724 sk_X509_free(signers); 725 } 726 else if (operation == SMIME_PK7OUT) 727 PEM_write_bio_PKCS7(out, p7); 728 else 729 { 730 if (to) 731 BIO_printf(out, "To: %s\n", to); 732 if (from) 733 BIO_printf(out, "From: %s\n", from); 734 if (subject) 735 BIO_printf(out, "Subject: %s\n", subject); 736 if (outformat == FORMAT_SMIME) 737 SMIME_write_PKCS7(out, p7, in, flags); 738 else if (outformat == FORMAT_PEM) 739 PEM_write_bio_PKCS7(out,p7); 740 else if (outformat == FORMAT_ASN1) 741 i2d_PKCS7_bio(out,p7); 742 else 743 { 744 BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 745 goto end; 746 } 747 } 748 ret = 0; 749 end: 750 if (need_rand) 751 app_RAND_write_file(NULL, bio_err); 752 if (ret) ERR_print_errors(bio_err); 753 sk_X509_pop_free(encerts, X509_free); 754 sk_X509_pop_free(other, X509_free); 755 if (vpm) 756 X509_VERIFY_PARAM_free(vpm); 757 X509_STORE_free(store); 758 X509_free(cert); 759 X509_free(recip); 760 X509_free(signer); 761 EVP_PKEY_free(key); 762 PKCS7_free(p7); 763 BIO_free(in); 764 BIO_free(indata); 765 BIO_free_all(out); 766 if (passin) OPENSSL_free(passin); 767 return (ret); 768 } 769 770 static int save_certs(char *signerfile, STACK_OF(X509) *signers) 771 { 772 int i; 773 BIO *tmp; 774 if (!signerfile) 775 return 1; 776 tmp = BIO_new_file(signerfile, "w"); 777 if (!tmp) return 0; 778 for(i = 0; i < sk_X509_num(signers); i++) 779 PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 780 BIO_free(tmp); 781 return 1; 782 } 783 784 785 /* Minimal callback just to output policy info (if any) */ 786 787 static int smime_cb(int ok, X509_STORE_CTX *ctx) 788 { 789 int error; 790 791 error = X509_STORE_CTX_get_error(ctx); 792 793 if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 794 && ((error != X509_V_OK) || (ok != 2))) 795 return ok; 796 797 policies_print(NULL, ctx); 798 799 return ok; 800 801 } 802