results from the single responses is stored in the corresponding certinfo_t structs
This commit is contained in:
@@ -645,7 +645,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
|
||||
certinfo->destroy(certinfo);
|
||||
return FALSE;
|
||||
}
|
||||
DBG2(DBG_CFG, "certificate is good");
|
||||
DBG1(DBG_CFG, "certificate is good");
|
||||
|
||||
/* with strict crl policy the public key must have the same
|
||||
* lifetime as the validity of the ocsp status or crl lifetime
|
||||
@@ -684,7 +684,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
|
||||
case CERT_UNKNOWN:
|
||||
case CERT_UNDEFINED:
|
||||
default:
|
||||
DBG2(DBG_CFG, "certificate status unknown");
|
||||
DBG1(DBG_CFG, "certificate status unknown");
|
||||
if (this->strict)
|
||||
{
|
||||
/* update status of end certificate in the credential store */
|
||||
|
||||
@@ -125,6 +125,22 @@ static cert_status_t get_status(const private_certinfo_t *this)
|
||||
return this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements certinfo_t.set_thisUpdate
|
||||
*/
|
||||
static void set_thisUpdate(private_certinfo_t *this, time_t thisUpdate)
|
||||
{
|
||||
this->thisUpdate = thisUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements certinfo_t.get_thisUpdate
|
||||
*/
|
||||
static time_t get_thisUpdate(const private_certinfo_t *this)
|
||||
{
|
||||
return this->thisUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements certinfo_t.set_nextUpdate
|
||||
*/
|
||||
@@ -192,6 +208,7 @@ certinfo_t *certinfo_create(chunk_t serial)
|
||||
/* initialize */
|
||||
this->serialNumber = chunk_clone(serial);
|
||||
this->status = CERT_UNDEFINED;
|
||||
this->thisUpdate = UNDEFINED_TIME;
|
||||
this->nextUpdate = UNDEFINED_TIME;
|
||||
this->revocationTime = UNDEFINED_TIME;
|
||||
this->revocationReason = REASON_UNSPECIFIED;
|
||||
@@ -201,6 +218,8 @@ certinfo_t *certinfo_create(chunk_t serial)
|
||||
this->public.get_serialNumber = (chunk_t (*) (const certinfo_t*))get_serialNumber;
|
||||
this->public.set_status = (void (*) (certinfo_t*,cert_status_t))set_status;
|
||||
this->public.get_status = (cert_status_t (*) (const certinfo_t*))get_status;
|
||||
this->public.set_thisUpdate = (void (*) (certinfo_t*,time_t))set_thisUpdate;
|
||||
this->public.get_thisUpdate = (time_t (*) (const certinfo_t*))get_thisUpdate;
|
||||
this->public.set_nextUpdate = (void (*) (certinfo_t*,time_t))set_nextUpdate;
|
||||
this->public.get_nextUpdate = (time_t (*) (const certinfo_t*))get_nextUpdate;
|
||||
this->public.set_revocationTime = (void (*) (certinfo_t*,time_t))set_revocationTime;
|
||||
|
||||
@@ -99,11 +99,27 @@ struct certinfo_t {
|
||||
*/
|
||||
cert_status_t (*get_status) (const certinfo_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set thisUpdate.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param thisUpdate thisUpdate
|
||||
*/
|
||||
void (*set_thisUpdate) (certinfo_t *this, time_t thisUpdate);
|
||||
|
||||
/**
|
||||
* @brief Get thisUpdate.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return thisUpdate
|
||||
*/
|
||||
time_t (*get_thisUpdate) (const certinfo_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set nextUpdate.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return nextUpdate
|
||||
* @param nextUpdate
|
||||
*/
|
||||
void (*set_nextUpdate) (certinfo_t *this, time_t nextUpdate);
|
||||
|
||||
|
||||
@@ -85,6 +85,11 @@ struct private_ocsp_t {
|
||||
* SHA-1 hash over issuer distinguished name
|
||||
*/
|
||||
chunk_t authNameID;
|
||||
|
||||
/**
|
||||
* SHA-1 hash over issuer public key
|
||||
*/
|
||||
chunk_t authKeyID;
|
||||
};
|
||||
|
||||
ENUM(response_status_names, STATUS_SUCCESSFUL, STATUS_UNAUTHORIZED,
|
||||
@@ -153,35 +158,6 @@ static response_t* response_create_from_chunk(chunk_t chunk)
|
||||
return this;
|
||||
}
|
||||
|
||||
/* single response container */
|
||||
typedef struct single_response single_response_t;
|
||||
|
||||
struct single_response {
|
||||
single_response_t *next;
|
||||
int hash_algorithm;
|
||||
chunk_t issuer_name_hash;
|
||||
chunk_t issuer_key_hash;
|
||||
chunk_t serialNumber;
|
||||
cert_status_t status;
|
||||
time_t revocationTime;
|
||||
crl_reason_t revocationReason;
|
||||
time_t thisUpdate;
|
||||
time_t nextUpdate;
|
||||
};
|
||||
|
||||
const single_response_t empty_single_response = {
|
||||
NULL , /* *next */
|
||||
OID_UNKNOWN , /* hash_algorithm */
|
||||
{ NULL, 0 } , /* issuer_name_hash */
|
||||
{ NULL, 0 } , /* issuer_key_hash */
|
||||
{ NULL, 0 } , /* serial_number */
|
||||
CERT_UNDEFINED , /* status */
|
||||
UNDEFINED_TIME , /* revocationTime */
|
||||
REASON_UNSPECIFIED, /* revocationReason */
|
||||
UNDEFINED_TIME , /* this_update */
|
||||
UNDEFINED_TIME /* next_update */
|
||||
};
|
||||
|
||||
/* some OCSP specific prefabricated ASN.1 constants */
|
||||
|
||||
static u_char ASN1_nonce_oid_str[] = {
|
||||
@@ -346,13 +322,12 @@ static chunk_t build_requestor_name(private_ocsp_t *this)
|
||||
*/
|
||||
static chunk_t build_request(private_ocsp_t *this, certinfo_t *certinfo)
|
||||
{
|
||||
chunk_t authKeyID = this->cacert->get_subjectKeyID(this->cacert);
|
||||
chunk_t serialNumber = certinfo->get_serialNumber(certinfo);
|
||||
|
||||
chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm",
|
||||
ASN1_sha1_id,
|
||||
asn1_simple_object(ASN1_OCTET_STRING, this->authNameID),
|
||||
asn1_simple_object(ASN1_OCTET_STRING, authKeyID),
|
||||
asn1_simple_object(ASN1_OCTET_STRING, this->authKeyID),
|
||||
asn1_simple_object(ASN1_INTEGER, serialNumber));
|
||||
|
||||
return asn1_wrap(ASN1_SEQUENCE, "m", reqCert);
|
||||
@@ -660,7 +635,7 @@ static bool ocsp_valid_response(response_t *res, x509_t *ocsp_cert)
|
||||
/**
|
||||
* parse a single OCSP response
|
||||
*/
|
||||
static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response_t *sres)
|
||||
static bool ocsp_parse_single_response(private_ocsp_t *this, chunk_t blob, int level0)
|
||||
{
|
||||
u_int level, extn_oid;
|
||||
asn1_ctx_t ctx;
|
||||
@@ -668,6 +643,8 @@ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response
|
||||
chunk_t object;
|
||||
int objectID = 0;
|
||||
|
||||
certinfo_t *certinfo = NULL;
|
||||
|
||||
asn1_init(&ctx, blob, level0, FALSE, FALSE);
|
||||
|
||||
while (objectID < SINGLE_RESPONSE_ROOF)
|
||||
@@ -680,38 +657,70 @@ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response
|
||||
switch (objectID)
|
||||
{
|
||||
case SINGLE_RESPONSE_ALGORITHM:
|
||||
sres->hash_algorithm = parse_algorithmIdentifier(object, level+1, NULL);
|
||||
if (parse_algorithmIdentifier(object, level+1, NULL) != OID_SHA1)
|
||||
{
|
||||
DBG1("only sha-1 hash supported in ocsp single response");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case SINGLE_RESPONSE_ISSUER_NAME_HASH:
|
||||
sres->issuer_name_hash = object;
|
||||
if (!chunk_equals(object, this->authNameID))
|
||||
{
|
||||
DBG1("ocsp single response has wrong issuer name hash");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case SINGLE_RESPONSE_ISSUER_KEY_HASH:
|
||||
sres->issuer_key_hash = object;
|
||||
if (!chunk_equals(object, this->authKeyID))
|
||||
{
|
||||
DBG1("ocsp single response has wrong issuer key hash");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case SINGLE_RESPONSE_SERIAL_NUMBER:
|
||||
sres->serialNumber = object;
|
||||
{
|
||||
iterator_t *iterator = this->certinfos->create_iterator(this->certinfos, TRUE);
|
||||
certinfo_t *current_certinfo;
|
||||
|
||||
while (iterator->iterate(iterator, (void**)¤t_certinfo))
|
||||
{
|
||||
if (chunk_equals(object, current_certinfo->get_serialNumber(current_certinfo)))
|
||||
{
|
||||
certinfo = current_certinfo;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
if (certinfo == NULL)
|
||||
{
|
||||
DBG1("unrequested serial number in ocsp single response");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SINGLE_RESPONSE_CERT_STATUS_GOOD:
|
||||
sres->status = CERT_GOOD;
|
||||
certinfo->set_status(certinfo, CERT_GOOD);
|
||||
break;
|
||||
case SINGLE_RESPONSE_CERT_STATUS_REVOKED:
|
||||
sres->status = CERT_REVOKED;
|
||||
certinfo->set_status(certinfo, CERT_REVOKED);
|
||||
break;
|
||||
case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:
|
||||
sres->revocationTime = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
||||
certinfo->set_revocationTime(certinfo,
|
||||
asn1totime(&object, ASN1_GENERALIZEDTIME));
|
||||
break;
|
||||
case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
|
||||
sres->revocationReason = (object.len == 1)
|
||||
? *object.ptr : REASON_UNSPECIFIED;
|
||||
certinfo->set_revocationReason(certinfo,
|
||||
(object.len == 1) ? *object.ptr : REASON_UNSPECIFIED);
|
||||
break;
|
||||
case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
|
||||
sres->status = CERT_UNKNOWN;
|
||||
certinfo->set_status(certinfo, CERT_UNKNOWN);
|
||||
break;
|
||||
case SINGLE_RESPONSE_THIS_UPDATE:
|
||||
sres->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
||||
certinfo->set_thisUpdate(certinfo,
|
||||
asn1totime(&object, ASN1_GENERALIZEDTIME));
|
||||
break;
|
||||
case SINGLE_RESPONSE_NEXT_UPDATE:
|
||||
sres->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
||||
certinfo->set_nextUpdate(certinfo,
|
||||
asn1totime(&object, ASN1_GENERALIZEDTIME));
|
||||
break;
|
||||
case SINGLE_RESPONSE_EXT_ID:
|
||||
extn_oid = known_oid(object);
|
||||
@@ -727,14 +736,6 @@ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* process received ocsp single response and add it to ocsp cache
|
||||
*/
|
||||
static void process_single_response(private_ocsp_t *this, single_response_t *sres)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
/**
|
||||
* verify and process ocsp response and update the ocsp cache
|
||||
*/
|
||||
@@ -825,12 +826,7 @@ static void ocsp_process_response(private_ocsp_t *this, response_t *res, credent
|
||||
}
|
||||
if (objectID == RESPONSES_SINGLE_RESPONSE)
|
||||
{
|
||||
single_response_t sres = empty_single_response;
|
||||
|
||||
if (ocsp_parse_single_response(object, level+1, &sres))
|
||||
{
|
||||
process_single_response(this, &sres);
|
||||
}
|
||||
ocsp_parse_single_response(this, object, level+1);
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
@@ -911,6 +907,8 @@ ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris)
|
||||
this->uris = uris;
|
||||
this->certinfos = linked_list_create();
|
||||
this->nonce = chunk_empty;
|
||||
this->authKeyID = cacert->get_subjectKeyID(cacert);
|
||||
/* TODO compute authKeyID in case subjectKeyID does not exist */
|
||||
{
|
||||
hasher_t *hasher = hasher_create(HASH_SHA1);
|
||||
identification_t *issuer = cacert->get_subject(cacert);
|
||||
|
||||
Reference in New Issue
Block a user