diff --git a/src/sniffer.c b/src/sniffer.c index 156f400fb..8696c5945 100644 --- a/src/sniffer.c +++ b/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 */ diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index 69757b7e4..67e942f03 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -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; diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index fedab6c06..28e26ba4e 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -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 diff --git a/wolfssl/sniffer_error.h b/wolfssl/sniffer_error.h index e3bc38b78..f3fe93ca4 100644 --- a/wolfssl/sniffer_error.h +++ b/wolfssl/sniffer_error.h @@ -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 !!!! */ diff --git a/wolfssl/sniffer_error.rc b/wolfssl/sniffer_error.rc index 336cf33e8..31e1317cc 100644 --- a/wolfssl/sniffer_error.rc +++ b/wolfssl/sniffer_error.rc @@ -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" }