X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=src%2Flib%2Fkrb5%2Fos%2Fsn2princ.c;h=f149febdadef32235a33b70fefff6b27f3c6e72f;hb=c3ab5fe0b01a68b14d5657740006488721b48b7b;hp=16b52df074cc43c09e3dcd10de1e5a019cd825fe;hpb=33bf8148d5adc0627984e61c9a4a4d1c2543f1f3;p=krb5.git diff --git a/src/lib/krb5/os/sn2princ.c b/src/lib/krb5/os/sn2princ.c index 16b52df07..f149febda 100644 --- a/src/lib/krb5/os/sn2princ.c +++ b/src/lib/krb5/os/sn2princ.c @@ -1,14 +1,14 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/os/sn2princ.c */ /* - * lib/krb5/os/sn2princ.c - * - * Copyright 1991 by the Massachusetts Institute of Technology. + * Copyright 1991,2002 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 @@ -22,121 +22,186 @@ * 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. - * - * - * Convert a hostname and service name to a principal in the "standard" - * form. */ -#define NEED_SOCKETS +/* Convert a hostname and service name to a principal in the "standard" + * form. */ + #include "k5-int.h" +#include "os-proto.h" +#include "fake-addrinfo.h" #include #ifdef HAVE_SYS_PARAM_H #include #endif -KRB5_DLLIMP krb5_error_code KRB5_CALLCONV -krb5_sname_to_principal(context, hostname, sname, type, ret_princ) - krb5_context context; - const char FAR * hostname; - const char FAR * sname; - krb5_int32 type; - krb5_principal FAR * ret_princ; +#if !defined(DEFAULT_RDNS_LOOKUP) +#define DEFAULT_RDNS_LOOKUP 1 +#endif + +static int +maybe_use_reverse_dns (krb5_context context, int defalt) +{ + krb5_error_code code; + char * value = NULL; + int use_rdns = 0; + + code = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_RDNS, 0, 0, &value); + if (code) + return defalt; + + if (value == 0) + return defalt; + + use_rdns = _krb5_conf_boolean(value); + profile_release_string(value); + return use_rdns; +} + + +krb5_error_code KRB5_CALLCONV +krb5_sname_to_principal(krb5_context context, const char *hostname, const char *sname, krb5_int32 type, krb5_principal *ret_princ) { - struct hostent *hp; char **hrealms, *realm, *remote_host; krb5_error_code retval; register char *cp; char localname[MAXHOSTNAMELEN]; +#ifdef DEBUG_REFERRALS + printf("krb5_sname_to_principal(host=%s, sname=%s, type=%d)\n",hostname,sname,type); + printf(" name types: 0=unknown, 3=srv_host\n"); +#endif if ((type == KRB5_NT_UNKNOWN) || - (type == KRB5_NT_SRV_HST)) { - - /* if hostname is NULL, use local hostname */ - if (! hostname) { - if (gethostname(localname, MAXHOSTNAMELEN)) - return SOCKET_ERRNO; - hostname = localname; - } - - /* if sname is NULL, use "host" */ - if (! sname) - sname = "host"; - - /* copy the hostname into non-volatile storage */ - - if (type == KRB5_NT_SRV_HST) { - char *addr; - - if (!(hp = gethostbyname(hostname))) - return KRB5_ERR_BAD_HOSTNAME; - remote_host = strdup(hp->h_name); - if (!remote_host) - return ENOMEM; - /* - * Do a reverse resolution to get the full name, just in - * case there's some funny business going on. If there - * isn't an in-addr record, give up. - */ - addr = malloc(hp->h_length); - if (!addr) - return ENOMEM; - memcpy(addr, hp->h_addr, hp->h_length); - hp = gethostbyaddr(addr, hp->h_length, hp->h_addrtype); - free(addr); - if (hp) { - free(remote_host); - remote_host = strdup(hp->h_name); - if (!remote_host) - return ENOMEM; - } - } else /* type == KRB5_NT_UNKNOWN */ { - remote_host = strdup((char *) hostname); - } - if (!remote_host) - return ENOMEM; - - if (type == KRB5_NT_SRV_HST) - for (cp = remote_host; *cp; cp++) - if (isupper((int) (*cp))) - *cp = tolower(*cp); - - /* - * Windows NT5's broken resolver gratuitously tacks on a - * trailing period to the hostname (at least it does in - * Beta2). Find and remove it. - */ - if (remote_host[0]) { - cp = remote_host + strlen(remote_host)-1; - if (*cp == '.') - *cp = 0; - } - - - if ((retval = krb5_get_host_realm(context, remote_host, &hrealms))) { - free(remote_host); - return retval; - } - if (!hrealms[0]) { - free(remote_host); - krb5_xfree(hrealms); - return KRB5_ERR_HOST_REALM_UNKNOWN; - } - realm = hrealms[0]; - - retval = krb5_build_principal(context, ret_princ, strlen(realm), - realm, sname, remote_host, - (char *)0); - - krb5_princ_type(context, *ret_princ) = type; - - free(remote_host); - - krb5_free_host_realm(context, hrealms); - return retval; + (type == KRB5_NT_SRV_HST)) { + + /* if hostname is NULL, use local hostname */ + if (! hostname) { + if (gethostname(localname, MAXHOSTNAMELEN)) + return SOCKET_ERRNO; + hostname = localname; + } + + /* if sname is NULL, use "host" */ + if (! sname) + sname = "host"; + + /* copy the hostname into non-volatile storage */ + + if (type == KRB5_NT_SRV_HST) { + struct addrinfo *ai = NULL, hints; + int err; + char hnamebuf[NI_MAXHOST]; + + /* Note that the old code would accept numeric addresses, + and if the gethostbyaddr step could convert them to + real hostnames, you could actually get reasonable + results. If the mapping failed, you'd get dotted + triples as realm names. *sigh* + + The latter has been fixed in hst_realm.c, but we should + keep supporting numeric addresses if they do have + hostnames associated. */ + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + err = getaddrinfo(hostname, 0, &hints, &ai); + if (err) { +#ifdef DEBUG_REFERRALS + printf("sname_to_princ: failed to canonicalize %s; using as-is", hostname); +#endif + } + remote_host = strdup((ai && ai->ai_canonname) ? ai->ai_canonname : hostname); + if (!remote_host) { + if(ai) + freeaddrinfo(ai); + return ENOMEM; + } + + if ((!err) && maybe_use_reverse_dns(context, DEFAULT_RDNS_LOOKUP)) { + /* + * Do a reverse resolution to get the full name, just in + * case there's some funny business going on. If there + * isn't an in-addr record, give up. + */ + /* XXX: This is *so* bogus. There are several cases where + this won't get us the canonical name of the host, but + this is what we've trained people to expect. We'll + probably fix it at some point, but let's try to + preserve the current behavior and only shake things up + once when it comes time to fix this lossage. */ + err = getnameinfo(ai->ai_addr, ai->ai_addrlen, + hnamebuf, sizeof(hnamebuf), 0, 0, NI_NAMEREQD); + freeaddrinfo(ai); + if (err == 0) { + free(remote_host); + remote_host = strdup(hnamebuf); + if (!remote_host) + return ENOMEM; + } + } else + freeaddrinfo(ai); + } else /* type == KRB5_NT_UNKNOWN */ { + remote_host = strdup(hostname); + } + if (!remote_host) + return ENOMEM; +#ifdef DEBUG_REFERRALS + printf("sname_to_princ: hostname <%s> after rdns processing\n",remote_host); +#endif + + if (type == KRB5_NT_SRV_HST) + for (cp = remote_host; *cp; cp++) + if (isupper((unsigned char) (*cp))) + *cp = tolower((unsigned char) (*cp)); + + /* + * Windows NT5's broken resolver gratuitously tacks on a + * trailing period to the hostname (at least it does in + * Beta2). Find and remove it. + */ + if (remote_host[0]) { + cp = remote_host + strlen(remote_host)-1; + if (*cp == '.') + *cp = 0; + } + + + if ((retval = krb5_get_host_realm(context, remote_host, &hrealms))) { + free(remote_host); + return retval; + } + +#ifdef DEBUG_REFERRALS + printf("sname_to_princ: realm <%s> after krb5_get_host_realm\n",hrealms[0]); +#endif + + if (!hrealms[0]) { + free(remote_host); + free(hrealms); + return KRB5_ERR_HOST_REALM_UNKNOWN; + } + realm = hrealms[0]; + + retval = krb5_build_principal(context, ret_princ, strlen(realm), + realm, sname, remote_host, + (char *)0); + if (retval == 0) + krb5_princ_type(context, *ret_princ) = type; + +#ifdef DEBUG_REFERRALS + printf("krb5_sname_to_principal returning\n"); + printf("realm: <%s>, sname: <%s>, remote_host: <%s>\n", + realm,sname,remote_host); + krb5int_dbgref_dump_principal("krb5_sname_to_principal",*ret_princ); +#endif + + free(remote_host); + + krb5_free_host_realm(context, hrealms); + return retval; } else { - return KRB5_SNAME_UNSUPP_NAMETYPE; + return KRB5_SNAME_UNSUPP_NAMETYPE; } } -