mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-01 03:34:39 +02:00
Added SNI named keys to the sniffer.
This commit is contained in:
@@ -46,6 +46,12 @@ SSL_SNIFFER_API int ssl_SetPrivateKey(const char* address, int port,
|
|||||||
const char* keyFile, int keyType,
|
const char* keyFile, int keyType,
|
||||||
const char* password, char* error);
|
const char* password, char* error);
|
||||||
|
|
||||||
|
CYASSL_API
|
||||||
|
SSL_SNIFFER_API int ssl_SetNamedPrivateKey(const char* name,
|
||||||
|
const char* address, int port,
|
||||||
|
const char* keyFile, int keyType,
|
||||||
|
const char* password, char* error);
|
||||||
|
|
||||||
CYASSL_API
|
CYASSL_API
|
||||||
SSL_SNIFFER_API int ssl_DecodePacket(const unsigned char* packet, int length,
|
SSL_SNIFFER_API int ssl_DecodePacket(const unsigned char* packet, int length,
|
||||||
unsigned char* data, char* error);
|
unsigned char* data, char* error);
|
||||||
|
@@ -104,6 +104,7 @@
|
|||||||
#define BAD_DECRYPT 70
|
#define BAD_DECRYPT 70
|
||||||
|
|
||||||
#define DECRYPT_KEYS_NOT_SETUP 71
|
#define DECRYPT_KEYS_NOT_SETUP 71
|
||||||
|
#define CLIENT_HELLO_LATE_KEY_STR 72
|
||||||
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */
|
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */
|
||||||
|
|
||||||
|
|
||||||
|
@@ -86,5 +86,6 @@ STRINGTABLE
|
|||||||
70, "Bad Decrypt Operation"
|
70, "Bad Decrypt Operation"
|
||||||
|
|
||||||
71, "Decrypt Keys Not Set Up"
|
71, "Decrypt Keys Not Set Up"
|
||||||
|
72, "Late Key Load Error"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
255
src/sniffer.c
255
src/sniffer.c
@@ -62,6 +62,7 @@ static INLINE word32 min(word32 a, word32 b)
|
|||||||
/* Misc constants */
|
/* Misc constants */
|
||||||
enum {
|
enum {
|
||||||
MAX_SERVER_ADDRESS = 128, /* maximum server address length */
|
MAX_SERVER_ADDRESS = 128, /* maximum server address length */
|
||||||
|
MAX_SERVER_NAME = 128, /* maximum server name length */
|
||||||
MAX_ERROR_LEN = 80, /* maximum error length */
|
MAX_ERROR_LEN = 80, /* maximum error length */
|
||||||
ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */
|
ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */
|
||||||
LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */
|
LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */
|
||||||
@@ -228,7 +229,8 @@ static const char* const msgTable[] =
|
|||||||
"Bad Decrypt Operation",
|
"Bad Decrypt Operation",
|
||||||
|
|
||||||
/* 71 */
|
/* 71 */
|
||||||
"Decrypt Keys Not Set Up"
|
"Decrypt Keys Not Set Up",
|
||||||
|
"Late Key Load Error"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -262,12 +264,30 @@ typedef struct PacketBuffer {
|
|||||||
} PacketBuffer;
|
} PacketBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_SNI
|
||||||
|
|
||||||
|
/* NamedKey maps a SNI name to a specific private key */
|
||||||
|
typedef struct NamedKey {
|
||||||
|
char name[MAX_SERVER_NAME]; /* server DNS name */
|
||||||
|
word32 nameSz; /* size of server DNS name */
|
||||||
|
byte* key; /* DER private key */
|
||||||
|
word32 keySz; /* size of DER private key */
|
||||||
|
struct NamedKey* next; /* for list */
|
||||||
|
} NamedKey;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Sniffer Server holds info for each server/port monitored */
|
/* Sniffer Server holds info for each server/port monitored */
|
||||||
typedef struct SnifferServer {
|
typedef struct SnifferServer {
|
||||||
SSL_CTX* ctx; /* SSL context */
|
SSL_CTX* ctx; /* SSL context */
|
||||||
char address[MAX_SERVER_ADDRESS]; /* passed in server address */
|
char address[MAX_SERVER_ADDRESS]; /* passed in server address */
|
||||||
word32 server; /* netowrk order address */
|
word32 server; /* netowrk order address */
|
||||||
int port; /* server port */
|
int port; /* server port */
|
||||||
|
#ifdef HAVE_SNI
|
||||||
|
NamedKey* namedKeys; /* mapping of names and keys */
|
||||||
|
CyaSSL_Mutex namedKeysMutex; /* mutex for namedKey list */
|
||||||
|
#endif
|
||||||
struct SnifferServer* next; /* for list */
|
struct SnifferServer* next; /* for list */
|
||||||
} SnifferServer;
|
} SnifferServer;
|
||||||
|
|
||||||
@@ -337,11 +357,47 @@ void ssl_InitSniffer(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_SNI
|
||||||
|
|
||||||
|
/* Free Named Key and the zero out the private key it holds */
|
||||||
|
static void FreeNamedKey(NamedKey* in)
|
||||||
|
{
|
||||||
|
if (in) {
|
||||||
|
if (in->key) {
|
||||||
|
XMEMSET(in->key, 0, in->keySz);
|
||||||
|
free(in->key);
|
||||||
|
}
|
||||||
|
free(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void FreeNamedKeyList(NamedKey* in)
|
||||||
|
{
|
||||||
|
NamedKey* next;
|
||||||
|
|
||||||
|
while (in) {
|
||||||
|
next = in->next;
|
||||||
|
FreeNamedKey(in);
|
||||||
|
in = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Free Sniffer Server's resources/self */
|
/* Free Sniffer Server's resources/self */
|
||||||
static void FreeSnifferServer(SnifferServer* srv)
|
static void FreeSnifferServer(SnifferServer* srv)
|
||||||
{
|
{
|
||||||
if (srv)
|
if (srv) {
|
||||||
|
#ifdef HAVE_SNI
|
||||||
|
LockMutex(&srv->namedKeysMutex);
|
||||||
|
FreeNamedKeyList(srv->namedKeys);
|
||||||
|
UnLockMutex(&srv->namedKeysMutex);
|
||||||
|
FreeMutex(&srv->namedKeysMutex);
|
||||||
|
#endif
|
||||||
SSL_CTX_free(srv->ctx);
|
SSL_CTX_free(srv->ctx);
|
||||||
|
}
|
||||||
free(srv);
|
free(srv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,6 +495,10 @@ static void InitSnifferServer(SnifferServer* sniffer)
|
|||||||
XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
|
XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
|
||||||
sniffer->server = 0;
|
sniffer->server = 0;
|
||||||
sniffer->port = 0;
|
sniffer->port = 0;
|
||||||
|
#ifdef HAVE_SNI
|
||||||
|
sniffer->namedKeys = 0;
|
||||||
|
InitMutex(&sniffer->namedKeysMutex);
|
||||||
|
#endif
|
||||||
sniffer->next = 0;
|
sniffer->next = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,6 +679,22 @@ static void TraceSetServer(const char* srv, int port, const char* keyFile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_SNI
|
||||||
|
|
||||||
|
/* Show Set Named Server info for Trace */
|
||||||
|
static void TraceSetNamedServer(const char* name,
|
||||||
|
const char* srv, int port, const char* keyFile)
|
||||||
|
{
|
||||||
|
if (TraceOn) {
|
||||||
|
fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
|
||||||
|
fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
|
||||||
|
name, srv, port, keyFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Trace got packet number */
|
/* Trace got packet number */
|
||||||
static void TracePacket(void)
|
static void TracePacket(void)
|
||||||
{
|
{
|
||||||
@@ -909,6 +985,143 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_SNI
|
||||||
|
|
||||||
|
static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
|
||||||
|
const char* keyFile, int typeKey,
|
||||||
|
const char* password)
|
||||||
|
{
|
||||||
|
byte* loadBuf;
|
||||||
|
byte* saveBuf;
|
||||||
|
long fileSz = 0;
|
||||||
|
int saveBufSz;
|
||||||
|
XFILE file;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typeKey = (typeKey == FILETYPE_PEM) ? SSL_FILETYPE_PEM : SSL_FILETYPE_ASN1;
|
||||||
|
|
||||||
|
file = XFOPEN(keyFile, "rb");
|
||||||
|
if (file == XBADFILE) return -1;
|
||||||
|
XFSEEK(file, 0, XSEEK_END);
|
||||||
|
fileSz = XFTELL(file);
|
||||||
|
XREWIND(file);
|
||||||
|
|
||||||
|
loadBuf = (byte*)malloc(fileSz);
|
||||||
|
if (loadBuf == NULL) {
|
||||||
|
XFCLOSE(file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = (int)XFREAD(loadBuf, fileSz, 1, file);
|
||||||
|
XFCLOSE(file);
|
||||||
|
|
||||||
|
if (typeKey == SSL_FILETYPE_PEM) {
|
||||||
|
saveBuf = (byte*)malloc(fileSz);
|
||||||
|
|
||||||
|
saveBufSz = CyaSSL_KeyPemToDer(loadBuf, (int)fileSz,
|
||||||
|
saveBuf, (int)fileSz, password);
|
||||||
|
free(loadBuf);
|
||||||
|
|
||||||
|
*keyBuf = saveBuf;
|
||||||
|
*keyBufSz = (word32)saveBufSz;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*keyBuf = loadBuf;
|
||||||
|
*keyBufSz = (word32)fileSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Sets the private key for a specific name, server and port */
|
||||||
|
/* returns 0 on success, -1 on error */
|
||||||
|
int ssl_SetNamedPrivateKey(const char* name,
|
||||||
|
const char* address, int port,
|
||||||
|
const char* keyFile, int typeKey,
|
||||||
|
const char* password, char* error)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
SnifferServer* sniffer;
|
||||||
|
NamedKey* namedKey;
|
||||||
|
word32 serverIp;
|
||||||
|
|
||||||
|
TraceHeader();
|
||||||
|
TraceSetNamedServer(name, address, port, keyFile);
|
||||||
|
|
||||||
|
/* Create the new Name-Key map item. */
|
||||||
|
namedKey = (NamedKey*)malloc(sizeof(NamedKey));
|
||||||
|
if (namedKey == NULL) {
|
||||||
|
SetError(MEMORY_STR, error, NULL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
XMEMSET(namedKey, 0, sizeof(NamedKey));
|
||||||
|
|
||||||
|
namedKey->nameSz = (word32)strnlen(name, sizeof(namedKey->name));
|
||||||
|
strncpy(namedKey->name, name, sizeof(namedKey->name));
|
||||||
|
|
||||||
|
ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
|
||||||
|
keyFile, typeKey, password);
|
||||||
|
|
||||||
|
/* Find the server in the list. */
|
||||||
|
serverIp = inet_addr(address);
|
||||||
|
|
||||||
|
LockMutex(&ServerListMutex);
|
||||||
|
sniffer = ServerList;
|
||||||
|
while (sniffer != NULL &&
|
||||||
|
(sniffer->server != serverIp || sniffer->port != port)) {
|
||||||
|
sniffer = sniffer->next;
|
||||||
|
}
|
||||||
|
UnLockMutex(&ServerListMutex);
|
||||||
|
|
||||||
|
/* if sniffer doesn't exist, create it. */
|
||||||
|
if (sniffer == NULL) {
|
||||||
|
sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
|
||||||
|
if (sniffer == NULL) {
|
||||||
|
SetError(MEMORY_STR, error, NULL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
InitSnifferServer(sniffer);
|
||||||
|
|
||||||
|
XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS);
|
||||||
|
sniffer->server = inet_addr(sniffer->address);
|
||||||
|
sniffer->port = port;
|
||||||
|
|
||||||
|
sniffer->ctx = SSL_CTX_new(SSLv3_client_method());
|
||||||
|
if (!sniffer->ctx) {
|
||||||
|
SetError(MEMORY_STR, error, NULL, 0);
|
||||||
|
FreeSnifferServer(sniffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LockMutex(&ServerListMutex);
|
||||||
|
sniffer->next = ServerList;
|
||||||
|
ServerList = sniffer;
|
||||||
|
UnLockMutex(&ServerListMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
LockMutex(&sniffer->namedKeysMutex);
|
||||||
|
namedKey->next = sniffer->namedKeys;
|
||||||
|
sniffer->namedKeys = namedKey;
|
||||||
|
UnLockMutex(&sniffer->namedKeysMutex);
|
||||||
|
|
||||||
|
Trace(NEW_SERVER_STR);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Sets the private key for a specific server and port */
|
/* Sets the private key for a specific server and port */
|
||||||
/* returns 0 on success, -1 on error */
|
/* returns 0 on success, -1 on error */
|
||||||
int ssl_SetPrivateKey(const char* serverAddress, int port, const char* keyFile,
|
int ssl_SetPrivateKey(const char* serverAddress, int port, const char* keyFile,
|
||||||
@@ -1317,6 +1530,44 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
|
|||||||
word16 len;
|
word16 len;
|
||||||
int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
|
int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
|
||||||
|
|
||||||
|
#ifdef HAVE_SNI
|
||||||
|
{
|
||||||
|
byte name[MAX_SERVER_NAME];
|
||||||
|
word32 nameSz = sizeof(name);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = CyaSSL_SNI_GetFromBuffer(
|
||||||
|
input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
|
||||||
|
*sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
|
||||||
|
CYASSL_SNI_HOST_NAME, name, &nameSz);
|
||||||
|
name[nameSz] = 0;
|
||||||
|
|
||||||
|
if (ret == SSL_SUCCESS) {
|
||||||
|
NamedKey* namedKey;
|
||||||
|
|
||||||
|
LockMutex(&session->context->namedKeysMutex);
|
||||||
|
namedKey = session->context->namedKeys;
|
||||||
|
while (namedKey != NULL) {
|
||||||
|
if (nameSz == namedKey->nameSz &&
|
||||||
|
XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
|
||||||
|
if (CyaSSL_use_PrivateKey_buffer(session->sslServer,
|
||||||
|
namedKey->key, namedKey->keySz,
|
||||||
|
SSL_FILETYPE_ASN1) != SSL_SUCCESS) {
|
||||||
|
UnLockMutex(&session->context->namedKeysMutex);
|
||||||
|
SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
|
||||||
|
FATAL_ERROR_STATE);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
namedKey = namedKey->next;
|
||||||
|
}
|
||||||
|
UnLockMutex(&session->context->namedKeysMutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
session->flags.clientHello = 1; /* don't process again */
|
session->flags.clientHello = 1; /* don't process again */
|
||||||
|
|
||||||
/* make sure can read up to session len */
|
/* make sure can read up to session len */
|
||||||
|
@@ -226,6 +226,25 @@ int main(int argc, char** argv)
|
|||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printf("Please run directly from sslSniffer/sslSnifferTest dir\n");
|
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
|
||||||
}
|
}
|
||||||
else if (argc >= 3) {
|
else if (argc >= 3) {
|
||||||
saveFile = 1;
|
saveFile = 1;
|
||||||
|
Reference in New Issue
Block a user