Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tls fingerprint and storage support #1

Closed
wants to merge 10 commits into from
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ util-runmodes.c util-runmodes.h \
util-file.c util-file.h \
util-path.c util-path.h \
util-buffer.c util-buffer.h \
util-crypt.c util-crypt.h \
tm-modules.c tm-modules.h \
tm-queues.c tm-queues.h \
tm-queuehandlers.c tm-queuehandlers.h \
Expand All @@ -264,6 +265,7 @@ alert-syslog.c alert-syslog.h \
alert-pcapinfo.c alert-pcapinfo.h \
log-droplog.c log-droplog.h \
log-httplog.c log-httplog.h \
log-tlslog.c log-tlslog.h \
log-pcap.c log-pcap.h \
log-file.c log-file.h \
log-filestore.c log-filestore.h \
Expand Down
15 changes: 15 additions & 0 deletions src/app-layer-ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,9 @@ void *SSLStateAlloc(void)
if (ssl_state == NULL)
return NULL;
memset(ssl_state, 0, sizeof(SSLState));
((SSLState*)ssl_state)->client_connp.cert_log_flag |= SSL_TLS_NOLOG_PEM;
((SSLState*)ssl_state)->server_connp.cert_log_flag |= SSL_TLS_NOLOG_PEM;
TAILQ_INIT(&((SSLState*)ssl_state)->server_connp.certs);

return ssl_state;
}
Expand All @@ -871,20 +874,32 @@ void *SSLStateAlloc(void)
void SSLStateFree(void *p)
{
SSLState *ssl_state = (SSLState *)p;
SSLCertsChain *item;

if (ssl_state->client_connp.trec)
SCFree(ssl_state->client_connp.trec);
if (ssl_state->client_connp.cert0_subject)
SCFree(ssl_state->client_connp.cert0_subject);
if (ssl_state->client_connp.cert0_issuerdn)
SCFree(ssl_state->client_connp.cert0_issuerdn);
if (ssl_state->client_connp.cert0_fingerprint)
SCFree(ssl_state->client_connp.cert0_fingerprint);

if (ssl_state->server_connp.trec)
SCFree(ssl_state->server_connp.trec);
if (ssl_state->server_connp.cert0_subject)
SCFree(ssl_state->server_connp.cert0_subject);
if (ssl_state->server_connp.cert0_issuerdn)
SCFree(ssl_state->server_connp.cert0_issuerdn);
if (ssl_state->server_connp.cert0_fingerprint)
SCFree(ssl_state->server_connp.cert0_fingerprint);

/* Free certificate chain */
while ((item = TAILQ_FIRST(&ssl_state->server_connp.certs))) {
TAILQ_REMOVE(&ssl_state->server_connp.certs, item, next);
SCFree(item);
}
TAILQ_INIT(&ssl_state->server_connp.certs);

SCFree(ssl_state);

Expand Down
20 changes: 20 additions & 0 deletions src/app-layer-ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#define __APP_LAYER_SSL_H__

#include "decode-events.h"
#include "queue.h"

enum {
/* TLS protocol messages */
Expand Down Expand Up @@ -64,6 +65,10 @@ enum {
#define SSL_AL_FLAG_STATE_SERVER_KEYX 0x1000
#define SSL_AL_FLAG_STATE_UNKNOWN 0x2000

#define SSL_TLS_NOLOG_PEM 0x0001
#define SSL_TLS_LOG_PEM 0x0002



/* SSL versions. We'll use a unified format for all, with the top byte
* holding the major version and the lower byte the minor version */
Expand All @@ -76,6 +81,13 @@ enum {
TLS_VERSION_12 = 0x0303,
};

typedef struct SSLCertsChain_ {
uint8_t *cert_data;
uint32_t cert_len;
TAILQ_ENTRY(SSLCertsChain_) next;
} SSLCertsChain;


typedef struct SSLStateConnp_ {
/* record length */
uint32_t record_length;
Expand All @@ -100,6 +112,14 @@ typedef struct SSLStateConnp_ {

char *cert0_subject;
char *cert0_issuerdn;
char *cert0_fingerprint;

uint8_t *cert_input;
uint32_t cert_input_len;

TAILQ_HEAD(, SSLCertsChain_) certs;

uint32_t cert_log_flag;

/* buffer for the tls record.
* We use a malloced buffer, if the record is fragmented */
Expand Down
37 changes: 33 additions & 4 deletions src/app-layer-tls-handshake.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
#include "util-decode-der.h"
#include "util-decode-der-get.h"

#include "util-crypt.h"

#define SSLV3_RECORD_LEN 5

static void TLSCertificateErrCodeToWarning(SSLState *ssl_state, uint32_t errcode)
Expand Down Expand Up @@ -120,29 +122,55 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input, uin
if (rc != 0) {
TLSCertificateErrCodeToWarning(ssl_state, errcode);
} else {
SSLCertsChain *ncert;
//SCLogInfo("TLS Cert %d: %s\n", i, buffer);
if (i==0) {
ssl_state->curr_connp->cert0_subject = SCStrdup(buffer);
if (ssl_state->curr_connp->cert0_subject == NULL) {
ssl_state->server_connp.cert0_subject = SCStrdup(buffer);
if (ssl_state->server_connp.cert0_subject == NULL) {
DerFree(cert);
return -1;
}
}
ncert = (SSLCertsChain *)SCMalloc(sizeof(SSLCertsChain));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing NULL check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

memset(ncert, 0, sizeof(*ncert));
ncert->cert_data = input;
ncert->cert_len = cur_cert_length;
TAILQ_INSERT_TAIL(&ssl_state->server_connp.certs, ncert, next);
}
rc = Asn1DerGetIssuerDN(cert, buffer, sizeof(buffer), &errcode);
if (rc != 0) {
TLSCertificateErrCodeToWarning(ssl_state, errcode);
} else {
//SCLogInfo("TLS IssuerDN %d: %s\n", i, buffer);
if (i==0) {
ssl_state->curr_connp->cert0_issuerdn = SCStrdup(buffer);
if (ssl_state->curr_connp->cert0_issuerdn == NULL) {
ssl_state->server_connp.cert0_issuerdn = SCStrdup(buffer);
if (ssl_state->server_connp.cert0_issuerdn == NULL) {
DerFree(cert);
return -1;
}
}
}
DerFree(cert);

if (i == 0 && ssl_state->server_connp.cert0_fingerprint == NULL) {
int msg_len = cur_cert_length;
int hash_len = 20;
int out_len = 60;
char out[out_len];
unsigned char* hash;
hash = ComputeSHA1((unsigned char*) input, (int) msg_len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hash is freed below, so ComputeSHA1 allocs memory? In that case it can fail and a NULL check should be added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch..

char *p = out;
int j = 0;
for (j = 0; j < hash_len; j++, p += 3) {
snprintf(p, 4, j == hash_len - 1 ? "%02x" : "%02x:", hash[j]);
}
SCFree(hash);
ssl_state->server_connp.cert0_fingerprint = SCStrdup(out);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NULL check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Adding only an error message as code already handle the NULL case.


ssl_state->server_connp.cert_input = input;
ssl_state->server_connp.cert_input_len = cur_cert_length;
}

}

i++;
Expand All @@ -152,5 +180,6 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input, uin
}

return parsed;

}

Loading