[xmlsec] add cert verification
- From: Aleksey Sanin <aleksey src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [xmlsec] add cert verification
- Date: Mon, 24 May 2010 22:36:13 +0000 (UTC)
commit d26ba23ea7697207a53b331ea1bba0bf29685000
Author: Aleksey Sanin <aleksey aleksey com>
Date: Mon May 24 11:08:29 2010 -0700
add cert verification
src/gnutls/x509utils.c | 10 +-
src/gnutls/x509vfy.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 250 insertions(+), 5 deletions(-)
---
diff --git a/src/gnutls/x509utils.c b/src/gnutls/x509utils.c
index 037096f..7417ed8 100644
--- a/src/gnutls/x509utils.c
+++ b/src/gnutls/x509utils.c
@@ -833,13 +833,15 @@ xmlSecGnuTLSPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
goto done;
}
for(ii = 0; ii < certsSize; ++ii) {
- cert = xmlSecPtrListRemoveAndReturn(certsList, ii);
- if(cert == NULL) {
+ gnutls_x509_crt_t tmp;
+
+ tmp = xmlSecPtrListGetItem(certsList, ii);
+ if(tmp == NULL) {
continue;
}
cert_id_size = sizeof(cert_id);
- err = gnutls_x509_crt_get_key_id(cert, 0, cert_id, &cert_id_size);
+ err = gnutls_x509_crt_get_key_id(tmp, 0, cert_id, &cert_id_size);
if(err != GNUTLS_E_SUCCESS) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
@@ -851,7 +853,7 @@ xmlSecGnuTLSPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
/* if key ids match, then this is THE key cert!!! */
if((key_id_size == cert_id_size) && (memcmp(key_id, cert_id, key_id_size) == 0)) {
- (*key_cert) = xmlSecGnuTLSX509CertDup(cert);
+ (*key_cert) = xmlSecGnuTLSX509CertDup(tmp);
if((*key_cert) == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
diff --git a/src/gnutls/x509vfy.c b/src/gnutls/x509vfy.c
index 0ebbcb0..c87b6aa 100644
--- a/src/gnutls/x509vfy.c
+++ b/src/gnutls/x509vfy.c
@@ -83,6 +83,11 @@ static gnutls_x509_crt_t xmlSecGnuTLSX509FindCert (xmlSecP
const xmlChar *issuerName,
const xmlChar *issuerSerial,
const xmlChar *ski);
+static gnutls_x509_crt_t xmlSecGnuTLSX509FindSignedCert (xmlSecPtrListPtr certs,
+ gnutls_x509_crt_t cert);
+static gnutls_x509_crt_t xmlSecGnuTLSX509FindSignerCert (xmlSecPtrListPtr certs,
+ gnutls_x509_crt_t cert);
+
/**
* xmlSecGnuTLSX509StoreGetKlass:
@@ -150,15 +155,123 @@ xmlSecGnuTLSX509StoreVerify(xmlSecKeyDataStorePtr store,
xmlSecPtrListPtr certs,
const xmlSecKeyInfoCtx* keyInfoCtx) {
xmlSecGnuTLSX509StoreCtxPtr ctx;
+ gnutls_x509_crt_t res = NULL;
+ xmlSecSize certs_size = 0;
+ gnutls_x509_crt_t * cert_list = NULL;
+ xmlSecSize cert_list_length;
+ gnutls_x509_crt_t * ca_list = NULL;
+ xmlSecSize ca_list_length;
+ xmlSecSize ii;
+ int err;
xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), NULL);
xmlSecAssert2(certs != NULL, NULL);
xmlSecAssert2(keyInfoCtx != NULL, NULL);
+ certs_size = xmlSecPtrListGetSize(certs);
+ if(certs_size <= 0) {
+ /* nothing to do */
+ return(NULL);
+ }
+
ctx = xmlSecGnuTLSX509StoreGetCtx(store);
xmlSecAssert2(ctx != NULL, NULL);
+ /* Prepare */
+ cert_list_length = certs_size + xmlSecPtrListGetSize(&(ctx->certsUntrusted));
+ if(cert_list_length > 0) {
+ cert_list = (gnutls_x509_crt_t *)xmlMalloc(sizeof(gnutls_x509_crt_t) * cert_list_length);
+ if(cert_list == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)(sizeof(gnutls_x509_crt_t) * cert_list_length));
+ goto done;
+ }
+ }
+ ca_list_length = xmlSecPtrListGetSize(&(ctx->certsTrusted));
+ if(ca_list_length > 0) {
+ ca_list = (gnutls_x509_crt_t *)xmlMalloc(sizeof(gnutls_x509_crt_t) * ca_list_length);
+ if(ca_list == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)(sizeof(gnutls_x509_crt_t) * ca_list_length));
+ goto done;
+ }
+ for(ii = 0; ii < ca_list_length; ++ii) {
+ ca_list[ii] = xmlSecPtrListGetItem(&(ctx->certsTrusted), ii);
+ if(ca_list[ii] == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecPtrListGetItem(certsTrusted)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+ }
+
/* We are going to build all possible cert chains and try to verify them */
+ for(ii = 0; (ii < certs_size) && (res == NULL); ++ii) {
+ gnutls_x509_crt_t cert, cert2;
+ xmlSecSize cert_list_cur_length = 0;
+ unsigned int verify = 0;
+
+ cert = xmlSecPtrListGetItem(certs, ii);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecPtrListGetItem(certs)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* check if we are the "leaf" node in the certs chain */
+ if(xmlSecGnuTLSX509FindSignedCert(certs, cert) != NULL) {
+ continue;
+ }
+
+ /* build the chain */
+ for(cert2 = cert, cert_list_cur_length = 0;
+ (cert2 != NULL) && (cert_list_cur_length < cert_list_length);
+ ++cert_list_cur_length)
+ {
+ gnutls_x509_crt_t tmp;
+
+ /* store */
+ cert_list[cert_list_cur_length] = cert2;
+
+ /* find next */
+ tmp = xmlSecGnuTLSX509FindSignerCert(certs, cert2);
+ if(tmp == NULL) {
+ tmp = xmlSecGnuTLSX509FindSignerCert(&(ctx->certsUntrusted), cert2);
+ }
+ cert2 = tmp;
+ }
+
+ /* try to verify */
+ err = gnutls_x509_crt_list_verify(
+ cert_list, (int)cert_list_cur_length, /* certs chain */
+ ca_list, (int)ca_list_length, /* trusted cas */
+ NULL, 0, /* crls */
+ 0, /* flags */
+ &verify);
+ if(err == GNUTLS_E_SUCCESS) {
+ /* TODO: check the timestamp */
+ res = cert;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_list_verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ /* don't stop, continue! */
+ }
+ }
/*
for(ii = 0; ii < certs.size; ++ii) {
@@ -183,7 +296,15 @@ xmlSecGnuTLSX509StoreVerify(xmlSecKeyDataStorePtr store,
}
*/
- return(NULL);
+done:
+ if(ca_list != NULL) {
+ xmlFree(ca_list);
+ }
+ if(cert_list != NULL) {
+ xmlFree(cert_list);
+ }
+
+ return(res);
#ifdef TODO
STACK_OF(X509)* certs2 = NULL;
@@ -561,6 +682,128 @@ xmlSecGnuTLSX509FindCert(xmlSecPtrListPtr certs,
return(NULL);
}
+/* signed cert has issuer dn equal to our's subject dn */
+static gnutls_x509_crt_t
+xmlSecGnuTLSX509FindSignedCert(xmlSecPtrListPtr certs, gnutls_x509_crt_t cert) {
+ gnutls_x509_crt_t res = NULL;
+ xmlChar * subject = NULL;
+ xmlSecSize ii, sz;
+
+ xmlSecAssert2(certs != NULL, NULL);
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* get subject */
+ subject = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+ if(subject == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetSubjectDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* todo: this is not the fastest way to search certs */
+ sz = xmlSecPtrListGetSize(certs);
+ for(ii = 0; (ii < sz) && (res == NULL); ++ii) {
+ gnutls_x509_crt_t tmp;
+ xmlChar * issuer;
+
+ tmp = xmlSecPtrListGetItem(certs, ii);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ goto done;
+ }
+
+ issuer = xmlSecGnuTLSX509CertGetIssuerDN(tmp);
+ if(issuer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetIssuerDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ goto done;
+ }
+
+ /* are we done? */
+ if(xmlStrEqual(subject, issuer)) {
+ res = tmp;
+ }
+ xmlFree(issuer);
+ }
+
+done:
+ if(subject != NULL) {
+ xmlFree(subject);
+ }
+ return(res);
+}
+
+/* signer cert has subject dn equal to our's issuer dn */
+static gnutls_x509_crt_t
+xmlSecGnuTLSX509FindSignerCert(xmlSecPtrListPtr certs, gnutls_x509_crt_t cert) {
+ gnutls_x509_crt_t res = NULL;
+ xmlChar * issuer = NULL;
+ xmlSecSize ii, sz;
+
+ xmlSecAssert2(certs != NULL, NULL);
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* get issuer */
+ issuer = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+ if(issuer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetIssuerDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* todo: this is not the fastest way to search certs */
+ sz = xmlSecPtrListGetSize(certs);
+ for(ii = 0; (ii < sz) && (res == NULL); ++ii) {
+ gnutls_x509_crt_t tmp;
+ xmlChar * subject;
+
+ tmp = xmlSecPtrListGetItem(certs, ii);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ goto done;
+ }
+
+ subject = xmlSecGnuTLSX509CertGetSubjectDN(tmp);
+ if(subject == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetSubjectDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ goto done;
+ }
+
+ /* are we done? */
+ if(xmlStrEqual(issuer, subject)) {
+ res = tmp;
+ }
+ xmlFree(subject);
+ }
+
+done:
+ if(issuer != NULL) {
+ xmlFree(issuer);
+ }
+ return(res);
+}
+
#endif /* XMLSEC_NO_X509 */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]