Juan Lang : crypt32: Check email address in subject name against rfc822 name constraints.
Alexandre Julliard
julliard at winehq.org
Wed Nov 18 09:40:40 CST 2009
Module: wine
Branch: master
Commit: d6f7d06cad28ebd28a98ea07e4d51abb208f711a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d6f7d06cad28ebd28a98ea07e4d51abb208f711a
Author: Juan Lang <juan.lang at gmail.com>
Date: Tue Nov 17 13:34:00 2009 -0800
crypt32: Check email address in subject name against rfc822 name constraints.
---
dlls/crypt32/chain.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 107 insertions(+), 0 deletions(-)
diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c
index 0d9a66d..a5b4141 100644
--- a/dlls/crypt32/chain.c
+++ b/dlls/crypt32/chain.c
@@ -865,11 +865,118 @@ static void compare_alt_name_with_constraints(const CERT_EXTENSION *altNameExt,
CERT_TRUST_INVALID_EXTENSION | CERT_TRUST_INVALID_NAME_CONSTRAINTS;
}
+static BOOL rfc822_attr_matches_excluded_name(const CERT_RDN_ATTR *attr,
+ const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
+{
+ DWORD i;
+ BOOL match = FALSE;
+
+ for (i = 0; !match && i < nameConstraints->cExcludedSubtree; i++)
+ {
+ const CERT_ALT_NAME_ENTRY *constraint =
+ &nameConstraints->rgExcludedSubtree[i].Base;
+
+ if (constraint->dwAltNameChoice == CERT_ALT_NAME_RFC822_NAME)
+ match = rfc822_name_matches(constraint->u.pwszRfc822Name,
+ (LPCWSTR)attr->Value.pbData, trustErrorStatus);
+ }
+ return match;
+}
+
+static BOOL rfc822_attr_matches_permitted_name(const CERT_RDN_ATTR *attr,
+ const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus,
+ BOOL *present)
+{
+ DWORD i;
+ BOOL match = FALSE;
+
+ for (i = 0; !match && i < nameConstraints->cPermittedSubtree; i++)
+ {
+ const CERT_ALT_NAME_ENTRY *constraint =
+ &nameConstraints->rgPermittedSubtree[i].Base;
+
+ if (constraint->dwAltNameChoice == CERT_ALT_NAME_RFC822_NAME)
+ {
+ *present = TRUE;
+ match = rfc822_name_matches(constraint->u.pwszRfc822Name,
+ (LPCWSTR)attr->Value.pbData, trustErrorStatus);
+ }
+ }
+ return match;
+}
+
+static void compare_subject_with_email_constraints(
+ const CERT_NAME_BLOB *subjectName,
+ const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
+{
+ CERT_NAME_INFO *name;
+ DWORD size;
+
+ if (CryptDecodeObjectEx(X509_ASN_ENCODING, X509_UNICODE_NAME,
+ subjectName->pbData, subjectName->cbData,
+ CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, &name, &size))
+ {
+ DWORD i, j;
+
+ for (i = 0; i < name->cRDN; i++)
+ for (j = 0; j < name->rgRDN[i].cRDNAttr; j++)
+ if (!strcmp(name->rgRDN[i].rgRDNAttr[j].pszObjId,
+ szOID_RSA_emailAddr))
+ {
+ BOOL nameFormPresent;
+
+ /* A name constraint only applies if the name form is
+ * present. From RFC 5280, section 4.2.1.10:
+ * "Restrictions apply only when the specified name form is
+ * present. If no name of the type is in the certificate,
+ * the certificate is acceptable."
+ */
+ if (rfc822_attr_matches_excluded_name(
+ &name->rgRDN[i].rgRDNAttr[j], nameConstraints,
+ trustErrorStatus))
+ *trustErrorStatus |=
+ CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT;
+ nameFormPresent = FALSE;
+ if (!rfc822_attr_matches_permitted_name(
+ &name->rgRDN[i].rgRDNAttr[j], nameConstraints,
+ trustErrorStatus, &nameFormPresent) && nameFormPresent)
+ *trustErrorStatus |=
+ CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT;
+ }
+ LocalFree(name);
+ }
+ else
+ *trustErrorStatus |=
+ CERT_TRUST_INVALID_EXTENSION | CERT_TRUST_INVALID_NAME_CONSTRAINTS;
+}
+
static void compare_subject_with_constraints(const CERT_NAME_BLOB *subjectName,
const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
{
+ BOOL hasEmailConstraint = FALSE;
DWORD i;
+ /* In general, a subject distinguished name only matches a directory name
+ * constraint. However, an exception exists for email addresses.
+ * From RFC 5280, section 4.2.1.6:
+ * "Legacy implementations exist where an electronic mail address is
+ * embedded in the subject distinguished name as an emailAddress
+ * attribute [RFC2985]."
+ * If an email address constraint exists, check that constraint separately.
+ */
+ for (i = 0; !hasEmailConstraint && i < nameConstraints->cExcludedSubtree;
+ i++)
+ if (nameConstraints->rgExcludedSubtree[i].Base.dwAltNameChoice ==
+ CERT_ALT_NAME_RFC822_NAME)
+ hasEmailConstraint = TRUE;
+ for (i = 0; !hasEmailConstraint && i < nameConstraints->cPermittedSubtree;
+ i++)
+ if (nameConstraints->rgPermittedSubtree[i].Base.dwAltNameChoice ==
+ CERT_ALT_NAME_RFC822_NAME)
+ hasEmailConstraint = TRUE;
+ if (hasEmailConstraint)
+ compare_subject_with_email_constraints(subjectName, nameConstraints,
+ trustErrorStatus);
for (i = 0; i < nameConstraints->cExcludedSubtree; i++)
{
CERT_ALT_NAME_ENTRY *constraint =
More information about the wine-cvs
mailing list