summaryrefslogtreecommitdiffstats
path: root/0002-Add-helper-to-determine-if-a-KDC-is-the-master.patch
diff options
context:
space:
mode:
Diffstat (limited to '0002-Add-helper-to-determine-if-a-KDC-is-the-master.patch')
-rw-r--r--0002-Add-helper-to-determine-if-a-KDC-is-the-master.patch233
1 files changed, 233 insertions, 0 deletions
diff --git a/0002-Add-helper-to-determine-if-a-KDC-is-the-master.patch b/0002-Add-helper-to-determine-if-a-KDC-is-the-master.patch
new file mode 100644
index 0000000..50ae55b
--- /dev/null
+++ b/0002-Add-helper-to-determine-if-a-KDC-is-the-master.patch
@@ -0,0 +1,233 @@
+From f4b1a7e7b80ce68e57912edcd48c39ea62c73e43 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sun, 6 Apr 2014 18:06:14 -0400
+Subject: [PATCH 02/13] Add helper to determine if a KDC is the master
+
+Add a new function k5_kdc_is_master in locate_kdc.c to determine
+whether a KDC matches one of the masters, and use it in
+krb5_sendto_kdc.
+---
+ src/lib/krb5/os/locate_kdc.c | 110 +++++++++++++++++++++++++++++--------------
+ src/lib/krb5/os/os-proto.h | 3 ++
+ src/lib/krb5/os/sendto_kdc.c | 31 +-----------
+ 3 files changed, 80 insertions(+), 64 deletions(-)
+
+diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
+index 88d55a8..4479465 100644
+--- a/src/lib/krb5/os/locate_kdc.c
++++ b/src/lib/krb5/os/locate_kdc.c
+@@ -166,6 +166,24 @@ add_host_to_list(struct serverlist *list, const char *hostname, int port,
+ return 0;
+ }
+
++/* Return true if server is identical to an entry in list. */
++static krb5_boolean
++server_list_contains(struct serverlist *list, struct server_entry *server)
++{
++ struct server_entry *ent;
++
++ for (ent = list->servers; ent < list->servers + list->nservers; ent++) {
++ if (server->hostname != NULL && ent->hostname != NULL &&
++ strcmp(server->hostname, ent->hostname) == 0)
++ return TRUE;
++ if (server->hostname == NULL && ent->hostname == NULL &&
++ server->addrlen == ent->addrlen &&
++ memcmp(&server->addr, &ent->addr, server->addrlen) == 0)
++ return TRUE;
++ }
++ return FALSE;
++}
++
+ static krb5_error_code
+ locate_srv_conf_1(krb5_context context, const krb5_data *realm,
+ const char * name, struct serverlist *serverlist,
+@@ -529,6 +547,41 @@ dns_locate_server(krb5_context context, const krb5_data *realm,
+ }
+ #endif /* KRB5_DNS_LOOKUP */
+
++static krb5_error_code
++locate_server(krb5_context context, const krb5_data *realm,
++ struct serverlist *serverlist, enum locate_service_type svc,
++ int socktype)
++{
++ krb5_error_code ret;
++ struct serverlist list = SERVERLIST_INIT;
++
++ *serverlist = list;
++
++ /* Try modules. If a module returns 0 but leaves the list empty, return an
++ * empty list. */
++ ret = module_locate_server(context, realm, &list, svc, socktype);
++ if (ret != KRB5_PLUGIN_NO_HANDLE)
++ goto done;
++
++ /* Try the profile. Fall back to DNS if it returns an empty list. */
++ ret = prof_locate_server(context, realm, &list, svc, socktype);
++ if (ret)
++ goto done;
++
++#ifdef KRB5_DNS_LOOKUP
++ if (list.nservers == 0)
++ ret = dns_locate_server(context, realm, &list, svc, socktype);
++#endif
++
++done:
++ if (ret) {
++ k5_free_serverlist(&list);
++ return ret;
++ }
++ *serverlist = list;
++ return 0;
++}
++
+ /*
+ * Wrapper function for the various backends
+ */
+@@ -538,54 +591,26 @@ k5_locate_server(krb5_context context, const krb5_data *realm,
+ struct serverlist *serverlist, enum locate_service_type svc,
+ int socktype)
+ {
+- krb5_error_code code;
+- struct serverlist al = SERVERLIST_INIT;
+-
+- *serverlist = al;
++ krb5_error_code ret;
+
++ memset(serverlist, 0, sizeof(*serverlist));
+ if (realm == NULL || realm->data == NULL || realm->data[0] == 0) {
+ krb5_set_error_message(context, KRB5_REALM_CANT_RESOLVE,
+ "Cannot find KDC for invalid realm name \"\"");
+ return KRB5_REALM_CANT_RESOLVE;
+ }
+
+- code = module_locate_server(context, realm, &al, svc, socktype);
+- Tprintf("module_locate_server returns %d\n", code);
+- if (code == KRB5_PLUGIN_NO_HANDLE) {
+- /*
+- * We always try the local file before DNS. Note that there
+- * is no way to indicate "service not available" via the
+- * config file.
+- */
+-
+- code = prof_locate_server(context, realm, &al, svc, socktype);
+-
+-#ifdef KRB5_DNS_LOOKUP
+- if (code == 0 && al.nservers == 0)
+- code = dns_locate_server(context, realm, &al, svc, socktype);
+-#endif /* KRB5_DNS_LOOKUP */
++ ret = locate_server(context, realm, serverlist, svc, socktype);
++ if (ret)
++ return ret;
+
+- /* We could put more heuristics here, like looking up a hostname
+- of "kerberos."+REALM, etc. */
+- }
+- if (code == 0)
+- Tprintf ("krb5int_locate_server found %d addresses\n",
+- al.nservers);
+- else
+- Tprintf ("krb5int_locate_server returning error code %d/%s\n",
+- code, error_message(code));
+- if (code != 0) {
+- k5_free_serverlist(&al);
+- return code;
+- }
+- if (al.nservers == 0) { /* No good servers */
+- k5_free_serverlist(&al);
++ if (serverlist->nservers == 0) {
++ k5_free_serverlist(serverlist);
+ krb5_set_error_message(context, KRB5_REALM_UNKNOWN,
+ _("Cannot find KDC for realm \"%.*s\""),
+ realm->length, realm->data);
+ return KRB5_REALM_UNKNOWN;
+ }
+- *serverlist = al;
+ return 0;
+ }
+
+@@ -598,3 +623,18 @@ k5_locate_kdc(krb5_context context, const krb5_data *realm,
+ stype = get_masters ? locate_service_master_kdc : locate_service_kdc;
+ return k5_locate_server(context, realm, serverlist, stype, socktype);
+ }
++
++krb5_boolean
++k5_kdc_is_master(krb5_context context, const krb5_data *realm,
++ struct server_entry *server)
++{
++ struct serverlist list;
++ krb5_boolean found;
++
++ if (locate_server(context, realm, &list, locate_service_master_kdc,
++ server->socktype) != 0)
++ return FALSE;
++ found = server_list_contains(&list, server);
++ k5_free_serverlist(&list);
++ return found;
++}
+diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h
+index c6b730f..9125ba0 100644
+--- a/src/lib/krb5/os/os-proto.h
++++ b/src/lib/krb5/os/os-proto.h
+@@ -76,6 +76,9 @@ krb5_error_code k5_locate_kdc(krb5_context context, const krb5_data *realm,
+ struct serverlist *serverlist, int get_masters,
+ int socktype);
+
++krb5_boolean k5_kdc_is_master(krb5_context context, const krb5_data *realm,
++ struct server_entry *server);
++
+ void k5_free_serverlist(struct serverlist *);
+
+ #ifdef HAVE_NETINET_IN_H
+diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
+index 5f781d3..e3855a3 100644
+--- a/src/lib/krb5/os/sendto_kdc.c
++++ b/src/lib/krb5/os/sendto_kdc.c
+@@ -293,25 +293,6 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime,
+ }
+
+ static int
+-in_addrlist(struct server_entry *entry, struct serverlist *list)
+-{
+- size_t i;
+- struct server_entry *le;
+-
+- for (i = 0; i < list->nservers; i++) {
+- le = &list->servers[i];
+- if (entry->hostname != NULL && le->hostname != NULL &&
+- strcmp(entry->hostname, le->hostname) == 0)
+- return 1;
+- if (entry->hostname == NULL && le->hostname == NULL &&
+- entry->addrlen == le->addrlen &&
+- memcmp(&entry->addr, &le->addr, entry->addrlen) == 0)
+- return 1;
+- }
+- return 0;
+-}
+-
+-static int
+ check_for_svc_unavailable (krb5_context context,
+ const krb5_data *reply,
+ void *msg_handler_data)
+@@ -418,17 +399,9 @@ krb5_sendto_kdc(krb5_context context, const krb5_data *message,
+ /* Set use_master to 1 if we ended up talking to a master when we didn't
+ * explicitly request to. */
+ if (*use_master == 0) {
+- struct serverlist mservers;
+- struct server_entry *entry = &servers.servers[server_used];
+- retval = k5_locate_kdc(context, realm, &mservers, TRUE,
+- entry->socktype);
+- if (retval == 0) {
+- if (in_addrlist(entry, &mservers))
+- *use_master = 1;
+- k5_free_serverlist(&mservers);
+- }
++ *use_master = k5_kdc_is_master(context, realm,
++ &servers.servers[server_used]);
+ TRACE_SENDTO_KDC_MASTER(context, *use_master);
+- retval = 0;
+ }
+
+ cleanup:
+--
+2.1.0
+