4aa25257257e46104bab64f9ed9dc2494f8b743c
[openssl.git] / apps / smime.c
1 /* smime.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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_RC2
149                 else if (!strcmp (*args, "-rc2-40")) 
150                                 cipher = EVP_rc2_40_cbc();
151                 else if (!strcmp (*args, "-rc2-128")) 
152                                 cipher = EVP_rc2_cbc();
153                 else if (!strcmp (*args, "-rc2-64")) 
154                                 cipher = EVP_rc2_64_cbc();
155 #endif
156 #ifndef OPENSSL_NO_AES
157                 else if (!strcmp(*args,"-aes128"))
158                                 cipher = EVP_aes_128_cbc();
159                 else if (!strcmp(*args,"-aes192"))
160                                 cipher = EVP_aes_192_cbc();
161                 else if (!strcmp(*args,"-aes256"))
162                                 cipher = EVP_aes_256_cbc();
163 #endif
164                 else if (!strcmp (*args, "-text")) 
165                                 flags |= PKCS7_TEXT;
166                 else if (!strcmp (*args, "-nointern")) 
167                                 flags |= PKCS7_NOINTERN;
168                 else if (!strcmp (*args, "-noverify")) 
169                                 flags |= PKCS7_NOVERIFY;
170                 else if (!strcmp (*args, "-nochain")) 
171                                 flags |= PKCS7_NOCHAIN;
172                 else if (!strcmp (*args, "-nocerts")) 
173                                 flags |= PKCS7_NOCERTS;
174                 else if (!strcmp (*args, "-noattr")) 
175                                 flags |= PKCS7_NOATTR;
176                 else if (!strcmp (*args, "-nodetach")) 
177                                 flags &= ~PKCS7_DETACHED;
178                 else if (!strcmp (*args, "-nosmimecap"))
179                                 flags |= PKCS7_NOSMIMECAP;
180                 else if (!strcmp (*args, "-binary"))
181                                 flags |= PKCS7_BINARY;
182                 else if (!strcmp (*args, "-nosigs"))
183                                 flags |= PKCS7_NOSIGS;
184                 else if (!strcmp (*args, "-nooldmime"))
185                                 flags |= PKCS7_NOOLDMIMETYPE;
186                 else if (!strcmp (*args, "-crlfeol"))
187                                 flags |= PKCS7_CRLFEOL;
188                 else if (!strcmp(*args,"-rand"))
189                         {
190                         if (!args[1])
191                                 goto argerr;
192                         args++;
193                         inrand = *args;
194                         need_rand = 1;
195                         }
196 #ifndef OPENSSL_NO_ENGINE
197                 else if (!strcmp(*args,"-engine"))
198                         {
199                         if (!args[1])
200                                 goto argerr;
201                         engine = *++args;
202                         }
203 #endif
204                 else if (!strcmp(*args,"-passin"))
205                         {
206                         if (!args[1])
207                                 goto argerr;
208                         passargin = *++args;
209                         }
210                 else if (!strcmp (*args, "-to"))
211                         {
212                         if (!args[1])
213                                 goto argerr;
214                         to = *++args;
215                         }
216                 else if (!strcmp (*args, "-from"))
217                         {
218                         if (!args[1])
219                                 goto argerr;
220                         from = *++args;
221                         }
222                 else if (!strcmp (*args, "-subject"))
223                         {
224                         if (!args[1])
225                                 goto argerr;
226                         subject = *++args;
227                         }
228                 else if (!strcmp (*args, "-signer"))
229                         {
230                         if (!args[1])
231                                 goto argerr;
232                         signerfile = *++args;
233                         }
234                 else if (!strcmp (*args, "-recip"))
235                         {
236                         if (!args[1])
237                                 goto argerr;
238                         recipfile = *++args;
239                         }
240                 else if (!strcmp (*args, "-inkey"))
241                         {
242                         if (!args[1])   
243                                 goto argerr;
244                         keyfile = *++args;
245                         }
246                 else if (!strcmp (*args, "-keyform"))
247                         {
248                         if (!args[1])
249                                 goto argerr;
250                         keyform = str2fmt(*++args);
251                         }
252                 else if (!strcmp (*args, "-certfile"))
253                         {
254                         if (!args[1])
255                                 goto argerr;
256                         certfile = *++args;
257                         }
258                 else if (!strcmp (*args, "-CAfile"))
259                         {
260                         if (!args[1])
261                                 goto argerr;
262                         CAfile = *++args;
263                         }
264                 else if (!strcmp (*args, "-CApath"))
265                         {
266                         if (!args[1])
267                                 goto argerr;
268                         CApath = *++args;
269                         }
270                 else if (!strcmp (*args, "-in"))
271                         {
272                         if (!args[1])
273                                 goto argerr;
274                         infile = *++args;
275                         }
276                 else if (!strcmp (*args, "-inform"))
277                         {
278                         if (!args[1])
279                                 goto argerr;
280                         informat = str2fmt(*++args);
281                         }
282                 else if (!strcmp (*args, "-outform"))
283                         {
284                         if (!args[1])
285                                 goto argerr;
286                         outformat = str2fmt(*++args);
287                         }
288                 else if (!strcmp (*args, "-out"))
289                         {
290                         if (!args[1])
291                                 goto argerr;
292                         outfile = *++args;
293                         }
294                 else if (!strcmp (*args, "-content"))
295                         {
296                         if (!args[1])
297                                 goto argerr;
298                         contfile = *++args;
299                         }
300                 else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
301                         continue;
302                 else
303                         badarg = 1;
304                 args++;
305                 }
306
307
308         if (operation == SMIME_SIGN)
309                 {
310                 if (!signerfile)
311                         {
312                         BIO_printf(bio_err, "No signer certificate specified\n");
313                         badarg = 1;
314                         }
315                 need_rand = 1;
316                 }
317         else if (operation == SMIME_DECRYPT)
318                 {
319                 if (!recipfile && !keyfile)
320                         {
321                         BIO_printf(bio_err, "No recipient certificate or key specified\n");
322                         badarg = 1;
323                         }
324                 }
325         else if (operation == SMIME_ENCRYPT)
326                 {
327                 if (!*args)
328                         {
329                         BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
330                         badarg = 1;
331                         }
332                 need_rand = 1;
333                 }
334         else if (!operation)
335                 badarg = 1;
336
337         if (badarg)
338                 {
339                 argerr:
340                 BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n");
341                 BIO_printf (bio_err, "where options are\n");
342                 BIO_printf (bio_err, "-encrypt       encrypt message\n");
343                 BIO_printf (bio_err, "-decrypt       decrypt encrypted message\n");
344                 BIO_printf (bio_err, "-sign          sign message\n");
345                 BIO_printf (bio_err, "-verify        verify signed message\n");
346                 BIO_printf (bio_err, "-pk7out        output PKCS#7 structure\n");
347 #ifndef OPENSSL_NO_DES
348                 BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
349                 BIO_printf (bio_err, "-des           encrypt with DES\n");
350 #endif
351 #ifndef OPENSSL_NO_RC2
352                 BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
353                 BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
354                 BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
355 #endif
356 #ifndef OPENSSL_NO_AES
357                 BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
358                 BIO_printf (bio_err, "               encrypt PEM output with cbc aes\n");
359 #endif
360                 BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
361                 BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
362                 BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
363                 BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
364                 BIO_printf (bio_err, "-nodetach      use opaque signing\n");
365                 BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
366                 BIO_printf (bio_err, "-binary        don't translate message to text\n");
367                 BIO_printf (bio_err, "-certfile file other certificates file\n");
368                 BIO_printf (bio_err, "-signer file   signer certificate file\n");
369                 BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
370                 BIO_printf (bio_err, "-in file       input file\n");
371                 BIO_printf (bio_err, "-inform arg    input format SMIME (default), PEM or DER\n");
372                 BIO_printf (bio_err, "-inkey file    input private key (if not signer or recipient)\n");
373                 BIO_printf (bio_err, "-keyform arg   input private key format (PEM or ENGINE)\n");
374                 BIO_printf (bio_err, "-out file      output file\n");
375                 BIO_printf (bio_err, "-outform arg   output format SMIME (default), PEM or DER\n");
376                 BIO_printf (bio_err, "-content file  supply or override content for detached signature\n");
377                 BIO_printf (bio_err, "-to addr       to address\n");
378                 BIO_printf (bio_err, "-from ad       from address\n");
379                 BIO_printf (bio_err, "-subject s     subject\n");
380                 BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
381                 BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
382                 BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
383                 BIO_printf (bio_err, "-crl_check     check revocation status of signer's certificate using CRLs\n");
384                 BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
385 #ifndef OPENSSL_NO_ENGINE
386                 BIO_printf (bio_err, "-engine e      use engine e, possibly a hardware device.\n");
387 #endif
388                 BIO_printf (bio_err, "-passin arg    input file pass phrase source\n");
389                 BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
390                 BIO_printf(bio_err,  "               load the file (or the files in the directory) into\n");
391                 BIO_printf(bio_err,  "               the random number generator\n");
392                 BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
393                 goto end;
394                 }
395
396 #ifndef OPENSSL_NO_ENGINE
397         e = setup_engine(bio_err, engine, 0);
398 #endif
399
400         if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
401                 {
402                 BIO_printf(bio_err, "Error getting password\n");
403                 goto end;
404                 }
405
406         if (need_rand)
407                 {
408                 app_RAND_load_file(NULL, bio_err, (inrand != NULL));
409                 if (inrand != NULL)
410                         BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
411                                 app_RAND_load_files(inrand));
412                 }
413
414         ret = 2;
415
416         if (operation != SMIME_SIGN)
417                 flags &= ~PKCS7_DETACHED;
418
419         if (operation & SMIME_OP)
420                 {
421                 if (flags & PKCS7_BINARY)
422                         inmode = "rb";
423                 if (outformat == FORMAT_ASN1)
424                         outmode = "wb";
425                 }
426         else
427                 {
428                 if (flags & PKCS7_BINARY)
429                         outmode = "wb";
430                 if (informat == FORMAT_ASN1)
431                         inmode = "rb";
432                 }
433
434         if (operation == SMIME_ENCRYPT)
435                 {
436                 if (!cipher)
437                         {
438 #ifndef OPENSSL_NO_RC2                  
439                         cipher = EVP_rc2_40_cbc();
440 #else
441                         BIO_printf(bio_err, "No cipher selected\n");
442                         goto end;
443 #endif
444                         }
445                 encerts = sk_X509_new_null();
446                 while (*args)
447                         {
448                         if (!(cert = load_cert(bio_err,*args,FORMAT_PEM,
449                                 NULL, e, "recipient certificate file")))
450                                 {
451 #if 0                           /* An appropriate message is already printed */
452                                 BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args);
453 #endif
454                                 goto end;
455                                 }
456                         sk_X509_push(encerts, cert);
457                         cert = NULL;
458                         args++;
459                         }
460                 }
461
462         if (signerfile && (operation == SMIME_SIGN))
463                 {
464                 if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL,
465                         e, "signer certificate")))
466                         {
467 #if 0                   /* An appropri message has already been printed */
468                         BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile);
469 #endif
470                         goto end;
471                         }
472                 }
473
474         if (certfile)
475                 {
476                 if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL,
477                         e, "certificate file")))
478                         {
479 #if 0                   /* An appropriate message has already been printed */
480                         BIO_printf(bio_err, "Can't read certificate file %s\n", certfile);
481 #endif
482                         ERR_print_errors(bio_err);
483                         goto end;
484                         }
485                 }
486
487         if (recipfile && (operation == SMIME_DECRYPT))
488                 {
489                 if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL,
490                         e, "recipient certificate file")))
491                         {
492 #if 0                   /* An appropriate message has alrady been printed */
493                         BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile);
494 #endif
495                         ERR_print_errors(bio_err);
496                         goto end;
497                         }
498                 }
499
500         if (operation == SMIME_DECRYPT)
501                 {
502                 if (!keyfile)
503                         keyfile = recipfile;
504                 }
505         else if (operation == SMIME_SIGN)
506                 {
507                 if (!keyfile)
508                         keyfile = signerfile;
509                 }
510         else keyfile = NULL;
511
512         if (keyfile)
513                 {
514                 key = load_key(bio_err, keyfile, keyform, 0, passin, e,
515                                "signing key file");
516                 if (!key)
517                         goto end;
518                 }
519
520         if (infile)
521                 {
522                 if (!(in = BIO_new_file(infile, inmode)))
523                         {
524                         BIO_printf (bio_err,
525                                  "Can't open input file %s\n", infile);
526                         goto end;
527                         }
528                 }
529         else
530                 in = BIO_new_fp(stdin, BIO_NOCLOSE);
531
532         if (outfile)
533                 {
534                 if (!(out = BIO_new_file(outfile, outmode)))
535                         {
536                         BIO_printf (bio_err,
537                                  "Can't open output file %s\n", outfile);
538                         goto end;
539                         }
540                 }
541         else
542                 {
543                 out = BIO_new_fp(stdout, BIO_NOCLOSE);
544 #ifdef OPENSSL_SYS_VMS
545                 {
546                     BIO *tmpbio = BIO_new(BIO_f_linebuffer());
547                     out = BIO_push(tmpbio, out);
548                 }
549 #endif
550                 }
551
552         if (operation == SMIME_VERIFY)
553                 {
554                 if (!(store = setup_verify(bio_err, CAfile, CApath)))
555                         goto end;
556                 X509_STORE_set_verify_cb_func(store, smime_cb);
557                 if (vpm)
558                         X509_STORE_set1_param(store, vpm);
559                 }
560
561
562         ret = 3;
563
564         if (operation == SMIME_ENCRYPT)
565                 p7 = PKCS7_encrypt(encerts, in, cipher, flags);
566         else if (operation == SMIME_SIGN)
567                 {
568                 /* If detached data and SMIME output enable partial
569                  * signing.
570                  */
571                 if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME))
572                         flags |= PKCS7_STREAM;
573                 p7 = PKCS7_sign(signer, key, other, in, flags);
574                 /* Don't need to rewind for partial signing */
575                 if (!(flags & PKCS7_STREAM) && (BIO_reset(in) != 0))
576                         {
577                         BIO_printf(bio_err, "Can't rewind input file\n");
578                         goto end;
579                         }
580                 }
581         else
582                 {
583                 if (informat == FORMAT_SMIME) 
584                         p7 = SMIME_read_PKCS7(in, &indata);
585                 else if (informat == FORMAT_PEM) 
586                         p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
587                 else if (informat == FORMAT_ASN1) 
588                         p7 = d2i_PKCS7_bio(in, NULL);
589                 else
590                         {
591                         BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
592                         goto end;
593                         }
594
595                 if (!p7)
596                         {
597                         BIO_printf(bio_err, "Error reading S/MIME message\n");
598                         goto end;
599                         }
600                 if (contfile)
601                         {
602                         BIO_free(indata);
603                         if (!(indata = BIO_new_file(contfile, "rb")))
604                                 {
605                                 BIO_printf(bio_err, "Can't read content file %s\n", contfile);
606                                 goto end;
607                                 }
608                         }
609                 }
610
611         if (!p7)
612                 {
613                 BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
614                 goto end;
615                 }
616
617         ret = 4;
618         if (operation == SMIME_DECRYPT)
619                 {
620                 if (!PKCS7_decrypt(p7, key, recip, out, flags))
621                         {
622                         BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
623                         goto end;
624                         }
625                 }
626         else if (operation == SMIME_VERIFY)
627                 {
628                 STACK_OF(X509) *signers;
629                 if (PKCS7_verify(p7, other, store, indata, out, flags))
630                         BIO_printf(bio_err, "Verification successful\n");
631                 else
632                         {
633                         BIO_printf(bio_err, "Verification failure\n");
634                         goto end;
635                         }
636                 signers = PKCS7_get0_signers(p7, other, flags);
637                 if (!save_certs(signerfile, signers))
638                         {
639                         BIO_printf(bio_err, "Error writing signers to %s\n",
640                                                                 signerfile);
641                         ret = 5;
642                         goto end;
643                         }
644                 sk_X509_free(signers);
645                 }
646         else if (operation == SMIME_PK7OUT)
647                 PEM_write_bio_PKCS7(out, p7);
648         else
649                 {
650                 if (to)
651                         BIO_printf(out, "To: %s\n", to);
652                 if (from)
653                         BIO_printf(out, "From: %s\n", from);
654                 if (subject)
655                         BIO_printf(out, "Subject: %s\n", subject);
656                 if (outformat == FORMAT_SMIME) 
657                         SMIME_write_PKCS7(out, p7, in, flags);
658                 else if (outformat == FORMAT_PEM) 
659                         PEM_write_bio_PKCS7(out,p7);
660                 else if (outformat == FORMAT_ASN1) 
661                         i2d_PKCS7_bio(out,p7);
662                 else
663                         {
664                         BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
665                         goto end;
666                         }
667                 }
668         ret = 0;
669 end:
670         if (need_rand)
671                 app_RAND_write_file(NULL, bio_err);
672         if (ret) ERR_print_errors(bio_err);
673         sk_X509_pop_free(encerts, X509_free);
674         sk_X509_pop_free(other, X509_free);
675         if (vpm)
676                 X509_VERIFY_PARAM_free(vpm);
677         X509_STORE_free(store);
678         X509_free(cert);
679         X509_free(recip);
680         X509_free(signer);
681         EVP_PKEY_free(key);
682         PKCS7_free(p7);
683         BIO_free(in);
684         BIO_free(indata);
685         BIO_free_all(out);
686         if (passin) OPENSSL_free(passin);
687         return (ret);
688 }
689
690 static int save_certs(char *signerfile, STACK_OF(X509) *signers)
691         {
692         int i;
693         BIO *tmp;
694         if (!signerfile)
695                 return 1;
696         tmp = BIO_new_file(signerfile, "w");
697         if (!tmp) return 0;
698         for(i = 0; i < sk_X509_num(signers); i++)
699                 PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
700         BIO_free(tmp);
701         return 1;
702         }
703         
704
705 /* Minimal callback just to output policy info (if any) */
706
707 static int smime_cb(int ok, X509_STORE_CTX *ctx)
708         {
709         int error;
710
711         error = X509_STORE_CTX_get_error(ctx);
712
713         if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
714                 && ((error != X509_V_OK) || (ok != 2)))
715                 return ok;
716
717         policies_print(NULL, ctx);
718
719         return ok;
720
721         }