/* * lib/krb5/os/def_realm.c * * Copyright 1990,1991 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * krb5_get_default_realm(), krb5_set_default_realm(), * krb5_free_default_realm() functions. */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright 2014 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. */ #include "k5-int.h" #include "os-proto.h" #include /* * Solaris Kerberos: * For krb5int_foreach_localaddr() */ #include "foreachaddr.h" #ifdef KRB5_DNS_LOOKUP #ifdef WSHELPER #include #else /* WSHELPER */ #ifdef HAVE_NETINET_IN_H #include #endif #include #include #include #include #endif /* WSHELPER */ /* for old Unixes and friends ... */ #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif #define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1) #endif /* KRB5_DNS_LOOKUP */ /* * Solaris Kerberos: * The following prototype is needed because it is a * private interface that does not have a prototype in any .h */ extern struct hostent *res_gethostbyaddr(const char *addr, int len, int type); /* * Solaris Kerberos: * krb5int_address_get_realm() given an address (either IPv4 or IPv6) tries to * find a realm based on the DNS name of that address. Assumes that its being * used as a callback for krb5int_foreach_localaddr(). */ static int krb5int_address_get_realm(void *data, struct sockaddr *addr) { krb5_context context = data; struct hostent *he = NULL; switch (addr->sa_family) { case AF_INET: he = res_gethostbyaddr((char*)(&sa2sin(addr)->sin_addr), sizeof(sa2sin(addr)->sin_addr), AF_INET); break; case AF_INET6: he = res_gethostbyaddr( (char*)(&sa2sin6(addr)->sin6_addr), sizeof(sa2sin6(addr)->sin6_addr), AF_INET6); break; } if (he) { /* Try to find realm using returned DNS name */ krb5int_fqdn_get_realm(context, he->h_name, &context->default_realm); /* If a realm was found return 1 to immediately halt * krb5int_foreach_localaddr() */ if (context->default_realm != 0) { return (1); } } return (0); } /* * Retrieves the default realm to be used if no user-specified realm is * available. [e.g. to interpret a user-typed principal name with the * realm omitted for convenience] * * returns system errors, NOT_ENOUGH_SPACE, KV5M_CONTEXT */ /* * Implementation: the default realm is stored in a configuration file, * named by krb5_config_file; the first token in this file is taken as * the default local realm name. */ 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. * _kerberos. * _kerberos. * */ 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_set_default_realm(krb5_context context, const char *lrealm) { if (!context || (context->magic != KV5M_CONTEXT)) return KV5M_CONTEXT; if (context->default_realm) { free(context->default_realm); context->default_realm = 0; } /* Allow the user to clear the default realm setting by passing in NULL */ if (!lrealm) return 0; context->default_realm = malloc(strlen (lrealm) + 1); if (!context->default_realm) return ENOMEM; strcpy(context->default_realm, lrealm); return(0); } /*ARGSUSED*/ void KRB5_CALLCONV krb5_free_default_realm(krb5_context context, char *lrealm) { free (lrealm); }