diff --git a/src/internal.c b/src/internal.c index 7a0096ba6..897babad7 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1162,7 +1162,7 @@ static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, exp[idx++] = options->havePeerVerify; exp[idx++] = options->usingPSK_cipher; exp[idx++] = options->usingAnon_cipher; - exp[idx++] = options->sendAlertState; + exp[idx++] = 0; /* Historical: options->sendAlertState */ exp[idx++] = options->partialWrite; exp[idx++] = options->quietShutdown; exp[idx++] = options->groupMessages; @@ -1345,7 +1345,7 @@ static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, options->havePeerVerify = exp[idx++]; options->usingPSK_cipher = exp[idx++]; options->usingAnon_cipher = exp[idx++]; - options->sendAlertState = exp[idx++]; + idx++; /* Historical: options->sendAlertState */ options->partialWrite = exp[idx++]; options->quietShutdown = exp[idx++]; options->groupMessages = exp[idx++]; @@ -17276,6 +17276,10 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) } #endif + ret = RetrySendAlert(ssl); + if (ret != 0) + return ret; + for (;;) { switch (ssl->options.processReply) { @@ -20289,6 +20293,10 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) } } + ret = RetrySendAlert(ssl); + if (ret != 0) + return ret; + for (;;) { byte* out; byte* sendBuffer = (byte*)data + sent; /* may switch on comp */ @@ -20554,6 +20562,19 @@ startScr: return size; } +int RetrySendAlert(WOLFSSL* ssl) +{ + int type = ssl->pendingAlert.code; + int severity = ssl->pendingAlert.level; + + if (severity == alert_none) + return 0; + + ssl->pendingAlert.code = 0; + ssl->pendingAlert.level = alert_none; + + return SendAlert(ssl, severity, type); +} /* send alert message */ int SendAlert(WOLFSSL* ssl, int severity, int type) @@ -20587,14 +20608,24 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) } #endif - /* if sendalert is called again for nonblocking */ - if (ssl->options.sendAlertState != 0) { - ret = SendBuffered(ssl); - if (ret == 0) - ssl->options.sendAlertState = 0; - return ret; + if (ssl->pendingAlert.level != alert_none) { + ret = RetrySendAlert(ssl); + if (ret != 0) { + if (ssl->pendingAlert.level == alert_none || + (ssl->pendingAlert.level != alert_fatal && + severity == alert_fatal)) { + /* Store current alert if pendingAlert if free or if current + * is fatal and previous was not */ + ssl->pendingAlert.code = type; + ssl->pendingAlert.level = severity; + } + return ret; + } } + ssl->pendingAlert.code = type; + ssl->pendingAlert.level = severity; + #ifdef OPENSSL_EXTRA if (ssl->CBIS != NULL) { ssl->CBIS(ssl, SSL_CB_ALERT, type); @@ -20607,16 +20638,8 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) /* check for available size */ outputSz = ALERT_SIZE + MAX_MSG_EXTRA + dtlsExtra; - if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) { - /* If CheckAvailableSize returned WANT_WRITE due to a blocking write - * then discard pending output and just send the alert. */ - if (ret != WANT_WRITE || severity != alert_fatal) - return ret; - ShrinkOutputBuffer(ssl); - if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) { - return ret; - } - } + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; /* Check output buffer */ if (ssl->buffers.outputBuffer.buffer == NULL) @@ -20670,10 +20693,12 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) #endif ssl->buffers.outputBuffer.length += sendSz; - ssl->options.sendAlertState = 1; ret = SendBuffered(ssl); + ssl->pendingAlert.code = 0; + ssl->pendingAlert.level = alert_none; + WOLFSSL_LEAVE("SendAlert", ret); return ret; diff --git a/src/ssl.c b/src/ssl.c index a5e75178d..f628aefef 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -11778,6 +11778,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)) int neededState; #endif + int ret = 0; + + (void)ret; WOLFSSL_ENTER("SSL_connect()"); @@ -11820,14 +11823,16 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, if ((ssl->ConnectFilter(ssl, ssl->ConnectFilter_arg, &res) == WOLFSSL_SUCCESS) && (res == WOLFSSL_NETFILTER_REJECT)) { - WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); + ssl->error = SOCKET_FILTERED_E; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } #endif /* WOLFSSL_WOLFSENTRY_HOOKS */ if (ssl->options.side != WOLFSSL_CLIENT_END) { - WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + ssl->error = SIDE_ERROR; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -11846,7 +11851,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, && ssl->error != WC_PENDING_E #endif ) { - if ( (ssl->error = SendBuffered(ssl)) == 0) { + if ( (ret = SendBuffered(ssl)) == 0) { /* fragOffset is non-zero when sending fragments. On the last * fragment, fragOffset is zero again, and the state can be * advanced. */ @@ -11870,11 +11875,19 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } } else { + ssl->error = ret; WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + switch (ssl->options.connectState) { case CONNECT_BEGIN : @@ -12117,6 +12130,8 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, FreeAsyncCtx(ssl, 1); #endif + ssl->error = 0; /* clear the error */ + WOLFSSL_LEAVE("SSL_connect()", WOLFSSL_SUCCESS); return WOLFSSL_SUCCESS; #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */ @@ -12207,6 +12222,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, word16 haveAnon = 0; word16 haveMcast = 0; #endif + int ret = 0; + + (void)ret; if (ssl == NULL) return WOLFSSL_FATAL_ERROR; @@ -12238,7 +12256,8 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, if ((ssl->AcceptFilter(ssl, ssl->AcceptFilter_arg, &res) == WOLFSSL_SUCCESS) && (res == WOLFSSL_NETFILTER_REJECT)) { - WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); + ssl->error = SOCKET_FILTERED_E; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } @@ -12264,7 +12283,8 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, (void)haveMcast; if (ssl->options.side != WOLFSSL_SERVER_END) { - WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + ssl->error = SIDE_ERROR; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -12303,7 +12323,8 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif { WOLFSSL_MSG("accept error: server key required"); - WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } @@ -12326,7 +12347,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, && ssl->error != WC_PENDING_E #endif ) { - if ( (ssl->error = SendBuffered(ssl)) == 0) { + if ( (ret = SendBuffered(ssl)) == 0) { /* fragOffset is non-zero when sending fragments. On the last * fragment, fragOffset is zero again, and the state can be * advanced. */ @@ -12355,11 +12376,19 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } } else { + ssl->error = ret; WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + switch (ssl->options.acceptState) { case ACCEPT_BEGIN : @@ -12589,6 +12618,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } } #endif + ssl->error = 0; /* clear the error */ WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS); return WOLFSSL_SUCCESS; diff --git a/src/tls13.c b/src/tls13.c index a88b15c7e..a0c0f85cf 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -8689,6 +8689,8 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, */ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) { + int ret = 0; + WOLFSSL_ENTER("wolfSSL_connect_TLSv13()"); #ifdef HAVE_ERRNO_H @@ -8696,7 +8698,8 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) #endif if (ssl->options.side != WOLFSSL_CLIENT_END) { - WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + ssl->error = SIDE_ERROR; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -8706,7 +8709,8 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) if ((ssl->ConnectFilter(ssl, ssl->ConnectFilter_arg, &res) == WOLFSSL_SUCCESS) && (res == WOLFSSL_NETFILTER_REJECT)) { - WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); + ssl->error = SOCKET_FILTERED_E; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } @@ -8719,7 +8723,7 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) && ssl->error != WC_PENDING_E #endif ) { - if ((ssl->error = SendBuffered(ssl)) == 0) { + if ((ret = SendBuffered(ssl)) == 0) { /* fragOffset is non-zero when sending fragments. On the last * fragment, fragOffset is zero again, and the state can be * advanced. */ @@ -8743,11 +8747,19 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) #endif } else { + ssl->error = ret; WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + switch (ssl->options.connectState) { case CONNECT_BEGIN: @@ -8946,6 +8958,8 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) FreeAsyncCtx(ssl, 1); #endif + ssl->error = 0; /* clear the error */ + WOLFSSL_LEAVE("wolfSSL_connect_TLSv13()", WOLFSSL_SUCCESS); return WOLFSSL_SUCCESS; @@ -9609,6 +9623,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) #if !defined(NO_CERTS) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) word16 havePSK = 0; #endif + int ret = 0; WOLFSSL_ENTER("SSL_accept_TLSv13()"); #ifdef HAVE_ERRNO_H @@ -9620,7 +9635,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) #endif if (ssl->options.side != WOLFSSL_SERVER_END) { - WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + ssl->error = SIDE_ERROR; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -9630,7 +9646,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) if ((ssl->AcceptFilter(ssl, ssl->AcceptFilter_arg, &res) == WOLFSSL_SUCCESS) && (res == WOLFSSL_NETFILTER_REJECT)) { - WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); + ssl->error = SOCKET_FILTERED_E; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } @@ -9654,7 +9671,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) !ssl->buffers.certificate->buffer) { WOLFSSL_MSG("accept error: server cert required"); - WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -9672,7 +9690,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) #endif { WOLFSSL_MSG("accept error: server key required"); - WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } @@ -9687,7 +9706,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) && ssl->error != WC_PENDING_E #endif ) { - if ((ssl->error = SendBuffered(ssl)) == 0) { + if ((ret = SendBuffered(ssl)) == 0) { /* fragOffset is non-zero when sending fragments. On the last * fragment, fragOffset is zero again, and the state can be * advanced. */ @@ -9718,11 +9737,19 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) } } else { + ssl->error = ret; WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } } + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + switch (ssl->options.acceptState) { #ifdef HAVE_SECURE_RENEGOTIATION @@ -9983,6 +10010,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) FreeAsyncCtx(ssl, 1); #endif + ssl->error = 0; /* clear the error */ + WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS); return WOLFSSL_SUCCESS; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 879d862c8..0462aca36 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3692,7 +3692,6 @@ typedef struct Options { word16 usingPSK_cipher:1; /* are using psk as cipher */ word16 usingAnon_cipher:1; /* are we using an anon cipher */ word16 noPskDheKe:1; /* Don't use (EC)DHE with PSK */ - word16 sendAlertState:1; /* nonblocking resume */ word16 partialWrite:1; /* only one msg per write call */ word16 quietShutdown:1; /* don't send close notify */ word16 certOnly:1; /* stop once we get cert */ @@ -4324,6 +4323,7 @@ struct WOLFSSL { ClientSession* clientSession; #endif WOLFSSL_ALERT_HISTORY alert_history; + WOLFSSL_ALERT pendingAlert; int error; int rfd; /* read file descriptor */ int wfd; /* write file descriptor */ @@ -4839,6 +4839,7 @@ WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL* ssl); WOLFSSL_LOCAL int SendBuffered(WOLFSSL* ssl); WOLFSSL_LOCAL int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek); WOLFSSL_LOCAL int SendFinished(WOLFSSL* ssl); +WOLFSSL_LOCAL int RetrySendAlert(WOLFSSL* ssl); WOLFSSL_LOCAL int SendAlert(WOLFSSL* ssl, int severity, int type); WOLFSSL_LOCAL int ProcessReply(WOLFSSL* ssl); WOLFSSL_LOCAL int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index acaa49c66..dec4a4a8a 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -769,6 +769,7 @@ enum AlertDescription { enum AlertLevel { + alert_none = 0, /* Used to indicate no alert level is set */ alert_warning = 1, alert_fatal = 2 };