get_host_realm.c revision 55682
155682Smarkm/*
255682Smarkm * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "krb5_locl.h"
3555682Smarkm#include <resolve.h>
3655682Smarkm
3755682SmarkmRCSID("$Id: get_host_realm.c,v 1.25 1999/12/11 23:14:07 assar Exp $");
3855682Smarkm
3955682Smarkm/* To automagically find the correct realm of a host (without
4055682Smarkm * [domain_realm] in krb5.conf) add a text record for your domain with
4155682Smarkm * the name of your realm, like this:
4255682Smarkm *
4355682Smarkm * krb5-realm	IN	TXT	FOO.SE
4455682Smarkm *
4555682Smarkm * The search is recursive, so you can add entries for specific
4655682Smarkm * hosts. To find the realm of host a.b.c, it first tries
4755682Smarkm * krb5-realm.a.b.c, then krb5-realm.b.c and so on.
4855682Smarkm *
4955682Smarkm * Also supported is _kerberos (following draft-ietf-cat-krb-dns-locate-01.txt)
5055682Smarkm *
5155682Smarkm */
5255682Smarkm
5355682Smarkmstatic int
5455682Smarkmcopy_txt_to_realms (struct resource_record *head,
5555682Smarkm		    krb5_realm **realms)
5655682Smarkm{
5755682Smarkm    struct resource_record *rr;
5855682Smarkm    int n, i;
5955682Smarkm
6055682Smarkm    for(n = 0, rr = head; rr; rr = rr->next)
6155682Smarkm	if (rr->type == T_TXT)
6255682Smarkm	    ++n;
6355682Smarkm
6455682Smarkm    if (n == 0)
6555682Smarkm	return -1;
6655682Smarkm
6755682Smarkm    *realms = malloc ((n + 1) * sizeof(krb5_realm));
6855682Smarkm    if (*realms == NULL)
6955682Smarkm	return -1;
7055682Smarkm
7155682Smarkm    for (i = 0; i < n + 1; ++i)
7255682Smarkm	(*realms)[i] = NULL;
7355682Smarkm
7455682Smarkm    for (i = 0, rr = head; rr; rr = rr->next) {
7555682Smarkm	if (rr->type == T_TXT) {
7655682Smarkm	    char *tmp;
7755682Smarkm
7855682Smarkm	    tmp = strdup(rr->u.txt);
7955682Smarkm	    if (tmp == NULL) {
8055682Smarkm		for (i = 0; i < n; ++i)
8155682Smarkm		    free ((*realms)[i]);
8255682Smarkm		free (*realms);
8355682Smarkm		return -1;
8455682Smarkm	    }
8555682Smarkm	    (*realms)[i] = tmp;
8655682Smarkm	    ++i;
8755682Smarkm	}
8855682Smarkm    }
8955682Smarkm    return 0;
9055682Smarkm}
9155682Smarkm
9255682Smarkmstatic int
9355682Smarkmdns_find_realm(krb5_context context,
9455682Smarkm	       const char *domain,
9555682Smarkm	       const char *dom_string,
9655682Smarkm	       krb5_realm **realms)
9755682Smarkm{
9855682Smarkm    char dom[MAXHOSTNAMELEN];
9955682Smarkm    struct dns_reply *r;
10055682Smarkm    int ret;
10155682Smarkm
10255682Smarkm    if(*domain == '.')
10355682Smarkm	domain++;
10455682Smarkm    snprintf(dom, sizeof(dom), "%s.%s.", dom_string, domain);
10555682Smarkm    r = dns_lookup(dom, "TXT");
10655682Smarkm    if(r == NULL)
10755682Smarkm	return -1;
10855682Smarkm
10955682Smarkm    ret = copy_txt_to_realms (r->head, realms);
11055682Smarkm    dns_free_data(r);
11155682Smarkm    return ret;
11255682Smarkm}
11355682Smarkm
11455682Smarkm/*
11555682Smarkm * Try to figure out what realms host in `domain' belong to from the
11655682Smarkm * configuration file.
11755682Smarkm */
11855682Smarkm
11955682Smarkmstatic int
12055682Smarkmconfig_find_realm(krb5_context context,
12155682Smarkm		  const char *domain,
12255682Smarkm		  krb5_realm **realms)
12355682Smarkm{
12455682Smarkm    char **tmp = krb5_config_get_strings (context, NULL,
12555682Smarkm					  "domain_realm",
12655682Smarkm					  domain,
12755682Smarkm					  NULL);
12855682Smarkm
12955682Smarkm    if (tmp == NULL)
13055682Smarkm	return -1;
13155682Smarkm    *realms = tmp;
13255682Smarkm    return 0;
13355682Smarkm}
13455682Smarkm
13555682Smarkm/*
13655682Smarkm * This function assumes that `host' is a FQDN (and doesn't handle the
13755682Smarkm * special case of host == NULL either).
13855682Smarkm * Try to find mapping in the config file or DNS and it that fails,
13955682Smarkm * fall back to guessing
14055682Smarkm */
14155682Smarkm
14255682Smarkmkrb5_error_code
14355682Smarkmkrb5_get_host_realm_int (krb5_context context,
14455682Smarkm			 const char *host,
14555682Smarkm			 krb5_realm **realms)
14655682Smarkm{
14755682Smarkm    const char *p;
14855682Smarkm
14955682Smarkm    for (p = host; p != NULL; p = strchr (p + 1, '.')) {
15055682Smarkm	if(config_find_realm(context, p, realms) == 0)
15155682Smarkm	    return 0;
15255682Smarkm	else if(dns_find_realm(context, p, "krb5-realm", realms) == 0)
15355682Smarkm	    return 0;
15455682Smarkm	else if(dns_find_realm(context, p, "_kerberos", realms) == 0)
15555682Smarkm	    return 0;
15655682Smarkm    }
15755682Smarkm    p = strchr(host, '.');
15855682Smarkm    if(p != NULL) {
15955682Smarkm	p++;
16055682Smarkm	*realms = malloc(2 * sizeof(krb5_realm));
16155682Smarkm	if (*realms == NULL)
16255682Smarkm	    return ENOMEM;
16355682Smarkm
16455682Smarkm	(*realms)[0] = strdup(p);
16555682Smarkm	if((*realms)[0] == NULL) {
16655682Smarkm	    free(*realms);
16755682Smarkm	    return ENOMEM;
16855682Smarkm	}
16955682Smarkm	strupr((*realms)[0]);
17055682Smarkm	(*realms)[1] = NULL;
17155682Smarkm	return 0;
17255682Smarkm    }
17355682Smarkm    return KRB5_ERR_HOST_REALM_UNKNOWN;
17455682Smarkm}
17555682Smarkm
17655682Smarkm/*
17755682Smarkm * Return the realm(s) of `host' as a NULL-terminated list in `realms'.
17855682Smarkm */
17955682Smarkm
18055682Smarkmkrb5_error_code
18155682Smarkmkrb5_get_host_realm(krb5_context context,
18255682Smarkm		    const char *host,
18355682Smarkm		    krb5_realm **realms)
18455682Smarkm{
18555682Smarkm    char hostname[MAXHOSTNAMELEN];
18655682Smarkm
18755682Smarkm    if (host == NULL) {
18855682Smarkm	if (gethostname (hostname, sizeof(hostname)))
18955682Smarkm	    return errno;
19055682Smarkm	host = hostname;
19155682Smarkm    }
19255682Smarkm
19355682Smarkm    return krb5_get_host_realm_int (context, host, realms);
19455682Smarkm}
195