]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Make better use of new load_cert_pass() variant of load_cert() in apps/ 12647/head
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Sun, 16 Aug 2020 13:25:27 +0000 (15:25 +0200)
committerDr. David von Oheimb <David.von.Oheimb@siemens.com>
Thu, 20 Aug 2020 12:55:52 +0000 (14:55 +0200)
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)

apps/ca.c
apps/include/apps.h
apps/lib/apps.c
apps/s_client.c
apps/s_server.c
apps/x509.c
doc/man1/openssl-ca.pod.in
doc/man1/openssl-s_client.pod.in
doc/man1/openssl-s_server.pod.in
doc/man1/openssl-x509.pod.in
test/recipes/25-test_x509.t

index 2c607155313225102599b802e49ccaa02cbc909c..8a5104f48810f68ba26d2a642abba25dc29049f7 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -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);
index 0f00e9f52aa34e564336bf9e9c463c5ec3691fd4..8d1eb7c280ffd80a15111d02006b74aa776dddf2 100644 (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);
index b2e29917eb4d21dfb01021dea4efd26712813432..150df997b8feae3f979e77298985761ff8c3f53a 100644 (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)
 {
index ba4fcdcca178d86c6e6ab4a948db48e84b347fe8..2a58589ce29ae4071317b2b81b186e76eba35f5c 100644 (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;
     }
index 1c20b48027cb4b8f23cc9e5b58bb37943b401a68..b936ff42262508a4b97de6f9cd011578a5f075cb 100644 (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) {
index fbe4b8cefe5efc455c05da81e916c7b81c1473d1..64a1cadc97eb256bdf659892ae689336ce512ac8 100644 (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;
 }
 
index 580ed574a34ba8a8afe44a424c60acb0ca755811..7d7f0752f39a1b11923f0f806f3acd62562303bf 100644 (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>
index bcb39f50ca82c0cf0f46e87e7c37f829e66e3af8..594d26f9bd99f9caa5f2a575a9be4d8104d3b28a 100644 (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>
index 7e10fdb0365b570542e7d00119d85a693a76d56c..b074485a63dea142d116eb79a1c3e8f123430557 100644 (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>.
 
index 33e24ac6e9420bb7c9c05d8aa6a5ffe3dc4427b1..8eb35e537e9f12ea74b9e176348021dec078e39a 100644 (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>
index 250738487a56d4514a95a8510183937203e6f4c8..3cfcb2290cc87af2e0512902ce66ded68e1962a1 100644 (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");