X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fstatem%2Fstatem.c;h=5c158fa24d209b669946abe9dc4179f216a61245;hp=0f3452216f5ae63a6a32e36859f49ff510874520;hb=47e2ee072290db534720565318f0a8110a2e7d92;hpb=198c42f5af0d2cc0eb4789c7597b68b6b10cc97a diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c index 0f3452216f..5c158fa24d 100644 --- a/ssl/statem/statem.c +++ b/ssl/statem/statem.c @@ -111,14 +111,32 @@ 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 (al != SSL_AD_NO_ALERT) + ssl3_send_alert(s, SSL3_AL_FATAL, al); } +/* + * 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. * @@ -316,29 +334,42 @@ 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))) { - SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR); + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); goto end; } } else { if ((s->version >> 8) != SSL3_VERSION_MAJOR) { - SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR); + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); goto end; } } if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { - SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW); + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); goto end; } 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; @@ -346,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; @@ -363,13 +396,15 @@ 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)) { - ossl_statem_set_error(s); + /* SSLfatal() already called */ goto end; } @@ -404,7 +439,8 @@ static int state_machine(SSL *s, int server) } } else { /* Error */ - ossl_statem_set_error(s); + check_fatal(s, SSL_F_STATE_MACHINE); + SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR); goto end; } } @@ -547,13 +583,13 @@ static SUB_STATE_RETURN read_state_machine(SSL *s) * to that state if so */ if (!transition(s, mt)) { - ossl_statem_set_error(s); + check_fatal(s, SSL_F_READ_STATE_MACHINE); return SUB_STATE_ERROR; } if (s->s3->tmp.message_size > max_message_size(s)) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); - SSLerr(SSL_F_READ_STATE_MACHINE, SSL_R_EXCESSIVE_MESSAGE_SIZE); + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE, + SSL_R_EXCESSIVE_MESSAGE_SIZE); return SUB_STATE_ERROR; } @@ -562,8 +598,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s) && s->s3->tmp.message_size > 0 && !grow_init_buf(s, s->s3->tmp.message_size + SSL3_HM_HEADER_LENGTH)) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_BUF_LIB); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE, + ERR_R_BUF_LIB); return SUB_STATE_ERROR; } @@ -582,8 +618,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s) s->first_packet = 0; if (!PACKET_buf_init(&pkt, s->init_msg, len)) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_INTERNAL_ERROR); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); return SUB_STATE_ERROR; } ret = process_message(s, &pkt); @@ -593,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: @@ -616,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: @@ -635,9 +674,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s) default: /* Shouldn't happen */ - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_INTERNAL_ERROR); - ossl_statem_set_error(s); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); return SUB_STATE_ERROR; } } @@ -752,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; @@ -759,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: @@ -772,7 +813,7 @@ static SUB_STATE_RETURN write_state_machine(SSL *s) return SUB_STATE_END_HANDSHAKE; } if (!get_construct_message_f(s, &pkt, &confunc, &mt)) { - ossl_statem_set_error(s); + /* SSLfatal() already called */ return SUB_STATE_ERROR; } if (mt == SSL3_MT_DUMMY) { @@ -782,12 +823,22 @@ static SUB_STATE_RETURN write_state_machine(SSL *s) break; } if (!WPACKET_init(&pkt, s->init_buf) - || !ssl_set_handshake_header(s, &pkt, mt) - || (confunc != NULL && !confunc(s, &pkt)) - || !ssl_close_construct_packet(s, &pkt, mt) + || !ssl_set_handshake_header(s, &pkt, mt)) { + WPACKET_cleanup(&pkt); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + if (confunc != NULL && !confunc(s, &pkt)) { + WPACKET_cleanup(&pkt); + check_fatal(s, SSL_F_WRITE_STATE_MACHINE); + return SUB_STATE_ERROR; + } + if (!ssl_close_construct_packet(s, &pkt, mt) || !WPACKET_finish(&pkt)) { WPACKET_cleanup(&pkt); - ossl_statem_set_error(s); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); return SUB_STATE_ERROR; } @@ -808,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: @@ -823,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; } }