[BACK]Return to smime.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/smime.c, Revision 1.16

1.16    ! inoguchi    1: /* $OpenBSD: smime.c,v 1.15 2022/01/11 15:45:00 inoguchi Exp $ */
1.1       jsing       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:
                     64: #include "apps.h"
                     65:
                     66: #include <openssl/crypto.h>
                     67: #include <openssl/err.h>
                     68: #include <openssl/pem.h>
                     69: #include <openssl/x509_vfy.h>
                     70: #include <openssl/x509v3.h>
                     71:
1.12      inoguchi   72: static int save_certs(char *signerfile, STACK_OF(X509) *signers);
                     73: static int smime_cb(int ok, X509_STORE_CTX *ctx);
1.1       jsing      74:
                     75: #define SMIME_OP       0x10
                     76: #define SMIME_IP       0x20
                     77: #define SMIME_SIGNERS  0x40
                     78: #define SMIME_ENCRYPT  (1 | SMIME_OP)
                     79: #define SMIME_DECRYPT  (2 | SMIME_IP)
                     80: #define SMIME_SIGN     (3 | SMIME_OP | SMIME_SIGNERS)
                     81: #define SMIME_VERIFY   (4 | SMIME_IP)
                     82: #define SMIME_PK7OUT   (5 | SMIME_IP | SMIME_OP)
                     83: #define SMIME_RESIGN   (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
                     84:
1.11      inoguchi   85: static struct {
                     86:        char *CAfile;
                     87:        char *CApath;
                     88:        char *certfile;
                     89:        const EVP_CIPHER *cipher;
                     90:        char *contfile;
                     91:        int flags;
                     92:        char *from;
                     93:        int indef;
                     94:        char *infile;
                     95:        int informat;
                     96:        char *keyfile;
                     97:        int keyform;
                     98:        int operation;
                     99:        char *outfile;
                    100:        int outformat;
                    101:        char *passargin;
                    102:        char *recipfile;
                    103:        const EVP_MD *sign_md;
                    104:        char *signerfile;
                    105:        STACK_OF(OPENSSL_STRING) *skkeys;
                    106:        STACK_OF(OPENSSL_STRING) *sksigners;
                    107:        char *subject;
                    108:        char *to;
                    109:        X509_VERIFY_PARAM *vpm;
                    110: } smime_config;
                    111:
                    112: static const EVP_CIPHER *
                    113: get_cipher_by_name(char *name)
                    114: {
                    115:        if (name == NULL || strcmp(name, "") == 0)
                    116:                return (NULL);
                    117: #ifndef OPENSSL_NO_AES
                    118:        else if (strcmp(name, "aes128") == 0)
                    119:                return EVP_aes_128_cbc();
                    120:        else if (strcmp(name, "aes192") == 0)
                    121:                return EVP_aes_192_cbc();
                    122:        else if (strcmp(name, "aes256") == 0)
                    123:                return EVP_aes_256_cbc();
                    124: #endif
                    125: #ifndef OPENSSL_NO_CAMELLIA
                    126:        else if (strcmp(name, "camellia128") == 0)
                    127:                return EVP_camellia_128_cbc();
                    128:        else if (strcmp(name, "camellia192") == 0)
                    129:                return EVP_camellia_192_cbc();
                    130:        else if (strcmp(name, "camellia256") == 0)
                    131:                return EVP_camellia_256_cbc();
                    132: #endif
                    133: #ifndef OPENSSL_NO_DES
                    134:        else if (strcmp(name, "des") == 0)
                    135:                return EVP_des_cbc();
                    136:        else if (strcmp(name, "des3") == 0)
                    137:                return EVP_des_ede3_cbc();
                    138: #endif
                    139: #ifndef OPENSSL_NO_RC2
                    140:        else if (!strcmp(name, "rc2-40"))
                    141:                return EVP_rc2_40_cbc();
                    142:        else if (!strcmp(name, "rc2-64"))
                    143:                return EVP_rc2_64_cbc();
                    144:        else if (!strcmp(name, "rc2-128"))
                    145:                return EVP_rc2_cbc();
                    146: #endif
1.14      inoguchi  147:        else
                    148:                return NULL;
1.11      inoguchi  149: }
                    150:
                    151: static int
                    152: smime_opt_cipher(int argc, char **argv, int *argsused)
                    153: {
                    154:        char *name = argv[0];
                    155:
                    156:        if (*name++ != '-')
                    157:                return (1);
                    158:
                    159:        if ((smime_config.cipher = get_cipher_by_name(name)) == NULL)
                    160:                if ((smime_config.cipher = EVP_get_cipherbyname(name)) == NULL)
                    161:                        return (1);
                    162:
                    163:        *argsused = 1;
                    164:        return (0);
                    165: }
                    166:
                    167: static int
                    168: smime_opt_inkey(char *arg)
                    169: {
                    170:        if (smime_config.keyfile == NULL) {
                    171:                smime_config.keyfile = arg;
                    172:                return (0);
                    173:        }
                    174:
                    175:        if (smime_config.signerfile == NULL) {
                    176:                BIO_puts(bio_err, "Illegal -inkey without -signer\n");
                    177:                return (1);
                    178:        }
                    179:
                    180:        if (smime_config.sksigners == NULL) {
                    181:                if ((smime_config.sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    182:                        return (1);
                    183:        }
                    184:        if (!sk_OPENSSL_STRING_push(smime_config.sksigners,
                    185:            smime_config.signerfile))
                    186:                return (1);
                    187:
                    188:        smime_config.signerfile = NULL;
                    189:
                    190:        if (smime_config.skkeys == NULL) {
                    191:                if ((smime_config.skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    192:                        return (1);
                    193:        }
                    194:        if (!sk_OPENSSL_STRING_push(smime_config.skkeys, smime_config.keyfile))
                    195:                return (1);
                    196:
                    197:        smime_config.keyfile = arg;
                    198:        return (0);
                    199: }
                    200:
                    201: static int
                    202: smime_opt_md(char *arg)
                    203: {
                    204:        if ((smime_config.sign_md = EVP_get_digestbyname(arg)) == NULL) {
                    205:                BIO_printf(bio_err, "Unknown digest %s\n", arg);
                    206:                return (1);
                    207:        }
                    208:        return (0);
                    209: }
                    210:
                    211: static int
                    212: smime_opt_signer(char *arg)
                    213: {
                    214:        if (smime_config.signerfile == NULL) {
                    215:                smime_config.signerfile = arg;
                    216:                return (0);
                    217:        }
                    218:
                    219:        if (smime_config.sksigners == NULL) {
                    220:                if ((smime_config.sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    221:                        return (1);
                    222:        }
                    223:        if (!sk_OPENSSL_STRING_push(smime_config.sksigners,
                    224:            smime_config.signerfile))
                    225:                return (1);
                    226:
                    227:        if (smime_config.keyfile == NULL)
                    228:                smime_config.keyfile = smime_config.signerfile;
                    229:
                    230:        if (smime_config.skkeys == NULL) {
                    231:                if ((smime_config.skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    232:                        return (1);
                    233:        }
                    234:        if (!sk_OPENSSL_STRING_push(smime_config.skkeys, smime_config.keyfile))
                    235:                return (1);
                    236:
                    237:        smime_config.keyfile = NULL;
                    238:
                    239:        smime_config.signerfile = arg;
                    240:        return (0);
                    241: }
                    242:
                    243: static int
                    244: smime_opt_verify_param(int argc, char **argv, int *argsused)
                    245: {
                    246:        int oargc = argc;
                    247:        int badarg = 0;
                    248:
                    249:        if (!args_verify(&argv, &argc, &badarg, bio_err, &smime_config.vpm))
                    250:                return (1);
                    251:        if (badarg)
                    252:                return (1);
                    253:
                    254:        *argsused = oargc - argc;
                    255:
                    256:        return (0);
                    257: }
                    258:
                    259: static const struct option smime_options[] = {
                    260: #ifndef OPENSSL_NO_AES
                    261:        {
                    262:                .name = "aes128",
                    263:                .desc = "Encrypt PEM output with CBC AES",
                    264:                .type = OPTION_ARGV_FUNC,
                    265:                .opt.argvfunc = smime_opt_cipher,
                    266:        },
                    267:        {
                    268:                .name = "aes192",
                    269:                .desc = "Encrypt PEM output with CBC AES",
                    270:                .type = OPTION_ARGV_FUNC,
                    271:                .opt.argvfunc = smime_opt_cipher,
                    272:        },
                    273:        {
                    274:                .name = "aes256",
                    275:                .desc = "Encrypt PEM output with CBC AES",
                    276:                .type = OPTION_ARGV_FUNC,
                    277:                .opt.argvfunc = smime_opt_cipher,
                    278:        },
                    279: #endif
                    280: #ifndef OPENSSL_NO_CAMELLIA
                    281:        {
                    282:                .name = "camellia128",
                    283:                .desc = "Encrypt PEM output with CBC Camellia",
                    284:                .type = OPTION_ARGV_FUNC,
                    285:                .opt.argvfunc = smime_opt_cipher,
                    286:        },
                    287:        {
                    288:                .name = "camellia192",
                    289:                .desc = "Encrypt PEM output with CBC Camellia",
                    290:                .type = OPTION_ARGV_FUNC,
                    291:                .opt.argvfunc = smime_opt_cipher,
                    292:        },
                    293:        {
                    294:                .name = "camellia256",
                    295:                .desc = "Encrypt PEM output with CBC Camellia",
                    296:                .type = OPTION_ARGV_FUNC,
                    297:                .opt.argvfunc = smime_opt_cipher,
                    298:        },
                    299: #endif
                    300: #ifndef OPENSSL_NO_DES
                    301:        {
                    302:                .name = "des",
                    303:                .desc = "Encrypt with DES",
                    304:                .type = OPTION_ARGV_FUNC,
                    305:                .opt.argvfunc = smime_opt_cipher,
                    306:        },
                    307:        {
                    308:                .name = "des3",
                    309:                .desc = "Encrypt with triple DES",
                    310:                .type = OPTION_ARGV_FUNC,
                    311:                .opt.argvfunc = smime_opt_cipher,
                    312:        },
                    313: #endif
                    314: #ifndef OPENSSL_NO_RC2
                    315:        {
                    316:                .name = "rc2-40",
                    317:                .desc = "Encrypt with RC2-40 (default)",
                    318:                .type = OPTION_ARGV_FUNC,
                    319:                .opt.argvfunc = smime_opt_cipher,
                    320:        },
                    321:        {
                    322:                .name = "rc2-64",
                    323:                .desc = "Encrypt with RC2-64",
                    324:                .type = OPTION_ARGV_FUNC,
                    325:                .opt.argvfunc = smime_opt_cipher,
                    326:        },
                    327:        {
                    328:                .name = "rc2-128",
                    329:                .desc = "Encrypt with RC2-128",
                    330:                .type = OPTION_ARGV_FUNC,
                    331:                .opt.argvfunc = smime_opt_cipher,
                    332:        },
                    333: #endif
                    334:        {
                    335:                .name = "CAfile",
                    336:                .argname = "file",
                    337:                .desc = "Certificate Authority file",
                    338:                .type = OPTION_ARG,
                    339:                .opt.arg = &smime_config.CAfile,
                    340:        },
                    341:        {
                    342:                .name = "CApath",
                    343:                .argname = "path",
                    344:                .desc = "Certificate Authority path",
                    345:                .type = OPTION_ARG,
                    346:                .opt.arg = &smime_config.CApath,
                    347:        },
                    348:        {
                    349:                .name = "binary",
                    350:                .desc = "Do not translate message to text",
                    351:                .type = OPTION_VALUE_OR,
                    352:                .opt.value = &smime_config.flags,
                    353:                .value = PKCS7_BINARY,
                    354:        },
                    355:        {
                    356:                .name = "certfile",
                    357:                .argname = "file",
                    358:                .desc = "Other certificates file",
                    359:                .type = OPTION_ARG,
                    360:                .opt.arg = &smime_config.certfile,
                    361:        },
                    362:        {
                    363:                .name = "content",
                    364:                .argname = "file",
                    365:                .desc = "Supply or override content for detached signature",
                    366:                .type = OPTION_ARG,
                    367:                .opt.arg = &smime_config.contfile,
                    368:        },
                    369:        {
                    370:                .name = "crlfeol",
                    371:                .desc = "Use CRLF as EOL termination instead of CR only",
                    372:                .type = OPTION_VALUE_OR,
                    373:                .opt.value = &smime_config.flags,
                    374:                .value = PKCS7_CRLFEOL,
                    375:        },
                    376:        {
                    377:                .name = "decrypt",
                    378:                .desc = "Decrypt encrypted message",
                    379:                .type = OPTION_VALUE,
                    380:                .opt.value = &smime_config.operation,
                    381:                .value = SMIME_DECRYPT,
                    382:        },
                    383:        {
                    384:                .name = "encrypt",
                    385:                .desc = "Encrypt message",
                    386:                .type = OPTION_VALUE,
                    387:                .opt.value = &smime_config.operation,
                    388:                .value = SMIME_ENCRYPT,
                    389:        },
                    390:        {
                    391:                .name = "from",
                    392:                .argname = "addr",
                    393:                .desc = "From address",
                    394:                .type = OPTION_ARG,
                    395:                .opt.arg = &smime_config.from,
                    396:        },
                    397:        {
                    398:                .name = "in",
                    399:                .argname = "file",
                    400:                .desc = "Input file",
                    401:                .type = OPTION_ARG,
                    402:                .opt.arg = &smime_config.infile,
                    403:        },
                    404:        {
                    405:                .name = "indef",
                    406:                .desc = "Same as -stream",
                    407:                .type = OPTION_VALUE,
                    408:                .opt.value = &smime_config.indef,
                    409:                .value = 1,
                    410:        },
                    411:        {
                    412:                .name = "inform",
                    413:                .argname = "fmt",
                    414:                .desc = "Input format (DER, PEM or SMIME (default))",
                    415:                .type = OPTION_ARG_FORMAT,
                    416:                .opt.value = &smime_config.informat,
                    417:        },
                    418:        {
                    419:                .name = "inkey",
                    420:                .argname = "file",
                    421:                .desc = "Input key file",
                    422:                .type = OPTION_ARG_FUNC,
                    423:                .opt.argfunc = smime_opt_inkey,
                    424:        },
                    425:        {
                    426:                .name = "keyform",
                    427:                .argname = "fmt",
                    428:                .desc = "Input key format (DER or PEM (default))",
                    429:                .type = OPTION_ARG_FORMAT,
                    430:                .opt.value = &smime_config.keyform,
                    431:        },
                    432:        {
                    433:                .name = "md",
                    434:                .argname = "digest",
                    435:                .desc = "Digest to use when signing or resigning",
                    436:                .type = OPTION_ARG_FUNC,
                    437:                .opt.argfunc = smime_opt_md,
                    438:        },
                    439:        {
                    440:                .name = "noattr",
                    441:                .desc = "Do not include any signed attributes",
                    442:                .type = OPTION_VALUE_OR,
                    443:                .opt.value = &smime_config.flags,
                    444:                .value = PKCS7_NOATTR,
                    445:        },
                    446:        {
                    447:                .name = "nocerts",
                    448:                .desc = "Do not include signer's certificate when signing",
                    449:                .type = OPTION_VALUE_OR,
                    450:                .opt.value = &smime_config.flags,
                    451:                .value = PKCS7_NOCERTS,
                    452:        },
                    453:        {
                    454:                .name = "nochain",
                    455:                .desc = "Do not chain verification of signer's certificates",
                    456:                .type = OPTION_VALUE_OR,
                    457:                .opt.value = &smime_config.flags,
                    458:                .value = PKCS7_NOCHAIN,
                    459:        },
                    460:        {
                    461:                .name = "nodetach",
                    462:                .desc = "Use opaque signing",
                    463:                .type = OPTION_VALUE_AND,
                    464:                .opt.value = &smime_config.flags,
                    465:                .value = ~PKCS7_DETACHED,
                    466:        },
                    467:        {
                    468:                .name = "noindef",
                    469:                .desc = "Disable streaming I/O",
                    470:                .type = OPTION_VALUE,
                    471:                .opt.value = &smime_config.indef,
                    472:                .value = 0,
                    473:        },
                    474:        {
                    475:                .name = "nointern",
                    476:                .desc = "Do not search certificates in message for signer",
                    477:                .type = OPTION_VALUE_OR,
                    478:                .opt.value = &smime_config.flags,
                    479:                .value = PKCS7_NOINTERN,
                    480:        },
                    481:        {
                    482:                .name = "nooldmime",
                    483:                .desc = "Output old S/MIME content type",
                    484:                .type = OPTION_VALUE_OR,
                    485:                .opt.value = &smime_config.flags,
                    486:                .value = PKCS7_NOOLDMIMETYPE,
                    487:        },
                    488:        {
                    489:                .name = "nosigs",
                    490:                .desc = "Do not verify message signature",
                    491:                .type = OPTION_VALUE_OR,
                    492:                .opt.value = &smime_config.flags,
                    493:                .value = PKCS7_NOSIGS,
                    494:        },
                    495:        {
                    496:                .name = "nosmimecap",
                    497:                .desc = "Omit the SMIMECapabilities attribute",
                    498:                .type = OPTION_VALUE_OR,
                    499:                .opt.value = &smime_config.flags,
                    500:                .value = PKCS7_NOSMIMECAP,
                    501:        },
                    502:        {
                    503:                .name = "noverify",
                    504:                .desc = "Do not verify signer's certificate",
                    505:                .type = OPTION_VALUE_OR,
                    506:                .opt.value = &smime_config.flags,
                    507:                .value = PKCS7_NOVERIFY,
                    508:        },
                    509:        {
                    510:                .name = "out",
                    511:                .argname = "file",
                    512:                .desc = "Output file",
                    513:                .type = OPTION_ARG,
                    514:                .opt.arg = &smime_config.outfile,
                    515:        },
                    516:        {
                    517:                .name = "outform",
                    518:                .argname = "fmt",
                    519:                .desc = "Output format (DER, PEM or SMIME (default))",
                    520:                .type = OPTION_ARG_FORMAT,
                    521:                .opt.value = &smime_config.outformat,
                    522:        },
                    523:        {
                    524:                .name = "passin",
                    525:                .argname = "src",
                    526:                .desc = "Private key password source",
                    527:                .type = OPTION_ARG,
                    528:                .opt.arg = &smime_config.passargin,
                    529:        },
                    530:        {
                    531:                .name = "pk7out",
                    532:                .desc = "Output PKCS#7 structure",
                    533:                .type = OPTION_VALUE,
                    534:                .opt.value = &smime_config.operation,
                    535:                .value = SMIME_PK7OUT,
                    536:        },
                    537:        {
                    538:                .name = "recip",
                    539:                .argname = "file",
                    540:                .desc = "Recipient certificate file for decryption",
                    541:                .type = OPTION_ARG,
                    542:                .opt.arg = &smime_config.recipfile,
                    543:        },
                    544:        {
                    545:                .name = "resign",
                    546:                .desc = "Resign a signed message",
                    547:                .type = OPTION_VALUE,
                    548:                .opt.value = &smime_config.operation,
                    549:                .value = SMIME_RESIGN,
                    550:        },
                    551:        {
                    552:                .name = "sign",
                    553:                .desc = "Sign message",
                    554:                .type = OPTION_VALUE,
                    555:                .opt.value = &smime_config.operation,
                    556:                .value = SMIME_SIGN,
                    557:        },
                    558:        {
                    559:                .name = "signer",
                    560:                .argname = "file",
                    561:                .desc = "Signer certificate file",
                    562:                .type = OPTION_ARG_FUNC,
                    563:                .opt.argfunc = smime_opt_signer,
                    564:        },
                    565:        {
                    566:                .name = "stream",
                    567:                .desc = "Enable streaming I/O",
                    568:                .type = OPTION_VALUE,
                    569:                .opt.value = &smime_config.indef,
                    570:                .value = 1,
                    571:        },
                    572:        {
                    573:                .name = "subject",
                    574:                .argname = "s",
                    575:                .desc = "Subject",
                    576:                .type = OPTION_ARG,
                    577:                .opt.arg = &smime_config.subject,
                    578:        },
                    579:        {
                    580:                .name = "text",
                    581:                .desc = "Include or delete text MIME headers",
                    582:                .type = OPTION_VALUE_OR,
                    583:                .opt.value = &smime_config.flags,
                    584:                .value = PKCS7_TEXT,
                    585:        },
                    586:        {
                    587:                .name = "to",
                    588:                .argname = "addr",
                    589:                .desc = "To address",
                    590:                .type = OPTION_ARG,
                    591:                .opt.arg = &smime_config.to,
                    592:        },
                    593:        {
                    594:                .name = "verify",
                    595:                .desc = "Verify signed message",
                    596:                .type = OPTION_VALUE,
                    597:                .opt.value = &smime_config.operation,
                    598:                .value = SMIME_VERIFY,
                    599:        },
                    600:        {
                    601:                .name = "check_ss_sig",
                    602:                .type = OPTION_ARGV_FUNC,
                    603:                .opt.argvfunc = smime_opt_verify_param,
                    604:        },
                    605:        {
                    606:                .name = "crl_check",
                    607:                .type = OPTION_ARGV_FUNC,
                    608:                .opt.argvfunc = smime_opt_verify_param,
                    609:        },
                    610:        {
                    611:                .name = "crl_check_all",
                    612:                .type = OPTION_ARGV_FUNC,
                    613:                .opt.argvfunc = smime_opt_verify_param,
                    614:        },
                    615:        {
                    616:                .name = "extended_crl",
                    617:                .type = OPTION_ARGV_FUNC,
                    618:                .opt.argvfunc = smime_opt_verify_param,
                    619:        },
                    620:        {
                    621:                .name = "ignore_critical",
                    622:                .type = OPTION_ARGV_FUNC,
                    623:                .opt.argvfunc = smime_opt_verify_param,
                    624:        },
                    625:        {
                    626:                .name = "issuer_checks",
                    627:                .type = OPTION_ARGV_FUNC,
                    628:                .opt.argvfunc = smime_opt_verify_param,
                    629:        },
                    630:        {
                    631:                .name = "policy_check",
                    632:                .type = OPTION_ARGV_FUNC,
                    633:                .opt.argvfunc = smime_opt_verify_param,
                    634:        },
                    635:        {
                    636:                .name = "x509_strict",
                    637:                .type = OPTION_ARGV_FUNC,
                    638:                .opt.argvfunc = smime_opt_verify_param,
                    639:        },
                    640:        {
                    641:                .name = NULL,
                    642:                .type = OPTION_ARGV_FUNC,
                    643:                .opt.argvfunc = smime_opt_cipher,
                    644:        },
                    645:        { NULL },
                    646: };
                    647:
                    648: static const struct option verify_shared_options[] = {
                    649:        {
                    650:                .name = "check_ss_sig",
                    651:                .desc = "Check the root CA self-signed certificate signature",
                    652:        },
                    653:        {
                    654:                .name = "crl_check",
                    655:                .desc = "Enable CRL checking for the leaf certificate",
                    656:        },
                    657:        {
                    658:                .name = "crl_check_all",
                    659:                .desc = "Enable CRL checking for the entire certificate chain",
                    660:        },
                    661:        {
                    662:                .name = "extended_crl",
                    663:                .desc = "Enable extended CRL support",
                    664:        },
                    665:        {
                    666:                .name = "ignore_critical",
                    667:                .desc = "Disable critical extension checking",
                    668:        },
                    669:        {
                    670:                .name = "issuer_checks",
                    671:                .desc = "Enable debugging of certificate issuer checks",
                    672:        },
                    673:        {
                    674:                .name = "policy_check",
                    675:                .desc = "Enable certificate policy checking",
                    676:        },
                    677:        {
                    678:                .name = "x509_strict",
                    679:                .desc = "Use strict X.509 rules (disables workarounds)",
                    680:        },
                    681:        { NULL },
                    682: };
                    683:
                    684: static void
                    685: smime_usage(void)
                    686: {
                    687:        fprintf(stderr, "usage: smime "
                    688:            "[-aes128 | -aes192 | -aes256 | -des |\n"
                    689:            "    -des3 | -rc2-40 | -rc2-64 | -rc2-128] [-binary]\n"
                    690:            "    [-CAfile file] [-CApath directory] [-certfile file]\n"
                    691:            "    [-content file]\n"
                    692:            "    [-decrypt] [-encrypt]\n"
                    693:            "    [-from addr] [-in file] [-indef]\n"
                    694:            "    [-inform der | pem | smime] [-inkey file]\n"
                    695:            "    [-keyform der | pem] [-md digest] [-noattr] [-nocerts]\n"
                    696:            "    [-nochain] [-nodetach] [-noindef] [-nointern] [-nosigs]\n"
                    697:            "    [-nosmimecap] [-noverify] [-out file]\n"
                    698:            "    [-outform der | pem | smime] [-passin arg] [-pk7out]\n"
                    699:            "    [-recip file] [-resign] [-sign]\n"
                    700:            "    [-signer file] [-stream] [-subject s] [-text] [-to addr]\n"
                    701:            "    [-verify] [cert.pem ...]\n\n");
                    702:
                    703:        options_usage(smime_options);
                    704:
                    705:        fprintf(stderr, "\nVerification options:\n\n");
                    706:        options_usage(verify_shared_options);
                    707: }
                    708:
1.1       jsing     709: int
                    710: smime_main(int argc, char **argv)
                    711: {
                    712:        int ret = 0;
                    713:        char **args;
1.11      inoguchi  714:        int argsused = 0;
1.1       jsing     715:        const char *inmode = "r", *outmode = "w";
                    716:        PKCS7 *p7 = NULL;
                    717:        X509_STORE *store = NULL;
                    718:        X509 *cert = NULL, *recip = NULL, *signer = NULL;
                    719:        EVP_PKEY *key = NULL;
1.12      inoguchi  720:        STACK_OF(X509) *encerts = NULL, *other = NULL;
1.1       jsing     721:        BIO *in = NULL, *out = NULL, *indata = NULL;
                    722:        int badarg = 0;
1.11      inoguchi  723:        char *passin = NULL;
1.5       doug      724:
                    725:        if (single_execution) {
1.8       deraadt   726:                if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
1.5       doug      727:                        perror("pledge");
1.7       doug      728:                        exit(1);
                    729:                }
1.5       doug      730:        }
1.1       jsing     731:
1.11      inoguchi  732:        memset(&smime_config, 0, sizeof(smime_config));
                    733:        smime_config.flags = PKCS7_DETACHED;
                    734:        smime_config.informat = FORMAT_SMIME;
                    735:        smime_config.outformat = FORMAT_SMIME;
                    736:        smime_config.keyform = FORMAT_PEM;
                    737:        if (options_parse(argc, argv, smime_options, NULL, &argsused) != 0) {
                    738:                goto argerr;
                    739:        }
                    740:        args = argv + argsused;
1.1       jsing     741:        ret = 1;
                    742:
1.16    ! inoguchi  743:        if (!(smime_config.operation & SMIME_SIGNERS) &&
        !           744:            (smime_config.skkeys != NULL || smime_config.sksigners != NULL)) {
1.1       jsing     745:                BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
                    746:                goto argerr;
                    747:        }
1.11      inoguchi  748:        if (smime_config.operation & SMIME_SIGNERS) {
1.1       jsing     749:                /* Check to see if any final signer needs to be appended */
1.16    ! inoguchi  750:                if (smime_config.keyfile != NULL &&
        !           751:                    smime_config.signerfile == NULL) {
1.1       jsing     752:                        BIO_puts(bio_err, "Illegal -inkey without -signer\n");
                    753:                        goto argerr;
                    754:                }
1.13      inoguchi  755:                if (smime_config.signerfile != NULL) {
1.15      inoguchi  756:                        if (smime_config.sksigners == NULL) {
1.16    ! inoguchi  757:                                if ((smime_config.sksigners =
        !           758:                                    sk_OPENSSL_STRING_new_null()) == NULL)
1.15      inoguchi  759:                                        goto end;
                    760:                        }
1.16    ! inoguchi  761:                        if (!sk_OPENSSL_STRING_push(smime_config.sksigners,
        !           762:                            smime_config.signerfile))
1.15      inoguchi  763:                                goto end;
                    764:                        if (smime_config.skkeys == NULL) {
1.16    ! inoguchi  765:                                if ((smime_config.skkeys =
        !           766:                                    sk_OPENSSL_STRING_new_null()) == NULL)
1.15      inoguchi  767:                                        goto end;
                    768:                        }
1.13      inoguchi  769:                        if (smime_config.keyfile == NULL)
1.11      inoguchi  770:                                smime_config.keyfile = smime_config.signerfile;
1.16    ! inoguchi  771:                        if (!sk_OPENSSL_STRING_push(smime_config.skkeys,
        !           772:                            smime_config.keyfile))
1.15      inoguchi  773:                                goto end;
1.1       jsing     774:                }
1.13      inoguchi  775:                if (smime_config.sksigners == NULL) {
1.16    ! inoguchi  776:                        BIO_printf(bio_err,
        !           777:                            "No signer certificate specified\n");
1.1       jsing     778:                        badarg = 1;
                    779:                }
1.11      inoguchi  780:                smime_config.signerfile = NULL;
                    781:                smime_config.keyfile = NULL;
                    782:        } else if (smime_config.operation == SMIME_DECRYPT) {
1.16    ! inoguchi  783:                if (smime_config.recipfile == NULL &&
        !           784:                    smime_config.keyfile == NULL) {
        !           785:                        BIO_printf(bio_err,
        !           786:                            "No recipient certificate or key specified\n");
1.1       jsing     787:                        badarg = 1;
                    788:                }
1.11      inoguchi  789:        } else if (smime_config.operation == SMIME_ENCRYPT) {
1.13      inoguchi  790:                if (*args == NULL) {
1.16    ! inoguchi  791:                        BIO_printf(bio_err,
        !           792:                            "No recipient(s) certificate(s) specified\n");
1.1       jsing     793:                        badarg = 1;
                    794:                }
1.15      inoguchi  795:        } else if (!smime_config.operation) {
1.1       jsing     796:                badarg = 1;
1.15      inoguchi  797:        }
1.1       jsing     798:
                    799:        if (badarg) {
1.10      jsing     800:  argerr:
1.11      inoguchi  801:                smime_usage();
1.1       jsing     802:                goto end;
                    803:        }
                    804:
1.11      inoguchi  805:        if (!app_passwd(bio_err, smime_config.passargin, NULL, &passin, NULL)) {
1.1       jsing     806:                BIO_printf(bio_err, "Error getting password\n");
                    807:                goto end;
                    808:        }
                    809:        ret = 2;
                    810:
1.11      inoguchi  811:        if (!(smime_config.operation & SMIME_SIGNERS))
                    812:                smime_config.flags &= ~PKCS7_DETACHED;
1.1       jsing     813:
1.11      inoguchi  814:        if (smime_config.operation & SMIME_OP) {
                    815:                if (smime_config.outformat == FORMAT_ASN1)
1.1       jsing     816:                        outmode = "wb";
                    817:        } else {
1.11      inoguchi  818:                if (smime_config.flags & PKCS7_BINARY)
1.1       jsing     819:                        outmode = "wb";
                    820:        }
                    821:
1.11      inoguchi  822:        if (smime_config.operation & SMIME_IP) {
                    823:                if (smime_config.informat == FORMAT_ASN1)
1.1       jsing     824:                        inmode = "rb";
                    825:        } else {
1.11      inoguchi  826:                if (smime_config.flags & PKCS7_BINARY)
1.1       jsing     827:                        inmode = "rb";
                    828:        }
                    829:
1.11      inoguchi  830:        if (smime_config.operation == SMIME_ENCRYPT) {
1.13      inoguchi  831:                if (smime_config.cipher == NULL) {
1.1       jsing     832: #ifndef OPENSSL_NO_RC2
1.11      inoguchi  833:                        smime_config.cipher = EVP_rc2_40_cbc();
1.1       jsing     834: #else
                    835:                        BIO_printf(bio_err, "No cipher selected\n");
                    836:                        goto end;
                    837: #endif
                    838:                }
1.15      inoguchi  839:                if ((encerts = sk_X509_new_null()) == NULL)
                    840:                        goto end;
1.13      inoguchi  841:                while (*args != NULL) {
                    842:                        if ((cert = load_cert(bio_err, *args, FORMAT_PEM,
                    843:                            NULL, "recipient certificate file")) == NULL) {
1.1       jsing     844:                                goto end;
                    845:                        }
1.15      inoguchi  846:                        if (!sk_X509_push(encerts, cert))
                    847:                                goto end;
1.1       jsing     848:                        cert = NULL;
                    849:                        args++;
                    850:                }
                    851:        }
1.13      inoguchi  852:        if (smime_config.certfile != NULL) {
1.16    ! inoguchi  853:                if ((other = load_certs(bio_err, smime_config.certfile,
        !           854:                    FORMAT_PEM, NULL, "certificate file")) == NULL) {
1.1       jsing     855:                        ERR_print_errors(bio_err);
                    856:                        goto end;
                    857:                }
                    858:        }
1.16    ! inoguchi  859:        if (smime_config.recipfile != NULL &&
        !           860:            (smime_config.operation == SMIME_DECRYPT)) {
        !           861:                if ((recip = load_cert(bio_err, smime_config.recipfile,
        !           862:                    FORMAT_PEM, NULL, "recipient certificate file")) == NULL) {
1.1       jsing     863:                        ERR_print_errors(bio_err);
                    864:                        goto end;
                    865:                }
                    866:        }
1.11      inoguchi  867:        if (smime_config.operation == SMIME_DECRYPT) {
1.13      inoguchi  868:                if (smime_config.keyfile == NULL)
1.11      inoguchi  869:                        smime_config.keyfile = smime_config.recipfile;
                    870:        } else if (smime_config.operation == SMIME_SIGN) {
1.13      inoguchi  871:                if (smime_config.keyfile == NULL)
1.11      inoguchi  872:                        smime_config.keyfile = smime_config.signerfile;
1.15      inoguchi  873:        } else {
1.11      inoguchi  874:                smime_config.keyfile = NULL;
1.15      inoguchi  875:        }
1.1       jsing     876:
1.13      inoguchi  877:        if (smime_config.keyfile != NULL) {
1.16    ! inoguchi  878:                key = load_key(bio_err, smime_config.keyfile,
        !           879:                    smime_config.keyform, 0, passin, "signing key file");
1.13      inoguchi  880:                if (key == NULL)
1.1       jsing     881:                        goto end;
                    882:        }
1.13      inoguchi  883:        if (smime_config.infile != NULL) {
                    884:                if ((in = BIO_new_file(smime_config.infile, inmode)) == NULL) {
1.1       jsing     885:                        BIO_printf(bio_err,
1.11      inoguchi  886:                            "Can't open input file %s\n", smime_config.infile);
1.1       jsing     887:                        goto end;
                    888:                }
1.15      inoguchi  889:        } else {
                    890:                if ((in = BIO_new_fp(stdin, BIO_NOCLOSE)) == NULL)
                    891:                        goto end;
                    892:        }
1.1       jsing     893:
1.11      inoguchi  894:        if (smime_config.operation & SMIME_IP) {
                    895:                if (smime_config.informat == FORMAT_SMIME)
1.1       jsing     896:                        p7 = SMIME_read_PKCS7(in, &indata);
1.11      inoguchi  897:                else if (smime_config.informat == FORMAT_PEM)
1.1       jsing     898:                        p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
1.11      inoguchi  899:                else if (smime_config.informat == FORMAT_ASN1)
1.1       jsing     900:                        p7 = d2i_PKCS7_bio(in, NULL);
                    901:                else {
1.16    ! inoguchi  902:                        BIO_printf(bio_err,
        !           903:                            "Bad input format for PKCS#7 file\n");
1.1       jsing     904:                        goto end;
                    905:                }
                    906:
1.13      inoguchi  907:                if (p7 == NULL) {
1.1       jsing     908:                        BIO_printf(bio_err, "Error reading S/MIME message\n");
                    909:                        goto end;
                    910:                }
1.13      inoguchi  911:                if (smime_config.contfile != NULL) {
1.1       jsing     912:                        BIO_free(indata);
1.16    ! inoguchi  913:                        if ((indata = BIO_new_file(smime_config.contfile,
        !           914:                            "rb")) == NULL) {
        !           915:                                BIO_printf(bio_err,
        !           916:                                    "Can't read content file %s\n",
        !           917:                                    smime_config.contfile);
1.1       jsing     918:                                goto end;
                    919:                        }
                    920:                }
                    921:        }
1.13      inoguchi  922:        if (smime_config.outfile != NULL) {
                    923:                if ((out = BIO_new_file(smime_config.outfile, outmode)) == NULL) {
1.1       jsing     924:                        BIO_printf(bio_err,
1.16    ! inoguchi  925:                            "Can't open output file %s\n",
        !           926:                            smime_config.outfile);
1.1       jsing     927:                        goto end;
                    928:                }
                    929:        } else {
1.15      inoguchi  930:                if ((out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
                    931:                        goto end;
1.1       jsing     932:        }
                    933:
1.11      inoguchi  934:        if (smime_config.operation == SMIME_VERIFY) {
1.16    ! inoguchi  935:                if ((store = setup_verify(bio_err, smime_config.CAfile,
        !           936:                    smime_config.CApath)) == NULL)
1.1       jsing     937:                        goto end;
                    938:                X509_STORE_set_verify_cb(store, smime_cb);
1.15      inoguchi  939:                if (smime_config.vpm != NULL) {
                    940:                        if (!X509_STORE_set1_param(store, smime_config.vpm))
                    941:                                goto end;
                    942:                }
1.1       jsing     943:        }
                    944:        ret = 3;
                    945:
1.11      inoguchi  946:        if (smime_config.operation == SMIME_ENCRYPT) {
                    947:                if (smime_config.indef)
                    948:                        smime_config.flags |= PKCS7_STREAM;
1.16    ! inoguchi  949:                p7 = PKCS7_encrypt(encerts, in, smime_config.cipher,
        !           950:                    smime_config.flags);
1.11      inoguchi  951:        } else if (smime_config.operation & SMIME_SIGNERS) {
1.1       jsing     952:                int i;
                    953:                /*
                    954:                 * If detached data content we only enable streaming if
                    955:                 * S/MIME output format.
                    956:                 */
1.11      inoguchi  957:                if (smime_config.operation == SMIME_SIGN) {
                    958:                        if (smime_config.flags & PKCS7_DETACHED) {
                    959:                                if (smime_config.outformat == FORMAT_SMIME)
                    960:                                        smime_config.flags |= PKCS7_STREAM;
1.15      inoguchi  961:                        } else if (smime_config.indef) {
1.11      inoguchi  962:                                smime_config.flags |= PKCS7_STREAM;
1.15      inoguchi  963:                        }
1.11      inoguchi  964:                        smime_config.flags |= PKCS7_PARTIAL;
1.16    ! inoguchi  965:                        p7 = PKCS7_sign(NULL, NULL, other, in,
        !           966:                            smime_config.flags);
1.13      inoguchi  967:                        if (p7 == NULL)
1.1       jsing     968:                                goto end;
1.15      inoguchi  969:                } else {
1.11      inoguchi  970:                        smime_config.flags |= PKCS7_REUSE_DIGEST;
1.15      inoguchi  971:                }
1.11      inoguchi  972:                for (i = 0; i < sk_OPENSSL_STRING_num(smime_config.sksigners); i++) {
1.16    ! inoguchi  973:                        smime_config.signerfile =
        !           974:                            sk_OPENSSL_STRING_value(smime_config.sksigners, i);
        !           975:                        smime_config.keyfile =
        !           976:                            sk_OPENSSL_STRING_value(smime_config.skkeys, i);
        !           977:                        signer = load_cert(bio_err, smime_config.signerfile,
        !           978:                            FORMAT_PEM, NULL, "signer certificate");
1.13      inoguchi  979:                        if (signer == NULL)
1.1       jsing     980:                                goto end;
1.16    ! inoguchi  981:                        key = load_key(bio_err, smime_config.keyfile,
        !           982:                            smime_config.keyform, 0, passin,
1.1       jsing     983:                            "signing key file");
1.13      inoguchi  984:                        if (key == NULL)
1.1       jsing     985:                                goto end;
1.13      inoguchi  986:                        if (PKCS7_sign_add_signer(p7, signer, key,
1.16    ! inoguchi  987:                            smime_config.sign_md, smime_config.flags) == NULL)
1.1       jsing     988:                                goto end;
                    989:                        X509_free(signer);
                    990:                        signer = NULL;
                    991:                        EVP_PKEY_free(key);
                    992:                        key = NULL;
                    993:                }
                    994:                /* If not streaming or resigning finalize structure */
1.16    ! inoguchi  995:                if ((smime_config.operation == SMIME_SIGN) &&
        !           996:                    !(smime_config.flags & PKCS7_STREAM)) {
1.11      inoguchi  997:                        if (!PKCS7_final(p7, in, smime_config.flags))
1.1       jsing     998:                                goto end;
                    999:                }
                   1000:        }
1.13      inoguchi 1001:        if (p7 == NULL) {
1.1       jsing    1002:                BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
                   1003:                goto end;
                   1004:        }
                   1005:        ret = 4;
1.16    ! inoguchi 1006:
1.11      inoguchi 1007:        if (smime_config.operation == SMIME_DECRYPT) {
                   1008:                if (!PKCS7_decrypt(p7, key, recip, out, smime_config.flags)) {
1.16    ! inoguchi 1009:                        BIO_printf(bio_err,
        !          1010:                            "Error decrypting PKCS#7 structure\n");
1.1       jsing    1011:                        goto end;
                   1012:                }
1.11      inoguchi 1013:        } else if (smime_config.operation == SMIME_VERIFY) {
1.12      inoguchi 1014:                STACK_OF(X509) *signers;
1.16    ! inoguchi 1015:                if (PKCS7_verify(p7, other, store, indata, out,
        !          1016:                    smime_config.flags)) {
1.1       jsing    1017:                        BIO_printf(bio_err, "Verification successful\n");
1.15      inoguchi 1018:                } else {
1.1       jsing    1019:                        BIO_printf(bio_err, "Verification failure\n");
                   1020:                        goto end;
                   1021:                }
1.16    ! inoguchi 1022:                if ((signers = PKCS7_get0_signers(p7, other,
        !          1023:                    smime_config.flags)) == NULL)
1.15      inoguchi 1024:                        goto end;
1.11      inoguchi 1025:                if (!save_certs(smime_config.signerfile, signers)) {
1.1       jsing    1026:                        BIO_printf(bio_err, "Error writing signers to %s\n",
1.11      inoguchi 1027:                            smime_config.signerfile);
1.1       jsing    1028:                        ret = 5;
                   1029:                        goto end;
                   1030:                }
                   1031:                sk_X509_free(signers);
1.15      inoguchi 1032:        } else if (smime_config.operation == SMIME_PK7OUT) {
1.1       jsing    1033:                PEM_write_bio_PKCS7(out, p7);
1.15      inoguchi 1034:        } else {
1.13      inoguchi 1035:                if (smime_config.to != NULL)
1.11      inoguchi 1036:                        BIO_printf(out, "To: %s\n", smime_config.to);
1.13      inoguchi 1037:                if (smime_config.from != NULL)
1.11      inoguchi 1038:                        BIO_printf(out, "From: %s\n", smime_config.from);
1.13      inoguchi 1039:                if (smime_config.subject != NULL)
1.11      inoguchi 1040:                        BIO_printf(out, "Subject: %s\n", smime_config.subject);
                   1041:                if (smime_config.outformat == FORMAT_SMIME) {
1.15      inoguchi 1042:                        if (smime_config.operation == SMIME_RESIGN) {
1.16    ! inoguchi 1043:                                if (!SMIME_write_PKCS7(out, p7, indata,
        !          1044:                                    smime_config.flags))
1.15      inoguchi 1045:                                        goto end;
                   1046:                        } else {
1.16    ! inoguchi 1047:                                if (!SMIME_write_PKCS7(out, p7, in,
        !          1048:                                    smime_config.flags))
1.15      inoguchi 1049:                                        goto end;
                   1050:                        }
                   1051:                } else if (smime_config.outformat == FORMAT_PEM) {
1.16    ! inoguchi 1052:                        if (!PEM_write_bio_PKCS7_stream(out, p7, in,
        !          1053:                            smime_config.flags))
1.15      inoguchi 1054:                                goto end;
                   1055:                } else if (smime_config.outformat == FORMAT_ASN1) {
1.16    ! inoguchi 1056:                        if (!i2d_PKCS7_bio_stream(out, p7, in,
        !          1057:                            smime_config.flags))
1.15      inoguchi 1058:                                goto end;
                   1059:                } else {
1.16    ! inoguchi 1060:                        BIO_printf(bio_err,
        !          1061:                            "Bad output format for PKCS#7 file\n");
1.1       jsing    1062:                        goto end;
                   1063:                }
                   1064:        }
1.15      inoguchi 1065:
1.1       jsing    1066:        ret = 0;
1.15      inoguchi 1067:
1.10      jsing    1068:  end:
1.1       jsing    1069:        if (ret)
                   1070:                ERR_print_errors(bio_err);
                   1071:        sk_X509_pop_free(encerts, X509_free);
                   1072:        sk_X509_pop_free(other, X509_free);
1.11      inoguchi 1073:        X509_VERIFY_PARAM_free(smime_config.vpm);
                   1074:        sk_OPENSSL_STRING_free(smime_config.sksigners);
                   1075:        sk_OPENSSL_STRING_free(smime_config.skkeys);
1.1       jsing    1076:        X509_STORE_free(store);
                   1077:        X509_free(cert);
                   1078:        X509_free(recip);
                   1079:        X509_free(signer);
                   1080:        EVP_PKEY_free(key);
                   1081:        PKCS7_free(p7);
                   1082:        BIO_free(in);
                   1083:        BIO_free(indata);
                   1084:        BIO_free_all(out);
                   1085:        free(passin);
                   1086:
                   1087:        return (ret);
                   1088: }
                   1089:
                   1090: static int
1.12      inoguchi 1091: save_certs(char *signerfile, STACK_OF(X509) *signers)
1.1       jsing    1092: {
                   1093:        int i;
                   1094:        BIO *tmp;
1.12      inoguchi 1095:
1.13      inoguchi 1096:        if (signerfile == NULL)
1.1       jsing    1097:                return 1;
                   1098:        tmp = BIO_new_file(signerfile, "w");
1.13      inoguchi 1099:        if (tmp == NULL)
1.1       jsing    1100:                return 0;
                   1101:        for (i = 0; i < sk_X509_num(signers); i++)
                   1102:                PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
                   1103:        BIO_free(tmp);
1.12      inoguchi 1104:
1.1       jsing    1105:        return 1;
                   1106: }
                   1107:
                   1108: /* Minimal callback just to output policy info (if any) */
                   1109: static int
1.12      inoguchi 1110: smime_cb(int ok, X509_STORE_CTX *ctx)
1.1       jsing    1111: {
                   1112:        int error;
                   1113:
                   1114:        error = X509_STORE_CTX_get_error(ctx);
                   1115:
1.16    ! inoguchi 1116:        if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) &&
        !          1117:            ((error != X509_V_OK) || (ok != 2)))
1.1       jsing    1118:                return ok;
                   1119:
                   1120:        policies_print(NULL, ctx);
                   1121:
                   1122:        return ok;
                   1123: }