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