More tweaks for comments due indent issues
[openssl.git] / ssl / ssltest.c
index 3c010409abeb5e3cd8d5908c867a074eb86b46da..9ff21171b1cc543511b94cd49154fe4ef5b60973 100644 (file)
  * OTHERWISE.
  */
 
-#define _BSD_SOURCE 1          /* Or gethostname won't be declared properly
-                                  on Linux and GNU platforms. */
+/* Or gethostname won't be declared properly on Linux and GNU platforms. */
+#define _BSD_SOURCE 1
 
 #include <assert.h>
 #include <errno.h>
 #include "e_os.h"
 
 #ifdef OPENSSL_SYS_VMS
-#define _XOPEN_SOURCE 500      /* Or isascii won't be declared properly on
-                                  VMS (at least with DECompHP C).  */
+/* Or isascii won't be declared properly on VMS (at least with DECompHP C).  */
+#define _XOPEN_SOURCE 500
 #endif
 
 #include <ctype.h>
 #endif
 #include <openssl/bn.h>
 
-#define _XOPEN_SOURCE_EXTENDED 1 /* Or gethostname won't be declared properly
-                                    on Compaq platforms (at least with DEC C).
-                                    Do not try to put it earlier, or IPv6 includes
-                                    get screwed...
-                                 */
+/*
+ * Or gethostname won't be declared properly
+ * on Compaq platforms (at least with DEC C).
+ * Do not try to put it earlier, or IPv6 includes
+ * get screwed...
+*/
+#define _XOPEN_SOURCE_EXTENDED 1 
 
 #ifdef OPENSSL_SYS_WINDOWS
 #include <winsock.h>
@@ -295,6 +297,364 @@ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
 static BIO *bio_err=NULL;
 static BIO *bio_stdout=NULL;
 
+static const char *alpn_client;
+static const char *alpn_server;
+static const char *alpn_expected;
+static unsigned char *alpn_selected;
+
+/*-
+ * next_protos_parse parses a comma separated list of strings into a string
+ * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
+ *   outlen: (output) set to the length of the resulting buffer on success.
+ *   err: (maybe NULL) on failure, an error message line is written to this BIO.
+ *   in: a NUL terminated string like "abc,def,ghi"
+ *
+ *   returns: a malloced buffer or NULL on failure.
+ */
+static unsigned char *next_protos_parse(unsigned short *outlen, const char *in)
+       {
+       size_t len;
+       unsigned char *out;
+       size_t i, start = 0;
+
+       len = strlen(in);
+       if (len >= 65535)
+               return NULL;
+
+       out = OPENSSL_malloc(strlen(in) + 1);
+       if (!out)
+               return NULL;
+
+       for (i = 0; i <= len; ++i)
+               {
+               if (i == len || in[i] == ',')
+                       {
+                       if (i - start > 255)
+                               {
+                               OPENSSL_free(out);
+                               return NULL;
+                               }
+                       out[start] = i - start;
+                       start = i + 1;
+                       }
+               else
+                       out[i+1] = in[i];
+               }
+
+       *outlen = len + 1;
+       return out;
+       }
+
+static int cb_server_alpn(SSL *s, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
+       {
+       unsigned char *protos;
+       unsigned short protos_len;
+
+       protos = next_protos_parse(&protos_len, alpn_server);
+       if (protos == NULL)
+               {
+               fprintf(stderr, "failed to parser ALPN server protocol string: %s\n", alpn_server);
+               abort();
+               }
+
+       if (SSL_select_next_proto((unsigned char**) out, outlen, protos, protos_len, in, inlen) !=
+           OPENSSL_NPN_NEGOTIATED)
+               {
+               OPENSSL_free(protos);
+               return SSL_TLSEXT_ERR_NOACK;
+               }
+
+       /* Make a copy of the selected protocol which will be freed in verify_alpn. */
+       alpn_selected = OPENSSL_malloc(*outlen);
+       memcpy(alpn_selected, *out, *outlen);
+       *out = alpn_selected;
+
+       OPENSSL_free(protos);
+       return SSL_TLSEXT_ERR_OK;
+       }
+
+static int verify_alpn(SSL *client, SSL *server)
+       {
+       const unsigned char *client_proto, *server_proto;
+       unsigned int client_proto_len = 0, server_proto_len = 0;
+       SSL_get0_alpn_selected(client, &client_proto, &client_proto_len);
+       SSL_get0_alpn_selected(server, &server_proto, &server_proto_len);
+
+       if (alpn_selected != NULL)
+               {
+               OPENSSL_free(alpn_selected);
+               alpn_selected = NULL;
+               }
+
+       if (client_proto_len != server_proto_len ||
+           memcmp(client_proto, server_proto, client_proto_len) != 0)
+               {
+               BIO_printf(bio_stdout, "ALPN selected protocols differ!\n");
+               goto err;
+               }
+
+       if (client_proto_len > 0 && alpn_expected == NULL)
+               {
+               BIO_printf(bio_stdout, "ALPN unexpectedly negotiated\n");
+               goto err;
+               }
+
+       if (alpn_expected != NULL &&
+           (client_proto_len != strlen(alpn_expected) ||
+            memcmp(client_proto, alpn_expected, client_proto_len) != 0))
+               {
+               BIO_printf(bio_stdout, "ALPN selected protocols not equal to expected protocol: %s\n", alpn_expected);
+               goto err;
+               }
+
+       return 0;
+
+err:
+       BIO_printf(bio_stdout, "ALPN results: client: '");
+       BIO_write(bio_stdout, client_proto, client_proto_len);
+       BIO_printf(bio_stdout, "', server: '");
+       BIO_write(bio_stdout, server_proto, server_proto_len);
+       BIO_printf(bio_stdout, "'\n");
+       BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '%s'\n", alpn_client, alpn_server);
+       return -1;
+       }
+
+#define SCT_EXT_TYPE 18
+
+/* WARNING : below extension types are *NOT* IETF assigned, and 
+   could conflict if these types are reassigned and handled 
+   specially by OpenSSL in the future */
+#define TACK_EXT_TYPE 62208
+#define CUSTOM_EXT_TYPE_0 1000
+#define CUSTOM_EXT_TYPE_1 1001
+#define CUSTOM_EXT_TYPE_2 1002
+#define CUSTOM_EXT_TYPE_3 1003
+
+const char custom_ext_cli_string[] = "abc";
+const char custom_ext_srv_string[] = "defg";
+
+/* These set from cmdline */
+char* serverinfo_file = NULL;
+int serverinfo_sct = 0;
+int serverinfo_tack = 0;
+
+/* These set based on extension callbacks */
+int serverinfo_sct_seen = 0;
+int serverinfo_tack_seen = 0;
+int serverinfo_other_seen = 0;
+
+/* This set from cmdline */
+int custom_ext = 0;
+
+/* This set based on extension callbacks */
+int custom_ext_error = 0;
+
+static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type,
+                                  const unsigned char *in, size_t inlen, 
+                                  int *al, void *arg)
+       {
+       if (ext_type == SCT_EXT_TYPE)
+               serverinfo_sct_seen++;
+       else if (ext_type == TACK_EXT_TYPE)
+               serverinfo_tack_seen++;
+       else
+               serverinfo_other_seen++;
+       return 1;
+       }
+
+static int verify_serverinfo()
+       {
+       if (serverinfo_sct != serverinfo_sct_seen)
+               return -1;
+       if (serverinfo_tack != serverinfo_tack_seen)
+               return -1;
+       if (serverinfo_other_seen)
+               return -1;
+       return 0;
+       }
+
+/*-
+ * Four test cases for custom extensions:
+ * 0 - no ClientHello extension or ServerHello response
+ * 1 - ClientHello with "abc", no response
+ * 2 - ClientHello with "abc", empty response
+ * 3 - ClientHello with "abc", "defg" response
+ */
+
+static int custom_ext_0_cli_add_cb(SSL *s, unsigned int ext_type,
+                                    const unsigned char **out,
+                                    size_t *outlen, int *al, void *arg)
+       {
+       if (ext_type != CUSTOM_EXT_TYPE_0)
+               custom_ext_error = 1;
+       return 0;  /* Don't send an extension */
+       }
+
+static int custom_ext_0_cli_parse_cb(SSL *s, unsigned int ext_type,
+                                     const unsigned char *in,
+                                     size_t inlen, int *al,
+                                     void *arg)
+       {
+       return 1;
+       }
+
+static int custom_ext_1_cli_add_cb(SSL *s, unsigned int ext_type,
+                                    const unsigned char **out,
+                                    size_t *outlen, int *al, void *arg)
+       {
+       if (ext_type != CUSTOM_EXT_TYPE_1)
+               custom_ext_error = 1;
+       *out = (const unsigned char*)custom_ext_cli_string;
+       *outlen = strlen(custom_ext_cli_string);
+       return 1; /* Send "abc" */
+       }
+
+static int custom_ext_1_cli_parse_cb(SSL *s, unsigned int ext_type,
+                                     const unsigned char *in,
+                                     size_t inlen, int *al,
+                                     void *arg)
+       {
+       return 1;
+       }
+
+static int custom_ext_2_cli_add_cb(SSL *s, unsigned int ext_type,
+                                    const unsigned char **out,
+                                    size_t *outlen, int *al, void *arg)
+       {
+       if (ext_type != CUSTOM_EXT_TYPE_2)
+               custom_ext_error = 1;
+       *out = (const unsigned char*)custom_ext_cli_string;
+       *outlen = strlen(custom_ext_cli_string);
+       return 1; /* Send "abc" */
+       }
+
+static int custom_ext_2_cli_parse_cb(SSL *s, unsigned int ext_type,
+                                     const unsigned char *in,
+                                     size_t inlen, int *al,
+                                     void *arg)
+       {
+       if (ext_type != CUSTOM_EXT_TYPE_2)
+               custom_ext_error = 1;
+       if (inlen != 0)
+               custom_ext_error = 1; /* Should be empty response */
+       return 1;
+       }
+
+static int custom_ext_3_cli_add_cb(SSL *s, unsigned int ext_type,
+                                    const unsigned char **out,
+                                    size_t *outlen, int *al, void *arg)
+       {
+       if (ext_type != CUSTOM_EXT_TYPE_3)
+               custom_ext_error = 1;
+       *out = (const unsigned char*)custom_ext_cli_string;
+       *outlen = strlen(custom_ext_cli_string);
+       return 1; /* Send "abc" */
+       }
+
+static int custom_ext_3_cli_parse_cb(SSL *s, unsigned int ext_type,
+                                     const unsigned char *in,
+                                     size_t inlen, int *al,
+                                     void *arg)
+       {
+       if (ext_type != CUSTOM_EXT_TYPE_3)
+               custom_ext_error = 1;
+       if (inlen != strlen(custom_ext_srv_string))
+               custom_ext_error = 1;
+       if (memcmp(custom_ext_srv_string, in, inlen) != 0)
+               custom_ext_error = 1; /* Check for "defg" */
+       return 1;
+       }
+
+/* custom_ext_0_cli_add_cb returns 0 - the server won't receive a callback for this extension */
+static int custom_ext_0_srv_parse_cb(SSL *s, unsigned int ext_type,
+                                    const unsigned char *in,
+                                    size_t inlen, int *al,
+                                    void *arg)
+       {
+       custom_ext_error = 1;
+       return 1;
+       }
+
+/* 'add' callbacks are only called if the 'parse' callback is called */
+static int custom_ext_0_srv_add_cb(SSL *s, unsigned int ext_type,
+                                     const unsigned char **out,
+                                     size_t *outlen, int *al, void *arg)
+       {
+       /* Error: should not have been called */
+       custom_ext_error = 1;
+        return 0; /* Don't send an extension */
+       }
+
+static int custom_ext_1_srv_parse_cb(SSL *s, unsigned int ext_type,
+                               const unsigned char *in,
+                               size_t inlen, int *al,
+                               void *arg)
+       {
+       if (ext_type != CUSTOM_EXT_TYPE_1)
+               custom_ext_error = 1;           
+        /* Check for "abc" */
+       if (inlen != strlen(custom_ext_cli_string))
+               custom_ext_error = 1;
+       if (memcmp(in, custom_ext_cli_string, inlen) != 0)
+               custom_ext_error = 1;
+       return 1;
+       }
+
+static int custom_ext_1_srv_add_cb(SSL *s, unsigned int ext_type,
+                                     const unsigned char **out,
+                                     size_t *outlen, int *al, void *arg)
+       {
+       return 0; /* Don't send an extension */
+       }
+
+static int custom_ext_2_srv_parse_cb(SSL *s, unsigned int ext_type,
+                                    const unsigned char *in,
+                                    size_t inlen, int *al,
+                                    void *arg)
+       {
+       if (ext_type != CUSTOM_EXT_TYPE_2)
+               custom_ext_error = 1;           
+        /* Check for "abc" */
+       if (inlen != strlen(custom_ext_cli_string))
+               custom_ext_error = 1;
+       if (memcmp(in, custom_ext_cli_string, inlen) != 0)
+               custom_ext_error = 1;
+       return 1;
+       }
+
+static int custom_ext_2_srv_add_cb(SSL *s, unsigned int ext_type,
+                                     const unsigned char **out,
+                                     size_t *outlen, int *al, void *arg)
+       {
+       *out = NULL;
+       *outlen = 0;
+       return 1; /* Send empty extension */
+       }
+
+static int custom_ext_3_srv_parse_cb(SSL *s, unsigned int ext_type,
+                                    const unsigned char *in,
+                                    size_t inlen, int *al,
+                                    void *arg)
+       {
+       if (ext_type != CUSTOM_EXT_TYPE_3)
+               custom_ext_error = 1;           
+        /* Check for "abc" */  
+       if (inlen != strlen(custom_ext_cli_string))
+               custom_ext_error = 1;
+       if (memcmp(in, custom_ext_cli_string, inlen) != 0)
+               custom_ext_error = 1;
+       return 1;
+       }
+
+static int custom_ext_3_srv_add_cb(SSL *s, unsigned int ext_type,
+                                     const unsigned char **out,
+                                     size_t *outlen, int *al, void *arg)
+       {
+       *out = (const unsigned char*)custom_ext_srv_string;
+       *outlen = strlen(custom_ext_srv_string);
+       return 1; /* Send "defg" */
+       }
+
 static char *cipher=NULL;
 static int verbose=0;
 static int debug=0;
@@ -321,7 +681,7 @@ static void sv_usage(void)
        fprintf(stderr," -client_auth  - do client authentication\n");
        fprintf(stderr," -proxy        - allow proxy certificates\n");
        fprintf(stderr," -proxy_auth <val> - set proxy policy rights\n");
-       fprintf(stderr," -proxy_cond <val> - experssion to test proxy policy rights\n");
+       fprintf(stderr," -proxy_cond <val> - expression to test proxy policy rights\n");
        fprintf(stderr," -v            - more output\n");
        fprintf(stderr," -d            - debug output\n");
        fprintf(stderr," -reuse        - use session-id reuse\n");
@@ -345,7 +705,7 @@ static void sv_usage(void)
 #ifndef OPENSSL_NO_SSL2
        fprintf(stderr," -ssl2         - use SSLv2\n");
 #endif
-#ifndef OPENSSL_NO_SSL3
+#ifndef OPENSSL_NO_SSL3_METHOD
        fprintf(stderr," -ssl3         - use SSLv3\n");
 #endif
 #ifndef OPENSSL_NO_TLS1
@@ -368,12 +728,16 @@ static void sv_usage(void)
                       "                 Use \"openssl ecparam -list_curves\" for all names\n"  \
                       "                 (default is sect163r2).\n");
 #endif
-       fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n");
-#ifndef OPENSSL_NO_TLSEXT
-       fprintf(stderr," -server_authz arg - binary authz file for certificate\n");
-       fprintf(stderr," -c_support_proof  - indicate client support for server_authz audit proofs\n");
-       fprintf(stderr," -c_require_proof  - fail if no audit proof is sent\n");
-#endif
+       fprintf(stderr," -test_cipherlist - Verifies the order of the ssl cipher lists.\n"
+                      "                    When this option is requested, the cipherlist\n"
+                      "                    tests are run instead of handshake tests.\n");
+       fprintf(stderr," -serverinfo_file file - have server use this file\n");
+       fprintf(stderr," -serverinfo_sct  - have client offer and expect SCT\n");
+       fprintf(stderr," -serverinfo_tack - have client offer and expect TACK\n");
+       fprintf(stderr," -custom_ext - try various custom extension callbacks\n");
+       fprintf(stderr," -alpn_client <string> - have client side offer ALPN\n");
+       fprintf(stderr," -alpn_server <string> - have server side offer ALPN\n");
+       fprintf(stderr," -alpn_expected <string> - the ALPN protocol that should be negotiated\n");
        }
 
 static void print_details(SSL *c_ssl, const char *prefix)
@@ -503,56 +867,6 @@ int opaque_prf_input_cb(SSL *ssl, void *peerinput, size_t len, void *arg_)
        }
 #endif
 
-#ifndef OPENSSL_NO_TLSEXT
-struct audit_proof_cb_arg_st
-       {
-       unsigned char *expected_proof;
-       size_t expected_proof_length;
-       int require;
-       };
-
-struct audit_proof_cb_arg_st c_expected = { NULL, 0, 0 };
-
-static int audit_proof_cb(SSL *s, void *arg)
-       {
-       const unsigned char *proof;
-       size_t proof_len;
-       SSL_SESSION *sess = SSL_get_session(s);
-       struct audit_proof_cb_arg_st *cb_arg = (struct audit_proof_cb_arg_st*)arg;
-
-       proof = SSL_SESSION_get_tlsext_authz_server_audit_proof(sess,
-               &proof_len);
-       if (proof != NULL)
-               {
-               if (proof_len == cb_arg->expected_proof_length &&
-                       cb_arg->expected_proof != NULL &&
-                       memcmp(proof, cb_arg->expected_proof, proof_len) == 0)
-                       {
-                       BIO_printf(bio_stdout, "Audit proof OK (%lu bytes).\n",
-                                  (long)proof_len);
-                       return 1;
-                       }
-               else
-                       {
-                       BIO_printf(bio_stdout, "Audit proof mismatch.\n");
-                       /* Cause handshake failure. */
-                       return 0;
-                       }
-               }
-
-       else /* proof == NULL */
-               {
-               BIO_printf(bio_stdout, "No audit proof found.\n");
-               if (cb_arg->require)
-                       {
-                       /* Cause handshake failure. */
-                       return 0;
-                       }
-               return 1;
-               }
-       }
-#endif
-
 int main(int argc, char *argv[])
        {
        char *CApath=NULL,*CAfile=NULL;
@@ -604,11 +918,7 @@ int main(int argc, char *argv[])
 #ifdef OPENSSL_FIPS
        int fips_mode=0;
 #endif
-#ifndef OPENSSL_NO_TLSEXT
-       char *s_authz_file = NULL;
-       int c_support_proof = 0;
-       int c_require_proof = 0;
-#endif
+        int no_protocol = 0;
 
        verbose = 0;
        debug = 0;
@@ -645,7 +955,7 @@ int main(int argc, char *argv[])
 #ifdef OPENSSL_FIPS
                        fips_mode=1;
 #else
-                       fprintf(stderr,"not compiled with FIPS support, so exitting without running.\n");
+                       fprintf(stderr,"not compiled with FIPS support, so exiting without running.\n");
                        EXIT(0);
 #endif
                        }
@@ -718,11 +1028,26 @@ int main(int argc, char *argv[])
                        }
 #endif
                else if (strcmp(*argv,"-ssl2") == 0)
-                       ssl2=1;
+                       {
+#ifdef OPENSSL_NO_SSL2
+                       no_protocol = 1;
+#endif
+                       ssl2 = 1;
+                       }
                else if (strcmp(*argv,"-tls1") == 0)
-                       tls1=1;
+                       {
+#ifdef OPENSSL_NO_TLS1
+                       no_protocol = 1;
+#endif
+                       tls1 = 1;
+                       }
                else if (strcmp(*argv,"-ssl3") == 0)
-                       ssl3=1;
+                       {
+#ifdef OPENSSL_NO_SSL3_METHOD
+                       no_protocol = 1;
+#endif
+                       ssl3 = 1;
+                       }
                else if (strncmp(*argv,"-num",4) == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -827,24 +1152,38 @@ int main(int argc, char *argv[])
                        {
                        test_cipherlist = 1;
                        }
-#ifndef OPENSSL_NO_TLSEXT
-               else if(strcmp(*argv,"-server_authz") == 0)
+               else if (strcmp(*argv,"-serverinfo_sct") == 0)
+                       {
+                       serverinfo_sct = 1;
+                       }
+               else if (strcmp(*argv,"-serverinfo_tack") == 0)
+                       {
+                       serverinfo_tack = 1;
+                       }
+               else if (strcmp(*argv,"-serverinfo_file") == 0)
                        {
                        if (--argc < 1) goto bad;
-                       s_authz_file = *(++argv);
-                       tls1 = 1;
+                       serverinfo_file = *(++argv);
                        }
-               else if (strcmp(*argv,"-c_support_proof") == 0)
+               else if (strcmp(*argv,"-custom_ext") == 0)
                        {
-                       c_support_proof = 1;
-                       tls1 = 1;
+                       custom_ext = 1;
                        }
-               else if (strcmp(*argv,"-c_require_proof") == 0)
+               else if (strcmp(*argv,"-alpn_client") == 0)
                        {
-                       c_require_proof = 1;
-                       tls1 = 1;
+                       if (--argc < 1) goto bad;
+                       alpn_client = *(++argv);
+                       }
+               else if (strcmp(*argv,"-alpn_server") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       alpn_server = *(++argv);
+                       }
+               else if (strcmp(*argv,"-alpn_expected") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       alpn_expected = *(++argv);
                        }
-#endif
                else
                        {
                        fprintf(stderr,"unknown option %s\n",*argv);
@@ -861,15 +1200,41 @@ bad:
                goto end;
                }
 
+       /*
+        * test_cipherlist prevails over protocol switch: we test the cipherlist
+        * for all enabled protocols.
+        */
        if (test_cipherlist == 1)
                {
                /* ensure that the cipher list are correctly sorted and exit */
+               fprintf(stdout, "Testing cipherlist order only. Ignoring all "
+                       "other options.\n");
                if (do_test_cipherlist() == 0)
                        EXIT(1);
                ret = 0;
                goto end;
                }
 
+       if (ssl2 + ssl3 + tls1 > 1)
+               {
+               fprintf(stderr, "At most one of -ssl2, -ssl3, or -tls1 should "
+                       "be requested.\n");
+               EXIT(1);
+               }
+
+       /*
+        * Testing was requested for a compiled-out protocol (e.g. SSLv2).
+         * Ideally, we would error out, but the generic test wrapper can't know
+        * when to expect failure. So we do nothing and return success.
+        */
+       if (no_protocol)
+               {
+               fprintf(stderr, "Testing was requested for a disabled protocol. "
+                       "Skipping tests.\n");
+               ret = 0;
+               goto end;
+               }
+
        if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force)
                {
                fprintf(stderr, "This case cannot work.  Use -f to perform "
@@ -878,15 +1243,6 @@ bad:
                        "to avoid protocol mismatch.\n");
                EXIT(1);
                }
-       if (c_require_proof && s_authz_file == NULL && !force)
-               {
-               fprintf(stderr, "This case cannot work. -c_require_proof "
-                       "requires an audit proof, but none was supplied. "
-                       "Use -f to perform the test anyway (and\n-d to see "
-                       "what happens), or use -server_authz to supply an "
-                       "audit proof.\n");
-               EXIT(1);
-               }
 
 #ifdef OPENSSL_FIPS
        if(fips_mode)
@@ -957,24 +1313,25 @@ bad:
        }
 #endif
 
-#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
+/* At this point, ssl2/ssl3/tls1 is only set if the protocol is available.
+ * (Otherwise we exit early.)
+ * However the compiler doesn't know this, so we ifdef. */
+#ifndef OPENSSL_NO_SSL2
        if (ssl2)
                meth=SSLv2_method();
-       else 
-       if (tls1)
-               meth=TLSv1_method();
        else
+#endif
+#ifndef OPENSSL_NO_SSL3
        if (ssl3)
                meth=SSLv3_method();
        else
-               meth=SSLv23_method();
-#else
-#ifdef OPENSSL_NO_SSL2
-       meth=SSLv3_method();
-#else
-       meth=SSLv2_method();
 #endif
+#ifndef OPENSSL_NO_TLS1
+       if (tls1)
+               meth=TLSv1_method();
+       else
 #endif
+       meth=SSLv23_method();
 
        c_ctx=SSL_CTX_new(meth);
        s_ctx=SSL_CTX_new(meth);
@@ -1053,8 +1410,10 @@ bad:
 #ifdef TLSEXT_TYPE_opaque_prf_input
        SSL_CTX_set_tlsext_opaque_prf_input_callback(c_ctx, opaque_prf_input_cb);
        SSL_CTX_set_tlsext_opaque_prf_input_callback(s_ctx, opaque_prf_input_cb);
-       SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(c_ctx, &co1); /* or &co2 or NULL */
-       SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(s_ctx, &so1); /* or &so2 or NULL */
+       /* or &co2 or NULL */
+       SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(c_ctx, &co1);
+       /* or &so2 or NULL */
+       SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(s_ctx, &so1);
 #endif
 
        if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM))
@@ -1152,34 +1511,77 @@ bad:
                SSL_CTX_set_srp_username_callback(s_ctx, ssl_srp_server_param_cb);
                }
 #endif
-#ifndef OPENSSL_NO_TLSEXT
-       if (s_authz_file != NULL)
-               {
-               if(!SSL_CTX_use_authz_file(s_ctx, s_authz_file))
+
+       if (serverinfo_sct)
+               SSL_CTX_add_client_custom_ext(c_ctx, SCT_EXT_TYPE,
+                                             NULL, NULL, NULL,
+                                             serverinfo_cli_parse_cb, NULL);
+       if (serverinfo_tack)
+               SSL_CTX_add_client_custom_ext(c_ctx, TACK_EXT_TYPE,
+                                             NULL, NULL, NULL,
+                                             serverinfo_cli_parse_cb, NULL);
+
+       if (serverinfo_file)
+               if (!SSL_CTX_use_serverinfo_file(s_ctx, serverinfo_file))
                        {
-                       BIO_printf(bio_err, "Unable to set authz data\n");
+                       BIO_printf(bio_err, "missing serverinfo file\n");
                        goto end;
                        }
-               }
-       if (c_support_proof || c_require_proof)
-               {
-               size_t proof_length;
-               const unsigned char *proof = SSL_CTX_get_authz_data(s_ctx,
-                       TLSEXT_AUTHZDATAFORMAT_audit_proof, &proof_length);
-               if (proof != NULL)
-                       {
-                       /* Store a local copy. */
-                       c_expected.expected_proof = OPENSSL_malloc(proof_length);
-                       c_expected.expected_proof_length = proof_length;
-                       memcpy(c_expected.expected_proof, proof, proof_length);
+
+       if (custom_ext)
+               {
+               SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_0, 
+                                             custom_ext_0_cli_add_cb,
+                                             NULL, NULL,
+                                             custom_ext_0_cli_parse_cb, NULL);
+               SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_1, 
+                                             custom_ext_1_cli_add_cb,
+                                             NULL, NULL,
+                                             custom_ext_1_cli_parse_cb, NULL);
+               SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_2, 
+                                             custom_ext_2_cli_add_cb,
+                                             NULL, NULL,
+                                             custom_ext_2_cli_parse_cb, NULL);
+               SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_3, 
+                                             custom_ext_3_cli_add_cb,
+                                             NULL, NULL,
+                                             custom_ext_3_cli_parse_cb, NULL);
+
+
+               SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_0, 
+                                             custom_ext_0_srv_add_cb,
+                                             NULL, NULL,
+                                             custom_ext_0_srv_parse_cb, NULL);
+               SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_1, 
+                                             custom_ext_1_srv_add_cb,
+                                             NULL, NULL,
+                                             custom_ext_1_srv_parse_cb, NULL);
+               SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_2, 
+                                             custom_ext_2_srv_add_cb,
+                                             NULL, NULL,
+                                             custom_ext_2_srv_parse_cb, NULL);
+               SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_3, 
+                                             custom_ext_3_srv_add_cb,
+                                             NULL, NULL,
+                                             custom_ext_3_srv_parse_cb, NULL);
+               }
+
+       if (alpn_server)
+               SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, NULL);
+
+       if (alpn_client)
+               {
+               unsigned short alpn_len;
+               unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client);
+
+               if (alpn == NULL)
+                       {
+                       BIO_printf(bio_err, "Error parsing -alpn_client argument\n");
+                       goto end;
                        }
-               c_expected.require = c_require_proof;
-               SSL_CTX_set_tlsext_authz_server_audit_proof_cb(c_ctx,
-                       audit_proof_cb);
-               SSL_CTX_set_tlsext_authz_server_audit_proof_cb_arg(c_ctx,
-                       &c_expected);
+               SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len);
+               OPENSSL_free(alpn);
                }
-#endif
 
        c_ssl=SSL_new(c_ctx);
        s_ssl=SSL_new(s_ctx);
@@ -1254,10 +1656,6 @@ end:
 #endif
 #ifndef OPENSSL_NO_ENGINE
        ENGINE_cleanup();
-#endif
-#ifndef OPENSSL_NO_TLSEXT
-       if (c_expected.expected_proof != NULL)
-               OPENSSL_free(c_expected.expected_proof);
 #endif
        CRYPTO_cleanup_all_ex_data();
        ERR_free_strings();
@@ -1302,7 +1700,8 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
 
        do
                {
-               /* c_ssl_bio:          SSL filter BIO
+               /*-
+                * c_ssl_bio:          SSL filter BIO
                 *
                 * client:             pseudo-I/O for SSL library
                 *
@@ -1635,6 +2034,24 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
 
        if (verbose)
                print_details(c_ssl, "DONE via BIO pair: ");
+
+       if (verify_serverinfo() < 0)
+               {
+               ret = 1;
+               goto err;
+               }
+       if (verify_alpn(c_ssl, s_ssl) < 0)
+               {
+               ret = 1;
+               goto err;
+               }
+
+       if (custom_ext_error)
+               {
+               ret = 1;
+               goto err;
+               }
+
 end:
        ret = 0;
 
@@ -1665,7 +2082,8 @@ end:
 
 int doit(SSL *s_ssl, SSL *c_ssl, long count)
        {
-       MS_STATIC char cbuf[1024*8],sbuf[1024*8];
+       char *cbuf=NULL,*sbuf=NULL;
+       long bufsiz;
        long cw_num=count,cr_num=count;
        long sw_num=count,sr_num=count;
        int ret=1;
@@ -1678,9 +2096,15 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
        int done=0;
        int c_write,s_write;
        int do_server=0,do_client=0;
+       int max_frag = 5*1024;
+
+       bufsiz = count>40*1024 ? 40*1024 : count;
+
+       if ((cbuf = OPENSSL_malloc(bufsiz))==NULL) goto err;
+       if ((sbuf = OPENSSL_malloc(bufsiz))==NULL) goto err;
 
-       memset(cbuf,0,sizeof(cbuf));
-       memset(sbuf,0,sizeof(sbuf));
+       memset(cbuf,0,bufsiz);
+       memset(sbuf,0,bufsiz);
 
        c_to_s=BIO_new(BIO_s_mem());
        s_to_c=BIO_new(BIO_s_mem());
@@ -1700,10 +2124,12 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
 
        SSL_set_connect_state(c_ssl);
        SSL_set_bio(c_ssl,s_to_c,c_to_s);
+       SSL_set_max_send_fragment(c_ssl,max_frag);
        BIO_set_ssl(c_bio,c_ssl,BIO_NOCLOSE);
 
        SSL_set_accept_state(s_ssl);
        SSL_set_bio(s_ssl,c_to_s,s_to_c);
+       SSL_set_max_send_fragment(s_ssl,max_frag);
        BIO_set_ssl(s_bio,s_ssl,BIO_NOCLOSE);
 
        c_r=0; s_r=1;
@@ -1727,7 +2153,8 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
                        if (SSL_in_init(s_ssl))
                                printf("server waiting in SSL_accept - %s\n",
                                        SSL_state_string_long(s_ssl));
-/*                     else if (s_write)
+/*-
+                       else if (s_write)
                                printf("server:SSL_write()\n");
                        else
                                printf("server:SSL_read()\n"); */
@@ -1738,7 +2165,8 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
                        if (SSL_in_init(c_ssl))
                                printf("client waiting in SSL_connect - %s\n",
                                        SSL_state_string_long(c_ssl));
-/*                     else if (c_write)
+/*-
+                       else if (c_write)
                                printf("client:SSL_write()\n");
                        else
                                printf("client:SSL_read()\n"); */
@@ -1754,8 +2182,8 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
                        {
                        if (c_write)
                                {
-                               j = (cw_num > (long)sizeof(cbuf)) ?
-                                       (int)sizeof(cbuf) : (int)cw_num;
+                               j = (cw_num > bufsiz) ?
+                                       (int)bufsiz : (int)cw_num;
                                i=BIO_write(c_bio,cbuf,j);
                                if (i < 0)
                                        {
@@ -1788,11 +2216,13 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
                                        s_r=1;
                                        c_write=0;
                                        cw_num-=i;
+                                       if (max_frag>1029)
+                                               SSL_set_max_send_fragment(c_ssl,max_frag-=5);
                                        }
                                }
                        else
                                {
-                               i=BIO_read(c_bio,cbuf,sizeof(cbuf));
+                               i=BIO_read(c_bio,cbuf,bufsiz);
                                if (i < 0)
                                        {
                                        c_r=0;
@@ -1840,7 +2270,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
                        {
                        if (!s_write)
                                {
-                               i=BIO_read(s_bio,sbuf,sizeof(cbuf));
+                               i=BIO_read(s_bio,sbuf,bufsiz);
                                if (i < 0)
                                        {
                                        s_r=0;
@@ -1885,8 +2315,8 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
                                }
                        else
                                {
-                               j = (sw_num > (long)sizeof(sbuf)) ?
-                                       (int)sizeof(sbuf) : (int)sw_num;
+                               j = (sw_num > bufsiz) ?
+                                       (int)bufsiz : (int)sw_num;
                                i=BIO_write(s_bio,sbuf,j);
                                if (i < 0)
                                        {
@@ -1921,6 +2351,8 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
                                        c_r=1;
                                        if (sw_num <= 0)
                                                done|=S_DONE;
+                                       if (max_frag>1029)
+                                               SSL_set_max_send_fragment(s_ssl,max_frag-=5);
                                        }
                                }
                        }
@@ -1930,6 +2362,16 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
 
        if (verbose)
                print_details(c_ssl, "DONE: ");
+       if (verify_serverinfo() < 0)
+               {
+               ret = 1;
+               goto err;
+               }
+       if (custom_ext_error)
+               {
+               ret = 1;
+               goto err;
+               }
        ret=0;
 err:
        /* We have to set the BIO's to NULL otherwise they will be
@@ -1954,6 +2396,10 @@ err:
        if (s_to_c != NULL) BIO_free(s_to_c);
        if (c_bio != NULL) BIO_free_all(c_bio);
        if (s_bio != NULL) BIO_free_all(s_bio);
+
+       if (cbuf) OPENSSL_free(cbuf);
+       if (sbuf) OPENSSL_free(sbuf);
+
        return(ret);
        }
 
@@ -2111,9 +2557,10 @@ static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
 
 static void process_proxy_debug(int indent, const char *format, ...)
        {
+       /* That's 80 > */
        static const char indentation[] =
                ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
-               ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; /* That's 80 > */
+               ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
        char my_format[256];
        va_list args;
 
@@ -2124,11 +2571,12 @@ static void process_proxy_debug(int indent, const char *format, ...)
        vfprintf(stderr, my_format, args);
        va_end(args);
        }
-/* Priority levels:
-   0   [!]var, ()
-   1   & ^
-   2   |
-*/
+/*-
+ * Priority levels:
+ *  0  [!]var, ()
+ *  1  & ^
+ *  2  |
+ */
 static int process_proxy_cond_adders(unsigned int letters[26],
        const char *cond, const char **cond_end, int *pos, int indent);
 static int process_proxy_cond_val(unsigned int letters[26],
@@ -2480,7 +2928,8 @@ static void free_tmp_rsa(void)
 #endif
 
 #ifndef OPENSSL_NO_DH
-/* These DH parameters have been generated as follows:
+/*-
+ * These DH parameters have been generated as follows:
  *    $ openssl dhparam -C -noout 512
  *    $ openssl dhparam -C -noout 1024
  *    $ openssl dhparam -C -noout -dsaparam 1024