From eb5bf3c2a5d619da31f491419ddb8b97096b4981 Mon Sep 17 00:00:00 2001 From: Karl Ramm Date: Mon, 29 Dec 2008 08:27:51 +0000 Subject: Attempt to compensate for mit krb5_get_realm_host_host stupidity. --- lib/ZInit.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) (limited to 'lib/ZInit.c') diff --git a/lib/ZInit.c b/lib/ZInit.c index 8f64257..dc3b418 100644 --- a/lib/ZInit.c +++ b/lib/ZInit.c @@ -32,6 +32,12 @@ static const char rcsid_ZInitialize_c[] = #define INADDR_NONE 0xffffffff #endif +#if defined(HAVE_KRB5) && defined(KRB5_REFERRAL_REALM) +#include + +int z_get_host_realm_replacement(char *, char ***); +#endif + Code_t ZInitialize(void) { @@ -107,9 +113,13 @@ ZInitialize(void) be made smarter, and probably per-message */ #ifdef HAVE_KRB5 +#ifndef KRB5_REFERRAL_REALM code = krb5_get_host_realm(Z_krb5_ctx, notice.z_message, &krealms); if (code) return(code); +#else + code = z_get_host_realm_replacement(notice.z_message, &krealms); +#endif #else #ifdef HAVE_KRB4 krealm = krb_realmofhost(notice.z_message); @@ -210,3 +220,201 @@ struct sockaddr_in ZGetDestAddr (void) { return __HM_addr; } +#if defined(HAVE_KRB5) && defined(KRB5_REFERRAL_REALM) +#include +#include +#include +#include + +static int txt_lookup(char *qname, char **result) { + int ret, buflen, left; + void *buf = NULL; + HEADER *hdr; + unsigned char *p; + char dname[MAXDNAME]; + int queries, answers, stored; + + ret = res_init(); + if (ret < 0) + return -1; + + buflen = 0; + do { + buflen = buflen ? buflen * 2 : 2048; + buf = (buf == NULL) ? malloc(buflen) : realloc(buf, buflen); + + ret = res_search(qname, C_IN, T_TXT, buf, buflen); + } while (ret > buflen); + + if (ret < 0) + return -1; + + buflen = ret; + left = ret; + + hdr = (HEADER *)buf; + p = buf; + queries = ntohs(hdr->qdcount); + answers = ntohs(hdr->ancount); + p += sizeof (HEADER); + left -= sizeof (HEADER); + + while (queries--) { + ret = dn_expand(buf, buf + buflen, p, dname, sizeof dname); + if (ret < 0 || (ret + 4) > left) + return -1; + p += ret + 4; + left -= ret + 4; + } + + if (!ret || !answers) + return -1; + + stored = 0; + while (answers--) { + int class, type; + + ret = dn_expand(buf, buf + buflen, p, dname, sizeof dname); + if (ret < 0 || ret > left) + return -1; + p += ret; + left -= ret; + + if (left < 10) + return -1; + type = ntohs(*(u_int16_t *)p); + p += 2; + class = ntohs(*(u_int16_t *)p); + p += 6; + ret = ntohs(*(u_int16_t *)p); + p += 2; + left -= 10; + + if (ret > left) + return -1; + + if (class == C_IN && type == T_TXT) { + *result = malloc(ret); + if (*result == NULL) + return -1; + memcpy(*result, p + 1, ret - 1); + (*result)[ret - 1] = 0; + return 0; + } + + p += ret; + } + return -1; +} + +int z_get_host_realm_replacement(char *inhost, char ***krealms) { + char *host, *p; + char *realm = NULL; + char *default_realm = NULL; + char *tmp_realm; + char *qname; + profile_t prof; + int ret; + + host = strdup(inhost); + + for (p = host; *p; p++) + if (isupper(*p)) + *p = tolower(*p); + + p = host; + while (p && !default_realm) { + if (*p == '.') { + p++; + if (default_realm == NULL) { + default_realm = p; + } + } else { + p = strchr(p, '.'); + } + } + + p = host; + tmp_realm = NULL; + + krb5_get_profile(Z_krb5_ctx, &prof); + while(p) { + ret = profile_get_string(prof, "domain_realm", p, + 0, NULL, &tmp_realm); + if (ret) { + profile_abandon(prof); + free(host); + return ret; + } + + if (tmp_realm != NULL) + break; + + if (*p == '.') + p++; + else + p = strchr(p, '.'); + } + + if (tmp_realm != NULL) { + realm = strdup(tmp_realm); + profile_release_string(tmp_realm); + if (realm == NULL) { + free(host); + return errno; + } + } + profile_abandon(prof); + + if (realm == NULL) { + p = host; + do { + qname = malloc(strlen(p) + strlen("_kerberos..") + 1); + if (qname == NULL) { + free(host); + return errno; + } + sprintf(qname, "_kerberos.%s.", p); + ret = txt_lookup(qname, &realm); + free(qname); + + p = strchr(p,'.'); + if (p) + p++; + } while (ret && p && p[0]); + } + + if (realm == NULL) { + if (default_realm != NULL) { + realm = strdup(default_realm); + if (realm == NULL) { + free(host); + return errno; + } + + for (p = realm; *p; p++) + if (islower(*p)) + *p = toupper(*p); + } else { + ret = krb5_get_default_realm(Z_krb5_ctx, &realm); + if (ret) { + free(host); + return ret; + } + } + } + + free(host); + + if ((*krealms = calloc(2, sizeof(*krealms))) == NULL) { + if (realm) + free(realm); + return errno; + } + + (*krealms)[0] = realm; + (*krealms)[1] = NULL; + + return 0; +} +#endif -- cgit v1.2.3