[31315] in CVS-changelog-for-Kerberos-V5

home help back first fref pref prev next nref lref last post

krb5 commit: Support site-local KDC discovery via DNS

daemon@ATHENA.MIT.EDU (ghudson@mit.edu)
Mon May 13 13:02:04 2024

From: ghudson@mit.edu
To: cvs-krb5@mit.edu
Message-Id: <20240513170158.010001019F0@krbdev.mit.edu>
Date: Mon, 13 May 2024 13:01:57 -0400 (EDT)
MIME-Version: 1.0
Reply-To: krbdev@mit.edu
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: cvs-krb5-bounces@mit.edu

https://github.com/krb5/krb5/commit/d035119c3b2b402f3ad49a4c7b6264826ea923bb
commit d035119c3b2b402f3ad49a4c7b6264826ea923bb
Author: Nicolas Williams <nico@cryptonector.com>
Date:   Thu May 13 00:43:26 2021 -0500

    Support site-local KDC discovery via DNS
    
    Add the sitename realm variable.  If set, service location via DNS
    will be attempted using the site name as specified in [MS-ADTS]
    6.3.2.3, falling back to regular discovery on failure.
    
    [ghudson@mit.edu: made this strictly a realm variable; moved
    k5_get_sitename() to locate_kdc.c and made it take a krb5_data input;
    fixed a memory leak; corrected documentation changes; fleshed out
    commit message]
    
    ticket: 9124 (new)

 doc/admin/conf_files/krb5_conf.rst |  4 ++++
 doc/admin/realm_config.rst         | 10 ++++++++++
 src/include/k5-int.h               |  1 +
 src/lib/krb5/os/dnssrv.c           | 34 ++++++++++++++++++++++++++++------
 src/lib/krb5/os/locate_kdc.c       | 31 ++++++++++++++++++++++++++++---
 src/lib/krb5/os/os-proto.h         |  4 +++-
 6 files changed, 74 insertions(+), 10 deletions(-)

diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index ab73a694d..2a45b1eaf 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -551,6 +551,10 @@ following tags may be specified in the realm's subsection:
     the updated database has not been propagated to the replica
     servers yet.  New in release 1.19.
 
+**sitename**
+    Specifies the name of the host's site for the purpose of DNS-based
+    KDC discovery for this realm.  New in release 1.22.
+
 **v4_instance_convert**
     This subsection allows the administrator to configure exceptions
     to the **default_domain** mapping rule.  It contains V4 instances
diff --git a/doc/admin/realm_config.rst b/doc/admin/realm_config.rst
index 35e4857e5..d0ed6f029 100644
--- a/doc/admin/realm_config.rst
+++ b/doc/admin/realm_config.rst
@@ -195,6 +195,13 @@ using the **kdc**, **master_kdc**, **admin_server**, and
 explicit server locations, providing SRV records will still benefit
 unconfigured clients, and be useful for other sites.
 
+Clients can be configured with the **sitename** realm variable (new in
+release 1.22).  If a site name is set, the client first attempts SRV
+record lookups with ".*sitename*._sites" inserted after the service
+and protocol name and before the Kerberos realm.  Site-specific
+records may indicate servers more proximal to the client, allowing for
+faster access.
+
 
 .. _kdc_discovery:
 
@@ -243,6 +250,9 @@ URI lookups are enabled by default, and can be disabled by setting
 precedence over SRV lookups, falling back to SRV lookups if no URI
 records are found.
 
+The **sitename** variable in the :ref:`realms` section of
+:ref:`krb5.conf(5)` applies to URI lookups as well as SRV lookups.
+
 
 .. _db_prop:
 
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index fe9959389..a5763bf68 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -293,6 +293,7 @@ typedef unsigned char   u_char;
 #define KRB5_CONF_REJECT_BAD_TRANSIT           "reject_bad_transit"
 #define KRB5_CONF_RENEW_LIFETIME               "renew_lifetime"
 #define KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT    "restrict_anonymous_to_tgt"
+#define KRB5_CONF_SITENAME                     "sitename"
 #define KRB5_CONF_SUPPORTED_ENCTYPES           "supported_enctypes"
 #define KRB5_CONF_SPAKE_PREAUTH_INDICATOR      "spake_preauth_indicator"
 #define KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE  "spake_preauth_kdc_challenge"
diff --git a/src/lib/krb5/os/dnssrv.c b/src/lib/krb5/os/dnssrv.c
index 62d6d1371..ffbbc8531 100644
--- a/src/lib/krb5/os/dnssrv.c
+++ b/src/lib/krb5/os/dnssrv.c
@@ -46,10 +46,10 @@ krb5int_free_srv_dns_data (struct srv_dns_entry *p)
 }
 
 /* Construct a DNS label of the form "service.[protocol.]realm.".  protocol may
- * be NULL. */
+ * and/or sitename be NULL. */
 static char *
 make_lookup_name(const krb5_data *realm, const char *service,
-                 const char *protocol)
+                 const char *protocol, const char *sitename)
 {
     struct k5buf buf;
 
@@ -60,6 +60,8 @@ make_lookup_name(const krb5_data *realm, const char *service,
     k5_buf_add_fmt(&buf, "%s.", service);
     if (protocol != NULL)
         k5_buf_add_fmt(&buf, "%s.", protocol);
+    if (sitename != NULL)
+        k5_buf_add_fmt(&buf, "%s._sites.", sitename);
     k5_buf_add_len(&buf, realm->data, realm->length);
 
     /*
@@ -119,6 +121,7 @@ k5_make_uri_query(krb5_context context, const krb5_data *realm,
 krb5_error_code
 krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
                              const char *service, const char *protocol,
+                             const char *sitename,
                              struct srv_dns_entry **answers)
 {
     char *name = NULL;
@@ -128,7 +131,7 @@ krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
 
     *answers = NULL;
 
-    name = make_lookup_name(realm, service, protocol);
+    name = make_lookup_name(realm, service, protocol, sitename);
     if (name == NULL)
         return 0;
 
@@ -136,6 +139,12 @@ krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
 
     st = DnsQuery_UTF8(name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &records,
                        NULL);
+    if (st != ERROR_SUCCESS && sitename != NULL) {
+        /* Try again without the site name. */
+        free(name);
+        return krb5int_make_srv_query_realm(context, realm, service, protocol,
+                                            NULL, answers);
+    }
     if (st != ERROR_SUCCESS)
         return 0;
 
@@ -176,7 +185,8 @@ cleanup:
 /* Query the URI RR, collecting weight, priority, and target. */
 krb5_error_code
 k5_make_uri_query(krb5_context context, const krb5_data *realm,
-                  const char *service, struct srv_dns_entry **answers)
+                  const char *service, const char *sitename,
+                  struct srv_dns_entry **answers)
 {
     const unsigned char *p = NULL, *base = NULL;
     char *name = NULL;
@@ -188,13 +198,18 @@ k5_make_uri_query(krb5_context context, const krb5_data *realm,
     *answers = NULL;
 
     /* Construct service.realm. */
-    name = make_lookup_name(realm, service, NULL);
+    name = make_lookup_name(realm, service, NULL, sitename);
     if (name == NULL)
         return 0;
 
     TRACE_DNS_URI_SEND(context, name);
 
     size = krb5int_dns_init(&ds, name, C_IN, T_URI);
+    if (size < 0 && sitename != NULL) {
+        /* Try again without the site name. */
+        free(name);
+        return k5_make_uri_query(context, realm, service, NULL, answers);
+    }
     if (size < 0)
         goto out;
 
@@ -242,6 +257,7 @@ out:
 krb5_error_code
 krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
                              const char *service, const char *protocol,
+                             const char *sitename,
                              struct srv_dns_entry **answers)
 {
     const unsigned char *p = NULL, *base = NULL;
@@ -262,13 +278,19 @@ krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
      *
      */
 
-    name = make_lookup_name(realm, service, protocol);
+    name = make_lookup_name(realm, service, protocol, sitename);
     if (name == NULL)
         return 0;
 
     TRACE_DNS_SRV_SEND(context, name);
 
     size = krb5int_dns_init(&ds, name, C_IN, T_SRV);
+    if (size < 0 && sitename) {
+        /* Try again without the site name. */
+        free(name);
+        return krb5int_make_srv_query_realm(context, realm, service, protocol,
+                                            NULL, answers);
+    }
     if (size < 0)
         goto out;
 
diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
index 7d246efac..e6f6e5f4b 100644
--- a/src/lib/krb5/os/locate_kdc.c
+++ b/src/lib/krb5/os/locate_kdc.c
@@ -98,6 +98,22 @@ _krb5_use_dns_realm(krb5_context context)
                          DEFAULT_LOOKUP_REALM);
 }
 
+static krb5_error_code
+get_sitename(krb5_context context, const krb5_data *realm, char **out)
+{
+    krb5_error_code ret;
+    char *realmstr;
+
+    *out = NULL;
+    realmstr = k5memdup0(realm->data, realm->length, &ret);
+    if (realmstr == NULL)
+        return ret;
+    ret = profile_get_string(context->profile, KRB5_CONF_REALMS,
+                             realmstr, KRB5_CONF_SITENAME, NULL, out);
+    free(realmstr);
+    return ret;
+}
+
 #endif /* KRB5_DNS_LOOKUP */
 
 /* Free up everything pointed to by the serverlist structure, but don't
@@ -328,9 +344,14 @@ locate_srv_dns_1(krb5_context context, const krb5_data *realm,
     struct srv_dns_entry *head = NULL, *entry = NULL;
     krb5_error_code code = 0;
     k5_transport transport;
+    char *sitename;
 
+    code = get_sitename(context, realm, &sitename);
+    if (code)
+        return code;
     code = krb5int_make_srv_query_realm(context, realm, service, protocol,
-                                        &head);
+                                        sitename, &head);
+    free(sitename);
     if (code)
         return 0;
 
@@ -616,11 +637,15 @@ locate_uri(krb5_context context, const krb5_data *realm,
     krb5_error_code ret;
     k5_transport transport, host_trans;
     struct srv_dns_entry *answers, *entry;
-    char *host;
+    char *host, *sitename;
     const char *host_field, *path;
     int port, def_port, primary;
 
-    ret = k5_make_uri_query(context, realm, req_service, &answers);
+    ret = get_sitename(context, realm, &sitename);
+    if (ret)
+        return ret;
+    ret = k5_make_uri_query(context, realm, req_service, sitename, &answers);
+    free(sitename);
     if (ret || answers == NULL)
         return ret;
 
diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h
index ad686a924..a21558d23 100644
--- a/src/lib/krb5/os/os-proto.h
+++ b/src/lib/krb5/os/os-proto.h
@@ -176,13 +176,15 @@ struct srv_dns_entry {
 krb5_error_code
 krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
                              const char *service, const char *protocol,
+                             const char *sitename,
                              struct srv_dns_entry **answers);
 
 void krb5int_free_srv_dns_data(struct srv_dns_entry *);
 
 krb5_error_code
 k5_make_uri_query(krb5_context context, const krb5_data *realm,
-                  const char *service, struct srv_dns_entry **answers);
+                  const char *service, const char *sitename,
+                  struct srv_dns_entry **answers);
 
 krb5_error_code k5_try_realm_txt_rr(krb5_context context, const char *prefix,
                                     const char *name, char **realm);
_______________________________________________
cvs-krb5 mailing list
cvs-krb5@mit.edu
https://mailman.mit.edu/mailman/listinfo/cvs-krb5

home help back first fref pref prev next nref lref last post