Merge pull request #2499 from ejohnstown/sniffer-features

Sniffer Features
This commit is contained in:
toddouska 2019-10-14 15:35:55 -07:00 committed by GitHub
commit d30e4ac74f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 763 additions and 227 deletions

View File

@ -84,6 +84,7 @@ endif
endif
EXTRA_DIST += scripts/testsuite.pcap \
scripts/sniffer-ipv6.pcap \
scripts/ping.test
# leave openssl.test as extra until non bash works

BIN
scripts/sniffer-ipv6.pcap Normal file

Binary file not shown.

View File

@ -8,6 +8,16 @@ echo -e "\nStaring snifftest on testsuite.pcap...\n"
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest failed\n" && exit 1
if test $# -ne 0 && test "x$1" = "x-6";
then
echo -e "\nStaring snifftest on sniffer-ipv6.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest ./scripts/sniffer-ipv6.pcap ./certs/server-key.pem ::1 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest (ipv6) failed\n" && exit 1
fi
echo -e "\nSuccess!\n"
exit 0

View File

@ -325,8 +325,8 @@ static int QSH_FreeAll(WOLFSSL* ssl)
#ifdef HAVE_NTRU
static WC_RNG* rng;
static wolfSSL_Mutex* rngMutex;
static WOLFSSL_GLOBAL WC_RNG* rng;
static WOLFSSL_GLOBAL wolfSSL_Mutex* rngMutex;
static word32 GetEntropy(unsigned char* out, word32 num_bytes)
{

File diff suppressed because it is too large Load Diff

View File

@ -304,8 +304,8 @@ int wolfSSL_send_session(WOLFSSL* ssl)
/* prevent multiple mutex initializations */
static volatile int initRefCount = 0;
static wolfSSL_Mutex count_mutex; /* init ref count mutex */
static volatile WOLFSSL_GLOBAL int initRefCount = 0;
static WOLFSSL_GLOBAL wolfSSL_Mutex count_mutex; /* init ref count mutex */
/* Create a new WOLFSSL_CTX struct and return the pointer to created struct.
WOLFSSL_METHOD pointer passed in is given to ctx to manage.
@ -4702,13 +4702,13 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW];
} SessionRow;
static SessionRow SessionCache[SESSION_ROWS];
static WOLFSSL_GLOBAL SessionRow SessionCache[SESSION_ROWS];
#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
static word32 PeakSessions;
static WOLFSSL_GLOBAL word32 PeakSessions;
#endif
static wolfSSL_Mutex session_mutex; /* SessionCache mutex */
static WOLFSSL_GLOBAL wolfSSL_Mutex session_mutex; /* SessionCache mutex */
#ifndef NO_CLIENT_CACHE
@ -4723,7 +4723,8 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
ClientSession Clients[SESSIONS_PER_ROW];
} ClientRow;
static ClientRow ClientCache[SESSION_ROWS]; /* Client Cache */
static WOLFSSL_GLOBAL ClientRow ClientCache[SESSION_ROWS];
/* Client Cache */
/* uses session mutex */
#endif /* NO_CLIENT_CACHE */
@ -19377,6 +19378,12 @@ const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0,
return GetCipherNameInternal(cipherSuite0, cipherSuite);
}
const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0,
const byte cipherSuite)
{
return GetCipherNameIana(cipherSuite0, cipherSuite);
}
word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher)
{
word16 cipher_id = 0;

View File

@ -26,6 +26,10 @@
#include <wolfssl/wolfcrypt/settings.h>
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
#include <wolfssl/wolfcrypt/memory.h>
#endif
#ifdef _WIN32
#define WOLFSSL_SNIFFER
#endif
@ -54,6 +58,7 @@ int main(void)
#include <stdlib.h> /* EXIT_SUCCESS */
#include <string.h> /* strcmp */
#include <signal.h> /* signal */
#include <ctype.h> /* isprint */
#include <cyassl/sniffer.h>
@ -72,6 +77,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_if_t* alldevs = NULL;
@ -159,17 +183,34 @@ static void err_sys(const char* msg)
#endif
static char* iptos(unsigned int addr)
static char* iptos(const struct in_addr* addr)
{
static char output[32];
byte *p = (byte*)&addr;
byte *p = (byte*)&addr->s_addr;
SNPRINTF(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
snprintf(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output;
}
static const char* ip6tos(const struct in6_addr* addr)
{
static char output[42];
return inet_ntop(AF_INET6, addr, output, 42);
}
#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
const byte rsaHash[] = {
@ -214,6 +255,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 = min(decryptBufSz - decryptBufOffset, STORE_DATA_BLOCK_SZ);
if (*data == NULL) {
byte* tmpData;
tmpData = (byte*)XREALLOC(*data, decryptBufSz + 1,
NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (tmpData == NULL) {
XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
*data = NULL;
return -1;
}
*data = tmpData;
}
memcpy(*data + decryptBufOffset, decryptBuf + decryptBufOffset, qty);
return qty;
}
#endif
int main(int argc, char** argv)
{
int ret = 0;
@ -229,6 +306,10 @@ int main(int argc, char** argv)
struct bpf_program fp;
pcap_if_t *d;
pcap_addr_t *a;
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
struct iovec chain[CHAIN_INPUT_COUNT];
int chainSz;
#endif
signal(SIGINT, sig_handler);
@ -240,6 +321,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 */
@ -275,22 +359,21 @@ int main(int argc, char** argv)
if (pcap == NULL) printf("pcap_create failed %s\n", err);
/* get an IPv4 address */
/* print out addresses for selected interface */
for (a = d->addresses; a; a = a->next) {
switch(a->addr->sa_family)
{
case AF_INET:
server =
iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr);
printf("server = %s\n", server);
break;
default:
break;
}
if (a->addr->sa_family == AF_INET) {
server =
iptos(&((struct sockaddr_in *)a->addr)->sin_addr);
printf("server = %s\n", server);
}
else if (a->addr->sa_family == AF_INET6) {
server =
ip6tos(&((struct sockaddr_in6 *)a->addr)->sin6_addr);
printf("server = %s\n", server);
}
}
if (server == NULL)
err_sys("Unable to get device IPv4 address");
err_sys("Unable to get device IPv4 or IPv6 address");
ret = pcap_set_snaplen(pcap, 65536);
if (ret != 0) printf("pcap_set_snaplen failed %s\n", pcap_geterr(pcap));
@ -322,32 +405,48 @@ int main(int argc, char** argv)
ret = pcap_setfilter(pcap, &fp);
if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap));
#ifndef WOLFSSL_SNIFFER_WATCH
ret = ssl_SetPrivateKey(server, port, "../../certs/server-key.pem",
FILETYPE_PEM, NULL, err);
if (ret != 0) {
printf("Please run directly from sslSniffer/sslSnifferTest dir\n");
}
#ifdef HAVE_SNI
{
char altName[128];
printf("Enter alternate SNI: ");
ret = scanf("%s", altName);
if (strnlen(altName, 128) > 0) {
ret = ssl_SetNamedPrivateKey(altName,
server, port, "../../certs/server-key.pem",
FILETYPE_PEM, NULL, err);
if (ret != 0) {
printf("Please run directly from "
"sslSniffer/sslSnifferTest dir\n");
}
/* get IPv4 or IPv6 addresses for selected interface */
for (a = d->addresses; a; a = a->next) {
server = NULL;
if (a->addr->sa_family == AF_INET) {
server =
iptos(&((struct sockaddr_in *)a->addr)->sin_addr);
}
}
#endif
#endif
else if (a->addr->sa_family == AF_INET6) {
server =
ip6tos(&((struct sockaddr_in6 *)a->addr)->sin6_addr);
}
if (server) {
#ifndef WOLFSSL_SNIFFER_WATCH
ret = ssl_SetPrivateKey(server, port,
"../../certs/server-key.pem",
FILETYPE_PEM, NULL, err);
if (ret != 0) {
printf("Please run directly from sslSniffer/sslSnifferTest"
"dir\n");
}
#ifdef HAVE_SNI
{
char altName[128];
printf("Enter alternate SNI: ");
ret = scanf("%s", altName);
if (strnlen(altName, 128) > 0) {
ret = ssl_SetNamedPrivateKey(altName,
server, port, "../../certs/server-key.pem",
FILETYPE_PEM, NULL, err);
if (ret != 0) {
printf("Please run directly from "
"sslSniffer/sslSnifferTest dir\n");
}
}
}
#endif
#endif
}
}
}
else if (argc >= 3) {
saveFile = 1;
@ -404,14 +503,50 @@ int main(int argc, char** argv)
}
else
continue;
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
{
unsigned int j = 0;
unsigned int remainder = header.caplen;
chainSz = 0;
do {
unsigned int chunkSz;
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,
header.caplen, &data, &sslInfo, err);
#else
ret = ssl_DecodePacketWithSessionInfo(packet, header.caplen, &data,
&sslInfo, err);
#endif
if (ret < 0) {
printf("ssl_Decode ret = %d, %s\n", ret, err);
hadBadPacket = 1;
}
if (ret > 0) {
int j;
/* Convert non-printable data to periods. */
for (j = 0; j < ret; j++) {
if (isprint(data[j]) || isspace(data[j])) continue;
data[j] = '.';
}
data[ret] = 0;
printf("SSL App Data(%d:%d):%s\n", packetNumber, ret, data);
ssl_FreeZeroDecodeBuffer(&data, ret, err);

View File

@ -2574,11 +2574,16 @@ static void test_client_nofail(void* args, void *cb)
/* IANA Cipher Suites Names */
/* Unless WOLFSSL_CIPHER_INTERNALNAME or NO_ERROR_STRINGS,
then its the internal cipher suite name */
then it's the internal cipher suite name */
cipher = wolfSSL_get_current_cipher(ssl);
cipherName1 = wolfSSL_CIPHER_get_name(cipher);
cipherName2 = wolfSSL_get_cipher(ssl);
AssertStrEQ(cipherName1, cipherName2);
#if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS)
cipherName1 = wolfSSL_get_cipher_name_iana_from_suite(
(cipherSuite >> 8), cipherSuite & 0xFF);
AssertStrEQ(cipherName1, cipherName2);
#endif
if (cb != NULL)
((cbType)cb)(ctx, ssl);
@ -18548,6 +18553,7 @@ static void test_wc_PemToDer(void)
if (cert_buf)
free(cert_buf);
printf(resultFmt, passed);
#endif
}
@ -18564,6 +18570,7 @@ static void test_wc_AllocDer(void)
AssertIntEQ(ret, 0);
AssertNotNull(pDer);
wc_FreeDer(&pDer);
printf(resultFmt, passed);
#endif
}

View File

@ -6,7 +6,7 @@
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,

View File

@ -152,6 +152,9 @@ typedef struct SSLStats
unsigned long int sslDecryptedPackets;
unsigned long int sslKeyMatches;
unsigned long int sslEncryptedConns;
unsigned long int sslResumptionValid;
unsigned long int sslResumptionInserts;
} SSLStats;
@ -177,6 +180,10 @@ typedef int (*SSLWatchCb)(void* vSniffer,
WOLFSSL_API
SSL_SNIFFER_API int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error);
WOLFSSL_API
SSL_SNIFFER_API int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId,
char* error);
WOLFSSL_API
SSL_SNIFFER_API int ssl_SetWatchKeyCtx(void* ctx, char* error);
@ -191,6 +198,28 @@ 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);
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
} /* extern "C" */
#endif

View File

@ -125,6 +125,11 @@
#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
#define CHAIN_INPUT_STR 93
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */

View File

@ -107,5 +107,10 @@ 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"
93, "Loading chain input"
}

View File

@ -815,6 +815,8 @@ WOLFSSL_API int wolfSSL_get_ciphers_iana(char*, int);
WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl);
WOLFSSL_API const char* wolfSSL_get_cipher_name_from_suite(const unsigned char,
const unsigned char);
WOLFSSL_API const char* wolfSSL_get_cipher_name_iana_from_suite(
const unsigned char, const unsigned char);
WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf,
int len);
WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl);

View File

@ -6,7 +6,7 @@
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,

View File

@ -1788,11 +1788,17 @@ extern void uITRON4_free(void *p) ;
#ifndef WOLFSSL_STATIC_RSA
#define WOLFSSL_STATIC_RSA
#endif
#ifndef WOLFSSL_SESSION_STATS
#define WOLFSSL_SESSION_STATS
#ifndef WOLFSSL_STATIC_DH
#define WOLFSSL_STATIC_DH
#endif
#ifndef WOLFSSL_PEAK_SESSIONS
#define WOLFSSL_PEAK_SESSIONS
/* Allow option to be disabled. */
#ifndef WOLFSSL_NO_SESSION_STATS
#ifndef WOLFSSL_SESSION_STATS
#define WOLFSSL_SESSION_STATS
#endif
#ifndef WOLFSSL_PEAK_SESSIONS
#define WOLFSSL_PEAK_SESSIONS
#endif
#endif
#endif

View File

@ -620,6 +620,12 @@
DYNAMIC_TYPE_HASH_TMP = 88,
DYNAMIC_TYPE_BLOB = 89,
DYNAMIC_TYPE_NAME_ENTRY = 90,
DYNAMIC_TYPE_SNIFFER_SERVER = 1000,
DYNAMIC_TYPE_SNIFFER_SESSION = 1001,
DYNAMIC_TYPE_SNIFFER_PB = 1002,
DYNAMIC_TYPE_SNIFFER_PB_BUFFER = 1003,
DYNAMIC_TYPE_SNIFFER_TICKET_ID = 1004,
DYNAMIC_TYPE_SNIFFER_NAMED_KEY = 1005,
};
/* max error buffer string size */

View File

@ -721,6 +721,15 @@ WOLFSSL_API int wolfCrypt_Cleanup(void);
will use dynamic buffer if not big enough */
#endif
#ifdef HAVE_CAVIUM_OCTEON
/* By default, the OCTEON's global variables are all thread local. This
* tag allows them to be shared between threads. */
#include "cvmx-platform.h"
#define WOLFSSL_GLOBAL CVMX_SHARED
#else
#define WOLFSSL_GLOBAL
#endif
#ifdef __cplusplus
} /* extern "C" */