コード例 #1
0
ファイル: ocsp.c プロジェクト: lullajd/openssl
int ocsp_main(int argc, char **argv)
{
    BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL;
    const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
    int trailing_md = 0;
    CA_DB *rdb = NULL;
    EVP_PKEY *key = NULL, *rkey = NULL;
    OCSP_BASICRESP *bs = NULL;
    OCSP_REQUEST *req = NULL;
    OCSP_RESPONSE *resp = NULL;
    STACK_OF(CONF_VALUE) *headers = NULL;
    STACK_OF(OCSP_CERTID) *ids = NULL;
    STACK_OF(OPENSSL_STRING) *reqnames = NULL;
    STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
    STACK_OF(X509) *issuers = NULL;
    X509 *issuer = NULL, *cert = NULL;
    STACK_OF(X509) *rca_cert = NULL;
    X509 *signer = NULL, *rsigner = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
    const char *CAfile = NULL, *CApath = NULL;
    char *header, *value;
    char *host = NULL, *port = NULL, *path = "/", *outfile = NULL;
    char *rca_filename = NULL, *reqin = NULL, *respin = NULL;
    char *reqout = NULL, *respout = NULL, *ridx_filename = NULL;
    char *rsignfile = NULL, *rkeyfile = NULL;
    char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
    char *signfile = NULL, *keyfile = NULL;
    char *thost = NULL, *tport = NULL, *tpath = NULL;
    int noCAfile = 0, noCApath = 0;
    int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1;
    int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1;
    int req_text = 0, resp_text = 0, ret = 1;
#ifndef OPENSSL_NO_SOCK
    int req_timeout = -1;
#endif
    long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
    unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
    OPTION_CHOICE o;
    char *prog;

    reqnames = sk_OPENSSL_STRING_new_null();
    if (reqnames == NULL)
        goto end;
    ids = sk_OCSP_CERTID_new_null();
    if (ids == NULL)
        goto end;
    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        return 1;

    prog = opt_init(argc, argv, ocsp_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            ret = 0;
            opt_help(ocsp_options);
            goto end;
        case OPT_OUTFILE:
            outfile = opt_arg();
            break;
        case OPT_TIMEOUT:
#ifndef OPENSSL_NO_SOCK
            req_timeout = atoi(opt_arg());
#endif
            break;
        case OPT_URL:
            OPENSSL_free(thost);
            OPENSSL_free(tport);
            OPENSSL_free(tpath);
            thost = tport = tpath = NULL;
            if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
                BIO_printf(bio_err, "%s Error parsing URL\n", prog);
                goto end;
            }
            thost = host;
            tport = port;
            tpath = path;
            break;
        case OPT_HOST:
            host = opt_arg();
            break;
        case OPT_PORT:
            port = opt_arg();
            break;
        case OPT_IGNORE_ERR:
            ignore_err = 1;
            break;
        case OPT_NOVERIFY:
            noverify = 1;
            break;
        case OPT_NONCE:
            add_nonce = 2;
            break;
        case OPT_NO_NONCE:
            add_nonce = 0;
            break;
        case OPT_RESP_NO_CERTS:
            rflags |= OCSP_NOCERTS;
            break;
        case OPT_RESP_KEY_ID:
            rflags |= OCSP_RESPID_KEY;
            break;
        case OPT_NO_CERTS:
            sign_flags |= OCSP_NOCERTS;
            break;
        case OPT_NO_SIGNATURE_VERIFY:
            verify_flags |= OCSP_NOSIGS;
            break;
        case OPT_NO_CERT_VERIFY:
            verify_flags |= OCSP_NOVERIFY;
            break;
        case OPT_NO_CHAIN:
            verify_flags |= OCSP_NOCHAIN;
            break;
        case OPT_NO_CERT_CHECKS:
            verify_flags |= OCSP_NOCHECKS;
            break;
        case OPT_NO_EXPLICIT:
            verify_flags |= OCSP_NOEXPLICIT;
            break;
        case OPT_TRUST_OTHER:
            verify_flags |= OCSP_TRUSTOTHER;
            break;
        case OPT_NO_INTERN:
            verify_flags |= OCSP_NOINTERN;
            break;
        case OPT_BADSIG:
            badsig = 1;
            break;
        case OPT_TEXT:
            req_text = resp_text = 1;
            break;
        case OPT_REQ_TEXT:
            req_text = 1;
            break;
        case OPT_RESP_TEXT:
            resp_text = 1;
            break;
        case OPT_REQIN:
            reqin = opt_arg();
            break;
        case OPT_RESPIN:
            respin = opt_arg();
            break;
        case OPT_SIGNER:
            signfile = opt_arg();
            break;
        case OPT_VAFILE:
            verify_certfile = opt_arg();
            verify_flags |= OCSP_TRUSTOTHER;
            break;
        case OPT_SIGN_OTHER:
            sign_certfile = opt_arg();
            break;
        case OPT_VERIFY_OTHER:
            verify_certfile = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto end;
            vpmtouched++;
            break;
        case OPT_VALIDITY_PERIOD:
            opt_long(opt_arg(), &nsec);
            break;
        case OPT_STATUS_AGE:
            opt_long(opt_arg(), &maxage);
            break;
        case OPT_SIGNKEY:
            keyfile = opt_arg();
            break;
        case OPT_REQOUT:
            reqout = opt_arg();
            break;
        case OPT_RESPOUT:
            respout = opt_arg();
            break;
        case OPT_PATH:
            path = opt_arg();
            break;
        case OPT_ISSUER:
            issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate");
            if (issuer == NULL)
                goto end;
            if (issuers == NULL) {
                if ((issuers = sk_X509_new_null()) == NULL)
                    goto end;
            }
            sk_X509_push(issuers, issuer);
            break;
        case OPT_CERT:
            X509_free(cert);
            cert = load_cert(opt_arg(), FORMAT_PEM, "certificate");
            if (cert == NULL)
                goto end;
            if (cert_id_md == NULL)
                cert_id_md = EVP_sha1();
            if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
                goto end;
            if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
                goto end;
            trailing_md = 0;
            break;
        case OPT_SERIAL:
            if (cert_id_md == NULL)
                cert_id_md = EVP_sha1();
            if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids))
                goto end;
            if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
                goto end;
            trailing_md = 0;
            break;
        case OPT_INDEX:
            ridx_filename = opt_arg();
            break;
        case OPT_CA:
            rca_filename = opt_arg();
            break;
        case OPT_NMIN:
            opt_int(opt_arg(), &nmin);
            if (ndays == -1)
                ndays = 0;
            break;
        case OPT_REQUEST:
            opt_int(opt_arg(), &accept_count);
            break;
        case OPT_NDAYS:
            ndays = atoi(opt_arg());
            break;
        case OPT_RSIGNER:
            rsignfile = opt_arg();
            break;
        case OPT_RKEY:
            rkeyfile = opt_arg();
            break;
        case OPT_ROTHER:
            rcertfile = opt_arg();
            break;
        case OPT_RMD:   /* Response MessageDigest */
            if (!opt_md(opt_arg(), &rsign_md))
                goto end;
            break;
        case OPT_HEADER:
            header = opt_arg();
            value = strchr(header, '=');
            if (value == NULL) {
                BIO_printf(bio_err, "Missing = in header key=value\n");
                goto opthelp;
            }
            *value++ = '\0';
            if (!X509V3_add_value(header, value, &headers))
                goto end;
            break;
        case OPT_MD:
            if (trailing_md) {
                BIO_printf(bio_err,
                           "%s: Digest must be before -cert or -serial\n",
                           prog);
                goto opthelp;
            }
            if (!opt_md(opt_unknown(), &cert_id_md))
                goto opthelp;
            trailing_md = 1;
            break;
        }
    }

    if (trailing_md) {
        BIO_printf(bio_err, "%s: Digest must be before -cert or -serial\n",
                   prog);
        goto opthelp;
    }
    argc = opt_num_rest();
    if (argc != 0)
        goto opthelp;

    /* Have we anything to do? */
    if (req == NULL&& reqin == NULL
        && respin == NULL && !(port != NULL && ridx_filename != NULL))
        goto opthelp;

    out = bio_open_default(outfile, 'w', FORMAT_TEXT);
    if (out == NULL)
        goto end;

    if (req == NULL && (add_nonce != 2))
        add_nonce = 0;

    if (req == NULL && reqin != NULL) {
        derbio = bio_open_default(reqin, 'r', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        req = d2i_OCSP_REQUEST_bio(derbio, NULL);
        BIO_free(derbio);
        if (req == NULL) {
            BIO_printf(bio_err, "Error reading OCSP request\n");
            goto end;
        }
    }

    if (req == NULL && port != NULL) {
        acbio = init_responder(port);
        if (acbio == NULL)
            goto end;
    }

    if (rsignfile != NULL) {
        if (rkeyfile == NULL)
            rkeyfile = rsignfile;
        rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate");
        if (rsigner == NULL) {
            BIO_printf(bio_err, "Error loading responder certificate\n");
            goto end;
        }
        if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM,
                        NULL, "CA certificate"))
            goto end;
        if (rcertfile != NULL) {
            if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL,
                            "responder other certificates"))
                goto end;
        }
        rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL,
                        "responder private key");
        if (rkey == NULL)
            goto end;
    }
    if (acbio != NULL)
        BIO_printf(bio_err, "Waiting for OCSP client connections...\n");

redo_accept:

    if (acbio != NULL) {
        if (!do_responder(&req, &cbio, acbio))
            goto end;
        if (req == NULL) {
            resp =
                OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
                                     NULL);
            send_ocsp_response(cbio, resp);
            goto done_resp;
        }
    }

    if (req == NULL
        && (signfile != NULL || reqout != NULL
            || host != NULL || add_nonce || ridx_filename != NULL)) {
        BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
        goto end;
    }

    if (req != NULL && add_nonce)
        OCSP_request_add1_nonce(req, NULL, -1);

    if (signfile != NULL) {
        if (keyfile == NULL)
            keyfile = signfile;
        signer = load_cert(signfile, FORMAT_PEM, "signer certificate");
        if (signer == NULL) {
            BIO_printf(bio_err, "Error loading signer certificate\n");
            goto end;
        }
        if (sign_certfile != NULL) {
            if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL,
                            "signer certificates"))
                goto end;
        }
        key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL,
                       "signer private key");
        if (key == NULL)
            goto end;

        if (!OCSP_request_sign
            (req, signer, key, NULL, sign_other, sign_flags)) {
            BIO_printf(bio_err, "Error signing OCSP request\n");
            goto end;
        }
    }

    if (req_text && req != NULL)
        OCSP_REQUEST_print(out, req, 0);

    if (reqout != NULL) {
        derbio = bio_open_default(reqout, 'w', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        i2d_OCSP_REQUEST_bio(derbio, req);
        BIO_free(derbio);
    }

    if (ridx_filename != NULL
        && (rkey == NULL || rsigner == NULL || rca_cert == NULL)) {
        BIO_printf(bio_err,
                   "Need a responder certificate, key and CA for this operation!\n");
        goto end;
    }

    if (ridx_filename != NULL && rdb == NULL) {
        rdb = load_index(ridx_filename, NULL);
        if (rdb == NULL)
            goto end;
        if (!index_index(rdb))
            goto end;
    }

    if (rdb != NULL) {
        make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey,
                               rsign_md, rother, rflags, nmin, ndays, badsig);
        if (cbio != NULL)
            send_ocsp_response(cbio, resp);
    } else if (host != NULL) {
# ifndef OPENSSL_NO_SOCK
        resp = process_responder(req, host, path,
                                 port, use_ssl, headers, req_timeout);
        if (resp == NULL)
            goto end;
# else
        BIO_printf(bio_err,
                   "Error creating connect BIO - sockets not supported.\n");
        goto end;
# endif
    } else if (respin != NULL) {
        derbio = bio_open_default(respin, 'r', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
        BIO_free(derbio);
        if (resp == NULL) {
            BIO_printf(bio_err, "Error reading OCSP response\n");
            goto end;
        }
    } else {
        ret = 0;
        goto end;
    }

 done_resp:

    if (respout != NULL) {
        derbio = bio_open_default(respout, 'w', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        i2d_OCSP_RESPONSE_bio(derbio, resp);
        BIO_free(derbio);
    }

    i = OCSP_response_status(resp);
    if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
        BIO_printf(out, "Responder Error: %s (%d)\n",
                   OCSP_response_status_str(i), i);
        if (ignore_err)
            goto redo_accept;
        ret = 0;
        goto end;
    }

    if (resp_text)
        OCSP_RESPONSE_print(out, resp, 0);

    /* If running as responder don't verify our own response */
    if (cbio != NULL) {
        /* If not unlimited, see if we took all we should. */
        if (accept_count != -1 && --accept_count <= 0) {
            ret = 0;
            goto end;
        }
        BIO_free_all(cbio);
        cbio = NULL;
        OCSP_REQUEST_free(req);
        req = NULL;
        OCSP_RESPONSE_free(resp);
        resp = NULL;
        goto redo_accept;
    }
    if (ridx_filename != NULL) {
        ret = 0;
        goto end;
    }

    if (store == NULL) {
        store = setup_verify(CAfile, CApath, noCAfile, noCApath);
        if (!store)
            goto end;
    }
    if (vpmtouched)
        X509_STORE_set1_param(store, vpm);
    if (verify_certfile != NULL) {
        if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL,
                        "validator certificate"))
            goto end;
    }

    bs = OCSP_response_get1_basic(resp);
    if (bs == NULL) {
        BIO_printf(bio_err, "Error parsing response\n");
        goto end;
    }

    ret = 0;

    if (!noverify) {
        if (req != NULL && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
            if (i == -1)
                BIO_printf(bio_err, "WARNING: no nonce in response\n");
            else {
                BIO_printf(bio_err, "Nonce Verify error\n");
                ret = 1;
                goto end;
            }
        }

        i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
        if (i <= 0 && issuers) {
            i = OCSP_basic_verify(bs, issuers, store, OCSP_TRUSTOTHER);
            if (i > 0)
                ERR_clear_error();
        }
        if (i <= 0) {
            BIO_printf(bio_err, "Response Verify Failure\n");
            ERR_print_errors(bio_err);
            ret = 1;
        } else {
            BIO_printf(bio_err, "Response verify OK\n");
        }
    }

    print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage);

 end:
    ERR_print_errors(bio_err);
    X509_free(signer);
    X509_STORE_free(store);
    X509_VERIFY_PARAM_free(vpm);
    EVP_PKEY_free(key);
    EVP_PKEY_free(rkey);
    X509_free(cert);
    sk_X509_pop_free(issuers, X509_free);
    X509_free(rsigner);
    sk_X509_pop_free(rca_cert, X509_free);
    free_index(rdb);
    BIO_free_all(cbio);
    BIO_free_all(acbio);
    BIO_free(out);
    OCSP_REQUEST_free(req);
    OCSP_RESPONSE_free(resp);
    OCSP_BASICRESP_free(bs);
    sk_OPENSSL_STRING_free(reqnames);
    sk_OCSP_CERTID_free(ids);
    sk_X509_pop_free(sign_other, X509_free);
    sk_X509_pop_free(verify_other, X509_free);
    sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
    OPENSSL_free(thost);
    OPENSSL_free(tport);
    OPENSSL_free(tpath);

    return ret;
}
コード例 #2
0
ファイル: verify.c プロジェクト: DoctorLawrence/openssl
int verify_main(int argc, char **argv)
{
    ENGINE *e = NULL;
    STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
    STACK_OF(X509_CRL) *crls = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
    char *prog, *CApath = NULL, *CAfile = NULL;
    char *untfile = NULL, *trustfile = NULL, *crlfile = NULL;
    int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1;
    OPTION_CHOICE o;

    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        goto end;

    prog = opt_init(argc, argv, verify_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(verify_options);
            BIO_printf(bio_err, "Recognized usages:\n");
            for (i = 0; i < X509_PURPOSE_get_count(); i++) {
                X509_PURPOSE *ptmp;
                ptmp = X509_PURPOSE_get0(i);
                BIO_printf(bio_err, "\t%-10s\t%s\n",
                        X509_PURPOSE_get0_sname(ptmp),
                        X509_PURPOSE_get0_name(ptmp));
            }

            BIO_printf(bio_err, "Recognized verify names:\n");
            for (i = 0; i < X509_VERIFY_PARAM_get_count(); i++) {
                const X509_VERIFY_PARAM *vptmp;
                vptmp = X509_VERIFY_PARAM_get0(i);
                BIO_printf(bio_err, "\t%-10s\n",
                        X509_VERIFY_PARAM_get0_name(vptmp));
            }
            ret = 0;
            goto end;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto end;
            vpmtouched++;
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_UNTRUSTED:
            untfile = opt_arg();
            break;
        case OPT_TRUSTED:
            trustfile = opt_arg();
            break;
        case OPT_CRLFILE:
            crlfile = opt_arg();
            break;
        case OPT_CRL_DOWNLOAD:
            crl_download = 1;
            break;
        case OPT_SHOW_CHAIN:
            show_chain = 1;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_VERBOSE:
            v_verbose = 1;
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (!(store = setup_verify(CAfile, CApath)))
        goto end;
    X509_STORE_set_verify_cb(store, cb);

    if (vpmtouched)
        X509_STORE_set1_param(store, vpm);

    ERR_clear_error();

    if (untfile) {
        untrusted = load_certs(untfile, FORMAT_PEM,
                               NULL, e, "untrusted certificates");
        if (!untrusted)
            goto end;
    }

    if (trustfile) {
        trusted = load_certs(trustfile, FORMAT_PEM,
                             NULL, e, "trusted certificates");
        if (!trusted)
            goto end;
    }

    if (crlfile) {
        crls = load_crls(crlfile, FORMAT_PEM, NULL, e, "other CRLs");
        if (!crls)
            goto end;
    }

    if (crl_download)
        store_setup_crl_download(store);

    ret = 0;
    if (argc < 1) {
        if (check(store, NULL, untrusted, trusted, crls, e, show_chain) != 1)
            ret = -1;
    } else {
        for (i = 0; i < argc; i++)
            if (check(store, argv[i], untrusted, trusted, crls, e,
                      show_chain) != 1)
                ret = -1;
    }

 end:
    X509_VERIFY_PARAM_free(vpm);
    X509_STORE_free(store);
    sk_X509_pop_free(untrusted, X509_free);
    sk_X509_pop_free(trusted, X509_free);
    sk_X509_CRL_pop_free(crls, X509_CRL_free);
    return (ret < 0 ? 2 : ret);
}
コード例 #3
0
ファイル: smime.c プロジェクト: dgervais/openssl
int smime_main(int argc, char **argv)
{
    BIO *in = NULL, *out = NULL, *indata = NULL;
    EVP_PKEY *key = NULL;
    PKCS7 *p7 = NULL;
    STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
    STACK_OF(X509) *encerts = NULL, *other = NULL;
    X509 *cert = NULL, *recip = NULL, *signer = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
    const EVP_CIPHER *cipher = NULL;
    const EVP_MD *sign_md = NULL;
    const char *CAfile = NULL, *CApath = NULL, *prog = NULL;
    char *certfile = NULL, *keyfile = NULL, *contfile = NULL, *inrand = NULL;
    char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile =
        NULL;
    char *passinarg = NULL, *passin = NULL, *to = NULL, *from =
        NULL, *subject = NULL;
    OPTION_CHOICE o;
    int noCApath = 0, noCAfile = 0;
    int flags = PKCS7_DETACHED, operation = 0, ret = 0, need_rand = 0, indef =
        0;
    int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform =
        FORMAT_PEM;
    int vpmtouched = 0, rv = 0;
    ENGINE *e = NULL;
    const char *mime_eol = "\n";

    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        return 1;

    prog = opt_init(argc, argv, smime_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(smime_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENCRYPT:
            operation = SMIME_ENCRYPT;
            break;
        case OPT_DECRYPT:
            operation = SMIME_DECRYPT;
            break;
        case OPT_SIGN:
            operation = SMIME_SIGN;
            break;
        case OPT_RESIGN:
            operation = SMIME_RESIGN;
            break;
        case OPT_VERIFY:
            operation = SMIME_VERIFY;
            break;
        case OPT_PK7OUT:
            operation = SMIME_PK7OUT;
            break;
        case OPT_TEXT:
            flags |= PKCS7_TEXT;
            break;
        case OPT_NOINTERN:
            flags |= PKCS7_NOINTERN;
            break;
        case OPT_NOVERIFY:
            flags |= PKCS7_NOVERIFY;
            break;
        case OPT_NOCHAIN:
            flags |= PKCS7_NOCHAIN;
            break;
        case OPT_NOCERTS:
            flags |= PKCS7_NOCERTS;
            break;
        case OPT_NOATTR:
            flags |= PKCS7_NOATTR;
            break;
        case OPT_NODETACH:
            flags &= ~PKCS7_DETACHED;
            break;
        case OPT_NOSMIMECAP:
            flags |= PKCS7_NOSMIMECAP;
            break;
        case OPT_BINARY:
            flags |= PKCS7_BINARY;
            break;
        case OPT_NOSIGS:
            flags |= PKCS7_NOSIGS;
            break;
        case OPT_STREAM:
        case OPT_INDEF:
            indef = 1;
            break;
        case OPT_NOINDEF:
            indef = 0;
            break;
        case OPT_CRLFEOL:
            flags |= PKCS7_CRLFEOL;
            mime_eol = "\r\n";
            break;
        case OPT_RAND:
            inrand = opt_arg();
            need_rand = 1;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_TO:
            to = opt_arg();
            break;
        case OPT_FROM:
            from = opt_arg();
            break;
        case OPT_SUBJECT:
            subject = opt_arg();
            break;
        case OPT_SIGNER:
            /* If previous -signer argument add signer to list */
            if (signerfile) {
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                if (keyfile == NULL)
                    keyfile = signerfile;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
                keyfile = NULL;
            }
            signerfile = opt_arg();
            break;
        case OPT_RECIP:
            recipfile = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_arg(), &sign_md))
                goto opthelp;
            break;
        case OPT_CIPHER:
            if (!opt_cipher(opt_unknown(), &cipher))
                goto opthelp;
            break;
        case OPT_INKEY:
            /* If previous -inkey argument add signer to list */
            if (keyfile) {
                if (signerfile == NULL) {
                    BIO_printf(bio_err,
                               "%s: Must have -signer before -inkey\n", prog);
                    goto opthelp;
                }
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                signerfile = NULL;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
            }
            keyfile = opt_arg();
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
                goto opthelp;
            break;
        case OPT_CERTFILE:
            certfile = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_CONTENT:
            contfile = opt_arg();
            break;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto opthelp;
            vpmtouched++;
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) {
        BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
        goto opthelp;
    }

    if (operation & SMIME_SIGNERS) {
        /* Check to see if any final signer needs to be appended */
        if (keyfile && !signerfile) {
            BIO_puts(bio_err, "Illegal -inkey without -signer\n");
            goto opthelp;
        }
        if (signerfile) {
            if (!sksigners
                && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(sksigners, signerfile);
            if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            if (!keyfile)
                keyfile = signerfile;
            sk_OPENSSL_STRING_push(skkeys, keyfile);
        }
        if (!sksigners) {
            BIO_printf(bio_err, "No signer certificate specified\n");
            goto opthelp;
        }
        signerfile = NULL;
        keyfile = NULL;
        need_rand = 1;
    } else if (operation == SMIME_DECRYPT) {
        if (!recipfile && !keyfile) {
            BIO_printf(bio_err,
                       "No recipient certificate or key specified\n");
            goto opthelp;
        }
    } else if (operation == SMIME_ENCRYPT) {
        if (argc == 0) {
            BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
            goto opthelp;
        }
        need_rand = 1;
    } else if (!operation)
        goto opthelp;

    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (need_rand) {
        app_RAND_load_file(NULL, (inrand != NULL));
        if (inrand != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));
    }

    ret = 2;

    if (!(operation & SMIME_SIGNERS))
        flags &= ~PKCS7_DETACHED;

    if (!(operation & SMIME_OP)) {
        if (flags & PKCS7_BINARY)
            outformat = FORMAT_BINARY;
    }

    if (!(operation & SMIME_IP)) {
        if (flags & PKCS7_BINARY)
            informat = FORMAT_BINARY;
    }

    if (operation == SMIME_ENCRYPT) {
        if (!cipher) {
#ifndef OPENSSL_NO_DES
            cipher = EVP_des_ede3_cbc();
#else
            BIO_printf(bio_err, "No cipher selected\n");
            goto end;
#endif
        }
        encerts = sk_X509_new_null();
        if (!encerts)
            goto end;
        while (*argv) {
            cert = load_cert(*argv, FORMAT_PEM,
                             "recipient certificate file");
            if (cert == NULL)
                goto end;
            sk_X509_push(encerts, cert);
            cert = NULL;
            argv++;
        }
    }

    if (certfile) {
        if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
                        "certificate file")) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (recipfile && (operation == SMIME_DECRYPT)) {
        if ((recip = load_cert(recipfile, FORMAT_PEM,
                               "recipient certificate file")) == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (operation == SMIME_DECRYPT) {
        if (!keyfile)
            keyfile = recipfile;
    } else if (operation == SMIME_SIGN) {
        if (!keyfile)
            keyfile = signerfile;
    } else
        keyfile = NULL;

    if (keyfile) {
        key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
        if (!key)
            goto end;
    }

    in = bio_open_default(infile, 'r', informat);
    if (in == NULL)
        goto end;

    if (operation & SMIME_IP) {
        if (informat == FORMAT_SMIME)
            p7 = SMIME_read_PKCS7(in, &indata);
        else if (informat == FORMAT_PEM)
            p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
        else if (informat == FORMAT_ASN1)
            p7 = d2i_PKCS7_bio(in, NULL);
        else {
            BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
            goto end;
        }

        if (!p7) {
            BIO_printf(bio_err, "Error reading S/MIME message\n");
            goto end;
        }
        if (contfile) {
            BIO_free(indata);
            if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
                BIO_printf(bio_err, "Can't read content file %s\n", contfile);
                goto end;
            }
        }
    }

    out = bio_open_default(outfile, 'w', outformat);
    if (out == NULL)
        goto end;

    if (operation == SMIME_VERIFY) {
        if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
            goto end;
        X509_STORE_set_verify_cb(store, smime_cb);
        if (vpmtouched)
            X509_STORE_set1_param(store, vpm);
    }

    ret = 3;

    if (operation == SMIME_ENCRYPT) {
        if (indef)
            flags |= PKCS7_STREAM;
        p7 = PKCS7_encrypt(encerts, in, cipher, flags);
    } else if (operation & SMIME_SIGNERS) {
        int i;
        /*
         * If detached data content we only enable streaming if S/MIME output
         * format.
         */
        if (operation == SMIME_SIGN) {
            if (flags & PKCS7_DETACHED) {
                if (outformat == FORMAT_SMIME)
                    flags |= PKCS7_STREAM;
            } else if (indef)
                flags |= PKCS7_STREAM;
            flags |= PKCS7_PARTIAL;
            p7 = PKCS7_sign(NULL, NULL, other, in, flags);
            if (!p7)
                goto end;
            if (flags & PKCS7_NOCERTS) {
                for (i = 0; i < sk_X509_num(other); i++) {
                    X509 *x = sk_X509_value(other, i);
                    PKCS7_add_certificate(p7, x);
                }
            }
        } else
            flags |= PKCS7_REUSE_DIGEST;
        for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
            signerfile = sk_OPENSSL_STRING_value(sksigners, i);
            keyfile = sk_OPENSSL_STRING_value(skkeys, i);
            signer = load_cert(signerfile, FORMAT_PEM,
                               "signer certificate");
            if (!signer)
                goto end;
            key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
            if (!key)
                goto end;
            if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags))
                goto end;
            X509_free(signer);
            signer = NULL;
            EVP_PKEY_free(key);
            key = NULL;
        }
        /* If not streaming or resigning finalize structure */
        if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) {
            if (!PKCS7_final(p7, in, flags))
                goto end;
        }
    }

    if (!p7) {
        BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
        goto end;
    }

    ret = 4;
    if (operation == SMIME_DECRYPT) {
        if (!PKCS7_decrypt(p7, key, recip, out, flags)) {
            BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
            goto end;
        }
    } else if (operation == SMIME_VERIFY) {
        STACK_OF(X509) *signers;
        if (PKCS7_verify(p7, other, store, indata, out, flags))
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            goto end;
        }
        signers = PKCS7_get0_signers(p7, other, flags);
        if (!save_certs(signerfile, signers)) {
            BIO_printf(bio_err, "Error writing signers to %s\n", signerfile);
            ret = 5;
            goto end;
        }
        sk_X509_free(signers);
    } else if (operation == SMIME_PK7OUT)
        PEM_write_bio_PKCS7(out, p7);
    else {
        if (to)
            BIO_printf(out, "To: %s%s", to, mime_eol);
        if (from)
            BIO_printf(out, "From: %s%s", from, mime_eol);
        if (subject)
            BIO_printf(out, "Subject: %s%s", subject, mime_eol);
        if (outformat == FORMAT_SMIME) {
            if (operation == SMIME_RESIGN)
                rv = SMIME_write_PKCS7(out, p7, indata, flags);
            else
                rv = SMIME_write_PKCS7(out, p7, in, flags);
        } else if (outformat == FORMAT_PEM)
            rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags);
        else if (outformat == FORMAT_ASN1)
            rv = i2d_PKCS7_bio_stream(out, p7, in, flags);
        else {
            BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
            goto end;
        }
        if (rv == 0) {
            BIO_printf(bio_err, "Error writing output\n");
            ret = 3;
            goto end;
        }
    }
    ret = 0;
 end:
    if (need_rand)
        app_RAND_write_file(NULL);
    if (ret)
        ERR_print_errors(bio_err);
    sk_X509_pop_free(encerts, X509_free);
    sk_X509_pop_free(other, X509_free);
    X509_VERIFY_PARAM_free(vpm);
    sk_OPENSSL_STRING_free(sksigners);
    sk_OPENSSL_STRING_free(skkeys);
    X509_STORE_free(store);
    X509_free(cert);
    X509_free(recip);
    X509_free(signer);
    EVP_PKEY_free(key);
    PKCS7_free(p7);
    release_engine(e);
    BIO_free(in);
    BIO_free(indata);
    BIO_free_all(out);
    OPENSSL_free(passin);
    return (ret);
}
コード例 #4
0
ファイル: ts.c プロジェクト: Beatzevo/openssl
int ts_main(int argc, char **argv)
{
    CONF *conf = NULL;
    char *CAfile = NULL, *untrusted = NULL, *engine = NULL, *prog, **helpp;
    char *configfile = default_config_file;
    char *section = NULL, *password = NULL;
    char *data = NULL, *digest = NULL, *rnd = NULL, *policy = NULL;
    char *in = NULL, *out = NULL, *queryfile = NULL, *passin = NULL;
    char *inkey = NULL, *signer = NULL, *chain = NULL, *CApath = NULL;
    const EVP_MD *md = NULL;
    OPTION_CHOICE o, mode = OPT_ERR;
    int ret = 1, no_nonce = 0, cert = 0, text = 0;
    int vpmtouched = 0;
    X509_VERIFY_PARAM *vpm = NULL;
    /* Input is ContentInfo instead of TimeStampResp. */
    int token_in = 0;
    /* Output is ContentInfo instead of TimeStampResp. */
    int token_out = 0;

    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        goto end;

    prog = opt_init(argc, argv, ts_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(ts_options);
            for (helpp = opt_helplist; *helpp; ++helpp)
                BIO_printf(bio_err, "%s\n", *helpp);
            ret = 0;
            goto end;
        case OPT_CONFIG:
            configfile = opt_arg();
            break;
        case OPT_SECTION:
            section = opt_arg();
            break;
        case OPT_QUERY:
        case OPT_REPLY:
        case OPT_VERIFY:
            if (mode != OPT_ERR)
                goto opthelp;
            mode = o;
            break;
        case OPT_DATA:
            data = opt_arg();
            break;
        case OPT_DIGEST:
            digest = opt_arg();
            break;
        case OPT_RAND:
            rnd = opt_arg();
            break;
        case OPT_TSPOLICY:
            policy = opt_arg();
            break;
        case OPT_NO_NONCE:
            no_nonce = 1;
            break;
        case OPT_CERT:
            cert = 1;
            break;
        case OPT_IN:
            in = opt_arg();
            break;
        case OPT_TOKEN_IN:
            token_in = 1;
            break;
        case OPT_OUT:
            out = opt_arg();
            break;
        case OPT_TOKEN_OUT:
            token_out = 1;
            break;
        case OPT_TEXT:
            text = 1;
            break;
        case OPT_QUERYFILE:
            queryfile = opt_arg();
            break;
        case OPT_PASSIN:
            passin = opt_arg();
            break;
        case OPT_INKEY:
            inkey = opt_arg();
            break;
        case OPT_SIGNER:
            signer = opt_arg();
            break;
        case OPT_CHAIN:
            chain = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_UNTRUSTED:
            untrusted = opt_arg();
            break;
        case OPT_ENGINE:
            engine = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_unknown(), &md))
                goto opthelp;
            break;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto end;
            vpmtouched++;
            break;
        }
    }
    if (mode == OPT_ERR || opt_num_rest() != 0)
        goto opthelp;

    /* Seed the random number generator if it is going to be used. */
    if (mode == OPT_QUERY && !no_nonce) {
        if (!app_RAND_load_file(NULL, 1) && rnd == NULL)
            BIO_printf(bio_err, "warning, not much extra random "
                       "data, consider using the -rand option\n");
        if (rnd != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(rnd));
    }

    if (mode == OPT_REPLY && passin &&
        !app_passwd(passin, NULL, &password, NULL)) {
        BIO_printf(bio_err, "Error getting password.\n");
        goto end;
    }

    conf = load_config_file(configfile);
    if (configfile != default_config_file && !app_load_modules(conf))
        goto end;

    /* Check parameter consistency and execute the appropriate function. */
    switch (mode) {
    default:
    case OPT_ERR:
        goto opthelp;
    case OPT_QUERY:
        if (vpmtouched)
            goto opthelp;
        if ((data != NULL) && (digest != NULL))
            goto opthelp;
        ret = !query_command(data, digest, md, policy, no_nonce, cert,
                             in, out, text);
        break;
    case OPT_REPLY:
        if (vpmtouched)
            goto opthelp;
        if ((in != NULL) && (queryfile != NULL))
            goto opthelp;
        if (in == NULL) {
            if ((conf == NULL) || (token_in != 0))
                goto opthelp;
        }
        ret = !reply_command(conf, section, engine, queryfile,
                             password, inkey, md, signer, chain, policy,
                             in, token_in, out, token_out, text);
        break;
    case OPT_VERIFY:
        if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest))
            goto opthelp;
        ret = !verify_command(data, digest, queryfile, in, token_in,
                              CApath, CAfile, untrusted,
                              vpmtouched ? vpm : NULL);
    }

 end:
    X509_VERIFY_PARAM_free(vpm);
    app_RAND_write_file(NULL);
    NCONF_free(conf);
    OPENSSL_free(password);
    return (ret);
}
コード例 #5
0
ファイル: main.c プロジェクト: AdityaSarang/pdsh
int main(int argc, char *argv[])
{
    opt_t opt;
    int retval = 0;
    const char *m;


    /*
     * Initialize.
     */
    err_init(xbasename(argv[0]));       /* init err package */

    /*
     *  If running setuid, fork a child to handle 
     *   all privileged operations and drop privs in this process.
     */
    privsep_init();

    /*
     * Seed options with default values:
     */
    opt_default(&opt, argv[0]);

    /*
     * Override defaults with environment
     */
    opt_env(&opt);

    /*
     * Process any options that need to be handled early:
     */
    opt_args_early(&opt, argc, argv);

    /*
     *  Load static or dynamic pdsh modules
     */
    mod_init();
    /*
     *  Allow module directory to be overridden, but not when
     *   running as root or setuid. (This is mainly for testing...)
     */
    if (!(m = getenv ("PDSH_MODULE_DIR")) ||
          getuid() == 0 ||
          getuid() != geteuid())
        m = pdsh_module_dir;
    if (mod_load_modules(m, &opt) < 0)
        errx("%p: Couldn't load any pdsh modules\n");

    /*
     * Handle options.
     */
    opt_args(&opt, argc, argv); /* override with command line           */

    if (opt_verify(&opt)) {     /* verify options, print errors         */
        /*
         * Do the work.
         */
        if (opt.info_only)      /* display info only */
            opt_list(&opt);
        else if (pdsh_personality() == PCP && opt.pcp_server) 
            retval = (_pcp_remote_server (&opt) < 0);
        else if (pdsh_personality() == PCP && opt.pcp_client)
            retval = (_pcp_remote_client (&opt) < 0);
        else if (pdsh_personality() == PCP || opt.cmd != NULL)
            retval = dsh(&opt); /* single dsh/pcp command */
        else                    /* prompt loop */
            _interactive_dsh(&opt);
    } else {
        retval = 1;
    }

    mod_exit(); 

    /*
     * Clean up.
     */
    privsep_fini();
    opt_free(&opt);             /* free heap storage in opt struct */
    err_cleanup();

    return retval;
}
コード例 #6
0
ファイル: cms.c プロジェクト: Muffo/openssl
int cms_main(int argc, char **argv)
{
    ASN1_OBJECT *econtent_type = NULL;
    BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
    CMS_ContentInfo *cms = NULL, *rcms = NULL;
    CMS_ReceiptRequest *rr = NULL;
    ENGINE *e = NULL;
    EVP_PKEY *key = NULL;
    const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
    const EVP_MD *sign_md = NULL;
    STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
    STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
    STACK_OF(X509) *encerts = NULL, *other = NULL;
    X509 *cert = NULL, *recip = NULL, *signer = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
    char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
    const char *CAfile = NULL, *CApath = NULL;
    char *certsoutfile = NULL;
    int noCAfile = 0, noCApath = 0;
    char *infile = NULL, *outfile = NULL, *rctfile = NULL, *inrand = NULL;
    char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile =
        NULL;
    char *to = NULL, *from = NULL, *subject = NULL, *prog;
    cms_key_param *key_first = NULL, *key_param = NULL;
    int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched =
        0;
    int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
    int need_rand = 0, operation = 0, ret = 1, rr_print = 0, rr_allorfirst =
        -1;
    int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
    size_t secret_keylen = 0, secret_keyidlen = 0;
    unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
    unsigned char *secret_key = NULL, *secret_keyid = NULL;
    long ltmp;
    const char *mime_eol = "\n";
    OPTION_CHOICE o;

    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        return 1;

    prog = opt_init(argc, argv, cms_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(cms_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat))
                goto opthelp;
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENCRYPT:
            operation = SMIME_ENCRYPT;
            break;
        case OPT_DECRYPT:
            operation = SMIME_DECRYPT;
            break;
        case OPT_SIGN:
            operation = SMIME_SIGN;
            break;
        case OPT_SIGN_RECEIPT:
            operation = SMIME_SIGN_RECEIPT;
            break;
        case OPT_RESIGN:
            operation = SMIME_RESIGN;
            break;
        case OPT_VERIFY:
            operation = SMIME_VERIFY;
            break;
        case OPT_VERIFY_RETCODE:
            verify_retcode = 1;
            break;
        case OPT_VERIFY_RECEIPT:
            operation = SMIME_VERIFY_RECEIPT;
            rctfile = opt_arg();
            break;
        case OPT_CMSOUT:
            operation = SMIME_CMSOUT;
            break;
        case OPT_DATA_OUT:
            operation = SMIME_DATAOUT;
            break;
        case OPT_DATA_CREATE:
            operation = SMIME_DATA_CREATE;
            break;
        case OPT_DIGEST_VERIFY:
            operation = SMIME_DIGEST_VERIFY;
            break;
        case OPT_DIGEST_CREATE:
            operation = SMIME_DIGEST_CREATE;
            break;
        case OPT_COMPRESS:
            operation = SMIME_COMPRESS;
            break;
        case OPT_UNCOMPRESS:
            operation = SMIME_UNCOMPRESS;
            break;
        case OPT_ED_DECRYPT:
            operation = SMIME_ENCRYPTED_DECRYPT;
            break;
        case OPT_ED_ENCRYPT:
            operation = SMIME_ENCRYPTED_ENCRYPT;
            break;
        case OPT_DEBUG_DECRYPT:
            flags |= CMS_DEBUG_DECRYPT;
            break;
        case OPT_TEXT:
            flags |= CMS_TEXT;
            break;
        case OPT_ASCIICRLF:
            flags |= CMS_ASCIICRLF;
            break;
        case OPT_NOINTERN:
            flags |= CMS_NOINTERN;
            break;
        case OPT_NOVERIFY:
            flags |= CMS_NO_SIGNER_CERT_VERIFY;
            break;
        case OPT_NOCERTS:
            flags |= CMS_NOCERTS;
            break;
        case OPT_NOATTR:
            flags |= CMS_NOATTR;
            break;
        case OPT_NODETACH:
            flags &= ~CMS_DETACHED;
            break;
        case OPT_NOSMIMECAP:
            flags |= CMS_NOSMIMECAP;
            break;
        case OPT_BINARY:
            flags |= CMS_BINARY;
            break;
        case OPT_KEYID:
            flags |= CMS_USE_KEYID;
            break;
        case OPT_NOSIGS:
            flags |= CMS_NOSIGS;
            break;
        case OPT_NO_CONTENT_VERIFY:
            flags |= CMS_NO_CONTENT_VERIFY;
            break;
        case OPT_NO_ATTR_VERIFY:
            flags |= CMS_NO_ATTR_VERIFY;
            break;
        case OPT_INDEF:
            flags |= CMS_STREAM;
            break;
        case OPT_NOINDEF:
            flags &= ~CMS_STREAM;
            break;
        case OPT_NOOLDMIME:
            flags |= CMS_NOOLDMIMETYPE;
            break;
        case OPT_CRLFEOL:
            mime_eol = "\r\n";
            flags |= CMS_CRLFEOL;
            break;
        case OPT_NOOUT:
            noout = 1;
            break;
        case OPT_RR_PRINT:
            rr_print = 1;
            break;
        case OPT_RR_ALL:
            rr_allorfirst = 0;
            break;
        case OPT_RR_FIRST:
            rr_allorfirst = 1;
            break;
        case OPT_RCTFORM:
            if (rctformat == FORMAT_SMIME)
                rcms = SMIME_read_CMS(rctin, NULL);
            else if (rctformat == FORMAT_PEM)
                rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
            else if (rctformat == FORMAT_ASN1)
                if (!opt_format(opt_arg(),
                                OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
                    goto opthelp;
            break;
        case OPT_CERTFILE:
            certfile = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_CONTENT:
            contfile = opt_arg();
            break;
        case OPT_RR_FROM:
            if (rr_from == NULL
                && (rr_from = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(rr_from, opt_arg());
            break;
        case OPT_RR_TO:
            if (rr_to == NULL
                && (rr_to = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(rr_to, opt_arg());
            break;
        case OPT_PRINT:
            noout = print = 1;
            break;
        case OPT_SECRETKEY:
            secret_key = OPENSSL_hexstr2buf(opt_arg(), &ltmp);
            if (secret_key == NULL) {
                BIO_printf(bio_err, "Invalid key %s\n", opt_arg());
                goto end;
            }
            secret_keylen = (size_t)ltmp;
            break;
        case OPT_SECRETKEYID:
            secret_keyid = OPENSSL_hexstr2buf(opt_arg(), &ltmp);
            if (secret_keyid == NULL) {
                BIO_printf(bio_err, "Invalid id %s\n", opt_arg());
                goto opthelp;
            }
            secret_keyidlen = (size_t)ltmp;
            break;
        case OPT_PWRI_PASSWORD:
            pwri_pass = (unsigned char *)opt_arg();
            break;
        case OPT_ECONTENT_TYPE:
            econtent_type = OBJ_txt2obj(opt_arg(), 0);
            if (econtent_type == NULL) {
                BIO_printf(bio_err, "Invalid OID %s\n", opt_arg());
                goto opthelp;
            }
            break;
        case OPT_RAND:
            inrand = opt_arg();
            need_rand = 1;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_TO:
            to = opt_arg();
            break;
        case OPT_FROM:
            from = opt_arg();
            break;
        case OPT_SUBJECT:
            subject = opt_arg();
            break;
        case OPT_CERTSOUT:
            certsoutfile = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_arg(), &sign_md))
                goto end;
            break;
        case OPT_SIGNER:
            /* If previous -signer argument add signer to list */
            if (signerfile) {
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                if (keyfile == NULL)
                    keyfile = signerfile;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
                keyfile = NULL;
            }
            signerfile = opt_arg();
            break;
        case OPT_INKEY:
            /* If previous -inkey argument add signer to list */
            if (keyfile) {
                if (signerfile == NULL) {
                    BIO_puts(bio_err, "Illegal -inkey without -signer\n");
                    goto end;
                }
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                signerfile = NULL;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
            }
            keyfile = opt_arg();
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
                goto opthelp;
            break;
        case OPT_RECIP:
            if (operation == SMIME_ENCRYPT) {
                if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL)
                    goto end;
                cert = load_cert(opt_arg(), FORMAT_PEM,
                                 "recipient certificate file");
                if (cert == NULL)
                    goto end;
                sk_X509_push(encerts, cert);
                cert = NULL;
            } else
                recipfile = opt_arg();
            break;
        case OPT_CIPHER:
            if (!opt_cipher(opt_unknown(), &cipher))
                goto end;
            break;
        case OPT_KEYOPT:
            keyidx = -1;
            if (operation == SMIME_ENCRYPT) {
                if (encerts)
                    keyidx += sk_X509_num(encerts);
            } else {
                if (keyfile || signerfile)
                    keyidx++;
                if (skkeys)
                    keyidx += sk_OPENSSL_STRING_num(skkeys);
            }
            if (keyidx < 0) {
                BIO_printf(bio_err, "No key specified\n");
                goto opthelp;
            }
            if (key_param == NULL || key_param->idx != keyidx) {
                cms_key_param *nparam;
                nparam = app_malloc(sizeof(*nparam), "key param buffer");
                nparam->idx = keyidx;
                if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                nparam->next = NULL;
                if (key_first == NULL)
                    key_first = nparam;
                else
                    key_param->next = nparam;
                key_param = nparam;
            }
            sk_OPENSSL_STRING_push(key_param->param, opt_arg());
            break;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto end;
            vpmtouched++;
            break;
        case OPT_3DES_WRAP:
# ifndef OPENSSL_NO_DES
            wrap_cipher = EVP_des_ede3_wrap();
# endif
            break;
        case OPT_AES128_WRAP:
            wrap_cipher = EVP_aes_128_wrap();
            break;
        case OPT_AES192_WRAP:
            wrap_cipher = EVP_aes_192_wrap();
            break;
        case OPT_AES256_WRAP:
            wrap_cipher = EVP_aes_256_wrap();
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (((rr_allorfirst != -1) || rr_from) && !rr_to) {
        BIO_puts(bio_err, "No Signed Receipts Recipients\n");
        goto opthelp;
    }

    if (!(operation & SMIME_SIGNERS) && (rr_to || rr_from)) {
        BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
        goto opthelp;
    }
    if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) {
        BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
        goto opthelp;
    }

    if (operation & SMIME_SIGNERS) {
        if (keyfile && !signerfile) {
            BIO_puts(bio_err, "Illegal -inkey without -signer\n");
            goto opthelp;
        }
        /* Check to see if any final signer needs to be appended */
        if (signerfile) {
            if (!sksigners
                && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(sksigners, signerfile);
            if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            if (!keyfile)
                keyfile = signerfile;
            sk_OPENSSL_STRING_push(skkeys, keyfile);
        }
        if (!sksigners) {
            BIO_printf(bio_err, "No signer certificate specified\n");
            goto opthelp;
        }
        signerfile = NULL;
        keyfile = NULL;
        need_rand = 1;
    }

    else if (operation == SMIME_DECRYPT) {
        if (!recipfile && !keyfile && !secret_key && !pwri_pass) {
            BIO_printf(bio_err,
                       "No recipient certificate or key specified\n");
            goto opthelp;
        }
    } else if (operation == SMIME_ENCRYPT) {
        if (*argv == NULL && !secret_key && !pwri_pass && !encerts) {
            BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
            goto opthelp;
        }
        need_rand = 1;
    } else if (!operation)
        goto opthelp;

    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (need_rand) {
        app_RAND_load_file(NULL, (inrand != NULL));
        if (inrand != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));
    }

    ret = 2;

    if (!(operation & SMIME_SIGNERS))
        flags &= ~CMS_DETACHED;

    if (!(operation & SMIME_OP)) {
        if (flags & CMS_BINARY)
            outformat = FORMAT_BINARY;
    }

    if (!(operation & SMIME_IP)) {
        if (flags & CMS_BINARY)
            informat = FORMAT_BINARY;
    }

    if (operation == SMIME_ENCRYPT) {
        if (!cipher) {
# ifndef OPENSSL_NO_DES
            cipher = EVP_des_ede3_cbc();
# else
            BIO_printf(bio_err, "No cipher selected\n");
            goto end;
# endif
        }

        if (secret_key && !secret_keyid) {
            BIO_printf(bio_err, "No secret key id\n");
            goto end;
        }

        if (*argv && !encerts)
            if ((encerts = sk_X509_new_null()) == NULL)
                goto end;
        while (*argv) {
            if ((cert = load_cert(*argv, FORMAT_PEM,
                                  "recipient certificate file")) == NULL)
                goto end;
            sk_X509_push(encerts, cert);
            cert = NULL;
            argv++;
        }
    }

    if (certfile) {
        if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
                        "certificate file")) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (recipfile && (operation == SMIME_DECRYPT)) {
        if ((recip = load_cert(recipfile, FORMAT_PEM,
                               "recipient certificate file")) == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (operation == SMIME_SIGN_RECEIPT) {
        if ((signer = load_cert(signerfile, FORMAT_PEM,
                                "receipt signer certificate file")) == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (operation == SMIME_DECRYPT) {
        if (!keyfile)
            keyfile = recipfile;
    } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) {
        if (!keyfile)
            keyfile = signerfile;
    } else
        keyfile = NULL;

    if (keyfile) {
        key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
        if (!key)
            goto end;
    }

    in = bio_open_default(infile, 'r', informat);
    if (in == NULL)
        goto end;

    if (operation & SMIME_IP) {
        if (informat == FORMAT_SMIME)
            cms = SMIME_read_CMS(in, &indata);
        else if (informat == FORMAT_PEM)
            cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
        else if (informat == FORMAT_ASN1)
            cms = d2i_CMS_bio(in, NULL);
        else {
            BIO_printf(bio_err, "Bad input format for CMS file\n");
            goto end;
        }

        if (!cms) {
            BIO_printf(bio_err, "Error reading S/MIME message\n");
            goto end;
        }
        if (contfile) {
            BIO_free(indata);
            if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
                BIO_printf(bio_err, "Can't read content file %s\n", contfile);
                goto end;
            }
        }
        if (certsoutfile) {
            STACK_OF(X509) *allcerts;
            allcerts = CMS_get1_certs(cms);
            if (!save_certs(certsoutfile, allcerts)) {
                BIO_printf(bio_err,
                           "Error writing certs to %s\n", certsoutfile);
                ret = 5;
                goto end;
            }
            sk_X509_pop_free(allcerts, X509_free);
        }
    }

    if (rctfile) {
        char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
        if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) {
            BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile);
            goto end;
        }

        if (rctformat == FORMAT_SMIME)
            rcms = SMIME_read_CMS(rctin, NULL);
        else if (rctformat == FORMAT_PEM)
            rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
        else if (rctformat == FORMAT_ASN1)
            rcms = d2i_CMS_bio(rctin, NULL);
        else {
            BIO_printf(bio_err, "Bad input format for receipt\n");
            goto end;
        }

        if (!rcms) {
            BIO_printf(bio_err, "Error reading receipt\n");
            goto end;
        }
    }

    out = bio_open_default(outfile, 'w', outformat);
    if (out == NULL)
        goto end;

    if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) {
        if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
            goto end;
        X509_STORE_set_verify_cb(store, cms_cb);
        if (vpmtouched)
            X509_STORE_set1_param(store, vpm);
    }

    ret = 3;

    if (operation == SMIME_DATA_CREATE) {
        cms = CMS_data_create(in, flags);
    } else if (operation == SMIME_DIGEST_CREATE) {
        cms = CMS_digest_create(in, sign_md, flags);
    } else if (operation == SMIME_COMPRESS) {
        cms = CMS_compress(in, -1, flags);
    } else if (operation == SMIME_ENCRYPT) {
        int i;
        flags |= CMS_PARTIAL;
        cms = CMS_encrypt(NULL, in, cipher, flags);
        if (!cms)
            goto end;
        for (i = 0; i < sk_X509_num(encerts); i++) {
            CMS_RecipientInfo *ri;
            cms_key_param *kparam;
            int tflags = flags;
            X509 *x = sk_X509_value(encerts, i);
            for (kparam = key_first; kparam; kparam = kparam->next) {
                if (kparam->idx == i) {
                    tflags |= CMS_KEY_PARAM;
                    break;
                }
            }
            ri = CMS_add1_recipient_cert(cms, x, tflags);
            if (!ri)
                goto end;
            if (kparam) {
                EVP_PKEY_CTX *pctx;
                pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
                if (!cms_set_pkey_param(pctx, kparam->param))
                    goto end;
            }
            if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
                && wrap_cipher) {
                EVP_CIPHER_CTX *wctx;
                wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
                EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL);
            }
        }

        if (secret_key) {
            if (!CMS_add0_recipient_key(cms, NID_undef,
                                        secret_key, secret_keylen,
                                        secret_keyid, secret_keyidlen,
                                        NULL, NULL, NULL))
                goto end;
            /* NULL these because call absorbs them */
            secret_key = NULL;
            secret_keyid = NULL;
        }
        if (pwri_pass) {
            pwri_tmp = (unsigned char *)OPENSSL_strdup((char *)pwri_pass);
            if (!pwri_tmp)
                goto end;
            if (!CMS_add0_recipient_password(cms,
                                             -1, NID_undef, NID_undef,
                                             pwri_tmp, -1, NULL))
                goto end;
            pwri_tmp = NULL;
        }
        if (!(flags & CMS_STREAM)) {
            if (!CMS_final(cms, in, NULL, flags))
                goto end;
        }
    } else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
        cms = CMS_EncryptedData_encrypt(in, cipher,
                                        secret_key, secret_keylen, flags);

    } else if (operation == SMIME_SIGN_RECEIPT) {
        CMS_ContentInfo *srcms = NULL;
        STACK_OF(CMS_SignerInfo) *sis;
        CMS_SignerInfo *si;
        sis = CMS_get0_SignerInfos(cms);
        if (!sis)
            goto end;
        si = sk_CMS_SignerInfo_value(sis, 0);
        srcms = CMS_sign_receipt(si, signer, key, other, flags);
        if (!srcms)
            goto end;
        CMS_ContentInfo_free(cms);
        cms = srcms;
    } else if (operation & SMIME_SIGNERS) {
        int i;
        /*
         * If detached data content we enable streaming if S/MIME output
         * format.
         */
        if (operation == SMIME_SIGN) {

            if (flags & CMS_DETACHED) {
                if (outformat == FORMAT_SMIME)
                    flags |= CMS_STREAM;
            }
            flags |= CMS_PARTIAL;
            cms = CMS_sign(NULL, NULL, other, in, flags);
            if (!cms)
                goto end;
            if (econtent_type)
                CMS_set1_eContentType(cms, econtent_type);

            if (rr_to) {
                rr = make_receipt_request(rr_to, rr_allorfirst, rr_from);
                if (!rr) {
                    BIO_puts(bio_err,
                             "Signed Receipt Request Creation Error\n");
                    goto end;
                }
            }
        } else
            flags |= CMS_REUSE_DIGEST;
        for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
            CMS_SignerInfo *si;
            cms_key_param *kparam;
            int tflags = flags;
            signerfile = sk_OPENSSL_STRING_value(sksigners, i);
            keyfile = sk_OPENSSL_STRING_value(skkeys, i);

            signer = load_cert(signerfile, FORMAT_PEM, "signer certificate");
            if (!signer)
                goto end;
            key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
            if (!key)
                goto end;
            for (kparam = key_first; kparam; kparam = kparam->next) {
                if (kparam->idx == i) {
                    tflags |= CMS_KEY_PARAM;
                    break;
                }
            }
            si = CMS_add1_signer(cms, signer, key, sign_md, tflags);
            if (!si)
                goto end;
            if (kparam) {
                EVP_PKEY_CTX *pctx;
                pctx = CMS_SignerInfo_get0_pkey_ctx(si);
                if (!cms_set_pkey_param(pctx, kparam->param))
                    goto end;
            }
            if (rr && !CMS_add1_ReceiptRequest(si, rr))
                goto end;
            X509_free(signer);
            signer = NULL;
            EVP_PKEY_free(key);
            key = NULL;
        }
        /* If not streaming or resigning finalize structure */
        if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) {
            if (!CMS_final(cms, in, NULL, flags))
                goto end;
        }
    }

    if (!cms) {
        BIO_printf(bio_err, "Error creating CMS structure\n");
        goto end;
    }

    ret = 4;
    if (operation == SMIME_DECRYPT) {
        if (flags & CMS_DEBUG_DECRYPT)
            CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags);

        if (secret_key) {
            if (!CMS_decrypt_set1_key(cms,
                                      secret_key, secret_keylen,
                                      secret_keyid, secret_keyidlen)) {
                BIO_puts(bio_err, "Error decrypting CMS using secret key\n");
                goto end;
            }
        }

        if (key) {
            if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
                BIO_puts(bio_err, "Error decrypting CMS using private key\n");
                goto end;
            }
        }

        if (pwri_pass) {
            if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) {
                BIO_puts(bio_err, "Error decrypting CMS using password\n");
                goto end;
            }
        }

        if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) {
            BIO_printf(bio_err, "Error decrypting CMS structure\n");
            goto end;
        }
    } else if (operation == SMIME_DATAOUT) {
        if (!CMS_data(cms, out, flags))
            goto end;
    } else if (operation == SMIME_UNCOMPRESS) {
        if (!CMS_uncompress(cms, indata, out, flags))
            goto end;
    } else if (operation == SMIME_DIGEST_VERIFY) {
        if (CMS_digest_verify(cms, indata, out, flags) > 0)
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            goto end;
        }
    } else if (operation == SMIME_ENCRYPTED_DECRYPT) {
        if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
                                       indata, out, flags))
            goto end;
    } else if (operation == SMIME_VERIFY) {
        if (CMS_verify(cms, other, store, indata, out, flags) > 0)
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            if (verify_retcode)
                ret = verify_err + 32;
            goto end;
        }
        if (signerfile) {
            STACK_OF(X509) *signers;
            signers = CMS_get0_signers(cms);
            if (!save_certs(signerfile, signers)) {
                BIO_printf(bio_err,
                           "Error writing signers to %s\n", signerfile);
                ret = 5;
                goto end;
            }
            sk_X509_free(signers);
        }
        if (rr_print)
            receipt_request_print(cms);

    } else if (operation == SMIME_VERIFY_RECEIPT) {
        if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0)
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            goto end;
        }
    } else {
        if (noout) {
            if (print)
                CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
        } else if (outformat == FORMAT_SMIME) {
            if (to)
                BIO_printf(out, "To: %s%s", to, mime_eol);
            if (from)
                BIO_printf(out, "From: %s%s", from, mime_eol);
            if (subject)
                BIO_printf(out, "Subject: %s%s", subject, mime_eol);
            if (operation == SMIME_RESIGN)
                ret = SMIME_write_CMS(out, cms, indata, flags);
            else
                ret = SMIME_write_CMS(out, cms, in, flags);
        } else if (outformat == FORMAT_PEM)
            ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
        else if (outformat == FORMAT_ASN1)
            ret = i2d_CMS_bio_stream(out, cms, in, flags);
        else {
            BIO_printf(bio_err, "Bad output format for CMS file\n");
            goto end;
        }
        if (ret <= 0) {
            ret = 6;
            goto end;
        }
    }
    ret = 0;
 end:
    if (ret)
        ERR_print_errors(bio_err);
    if (need_rand)
        app_RAND_write_file(NULL);
    sk_X509_pop_free(encerts, X509_free);
    sk_X509_pop_free(other, X509_free);
    X509_VERIFY_PARAM_free(vpm);
    sk_OPENSSL_STRING_free(sksigners);
    sk_OPENSSL_STRING_free(skkeys);
    OPENSSL_free(secret_key);
    OPENSSL_free(secret_keyid);
    OPENSSL_free(pwri_tmp);
    ASN1_OBJECT_free(econtent_type);
    CMS_ReceiptRequest_free(rr);
    sk_OPENSSL_STRING_free(rr_to);
    sk_OPENSSL_STRING_free(rr_from);
    for (key_param = key_first; key_param;) {
        cms_key_param *tparam;
        sk_OPENSSL_STRING_free(key_param->param);
        tparam = key_param->next;
        OPENSSL_free(key_param);
        key_param = tparam;
    }
    X509_STORE_free(store);
    X509_free(cert);
    X509_free(recip);
    X509_free(signer);
    EVP_PKEY_free(key);
    CMS_ContentInfo_free(cms);
    CMS_ContentInfo_free(rcms);
    BIO_free(rctin);
    BIO_free(in);
    BIO_free(indata);
    BIO_free_all(out);
    OPENSSL_free(passin);
    return (ret);
}