mirror of
https://github.com/zeek/zeek.git
synced 2025-10-12 11:38:20 +00:00
Make OCSP analyzer part of the X.509 analyzer
This allows the easier integration of shared functionality. And it also makes logical sense, given that OCSP is not interesting without X.509.
This commit is contained in:
parent
dfc871f831
commit
c670613996
16 changed files with 13 additions and 47 deletions
685
src/file_analysis/analyzer/x509/OCSP.cc
Normal file
685
src/file_analysis/analyzer/x509/OCSP.cc
Normal file
|
@ -0,0 +1,685 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "OCSP.h"
|
||||
#include "Event.h"
|
||||
|
||||
#include "ocsp_events.bif.h"
|
||||
#include "ocsp_types.bif.h"
|
||||
|
||||
#include "file_analysis/Manager.h"
|
||||
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
// helper function of sk_X509_value to avoid namespace problem
|
||||
// sk_X509_value(X,Y) = > SKM_sk_value(X509,X,Y)
|
||||
// X509 => file_analysis::X509
|
||||
X509 *helper_sk_X509_value(STACK_OF(X509) *certs, int i)
|
||||
{
|
||||
return sk_X509_value(certs, i);
|
||||
}
|
||||
|
||||
#include "file_analysis/analyzer/x509/X509.h"
|
||||
|
||||
using namespace file_analysis;
|
||||
|
||||
IMPLEMENT_SERIAL(OCSP_REQVal, SER_OCSP_REQ_VAL);
|
||||
IMPLEMENT_SERIAL(OCSP_RESPVal, SER_OCSP_RESP_VAL);
|
||||
|
||||
#define OCSP_STRING_BUF_SIZE 2048
|
||||
|
||||
//this function is copied from src/file_analysis/analyzer/extract/Extract.cc
|
||||
static Val* get_extract_field_val(RecordVal* args, const char* name)
|
||||
{
|
||||
Val* rval = args->Lookup(name);
|
||||
if ( ! rval )
|
||||
reporter->Error("File extraction analyzer missing arg field: %s", name);
|
||||
return rval;
|
||||
}
|
||||
|
||||
//convert different ANS1 type to c string
|
||||
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 (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)
|
||||
{
|
||||
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 void ocsp_print_cert_id(OCSP_CERTID *cid)
|
||||
{
|
||||
if (cid == NULL)
|
||||
return;
|
||||
char buf[OCSP_STRING_BUF_SIZE];
|
||||
int len = sizeof(buf);
|
||||
memset(buf, 0, len);
|
||||
int new_len = -1;
|
||||
|
||||
//print hashAlgorithm
|
||||
new_len = ASN1_OBJECT_to_cstr(buf, len, (void *)(cid->hashAlgorithm->algorithm));
|
||||
StringVal hashAlgorithm = StringVal(new_len, buf);
|
||||
printf("[%d]hashAlgorithm: %s\n", new_len, hashAlgorithm.CheckString());
|
||||
|
||||
//print issuerNameHash
|
||||
new_len = ASN1_OCTET_STRING_to_cstr(buf, len, (void *)(cid->issuerNameHash));
|
||||
StringVal issuerNameHash = StringVal(new_len, buf);
|
||||
printf("[%d]issuerNameHash: %s\n", new_len, issuerNameHash.CheckString());
|
||||
|
||||
//print issuerKeyHash
|
||||
new_len = ASN1_OCTET_STRING_to_cstr(buf, len, (void *)(cid->issuerKeyHash));
|
||||
StringVal issuerKeyHash = StringVal(new_len, buf);
|
||||
printf("[%d]issuerKeyHash: %s\n", new_len, issuerKeyHash.CheckString());
|
||||
|
||||
//print serialNumber
|
||||
new_len = ASN1_INTEGER_to_cstr(buf, len, (void *)(cid->serialNumber));
|
||||
StringVal serialNumber = StringVal(new_len, buf);
|
||||
printf("[%d]serialNumber: %s\n", new_len, serialNumber.CheckString());
|
||||
}
|
||||
|
||||
//fill in cert id
|
||||
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)
|
||||
{
|
||||
Val* ocsp_type = get_extract_field_val(args, "ocsp_type");
|
||||
if (! ocsp_type )
|
||||
return 0;
|
||||
return new OCSP(args, file, ocsp_type->AsString()->CheckString());
|
||||
}
|
||||
|
||||
file_analysis::OCSP::OCSP(RecordVal* args, file_analysis::File* file, const string& arg_ocsp_type)
|
||||
: file_analysis::Analyzer(file_mgr->GetComponentTag("OCSP"), args, file)
|
||||
{
|
||||
ocsp_type = arg_ocsp_type;
|
||||
ocsp_data.clear();
|
||||
}
|
||||
|
||||
bool file_analysis::OCSP::DeliverStream(const u_char* data, uint64 len)
|
||||
{
|
||||
ocsp_data.append(reinterpret_cast<const char*>(data), len);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool file_analysis::OCSP::Undelivered(uint64 offset, uint64 len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse OCSP request or response and send data to bro scriptland
|
||||
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());
|
||||
|
||||
if (ocsp_type == "request")
|
||||
{
|
||||
req = d2i_OCSP_REQUEST(NULL, &ocsp_char, ocsp_data.size());
|
||||
if (!req)
|
||||
{
|
||||
reporter->Weird(fmt("OPENSSL Could not parse OCSP request (fuid %s)", GetFile()->GetID().c_str()));
|
||||
goto ocsp_cleanup;
|
||||
}
|
||||
|
||||
//parse request into record
|
||||
OCSP_REQVal* req_val = new OCSP_REQVal(req);
|
||||
RecordVal* req_record = ParseRequest(req_val);
|
||||
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
|
||||
val_list* vl = new val_list();
|
||||
vl->append(GetFile()->GetVal()->Ref());
|
||||
vl->append(req_val->Ref());
|
||||
vl->append(req_record->Ref());
|
||||
mgr.QueueEvent(ocsp_request, vl);
|
||||
|
||||
Unref(req_val);
|
||||
Unref(req_record);
|
||||
}
|
||||
else if (ocsp_type == "response")
|
||||
{
|
||||
resp = d2i_OCSP_RESPONSE(NULL, &ocsp_char, ocsp_data.size());
|
||||
if (!resp)
|
||||
{
|
||||
reporter->Weird(fmt("OPENSSL Could not parse OCSP response (fuid %s)", GetFile()->GetID().c_str()));
|
||||
goto ocsp_cleanup;
|
||||
}
|
||||
|
||||
//parse request into record
|
||||
OCSP_RESPVal* resp_val = new OCSP_RESPVal(resp);
|
||||
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
|
||||
val_list* vl = new val_list();
|
||||
vl->append(GetFile()->GetVal()->Ref());
|
||||
vl->append(resp_val->Ref());
|
||||
vl->append(resp_record->Ref());
|
||||
mgr.QueueEvent(ocsp_response, vl);
|
||||
|
||||
Unref(resp_val);
|
||||
Unref(resp_record);
|
||||
}
|
||||
else
|
||||
reporter->Weird(fmt("the given argument of ocsp_type (%s) is not recognized", ocsp_type.c_str()));
|
||||
ocsp_cleanup:
|
||||
//if (resp)
|
||||
// OCSP_RESPONSE_free(resp);
|
||||
//if (req)
|
||||
// OCSP_REQUEST_free(req);
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse OCSP request and trigger event
|
||||
RecordVal *file_analysis::OCSP::ParseRequest(OCSP_REQVal *req_val)
|
||||
{
|
||||
if (req_val == NULL)
|
||||
return NULL;
|
||||
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;
|
||||
VectorVal* all_req_bro = NULL;
|
||||
|
||||
int req_count = -1, i = -1, len = -1;
|
||||
long version = -1;
|
||||
|
||||
req = req_val->GetReq();
|
||||
if (req == NULL)
|
||||
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)
|
||||
{
|
||||
len = -1;
|
||||
len = GENERAL_NAME_to_cstr(buf, buf_len, (void *)(inf->requestorName));
|
||||
if (len > 0)
|
||||
ocsp_req_record->Assign(1, new StringVal(len, buf));
|
||||
}
|
||||
|
||||
//deal with details of the request
|
||||
req_count = OCSP_request_onereq_count(req);
|
||||
if (req_count <= 0)
|
||||
goto clean_up;
|
||||
for (i=0; i<req_count; i++)
|
||||
{
|
||||
one_req = OCSP_request_onereq_get0(req, i);
|
||||
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);
|
||||
all_req_bro->Assign(all_req_bro->Size(), one_req_bro);
|
||||
}
|
||||
|
||||
if (all_req_bro != NULL)
|
||||
ocsp_req_record->Assign(2, all_req_bro);
|
||||
clean_up:
|
||||
return ocsp_req_record;
|
||||
}
|
||||
|
||||
// parse OCSP response and trigger event
|
||||
RecordVal *file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val)
|
||||
{
|
||||
if (resp_val == NULL)
|
||||
return NULL;
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
OCSP_RESPBYTES *resp_bytes = NULL;
|
||||
OCSP_CERTID *cert_id = NULL;
|
||||
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;
|
||||
VectorVal *all_resp_bro = NULL;
|
||||
|
||||
int resp_count = -1, status = -1, i = -1, len = -1;
|
||||
long version = -1;
|
||||
|
||||
resp = resp_val->GetResp();
|
||||
if (resp == NULL)
|
||||
return NULL;
|
||||
|
||||
char buf[OCSP_STRING_BUF_SIZE];
|
||||
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));
|
||||
|
||||
//responseType
|
||||
resp_bytes = resp->responseBytes;
|
||||
if (!resp_bytes)
|
||||
goto clean_up;
|
||||
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
|
||||
basic_resp = OCSP_response_get1_basic(resp);
|
||||
if (!basic_resp)
|
||||
goto clean_up;
|
||||
resp_data = basic_resp->tbsResponseData;
|
||||
if (!resp_data)
|
||||
goto clean_up;
|
||||
|
||||
//version
|
||||
version = ASN1_INTEGER_get(resp_data->version);
|
||||
if (version != -1)
|
||||
ocsp_resp_record->Assign(2, new Val((uint64)version, TYPE_COUNT));
|
||||
|
||||
//responderID
|
||||
resp_id = resp_data->responderId;
|
||||
len = -1;
|
||||
len = OCSP_RESPID_to_cstr(buf, buf_len, resp_id);
|
||||
if (len > 0)
|
||||
ocsp_resp_record->Assign(3, new StringVal(len, buf));
|
||||
|
||||
//producedAt
|
||||
len = -1;
|
||||
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
|
||||
resp_count = sk_OCSP_SINGLERESP_num(resp_data->responses);
|
||||
if (resp_count <= 0)
|
||||
goto clean_up;
|
||||
for (i=0; i<resp_count; i++)
|
||||
{
|
||||
single_resp = sk_OCSP_SINGLERESP_value(resp_data->responses, i);
|
||||
if (!single_resp)
|
||||
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 = single_resp->certId;
|
||||
ocsp_fill_cert_id(cert_id, single_resp_bro);
|
||||
|
||||
//certStatus
|
||||
cert_status = single_resp->certStatus;
|
||||
std::string cert_status_str = OCSP_cert_status_str(cert_status->type);
|
||||
std::string revoke_reason = "";
|
||||
std::string revoke_time = "";
|
||||
|
||||
//add revocation time and reason if it is revoked
|
||||
if (cert_status->type == V_OCSP_CERTSTATUS_REVOKED)
|
||||
{
|
||||
revoked_info = cert_status->value.revoked;
|
||||
len = -1;
|
||||
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)
|
||||
revoke_reason = OCSP_crl_reason_str(ASN1_ENUMERATED_get(revoked_info->revocationReason));
|
||||
}
|
||||
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()));
|
||||
|
||||
//thisUpdate
|
||||
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
|
||||
if (basic_resp->signatureAlgorithm)
|
||||
{
|
||||
len = -1;
|
||||
len = ASN1_OBJECT_to_cstr(buf, buf_len, (void *)(basic_resp->signatureAlgorithm->algorithm));
|
||||
if (len > 0)
|
||||
ocsp_resp_record->Assign(6, new StringVal(len, buf));
|
||||
}
|
||||
//signature
|
||||
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
|
||||
if (basic_resp->certs)
|
||||
{
|
||||
VectorVal *certs_vector = new VectorVal(internal_type("x509_opaque_vector")->AsVectorType());
|
||||
int num_certs = sk_X509_num(basic_resp->certs);
|
||||
for (i=0; i<num_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));
|
||||
if (this_cert)
|
||||
certs_vector->Assign(i, new file_analysis::X509Val(this_cert));
|
||||
else
|
||||
reporter->Weird("OpenSSL returned null certificate");
|
||||
}
|
||||
ocsp_resp_record->Assign(8, certs_vector);
|
||||
}
|
||||
clean_up:
|
||||
if (basic_resp)
|
||||
OCSP_BASICRESP_free(basic_resp);
|
||||
return ocsp_resp_record;
|
||||
}
|
||||
|
||||
//OCSP_REQVal
|
||||
OCSP_REQVal::OCSP_REQVal(OCSP_REQUEST* arg_ocsp_req) : OpaqueVal(ocsp_req_opaque_type)
|
||||
{
|
||||
ocsp_req = arg_ocsp_req;
|
||||
}
|
||||
|
||||
OCSP_REQVal::OCSP_REQVal() : OpaqueVal(ocsp_req_opaque_type)
|
||||
{
|
||||
ocsp_req = NULL;
|
||||
}
|
||||
|
||||
OCSP_REQVal::~OCSP_REQVal()
|
||||
{
|
||||
if (ocsp_req)
|
||||
OCSP_REQUEST_free(ocsp_req);
|
||||
}
|
||||
|
||||
OCSP_REQUEST* OCSP_REQVal::GetReq() const
|
||||
{
|
||||
return ocsp_req;
|
||||
}
|
||||
|
||||
bool OCSP_REQVal::DoSerialize(SerialInfo* info) const
|
||||
{
|
||||
DO_SERIALIZE(SER_OCSP_REQ_VAL, OpaqueVal);
|
||||
unsigned char *buf = NULL;
|
||||
int length = i2d_OCSP_REQUEST(ocsp_req, &buf);
|
||||
if ( length < 0 )
|
||||
return false;
|
||||
bool res = SERIALIZE_STR(reinterpret_cast<const char*>(buf), length);
|
||||
OPENSSL_free(buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool OCSP_REQVal::DoUnserialize(UnserialInfo* info)
|
||||
{
|
||||
DO_UNSERIALIZE(OpaqueVal)
|
||||
|
||||
int length;
|
||||
unsigned char *ocsp_req_buf, *opensslbuf;
|
||||
|
||||
if ( ! UNSERIALIZE_STR(reinterpret_cast<char **>(&ocsp_req_buf), &length) )
|
||||
return false;
|
||||
opensslbuf = ocsp_req_buf; // OpenSSL likes to shift pointers around. really.
|
||||
ocsp_req = d2i_OCSP_REQUEST(NULL, const_cast<const unsigned char**>(&opensslbuf), length);
|
||||
delete[] ocsp_req_buf;
|
||||
if ( !ocsp_req )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//OCSP_RESPVal
|
||||
OCSP_RESPVal::OCSP_RESPVal(OCSP_RESPONSE* arg_ocsp_resp) : OpaqueVal(ocsp_resp_opaque_type)
|
||||
{
|
||||
ocsp_resp = arg_ocsp_resp;
|
||||
}
|
||||
|
||||
OCSP_RESPVal::OCSP_RESPVal() : OpaqueVal(ocsp_resp_opaque_type)
|
||||
{
|
||||
ocsp_resp = NULL;
|
||||
}
|
||||
|
||||
OCSP_RESPVal::~OCSP_RESPVal()
|
||||
{
|
||||
if (ocsp_resp)
|
||||
OCSP_RESPONSE_free(ocsp_resp);
|
||||
}
|
||||
|
||||
OCSP_RESPONSE* OCSP_RESPVal::GetResp() const
|
||||
{
|
||||
return ocsp_resp;
|
||||
}
|
||||
|
||||
bool OCSP_RESPVal::DoSerialize(SerialInfo* info) const
|
||||
{
|
||||
DO_SERIALIZE(SER_OCSP_RESP_VAL, OpaqueVal);
|
||||
unsigned char *buf = NULL;
|
||||
int length = i2d_OCSP_RESPONSE(ocsp_resp, &buf);
|
||||
if ( length < 0 )
|
||||
return false;
|
||||
bool res = SERIALIZE_STR(reinterpret_cast<const char*>(buf), length);
|
||||
OPENSSL_free(buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool OCSP_RESPVal::DoUnserialize(UnserialInfo* info)
|
||||
{
|
||||
DO_UNSERIALIZE(OpaqueVal)
|
||||
|
||||
int length;
|
||||
unsigned char *ocsp_resp_buf, *opensslbuf;
|
||||
|
||||
if ( ! UNSERIALIZE_STR(reinterpret_cast<char **>(&ocsp_resp_buf), &length) )
|
||||
return false;
|
||||
opensslbuf = ocsp_resp_buf; // OpenSSL likes to shift pointers around. really.
|
||||
ocsp_resp = d2i_OCSP_RESPONSE(NULL, const_cast<const unsigned char**>(&opensslbuf), length);
|
||||
delete[] ocsp_resp_buf;
|
||||
if ( !ocsp_resp )
|
||||
return false;
|
||||
return true;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue