Index: nss/lib/certdb/genname.c |
diff --git a/nss/lib/certdb/genname.c b/nss/lib/certdb/genname.c |
index 1b0cc970489478dc36bd9a4c38d8bca6231eb9b3..e3bc11d59109d83a24daaf82aacd91a4969e49c1 100644 |
--- a/nss/lib/certdb/genname.c |
+++ b/nss/lib/certdb/genname.c |
@@ -1556,76 +1556,98 @@ done: |
return rv; |
} |
-/* Add name constraints to certain certs that do not include name constraints |
- * This is the core of the implementation for bug 952572. |
+/* |
+ * Here we define a list of name constraints to be imposed on |
+ * certain certificates, most importantly root certificates. |
+ * |
+ * Each entry in the name constraints list is constructed with this |
+ * macro. An entry contains two SECItems, which have names in |
+ * specific forms to make the macro work: |
+ * |
+ * * ${CA}_SUBJECT_DN - The subject DN for which the constraints |
+ * should be applied |
+ * * ${CA}_NAME_CONSTRAINTS - The name constraints extension |
+ * |
+ * Entities subject to name constraints are identified by subject name |
+ * so that we can cover all certificates for that entity, including, e.g., |
+ * cross-certificates. We use subject rather than public key because |
+ * calling methods often have easy access to that field (vs., say, a key ID), |
+ * and in practice, subject names and public keys are usually in one-to-one |
+ * correspondence anyway. |
+ * |
*/ |
-static SECStatus |
-getNameExtensionsBuiltIn(CERTCertificate *cert, |
- SECItem *extensions) |
+#define STRING_TO_SECITEM(str) \ |
+{ siBuffer, (unsigned char*) str, sizeof(str) - 1 } |
+ |
+#define NAME_CONSTRAINTS_ENTRY(CA) \ |
+ { \ |
+ STRING_TO_SECITEM(CA ## _SUBJECT_DN), \ |
+ STRING_TO_SECITEM(CA ## _NAME_CONSTRAINTS) \ |
+ } |
+ |
+/* Agence Nationale de la Securite des Systemes d'Information (ANSSI) */ |
+ |
+#define ANSSI_SUBJECT_DN \ |
+ "\x30\x81\x85" \ |
+ "\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02" "FR" /* C */ \ |
+ "\x31\x0F\x30\x0D\x06\x03\x55\x04\x08\x13\x06" "France" /* ST */ \ |
+ "\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05" "Paris" /* L */ \ |
+ "\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07" "PM/SGDN" /* O */ \ |
+ "\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13\x05" "DCSSI" /* OU */ \ |
+ "\x31\x0E\x30\x0C\x06\x03\x55\x04\x03\x13\x05" "IGC/A" /* CN */ \ |
+ "\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01" \ |
+ "\x16\x14" "igca@sgdn.pm.gouv.fr" /* emailAddress */ \ |
+ |
+#define ANSSI_NAME_CONSTRAINTS \ |
+ "\x30\x5D\xA0\x5B" \ |
+ "\x30\x05\x82\x03" ".fr" \ |
+ "\x30\x05\x82\x03" ".gp" \ |
+ "\x30\x05\x82\x03" ".gf" \ |
+ "\x30\x05\x82\x03" ".mq" \ |
+ "\x30\x05\x82\x03" ".re" \ |
+ "\x30\x05\x82\x03" ".yt" \ |
+ "\x30\x05\x82\x03" ".pm" \ |
+ "\x30\x05\x82\x03" ".bl" \ |
+ "\x30\x05\x82\x03" ".mf" \ |
+ "\x30\x05\x82\x03" ".wf" \ |
+ "\x30\x05\x82\x03" ".pf" \ |
+ "\x30\x05\x82\x03" ".nc" \ |
+ "\x30\x05\x82\x03" ".tf" \ |
+ |
+static const SECItem builtInNameConstraints[][2] = { |
+ NAME_CONSTRAINTS_ENTRY(ANSSI) |
+}; |
+ |
+SECStatus |
+CERT_GetImposedNameConstraints(const SECItem *derSubject, |
+ SECItem *extensions) |
{ |
- const char constraintFranceGov[] = "\x30\x5D" /* sequence len = 93*/ |
- "\xA0\x5B" /* element len =91 */ |
- "\x30\x05" /* sequence len 5 */ |
- "\x82\x03" /* entry len 3 */ |
- ".fr" |
- "\x30\x05\x82\x03" /* sequence len5, entry len 3 */ |
- ".gp" |
- "\x30\x05\x82\x03" |
- ".gf" |
- "\x30\x05\x82\x03" |
- ".mq" |
- "\x30\x05\x82\x03" |
- ".re" |
- "\x30\x05\x82\x03" |
- ".yt" |
- "\x30\x05\x82\x03" |
- ".pm" |
- "\x30\x05\x82\x03" |
- ".bl" |
- "\x30\x05\x82\x03" |
- ".mf" |
- "\x30\x05\x82\x03" |
- ".wf" |
- "\x30\x05\x82\x03" |
- ".pf" |
- "\x30\x05\x82\x03" |
- ".nc" |
- "\x30\x05\x82\x03" |
- ".tf"; |
- |
- /* The stringified value for the subject is: |
- E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR |
- */ |
- const char rawANSSISubject[] = "\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04" |
- "\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03" |
- "\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65" |
- "\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05" |
- "\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03" |
- "\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44" |
- "\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13" |
- "\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06" |
- "\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41" |
- "\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7" |
- "\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40" |
- "\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75" |
- "\x76\x2E\x66\x72"; |
- |
- const SECItem anssi_subject = {0, (unsigned char *) rawANSSISubject, |
- sizeof(rawANSSISubject)-1}; |
- const SECItem permitFranceGovNC = {0, (unsigned char *) constraintFranceGov, |
- sizeof(constraintFranceGov)-1}; |
- |
- if (SECITEM_ItemsAreEqual(&cert->derSubject, &anssi_subject)) { |
- SECStatus rv; |
- rv = SECITEM_CopyItem(NULL, extensions, &permitFranceGovNC); |
- return rv; |
- } |
- PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND); |
- return SECFailure; |
+ size_t i; |
+ |
+ if (!extensions) { |
+ PORT_SetError(SEC_ERROR_INVALID_ARGS); |
+ return SECFailure; |
+ } |
+ |
+ for (i = 0; i < PR_ARRAY_SIZE(builtInNameConstraints); ++i) { |
+ if (SECITEM_ItemsAreEqual(derSubject, &builtInNameConstraints[i][0])) { |
+ return SECITEM_CopyItem(NULL, |
+ extensions, |
+ &builtInNameConstraints[i][1]); |
+ } |
+ } |
+ |
+ PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND); |
+ return SECFailure; |
} |
-/* Extract the name constraints extension from the CA cert. */ |
+/* |
+ * Extract the name constraints extension from the CA cert. |
+ * If the certificate contains no name constraints extension, but |
+ * CERT_GetImposedNameConstraints returns a name constraints extension |
+ * for the subject of the certificate, then that extension will be returned. |
+ */ |
SECStatus |
CERT_FindNameConstraintsExten(PLArenaPool *arena, |
CERTCertificate *cert, |
@@ -1643,7 +1665,8 @@ CERT_FindNameConstraintsExten(PLArenaPool *arena, |
if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { |
return rv; |
} |
- rv = getNameExtensionsBuiltIn(cert, &constraintsExtension); |
+ rv = CERT_GetImposedNameConstraints(&cert->derSubject, |
+ &constraintsExtension); |
if (rv != SECSuccess) { |
if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) { |
return SECSuccess; |