Imported Upstream version 1.15.1
[platform/upstream/krb5.git] / src / lib / krb5 / os / dnsglue.c
index 6d11896..1a259b3 100644 (file)
@@ -28,6 +28,9 @@
 #ifdef KRB5_DNS_LOOKUP
 
 #include "dnsglue.h"
+#ifdef __APPLE__
+#include <dns.h>
+#endif
 
 /*
  * Only use res_ninit() if there's also a res_ndestroy(), to avoid
@@ -37,9 +40,6 @@
  * In any case, it is probable that platforms having broken
  * res_ninit() will have thread safety hacks for res_init() and _res.
  */
-#if HAVE_RES_NINIT && HAVE_RES_NDESTROY && HAVE_RES_NSEARCH
-#define USE_RES_NINIT 1
-#endif
 
 /*
  * Opaque handle
@@ -64,6 +64,44 @@ static int initparse(struct krb5int_dns_state *);
 #endif
 
 /*
+ * Define macros to use the best available DNS search functions.  INIT_HANDLE()
+ * returns true if handle initialization is successful, false if it is not.
+ * SEARCH() returns the length of the response or -1 on error.
+ * DECLARE_HANDLE() must be used last in the declaration list since it may
+ * evaluate to nothing.
+ */
+
+#if defined(__APPLE__)
+
+/* Use the OS X interfaces dns_open, dns_search, and dns_free. */
+#define DECLARE_HANDLE(h) dns_handle_t h
+#define INIT_HANDLE(h) ((h = dns_open(NULL)) != NULL)
+#define SEARCH(h, n, c, t, a, l) dns_search(h, n, c, t, a, l, NULL, NULL)
+#define DESTROY_HANDLE(h) dns_free(h)
+
+#elif HAVE_RES_NINIT && HAVE_RES_NSEARCH
+
+/* Use res_ninit, res_nsearch, and res_ndestroy or res_nclose. */
+#define DECLARE_HANDLE(h) struct __res_state h
+#define INIT_HANDLE(h) (memset(&h, 0, sizeof(h)), res_ninit(&h) == 0)
+#define SEARCH(h, n, c, t, a, l) res_nsearch(&h, n, c, t, a, l)
+#if HAVE_RES_NDESTROY
+#define DESTROY_HANDLE(h) res_ndestroy(&h)
+#else
+#define DESTROY_HANDLE(h) res_nclose(&h)
+#endif
+
+#else
+
+/* Use res_init and res_search. */
+#define DECLARE_HANDLE(h)
+#define INIT_HANDLE(h) (res_init() == 0)
+#define SEARCH(h, n, c, t, a, l) res_search(n, c, t, a, l)
+#define DESTROY_HANDLE(h)
+
+#endif
+
+/*
  * krb5int_dns_init()
  *
  * Initialize an opaque handle.  Do name lookup and initial parsing of
@@ -74,13 +112,11 @@ int
 krb5int_dns_init(struct krb5int_dns_state **dsp,
                  char *host, int nclass, int ntype)
 {
-#if USE_RES_NINIT
-    struct __res_state statbuf;
-#endif
     struct krb5int_dns_state *ds;
     int len, ret;
     size_t nextincr, maxincr;
     unsigned char *p;
+    DECLARE_HANDLE(h);
 
     *dsp = ds = malloc(sizeof(*ds));
     if (ds == NULL)
@@ -92,20 +128,14 @@ krb5int_dns_init(struct krb5int_dns_state **dsp,
     ds->ansp = NULL;
     ds->anslen = 0;
     ds->ansmax = 0;
-    nextincr = 2048;
+    nextincr = 4096;
     maxincr = INT_MAX;
 
 #if HAVE_NS_INITPARSE
     ds->cur_ans = 0;
 #endif
 
-#if USE_RES_NINIT
-    memset(&statbuf, 0, sizeof(statbuf));
-    ret = res_ninit(&statbuf);
-#else
-    ret = res_init();
-#endif
-    if (ret < 0)
+    if (!INIT_HANDLE(h))
         return -1;
 
     do {
@@ -119,13 +149,7 @@ krb5int_dns_init(struct krb5int_dns_state **dsp,
         ds->ansp = p;
         ds->ansmax = nextincr;
 
-#if USE_RES_NINIT
-        len = res_nsearch(&statbuf, host, ds->nclass, ds->ntype,
-                          ds->ansp, ds->ansmax);
-#else
-        len = res_search(host, ds->nclass, ds->ntype,
-                         ds->ansp, ds->ansmax);
-#endif
+        len = SEARCH(h, host, ds->nclass, ds->ntype, ds->ansp, ds->ansmax);
         if ((size_t) len > maxincr) {
             ret = -1;
             goto errout;
@@ -150,9 +174,7 @@ krb5int_dns_init(struct krb5int_dns_state **dsp,
     ret = 0;
 
 errout:
-#if USE_RES_NINIT
-    res_ndestroy(&statbuf);
-#endif
+    DESTROY_HANDLE(h);
     if (ret < 0) {
         if (ds->ansp != NULL) {
             free(ds->ansp);
@@ -337,7 +359,8 @@ out:
  */
 
 krb5_error_code
-krb5_try_realm_txt_rr(const char *prefix, const char *name, char **realm)
+k5_try_realm_txt_rr(krb5_context context, const char *prefix, const char *name,
+                    char **realm)
 {
     krb5_error_code retval = KRB5_ERR_HOST_REALM_UNKNOWN;
     const unsigned char *p, *base;
@@ -350,11 +373,11 @@ krb5_try_realm_txt_rr(const char *prefix, const char *name, char **realm)
      * Form our query, and send it via DNS
      */
 
-    krb5int_buf_init_fixed(&buf, host, sizeof(host));
+    k5_buf_init_fixed(&buf, host, sizeof(host));
     if (name == NULL || name[0] == '\0') {
-        krb5int_buf_add(&buf, prefix);
+        k5_buf_add(&buf, prefix);
     } else {
-        krb5int_buf_add_fmt(&buf, "%s.%s", prefix, name);
+        k5_buf_add_fmt(&buf, "%s.%s", prefix, name);
 
         /* Realm names don't (normally) end with ".", but if the query
            doesn't end with "." and doesn't get an answer as is, the
@@ -366,15 +389,16 @@ krb5_try_realm_txt_rr(const char *prefix, const char *name, char **realm)
            the local domain or domain search lists to be expanded.
         */
 
-        len = krb5int_buf_len(&buf);
-        if (len > 0 && host[len - 1] != '.')
-            krb5int_buf_add(&buf, ".");
+        if (buf.len > 0 && host[buf.len - 1] != '.')
+            k5_buf_add(&buf, ".");
     }
-    if (krb5int_buf_data(&buf) == NULL)
+    if (k5_buf_status(&buf) != 0)
         return KRB5_ERR_HOST_REALM_UNKNOWN;
     ret = krb5int_dns_init(&ds, host, C_IN, T_TXT);
-    if (ret < 0)
+    if (ret < 0) {
+        TRACE_TXT_LOOKUP_NOTFOUND(context, host);
         goto errout;
+    }
 
     ret = krb5int_dns_nextans(ds, &base, &rdlen);
     if (ret < 0 || base == NULL)
@@ -395,6 +419,7 @@ krb5_try_realm_txt_rr(const char *prefix, const char *name, char **realm)
     if ( (*realm)[len-1] == '.' )
         (*realm)[len-1] = '\0';
     retval = 0;
+    TRACE_TXT_LOOKUP_SUCCESS(context, host, *realm);
 
 errout:
     if (ds != NULL) {