提交 b3c5aadf 编写于 作者: D Dr. David von Oheimb

apps: make use of OSSL_STORE for generalized certs and CRLs loading

Reviewed-by: NRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12647)
上级 ed4faae0
......@@ -214,7 +214,7 @@ const OPTIONS ca_options[] = {
OPT_SECTION("Signing"),
{"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"},
{"keyfile", OPT_KEYFILE, 's', "Private key"},
{"keyfile", OPT_KEYFILE, 's', "The CA private key"},
{"keyform", OPT_KEYFORM, 'f', "Private key file format (ENGINE, other values ignored)"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"key", OPT_KEY, 's', "Key to decode the private key if it is encrypted"},
......
......@@ -138,8 +138,6 @@ static char *opt_certform_s = "PEM";
static int opt_certform = FORMAT_PEM;
static char *opt_keyform_s = "PEM";
static int opt_keyform = FORMAT_PEM;
static char *opt_certsform_s = "PEM";
static int opt_certsform = FORMAT_PEM;
static char *opt_otherpass = NULL;
static char *opt_engine = NULL;
......@@ -222,7 +220,7 @@ typedef enum OPTION_choice {
OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
OPT_UNPROTECTED_REQUESTS,
OPT_CERTFORM, OPT_KEYFORM, OPT_CERTSFORM,
OPT_CERTFORM, OPT_KEYFORM,
OPT_OTHERPASS,
#ifndef OPENSSL_NO_ENGINE
OPT_ENGINE,
......@@ -394,12 +392,8 @@ const OPTIONS cmp_options[] = {
OPT_SECTION("Credentials format"),
{"certform", OPT_CERTFORM, 's',
"Format (PEM or DER) to use when saving a certificate to a file. Default PEM"},
{OPT_MORE_STR, 0, 0,
"This also determines format to use for writing (not supported for P12)"},
{"keyform", OPT_KEYFORM, 's',
"Format to assume when reading key files. Default PEM"},
{"certsform", OPT_CERTSFORM, 's',
"Format (PEM/DER/P12) to try first reading multiple certs. Default PEM"},
"Format of the key input (ENGINE, other values ignored)"},
{"otherpass", OPT_OTHERPASS, 's',
"Pass phrase source potentially needed for loading certificates of others"},
#ifndef OPENSSL_NO_ENGINE
......@@ -540,7 +534,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
{&opt_digest}, {&opt_mac}, {&opt_extracerts},
{(char **)&opt_unprotected_requests},
{&opt_certform_s}, {&opt_keyform_s}, {&opt_certsform_s},
{&opt_certform_s}, {&opt_keyform_s},
{&opt_otherpass},
#ifndef OPENSSL_NO_ENGINE
{&opt_engine},
......@@ -642,51 +636,6 @@ static X509 *load_cert_pwd(const char *uri, const char *pass, const char *desc)
return cert;
}
/* TODO remove when PR #4930 is merged */
static int load_pkcs12(BIO *in, const char *desc,
pem_password_cb *pem_cb, void *cb_data,
EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
{
const char *pass;
char tpass[PEM_BUFSIZE];
int len;
int ret = 0;
PKCS12 *p12 = d2i_PKCS12_bio(in, NULL);
if (desc == NULL)
desc = "PKCS12 input";
if (p12 == NULL) {
BIO_printf(bio_err, "error loading PKCS12 file for %s\n", desc);
goto die;
}
/* See if an empty password will do */
if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) {
pass = "";
} else {
if (pem_cb == NULL)
pem_cb = wrap_password_callback;
len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
if (len < 0) {
BIO_printf(bio_err, "passphrase callback error for %s\n", desc);
goto die;
}
if (len < PEM_BUFSIZE)
tpass[len] = 0;
if (!PKCS12_verify_mac(p12, tpass, len)) {
BIO_printf(bio_err,
"mac verify error (wrong password?) in PKCS12 file for %s\n",
desc);
goto die;
}
pass = tpass;
}
ret = PKCS12_parse(p12, pass, pkey, cert, ca);
die:
PKCS12_free(p12);
return ret;
}
/* TODO potentially move this and related functions to apps/lib/apps.c */
static int adjust_format(const char **infile, int format, int engine_ok)
{
......@@ -752,47 +701,6 @@ static X509_REQ *load_csr_autofmt(const char *infile, const char *desc)
return csr;
}
/* TODO replace by calling generalized load_certs() when PR #4930 is merged */
static int load_certs_preliminary(const char *file, STACK_OF(X509) **certs,
int format, const char *pass,
const char *desc)
{
X509 *cert = NULL;
int ret = 0;
if (format == FORMAT_PKCS12) {
BIO *bio = bio_open_default(file, 'r', format);
if (bio != NULL) {
EVP_PKEY *pkey = NULL; /* pkey is needed until PR #4930 is merged */
PW_CB_DATA cb_data;
cb_data.password = pass;
cb_data.prompt_info = file;
ret = load_pkcs12(bio, desc, wrap_password_callback,
&cb_data, &pkey, &cert, certs);
EVP_PKEY_free(pkey);
BIO_free(bio);
}
} else if (format == FORMAT_ASN1) { /* load only one cert in this case */
CMP_warn1("can load only one certificate in DER format from %s", file);
cert = load_cert_pass(file, 0, pass, desc);
}
if (format == FORMAT_PKCS12 || format == FORMAT_ASN1) {
if (cert) {
if (*certs == NULL)
*certs = sk_X509_new_null();
if (*certs != NULL)
ret = sk_X509_insert(*certs, cert, 0);
else
X509_free(cert);
}
} else {
ret = load_certs(file, certs, format, pass, desc);
}
return ret;
}
static void warn_certs_expired(const char *file, STACK_OF(X509) **certs)
{
int i, res;
......@@ -812,34 +720,20 @@ static void warn_certs_expired(const char *file, STACK_OF(X509) **certs)
}
}
/*
* TODO potentially move this and related functions to apps/lib/
* or even better extend OSSL_STORE with type OSSL_STORE_INFO_CERTS
*/
static int load_certs_autofmt(const char *infile, STACK_OF(X509) **certs,
int exclude_http, const char *pass,
const char *desc)
static int load_certs_pwd(const char *infile, STACK_OF(X509) **certs,
int exclude_http, const char *pass,
const char *desc)
{
int ret = 0;
char *pass_string;
BIO *bio_bak = bio_err;
int format = adjust_format(&infile, opt_certsform, 0);
int format = adjust_format(&infile, FORMAT_PEM, 0);
if (exclude_http && format == FORMAT_HTTP) {
BIO_printf(bio_err, "error: HTTP retrieval not allowed for %s\n", desc);
return ret;
}
pass_string = get_passwd(pass, desc);
if (format != FORMAT_HTTP)
bio_err = NULL; /* do not show errors on more than one try */
ret = load_certs_preliminary(infile, certs, format, pass_string, desc);
bio_err = bio_bak;
if (!ret && format != FORMAT_HTTP) {
int format2 = format == FORMAT_PEM ? FORMAT_ASN1 : FORMAT_PEM;
ERR_clear_error();
ret = load_certs_preliminary(infile, certs, format2, pass_string, desc);
}
ret = load_certs(infile, certs, pass_string, desc);
clear_free(pass_string);
if (ret)
......@@ -1129,7 +1023,7 @@ static X509_STORE *load_certstore(char *input, const char *desc)
while (input != NULL) {
char *next = next_item(input); \
if (!load_certs_autofmt(input, &certs, 1, opt_otherpass, desc)
if (!load_certs_pwd(input, &certs, 1, opt_otherpass, desc)
|| !(store = sk_X509_to_store(store, certs))) {
/* CMP_err("out of memory"); */
X509_STORE_free(store);
......@@ -1160,7 +1054,7 @@ static STACK_OF(X509) *load_certs_multifile(char *files,
while (files != NULL) {
char *next = next_item(files);
if (!load_certs_autofmt(files, &certs, 0, pass, desc))
if (!load_certs_pwd(files, &certs, 0, pass, desc))
goto err;
if (!X509_add_certs(result, certs,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
......@@ -1256,13 +1150,6 @@ static int transform_opts(void)
return 0;
}
if (opt_certsform_s != NULL
&& !opt_format(opt_certsform_s, OPT_FMT_PEMDER | OPT_FMT_PKCS12,
&opt_certsform)) {
CMP_err("unknown option given for certificate list loading format");
return 0;
}
return 1;
}
......@@ -1554,8 +1441,8 @@ static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
X509 *cert;
STACK_OF(X509) *certs = NULL;
if (!load_certs_autofmt(opt_tls_cert, &certs, 0, opt_tls_keypass,
"TLS client certificate (optionally with chain)"))
if (!load_certs_pwd(opt_tls_cert, &certs, 0, opt_tls_keypass,
"TLS client certificate (optionally with chain)"))
/*
* opt_tls_keypass is needed in case opt_tls_cert is an encrypted
* PKCS#12 file
......@@ -1722,8 +1609,8 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
STACK_OF(X509) *certs = NULL;
int ok;
if (!load_certs_autofmt(opt_cert, &certs, 0, opt_keypass,
"CMP client certificate (and optionally extra certs)"))
if (!load_certs_pwd(opt_cert, &certs, 0, opt_keypass,
"CMP client certificate (and optionally extra certs)"))
/* opt_keypass is needed if opt_cert is an encrypted PKCS#12 file */
goto err;
......@@ -2666,9 +2553,6 @@ static int get_opts(int argc, char **argv)
case OPT_KEYFORM:
opt_keyform_s = opt_str("keyform");
break;
case OPT_CERTSFORM:
opt_certsform_s = opt_str("certsform");
break;
case OPT_OTHERPASS:
opt_otherpass = opt_str("otherpass");
break;
......
......@@ -822,8 +822,7 @@ int cms_main(int argc, char **argv)
}
if (certfile != NULL) {
if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
"certificate file")) {
if (!load_certs(certfile, &other, NULL, "certificate file")) {
ERR_print_errors(bio_err);
goto end;
}
......
......@@ -113,10 +113,15 @@ EVP_PKEY *load_key(const char *uri, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *desc);
EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *desc);
int load_certs(const char *file, STACK_OF(X509) **certs, int format,
int load_certs(const char *uri, STACK_OF(X509) **certs,
const char *pass, const char *desc);
int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
const char *pass, const char *desc);
int load_key_certs_crls(const char *uri, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
X509 **pcert, STACK_OF(X509) **pcerts,
X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls);
int load_key_cert_crl(const char *uri, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
......
......@@ -491,8 +491,8 @@ X509 *load_cert_pass(const char *uri, int maybe_stdin,
if (desc == NULL)
desc = "certificate";
(void)load_key_cert_crl(uri, maybe_stdin, pass, desc,
NULL, NULL, &cert, NULL);
(void)load_key_certs_crls(uri, maybe_stdin, pass, desc,
NULL, NULL, &cert, NULL, NULL, NULL);
if (cert == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
......@@ -513,8 +513,8 @@ X509_CRL *load_crl(const char *uri, int format, const char *desc)
if (desc == NULL)
desc = "CRL";
(void)load_key_cert_crl(uri, 0, NULL, desc,
NULL, NULL, NULL, &crl);
(void)load_key_certs_crls(uri, 0, NULL, desc,
NULL, NULL, NULL, NULL, &crl, NULL);
if (crl == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
......@@ -593,8 +593,8 @@ EVP_PKEY *load_key(const char *uri, int format, int may_stdin,
#endif
}
} else {
(void)load_key_cert_crl(uri, may_stdin, pass, desc,
&pkey, NULL, NULL, NULL);
(void)load_key_certs_crls(uri, may_stdin, pass, desc,
&pkey, NULL, NULL, NULL, NULL, NULL);
}
if (pkey == NULL) {
......@@ -632,8 +632,8 @@ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
#endif
}
} else {
(void)load_key_cert_crl(uri, maybe_stdin, pass, desc,
NULL, &pkey, NULL, NULL);
(void)load_key_certs_crls(uri, maybe_stdin, pass, desc,
NULL, &pkey, NULL, NULL, NULL, NULL);
}
if (pkey == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
......@@ -642,89 +642,6 @@ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
return pkey;
}
static int load_certs_crls(const char *file, int format,
const char *pass, const char *desc,
STACK_OF(X509) **pcerts,
STACK_OF(X509_CRL) **pcrls)
{
int i;
BIO *bio;
STACK_OF(X509_INFO) *xis = NULL;
X509_INFO *xi;
PW_CB_DATA cb_data;
int rv = 0;
cb_data.password = pass;
cb_data.prompt_info = file;
if (format != FORMAT_PEM) {
BIO_printf(bio_err, "Bad input format specified for %s\n", desc);
return 0;
}
bio = bio_open_default(file, 'r', FORMAT_PEM);
if (bio == NULL)
return 0;
xis = PEM_X509_INFO_read_bio_with_libctx(bio, NULL,
(pem_password_cb *)password_callback,
&cb_data,
app_get0_libctx(),
app_get0_propq());
BIO_free(bio);
if (pcerts != NULL && *pcerts == NULL) {
*pcerts = sk_X509_new_null();
if (*pcerts == NULL)
goto end;
}
if (pcrls != NULL && *pcrls == NULL) {
*pcrls = sk_X509_CRL_new_null();
if (*pcrls == NULL)
goto end;
}
for (i = 0; i < sk_X509_INFO_num(xis); i++) {
xi = sk_X509_INFO_value(xis, i);
if (xi->x509 != NULL && pcerts != NULL) {
if (!sk_X509_push(*pcerts, xi->x509))
goto end;
xi->x509 = NULL;
}
if (xi->crl != NULL && pcrls != NULL) {
if (!sk_X509_CRL_push(*pcrls, xi->crl))
goto end;
xi->crl = NULL;
}
}
if (pcerts != NULL && sk_X509_num(*pcerts) > 0)
rv = 1;
if (pcrls != NULL && sk_X509_CRL_num(*pcrls) > 0)
rv = 1;
end:
sk_X509_INFO_pop_free(xis, X509_INFO_free);
if (rv == 0) {
if (pcerts != NULL) {
sk_X509_pop_free(*pcerts, X509_free);
*pcerts = NULL;
}
if (pcrls != NULL) {
sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
*pcrls = NULL;
}
BIO_printf(bio_err, "Unable to load %s\n", desc != NULL ? desc :
pcerts != NULL ? "certificates" : "CRLs");
}
return rv;
}
void app_bail_out(char *fmt, ...)
{
va_list args;
......@@ -749,37 +666,49 @@ void* app_malloc(int sz, const char *what)
/*
* Initialize or extend, if *certs != NULL, a certificate stack.
*/
int load_certs(const char *file, STACK_OF(X509) **certs, int format,
int load_certs(const char *uri, STACK_OF(X509) **certs,
const char *pass, const char *desc)
{
return load_certs_crls(file, format, pass, desc, certs, NULL);
return load_key_certs_crls(uri, 0, pass, desc, NULL, NULL,
NULL, certs, NULL, NULL);
}
/*
* Initialize or extend, if *crls != NULL, a certificate stack.
*/
int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
const char *pass, const char *desc)
{
return load_certs_crls(file, format, pass, desc, NULL, crls);
return load_key_certs_crls(uri, 0, pass, desc, NULL, NULL,
NULL, NULL, NULL, crls);
}
/*
* Load those types of credentials for which the result pointer is not NULL.
* Reads from stdio if uri is NULL and maybe_stdin is nonzero.
* For each type the first credential found in the store is loaded.
* May yield partial result even if rv == 0.
* For non-NULL ppkey, pcert, and pcrl the first suitable value found is loaded.
* If pcerts is non-NULL and *pcerts == NULL then a new cert list is allocated.
* If pcerts is non-NULL then all available certificates are appended to *pcerts
* except any certificate assigned to *pcert.
* If pcrls is non-NULL and *pcrls == NULL then a new list of CRLs is allocated.
* If pcrls is non-NULL then all available CRLs are appended to *pcerts
* except any CRL assigned to *pcrl.
* In any case (also on error) the caller is responsible for freeing all members
* of *pcerts and *pcrls (as far as they are not NULL).
*/
int load_key_cert_crl(const char *uri, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
X509 **pcert, X509_CRL **pcrl)
int load_key_certs_crls(const char *uri, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
X509 **pcert, STACK_OF(X509) **pcerts,
X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls)
{
PW_CB_DATA uidata;
OSSL_STORE_CTX *ctx = NULL;
OPENSSL_CTX *libctx = app_get0_libctx();
const char *propq = app_get0_propq();
int ret = 0;
int ncerts = 0;
int ncrls = 0;
const char *failed = NULL;
/* TODO make use of the engine reference 'eng' when loading pkeys */
if (ppkey != NULL)
......@@ -788,8 +717,18 @@ int load_key_cert_crl(const char *uri, int maybe_stdin,
*ppubkey = NULL;
if (pcert != NULL)
*pcert = NULL;
if (pcerts != NULL && *pcerts == NULL
&& (*pcerts = sk_X509_new_null()) == NULL) {
BIO_printf(bio_err, "Out of memory");
return 0;
}
if (pcrl != NULL)
*pcrl = NULL;
if (pcrls != NULL && *pcrls == NULL
&& (*pcrls = sk_X509_CRL_new_null()) == NULL) {
BIO_printf(bio_err, "Out of memory");
return 0;
}
if (desc == NULL)
desc = "key/certificate/CRL";
......@@ -799,6 +738,7 @@ int load_key_cert_crl(const char *uri, int maybe_stdin,
if (uri == NULL) {
BIO *bio;
uri = "<stdin>";
if (!maybe_stdin) {
BIO_printf(bio_err, "No filename or uri specified for loading %s\n",
desc);
......@@ -809,7 +749,6 @@ int load_key_cert_crl(const char *uri, int maybe_stdin,
if (bio != NULL)
ctx = OSSL_STORE_attach(bio, "file", libctx, propq,
get_ui_method(), &uidata, NULL, NULL);
uri = "<stdin>";
} else {
ctx = OSSL_STORE_open_with_libctx(uri, libctx, propq, get_ui_method(),
&uidata, NULL, NULL);
......@@ -820,61 +759,71 @@ int load_key_cert_crl(const char *uri, int maybe_stdin,
goto end;
}
for (;;) {
while (!OSSL_STORE_eof(ctx)) {
OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info);
const char *infostr =
info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
int err = 0;
if (info == NULL) {
if (OSSL_STORE_eof(ctx))
ret = 1;
break;
}
int ok = 1;
switch (type) {
case OSSL_STORE_INFO_PKEY:
if (ppkey != NULL && *ppkey == NULL)
err = ((*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL);
ok = (*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL;
/*
* An EVP_PKEY with private parts also holds the public parts,
* so if the caller asked for a public key, and we got a private
* key, we can still pass it back.
*/
if (ppubkey != NULL && *ppubkey == NULL)
err = ((*ppubkey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL);
if (ok && ppubkey != NULL && *ppubkey == NULL)
ok = ((*ppubkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL);
break;
case OSSL_STORE_INFO_PUBKEY:
if (ppubkey != NULL && *ppubkey == NULL)
err = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) == NULL);
ok = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) != NULL);
break;
case OSSL_STORE_INFO_CERT:
if (pcert != NULL && *pcert == NULL)
err = ((*pcert = OSSL_STORE_INFO_get1_CERT(info)) == NULL);
ok = (*pcert = OSSL_STORE_INFO_get1_CERT(info)) != NULL;
else if (pcerts != NULL)
ok = X509_add_cert(*pcerts,
OSSL_STORE_INFO_get1_CERT(info),
X509_ADD_FLAG_DEFAULT);
ncerts += ok;
break;
case OSSL_STORE_INFO_CRL:
if (pcrl != NULL && *pcrl == NULL)
err = ((*pcrl = OSSL_STORE_INFO_get1_CRL(info)) == NULL);
ok = (*pcrl = OSSL_STORE_INFO_get1_CRL(info)) != NULL;
else if (pcrls != NULL)
ok = sk_X509_CRL_push(*pcrls, OSSL_STORE_INFO_get1_CRL(info));
ncrls += ok;
break;
default:
/* skip any other type */
break;
}
OSSL_STORE_INFO_free(info);
if (err) {
BIO_printf(bio_err, "Could not read %s of %s from %s\n",
infostr, desc, uri);
if (!ok) {
failed = info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
BIO_printf(bio_err, "Error reading %s of %s from %s\n",
failed, desc, uri);
break;
}
}
end:
OSSL_STORE_close(ctx);
if (!ret)
if (ppkey != NULL && *ppkey == NULL)
failed = "key";
else if ((pcert != NULL || pcerts != NULL) && ncerts == 0)
failed = "cert";
else if ((pcrl != NULL || pcrls != NULL) && ncrls == 0)
failed = "CRL";
if (failed != NULL) {
BIO_printf(bio_err, "Could not read any %s of %s from %s\n",
failed, desc, uri);
ERR_print_errors(bio_err);
return ret;
}
return failed == NULL;
}
......
......@@ -1040,8 +1040,7 @@ int load_excert(SSL_EXCERT **pexc)
if (exc->key == NULL)
return 0;
if (exc->chainfile != NULL) {
if (!load_certs(exc->chainfile, &exc->chain, FORMAT_PEM, NULL,
"Server Chain"))
if (!load_certs(exc->chainfile, &exc->chain, NULL, "Server Chain"))
return 0;
}
}
......
......@@ -567,11 +567,10 @@ int ocsp_main(int argc, char **argv)
BIO_printf(bio_err, "Error loading responder certificate\n");
goto end;
}
if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM,
NULL, "CA certificate"))
if (!load_certs(rca_filename, &rca_cert, NULL, "CA certificates"))
goto end;
if (rcertfile != NULL) {
if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL,
if (!load_certs(rcertfile, &rother, NULL,
"responder other certificates"))
goto end;
}
......@@ -665,7 +664,7 @@ redo_accept:
goto end;
}
if (sign_certfile != NULL) {
if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL,
if (!load_certs(sign_certfile, &sign_other, NULL,
"signer certificates"))
goto end;
}
......@@ -774,8 +773,8 @@ redo_accept:
if (vpmtouched)
X509_STORE_set1_param(store, vpm);
if (verify_certfile != NULL) {
if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL,
"validator certificate"))
if (!load_certs(verify_certfile, &verify_other, NULL,
"validator certificates"))
goto end;
}
......
......@@ -59,7 +59,7 @@ typedef enum OPTION_choice {
OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
OPT_DESCERT, OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_NOENC, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME,
OPT_INKEY, OPT_CERTFILE, OPT_PASSCERTS, OPT_NAME, OPT_CSP, OPT_CANAME,
OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_ENGINE,
OPT_R_ENUM, OPT_PROV_ENUM, OPT_LEGACY_ALG
......@@ -87,6 +87,7 @@ const OPTIONS pkcs12_options[] = {
OPT_SECTION("Input"),
{"inkey", OPT_INKEY, 's', "Private key if not infile"},
{"certfile", OPT_CERTFILE, '<', "Load certs from file"},
{"passcerts", OPT_PASSCERTS, 's', "Certificate file pass phrase source"},
{"name", OPT_NAME, 's', "Use name as friendly name"},
{"CSP", OPT_CSP, 's', "Microsoft CSP name"},
{"caname", OPT_CANAME, 's',
......@@ -143,6 +144,7 @@ const OPTIONS pkcs12_options[] = {
int pkcs12_main(int argc, char **argv)
{
char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
char *passcertsarg = NULL, *passcerts = NULL;
char *name = NULL, *csp_name = NULL;
char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = "";
int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0, use_legacy = 0;
......@@ -260,6 +262,9 @@ int pkcs12_main(int argc, char **argv)
case OPT_CERTFILE:
certfile = opt_arg();
break;
case OPT_PASSCERTS:
passcertsarg = opt_arg();
break;
case OPT_NAME:
name = opt_arg();
break;
......@@ -322,6 +327,9 @@ int pkcs12_main(int argc, char **argv)
}
argc = opt_num_rest();
if (!export_cert && passcertsarg != NULL)
BIO_printf(bio_err,
"Warning: -passcerts option ignored without -export\n");
if (use_legacy) {
/* load the legacy provider if not loaded already*/
if (!OSSL_PROVIDER_available(app_get0_libctx(), "legacy")) {
......@@ -349,6 +357,11 @@ int pkcs12_main(int argc, char **argv)
private = 1;
if (!app_passwd(passcertsarg, NULL, &passcerts, NULL)) {
BIO_printf(bio_err, "Error getting certificate file password\n");
goto end;
}
if (passarg != NULL) {
if (export_cert)
passoutarg = passarg;
......@@ -424,8 +437,7 @@ int pkcs12_main(int argc, char **argv)
/* Load in all certs in input file */
if (!(options & NOCERTS)) {
if (!load_certs(infile, &certs, FORMAT_PEM, NULL,
"certificates"))
if (!load_certs(infile, &certs, passin, "input certificates"))
goto export_end;
if (key != NULL) {
......@@ -453,7 +465,7 @@ int pkcs12_main(int argc, char **argv)
/* Add any more certificates asked for */
if (certfile != NULL) {
if (!load_certs(certfile, &certs, FORMAT_PEM, NULL,
if (!load_certs(certfile, &certs, passcerts,
"certificates from certfile"))
goto export_end;
}
......@@ -652,6 +664,7 @@ int pkcs12_main(int argc, char **argv)
BIO_free_all(out);
sk_OPENSSL_STRING_free(canames);
OPENSSL_free(badpass);
OPENSSL_free(passcerts);
OPENSSL_free(passin);
OPENSSL_free(passout);
return ret;
......
......@@ -1746,8 +1746,7 @@ int s_client_main(int argc, char **argv)
}
if (chain_file != NULL) {
if (!load_certs(chain_file, &chain, FORMAT_PEM, NULL,
"client certificate chain"))
if (!load_certs(chain_file, &chain, pass, "client certificate chain"))
goto end;
}
......
......@@ -1758,7 +1758,7 @@ int s_server_main(int argc, char *argv[])
if (s_cert == NULL)
goto end;
if (s_chain_file != NULL) {
if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL,
if (!load_certs(s_chain_file, &s_chain, NULL,
"server certificate chain"))
goto end;
}
......@@ -1822,7 +1822,7 @@ int s_server_main(int argc, char *argv[])
goto end;
}
if (s_dchain_file != NULL) {
if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL,
if (!load_certs(s_dchain_file, &s_dchain, NULL,
"second server certificate chain"))
goto end;
}
......
......@@ -449,8 +449,7 @@ int smime_main(int argc, char **argv)
}
if (certfile != NULL) {
if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
"certificate file")) {
if (!load_certs(certfile, &other, NULL, "certificates")) {
ERR_print_errors(bio_err);
goto end;
}
......
......@@ -149,7 +149,7 @@ int verify_main(int argc, char **argv)
break;
case OPT_UNTRUSTED:
/* Zero or more times */
if (!load_certs(opt_arg(), &untrusted, FORMAT_PEM, NULL,
if (!load_certs(opt_arg(), &untrusted, NULL,
"untrusted certificates"))
goto end;
break;
......@@ -158,14 +158,12 @@ int verify_main(int argc, char **argv)
noCAfile = 1;
noCApath = 1;
noCAstore = 1;
if (!load_certs(opt_arg(), &trusted, FORMAT_PEM, NULL,
"trusted certificates"))
if (!load_certs(opt_arg(), &trusted, NULL, "trusted certificates"))
goto end;
break;
case OPT_CRLFILE:
/* Zero or more times */
if (!load_crls(opt_arg(), &crls, FORMAT_PEM, NULL,
"other CRLs"))
if (!load_crls(opt_arg(), &crls, NULL, "other CRLs"))
goto end;
break;
case OPT_CRL_DOWNLOAD:
......
......@@ -140,7 +140,7 @@ F<.pem> appended.
=item B<-cert>
The CA certificate file.
The CA certificate, which must match with B<-keyfile>.
=item B<-certform> B<DER>|B<PEM>|B<P12>
......@@ -149,7 +149,7 @@ This option has no effect and is retained for backward compatibility only.
=item B<-keyfile> I<filename>
The private key to sign requests with.
The CA private key to sign requests with. This must match with B<-cert>.
=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
......@@ -179,6 +179,7 @@ The password used to encrypt the private key. Since on some
systems the command line arguments are visible (e.g., when using
L<ps(1)> on Unix),
this option should be used with caution.
Better use B<-passin>.
=item B<-selfsign>
......
......@@ -69,7 +69,6 @@ B<openssl> B<cmp>
[B<-certform> I<PEM|DER>]
[B<-keyform> I<PEM|DER|P12|ENGINE>]
[B<-certsform> I<PEM|DER|P12>]
[B<-otherpass> I<arg>]
{- $OpenSSL::safe::opt_engine_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
......@@ -681,15 +680,10 @@ Send messages without CMP-level protection.
File format to use when saving a certificate to a file.
Default value is PEM.
=item B<-keyform> I<PEM|DER|P12>
=item B<-keyform> I<PEM|DER|P12|ENGINE>
Format to assume when reading key files.
Default value is PEM.
=item B<-certsform> I<PEM|DER|P12>
Format to try first when reading multiple certificates from file(s).
Default value is PEM.
The format of the key input.
The only value with effect is B<ENGINE>.
=item B<-otherpass> I<arg>
......
......@@ -380,6 +380,7 @@ the MIME type multipart/signed is used.
Allows additional certificates to be specified. When signing these will
be included with the message. When verifying these will be searched for
the signers certificates.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-certsout> I<file>
......
......@@ -130,6 +130,7 @@ the OCSP request is not signed.
=item B<-sign_other> I<filename>
Additional certificates to include in the signed request.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-nonce>, B<-no_nonce>
......@@ -180,10 +181,12 @@ the complete request is received.
=item B<-verify_other> I<file>
File containing additional certificates to search when attempting to locate
File or URI containing additional certificates to search
when attempting to locate
the OCSP response signing certificate. Some responders omit the actual signer's
certificate from the response: this option can be used to supply the necessary
certificate in such cases.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-trust_other>
......@@ -194,8 +197,9 @@ root CA is not appropriate.
=item B<-VAfile> I<file>
File containing explicitly trusted responder certificates. Equivalent to the
B<-verify_other> and B<-trust_other> options.
File or URI containing explicitly trusted responder certificates.
Equivalent to the B<-verify_other> and B<-trust_other> options.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-noverify>
......@@ -296,6 +300,7 @@ must also be present.
CA certificate corresponding to the revocation information in the index
file given with B<-index>.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-rsigner> I<file>
......@@ -314,6 +319,7 @@ see L<openssl(1)/Pass Phrase Options>.
=item B<-rother> I<file>
Additional certificates to include in the OCSP response.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-rsigopt> I<nm>:I<v>
......
......@@ -13,6 +13,7 @@ B<openssl> B<pkcs12>
[B<-chain>]
[B<-inkey> I<file_or_id>]
[B<-certfile> I<filename>]
[B<-passcerts> I<arg>]
[B<-name> I<name>]
[B<-caname> I<name>]
[B<-in> I<filename>]
......@@ -85,8 +86,10 @@ Print out a usage message.
=item B<-in> I<filename>
This specifies filename of the PKCS#12 file to be parsed. Standard input is used
by default.
This specifies filename or URI of the PKCS#12 file to be parsed.
With B<-export>, this refers to the the certificate and/or key input,
which can be in PEM, DER, or PKCS#12 format.
Standard input is used by default.
=item B<-out> I<filename>
......@@ -195,9 +198,10 @@ by default.
=item B<-in> I<filename>
The filename to read certificates and private keys from, standard input by
default. They must all be in PEM format. The order doesn't matter but one
private key and its corresponding certificate should be present. If additional
The filename or URI to read certificates and private keys from, standard input
by default. They can be in PEM, DER, or PKCS#12 format.
The order doesn't matter but one private key and
its corresponding certificate should be present. If additional
certificates are present they will also be included in the PKCS#12 file.
=item B<-inkey> I<file_or_id>
......@@ -214,7 +218,14 @@ name is typically displayed in list boxes by software importing the file.
=item B<-certfile> I<filename>
A filename to read additional certificates from.
A filename or URI to read additional certificates from.
The file can be in PEM, DER, or PKCS#12 format.
=item B<-passcerts> I<arg>
The password source for certificate input such as B<-certfile>.
For more information about the format of B<arg>
see the B<PASS PHRASE ARGUMENTS> section in L<openssl(1)>.
=item B<-caname> I<friendlyname>
......
......@@ -248,8 +248,9 @@ This option has no effect and is retained for backward compatibility only.
=item B<-cert_chain>
A file containing untrusted certificates to use when attempting to build the
A file or URI of untrusted certificates to use when attempting to build the
certificate chain related to the certificate specified via the B<-cert> option.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-build_chain>
......
......@@ -228,8 +228,9 @@ This option has no effect and is retained for backward compatibility only.
=item B<-cert_chain>
A file containing untrusted certificates to use when attempting to build the
A file or URI of untrusted certificates to use when attempting to build the
certificate chain related to the certificate specified via the B<-cert> option.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-build_chain>
......@@ -274,9 +275,10 @@ by using an appropriate certificate.
=item B<-dcert_chain>
A file containing untrusted certificates to use when attempting to build the
A file or URI of untrusted certificates to use when attempting to build the
server certificate chain when a certificate specified via the B<-dcert> option
is in use.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-dcertform> B<DER>|B<PEM>|B<P12>
......
......@@ -238,6 +238,7 @@ option is present B<CRLF> is used instead.
Allows additional certificates to be specified. When signing these will
be included with the message. When verifying these will be searched for
the signers certificates.
The input can be in PEM, DER, or PKCS#12 format.
=item B<-signer> I<file>
......
......@@ -40,7 +40,7 @@ Print out a usage message.
=item B<-CRLfile> I<file>
The I<file> should contain one or more CRLs in PEM format.
The file or URI should contain one or more CRLs in PEM or DER format.
This option can be specified more than once to include CRLs from multiple
I<file>s.
......@@ -60,13 +60,14 @@ Print extra information about the operations being performed.
=item B<-trusted> I<file>
A file of trusted certificates in PEM format.
A file or URI of trusted certificates in PEM, DER, or PKCS#12 format.
This option can be specified more than once to load certificates from multiple
I<file>s.
=item B<-untrusted> I<file>
A file of untrusted certificates in PEM format to use for chain building.
A file or URI of untrusted certificates in PEM, DER, or PKCS#12 format
to use for chain building.
This option can be specified more than once to load certificates from multiple
I<file>s.
......
......@@ -57,7 +57,7 @@ if (eval { require Win32::API; 1; }) {
}
$ENV{OPENSSL_WIN32_UTF8}=1;
plan tests => 2;
plan tests => 4;
# Test different PKCS#12 formats
ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats");
......@@ -68,4 +68,27 @@ ok(run(app(["openssl", "pkcs12", "-noout",
"-in", srctop_file("test", "shibboleth.pfx")])),
"test_pkcs12");
my @path = qw(test certs);
my $tmpfile = "tmp.p12";
# Test the -passcerts option
ok(run(app(["openssl", "pkcs12", "-export",
"-in", srctop_file(@path, "ee-cert.pem"),
"-certfile", srctop_file(@path, "v3-certs-TDES.p12"),
"-passcerts", "pass:v3-certs",
"-nokeys", "-passout", "pass:v3-certs", "-descert",
"-out", $tmpfile])),
"test_pkcs12_passcert");
unlink $tmpfile;
# Test reading legacy PKCS#12 file
ok(run(app(["openssl", "pkcs12", "-export",
"-in", srctop_file(@path, "v3-certs-RC2.p12"),
"-passin", "pass:v3-certs",
"-provider", "default", "-provider", "legacy",
"-nokeys", "-passout", "pass:v3-certs", "-descert",
"-out", $tmpfile])),
"test_pkcs12_passcert");
unlink $tmpfile;
SetConsoleOutputCP($savedcp) if (defined($savedcp));
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册