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);
|
certinfo->destroy(certinfo);
|
||||||
return FALSE;
|
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
|
/* with strict crl policy the public key must have the same
|
||||||
* lifetime as the validity of the ocsp status or crl lifetime
|
* 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_UNKNOWN:
|
||||||
case CERT_UNDEFINED:
|
case CERT_UNDEFINED:
|
||||||
default:
|
default:
|
||||||
DBG2(DBG_CFG, "certificate status unknown");
|
DBG1(DBG_CFG, "certificate status unknown");
|
||||||
if (this->strict)
|
if (this->strict)
|
||||||
{
|
{
|
||||||
/* update status of end certificate in the credential store */
|
/* 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;
|
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
|
* Implements certinfo_t.set_nextUpdate
|
||||||
*/
|
*/
|
||||||
@@ -192,6 +208,7 @@ certinfo_t *certinfo_create(chunk_t serial)
|
|||||||
/* initialize */
|
/* initialize */
|
||||||
this->serialNumber = chunk_clone(serial);
|
this->serialNumber = chunk_clone(serial);
|
||||||
this->status = CERT_UNDEFINED;
|
this->status = CERT_UNDEFINED;
|
||||||
|
this->thisUpdate = UNDEFINED_TIME;
|
||||||
this->nextUpdate = UNDEFINED_TIME;
|
this->nextUpdate = UNDEFINED_TIME;
|
||||||
this->revocationTime = UNDEFINED_TIME;
|
this->revocationTime = UNDEFINED_TIME;
|
||||||
this->revocationReason = REASON_UNSPECIFIED;
|
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.get_serialNumber = (chunk_t (*) (const certinfo_t*))get_serialNumber;
|
||||||
this->public.set_status = (void (*) (certinfo_t*,cert_status_t))set_status;
|
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.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.set_nextUpdate = (void (*) (certinfo_t*,time_t))set_nextUpdate;
|
||||||
this->public.get_nextUpdate = (time_t (*) (const certinfo_t*))get_nextUpdate;
|
this->public.get_nextUpdate = (time_t (*) (const certinfo_t*))get_nextUpdate;
|
||||||
this->public.set_revocationTime = (void (*) (certinfo_t*,time_t))set_revocationTime;
|
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);
|
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.
|
* @brief Set nextUpdate.
|
||||||
*
|
*
|
||||||
* @param this calling object
|
* @param this calling object
|
||||||
* @return nextUpdate
|
* @param nextUpdate
|
||||||
*/
|
*/
|
||||||
void (*set_nextUpdate) (certinfo_t *this, time_t 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
|
* SHA-1 hash over issuer distinguished name
|
||||||
*/
|
*/
|
||||||
chunk_t authNameID;
|
chunk_t authNameID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHA-1 hash over issuer public key
|
||||||
|
*/
|
||||||
|
chunk_t authKeyID;
|
||||||
};
|
};
|
||||||
|
|
||||||
ENUM(response_status_names, STATUS_SUCCESSFUL, STATUS_UNAUTHORIZED,
|
ENUM(response_status_names, STATUS_SUCCESSFUL, STATUS_UNAUTHORIZED,
|
||||||
@@ -153,35 +158,6 @@ static response_t* response_create_from_chunk(chunk_t chunk)
|
|||||||
return this;
|
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 */
|
/* some OCSP specific prefabricated ASN.1 constants */
|
||||||
|
|
||||||
static u_char ASN1_nonce_oid_str[] = {
|
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)
|
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 serialNumber = certinfo->get_serialNumber(certinfo);
|
||||||
|
|
||||||
chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm",
|
chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm",
|
||||||
ASN1_sha1_id,
|
ASN1_sha1_id,
|
||||||
asn1_simple_object(ASN1_OCTET_STRING, this->authNameID),
|
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));
|
asn1_simple_object(ASN1_INTEGER, serialNumber));
|
||||||
|
|
||||||
return asn1_wrap(ASN1_SEQUENCE, "m", reqCert);
|
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
|
* 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;
|
u_int level, extn_oid;
|
||||||
asn1_ctx_t ctx;
|
asn1_ctx_t ctx;
|
||||||
@@ -668,6 +643,8 @@ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response
|
|||||||
chunk_t object;
|
chunk_t object;
|
||||||
int objectID = 0;
|
int objectID = 0;
|
||||||
|
|
||||||
|
certinfo_t *certinfo = NULL;
|
||||||
|
|
||||||
asn1_init(&ctx, blob, level0, FALSE, FALSE);
|
asn1_init(&ctx, blob, level0, FALSE, FALSE);
|
||||||
|
|
||||||
while (objectID < SINGLE_RESPONSE_ROOF)
|
while (objectID < SINGLE_RESPONSE_ROOF)
|
||||||
@@ -680,38 +657,70 @@ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response
|
|||||||
switch (objectID)
|
switch (objectID)
|
||||||
{
|
{
|
||||||
case SINGLE_RESPONSE_ALGORITHM:
|
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;
|
break;
|
||||||
case SINGLE_RESPONSE_ISSUER_NAME_HASH:
|
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;
|
break;
|
||||||
case SINGLE_RESPONSE_ISSUER_KEY_HASH:
|
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;
|
break;
|
||||||
case SINGLE_RESPONSE_SERIAL_NUMBER:
|
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;
|
break;
|
||||||
case SINGLE_RESPONSE_CERT_STATUS_GOOD:
|
case SINGLE_RESPONSE_CERT_STATUS_GOOD:
|
||||||
sres->status = CERT_GOOD;
|
certinfo->set_status(certinfo, CERT_GOOD);
|
||||||
break;
|
break;
|
||||||
case SINGLE_RESPONSE_CERT_STATUS_REVOKED:
|
case SINGLE_RESPONSE_CERT_STATUS_REVOKED:
|
||||||
sres->status = CERT_REVOKED;
|
certinfo->set_status(certinfo, CERT_REVOKED);
|
||||||
break;
|
break;
|
||||||
case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:
|
case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:
|
||||||
sres->revocationTime = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
certinfo->set_revocationTime(certinfo,
|
||||||
|
asn1totime(&object, ASN1_GENERALIZEDTIME));
|
||||||
break;
|
break;
|
||||||
case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
|
case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
|
||||||
sres->revocationReason = (object.len == 1)
|
certinfo->set_revocationReason(certinfo,
|
||||||
? *object.ptr : REASON_UNSPECIFIED;
|
(object.len == 1) ? *object.ptr : REASON_UNSPECIFIED);
|
||||||
break;
|
break;
|
||||||
case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
|
case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
|
||||||
sres->status = CERT_UNKNOWN;
|
certinfo->set_status(certinfo, CERT_UNKNOWN);
|
||||||
break;
|
break;
|
||||||
case SINGLE_RESPONSE_THIS_UPDATE:
|
case SINGLE_RESPONSE_THIS_UPDATE:
|
||||||
sres->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
certinfo->set_thisUpdate(certinfo,
|
||||||
|
asn1totime(&object, ASN1_GENERALIZEDTIME));
|
||||||
break;
|
break;
|
||||||
case SINGLE_RESPONSE_NEXT_UPDATE:
|
case SINGLE_RESPONSE_NEXT_UPDATE:
|
||||||
sres->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
certinfo->set_nextUpdate(certinfo,
|
||||||
|
asn1totime(&object, ASN1_GENERALIZEDTIME));
|
||||||
break;
|
break;
|
||||||
case SINGLE_RESPONSE_EXT_ID:
|
case SINGLE_RESPONSE_EXT_ID:
|
||||||
extn_oid = known_oid(object);
|
extn_oid = known_oid(object);
|
||||||
@@ -727,14 +736,6 @@ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response
|
|||||||
return TRUE;
|
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
|
* 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)
|
if (objectID == RESPONSES_SINGLE_RESPONSE)
|
||||||
{
|
{
|
||||||
single_response_t sres = empty_single_response;
|
ocsp_parse_single_response(this, object, level+1);
|
||||||
|
|
||||||
if (ocsp_parse_single_response(object, level+1, &sres))
|
|
||||||
{
|
|
||||||
process_single_response(this, &sres);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
objectID++;
|
objectID++;
|
||||||
}
|
}
|
||||||
@@ -911,6 +907,8 @@ ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris)
|
|||||||
this->uris = uris;
|
this->uris = uris;
|
||||||
this->certinfos = linked_list_create();
|
this->certinfos = linked_list_create();
|
||||||
this->nonce = chunk_empty;
|
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);
|
hasher_t *hasher = hasher_create(HASH_SHA1);
|
||||||
identification_t *issuer = cacert->get_subject(cacert);
|
identification_t *issuer = cacert->get_subject(cacert);
|
||||||
|
|||||||
Reference in New Issue
Block a user