~ubuntu-branches/ubuntu/precise/openssl098/precise

« back to all changes in this revision

Viewing changes to apps/smime.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2011-03-23 19:50:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110323195031-6h9crj4bymhhr8b8
Tags: upstream-0.9.8o
ImportĀ upstreamĀ versionĀ 0.9.8o

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        }