From: Greg Hudson Date: Sun, 3 Jun 2018 20:41:18 +0000 (-0400) Subject: Stop using wshelper for SRV/TXT lookups X-Git-Tag: krb5-1.17-beta1~103 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=67de45e349912caccfba73aff6ebda111281e819;p=thirdparty%2Fkrb5.git Stop using wshelper for SRV/TXT lookups Add Windows-specific versions of k5_try_realm_txt_rr(), k5_make_uri_query(), and krb5int_make_srv_query_realm(), bypassing wshelper and using DnsQuery_UTF8() directly. Windows does not currently know how to decode URI records and has no interface to allow the caller to do so, so disable URI lookups on Windows for now. Add a comment that dnsglue.h is not used on Windows (since DnsQuery parses out and decodes SRV and TXT records for us), and remove the header conditionals from it. ticket: 8687 --- diff --git a/src/config/win-pre.in b/src/config/win-pre.in index 8190415897..384868f3b4 100644 --- a/src/config/win-pre.in +++ b/src/config/win-pre.in @@ -88,25 +88,8 @@ C=.^\ srcdir = . top_srcdir = $(srcdir)\$(BUILDTOP) -DNS_LIB=$(BUILDTOP)\util\wshelper\$(OUTPRE)$(DLIB).lib -DNS_INC=$(BUILDTOP)\windows\include - -!if defined(KRB5_NO_WSHELPER) -DNSMSG=resolver -!else -DNSMSG=wshelper -DNSFLAGS=-DWSHELPER=1 -!endif -!if !defined(DNS_INC) -!message Must define DNS_INC to point to $(DNSMSG) includes dir! -!error -!endif -!if !defined(DNS_LIB) -!message Must define DNS_LIB to point to $(DNSMSG) library! -!error -!endif -DNSLIBS=$(DNS_LIB) -DNSFLAGS=-I$(DNS_INC) $(DNSFLAGS) -DKRB5_DNS_LOOKUP=1 +DNSLIBS=dnsapi.lib +DNSFLAGS=-DKRB5_DNS_LOOKUP=1 !if defined(KRB5_USE_DNS_REALMS) DNSFLAGS=$(DNSFLAGS) -DKRB5_DNS_LOOKUP_REALM=1 !endif diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in index 7f50b7d666..681718420a 100644 --- a/src/lib/Makefile.in +++ b/src/lib/Makefile.in @@ -118,7 +118,7 @@ clean-windows:: ##WIN32## $(PLIBS) $(PGLUE) $(PRES) $(CLIB) $(SLIB) $(WINLIBS) ##WIN32## $(_VC_MANIFEST_EMBED_DLL) -##WIN32##$(KLIB): $(KDEF) $(KLIBS) $(KGLUE) $(KRES) $(CLIB) $(SLIB) $(MITLIBS) $(DNSLIBS) +##WIN32##$(KLIB): $(KDEF) $(KLIBS) $(KGLUE) $(KRES) $(CLIB) $(SLIB) $(MITLIBS) ##WIN32## link $(WINDLLFLAGS) -def:$(KDEF) -out:$*.dll \ ##WIN32## $(KLIBS) $(KGLUE) $(KRES) $(CLIB) $(SLIB) $(MITLIBS) $(DNSLIBS) $(WINLIBS) ##WIN32## $(_VC_MANIFEST_EMBED_DLL) diff --git a/src/lib/krb5/os/dnsglue.c b/src/lib/krb5/os/dnsglue.c index 86138c478b..59ff929638 100644 --- a/src/lib/krb5/os/dnsglue.c +++ b/src/lib/krb5/os/dnsglue.c @@ -24,9 +24,13 @@ * or implied warranty. */ -#include "autoconf.h" +#include "k5-int.h" +#include "os-proto.h" + #ifdef KRB5_DNS_LOOKUP +#ifndef _WIN32 + #include "dnsglue.h" #ifdef __APPLE__ #include @@ -352,12 +356,85 @@ out: return -1; } -#endif +#endif /* !HAVE_NS_INITPARSE */ +#endif /* not _WIN32 */ + +/* Construct a DNS label of the form "prefix[.name.]". name may be NULL. */ +static char * +txt_lookup_name(const char *prefix, const char *name) +{ + struct k5buf buf; + + k5_buf_init_dynamic(&buf); + + if (name == NULL || name[0] == '\0') { + k5_buf_add(&buf, prefix); + } else { + 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 resolv code will + * try appending the local domain. Since the realm names are + * absolutes, let's stop that. + * + * But only if a name has been specified. If we are performing a + * search on the prefix alone then the intention is to allow the local + * domain or domain search lists to be expanded. + */ + + if (buf.len > 0 && ((char *)buf.data)[buf.len - 1] != '.') + k5_buf_add(&buf, "."); + } + + return buf.data; +} /* * Try to look up a TXT record pointing to a Kerberos realm */ +#ifdef _WIN32 + +#include + +krb5_error_code +k5_try_realm_txt_rr(krb5_context context, const char *prefix, const char *name, + char **realm) +{ + krb5_error_code ret = 0; + char *txtname = NULL; + PDNS_RECORD rr = NULL; + DNS_STATUS st; + + *realm = NULL; + + txtname = txt_lookup_name(prefix, name); + if (txtname == NULL) + return ENOMEM; + + st = DnsQuery_UTF8(txtname, DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, + &rr, NULL); + if (st != ERROR_SUCCESS || rr == NULL) { + TRACE_TXT_LOOKUP_NOTFOUND(context, txtname); + ret = KRB5_ERR_HOST_REALM_UNKNOWN; + goto cleanup; + } + + *realm = strdup(rr->Data.TXT.pStringArray[0]); + if (*realm == NULL) + ret = ENOMEM; + TRACE_TXT_LOOKUP_SUCCESS(context, txtname, *realm); + +cleanup: + free(txtname); + if (rr != NULL) + DnsRecordListFree(rr, DnsFreeRecordList); + return ret; +} + +#else /* _WIN32 */ + krb5_error_code k5_try_realm_txt_rr(krb5_context context, const char *prefix, const char *name, char **realm) @@ -367,34 +444,14 @@ k5_try_realm_txt_rr(krb5_context context, const char *prefix, const char *name, char *txtname = NULL; int ret, rdlen, len; struct krb5int_dns_state *ds = NULL; - struct k5buf buf; /* * Form our query, and send it via DNS */ - k5_buf_init_dynamic(&buf); - if (name == NULL || name[0] == '\0') { - k5_buf_add(&buf, prefix); - } else { - 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 - resolv code will try appending the local domain. Since the - realm names are absolutes, let's stop that. - - But only if a name has been specified. If we are performing - a search on the prefix alone then the intention is to allow - the local domain or domain search lists to be expanded. - */ - - 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; - txtname = buf.data; + txtname = txt_lookup_name(prefix, name); + if (txtname == NULL) + return ENOMEM; ret = krb5int_dns_init(&ds, txtname, C_IN, T_TXT); if (ret < 0) { TRACE_TXT_LOOKUP_NOTFOUND(context, txtname); @@ -428,4 +485,5 @@ errout: return retval; } +#endif /* not _WIN32 */ #endif /* KRB5_DNS_LOOKUP */ diff --git a/src/lib/krb5/os/dnsglue.h b/src/lib/krb5/os/dnsglue.h index b5d054ac0f..9e98735249 100644 --- a/src/lib/krb5/os/dnsglue.h +++ b/src/lib/krb5/os/dnsglue.h @@ -26,7 +26,8 @@ /* * Glue layer for DNS resolver, to make parsing of replies easier - * whether we are using BIND 4, 8, or 9. + * whether we are using BIND 4, 8, or 9. This header is not used on + * Windows. */ /* @@ -50,15 +51,11 @@ #include "k5-int.h" #include "os-proto.h" -#ifdef WSHELPER -#include -#else /* WSHELPER */ #include #include #include #include #include -#endif /* WSHELPER */ #if HAVE_SYS_PARAM_H #include /* for MAXHOSTNAMELEN */ diff --git a/src/lib/krb5/os/dnssrv.c b/src/lib/krb5/os/dnssrv.c index ff14b56a56..02ba879559 100644 --- a/src/lib/krb5/os/dnssrv.c +++ b/src/lib/krb5/os/dnssrv.c @@ -26,8 +26,8 @@ #include "autoconf.h" #ifdef KRB5_DNS_LOOKUP - -#include "dnsglue.h" +#include "k5-int.h" +#include "os-proto.h" /* * Lookup a KDC via DNS SRV records @@ -102,6 +102,77 @@ place_srv_entry(struct srv_dns_entry **head, struct srv_dns_entry *new) } } +#ifdef _WIN32 + +#include + +krb5_error_code +k5_make_uri_query(krb5_context context, const krb5_data *realm, + const char *service, struct srv_dns_entry **answers) +{ + /* Windows does not currently support the URI record type or make it + * possible to query for a record type it does not have support for. */ + *answers = NULL; + return 0; +} + +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) +{ + char *name = NULL; + DNS_STATUS st; + PDNS_RECORD records, rr; + struct srv_dns_entry *head = NULL, *srv = NULL; + + *answers = NULL; + + name = make_lookup_name(realm, service, protocol); + if (name == NULL) + return 0; + + TRACE_DNS_SRV_SEND(context, name); + + st = DnsQuery_UTF8(name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &records, + NULL); + if (st != ERROR_SUCCESS) + return 0; + + for (rr = records; rr != NULL; rr = rr->pNext) { + if (rr->wType != DNS_TYPE_SRV) + continue; + + srv = malloc(sizeof(struct srv_dns_entry)); + if (srv == NULL) + goto cleanup; + + srv->priority = rr->Data.SRV.wPriority; + srv->weight = rr->Data.SRV.wWeight; + srv->port = rr->Data.SRV.wPort; + /* Make sure the name looks fully qualified to the resolver. */ + if (asprintf(&srv->host, "%s.", rr->Data.SRV.pNameTarget) < 0) { + free(srv); + goto cleanup; + } + + TRACE_DNS_SRV_ANS(context, srv->host, srv->port, srv->priority, + srv->weight); + place_srv_entry(&head, srv); + } + +cleanup: + free(name); + if (records != NULL) + DnsRecordListFree(records, DnsFreeRecordList); + *answers = head; + return 0; +} + +#else /* _WIN32 */ + +#include "dnsglue.h" + /* Query the URI RR, collecting weight, priority, and target. */ krb5_error_code k5_make_uri_query(krb5_context context, const krb5_data *realm, @@ -251,4 +322,6 @@ out: *answers = head; return 0; } -#endif + +#endif /* not _WIN32 */ +#endif /* KRB5_DNS_LOOKUP */