Hi!

Attached patches make possible to use HTTP/ipa.server@REALM to query AD
DC over LDAP immediately after trust is established. We need this to get
range discovery working prior to creating range for trusted domain.

The patch 0109 makes KDC hostname cached on ipadb context to avoid
resolving own hostname multiple times.

The patch 0110 depends on ulc_casemap patches by Nathaniel and makes
exception for HTTP/ipa.server@REALM when TGT is requested and MS-PAC is
asked for -- we force refreshing list of trusted domains here.

More details are available in the commit logs.
--
/ Alexander Bokovoy
>From c6c2991ddf939d1e4245564b666d9b04a8c7be12 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <aboko...@redhat.com>
Date: Thu, 18 Jul 2013 17:10:01 +0300
Subject: [PATCH 6/7] ipa-kdb: cache KDC hostname on startup

We need KDC hostname for several purposes:
- short-circuit detection of principals on the same server as KDC
- generating NetBIOS name

Make sure we cache hostname information on startup and use it
instead of detecting the hostname in run-time. This will miss the
case that KDC hostname got changed but such cases are not supported
anyway without restarting KDC and making changes to principals.
---
 daemons/ipa-kdb/ipa_kdb.c       | 15 +++++++++++++++
 daemons/ipa-kdb/ipa_kdb.h       |  1 +
 daemons/ipa-kdb/ipa_kdb_mspac.c |  9 +++------
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index 8464264..51b879c 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -21,6 +21,7 @@
  */
 
 #include <talloc.h>
+#include <sys/utsname.h>
 
 #include "ipa_kdb.h"
 
@@ -46,6 +47,7 @@ static void ipadb_context_free(krb5_context kcontext,
         free((*ctx)->uri);
         free((*ctx)->base);
         free((*ctx)->realm_base);
+        free((*ctx)->kdc_hostname);
         /* ldap free lcontext */
         if ((*ctx)->lcontext) {
             ldap_unbind_ext_s((*ctx)->lcontext, NULL, NULL);
@@ -442,6 +444,7 @@ static krb5_error_code ipadb_init_module(krb5_context 
kcontext,
     krb5_error_code kerr;
     int ret;
     int i;
+    struct utsname uname_data;
 
     /* make sure the context is freed to avoid leaking it */
     ipactx = ipadb_get_context(kcontext);
@@ -494,6 +497,18 @@ static krb5_error_code ipadb_init_module(krb5_context 
kcontext,
         goto fail;
     }
 
+    ret = uname(&uname_data);
+    if (ret) {
+        ret = EINVAL;
+        goto fail;
+    }
+
+    ipactx->kdc_hostname = strdup(uname_data.nodename);
+    if (!ipactx->kdc_hostname) {
+        ret = ENOMEM;
+        goto fail;
+    }
+
     ret = ipadb_get_connection(ipactx);
     if (ret != 0) {
         /* not a fatal failure, as the LDAP server may be temporarily down */
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index f7797c4..a611bc2 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -92,6 +92,7 @@ struct ipadb_context {
     char *base;
     char *realm;
     char *realm_base;
+    char *kdc_hostname;
     LDAP *lcontext;
     krb5_context kcontext;
     bool override_restrictions;
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
index 96eac6f..d6c4f9a 100644
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
@@ -1905,16 +1905,13 @@ done:
     return kerr;
 }
 
-static char *get_server_netbios_name(void)
+static char *get_server_netbios_name(struct ipadb_context *ipactx)
 {
     char hostname[MAXHOSTNAMELEN + 1]; /* NOTE: this is 64, too little ? */
     char *p;
     int ret;
 
-    ret = gethostname(hostname, MAXHOSTNAMELEN);
-    if (ret) {
-        return NULL;
-    }
+    strncpy(hostname, ipactx->kdc_hostname, MAXHOSTNAMELEN);
     /* May miss termination */
     hostname[MAXHOSTNAMELEN] = '\0';
     for (p = hostname; *p; p++) {
@@ -2245,7 +2242,7 @@ krb5_error_code ipadb_reinit_mspac(struct ipadb_context 
*ipactx)
     free(resstr);
 
     free(ipactx->mspac->flat_server_name);
-    ipactx->mspac->flat_server_name = get_server_netbios_name();
+    ipactx->mspac->flat_server_name = get_server_netbios_name(ipactx);
     if (!ipactx->mspac->flat_server_name) {
         kerr = ENOMEM;
         goto done;
-- 
1.8.3.1

>From 7c452bb3501bf7d5e3fce774d4edce8b2b46579d Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <aboko...@redhat.com>
Date: Thu, 18 Jul 2013 13:32:42 +0300
Subject: [PATCH 7/7] ipa-kdb: reinit mspac on HTTP TGT acquisition to aid
 trust-add case

When trust is established, we also create idrange for the trusted domain.
With FreeIPA 3.3 these ranges can have different types, and in order to
detect which one is to create, we need to do lookup at AD LDAP server.

Such lookup requires authenticated bind. We cannot bind as user because
IPA framework operates under constrained delegation using the user's
credentials and allowing HTTP/ipa.server@REALM to impersonate the user
against trusted domain's services would require two major things:

  - first, as we don't really know exact AD LDAP server names (any AD DC
    can be used), constrained delegation would have to be defined against
    a wild-card

  - second, constrained delegation requires that target principal exists
    in IPA LDAP as DN.

These two together limit use of user's ticket for the purpose of IPA
framework looking up AD LDAP.

Additionally, immediately after trust is established, issuing TGT with
MS-PAC to HTTP/ipa.server@REALM may fail due to the fact that KDB driver
did not yet refreshed its list of trusted domains -- we have limited
refresh rate of 60 seconds by default.

This patch makes possible to force re-initialization of trusted domains'
view in KDB driver if we are asked for TGT for HTTP/ipa.server@REALM.

We will need to improve refresh of trusted domains' view in KDB driver
in future to notice changes in cn=etc,$SUFFIX tree automatically.

This improvement is tracked in https://fedorahosted.org/freeipa/ticket/1302 and
https://fedorahosted.org/freeipa/ticket/3626

Part of https://fedorahosted.org/freeipa/ticket/3649
---
 daemons/ipa-kdb/ipa_kdb.c       |  4 ++--
 daemons/ipa-kdb/ipa_kdb.h       |  2 +-
 daemons/ipa-kdb/ipa_kdb_mspac.c | 29 ++++++++++++++++++++++++++---
 3 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index 51b879c..cfdafce 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -393,8 +393,8 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
         goto done;
     }
 
-    /* get adtrust options */
-    ret = ipadb_reinit_mspac(ipactx);
+    /* get adtrust options using default refresh interval */
+    ret = ipadb_reinit_mspac(ipactx, -1);
     if (ret && ret != ENOENT) {
         /* TODO: log that there is an issue with adtrust settings */
     }
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index a611bc2..a117937 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -250,7 +250,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
                                     krb5_authdata **tgt_auth_data,
                                     krb5_authdata ***signed_auth_data);
 
-krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx);
+krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, int interval);
 
 void ipadb_mspac_struct_free(struct ipadb_mspac **mspac);
 
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
index d6c4f9a..4ddf3e8 100644
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
@@ -24,6 +24,7 @@
 #include "ipa_mspac.h"
 #include <talloc.h>
 #include <syslog.h>
+#include <unicase.h>
 #include "util/time.h"
 #include "gen_ndr/ndr_krb5pac.h"
 
@@ -1282,7 +1283,8 @@ static struct ipadb_adtrusts 
*get_domain_from_realm_update(krb5_context context,
         return NULL;
     }
 
-    kerr = ipadb_reinit_mspac(ipactx);
+    /* re-init MS-PAC info using default update interval */
+    kerr = ipadb_reinit_mspac(ipactx, -1);
     if (kerr != 0) {
         return NULL;
     }
@@ -1805,8 +1807,10 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
     krb5_error_code kerr;
     krb5_pac pac = NULL;
     krb5_data pac_data;
+    struct ipadb_context *ipactx;
     bool with_pac;
     bool with_pad;
+    int result;
 
     /* When using s4u2proxy client_princ actually refers to the proxied user
      * while client->princ to the proxy service asking for the TGS on behalf
@@ -1831,6 +1835,22 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
     is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
 
     if (is_as_req && with_pac && (flags & KRB5_KDB_FLAG_INCLUDE_PAC)) {
+        /* Be aggressive here: special case for discovering range type
+         * immediately after establishing the trust by IPA framework */
+        if ((krb5_princ_size(context, ks_client_princ) == 2) &&
+            (strncmp(krb5_princ_component(context, ks_client_princ, 0)->data, 
"HTTP",
+                     krb5_princ_component(context, ks_client_princ, 
0)->length) == 0)) {
+            ipactx = ipadb_get_context(context);
+            if (!ipactx) {
+                goto done;
+            }
+            if (ulc_casecmp(krb5_princ_component(context, ks_client_princ, 
1)->data,
+                            krb5_princ_component(context, ks_client_princ, 
1)->length,
+                            ipactx->kdc_hostname, strlen(ipactx->kdc_hostname),
+                            NULL, NULL, &result) == 0) {
+                kerr = ipadb_reinit_mspac(ipactx, 1);
+            }
+        }
 
         kerr = ipadb_get_pac(context, client, &pac);
         if (kerr != 0 && kerr != ENOENT) {
@@ -2155,7 +2175,7 @@ done:
     return ret;
 }
 
-krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx)
+krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, int interval)
 {
     char *dom_attrs[] = { "ipaNTFlatName",
                           "ipaNTFallbackPrimaryGroup",
@@ -2174,8 +2194,11 @@ krb5_error_code ipadb_reinit_mspac(struct ipadb_context 
*ipactx)
      * avoid heavy load on the directory server if there are lots of requests
      * from domains which we do not trust. */
     now = time(NULL);
+    if (interval <= 0) {
+        interval = 60;
+    }
     if (ipactx->mspac != NULL && now > ipactx->mspac->last_update &&
-        (now - ipactx->mspac->last_update) < 60) {
+        (now - ipactx->mspac->last_update) < interval) {
         return 0;
     }
 
-- 
1.8.3.1

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

Reply via email to