smime.c revision 194206
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
72static int save_certs(char *signerfile, STACK_OF(X509) *signers);
73static 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
82int MAIN(int, char **);
83
84int 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;
749end:
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
770static 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
787static 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