Fixes for async sniffer handling of packets with multiple TLS messages. Other minor cleanups for spelling and `CheckPreRecord` `SnifferSession` deference.

pull/5734/head
David Garske 2022-10-25 13:46:25 -07:00
parent e7a121325b
commit fe28702891
2 changed files with 66 additions and 38 deletions

View File

@ -3733,7 +3733,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
#endif #endif
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
if (session->sslServer->error != WC_PENDING_E) if (session->sslServer->error != WC_PENDING_E && session->pendSeq == 0)
#endif #endif
{ {
/* hash server_hello */ /* hash server_hello */
@ -4412,7 +4412,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
#ifdef WOLFSSL_TLS13 #ifdef WOLFSSL_TLS13
if (type != client_hello && type != server_hello if (type != client_hello && type != server_hello
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
&& session->sslServer->error != WC_PENDING_E && session->sslServer->error != WC_PENDING_E && session->pendSeq == 0
#endif #endif
) { ) {
/* For resumption the hash is before / after client_hello PSK binder */ /* For resumption the hash is before / after client_hello PSK binder */
@ -4492,11 +4492,10 @@ static int DoHandShake(const byte* input, int* sslBytes,
case client_key_exchange: case client_key_exchange:
Trace(GOT_CLIENT_KEY_EX_STR); Trace(GOT_CLIENT_KEY_EX_STR);
#ifdef HAVE_EXTENDED_MASTER #ifdef HAVE_EXTENDED_MASTER
#ifdef WOLFSSL_ASYNC_CRYPT if (session->flags.expectEms) {
if (session->sslServer->error != WC_PENDING_E) /* on async reentry the session->hash is already copied
#endif * and free'd */
{ if (session->hash != NULL) {
if (session->flags.expectEms && session->hash != NULL) {
if (HashCopy(session->sslServer->hsHashes, if (HashCopy(session->sslServer->hsHashes,
session->hash) == 0 && session->hash) == 0 &&
HashCopy(session->sslClient->hsHashes, HashCopy(session->sslClient->hsHashes,
@ -4514,10 +4513,10 @@ static int DoHandShake(const byte* input, int* sslBytes,
XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
session->hash = NULL; session->hash = NULL;
} }
else { }
session->sslServer->options.haveEMS = 0; else {
session->sslClient->options.haveEMS = 0; session->sslServer->options.haveEMS = 0;
} session->sslClient->options.haveEMS = 0;
} }
#endif #endif
if (ret == 0) { if (ret == 0) {
@ -5437,7 +5436,11 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
if (real < *expected) { if (real < *expected) {
if (real + *sslBytes > *expected) { if (real + *sslBytes > *expected) {
if (session->sslServer->error != WC_PENDING_E) { #ifdef WOLFSSL_ASYNC_CRYPT
if (session->sslServer->error != WC_PENDING_E &&
session->pendSeq != tcpInfo->sequence)
#endif
{
Trace(OVERLAP_DUPLICATE_STR); Trace(OVERLAP_DUPLICATE_STR);
} }
@ -5488,7 +5491,11 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
if (*sslBytes > 0) { if (*sslBytes > 0) {
/* If packet has data attempt to process packet, if hasn't /* If packet has data attempt to process packet, if hasn't
* already been ack'd during handshake */ * already been ack'd during handshake */
if (session->sslServer->error != WC_PENDING_E && if (
#ifdef WOLFSSL_ASYNC_CRYPT
session->sslServer->error != WC_PENDING_E &&
session->pendSeq != tcpInfo->sequence &&
#endif
FindPrevAck(session, real)) { FindPrevAck(session, real)) {
Trace(DUPLICATE_STR); Trace(DUPLICATE_STR);
ret = 1; ret = 1;
@ -5733,8 +5740,7 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
/* check if this session is pending */ /* check if this session is pending */
if (session->sslServer->error == WC_PENDING_E && if (session->pendSeq != 0 && session->pendSeq != tcpInfo->sequence) {
session->pendSeq != tcpInfo->sequence) {
/* this stream is processing, queue packet */ /* this stream is processing, queue packet */
return WC_PENDING_E; return WC_PENDING_E;
} }
@ -5773,38 +5779,56 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
/* Check Status before record processing */ /* Check Status before record processing */
/* returns 0 on success (continue), -1 on error, 1 on success (end) */ /* returns 0 on success (continue), -1 on error, 1 on success (end) */
static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
const byte** sslFrame, SnifferSession** session, const byte** sslFrame, SnifferSession** pSession,
int* sslBytes, const byte** end, int* sslBytes, const byte** end,
void* vChain, word32 chainSz, char* error) void* vChain, word32 chainSz, char* error)
{ {
word32 length; word32 length;
WOLFSSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ? SnifferSession* session = *pSession;
(*session)->sslServer : (*session)->sslClient; WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ? session->sslServer : session->sslClient;
(*session)->flags.srvSkipPartial : byte skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
(*session)->flags.cliSkipPartial; session->flags.srvSkipPartial :
session->flags.cliSkipPartial;
#ifdef WOLFSSL_ASYNC_CRYPT
/* if this is a pending async packet do not "grow" on partial (we already did) */
if (session->pendSeq == tcpInfo->sequence) {
if (session->sslServer->error == WC_PENDING_E) {
return 0; /* don't check pre-record again */
}
/* if record check already done then restore, otherwise process normal */
if (ssl->buffers.inputBuffer.length > 0) {
*sslBytes = ssl->buffers.inputBuffer.length;
*sslFrame = ssl->buffers.inputBuffer.buffer;
*end = *sslFrame + *sslBytes;
return 0;
}
}
#endif
/* remove SnifferSession on 2nd FIN or RST */ /* remove SnifferSession on 2nd FIN or RST */
if (tcpInfo->fin || tcpInfo->rst) { if (tcpInfo->fin || tcpInfo->rst) {
/* flag FIN and RST */ /* flag FIN and RST */
if (tcpInfo->fin) if (tcpInfo->fin)
(*session)->flags.finCount += 1; session->flags.finCount += 1;
else if (tcpInfo->rst) else if (tcpInfo->rst)
(*session)->flags.finCount += 2; session->flags.finCount += 2;
if ((*session)->flags.finCount >= 2) { if (session->flags.finCount >= 2) {
RemoveSession(*session, ipInfo, tcpInfo, 0); RemoveSession(session, ipInfo, tcpInfo, 0);
*session = NULL; *pSession = NULL;
return 1; return 1;
} }
} }
if ((*session)->flags.fatalError == FATAL_ERROR_STATE) { if (session->flags.fatalError == FATAL_ERROR_STATE) {
SetError(FATAL_ERROR_STR, error, NULL, 0); SetError(FATAL_ERROR_STR, error, NULL, 0);
return -1; return -1;
} }
if (skipPartial) { if (skipPartial) {
if (FindNextRecordInAssembly(*session, if (FindNextRecordInAssembly(session,
sslFrame, sslBytes, end, error) < 0) { sslFrame, sslBytes, end, error) < 0) {
return -1; return -1;
} }
@ -5823,7 +5847,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
return -1; return -1;
} }
} }
@ -5846,7 +5870,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
return -1; return -1;
} }
} }
@ -5876,14 +5900,14 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
} }
} }
if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) { if (session->flags.clientHello == 0 && **sslFrame != handshake) {
/* Sanity check the packet for an old style client hello. */ /* Sanity check the packet for an old style client hello. */
int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]); int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
if ((rhSize <= (*sslBytes - 2)) && if ((rhSize <= (*sslBytes - 2)) &&
(*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) { (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
#ifdef OLD_HELLO_ALLOWED #ifdef OLD_HELLO_ALLOWED
int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error); int ret = DoOldHello(session, *sslFrame, &rhSize, sslBytes, error);
if (ret < 0) if (ret < 0)
return -1; /* error already set */ return -1; /* error already set */
if (*sslBytes <= 0) if (*sslBytes <= 0)
@ -5982,7 +6006,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
const byte* recordEnd; /* end of record indicator */ const byte* recordEnd; /* end of record indicator */
const byte* inRecordEnd; /* indicator from input stream not decrypt */ const byte* inRecordEnd; /* indicator from input stream not decrypt */
RecordLayerHeader rh; RecordLayerHeader rh;
int rhSize = 0; int rhSize;
int ret; int ret;
int errCode = 0; int errCode = 0;
int decoded = 0; /* bytes stored for user in data */ int decoded = 0; /* bytes stored for user in data */
@ -5991,7 +6015,9 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
session->sslServer : session->sslClient; session->sslServer : session->sslClient;
doMessage: doMessage:
notEnough = 0; notEnough = 0;
rhSize = 0;
if (sslBytes < 0) { if (sslBytes < 0) {
SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE); SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
return -1; return -1;
@ -6003,8 +6029,9 @@ doMessage:
return 0; return 0;
} }
} }
else else {
notEnough = 1; notEnough = 1;
}
if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) { if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
/* don't have enough input yet to process full SSL record */ /* don't have enough input yet to process full SSL record */
@ -6031,7 +6058,7 @@ doMessage:
inRecordEnd = recordEnd; inRecordEnd = recordEnd;
/* Make sure cipher is on for client, if we get an application data packet /* Make sure cipher is on for client, if we get an application data packet
* and handhsake is done for server. This workaround is required if client * and handshake is done for server. This workaround is required if client
* handshake packets were missed, retransmitted or sent out of order. */ * handshake packets were missed, retransmitted or sent out of order. */
if ((enum ContentType)rh.type == application_data && if ((enum ContentType)rh.type == application_data &&
ssl->options.handShakeDone && session->flags.serverCipherOn) { ssl->options.handShakeDone && session->flags.serverCipherOn) {
@ -6431,7 +6458,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
session->sslServer->error = ret; session->sslServer->error = ret;
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
/* capture the seq pending for this session */ /* capture the seq pending for this session */
session->pendSeq = tcpInfo.sequence; session->pendSeq = (ret == WC_PENDING_E) ? tcpInfo.sequence : 0;
if (ret == WC_PENDING_E) { if (ret == WC_PENDING_E) {
session->flags.wasPolled = 0; session->flags.wasPolled = 0;
@ -6892,6 +6919,7 @@ int ssl_PollSniffer(WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags,
SnifferSession* session = FindSession(ssl); SnifferSession* session = FindSession(ssl);
if (session) { if (session) {
session->flags.wasPolled = 1; session->flags.wasPolled = 1;
session->sslServer->error = events[i]->ret;
} }
} }
wc_UnLockMutex(&SessionMutex); wc_UnLockMutex(&SessionMutex);

View File

@ -545,7 +545,7 @@ static int SnifferAsyncPollQueue(byte** data, char* err, SSLInfo* sslInfo,
if (ret == 0) { if (ret == 0) {
/* attempt to reprocess pending packet */ /* attempt to reprocess pending packet */
#ifdef DEBUG_SNIFFER #ifdef DEBUG_SNIFFER
printf("Retrying packet %d\n", asyncQueue[i].packetNumber); printf("Packet Number: %d (retry)\n", asyncQueue[i].packetNumber);
#endif #endif
ret = ssl_DecodePacketAsync(asyncQueue[i].packet, ret = ssl_DecodePacketAsync(asyncQueue[i].packet,
asyncQueue[i].length, 0, data, err, sslInfo, NULL); asyncQueue[i].length, 0, data, err, sslInfo, NULL);
@ -828,7 +828,7 @@ int main(int argc, char** argv)
/* grab next pcap packet */ /* grab next pcap packet */
packetNumber++; packetNumber++;
packet = pcap_next(pcap, &header); packet = pcap_next(pcap, &header);
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(DEBUG_SNIFFER) #ifdef DEBUG_SNIFFER
printf("Packet Number: %d\n", packetNumber); printf("Packet Number: %d\n", packetNumber);
#endif #endif
} }