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; }
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); }
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); }
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); }
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; }
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(), <mp); 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(), <mp); 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); }