Rewrite of big parts of the OCSP analyzer.

Less redundancy, style closer to the X.509 analyzer, times being parsed
as real times, and lots of other changes.
This commit is contained in:
Johanna Amann 2017-02-08 16:24:52 -08:00
parent c670613996
commit b021fe7562
13 changed files with 376 additions and 629 deletions

View file

@ -1 +1,2 @@
@load ./main @load ./main
@load ./ocsp

View file

@ -1,3 +1,4 @@
@load base/protocols/http
@load base/frameworks/files @load base/frameworks/files
@load base/utils/paths @load base/utils/paths
@load base/utils/queue @load base/utils/queue
@ -68,7 +69,7 @@ export {
## responderID ## responderID
responderID: string &log &optional; responderID: string &log &optional;
## producedAt ## producedAt
producedAt: string &log &optional; producedAt: time &log &optional;
## certificates ## certificates
certs: vector of opaque of x509 &optional; certs: vector of opaque of x509 &optional;
@ -85,9 +86,9 @@ export {
## certStatus (this is the response to look at) ## certStatus (this is the response to look at)
certStatus: string &log &optional; certStatus: string &log &optional;
## thisUpdate ## thisUpdate
thisUpdate: string &log &optional; thisUpdate: time &log &optional;
## nextUpdate ## nextUpdate
nextUpdate: string &log &optional; nextUpdate: time &log &optional;
}; };
type Info: record { type Info: record {

View file

@ -3651,42 +3651,45 @@ export {
issuerNameHash: string &log; issuerNameHash: string &log;
issuerKeyHash: string &log; issuerKeyHash: string &log;
serialNumber: string &log; serialNumber: string &log;
#RequestExtensions: xxx
}; };
type Request: record { type Request: record {
version: count &log &optional; version: count &log &optional;
requestorName: string &log &optional; requestorName: string &log &optional;
requestList: vector of OneReq; requestList: vector of OneReq;
#requestExtensions: xxx };
};
type SingleResp: record { type SingleResp: record {
hashAlgorithm: string &log; hashAlgorithm: string &log;
issuerNameHash: string &log; issuerNameHash: string &log;
issuerKeyHash: string &log; issuerKeyHash: string &log;
serialNumber: string &log; serialNumber: string &log;
certStatus: string &log; certStatus: string &log;
thisUpdate: string &log; revoketime: time &log &optional;
nextUpdate: string &log &optional; revokereason: string &log &optional;
#Extensions: xxx thisUpdate: time &log;
nextUpdate: time &log &optional;
}; };
type Response: record { type Response: record {
responseStatus: string &log; responseStatus: string &log;
responseType: string &log; responseType: string &log &optional;
version: count &log; version: count &log &optional;
responderID: string &log; responderID: string &log &optional;
producedAt: string &log; producedAt: time &log &optional;
responses: vector of SingleResp; responses: vector of SingleResp;
#responseExtensions:xxx
signatureAlgorithm: string &log &optional; signatureAlgorithm: string &log &optional;
signature: string &optional; #&log; #signature: string &optional; #&log;
certs: vector of opaque of x509 &optional; certs: vector of opaque of x509 &optional;
}; };
type CertId: record { type CertId: record {
hashAlgorithm: string &log &optional; hashAlgorithm: string &log &optional;
issuerNameHash: string &log &optional; issuerNameHash: string &log &optional;
issuerKeyHash: string &log &optional; issuerKeyHash: string &log &optional;
serialNumber: string &log &optional; serialNumber: string &log &optional;
}; };
} }
module GLOBAL; module GLOBAL;

View file

@ -0,0 +1,157 @@
static double GetTimeFromAsn1(const ASN1_TIME* atime, const char* arg_fid, Reporter* reporter)
{
const char *fid = arg_fid ? arg_fid : "";
time_t lResult = 0;
char lBuffer[26];
char* pBuffer = lBuffer;
const char *pString = (const char *) atime->data;
unsigned int remaining = atime->length;
if ( atime->type == V_ASN1_UTCTIME )
{
if ( remaining < 11 || remaining > 17 )
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- UTCTime has wrong length", fid));
return 0;
}
if ( pString[remaining-1] != 'Z' )
{
// not valid according to RFC 2459 4.1.2.5.1
reporter->Weird(fmt("Could not parse UTC time in non-YY-format in X509 certificate (x509 %s)", fid));
return 0;
}
// year is first two digits in YY format. Buffer expects YYYY format.
if ( pString[0] < '5' ) // RFC 2459 4.1.2.5.1
{
*(pBuffer++) = '2';
*(pBuffer++) = '0';
}
else
{
*(pBuffer++) = '1';
*(pBuffer++) = '9';
}
memcpy(pBuffer, pString, 10);
pBuffer += 10;
pString += 10;
remaining -= 10;
}
else if ( atime->type == V_ASN1_GENERALIZEDTIME )
{
// generalized time. We apparently ignore the YYYYMMDDHH case
// for now and assume we always have minutes and seconds.
// This should be ok because it is specified as a requirement in RFC 2459 4.1.2.5.2
if ( remaining < 12 || remaining > 23 )
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- Generalized time has wrong length", fid));
return 0;
}
memcpy(pBuffer, pString, 12);
pBuffer += 12;
pString += 12;
remaining -= 12;
}
else
{
reporter->Weird(fmt("Invalid time type in X509 certificate (fuid %s)", fid));
return 0;
}
if ( (remaining == 0) || (*pString == 'Z') || (*pString == '-') || (*pString == '+') )
{
*(pBuffer++) = '0';
*(pBuffer++) = '0';
}
else if ( remaining >= 2 )
{
*(pBuffer++) = *(pString++);
*(pBuffer++) = *(pString++);
remaining -= 2;
// Skip any fractional seconds...
if ( (remaining > 0) && (*pString == '.') )
{
pString++;
remaining--;
while ( (remaining > 0) && (*pString >= '0') && (*pString <= '9') )
{
pString++;
remaining--;
}
}
}
else
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- additional char after time", fid));
return 0;
}
*(pBuffer++) = 'Z';
*(pBuffer++) = '\0';
time_t lSecondsFromUTC;
if ( remaining == 0 || *pString == 'Z' )
lSecondsFromUTC = 0;
else
{
if ( remaining < 5 )
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- not enough bytes remaining for offset", fid));
return 0;
}
if ((*pString != '+') && (*pString != '-'))
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- unknown offset type", fid));
return 0;
}
lSecondsFromUTC = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60;
lSecondsFromUTC += (pString[3] - '0') * 10 + (pString[4] - '0');
if (*pString == '-')
lSecondsFromUTC = -lSecondsFromUTC;
}
tm lTime;
lTime.tm_sec = ((lBuffer[12] - '0') * 10) + (lBuffer[13] - '0');
lTime.tm_min = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
lTime.tm_hour = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
lTime.tm_mday = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
lTime.tm_mon = (((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0')) - 1;
lTime.tm_year = (lBuffer[0] - '0') * 1000 + (lBuffer[1] - '0') * 100 + ((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0');
if ( lTime.tm_year > 1900)
lTime.tm_year -= 1900;
lTime.tm_wday = 0;
lTime.tm_yday = 0;
lTime.tm_isdst = 0; // No DST adjustment requested
lResult = mktime(&lTime);
if ( lResult )
{
if ( lTime.tm_isdst != 0 )
lResult -= 3600; // mktime may adjust for DST (OS dependent)
lResult += lSecondsFromUTC;
}
else
lResult = 0;
return lResult;
}

View file

@ -15,6 +15,9 @@
#include <openssl/asn1.h> #include <openssl/asn1.h>
#include <openssl/opensslconf.h> #include <openssl/opensslconf.h>
#include "file_analysis/analyzer/x509/X509.h"
#include "Asn1Time.h"
// helper function of sk_X509_value to avoid namespace problem // helper function of sk_X509_value to avoid namespace problem
// sk_X509_value(X,Y) = > SKM_sk_value(X509,X,Y) // sk_X509_value(X,Y) = > SKM_sk_value(X509,X,Y)
// X509 => file_analysis::X509 // X509 => file_analysis::X509
@ -23,8 +26,6 @@ X509 *helper_sk_X509_value(STACK_OF(X509) *certs, int i)
return sk_X509_value(certs, i); return sk_X509_value(certs, i);
} }
#include "file_analysis/analyzer/x509/X509.h"
using namespace file_analysis; using namespace file_analysis;
IMPLEMENT_SERIAL(OCSP_REQVal, SER_OCSP_REQ_VAL); IMPLEMENT_SERIAL(OCSP_REQVal, SER_OCSP_REQ_VAL);
@ -32,213 +33,59 @@ IMPLEMENT_SERIAL(OCSP_RESPVal, SER_OCSP_RESP_VAL);
#define OCSP_STRING_BUF_SIZE 2048 #define OCSP_STRING_BUF_SIZE 2048
//this function is copied from src/file_analysis/analyzer/extract/Extract.cc static Val* get_ocsp_type(RecordVal* args, const char* name)
static Val* get_extract_field_val(RecordVal* args, const char* name)
{ {
Val* rval = args->Lookup(name); Val* rval = args->Lookup(name);
if ( ! rval ) if ( ! rval )
reporter->Error("File extraction analyzer missing arg field: %s", name); reporter->Error("File extraction analyzer missing arg field: %s", name);
return rval; return rval;
} }
//convert different ANS1 type to c string static void OCSP_RESPID_bio(OCSP_RESPID *resp_id, BIO* bio)
static int ANS1_to_cstr(char *buf, int buf_len, void *data, int type)
{ {
if (data == NULL || buf == NULL || buf_len <=0)
return -1;
int new_len = -1;
BIO *bio = BIO_new(BIO_s_mem());
memset(buf, 0, buf_len);
if (type == V_ASN1_OCTET_STRING)
{
if (i2a_ASN1_STRING(bio, (ASN1_STRING *)data, V_ASN1_OCTET_STRING) <= 0)
goto err;
}
else if (type == V_ASN1_BIT_STRING)
{
if (i2a_ASN1_STRING(bio, (ASN1_STRING *)data, V_ASN1_BIT_STRING) <= 0)
goto err;
}
else if (type == V_ASN1_INTEGER)
{
// NOTE: this will print the hex number
// wireshark may display decimal number
if (i2a_ASN1_INTEGER(bio, (ASN1_INTEGER *)data) <= 0)
goto err;
}
else if (type == V_ASN1_OBJECT)
{
if (i2a_ASN1_OBJECT(bio, (ASN1_OBJECT *)data) <= 0)
goto err;
}
else if (type == V_ASN1_GENERALIZEDTIME)
{
// TODO: convert ASN1_GENERALIZEDTIME to epoch time?
// new API: ASN1_TIME_diff() requires openssl 1.0.2
// epoch time might be better for post processing
// NOTE: this is for human readable time format
//if (!ASN1_GENERALIZEDTIME_print(bio, (ASN1_GENERALIZEDTIME *)data))
// goto err;
// NOTE: this is printing the raw string which is also understandable
// since this is smaller, let's keep ASN1_GENERALIZEDTIME as this for now?
ASN1_GENERALIZEDTIME *tmp = (ASN1_GENERALIZEDTIME *)data;
BIO_write(bio, tmp->data, tmp->length);
}
else
goto err;
new_len = BIO_read(bio, buf, buf_len);
err:
BIO_free_all(bio);
return new_len;
}
//ANS1 OCTET string to c string
static int ASN1_OCTET_STRING_to_cstr(char *buf, int len, void *data)
{
return ANS1_to_cstr(buf, len, data, V_ASN1_OCTET_STRING);
}
//ANS1 BIT string to c string
static int ASN1_BIT_STRING_to_cstr(char *buf, int len, void *data)
{
return ANS1_to_cstr(buf, len, data, V_ASN1_BIT_STRING);
}
//ANS1 integer to c string
static int ASN1_INTEGER_to_cstr(char *buf, int len, void *data)
{
return ANS1_to_cstr(buf, len, data, V_ASN1_INTEGER);
}
//ANS1 object to c string
static int ASN1_OBJECT_to_cstr(char *buf, int len, void *data)
{
return ANS1_to_cstr(buf, len, data, V_ASN1_OBJECT);
}
//ASN1_GENERALIZEDTIME to c string
static int ASN1_GENERALIZEDTIME_to_cstr(char *buf, int len, void *data)
{
return ANS1_to_cstr(buf, len, data, V_ASN1_GENERALIZEDTIME);
}
//CENERAL XXX to c string
static int GENERAL_NAME_to_cstr(char *buf, int buf_len, void *data)
{
if (data == NULL || buf == NULL || buf_len <= 0)
return -1;
int new_len = -1;
BIO *bio = BIO_new(BIO_s_mem());
memset(buf, 0, buf_len);
if (GENERAL_NAME_print(bio, (GENERAL_NAME *)data) <= 0)
goto err;
new_len = BIO_read(bio, buf, buf_len);
err:
BIO_free_all(bio);
return new_len;
}
//OCSP respond id to c string
static int OCSP_RESPID_to_cstr(char *buf, int buf_len, OCSP_RESPID *resp_id)
{
if (resp_id == NULL || buf == NULL || buf_len <= 0)
return -1;
int new_len = -1;
BIO *bio = BIO_new(BIO_s_mem());
memset(buf, 0, buf_len);
if (resp_id->type == V_OCSP_RESPID_NAME) if (resp_id->type == V_OCSP_RESPID_NAME)
{ X509_NAME_print_ex(bio, resp_id->value.byName, 0, XN_FLAG_ONELINE);
if (X509_NAME_print_ex(bio, resp_id->value.byName, 0, XN_FLAG_ONELINE) <=0)
goto err;
}
else if (resp_id->type == V_OCSP_RESPID_KEY) else if (resp_id->type == V_OCSP_RESPID_KEY)
{ i2a_ASN1_STRING(bio, resp_id->value.byKey, V_ASN1_OCTET_STRING);
if (i2a_ASN1_STRING(bio, resp_id->value.byKey, V_ASN1_OCTET_STRING) <= 0)
goto err;
}
else
goto err;
new_len = BIO_read(bio, buf, buf_len);
err:
BIO_free_all(bio);
return new_len;
} }
//print out a cert id for debug static RecordVal* ocsp_fill_cert_id(OCSP_CERTID *cert_id, RecordType* type, BIO* bio)
static void ocsp_print_cert_id(OCSP_CERTID *cid)
{ {
if (cid == NULL) RecordVal *d = new RecordVal(type);
return;
char buf[OCSP_STRING_BUF_SIZE]; char buf[OCSP_STRING_BUF_SIZE];
int len = sizeof(buf); memset(buf, 0, sizeof(buf));
memset(buf, 0, len);
int new_len = -1;
//print hashAlgorithm i2a_ASN1_OBJECT(bio, cert_id->hashAlgorithm->algorithm);
new_len = ASN1_OBJECT_to_cstr(buf, len, (void *)(cid->hashAlgorithm->algorithm)); int len = BIO_read(bio, buf, sizeof(buf));
StringVal hashAlgorithm = StringVal(new_len, buf); d->Assign(0, new StringVal(len, buf));
printf("[%d]hashAlgorithm: %s\n", new_len, hashAlgorithm.CheckString()); BIO_reset(bio);
//print issuerNameHash i2a_ASN1_STRING(bio, cert_id->issuerNameHash, V_ASN1_OCTET_STRING);
new_len = ASN1_OCTET_STRING_to_cstr(buf, len, (void *)(cid->issuerNameHash)); len = BIO_read(bio, buf, sizeof(buf));
StringVal issuerNameHash = StringVal(new_len, buf); d->Assign(1, new StringVal(len, buf));
printf("[%d]issuerNameHash: %s\n", new_len, issuerNameHash.CheckString()); BIO_reset(bio);
//print issuerKeyHash i2a_ASN1_STRING(bio, cert_id->issuerKeyHash, V_ASN1_OCTET_STRING);
new_len = ASN1_OCTET_STRING_to_cstr(buf, len, (void *)(cid->issuerKeyHash)); len = BIO_read(bio, buf, sizeof(buf));
StringVal issuerKeyHash = StringVal(new_len, buf); d->Assign(2, new StringVal(len, buf));
printf("[%d]issuerKeyHash: %s\n", new_len, issuerKeyHash.CheckString()); BIO_reset(bio);
//print serialNumber i2a_ASN1_INTEGER(bio, cert_id->serialNumber);
new_len = ASN1_INTEGER_to_cstr(buf, len, (void *)(cid->serialNumber)); d->Assign(3, new StringVal(len, buf));
StringVal serialNumber = StringVal(new_len, buf); BIO_reset(bio);
printf("[%d]serialNumber: %s\n", new_len, serialNumber.CheckString());
}
//fill in cert id return d;
static void ocsp_fill_cert_id(OCSP_CERTID *cert_id, RecordVal *d)
{
if (d == NULL || cert_id == NULL)
return;
char buf[OCSP_STRING_BUF_SIZE];
int buf_len = sizeof(buf);
memset(buf, 0, buf_len);
//hashAlgorithm
int len = -1;
len = ASN1_OBJECT_to_cstr(buf, buf_len, (void *)(cert_id->hashAlgorithm->algorithm));
if (len > 0)
d->Assign(0, new StringVal(len, buf));
//issuerNameHash
len = -1;
len = ASN1_OCTET_STRING_to_cstr(buf, buf_len, (void *)(cert_id->issuerNameHash));
if (len > 0)
d->Assign(1, new StringVal(len, buf));
//issuerKeyHash
len = -1;
len = ASN1_OCTET_STRING_to_cstr(buf, buf_len, (void *)(cert_id->issuerKeyHash));
if (len > 0)
d->Assign(2, new StringVal(len, buf));
//serialNumber
len = -1;
len = ASN1_INTEGER_to_cstr(buf, buf_len, (void *)(cert_id->serialNumber));
if (len > 0)
d->Assign(3, new StringVal(len, buf));
} }
file_analysis::Analyzer* OCSP::Instantiate(RecordVal* args, File* file) file_analysis::Analyzer* OCSP::Instantiate(RecordVal* args, File* file)
{ {
Val* ocsp_type = get_extract_field_val(args, "ocsp_type"); Val* ocsp_type = get_ocsp_type(args, "ocsp_type");
if (! ocsp_type )
if (! ocsp_type )
return 0; return 0;
return new OCSP(args, file, ocsp_type->AsString()->CheckString()); return new OCSP(args, file, ocsp_type->AsString()->CheckString());
} }
@ -260,328 +107,223 @@ bool file_analysis::OCSP::Undelivered(uint64 offset, uint64 len)
return false; return false;
} }
// parse OCSP request or response and send data to bro scriptland // we parse the entire OCSP response in EOF, because we just pass it on
// to OpenSSL.
bool file_analysis::OCSP::EndOfFile() bool file_analysis::OCSP::EndOfFile()
{ {
OCSP_REQUEST *req = NULL;
OCSP_RESPONSE *resp = NULL;
const unsigned char* ocsp_char = reinterpret_cast<const unsigned char*>(ocsp_data.data()); const unsigned char* ocsp_char = reinterpret_cast<const unsigned char*>(ocsp_data.data());
if (ocsp_type == "request") if (ocsp_type == "request")
{ {
req = d2i_OCSP_REQUEST(NULL, &ocsp_char, ocsp_data.size()); OCSP_REQUEST *req = d2i_OCSP_REQUEST(NULL, &ocsp_char, ocsp_data.size());
if (!req) if (!req)
{ {
reporter->Weird(fmt("OPENSSL Could not parse OCSP request (fuid %s)", GetFile()->GetID().c_str())); reporter->Weird(fmt("OPENSSL Could not parse OCSP request (fuid %s)", GetFile()->GetID().c_str()));
goto ocsp_cleanup; return false;
} }
//parse request into record OCSP_REQVal* req_val = new OCSP_REQVal(req); // req_val takes ownership
OCSP_REQVal* req_val = new OCSP_REQVal(req);
RecordVal* req_record = ParseRequest(req_val); RecordVal* req_record = ParseRequest(req_val, GetFile()->GetID().c_str());
if (!req_record)
{
reporter->Weird(fmt("Internal fail to parse OCSP request (fuid %s)", GetFile()->GetID().c_str()));
Unref(req_val);
goto ocsp_cleanup;
}
// and send the record on to scriptland // and send the record on to scriptland
val_list* vl = new val_list(); val_list* vl = new val_list();
vl->append(GetFile()->GetVal()->Ref()); vl->append(GetFile()->GetVal()->Ref());
vl->append(req_val->Ref()); vl->append(req_val);
vl->append(req_record->Ref()); vl->append(req_record);
mgr.QueueEvent(ocsp_request, vl); mgr.QueueEvent(ocsp_request, vl);
Unref(req_val);
Unref(req_record);
} }
else if (ocsp_type == "response") else if (ocsp_type == "response")
{ {
resp = d2i_OCSP_RESPONSE(NULL, &ocsp_char, ocsp_data.size()); OCSP_RESPONSE *resp = d2i_OCSP_RESPONSE(NULL, &ocsp_char, ocsp_data.size());
if (!resp) if (!resp)
{ {
reporter->Weird(fmt("OPENSSL Could not parse OCSP response (fuid %s)", GetFile()->GetID().c_str())); reporter->Weird(fmt("OPENSSL Could not parse OCSP response (fuid %s)", GetFile()->GetID().c_str()));
goto ocsp_cleanup; return false;
} }
//parse request into record OCSP_RESPVal* resp_val = new OCSP_RESPVal(resp); // resp_val takes ownership
OCSP_RESPVal* resp_val = new OCSP_RESPVal(resp); RecordVal* resp_record = ParseResponse(resp_val, GetFile()->GetID().c_str());
RecordVal* resp_record = ParseResponse(resp_val);
if (!resp_record)
{
reporter->Weird(fmt("Internal fail to parse OCSP response (fuid %s)", GetFile()->GetID().c_str()));
Unref(resp_val);
goto ocsp_cleanup;
}
// and send the record on to scriptland // and send the record on to scriptland
val_list* vl = new val_list(); val_list* vl = new val_list();
vl->append(GetFile()->GetVal()->Ref()); vl->append(GetFile()->GetVal()->Ref());
vl->append(resp_val->Ref()); vl->append(resp_val);
vl->append(resp_record->Ref()); vl->append(resp_record);
mgr.QueueEvent(ocsp_response, vl); mgr.QueueEvent(ocsp_response, vl);
Unref(resp_val);
Unref(resp_record);
} }
else else
{
reporter->Weird(fmt("the given argument of ocsp_type (%s) is not recognized", ocsp_type.c_str())); reporter->Weird(fmt("the given argument of ocsp_type (%s) is not recognized", ocsp_type.c_str()));
ocsp_cleanup: return false;
//if (resp) }
// OCSP_RESPONSE_free(resp);
//if (req) return true;
// OCSP_REQUEST_free(req);
return false;
} }
// parse OCSP request and trigger event RecordVal *file_analysis::OCSP::ParseRequest(OCSP_REQVal *req_val, const char* fid)
RecordVal *file_analysis::OCSP::ParseRequest(OCSP_REQVal *req_val)
{ {
if (req_val == NULL) OCSP_REQUEST *req = req_val->GetReq();
return NULL; OCSP_REQINFO *inf = req->tbsRequest;
OCSP_REQUEST *req = NULL;
OCSP_ONEREQ *one_req = NULL;
OCSP_CERTID *cert_id = NULL;
OCSP_REQINFO *inf = NULL;
//OCSP_SIGNATURE *sig = NULL;
RecordVal* ocsp_req_record = NULL; char buf[OCSP_STRING_BUF_SIZE]; // we need a buffer for some of the openssl functions
VectorVal* all_req_bro = NULL; memset(buf, 0, sizeof(buf));
int req_count = -1, i = -1, len = -1; RecordVal* ocsp_req_record = new RecordVal(BifType::Record::OCSP::Request);
long version = -1;
req = req_val->GetReq(); ocsp_req_record->Assign(0, new Val((uint64)ASN1_INTEGER_get(inf->version), TYPE_COUNT));
if (req == NULL) BIO *bio = BIO_new(BIO_s_mem());
return NULL;
char buf[OCSP_STRING_BUF_SIZE];
int buf_len = sizeof(buf);
memset(buf, 0, buf_len);
inf = req->tbsRequest;
//sig = req->optionalSignature;
if (inf == NULL)
return NULL;
ocsp_req_record = new RecordVal(BifType::Record::OCSP::Request);
if (!ocsp_req_record)
{
reporter->Error("Cannot create OCSP request structure: Internal memory error");
return NULL;
}
//version
version = ASN1_INTEGER_get(inf->version);
if (version != -1)
ocsp_req_record->Assign(0, new Val((uint64)version, TYPE_COUNT));
//requestorName
if (inf->requestorName != NULL) if (inf->requestorName != NULL)
{ {
len = -1; GENERAL_NAME_print(bio, inf->requestorName);
len = GENERAL_NAME_to_cstr(buf, buf_len, (void *)(inf->requestorName)); int len = BIO_read(bio, buf, sizeof(buf));
if (len > 0) ocsp_req_record->Assign(1, new StringVal(len, buf));
ocsp_req_record->Assign(1, new StringVal(len, buf)); BIO_reset(bio);
} }
//deal with details of the request VectorVal* all_req_bro = new VectorVal(internal_type("ocsp_req_vec")->AsVectorType());
req_count = OCSP_request_onereq_count(req); ocsp_req_record->Assign(2, all_req_bro);
if (req_count <= 0)
goto clean_up; int req_count = OCSP_request_onereq_count(req);
for (i=0; i<req_count; i++) for ( int i=0; i<req_count; i++ )
{ {
one_req = OCSP_request_onereq_get0(req, i); OCSP_ONEREQ *one_req = OCSP_request_onereq_get0(req, i);
cert_id = OCSP_onereq_get0_id(one_req); OCSP_CERTID *cert_id = OCSP_onereq_get0_id(one_req);
if (all_req_bro == NULL)
all_req_bro = new VectorVal(internal_type("ocsp_req_vec")->AsVectorType());
RecordVal *one_req_bro = new RecordVal(BifType::Record::OCSP::OneReq);
ocsp_fill_cert_id(cert_id, one_req_bro); RecordVal* one_req_bro = ocsp_fill_cert_id(cert_id, BifType::Record::OCSP::OneReq, bio);
all_req_bro->Assign(all_req_bro->Size(), one_req_bro); all_req_bro->Assign(i, one_req_bro);
} }
if (all_req_bro != NULL) BIO_free(bio);
ocsp_req_record->Assign(2, all_req_bro);
clean_up:
return ocsp_req_record; return ocsp_req_record;
} }
// parse OCSP response and trigger event RecordVal *file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val, const char* fid)
RecordVal *file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val)
{ {
if (resp_val == NULL) OCSP_RESPONSE *resp = resp_val->GetResp();
return NULL; OCSP_RESPBYTES *resp_bytes = resp->responseBytes;
OCSP_RESPONSE *resp = NULL; OCSP_BASICRESP *basic_resp = nullptr;
OCSP_RESPBYTES *resp_bytes = NULL; OCSP_RESPDATA *resp_data = nullptr;
OCSP_CERTID *cert_id = NULL; OCSP_RESPID *resp_id = nullptr;
OCSP_BASICRESP *basic_resp = NULL;
OCSP_RESPDATA *resp_data = NULL;
OCSP_RESPID *resp_id = NULL;
OCSP_SINGLERESP *single_resp = NULL;
OCSP_REVOKEDINFO *revoked_info = NULL;
OCSP_CERTSTATUS *cert_status = NULL;
RecordVal *ocsp_resp_record = NULL; int resp_count = 0;
VectorVal *all_resp_bro = NULL; VectorVal *all_resp_bro = nullptr;
int resp_count = -1, status = -1, i = -1, len = -1; char buf[OCSP_STRING_BUF_SIZE];
long version = -1; memset(buf, 0, sizeof(buf));
resp = resp_val->GetResp(); RecordVal *ocsp_resp_record = new RecordVal(BifType::Record::OCSP::Response);
if (resp == NULL)
return NULL;
char buf[OCSP_STRING_BUF_SIZE]; const char *status_str = OCSP_response_status_str(OCSP_response_status(resp));
int buf_len = sizeof(buf);
memset(buf, 0, buf_len);
ocsp_resp_record = new RecordVal(BifType::Record::OCSP::Response);
if (!ocsp_resp_record)
{
reporter->Error("Cannot create OCSP response structure: Internal memory error");
return NULL;
}
//responseStatus
status = OCSP_response_status(resp);
const char *status_str = OCSP_response_status_str(status);
ocsp_resp_record->Assign(0, new StringVal(strlen(status_str), status_str)); ocsp_resp_record->Assign(0, new StringVal(strlen(status_str), status_str));
//responseType
resp_bytes = resp->responseBytes;
if (!resp_bytes) if (!resp_bytes)
goto clean_up; return ocsp_resp_record;
len = -1;
len = ASN1_OBJECT_to_cstr(buf, buf_len, (void *)(resp_bytes->responseType));
if (len > 0)
ocsp_resp_record->Assign(1, new StringVal(len, buf));
//get the basic response BIO *bio = BIO_new(BIO_s_mem());
i2a_ASN1_OBJECT(bio, resp_bytes->responseType);
int len = BIO_read(bio, buf, sizeof(buf));
ocsp_resp_record->Assign(1, new StringVal(len, buf));
BIO_reset(bio);
// get the basic response
basic_resp = OCSP_response_get1_basic(resp); basic_resp = OCSP_response_get1_basic(resp);
if (!basic_resp) if ( !basic_resp )
goto clean_up; goto clean_up;
resp_data = basic_resp->tbsResponseData; resp_data = basic_resp->tbsResponseData;
if (!resp_data) if ( !resp_data )
goto clean_up; goto clean_up;
//version ocsp_resp_record->Assign(2, new Val((uint64)ASN1_INTEGER_get(resp_data->version), TYPE_COUNT));
version = ASN1_INTEGER_get(resp_data->version); // responderID
if (version != -1)
ocsp_resp_record->Assign(2, new Val((uint64)version, TYPE_COUNT));
//responderID
resp_id = resp_data->responderId; resp_id = resp_data->responderId;
len = -1; OCSP_RESPID_bio(resp_id, bio);
len = OCSP_RESPID_to_cstr(buf, buf_len, resp_id); len = BIO_read(bio, buf, sizeof(buf));
if (len > 0) ocsp_resp_record->Assign(3, new StringVal(len, buf));
ocsp_resp_record->Assign(3, new StringVal(len, buf)); BIO_reset(bio);
//producedAt // producedAt
len = -1; ocsp_resp_record->Assign(4, new Val(GetTimeFromAsn1(resp_data->producedAt, fid, reporter), TYPE_TIME));
len = ASN1_GENERALIZEDTIME_to_cstr(buf, buf_len, (void *)(resp_data->producedAt));
if (len > 0)
ocsp_resp_record->Assign(4, new StringVal(len, buf));
//responses all_resp_bro = new VectorVal(internal_type("ocsp_resp_vec")->AsVectorType());
ocsp_resp_record->Assign(5, all_resp_bro);
// responses
resp_count = sk_OCSP_SINGLERESP_num(resp_data->responses); resp_count = sk_OCSP_SINGLERESP_num(resp_data->responses);
if (resp_count <= 0) for ( int i=0; i<resp_count; i++ )
goto clean_up;
for (i=0; i<resp_count; i++)
{ {
single_resp = sk_OCSP_SINGLERESP_value(resp_data->responses, i); OCSP_SINGLERESP *single_resp = sk_OCSP_SINGLERESP_value(resp_data->responses, i);
if (!single_resp) if ( !single_resp )
continue; continue;
if (all_resp_bro == NULL)
all_resp_bro = new VectorVal(internal_type("ocsp_resp_vec")->AsVectorType());
RecordVal *single_resp_bro = new RecordVal(BifType::Record::OCSP::SingleResp);
//cert id // cert id
cert_id = single_resp->certId; OCSP_CERTID *cert_id = single_resp->certId;
ocsp_fill_cert_id(cert_id, single_resp_bro); RecordVal *single_resp_bro = ocsp_fill_cert_id(cert_id, BifType::Record::OCSP::SingleResp, bio);
BIO_reset(bio);
//certStatus // certStatus
cert_status = single_resp->certStatus; OCSP_CERTSTATUS *cert_status = single_resp->certStatus;
std::string cert_status_str = OCSP_cert_status_str(cert_status->type); const char* cert_status_str = OCSP_cert_status_str(cert_status->type);
std::string revoke_reason = ""; single_resp_bro->Assign(4, new StringVal(strlen(cert_status_str), cert_status_str));
std::string revoke_time = "";
//add revocation time and reason if it is revoked // revocation time and reason if revoked
if (cert_status->type == V_OCSP_CERTSTATUS_REVOKED) if ( cert_status->type == V_OCSP_CERTSTATUS_REVOKED )
{ {
revoked_info = cert_status->value.revoked; OCSP_REVOKEDINFO *revoked_info = cert_status->value.revoked;
len = -1; single_resp_bro->Assign(5, new Val(GetTimeFromAsn1(revoked_info->revocationTime, fid, reporter), TYPE_TIME));
len = ASN1_GENERALIZEDTIME_to_cstr(buf, buf_len, (void *)(revoked_info->revocationTime));
if (len > 0)
revoke_time.assign((const char *)buf, len);
if (revoked_info->revocationReason) if ( revoked_info->revocationReason )
revoke_reason = OCSP_crl_reason_str(ASN1_ENUMERATED_get(revoked_info->revocationReason)); {
const char* revoke_reason = OCSP_crl_reason_str(ASN1_ENUMERATED_get(revoked_info->revocationReason));
single_resp_bro->Assign(6, new StringVal(strlen(revoke_reason), revoke_reason));
}
} }
if (revoke_time.length() > 0)
cert_status_str += " " + revoke_time;
if (revoke_reason.length() > 0)
cert_status_str += " " + revoke_reason;
single_resp_bro->Assign(4, new StringVal(cert_status_str.length(), cert_status_str.c_str())); single_resp_bro->Assign(7, new Val(GetTimeFromAsn1(single_resp->thisUpdate, fid, reporter), TYPE_TIME));
if ( single_resp->nextUpdate )
single_resp_bro->Assign(8, new Val(GetTimeFromAsn1(single_resp->nextUpdate, fid, reporter), TYPE_TIME));
//thisUpdate all_resp_bro->Assign(i, single_resp_bro);
len = -1;
len = ASN1_GENERALIZEDTIME_to_cstr(buf, buf_len, (void *)(single_resp->thisUpdate));
if (len > 0)
single_resp_bro->Assign(5, new StringVal(len, buf));
//nextUpdate
len = -1;
len = ASN1_GENERALIZEDTIME_to_cstr(buf, buf_len, (void *)(single_resp->nextUpdate));
if (len > 0)
single_resp_bro->Assign(6, new StringVal(len, buf));
all_resp_bro->Assign(all_resp_bro->Size(), single_resp_bro);
} }
if (all_resp_bro != NULL)
ocsp_resp_record->Assign(5, all_resp_bro);
//signatureAlgorithm i2a_ASN1_OBJECT(bio, basic_resp->signatureAlgorithm->algorithm);
if (basic_resp->signatureAlgorithm) len = BIO_read(bio, buf, sizeof(buf));
{ ocsp_resp_record->Assign(6, new StringVal(len, buf));
len = -1; BIO_reset(bio);
len = ASN1_OBJECT_to_cstr(buf, buf_len, (void *)(basic_resp->signatureAlgorithm->algorithm));
if (len > 0) //i2a_ASN1_OBJECT(bio, basic_resp->signature);
ocsp_resp_record->Assign(6, new StringVal(len, buf)); //len = BIO_read(bio, buf, sizeof(buf));
} //ocsp_resp_record->Assign(7, new StringVal(len, buf));
//signature //BIO_reset(bio);
if (basic_resp->signature)
{
len = -1;
len = ASN1_BIT_STRING_to_cstr(buf, buf_len, (void *)(basic_resp->signature));
if (len > 0)
ocsp_resp_record->Assign(7, new StringVal(len, buf));
}
//certs //certs
if (basic_resp->certs) if ( basic_resp->certs )
{ {
VectorVal *certs_vector = new VectorVal(internal_type("x509_opaque_vector")->AsVectorType()); VectorVal *certs_vector = new VectorVal(internal_type("x509_opaque_vector")->AsVectorType());
int num_certs = sk_X509_num(basic_resp->certs); int num_certs = sk_X509_num(basic_resp->certs);
for (i=0; i<num_certs; i++) { for ( int i=0; i<num_certs; i++ )
{
::X509 *this_cert = X509_dup(helper_sk_X509_value(basic_resp->certs, i)); ::X509 *this_cert = X509_dup(helper_sk_X509_value(basic_resp->certs, i));
//::X509 *this_cert = X509_dup(sk_X509_value(basic_resp->certs, i)); //::X509 *this_cert = X509_dup(sk_X509_value(basic_resp->certs, i));
if (this_cert) if (this_cert)
certs_vector->Assign(i, new file_analysis::X509Val(this_cert)); certs_vector->Assign(i, new file_analysis::X509Val(this_cert));
else else
reporter->Weird("OpenSSL returned null certificate"); reporter->Weird("OpenSSL returned null certificate");
} }
ocsp_resp_record->Assign(8, certs_vector); ocsp_resp_record->Assign(7, certs_vector);
} }
clean_up: clean_up:
if (basic_resp) if (basic_resp)
OCSP_BASICRESP_free(basic_resp); OCSP_BASICRESP_free(basic_resp);
BIO_free(bio);
return ocsp_resp_record; return ocsp_resp_record;
} }
//OCSP_REQVal
OCSP_REQVal::OCSP_REQVal(OCSP_REQUEST* arg_ocsp_req) : OpaqueVal(ocsp_req_opaque_type) OCSP_REQVal::OCSP_REQVal(OCSP_REQUEST* arg_ocsp_req) : OpaqueVal(ocsp_req_opaque_type)
{ {
ocsp_req = arg_ocsp_req; ocsp_req = arg_ocsp_req;
@ -589,7 +331,7 @@ OCSP_REQVal::OCSP_REQVal(OCSP_REQUEST* arg_ocsp_req) : OpaqueVal(ocsp_req_opaque
OCSP_REQVal::OCSP_REQVal() : OpaqueVal(ocsp_req_opaque_type) OCSP_REQVal::OCSP_REQVal() : OpaqueVal(ocsp_req_opaque_type)
{ {
ocsp_req = NULL; ocsp_req = nullptr;
} }
OCSP_REQVal::~OCSP_REQVal() OCSP_REQVal::~OCSP_REQVal()
@ -606,7 +348,7 @@ OCSP_REQUEST* OCSP_REQVal::GetReq() const
bool OCSP_REQVal::DoSerialize(SerialInfo* info) const bool OCSP_REQVal::DoSerialize(SerialInfo* info) const
{ {
DO_SERIALIZE(SER_OCSP_REQ_VAL, OpaqueVal); DO_SERIALIZE(SER_OCSP_REQ_VAL, OpaqueVal);
unsigned char *buf = NULL; unsigned char *buf = nullptr;
int length = i2d_OCSP_REQUEST(ocsp_req, &buf); int length = i2d_OCSP_REQUEST(ocsp_req, &buf);
if ( length < 0 ) if ( length < 0 )
return false; return false;
@ -625,7 +367,7 @@ bool OCSP_REQVal::DoUnserialize(UnserialInfo* info)
if ( ! UNSERIALIZE_STR(reinterpret_cast<char **>(&ocsp_req_buf), &length) ) if ( ! UNSERIALIZE_STR(reinterpret_cast<char **>(&ocsp_req_buf), &length) )
return false; return false;
opensslbuf = ocsp_req_buf; // OpenSSL likes to shift pointers around. really. opensslbuf = ocsp_req_buf; // OpenSSL likes to shift pointers around. really.
ocsp_req = d2i_OCSP_REQUEST(NULL, const_cast<const unsigned char**>(&opensslbuf), length); ocsp_req = d2i_OCSP_REQUEST(nullptr, const_cast<const unsigned char**>(&opensslbuf), length);
delete[] ocsp_req_buf; delete[] ocsp_req_buf;
if ( !ocsp_req ) if ( !ocsp_req )
return false; return false;
@ -641,7 +383,7 @@ OCSP_RESPVal::OCSP_RESPVal(OCSP_RESPONSE* arg_ocsp_resp) : OpaqueVal(ocsp_resp_o
OCSP_RESPVal::OCSP_RESPVal() : OpaqueVal(ocsp_resp_opaque_type) OCSP_RESPVal::OCSP_RESPVal() : OpaqueVal(ocsp_resp_opaque_type)
{ {
ocsp_resp = NULL; ocsp_resp = nullptr;
} }
OCSP_RESPVal::~OCSP_RESPVal() OCSP_RESPVal::~OCSP_RESPVal()
@ -658,7 +400,7 @@ OCSP_RESPONSE* OCSP_RESPVal::GetResp() const
bool OCSP_RESPVal::DoSerialize(SerialInfo* info) const bool OCSP_RESPVal::DoSerialize(SerialInfo* info) const
{ {
DO_SERIALIZE(SER_OCSP_RESP_VAL, OpaqueVal); DO_SERIALIZE(SER_OCSP_RESP_VAL, OpaqueVal);
unsigned char *buf = NULL; unsigned char *buf = nullptr;
int length = i2d_OCSP_RESPONSE(ocsp_resp, &buf); int length = i2d_OCSP_RESPONSE(ocsp_resp, &buf);
if ( length < 0 ) if ( length < 0 )
return false; return false;
@ -677,7 +419,7 @@ bool OCSP_RESPVal::DoUnserialize(UnserialInfo* info)
if ( ! UNSERIALIZE_STR(reinterpret_cast<char **>(&ocsp_resp_buf), &length) ) if ( ! UNSERIALIZE_STR(reinterpret_cast<char **>(&ocsp_resp_buf), &length) )
return false; return false;
opensslbuf = ocsp_resp_buf; // OpenSSL likes to shift pointers around. really. opensslbuf = ocsp_resp_buf; // OpenSSL likes to shift pointers around. really.
ocsp_resp = d2i_OCSP_RESPONSE(NULL, const_cast<const unsigned char**>(&opensslbuf), length); ocsp_resp = d2i_OCSP_RESPONSE(nullptr, const_cast<const unsigned char**>(&opensslbuf), length);
delete[] ocsp_resp_buf; delete[] ocsp_resp_buf;
if ( !ocsp_resp ) if ( !ocsp_resp )
return false; return false;

View file

@ -24,8 +24,8 @@ public:
virtual bool Undelivered(uint64 offset, uint64 len); virtual bool Undelivered(uint64 offset, uint64 len);
virtual bool EndOfFile(); virtual bool EndOfFile();
static RecordVal *ParseResponse(OCSP_RESPVal *); static RecordVal *ParseResponse(OCSP_RESPVal *, const char* fid = 0);
static RecordVal *ParseRequest(OCSP_REQVal *); static RecordVal *ParseRequest(OCSP_REQVal *, const char* fid = 0);
static file_analysis::Analyzer* Instantiate(RecordVal* args, File* file); static file_analysis::Analyzer* Instantiate(RecordVal* args, File* file);

View file

@ -16,6 +16,8 @@
#include <openssl/opensslconf.h> #include <openssl/opensslconf.h>
#include <openssl/err.h> #include <openssl/err.h>
#include "Asn1Time.h"
using namespace file_analysis; using namespace file_analysis;
IMPLEMENT_SERIAL(X509Val, SER_X509_VAL); IMPLEMENT_SERIAL(X509Val, SER_X509_VAL);
@ -133,8 +135,8 @@ RecordVal* file_analysis::X509::ParseCertificate(X509Val* cert_val, const char*
pX509Cert->Assign(3, new StringVal(len, buf)); pX509Cert->Assign(3, new StringVal(len, buf));
BIO_free(bio); BIO_free(bio);
pX509Cert->Assign(5, new Val(GetTimeFromAsn1(X509_get_notBefore(ssl_cert), fid), TYPE_TIME)); pX509Cert->Assign(5, new Val(GetTimeFromAsn1(X509_get_notBefore(ssl_cert), fid, reporter), TYPE_TIME));
pX509Cert->Assign(6, new Val(GetTimeFromAsn1(X509_get_notAfter(ssl_cert), fid), TYPE_TIME)); pX509Cert->Assign(6, new Val(GetTimeFromAsn1(X509_get_notAfter(ssl_cert), fid, reporter), TYPE_TIME));
// we only read 255 bytes because byte 256 is always 0. // we only read 255 bytes because byte 256 is always 0.
// if the string is longer than 255, that will be our null-termination, // if the string is longer than 255, that will be our null-termination,
@ -517,164 +519,6 @@ unsigned int file_analysis::X509::KeyLength(EVP_PKEY *key)
reporter->InternalError("cannot be reached"); reporter->InternalError("cannot be reached");
} }
double file_analysis::X509::GetTimeFromAsn1(const ASN1_TIME* atime, const char* arg_fid)
{
const char *fid = arg_fid ? arg_fid : "";
time_t lResult = 0;
char lBuffer[26];
char* pBuffer = lBuffer;
const char *pString = (const char *) atime->data;
unsigned int remaining = atime->length;
if ( atime->type == V_ASN1_UTCTIME )
{
if ( remaining < 11 || remaining > 17 )
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- UTCTime has wrong length", fid));
return 0;
}
if ( pString[remaining-1] != 'Z' )
{
// not valid according to RFC 2459 4.1.2.5.1
reporter->Weird(fmt("Could not parse UTC time in non-YY-format in X509 certificate (x509 %s)", fid));
return 0;
}
// year is first two digits in YY format. Buffer expects YYYY format.
if ( pString[0] < '5' ) // RFC 2459 4.1.2.5.1
{
*(pBuffer++) = '2';
*(pBuffer++) = '0';
}
else
{
*(pBuffer++) = '1';
*(pBuffer++) = '9';
}
memcpy(pBuffer, pString, 10);
pBuffer += 10;
pString += 10;
remaining -= 10;
}
else if ( atime->type == V_ASN1_GENERALIZEDTIME )
{
// generalized time. We apparently ignore the YYYYMMDDHH case
// for now and assume we always have minutes and seconds.
// This should be ok because it is specified as a requirement in RFC 2459 4.1.2.5.2
if ( remaining < 12 || remaining > 23 )
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- Generalized time has wrong length", fid));
return 0;
}
memcpy(pBuffer, pString, 12);
pBuffer += 12;
pString += 12;
remaining -= 12;
}
else
{
reporter->Weird(fmt("Invalid time type in X509 certificate (fuid %s)", fid));
return 0;
}
if ( (remaining == 0) || (*pString == 'Z') || (*pString == '-') || (*pString == '+') )
{
*(pBuffer++) = '0';
*(pBuffer++) = '0';
}
else if ( remaining >= 2 )
{
*(pBuffer++) = *(pString++);
*(pBuffer++) = *(pString++);
remaining -= 2;
// Skip any fractional seconds...
if ( (remaining > 0) && (*pString == '.') )
{
pString++;
remaining--;
while ( (remaining > 0) && (*pString >= '0') && (*pString <= '9') )
{
pString++;
remaining--;
}
}
}
else
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- additional char after time", fid));
return 0;
}
*(pBuffer++) = 'Z';
*(pBuffer++) = '\0';
time_t lSecondsFromUTC;
if ( remaining == 0 || *pString == 'Z' )
lSecondsFromUTC = 0;
else
{
if ( remaining < 5 )
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- not enough bytes remaining for offset", fid));
return 0;
}
if ((*pString != '+') && (*pString != '-'))
{
reporter->Weird(fmt("Could not parse time in X509 certificate (fuid %s) -- unknown offset type", fid));
return 0;
}
lSecondsFromUTC = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60;
lSecondsFromUTC += (pString[3] - '0') * 10 + (pString[4] - '0');
if (*pString == '-')
lSecondsFromUTC = -lSecondsFromUTC;
}
tm lTime;
lTime.tm_sec = ((lBuffer[12] - '0') * 10) + (lBuffer[13] - '0');
lTime.tm_min = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
lTime.tm_hour = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
lTime.tm_mday = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
lTime.tm_mon = (((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0')) - 1;
lTime.tm_year = (lBuffer[0] - '0') * 1000 + (lBuffer[1] - '0') * 100 + ((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0');
if ( lTime.tm_year > 1900)
lTime.tm_year -= 1900;
lTime.tm_wday = 0;
lTime.tm_yday = 0;
lTime.tm_isdst = 0; // No DST adjustment requested
lResult = mktime(&lTime);
if ( lResult )
{
if ( lTime.tm_isdst != 0 )
lResult -= 3600; // mktime may adjust for DST (OS dependent)
lResult += lSecondsFromUTC;
}
else
lResult = 0;
return lResult;
}
X509Val::X509Val(::X509* arg_certificate) : OpaqueVal(x509_opaque_type) X509Val::X509Val(::X509* arg_certificate) : OpaqueVal(x509_opaque_type)
{ {
certificate = arg_certificate; certificate = arg_certificate;

View file

@ -62,7 +62,6 @@ private:
std::string cert_data; std::string cert_data;
// Helpers for ParseCertificate. // Helpers for ParseCertificate.
static double GetTimeFromAsn1(const ASN1_TIME * atime, const char* fid);
static StringVal* KeyCurve(EVP_PKEY *key); static StringVal* KeyCurve(EVP_PKEY *key);
static unsigned int KeyLength(EVP_PKEY *key); static unsigned int KeyLength(EVP_PKEY *key);
}; };

View file

@ -3,8 +3,8 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path ocsp #path ocsp
#open 2015-07-15-20-38-15 #open 2017-02-09-00-23-43
#fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method #fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method
#types time addr port addr port string string string string string string count string count time string string string count string string count string string string string #types time addr port addr port string string string string string string count string count time string string string count string time count string time time string
1436909712.307162 192.168.6.109 54690 216.58.192.46 80 CXWv6p3arKYeMETxOg sha1 F2E06AF9858A1D8D709B4919237AA9B51A287E64 4ADD06161BBCF668B576F581B6BB621ABA5A812F 3D474496FF942316 H4c4c3b287beafd8d7f4806a0b14d2ee1de88e4be 0 - 1 1436909712.329517 Ft368Gc1ce0Juvj0d successful Basic OCSP Response 0 4ADD06161BBCF668B576F581B6BB621ABA5A812F 20150711011056Z 1 good 20150711011056Z 20150718011056Z GET 1436909712.307162 192.168.6.109 54690 216.58.192.46 80 CHhAvVGS1DHFjwGM9 sha1 F2E06AF9858A1D8D709B4919237AA9B51A287E64 4ADD06161BBCF668B576F581B6BB621ABA5A812F 4ADD06161BBCF668B576F581B6BB621ABA5A812F H4c4c3b287beafd8d7f4806a0b14d2ee1de88e4be 0 - 1 1436909712.329517 Ft368Gc1ce0Juvj0d successful Basic OCSP Response 0 4ADD06161BBCF668B576F581B6BB621ABA5A812F 1436577056.000000 1 good 1436577056.000000 1437181856.000000 GET
#close 2015-07-15-20-38-15 #close 2017-02-09-00-23-43

View file

@ -3,8 +3,8 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path ocsp #path ocsp
#open 2015-07-15-20-25-27 #open 2017-02-09-00-24-29
#fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method #fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method
#types time addr port addr port string string string string string string count string count time string string string count string string count string string string string #types time addr port addr port string string string string string string count string count time string string string count string time count string time time string
1434666864.046145 192.168.6.109 34334 72.167.18.239 80 CXWv6p3arKYeMETxOg sha1 B6080D5F6C6B76EB13E438A5F8660BA85233344E 40C2BD278ECC348330A233D7FB6CB3F0B42C80CE 081C862DC8AAC9 FMbJOe2y5n1E7iSVsg 0 - 1 - - - - - - - - - - - POST 1434666864.046145 192.168.6.109 34334 72.167.18.239 80 CHhAvVGS1DHFjwGM9 sha1 B6080D5F6C6B76EB13E438A5F8660BA85233344E 40C2BD278ECC348330A233D7FB6CB3F0B42C80CE 40C2BD278ECC348330A233D7FB6CB3F0B42C80CE FMbJOe2y5n1E7iSVsg 0 - 1 - - - - - - - - - - - POST
#close 2015-07-15-20-25-27 #close 2017-02-09-00-24-29

View file

@ -3,8 +3,8 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path ocsp #path ocsp
#open 2015-07-15-20-24-10 #open 2017-02-09-00-24-32
#fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method #fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method
#types time addr port addr port string string string string string string count string count time string string string count string string count string string string string #types time addr port addr port string string string string string string count string count time string string string count string time count string time time string
1434666864.046145 192.168.6.109 34334 72.167.18.239 80 CXWv6p3arKYeMETxOg sha1 B6080D5F6C6B76EB13E438A5F8660BA85233344E 40C2BD278ECC348330A233D7FB6CB3F0B42C80CE 081C862DC8AAC9 FMbJOe2y5n1E7iSVsg 0 - 1 1434666864.070748 Fb215u2y5byABaV747 successful Basic OCSP Response 0 C = US, ST = Arizona, L = Scottsdale, O = GoDaddy Inc., CN = Go Daddy Validation Authority - G2 20150618220334Z 1 good 20150618220334Z 20150620100334Z POST 1434666864.046145 192.168.6.109 34334 72.167.18.239 80 CHhAvVGS1DHFjwGM9 sha1 B6080D5F6C6B76EB13E438A5F8660BA85233344E 40C2BD278ECC348330A233D7FB6CB3F0B42C80CE 40C2BD278ECC348330A233D7FB6CB3F0B42C80CE FMbJOe2y5n1E7iSVsg 0 - 1 1434666864.070748 Fb215u2y5byABaV747 successful Basic OCSP Response 0 C = US, ST = Arizona, L = Scottsdale, O = GoDaddy Inc., CN = Go Daddy Validation Authority - G2 1434665014.000000 1 good 1434665014.000000 1434794614.000000 POST
#close 2015-07-15-20-24-11 #close 2017-02-09-00-24-32

View file

@ -3,8 +3,8 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path ocsp #path ocsp
#open 2015-07-15-20-26-35 #open 2017-02-09-00-24-34
#fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method #fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method
#types time addr port addr port string string string string string string count string count time string string string count string string count string string string string #types time addr port addr port string string string string string string count string count time string string string count string time count string time time string
1434666864.070748 192.168.6.109 34334 72.167.18.239 80 CXWv6p3arKYeMETxOg sha1 B6080D5F6C6B76EB13E438A5F8660BA85233344E 40C2BD278ECC348330A233D7FB6CB3F0B42C80CE 081C862DC8AAC9 - - - - 1434666864.070748 Fb215u2y5byABaV747 successful Basic OCSP Response 0 C = US, ST = Arizona, L = Scottsdale, O = GoDaddy Inc., CN = Go Daddy Validation Authority - G2 20150618220334Z 1 good 20150618220334Z 20150620100334Z - 1434666864.070748 192.168.6.109 34334 72.167.18.239 80 CHhAvVGS1DHFjwGM9 sha1 B6080D5F6C6B76EB13E438A5F8660BA85233344E 40C2BD278ECC348330A233D7FB6CB3F0B42C80CE 40C2BD278ECC348330A233D7FB6CB3F0B42C80CE - - - - 1434666864.070748 Fb215u2y5byABaV747 successful Basic OCSP Response 0 C = US, ST = Arizona, L = Scottsdale, O = GoDaddy Inc., CN = Go Daddy Validation Authority - G2 1434665014.000000 1 good 1434665014.000000 1434794614.000000 -
#close 2015-07-15-20-26-36 #close 2017-02-09-00-24-34

View file

@ -3,11 +3,11 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path ocsp #path ocsp
#open 2015-07-31-20-35-18 #open 2017-02-09-00-24-36
#fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method #fields ts cid.orig_h cid.orig_p cid.resp_h cid.resp_p cuid certId.hashAlgorithm certId.issuerNameHash certId.issuerKeyHash certId.serialNumber req.id req.version req.requestorName req.index resp_ts resp.id resp.responseStatus resp.responseType resp.version resp.responderID resp.producedAt resp.index resp.certStatus resp.thisUpdate resp.nextUpdate method
#types time addr port addr port string string string string string string count string count time string string string count string string count string string string string #types time addr port addr port string string string string string string count string count time string string string count string time count string time time string
1438374032.518621 192.168.6.109 41812 23.5.251.27 80 CXWv6p3arKYeMETxOg sha1 74241467069FF5E0983F5E3E1A6BA0652A541575 0159ABE7DD3A0B59A66463D6CF200757D591E76A 010BF45E184C4169AB61B41168DF802E FDsgjS1bTYOzDpRJT4 0 - 1 1438374032.607628 Ftl4F41OsGtUDrOTWc successful Basic OCSP Response 0 F6215E926EB3EC41FE08FC25F09FB1B9A0344A10 20150707162834Z 1 revoked 20150514145849Z superseded 20150707162834Z 20150929011242Z POST 1438374032.518621 192.168.6.109 41812 23.5.251.27 80 CHhAvVGS1DHFjwGM9 sha1 74241467069FF5E0983F5E3E1A6BA0652A541575 0159ABE7DD3A0B59A66463D6CF200757D591E76A 0159ABE7DD3A0B59A66463D6CF200757D591E76A FDsgjS1bTYOzDpRJT4 0 - 1 1438374032.607628 Ftl4F41OsGtUDrOTWc successful Basic OCSP Response 0 F6215E926EB3EC41FE08FC25F09FB1B9A0344A10 1436286514.000000 1 revoked 1436286514.000000 1443489162.000000 POST
1438374032.650255 192.168.6.109 41813 23.5.251.27 80 CjhGID4nQcgTWjvg4c sha1 74241467069FF5E0983F5E3E1A6BA0652A541575 0159ABE7DD3A0B59A66463D6CF200757D591E76A 013D34BFD6348EBA231D6925768ACD87 F5Tv7Z16QkNApNg0yl 0 - 1 1438374032.732035 FXISxH2UuTiDn0qCa1 successful Basic OCSP Response 0 F6215E926EB3EC41FE08FC25F09FB1B9A0344A10 20150707212334Z 1 revoked 20150127203801Z unspecified 20150707212334Z 20150930071359Z POST 1438374032.650255 192.168.6.109 41813 23.5.251.27 80 ClEkJM2Vm5giqnMf4h sha1 74241467069FF5E0983F5E3E1A6BA0652A541575 0159ABE7DD3A0B59A66463D6CF200757D591E76A 0159ABE7DD3A0B59A66463D6CF200757D591E76A F5Tv7Z16QkNApNg0yl 0 - 1 1438374032.732035 FXISxH2UuTiDn0qCa1 successful Basic OCSP Response 0 F6215E926EB3EC41FE08FC25F09FB1B9A0344A10 1436304214.000000 1 revoked 1436304214.000000 1443597239.000000 POST
1438374032.759133 192.168.6.109 41814 23.5.251.27 80 CCvvfg3TEfuqmmG4bh sha1 74241467069FF5E0983F5E3E1A6BA0652A541575 0159ABE7DD3A0B59A66463D6CF200757D591E76A 0150C0C06D53F9D39205D84EFB5F2BA4 FGzVem3KYelVVdAze 0 - 1 1438374032.848522 F3OYfx3A0JvMX787V3 successful Basic OCSP Response 0 F6215E926EB3EC41FE08FC25F09FB1B9A0344A10 20150707030344Z 1 revoked 20150528055348Z (UNKNOWN) 20150707030344Z 20150928205739Z POST 1438374032.759133 192.168.6.109 41814 23.5.251.27 80 C4J4Th3PJpwUYZZ6gc sha1 74241467069FF5E0983F5E3E1A6BA0652A541575 0159ABE7DD3A0B59A66463D6CF200757D591E76A 0159ABE7DD3A0B59A66463D6CF200757D591E76A FGzVem3KYelVVdAze 0 - 1 1438374032.848522 F3OYfx3A0JvMX787V3 successful Basic OCSP Response 0 F6215E926EB3EC41FE08FC25F09FB1B9A0344A10 1436238224.000000 1 revoked 1436238224.000000 1443473859.000000 POST
1438374032.875001 192.168.6.109 41815 23.5.251.27 80 CsRx2w45OKnoww6xl4 sha1 74241467069FF5E0983F5E3E1A6BA0652A541575 0159ABE7DD3A0B59A66463D6CF200757D591E76A 017447CB30072EE15B9C1B057B731C5A FbmX4PpDIRU82YGK8 0 - 1 1438374033.033504 FVty9v3KTnCvbg0Xf2 successful Basic OCSP Response 0 F6215E926EB3EC41FE08FC25F09FB1B9A0344A10 20150708020344Z 1 revoked 20150117113259Z keyCompromise 20150708020344Z 20150928165507Z POST 1438374032.875001 192.168.6.109 41815 23.5.251.27 80 CtPZjS20MLrsMUOJi2 sha1 74241467069FF5E0983F5E3E1A6BA0652A541575 0159ABE7DD3A0B59A66463D6CF200757D591E76A 0159ABE7DD3A0B59A66463D6CF200757D591E76A FbmX4PpDIRU82YGK8 0 - 1 1438374033.033504 FVty9v3KTnCvbg0Xf2 successful Basic OCSP Response 0 F6215E926EB3EC41FE08FC25F09FB1B9A0344A10 1436321024.000000 1 revoked 1436321024.000000 1443459307.000000 POST
#close 2015-07-31-20-35-18 #close 2017-02-09-00-24-36