From 888bc144da94c9bf8d2c35ab38868e748c059de3 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Fri, 5 Sep 2014 17:51:35 -0400 Subject: Add HTTPS patches from master Pull in a stack of patches to add support for accessing servers via HTTPS proxies, such as python-kdcproxy or the KDC Proxy Service on a properly-outfitted Windows box. Pull in the patch to move the logic out of libkrb5 proper and into a loadable plugin to avoid linking our local applications against our libkrb5 against libssl against the installed copy of libgssapi_krb5 and our local libkrb5support. Adjust a couple of other patches to apply correctly after them. --- ...elper-to-determine-if-a-KDC-is-the-master.patch | 233 +++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 0002-Add-helper-to-determine-if-a-KDC-is-the-master.patch (limited to '0002-Add-helper-to-determine-if-a-KDC-is-the-master.patch') 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 +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 + -- cgit