krb5 commit: Reorganize internal DNS interfaces

Greg Hudson ghudson at mit.edu
Tue Jun 12 19:24:06 EDT 2018


https://github.com/krb5/krb5/commit/c3b2dc0041918128dceedaf21ad718465e759e63
commit c3b2dc0041918128dceedaf21ad718465e759e63
Author: Greg Hudson <ghudson at mit.edu>
Date:   Sat Jun 2 18:25:43 2018 -0400

    Reorganize internal DNS interfaces
    
    Move SRV lookup function declarations out of dnsglue.h into
    os-proto.h, where the TXT lookup function is declared.  Only include
    dnsglue.h within files which need to parse DNS records.
    
    To avoid needing MAXDNAME, use dynamic allocation for the results of
    DNS lookups (including hostname canonicalization) where we currently
    use fixed buffers.  Remove clean_hostname from the accessor (nothing
    uses it) and make it a static function within hostrealm.c.

 src/include/k5-int.h            |    5 +--
 src/lib/krb5/os/accessor.c      |    2 -
 src/lib/krb5/os/deps            |    3 +-
 src/lib/krb5/os/dnsglue.c       |   19 +++++------
 src/lib/krb5/os/dnsglue.h       |   23 -------------
 src/lib/krb5/os/dnssrv.c        |   38 ++++++++++++----------
 src/lib/krb5/os/hostrealm.c     |   66 ++++++++++++++++++++++----------------
 src/lib/krb5/os/hostrealm_dns.c |    6 ++--
 src/lib/krb5/os/locate_kdc.c    |   11 +------
 src/lib/krb5/os/os-proto.h      |   22 ++++++++++++-
 10 files changed, 93 insertions(+), 102 deletions(-)

diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 5d84985..1dedeb9 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -1831,16 +1831,13 @@ krb5int_random_string(krb5_context, char *string, unsigned int length);
 /* To keep happy libraries which are (for now) accessing internal stuff */
 
 /* Make sure to increment by one when changing the struct */
-#define KRB5INT_ACCESS_STRUCT_VERSION 21
+#define KRB5INT_ACCESS_STRUCT_VERSION 22
 
 typedef struct _krb5int_access {
     krb5_error_code (*auth_con_get_subkey_enctype)(krb5_context,
                                                    krb5_auth_context,
                                                    krb5_enctype *);
 
-    krb5_error_code (*clean_hostname)(krb5_context, const char *, char *,
-                                      size_t);
-
     krb5_error_code (*mandatory_cksumtype)(krb5_context, krb5_enctype,
                                            krb5_cksumtype *);
     krb5_error_code (KRB5_CALLCONV *ser_pack_int64)(int64_t, krb5_octet **,
diff --git a/src/lib/krb5/os/accessor.c b/src/lib/krb5/os/accessor.c
index 11552ef..d77f8c6 100644
--- a/src/lib/krb5/os/accessor.c
+++ b/src/lib/krb5/os/accessor.c
@@ -56,8 +56,6 @@ krb5int_accessor(krb5int_access *internals, krb5_int32 version)
 #endif
             S (auth_con_get_subkey_enctype, krb5_auth_con_get_subkey_enctype),
 
-            S (clean_hostname, k5_clean_hostname),
-
 #ifndef LEAN_CLIENT
 #define SC(FIELD, VAL)  S(FIELD, VAL)
 #else /* disable */
diff --git a/src/lib/krb5/os/deps b/src/lib/krb5/os/deps
index c09087d..0e5de6e 100644
--- a/src/lib/krb5/os/deps
+++ b/src/lib/krb5/os/deps
@@ -329,8 +329,7 @@ locate_kdc.so locate_kdc.po $(OUTPRE)locate_kdc.$(OBJEXT): \
   $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
   $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
   $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h dnsglue.h locate_kdc.c \
-  os-proto.h
+  $(top_srcdir)/include/socket-utils.h locate_kdc.c os-proto.h
 lock_file.so lock_file.po $(OUTPRE)lock_file.$(OBJEXT): \
   $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
   $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
diff --git a/src/lib/krb5/os/dnsglue.c b/src/lib/krb5/os/dnsglue.c
index e29066d..86138c4 100644
--- a/src/lib/krb5/os/dnsglue.c
+++ b/src/lib/krb5/os/dnsglue.c
@@ -364,7 +364,7 @@ k5_try_realm_txt_rr(krb5_context context, const char *prefix, const char *name,
 {
     krb5_error_code retval = KRB5_ERR_HOST_REALM_UNKNOWN;
     const unsigned char *p, *base;
-    char host[MAXDNAME];
+    char *txtname = NULL;
     int ret, rdlen, len;
     struct krb5int_dns_state *ds = NULL;
     struct k5buf buf;
@@ -373,7 +373,7 @@ k5_try_realm_txt_rr(krb5_context context, const char *prefix, const char *name,
      * Form our query, and send it via DNS
      */
 
-    k5_buf_init_fixed(&buf, host, sizeof(host));
+    k5_buf_init_dynamic(&buf);
     if (name == NULL || name[0] == '\0') {
         k5_buf_add(&buf, prefix);
     } else {
@@ -389,14 +389,15 @@ k5_try_realm_txt_rr(krb5_context context, const char *prefix, const char *name,
            the local domain or domain search lists to be expanded.
         */
 
-        if (buf.len > 0 && host[buf.len - 1] != '.')
+        if (buf.len > 0 && ((char *)buf.data)[buf.len - 1] != '.')
             k5_buf_add(&buf, ".");
     }
     if (k5_buf_status(&buf) != 0)
         return KRB5_ERR_HOST_REALM_UNKNOWN;
-    ret = krb5int_dns_init(&ds, host, C_IN, T_TXT);
+    txtname = buf.data;
+    ret = krb5int_dns_init(&ds, txtname, C_IN, T_TXT);
     if (ret < 0) {
-        TRACE_TXT_LOOKUP_NOTFOUND(context, host);
+        TRACE_TXT_LOOKUP_NOTFOUND(context, txtname);
         goto errout;
     }
 
@@ -419,13 +420,11 @@ k5_try_realm_txt_rr(krb5_context context, const char *prefix, const char *name,
     if ( (*realm)[len-1] == '.' )
         (*realm)[len-1] = '\0';
     retval = 0;
-    TRACE_TXT_LOOKUP_SUCCESS(context, host, *realm);
+    TRACE_TXT_LOOKUP_SUCCESS(context, txtname, *realm);
 
 errout:
-    if (ds != NULL) {
-        krb5int_dns_fini(ds);
-        ds = NULL;
-    }
+    krb5int_dns_fini(ds);
+    free(txtname);
     return retval;
 }
 
diff --git a/src/lib/krb5/os/dnsglue.h b/src/lib/krb5/os/dnsglue.h
index e784404..b5d054a 100644
--- a/src/lib/krb5/os/dnsglue.h
+++ b/src/lib/krb5/os/dnsglue.h
@@ -64,10 +64,6 @@
 #include <sys/param.h>          /* for MAXHOSTNAMELEN */
 #endif
 
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 64       /* if we can't find it elswhere */
-#endif
-
 #ifndef MAXDNAME
 
 #ifdef NS_MAXDNAME
@@ -159,24 +155,5 @@ int krb5int_dns_expand(struct krb5int_dns_state *,
                        const unsigned char *, char *, int);
 void krb5int_dns_fini(struct krb5int_dns_state *);
 
-struct srv_dns_entry {
-    struct srv_dns_entry *next;
-    int priority;
-    int weight;
-    unsigned short port;
-    char *host;
-};
-
-krb5_error_code
-krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
-                             const char *service, const char *protocol,
-                             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);
-
 #endif /* KRB5_DNS_LOOKUP */
 #endif /* !defined(KRB5_DNSGLUE_H) */
diff --git a/src/lib/krb5/os/dnssrv.c b/src/lib/krb5/os/dnssrv.c
index d66a8f9..ff14b56 100644
--- a/src/lib/krb5/os/dnssrv.c
+++ b/src/lib/krb5/os/dnssrv.c
@@ -45,18 +45,18 @@ krb5int_free_srv_dns_data (struct srv_dns_entry *p)
     }
 }
 
-/* Construct a DNS label of the form "service.[protocol.]realm.", placing the
- * result into fixed_buf.  protocol may be NULL. */
-static krb5_error_code
-prepare_lookup_buf(const krb5_data *realm, const char *service,
-                   const char *protocol, char *fixed_buf, size_t bufsize)
+/* Construct a DNS label of the form "service.[protocol.]realm.".  protocol may
+ * be NULL. */
+static char *
+make_lookup_name(const krb5_data *realm, const char *service,
+                 const char *protocol)
 {
     struct k5buf buf;
 
     if (memchr(realm->data, 0, realm->length))
-        return EINVAL;
+        return NULL;
 
-    k5_buf_init_fixed(&buf, fixed_buf, bufsize);
+    k5_buf_init_dynamic(&buf);
     k5_buf_add_fmt(&buf, "%s.", service);
     if (protocol != NULL)
         k5_buf_add_fmt(&buf, "%s.", protocol);
@@ -72,7 +72,7 @@ prepare_lookup_buf(const krb5_data *realm, const char *service,
     if (buf.len > 0 && ((char *)buf.data)[buf.len - 1] != '.')
         k5_buf_add(&buf, ".");
 
-    return k5_buf_status(&buf);
+    return buf.data;
 }
 
 /* Insert new into the list *head, ordering by priority.  Weight is not
@@ -108,7 +108,7 @@ k5_make_uri_query(krb5_context context, const krb5_data *realm,
                   const char *service, struct srv_dns_entry **answers)
 {
     const unsigned char *p = NULL, *base = NULL;
-    char host[MAXDNAME];
+    char *name = NULL;
     int size, ret, rdlen;
     unsigned short priority, weight;
     struct krb5int_dns_state *ds = NULL;
@@ -117,13 +117,13 @@ k5_make_uri_query(krb5_context context, const krb5_data *realm,
     *answers = NULL;
 
     /* Construct service.realm. */
-    ret = prepare_lookup_buf(realm, service, NULL, host, sizeof(host));
-    if (ret)
+    name = make_lookup_name(realm, service, NULL);
+    if (name == NULL)
         return 0;
 
-    TRACE_DNS_URI_SEND(context, host);
+    TRACE_DNS_URI_SEND(context, name);
 
-    size = krb5int_dns_init(&ds, host, C_IN, T_URI);
+    size = krb5int_dns_init(&ds, name, C_IN, T_URI);
     if (size < 0)
         goto out;
 
@@ -156,6 +156,7 @@ k5_make_uri_query(krb5_context context, const krb5_data *realm,
 
 out:
     krb5int_dns_fini(ds);
+    free(name);
     *answers = head;
     return 0;
 }
@@ -173,7 +174,7 @@ krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
                              struct srv_dns_entry **answers)
 {
     const unsigned char *p = NULL, *base = NULL;
-    char host[MAXDNAME];
+    char *name = NULL, host[MAXDNAME];
     int size, ret, rdlen, nlen;
     unsigned short priority, weight, port;
     struct krb5int_dns_state *ds = NULL;
@@ -190,13 +191,13 @@ krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
      *
      */
 
-    ret = prepare_lookup_buf(realm, service, protocol, host, sizeof(host));
-    if (ret)
+    name = make_lookup_name(realm, service, protocol);
+    if (name == NULL)
         return 0;
 
-    TRACE_DNS_SRV_SEND(context, host);
+    TRACE_DNS_SRV_SEND(context, name);
 
-    size = krb5int_dns_init(&ds, host, C_IN, T_SRV);
+    size = krb5int_dns_init(&ds, name, C_IN, T_SRV);
     if (size < 0)
         goto out;
 
@@ -246,6 +247,7 @@ krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
 
 out:
     krb5int_dns_fini(ds);
+    free(name);
     *answers = head;
     return 0;
 }
diff --git a/src/lib/krb5/os/hostrealm.c b/src/lib/krb5/os/hostrealm.c
index 78d6c5d..fcab360 100644
--- a/src/lib/krb5/os/hostrealm.c
+++ b/src/lib/krb5/os/hostrealm.c
@@ -254,13 +254,15 @@ translate_gai_error(int num)
 /* Get the canonical form of the local host name, using forward
  * canonicalization only. */
 krb5_error_code
-krb5int_get_fq_local_hostname(char *buf, size_t bufsize)
+krb5int_get_fq_local_hostname(char **hostname_out)
 {
     struct addrinfo *ai, hints;
+    char buf[MAXHOSTNAMELEN];
     int err;
 
-    buf[0] = '\0';
-    if (gethostname(buf, bufsize) == -1)
+    *hostname_out = NULL;
+
+    if (gethostname(buf, sizeof(buf)) == -1)
         return SOCKET_ERRNO;
 
     memset(&hints, 0, sizeof(hints));
@@ -272,26 +274,26 @@ krb5int_get_fq_local_hostname(char *buf, size_t bufsize)
         freeaddrinfo(ai);
         return KRB5_EAI_FAIL;
     }
-    if (strlcpy(buf, ai->ai_canonname, bufsize) >= bufsize)
-        return ENOMEM;
+    *hostname_out = strdup(ai->ai_canonname);
     freeaddrinfo(ai);
-    return 0;
+    return (*hostname_out == NULL) ? ENOMEM : 0;
 }
 
-krb5_error_code
-k5_clean_hostname(krb5_context context, const char *host, char *cleanname,
-                  size_t lhsize)
+static krb5_error_code
+clean_hostname(krb5_context context, const char *host, char **cleanname_out)
 {
-    char *p;
+    char *p, *cleanname;
     krb5_error_code ret;
     size_t l;
 
-    cleanname[0] = '\0';
+    *cleanname_out = NULL;
+
     if (host != NULL) {
-        if (strlcpy(cleanname, host, lhsize) >= lhsize)
+        cleanname = strdup(host);
+        if (cleanname == NULL)
             return ENOMEM;
     } else {
-        ret = krb5int_get_fq_local_hostname(cleanname, lhsize);
+        ret = krb5int_get_fq_local_hostname(&cleanname);
         if (ret)
             return ret;
     }
@@ -307,6 +309,7 @@ k5_clean_hostname(krb5_context context, const char *host, char *cleanname,
     if (l > 0 && cleanname[l - 1] == '.')
         cleanname[l - 1] = '\0';
 
+    *cleanname_out = cleanname;
     return 0;
 }
 
@@ -359,19 +362,19 @@ krb5_get_host_realm(krb5_context context, const char *host, char ***realms_out)
 {
     krb5_error_code ret;
     struct hostrealm_module_handle **hp;
-    char **realms, cleanname[1024];
+    char **realms, *cleanname = NULL;
 
     *realms_out = NULL;
 
     if (context->hostrealm_handles == NULL) {
         ret = load_hostrealm_modules(context);
         if (ret)
-            return ret;
+            goto cleanup;
     }
 
-    ret = k5_clean_hostname(context, host, cleanname, sizeof(cleanname));
+    ret = clean_hostname(context, host, &cleanname);
     if (ret)
-        return ret;
+        goto cleanup;
 
     /* Give each module a chance to determine the host's realms. */
     for (hp = context->hostrealm_handles; *hp != NULL; hp++) {
@@ -379,15 +382,19 @@ krb5_get_host_realm(krb5_context context, const char *host, char ***realms_out)
         if (ret == 0) {
             ret = copy_list(realms, realms_out);
             free_list(context, *hp, realms);
-            return ret;
+            goto cleanup;
         } else if (ret != KRB5_PLUGIN_NO_HANDLE) {
-            return ret;
+            goto cleanup;
         }
     }
 
     /* Return a list containing the "referral realm" (an empty realm), as a
      * cue to try referrals. */
-    return k5_make_realmlist(KRB5_REFERRAL_REALM, realms_out);
+    ret = k5_make_realmlist(KRB5_REFERRAL_REALM, realms_out);
+
+cleanup:
+    free(cleanname);
+    return ret;
 }
 
 krb5_error_code KRB5_CALLCONV
@@ -396,23 +403,23 @@ krb5_get_fallback_host_realm(krb5_context context, krb5_data *hdata,
 {
     krb5_error_code ret;
     struct hostrealm_module_handle **hp;
-    char **realms, *defrealm, *host, cleanname[1024];
+    char **realms, *defrealm, *host, *cleanname = NULL;
 
     *realms_out = NULL;
 
     /* Convert hdata into a string and clean it. */
     host = k5memdup0(hdata->data, hdata->length, &ret);
     if (host == NULL)
-        return ret;
-    ret = k5_clean_hostname(context, host, cleanname, sizeof(cleanname));
+        goto cleanup;
+    ret = clean_hostname(context, host, &cleanname);
     free(host);
     if (ret)
-        return ret;
+        goto cleanup;
 
     if (context->hostrealm_handles == NULL) {
         ret = load_hostrealm_modules(context);
         if (ret)
-            return ret;
+            goto cleanup;
     }
 
     /* Give each module a chance to determine the fallback realms. */
@@ -421,18 +428,21 @@ krb5_get_fallback_host_realm(krb5_context context, krb5_data *hdata,
         if (ret == 0) {
             ret = copy_list(realms, realms_out);
             free_list(context, *hp, realms);
-            return ret;
+            goto cleanup;
         } else if (ret != KRB5_PLUGIN_NO_HANDLE) {
-            return ret;
+            goto cleanup;
         }
     }
 
     /* Return a list containing the default realm. */
     ret = krb5_get_default_realm(context, &defrealm);
     if (ret)
-        return ret;
+        goto cleanup;
     ret = k5_make_realmlist(defrealm, realms_out);
     krb5_free_default_realm(context, defrealm);
+
+cleanup:
+    free(cleanname);
     return ret;
 }
 
diff --git a/src/lib/krb5/os/hostrealm_dns.c b/src/lib/krb5/os/hostrealm_dns.c
index 7f017a8..a55a12c 100644
--- a/src/lib/krb5/os/hostrealm_dns.c
+++ b/src/lib/krb5/os/hostrealm_dns.c
@@ -41,7 +41,6 @@
 #include <krb5/hostrealm_plugin.h>
 
 #ifdef KRB5_DNS_LOOKUP
-#include "dnsglue.h"
 
 /* Try a _kerberos TXT lookup for fqdn and each parent domain; return the
  * resulting realm (caller must free) or NULL. */
@@ -85,19 +84,20 @@ dns_default_realm(krb5_context context, krb5_hostrealm_moddata data,
                   char ***realms_out)
 {
     krb5_error_code ret;
-    char localhost[MAXDNAME + 1], *realm;
+    char *localhost, *realm;
 
     *realms_out = NULL;
     if (!_krb5_use_dns_realm(context))
         return KRB5_PLUGIN_NO_HANDLE;
 
-    ret = krb5int_get_fq_local_hostname(localhost, sizeof(localhost));
+    ret = krb5int_get_fq_local_hostname(&localhost);
     if (ret)
         return ret;
 
     /* If we don't find a TXT record for localhost or any parent, look for a
      * global record. */
     realm = txt_lookup(context, localhost);
+    free(localhost);
     if (realm == NULL)
         (void)k5_try_realm_txt_rr(context, "_kerberos", NULL, &realm);
 
diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
index b9edecc..c32a967 100644
--- a/src/lib/krb5/os/locate_kdc.c
+++ b/src/lib/krb5/os/locate_kdc.c
@@ -27,17 +27,8 @@
 #include "k5-int.h"
 #include "fake-addrinfo.h"
 #include "os-proto.h"
+
 #ifdef KRB5_DNS_LOOKUP
-#ifdef WSHELPER
-#include <wshelper.h>
-#else /* WSHELPER */
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <netdb.h>
-#endif /* WSHELPER */
-#include "dnsglue.h"
 
 #define DEFAULT_LOOKUP_KDC 1
 #if KRB5_DNS_LOOKUP_REALM
diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h
index 7cf5a48..634e82d 100644
--- a/src/lib/krb5/os/os-proto.h
+++ b/src/lib/krb5/os/os-proto.h
@@ -110,6 +110,25 @@ krb5_error_code krb5_make_full_ipaddr(krb5_context,
 
 #endif /* HAVE_NETINET_IN_H */
 
+struct srv_dns_entry {
+    struct srv_dns_entry *next;
+    int priority;
+    int weight;
+    unsigned short port;
+    char *host;
+};
+
+krb5_error_code
+krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
+                             const char *service, const char *protocol,
+                             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);
+
 krb5_error_code k5_try_realm_txt_rr(krb5_context context, const char *prefix,
                                     const char *name, char **realm);
 
@@ -128,7 +147,7 @@ krb5_error_code k5_sendto(krb5_context context, const krb5_data *message,
                                              void *),
                           void *msg_handler_data);
 
-krb5_error_code krb5int_get_fq_local_hostname(char *, size_t);
+krb5_error_code krb5int_get_fq_local_hostname(char **);
 
 /* The io vector is *not* const here, unlike writev()!  */
 int krb5int_net_writev (krb5_context, int, sg_buf *, int);
@@ -152,7 +171,6 @@ krb5_error_code k5_time_with_offset(krb5_timestamp offset,
                                     krb5_timestamp *time_out,
                                     krb5_int32 *usec_out);
 void k5_set_prompt_types(krb5_context, krb5_prompt_type *);
-krb5_error_code k5_clean_hostname(krb5_context, const char *, char *, size_t);
 krb5_boolean k5_is_numeric_address(const char *name);
 krb5_error_code k5_make_realmlist(const char *realm, char ***realms_out);
 krb5_error_code k5_kt_client_default_name(krb5_context context,


More information about the cvs-krb5 mailing list