krb5_error_code KRB5_CALLCONV krb5_get_default_realm(krb5_context context, char **lrealm) { char *realm = 0; char *cp; char localhost[MAX_DNS_NAMELEN+1]; krb5_error_code retval; (void) memset(localhost, 0, sizeof(localhost)); if (!context || (context->magic != KV5M_CONTEXT)) return KV5M_CONTEXT; /* * Solaris Kerberos: (illumos) * Another way to provide the default realm. */ if (!context->default_realm) { if ((realm = getenv("KRB5_DEFAULT_REALM")) != NULL) { context->default_realm = strdup(realm); if (context->default_realm == NULL) return ENOMEM; } } if (!context->default_realm) { context->default_realm = 0; if (context->profile != 0) { retval = profile_get_string(context->profile, "libdefaults", "default_realm", 0, 0, &realm); if (!retval && realm) { context->default_realm = malloc(strlen(realm) + 1); if (!context->default_realm) { profile_release_string(realm); return ENOMEM; } strcpy(context->default_realm, realm); profile_release_string(realm); } } if (context->default_realm == 0) { #ifdef KRB5_DNS_LOOKUP if (_krb5_use_dns_realm(context)) { /* * Since this didn't appear in our config file, try looking * it up via DNS. Look for a TXT records of the form: * * _kerberos.<localhost> * _kerberos.<domainname> * _kerberos.<searchlist> * */ char * p; krb5int_get_fq_local_hostname (localhost, sizeof(localhost)); if ( localhost[0] ) { p = localhost; do { retval = krb5_try_realm_txt_rr("_kerberos", p, &context->default_realm); p = strchr(p,'.'); if (p) p++; } while (retval && p && p[0]); if (retval) retval = krb5_try_realm_txt_rr("_kerberos", "", &context->default_realm); } else { retval = krb5_try_realm_txt_rr("_kerberos", "", &context->default_realm); } if (retval) { return(KRB5_CONFIG_NODEFREALM); } } else #endif /* KRB5_DNS_LOOKUP */ if (getenv("MS_INTEROP") == NULL) { /* * Solaris Kerberos: * Try to find a realm based on one of the local IP addresses. * Don't do this for AD, which often does _not_ support any * DNS reverse lookup, making these queries take forever. */ (void) krb5int_foreach_localaddr(context, krb5int_address_get_realm, 0, 0); /* * Solaris Kerberos: * As a final fallback try to find a realm based on the resolver search * list */ if (context->default_realm == 0) { struct __res_state res; int i; (void) memset(&res, 0, sizeof (res)); if (res_ninit(&res) == 0) { for (i = 0; res.dnsrch[i]; i++) { krb5int_domain_get_realm(context, res.dnsrch[i], &context->default_realm); if (context->default_realm != 0) break; } res_ndestroy(&res); } } } } } if (context->default_realm == 0) return(KRB5_CONFIG_NODEFREALM); if (context->default_realm[0] == 0) { free (context->default_realm); context->default_realm = 0; return KRB5_CONFIG_NODEFREALM; } realm = context->default_realm; /*LINTED*/ if (!(*lrealm = cp = malloc((unsigned int) strlen(realm) + 1))) return ENOMEM; strcpy(cp, realm); return(0); }
krb5_error_code KRB5_CALLCONV krb5_get_fallback_host_realm(krb5_context context, krb5_data *hdata, char ***realmsp) { char **retrealms; char *realm, *cp; krb5_error_code retval; char local_host[MAXDNAME+1], host[MAXDNAME+1]; /* Convert what we hope is a hostname to a string. */ memcpy(host, hdata->data, hdata->length); host[hdata->length]=0; #ifdef DEBUG_REFERRALS printf("get_fallback_host_realm(host >%s<) called\n",host); #endif retval = krb5int_clean_hostname(context, host, local_host, sizeof local_host); if (retval) return retval; /* * Try looking up a _kerberos.<hostname> TXT record in DNS. This * heuristic is turned off by default since, in the absence of * secure DNS, it can allow an attacker to control the realm used * for a host. */ realm = (char *)NULL; #ifdef KRB5_DNS_LOOKUP if (_krb5_use_dns_realm(context)) { cp = local_host; do { retval = krb5_try_realm_txt_rr("_kerberos", cp, &realm); cp = strchr(cp,'.'); if (cp) cp++; } while (retval && cp && cp[0]); } #endif /* KRB5_DNS_LOOKUP */ /* * Next try searching the domain components as realms. This * heuristic is also turned off by default. If DNS lookups for * KDCs are enabled (as they are by default), an attacker could * control which domain component is used as the realm for a host. */ if (realm == (char *)NULL) { int limit; errcode_t code; code = profile_get_integer(context->profile, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_REALM_TRY_DOMAINS, 0, -1, &limit); if (code == 0) { retval = domain_heuristic(context, local_host, &realm, limit); if (retval) return retval; } } /* * The next fallback--and the first one to apply with default * configuration--is to use the upper-cased parent domain of the * hostname, regardless of whether we can actually look it up as a * realm. */ if (realm == (char *)NULL) { cp = strchr(local_host, '.'); if (cp) { if (!(realm = strdup(cp + 1))) return ENOMEM; for (cp = realm; *cp; cp++) if (islower((int) (*cp))) *cp = toupper((int) *cp); } } /* * The final fallback--used when the fully-qualified hostname has * only one component--is to use the local default realm. */ if (realm == (char *)NULL) { retval = krb5_get_default_realm(context, &realm); if (retval) return retval; } if (!(retrealms = (char **)calloc(2, sizeof(*retrealms)))) { if (realm != (char *)NULL) free(realm); return ENOMEM; } retrealms[0] = realm; retrealms[1] = 0; *realmsp = retrealms; return 0; }
krb5_error_code KRB5_CALLCONV krb5_get_default_realm(krb5_context context, char **lrealm) { char *realm = 0; krb5_error_code retval; if (!context || (context->magic != KV5M_CONTEXT)) return KV5M_CONTEXT; if (!context->default_realm) { /* * XXX should try to figure out a reasonable default based * on the host's DNS domain. */ context->default_realm = 0; if (context->profile != 0) { retval = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_DEFAULT_REALM, 0, 0, &realm); if (!retval && realm) { context->default_realm = strdup(realm); if (!context->default_realm) { profile_release_string(realm); return ENOMEM; } profile_release_string(realm); } } #ifndef KRB5_DNS_LOOKUP else return KRB5_CONFIG_CANTOPEN; #else /* KRB5_DNS_LOOKUP */ if (context->default_realm == 0) { int use_dns = _krb5_use_dns_realm(context); if ( use_dns ) { /* * Since this didn't appear in our config file, try looking * it up via DNS. Look for a TXT records of the form: * * _kerberos.<localhost> * _kerberos.<domainname> * _kerberos.<searchlist> * */ char localhost[MAX_DNS_NAMELEN+1]; char * p; krb5int_get_fq_local_hostname (localhost, sizeof(localhost)); if ( localhost[0] ) { p = localhost; do { retval = krb5_try_realm_txt_rr("_kerberos", p, &context->default_realm); p = strchr(p,'.'); if (p) p++; } while (retval && p && p[0]); if (retval) retval = krb5_try_realm_txt_rr("_kerberos", "", &context->default_realm); } else { retval = krb5_try_realm_txt_rr("_kerberos", "", &context->default_realm); } if (retval) { return(KRB5_CONFIG_NODEFREALM); } } } #endif /* KRB5_DNS_LOOKUP */ } if (context->default_realm == 0) return(KRB5_CONFIG_NODEFREALM); if (context->default_realm[0] == 0) { free (context->default_realm); context->default_realm = 0; return KRB5_CONFIG_NODEFREALM; } realm = context->default_realm; if (!(*lrealm = strdup(realm))) return ENOMEM; return(0); }