app-layer-ssl: add validity dates from certificate

Parsing of certificate validity dates to get notBefore and notAfter
fields.
pull/2284/head
Mats Klepsland 10 years ago committed by Victor Julien
parent 6c1c53b5a1
commit bfd16dc74e

@ -147,6 +147,8 @@ typedef struct SSLStateConnp_ {
char *cert0_subject;
char *cert0_issuerdn;
time_t cert0_not_before;
time_t cert0_not_after;
char *cert0_fingerprint;
/* ssl server name indication extension */

@ -87,6 +87,7 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input,
int i;
Asn1Generic *cert;
char buffer[256];
time_t not_before, not_after;
int rc;
int parsed;
uint8_t *start_data;
@ -176,6 +177,16 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input,
}
}
rc = Asn1DerGetValidity(cert, &not_before, &not_after, &errcode);
if (rc != 0) {
TLSCertificateErrCodeToWarning(ssl_state, errcode);
} else {
if (i == 0) {
ssl_state->server_connp.cert0_not_before = not_before;
ssl_state->server_connp.cert0_not_after = not_after;
}
}
DerFree(cert);
if (i == 0 && ssl_state->server_connp.cert0_fingerprint == NULL) {

@ -38,6 +38,7 @@
#include "util-decode-der-get.h"
static const uint8_t SEQ_IDX_ISSUER[] = { 0, 2 };
static const uint8_t SEQ_IDX_VALIDITY[] = { 0, 3 };
static const uint8_t SEQ_IDX_SUBJECT[] = { 0, 4 };
static const char *Oid2ShortStr(const char *oid)
@ -72,6 +73,68 @@ static const char *Oid2ShortStr(const char *oid)
return "unknown";
}
static time_t GentimeToTime(char *gentime)
{
time_t time;
struct tm tm;
/* GeneralizedTime values MUST be expressed in Greenwich Mean Time
* (Zulu) and MUST include seconds (rfc5280 4.1.2.5.2). It MUST NOT
* include fractional seconds. It should therefore be on the format
* YYYYmmddHHMMSSZ. */
if (strlen(gentime) != 15)
goto error;
tm.tm_gmtoff = 0;
strptime(gentime, "%Y%m%d%H%M%SZ", &tm);
time = SCMkTimeUtc(&tm);
if (time < 0)
goto error;
return time;
error:
return -1;
}
static time_t UtctimeToTime(char *utctime)
{
time_t time;
unsigned int year;
char yy[2];
char buf[20];
/* UTCTime values MUST be expressed in Greenwich Mean Time (Zulu)
* and MUST include seconds (rfc5280 4.1.2.5.1). It should
* therefore be on the format YYmmddHHMMSSZ. */
if (strlen(utctime) != 13)
goto error;
/* UTCTime use two digits to represent the year. The year field (YY)
* should be interpreted as 19YY when it is greater than or equal to
* 50. If it is less than 50 it should be interpreted as 20YY.
* Because of this, GeneralizedTime must be used for dates in the
* year 2050 or later. */
strlcpy(yy, utctime, sizeof(yy));
year = strtol(yy, NULL, 10);
if (year >= 50)
snprintf(buf, sizeof(buf), "%i%s", 19, utctime);
else if (year < 50)
snprintf(buf, sizeof(buf), "%i%s", 20, utctime);
else
goto error;
time = GentimeToTime(buf);
if (time == -1)
goto error;
return time;
error:
return -1;
}
/**
* \brief Iterate through an ASN.1 structure, following the index sequence.
* Context specific elements are skipped.
@ -129,6 +192,57 @@ const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index,
return node;
}
int Asn1DerGetValidity(const Asn1Generic *cert, time_t *not_before,
time_t *not_after, uint32_t *errcode)
{
const Asn1Generic *node, *it;
int rc = -1;
if (errcode)
*errcode = ERR_DER_MISSING_ELEMENT;
node = Asn1DerGet(cert, SEQ_IDX_VALIDITY, sizeof(SEQ_IDX_VALIDITY), errcode);
if ((node == NULL) || node->type != ASN1_SEQUENCE)
goto validity_error;
it = node->data;
if (it == NULL || it->str == NULL)
goto validity_error;
if (it->type == ASN1_UTCTIME)
*not_before = UtctimeToTime(it->str);
else if (it->type == ASN1_GENERALIZEDTIME)
*not_before = GentimeToTime(it->str);
else
goto validity_error;
if (*not_before == -1)
goto validity_error;
if (node->next == NULL)
goto validity_error;
it = node->next->data;
if (it == NULL || it->str == NULL)
goto validity_error;
if (it->type == ASN1_UTCTIME)
*not_after = UtctimeToTime(it->str);
else if (it->type == ASN1_GENERALIZEDTIME)
*not_after = GentimeToTime(it->str);
else
goto validity_error;
if (*not_after == -1)
goto validity_error;
rc = 0;
validity_error:
return rc;
}
int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length,
uint32_t *errcode)
{

@ -38,6 +38,7 @@
const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index, const uint32_t seqsz, uint32_t *errcode);
int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode);
int Asn1DerGetValidity(const Asn1Generic *cert, time_t *not_before, time_t *not_after, uint32_t *errcode);
int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode);
#endif /* __UTIL_DECODE_DER_GET_H__ */

Loading…
Cancel
Save