]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
ab: Add client certificate support.
authorGraham Leggett <minfrin@apache.org>
Wed, 10 Oct 2018 09:13:20 +0000 (09:13 +0000)
committerGraham Leggett <minfrin@apache.org>
Wed, 10 Oct 2018 09:13:20 +0000 (09:13 +0000)
trunk: http://svn.apache.org/r1841784
2.4.x: svn merge -c r1841784 ^/httpd/httpd/trunk .
+1: minfrin, jim, ylavic

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1843412 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
docs/manual/programs/ab.xml
support/ab.c

diff --git a/CHANGES b/CHANGES
index 416cb4a1917062cb365f2f6b686f2444dbb82eb3..1a588d9d8f10355f9fcd3e321ba641a436c8a4cb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.4.36
 
+  *) ab: Add client certificate support. [Graham Leggett]
+
   *) ab: Disable printing temp key for OpenSSL before
      version 1.0.2. SSL_get_server_tmp_key is not available
      there. [Rainer Jung]
diff --git a/STATUS b/STATUS
index 906632c8a054a7a66683580f2b304a9b733c1768..1f7e9f2073152909126e1789857f0294ceba330f 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -124,11 +124,7 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  *) ab: Add client certificate support.
-     trunk: http://svn.apache.org/r1841784
-     2.4.x: svn merge -c r1841784 ^/httpd/httpd/trunk .
-     (requires r1738415 and r1826930 above to resolve conflict)
-     +1: minfrin, jim, ylavic
+
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]
index a4777b3bb6b9e93a276f2f5fff86e2b1d4991c9d..bb177f3cad226758794638b95ea633b41181fa85 100644 (file)
@@ -43,6 +43,7 @@
     [ -<strong>C</strong> <var>cookie-name</var>=<var>value</var> ]
     [ -<strong>d</strong> ]
     [ -<strong>e</strong> <var>csv-file</var> ]
+    [ -<strong>E</strong> <var>client-certificate file</var> ]
     [ -<strong>f</strong> <var>protocol</var> ]
     [ -<strong>g</strong> <var>gnuplot-file</var> ]
     [ -<strong>h</strong> ]
     that percentage of the requests. This is usually more useful than the
     'gnuplot' file; as the results are already 'binned'.</dd>
 
+    <dt><code>-E <var>client-certificate-file</var></code></dt>
+    <dd>When connecting to an SSL website, use the provided client certificate
+    in PEM format to authenticate with the server. The file is expected to
+    contain the client certificate, followed by intermediate certificates,
+    followed by the private key. Available in 2.4.36 and later.</dd>
+
     <dt><code>-f <var>protocol</var></code></dt>
     <dd>Specify SSL/TLS protocol (SSL2, SSL3, TLS1, TLS1.1, TLS1.2, or ALL).
     TLS1.1 and TLS1.2 support available in 2.4.4 and later.</dd>
index 224bd69f99af018c128cdcab9c1ec80296343cfa..410d58e56e587366781d376819efa6aec6cafe95 100644 (file)
@@ -353,6 +353,7 @@ int is_ssl;
 SSL_CTX *ssl_ctx;
 char *ssl_cipher = NULL;
 char *ssl_info = NULL;
+char *ssl_cert = NULL;
 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
 char *ssl_tmp_key = NULL;
 #endif
@@ -2170,6 +2171,7 @@ static void usage(const char *progname)
     fprintf(stderr, "    -Z ciphersuite  Specify SSL/TLS cipher suite (See openssl ciphers)\n");
     fprintf(stderr, "    -f protocol     Specify SSL/TLS protocol\n");
     fprintf(stderr, "                    (" SSL2_HELP_MSG SSL3_HELP_MSG "TLS1" TLS1_X_HELP_MSG " or ALL)\n");
+    fprintf(stderr, "    -E certfile     Specify optional client certificate chain and private key\n");
 #endif
     exit(EINVAL);
 }
@@ -2340,7 +2342,7 @@ int main(int argc, const char * const argv[])
     apr_getopt_init(&opt, cntxt, argc, argv);
     while ((status = apr_getopt(opt, "n:c:t:s:b:T:p:u:v:lrkVhwiIx:y:z:C:H:P:A:g:X:de:SqB:m:"
 #ifdef USE_SSL
-            "Z:f:"
+            "Z:f:E:"
 #endif
             ,&c, &opt_arg)) == APR_SUCCESS) {
         switch (c) {
@@ -2524,6 +2526,9 @@ int main(int argc, const char * const argv[])
             case 'Z':
                 ssl_cipher = strdup(opt_arg);
                 break;
+            case 'E':
+                ssl_cert = strdup(opt_arg);
+                break;
             case 'f':
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
                 if (strncasecmp(opt_arg, "ALL", 3) == 0) {
@@ -2658,6 +2663,26 @@ int main(int argc, const char * const argv[])
     if (verbosity >= 3) {
         SSL_CTX_set_info_callback(ssl_ctx, ssl_state_cb);
     }
+    if (ssl_cert != NULL) {
+        if (SSL_CTX_use_certificate_chain_file(ssl_ctx, ssl_cert) <= 0) {
+            BIO_printf(bio_err, "unable to get certificate from '%s'\n",
+                       ssl_cert);
+            ERR_print_errors(bio_err);
+            exit(1);
+        }
+        if (SSL_CTX_use_PrivateKey_file(ssl_ctx, ssl_cert, SSL_FILETYPE_PEM) <= 0) {
+            BIO_printf(bio_err, "unable to get private key from '%s'\n",
+                ssl_cert);
+            ERR_print_errors(bio_err);
+            exit(1);
+        }
+        if (!SSL_CTX_check_private_key(ssl_ctx)) {
+            BIO_printf(bio_err,
+                       "private key does not match the certificate public key in %s\n", ssl_cert);
+            exit(1);
+        }
+    }
+
 #endif
 #ifdef SIGPIPE
     apr_signal(SIGPIPE, SIG_IGN);       /* Ignore writes to connections that