17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * lib/krb5/os/hst_realm.c 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * Copyright 1990,1991,2002 by the Massachusetts Institute of Technology. 57c478bd9Sstevel@tonic-gate * All Rights Reserved. 67c478bd9Sstevel@tonic-gate * 77c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 87c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 97c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 107c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 117c478bd9Sstevel@tonic-gate * 127c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 137c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 147c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 157c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 167c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 177c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 187c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 197c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 207c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 217c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 227c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 237c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 247c478bd9Sstevel@tonic-gate * or implied warranty. 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * 277c478bd9Sstevel@tonic-gate * krb5_get_host_realm() 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 30fe598cdcSmp /* 31*56bbb0b2SPeter Shoults * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 32fe598cdcSmp */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /* 357c478bd9Sstevel@tonic-gate Figures out the Kerberos realm names for host, filling in a 367c478bd9Sstevel@tonic-gate pointer to an argv[] style list of names, terminated with a null pointer. 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate If host is NULL, the local host's realms are determined. 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate If there are no known realms for the host, the filled-in pointer is set 417c478bd9Sstevel@tonic-gate to NULL. 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate The pointer array and strings pointed to are all in allocated storage, 447c478bd9Sstevel@tonic-gate and should be freed by the caller when finished. 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate returns system errors 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* 507c478bd9Sstevel@tonic-gate * Implementation notes: 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate * this implementation only provides one realm per host, using the same 537c478bd9Sstevel@tonic-gate * mapping file used in kerberos v4. 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate * Given a fully-qualified domain-style primary host name, 567c478bd9Sstevel@tonic-gate * return the name of the Kerberos realm for the host. 577c478bd9Sstevel@tonic-gate * If the hostname contains no discernable domain, or an error occurs, 587c478bd9Sstevel@tonic-gate * return the local realm name, as supplied by krb5_get_default_realm(). 597c478bd9Sstevel@tonic-gate * If the hostname contains a domain, but no translation is found, 607c478bd9Sstevel@tonic-gate * the hostname's domain is converted to upper-case and returned. 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * The format of each line of the translation file is: 637c478bd9Sstevel@tonic-gate * domain_name kerberos_realm 647c478bd9Sstevel@tonic-gate * -or- 657c478bd9Sstevel@tonic-gate * host_name kerberos_realm 667c478bd9Sstevel@tonic-gate * 677c478bd9Sstevel@tonic-gate * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU) 687c478bd9Sstevel@tonic-gate * host names should be in the usual form (e.g. FOO.BAR.BAZ) 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate 71fe598cdcSmp 727c478bd9Sstevel@tonic-gate #include "k5-int.h" 737c478bd9Sstevel@tonic-gate #include "os-proto.h" 747c478bd9Sstevel@tonic-gate #include <ctype.h> 757c478bd9Sstevel@tonic-gate #include <stdio.h> 767c478bd9Sstevel@tonic-gate #ifdef HAVE_STRING_H 777c478bd9Sstevel@tonic-gate #include <string.h> 787c478bd9Sstevel@tonic-gate #else 797c478bd9Sstevel@tonic-gate #include <strings.h> 807c478bd9Sstevel@tonic-gate #endif 817c478bd9Sstevel@tonic-gate 82159d09a2SMark Phalan #include "fake-addrinfo.h" 837c478bd9Sstevel@tonic-gate 84505d05c7Sgtb #ifdef KRB5_DNS_LOOKUP 857c478bd9Sstevel@tonic-gate 86505d05c7Sgtb #include "dnsglue.h" 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * Try to look up a TXT record pointing to a Kerberos realm 897c478bd9Sstevel@tonic-gate */ 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate krb5_error_code 927c478bd9Sstevel@tonic-gate krb5_try_realm_txt_rr(const char *prefix, const char *name, char **realm) 937c478bd9Sstevel@tonic-gate { 94505d05c7Sgtb krb5_error_code retval = KRB5_ERR_HOST_REALM_UNKNOWN; 95505d05c7Sgtb const unsigned char *p, *base; 96505d05c7Sgtb char host[MAXDNAME], *h; 97505d05c7Sgtb int ret, rdlen, len; 98505d05c7Sgtb struct krb5int_dns_state *ds = NULL; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * Form our query, and send it via DNS 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate if (name == NULL || name[0] == '\0') { 1057c478bd9Sstevel@tonic-gate if (strlen (prefix) >= sizeof(host)-1) 1067c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 1077c478bd9Sstevel@tonic-gate strcpy(host,prefix); 1087c478bd9Sstevel@tonic-gate } else { 109505d05c7Sgtb if ( strlen(prefix) + strlen(name) + 3 > MAXDNAME ) 1107c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 1117c478bd9Sstevel@tonic-gate /*LINTED*/ 1127c478bd9Sstevel@tonic-gate sprintf(host,"%s.%s", prefix, name); 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* Realm names don't (normally) end with ".", but if the query 1157c478bd9Sstevel@tonic-gate doesn't end with "." and doesn't get an answer as is, the 1167c478bd9Sstevel@tonic-gate resolv code will try appending the local domain. Since the 1177c478bd9Sstevel@tonic-gate realm names are absolutes, let's stop that. 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate But only if a name has been specified. If we are performing 1207c478bd9Sstevel@tonic-gate a search on the prefix alone then the intention is to allow 1217c478bd9Sstevel@tonic-gate the local domain or domain search lists to be expanded. 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate h = host + strlen (host); 1257c478bd9Sstevel@tonic-gate if ((h > host) && (h[-1] != '.') && ((h - host + 1) < sizeof(host))) 1267c478bd9Sstevel@tonic-gate strcpy (h, "."); 1277c478bd9Sstevel@tonic-gate } 128505d05c7Sgtb ret = krb5int_dns_init(&ds, host, C_IN, T_TXT); 129505d05c7Sgtb if (ret < 0) 130fe598cdcSmp goto errout; 131505d05c7Sgtb 132505d05c7Sgtb ret = krb5int_dns_nextans(ds, &base, &rdlen); 133505d05c7Sgtb if (ret < 0 || base == NULL) 134fe598cdcSmp goto errout; 135505d05c7Sgtb 136505d05c7Sgtb p = base; 137505d05c7Sgtb if (!INCR_OK(base, rdlen, p, 1)) 138fe598cdcSmp goto errout; 139505d05c7Sgtb len = *p++; 140505d05c7Sgtb *realm = malloc((size_t)len + 1); 141505d05c7Sgtb if (*realm == NULL) { 142fe598cdcSmp retval = ENOMEM; 143fe598cdcSmp goto errout; 1447c478bd9Sstevel@tonic-gate } 145505d05c7Sgtb strncpy(*realm, (const char *)p, (size_t)len); 146505d05c7Sgtb (*realm)[len] = '\0'; 147505d05c7Sgtb /* Avoid a common error. */ 148505d05c7Sgtb if ( (*realm)[len-1] == '.' ) 149fe598cdcSmp (*realm)[len-1] = '\0'; 150505d05c7Sgtb retval = 0; 151505d05c7Sgtb 152505d05c7Sgtb errout: 153505d05c7Sgtb if (ds != NULL) { 154fe598cdcSmp krb5int_dns_fini(ds); 155fe598cdcSmp ds = NULL; 1567c478bd9Sstevel@tonic-gate } 157505d05c7Sgtb return retval; 1587c478bd9Sstevel@tonic-gate } 159505d05c7Sgtb #else /* KRB5_DNS_LOOKUP */ 160505d05c7Sgtb #ifndef MAXDNAME 161505d05c7Sgtb #define MAXDNAME (16 * MAXHOSTNAMELEN) 162505d05c7Sgtb #endif /* MAXDNAME */ 1637c478bd9Sstevel@tonic-gate #endif /* KRB5_DNS_LOOKUP */ 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate krb5_error_code krb5int_translate_gai_error (int); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate static krb5_error_code 1687c478bd9Sstevel@tonic-gate krb5int_get_fq_hostname (char *buf, size_t bufsize, const char *name) 1697c478bd9Sstevel@tonic-gate { 1707c478bd9Sstevel@tonic-gate struct addrinfo *ai, hints; 1717c478bd9Sstevel@tonic-gate int err; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate memset (&hints, 0, sizeof (hints)); 1747c478bd9Sstevel@tonic-gate hints.ai_flags = AI_CANONNAME; 1757c478bd9Sstevel@tonic-gate err = getaddrinfo (name, 0, &hints, &ai); 1767c478bd9Sstevel@tonic-gate if (err) 1777c478bd9Sstevel@tonic-gate return krb5int_translate_gai_error (err); 1787c478bd9Sstevel@tonic-gate if (ai->ai_canonname == 0) 1797c478bd9Sstevel@tonic-gate return KRB5_EAI_FAIL; 1807c478bd9Sstevel@tonic-gate strncpy (buf, ai->ai_canonname, bufsize); 1817c478bd9Sstevel@tonic-gate buf[bufsize-1] = 0; 1827c478bd9Sstevel@tonic-gate freeaddrinfo (ai); 1837c478bd9Sstevel@tonic-gate return 0; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* Get the local host name, try to make it fully-qualified. 1877c478bd9Sstevel@tonic-gate Always return a null-terminated string. 1887c478bd9Sstevel@tonic-gate Might return an error if gethostname fails. */ 1897c478bd9Sstevel@tonic-gate krb5_error_code 1907c478bd9Sstevel@tonic-gate krb5int_get_fq_local_hostname (char *buf, size_t bufsiz) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate buf[0] = 0; 1937c478bd9Sstevel@tonic-gate if (gethostname (buf, bufsiz) == -1) 1947c478bd9Sstevel@tonic-gate return SOCKET_ERRNO; 1957c478bd9Sstevel@tonic-gate buf[bufsiz - 1] = 0; 1967c478bd9Sstevel@tonic-gate return krb5int_get_fq_hostname (buf, bufsiz, buf); 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate krb5_error_code KRB5_CALLCONV 2007c478bd9Sstevel@tonic-gate krb5_get_host_realm(krb5_context context, const char *host, char ***realmsp) 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate char **retrealms; 203fe598cdcSmp char *realm, *cp, *temp_realm; 2047c478bd9Sstevel@tonic-gate krb5_error_code retval; 205505d05c7Sgtb char local_host[MAXDNAME+1]; 2067c478bd9Sstevel@tonic-gate 207fe598cdcSmp #ifdef DEBUG_REFERRALS 208fe598cdcSmp printf("get_host_realm(host:%s) called\n",host); 209fe598cdcSmp #endif 2107c478bd9Sstevel@tonic-gate 211fe598cdcSmp krb5int_clean_hostname(context, host, local_host, sizeof local_host); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate Search for the best match for the host or domain. 2157c478bd9Sstevel@tonic-gate Example: Given a host a.b.c.d, try to match on: 2167c478bd9Sstevel@tonic-gate 1) A.B.C.D 2177c478bd9Sstevel@tonic-gate 2) .B.C.D 2187c478bd9Sstevel@tonic-gate 3) B.C.D 2197c478bd9Sstevel@tonic-gate 4) .C.D 2207c478bd9Sstevel@tonic-gate 5) C.D 2217c478bd9Sstevel@tonic-gate 6) .D 2227c478bd9Sstevel@tonic-gate 7) D 2237c478bd9Sstevel@tonic-gate */ 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate cp = local_host; 226fe598cdcSmp #ifdef DEBUG_REFERRALS 227fe598cdcSmp printf(" local_host: %s\n",local_host); 228fe598cdcSmp #endif 229fe598cdcSmp realm = (char *)NULL; 2307c478bd9Sstevel@tonic-gate temp_realm = 0; 2317c478bd9Sstevel@tonic-gate while (cp) { 232fe598cdcSmp #ifdef DEBUG_REFERRALS 233fe598cdcSmp printf(" trying to look up %s in the domain_realm map\n",cp); 234fe598cdcSmp #endif 2357c478bd9Sstevel@tonic-gate retval = profile_get_string(context->profile, "domain_realm", cp, 2367c478bd9Sstevel@tonic-gate 0, (char *)NULL, &temp_realm); 2377c478bd9Sstevel@tonic-gate if (retval) 2387c478bd9Sstevel@tonic-gate return retval; 2397c478bd9Sstevel@tonic-gate if (temp_realm != (char *)NULL) 2407c478bd9Sstevel@tonic-gate break; /* Match found */ 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* Setup for another test */ 2437c478bd9Sstevel@tonic-gate if (*cp == '.') { 2447c478bd9Sstevel@tonic-gate cp++; 2457c478bd9Sstevel@tonic-gate } else { 2467c478bd9Sstevel@tonic-gate cp = strchr(cp, '.'); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate } 249fe598cdcSmp #ifdef DEBUG_REFERRALS 250fe598cdcSmp printf(" done searching the domain_realm map\n"); 251fe598cdcSmp #endif 2527c478bd9Sstevel@tonic-gate if (temp_realm) { 253fe598cdcSmp #ifdef DEBUG_REFERRALS 254fe598cdcSmp printf(" temp_realm is %s\n",temp_realm); 255fe598cdcSmp #endif 2567c478bd9Sstevel@tonic-gate realm = malloc(strlen(temp_realm) + 1); 2577c478bd9Sstevel@tonic-gate if (!realm) { 2587c478bd9Sstevel@tonic-gate profile_release_string(temp_realm); 2597c478bd9Sstevel@tonic-gate return ENOMEM; 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate strcpy(realm, temp_realm); 2627c478bd9Sstevel@tonic-gate profile_release_string(temp_realm); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate if (realm == (char *)NULL) { 266fe598cdcSmp if (!(cp = (char *)malloc(strlen(KRB5_REFERRAL_REALM)+1))) 267fe598cdcSmp return ENOMEM; 268fe598cdcSmp strcpy(cp, KRB5_REFERRAL_REALM); 269fe598cdcSmp realm = cp; 2707c478bd9Sstevel@tonic-gate } 271fe598cdcSmp 2727c478bd9Sstevel@tonic-gate if (!(retrealms = (char **)calloc(2, sizeof(*retrealms)))) { 2737c478bd9Sstevel@tonic-gate if (realm != (char *)NULL) 2747c478bd9Sstevel@tonic-gate free(realm); 2757c478bd9Sstevel@tonic-gate return ENOMEM; 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate retrealms[0] = realm; 2797c478bd9Sstevel@tonic-gate retrealms[1] = 0; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate *realmsp = retrealms; 2827c478bd9Sstevel@tonic-gate return 0; 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate #if defined(_WIN32) && !defined(__CYGWIN32__) 2867c478bd9Sstevel@tonic-gate # ifndef EAFNOSUPPORT 2877c478bd9Sstevel@tonic-gate # define EAFNOSUPPORT WSAEAFNOSUPPORT 2887c478bd9Sstevel@tonic-gate # endif 2897c478bd9Sstevel@tonic-gate #endif 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate krb5_error_code 2927c478bd9Sstevel@tonic-gate krb5int_translate_gai_error (int num) 2937c478bd9Sstevel@tonic-gate { 2947c478bd9Sstevel@tonic-gate switch (num) { 2957c478bd9Sstevel@tonic-gate #ifdef EAI_ADDRFAMILY 2967c478bd9Sstevel@tonic-gate case EAI_ADDRFAMILY: 2977c478bd9Sstevel@tonic-gate return EAFNOSUPPORT; 2987c478bd9Sstevel@tonic-gate #endif 2997c478bd9Sstevel@tonic-gate case EAI_AGAIN: 3007c478bd9Sstevel@tonic-gate return EAGAIN; 3017c478bd9Sstevel@tonic-gate case EAI_BADFLAGS: 3027c478bd9Sstevel@tonic-gate return EINVAL; 3037c478bd9Sstevel@tonic-gate case EAI_FAIL: 3047c478bd9Sstevel@tonic-gate return KRB5_EAI_FAIL; 3057c478bd9Sstevel@tonic-gate case EAI_FAMILY: 3067c478bd9Sstevel@tonic-gate return EAFNOSUPPORT; 3077c478bd9Sstevel@tonic-gate case EAI_MEMORY: 3087c478bd9Sstevel@tonic-gate return ENOMEM; 309159d09a2SMark Phalan #if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME 3107c478bd9Sstevel@tonic-gate case EAI_NODATA: 3117c478bd9Sstevel@tonic-gate return KRB5_EAI_NODATA; 3127c478bd9Sstevel@tonic-gate #endif 3137c478bd9Sstevel@tonic-gate case EAI_NONAME: 3147c478bd9Sstevel@tonic-gate return KRB5_EAI_NONAME; 315159d09a2SMark Phalan #if defined(EAI_OVERFLOW) 316159d09a2SMark Phalan case EAI_OVERFLOW: 317159d09a2SMark Phalan return EINVAL; /* XXX */ 318159d09a2SMark Phalan #endif 3197c478bd9Sstevel@tonic-gate case EAI_SERVICE: 3207c478bd9Sstevel@tonic-gate return KRB5_EAI_SERVICE; 3217c478bd9Sstevel@tonic-gate case EAI_SOCKTYPE: 3227c478bd9Sstevel@tonic-gate return EINVAL; 3237c478bd9Sstevel@tonic-gate #ifdef EAI_SYSTEM 3247c478bd9Sstevel@tonic-gate case EAI_SYSTEM: 3257c478bd9Sstevel@tonic-gate return errno; 3267c478bd9Sstevel@tonic-gate #endif 3277c478bd9Sstevel@tonic-gate } 328159d09a2SMark Phalan /* Solaris Kerberos */ 3297c478bd9Sstevel@tonic-gate /* abort (); */ 3307c478bd9Sstevel@tonic-gate return -1; 3317c478bd9Sstevel@tonic-gate } 332fe598cdcSmp 333fe598cdcSmp 334fe598cdcSmp /* 335fe598cdcSmp * Ganked from krb5_get_host_realm; handles determining a fallback realm 336fe598cdcSmp * to try in the case where referrals have failed and it's time to go 337fe598cdcSmp * look at TXT records or make a DNS-based assumption. 338fe598cdcSmp */ 339fe598cdcSmp 340fe598cdcSmp krb5_error_code KRB5_CALLCONV 341fe598cdcSmp krb5_get_fallback_host_realm(krb5_context context, krb5_data *hdata, char ***realmsp) 342fe598cdcSmp { 343fe598cdcSmp char **retrealms; 344fe598cdcSmp char *realm = (char *)NULL, *cp; 345fe598cdcSmp krb5_error_code retval; 346fe598cdcSmp char local_host[MAXDNAME+1], host[MAXDNAME+1]; 347fe598cdcSmp 348fe598cdcSmp /* Convert what we hope is a hostname to a string. */ 349fe598cdcSmp memcpy(host, hdata->data, hdata->length); 350fe598cdcSmp host[hdata->length]=0; 351fe598cdcSmp 352fe598cdcSmp #ifdef DEBUG_REFERRALS 353fe598cdcSmp printf("get_fallback_host_realm(host >%s<) called\n",host); 354fe598cdcSmp #endif 355fe598cdcSmp 356fe598cdcSmp krb5int_clean_hostname(context, host, local_host, sizeof local_host); 357fe598cdcSmp 358fe598cdcSmp #ifdef DEBUG_REFERRALS 359fe598cdcSmp printf(" local_host: %s\n",local_host); 360fe598cdcSmp #endif 361fe598cdcSmp 362fe598cdcSmp #ifdef KRB5_DNS_LOOKUP 363fe598cdcSmp if (_krb5_use_dns_realm(context)) { 364fe598cdcSmp /* 365fe598cdcSmp * Since this didn't appear in our config file, try looking 366fe598cdcSmp * it up via DNS. Look for a TXT records of the form: 367fe598cdcSmp * 368fe598cdcSmp * _kerberos.<hostname> 369fe598cdcSmp * 370fe598cdcSmp */ 371fe598cdcSmp cp = local_host; 372fe598cdcSmp do { 373fe598cdcSmp retval = krb5_try_realm_txt_rr("_kerberos", cp, &realm); 374fe598cdcSmp cp = strchr(cp,'.'); 375fe598cdcSmp if (cp) 376fe598cdcSmp cp++; 377fe598cdcSmp } while (retval && cp && cp[0]); 378fe598cdcSmp } else 379fe598cdcSmp #endif /* KRB5_DNS_LOOKUP */ 380fe598cdcSmp { 381fe598cdcSmp /* 382fe598cdcSmp * Solaris Kerberos: 383fe598cdcSmp * Fallback to looking for a realm based on the DNS domain 384fe598cdcSmp * of the host. Note: "local_host" here actually refers to the 385fe598cdcSmp * host and NOT necessarily the local hostnane. 386fe598cdcSmp */ 387fe598cdcSmp (void) krb5int_fqdn_get_realm(context, local_host, 388fe598cdcSmp &realm); 389fe598cdcSmp #ifdef DEBUG_REFERRALS 390fe598cdcSmp printf(" done finding DNS-based default realm: >%s<\n",realm); 391fe598cdcSmp #endif 392fe598cdcSmp } 393fe598cdcSmp 394fe598cdcSmp 395fe598cdcSmp if (realm == (char *)NULL) { 396fe598cdcSmp /* We are defaulting to the local realm */ 397fe598cdcSmp retval = krb5_get_default_realm(context, &realm); 398fe598cdcSmp if (retval) { 399fe598cdcSmp return retval; 400fe598cdcSmp } 401fe598cdcSmp } 402fe598cdcSmp if (!(retrealms = (char **)calloc(2, sizeof(*retrealms)))) { 403fe598cdcSmp if (realm != (char *)NULL) 404fe598cdcSmp free(realm); 405fe598cdcSmp return ENOMEM; 406fe598cdcSmp } 407fe598cdcSmp 408fe598cdcSmp retrealms[0] = realm; 409fe598cdcSmp retrealms[1] = 0; 410fe598cdcSmp 411fe598cdcSmp *realmsp = retrealms; 412fe598cdcSmp return 0; 413fe598cdcSmp } 414fe598cdcSmp 415fe598cdcSmp /* 416fe598cdcSmp * Common code for krb5_get_host_realm and krb5_get_fallback_host_realm 417fe598cdcSmp * to do basic sanity checks on supplied hostname. 418fe598cdcSmp */ 419fe598cdcSmp krb5_error_code KRB5_CALLCONV 420fe598cdcSmp krb5int_clean_hostname(krb5_context context, const char *host, char *local_host, size_t lhsize) 421fe598cdcSmp { 422fe598cdcSmp char *cp; 423fe598cdcSmp krb5_error_code retval; 424fe598cdcSmp int l; 425fe598cdcSmp 426fe598cdcSmp local_host[0]=0; 427fe598cdcSmp #ifdef DEBUG_REFERRALS 428fe598cdcSmp printf("krb5int_clean_hostname called: host<%s>, local_host<%s>, size %d\n",host,local_host,lhsize); 429fe598cdcSmp #endif 430fe598cdcSmp if (host) { 431fe598cdcSmp /* Filter out numeric addresses if the caller utterly failed to 432fe598cdcSmp convert them to names. */ 433fe598cdcSmp /* IPv4 - dotted quads only */ 434fe598cdcSmp if (strspn(host, "01234567890.") == strlen(host)) { 435fe598cdcSmp /* All numbers and dots... if it's three dots, it's an 436fe598cdcSmp IP address, and we reject it. But "12345" could be 437fe598cdcSmp a local hostname, couldn't it? We'll just assume 438fe598cdcSmp that a name with three dots is not meant to be an 439fe598cdcSmp all-numeric hostname three all-numeric domains down 440fe598cdcSmp from the current domain. */ 441fe598cdcSmp int ndots = 0; 442fe598cdcSmp const char *p; 443fe598cdcSmp for (p = host; *p; p++) 444fe598cdcSmp if (*p == '.') 445fe598cdcSmp ndots++; 446fe598cdcSmp if (ndots == 3) 447fe598cdcSmp return KRB5_ERR_NUMERIC_REALM; 448fe598cdcSmp } 449fe598cdcSmp if (strchr(host, ':')) 450fe598cdcSmp /* IPv6 numeric address form? Bye bye. */ 451fe598cdcSmp return KRB5_ERR_NUMERIC_REALM; 452fe598cdcSmp 453fe598cdcSmp /* Should probably error out if strlen(host) > MAXDNAME. */ 454fe598cdcSmp strncpy(local_host, host, lhsize); 455fe598cdcSmp local_host[lhsize - 1] = '\0'; 456fe598cdcSmp } else { 457fe598cdcSmp retval = krb5int_get_fq_local_hostname (local_host, lhsize); 458fe598cdcSmp if (retval) 459fe598cdcSmp return retval; 460fe598cdcSmp } 461fe598cdcSmp 462fe598cdcSmp /* fold to lowercase */ 463fe598cdcSmp for (cp = local_host; *cp; cp++) { 464fe598cdcSmp if (isupper((unsigned char) (*cp))) 465fe598cdcSmp *cp = tolower((unsigned char) *cp); 466fe598cdcSmp } 467fe598cdcSmp l = strlen(local_host); 468fe598cdcSmp /* strip off trailing dot */ 469fe598cdcSmp if (l && local_host[l-1] == '.') 470fe598cdcSmp local_host[l-1] = 0; 471fe598cdcSmp 472fe598cdcSmp #ifdef DEBUG_REFERRALS 473fe598cdcSmp printf("krb5int_clean_hostname ending: host<%s>, local_host<%s>, size %d\n",host,local_host,lhsize); 474fe598cdcSmp #endif 475fe598cdcSmp return 0; 476fe598cdcSmp } 477fe598cdcSmp 478fe598cdcSmp /* 479fe598cdcSmp * Solaris Kerberos: 480fe598cdcSmp * Walk through the components of a domain. At each 481fe598cdcSmp * stage determine if a KDC can be located for that domain. 482fe598cdcSmp * Return a realm corresponding to the upper-cased domain name 483fe598cdcSmp * for which a KDC was found or NULL if no KDC was found. 484fe598cdcSmp */ 485fe598cdcSmp krb5_error_code 486fe598cdcSmp krb5int_domain_get_realm(krb5_context context, const char *domain, char **realm) { 487fe598cdcSmp krb5_error_code retval; 488*56bbb0b2SPeter Shoults struct addrlist addrlist = ADDRLIST_INIT; /* Solaris Kerberos */ 489fe598cdcSmp krb5_data drealm; 490fe598cdcSmp char *cp = NULL; 491fe598cdcSmp char *fqdn = NULL; 492fe598cdcSmp 493fe598cdcSmp *realm = NULL; 494fe598cdcSmp memset(&drealm, 0, sizeof (drealm)); 495fe598cdcSmp 496fe598cdcSmp if (!(fqdn = malloc(strlen(domain) + 1))) { 497fe598cdcSmp return (ENOMEM); 498fe598cdcSmp } 499fe598cdcSmp strlcpy(fqdn, domain, strlen(domain) + 1); 500fe598cdcSmp 501fe598cdcSmp /* Upper case the domain (for use as a realm) */ 502fe598cdcSmp for (cp = fqdn; *cp; cp++) 503fe598cdcSmp if (islower((int)(*cp))) 504fe598cdcSmp *cp = toupper((int)*cp); 505fe598cdcSmp 506fe598cdcSmp cp = fqdn; 507fe598cdcSmp while (strchr(cp, '.') != NULL) { 508fe598cdcSmp 509fe598cdcSmp drealm.length = strlen(cp); 510fe598cdcSmp drealm.data = cp; 511fe598cdcSmp 512fe598cdcSmp /* Find a kdc based on this part of the domain name */ 513fe598cdcSmp retval = krb5_locate_kdc(context, &drealm, &addrlist, 0, SOCK_DGRAM, 0); 514fe598cdcSmp krb5int_free_addrlist(&addrlist); 515fe598cdcSmp 516fe598cdcSmp if (!retval) { /* Found a KDC! */ 517fe598cdcSmp if (!(*realm = malloc(strlen(cp) + 1))) { 518fe598cdcSmp free(fqdn); 519fe598cdcSmp return (ENOMEM); 520fe598cdcSmp } 521fe598cdcSmp strlcpy(*realm, cp, strlen(cp) + 1); 522fe598cdcSmp break; 523fe598cdcSmp } 524fe598cdcSmp 525fe598cdcSmp cp = strchr(cp, '.'); 526fe598cdcSmp cp++; 527fe598cdcSmp } 528fe598cdcSmp free(fqdn); 529fe598cdcSmp return (0); 530fe598cdcSmp } 531fe598cdcSmp 532fe598cdcSmp /* 533fe598cdcSmp * Solaris Kerberos: 534fe598cdcSmp * Discards the first component of the fqdn and calls 535fe598cdcSmp * krb5int_domain_get_realm() with the remaining string (domain). 536fe598cdcSmp * 537fe598cdcSmp */ 538fe598cdcSmp krb5_error_code 539fe598cdcSmp krb5int_fqdn_get_realm(krb5_context context, const char *fqdn, char **realm) { 540fe598cdcSmp char *domain = strchr(fqdn, '.'); 541fe598cdcSmp 542fe598cdcSmp if (domain) { 543fe598cdcSmp domain++; 544fe598cdcSmp return (krb5int_domain_get_realm(context, domain, realm)); 545fe598cdcSmp } else { 546fe598cdcSmp return (-1); 547fe598cdcSmp } 548fe598cdcSmp } 549fe598cdcSmp 550