Make better use of new load_cert_pass() variant of load_cert() in apps/

allows loading password-protected PKCS#12 files in x509, ca, s_client, s_server

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12647)
This commit is contained in:
Dr. David von Oheimb 2020-08-16 15:25:27 +02:00
parent b3c5aadf4c
commit 2a33470b4f
11 changed files with 64 additions and 56 deletions

View File

@ -106,7 +106,7 @@ static int certify(X509 **xret, const char *infile, int informat,
int verbose, unsigned long certopt, unsigned long nameopt,
int default_op, int ext_copy, int selfsign);
static int certify_cert(X509 **xret, const char *infile, int informat,
EVP_PKEY *pkey, X509 *x509,
const char *passin, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(OPENSSL_STRING) *vfyopts,
@ -216,15 +216,15 @@ const OPTIONS ca_options[] = {
{"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"},
{"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"},
{"passin", OPT_PASSIN, 's', "Key and cert input file pass phrase source"},
{"key", OPT_KEY, 's', "Key to decrypt key or cert files. Better use -passin"},
{"cert", OPT_CERT, '<', "The CA cert"},
{"certform", OPT_CERTFORM, 'F',
"certificate input format (DER/PEM/P12); has no effect"},
"Certificate input format (DER/PEM/P12); has no effect"},
{"selfsign", OPT_SELFSIGN, '-',
"Sign a cert with the key associated with it"},
{"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
{"vfyopt", OPT_SIGOPT, 's', "Verification parameter in n:v form"},
{"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
OPT_SECTION("Revocation"),
{"gencrl", OPT_GENCRL, '-', "Generate a new CRL"},
@ -272,10 +272,11 @@ int ca_main(int argc, char **argv)
const EVP_MD *dgst = NULL;
char *configfile = default_config_file, *section = NULL;
char *md = NULL, *policy = NULL, *keyfile = NULL;
char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL, *key = NULL;
char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL;
int certformat = FORMAT_PEM, informat = FORMAT_PEM;
const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL;
const char *extensions = NULL, *extfile = NULL, *passinarg = NULL;
char *passin = NULL;
char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL;
const char *serialfile = NULL, *subj = NULL;
char *prog, *startdate = NULL, *enddate = NULL;
@ -285,7 +286,7 @@ int ca_main(int argc, char **argv)
char *const *pp;
const char *p;
size_t outdirlen = 0;
int create_ser = 0, free_key = 0, total = 0, total_done = 0;
int create_ser = 0, free_passin = 0, total = 0, total_done = 0;
int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE;
int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0;
int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0;
@ -379,7 +380,7 @@ opthelp:
goto end;
break;
case OPT_KEY:
key = opt_arg();
passin = opt_arg();
break;
case OPT_CERT:
certfile = opt_arg();
@ -565,15 +566,14 @@ end_of_options:
&& (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL)
goto end;
if (key == NULL) {
free_key = 1;
if (!app_passwd(passinarg, NULL, &key, NULL)) {
if (passin == NULL) {
free_passin = 1;
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
}
pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key");
cleanse(key);
pkey = load_key(keyfile, keyformat, 0, passin, e, "CA private key");
if (pkey == NULL)
/* load_key() has already printed an appropriate message */
goto end;
@ -585,7 +585,7 @@ end_of_options:
&& (certfile = lookup_conf(conf, section, ENV_CERTIFICATE)) == NULL)
goto end;
x509 = load_cert(certfile, certformat, "CA certificate");
x509 = load_cert_pass(certfile, certformat, passin, "CA certificate");
if (x509 == NULL)
goto end;
@ -940,8 +940,8 @@ end_of_options:
}
if (ss_cert_file != NULL) {
total++;
j = certify_cert(&x, ss_cert_file, certformat, pkey, x509, dgst,
sigopts, vfyopts, attribs,
j = certify_cert(&x, ss_cert_file, certformat, passin, pkey,
x509, dgst, sigopts, vfyopts, attribs,
db, serial, subj, chtype, multirdn, email_dn,
startdate, enddate, days, batch, extensions,
conf, verbose, certopt, get_nameopt(), default_op,
@ -1262,7 +1262,8 @@ end_of_options:
goto end;
} else {
X509 *revcert;
revcert = load_cert(infile, certformat, infile);
revcert = load_cert_pass(infile, certformat, passin, infile);
if (revcert == NULL)
goto end;
if (dorevoke == 2)
@ -1291,8 +1292,9 @@ end_of_options:
BIO_free_all(in);
sk_X509_pop_free(cert_sk, X509_free);
if (free_key)
OPENSSL_free(key);
cleanse(passin);
if (free_passin)
OPENSSL_free(passin);
BN_free(serial);
BN_free(crlnumber);
free_index(db);
@ -1379,7 +1381,7 @@ static int certify(X509 **xret, const char *infile, int informat,
}
static int certify_cert(X509 **xret, const char *infile, int certformat,
EVP_PKEY *pkey, X509 *x509,
const char *passin, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(OPENSSL_STRING) *vfyopts,
@ -1395,7 +1397,7 @@ static int certify_cert(X509 **xret, const char *infile, int certformat,
EVP_PKEY *pktmp = NULL;
int ok = -1, i;
if ((req = load_cert(infile, certformat, infile)) == NULL)
if ((req = load_cert_pass(infile, certformat, passin, infile)) == NULL)
goto end;
if (verbose)
X509_print(bio_err, req);

View File

@ -105,7 +105,7 @@ X509_REQ *load_csr(const char *file, int format, const char *desc);
X509 *load_cert_pass(const char *uri, int maybe_stdin,
const char *pass, const char *desc);
/* the format parameter is meanwhile not needed anymore and thus ignored */
X509 *load_cert(const char *uri, int format, const char *desc);
#define load_cert(uri, format, desc) load_cert_pass(uri, 0, NULL, desc)
X509_CRL *load_crl(const char *uri, int format, const char *desc);
void cleanse(char *str);
void clear_free(char *str);

View File

@ -500,12 +500,6 @@ X509 *load_cert_pass(const char *uri, int maybe_stdin,
return cert;
}
/* the format parameter is meanwhile not needed anymore and thus ignored */
X509 *load_cert(const char *uri, int format, const char *desc)
{
return load_cert_pass(uri, 1, NULL, desc);
}
/* the format parameter is meanwhile not needed anymore and thus ignored */
X509_CRL *load_crl(const char *uri, int format, const char *desc)
{

View File

@ -612,7 +612,7 @@ const OPTIONS s_client_options[] = {
{"host", OPT_HOST, 's', "Use -connect instead"},
{"port", OPT_PORT, 'p', "Use -connect instead"},
{"connect", OPT_CONNECT, 's',
"TCP/IP where to connect (default is :" PORT ")"},
"TCP/IP where to connect; default: " PORT ")"},
{"bind", OPT_BIND, 's', "bind local address for connection"},
{"proxy", OPT_PROXY, 's',
"Connect to via specified proxy to the real server"},
@ -643,9 +643,9 @@ const OPTIONS s_client_options[] = {
{"cert_chain", OPT_CERT_CHAIN, '<',
"Client certificate chain file (in PEM format)"},
{"build_chain", OPT_BUILD_CHAIN, '-', "Build client certificate chain"},
{"key", OPT_KEY, 's', "Private key file to use; default is: -cert file"},
{"key", OPT_KEY, 's', "Private key file to use; default: -cert file"},
{"keyform", OPT_KEYFORM, 'E', "Key format (ENGINE, other values ignored)"},
{"pass", OPT_PASS, 's', "Private key file pass phrase source"},
{"pass", OPT_PASS, 's', "Private key and cert file pass phrase source"},
{"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"},
{"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
{"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
@ -702,7 +702,7 @@ const OPTIONS s_client_options[] = {
{"keymatexport", OPT_KEYMATEXPORT, 's',
"Export keying material using label"},
{"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
"Export len bytes of keying material (default 20)"},
"Export len bytes of keying material; default 20"},
{"security_debug", OPT_SECURITY_DEBUG, '-',
"Enable security debug messages"},
{"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
@ -790,7 +790,7 @@ const OPTIONS s_client_options[] = {
OPT_V_OPTIONS,
{"CRL", OPT_CRL, '<', "CRL file to use"},
{"crl_download", OPT_CRL_DOWNLOAD, '-', "Download CRL from distribution points"},
{"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"},
{"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER); default PEM"},
{"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
"Close connection on verification error"},
{"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"},
@ -1740,7 +1740,7 @@ int s_client_main(int argc, char **argv)
}
if (cert_file != NULL) {
cert = load_cert(cert_file, cert_format, "client certificate file");
cert = load_cert_pass(cert_file, cert_format, pass, "client certificate file");
if (cert == NULL)
goto end;
}

View File

@ -809,9 +809,9 @@ const OPTIONS s_server_options[] = {
{"Verify", OPT_UPPER_V_VERIFY, 'n',
"Turn on peer certificate verification, must have a cert"},
{"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
{"cert", OPT_CERT, '<', "Server certificate file to use; default is " TEST_CERT},
{"cert", OPT_CERT, '<', "Server certificate file to use; default " TEST_CERT},
{"cert2", OPT_CERT2, '<',
"Certificate file to use for servername; default is" TEST_CERT2},
"Certificate file to use for servername; default " TEST_CERT2},
{"certform", OPT_CERTFORM, 'F',
"Server certificate file format (PEM/DER/P12); has no effect"},
{"cert_chain", OPT_CERT_CHAIN, '<',
@ -824,7 +824,7 @@ const OPTIONS s_server_options[] = {
{"key2", OPT_KEY2, '<',
"-Private Key file to use for servername if not in -cert2"},
{"keyform", OPT_KEYFORM, 'f', "Key format (ENGINE, other values ignored)"},
{"pass", OPT_PASS, 's', "Private key file pass phrase source"},
{"pass", OPT_PASS, 's', "Private key and cert file pass phrase source"},
{"dcert", OPT_DCERT, '<',
"Second server certificate file to use (usually for DSA)"},
{"dcertform", OPT_DCERTFORM, 'F',
@ -835,16 +835,14 @@ const OPTIONS s_server_options[] = {
"Second private key file to use (usually for DSA)"},
{"dkeyform", OPT_DKEYFORM, 'F',
"Second key file format (ENGINE, other values ignored)"},
{"dpass", OPT_DPASS, 's', "Second private key file pass phrase source"},
{"dpass", OPT_DPASS, 's', "Second private key and cert file pass phrase source"},
{"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"},
{"servername", OPT_SERVERNAME, 's',
"Servername for HostName TLS extension"},
{"servername_fatal", OPT_SERVERNAME_FATAL, '-',
"mismatch send fatal alert (default warning alert)"},
{"nbio_test", OPT_NBIO_TEST, '-', "Test with the non-blocking test bio"},
{"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"},
{"quiet", OPT_QUIET, '-', "No server output"},
{"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-',
"Disable caching and tickets if ephemeral (EC)DH is used"},
@ -860,7 +858,7 @@ const OPTIONS s_server_options[] = {
{"keymatexport", OPT_KEYMATEXPORT, 's',
"Export keying material using label"},
{"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
"Export len bytes of keying material (default 20)"},
"Export len bytes of keying material; default 20"},
{"CRL", OPT_CRL, '<', "CRL file to use"},
{"CRLform", OPT_CRLFORM, 'F', "CRL file format (PEM or DER); default PEM"},
{"crl_download", OPT_CRL_DOWNLOAD, '-',
@ -1752,7 +1750,7 @@ int s_server_main(int argc, char *argv[])
if (s_key == NULL)
goto end;
s_cert = load_cert(s_cert_file, s_cert_format,
s_cert = load_cert_pass(s_cert_file, s_cert_format, pass,
"server certificate file");
if (s_cert == NULL)
@ -1769,7 +1767,7 @@ int s_server_main(int argc, char *argv[])
if (s_key2 == NULL)
goto end;
s_cert2 = load_cert(s_cert_file2, s_cert_format,
s_cert2 = load_cert_pass(s_cert_file2, s_cert_format, pass,
"second server certificate file");
if (s_cert2 == NULL)
@ -1814,7 +1812,7 @@ int s_server_main(int argc, char *argv[])
if (s_dkey == NULL)
goto end;
s_dcert = load_cert(s_dcert_file, s_dcert_format,
s_dcert = load_cert_pass(s_dcert_file, s_dcert_format, dpass,
"second server certificate file");
if (s_dcert == NULL) {

View File

@ -80,7 +80,7 @@ const OPTIONS x509_options[] = {
{"inform", OPT_INFORM, 'f',
"CSR input format (DER or PEM) - default PEM"},
{"in", OPT_IN, '<', "Input file - default stdin"},
{"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"},
{"passin", OPT_PASSIN, 's', "Private key and cert file pass-phrase source"},
{"outform", OPT_OUTFORM, 'f',
"Output format (DER or PEM) - default PEM"},
{"out", OPT_OUT, '>', "Output file - default stdout"},
@ -633,7 +633,7 @@ int x509_main(int argc, char **argv)
if (!X509_set_pubkey(x, fkey != NULL ? fkey : X509_REQ_get0_pubkey(req)))
goto end;
} else {
x = load_cert(infile, FORMAT_UNDEF, "Certificate");
x = load_cert_pass(infile, FORMAT_UNDEF, passin, "Certificate");
if (x == NULL)
goto end;
if (fkey != NULL && !X509_set_pubkey(x, fkey))
@ -643,7 +643,7 @@ int x509_main(int argc, char **argv)
}
if (CA_flag) {
xca = load_cert(CAfile, CAformat, "CA Certificate");
xca = load_cert_pass(CAfile, CAformat, passin, "CA Certificate");
if (xca == NULL)
goto end;
}
@ -963,7 +963,7 @@ int x509_main(int argc, char **argv)
sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
ASN1_OBJECT_free(objtmp);
release_engine(e);
OPENSSL_free(passin);
clear_free(passin);
return ret;
}

View File

@ -138,7 +138,7 @@ The directory to output certificates to. The certificate will be
written to a filename consisting of the serial number in hex with
F<.pem> appended.
=item B<-cert>
=item B<-cert> I<filename>
The CA certificate, which must match with B<-keyfile>.
@ -197,7 +197,8 @@ self-signed certificate.
=item B<-passin> I<arg>
The key password source. For more information about the format of B<arg>
The key and certificate password source.
For more information about the format of B<arg>
see L<openssl(1)/Pass Phrase Options>.
=item B<-notext>

View File

@ -234,7 +234,7 @@ Suppresses sending of the SNI (Server Name Indication) extension in the
ClientHello message. Cannot be used in conjunction with the B<-servername> or
<-dane_tlsa_domain> options.
=item B<-cert> I<certname>
=item B<-cert> I<filename>
The client certificate to use, if one is requested by the server.
The default is not to use a certificate.
@ -283,7 +283,8 @@ See L<openssl(1)/Format Options> for details.
=item B<-pass> I<arg>
the private key password source. For more information about the format of I<arg>
the private key and certifiate file password source.
For more information about the format of I<arg>
see L<openssl(1)/Pass phrase options>.
=item B<-verify> I<depth>

View File

@ -258,7 +258,7 @@ See L<openssl(1)/Format Options> for details.
=item B<-pass> I<val>
The private key password source.
The private key and certificate file password source.
For more information about the format of I<val>,
see L<openssl(1)/Pass Phrase Options>.
@ -293,7 +293,7 @@ See L<openssl(1)/Format Options>.
=item B<-dpass> I<val>
The passphrase for the additional private key.
The passphrase for the additional private key and certificate.
For more information about the format of I<val>,
see L<openssl(1)/Pass Phrase Options>.

View File

@ -386,7 +386,8 @@ Names and values of these options are algorithm-specific.
=item B<-passin> I<arg>
The key password source. For more information about the format of I<arg>
The key and certificate file password source.
For more information about the format of I<arg>
see L<openssl(1)/Pass Phrase Options>.
=item B<-clrext>

View File

@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
setup("test_x509");
plan tests => 11;
plan tests => 12;
require_ok(srctop_file('test','recipes','tconversion.pl'));
@ -35,6 +35,17 @@ ok(run(app(["openssl", "x509", "-text", "-in", $pem, "-out", $out_utf8,
is(cmp_text($out_utf8, srctop_file("test/certs", "cyrillic.utf8")),
0, 'Comparing utf8 output');
SKIP: {
skip "DES disabled", 1 if disabled("des");
my $p12 = srctop_file("test", "shibboleth.pfx");
my $p12pass = "σύνθημα γνώρισμα";
my $out_pem = "out.pem";
ok(run(app(["openssl", "x509", "-text", "-in", $p12, "-out", $out_pem,
"-passin", "pass:$p12pass"])));
unlink $out_pem;
}
SKIP: {
skip "EC disabled", 1 if disabled("ec");