diff options
author | Anas Nashif <anas.nashif@intel.com> | 2013-09-20 04:45:41 -0400 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2013-09-20 04:45:41 -0400 |
commit | 6b6383d52bc147134bb6b60b07e924b176c67e3a (patch) | |
tree | 9753a1ec40b1fbe2acfaa881af46e3c0f7da6401 /src/gnutls/x509vfy.c | |
parent | 07bb297329b9e9754d09dcb6d70417272a626619 (diff) | |
download | xmlsec1-6b6383d52bc147134bb6b60b07e924b176c67e3a.tar.gz xmlsec1-6b6383d52bc147134bb6b60b07e924b176c67e3a.tar.bz2 xmlsec1-6b6383d52bc147134bb6b60b07e924b176c67e3a.zip |
Imported Upstream version 1.2.19
Diffstat (limited to 'src/gnutls/x509vfy.c')
-rw-r--r-- | src/gnutls/x509vfy.c | 802 |
1 files changed, 802 insertions, 0 deletions
diff --git a/src/gnutls/x509vfy.c b/src/gnutls/x509vfy.c new file mode 100644 index 00000000..fd15c5ac --- /dev/null +++ b/src/gnutls/x509vfy.c @@ -0,0 +1,802 @@ +/** + * XMLSec library + * + * X509 support + * + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#ifndef XMLSEC_NO_X509 + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +#include <libxml/tree.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/keyinfo.h> +#include <xmlsec/keysmngr.h> +#include <xmlsec/base64.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gnutls/crypto.h> +#include <xmlsec/gnutls/x509.h> + +#include "x509utils.h" + +/************************************************************************** + * + * Internal GnuTLS X509 store CTX + * + *************************************************************************/ +typedef struct _xmlSecGnuTLSX509StoreCtx xmlSecGnuTLSX509StoreCtx, + *xmlSecGnuTLSX509StoreCtxPtr; +struct _xmlSecGnuTLSX509StoreCtx { + xmlSecPtrList certsTrusted; + xmlSecPtrList certsUntrusted; +}; + +/**************************************************************************** + * + * xmlSecGnuTLSKeyDataStoreX509Id: + * + * xmlSecGnuTLSX509StoreCtx is located after xmlSecTransform + * + ***************************************************************************/ +#define xmlSecGnuTLSX509StoreGetCtx(store) \ + ((xmlSecGnuTLSX509StoreCtxPtr)(((xmlSecByte*)(store)) + \ + sizeof(xmlSecKeyDataStoreKlass))) +#define xmlSecGnuTLSX509StoreSize \ + (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecGnuTLSX509StoreCtx)) + +static int xmlSecGnuTLSX509StoreInitialize (xmlSecKeyDataStorePtr store); +static void xmlSecGnuTLSX509StoreFinalize (xmlSecKeyDataStorePtr store); + +static xmlSecKeyDataStoreKlass xmlSecGnuTLSX509StoreKlass = { + sizeof(xmlSecKeyDataStoreKlass), + xmlSecGnuTLSX509StoreSize, + + /* data */ + xmlSecNameX509Store, /* const xmlChar* name; */ + + /* constructors/destructor */ + xmlSecGnuTLSX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */ + xmlSecGnuTLSX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +static gnutls_x509_crt_t xmlSecGnuTLSX509FindCert (xmlSecPtrListPtr certs, + const xmlChar *subjectName, + 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: + * + * The GnuTLS X509 certificates key data store klass. + * + * Returns: pointer to GnuTLS X509 certificates key data store klass. + */ +xmlSecKeyDataStoreId +xmlSecGnuTLSX509StoreGetKlass(void) { + return(&xmlSecGnuTLSX509StoreKlass); +} + +/** + * xmlSecGnuTLSX509StoreFindCert: + * @store: the pointer to X509 key data store klass. + * @subjectName: the desired certificate name. + * @issuerName: the desired certificate issuer name. + * @issuerSerial: the desired certificate issuer serial number. + * @ski: the desired certificate SKI. + * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context. + * + * Searches @store for a certificate that matches given criteria. + * + * Returns: pointer to found certificate or NULL if certificate is not found + * or an error occurs. + */ +gnutls_x509_crt_t +xmlSecGnuTLSX509StoreFindCert(xmlSecKeyDataStorePtr store, + const xmlChar *subjectName, + const xmlChar *issuerName, + const xmlChar *issuerSerial, + const xmlChar *ski, + const xmlSecKeyInfoCtx* keyInfoCtx) { + xmlSecGnuTLSX509StoreCtxPtr ctx; + gnutls_x509_crt_t res = NULL; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), NULL); + xmlSecAssert2(keyInfoCtx != NULL, NULL); + + ctx = xmlSecGnuTLSX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, NULL); + + if(res == NULL) { + res = xmlSecGnuTLSX509FindCert(&(ctx->certsTrusted), subjectName, issuerName, issuerSerial, ski); + } + if(res == NULL) { + res = xmlSecGnuTLSX509FindCert(&(ctx->certsUntrusted), subjectName, issuerName, issuerSerial, ski); + } + return(res); +} + +static int +xmlSecGnuTLSX509CheckTime(const gnutls_x509_crt_t * cert_list, + xmlSecSize cert_list_length, + time_t ts) +{ + time_t notValidBefore, notValidAfter; + xmlSecSize ii; + + xmlSecAssert2(cert_list != NULL, -1); + + for(ii = 0; ii < cert_list_length; ++ii) { + const gnutls_x509_crt_t cert = cert_list[ii]; + if(cert == NULL) { + continue; + } + + /* get expiration times */ + notValidBefore = gnutls_x509_crt_get_activation_time(cert); + if(notValidBefore == (time_t)-1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gnutls_x509_crt_get_activation_time", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + notValidAfter = gnutls_x509_crt_get_expiration_time(cert); + if(notValidAfter == (time_t)-1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gnutls_x509_crt_get_expiration_time", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* check */ + if(ts < notValidBefore) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, + XMLSEC_ERRORS_NO_MESSAGE); + return(0); + } + if(ts > notValidAfter) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, + XMLSEC_ERRORS_NO_MESSAGE); + return(0); + } + } + + /* GOOD! */ + return(1); +} + +/** + * xmlSecGnuTLSX509StoreVerify: + * @store: the pointer to X509 key data store klass. + * @certs: the untrusted certificates. + * @crls: the crls. + * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context. + * + * Verifies @certs list. + * + * Returns: pointer to the first verified certificate from @certs. + */ +gnutls_x509_crt_t +xmlSecGnuTLSX509StoreVerify(xmlSecKeyDataStorePtr store, + xmlSecPtrListPtr certs, + xmlSecPtrListPtr crls, + 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_crl_t * crl_list = NULL; + xmlSecSize crl_list_length; + gnutls_x509_crt_t * ca_list = NULL; + xmlSecSize ca_list_length; + time_t verification_time; + unsigned int flags = 0; + xmlSecSize ii; + int ret; + int err; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), NULL); + xmlSecAssert2(certs != NULL, NULL); + xmlSecAssert2(crls != 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; + } + } + crl_list_length = xmlSecPtrListGetSize(crls); + if(crl_list_length > 0) { + crl_list = (gnutls_x509_crl_t *)xmlMalloc(sizeof(gnutls_x509_crl_t) * crl_list_length); + if(crl_list == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "xmlMalloc", + XMLSEC_ERRORS_R_MALLOC_FAILED, + "size=%d", (int)(sizeof(gnutls_x509_crl_t) * crl_list_length)); + goto done; + } + for(ii = 0; ii < crl_list_length; ++ii) { + crl_list[ii] = xmlSecPtrListGetItem(crls, ii); + if(crl_list[ii] == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "xmlSecPtrListGetItem(crls)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + 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; + } + } + } + + /* gnutls doesn't allow to specify "verification" timestamp so + we have to do it ourselves */ + verification_time = (keyInfoCtx->certsVerificationTime > 0) ? + keyInfoCtx->certsVerificationTime : + time(0); + flags |= GNUTLS_VERIFY_DISABLE_TIME_CHECKS; + + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS) != 0) { + flags |= GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2; + flags |= GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5; + } + + /* 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 */ + crl_list, (int)crl_list_length, /* crls */ + flags, /* flags */ + &verify); + if(err != GNUTLS_E_SUCCESS) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gnutls_x509_crt_list_verify", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GNUTLS_REPORT_ERROR(err)); + /* don't stop, continue! */ + continue; + } else if(verify != 0){ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gnutls_x509_crt_list_verify", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "Verification failed: verify=%u", verify); + /* don't stop, continue! */ + continue; + } + + /* gnutls doesn't allow to specify "verification" timestamp so + we have to do it ourselves */ + ret = xmlSecGnuTLSX509CheckTime(cert_list, cert_list_cur_length, verification_time); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "Time verification failed"); + /* don't stop, continue! */ + continue; + } + + /* DONE! */ + res = cert; + } + +done: + /* cleanup */ + if(ca_list != NULL) { + xmlFree(ca_list); + } + if(crl_list != NULL) { + xmlFree(crl_list); + } + if(cert_list != NULL) { + xmlFree(cert_list); + } + + return(res); +} + +/** + * xmlSecGnuTLSX509StoreAdoptCert: + * @store: the pointer to X509 key data store klass. + * @cert: the pointer to GnuTLS X509 certificate. + * @type: the certificate type (trusted/untrusted). + * + * Adds trusted (root) or untrusted certificate to the store. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecGnuTLSX509StoreAdoptCert(xmlSecKeyDataStorePtr store, gnutls_x509_crt_t cert, xmlSecKeyDataType type) { + xmlSecGnuTLSX509StoreCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), -1); + xmlSecAssert2(cert != NULL, -1); + + ctx = xmlSecGnuTLSX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, -1); + + if((type & xmlSecKeyDataTypeTrusted) != 0) { + ret = xmlSecPtrListAdd(&(ctx->certsTrusted), cert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "xmlSecPtrListAdd(trusted)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } else { + ret = xmlSecPtrListAdd(&(ctx->certsUntrusted), cert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "xmlSecPtrListAdd(untrusted)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + /* done */ + return(0); +} + +static int +xmlSecGnuTLSX509StoreInitialize(xmlSecKeyDataStorePtr store) { + xmlSecGnuTLSX509StoreCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), -1); + + ctx = xmlSecGnuTLSX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecGnuTLSX509StoreCtx)); + + ret = xmlSecPtrListInitialize(&(ctx->certsTrusted), xmlSecGnuTLSX509CrtListId); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "xmlSecPtrListInitialize(trusted)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecPtrListInitialize(&(ctx->certsUntrusted), xmlSecGnuTLSX509CrtListId); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "xmlSecPtrListInitialize(untrusted)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static void +xmlSecGnuTLSX509StoreFinalize(xmlSecKeyDataStorePtr store) { + xmlSecGnuTLSX509StoreCtxPtr ctx; + xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId)); + + ctx = xmlSecGnuTLSX509StoreGetCtx(store); + xmlSecAssert(ctx != NULL); + + xmlSecPtrListFinalize(&(ctx->certsTrusted)); + xmlSecPtrListFinalize(&(ctx->certsUntrusted)); + + memset(ctx, 0, sizeof(xmlSecGnuTLSX509StoreCtx)); +} + + +/***************************************************************************** + * + * Low-level x509 functions + * + *****************************************************************************/ +#define XMLSEC_GNUTLS_DN_ATTRS_SIZE 1024 +static int +xmlSecGnuTLSX509DnsEqual(const xmlChar * ll, const xmlChar * rr) { + xmlSecGnuTLSDnAttr ll_attrs[XMLSEC_GNUTLS_DN_ATTRS_SIZE]; + xmlSecGnuTLSDnAttr rr_attrs[XMLSEC_GNUTLS_DN_ATTRS_SIZE]; + int ret; + int res = -1; + + xmlSecAssert2(ll != NULL, -1); + xmlSecAssert2(rr != NULL, -1); + + /* fast version first */ + if(xmlStrEqual(ll, rr)) { + return(1); + } + + /* prepare */ + xmlSecGnuTLSDnAttrsInitialize(ll_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE); + xmlSecGnuTLSDnAttrsInitialize(rr_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE); + + /* parse */ + ret = xmlSecGnuTLSDnAttrsParse(ll, ll_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGnuTLSDnAttrsParse(ll)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + ret = xmlSecGnuTLSDnAttrsParse(rr, rr_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGnuTLSDnAttrsParse(rr)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + /* compare */ + ret = xmlSecGnuTLSDnAttrsEqual(ll_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE, + rr_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE); + if(ret == 1) { + res = 1; + } else if(ret == 0) { + res = 0; + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGnuTLSDnAttrsEqual", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + +done: + xmlSecGnuTLSDnAttrsDeinitialize(ll_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE); + xmlSecGnuTLSDnAttrsDeinitialize(rr_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE); + return(res); +} + +static gnutls_x509_crt_t +xmlSecGnuTLSX509FindCert(xmlSecPtrListPtr certs, + const xmlChar *subjectName, + const xmlChar *issuerName, + const xmlChar *issuerSerial, + const xmlChar *ski) { + xmlSecSize ii, sz; + + xmlSecAssert2(certs != NULL, NULL); + + /* todo: this is not the fastest way to search certs */ + sz = xmlSecPtrListGetSize(certs); + for(ii = 0; (ii < sz); ++ii) { + gnutls_x509_crt_t cert = xmlSecPtrListGetItem(certs, ii); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListGetItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%i", (int)ii); + return(NULL); + } + + if(subjectName != NULL) { + xmlChar * tmp; + + tmp = xmlSecGnuTLSX509CertGetSubjectDN(cert); + if(tmp == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGnuTLSX509CertGetSubjectDN", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%i", (int)ii); + return(NULL); + } + + if(xmlSecGnuTLSX509DnsEqual(subjectName, tmp) == 1) { + xmlFree(tmp); + return(cert); + } + xmlFree(tmp); + } else if((issuerName != NULL) && (issuerSerial != NULL)) { + xmlChar * tmp1; + xmlChar * tmp2; + + tmp1 = xmlSecGnuTLSX509CertGetIssuerDN(cert); + if(tmp1 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGnuTLSX509CertGetIssuerDN", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%i", (int)ii); + return(NULL); + } + + tmp2 = xmlSecGnuTLSX509CertGetIssuerSerial(cert); + if(tmp2 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGnuTLSX509CertGetIssuerSerial", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%i", (int)ii); + xmlFree(tmp1); + return(NULL); + } + + if((xmlSecGnuTLSX509DnsEqual(issuerName, tmp1) == 1) && xmlStrEqual(issuerSerial, tmp2)) { + xmlFree(tmp1); + xmlFree(tmp2); + return(cert); + } + xmlFree(tmp1); + xmlFree(tmp2); + } else if(ski != NULL) { + xmlChar * tmp; + + tmp = xmlSecGnuTLSX509CertGetSKI(cert); + if(tmp == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGnuTLSX509CertGetSKI", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%i", (int)ii); + return(NULL); + } + + if(xmlStrEqual(ski, tmp)) { + xmlFree(tmp); + return(cert); + } + xmlFree(tmp); + } + } + + 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(xmlSecGnuTLSX509DnsEqual(subject, issuer) == 1) { + 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((xmlSecGnuTLSX509DnsEqual(issuer, subject) == 1)) { + res = tmp; + } + xmlFree(subject); + } + +done: + if(issuer != NULL) { + xmlFree(issuer); + } + return(res); +} + +#endif /* XMLSEC_NO_X509 */ + + |