Skip to content

Commit

Permalink
If we have a capture on device 'any', then we need to handle the offset
Browse files Browse the repository at this point in the history
Detect reading of packet errors

--enable-all and --enable-sniffer exposed this issue

Don't need variable

Rework argument parsing

Need a way to allow arguments to be supplied more granularly. Partucilarly, I needed a "-tracefile" argument without requiring the use of a PCAP file

Fix error prints to STDERR

Fix setting of port filtering

Fix 80 char limit

Not actually a bad packet when there are no more packets

Fix strcat size

Allow the sniffer to print the trace to STDOUT

Fix indexing

Take out superfluous error which is handled later

Set default port to 11111

Single return point

Combine chain to one contiguous memory block

Fix return

Add in error handling for XMALLOC

Add in debugging output when --enable-debug

It makes no sense to allocate a ton of small buffers to process chains

Ultimately, the code is slower because of the several small memcpy instead of a single large contiguous memcpy

Pass in a device name

Fix unused variable

Fix cast

Addressing PR comments

Add new flags to --help
  • Loading branch information
Andras Fekete committed Oct 29, 2024
1 parent 0ded8ba commit 2cdecd8
Show file tree
Hide file tree
Showing 4 changed files with 313 additions and 298 deletions.
164 changes: 80 additions & 84 deletions src/sniffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -4292,8 +4292,8 @@ static int KeyWatchCall(SnifferSession* session, const byte* data, int dataSz,
char* error)
{
int ret;
Sha256 sha;
byte digest[SHA256_DIGEST_SIZE];
wc_Sha256 sha;
byte digest[WC_SHA256_DIGEST_SIZE];

if (WatchCb == NULL) {
SetError(WATCH_CB_MISSING_STR, error, session, FATAL_ERROR_STATE);
Expand Down Expand Up @@ -6023,8 +6023,7 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
/* returns 0 on success (continue), -1 on error, 1 on success (end) */
static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
const byte** sslFrame, SnifferSession** pSession,
int* sslBytes, const byte** end,
void* vChain, word32 chainSz, char* error)
int* sslBytes, const byte** end, char* error)
{
word32 length;
SnifferSession* session = *pSession;
Expand Down Expand Up @@ -6094,53 +6093,12 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
return WOLFSSL_FATAL_ERROR;
}
}
if (vChain == NULL) {
XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
*sslFrame, *sslBytes);
*sslBytes += length;
ssl->buffers.inputBuffer.length = *sslBytes;
*sslFrame = ssl->buffers.inputBuffer.buffer;
*end = *sslFrame + *sslBytes;
}
else {
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
struct iovec* chain = (struct iovec*)vChain;
word32 i, offset, headerSz, qty, remainder;

Trace(CHAIN_INPUT_STR);
headerSz = (word32)((const byte*)*sslFrame - (const byte*)chain[0].iov_base);
remainder = *sslBytes;

if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
return WOLFSSL_FATAL_ERROR;
}
}

qty = min(*sslBytes, (word32)chain[0].iov_len - headerSz);
XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
(byte*)chain[0].iov_base + headerSz, qty);
offset = length;
for (i = 1; i < chainSz; i++) {
offset += qty;
remainder -= qty;

if (chain[i].iov_len > remainder)
qty = remainder;
else
qty = (word32)chain[i].iov_len;
XMEMCPY(ssl->buffers.inputBuffer.buffer + offset,
chain[i].iov_base, qty);
}

*sslBytes += length;
ssl->buffers.inputBuffer.length = *sslBytes;
*sslFrame = ssl->buffers.inputBuffer.buffer;
*end = *sslFrame + *sslBytes;
#endif
(void)chainSz;
}
XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
*sslFrame, *sslBytes);
*sslBytes += length;
ssl->buffers.inputBuffer.length = *sslBytes;
*sslFrame = ssl->buffers.inputBuffer.buffer;
*end = *sslFrame + *sslBytes;
}

if (session->flags.clientHello == 0 && **sslFrame != handshake) {
Expand Down Expand Up @@ -6616,27 +6574,33 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
{
TcpInfo tcpInfo;
IpInfo ipInfo;
byte* tmpPacket = NULL; /* Assemble the chain */
const byte* sslFrame;
const byte* end;
int sslBytes; /* ssl bytes unconsumed */
int ret;
SnifferSession* session = NULL;
void* vChain = NULL;
word32 chainSz = 0;

if (isChain) {
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
struct iovec* chain;
word32 i;

vChain = (void*)packet;
chainSz = (word32)length;
word32 chainSz = (word32)length;

chain = (struct iovec*)vChain;
chain = (struct iovec*)packet;
length = 0;
for (i = 0; i < chainSz; i++)
for (i = 0; i < chainSz; i++) length += chain[i].iov_len;

tmpPacket = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_SNIFFER_CHAIN_BUFFER);
if (tmpPacket == NULL) return MEMORY_E;

length = 0;
for (i = 0; i < chainSz; i++) {
XMEMCPY(tmpPacket+length,chain[i].iov_base,chain[i].iov_len);
length += chain[i].iov_len;
packet = (const byte*)chain[0].iov_base;
}
packet = (const byte*)tmpPacket;
#else
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
return WOLFSSL_SNIFFER_ERROR;
Expand All @@ -6645,18 +6609,27 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,

if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
error, 1, 1) != 0) {
return WOLFSSL_SNIFFER_ERROR;
ret = WOLFSSL_SNIFFER_ERROR;
goto exit_decode;
}

end = sslFrame + sslBytes;

ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
return WOLFSSL_SNIFFER_FATAL_ERROR;
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
ret = WOLFSSL_SNIFFER_FATAL_ERROR;
goto exit_decode;
}
#ifdef WOLFSSL_ASYNC_CRYPT
else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return WC_PENDING_E;
else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = WC_PENDING_E;
goto exit_decode;
}
#endif
else if (ret == -1) return WOLFSSL_SNIFFER_ERROR;
else if (ret == -1) {
ret = WOLFSSL_SNIFFER_ERROR;
goto exit_decode;
}
else if (ret == 1) {
#ifdef WOLFSSL_SNIFFER_STATS
if (sslBytes > 0) {
Expand All @@ -6669,46 +6642,59 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
INC_STAT(SnifferStats.sslDecryptedPackets);
}
#endif
return 0; /* done for now */
ret = 0;
goto exit_decode; /* done for now */
}

#ifdef WOLFSSL_ASYNC_CRYPT
session->userCtx = ctx;
#endif

ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
return WOLFSSL_SNIFFER_FATAL_ERROR;
else if (ret == -1) return WOLFSSL_SNIFFER_ERROR;
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
ret = WOLFSSL_SNIFFER_FATAL_ERROR;
goto exit_decode;
}
else if (ret == -1) {
ret = WOLFSSL_SNIFFER_ERROR;
goto exit_decode;
}
else if (ret == 1) {
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslDecryptedPackets);
#endif
return 0; /* done for now */
ret = 0;
goto exit_decode; /* done for now */
}
else if (ret != 0) {
/* return specific error case */
return ret;
goto exit_decode; /* return specific error case */
}

ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
&end, vChain, chainSz, error);
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
return WOLFSSL_SNIFFER_FATAL_ERROR;
else if (ret == -1) return WOLFSSL_SNIFFER_ERROR;
&end, error);
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
ret = WOLFSSL_SNIFFER_FATAL_ERROR;
goto exit_decode;
}
else if (ret == -1) {
ret = WOLFSSL_SNIFFER_ERROR;
goto exit_decode;
}
else if (ret == 1) {
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslDecryptedPackets);
#endif
return 0; /* done for now */
ret = 0;
goto exit_decode; /* done for now */
}

#ifdef WOLFSSL_ASYNC_CRYPT
/* make sure this server was polled */
if (asyncOkay &&
session->sslServer->error == WC_NO_ERR_TRACE(WC_PENDING_E) &&
!session->flags.wasPolled) {
return WC_PENDING_E;
ret = WC_PENDING_E;
goto exit_decode;
}
#endif

Expand Down Expand Up @@ -6745,7 +6731,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
wolfSSL_AsyncPoll(session->sslServer, WOLF_POLL_FLAG_CHECK_HW);
}
else {
return ret; /* return to caller */
goto exit_decode; /* return to caller */
}
}
else {
Expand All @@ -6756,12 +6742,18 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
(void)asyncOkay;
#endif

if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
return WOLFSSL_SNIFFER_FATAL_ERROR;
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
ret = WOLFSSL_SNIFFER_FATAL_ERROR;
goto exit_decode;
}
if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) {
CopySessionInfo(session, sslInfo);
}

exit_decode:
if (isChain) {
XFREE(tmpPacket, NULL, DYNAMIC_TYPE_SNIFFER_CHAIN_BUFFER);
}
return ret;
}

Expand Down Expand Up @@ -6868,11 +6860,15 @@ int ssl_Trace(const char* traceFile, char* error)
if (traceFile) {
/* Don't try to reopen the file */
if (TraceFile == NULL) {
TraceFile = XFOPEN(traceFile, "a");
if (!TraceFile) {
SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
return WOLFSSL_FATAL_ERROR;
}
if (XSTRCMP(traceFile, "-") == 0) {
TraceFile = stdout;
} else {
TraceFile = XFOPEN(traceFile, "a");
if (!TraceFile) {
SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
return WOLFSSL_FATAL_ERROR;
}
}
TraceOn = 1;
}
}
Expand Down
2 changes: 1 addition & 1 deletion sslSniffer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ Frees all resources consumed by the wolfSSL sniffer and should be called when us
int ssl_Trace(const char* traceFile, char* error);
```
Enables Tracing when a file is passed in. Disables Tracing if previously on and a NULL value is passed in for the file.
Enables Tracing when a file is passed in. When `traceFile` is "-", then the trace will be printed to STDOUT. Disables Tracing if previously on and a NULL value is passed in for the file.
Returns Values:
Expand Down
Loading

0 comments on commit 2cdecd8

Please sign in to comment.