summaryrefslogtreecommitdiff
path: root/src/nss/x509vfy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nss/x509vfy.c')
-rw-r--r--src/nss/x509vfy.c826
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 */