From cd4b23b2c9f4a26d303e433656fc32c9b672bf89 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 16 Mar 2018 11:05:17 +0100
Subject: [PATCH] Adds test for bad client certificate

---
 UnitTest1/unittest1.cpp     | 21 ++++++---
 picoquic_t/picoquic_t.c     |  3 +-
 picoquictest/picoquictest.h |  1 +
 picoquictest/tls_api_test.c | 86 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 101 insertions(+), 10 deletions(-)

diff --git a/UnitTest1/unittest1.cpp b/UnitTest1/unittest1.cpp
index 00d0044d..8dc463c6 100644
--- a/UnitTest1/unittest1.cpp
+++ b/UnitTest1/unittest1.cpp
@@ -26,16 +26,16 @@
 using namespace Microsoft::VisualStudio::CppUnitTestFramework;
 
 namespace UnitTest1
-{		
+{
 	TEST_CLASS(UnitTest1)
 	{
 	public:
-		TEST_METHOD(test_picohash)
-		{
+		    TEST_METHOD(test_picohash)
+		    {
             int ret = picohash_test();
 
-            Assert::AreEqual(ret, 0); 
-		}
+            Assert::AreEqual(ret, 0);
+		    }
 
         TEST_METHOD(test_cnxcreation)
         {
@@ -462,7 +462,7 @@ namespace UnitTest1
             int ret = set_verify_certificate_callback_test();
 
             Assert::AreEqual(ret, 0);
-	}
+        }
 
         TEST_METHOD(test_request_client_authentication)
         {
@@ -498,5 +498,12 @@ namespace UnitTest1
 
             Assert::AreEqual(ret, 0);
         }
-    };
+
+        TEST_METHOD(test_bad_client_certificate)
+        {
+            int ret = bad_client_certificate_test();
+
+            Assert::AreEqual(ret, 0);
+        }
+  };
 }
diff --git a/picoquic_t/picoquic_t.c b/picoquic_t/picoquic_t.c
index 7bc09f03..63866efb 100644
--- a/picoquic_t/picoquic_t.c
+++ b/picoquic_t/picoquic_t.c
@@ -100,7 +100,8 @@ static const picoquic_test_def_t test_table[] = {
     { "different_params", tls_different_params_test },
     { "wrong_tls_version", wrong_tls_version_test },
     { "set_certificate_and_key", set_certificate_and_key_test },
-    { "request_client_authentication", request_client_authentication_test }
+    { "request_client_authentication", request_client_authentication_test },
+    { "bad_client_certificate", bad_client_certificate_test }
 };
 
 static size_t const nb_tests = sizeof(test_table) / sizeof(picoquic_test_def_t);
diff --git a/picoquictest/picoquictest.h b/picoquictest/picoquictest.h
index 0b561aa6..e6c2b1c0 100644
--- a/picoquictest/picoquictest.h
+++ b/picoquictest/picoquictest.h
@@ -95,6 +95,7 @@ int wrong_tls_version_test();
 int set_certificate_and_key_test();
 int transport_param_stream_id_test();
 int request_client_authentication_test();
+int bad_client_certificate_test();
 
 #ifdef __cplusplus
 }
diff --git a/picoquictest/tls_api_test.c b/picoquictest/tls_api_test.c
index af6f9fe0..15bc3aed 100644
--- a/picoquictest/tls_api_test.c
+++ b/picoquictest/tls_api_test.c
@@ -2423,8 +2423,10 @@ int bad_certificate_test()
         else if (test_ctx->cnx_client->cnx_state != picoquic_state_disconnected) {
             ret = -1;
         }
-        else if (
-            test_ctx->cnx_client->local_error != PICOQUIC_TLS_HANDSHAKE_FAILED) {
+        else if (picoquic_get_local_error(test_ctx->cnx_client) != PICOQUIC_TLS_HANDSHAKE_FAILED) {
+            ret = -1;
+        }
+        else if (picoquic_get_remote_error(test_ctx->cnx_server) != PICOQUIC_TLS_HANDSHAKE_FAILED) {
             ret = -1;
         }
         else {
@@ -2770,3 +2772,83 @@ int request_client_authentication_test()
 
     return ret;
 }
+
+int bad_client_certificate_test()
+{
+    uint64_t simulated_time = 0;
+    uint64_t loss_mask = 0;
+    picoquic_test_tls_api_ctx_t* test_ctx = NULL;
+    int ret = tls_api_init_ctx(&test_ctx, 0, "test-sni", "test-alpn", &simulated_time, NULL, 0, 0);
+
+    /* Delete the client context, and recreate with a certificate */
+    if (ret == 0)
+    {
+        if (test_ctx->qclient != NULL) {
+            picoquic_free(test_ctx->qclient);
+            test_ctx->cnx_client = NULL;
+        }
+
+        test_ctx->qclient = picoquic_create(8,
+#ifdef _WINDOWS
+#ifdef _WINDOWS64
+            "..\\..\\certs\\badcert.pem", "..\\..\\certs\\key.pem",
+#else
+            "..\\certs\\badcert.pem", "..\\certs\\key.pem",
+#endif
+#else
+            "certs/badcert.pem", "certs/key.pem",
+#endif
+            NULL, test_api_callback, (void*)&test_ctx->client_callback, NULL, NULL, NULL,
+            simulated_time, &simulated_time, NULL, NULL, 0);
+
+        if (test_ctx->qclient == NULL) {
+            ret = -1;
+        }
+    }
+
+    /* recreate the client connection */
+    if (ret == 0) {
+        test_ctx->cnx_client = picoquic_create_cnx(test_ctx->qclient, picoquic_null_connection_id,
+                                                   picoquic_null_connection_id,
+                                                   (struct sockaddr*)&test_ctx->server_addr, 0,
+                                                   0, "test-sni", "test-alpn", 1);
+
+        if (test_ctx->cnx_client == NULL) {
+            ret = -1;
+        } else {
+            ret = picoquic_start_client_cnx(test_ctx->cnx_client);
+        }
+    }
+
+    if (ret == 0) {
+        picoquic_set_client_authentication(test_ctx->qserver, 1);
+    }
+
+    /* Proceed with the connection loop. It should fail */
+    if (ret == 0) {
+        ret = tls_api_connection_loop(test_ctx, &loss_mask, 0, &simulated_time);
+
+        if (test_ctx->cnx_client == NULL) {
+            ret = -1;
+        }
+        else if (test_ctx->cnx_client->cnx_state != picoquic_state_disconnected) {
+            ret = -1;
+        }
+        else if (picoquic_get_local_error(test_ctx->cnx_server) != PICOQUIC_TLS_HANDSHAKE_FAILED) {
+            ret = -1;
+        }
+        else if (picoquic_get_remote_error(test_ctx->cnx_client) != PICOQUIC_TLS_HANDSHAKE_FAILED) {
+            ret = -1;
+        }
+        else {
+            ret = 0;
+        }
+    }
+
+    if (test_ctx != NULL) {
+        tls_api_delete_ctx(test_ctx);
+        test_ctx = NULL;
+    }
+
+    return ret;
+}
-- 
GitLab