Provide an SSLfatal() macro
authorMatt Caswell <matt@openssl.org>
Thu, 23 Nov 2017 16:21:46 +0000 (16:21 +0000)
committerMatt Caswell <matt@openssl.org>
Mon, 4 Dec 2017 13:31:48 +0000 (13:31 +0000)
Typically if a fatal error occurs three things need to happen:

- Put an error on the error queue
- Send an alert
- Put the state machine into the error state

Although all 3 of these things need to be done every time we hit a fatal
error the responsibilities for doing this are distributed throughout the
code. The place where the error goes on the queue, where the alert gets
sent and where the state machine goes into the error state are almost
invariably different. It has been a common pattern to pass alert codes up
and down the stack to get the alert information from the point in the code
where the error is detected to the point in the code where the alert gets
sent.

This commit provides an SSLfatal() macro (backed by an ossl_statem_fatal
function) that does all 3 of the above error tasks. This is largely a drop
in replacement for SSLerr, but takes a couple of extra parameters (the SSL
object, and an alert code).

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4778)

ssl/statem/statem.c
ssl/statem/statem.h

index 0f3452216f5ae63a6a32e36859f49ff510874520..c9ac4fb571831485ee4680b37e7c0f14573dac91 100644 (file)
@@ -111,12 +111,23 @@ void ossl_statem_set_renegotiate(SSL *s)
 }
 
 /*
- * Put the state machine into an error state. This is a permanent error for
- * the current connection.
+ * Put the state machine into an error state and send an alert if appropriate.
+ * This is a permanent error for the current connection.
  */
-void ossl_statem_set_error(SSL *s)
+void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
+                       int line)
 {
+    s->statem.in_init = 1;
     s->statem.state = MSG_FLOW_ERROR;
+    ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
+    if (s->statem.hand_state != TLS_ST_BEFORE
+            && s->statem.hand_state != TLS_ST_CW_CLNT_HELLO) {
+        /*
+         * We only send an alert if we've got as far as actually sending or
+         * receiving a message.
+         */
+        ssl3_send_alert(s, SSL3_AL_FATAL, al);
+    }
 }
 
 /*
@@ -368,10 +379,8 @@ static int state_machine(SSL *s, int server)
 
         if ((SSL_in_before(s))
                 || s->renegotiate) {
-            if (!tls_setup_handshake(s)) {
-                ossl_statem_set_error(s);
+            if (!tls_setup_handshake(s))
                 goto end;
-            }
 
             if (SSL_IS_FIRST_HANDSHAKE(s))
                 st->read_state_first_init = 1;
@@ -404,7 +413,8 @@ static int state_machine(SSL *s, int server)
             }
         } else {
             /* Error */
-            ossl_statem_set_error(s);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_STATE_MACHINE,
+                     ERR_R_INTERNAL_ERROR);
             goto end;
         }
     }
index 98c82917f342feaabd81bf63b37641d9019d1f39..83bebe77e6ba589b69f1437a17fd115a66c7cef3 100644 (file)
@@ -114,7 +114,16 @@ __owur int ossl_statem_accept(SSL *s);
 __owur int ossl_statem_connect(SSL *s);
 void ossl_statem_clear(SSL *s);
 void ossl_statem_set_renegotiate(SSL *s);
-void ossl_statem_set_error(SSL *s);
+void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
+                       int line);
+# define SSL_AD_NO_ALERT    -1
+# ifndef OPENSSL_NO_ERR
+#  define SSLfatal(s, al, f, r)  ossl_statem_fatal((s), (al), (f), (r), \
+                                                   OPENSSL_FILE, OPENSSL_LINE)
+# else
+#  define SSLfatal(s, al, f, r)  ossl_statem_fatal((s), (al), (f), (r), NULL, 0)
+# endif
+
 int ossl_statem_in_error(const SSL *s);
 void ossl_statem_set_in_init(SSL *s, int init);
 int ossl_statem_get_in_handshake(SSL *s);