Merge pull request #2287 from ejohnstown/sniffer-stats

Sniffer Statistics
This commit is contained in:
toddouska 2019-06-25 11:22:24 -07:00 committed by GitHub
commit eceb460cff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 264 additions and 10 deletions

View File

@ -410,6 +410,12 @@ static word32 MissedDataSessions = 0; /* # of sessions with missed data */
static SSLConnCb ConnectionCb;
static void* ConnectionCbCtx = NULL;
#ifdef WOLFSSL_SNIFFER_STATS
/* Sessions Statistics */
static SSLStats SnifferStats;
static wolfSSL_Mutex StatsMutex;
#endif
static void UpdateMissedDataSessions(void)
{
@ -419,6 +425,18 @@ static void UpdateMissedDataSessions(void)
}
#ifdef WOLFSSL_SNIFFER_STATS
#define LOCK_STAT() do { wc_LockMutex(&StatsMutex); } while (0)
#define UNLOCK_STAT() do { wc_UnLockMutex(&StatsMutex); } while (0)
#define NOLOCK_ADD_TO_STAT(x,y) do { TraceStat(#x, y); x += y; } while (0)
#define NOLOCK_INC_STAT(x) NOLOCK_ADD_TO_STAT(x,1)
#define ADD_TO_STAT(x,y) do { LOCK_STAT(); \
NOLOCK_ADD_TO_STAT(x,y); UNLOCK_STAT(); } while (0)
#define INC_STAT(x) do { LOCK_STAT(); \
NOLOCK_INC_STAT(x); UNLOCK_STAT(); } while (0)
#endif
/* Initialize overall Sniffer */
void ssl_InitSniffer(void)
{
@ -426,6 +444,10 @@ void ssl_InitSniffer(void)
wc_InitMutex(&ServerListMutex);
wc_InitMutex(&SessionMutex);
wc_InitMutex(&RecoveryMutex);
#ifdef WOLFSSL_SNIFFER_STATS
XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
wc_InitMutex(&StatsMutex);
#endif
}
@ -1052,6 +1074,19 @@ static void TraceSessionInfo(SSLInfo* sslInfo)
}
#ifdef WOLFSSL_SNIFFER_STATS
/* Show value added to a named statistic. */
static void TraceStat(const char* name, int add)
{
if (TraceOn) {
fprintf(TraceFile, "\tAdding %d to %s\n", add, name);
}
}
#endif
/* Set user error string */
static void SetError(int idx, char* error, SnifferSession* session, int fatal)
{
@ -1693,6 +1728,11 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
} while (ret == WC_PENDING_E);
}
#ifdef WOLFSSL_SNIFFER_STATS
if (ret != 0)
INC_STAT(SnifferStats.sslKeyFails);
#endif
if (keyInit)
wc_ecc_free(&key);
if (pubKeyInit)
@ -1799,7 +1839,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
SnifferSession* session, char* error)
{
ProtocolVersion pv;
byte b;
byte b, b0;
int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
int doResume = 0;
int initialBytes = *sslBytes;
@ -1847,14 +1887,33 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
*sslBytes -= b;
/* cipher suite */
b = *input++; /* first byte, ECC or not */
session->sslServer->options.cipherSuite0 = b;
session->sslClient->options.cipherSuite0 = b;
b0 = *input++; /* first byte, ECC or not */
session->sslServer->options.cipherSuite0 = b0;
session->sslClient->options.cipherSuite0 = b0;
b = *input++;
session->sslServer->options.cipherSuite = b;
session->sslClient->options.cipherSuite = b;
*sslBytes -= SUITE_LEN;
#ifdef WOLFSSL_SNIFFER_STATS
{
const CipherSuiteInfo* suites = GetCipherNames();
int suitesSz = GetCipherNamesSize();
int match = 0;
while (suitesSz) {
if (b0 == suites->cipherSuite0 && b == suites->cipherSuite) {
match = 1;
break;
}
suites++;
suitesSz--;
}
if (!match)
INC_STAT(SnifferStats.sslCiphersUnsupported);
}
#endif /* WOLFSSL_SNIFFER_STATS */
/* compression */
b = *input++;
*sslBytes -= ENUM_LEN;
@ -1920,10 +1979,16 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
}
#endif
if (session->sslServer->options.haveSessionId &&
XMEMCMP(session->sslServer->arrays->sessionID,
if (session->sslServer->options.haveSessionId) {
if (XMEMCMP(session->sslServer->arrays->sessionID,
session->sslClient->arrays->sessionID, ID_LEN) == 0)
doResume = 1;
doResume = 1;
else if (session->sslClient->options.haveSessionId) {
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslResumeMisses);
#endif
}
}
else if (session->sslClient->options.haveSessionId == 0 &&
session->sslServer->options.haveSessionId == 0 &&
session->ticketID)
@ -1950,6 +2015,9 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
session->flags.resuming = 1;
Trace(SERVER_DID_RESUMPTION_STR);
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslResumedConns);
#endif
if (SetCipherSpecs(session->sslServer) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
return -1;
@ -1976,6 +2044,11 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
return -1;
}
}
else {
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslStandardConns);
#endif
}
#ifdef SHOW_SECRETS
{
int i;
@ -2286,6 +2359,9 @@ static int DoHandShake(const byte* input, int* sslBytes,
Trace(GOT_CERT_REQ_STR);
break;
case server_key_exchange:
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslEphemeralMisses);
#endif
Trace(GOT_SERVER_KEY_EX_STR);
/* can't know temp key passively */
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
@ -2293,6 +2369,11 @@ static int DoHandShake(const byte* input, int* sslBytes,
break;
case certificate:
Trace(GOT_CERT_STR);
if (session->flags.side == WOLFSSL_SERVER_END) {
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslClientAuthConns);
#endif
}
break;
case server_hello_done:
Trace(GOT_SERVER_HELLO_DONE_STR);
@ -2780,6 +2861,9 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
/* create a new SnifferSession on client SYN */
if (tcpInfo->syn && !tcpInfo->ack) {
TraceClientSyn(tcpInfo->sequence);
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslEncryptedConns);
#endif
*session = CreateSession(ipInfo, tcpInfo, error);
if (*session == NULL) {
*session = GetSnifferSession(ipInfo, tcpInfo);
@ -2803,6 +2887,13 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
if (sslBytes == 0 && tcpInfo->ack)
return 1;
#ifdef WOLFSSL_SNIFFER_STATS
LOCK_STAT();
NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets);
NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes);
UNLOCK_STAT();
#endif
SetError(BAD_SESSION_STR, error, NULL, 0);
return -1;
}
@ -3146,6 +3237,9 @@ static int FindNextRecordInAssembly(SnifferSession* session,
}
Trace(DROPPING_LOST_FRAG_STR);
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslDecodeFails);
#endif
prev = curr;
curr = curr->next;
*reassemblyMemory -= (prev->end - prev->begin + 1);
@ -3577,6 +3671,9 @@ doPart:
break;
case alert:
Trace(GOT_ALERT_STR);
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslAlerts);
#endif
sslFrame += rhSize;
sslBytes -= rhSize;
break;
@ -3683,18 +3780,51 @@ static int ssl_DecodePacketInternal(const byte* packet, int length,
ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
else if (ret == -1) return -1;
else if (ret == 1) return 0; /* done for now */
else if (ret == 1) {
#ifdef WOLFSSL_SNIFFER_STATS
if (sslBytes > 0) {
LOCK_STAT();
NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
UNLOCK_STAT();
}
else
INC_STAT(SnifferStats.sslDecryptedPackets);
#endif
return 0; /* done for now */
}
ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
else if (ret == -1) return -1;
else if (ret == 1) return 0; /* done for now */
else if (ret == 1) {
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslDecryptedPackets);
#endif
return 0; /* done for now */
}
ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
&end, error);
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
else if (ret == -1) return -1;
else if (ret == 1) return 0; /* done for now */
else if (ret == 1) {
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslDecryptedPackets);
#endif
return 0; /* done for now */
}
#ifdef WOLFSSL_SNIFFER_STATS
if (sslBytes > 0) {
LOCK_STAT();
NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
UNLOCK_STAT();
}
else
INC_STAT(SnifferStats.sslDecryptedPackets);
#endif
ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
@ -3845,6 +3975,49 @@ int ssl_SetConnectionCtx(void* ctx)
}
#ifdef WOLFSSL_SNIFFER_STATS
/* Resets the statistics tracking global structure.
* returns 0 on success, -1 on error */
int ssl_ResetStatistics(void)
{
wc_LockMutex(&StatsMutex);
XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
wc_UnLockMutex(&StatsMutex);
return 0;
}
/* Copies the SSL statistics into the provided stats record.
* returns 0 on success, -1 on error */
int ssl_ReadStatistics(SSLStats* stats)
{
if (stats == NULL)
return -1;
wc_LockMutex(&StatsMutex);
XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
wc_UnLockMutex(&StatsMutex);
return 0;
}
/* Copies the SSL statistics into the provided stats record then
* resets the statistics tracking global structure.
* returns 0 on success, -1 on error */
int ssl_ReadResetStatistics(SSLStats* stats)
{
if (stats == NULL)
return -1;
wc_LockMutex(&StatsMutex);
XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
wc_UnLockMutex(&StatsMutex);
return 0;
}
#endif /* WOLFSSL_SNIFFER_STATS */
#endif /* WOLFSSL_SNIFFER */
#endif /* WOLFCRYPT_ONLY */

View File

@ -87,10 +87,58 @@ static void FreeAll(void)
#endif
}
#ifdef WOLFSSL_SNIFFER_STATS
static void DumpStats(void)
{
SSLStats sslStats;
ssl_ReadStatistics(&sslStats);
printf("SSL Stats (sslStandardConns):%lu\n",
sslStats.sslStandardConns);
printf("SSL Stats (sslClientAuthConns):%lu\n",
sslStats.sslClientAuthConns);
printf("SSL Stats (sslResumedConns):%lu\n",
sslStats.sslResumedConns);
printf("SSL Stats (sslEphemeralMisses):%lu\n",
sslStats.sslEphemeralMisses);
printf("SSL Stats (sslResumeMisses):%lu\n",
sslStats.sslResumeMisses);
printf("SSL Stats (sslCiphersUnsupported):%lu\n",
sslStats.sslCiphersUnsupported);
printf("SSL Stats (sslKeysUnmatched):%lu\n",
sslStats.sslKeysUnmatched);
printf("SSL Stats (sslKeyFails):%lu\n",
sslStats.sslKeyFails);
printf("SSL Stats (sslDecodeFails):%lu\n",
sslStats.sslDecodeFails);
printf("SSL Stats (sslAlerts):%lu\n",
sslStats.sslAlerts);
printf("SSL Stats (sslDecryptedBytes):%lu\n",
sslStats.sslDecryptedBytes);
printf("SSL Stats (sslEncryptedBytes):%lu\n",
sslStats.sslEncryptedBytes);
printf("SSL Stats (sslEncryptedPackets):%lu\n",
sslStats.sslEncryptedPackets);
printf("SSL Stats (sslDecryptedPackets):%lu\n",
sslStats.sslDecryptedPackets);
printf("SSL Stats (sslKeyMatches):%lu\n",
sslStats.sslKeyMatches);
printf("SSL Stats (sslEncryptedConns):%lu\n",
sslStats.sslEncryptedConns);
}
#endif
static void sig_handler(const int sig)
{
printf("SIGINT handled = %d.\n", sig);
FreeAll();
#ifdef WOLFSSL_SNIFFER_STATS
DumpStats();
#endif
if (sig)
exit(EXIT_SUCCESS);
}

View File

@ -134,6 +134,39 @@ WOLFSSL_API
SSL_SNIFFER_API int ssl_SetConnectionCtx(void* ctx);
typedef struct SSLStats
{
unsigned long int sslStandardConns;
unsigned long int sslClientAuthConns;
unsigned long int sslResumedConns;
unsigned long int sslEphemeralMisses;
unsigned long int sslResumeMisses;
unsigned long int sslCiphersUnsupported;
unsigned long int sslKeysUnmatched;
unsigned long int sslKeyFails;
unsigned long int sslDecodeFails;
unsigned long int sslAlerts;
unsigned long int sslDecryptedBytes;
unsigned long int sslEncryptedBytes;
unsigned long int sslEncryptedPackets;
unsigned long int sslDecryptedPackets;
unsigned long int sslKeyMatches;
unsigned long int sslEncryptedConns;
} SSLStats;
WOLFSSL_API
SSL_SNIFFER_API int ssl_ResetStatistics(void);
WOLFSSL_API
SSL_SNIFFER_API int ssl_ReadStatistics(SSLStats* stats);
WOLFSSL_API
SSL_SNIFFER_API int ssl_ReadResetStatistics(SSLStats* stats);
#ifdef __cplusplus
} /* extern "C" */
#endif