1 /* 2 * lib/krb5/os/def_realm.c 3 * 4 * Copyright 1990,1991 by the Massachusetts Institute of Technology. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 * 26 * 27 * krb5_get_default_realm(), krb5_set_default_realm(), 28 * krb5_free_default_realm() functions. 29 */ 30 31 /* 32 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 33 * Use is subject to license terms. 34 * 35 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 36 * Copyright (c) 2016 by Delphix. All rights reserved. 37 */ 38 39 #include "k5-int.h" 40 #include "os-proto.h" 41 #include <stdio.h> 42 43 /* 44 * Solaris Kerberos: 45 * For krb5int_foreach_localaddr() 46 */ 47 #include "foreachaddr.h" 48 49 #ifdef KRB5_DNS_LOOKUP 50 #ifdef WSHELPER 51 #include <wshelper.h> 52 #else /* WSHELPER */ 53 #ifdef HAVE_NETINET_IN_H 54 #include <netinet/in.h> 55 #endif 56 #include <arpa/inet.h> 57 #include <arpa/nameser.h> 58 #include <resolv.h> 59 #include <netdb.h> 60 #endif /* WSHELPER */ 61 62 /* for old Unixes and friends ... */ 63 #ifndef MAXHOSTNAMELEN 64 #define MAXHOSTNAMELEN 64 65 #endif 66 67 #define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1) 68 69 #endif /* KRB5_DNS_LOOKUP */ 70 71 /* 72 * Solaris Kerberos: 73 * The following prototype is needed because it is a 74 * private interface that does not have a prototype in any .h 75 */ 76 extern struct hostent *res_gethostbyaddr(const char *addr, int len, int type); 77 78 /* 79 * Solaris Kerberos: 80 * krb5int_address_get_realm() given an address (either IPv4 or IPv6) tries to 81 * find a realm based on the DNS name of that address. Assumes that its being 82 * used as a callback for krb5int_foreach_localaddr(). 83 */ 84 static int krb5int_address_get_realm(void *data, struct sockaddr *addr) { 85 86 krb5_context context = data; 87 struct hostent *he = NULL; 88 89 switch (addr->sa_family) { 90 case AF_INET: 91 he = res_gethostbyaddr((char*)(&sa2sin(addr)->sin_addr), 92 sizeof(sa2sin(addr)->sin_addr), AF_INET); 93 break; 94 case AF_INET6: 95 he = res_gethostbyaddr( 96 (char*)(&sa2sin6(addr)->sin6_addr), 97 sizeof(sa2sin6(addr)->sin6_addr), AF_INET6); 98 break; 99 } 100 101 if (he) { 102 /* Try to find realm using returned DNS name */ 103 krb5int_fqdn_get_realm(context, he->h_name, 104 &context->default_realm); 105 106 /* If a realm was found return 1 to immediately halt 107 * krb5int_foreach_localaddr() 108 */ 109 if (context->default_realm != 0) { 110 return (1); 111 } 112 } 113 return (0); 114 } 115 116 117 /* 118 * Retrieves the default realm to be used if no user-specified realm is 119 * available. [e.g. to interpret a user-typed principal name with the 120 * realm omitted for convenience] 121 * 122 * returns system errors, NOT_ENOUGH_SPACE, KV5M_CONTEXT 123 */ 124 125 /* 126 * Implementation: the default realm is stored in a configuration file, 127 * named by krb5_config_file; the first token in this file is taken as 128 * the default local realm name. 129 */ 130 131 krb5_error_code KRB5_CALLCONV 132 krb5_get_default_realm(krb5_context context, char **lrealm) 133 { 134 char *realm = 0; 135 char *cp; 136 char localhost[MAX_DNS_NAMELEN+1]; 137 krb5_error_code retval; 138 139 (void) memset(localhost, 0, sizeof(localhost)); 140 141 if (!context || (context->magic != KV5M_CONTEXT)) 142 return KV5M_CONTEXT; 143 144 /* 145 * Solaris Kerberos: (illumos) 146 * Another way to provide the default realm. 147 */ 148 if (!context->default_realm) { 149 if ((realm = getenv("KRB5_DEFAULT_REALM")) != NULL) { 150 context->default_realm = strdup(realm); 151 if (context->default_realm == NULL) 152 return ENOMEM; 153 } 154 } 155 156 if (!context->default_realm) { 157 context->default_realm = 0; 158 if (context->profile != 0) { 159 retval = profile_get_string(context->profile, "libdefaults", 160 "default_realm", 0, 0, 161 &realm); 162 163 if (!retval && realm) { 164 context->default_realm = malloc(strlen(realm) + 1); 165 if (!context->default_realm) { 166 profile_release_string(realm); 167 return ENOMEM; 168 } 169 strcpy(context->default_realm, realm); 170 profile_release_string(realm); 171 } 172 } 173 if (context->default_realm == 0) { 174 #ifdef KRB5_DNS_LOOKUP 175 if (_krb5_use_dns_realm(context)) { 176 /* 177 * Since this didn't appear in our config file, try looking 178 * it up via DNS. Look for a TXT records of the form: 179 * 180 * _kerberos.<localhost> 181 * _kerberos.<domainname> 182 * _kerberos.<searchlist> 183 * 184 */ 185 char * p; 186 krb5int_get_fq_local_hostname (localhost, sizeof(localhost)); 187 188 if ( localhost[0] ) { 189 p = localhost; 190 do { 191 retval = krb5_try_realm_txt_rr("_kerberos", p, 192 &context->default_realm); 193 p = strchr(p,'.'); 194 if (p) 195 p++; 196 } while (retval && p && p[0]); 197 198 if (retval) 199 retval = krb5_try_realm_txt_rr("_kerberos", "", 200 &context->default_realm); 201 } else { 202 retval = krb5_try_realm_txt_rr("_kerberos", "", 203 &context->default_realm); 204 } 205 if (retval) { 206 return(KRB5_CONFIG_NODEFREALM); 207 } 208 } else 209 #endif /* KRB5_DNS_LOOKUP */ 210 if (getenv("MS_INTEROP") == NULL) { 211 212 /* 213 * Solaris Kerberos: 214 * Try to find a realm based on one of the local IP addresses. 215 * Don't do this for AD, which often does _not_ support any 216 * DNS reverse lookup, making these queries take forever. 217 */ 218 (void) krb5int_foreach_localaddr(context, 219 krb5int_address_get_realm, 0, 0); 220 221 /* 222 * Solaris Kerberos: 223 * As a final fallback try to find a realm based on the resolver search 224 * list 225 */ 226 if (context->default_realm == 0) { 227 struct __res_state res; 228 int i; 229 230 (void) memset(&res, 0, sizeof (res)); 231 232 if (res_ninit(&res) == 0) { 233 for (i = 0; res.dnsrch[i]; i++) { 234 krb5int_domain_get_realm(context, 235 res.dnsrch[i], &context->default_realm); 236 237 if (context->default_realm != 0) 238 break; 239 } 240 res_ndestroy(&res); 241 } 242 } 243 244 } 245 } 246 } 247 248 if (context->default_realm == 0) 249 return(KRB5_CONFIG_NODEFREALM); 250 if (context->default_realm[0] == 0) { 251 free (context->default_realm); 252 context->default_realm = 0; 253 return KRB5_CONFIG_NODEFREALM; 254 } 255 256 realm = context->default_realm; 257 258 /*LINTED*/ 259 if (!(*lrealm = cp = malloc((unsigned int) strlen(realm) + 1))) 260 return ENOMEM; 261 strcpy(cp, realm); 262 return(0); 263 } 264 265 krb5_error_code KRB5_CALLCONV 266 krb5_set_default_realm(krb5_context context, const char *lrealm) 267 { 268 if (!context || (context->magic != KV5M_CONTEXT)) 269 return KV5M_CONTEXT; 270 271 if (context->default_realm) { 272 free(context->default_realm); 273 context->default_realm = 0; 274 } 275 276 /* Allow the user to clear the default realm setting by passing in 277 NULL */ 278 if (!lrealm) return 0; 279 280 context->default_realm = malloc(strlen (lrealm) + 1); 281 282 if (!context->default_realm) 283 return ENOMEM; 284 285 strcpy(context->default_realm, lrealm); 286 return(0); 287 288 } 289 290 /*ARGSUSED*/ 291 void KRB5_CALLCONV 292 krb5_free_default_realm(krb5_context context, char *lrealm) 293 { 294 free (lrealm); 295 } 296