ISSUE 43: Add BIO_sock_shutdown
[openssl.git] / apps / s_server.c
index a1fcb6e..99442cd 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <openssl/async.h>
 
 #include <openssl/e_os2.h>
 
@@ -184,18 +185,10 @@ typedef unsigned int u_int;
 #include "s_apps.h"
 #include "timeouts.h"
 
-#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000)
-/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */
-# undef FIONBIO
-#endif
-
-#ifndef OPENSSL_NO_RSA
-static RSA *tmp_rsa_cb(SSL *s, int is_export, int keylength);
-#endif
 static int not_resumable_sess_cb(SSL *s, int is_forward_secure);
-static int sv_body(char *hostname, int s, int stype, unsigned char *context);
-static int www_body(char *hostname, int s, int stype, unsigned char *context);
-static int rev_body(char *hostname, int s, int stype, unsigned char *context);
+static int sv_body(int s, int stype, unsigned char *context);
+static int www_body(int s, int stype, unsigned char *context);
+static int rev_body(int s, int stype, unsigned char *context);
 static void close_accept_socket(void);
 static int init_ssl_connection(SSL *s);
 static void print_stats(BIO *bp, SSL_CTX *ctx);
@@ -228,11 +221,9 @@ static const char *s_cert_file = TEST_CERT, *s_key_file =
 
 static const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL;
 static char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL;
-#ifdef FIONBIO
 static int s_nbio = 0;
-#endif
 static int s_nbio_test = 0;
-int s_crlf = 0;
+static int s_crlf = 0;
 static SSL_CTX *ctx = NULL;
 static SSL_CTX *ctx2 = NULL;
 static int www = 0;
@@ -252,16 +243,19 @@ static int s_brief = 0;
 static char *keymatexportlabel = NULL;
 static int keymatexportlen = 20;
 
+static int async = 0;
+
 #ifndef OPENSSL_NO_ENGINE
 static char *engine_id = NULL;
 #endif
 static const char *session_id_prefix = NULL;
 
+#ifndef OPENSSL_NO_DTLS
 static int enable_timeouts = 0;
 static long socket_mtu;
-#ifndef OPENSSL_NO_DTLS1
 static int cert_chain = 0;
 #endif
+static int dtlslisten = 0;
 
 static BIO *serverinfo_in = NULL;
 static const char *s_serverinfo_file = NULL;
@@ -351,6 +345,8 @@ typedef struct srpsrvparm_st {
 static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
 {
     srpsrvparm *p = (srpsrvparm *) arg;
+    int ret = SSL3_AL_FATAL;
+
     if (p->login == NULL && p->user == NULL) {
         p->login = SSL_get_srp_username(s);
         BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
@@ -359,21 +355,25 @@ static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
 
     if (p->user == NULL) {
         BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
-        return SSL3_AL_FATAL;
+        goto err;
     }
+
     if (SSL_set_srp_server_param
         (s, p->user->N, p->user->g, p->user->s, p->user->v,
          p->user->info) < 0) {
         *ad = SSL_AD_INTERNAL_ERROR;
-        return SSL3_AL_FATAL;
+        goto err;
     }
     BIO_printf(bio_err,
                "SRP parameters set: username = \"%s\" info=\"%s\" \n",
                p->login, p->user->info);
-    /* need to check whether there are memory leaks */
+    ret = SSL_ERROR_NONE;
+
+err:
+    SRP_user_pwd_free(p->user);
     p->user = NULL;
     p->login = NULL;
-    return SSL_ERROR_NONE;
+    return ret;
 }
 
 #endif
@@ -401,6 +401,7 @@ static void s_server_init(void)
     s_msg = 0;
     s_quiet = 0;
     s_brief = 0;
+    async = 0;
 #ifndef OPENSSL_NO_ENGINE
     engine_id = NULL;
 #endif
@@ -666,7 +667,7 @@ static int cert_status_cb(SSL *s, void *arg)
         goto done;
     }
     req = OCSP_REQUEST_new();
-    if (!req)
+    if (req == NULL)
         goto err;
     id = OCSP_cert_to_id(NULL, x, obj.data.x509);
     X509_free(obj.data.x509);
@@ -780,7 +781,6 @@ static int not_resumable_sess_cb(SSL *s, int is_forward_secure)
     return is_forward_secure;
 }
 
-static char *jpake_secret = NULL;
 #ifndef OPENSSL_NO_SRP
 static srpsrvparm srp_callback_parm;
 #endif
@@ -789,27 +789,27 @@ static char *srtp_profiles = NULL;
 #endif
 
 typedef enum OPTION_choice {
-    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_ENGINE, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT,
+    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE,
+    OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT,
     OPT_VERIFY, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL,
     OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM,
     OPT_PASS, OPT_CERT_CHAIN, OPT_DHPARAM, OPT_DCERTFORM, OPT_DCERT,
     OPT_DKEYFORM, OPT_DPASS, OPT_DKEY, OPT_DCERT_CHAIN, OPT_NOCERT,
-    OPT_CAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE,
+    OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE,
     OPT_EXT_CACHE, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET,
-    OPT_BUILD_CHAIN, OPT_CAFILE, OPT_CHAINCAFILE, OPT_VERIFYCAFILE,
-    OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF, OPT_DEBUG,
-    OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE, OPT_STATUS_TIMEOUT,
-    OPT_STATUS_URL, OPT_MSG, OPT_MSGFILE, OPT_TRACE, OPT_SECURITY_DEBUG,
-    OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE, OPT_CRLF, OPT_QUIET,
-    OPT_BRIEF, OPT_NO_TMP_RSA, OPT_NO_DHE, OPT_NO_ECDHE,
+    OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE,
+    OPT_VERIFYCAFILE, OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF,
+    OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE,
+    OPT_STATUS_TIMEOUT, OPT_STATUS_URL, OPT_MSG, OPT_MSGFILE, OPT_TRACE,
+    OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE, OPT_CRLF,
+    OPT_QUIET, OPT_BRIEF, OPT_NO_DHE,
     OPT_NO_RESUME_EPHEMERAL, OPT_PSK_HINT, OPT_PSK, OPT_SRPVFILE,
-    OPT_SRPUSERSEED, OPT_REV, OPT_WWW, OPT_UPPER_WWW, OPT_HTTP,
-    OPT_SSL3,
+    OPT_SRPUSERSEED, OPT_REV, OPT_WWW, OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC,
+    OPT_SSL_CONFIG, OPT_SSL3,
     OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
-    OPT_DTLS1_2, OPT_TIMEOUT, OPT_MTU, OPT_CHAIN,
+    OPT_DTLS1_2, OPT_TIMEOUT, OPT_MTU, OPT_CHAIN, OPT_LISTEN,
     OPT_ID_PREFIX, OPT_RAND, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
-    OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, OPT_JPAKE,
+    OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
     OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
     OPT_S_ENUM,
     OPT_V_ENUM,
@@ -818,11 +818,18 @@ typedef enum OPTION_choice {
 
 OPTIONS s_server_options[] = {
     {"help", OPT_HELP, '-', "Display this summary"},
-    {"port", OPT_PORT, 'p'},
-    {"accept", OPT_PORT, 'p',
-     "TCP/IP port to accept on (default is " PORT_STR ")"},
+    {"port", OPT_PORT, 'p',
+     "TCP/IP port to listen on for connections (default is " PORT ")"},
+    {"accept", OPT_ACCEPT, 's',
+     "TCP/IP optional host and port to accept on (default is " PORT ")"},
+#ifdef AF_UNIX
     {"unix", OPT_UNIX, 's', "Unix domain socket to accept on"},
+#endif
+    {"4", OPT_4, '-', "Use IPv4 only"},
+    {"6", OPT_6, '-', "Use IPv6 only"},
+#ifdef AF_UNIX
     {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"},
+#endif
     {"context", OPT_CONTEXT, 's', "Set session ID context"},
     {"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"},
     {"Verify", OPT_UPPER_V_VERIFY, 'n',
@@ -851,16 +858,17 @@ OPTIONS s_server_options[] = {
     {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"},
     {"debug", OPT_DEBUG, '-', "Print more output"},
     {"msg", OPT_MSG, '-', "Show protocol messages"},
-    {"msgfile", OPT_MSGFILE, '>'},
+    {"msgfile", OPT_MSGFILE, '>',
+     "File to send output of -msg or -trace, instead of stdout"},
     {"state", OPT_STATE, '-', "Print the SSL states"},
-    {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
     {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
+    {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
+    {"no-CAfile", OPT_NOCAFILE, '-',
+     "Do not load the default certificates file"},
+    {"no-CApath", OPT_NOCAPATH, '-',
+     "Do not load certificates from the default certificates directory"},
     {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"},
     {"quiet", OPT_QUIET, '-', "No server output"},
-    {"no_tmp_rsa", OPT_NO_TMP_RSA, '-', "Do not generate a tmp RSA key"},
-    {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"},
-    {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"},
-    {"tls1", OPT_TLS1, '-', "Just talk TLSv1"},
     {"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-',
      "Disable caching and tickets if ephemeral (EC)DH is used"},
     {"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"},
@@ -884,43 +892,59 @@ OPTIONS s_server_options[] = {
      "Export keying material using label"},
     {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
      "Export len bytes of keying material (default 20)"},
-    {"CRL", OPT_CRL, '<'},
-    {"crl_download", OPT_CRL_DOWNLOAD, '-'},
-    {"cert_chain", OPT_CERT_CHAIN, '<'},
-    {"dcert_chain", OPT_DCERT_CHAIN, '<'},
-    {"chainCApath", OPT_CHAINCAPATH, '/'},
-    {"verifyCApath", OPT_VERIFYCAPATH, '/'},
-    {"no_cache", OPT_NO_CACHE, '-'},
-    {"ext_cache", OPT_EXT_CACHE, '-'},
-    {"CRLform", OPT_CRLFORM, 'F'},
-    {"verify_return_error", OPT_VERIFY_RET_ERROR, '-'},
-    {"verify_quiet", OPT_VERIFY_QUIET, '-'},
-    {"build_chain", OPT_BUILD_CHAIN, '-'},
-    {"chainCAfile", OPT_CHAINCAFILE, '<'},
-    {"verifyCAfile", OPT_VERIFYCAFILE, '<'},
-    {"ign_eof", OPT_IGN_EOF, '-'},
-    {"no_ign_eof", OPT_NO_IGN_EOF, '-'},
-    {"status", OPT_STATUS, '-'},
-    {"status_verbose", OPT_STATUS_VERBOSE, '-'},
-    {"status_timeout", OPT_STATUS_TIMEOUT, 'n'},
-    {"status_url", OPT_STATUS_URL, 's'},
-    {"trace", OPT_TRACE, '-'},
-    {"security_debug", OPT_SECURITY_DEBUG, '-'},
-    {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-'},
-    {"brief", OPT_BRIEF, '-'},
-    {"rev", OPT_REV, '-'},
+    {"CRL", OPT_CRL, '<', "CRL file to use"},
+    {"crl_download", OPT_CRL_DOWNLOAD, '-',
+     "Download CRL from distribution points"},
+    {"cert_chain", OPT_CERT_CHAIN, '<',
+     "certificate chain file in PEM format"},
+    {"dcert_chain", OPT_DCERT_CHAIN, '<',
+     "second certificate chain file in PEM format"},
+    {"chainCApath", OPT_CHAINCAPATH, '/',
+     "use dir as certificate store path to build CA certificate chain"},
+    {"verifyCApath", OPT_VERIFYCAPATH, '/',
+     "use dir as certificate store path to verify CA certificate"},
+    {"no_cache", OPT_NO_CACHE, '-', "Disable session cache"},
+    {"ext_cache", OPT_EXT_CACHE, '-',
+     "Disable internal cache, setup and use external cache"},
+    {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default" },
+    {"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
+     "Close connection on verification error"},
+    {"verify_quiet", OPT_VERIFY_QUIET, '-',
+     "No verify output except verify errors"},
+    {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"},
+    {"chainCAfile", OPT_CHAINCAFILE, '<',
+     "CA file for certificate chain (PEM format)"},
+    {"verifyCAfile", OPT_VERIFYCAFILE, '<',
+     "CA file for certificate verification (PEM format)"},
+    {"ign_eof", OPT_IGN_EOF, '-', "ignore input eof (default when -quiet)"},
+    {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input eof"},
+    {"status", OPT_STATUS, '-', "Request certificate status from server"},
+    {"status_verbose", OPT_STATUS_VERBOSE, '-',
+     "Print more output in certificate status callback"},
+    {"status_timeout", OPT_STATUS_TIMEOUT, 'n',
+     "Status request responder timeout"},
+    {"status_url", OPT_STATUS_URL, 's', "Status request fallback URL"},
+#ifndef OPENSSL_NO_SSL_TRACE
+    {"trace", OPT_TRACE, '-', "trace protocol messages"},
+#endif
+    {"security_debug", OPT_SECURITY_DEBUG, '-',
+     "Print output from SSL/TLS security framework"},
+    {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
+     "Print more output from SSL/TLS security framework"},
+    {"brief", OPT_BRIEF, '-', \
+     "Restrict output to brief summary of connection parameters"},
+    {"rev", OPT_REV, '-',
+     "act as a simple test server which just sends back with the received text reversed"},
+    {"async", OPT_ASYNC, '-', "Operate in asynchronous mode"},
+    {"ssl_config", OPT_SSL_CONFIG, 's', \
+     "Configure SSL_CTX using the configuration 'val'"},
     OPT_S_OPTIONS,
     OPT_V_OPTIONS,
     OPT_X_OPTIONS,
-#ifdef FIONBIO
     {"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
-#endif
 #ifndef OPENSSL_NO_PSK
     {"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"},
     {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"},
-# ifndef OPENSSL_NO_JPAKE
-    {"jpake", OPT_JPAKE, 's', "JPAKE secret to use"},
-# endif
 #endif
 #ifndef OPENSSL_NO_SRP
     {"srpvfile", OPT_SRPVFILE, '<', "The verifier file for SRP"},
@@ -930,32 +954,44 @@ OPTIONS s_server_options[] = {
 #ifndef OPENSSL_NO_SSL3
     {"ssl3", OPT_SSL3, '-', "Just talk SSLv3"},
 #endif
-#ifndef OPENSSL_NO_DTLS1
-    {"dtls", OPT_DTLS, '-'},
-    {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"},
-    {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"},
+#ifndef OPENSSL_NO_TLS1
+    {"tls1", OPT_TLS1, '-', "Just talk TLSv1"},
+#endif
+#ifndef OPENSSL_NO_TLS1_1
+    {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"},
+#endif
+#ifndef OPENSSL_NO_TLS1_2
+    {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"},
+#endif
+#ifndef OPENSSL_NO_DTLS
+    {"dtls", OPT_DTLS, '-', "Use any DTLS version"},
     {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"},
     {"mtu", OPT_MTU, 'p', "Set link layer MTU"},
     {"chain", OPT_CHAIN, '-', "Read a certificate chain"},
+    {"listen", OPT_LISTEN, '-',
+     "Listen for a DTLS ClientHello with a cookie and then connect"},
+#endif
+#ifndef OPENSSL_NO_DTLS1
+    {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"},
+#endif
+#ifndef OPENSSL_NO_DTLS1_2
+    {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"},
 #endif
 #ifndef OPENSSL_NO_DH
     {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
 #endif
-#ifndef OPENSSL_NO_EC
-    {"no_ecdhe", OPT_NO_ECDHE, '-', "Disable ephemeral ECDH"},
-#endif
 #ifndef OPENSSL_NO_NEXTPROTONEG
     {"nextprotoneg", OPT_NEXTPROTONEG, 's',
      "Set the advertised protocols for the NPN extension (comma-separated list)"},
 #endif
 #ifndef OPENSSL_NO_SRTP
-    {"use_srtp", OPT_SRTP_PROFILES, '<',
+    {"use_srtp", OPT_SRTP_PROFILES, 's',
      "Offer SRTP key management with a colon-separated profile list"},
+#endif
     {"alpn", OPT_ALPN, 's',
      "Set the advertised protocols for the ALPN extension (comma-separated list)"},
-#endif
 #ifndef OPENSSL_NO_ENGINE
-    {"engine", OPT_ENGINE, 's'},
+    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
     {NULL}
 };
@@ -973,30 +1009,38 @@ int s_server_main(int argc, char *argv[])
     X509 *s_cert = NULL, *s_dcert = NULL;
     X509_VERIFY_PARAM *vpm = NULL;
     char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL;
-    char *dhfile = NULL, *dpassarg = NULL, *dpass = NULL, *inrand = NULL;
+#ifndef OPENSSL_NO_DH
+    char *dhfile = NULL;
+#endif
+    char *dpassarg = NULL, *dpass = NULL, *inrand = NULL;
     char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
     char *crl_file = NULL, *prog;
 #ifndef OPENSSL_NO_PSK
     char *p;
 #endif
-    const char *unix_path = NULL;
-#ifndef NO_SYS_UN_H
+#ifdef AF_UNIX
     int unlink_unix_path = 0;
 #endif
-    int (*server_cb) (char *hostname, int s, int stype,
-                      unsigned char *context);
+    do_server_cb server_cb;
     int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0;
-    int no_tmp_rsa = 0, no_dhe = 0, no_ecdhe = 0, nocert = 0, ret = 1;
+#ifndef OPENSSL_NO_DH
+    int no_dhe = 0;
+#endif
+    int nocert = 0, ret = 1;
+    int noCApath = 0, noCAfile = 0;
     int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM;
     int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM;
-    int rev = 0, naccept = -1, sdebug = 0, socket_type = SOCK_STREAM;
+    int rev = 0, naccept = -1, sdebug = 0;
+    int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM;
     int state = 0, crl_format = FORMAT_PEM, crl_download = 0;
-    unsigned short port = PORT;
+    char *host = NULL;
+    char *port = BUF_strdup(PORT);
     unsigned char *context = NULL;
     OPTION_CHOICE o;
     EVP_PKEY *s_key2 = NULL;
     X509 *s_cert2 = NULL;
     tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING };
+    const char *ssl_config = NULL;
 #ifndef OPENSSL_NO_NEXTPROTONEG
     const char *next_proto_neg_in = NULL;
     tlsextnextprotoctx next_proto = { NULL, 0 };
@@ -1025,18 +1069,6 @@ int s_server_main(int argc, char *argv[])
     prog = opt_init(argc, argv, s_server_options);
     while ((o = opt_next()) != OPT_EOF) {
         switch (o) {
-#ifdef OPENSSL_NO_PSK
-        case OPT_PSK_HINT:
-        case OPT_PSK:
-#endif
-#ifdef OPENSSL_NO_DTLS1
-        case OPT_DTLS:
-        case OPT_DTLS1:
-        case OPT_DTLS1_2:
-        case OPT_TIMEOUT:
-        case OPT_MTU:
-        case OPT_CHAIN:
-#endif
         case OPT_EOF:
         case OPT_ERR:
  opthelp:
@@ -1047,26 +1079,71 @@ int s_server_main(int argc, char *argv[])
             ret = 0;
             goto end;
 
+        case OPT_4:
+#ifdef AF_UNIX
+            if (socket_family == AF_UNIX) {
+                OPENSSL_free(host); host = NULL;
+                OPENSSL_free(port); port = NULL;
+            }
+#endif
+            socket_family = AF_INET;
+            break;
+        case OPT_6:
+            if (1) {
+#ifdef AF_INET6
+#ifdef AF_UNIX
+                if (socket_family == AF_UNIX) {
+                    OPENSSL_free(host); host = NULL;
+                    OPENSSL_free(port); port = NULL;
+                }
+#endif
+                socket_family = AF_INET6;
+            } else {
+#endif
+                BIO_printf(bio_err, "%s: IPv6 domain sockets unsupported\n", prog);
+                goto end;
+            }
+            break;
         case OPT_PORT:
-            if (!extract_port(opt_arg(), &port))
+#ifdef AF_UNIX
+            if (socket_family == AF_UNIX) {
+                socket_family = AF_UNSPEC;
+            }
+#endif
+            OPENSSL_free(port); port = NULL;
+            OPENSSL_free(host); host = NULL;
+            if (BIO_parse_hostserv(opt_arg(), NULL, &port, BIO_PARSE_PRIO_SERV) < 1) {
+                BIO_printf(bio_err,
+                           "%s: -port argument malformed or ambiguous\n",
+                           port);
                 goto end;
+            }
             break;
-        case OPT_UNIX:
-#ifdef NO_SYS_UN_H
-            BIO_printf(bio_err, "unix domain sockets unsupported\n");
-            goto end;
-#else
-            unix_path = opt_arg();
+        case OPT_ACCEPT:
+#ifdef AF_UNIX
+            if (socket_family == AF_UNIX) {
+                socket_family = AF_UNSPEC;
+            }
 #endif
+            OPENSSL_free(port); port = NULL;
+            OPENSSL_free(host); host = NULL;
+            if (BIO_parse_hostserv(opt_arg(), &host, &port, BIO_PARSE_PRIO_SERV) < 1) {
+                BIO_printf(bio_err,
+                           "%s: -accept argument malformed or ambiguous\n",
+                           port);
+                goto end;
+            }
+            break;
+#ifdef AF_UNIX
+        case OPT_UNIX:
+            socket_family = AF_UNIX;
+            OPENSSL_free(host); host = BUF_strdup(opt_arg());
+            OPENSSL_free(port); port = NULL;
             break;
         case OPT_UNLINK:
-#ifdef NO_SYS_UN_H
-            BIO_printf(bio_err, "unix domain sockets unsupported\n");
-            goto end;
-#else
             unlink_unix_path = 1;
-#endif
             break;
+#endif
         case OPT_NACCEPT:
             naccept = atol(opt_arg());
             break;
@@ -1119,7 +1196,9 @@ int s_server_main(int argc, char *argv[])
             s_chain_file = opt_arg();
             break;
         case OPT_DHPARAM:
+#ifndef OPENSSL_NO_DH
             dhfile = opt_arg();
+#endif
             break;
         case OPT_DCERTFORM:
             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format))
@@ -1147,6 +1226,9 @@ int s_server_main(int argc, char *argv[])
         case OPT_CAPATH:
             CApath = opt_arg();
             break;
+        case OPT_NOCAPATH:
+            noCApath = 1;
+            break;
         case OPT_CHAINCAPATH:
             chCApath = opt_arg();
             break;
@@ -1194,6 +1276,9 @@ int s_server_main(int argc, char *argv[])
         case OPT_CAFILE:
             CAfile = opt_arg();
             break;
+        case OPT_NOCAFILE:
+            noCAfile = 1;
+            break;
         case OPT_CHAINCAFILE:
             chCAfile = opt_arg();
             break;
@@ -1247,9 +1332,8 @@ int s_server_main(int argc, char *argv[])
         case OPT_TRACE:
 #ifndef OPENSSL_NO_SSL_TRACE
             s_msg = 2;
-#else
-            break;
 #endif
+            break;
         case OPT_SECURITY_DEBUG:
             sdebug = 1;
             break;
@@ -1268,49 +1352,41 @@ int s_server_main(int argc, char *argv[])
         case OPT_BRIEF:
             s_quiet = s_brief = verify_quiet = 1;
             break;
-        case OPT_NO_TMP_RSA:
-            no_tmp_rsa = 1;
-            break;
         case OPT_NO_DHE:
+#ifndef OPENSSL_NO_DH
             no_dhe = 1;
-            break;
-        case OPT_NO_ECDHE:
-            no_ecdhe = 1;
+#endif
             break;
         case OPT_NO_RESUME_EPHEMERAL:
             no_resume_ephemeral = 1;
             break;
-#ifndef OPENSSL_NO_PSK
         case OPT_PSK_HINT:
+#ifndef OPENSSL_NO_PSK
             psk_identity_hint = opt_arg();
+#endif
             break;
         case OPT_PSK:
+#ifndef OPENSSL_NO_PSK
             for (p = psk_key = opt_arg(); *p; p++) {
-                if (isxdigit(*p))
+                if (isxdigit(_UC(*p)))
                     continue;
                 BIO_printf(bio_err, "Not a hex number '%s'\n", *argv);
                 goto end;
             }
-            break;
-#else
-        case OPT_PSK_HINT:
-        case OPT_PSK:
-            break;
 #endif
-#ifndef OPENSSL_NO_SRP
+            break;
         case OPT_SRPVFILE:
+#ifndef OPENSSL_NO_SRP
             srp_verifier_file = opt_arg();
             meth = TLSv1_server_method();
+#endif
             break;
         case OPT_SRPUSERSEED:
+#ifndef OPENSSL_NO_SRP
             srpuserseed = opt_arg();
             meth = TLSv1_server_method();
-            break;
-#else
-        case OPT_SRPVFILE:
-        case OPT_SRPUSERSEED:
-            break;
 #endif
+            break;
         case OPT_REV:
             rev = 1;
             break;
@@ -1323,51 +1399,67 @@ int s_server_main(int argc, char *argv[])
         case OPT_HTTP:
             www = 3;
             break;
+        case OPT_SSL_CONFIG:
+            ssl_config = opt_arg();
+            break;
         case OPT_SSL3:
 #ifndef OPENSSL_NO_SSL3
             meth = SSLv3_server_method();
 #endif
             break;
         case OPT_TLS1_2:
+#ifndef OPENSSL_NO_TLS1_2
             meth = TLSv1_2_server_method();
+#endif
             break;
         case OPT_TLS1_1:
+#ifndef OPENSSL_NO_TLS1_1
             meth = TLSv1_1_server_method();
+#endif
             break;
         case OPT_TLS1:
+#ifndef OPENSSL_NO_TLS1
             meth = TLSv1_server_method();
+#endif
             break;
-#ifndef OPENSSL_NO_DTLS1
         case OPT_DTLS:
+#ifndef OPENSSL_NO_DTLS
             meth = DTLS_server_method();
             socket_type = SOCK_DGRAM;
+#endif
             break;
         case OPT_DTLS1:
+#ifndef OPENSSL_NO_DTLS1
             meth = DTLSv1_server_method();
             socket_type = SOCK_DGRAM;
+#endif
             break;
         case OPT_DTLS1_2:
+#ifndef OPENSSL_NO_DTLS1_2
             meth = DTLSv1_2_server_method();
             socket_type = SOCK_DGRAM;
+#endif
             break;
         case OPT_TIMEOUT:
+#ifndef OPENSSL_NO_DTLS
             enable_timeouts = 1;
+#endif
             break;
         case OPT_MTU:
+#ifndef OPENSSL_NO_DTLS
             socket_mtu = atol(opt_arg());
+#endif
             break;
         case OPT_CHAIN:
+#ifndef OPENSSL_NO_DTLS
             cert_chain = 1;
+#endif
             break;
-#else
-        case OPT_DTLS:
-        case OPT_DTLS1:
-        case OPT_DTLS1_2:
-        case OPT_TIMEOUT:
-        case OPT_MTU:
-        case OPT_CHAIN:
-            break;
+        case OPT_LISTEN:
+#ifndef OPENSSL_NO_DTLS
+            dtlslisten = 1;
 #endif
+            break;
         case OPT_ID_PREFIX:
             session_id_prefix = opt_arg();
             break;
@@ -1397,16 +1489,10 @@ int s_server_main(int argc, char *argv[])
         case OPT_ALPN:
             alpn_in = opt_arg();
             break;
-#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK)
-        case OPT_JPAKE:
-            jpake_secret = opt_arg();
-            break;
-#else
-        case OPT_JPAKE:
-            goto opthelp;
-#endif
         case OPT_SRTP_PROFILES:
+#ifndef OPENSSL_NO_SRTP
             srtp_profiles = opt_arg();
+#endif
             break;
         case OPT_KEYMATEXPORT:
             keymatexportlabel = opt_arg();
@@ -1414,31 +1500,32 @@ int s_server_main(int argc, char *argv[])
         case OPT_KEYMATEXPORTLEN:
             keymatexportlen = atoi(opt_arg());
             break;
+        case OPT_ASYNC:
+            async = 1;
+            break;
         }
     }
     argc = opt_num_rest();
     argv = opt_rest();
 
-#ifndef OPENSSL_NO_DTLS1
+#ifndef OPENSSL_NO_DTLS
     if (www && socket_type == SOCK_DGRAM) {
         BIO_printf(bio_err, "Can't use -HTTP, -www or -WWW with DTLS\n");
         goto end;
     }
+
+    if (dtlslisten && socket_type != SOCK_DGRAM) {
+        BIO_printf(bio_err, "Can only use -listen with DTLS\n");
+        goto end;
+    }
 #endif
 
-    if (unix_path && (socket_type != SOCK_STREAM)) {
+#ifdef AF_UNIX
+    if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) {
         BIO_printf(bio_err,
                    "Can't use unix sockets and datagrams together\n");
         goto end;
     }
-#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK)
-    if (jpake_secret) {
-        if (psk_key) {
-            BIO_printf(bio_err, "Can't use JPAKE and PSK together\n");
-            goto end;
-        }
-        psk_identity = "JPAKE";
-    }
 #endif
 
     if (!app_passwd(passarg, dpassarg, &pass, &dpass)) {
@@ -1446,9 +1533,6 @@ int s_server_main(int argc, char *argv[])
         goto end;
     }
 
-    if (!app_load_modules(NULL))
-        goto end;
-
     if (s_key_file == NULL)
         s_key_file = s_cert_file;
 
@@ -1467,16 +1551,15 @@ int s_server_main(int argc, char *argv[])
         }
 
         s_cert = load_cert(s_cert_file, s_cert_format,
-                           NULL, e, "server certificate file");
+                           "server certificate file");
 
         if (!s_cert) {
             ERR_print_errors(bio_err);
             goto end;
         }
         if (s_chain_file) {
-            s_chain = load_certs(s_chain_file, FORMAT_PEM,
-                                 NULL, e, "server certificate chain");
-            if (!s_chain)
+            if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL,
+                            "server certificate chain"))
                 goto end;
         }
 
@@ -1489,7 +1572,7 @@ int s_server_main(int argc, char *argv[])
             }
 
             s_cert2 = load_cert(s_cert_file2, s_cert_format,
-                                NULL, e, "second server certificate file");
+                                "second server certificate file");
 
             if (!s_cert2) {
                 ERR_print_errors(bio_err);
@@ -1547,16 +1630,15 @@ int s_server_main(int argc, char *argv[])
         }
 
         s_dcert = load_cert(s_dcert_file, s_dcert_format,
-                            NULL, e, "second server certificate file");
+                            "second server certificate file");
 
         if (!s_dcert) {
             ERR_print_errors(bio_err);
             goto end;
         }
         if (s_dchain_file) {
-            s_dchain = load_certs(s_dchain_file, FORMAT_PEM,
-                                  NULL, e, "second server certificate chain");
-            if (!s_dchain)
+            if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL,
+                            "second server certificate chain"))
                 goto end;
         }
 
@@ -1575,10 +1657,10 @@ int s_server_main(int argc, char *argv[])
         if (s_quiet && !s_debug) {
             bio_s_out = BIO_new(BIO_s_null());
             if (s_msg && !bio_s_msg)
-                bio_s_msg = dup_bio_out();
+                bio_s_msg = dup_bio_out(FORMAT_TEXT);
         } else {
             if (bio_s_out == NULL)
-                bio_s_out = dup_bio_out();
+                bio_s_out = dup_bio_out(FORMAT_TEXT);
         }
     }
 #if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
@@ -1594,12 +1676,21 @@ int s_server_main(int argc, char *argv[])
     }
 
     ctx = SSL_CTX_new(meth);
+    if (ctx == NULL) {
+        ERR_print_errors(bio_err);
+        goto end;
+    }
     if (sdebug)
         ssl_ctx_security_debug(ctx, sdebug);
-    if (ctx == NULL) {
+    if (ssl_config) {
+        if (SSL_CTX_config(ctx, ssl_config) == 0) {
+            BIO_printf(bio_err, "Error using configuration \"%s\"\n",
+                       ssl_config);
         ERR_print_errors(bio_err);
         goto end;
+        }
     }
+
     if (session_id_prefix) {
         if (strlen(session_id_prefix) >= 32)
             BIO_printf(bio_err,
@@ -1624,6 +1715,10 @@ int s_server_main(int argc, char *argv[])
     else
         SSL_CTX_sess_set_cache_size(ctx, 128);
 
+    if (async) {
+        SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC);
+    }
+
 #ifndef OPENSSL_NO_SRTP
     if (srtp_profiles != NULL) {
         /* Returns 0 on success! */
@@ -1635,7 +1730,7 @@ int s_server_main(int argc, char *argv[])
     }
 #endif
 
-    if (!ctx_set_verify_locations(ctx, CAfile, CApath)) {
+    if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
         ERR_print_errors(bio_err);
         goto end;
     }
@@ -1646,7 +1741,7 @@ int s_server_main(int argc, char *argv[])
     }
 
     ssl_ctx_add_crls(ctx, crls, 0);
-    if (!config_ctx(cctx, ssl_args, ctx, no_ecdhe, jpake_secret == NULL))
+    if (!config_ctx(cctx, ssl_args, ctx))
         goto end;
 
     if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
@@ -1695,6 +1790,9 @@ int s_server_main(int argc, char *argv[])
         else
             SSL_CTX_sess_set_cache_size(ctx2, 128);
 
+        if (async)
+            SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC);
+
         if ((!SSL_CTX_load_verify_locations(ctx2, CAfile, CApath)) ||
             (!SSL_CTX_set_default_verify_paths(ctx2))) {
             ERR_print_errors(bio_err);
@@ -1706,7 +1804,7 @@ int s_server_main(int argc, char *argv[])
         }
 
         ssl_ctx_add_crls(ctx2, crls, 0);
-        if (!config_ctx(cctx, ssl_args, ctx2, no_ecdhe, jpake_secret == NULL))
+        if (!config_ctx(cctx, ssl_args, ctx2))
             goto end;
     }
 #ifndef OPENSSL_NO_NEXTPROTONEG
@@ -1782,13 +1880,6 @@ int s_server_main(int argc, char *argv[])
         if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain))
             goto end;
     }
-#ifndef OPENSSL_NO_RSA
-    if (!no_tmp_rsa) {
-        SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb);
-        if (ctx2)
-            SSL_CTX_set_tmp_rsa_callback(ctx2, tmp_rsa_cb);
-    }
-#endif
 
     if (no_resume_ephemeral) {
         SSL_CTX_set_not_resumable_session_callback(ctx,
@@ -1799,15 +1890,10 @@ int s_server_main(int argc, char *argv[])
                                                        not_resumable_sess_cb);
     }
 #ifndef OPENSSL_NO_PSK
-# ifdef OPENSSL_NO_JPAKE
-    if (psk_key != NULL)
-# else
-    if (psk_key != NULL || jpake_secret)
-# endif
-    {
+    if (psk_key != NULL) {
         if (s_debug)
             BIO_printf(bio_s_out,
-                       "PSK key given or JPAKE in use, setting server callback\n");
+                       "PSK key given, setting server callback\n");
         SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);
     }
 
@@ -1888,16 +1974,13 @@ int s_server_main(int argc, char *argv[])
         server_cb = www_body;
     else
         server_cb = sv_body;
-#ifndef NO_SYS_UN_H
-    if (unix_path) {
-        if (unlink_unix_path)
-            unlink(unix_path);
-        do_server_unix(unix_path, &accept_socket, server_cb, context,
-                       naccept);
-    } else
+#ifdef AF_UNIX
+    if (socket_family == AF_UNIX
+        && unlink_unix_path)
+        unlink(host);
 #endif
-        do_server(port, socket_type, &accept_socket, server_cb, context,
-                  naccept);
+    do_server(&accept_socket, host, port, socket_family, socket_type,
+              server_cb, context, naccept);
     print_stats(bio_s_out, ctx);
     ret = 0;
  end:
@@ -1911,6 +1994,8 @@ int s_server_main(int argc, char *argv[])
     sk_X509_pop_free(s_dchain, X509_free);
     OPENSSL_free(pass);
     OPENSSL_free(dpass);
+    OPENSSL_free(host);
+    OPENSSL_free(port);
     X509_VERIFY_PARAM_free(vpm);
     free_sessions();
     OPENSSL_free(tlscstatp.host);
@@ -1962,7 +2047,7 @@ static void print_stats(BIO *bio, SSL_CTX *ssl_ctx)
                SSL_CTX_sess_get_cache_size(ssl_ctx));
 }
 
-static int sv_body(char *hostname, int s, int stype, unsigned char *context)
+static int sv_body(int s, int stype, unsigned char *context)
 {
     char *buf = NULL;
     fd_set readfds;
@@ -1979,16 +2064,12 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
 #endif
 
     buf = app_malloc(bufsize, "server buffer");
-#ifdef FIONBIO
     if (s_nbio) {
-        unsigned long sl = 1;
-
-        if (!s_quiet)
-            BIO_printf(bio_err, "turning on non blocking io\n");
-        if (BIO_socket_ioctl(s, FIONBIO, &sl) < 0)
+        if (!BIO_socket_nbio(s, 1))
             ERR_print_errors(bio_err);
+        else if (!s_quiet)
+            BIO_printf(bio_err, "Turned on non blocking io\n");
     }
-#endif
 
     if (con == NULL) {
         con = SSL_new(ctx);
@@ -2011,7 +2092,7 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
         ret = -1;
         goto err;
     }
-
+#ifndef OPENSSL_NO_DTLS
     if (stype == SOCK_DGRAM) {
 
         sbio = BIO_new_dgram(s, BIO_NOCLOSE);
@@ -2048,6 +2129,7 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
         /* turn on cookie exchange */
         SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE);
     } else
+#endif
         sbio = BIO_new_socket(s, BIO_NOCLOSE);
 
     if (s_nbio_test) {
@@ -2056,17 +2138,12 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
         test = BIO_new(BIO_f_nbio_test());
         sbio = BIO_push(test, sbio);
     }
-#ifndef OPENSSL_NO_JPAKE
-    if (jpake_secret)
-        jpake_server_auth(bio_s_out, sbio, jpake_secret);
-#endif
 
     SSL_set_bio(con, sbio, sbio);
     SSL_set_accept_state(con);
     /* SSL_set_fd(con,s); */
 
     if (s_debug) {
-        SSL_set_debug(con, 1);
         BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
         BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
     }
@@ -2091,7 +2168,8 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
         int read_from_sslcon;
 
         read_from_terminal = 0;
-        read_from_sslcon = SSL_pending(con);
+        read_from_sslcon = SSL_pending(con)
+                           || (async && SSL_waiting_for_async(con));
 
         if (!read_from_sslcon) {
             FD_ZERO(&readfds);
@@ -2167,7 +2245,7 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
                 if ((i <= 0) || (buf[0] == 'Q')) {
                     BIO_printf(bio_s_out, "DONE\n");
                     (void)BIO_flush(bio_s_out);
-                    SHUTDOWN(s);
+                    BIO_closesocket(s);
                     close_accept_socket();
                     ret = -11;
                     goto err;
@@ -2176,7 +2254,7 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
                     BIO_printf(bio_s_out, "DONE\n");
                     (void)BIO_flush(bio_s_out);
                     if (SSL_version(con) != DTLS1_VERSION)
-                        SHUTDOWN(s);
+                        BIO_closesocket(s);
                     /*
                      * close_accept_socket(); ret= -11;
                      */
@@ -2241,9 +2319,10 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
 #ifndef OPENSSL_NO_SRP
                 while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) {
                     BIO_printf(bio_s_out, "LOOKUP renego during write\n");
+                    SRP_user_pwd_free(srp_callback_parm.user);
                     srp_callback_parm.user =
-                        SRP_VBASE_get_by_user(srp_callback_parm.vb,
-                                              srp_callback_parm.login);
+                        SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+                                               srp_callback_parm.login);
                     if (srp_callback_parm.user)
                         BIO_printf(bio_s_out, "LOOKUP done %s\n",
                                    srp_callback_parm.user->info);
@@ -2255,6 +2334,10 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
                 switch (SSL_get_error(con, k)) {
                 case SSL_ERROR_NONE:
                     break;
+                case SSL_ERROR_WANT_ASYNC:
+                    BIO_printf(bio_s_out, "Write BLOCK (Async)\n");
+                    wait_for_async(con);
+                    break;
                 case SSL_ERROR_WANT_WRITE:
                 case SSL_ERROR_WANT_READ:
                 case SSL_ERROR_WANT_X509_LOOKUP:
@@ -2283,7 +2366,13 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
             }
         }
         if (read_from_sslcon) {
-            if (!SSL_is_init_finished(con)) {
+            /*
+             * init_ssl_connection handles all async events itself so if we're
+             * waiting for async then we shouldn't go back into
+             * init_ssl_connection
+             */
+            if ((!async || !SSL_waiting_for_async(con))
+                    && !SSL_is_init_finished(con)) {
                 i = init_ssl_connection(con);
 
                 if (i < 0) {
@@ -2299,9 +2388,10 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
 #ifndef OPENSSL_NO_SRP
                 while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
                     BIO_printf(bio_s_out, "LOOKUP renego during read\n");
+                    SRP_user_pwd_free(srp_callback_parm.user);
                     srp_callback_parm.user =
-                        SRP_VBASE_get_by_user(srp_callback_parm.vb,
-                                              srp_callback_parm.login);
+                        SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+                                               srp_callback_parm.login);
                     if (srp_callback_parm.user)
                         BIO_printf(bio_s_out, "LOOKUP done %s\n",
                                    srp_callback_parm.user->info);
@@ -2319,6 +2409,10 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context)
                     if (SSL_pending(con))
                         goto again;
                     break;
+                case SSL_ERROR_WANT_ASYNC:
+                    BIO_printf(bio_s_out, "Read BLOCK (Async)\n");
+                    wait_for_async(con);
+                    break;
                 case SSL_ERROR_WANT_WRITE:
                 case SSL_ERROR_WANT_READ:
                     BIO_printf(bio_s_out, "Read BLOCK\n");
@@ -2357,7 +2451,7 @@ static void close_accept_socket(void)
 {
     BIO_printf(bio_err, "shutdown accept socket\n");
     if (accept_socket >= 0) {
-        SHUTDOWN2(accept_socket);
+        BIO_closesocket(accept_socket);
     }
 }
 
@@ -2366,7 +2460,7 @@ static int init_ssl_connection(SSL *con)
     int i;
     const char *str;
     X509 *peer;
-    long verify_error;
+    long verify_err;
     char buf[BUFSIZ];
 #if !defined(OPENSSL_NO_NEXTPROTONEG)
     const unsigned char *next_proto_neg;
@@ -2374,45 +2468,81 @@ static int init_ssl_connection(SSL *con)
 #endif
     unsigned char *exportedkeymat;
 
-    i = SSL_accept(con);
+#ifndef OPENSSL_NO_DTLS
+    if(dtlslisten) {
+        BIO_ADDR *client = NULL;
+
+        if ((client = BIO_ADDR_new()) == NULL) {
+            BIO_printf(bio_err, "ERROR - memory\n");
+            return 0;
+        }
+        i = DTLSv1_listen(con, client);
+        if (i > 0) {
+            BIO *wbio;
+            int fd = -1;
+
+            wbio = SSL_get_wbio(con);
+            if(wbio) {
+                BIO_get_fd(wbio, &fd);
+            }
+
+            if(!wbio || BIO_connect(fd, client, 0) == 0) {
+                BIO_printf(bio_err, "ERROR - unable to connect\n");
+                BIO_ADDR_free(client);
+                return 0;
+            }
+            BIO_ADDR_free(client);
+            dtlslisten = 0;
+            i = SSL_accept(con);
+        }
+    } else
+#endif
+
+    do {
+        i = SSL_accept(con);
+
 #ifdef CERT_CB_TEST_RETRY
-    {
-        while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP
-               && SSL_state(con) == SSL3_ST_SR_CLNT_HELLO_C) {
-            BIO_printf(bio_err,
+        {
+            while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP
+                    && SSL_get_state(con) == TLS_ST_SR_CLNT_HELLO) {
+                BIO_printf(bio_err,
                        "LOOKUP from certificate callback during accept\n");
-            i = SSL_accept(con);
+                i = SSL_accept(con);
+            }
         }
-    }
 #endif
+
 #ifndef OPENSSL_NO_SRP
-    while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
-        BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
-                   srp_callback_parm.login);
-        srp_callback_parm.user =
-            SRP_VBASE_get_by_user(srp_callback_parm.vb,
-                                  srp_callback_parm.login);
-        if (srp_callback_parm.user)
-            BIO_printf(bio_s_out, "LOOKUP done %s\n",
-                       srp_callback_parm.user->info);
-        else
-            BIO_printf(bio_s_out, "LOOKUP not successful\n");
-        i = SSL_accept(con);
-    }
+        while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
+            BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
+                       srp_callback_parm.login);
+            SRP_user_pwd_free(srp_callback_parm.user);
+            srp_callback_parm.user =
+                SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+                                       srp_callback_parm.login);
+            if (srp_callback_parm.user)
+                BIO_printf(bio_s_out, "LOOKUP done %s\n",
+                           srp_callback_parm.user->info);
+            else
+                BIO_printf(bio_s_out, "LOOKUP not successful\n");
+            i = SSL_accept(con);
+        }
 #endif
+    } while (i < 0 && SSL_waiting_for_async(con));
 
     if (i <= 0) {
-        if (BIO_sock_should_retry(i)) {
+        if ((dtlslisten && i == 0)
+                || (!dtlslisten && BIO_sock_should_retry(i))) {
             BIO_printf(bio_s_out, "DELAY\n");
             return (1);
         }
 
         BIO_printf(bio_err, "ERROR\n");
 
-        verify_error = SSL_get_verify_result(con);
-        if (verify_error != X509_V_OK) {
+        verify_err = SSL_get_verify_result(con);
+        if (verify_err != X509_V_OK) {
             BIO_printf(bio_err, "verify error:%s\n",
-                       X509_verify_cert_error_string(verify_error));
+                       X509_verify_cert_error_string(verify_err));
         }
         /* Always print any error messages */
         ERR_print_errors(bio_err);
@@ -2463,7 +2593,7 @@ static int init_ssl_connection(SSL *con)
                        srtp_profile->name);
     }
 #endif
-    if (SSL_cache_hit(con))
+    if (SSL_session_reused(con))
         BIO_printf(bio_s_out, "Reused session-id\n");
     BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
                SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
@@ -2505,7 +2635,7 @@ static DH *load_dh_param(const char *dhfile)
 }
 #endif
 
-static int www_body(char *hostname, int s, int stype, unsigned char *context)
+static int www_body(int s, int stype, unsigned char *context)
 {
     char *buf = NULL;
     int ret = 1;
@@ -2516,6 +2646,11 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
 #ifdef RENEG
     int total_bytes = 0;
 #endif
+    int width;
+    fd_set readfds;
+
+    /* Set width for a select call if needed */
+    width = s + 1;
 
     buf = app_malloc(bufsize, "server www buffer");
     io = BIO_new(BIO_f_buffer());
@@ -2523,16 +2658,12 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
     if ((io == NULL) || (ssl_bio == NULL))
         goto err;
 
-#ifdef FIONBIO
     if (s_nbio) {
-        unsigned long sl = 1;
-
-        if (!s_quiet)
-            BIO_printf(bio_err, "turning on non blocking io\n");
-        if (BIO_socket_ioctl(s, FIONBIO, &sl) < 0)
+        if (!BIO_socket_nbio(s, 1))
             ERR_print_errors(bio_err);
+        else if (!s_quiet)
+            BIO_printf(bio_err, "Turned on non blocking io\n");
     }
-#endif
 
     /* lets make the output buffer a reasonable size */
     if (!BIO_set_write_buffer_size(io, bufsize))
@@ -2568,7 +2699,6 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
 #endif
 
     if (s_debug) {
-        SSL_set_debug(con, 1);
         BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
         BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
     }
@@ -2585,12 +2715,28 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
     for (;;) {
         i = BIO_gets(io, buf, bufsize - 1);
         if (i < 0) {            /* error */
-            if (!BIO_should_retry(io)) {
+            if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) {
                 if (!s_quiet)
                     ERR_print_errors(bio_err);
                 goto err;
             } else {
                 BIO_printf(bio_s_out, "read R BLOCK\n");
+#ifndef OPENSSL_NO_SRP
+                if (BIO_should_io_special(io)
+                    && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
+                    BIO_printf(bio_s_out, "LOOKUP renego during read\n");
+                    SRP_user_pwd_free(srp_callback_parm.user);
+                    srp_callback_parm.user =
+                        SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+                                               srp_callback_parm.login);
+                    if (srp_callback_parm.user)
+                        BIO_printf(bio_s_out, "LOOKUP done %s\n",
+                                   srp_callback_parm.user->info);
+                    else
+                        BIO_printf(bio_s_out, "LOOKUP not successful\n");
+                    continue;
+                }
+#endif
 #if defined(OPENSSL_SYS_NETWARE)
                 delay(1000);
 #elif !defined(OPENSSL_SYS_MSDOS)
@@ -2618,6 +2764,7 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
                                    NULL);
                 i = SSL_renegotiate(con);
                 BIO_printf(bio_s_out, "SSL_renegotiate -> %d\n", i);
+                /* Send the HelloRequest */
                 i = SSL_do_handshake(con);
                 if (i <= 0) {
                     BIO_printf(bio_s_out, "SSL_do_handshake() Retval %d\n",
@@ -2625,23 +2772,29 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
                     ERR_print_errors(bio_err);
                     goto err;
                 }
-                /* EVIL HACK! */
-                SSL_set_state(con, SSL_ST_ACCEPT);
-                i = SSL_do_handshake(con);
-                BIO_printf(bio_s_out, "SSL_do_handshake -> %d\n", i);
-                if (i <= 0) {
-                    BIO_printf(bio_s_out, "SSL_do_handshake() Retval %d\n",
-                               SSL_get_error(con, i));
+                /* Wait for a ClientHello to come back */
+                FD_ZERO(&readfds);
+                openssl_fdset(s, &readfds);
+                i = select(width, (void *)&readfds, NULL, NULL, NULL);
+                if (i <= 0 || !FD_ISSET(s, &readfds)) {
+                    BIO_printf(bio_s_out, "Error waiting for client response\n");
                     ERR_print_errors(bio_err);
                     goto err;
                 }
+                /*
+                 * We're not acutally expecting any data here and we ignore
+                 * any that is sent. This is just to force the handshake that
+                 * we're expecting to come from the client. If they haven't
+                 * sent one there's not much we can do.
+                 */
+                BIO_gets(io, buf, bufsize - 1);
             }
 
             BIO_puts(io,
                      "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
             BIO_puts(io, "<HTML><BODY BGCOLOR=\"#ffffff\">\n");
             BIO_puts(io, "<pre>\n");
-/*                      BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/
+/*                      BIO_puts(io,OpenSSL_version(OPENSSL_VERSION));*/
             BIO_puts(io, "\n");
             for (i = 0; i < local_argc; i++) {
                 const char *myp;
@@ -2706,7 +2859,7 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
 #ifndef OPENSSL_NO_EC
             ssl_print_curves(io, con, 0);
 #endif
-            BIO_printf(io, (SSL_cache_hit(con)
+            BIO_printf(io, (SSL_session_reused(con)
                             ? "---\nReused, " : "---\nNew, "));
             c = SSL_get_current_cipher(con);
             BIO_printf(io, "%s, Cipher is %s\n",
@@ -2830,7 +2983,7 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
 #endif
                     k = BIO_write(io, &(buf[j]), i - j);
                     if (k <= 0) {
-                        if (!BIO_should_retry(io))
+                        if (!BIO_should_retry(io)  && !SSL_waiting_for_async(con))
                             goto write_error;
                         else {
                             BIO_printf(bio_s_out, "rwrite W BLOCK\n");
@@ -2866,7 +3019,7 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
     return (ret);
 }
 
-static int rev_body(char *hostname, int s, int stype, unsigned char *context)
+static int rev_body(int s, int stype, unsigned char *context)
 {
     char *buf = NULL;
     int i;
@@ -2908,7 +3061,6 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context)
 #endif
 
     if (s_debug) {
-        SSL_set_debug(con, 1);
         BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
         BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
     }
@@ -2931,6 +3083,22 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context)
             ERR_print_errors(bio_err);
             goto end;
         }
+#ifndef OPENSSL_NO_SRP
+        if (BIO_should_io_special(io)
+            && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
+            BIO_printf(bio_s_out, "LOOKUP renego during accept\n");
+            SRP_user_pwd_free(srp_callback_parm.user);
+            srp_callback_parm.user =
+                SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+                                       srp_callback_parm.login);
+            if (srp_callback_parm.user)
+                BIO_printf(bio_s_out, "LOOKUP done %s\n",
+                           srp_callback_parm.user->info);
+            else
+                BIO_printf(bio_s_out, "LOOKUP not successful\n");
+            continue;
+        }
+#endif
     }
     BIO_printf(bio_err, "CONNECTION ESTABLISHED\n");
     print_ssl_summary(con);
@@ -2944,6 +3112,22 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context)
                 goto err;
             } else {
                 BIO_printf(bio_s_out, "read R BLOCK\n");
+#ifndef OPENSSL_NO_SRP
+                if (BIO_should_io_special(io)
+                    && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
+                    BIO_printf(bio_s_out, "LOOKUP renego during read\n");
+                    SRP_user_pwd_free(srp_callback_parm.user);
+                    srp_callback_parm.user =
+                        SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+                                               srp_callback_parm.login);
+                    if (srp_callback_parm.user)
+                        BIO_printf(bio_s_out, "LOOKUP done %s\n",
+                                   srp_callback_parm.user->info);
+                    else
+                        BIO_printf(bio_s_out, "LOOKUP not successful\n");
+                    continue;
+                }
+#endif
 #if defined(OPENSSL_SYS_NETWARE)
                 delay(1000);
 #elif !defined(OPENSSL_SYS_MSDOS)
@@ -2989,35 +3173,6 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context)
     return (ret);
 }
 
-#ifndef OPENSSL_NO_RSA
-static RSA *tmp_rsa_cb(SSL *s, int is_export, int keylength)
-{
-    BIGNUM *bn = NULL;
-    static RSA *rsa_tmp = NULL;
-
-    if (!rsa_tmp && ((bn = BN_new()) == NULL))
-        BIO_printf(bio_err, "Allocation error in generating RSA key\n");
-    if (!rsa_tmp && bn) {
-        if (!s_quiet) {
-            BIO_printf(bio_err, "Generating temp (%d bit) RSA key...",
-                       keylength);
-            (void)BIO_flush(bio_err);
-        }
-        if (!BN_set_word(bn, RSA_F4) || ((rsa_tmp = RSA_new()) == NULL) ||
-            !RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL)) {
-            RSA_free(rsa_tmp);
-            rsa_tmp = NULL;
-        }
-        if (!s_quiet) {
-            BIO_printf(bio_err, "\n");
-            (void)BIO_flush(bio_err);
-        }
-        BN_free(bn);
-    }
-    return (rsa_tmp);
-}
-#endif
-
 #define MAX_SESSION_ID_ATTEMPTS 10
 static int generate_session_id(const SSL *ssl, unsigned char *id,
                                unsigned int *id_len)
@@ -3074,7 +3229,7 @@ static int add_session(SSL *ssl, SSL_SESSION *session)
         return 0;
     }
 
-    sess->id = BUF_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen);
+    sess->id = OPENSSL_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen);
     sess->der = app_malloc(sess->derlen, "get session buffer");
     if (!sess->id) {
         BIO_printf(bio_err, "Out of memory adding to external cache\n");
@@ -3100,7 +3255,7 @@ static int add_session(SSL *ssl, SSL_SESSION *session)
     return 0;
 }
 
-static SSL_SESSION *get_session(SSL *ssl, unsigned char *id, int idlen,
+static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen,
                                 int *do_copy)
 {
     simple_ssl_session *sess;