forked from wolfSSL/wolfssl
Store Data Callback
Added a callback and support to allow one to handle storing the data directly without reallocating the data buffer. Also added an example that uses this callback if the callback is enabled in the build.
This commit is contained in:
108
src/sniffer.c
108
src/sniffer.c
@@ -261,7 +261,12 @@ static const char* const msgTable[] =
|
||||
"Watch callback not set",
|
||||
"Watch hash failed",
|
||||
"Watch callback failed",
|
||||
"Bad Certificate Message"
|
||||
"Bad Certificate Message",
|
||||
"Store data callback not set",
|
||||
|
||||
/* 91 */
|
||||
"No data destination Error",
|
||||
"Store data callback failed"
|
||||
};
|
||||
|
||||
|
||||
@@ -437,6 +442,11 @@ static WOLFSSL_GLOBAL SSLWatchCb WatchCb;
|
||||
static WOLFSSL_GLOBAL void* WatchCbCtx = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
|
||||
/* Store Data Callback */
|
||||
static WOLFSSL_GLOBAL SSLStoreDataCb StoreDataCb;
|
||||
#endif
|
||||
|
||||
|
||||
static void UpdateMissedDataSessions(void)
|
||||
{
|
||||
@@ -3707,7 +3717,7 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
|
||||
/* return Number of bytes on success, 0 for no data yet, and -1 on error */
|
||||
static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
|
||||
int sslBytes, byte** data, const byte* end,
|
||||
char* error)
|
||||
void* ctx, char* error)
|
||||
{
|
||||
const byte* sslBegin = sslFrame;
|
||||
const byte* recordEnd; /* end of record indicator */
|
||||
@@ -3839,22 +3849,55 @@ doPart:
|
||||
ret = ssl->buffers.clearOutputBuffer.length;
|
||||
TraceGotData(ret);
|
||||
if (ret) { /* may be blank message */
|
||||
byte* tmpData; /* don't leak on realloc free */
|
||||
/* add an extra byte at end of allocation in case user
|
||||
* wants to null terminate plaintext */
|
||||
tmpData = (byte*)XREALLOC(*data, decoded + ret + 1,
|
||||
NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (tmpData == NULL) {
|
||||
ForceZero(*data, decoded);
|
||||
XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
*data = NULL;
|
||||
SetError(MEMORY_STR, error, session,
|
||||
FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
if (data != NULL) {
|
||||
byte* tmpData; /* don't leak on realloc free */
|
||||
/* add an extra byte at end of allocation in case
|
||||
* user wants to null terminate plaintext */
|
||||
tmpData = (byte*)XREALLOC(*data, decoded + ret + 1,
|
||||
NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (tmpData == NULL) {
|
||||
ForceZero(*data, decoded);
|
||||
XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
*data = NULL;
|
||||
SetError(MEMORY_STR, error, session,
|
||||
FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
*data = tmpData;
|
||||
XMEMCPY(*data + decoded,
|
||||
ssl->buffers.clearOutputBuffer.buffer, ret);
|
||||
}
|
||||
else {
|
||||
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
|
||||
if (StoreDataCb) {
|
||||
const byte* buf;
|
||||
word32 offset = 0;
|
||||
word32 bufSz;
|
||||
int stored;
|
||||
|
||||
buf = ssl->buffers.clearOutputBuffer.buffer;
|
||||
bufSz = ssl->buffers.clearOutputBuffer.length;
|
||||
do {
|
||||
stored = StoreDataCb(buf, bufSz, offset,
|
||||
ctx);
|
||||
if (stored <= 0) {
|
||||
return -1;
|
||||
}
|
||||
offset += stored;
|
||||
} while (offset < bufSz);
|
||||
}
|
||||
else {
|
||||
SetError(STORE_DATA_CB_MISSING_STR, error,
|
||||
session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
(void)ctx;
|
||||
SetError(NO_DATA_DEST_STR, error, session,
|
||||
FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
*data = tmpData;
|
||||
XMEMCPY(*data + decoded,
|
||||
ssl->buffers.clearOutputBuffer.buffer, ret);
|
||||
TraceAddedData(ret, decoded);
|
||||
decoded += ret;
|
||||
ssl->buffers.clearOutputBuffer.length = 0;
|
||||
@@ -3965,7 +4008,8 @@ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
|
||||
/* 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 */
|
||||
static int ssl_DecodePacketInternal(const byte* packet, int length,
|
||||
byte** data, SSLInfo* sslInfo, char* error)
|
||||
byte** data, SSLInfo* sslInfo,
|
||||
void* ctx, char* error)
|
||||
{
|
||||
TcpInfo tcpInfo;
|
||||
IpInfo ipInfo;
|
||||
@@ -4028,7 +4072,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length,
|
||||
INC_STAT(SnifferStats.sslDecryptedPackets);
|
||||
#endif
|
||||
|
||||
ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
|
||||
ret = ProcessMessage(sslFrame, session, sslBytes, data, end, ctx, error);
|
||||
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
|
||||
if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) {
|
||||
CopySessionInfo(session, sslInfo);
|
||||
@@ -4044,7 +4088,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length,
|
||||
int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length,
|
||||
unsigned char** data, SSLInfo* sslInfo, char* error)
|
||||
{
|
||||
return ssl_DecodePacketInternal(packet, length, data, sslInfo, error);
|
||||
return ssl_DecodePacketInternal(packet, length, data, sslInfo, NULL, error);
|
||||
}
|
||||
|
||||
|
||||
@@ -4052,10 +4096,21 @@ int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length,
|
||||
/* 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)
|
||||
{
|
||||
return ssl_DecodePacketInternal(packet, length, data, NULL, error);
|
||||
return ssl_DecodePacketInternal(packet, length, data, NULL, NULL, error);
|
||||
}
|
||||
|
||||
|
||||
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
|
||||
|
||||
int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet,
|
||||
int length, void* ctx, SSLInfo* sslInfo, char* error)
|
||||
{
|
||||
return ssl_DecodePacketInternal(packet, length, NULL, sslInfo, ctx, error);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Deallocator for the decoded data buffer. */
|
||||
/* returns 0 on success, -1 on error */
|
||||
int ssl_FreeDecodeBuffer(byte** data, char* error)
|
||||
@@ -4310,5 +4365,16 @@ int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType,
|
||||
|
||||
#endif /* WOLFSSL_SNIFFER_WATCH */
|
||||
|
||||
|
||||
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
|
||||
|
||||
int ssl_SetStoreDataCallback(SSLStoreDataCb cb)
|
||||
{
|
||||
StoreDataCb = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */
|
||||
|
||||
#endif /* WOLFSSL_SNIFFER */
|
||||
#endif /* WOLFCRYPT_ONLY */
|
||||
|
@@ -214,6 +214,42 @@ static int myWatchCb(void* vSniffer,
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
|
||||
|
||||
static int myStoreDataCb(const unsigned char* decryptBuf,
|
||||
unsigned int decryptBufSz, unsigned int decryptBufOffset, void* ctx)
|
||||
{
|
||||
byte** data = (byte**)ctx;
|
||||
unsigned int qty;
|
||||
|
||||
if (data == NULL)
|
||||
return -1;
|
||||
|
||||
if (decryptBufSz < decryptBufOffset)
|
||||
return -1;
|
||||
|
||||
qty = (decryptBufSz - decryptBufOffset) < 32 ?
|
||||
(decryptBufSz - decryptBufOffset) : 32;
|
||||
|
||||
if (*data == NULL) {
|
||||
byte* tmpData;
|
||||
tmpData = (byte*)realloc(*data, decryptBufSz + 1);
|
||||
if (tmpData == NULL) {
|
||||
free(*data);
|
||||
*data = NULL;
|
||||
return -1;
|
||||
}
|
||||
*data = tmpData;
|
||||
}
|
||||
|
||||
memcpy(*data + decryptBufOffset, decryptBuf + decryptBufOffset, qty);
|
||||
|
||||
return qty;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -240,6 +276,9 @@ int main(int argc, char** argv)
|
||||
#ifdef WOLFSSL_SNIFFER_WATCH
|
||||
ssl_SetWatchKeyCallback(myWatchCb, err);
|
||||
#endif
|
||||
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
|
||||
ssl_SetStoreDataCallback(myStoreDataCb);
|
||||
#endif
|
||||
|
||||
if (argc == 1) {
|
||||
/* normal case, user chooses device and port */
|
||||
@@ -405,8 +444,13 @@ int main(int argc, char** argv)
|
||||
else
|
||||
continue;
|
||||
|
||||
#ifndef WOLFSSL_SNIFFER_STORE_DATA_CB
|
||||
ret = ssl_DecodePacketWithSessionInfo(packet, header.caplen, &data,
|
||||
&sslInfo, err);
|
||||
#else
|
||||
ret = ssl_DecodePacketWithSessionInfoStoreData(packet,
|
||||
header.caplen, &data, &sslInfo, err);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
printf("ssl_Decode ret = %d, %s\n", ret, err);
|
||||
hadBadPacket = 1;
|
||||
|
@@ -194,6 +194,17 @@ SSL_SNIFFER_API int ssl_SetWatchKey_file(void* vSniffer,
|
||||
const char* password, char* error);
|
||||
|
||||
|
||||
typedef int (*SSLStoreDataCb)(const unsigned char* decryptBuf,
|
||||
unsigned int decryptBufSz, unsigned int decryptBufOffset, void* ctx);
|
||||
|
||||
WOLFSSL_API
|
||||
SSL_SNIFFER_API int ssl_SetStoreDataCallback(SSLStoreDataCb cb);
|
||||
|
||||
WOLFSSL_API
|
||||
SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfoStoreData(
|
||||
const unsigned char* packet, int length, void* ctx,
|
||||
SSLInfo* sslInfo, char* error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
@@ -125,6 +125,10 @@
|
||||
#define WATCH_HASH_STR 87
|
||||
#define WATCH_FAIL_STR 88
|
||||
#define BAD_CERT_MSG_STR 89
|
||||
#define STORE_DATA_CB_MISSING_STR 90
|
||||
|
||||
#define NO_DATA_DEST_STR 91
|
||||
#define STORE_DATA_FAIL_STR 92
|
||||
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */
|
||||
|
||||
|
||||
|
@@ -107,5 +107,9 @@ STRINGTABLE
|
||||
87, "Watch hash failed"
|
||||
88, "Watch callback failed"
|
||||
89, "Bad Certificate Message"
|
||||
90, "Store data callback not set"
|
||||
|
||||
91, "No data destination Error"
|
||||
92, "Store Data callback failed"
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user