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/nss/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/nss/x509vfy.c')
-rw-r--r-- | src/nss/x509vfy.c | 826 |
1 files changed, 465 insertions, 361 deletions
diff --git a/src/nss/x509vfy.c b/src/nss/x509vfy.c index 25bf5042..fdb866fe 100644 --- a/src/nss/x509vfy.c +++ b/src/nss/x509vfy.c @@ -1,4 +1,4 @@ -/** +/** * XMLSec library * * X509 support @@ -6,7 +6,7 @@ * * This is free software; see Copyright file in the source * distribution for preciese wording. - * + * * Copyright (c) 2003 America Online, Inc. All rights reserved. */ #include "globals.h" @@ -40,11 +40,20 @@ * Internal NSS X509 store CTX * *************************************************************************/ -typedef struct _xmlSecNssX509StoreCtx xmlSecNssX509StoreCtx, - *xmlSecNssX509StoreCtxPtr; +typedef struct _xmlSecNssX509StoreCtx xmlSecNssX509StoreCtx, + *xmlSecNssX509StoreCtxPtr; struct _xmlSecNssX509StoreCtx { + /* Two uses: + * + * 1) Just keeping a reference to destroy later. + * + * 2) NSS doesn't update it's cache correctly when new certs are added + * https://bugzilla.mozilla.org/show_bug.cgi?id=211051 + * we use this list to perform search ourselves. + */ + CERTCertList* certsList; /* just keeping a reference to destroy later */ -}; +}; /**************************************************************************** * @@ -55,22 +64,23 @@ struct _xmlSecNssX509StoreCtx { ***************************************************************************/ #define xmlSecNssX509StoreGetCtx(store) \ ((xmlSecNssX509StoreCtxPtr)(((xmlSecByte*)(store)) + \ - sizeof(xmlSecKeyDataStoreKlass))) -#define xmlSecNssX509StoreSize \ + sizeof(xmlSecKeyDataStoreKlass))) +#define xmlSecNssX509StoreSize \ (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecNssX509StoreCtx)) - -static int xmlSecNssX509StoreInitialize (xmlSecKeyDataStorePtr store); -static void xmlSecNssX509StoreFinalize (xmlSecKeyDataStorePtr store); -static int xmlSecNssX509NameStringRead (xmlSecByte **str, - int *strLen, - xmlSecByte *res, - int resLen, - xmlSecByte delim, - int ingoreTrailingSpaces); -static xmlSecByte * xmlSecNssX509NameRead (xmlSecByte *str, - int len); -static void xmlSecNssNumToItem(SECItem *it, unsigned long num); +static int xmlSecNssX509StoreInitialize (xmlSecKeyDataStorePtr store); +static void xmlSecNssX509StoreFinalize (xmlSecKeyDataStorePtr store); +static int xmlSecNssX509NameStringRead (xmlSecByte **str, + int *strLen, + xmlSecByte *res, + int resLen, + xmlSecByte delim, + int ingoreTrailingSpaces); +static xmlSecByte * xmlSecNssX509NameRead (xmlSecByte *str, + int len); + +static int xmlSecNssNumToItem (SECItem *it, + PRUint64 num); static xmlSecKeyDataStoreKlass xmlSecNssX509StoreKlass = { @@ -78,43 +88,44 @@ static xmlSecKeyDataStoreKlass xmlSecNssX509StoreKlass = { xmlSecNssX509StoreSize, /* data */ - xmlSecNameX509Store, /* const xmlChar* name; */ - + xmlSecNameX509Store, /* const xmlChar* name; */ + /* constructors/destructor */ - xmlSecNssX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */ - xmlSecNssX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */ + xmlSecNssX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */ + xmlSecNssX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */ /* reserved for the future */ - NULL, /* void* reserved0; */ - NULL, /* void* reserved1; */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ }; -static CERTCertificate* xmlSecNssX509FindCert(xmlChar *subjectName, - xmlChar *issuerName, - xmlChar *issuerSerial, - xmlChar *ski); +static CERTCertificate* xmlSecNssX509FindCert(CERTCertList* certsList, + const xmlChar *subjectName, + const xmlChar *issuerName, + const xmlChar *issuerSerial, + xmlChar *ski); -/** +/** * xmlSecNssX509StoreGetKlass: - * + * * The NSS X509 certificates key data store klass. * * Returns: pointer to NSS X509 certificates key data store klass. */ -xmlSecKeyDataStoreId +xmlSecKeyDataStoreId xmlSecNssX509StoreGetKlass(void) { return(&xmlSecNssX509StoreKlass); } /** * xmlSecNssX509StoreFindCert: - * @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. + * @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. * @@ -123,32 +134,32 @@ xmlSecNssX509StoreGetKlass(void) { */ CERTCertificate * xmlSecNssX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName, - xmlChar *issuerName, xmlChar *issuerSerial, - xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) { + xmlChar *issuerName, xmlChar *issuerSerial, + xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) { xmlSecNssX509StoreCtxPtr ctx; - + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId), NULL); xmlSecAssert2(keyInfoCtx != NULL, NULL); ctx = xmlSecNssX509StoreGetCtx(store); xmlSecAssert2(ctx != NULL, NULL); - return(xmlSecNssX509FindCert(subjectName, issuerName, issuerSerial, ski)); + return xmlSecNssX509FindCert(ctx->certsList, subjectName, issuerName, issuerSerial, ski); } /** * xmlSecNssX509StoreVerify: - * @store: the pointer to X509 key data store klass. - * @certs: the untrusted certificates stack. - * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context. + * @store: the pointer to X509 key data store klass. + * @certs: the untrusted certificates stack. + * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context. * * Verifies @certs list. * * Returns: pointer to the first verified certificate from @certs. - */ -CERTCertificate * + */ +CERTCertificate * xmlSecNssX509StoreVerify(xmlSecKeyDataStorePtr store, CERTCertList* certs, - xmlSecKeyInfoCtx* keyInfoCtx) { + xmlSecKeyInfoCtx* keyInfoCtx) { xmlSecNssX509StoreCtxPtr ctx; CERTCertListNode* head; CERTCertificate* cert = NULL; @@ -169,88 +180,88 @@ xmlSecNssX509StoreVerify(xmlSecKeyDataStorePtr store, CERTCertList* certs, !CERT_LIST_END(head, certs); head = CERT_LIST_NEXT(head)) { cert = head->cert; - if(keyInfoCtx->certsVerificationTime > 0) { - /* convert the time since epoch in seconds to microseconds */ - LL_UI2L(timeboundary, keyInfoCtx->certsVerificationTime); - tmp1 = (int64)PR_USEC_PER_SEC; - tmp2 = timeboundary; - LL_MUL(timeboundary, tmp1, tmp2); - } else { - timeboundary = PR_Now(); - } - - /* if cert is the issuer of any other cert in the list, then it is - * to be skipped */ - for (head1 = CERT_LIST_HEAD(certs); - !CERT_LIST_END(head1, certs); - head1 = CERT_LIST_NEXT(head1)) { - - cert1 = head1->cert; - if (cert1 == cert) { - continue; - } - - if (SECITEM_CompareItem(&cert1->derIssuer, &cert->derSubject) - == SECEqual) { - break; - } - } - - if (!CERT_LIST_END(head1, certs)) { - continue; - } - - status = CERT_VerifyCertificate(CERT_GetDefaultCertDB(), - cert, PR_FALSE, - (SECCertificateUsage)0, - timeboundary , NULL, NULL, NULL); - if (status == SECSuccess) { - break; - } + if(keyInfoCtx->certsVerificationTime > 0) { + /* convert the time since epoch in seconds to microseconds */ + LL_UI2L(timeboundary, keyInfoCtx->certsVerificationTime); + tmp1 = (int64)PR_USEC_PER_SEC; + tmp2 = timeboundary; + LL_MUL(timeboundary, tmp1, tmp2); + } else { + timeboundary = PR_Now(); + } + + /* if cert is the issuer of any other cert in the list, then it is + * to be skipped */ + for (head1 = CERT_LIST_HEAD(certs); + !CERT_LIST_END(head1, certs); + head1 = CERT_LIST_NEXT(head1)) { + + cert1 = head1->cert; + if (cert1 == cert) { + continue; + } + + if (SECITEM_CompareItem(&cert1->derIssuer, &cert->derSubject) + == SECEqual) { + break; + } + } + + if (!CERT_LIST_END(head1, certs)) { + continue; + } + + status = CERT_VerifyCertificate(CERT_GetDefaultCertDB(), + cert, PR_FALSE, + (SECCertificateUsage)0, + timeboundary , NULL, NULL, NULL); + if (status == SECSuccess) { + break; + } } if (status == SECSuccess) { - return (cert); + return (cert); } - + switch(PORT_GetError()) { - case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: - case SEC_ERROR_CA_CERT_INVALID: - case SEC_ERROR_UNKNOWN_SIGNER: + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + case SEC_ERROR_CA_CERT_INVALID: + case SEC_ERROR_UNKNOWN_SIGNER: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, "cert with subject name %s could not be verified because the issuer's cert is expired/invalid or not found", cert->subjectName); - break; - case SEC_ERROR_EXPIRED_CERTIFICATE: + break; + case SEC_ERROR_EXPIRED_CERTIFICATE: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, "cert with subject name %s has expired", cert->subjectName); - break; - case SEC_ERROR_REVOKED_CERTIFICATE: + break; + case SEC_ERROR_REVOKED_CERTIFICATE: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_REVOKED, "cert with subject name %s has been revoked", cert->subjectName); - break; - default: + break; + default: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, - "cert with subject name %s could not be verified, errcode %d", - cert->subjectName, - PORT_GetError()); - break; + "cert with subject name %s could not be verified, errcode %d", + cert->subjectName, + PORT_GetError()); + break; } - + return (NULL); } @@ -282,7 +293,7 @@ xmlSecNssX509StoreAdoptCert(xmlSecKeyDataStorePtr store, CERTCertificate* cert, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "CERT_NewCertList", XMLSEC_ERRORS_R_CRYPTO_FAILED, - "error code=%d", PORT_GetError()); + "error code=%d", PORT_GetError()); return(-1); } } @@ -293,7 +304,7 @@ xmlSecNssX509StoreAdoptCert(xmlSecKeyDataStorePtr store, CERTCertificate* cert, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "CERT_AddCertToListTail", XMLSEC_ERRORS_R_CRYPTO_FAILED, - "error code=%d", PORT_GetError()); + "error code=%d", PORT_GetError()); return(-1); } @@ -310,7 +321,7 @@ xmlSecNssX509StoreInitialize(xmlSecKeyDataStorePtr store) { memset(ctx, 0, sizeof(xmlSecNssX509StoreCtx)); - return(0); + return(0); } static void @@ -320,10 +331,10 @@ xmlSecNssX509StoreFinalize(xmlSecKeyDataStorePtr store) { ctx = xmlSecNssX509StoreGetCtx(store); xmlSecAssert(ctx != NULL); - + if (ctx->certsList) { - CERT_DestroyCertList(ctx->certsList); - ctx->certsList = NULL; + CERT_DestroyCertList(ctx->certsList); + ctx->certsList = NULL; } memset(ctx, 0, sizeof(xmlSecNssX509StoreCtx)); @@ -335,126 +346,188 @@ xmlSecNssX509StoreFinalize(xmlSecKeyDataStorePtr store) { * Low-level x509 functions * *****************************************************************************/ -static CERTCertificate* -xmlSecNssX509FindCert(xmlChar *subjectName, xmlChar *issuerName, - xmlChar *issuerSerial, xmlChar *ski) { +static CERTName * +xmlSecNssGetCertName(const xmlChar * name) { + xmlChar *tmp, *name2; + xmlChar *p; + CERTName *res; + + xmlSecAssert2(name != NULL, NULL); + + /* nss doesn't support emailAddress (see https://bugzilla.mozilla.org/show_bug.cgi?id=561689) + * This code is not bullet proof and may produce incorrect results if someone has + * "emailAddress=" string in one of the fields, but it is best I can suggest to fix + * this problem. + */ + name2 = xmlStrdup(name); + if(name2 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_MALLOC_FAILED, + "xmlStrlen(name)=%d", + xmlStrlen(name)); + return(NULL); + } + while( (p = (xmlChar*)xmlStrstr(name2, BAD_CAST "emailAddress=")) != NULL) { + memcpy(p, " E=", 13); + } + + tmp = xmlSecNssX509NameRead(name2, xmlStrlen(name2)); + if(tmp == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssX509NameRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "name2=\"%s\"", + xmlSecErrorsSafeString(name2)); + xmlFree(name2); + return(NULL); + } + + res = CERT_AsciiToName((char*)tmp); + if (name == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "CERT_AsciiToName", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "ascii=\"%s\", error code=%d", + xmlSecErrorsSafeString((char*)tmp), + PORT_GetError()); + PORT_Free(tmp); + xmlFree(name2); + return(NULL); + } + + PORT_Free(tmp); + return(res); +} + +static CERTCertificate* +xmlSecNssX509FindCert(CERTCertList* certsList, const xmlChar *subjectName, + const xmlChar *issuerName, const xmlChar *issuerSerial, + xmlChar *ski) { CERTCertificate *cert = NULL; - xmlChar *p = NULL; CERTName *name = NULL; SECItem *nameitem = NULL; + CERTCertListNode* head; + SECItem tmpitem; + SECStatus status; PRArenaPool *arena = NULL; + int rv; - if (subjectName != NULL) { - p = xmlSecNssX509NameRead(subjectName, xmlStrlen(subjectName)); - if (p == NULL) { + if ((cert == NULL) && (subjectName != NULL)) { + name = xmlSecNssGetCertName(subjectName); + if (name == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, - "xmlSecNssX509NameRead", + "xmlSecNssGetCertName", XMLSEC_ERRORS_R_XMLSEC_FAILED, "subject=%s", xmlSecErrorsSafeString(subjectName)); - goto done; - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "PORT_NewArena", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - goto done; - } + goto done; + } - name = CERT_AsciiToName((char*)p); - if (name == NULL) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "CERT_AsciiToName", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - goto done; - } + if(arena == NULL) { + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PORT_NewArena", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } - nameitem = SEC_ASN1EncodeItem(arena, NULL, (void *)name, - SEC_ASN1_GET(CERT_NameTemplate)); - if (nameitem == NULL) { + nameitem = SEC_ASN1EncodeItem(arena, NULL, (void *)name, + SEC_ASN1_GET(CERT_NameTemplate)); + if (nameitem == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "SEC_ASN1EncodeItem", XMLSEC_ERRORS_R_XMLSEC_FAILED, - "error code=%d", PORT_GetError()); - goto done; - } + "error code=%d", PORT_GetError()); + goto done; + } - cert = CERT_FindCertByName(CERT_GetDefaultCertDB(), nameitem); - goto done; + cert = CERT_FindCertByName(CERT_GetDefaultCertDB(), nameitem); } - if((issuerName != NULL) && (issuerSerial != NULL)) { - CERTIssuerAndSN issuerAndSN; + if((cert == NULL) && (issuerName != NULL) && (issuerSerial != NULL)) { + CERTIssuerAndSN issuerAndSN; + PRUint64 issuerSN = 0; - p = xmlSecNssX509NameRead(issuerName, xmlStrlen(issuerName)); - if (p == NULL) { + name = xmlSecNssGetCertName(issuerName); + if (name == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, - "xmlSecNssX509NameRead", + "xmlSecNssGetCertName", XMLSEC_ERRORS_R_XMLSEC_FAILED, "issuer=%s", xmlSecErrorsSafeString(issuerName)); - goto done; - } + goto done; + } - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) { + if(arena == NULL) { + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PORT_NewArena", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } + + nameitem = SEC_ASN1EncodeItem(arena, NULL, (void *)name, + SEC_ASN1_GET(CERT_NameTemplate)); + if (nameitem == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, - "PORT_NewArena", + "SEC_ASN1EncodeItem", XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - goto done; - } + "error code=%d", PORT_GetError()); + goto done; + } + + memset(&issuerAndSN, 0, sizeof(issuerAndSN)); + + issuerAndSN.derIssuer.data = nameitem->data; + issuerAndSN.derIssuer.len = nameitem->len; - name = CERT_AsciiToName((char*)p); - if (name == NULL) { + /* TBD: serial num can be arbitrarily long */ + if(PR_sscanf((char *)issuerSerial, "%llu", &issuerSN) != 1) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, - "CERT_AsciiToName", + "PR_sscanf", XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - goto done; - } + "error code=%d", PR_GetError()); + SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE); + goto done; + } - nameitem = SEC_ASN1EncodeItem(arena, NULL, (void *)name, - SEC_ASN1_GET(CERT_NameTemplate)); - if (nameitem == NULL) { + rv = xmlSecNssNumToItem(&issuerAndSN.serialNumber, issuerSN); + if(rv <= 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, - "SEC_ASN1EncodeItem", + "xmlSecNssNumToItem", XMLSEC_ERRORS_R_XMLSEC_FAILED, - "error code=%d", PORT_GetError()); - goto done; - } - - memset(&issuerAndSN, 0, sizeof(issuerAndSN)); - - issuerAndSN.derIssuer.data = nameitem->data; - issuerAndSN.derIssuer.len = nameitem->len; - - /* TBD: serial num can be arbitrarily long */ - xmlSecNssNumToItem(&issuerAndSN.serialNumber, PORT_Atoi((char *)issuerSerial)); + "error code=%d", PR_GetError()); + SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE); + goto done; + } - cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), - &issuerAndSN); - SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE); - goto done; + cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerAndSN); + SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE); } - if(ski != NULL) { - SECItem subjKeyID; - int len; + if((cert == NULL) && (ski != NULL)) { + SECItem subjKeyID; + int len; - len = xmlSecBase64Decode(ski, (xmlSecByte*)ski, xmlStrlen(ski)); + len = xmlSecBase64Decode(ski, (xmlSecByte*)ski, xmlStrlen(ski)); if(len < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, @@ -462,25 +535,63 @@ xmlSecNssX509FindCert(xmlChar *subjectName, xmlChar *issuerName, XMLSEC_ERRORS_R_XMLSEC_FAILED, "ski=%s", xmlSecErrorsSafeString(ski)); - goto done; + goto done; } - memset(&subjKeyID, 0, sizeof(subjKeyID)); - subjKeyID.data = ski; - subjKeyID.len = xmlStrlen(ski); - cert = CERT_FindCertBySubjectKeyID(CERT_GetDefaultCertDB(), - &subjKeyID); + memset(&subjKeyID, 0, sizeof(subjKeyID)); + subjKeyID.data = ski; + subjKeyID.len = len; + cert = CERT_FindCertBySubjectKeyID(CERT_GetDefaultCertDB(), + &subjKeyID); + + /* try to search in our list - NSS doesn't update it's cache correctly + * when new certs are added https://bugzilla.mozilla.org/show_bug.cgi?id=211051 + */ + if((cert == NULL) && (certsList != NULL)) { + + for(head = CERT_LIST_HEAD(certsList); + (cert == NULL) && !CERT_LIST_END(head, certsList) && + (head != NULL) && (head->cert != NULL); + head = CERT_LIST_NEXT(head) + ) { + + memset(&tmpitem, 0, sizeof(tmpitem)); + status = CERT_FindSubjectKeyIDExtension(head->cert, &tmpitem); + if (status != SECSuccess) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "CERT_FindSubjectKeyIDExtension", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "ski"); + SECITEM_FreeItem(&tmpitem, PR_FALSE); + goto done; + } + + if((tmpitem.len == subjKeyID.len) && + (memcmp(tmpitem.data, subjKeyID.data, subjKeyID.len) == 0) + ) { + cert = CERT_DupCertificate(head->cert); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "CERT_DupCertificate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "error code=%d", PORT_GetError()); + SECITEM_FreeItem(&tmpitem, PR_FALSE); + goto done; + } + } + SECITEM_FreeItem(&tmpitem, PR_FALSE); + } + } } done: - if (p != NULL) { - PORT_Free(p); - } if (arena != NULL) { - PORT_FreeArena(arena, PR_FALSE); + PORT_FreeArena(arena, PR_FALSE); } if (name != NULL) { - CERT_DestroyName(name); + CERT_DestroyName(name); } return(cert); @@ -495,161 +606,161 @@ xmlSecNssX509NameRead(xmlSecByte *str, int len) { int nameLen, valueLen; xmlSecAssert2(str != NULL, NULL); - + /* return string should be no longer than input string */ retval = (xmlSecByte *)PORT_Alloc(len+1); if(retval == NULL) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "PORT_Alloc", - XMLSEC_ERRORS_R_MALLOC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - return(NULL); + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PORT_Alloc", + XMLSEC_ERRORS_R_MALLOC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); } p = retval; - + while(len > 0) { - /* skip spaces after comma or semicolon */ - while((len > 0) && isspace(*str)) { - ++str; --len; - } - - nameLen = xmlSecNssX509NameStringRead(&str, &len, name, sizeof(name), '=', 0); - if(nameLen < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "xmlSecNssX509NameStringRead", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - goto done; - } - memcpy(p, name, nameLen); - p+=nameLen; - *p++='='; - if(len > 0) { - ++str; --len; - if((*str) == '\"') { - valueLen = xmlSecNssX509NameStringRead(&str, &len, - value, sizeof(value), '"', 1); - if(valueLen < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "xmlSecNssX509NameStringRead", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - goto done; - } - /* skip spaces before comma or semicolon */ - while((len > 0) && isspace(*str)) { - ++str; --len; - } - if((len > 0) && ((*str) != ',')) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - NULL, - XMLSEC_ERRORS_R_INVALID_DATA, - "comma is expected"); - goto done; - } - if(len > 0) { - ++str; --len; - } - *p++='\"'; - memcpy(p, value, valueLen); - p+=valueLen; - *p++='\"'; - } else if((*str) == '#') { - /* TODO: read octect values */ - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - NULL, - XMLSEC_ERRORS_R_INVALID_DATA, - "reading octect values is not implemented yet"); - goto done; - } else { - valueLen = xmlSecNssX509NameStringRead(&str, &len, - value, sizeof(value), ',', 1); - if(valueLen < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "xmlSecNssX509NameStringRead", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - goto done; - } - memcpy(p, value, valueLen); - p+=valueLen; - if (len > 0) - *p++=','; - } - } else { - valueLen = 0; - } - if(len > 0) { - ++str; --len; - } + /* skip spaces after comma or semicolon */ + while((len > 0) && isspace(*str)) { + ++str; --len; + } + + nameLen = xmlSecNssX509NameStringRead(&str, &len, name, sizeof(name), '=', 0); + if(nameLen < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssX509NameStringRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + memcpy(p, name, nameLen); + p+=nameLen; + *p++='='; + if(len > 0) { + ++str; --len; + if((*str) == '\"') { + valueLen = xmlSecNssX509NameStringRead(&str, &len, + value, sizeof(value), '"', 1); + if(valueLen < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssX509NameStringRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + /* skip spaces before comma or semicolon */ + while((len > 0) && isspace(*str)) { + ++str; --len; + } + if((len > 0) && ((*str) != ',')) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "comma is expected"); + goto done; + } + if(len > 0) { + ++str; --len; + } + *p++='\"'; + memcpy(p, value, valueLen); + p+=valueLen; + *p++='\"'; + } else if((*str) == '#') { + /* TODO: read octect values */ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "reading octect values is not implemented yet"); + goto done; + } else { + valueLen = xmlSecNssX509NameStringRead(&str, &len, + value, sizeof(value), ',', 1); + if(valueLen < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssX509NameStringRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + memcpy(p, value, valueLen); + p+=valueLen; + if (len > 0) + *p++=','; + } + } else { + valueLen = 0; + } + if(len > 0) { + ++str; --len; + } } *p = 0; return(retval); - + done: PORT_Free(retval); return (NULL); } -static int -xmlSecNssX509NameStringRead(xmlSecByte **str, int *strLen, - xmlSecByte *res, int resLen, - xmlSecByte delim, int ingoreTrailingSpaces) { - xmlSecByte *p, *q, *nonSpace; +static int +xmlSecNssX509NameStringRead(xmlSecByte **str, int *strLen, + xmlSecByte *res, int resLen, + xmlSecByte delim, int ingoreTrailingSpaces) { + xmlSecByte *p, *q, *nonSpace; xmlSecAssert2(str != NULL, -1); xmlSecAssert2(strLen != NULL, -1); xmlSecAssert2(res != NULL, -1); - + p = (*str); nonSpace = q = res; - while(((p - (*str)) < (*strLen)) && ((*p) != delim) && ((q - res) < resLen)) { - if((*p) != '\\') { - if(ingoreTrailingSpaces && !isspace(*p)) { - nonSpace = q; - } - *(q++) = *(p++); - } else { - ++p; - nonSpace = q; - if(xmlSecIsHex((*p))) { - if((p - (*str) + 1) >= (*strLen)) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - NULL, - XMLSEC_ERRORS_R_INVALID_DATA, - "two hex digits expected"); - return(-1); - } - *(q++) = xmlSecGetHex(p[0]) * 16 + xmlSecGetHex(p[1]); - p += 2; - } else { - if(((++p) - (*str)) >= (*strLen)) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - NULL, - XMLSEC_ERRORS_R_INVALID_DATA, - "escaped symbol missed"); - return(-1); - } - *(q++) = *(p++); - } - } + while(((p - (*str)) < (*strLen)) && ((*p) != delim) && ((q - res) < resLen)) { + if((*p) != '\\') { + if(ingoreTrailingSpaces && !isspace(*p)) { + nonSpace = q; + } + *(q++) = *(p++); + } else { + ++p; + nonSpace = q; + if(xmlSecIsHex((*p))) { + if((p - (*str) + 1) >= (*strLen)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "two hex digits expected"); + return(-1); + } + *(q++) = xmlSecGetHex(p[0]) * 16 + xmlSecGetHex(p[1]); + p += 2; + } else { + if(((++p) - (*str)) >= (*strLen)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "escaped symbol missed"); + return(-1); + } + *(q++) = *(p++); + } + } } if(((p - (*str)) < (*strLen)) && ((*p) != delim)) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - NULL, - XMLSEC_ERRORS_R_INVALID_SIZE, - "buffer is too small"); - return(-1); + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "buffer is too small"); + return(-1); } (*strLen) -= (p - (*str)); (*str) = p; @@ -657,47 +768,40 @@ xmlSecNssX509NameStringRead(xmlSecByte **str, int *strLen, } /* code lifted from NSS */ -static void -xmlSecNssNumToItem(SECItem *it, unsigned long ui) +static int +xmlSecNssNumToItem(SECItem *it, PRUint64 ui) { - unsigned char bb[5]; - int len; + unsigned char bb[9]; + unsigned int zeros_len; - bb[0] = 0; - bb[1] = (unsigned char) (ui >> 24); - bb[2] = (unsigned char) (ui >> 16); - bb[3] = (unsigned char) (ui >> 8); - bb[4] = (unsigned char) (ui); + xmlSecAssert2(it != NULL, -1); + + bb[0] = 0; /* important: we should have 0 at the beginning! */ + bb[1] = (unsigned char) (ui >> 56); + bb[2] = (unsigned char) (ui >> 48); + bb[3] = (unsigned char) (ui >> 40); + bb[4] = (unsigned char) (ui >> 32); + bb[5] = (unsigned char) (ui >> 24); + bb[6] = (unsigned char) (ui >> 16); + bb[7] = (unsigned char) (ui >> 8); + bb[8] = (unsigned char) (ui); /* ** Small integers are encoded in a single byte. Larger integers - ** require progressively more space. + ** require progressively more space. Start from 1 because byte at + ** position 0 is zero */ - if (ui > 0x7f) { - if (ui > 0x7fff) { - if (ui > 0x7fffffL) { - if (ui >= 0x80000000L) { - len = 5; - } else { - len = 4; - } - } else { - len = 3; - } - } else { - len = 2; - } - } else { - len = 1; - } + for(zeros_len = 1; (zeros_len < sizeof(bb)) && (bb[zeros_len] == 0); ++zeros_len); - it->data = (unsigned char *)PORT_Alloc(len); + it->len = sizeof(bb) - (zeros_len - 1); + it->data = (unsigned char *)PORT_Alloc(it->len); if (it->data == NULL) { - return; + it->len = 0; + return (-1); } - it->len = len; - PORT_Memcpy(it->data, bb + (sizeof(bb) - len), len); + PORT_Memcpy(it->data, bb + (zeros_len - 1), it->len); + return(it->len); } #endif /* XMLSEC_NO_X509 */ |