Test that the peers send at most one fatal alert
authorEmilia Kasper <emilia@openssl.org>
Fri, 12 Aug 2016 12:29:24 +0000 (14:29 +0200)
committerEmilia Kasper <emilia@openssl.org>
Thu, 18 Aug 2016 10:49:32 +0000 (12:49 +0200)
Duplicate alerts have happened, see
70c22888c1648fe8652e77107f3c74bf2212de36

Reviewed-by: Rich Salz <rsalz@openssl.org>
test/README.ssltest.md
test/handshake_helper.c
test/handshake_helper.h
test/ssl_test.c

index 9c27da0..4e9c0e1 100644 (file)
@@ -82,7 +82,11 @@ handshake.
   - InternalError - some other error
 
 * ExpectedClientAlert, ExpectedServerAlert - expected alert. See
-  `ssl_test_ctx.c` for known values.
+  `ssl_test_ctx.c` for known values. Note: the expected alert is currently
+  matched against the _last_ received alert (i.e., a fatal alert or a
+  `close_notify`). Warning alert expectations are not yet supported. (A warning
+  alert will not be correctly matched, if followed by a `close_notify` or
+  another alert.)
 
 * ExpectedProtocol - expected negotiated protocol. One of
   SSLv3, TLSv1, TLSv1.1, TLSv1.2.
index 6b5f834..409f16c 100644 (file)
@@ -41,6 +41,7 @@ void HANDSHAKE_RESULT_free(HANDSHAKE_RESULT *result)
  */
 typedef struct handshake_ex_data_st {
     int alert_sent;
+    int num_fatal_alerts_sent;
     int alert_received;
     int session_ticket_do_not_call;
     ssl_servername_t servername;
@@ -71,6 +72,9 @@ static void info_cb(const SSL *s, int where, int ret)
             (HANDSHAKE_EX_DATA*)(SSL_get_ex_data(s, ex_data_idx));
         if (where & SSL_CB_WRITE) {
             ex_data->alert_sent = ret;
+            if (strcmp(SSL_alert_type_string(ret), "F") == 0
+                || strcmp(SSL_alert_desc_string(ret), "CN") == 0)
+                ex_data->num_fatal_alerts_sent++;
         } else {
             ex_data->alert_received = ret;
         }
@@ -840,8 +844,10 @@ static HANDSHAKE_RESULT *do_handshake_internal(
     }
  err:
     ret->server_alert_sent = server_ex_data.alert_sent;
+    ret->server_num_fatal_alerts_sent = server_ex_data.num_fatal_alerts_sent;
     ret->server_alert_received = client_ex_data.alert_received;
     ret->client_alert_sent = client_ex_data.alert_sent;
+    ret->client_num_fatal_alerts_sent = client_ex_data.num_fatal_alerts_sent;
     ret->client_alert_received = server_ex_data.alert_received;
     ret->server_protocol = SSL_version(server.ssl);
     ret->client_protocol = SSL_version(client.ssl);
index 2fb8ac0..8425b2a 100644 (file)
 typedef struct handshake_result {
     ssl_test_result_t result;
     /* These alerts are in the 2-byte format returned by the info_callback. */
-    /* Alert sent by the client; 0 if no alert. */
+    /* (Latest) alert sent by the client; 0 if no alert. */
     int client_alert_sent;
-    /* Alert received by the server; 0 if no alert. */
+    /* Number of fatal or close_notify alerts sent. */
+    int client_num_fatal_alerts_sent;
+    /* (Latest) alert received by the server; 0 if no alert. */
     int client_alert_received;
-    /* Alert sent by the server; 0 if no alert. */
+    /* (Latest) alert sent by the server; 0 if no alert. */
     int server_alert_sent;
-    /* Alert received by the client; 0 if no alert. */
+    /* Number of fatal or close_notify alerts sent. */
+    int server_num_fatal_alerts_sent;
+    /* (Latest) alert received by the client; 0 if no alert. */
     int server_alert_received;
     /* Negotiated protocol. On success, these should always match. */
     int server_protocol;
index c2324bf..9f14618 100644 (file)
@@ -100,6 +100,16 @@ static int check_alerts(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
         return 0;
     }
 
+    if (result->client_num_fatal_alerts_sent > 1) {
+        fprintf(stderr, "Client sent %d fatal alerts.\n",
+                result->client_num_fatal_alerts_sent);
+        return 0;
+    }
+    if (result->server_num_fatal_alerts_sent > 1) {
+        fprintf(stderr, "Server sent %d alerts.\n",
+                result->server_num_fatal_alerts_sent);
+        return 0;
+    }
     return 1;
 }