forked from wolfSSL/wolfssl
Sniffer Chain Input
Add a new method for handling input records where the input is in the form of an iovec list.
This commit is contained in:
@@ -266,7 +266,8 @@ static const char* const msgTable[] =
|
|||||||
|
|
||||||
/* 91 */
|
/* 91 */
|
||||||
"No data destination Error",
|
"No data destination Error",
|
||||||
"Store data callback failed"
|
"Store data callback failed",
|
||||||
|
"Loading chain input"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -3562,7 +3563,8 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
|
|||||||
/* 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** session,
|
||||||
int* sslBytes, const byte** end, char* error)
|
int* sslBytes, const byte** end,
|
||||||
|
void* vChain, word32 chainSz, char* error)
|
||||||
{
|
{
|
||||||
word32 length;
|
word32 length;
|
||||||
SSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
|
SSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
|
||||||
@@ -3604,7 +3606,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
|
|||||||
|
|
||||||
/* if current partial data, add to end of partial */
|
/* if current partial data, add to end of partial */
|
||||||
/* if skipping, the data is already at the end of partial */
|
/* if skipping, the data is already at the end of partial */
|
||||||
if ( !skipPartial &&
|
if ( !skipPartial && !vChain &&
|
||||||
(length = ssl->buffers.inputBuffer.length) ) {
|
(length = ssl->buffers.inputBuffer.length) ) {
|
||||||
Trace(PARTIAL_ADD_STR);
|
Trace(PARTIAL_ADD_STR);
|
||||||
|
|
||||||
@@ -3621,6 +3623,44 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
|
|||||||
*end = *sslFrame + *sslBytes;
|
*end = *sslFrame + *sslBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vChain != NULL) {
|
||||||
|
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
|
||||||
|
struct iovec* chain = (struct iovec*)vChain;
|
||||||
|
word32 i, offset, headerOffset, qty;
|
||||||
|
|
||||||
|
Trace(CHAIN_INPUT_STR);
|
||||||
|
headerOffset = (word32)*sslFrame - (word32)chain[0].iov_base;
|
||||||
|
length = *sslBytes + headerOffset;
|
||||||
|
if (length > ssl->buffers.inputBuffer.bufferSize) {
|
||||||
|
if (GrowInputBuffer(ssl, length, 0) < 0) {
|
||||||
|
SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
for (i = 0; i < chainSz; i++) {
|
||||||
|
/* In case there is extra data in the chain that isn't covered
|
||||||
|
* by the sizes in the TCP headers, don't copy too much. This
|
||||||
|
* case has been seen where there are 4 extra bytes in the
|
||||||
|
* packet capture than the TCP header indicates. */
|
||||||
|
if (offset + chain[i].iov_len > length)
|
||||||
|
qty = length - offset;
|
||||||
|
else
|
||||||
|
qty = (word32)chain[i].iov_len;
|
||||||
|
XMEMCPY(ssl->buffers.inputBuffer.buffer + offset,
|
||||||
|
chain[i].iov_base, qty);
|
||||||
|
offset += qty;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl->buffers.inputBuffer.length = length;
|
||||||
|
*sslFrame = ssl->buffers.inputBuffer.buffer + headerOffset;
|
||||||
|
*end = *sslFrame + *sslBytes;
|
||||||
|
#else
|
||||||
|
(void)chainSz;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
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]);
|
||||||
@@ -3637,6 +3677,8 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef STARTTLS_ALLOWED
|
#ifdef STARTTLS_ALLOWED
|
||||||
|
if (ssl->buffers.inputBuffer.dynamicFlag)
|
||||||
|
ShrinkInputBuffer(ssl, NO_FORCED_FREE);
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -4008,6 +4050,7 @@ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
|
|||||||
/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
|
/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
|
||||||
/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
|
/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
|
||||||
static int ssl_DecodePacketInternal(const byte* packet, int length,
|
static int ssl_DecodePacketInternal(const byte* packet, int length,
|
||||||
|
void* vChain, word32 chainSz,
|
||||||
byte** data, SSLInfo* sslInfo,
|
byte** data, SSLInfo* sslInfo,
|
||||||
void* ctx, char* error)
|
void* ctx, char* error)
|
||||||
{
|
{
|
||||||
@@ -4019,6 +4062,18 @@ static int ssl_DecodePacketInternal(const byte* packet, int length,
|
|||||||
int ret;
|
int ret;
|
||||||
SnifferSession* session = 0;
|
SnifferSession* session = 0;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
|
||||||
|
if (packet == NULL && vChain != NULL) {
|
||||||
|
struct iovec* chain = (struct iovec*)vChain;
|
||||||
|
word32 i;
|
||||||
|
|
||||||
|
length = 0;
|
||||||
|
for (i = 0; i < chainSz; i++)
|
||||||
|
length += chain[i].iov_len;
|
||||||
|
packet = (const byte*)chain[0].iov_base;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
|
if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
|
||||||
error) != 0)
|
error) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -4051,7 +4106,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
|
ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
|
||||||
&end, error);
|
&end, vChain, chainSz, error);
|
||||||
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
|
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
|
||||||
else if (ret == -1) return -1;
|
else if (ret == -1) return -1;
|
||||||
else if (ret == 1) {
|
else if (ret == 1) {
|
||||||
@@ -4088,7 +4143,8 @@ static int ssl_DecodePacketInternal(const byte* packet, int length,
|
|||||||
int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length,
|
int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length,
|
||||||
unsigned char** data, SSLInfo* sslInfo, char* error)
|
unsigned char** data, SSLInfo* sslInfo, char* error)
|
||||||
{
|
{
|
||||||
return ssl_DecodePacketInternal(packet, length, data, sslInfo, NULL, error);
|
return ssl_DecodePacketInternal(packet, length, NULL, 0, data, sslInfo,
|
||||||
|
NULL, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4096,7 +4152,8 @@ int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length,
|
|||||||
/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
|
/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
|
||||||
int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
|
int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
|
||||||
{
|
{
|
||||||
return ssl_DecodePacketInternal(packet, length, data, NULL, NULL, error);
|
return ssl_DecodePacketInternal(packet, length, NULL, 0, data, NULL, NULL,
|
||||||
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4105,7 +4162,33 @@ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
|
|||||||
int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet,
|
int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet,
|
||||||
int length, void* ctx, SSLInfo* sslInfo, char* error)
|
int length, void* ctx, SSLInfo* sslInfo, char* error)
|
||||||
{
|
{
|
||||||
return ssl_DecodePacketInternal(packet, length, NULL, sslInfo, ctx, error);
|
return ssl_DecodePacketInternal(packet, length, NULL, 0, NULL, sslInfo,
|
||||||
|
ctx, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
|
||||||
|
|
||||||
|
int ssl_DecodePacketWithChain(void* vChain, word32 chainSz, byte** data,
|
||||||
|
char* error)
|
||||||
|
{
|
||||||
|
return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, data, NULL, NULL,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \
|
||||||
|
defined(WOLFSSL_SNIFFER_STORE_DATA_CB)
|
||||||
|
|
||||||
|
int ssl_DecodePacketWithChainSessionInfoStoreData(void* vChain, word32 chainSz,
|
||||||
|
void* ctx, SSLInfo* sslInfo, char* error)
|
||||||
|
{
|
||||||
|
return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, NULL, sslInfo,
|
||||||
|
ctx, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -72,6 +72,25 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* A TLS record can be 16k and change. The chain is broken up into 2K chunks.
|
||||||
|
* This covers the TLS record, plus a chunk for TCP/IP headers. */
|
||||||
|
#ifndef CHAIN_INPUT_CHUNK_SIZE
|
||||||
|
#define CHAIN_INPUT_CHUNK_SIZE 2048
|
||||||
|
#elif (CHAIN_INPUT_CHUNK_SIZE < 256)
|
||||||
|
#undef CHAIN_INPUT_CHUNK_SIZE
|
||||||
|
#define CHAIN_INPUT_CHUNK_SIZE 256
|
||||||
|
#elif (CHAIN_INPUT_CHUNK_SIZE > 16384)
|
||||||
|
#undef CHAIN_INPUT_CHUNK_SIZE
|
||||||
|
#define CHAIN_INPUT_CHUNK_SIZE 16384
|
||||||
|
#endif
|
||||||
|
#define CHAIN_INPUT_COUNT ((16384 / CHAIN_INPUT_CHUNK_SIZE) + 1)
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef STORE_DATA_BLOCK_SZ
|
||||||
|
#define STORE_DATA_BLOCK_SZ 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
pcap_t* pcap = NULL;
|
pcap_t* pcap = NULL;
|
||||||
pcap_if_t* alldevs = NULL;
|
pcap_if_t* alldevs = NULL;
|
||||||
|
|
||||||
@@ -170,6 +189,16 @@ static char* iptos(unsigned int addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_SNIFFER_STORE_DATA_CB) || defined(WOLFSSL_SNIFFER_CHAIN_INPUT)
|
||||||
|
|
||||||
|
static inline unsigned int min(unsigned int a, unsigned int b)
|
||||||
|
{
|
||||||
|
return a > b ? b : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_SNIFFER_WATCH
|
#ifdef WOLFSSL_SNIFFER_WATCH
|
||||||
|
|
||||||
const byte rsaHash[] = {
|
const byte rsaHash[] = {
|
||||||
@@ -228,8 +257,7 @@ static int myStoreDataCb(const unsigned char* decryptBuf,
|
|||||||
if (decryptBufSz < decryptBufOffset)
|
if (decryptBufSz < decryptBufOffset)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
qty = (decryptBufSz - decryptBufOffset) < 32 ?
|
qty = min(decryptBufSz - decryptBufOffset, STORE_DATA_BLOCK_SZ);
|
||||||
(decryptBufSz - decryptBufOffset) : 32;
|
|
||||||
|
|
||||||
if (*data == NULL) {
|
if (*data == NULL) {
|
||||||
byte* tmpData;
|
byte* tmpData;
|
||||||
@@ -265,6 +293,10 @@ int main(int argc, char** argv)
|
|||||||
struct bpf_program fp;
|
struct bpf_program fp;
|
||||||
pcap_if_t *d;
|
pcap_if_t *d;
|
||||||
pcap_addr_t *a;
|
pcap_addr_t *a;
|
||||||
|
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
|
||||||
|
struct iovec chain[CHAIN_INPUT_COUNT];
|
||||||
|
int chainSz;
|
||||||
|
#endif
|
||||||
|
|
||||||
signal(SIGINT, sig_handler);
|
signal(SIGINT, sig_handler);
|
||||||
|
|
||||||
@@ -443,13 +475,38 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
|
||||||
|
{
|
||||||
|
unsigned int j = 0;
|
||||||
|
unsigned int remainder = header.caplen;
|
||||||
|
|
||||||
#ifndef WOLFSSL_SNIFFER_STORE_DATA_CB
|
chainSz = 0;
|
||||||
ret = ssl_DecodePacketWithSessionInfo(packet, header.caplen, &data,
|
do {
|
||||||
&sslInfo, err);
|
unsigned int chunkSz;
|
||||||
#else
|
|
||||||
|
chunkSz = min(remainder, CHAIN_INPUT_CHUNK_SIZE);
|
||||||
|
chain[chainSz].iov_base = (void*)(packet + j);
|
||||||
|
chain[chainSz].iov_len = chunkSz;
|
||||||
|
j += chunkSz;
|
||||||
|
remainder -= chunkSz;
|
||||||
|
chainSz++;
|
||||||
|
} while (j < header.caplen);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \
|
||||||
|
defined(WOLFSSL_SNIFFER_STORE_DATA_CB)
|
||||||
|
ret = ssl_DecodePacketWithChainSessionInfoStoreData(chain, chainSz,
|
||||||
|
&data, &sslInfo, err);
|
||||||
|
#elif defined(WOLFSSL_SNIFFER_CHAIN_INPUT)
|
||||||
|
(void)sslInfo;
|
||||||
|
ret = ssl_DecodePacketWithChain(chain, chainSz, &data, err);
|
||||||
|
#elif defined(WOLFSSL_SNIFFER_STORE_DATA_CB)
|
||||||
ret = ssl_DecodePacketWithSessionInfoStoreData(packet,
|
ret = ssl_DecodePacketWithSessionInfoStoreData(packet,
|
||||||
header.caplen, &data, &sslInfo, err);
|
header.caplen, &data, &sslInfo, err);
|
||||||
|
#else
|
||||||
|
ret = ssl_DecodePacketWithSessionInfo(packet, header.caplen, &data,
|
||||||
|
&sslInfo, err);
|
||||||
#endif
|
#endif
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printf("ssl_Decode ret = %d, %s\n", ret, err);
|
printf("ssl_Decode ret = %d, %s\n", ret, err);
|
||||||
|
@@ -205,6 +205,17 @@ SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfoStoreData(
|
|||||||
const unsigned char* packet, int length, void* ctx,
|
const unsigned char* packet, int length, void* ctx,
|
||||||
SSLInfo* sslInfo, char* error);
|
SSLInfo* sslInfo, char* error);
|
||||||
|
|
||||||
|
|
||||||
|
WOLFSSL_API
|
||||||
|
SSL_SNIFFER_API int ssl_DecodePacketWithChain(void* vChain,
|
||||||
|
unsigned int chainSz, unsigned char** data, char* error);
|
||||||
|
|
||||||
|
|
||||||
|
WOLFSSL_API
|
||||||
|
SSL_SNIFFER_API int ssl_DecodePacketWithChainSessionInfoStoreData(
|
||||||
|
void* vChain, unsigned int chainSz, void* ctx, SSLInfo* sslInfo,
|
||||||
|
char* error);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
@@ -129,6 +129,7 @@
|
|||||||
|
|
||||||
#define NO_DATA_DEST_STR 91
|
#define NO_DATA_DEST_STR 91
|
||||||
#define STORE_DATA_FAIL_STR 92
|
#define STORE_DATA_FAIL_STR 92
|
||||||
|
#define CHAIN_INPUT_STR 93
|
||||||
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */
|
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */
|
||||||
|
|
||||||
|
|
||||||
|
@@ -111,5 +111,6 @@ STRINGTABLE
|
|||||||
|
|
||||||
91, "No data destination Error"
|
91, "No data destination Error"
|
||||||
92, "Store Data callback failed"
|
92, "Store Data callback failed"
|
||||||
|
93, "Loading chain input"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user