This is a patch for the version of ab on the trunk.
In this version of ab, HAVE_OPENSSL controls if I
have OpenSSL.  I conformed to the way although I
did not checked the case of HAVE_SSLC.

There has also been small more fixes.

1. The resulting shared key bit length is now the
  number of effective bits.

2. Now ab does not dump core in case of SSL handshake
  error.

Later, I will also submit the above changes for the
original 2.0.54 patch.

--
Masaoki Kobayashi
<[EMAIL PROTECTED]>
--- ab.c.org    2005-05-11 13:32:42.263557000 +0900
+++ ab.c        2005-05-11 21:05:19.957780000 +0900
@@ -164,6 +164,9 @@
 #include <sslc.h>
 #define USE_SSL
 #define RSAREF
+#define SK_NUM(x) sk_num(x)
+#define SK_VALUE(x,y) sk_value(x,y)
+typedef STACK X509_STACK_TYPE;
 
 #elif defined(HAVE_OPENSSL)
 
@@ -176,6 +179,9 @@
 #include <openssl/ssl.h>
 #include <openssl/rand.h>
 #define USE_SSL
+#define SK_NUM(x) sk_X509_num(x)
+#define SK_VALUE(x,y) sk_X509_value(x,y)
+typedef STACK_OF(X509) X509_STACK_TYPE;
 
 #endif
 
@@ -232,9 +238,6 @@
 };
 
 struct data {
-#ifdef USE_SSL
-    /* XXXX insert SSL timings */
-#endif
     int read;              /* number of bytes read */
     apr_time_t starttime;  /* start time of connection in seconds since
                             * Jan. 1, 1970 */
@@ -301,10 +304,11 @@
 long epipe = 0;             /* number of broken pipe writes */
 
 #ifdef USE_SSL
-int ssl = 0;
-SSL_CTX *ctx;
+int is_ssl;
+SSL_CTX *ssl_ctx;
+char *ssl_cipher = NULL;
+char *ssl_info = NULL;
 BIO *bio_out,*bio_err;
-static void write_request(struct connection * c);
 #endif
 
 /* store error cases */
@@ -336,7 +340,24 @@
 apr_xlate_t *from_ascii, *to_ascii;
 #endif
 
+static void err(char *s);
+static void apr_err(char *s, apr_status_t rv);
+static void write_request(struct connection * c);
+static int compradre(struct data * a, struct data * b);
+static int comprando(struct data * a, struct data * b);
+static int compri(struct data * a, struct data * b);
+static int compwait(struct data * a, struct data * b);
+static void output_results(void);
+static void output_html_results(void);
+static void start_connect(struct connection * c);
 static void close_connection(struct connection * c);
+static void read_connection(struct connection * c);
+static void test(void);
+static void copyright(void);
+static void usage(const char *progname);
+static int parse_url(char *url);
+static int open_postfile(const char *pfile);
+
 /* --------------------------------------------------------- */
 
 /* simple little function to write an error string and exit */
@@ -363,74 +384,6 @@
     exit(rv);
 }
 
-#if defined(USE_SSL) && USE_THREADS
-/*
- * To ensure thread-safetyness in OpenSSL - work in progress
- */
-
-static apr_thread_mutex_t **lock_cs;
-static int                  lock_num_locks;
-
-static void ssl_util_thr_lock(int mode, int type,
-                              const char *file, int line)
-{
-    if (type < lock_num_locks) {
-        if (mode & CRYPTO_LOCK) {
-            apr_thread_mutex_lock(lock_cs[type]);
-        }
-        else {
-            apr_thread_mutex_unlock(lock_cs[type]);
-        }
-    }
-}
-
-static unsigned long ssl_util_thr_id(void)
-{
-    /* OpenSSL needs this to return an unsigned long.  On OS/390, the pthread 
-     * id is a structure twice that big.  Use the TCB pointer instead as a 
-     * unique unsigned long.
-     */
-#ifdef __MVS__
-    struct PSA {
-        char unmapped[540];
-        unsigned long PSATOLD;
-    } *psaptr = 0;
-
-    return psaptr->PSATOLD;
-#else
-    return (unsigned long) apr_os_thread_current();
-#endif
-}
-
-static apr_status_t ssl_util_thread_cleanup(void *data)
-{
-    CRYPTO_set_locking_callback(NULL);
-
-    /* Let the registered mutex cleanups do their own thing 
-     */
-    return APR_SUCCESS;
-}
-
-void ssl_util_thread_setup(apr_pool_t *p)
-{
-    int i;
-
-    lock_num_locks = CRYPTO_num_locks();
-    lock_cs = apr_palloc(p, lock_num_locks * sizeof(*lock_cs));
-
-    for (i = 0; i < lock_num_locks; i++) {
-        apr_thread_mutex_create(&(lock_cs[i]), APR_THREAD_MUTEX_DEFAULT, p);
-    }
-
-    CRYPTO_set_id_callback(ssl_util_thr_id);
-
-    CRYPTO_set_locking_callback(ssl_util_thr_lock);
-
-    apr_pool_cleanup_register(p, NULL, ssl_util_thread_cleanup,
-                                       apr_pool_cleanup_null);
-}
-#endif
-
 /* --------------------------------------------------------- */
 /* write out request to a connection - assumes we can write
  * (small) request out in one go into our new socket buffer
@@ -460,6 +413,24 @@
     return(ret);
 }
 
+static void ssl_state_cb(const SSL *s, int w, int r)
+{
+    if (w & SSL_CB_ALERT) {
+       BIO_printf(bio_err, "SSL/TLS Alert [%s] %s:%s\n",
+           (w & SSL_CB_READ ? "read" : "write"),
+            SSL_alert_type_string_long(r),
+            SSL_alert_desc_string_long(r));
+    } else if (w & SSL_CB_LOOP) {
+       BIO_printf(bio_err, "SSL/TLS State [%s] %s\n",
+           (SSL_in_connect_init((SSL*)s) ? "connect" : "-"),
+           SSL_state_string_long(s));
+    } else if (w & (SSL_CB_HANDSHAKE_START|SSL_CB_HANDSHAKE_DONE)) {
+       BIO_printf(bio_err, "SSL/TLS Handshake [%s] %s\n",
+           (w & SSL_CB_HANDSHAKE_START ? "Start" : "Done"),
+           SSL_state_string_long(s));
+    }
+}
+
 #ifndef RAND_MAX
 #include <limits.h>
 #define RAND_MAX INT_MAX
@@ -526,166 +497,125 @@
     return(1);
 }
 
-static int ssl_print_cert_info(BIO *bio, X509 *x509cert)
+static void ssl_print_cert_info(BIO *bio, X509 *cert)
 {
     X509_NAME *dn;
-    char buf[64];
-
-    BIO_printf(bio,"Certificate version: %d\n",X509_get_version(x509cert)+1);
+    char buf[1024];
 
+    BIO_printf(bio, "Certificate version: %d\n", X509_get_version(cert)+1);
     BIO_printf(bio,"Valid from: ");
-    ASN1_UTCTIME_print(bio, X509_get_notBefore(x509cert));
+    ASN1_UTCTIME_print(bio, X509_get_notBefore(cert));
     BIO_printf(bio,"\n");
 
     BIO_printf(bio,"Valid to  : ");
-    ASN1_UTCTIME_print(bio, X509_get_notAfter(x509cert));
+    ASN1_UTCTIME_print(bio, X509_get_notAfter(cert));
     BIO_printf(bio,"\n");
 
     BIO_printf(bio,"Public key is %d bits\n",
-        EVP_PKEY_bits(X509_get_pubkey(x509cert)));
+       EVP_PKEY_bits(X509_get_pubkey(cert)));
 
-    dn=X509_get_issuer_name(x509cert);
-    X509_NAME_oneline(dn, buf, sizeof buf);
+    dn = X509_get_issuer_name(cert);
+    X509_NAME_oneline(dn, buf, sizeof(buf));
     BIO_printf(bio,"The issuer name is %s\n", buf);
 
-    dn=X509_get_subject_name(x509cert);
-    X509_NAME_oneline(dn, buf, sizeof buf);
+    dn=X509_get_subject_name(cert);
+    X509_NAME_oneline(dn, buf, sizeof(buf));
     BIO_printf(bio,"The subject name is %s\n", buf);
 
     /* dump the extension list too */
-    BIO_printf(bio,"Extension Count: %d\n",X509_get_ext_count(x509cert));
-
-    return(1);
+    BIO_printf(bio, "Extension Count: %d\n", X509_get_ext_count(cert));
 }
 
-static void ssl_start_connect(struct connection * c)
+void ssl_print_info(struct connection *c)
 {
-    BIO *bio;
-    X509 *x509cert;
-#ifdef RSAREF
-    STACK *sk;
-#else
-    STACK_OF(X509) *sk;
-#endif
-    int i, count, hdone = 0;
-    char ssl_hostname[80];
-    
-    /* XXX - Verify if it's okay - TBD */
-    if (requests < concurrency)
-        requests = concurrency;
+    X509_STACK_TYPE *sk;
+    X509 *cert;
+    int count;
 
-    if (!(started < requests))
-        return;
-
-    c->read = 0;
-    c->bread = 0;
-    c->keepalive = 0;
-    c->cbx = 0;
-    c->gotheader = 0;
-    c->rwrite = 0;
-    if (c->ctx)
-        apr_pool_destroy(c->ctx);
-    apr_pool_create(&c->ctx, cntxt);
-
-    if ((c->ssl=SSL_new(ctx)) == NULL)
-    {
-        BIO_printf(bio_err,"SSL_new failed\n");
-        exit(1);
+    BIO_printf(bio_err, "\n");
+    sk = SSL_get_peer_cert_chain(c->ssl);
+    if ((count = SK_NUM(sk)) > 0) {
+        int i;
+        for (i=1; i<count; i++) {
+            cert = (X509 *)SK_VALUE(sk, i);
+            ssl_print_cert_info(bio_out, cert);
+            X509_free(cert);
     }
-
-    ssl_rand_seed();
-
-    c->start = apr_time_now();
-    memset(ssl_hostname, 0, 80);
-    sprintf(ssl_hostname, "%s:%d", hostname, port);
-
-    if ((bio = BIO_new_connect(ssl_hostname)) == NULL)
-    {
-        BIO_printf(bio_err,"BIO_new_connect failed\n");
-        exit(1);
     }
-    SSL_set_bio(c->ssl,bio,bio);
-    SSL_set_connect_state(c->ssl);
-
-    if (verbosity >= 4)
-    {
-        BIO_set_callback(bio,ssl_print_cb);
-        BIO_set_callback_arg(bio,(void*)bio_err);
+    cert = SSL_get_peer_certificate(c->ssl);
+    if (cert == NULL) {
+        BIO_printf(bio_out, "Anon DH\n");
+    } else {
+        BIO_printf(bio_out, "Peer certificate\n");
+        ssl_print_cert_info(bio_out, cert);
+        X509_free(cert);
+    }
+    ssl_print_connection_info(bio_err,c->ssl);
+    SSL_SESSION_print(bio_err, SSL_get_session(c->ssl));
     }
 
-    while (!hdone)
+void ssl_proceed_handshake(struct connection *c)
     {
-        i = SSL_do_handshake(c->ssl);
+    int do_next = 1;
 
-        switch (SSL_get_error(c->ssl,i))
-        {
+    while(do_next) {
+        int ret, ecode;
+        apr_pollfd_t new_pollfd;
+
+        ret = SSL_do_handshake(c->ssl);
+        ecode = SSL_get_error(c->ssl, ret);
+
+        switch(ecode) {
             case SSL_ERROR_NONE:
-                hdone=1;
-                break;
-            case SSL_ERROR_SSL:
-            case SSL_ERROR_SYSCALL:
-                BIO_printf(bio_err,"SSL connection failed\n");
-                err_conn++;
-                c->state = STATE_UNCONNECTED;
-                if (bad++ > 10) {
-                    SSL_free (c->ssl);
-                    BIO_printf(bio_err,"\nTest aborted after 10 failures\n\n");
-                    exit (1);
+            if (verbosity >= 2)
+                ssl_print_info(c);
+            if (ssl_info == NULL) {
+                SSL_CIPHER *ci;
+                X509 *cert;
+                int sk_bits, pk_bits, swork;
+
+                ci = SSL_get_current_cipher(c->ssl);
+                sk_bits = SSL_CIPHER_get_bits(ci, &swork);
+                cert = SSL_get_peer_certificate(c->ssl);
+                if (cert)
+                    pk_bits = EVP_PKEY_bits(X509_get_pubkey(cert));
+                else
+                    pk_bits = 0;  /* Anon DH */
+
+                ssl_info = malloc(128);
+                apr_snprintf(ssl_info, 128, "%s,%s,%d,%d",
+                    SSL_CIPHER_get_version(ci),
+                    SSL_CIPHER_get_name(ci),
+                    pk_bits, sk_bits);
                 }
+            write_request(c);
+            do_next = 0;
                 break;
             case SSL_ERROR_WANT_READ:
+            new_pollfd.desc_type = APR_POLL_SOCKET;
+            new_pollfd.reqevents = APR_POLLIN;
+            new_pollfd.desc.s = c->aprsock;
+            new_pollfd.client_data = c;
+            apr_pollset_add(readbits, &new_pollfd);
+            do_next = 0;
+            break;
             case SSL_ERROR_WANT_WRITE:
-            case SSL_ERROR_WANT_CONNECT:
-                BIO_printf(bio_err, "Waiting .. sleep(1)\n");
-                apr_sleep(apr_time_from_sec(1));
-                c->state = STATE_CONNECTED;
-                c->rwrite = 0;
+            /* Try again */
+            do_next = 1;
                 break;
-            case SSL_ERROR_ZERO_RETURN:
-                BIO_printf(bio_err,"socket closed\n");
+        case SSL_ERROR_WANT_CONNECT:
+        case SSL_ERROR_SSL:
+        case SSL_ERROR_SYSCALL:
+            /* Unexpected result */
+            BIO_printf(bio_err, "SSL handshake failed (%d).\n", ecode);
+            ERR_print_errors(bio_err);
+            close_connection(c);
+           do_next = 0;
                 break;
         }
     }
-    
-    if (verbosity >= 2)
-    {
-        BIO_printf(bio_err, "\n");
-        sk = SSL_get_peer_cert_chain(c->ssl);
-#ifdef RSAREF
-        if ((count = sk_num(sk)) > 0)
-#else
-        if ((count = sk_X509_num(sk)) > 0)
-#endif
-        {
-            for (i=1; i<count; i++)
-            {
-#ifdef RSAREF
-                x509cert = (X509 *)sk_value(sk,i);
-#else
-                x509cert = (X509 *)sk_X509_value(sk,i);
-#endif
-                ssl_print_cert_info(bio_out,x509cert);
-            }
-        }
-
-        x509cert = SSL_get_peer_certificate(c->ssl);
-        if (x509cert == NULL)
-            BIO_printf(bio_out, "Anon DH\n");
-        else
-        {
-            BIO_printf(bio_out, "Peer certificate\n");
-            ssl_print_cert_info(bio_out,x509cert);
-            X509_free(x509cert);
-        }
-
-        ssl_print_connection_info(bio_err,c->ssl);
-        SSL_SESSION_print(bio_err,SSL_get_session(c->ssl));
     }
 
-    /* connected first time */
-    started++;
-    write_request(c);
-}
 #endif /* USE_SSL */
 
 static void write_request(struct connection * c)
@@ -699,9 +629,6 @@
          * First time round ?
          */
         if (c->rwrite == 0) {
-#ifdef USE_SSL
-            if (ssl != 1)
-#endif
             apr_socket_timeout_set(c->aprsock, 0);
             c->connect = tnow;
             c->rwrite = reqlen;
@@ -716,16 +643,18 @@
         }
     
 #ifdef USE_SSL
-        if (ssl == 1) {
+        if (c->ssl) {
             apr_size_t e_ssl;
             e_ssl = SSL_write(c->ssl,request + c->rwrote, l);
             if (e_ssl != l)
             {
-                printf("SSL write failed - closing connection\n");
+                BIO_printf(bio_err, "SSL write failed - closing connection\n");
+               ERR_print_errors(bio_err);
                 close_connection (c);
                 return;
             }
             l = e_ssl;
+            e = APR_SUCCESS;
         }
         else
 #endif
@@ -737,9 +666,6 @@
         if (l == c->rwrite)
             break;
     
-#ifdef USE_SSL
-        if (ssl != 1)
-#endif
         if (e != APR_SUCCESS) {
             /*
              * Let's hope this traps EWOULDBLOCK too !
@@ -758,9 +684,6 @@
     totalposted += c->rwrite;
     c->state = STATE_READ;
     c->endwrite = apr_time_now();
-#ifdef USE_SSL
-    if (ssl != 1)
-#endif
     {
         apr_pollfd_t new_pollfd;
         new_pollfd.desc_type = APR_POLL_SOCKET;
@@ -827,6 +750,10 @@
     printf("Server Software:        %s\n", servername);
     printf("Server Hostname:        %s\n", hostname);
     printf("Server Port:            %hd\n", port);
+#ifdef USE_SSL
+    if (is_ssl && ssl_info)
+    printf("SSL/TLS Protocol:       %s\n", ssl_info);
+#endif
     printf("\n");
     printf("Document Path:          %s\n", path);
     printf("Document Length:        %" APR_SIZE_T_FMT " bytes\n", doclen);
@@ -1193,13 +1120,6 @@
 {
     apr_status_t rv;
 
-#ifdef USE_SSL
-    if (ssl == 1) {
-        ssl_start_connect(c);
-        return;
-    }
-#endif
-    
     if (!(started < requests))
     return;
 
@@ -1222,6 +1142,29 @@
         apr_err("socket nonblock", rv);
     }
     c->start = apr_time_now();
+#ifdef USE_SSL
+    if (is_ssl) {
+       BIO *bio;
+       apr_os_sock_t fd;
+
+       if ((c->ssl = SSL_new(ssl_ctx)) == NULL) {
+           BIO_printf(bio_err, "SSL_new failed.\n");
+           ERR_print_errors(bio_err);
+           exit(1);
+       }
+       ssl_rand_seed();
+       apr_os_sock_get(&fd, c->aprsock);
+       bio = BIO_new_socket(fd, BIO_NOCLOSE);
+       SSL_set_bio(c->ssl, bio, bio);
+       SSL_set_connect_state(c->ssl);
+       if (verbosity >= 4) {
+           BIO_set_callback(bio, ssl_print_cb);
+           BIO_set_callback_arg(bio, bio_err);
+       }
+    } else {
+       c->ssl = NULL;
+    }
+#endif
     if ((rv = apr_socket_connect(c->aprsock, destsa)) != APR_SUCCESS) {
         if (APR_STATUS_IS_EINPROGRESS(rv)) {
             apr_pollfd_t new_pollfd;
@@ -1255,6 +1198,11 @@
     /* connected first time */
     c->state = STATE_CONNECTED;
     started++;
+#ifdef USE_SSL
+    if (c->ssl)
+       ssl_proceed_handshake(c);
+    else
+#endif
     write_request(c);
 }
 
@@ -1297,18 +1245,18 @@
         }
     }
 
-#ifdef USE_SSL
-    if (ssl == 1) {
-        SSL_shutdown(c->ssl);
-        SSL_free(c->ssl);
-    }
-    else
-#endif
     {
         apr_pollfd_t remove_pollfd;
         remove_pollfd.desc_type = APR_POLL_SOCKET;
         remove_pollfd.desc.s = c->aprsock;
         apr_pollset_remove(readbits, &remove_pollfd);
+#ifdef USE_SSL
+       if (c->ssl) {
+           SSL_shutdown(c->ssl);
+           SSL_free(c->ssl);
+           c->ssl = NULL;
+       }
+#endif
         apr_socket_close(c->aprsock);
     }
     c->state = STATE_UNCONNECTED;
@@ -1331,12 +1279,13 @@
 
     r = sizeof(buffer);
 #ifdef USE_SSL
-    if (ssl == 1)
-    {
+    if (c->ssl) {
         status = SSL_read (c->ssl, buffer, r);
         if (status <= 0) {
             good++; c->read = 0;
-            if (status < 0) printf("SSL read failed - closing connection\n");
+            if (status < 0)
+               BIO_printf(bio_err, "SSL read failed - closing connection\n");
+            ERR_print_errors(bio_err);
             close_connection(c);
             return;
         }
@@ -1637,9 +1586,6 @@
 #endif              /* NOT_ASCII */
 
     /* This only needs to be done once */
-#ifdef USE_SSL
-    if (ssl != 1)
-#endif
     if ((rv = apr_sockaddr_info_get(&destsa, connecthost, APR_UNSPEC, 
connectport, 0, cntxt))
        != APR_SUCCESS) {
         char buf[120];
@@ -1671,11 +1617,6 @@
         }
     
         n = concurrency;
-#ifdef USE_SSL
-        if (ssl == 1)
-            status = APR_SUCCESS;
-        else
-#endif
         status = apr_pollset_poll(readbits, aprtimeout, &n, &pollresults);
         if (status != APR_SUCCESS)
             apr_err("apr_poll", status);
@@ -1688,11 +1629,6 @@
             const apr_pollfd_t *next_fd = &(pollresults[i]);
             struct connection *c;
                 
-#ifdef USE_SSL
-            if (ssl) 
-                c = &con[i];
-            else
-#endif
                 c = next_fd->client_data;
 
             /*
@@ -1701,12 +1637,14 @@
             if (c->state == STATE_UNCONNECTED)
                 continue;
     
+           rv = next_fd->rtnevents;
+
 #ifdef USE_SSL
-            if (ssl == 1)
-                rv = APR_POLLIN;
-            else
+           if (c->state == STATE_CONNECTED && c->ssl && SSL_in_init(c->ssl)) {
+               ssl_proceed_handshake(c);
+               continue;
+           }
 #endif
-                rv = next_fd->rtnevents;
 
             /*
              * Notes: APR_POLLHUP is set after FIN is received on some
@@ -1749,6 +1687,11 @@
                     }
                     else {
                         c->state = STATE_CONNECTED;
+#ifdef USE_SSL
+                       if (c->ssl)
+                           ssl_proceed_handshake(c);
+                       else
+#endif
                         write_request(c);
                     }
                 }
@@ -1764,9 +1707,6 @@
              * connection is in STATE_READ or STATE_CONNECTING we'll add the
              * socket back in as APR_POLLIN.
              */
-#ifdef USE_SSL
-            if (ssl != 1)
-#endif
                 if (c->state == STATE_READ) {
                     apr_pollfd_t new_pollfd;
                     new_pollfd.desc_type = APR_POLL_SOCKET;
@@ -1843,10 +1783,11 @@
     fprintf(stderr, "    -S              Do not show confidence estimators and 
warnings.\n");
     fprintf(stderr, "    -g filename     Output collected data to gnuplot 
format file.\n");
     fprintf(stderr, "    -e filename     Output CSV file with percentages 
served\n");
+    fprintf(stderr, "    -h              Display usage information (this 
message)\n");
 #ifdef USE_SSL
-    fprintf(stderr, "    -s              Use httpS instead of HTTP (SSL)\n");
+    fprintf(stderr, "    -Z ciphersuite  Specify SSL/TLS cipher suite (See 
openssl ciphers)\n");
+    fprintf(stderr, "    -f protocol     Specify SSL/TLS protocol (SSL2, SSL3, 
TLS1, or ALL)\n");
 #endif
-    fprintf(stderr, "    -h              Display usage information (this 
message)\n");
     exit(EINVAL);
 }
 
@@ -1867,14 +1808,14 @@
     if (strlen(url) > 7 && strncmp(url, "http://";, 7) == 0) {
         url += 7;
 #ifdef USE_SSL
-        ssl = 0;
+        is_ssl = 0;
 #endif
     }
     else
 #ifdef USE_SSL
     if (strlen(url) > 8 && strncmp(url, "https://";, 8) == 0) {
         url += 8;
-        ssl = 1;
+        is_ssl = 1;
     }
 #else
     if (strlen(url) > 8 && strncmp(url, "https://";, 8) == 0) {
@@ -1903,7 +1844,7 @@
 
     if (port == 0) {        /* no port specified */
 #ifdef USE_SSL
-        if (ssl == 1)
+        if (is_ssl)
             port = 443;
         else
 #endif
@@ -1912,7 +1853,7 @@
 
     if ((
 #ifdef USE_SSL
-         (ssl == 1) && (port != 443)) || (( ssl == 0 ) && 
+         is_ssl && (port != 443)) || (!is_ssl &&
 #endif
          (port != 80)))
     {
@@ -1968,6 +1909,9 @@
     apr_getopt_t *opt;
     const char *optarg;
     char c;
+#ifdef USE_SSL
+    SSL_METHOD *meth = SSLv23_client_method();
+#endif
 
     /* table defaults  */
     tablestring = "";
@@ -2003,18 +1947,10 @@
     apr_getopt_init(&opt, cntxt, argc, argv);
     while ((status = apr_getopt(opt, "n:c:t:T:p:v:kVhwix:y:z:C:H:P:A:g:X:de:Sq"
 #ifdef USE_SSL
-            "s"
+            "Z:f:"
 #endif
             ,&c, &optarg)) == APR_SUCCESS) {
         switch (c) {
-            case 's':
-#ifdef USE_SSL
-                ssl = 1;
-                break;
-#else
-                fprintf(stderr, "SSL not compiled in; no https support\n");
-                exit(1);
-#endif
             case 'n':
                 requests = atoi(optarg);
                 if (!requests) {
@@ -2145,6 +2081,22 @@
             case 'V':
                 copyright();
                 return 0;
+#ifdef USE_SSL
+           case 'Z':
+               ssl_cipher = strdup(optarg);
+               break;
+           case 'f':
+               if (strncasecmp(optarg, "ALL", 3) == 0) {
+                   meth = SSLv23_client_method();
+               } else if (strncasecmp(optarg, "SSL2", 4) == 0) {
+                   meth = SSLv2_client_method();
+               } else if (strncasecmp(optarg, "SSL3", 4) == 0) {
+                   meth = SSLv3_client_method();
+               } else if (strncasecmp(optarg, "TLS1", 4) == 0) {
+                   meth = TLSv1_client_method();
+               }
+               break;
+#endif
         }
     }
 
@@ -2190,16 +2142,22 @@
     bio_out=BIO_new_fp(stdout,BIO_NOCLOSE);
     bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
 
-    /* TODO: Allow force SSLv2_client_method() (TLSv1?) */
-    if (!(ctx = SSL_CTX_new(SSLv23_client_method()))) {
-        fprintf(stderr, "Could not init SSL CTX");
+    if (!(ssl_ctx = SSL_CTX_new(meth))) {
+        BIO_printf(bio_err, "Could not initialize SSL Context.\n");
+        ERR_print_errors(bio_err);
+        exit(1);
+    }
+    SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
+    if (ssl_cipher != NULL) {
+       if (!SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher)) {
+           fprintf(stderr, "error setting cipher list [%s]\n", ssl_cipher);
         ERR_print_errors_fp(stderr);
         exit(1);
     }
-    SSL_CTX_set_options(ctx, SSL_OP_ALL);
-#ifdef USE_THREADS
-    ssl_util_thread_setup(cntxt);
-#endif
+    }
+    if (verbosity >= 3) {
+       SSL_CTX_set_info_callback(ssl_ctx, ssl_state_cb);
+    }
 #endif
 #ifdef SIGPIPE
     apr_signal(SIGPIPE, SIG_IGN);       /* Ignore writes to connections that

Reply via email to