#define NEED_SOCKETS
#include "k5-int.h"
#include "fake-addrinfo.h"
#include <ctype.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#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, "libdefaults",
"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)
{
char **hrealms, *realm, *remote_host;
krb5_error_code retval;
register char *cp;
char localname[MAXHOSTNAMELEN];
if ((type == KRB5_NT_UNKNOWN) ||
(type == KRB5_NT_SRV_HST)) {
if (! hostname) {
if (gethostname(localname, MAXHOSTNAMELEN))
return SOCKET_ERRNO;
hostname = localname;
}
if (! sname)
sname = "host";
if (type == KRB5_NT_SRV_HST) {
struct addrinfo *ai, hints;
int err;
char hnamebuf[NI_MAXHOST];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
try_getaddrinfo_again:
err = getaddrinfo(hostname, 0, &hints, &ai);
if (err) {
if (hints.ai_family == AF_INET) {
hints.ai_family = 0;
goto try_getaddrinfo_again;
}
return KRB5_ERR_BAD_HOSTNAME;
}
remote_host = strdup(ai->ai_canonname ? ai->ai_canonname : hostname);
if (!remote_host) {
freeaddrinfo(ai);
return ENOMEM;
}
if (maybe_use_reverse_dns(context, DEFAULT_RDNS_LOOKUP)) {
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 {
remote_host = strdup(hostname);
}
if (!remote_host)
return ENOMEM;
if (type == KRB5_NT_SRV_HST)
for (cp = remote_host; *cp; cp++)
if (isupper((int) (*cp)))
*cp = tolower((int) (*cp));
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;
} else {
return KRB5_SNAME_UNSUPP_NAMETYPE;
}
}