diff --git a/src/sniffer.c b/src/sniffer.c index 96c633fe5..5db8f423c 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -245,7 +245,8 @@ static const char* const msgTable[] = /* 81 */ "Bad Decrypt Size", - "Extended Master Secret Hash Error" + "Extended Master Secret Hash Error", + "Handshake Message Split Across TLS Records" }; @@ -1016,6 +1017,23 @@ static void TraceRemovedSession(void) } +/* Show SSLInfo if provided and is valid. */ +static void TraceSessionInfo(SSLInfo* sslInfo) +{ + if (TraceOn) { + if (sslInfo != NULL && sslInfo->isValid) { + fprintf(TraceFile, + "\tver:(%u %u) suiteId:(%02x %02x) suiteName:(%s)\n", + sslInfo->protocolVersionMajor, + sslInfo->protocolVersionMinor, + sslInfo->serverCipherSuite0, + sslInfo->serverCipherSuite, + sslInfo->serverCipherSuiteName); + } + } +} + + /* Set user error string */ static void SetError(int idx, char* error, SnifferSession* session, int fatal) { @@ -2060,8 +2078,9 @@ static int DoHandShake(const byte* input, int* sslBytes, startBytes = *sslBytes; if (*sslBytes < size) { - SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE); - return -1; + Trace(SPLIT_HANDSHAKE_MSG_STR); + *sslBytes = 0; + return ret; } /* A session's arrays are released when the handshake is completed. */ @@ -3463,9 +3482,42 @@ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, } +/* Copies the session's infomation to the provided sslInfo. Skip copy if + * SSLInfo is not provided. */ +static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo) +{ + if (NULL != sslInfo) { + XMEMSET(sslInfo, 0, sizeof(SSLInfo)); + + /* Pass back Session Info after we have processed the Server Hello. */ + if (0 != session->sslServer->options.cipherSuite) { + const char* pCipher; + + sslInfo->isValid = 1; + sslInfo->protocolVersionMajor = session->sslServer->version.major; + sslInfo->protocolVersionMinor = session->sslServer->version.minor; + sslInfo->serverCipherSuite0 = + session->sslServer->options.cipherSuite0; + sslInfo->serverCipherSuite = + session->sslServer->options.cipherSuite; + + pCipher = wolfSSL_get_cipher(session->sslServer); + if (NULL != pCipher) { + XSTRNCPY((char*)sslInfo->serverCipherSuiteName, pCipher, + sizeof(sslInfo->serverCipherSuiteName)); + sslInfo->serverCipherSuiteName + [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0'; + } + TraceSessionInfo(sslInfo); + } + } +} + + /* 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 */ -int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) +static int ssl_DecodePacketInternal(const byte* packet, int length, + byte** data, SSLInfo* sslInfo, char* error) { TcpInfo tcpInfo; IpInfo ipInfo; @@ -3498,10 +3550,31 @@ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; CheckFinCapture(&ipInfo, &tcpInfo, session); + + CopySessionInfo(session, sslInfo); + return ret; } +/* 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 */ +/* Also returns Session Info if available */ +int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, + unsigned char** data, SSLInfo* sslInfo, char* error) +{ + return ssl_DecodePacketInternal(packet, length, data, sslInfo, error); +} + + +/* 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 */ +int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) +{ + return ssl_DecodePacketInternal(packet, length, data, NULL, error); +} + + /* Deallocator for the decoded data buffer. */ /* returns 0 on success, -1 on error */ int ssl_FreeDecodeBuffer(byte** data, char* error) diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index a2aec78ef..998d1d7b8 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -295,6 +295,7 @@ int main(int argc, char** argv) static int packetNumber = 0; struct pcap_pkthdr header; const unsigned char* packet = pcap_next(pcap, &header); + SSLInfo sslInfo; packetNumber++; if (packet) { @@ -307,7 +308,8 @@ int main(int argc, char** argv) else continue; - ret = ssl_DecodePacket(packet, header.caplen, &data, err); + ret = ssl_DecodePacketWithSessionInfo(packet, header.caplen, &data, + &sslInfo, err); 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 4bd9f42d7..2595d23be 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -93,6 +93,37 @@ enum { }; +/* + * New Sniffer API that provides read-only access to the TLS and cipher + * information associated with the SSL session. + */ + +#if defined(__GNUC__) + #define WOLFSSL_PACK __attribute__ ((packed)) +#else + #define WOLFSSL_PACK +#endif + + +typedef struct SSLInfo +{ + unsigned char isValid; + /* indicates if the info in this struct is valid: 0 = no, 1 = yes */ + unsigned char protocolVersionMajor; /* SSL Version: major */ + unsigned char protocolVersionMinor; /* SSL Version: minor */ + unsigned char serverCipherSuite0; /* first byte, normally 0 */ + unsigned char serverCipherSuite; /* second byte, actual suite */ + unsigned char serverCipherSuiteName[256]; + /* cipher name, e.g., "TLS_RSA_..." */ +} WOLFSSL_PACK SSLInfo; + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfo( + const unsigned char* packet, int length, + unsigned char** data, SSLInfo* sslInfo, char* error); + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/sniffer_error.h b/wolfssl/sniffer_error.h index 8c813b198..0af7079a1 100644 --- a/wolfssl/sniffer_error.h +++ b/wolfssl/sniffer_error.h @@ -118,6 +118,7 @@ #define BAD_DECRYPT_SIZE 81 #define EXTENDED_MASTER_HASH_STR 82 +#define SPLIT_HANDSHAKE_MSG_STR 83 /* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ diff --git a/wolfssl/sniffer_error.rc b/wolfssl/sniffer_error.rc index 947be6119..735e3184a 100644 --- a/wolfssl/sniffer_error.rc +++ b/wolfssl/sniffer_error.rc @@ -99,5 +99,6 @@ STRINGTABLE 81, "Bad Decrypt Size" 82, "Extended Master Secret Hash Error" + 83, "Handshake Message Split Across TLS Records" }