1*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 2*7c478bd9Sstevel@tonic-gate 3*7c478bd9Sstevel@tonic-gate /* 4*7c478bd9Sstevel@tonic-gate * lib/krb5/os/hst_realm.c 5*7c478bd9Sstevel@tonic-gate * 6*7c478bd9Sstevel@tonic-gate * Copyright 1990,1991,2002 by the Massachusetts Institute of Technology. 7*7c478bd9Sstevel@tonic-gate * All Rights Reserved. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 10*7c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 11*7c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 12*7c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 15*7c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 16*7c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 17*7c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 18*7c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 19*7c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 20*7c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 21*7c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 22*7c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 23*7c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 24*7c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 25*7c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 26*7c478bd9Sstevel@tonic-gate * or implied warranty. 27*7c478bd9Sstevel@tonic-gate * 28*7c478bd9Sstevel@tonic-gate * 29*7c478bd9Sstevel@tonic-gate * krb5_get_host_realm() 30*7c478bd9Sstevel@tonic-gate */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate Figures out the Kerberos realm names for host, filling in a 35*7c478bd9Sstevel@tonic-gate pointer to an argv[] style list of names, terminated with a null pointer. 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate If host is NULL, the local host's realms are determined. 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate If there are no known realms for the host, the filled-in pointer is set 40*7c478bd9Sstevel@tonic-gate to NULL. 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate The pointer array and strings pointed to are all in allocated storage, 43*7c478bd9Sstevel@tonic-gate and should be freed by the caller when finished. 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate returns system errors 46*7c478bd9Sstevel@tonic-gate */ 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* 49*7c478bd9Sstevel@tonic-gate * Implementation notes: 50*7c478bd9Sstevel@tonic-gate * 51*7c478bd9Sstevel@tonic-gate * this implementation only provides one realm per host, using the same 52*7c478bd9Sstevel@tonic-gate * mapping file used in kerberos v4. 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate * Given a fully-qualified domain-style primary host name, 55*7c478bd9Sstevel@tonic-gate * return the name of the Kerberos realm for the host. 56*7c478bd9Sstevel@tonic-gate * If the hostname contains no discernable domain, or an error occurs, 57*7c478bd9Sstevel@tonic-gate * return the local realm name, as supplied by krb5_get_default_realm(). 58*7c478bd9Sstevel@tonic-gate * If the hostname contains a domain, but no translation is found, 59*7c478bd9Sstevel@tonic-gate * the hostname's domain is converted to upper-case and returned. 60*7c478bd9Sstevel@tonic-gate * 61*7c478bd9Sstevel@tonic-gate * The format of each line of the translation file is: 62*7c478bd9Sstevel@tonic-gate * domain_name kerberos_realm 63*7c478bd9Sstevel@tonic-gate * -or- 64*7c478bd9Sstevel@tonic-gate * host_name kerberos_realm 65*7c478bd9Sstevel@tonic-gate * 66*7c478bd9Sstevel@tonic-gate * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU) 67*7c478bd9Sstevel@tonic-gate * host names should be in the usual form (e.g. FOO.BAR.BAZ) 68*7c478bd9Sstevel@tonic-gate */ 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate #define NEED_SOCKETS 71*7c478bd9Sstevel@tonic-gate #include "k5-int.h" 72*7c478bd9Sstevel@tonic-gate #include "os-proto.h" 73*7c478bd9Sstevel@tonic-gate #include <ctype.h> 74*7c478bd9Sstevel@tonic-gate #include <stdio.h> 75*7c478bd9Sstevel@tonic-gate #ifdef HAVE_STRING_H 76*7c478bd9Sstevel@tonic-gate #include <string.h> 77*7c478bd9Sstevel@tonic-gate #else 78*7c478bd9Sstevel@tonic-gate #include <strings.h> 79*7c478bd9Sstevel@tonic-gate #endif 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate #ifdef KRB5_DNS_LOOKUP 82*7c478bd9Sstevel@tonic-gate #ifdef WSHELPER 83*7c478bd9Sstevel@tonic-gate #include <wshelper.h> 84*7c478bd9Sstevel@tonic-gate #else /* WSHELPER */ 85*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 86*7c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 87*7c478bd9Sstevel@tonic-gate #ifndef T_TXT /* not defined on SunOS 4 */ 88*7c478bd9Sstevel@tonic-gate # define T_TXT 15 89*7c478bd9Sstevel@tonic-gate #endif 90*7c478bd9Sstevel@tonic-gate #include <resolv.h> 91*7c478bd9Sstevel@tonic-gate #include <netdb.h> 92*7c478bd9Sstevel@tonic-gate #endif /* WSHELPER */ 93*7c478bd9Sstevel@tonic-gate #endif /* KRB5_DNS_LOOKUP */ 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate #include <fake-addrinfo.h> 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* for old Unixes and friends ... */ 98*7c478bd9Sstevel@tonic-gate #ifndef MAXHOSTNAMELEN 99*7c478bd9Sstevel@tonic-gate #define MAXHOSTNAMELEN 64 100*7c478bd9Sstevel@tonic-gate #endif 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate #define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1) 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate #ifdef KRB5_DNS_LOOKUP 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * Try to look up a TXT record pointing to a Kerberos realm 107*7c478bd9Sstevel@tonic-gate */ 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate krb5_error_code 110*7c478bd9Sstevel@tonic-gate krb5_try_realm_txt_rr(const char *prefix, const char *name, char **realm) 111*7c478bd9Sstevel@tonic-gate { 112*7c478bd9Sstevel@tonic-gate union { 113*7c478bd9Sstevel@tonic-gate unsigned char bytes[2048]; 114*7c478bd9Sstevel@tonic-gate HEADER hdr; 115*7c478bd9Sstevel@tonic-gate } answer; 116*7c478bd9Sstevel@tonic-gate unsigned char *p; 117*7c478bd9Sstevel@tonic-gate char host[MAX_DNS_NAMELEN], *h; 118*7c478bd9Sstevel@tonic-gate int size; 119*7c478bd9Sstevel@tonic-gate int type, rrclass, numanswers, numqueries, rdlen, len; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * Form our query, and send it via DNS 123*7c478bd9Sstevel@tonic-gate */ 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate if (name == NULL || name[0] == '\0') { 126*7c478bd9Sstevel@tonic-gate if (strlen (prefix) >= sizeof(host)-1) 127*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 128*7c478bd9Sstevel@tonic-gate strcpy(host,prefix); 129*7c478bd9Sstevel@tonic-gate } else { 130*7c478bd9Sstevel@tonic-gate if ( strlen(prefix) + strlen(name) + 3 > MAX_DNS_NAMELEN ) 131*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 132*7c478bd9Sstevel@tonic-gate /*LINTED*/ 133*7c478bd9Sstevel@tonic-gate sprintf(host,"%s.%s", prefix, name); 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* Realm names don't (normally) end with ".", but if the query 136*7c478bd9Sstevel@tonic-gate doesn't end with "." and doesn't get an answer as is, the 137*7c478bd9Sstevel@tonic-gate resolv code will try appending the local domain. Since the 138*7c478bd9Sstevel@tonic-gate realm names are absolutes, let's stop that. 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate But only if a name has been specified. If we are performing 141*7c478bd9Sstevel@tonic-gate a search on the prefix alone then the intention is to allow 142*7c478bd9Sstevel@tonic-gate the local domain or domain search lists to be expanded. 143*7c478bd9Sstevel@tonic-gate */ 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate h = host + strlen (host); 146*7c478bd9Sstevel@tonic-gate if ((h > host) && (h[-1] != '.') && ((h - host + 1) < sizeof(host))) 147*7c478bd9Sstevel@tonic-gate strcpy (h, "."); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate size = res_search(host, C_IN, T_TXT, answer.bytes, sizeof(answer.bytes)); 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate if ((size < sizeof(HEADER)) || (size > sizeof(answer.bytes))) 152*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate p = answer.bytes; 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate numqueries = ntohs(answer.hdr.qdcount); 157*7c478bd9Sstevel@tonic-gate numanswers = ntohs(answer.hdr.ancount); 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate p += sizeof(HEADER); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * We need to skip over the questions before we can get to the answers, 163*7c478bd9Sstevel@tonic-gate * which means we have to iterate over every query record. We use 164*7c478bd9Sstevel@tonic-gate * dn_expand to tell us how long each compressed name is. 165*7c478bd9Sstevel@tonic-gate */ 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate #define INCR_CHECK(x, y) x += y; if (x > size + answer.bytes) \ 168*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN 169*7c478bd9Sstevel@tonic-gate #define CHECK(x, y) if (x + y > size + answer.bytes) \ 170*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN 171*7c478bd9Sstevel@tonic-gate #define NTOHSP(x, y) x[0] << 8 | x[1]; x += y 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate while (numqueries--) { 174*7c478bd9Sstevel@tonic-gate len = dn_expand(answer.bytes, answer.bytes + size, p, host, 175*7c478bd9Sstevel@tonic-gate sizeof(host)); 176*7c478bd9Sstevel@tonic-gate if (len < 0) 177*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 178*7c478bd9Sstevel@tonic-gate INCR_CHECK(p, len + 4); /* Name plus type plus class */ 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* 182*7c478bd9Sstevel@tonic-gate * We're now pointing at the answer records. Process the first 183*7c478bd9Sstevel@tonic-gate * TXT record we find. 184*7c478bd9Sstevel@tonic-gate */ 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate while (numanswers--) { 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* First the name; use dn_expand to get the compressed size */ 189*7c478bd9Sstevel@tonic-gate len = dn_expand(answer.bytes, answer.bytes + size, p, 190*7c478bd9Sstevel@tonic-gate host, sizeof(host)); 191*7c478bd9Sstevel@tonic-gate if (len < 0) 192*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 193*7c478bd9Sstevel@tonic-gate INCR_CHECK(p, len); 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate /* Next is the query type */ 196*7c478bd9Sstevel@tonic-gate CHECK(p, 2); 197*7c478bd9Sstevel@tonic-gate type = NTOHSP(p,2); 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate /* Next is the query class; also skip over 4 byte TTL */ 200*7c478bd9Sstevel@tonic-gate CHECK(p,6); 201*7c478bd9Sstevel@tonic-gate rrclass = NTOHSP(p,6); 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate /* Record data length - make sure we aren't truncated */ 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate CHECK(p,2); 206*7c478bd9Sstevel@tonic-gate rdlen = NTOHSP(p,2); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate if (p + rdlen > answer.bytes + size) 209*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * If this is a TXT record, return the string. Note that the 213*7c478bd9Sstevel@tonic-gate * string has a 1-byte length in the front 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate /* XXX What about flagging multiple TXT records as an error? */ 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate if (rrclass == C_IN && type == T_TXT) { 218*7c478bd9Sstevel@tonic-gate len = *p++; 219*7c478bd9Sstevel@tonic-gate if (p + len > answer.bytes + size) 220*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 221*7c478bd9Sstevel@tonic-gate *realm = malloc(len + 1); 222*7c478bd9Sstevel@tonic-gate if (*realm == NULL) 223*7c478bd9Sstevel@tonic-gate return ENOMEM; 224*7c478bd9Sstevel@tonic-gate strncpy(*realm, (char *) p, len); 225*7c478bd9Sstevel@tonic-gate (*realm)[len] = '\0'; 226*7c478bd9Sstevel@tonic-gate /* Avoid a common error. */ 227*7c478bd9Sstevel@tonic-gate if ( (*realm)[len-1] == '.' ) 228*7c478bd9Sstevel@tonic-gate (*realm)[len-1] = '\0'; 229*7c478bd9Sstevel@tonic-gate return 0; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN; 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate #endif /* KRB5_DNS_LOOKUP */ 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate krb5_error_code krb5int_translate_gai_error (int); 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate static krb5_error_code 240*7c478bd9Sstevel@tonic-gate krb5int_get_fq_hostname (char *buf, size_t bufsize, const char *name) 241*7c478bd9Sstevel@tonic-gate { 242*7c478bd9Sstevel@tonic-gate struct addrinfo *ai, hints; 243*7c478bd9Sstevel@tonic-gate int err; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate memset (&hints, 0, sizeof (hints)); 246*7c478bd9Sstevel@tonic-gate hints.ai_family = AF_UNSPEC; 247*7c478bd9Sstevel@tonic-gate hints.ai_flags = AI_CANONNAME; 248*7c478bd9Sstevel@tonic-gate err = getaddrinfo (name, 0, &hints, &ai); 249*7c478bd9Sstevel@tonic-gate if (err) 250*7c478bd9Sstevel@tonic-gate return krb5int_translate_gai_error (err); 251*7c478bd9Sstevel@tonic-gate if (ai->ai_canonname == 0) 252*7c478bd9Sstevel@tonic-gate return KRB5_EAI_FAIL; 253*7c478bd9Sstevel@tonic-gate strncpy (buf, ai->ai_canonname, bufsize); 254*7c478bd9Sstevel@tonic-gate buf[bufsize-1] = 0; 255*7c478bd9Sstevel@tonic-gate freeaddrinfo (ai); 256*7c478bd9Sstevel@tonic-gate return 0; 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /* Get the local host name, try to make it fully-qualified. 260*7c478bd9Sstevel@tonic-gate Always return a null-terminated string. 261*7c478bd9Sstevel@tonic-gate Might return an error if gethostname fails. */ 262*7c478bd9Sstevel@tonic-gate krb5_error_code 263*7c478bd9Sstevel@tonic-gate krb5int_get_fq_local_hostname (char *buf, size_t bufsiz) 264*7c478bd9Sstevel@tonic-gate { 265*7c478bd9Sstevel@tonic-gate buf[0] = 0; 266*7c478bd9Sstevel@tonic-gate if (gethostname (buf, bufsiz) == -1) 267*7c478bd9Sstevel@tonic-gate return SOCKET_ERRNO; 268*7c478bd9Sstevel@tonic-gate buf[bufsiz - 1] = 0; 269*7c478bd9Sstevel@tonic-gate return krb5int_get_fq_hostname (buf, bufsiz, buf); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate krb5_error_code KRB5_CALLCONV 273*7c478bd9Sstevel@tonic-gate krb5_get_host_realm(krb5_context context, const char *host, char ***realmsp) 274*7c478bd9Sstevel@tonic-gate { 275*7c478bd9Sstevel@tonic-gate char **retrealms; 276*7c478bd9Sstevel@tonic-gate char *default_realm, *realm, *cp, *temp_realm; 277*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 278*7c478bd9Sstevel@tonic-gate int l; 279*7c478bd9Sstevel@tonic-gate char local_host[MAX_DNS_NAMELEN+1]; 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate if (host) { 282*7c478bd9Sstevel@tonic-gate /* Filter out numeric addresses if the caller utterly failed to 283*7c478bd9Sstevel@tonic-gate convert them to names. */ 284*7c478bd9Sstevel@tonic-gate /* IPv4 - dotted quads only */ 285*7c478bd9Sstevel@tonic-gate if (strspn(host, "01234567890.") == strlen(host)) { 286*7c478bd9Sstevel@tonic-gate /* All numbers and dots... if it's three dots, it's an 287*7c478bd9Sstevel@tonic-gate IP address, and we reject it. But "12345" could be 288*7c478bd9Sstevel@tonic-gate a local hostname, couldn't it? We'll just assume 289*7c478bd9Sstevel@tonic-gate that a name with three dots is not meant to be an 290*7c478bd9Sstevel@tonic-gate all-numeric hostname three all-numeric domains down 291*7c478bd9Sstevel@tonic-gate from the current domain. */ 292*7c478bd9Sstevel@tonic-gate int ndots = 0; 293*7c478bd9Sstevel@tonic-gate const char *p; 294*7c478bd9Sstevel@tonic-gate for (p = host; *p; p++) 295*7c478bd9Sstevel@tonic-gate if (*p == '.') 296*7c478bd9Sstevel@tonic-gate ndots++; 297*7c478bd9Sstevel@tonic-gate if (ndots == 3) 298*7c478bd9Sstevel@tonic-gate return KRB5_ERR_NUMERIC_REALM; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate if (strchr(host, ':')) 301*7c478bd9Sstevel@tonic-gate /* IPv6 numeric address form? Bye bye. */ 302*7c478bd9Sstevel@tonic-gate return KRB5_ERR_NUMERIC_REALM; 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* Should probably error out if strlen(host) > MAX_DNS_NAMELEN. */ 305*7c478bd9Sstevel@tonic-gate strncpy(local_host, host, sizeof(local_host)); 306*7c478bd9Sstevel@tonic-gate local_host[sizeof(local_host) - 1] = '\0'; 307*7c478bd9Sstevel@tonic-gate } else { 308*7c478bd9Sstevel@tonic-gate retval = krb5int_get_fq_local_hostname (local_host, 309*7c478bd9Sstevel@tonic-gate sizeof (local_host)); 310*7c478bd9Sstevel@tonic-gate if (retval) 311*7c478bd9Sstevel@tonic-gate return retval; 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate for (cp = local_host; *cp; cp++) { 315*7c478bd9Sstevel@tonic-gate if (isupper((int) (*cp))) 316*7c478bd9Sstevel@tonic-gate *cp = tolower((int) *cp); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate l = strlen(local_host); 319*7c478bd9Sstevel@tonic-gate /* strip off trailing dot */ 320*7c478bd9Sstevel@tonic-gate if (l && local_host[l-1] == '.') 321*7c478bd9Sstevel@tonic-gate local_host[l-1] = 0; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate Search for the best match for the host or domain. 325*7c478bd9Sstevel@tonic-gate Example: Given a host a.b.c.d, try to match on: 326*7c478bd9Sstevel@tonic-gate 1) A.B.C.D 327*7c478bd9Sstevel@tonic-gate 2) .B.C.D 328*7c478bd9Sstevel@tonic-gate 3) B.C.D 329*7c478bd9Sstevel@tonic-gate 4) .C.D 330*7c478bd9Sstevel@tonic-gate 5) C.D 331*7c478bd9Sstevel@tonic-gate 6) .D 332*7c478bd9Sstevel@tonic-gate 7) D 333*7c478bd9Sstevel@tonic-gate */ 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate cp = local_host; 336*7c478bd9Sstevel@tonic-gate realm = default_realm = (char *)NULL; 337*7c478bd9Sstevel@tonic-gate temp_realm = 0; 338*7c478bd9Sstevel@tonic-gate while (cp) { 339*7c478bd9Sstevel@tonic-gate retval = profile_get_string(context->profile, "domain_realm", cp, 340*7c478bd9Sstevel@tonic-gate 0, (char *)NULL, &temp_realm); 341*7c478bd9Sstevel@tonic-gate if (retval) 342*7c478bd9Sstevel@tonic-gate return retval; 343*7c478bd9Sstevel@tonic-gate if (temp_realm != (char *)NULL) 344*7c478bd9Sstevel@tonic-gate break; /* Match found */ 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate /* Setup for another test */ 347*7c478bd9Sstevel@tonic-gate if (*cp == '.') { 348*7c478bd9Sstevel@tonic-gate cp++; 349*7c478bd9Sstevel@tonic-gate if (default_realm == (char *)NULL) { 350*7c478bd9Sstevel@tonic-gate /* If nothing else works, use the host's domain */ 351*7c478bd9Sstevel@tonic-gate default_realm = cp; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate } else { 354*7c478bd9Sstevel@tonic-gate cp = strchr(cp, '.'); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate if (temp_realm) { 358*7c478bd9Sstevel@tonic-gate realm = malloc(strlen(temp_realm) + 1); 359*7c478bd9Sstevel@tonic-gate if (!realm) { 360*7c478bd9Sstevel@tonic-gate profile_release_string(temp_realm); 361*7c478bd9Sstevel@tonic-gate return ENOMEM; 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate strcpy(realm, temp_realm); 364*7c478bd9Sstevel@tonic-gate profile_release_string(temp_realm); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate #ifdef KRB5_DNS_LOOKUP 368*7c478bd9Sstevel@tonic-gate if (realm == (char *)NULL) { 369*7c478bd9Sstevel@tonic-gate int use_dns = _krb5_use_dns_realm(context); 370*7c478bd9Sstevel@tonic-gate if ( use_dns ) { 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * Since this didn't appear in our config file, try looking 373*7c478bd9Sstevel@tonic-gate * it up via DNS. Look for a TXT records of the form: 374*7c478bd9Sstevel@tonic-gate * 375*7c478bd9Sstevel@tonic-gate * _kerberos.<hostname> 376*7c478bd9Sstevel@tonic-gate * 377*7c478bd9Sstevel@tonic-gate */ 378*7c478bd9Sstevel@tonic-gate cp = local_host; 379*7c478bd9Sstevel@tonic-gate do { 380*7c478bd9Sstevel@tonic-gate retval = krb5_try_realm_txt_rr("_kerberos", cp, &realm); 381*7c478bd9Sstevel@tonic-gate cp = strchr(cp,'.'); 382*7c478bd9Sstevel@tonic-gate if (cp) 383*7c478bd9Sstevel@tonic-gate cp++; 384*7c478bd9Sstevel@tonic-gate } while (retval && cp && cp[0]); 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate #endif /* KRB5_DNS_LOOKUP */ 388*7c478bd9Sstevel@tonic-gate if (realm == (char *)NULL) { 389*7c478bd9Sstevel@tonic-gate if (default_realm != (char *)NULL) { 390*7c478bd9Sstevel@tonic-gate /* We are defaulting to the realm of the host */ 391*7c478bd9Sstevel@tonic-gate if (!(cp = (char *)malloc(strlen(default_realm)+1))) 392*7c478bd9Sstevel@tonic-gate return ENOMEM; 393*7c478bd9Sstevel@tonic-gate strcpy(cp, default_realm); 394*7c478bd9Sstevel@tonic-gate realm = cp; 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate /* Assume the realm name is upper case */ 397*7c478bd9Sstevel@tonic-gate for (cp = realm; *cp; cp++) 398*7c478bd9Sstevel@tonic-gate if (islower((int) (*cp))) 399*7c478bd9Sstevel@tonic-gate *cp = toupper((int) *cp); 400*7c478bd9Sstevel@tonic-gate } else { 401*7c478bd9Sstevel@tonic-gate /* We are defaulting to the local realm */ 402*7c478bd9Sstevel@tonic-gate retval = krb5_get_default_realm(context, &realm); 403*7c478bd9Sstevel@tonic-gate if (retval) { 404*7c478bd9Sstevel@tonic-gate return retval; 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate if (!(retrealms = (char **)calloc(2, sizeof(*retrealms)))) { 409*7c478bd9Sstevel@tonic-gate if (realm != (char *)NULL) 410*7c478bd9Sstevel@tonic-gate free(realm); 411*7c478bd9Sstevel@tonic-gate return ENOMEM; 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate retrealms[0] = realm; 415*7c478bd9Sstevel@tonic-gate retrealms[1] = 0; 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate *realmsp = retrealms; 418*7c478bd9Sstevel@tonic-gate return 0; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate #if defined(_WIN32) && !defined(__CYGWIN32__) 422*7c478bd9Sstevel@tonic-gate # ifndef EAFNOSUPPORT 423*7c478bd9Sstevel@tonic-gate # define EAFNOSUPPORT WSAEAFNOSUPPORT 424*7c478bd9Sstevel@tonic-gate # endif 425*7c478bd9Sstevel@tonic-gate #endif 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate krb5_error_code 428*7c478bd9Sstevel@tonic-gate krb5int_translate_gai_error (int num) 429*7c478bd9Sstevel@tonic-gate { 430*7c478bd9Sstevel@tonic-gate switch (num) { 431*7c478bd9Sstevel@tonic-gate #ifdef EAI_ADDRFAMILY 432*7c478bd9Sstevel@tonic-gate case EAI_ADDRFAMILY: 433*7c478bd9Sstevel@tonic-gate return EAFNOSUPPORT; 434*7c478bd9Sstevel@tonic-gate #endif 435*7c478bd9Sstevel@tonic-gate case EAI_AGAIN: 436*7c478bd9Sstevel@tonic-gate return EAGAIN; 437*7c478bd9Sstevel@tonic-gate case EAI_BADFLAGS: 438*7c478bd9Sstevel@tonic-gate return EINVAL; 439*7c478bd9Sstevel@tonic-gate case EAI_FAIL: 440*7c478bd9Sstevel@tonic-gate return KRB5_EAI_FAIL; 441*7c478bd9Sstevel@tonic-gate case EAI_FAMILY: 442*7c478bd9Sstevel@tonic-gate return EAFNOSUPPORT; 443*7c478bd9Sstevel@tonic-gate case EAI_MEMORY: 444*7c478bd9Sstevel@tonic-gate return ENOMEM; 445*7c478bd9Sstevel@tonic-gate #if EAI_NODATA != EAI_NONAME 446*7c478bd9Sstevel@tonic-gate case EAI_NODATA: 447*7c478bd9Sstevel@tonic-gate return KRB5_EAI_NODATA; 448*7c478bd9Sstevel@tonic-gate #endif 449*7c478bd9Sstevel@tonic-gate case EAI_NONAME: 450*7c478bd9Sstevel@tonic-gate return KRB5_EAI_NONAME; 451*7c478bd9Sstevel@tonic-gate case EAI_SERVICE: 452*7c478bd9Sstevel@tonic-gate return KRB5_EAI_SERVICE; 453*7c478bd9Sstevel@tonic-gate case EAI_SOCKTYPE: 454*7c478bd9Sstevel@tonic-gate return EINVAL; 455*7c478bd9Sstevel@tonic-gate #ifdef EAI_SYSTEM 456*7c478bd9Sstevel@tonic-gate case EAI_SYSTEM: 457*7c478bd9Sstevel@tonic-gate return errno; 458*7c478bd9Sstevel@tonic-gate #endif 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate /* abort (); */ 461*7c478bd9Sstevel@tonic-gate return -1; 462*7c478bd9Sstevel@tonic-gate } 463