get_host_realm.c revision 78527
155682Smarkm/* 278527Sassar * Copyright (c) 1997 - 2001 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 3778527SassarRCSID("$Id: get_host_realm.c,v 1.28 2001/05/14 06:14:47 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, 14578527Sassar krb5_boolean use_dns, 14655682Smarkm krb5_realm **realms) 14755682Smarkm{ 14855682Smarkm const char *p; 14955682Smarkm 15055682Smarkm for (p = host; p != NULL; p = strchr (p + 1, '.')) { 15155682Smarkm if(config_find_realm(context, p, realms) == 0) 15255682Smarkm return 0; 15378527Sassar else if(use_dns) { 15478527Sassar if(dns_find_realm(context, p, "krb5-realm", realms) == 0) 15578527Sassar return 0; 15678527Sassar if(dns_find_realm(context, p, "_kerberos", realms) == 0) 15778527Sassar return 0; 15878527Sassar } 15955682Smarkm } 16055682Smarkm p = strchr(host, '.'); 16155682Smarkm if(p != NULL) { 16255682Smarkm p++; 16355682Smarkm *realms = malloc(2 * sizeof(krb5_realm)); 16478527Sassar if (*realms == NULL) { 16578527Sassar krb5_set_error_string(context, "malloc: out of memory"); 16655682Smarkm return ENOMEM; 16778527Sassar } 16855682Smarkm 16955682Smarkm (*realms)[0] = strdup(p); 17055682Smarkm if((*realms)[0] == NULL) { 17155682Smarkm free(*realms); 17278527Sassar krb5_set_error_string(context, "malloc: out of memory"); 17355682Smarkm return ENOMEM; 17455682Smarkm } 17555682Smarkm strupr((*realms)[0]); 17655682Smarkm (*realms)[1] = NULL; 17755682Smarkm return 0; 17855682Smarkm } 17978527Sassar krb5_set_error_string(context, "unable to find realm of host %s", host); 18055682Smarkm return KRB5_ERR_HOST_REALM_UNKNOWN; 18155682Smarkm} 18255682Smarkm 18355682Smarkm/* 18455682Smarkm * Return the realm(s) of `host' as a NULL-terminated list in `realms'. 18555682Smarkm */ 18655682Smarkm 18755682Smarkmkrb5_error_code 18855682Smarkmkrb5_get_host_realm(krb5_context context, 18955682Smarkm const char *host, 19055682Smarkm krb5_realm **realms) 19155682Smarkm{ 19255682Smarkm char hostname[MAXHOSTNAMELEN]; 19355682Smarkm 19455682Smarkm if (host == NULL) { 19555682Smarkm if (gethostname (hostname, sizeof(hostname))) 19655682Smarkm return errno; 19755682Smarkm host = hostname; 19855682Smarkm } 19955682Smarkm 20078527Sassar return krb5_get_host_realm_int (context, host, 1, realms); 20155682Smarkm} 202