#include "k5-int.h"
#include "os-proto.h"
#include <stdio.h>
#include "foreachaddr.h"
#ifdef KRB5_DNS_LOOKUP
#ifdef WSHELPER
#include <wshelper.h>
#else
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <netdb.h>
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1)
#endif
extern struct hostent *res_gethostbyaddr(const char *addr, int len, int type);
static int krb5int_address_get_realm(void *data, struct sockaddr *addr) {
krb5_context context = data;
struct hostent *he = NULL;
switch (addr->sa_family) {
case AF_INET:
he = res_gethostbyaddr((char*)(&sa2sin(addr)->sin_addr),
sizeof(sa2sin(addr)->sin_addr), AF_INET);
break;
case AF_INET6:
he = res_gethostbyaddr(
(char*)(&sa2sin6(addr)->sin6_addr),
sizeof(sa2sin6(addr)->sin6_addr), AF_INET6);
break;
}
if (he) {
krb5int_fqdn_get_realm(context, he->h_name,
&context->default_realm);
if (context->default_realm != 0) {
return (1);
}
}
return (0);
}
krb5_error_code KRB5_CALLCONV
krb5_get_default_realm(krb5_context context, char **lrealm)
{
char *realm = 0;
char *cp;
char localhost[MAX_DNS_NAMELEN+1];
krb5_error_code retval;
(void) memset(localhost, 0, sizeof(localhost));
if (!context || (context->magic != KV5M_CONTEXT))
return KV5M_CONTEXT;
if (!context->default_realm) {
if ((realm = getenv("KRB5_DEFAULT_REALM")) != NULL) {
context->default_realm = strdup(realm);
if (context->default_realm == NULL)
return ENOMEM;
}
}
if (!context->default_realm) {
context->default_realm = 0;
if (context->profile != 0) {
retval = profile_get_string(context->profile, "libdefaults",
"default_realm", 0, 0,
&realm);
if (!retval && realm) {
context->default_realm = malloc(strlen(realm) + 1);
if (!context->default_realm) {
profile_release_string(realm);
return ENOMEM;
}
strcpy(context->default_realm, realm);
profile_release_string(realm);
}
}
if (context->default_realm == 0) {
#ifdef KRB5_DNS_LOOKUP
if (_krb5_use_dns_realm(context)) {
char * p;
krb5int_get_fq_local_hostname (localhost, sizeof(localhost));
if ( localhost[0] ) {
p = localhost;
do {
retval = krb5_try_realm_txt_rr("_kerberos", p,
&context->default_realm);
p = strchr(p,'.');
if (p)
p++;
} while (retval && p && p[0]);
if (retval)
retval = krb5_try_realm_txt_rr("_kerberos", "",
&context->default_realm);
} else {
retval = krb5_try_realm_txt_rr("_kerberos", "",
&context->default_realm);
}
if (retval) {
return(KRB5_CONFIG_NODEFREALM);
}
} else
#endif
if (getenv("MS_INTEROP") == NULL) {
(void) krb5int_foreach_localaddr(context,
krb5int_address_get_realm, 0, 0);
if (context->default_realm == 0) {
struct __res_state res;
int i;
(void) memset(&res, 0, sizeof (res));
if (res_ninit(&res) == 0) {
for (i = 0; res.dnsrch[i]; i++) {
krb5int_domain_get_realm(context,
res.dnsrch[i], &context->default_realm);
if (context->default_realm != 0)
break;
}
res_ndestroy(&res);
}
}
}
}
}
if (context->default_realm == 0)
return(KRB5_CONFIG_NODEFREALM);
if (context->default_realm[0] == 0) {
free (context->default_realm);
context->default_realm = 0;
return KRB5_CONFIG_NODEFREALM;
}
realm = context->default_realm;
if (!(*lrealm = cp = malloc((unsigned int) strlen(realm) + 1)))
return ENOMEM;
strcpy(cp, realm);
return(0);
}
krb5_error_code KRB5_CALLCONV
krb5_set_default_realm(krb5_context context, const char *lrealm)
{
if (!context || (context->magic != KV5M_CONTEXT))
return KV5M_CONTEXT;
if (context->default_realm) {
free(context->default_realm);
context->default_realm = 0;
}
if (!lrealm) return 0;
context->default_realm = malloc(strlen (lrealm) + 1);
if (!context->default_realm)
return ENOMEM;
strcpy(context->default_realm, lrealm);
return(0);
}
void KRB5_CALLCONV
krb5_free_default_realm(krb5_context context, char *lrealm)
{
free (lrealm);
}