During the Kerberos interop we found out we are still missing to
generate a Ms-PAc field the MS testsuite wants to see.

I did some work in the past to create the UPN_DNS_INFO buffer in the
samba IDL files but it has been recently reverted upstream due to some
issues it created for Samba4 and is being reworked by G√ľnther and Metze.

However I still went ahead and created a prototype patch that would use
the new union buffer once it is released.

In doing that I realize recent changes made it difficult to add the
buffer so I created a patch that splits out some checks.

I would like to push patch 0001, so that in the future we will also be
able to push patch 0002, however 0002 cannot be pushed now as we miss
the necessary code in the samba packages. So 0002 is added here only for
reference to understand why I coded 0001 the way I did.

Simo.

-- 
Simo Sorce * Red Hat, Inc * New York
>From a530fa5440f4928320d886e78504688d50607553 Mon Sep 17 00:00:00 2001
From: Simo Sorce <s...@redhat.com>
Date: Wed, 9 Oct 2013 20:32:18 -0400
Subject: [PATCH 1/2] mspac: Split retrieval of basic account data

Split ipadb_fill_info3 in 2 functions:
- one that retrieves basic account data and optionally fakes up some of
the data
- the other just fills info3 based on the input data as the name says
---
 daemons/ipa-kdb/ipa_kdb_mspac.c | 130 ++++++++++++++++++++++++++--------------
 1 file changed, 86 insertions(+), 44 deletions(-)

diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
index ff67391538234e2272ea1ec886ec96fa88ea579b..302a692fda3603cc58a1698e5ca246d77cdbf756 100644
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
@@ -397,42 +397,38 @@ static bool is_master_host(struct ipadb_context *ipactx, const char *fqdn)
     return false;
 }
 
-static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
-                                        LDAPMessage *lentry,
-                                        TALLOC_CTX *memctx,
-                                        struct netr_SamInfo3 *info3)
+static krb5_error_code ipadb_basic_account_data(struct ipadb_context *ipactx,
+                                                LDAPMessage *lentry,
+                                                TALLOC_CTX *memctx,
+                                                char **account_name,
+                                                uint32_t *account_rid,
+                                                gid_t *primary_gid)
 {
     LDAP *lcontext = ipactx->lcontext;
-    LDAPDerefRes *deref_results = NULL;
-    struct dom_sid sid;
-    gid_t prigid = -1;
-    time_t timeres;
-    char *strres;
-    int intres;
-    int ret;
-    int i;
     char **objectclasses = NULL;
-    size_t c;
     bool is_host = false;
     bool is_user = false;
     bool is_service = false;
+    char *strres;
     krb5_principal princ;
     krb5_data *data;
+    int ret;
+    int i;
 
     ret = ipadb_ldap_attr_to_strlist(lcontext, lentry, "objectClass",
                                      &objectclasses);
     if (ret == 0 && objectclasses != NULL) {
-        for (c = 0; objectclasses[c] != NULL; c++) {
-            if (strcasecmp(objectclasses[c], "ipaHost") == 0) {
+        for (i = 0; objectclasses[i] != NULL; i++) {
+            if (strcasecmp(objectclasses[i], "ipaHost") == 0) {
                 is_host = true;
             }
-            if (strcasecmp(objectclasses[c], "ipaService") == 0) {
+            if (strcasecmp(objectclasses[i], "ipaService") == 0) {
                 is_service = true;
             }
-            if (strcasecmp(objectclasses[c], "ipaNTUserAttrs") == 0) {
+            if (strcasecmp(objectclasses[i], "ipaNTUserAttrs") == 0) {
                 is_user = true;
             }
-            free(objectclasses[c]);
+            free(objectclasses[i]);
         }
     }
     free(objectclasses);
@@ -446,7 +442,7 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
         ret = ipadb_ldap_attr_to_str(lcontext, lentry, "fqdn", &strres);
         if (ret) {
             /* fqdn is mandatory for hosts */
-            return ret;
+            return ENOENT;
         }
 
         /* Currently we only add a PAC to TGTs for IPA servers to allow SSSD in
@@ -459,7 +455,7 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
         ret = ipadb_ldap_attr_to_str(lcontext, lentry, "krbPrincipalName", &strres);
         if (ret) {
             /* krbPrincipalName is mandatory for services */
-            return ret;
+            return ENOENT;
         }
 
         ret = krb5_parse_name(ipactx->kcontext, strres, &princ);
@@ -507,15 +503,49 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
         ret = ipadb_ldap_attr_to_str(lcontext, lentry, "uid", &strres);
         if (ret) {
             /* uid is mandatory */
-            return ret;
+            return ENOENT;
         }
     }
 
+    *account_name = talloc_strdup(memctx, strres);
+    if (!*account_name) {
+        return ENOMEM;
+    }
+
+    if (is_host || is_service) {
+        *account_rid = 516; /* Well know RID of domain controllers group */
+        *primary_gid = 515; /* Well known RID for domain computers group */
+    } else {
+        *account_rid = 0;
+        *primary_gid = 0;
+    }
+
+    return 0;
+}
+
+static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
+                                        LDAPMessage *lentry,
+                                        TALLOC_CTX *memctx,
+                                        char *account_name,
+                                        uint32_t account_rid,
+                                        gid_t primary_gid,
+                                        struct netr_SamInfo3 *info3)
+{
+    LDAP *lcontext = ipactx->lcontext;
+    LDAPDerefRes *deref_results = NULL;
+    struct dom_sid sid;
+    gid_t prigid = -1;
+    time_t timeres;
+    char *strres;
+    int intres;
+    int ret;
+    int i;
+
     info3->base.account_name.string = talloc_strdup(memctx, strres);
     free(strres);
 
-    if (is_host || is_service) {
-        prigid = 515; /* Well known RID for domain computers group */
+    if (primary_gid != 0) {
+        prigid = primary_gid;
     } else {
         ret = ipadb_ldap_attr_to_int(lcontext, lentry, "gidNumber", &intres);
         if (ret) {
@@ -637,9 +667,8 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
     info3->base.logon_count = 0; /* we do not have this info yet */
     info3->base.bad_password_count = 0; /* we do not have this info yet */
 
-    if (is_host || is_service) {
-        /* Well know RID of domain controllers group */
-        info3->base.rid = 516;
+    if (account_rid != 0) {
+        info3->base.rid = account_rid;
     } else {
         ret = ipadb_ldap_attr_to_str(lcontext, lentry,
                                      "ipaNTSecurityIdentifier", &strres);
@@ -728,8 +757,8 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
     }
 
     if (info3->base.primary_gid == 0) {
-        if (is_host || is_service) {
-            info3->base.primary_gid = 515;  /* Well known RID for domain computers group */
+        if (primary_gid != 0) {
+            info3->base.primary_gid = primary_gid;
         } else {
             if (ipactx->mspac->fallback_rid) {
                 info3->base.primary_gid = ipactx->mspac->fallback_rid;
@@ -768,7 +797,7 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
         return ENOENT;
     }
 
-    if (is_host || is_service) {
+    if (account_rid != 0) {
         info3->base.domain_sid = talloc_memdup(memctx, &ipactx->mspac->domsid,
                                                sizeof(ipactx->mspac->domsid));
     } else {
@@ -805,6 +834,9 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext,
     union PAC_INFO pac_info;
     krb5_error_code kerr;
     enum ndr_err_code ndr_err;
+    char *account_name = NULL;
+    uint32_t account_rid = 0;
+    gid_t primary_gid = 0;
 
     ipactx = ipadb_get_context(kcontext);
     if (!ipactx) {
@@ -821,16 +853,11 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext,
         return ENOMEM;
     }
 
-    memset(&pac_info, 0, sizeof(pac_info));
-    pac_info.logon_info.info = talloc_zero(tmpctx, struct PAC_LOGON_INFO);
-    if (!pac_info.logon_info.info) {
-        kerr = ENOMEM;
+    kerr = krb5_pac_init(kcontext, pac);
+    if (kerr) {
         goto done;
     }
 
-    /* PAC_LOGON_NAME and PAC_TYPE_UPN_DNS_INFO are automatically added
-     * by krb5_pac_sign() later on */
-
     /* == Search PAC info == */
     kerr = ipadb_deref_search(ipactx, ied->entry_dn, LDAP_SCOPE_BASE,
                               "(objectclass=*)", user_pac_attrs,
@@ -846,14 +873,29 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext,
         goto done;
     }
 
+    kerr = ipadb_basic_account_data(ipactx, lentry, tmpctx, &account_name,
+                                    &account_rid, &primary_gid);
+    if (kerr) {
+        goto done;
+    }
+
+    /* PAC_LOGON_NAME is automatically added by krb5_pac_sign() */
+
     /* == Fill Info3 == */
-    kerr = ipadb_fill_info3(ipactx, lentry, tmpctx,
-                            &pac_info.logon_info.info->info3);
+    memset(&pac_info, 0, sizeof(pac_info));
+    pac_info.logon_info.info = talloc_zero(tmpctx, struct PAC_LOGON_INFO);
+    if (!pac_info.logon_info.info) {
+        kerr = ENOMEM;
+        goto done;
+    }
+
+    kerr = ipadb_fill_info3(ipactx, lentry, tmpctx, account_name, account_rid,
+                            primary_gid, &pac_info.logon_info.info->info3);
     if (kerr) {
         goto done;
     }
 
-    /* == Package PAC == */
+    /* == Add PAC Buffer == */
     ndr_err = ndr_push_union_blob(&pac_data, tmpctx, &pac_info,
                                   PAC_TYPE_LOGON_INFO,
                                   (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
@@ -862,18 +904,18 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext,
         goto done;
     }
 
-    kerr = krb5_pac_init(kcontext, pac);
-    if (kerr) {
-        goto done;
-    }
-
     data.magic = KV5M_DATA;
     data.data = (char *)pac_data.data;
     data.length = pac_data.length;
 
     kerr = krb5_pac_add_buffer(kcontext, *pac, KRB5_PAC_LOGON_INFO, &data);
 
+
+
 done:
+    if (kerr) {
+        krb5_pac_free(kcontext, *pac);
+    }
     ldap_msgfree(results);
     talloc_free(tmpctx);
     return kerr;
-- 
1.8.3.1

>From d396778163af4a84b29b9c3477181521508bcb44 Mon Sep 17 00:00:00 2001
From: Simo Sorce <s...@redhat.com>
Date: Wed, 9 Oct 2013 20:34:14 -0400
Subject: [PATCH 2/2] mspac: Add support for UPN_DNS_INFO buffer

Fill up a upn_dns_info buffer and adds it to the pac.
---
 daemons/ipa-kdb/ipa_kdb_mspac.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
index 302a692fda3603cc58a1698e5ca246d77cdbf756..b670697f95c07d298d09f9e4ff18fc395f0642dc 100644
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
@@ -820,6 +820,26 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
     return 0;
 }
 
+static krb5_error_code ipadb_fill_upn_dns_info(struct ipadb_context *ipactx,
+                                               TALLOC_CTX *memctx,
+                                               const char *account_name,
+                                               struct PAC_UPN_DNS_INFO *info)
+{
+    /* for now always declare that the user has no UPN */
+    info->flags = UDI_ACCT_HAS_NO_UPN;
+    info->upn_name = talloc_asprintf(memctx, "%s@%s",
+                                     account_name, ipactx->realm);
+    if (!info->upn_name) {
+        return ENOMEM;
+    }
+    info->domain_name = talloc_strdup(memctx, ipactx->realm);
+    if (!info->domain_name) {
+        return ENOMEM;
+    }
+
+    return 0;
+}
+
 static krb5_error_code ipadb_get_pac(krb5_context kcontext,
                                      krb5_db_entry *client,
                                      krb5_pac *pac)
@@ -910,7 +930,27 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext,
 
     kerr = krb5_pac_add_buffer(kcontext, *pac, KRB5_PAC_LOGON_INFO, &data);
 
+    /* == Fill UPN_DNS_INFO == */
+    kerr = ipadb_fill_upn_dns_info(ipactx, tmpctx, account_name,
+                                   &pac_info.upn_dns_info);
+    if (kerr) {
+        goto done;
+    }
 
+    /* == Add PAC Buffer == */
+    ndr_err = ndr_push_union_blob(&pac_data, tmpctx, &pac_info,
+                                  PAC_TYPE_UPN_DNS_INFO,
+                                  (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
+    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+        kerr = KRB5_KDB_INTERNAL_ERROR;
+        goto done;
+    }
+
+    data.magic = KV5M_DATA;
+    data.data = (char *)pac_data.data;
+    data.length = pac_data.length;
+
+    kerr = krb5_pac_add_buffer(kcontext, *pac, KRB5_PAC_UPN_DNS_INFO, &data);
 
 done:
     if (kerr) {
-- 
1.8.3.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to