Added a more extensive SSL sandbox.

After running `make examples`, if SSL is enabled, you
can quickly test HTTPS, with optional client-based
certificate authentication using the following process within
the build directory:

```
./examples/https/bin/generate.sh

-- Test without client auth

./examples/example_https              \
  -cert examples/https/server-crt.pem \
  -key  examples/https/server-key.pem

curl -vk https://localhost:4443/

-- Test WITH client auth

./examples/example_https              \
  -cert examples/https/server-crt.pem \
  -key  examples/https/server-key.pem \
  -ca   examples/https/ca-crt.pem     \
  -verify-peer                        \
  -verify-depth 2                     \
  -enforce-peer-cert

curl -kv \
  --key  examples/https/client1-key.pem \
  --cert examples/https/client1-crt.pem \
  https://localhost:4443/

```
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 76ad4d0..31c3b8b 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -8,6 +8,7 @@
 add_executable(test_perf EXCLUDE_FROM_ALL test_perf.c)
 add_executable(example_vhost EXCLUDE_FROM_ALL example_vhost.c)
 add_executable(example_pause EXCLUDE_FROM_ALL example_pause.c)
+add_executable(example_https EXCLUDE_FROM_ALL https/example_https.c)
 
 if (NOT EVHTP_DISABLE_EVTHR)
 	add_executable(test_proxy EXCLUDE_FROM_ALL test_proxy.c)
@@ -23,7 +24,16 @@
 target_link_libraries(test_perf    evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
 target_link_libraries(example_vhost evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
 target_link_libraries(example_pause evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
+target_link_libraries(example_https evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
 
-add_dependencies(examples example_pause example_vhost test_extensive test_basic test_vhost test_client test_query test_perf)
+add_dependencies(examples example_https example_pause example_vhost test_extensive test_basic test_vhost test_client test_query test_perf)
 
+file (COPY
+    https/etc/ca.cnf
+    https/etc/client1.cnf
+    https/etc/client2.cnf
+    https/etc/server.cnf
+    DESTINATION
+    https/etc/)
 
+configure_file(https/bin/generate.sh.in https/bin/generate.sh @ONLY)
diff --git a/examples/https/bin/generate.sh.in b/examples/https/bin/generate.sh.in
new file mode 100755
index 0000000..6f78154
--- /dev/null
+++ b/examples/https/bin/generate.sh.in
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+
+CONFIG_DIR="@PROJECT_BINARY_DIR@/examples/https"
+
+# Create new CA
+openssl req -new -x509 -days 9999    \
+    -config "$CONFIG_DIR/etc/ca.cnf" \
+    -keyout "$CONFIG_DIR/ca-key.pem" \
+    -out    "$CONFIG_DIR/ca-crt.pem"
+
+# Generate private key for server
+openssl genrsa -out "$CONFIG_DIR/server-key.pem" 4096
+
+# Generate cert signing request
+openssl req -new \
+    -config "$CONFIG_DIR/etc/server.cnf" \
+    -key    "$CONFIG_DIR/server-key.pem" \
+    -out    "$CONFIG_DIR/server-csr.pem"
+
+# Sign the request
+openssl x509 -req                         \
+    -extfile "$CONFIG_DIR/etc/server.cnf" \
+    -days 999                             \
+    -passin "pass:password"               \
+    -in "$CONFIG_DIR/server-csr.pem"      \
+    -CA "$CONFIG_DIR/ca-crt.pem"          \
+    -CAkey "$CONFIG_DIR/ca-key.pem"       \
+    -CAcreateserial                       \
+    -out "$CONFIG_DIR/server-crt.pem"
+
+# Generate a few client certs
+openssl genrsa -out "$CONFIG_DIR/client1-key.pem" 4096
+openssl genrsa -out "$CONFIG_DIR/client2-key.pem" 4096
+
+# create two cert sign requests
+openssl req -new -config "$CONFIG_DIR/etc/client1.cnf" -key $CONFIG_DIR/client1-key.pem -out $CONFIG_DIR/client1-csr.pem
+openssl req -new -config $CONFIG_DIR/etc/client2.cnf -key $CONFIG_DIR/client2-key.pem -out $CONFIG_DIR/client2-csr.pem
+
+# sign the above client certs
+openssl x509 -req            \
+    -extfile $CONFIG_DIR/etc/client1.cnf \
+    -days 999                \
+    -passin "pass:password"  \
+    -in $CONFIG_DIR/client1-csr.pem      \
+    -CA $CONFIG_DIR/ca-crt.pem           \
+    -CAkey $CONFIG_DIR/ca-key.pem        \
+    -CAcreateserial          \
+    -out $CONFIG_DIR/client1-crt.pem
+
+openssl x509 -req            \
+    -extfile $CONFIG_DIR/etc/client2.cnf \
+    -days 999                \
+    -passin "pass:password"  \
+    -in $CONFIG_DIR/client2-csr.pem      \
+    -CA $CONFIG_DIR/ca-crt.pem           \
+    -CAkey $CONFIG_DIR/ca-key.pem        \
+    -CAcreateserial          \
+    -out $CONFIG_DIR/client2-crt.pem
diff --git a/examples/https/etc/ca.cnf b/examples/https/etc/ca.cnf
new file mode 100644
index 0000000..53eab64
--- /dev/null
+++ b/examples/https/etc/ca.cnf
@@ -0,0 +1,31 @@
+[ ca ]
+default_ca      = CA_default
+
+[ CA_default ]
+serial = ca-serial
+crl = ca-crl.pem
+database = ca-database.txt
+name_opt = CA_default
+cert_opt = CA_default
+default_crl_days = 9999
+default_md = md5
+
+[ req ]
+default_bits           = 4096
+days                   = 9999
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+output_password        = password
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = MA
+L                      = Boston
+O                      = Critical Stack
+OU                     = evhtp
+CN                     = ca
+emailAddress           = nate@cl0d.com
+
+[ req_attributes ]
+challengePassword      = test
diff --git a/examples/https/etc/client1.cnf b/examples/https/etc/client1.cnf
new file mode 100644
index 0000000..6e881ff
--- /dev/null
+++ b/examples/https/etc/client1.cnf
@@ -0,0 +1,26 @@
+[ req ]
+default_bits           = 4096
+days                   = 9999
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+x509_extensions        = v3_ca
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = MA
+L                      = Boston
+O                      = Critical Stack
+OU                     = evhtp
+CN                     = client1
+emailAddress           = nate@cl0d.com
+
+[ req_attributes ]
+challengePassword      = password
+
+[ v3_ca ]
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+OCSP;URI.0 = http://ocsp.example.com/
+caIssuers;URI.0 = http://example.com/ca.cert
diff --git a/examples/https/etc/client2.cnf b/examples/https/etc/client2.cnf
new file mode 100644
index 0000000..2cbf570
--- /dev/null
+++ b/examples/https/etc/client2.cnf
@@ -0,0 +1,26 @@
+[ req ]
+default_bits           = 4096
+days                   = 9999
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+x509_extensions        = v3_ca
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = MA
+L                      = Boston
+O                      = Critical Stack
+OU                     = evhtp
+CN                     = client2
+emailAddress           = nate@cl0d.com
+
+[ req_attributes ]
+challengePassword      = password
+
+[ v3_ca ]
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+OCSP;URI.0 = http://ocsp.example.com/
+caIssuers;URI.0 = http://example.com/ca.cert
diff --git a/examples/https/etc/server.cnf b/examples/https/etc/server.cnf
new file mode 100644
index 0000000..2c36ee4
--- /dev/null
+++ b/examples/https/etc/server.cnf
@@ -0,0 +1,26 @@
+[ req ]
+default_bits           = 4096
+days                   = 9999
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+x509_extensions        = v3_ca
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = MA
+L                      = Boston
+O                      = Critical Stack
+OU                     = evhtp
+CN                     = localhost
+emailAddress           = nate@cl0d.com
+
+[ req_attributes ]
+challengePassword      = password
+
+[ v3_ca ]
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+OCSP;URI.0 = http://ocsp.example.com/
+caIssuers;URI.0 = http://example.com/ca.cert
diff --git a/examples/https/example_https.c b/examples/https/example_https.c
new file mode 100644
index 0000000..f39105b
--- /dev/null
+++ b/examples/https/example_https.c
@@ -0,0 +1,256 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "../log.h"
+#include "internal.h"
+#include "evhtp/evhtp.h"
+
+static void
+http__callback_(evhtp_request_t * req, void * arg) {
+    return evhtp_send_reply(req, EVHTP_RES_OK);
+}
+
+static int
+ssl__x509_verify_(int ok, X509_STORE_CTX * store) {
+    char                 buf[256];
+    X509               * err_cert;
+    int                  err;
+    int                  depth;
+    SSL                * ssl;
+    evhtp_connection_t * connection;
+    evhtp_ssl_cfg_t    * ssl_cfg;
+
+    err_cert   = X509_STORE_CTX_get_current_cert(store);
+    err        = X509_STORE_CTX_get_error(store);
+    depth      = X509_STORE_CTX_get_error_depth(store);
+    ssl        = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());
+
+    X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
+
+    connection = SSL_get_app_data(ssl);
+    ssl_cfg    = connection->htp->ssl_cfg;
+
+    if (depth > ssl_cfg->verify_depth) {
+        ok  = 0;
+        err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+
+        X509_STORE_CTX_set_error(store, err);
+    }
+
+    if (!ok) {
+        log_error("SSL: verify error:num=%d:%s:depth=%d:%s", err,
+                  X509_verify_cert_error_string(err), depth, buf);
+    }
+
+    return ok;
+}
+
+enum {
+    OPTARG_CERT = 1000,
+    OPTARG_KEY,
+    OPTARG_CA,
+    OPTARG_CAPATH,
+    OPTARG_CIPHERS,
+    OPTARG_VERIFY_PEER,
+    OPTARG_ENFORCE_PEER_CERT,
+    OPTARG_VERIFY_DEPTH,
+    OPTARG_ENABLE_CACHE,
+    OPTARG_CACHE_TIMEOUT,
+    OPTARG_CACHE_SIZE,
+    OPTARG_CTX_TIMEOUT,
+    OPTARG_ENABLE_PROTOCOL,
+    OPTARG_DISABLE_PROTOCOL
+};
+
+static const char * help =
+    "Usage %s [opts] <host>:<port>\n"
+    "  -cert          <file> : Server PEM-encoded X.509 Certificate file\n"
+    "  -key           <file> : Server PEM-encoded Private Key file\n"
+    "  -ca            <file> : File of PEM-encoded Server CA Certificates\n"
+    "  -capath        <path> : Directory of PEM-encoded CA Certificates for Client Auth\n"
+    "  -ciphers        <str> : Accepted SSL Ciphers\n"
+    "  -verify-peer          : Enable SSL client verification\n"
+    "  -enforce-peer-cert    : Reject clients without a cert\n"
+    "  -verify-depth     <n> : Maximum depth of CA Certificates in Client Certificate verification\n"
+    "  -enable-protocol  <p> : Enable one of the following protocols: SSLv2, SSLv3, TLSv1, or ALL\n"
+    "  -disable-protocol <p> : Disable one of the following protocols: SSLv2, SSLv3, TLSv1, or ALL\n"
+    "  -ctx-timeout      <n> : SSL Session Timeout (SSL >= 1.0)\n";
+
+evhtp_ssl_cfg_t *
+parse__ssl_opts_(int argc, char ** argv) {
+    int               opt               = 0;
+    int               long_index        = 0;
+    int               ssl_verify_mode   = 0;
+    struct stat       f_stat;
+    evhtp_ssl_cfg_t * ssl_config        = calloc(1, sizeof(evhtp_ssl_cfg_t));
+
+
+    ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
+
+    static struct option long_options[] = {
+        { "cert",              required_argument, 0, OPTARG_CERT              },
+        { "key",               required_argument, 0, OPTARG_KEY               },
+        { "ca",                required_argument, 0, OPTARG_CA                },
+        { "capath",            required_argument, 0, OPTARG_CAPATH            },
+        { "ciphers",           required_argument, 0, OPTARG_CIPHERS           },
+        { "verify-peer",       no_argument,       0, OPTARG_VERIFY_PEER       },
+        { "enforce-peer-cert", no_argument,       0, OPTARG_ENFORCE_PEER_CERT },
+        { "verify-depth",      required_argument, 0, OPTARG_VERIFY_DEPTH      },
+        { "enable-cache",      no_argument,       0, OPTARG_ENABLE_CACHE      },
+        { "cache-timeout",     required_argument, 0, OPTARG_CACHE_TIMEOUT     },
+        { "cache-size",        required_argument, 0, OPTARG_CACHE_SIZE        },
+        { "enable-protocol",   required_argument, 0, OPTARG_ENABLE_PROTOCOL   },
+        { "disable-protocol",  required_argument, 0, OPTARG_DISABLE_PROTOCOL  },
+        { "ctx-timeout",       required_argument, 0, OPTARG_CTX_TIMEOUT       },
+        { "help",              no_argument,       0, 'h'                      },
+        { NULL,                0,                 0, 0                        }
+    };
+
+    while ((opt = getopt_long_only(argc, argv, "", long_options, &long_index)) != -1) {
+        switch (opt) {
+            case 'h':
+                printf(help, argv[0]);
+                exit(EXIT_FAILURE);
+            case OPTARG_CERT:
+                ssl_config->pemfile         = strdup(optarg);
+                break;
+            case OPTARG_KEY:
+                ssl_config->privfile        = strdup(optarg);
+                break;
+            case OPTARG_CA:
+                ssl_config->cafile          = strdup(optarg);
+                break;
+            case OPTARG_CAPATH:
+                ssl_config->capath          = strdup(optarg);
+                break;
+            case OPTARG_CIPHERS:
+                ssl_config->ciphers         = strdup(optarg);
+                break;
+            case OPTARG_VERIFY_DEPTH:
+                ssl_config->verify_depth = atoi(optarg);
+                break;
+            case OPTARG_VERIFY_PEER:
+                ssl_verify_mode            |= SSL_VERIFY_PEER;
+                break;
+            case OPTARG_ENFORCE_PEER_CERT:
+                ssl_verify_mode            |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+                break;
+            case OPTARG_ENABLE_CACHE:
+                ssl_config->scache_type     = evhtp_ssl_scache_type_internal;
+                break;
+            case OPTARG_CACHE_TIMEOUT:
+                ssl_config->scache_timeout  = atoi(optarg);
+                break;
+            case OPTARG_CACHE_SIZE:
+                ssl_config->scache_size     = atoi(optarg);
+                break;
+            case OPTARG_CTX_TIMEOUT:
+                ssl_config->ssl_ctx_timeout = atoi(optarg);
+                break;
+            case OPTARG_ENABLE_PROTOCOL:
+                if (!strcasecmp(optarg, "SSLv2")) {
+                    ssl_config->ssl_opts &= ~SSL_OP_NO_SSLv2;
+                } else if (!strcasecmp(optarg, "SSLv3")) {
+                    ssl_config->ssl_opts &= ~SSL_OP_NO_SSLv3;
+                } else if (!strcasecmp(optarg, "TLSv1")) {
+                    ssl_config->ssl_opts &= ~SSL_OP_NO_TLSv1;
+                } else if (!strcasecmp(optarg, "ALL")) {
+                    ssl_config->ssl_opts = 0;
+                }
+
+                break;
+            case OPTARG_DISABLE_PROTOCOL:
+                if (!strcasecmp(optarg, "SSLv2")) {
+                    ssl_config->ssl_opts |= SSL_OP_NO_SSLv2;
+                } else if (!strcasecmp(optarg, "SSLv3")) {
+                    ssl_config->ssl_opts |= SSL_OP_NO_SSLv3;
+                } else if (!strcasecmp(optarg, "TLSv1")) {
+                    ssl_config->ssl_opts |= SSL_OP_NO_TLSv1;
+                } else if (!strcasecmp(optarg, "ALL")) {
+                    ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
+                }
+                break;
+
+            default:
+                break;
+        } /* switch */
+    }
+
+    if (ssl_verify_mode != 0) {
+        ssl_config->verify_peer    = ssl_verify_mode;
+        ssl_config->x509_verify_cb = ssl__x509_verify_;
+    }
+
+
+    if (ssl_config->pemfile) {
+        if (stat(ssl_config->pemfile, &f_stat) != 0) {
+            log_error("Cannot load SSL cert '%s' (%s)", ssl_config->pemfile, strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    if (ssl_config->privfile) {
+        if (stat(ssl_config->privfile, &f_stat) != 0) {
+            log_error("Cannot load SSL key '%s' (%s)", ssl_config->privfile, strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    if (ssl_config->cafile) {
+        if (stat(ssl_config->cafile, &f_stat) != 0) {
+            log_error("Cannot find SSL CA File '%s' (%s)", ssl_config->cafile, strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    if (ssl_config->capath) {
+        if (stat(ssl_config->capath, &f_stat) != 0) {
+            log_error("Cannot find SSL CA PATH '%s' (%s)", ssl_config->capath, strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    return ssl_config;
+} /* parse__ssl_opts_ */
+
+int
+main(int argc, char ** argv) {
+    evhtp_t           * htp;
+    struct event_base * evbase;
+
+    evbase = event_base_new();
+    evhtp_alloc_assert(evbase);
+
+    htp    = evhtp_new(evbase, NULL);
+    evhtp_alloc_assert(htp);
+
+    evhtp_ssl_init(htp, parse__ssl_opts_(argc, argv));
+    evhtp_set_gencb(htp, http__callback_, NULL);
+
+    evhtp_bind_socket(htp, "127.0.0.1", 4443, 128);
+    {
+        struct sockaddr_in sin;
+        socklen_t          len = sizeof(struct sockaddr);
+        uint16_t           port;
+
+        getsockname(
+            evconnlistener_get_fd(htp->server),
+            (struct sockaddr *)&sin, &len);
+
+        port = ntohs(sin.sin_port);
+
+        log_info("curl https://127.0.0.1:%d/", port);
+    }
+
+    event_base_loop(evbase, 0);
+
+
+    return 0;
+}