File pkinit-nss-0.6.1-match-default-realms.patch of Package krb5-plugin-preauth-pkinit-nss

Index: src/certs.c
===================================================================
--- src/certs.c.orig
+++ src/certs.c
@@ -1369,6 +1369,92 @@ cert_eku_matches_eku_for_realm(struct mo
 	return status;
 }
 
+static PRBool
+cert_san_matches_upn_check (struct module_context *mcontext,
+                            krb5_context kcontext,
+                            SECItem *unparsed_name,
+                            char *unparsed_realm,
+                            SECItem *ms_upn_name)
+{
+        unsigned char *ms_upn_domain;
+        SECItem unparsed_tmp, ms_upn_tmp;
+        int rc;
+        PRBool ret;
+        char **realms;
+        char *ms_upn_host;
+        int len;
+
+        /* And it matches, then we're okay. */
+        if (SECITEM_ItemsAreEqual(ms_upn_name, unparsed_name)) {
+                pkinit_debug(mcontext, 2, "UPN Matched.\n");
+                return PR_TRUE;
+        }
+        
+        if (!unparsed_realm) {
+                return PR_FALSE;
+        }
+
+        ms_upn_domain = memchr (ms_upn_name->data, '@', ms_upn_name->len);
+        if (!ms_upn_domain) {
+                return PR_FALSE;
+        }
+
+        ms_upn_domain++;
+        
+        unparsed_tmp.data = unparsed_name->data;
+        unparsed_tmp.len = unparsed_realm - (char *)unparsed_name->data;
+        
+        ms_upn_tmp.data = ms_upn_name->data;
+        ms_upn_tmp.len = ms_upn_domain - ms_upn_name->data;
+
+        /* compare user names... */
+        if (!SECITEM_ItemsAreEqual(&ms_upn_tmp, &unparsed_tmp)) {
+                return PR_FALSE;
+        }
+        
+        len = ms_upn_name->len - ms_upn_tmp.len;
+        ms_upn_host = malloc (len + 2); /* dot and nil */
+        if (!ms_upn_host) {
+            pkinit_debug (mcontext, 2,
+                          "Could not alloc upn_host: length was %d.\n",
+                          len);
+            return PR_FALSE;
+        }
+
+        /* ms_upn_domain isn't NULL terminated, so we need to copy it
+         * out... */
+        ms_upn_host[0] = '.';
+        strncpy (ms_upn_host + 1, (char *)ms_upn_domain, len);
+        ms_upn_host[len + 1] = '\0';
+        rc = krb5_get_host_realm (kcontext, ms_upn_host, &realms);
+        free (ms_upn_host);
+        ms_upn_host = NULL;
+        if (rc != 0) {
+                pkinit_debug (mcontext, 2, 
+                              "Could not get host realm for .%s: %d.\n",
+                              ms_upn_domain, rc);
+                return PR_FALSE;
+        } else {
+                pkinit_debug (mcontext, 2,
+                              "Found domain \".%.*s\" mapped to realm \"%s\".\n",
+                              len, ms_upn_domain, realms[0]);
+        }
+
+        ms_upn_tmp.data = (unsigned char *)realms[0];
+        ms_upn_tmp.len = strlen (realms[0]);
+
+        unparsed_tmp.data = (unsigned char *)unparsed_realm;
+        unparsed_tmp.len = len;
+
+        ret = SECITEM_ItemsAreEqual (&ms_upn_tmp, &unparsed_tmp);
+        if (ret) {
+                pkinit_debug (mcontext, 2, "UPN Matched.\n");
+        }
+        free (realms[0]);
+        free (realms);
+        return ret;
+}
+
 /* Check if the certificate subjectAltName UPN value matches the principal. */
 static SECStatus
 cert_san_matches_upn(struct module_context *mcontext, CERTCertificate *cert,
@@ -1377,7 +1463,7 @@ cert_san_matches_upn(struct module_conte
 {
 	struct subject_alt_name **names;
 	SECItem san_value, unparsed_name, ms_upn_name;
-	char *unparsed;
+	char *unparsed, *unparsed_realm;
 	int i;
 
 	i = 0;
@@ -1411,6 +1497,11 @@ cert_san_matches_upn(struct module_conte
 	unparsed_name.data = (unsigned char *) unparsed;
 	unparsed_name.len = strlen(unparsed);
 
+        unparsed_realm = memchr (unparsed_name.data, '@', unparsed_name.len);
+        if (unparsed_realm != NULL) {
+            unparsed_realm++;
+        }
+
 	/* Iterate over all of the values. */
 	*matches = PR_FALSE;
 	for (i = 0; (names != NULL) && (names[i] != NULL) && !(*matches); i++) {
@@ -1427,12 +1518,11 @@ cert_san_matches_upn(struct module_conte
 						       ms_upn_name_template,
 						       &names[i]->subject_alt_name_value.other_name.data) == SECSuccess) {
 					/* And it matches, then we're okay. */
-					if (SECITEM_ItemsAreEqual(&ms_upn_name,
-								  &unparsed_name)) {
-						pkinit_debug(mcontext, 2,
-							     "UPN Matched.\n");
-						*matches = PR_TRUE;
-					} else {
+                                        *matches = cert_san_matches_upn_check (mcontext, kcontext, 
+                                                                               &unparsed_name,
+                                                                               unparsed_realm,
+                                                                               &ms_upn_name);
+                                        if (!*matches) {
 						pkinit_debug(mcontext, 2,
 							     "\"%.*s\" != "
 							     "\"%.*s\"\n",
openSUSE Build Service is sponsored by