Files
heimdal/lib/hx509/revoke.c
Love Hörnquist Åstrand 099a14e094 hx509_certs_find is now exposed.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@16811 ec53bebd-3082-4978-b11e-865c3cabbd6b
2006-03-26 23:49:04 +00:00

248 lines
6.6 KiB
C

/*
* Copyright (c) 2006 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "hx_locl.h"
RCSID("$Id$");
struct revoke_crl {
char *path;
CRLCertificateList crl;
int verified;
};
struct hx509_revoke_ctx_data {
struct {
struct revoke_crl *val;
size_t len;
} crls;
};
int
hx509_revoke_init(hx509_context context, hx509_revoke_ctx *revoke)
{
*revoke = calloc(1, sizeof(**revoke));
if (*revoke == NULL)
return ENOMEM;
(*revoke)->crls.len = 0;
(*revoke)->crls.val = NULL;
return 0;
}
void
hx509_revoke_free(hx509_revoke_ctx *revoke)
{
size_t i ;
for (i = 0; i < (*revoke)->crls.len; i++) {
free((*revoke)->crls.val[i].path);
free_CRLCertificateList(&(*revoke)->crls.val[i].crl);
}
free((*revoke)->crls.val);
memset(*revoke, 0, sizeof(**revoke));
free(*revoke);
*revoke = NULL;
}
static int
verify_crl(hx509_context context,
CRLCertificateList *crl,
time_t time_now,
hx509_certs certs)
{
heim_octet_string os;
hx509_cert signer;
hx509_query q;
time_t t;
int ret;
t = _hx509_Time2time_t(&crl->tbsCertList.thisUpdate);
if (t > time_now)
return HX509_CRL_USED_BEFORE_TIME;
if (crl->tbsCertList.nextUpdate == NULL)
return HX509_CRL_INVALID_FORMAT;
t = _hx509_Time2time_t(crl->tbsCertList.nextUpdate);
if (t < time_now)
return HX509_CRL_USED_AFTER_TIME;
_hx509_query_clear(&q);
q.match = HX509_QUERY_MATCH_SUBJECT_NAME;
q.subject_name = &crl->tbsCertList.issuer;
ret = hx509_certs_find(context, certs, &q, &signer);
if (ret)
return ret;
os.data = crl->signatureValue.data;
os.length = crl->signatureValue.length / 8;
ret = hx509_verify_signature(context,
signer,
&crl->signatureAlgorithm,
&crl->tbsCertList._save,
&os);
hx509_cert_free(signer);
return ret;
}
int
hx509_revoke_add_crl(hx509_context context,
hx509_revoke_ctx revoke,
const char *path)
{
size_t length, size;
void *data;
size_t i;
int ret;
if (strncmp(path, "FILE:", 5) != 0)
return EINVAL;
path += 5;
for (i = 0; i < revoke->crls.len; i++) {
if (strcmp(revoke->crls.val[0].path, path) == 0)
return 0;
}
data = realloc(revoke->crls.val,
(revoke->crls.len + 1) * sizeof(revoke->crls.val[0]));
if (data == NULL)
return ENOMEM;
revoke->crls.val = data;
memset(&revoke->crls.val[revoke->crls.len], 0, sizeof(revoke->crls.val[0]));
revoke->crls.val[revoke->crls.len].path = strdup(path);
if (revoke->crls.val[revoke->crls.len].path == NULL)
return ENOMEM;
ret = _hx509_map_file(path, &data, &length);
if (ret) {
free(revoke->crls.val[revoke->crls.len].path);
return ret;
}
ret = decode_CRLCertificateList(data, length,
&revoke->crls.val[revoke->crls.len].crl,
&size);
_hx509_unmap_file(data, length);
if (ret) {
free(revoke->crls.val[revoke->crls.len].path);
return ret;
}
/* check signature is aligned */
if (revoke->crls.val[revoke->crls.len].crl.signatureValue.length & 7) {
free(revoke->crls.val[revoke->crls.len].path);
free_CRLCertificateList(&revoke->crls.val[revoke->crls.len].crl);
return EINVAL;
}
revoke->crls.len++;
return ret;
}
int
hx509_revoke_verify(hx509_context context,
hx509_revoke_ctx revoke,
hx509_certs certs,
time_t now,
hx509_cert cert)
{
const Certificate *c = _hx509_get_cert(cert);
unsigned long i, j, k;
int ret;
for (i = 0; i < revoke->crls.len; i++) {
struct revoke_crl *crl = &revoke->crls.val[i];
/* check if cert.issuer == crls.val[i].crl.issuer */
ret = _hx509_name_cmp(&c->tbsCertificate.issuer,
&crl->crl.tbsCertList.issuer);
if (ret)
continue;
/* verify signature in crl if not already done */
if (crl->verified == 0) {
ret = verify_crl(context, &crl->crl, now, certs);
if (ret)
return ret;
crl->verified = 1;
}
if (crl->crl.tbsCertList.crlExtensions)
for (j = 0; j < crl->crl.tbsCertList.crlExtensions->len; j++)
if (crl->crl.tbsCertList.crlExtensions->val[j].critical)
return HX509_CRL_UNKNOWN_EXTENSION;
if (crl->crl.tbsCertList.revokedCertificates == NULL)
return 0;
/* check if cert is in crl */
for (j = 0; j < crl->crl.tbsCertList.revokedCertificates->len; j++) {
time_t t;
ret = heim_integer_cmp(&crl->crl.tbsCertList.revokedCertificates->val[j].userCertificate,
&c->tbsCertificate.serialNumber);
if (ret != 0)
continue;
t = _hx509_Time2time_t(&crl->crl.tbsCertList.revokedCertificates->val[j].revocationDate);
if (t > now)
continue;
if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions)
for (k = 0; k < crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->len; k++)
if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->val[k].critical)
return HX509_CRL_UNKNOWN_EXTENSION;
return HX509_CRL_CERT_REVOKED;
}
return 0;
}
if (context->flags & HX509_CTX_CRL_MISSING_OK)
return 0;
return HX509_CRL_MISSING;
}