[openssl-commits] [openssl] OpenSSL_1_1_0-stable update
Matt Caswell
matt at openssl.org
Wed May 10 15:57:50 UTC 2017
The branch OpenSSL_1_1_0-stable has been updated
via ad1855847e3bc0e25aa4a013bbc06135bd6c19da (commit)
via c645f9de477e3a90da2109863f9971e93ea38b58 (commit)
from fbf09642692d3bf9343301d1e8befd37eef0277c (commit)
- Log -----------------------------------------------------------------
commit ad1855847e3bc0e25aa4a013bbc06135bd6c19da
Author: Matt Caswell <matt at openssl.org>
Date: Wed May 10 10:54:18 2017 +0100
Add a test for SNI in conjunction with custom extensions
Test that custom extensions still work even after a change in SSL_CTX due
to SNI. See #2180.
Reviewed-by: Rich Salz <rsalz at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3426)
commit c645f9de477e3a90da2109863f9971e93ea38b58
Author: Matt Caswell <matt at openssl.org>
Date: Wed May 10 11:28:53 2017 +0100
Copy custom extension flags in a call to SSL_set_SSL_CTX()
The function SSL_set_SSL_CTX() can be used to swap the SSL_CTX used for
a connection as part of an SNI callback. One result of this is that the
s->cert structure is replaced. However this structure contains information
about any custom extensions that have been loaded. In particular flags are
set indicating whether a particular extension has been received in the
ClientHello. By replacing the s->cert structure we lose the custom
extension flag values, and it appears as if a client has not sent those
extensions.
SSL_set_SSL_CTX() should copy any flags for custom extensions that appear
in both the old and the new cert structure.
Fixes #2180
Reviewed-by: Rich Salz <rsalz at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3426)
-----------------------------------------------------------------------
Summary of changes:
ssl/ssl_lib.c | 6 ++
ssl/ssl_locl.h | 2 +
ssl/t1_ext.c | 19 +++++
test/sslapitest.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
test/ssltestlib.c | 8 ++-
5 files changed, 234 insertions(+), 3 deletions(-)
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index fc651bb..cf24615 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3393,6 +3393,12 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
if (new_cert == NULL) {
return NULL;
}
+
+ if (!custom_exts_copy_flags(&new_cert->srv_ext, &ssl->cert->srv_ext)) {
+ ssl_cert_free(new_cert);
+ return NULL;
+ }
+
ssl_cert_free(ssl->cert);
ssl->cert = new_cert;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 08de52e..eb7e8c9 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -2117,6 +2117,8 @@ __owur int custom_ext_add(SSL *s, int server, unsigned char **pret,
__owur int custom_exts_copy(custom_ext_methods *dst,
const custom_ext_methods *src);
+__owur int custom_exts_copy_flags(custom_ext_methods *dst,
+ const custom_ext_methods *src);
void custom_exts_free(custom_ext_methods *exts);
void ssl_comp_free_compression_methods_int(void);
diff --git a/ssl/t1_ext.c b/ssl/t1_ext.c
index adcd0f9..a996a20 100644
--- a/ssl/t1_ext.c
+++ b/ssl/t1_ext.c
@@ -131,6 +131,25 @@ int custom_ext_add(SSL *s, int server,
return 1;
}
+/* Copy the flags from src to dst for any extensions that exist in both */
+int custom_exts_copy_flags(custom_ext_methods *dst,
+ const custom_ext_methods *src)
+{
+ size_t i;
+ custom_ext_method *methsrc = src->meths;
+
+ for (i = 0; i < src->meths_count; i++, methsrc++) {
+ custom_ext_method *methdst = custom_ext_find(dst, methsrc->ext_type);
+
+ if (methdst == NULL)
+ continue;
+
+ methdst->ext_flags = methsrc->ext_flags;
+ }
+
+ return 1;
+}
+
/* Copy table of custom extensions */
int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
{
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 32fd18f..20ebb8a 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -996,6 +996,207 @@ static int test_set_sigalgs(int idx)
return testresult;
}
+static int clntaddcb = 0;
+static int clntparsecb = 0;
+static int srvaddcb = 0;
+static int srvparsecb = 0;
+static int snicb = 0;
+
+#define TEST_EXT_TYPE1 0xff00
+
+static int add_cb(SSL *s, unsigned int ext_type, const unsigned char **out,
+ size_t *outlen, int *al, void *add_arg)
+{
+ int *server = (int *)add_arg;
+ unsigned char *data;
+
+ if (SSL_is_server(s))
+ srvaddcb++;
+ else
+ clntaddcb++;
+
+ if (*server != SSL_is_server(s)
+ || (data = OPENSSL_malloc(sizeof(*data))) == NULL)
+ return -1;
+
+ *data = 1;
+ *out = data;
+ *outlen = sizeof(char);
+ return 1;
+}
+
+static void free_cb(SSL *s, unsigned int ext_type, const unsigned char *out,
+ void *add_arg)
+{
+ OPENSSL_free((unsigned char *)out);
+}
+
+static int parse_cb(SSL *s, unsigned int ext_type, const unsigned char *in,
+ size_t inlen, int *al, void *parse_arg)
+{
+ int *server = (int *)parse_arg;
+
+ if (SSL_is_server(s))
+ srvparsecb++;
+ else
+ clntparsecb++;
+
+ if (*server != SSL_is_server(s)
+ || inlen != sizeof(char)
+ || *in != 1)
+ return -1;
+
+ return 1;
+}
+
+static int sni_cb(SSL *s, int *al, void *arg)
+{
+ SSL_CTX *ctx = (SSL_CTX *)arg;
+
+ if (SSL_set_SSL_CTX(s, ctx) == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+ }
+ snicb++;
+ return SSL_TLSEXT_ERR_OK;
+}
+
+/*
+ * Custom call back tests.
+ * Test 0: callbacks in TLSv1.2
+ * Test 1: callbacks in TLSv1.2 with SNI
+ */
+static int test_custom_exts(int tst)
+{
+ SSL_CTX *cctx = NULL, *sctx = NULL, *sctx2 = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0;
+ static int server = 1;
+ static int client = 0;
+ SSL_SESSION *sess = NULL;
+
+ /* Reset callback counters */
+ clntaddcb = clntparsecb = srvaddcb = srvparsecb = 0;
+ snicb = 0;
+
+ if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), &sctx,
+ &cctx, cert, privkey)) {
+ printf("Unable to create SSL_CTX pair\n");
+ goto end;
+ }
+
+ if (tst == 1
+ && !create_ssl_ctx_pair(TLS_server_method(), NULL, &sctx2, NULL,
+ cert, privkey)) {
+ printf("Unable to create SSL_CTX pair (2)\n");
+ goto end;
+ }
+
+ /* Create a client side custom extension */
+ if (!SSL_CTX_add_client_custom_ext(cctx, TEST_EXT_TYPE1, add_cb, free_cb,
+ &client, parse_cb, &client)) {
+ printf("Unable to add client custom extension\n");
+ goto end;
+ }
+
+ /* Should not be able to add duplicates */
+ if (SSL_CTX_add_client_custom_ext(cctx, TEST_EXT_TYPE1, add_cb, free_cb,
+ &client, parse_cb, &client)) {
+ printf("Unexpected success adding duplicate extension\n");
+ goto end;
+ }
+
+ /* Create a server side custom extension */
+ if (!SSL_CTX_add_server_custom_ext(sctx, TEST_EXT_TYPE1, add_cb, free_cb,
+ &server, parse_cb, &server)) {
+ printf("Unable to add server custom extension\n");
+ goto end;
+ }
+ if (sctx2 != NULL
+ && !SSL_CTX_add_server_custom_ext(sctx2, TEST_EXT_TYPE1,
+ add_cb, free_cb,
+ &server, parse_cb,
+ &server)) {
+ printf("Unable to add server custom extension for SNI\n");
+ goto end;
+ }
+
+ /* Should not be able to add duplicates */
+ if (SSL_CTX_add_server_custom_ext(sctx, TEST_EXT_TYPE1, add_cb, free_cb,
+ &server, parse_cb, &server)) {
+ printf("Unexpected success adding duplicate extension (2)\n");
+ goto end;
+ }
+
+ if (tst == 1) {
+ /* Set up SNI */
+ if (!SSL_CTX_set_tlsext_servername_callback(sctx, sni_cb)
+ || !SSL_CTX_set_tlsext_servername_arg(sctx, sctx2)) {
+ printf("Cannot set SNI callbacks\n");
+ goto end;
+ }
+ }
+
+ if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)
+ || !create_ssl_connection(serverssl, clientssl)) {
+ printf("Cannot create SSL connection\n");
+ goto end;
+ }
+
+ if (clntaddcb != 1
+ || clntparsecb != 1
+ || srvaddcb != 1
+ || srvparsecb != 1
+ || (tst != 1 && snicb != 0)
+ || (tst == 1 && snicb != 1)) {
+ printf("Incorrect callback counts\n");
+ goto end;
+ }
+
+ sess = SSL_get1_session(clientssl);
+ SSL_shutdown(clientssl);
+ SSL_shutdown(serverssl);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ serverssl = clientssl = NULL;
+
+ if (tst == 1) {
+ /* We don't bother with the resumption aspects for this test */
+ testresult = 1;
+ goto end;
+ }
+
+ if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)
+ || !SSL_set_session(clientssl, sess)
+ || !create_ssl_connection(serverssl, clientssl)) {
+ printf("Cannot create resumption connection\n");
+ goto end;
+ }
+
+ /*
+ * For a resumed session we expect to add the ClientHello extension but we
+ * should ignore it on the server side.
+ */
+ if (clntaddcb != 2
+ || clntparsecb != 1
+ || srvaddcb != 1
+ || srvparsecb != 1) {
+ printf("Incorrect resumption callback counts\n");
+ goto end;
+ }
+
+ testresult = 1;
+
+end:
+ SSL_SESSION_free(sess);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx2);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ return testresult;
+}
+
int main(int argc, char *argv[])
{
BIO *err = NULL;
@@ -1031,6 +1232,7 @@ int main(int argc, char *argv[])
ADD_TEST(test_ssl_bio_change_rbio);
ADD_TEST(test_ssl_bio_change_wbio);
ADD_ALL_TESTS(test_set_sigalgs, OSSL_NELEM(testsigalgs) * 2);
+ ADD_ALL_TESTS(test_custom_exts, 2);
testresult = run_tests(argv[0]);
diff --git a/test/ssltestlib.c b/test/ssltestlib.c
index 192a7ab..8725491 100644
--- a/test/ssltestlib.c
+++ b/test/ssltestlib.c
@@ -531,8 +531,9 @@ int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm,
SSL_CTX *clientctx = NULL;
serverctx = SSL_CTX_new(sm);
- clientctx = SSL_CTX_new(cm);
- if (serverctx == NULL || clientctx == NULL) {
+ if (cctx != NULL)
+ clientctx = SSL_CTX_new(cm);
+ if (serverctx == NULL || (cctx != NULL && clientctx == NULL)) {
printf("Failed to create SSL_CTX\n");
goto err;
}
@@ -556,7 +557,8 @@ int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm,
#endif
*sctx = serverctx;
- *cctx = clientctx;
+ if (cctx != NULL)
+ *cctx = clientctx;
return 1;
err:
More information about the openssl-commits
mailing list