summaryrefslogtreecommitdiffstats
path: root/ssl/statem/statem.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2017-11-23 12:10:54 +0000
committerMatt Caswell <matt@openssl.org>2017-12-04 13:31:48 +0000
commit47e2ee072290db534720565318f0a8110a2e7d92 (patch)
treede0339da635ef1d0d1905b242ee4ed9fbe174183 /ssl/statem/statem.c
parent635c8f771574fbf48281b2372a2f7aba0c673544 (diff)
Add some sanity checks for the fatal error condition
Sometimes at the top level of the state machine code we know we are supposed to be in a fatal error condition. This commit adds some sanity checks to ensure that SSLfatal() has been called. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/4778)
Diffstat (limited to 'ssl/statem/statem.c')
-rw-r--r--ssl/statem/statem.c51
1 files changed, 44 insertions, 7 deletions
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index db2de6e3bf..5c158fa24d 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -125,6 +125,19 @@ void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
}
/*
+ * This macro should only be called if we are already expecting to be in
+ * a fatal error state. We verify that we are, and set it if not (this would
+ * indicate a bug).
+ */
+#define check_fatal(s, f) \
+ do { \
+ if (!ossl_assert((s)->statem.in_init \
+ || (s)->statem.state != MSG_FLOW_ERROR)) \
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, (f), \
+ SSL_R_MISSING_FATAL); \
+ } while (0)
+
+/*
* Discover whether the current connection is in the error state.
*
* Valid return values are:
@@ -321,17 +334,21 @@ static int state_machine(SSL *s, int server)
if (cb != NULL)
cb(s, SSL_CB_HANDSHAKE_START, 1);
+ /*
+ * Fatal errors in this block don't send an alert because we have
+ * failed to even initialise properly. Sending an alert is probably
+ * doomed to failure.
+ */
+
if (SSL_IS_DTLS(s)) {
if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
(server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) {
- /* We've failed to even initialise so no alert sent */
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
}
} else {
if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
- /* We've failed to even initialise so no alert sent */
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
@@ -339,7 +356,6 @@ static int state_machine(SSL *s, int server)
}
if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
- /* We've failed to even initialise so no alert sent */
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
@@ -347,9 +363,13 @@ static int state_machine(SSL *s, int server)
if (s->init_buf == NULL) {
if ((buf = BUF_MEM_new()) == NULL) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
goto end;
}
if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
goto end;
}
s->init_buf = buf;
@@ -357,6 +377,8 @@ static int state_machine(SSL *s, int server)
}
if (!ssl3_setup_buffers(s)) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
goto end;
}
s->init_num = 0;
@@ -374,13 +396,17 @@ static int state_machine(SSL *s, int server)
if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
#endif
if (!ssl_init_wbio_buffer(s)) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
goto end;
}
if ((SSL_in_before(s))
|| s->renegotiate) {
- if (!tls_setup_handshake(s))
+ if (!tls_setup_handshake(s)) {
+ /* SSLfatal() already called */
goto end;
+ }
if (SSL_IS_FIRST_HANDSHAKE(s))
st->read_state_first_init = 1;
@@ -413,8 +439,8 @@ static int state_machine(SSL *s, int server)
}
} else {
/* Error */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ check_fatal(s, SSL_F_STATE_MACHINE);
+ SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
goto end;
}
}
@@ -557,6 +583,7 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
* to that state if so
*/
if (!transition(s, mt)) {
+ check_fatal(s, SSL_F_READ_STATE_MACHINE);
return SUB_STATE_ERROR;
}
@@ -602,6 +629,7 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
switch (ret) {
case MSG_PROCESS_ERROR:
+ check_fatal(s, SSL_F_READ_STATE_MACHINE);
return SUB_STATE_ERROR;
case MSG_PROCESS_FINISHED_READING:
@@ -625,6 +653,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
st->read_state_work = post_process_message(s, st->read_state_work);
switch (st->read_state_work) {
case WORK_ERROR:
+ check_fatal(s, SSL_F_READ_STATE_MACHINE);
+ /* Fall through */
case WORK_MORE_A:
case WORK_MORE_B:
case WORK_MORE_C:
@@ -760,6 +790,7 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
break;
case WRITE_TRAN_ERROR:
+ check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
return SUB_STATE_ERROR;
}
break;
@@ -767,6 +798,8 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
case WRITE_STATE_PRE_WORK:
switch (st->write_state_work = pre_work(s, st->write_state_work)) {
case WORK_ERROR:
+ check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+ /* Fall through */
case WORK_MORE_A:
case WORK_MORE_B:
case WORK_MORE_C:
@@ -798,7 +831,7 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
}
if (confunc != NULL && !confunc(s, &pkt)) {
WPACKET_cleanup(&pkt);
- /* SSLfatal() already called */
+ check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
return SUB_STATE_ERROR;
}
if (!ssl_close_construct_packet(s, &pkt, mt)
@@ -826,6 +859,8 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
case WRITE_STATE_POST_WORK:
switch (st->write_state_work = post_work(s, st->write_state_work)) {
case WORK_ERROR:
+ check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+ /* Fall through */
case WORK_MORE_A:
case WORK_MORE_B:
case WORK_MORE_C:
@@ -841,6 +876,8 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
break;
default:
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
}