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 36 #include "k5-int.h" 37 #include "os-proto.h" 38 #include <stdio.h> 39 40 /* 41 * Solaris Kerberos: 42 * For krb5int_foreach_localaddr() 43 */ 44 #include "foreachaddr.h" 45 46 #ifdef KRB5_DNS_LOOKUP 47 #ifdef WSHELPER 48 #include <wshelper.h> 49 #else /* WSHELPER */ 50 #ifdef HAVE_NETINET_IN_H 51 #include <netinet/in.h> 52 #endif 53 #include <arpa/inet.h> 54 #include <arpa/nameser.h> 55 #include <resolv.h> 56 #include <netdb.h> 57 #endif /* WSHELPER */ 58 59 /* for old Unixes and friends ... */ 60 #ifndef MAXHOSTNAMELEN 61 #define MAXHOSTNAMELEN 64 62 #endif 63 64 #define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1) 65 66 #endif /* KRB5_DNS_LOOKUP */ 67 68 /* 69 * Solaris Kerberos: 70 * The following prototype is needed because it is a 71 * private interface that does not have a prototype in any .h 72 */ 73 extern struct hostent *res_gethostbyaddr(const char *addr, int len, int type); 74 75 /* 76 * Solaris Kerberos: 77 * krb5int_address_get_realm() given an address (either IPv4 or IPv6) tries to 78 * find a realm based on the DNS name of that address. Assumes that its being 79 * used as a callback for krb5int_foreach_localaddr(). 80 */ 81 static int krb5int_address_get_realm(void *data, struct sockaddr *addr) { 82 83 krb5_context context = data; 84 struct hostent *he = NULL; 85 86 switch (addr->sa_family) { 87 case AF_INET: 88 he = res_gethostbyaddr((char*)(&sa2sin(addr)->sin_addr), 89 sizeof(sa2sin(addr)->sin_addr), AF_INET); 90 break; 91 case AF_INET6: 92 he = res_gethostbyaddr( 93 (char*)(&sa2sin6(addr)->sin6_addr), 94 sizeof(sa2sin6(addr)->sin6_addr), AF_INET6); 95 break; 96 } 97 98 if (he) { 99 /* Try to find realm using returned DNS name */ 100 krb5int_fqdn_get_realm(context, he->h_name, 101 &context->default_realm); 102 103 /* If a realm was found return 1 to immediately halt 104 * krb5int_foreach_localaddr() 105 */ 106 if (context->default_realm != 0) { 107 return (1); 108 } 109 } 110 return (0); 111 } 112 113 114 /* 115 * Retrieves the default realm to be used if no user-specified realm is 116 * available. [e.g. to interpret a user-typed principal name with the 117 * realm omitted for convenience] 118 * 119 * returns system errors, NOT_ENOUGH_SPACE, KV5M_CONTEXT 120 */ 121 122 /* 123 * Implementation: the default realm is stored in a configuration file, 124 * named by krb5_config_file; the first token in this file is taken as 125 * the default local realm name. 126 */ 127 128 krb5_error_code KRB5_CALLCONV 129 krb5_get_default_realm(krb5_context context, char **lrealm) 130 { 131 char *realm = 0; 132 char *cp; 133 char localhost[MAX_DNS_NAMELEN+1]; 134 krb5_error_code retval; 135 136 (void) memset(localhost, 0, sizeof(localhost)); 137 138 if (!context || (context->magic != KV5M_CONTEXT)) 139 return KV5M_CONTEXT; 140 141 if (!context->default_realm) { 142 context->default_realm = 0; 143 if (context->profile != 0) { 144 retval = profile_get_string(context->profile, "libdefaults", 145 "default_realm", 0, 0, 146 &realm); 147 148 if (!retval && realm) { 149 context->default_realm = malloc(strlen(realm) + 1); 150 if (!context->default_realm) { 151 profile_release_string(realm); 152 return ENOMEM; 153 } 154 strcpy(context->default_realm, realm); 155 profile_release_string(realm); 156 } 157 } 158 if (context->default_realm == 0) { 159 #ifdef KRB5_DNS_LOOKUP 160 if (_krb5_use_dns_realm(context)) { 161 /* 162 * Since this didn't appear in our config file, try looking 163 * it up via DNS. Look for a TXT records of the form: 164 * 165 * _kerberos.<localhost> 166 * _kerberos.<domainname> 167 * _kerberos.<searchlist> 168 * 169 */ 170 char * p; 171 krb5int_get_fq_local_hostname (localhost, sizeof(localhost)); 172 173 if ( localhost[0] ) { 174 p = localhost; 175 do { 176 retval = krb5_try_realm_txt_rr("_kerberos", p, 177 &context->default_realm); 178 p = strchr(p,'.'); 179 if (p) 180 p++; 181 } while (retval && p && p[0]); 182 183 if (retval) 184 retval = krb5_try_realm_txt_rr("_kerberos", "", 185 &context->default_realm); 186 } else { 187 retval = krb5_try_realm_txt_rr("_kerberos", "", 188 &context->default_realm); 189 } 190 if (retval) { 191 return(KRB5_CONFIG_NODEFREALM); 192 } 193 } else 194 #endif /* KRB5_DNS_LOOKUP */ 195 { 196 197 /* 198 * Solaris Kerberos: 199 * Try to find a realm based on one of the local IP addresses 200 */ 201 (void) krb5int_foreach_localaddr(context, 202 krb5int_address_get_realm, 0, 0); 203 204 /* 205 * Solaris Kerberos: 206 * As a final fallback try to find a realm based on the resolver search 207 * list 208 */ 209 if (context->default_realm == 0) { 210 struct __res_state res; 211 int i; 212 213 (void) memset(&res, 0, sizeof (res)); 214 215 if (res_ninit(&res) == 0) { 216 for (i = 0; res.dnsrch[i]; i++) { 217 krb5int_domain_get_realm(context, 218 res.dnsrch[i], &context->default_realm); 219 220 if (context->default_realm != 0) 221 break; 222 } 223 res_ndestroy(&res); 224 } 225 } 226 227 } 228 } 229 } 230 231 if (context->default_realm == 0) 232 return(KRB5_CONFIG_NODEFREALM); 233 if (context->default_realm[0] == 0) { 234 free (context->default_realm); 235 context->default_realm = 0; 236 return KRB5_CONFIG_NODEFREALM; 237 } 238 239 realm = context->default_realm; 240 241 /*LINTED*/ 242 if (!(*lrealm = cp = malloc((unsigned int) strlen(realm) + 1))) 243 return ENOMEM; 244 strcpy(cp, realm); 245 return(0); 246 } 247 248 krb5_error_code KRB5_CALLCONV 249 krb5_set_default_realm(krb5_context context, const char *lrealm) 250 { 251 if (!context || (context->magic != KV5M_CONTEXT)) 252 return KV5M_CONTEXT; 253 254 if (context->default_realm) { 255 free(context->default_realm); 256 context->default_realm = 0; 257 } 258 259 /* Allow the user to clear the default realm setting by passing in 260 NULL */ 261 if (!lrealm) return 0; 262 263 context->default_realm = malloc(strlen (lrealm) + 1); 264 265 if (!context->default_realm) 266 return ENOMEM; 267 268 strcpy(context->default_realm, lrealm); 269 return(0); 270 271 } 272 273 /*ARGSUSED*/ 274 void KRB5_CALLCONV 275 krb5_free_default_realm(krb5_context context, char *lrealm) 276 { 277 free (lrealm); 278 } 279