Home | History | Annotate | Line # | Download | only in krb5
expand_hostname.c revision 1.1.1.1.6.1
      1 /*	$NetBSD: expand_hostname.c,v 1.1.1.1.6.1 2017/08/30 07:11:01 snj Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1999 - 2001 Kungliga Tekniska Hgskolan
      5  * (Royal Institute of Technology, Stockholm, Sweden).
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the Institute nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include "krb5_locl.h"
     37 
     38 static krb5_error_code
     39 copy_hostname(krb5_context context,
     40 	      const char *orig_hostname,
     41 	      char **new_hostname)
     42 {
     43     *new_hostname = strdup (orig_hostname);
     44     if (*new_hostname == NULL)
     45 	return krb5_enomem(context);
     46     strlwr (*new_hostname);
     47     return 0;
     48 }
     49 
     50 /**
     51  * krb5_expand_hostname() tries to make orig_hostname into a more
     52  * canonical one in the newly allocated space returned in
     53  * new_hostname.
     54 
     55  * @param context a Keberos context
     56  * @param orig_hostname hostname to canonicalise.
     57  * @param new_hostname output hostname, caller must free hostname with
     58  *        krb5_xfree().
     59  *
     60  * @return Return an error code or 0, see krb5_get_error_message().
     61  *
     62  * @ingroup krb5_support
     63  */
     64 
     65 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     66 krb5_expand_hostname (krb5_context context,
     67 		      const char *orig_hostname,
     68 		      char **new_hostname)
     69 {
     70     struct addrinfo *ai, *a, hints;
     71     int error;
     72 
     73     if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0)
     74 	return copy_hostname (context, orig_hostname, new_hostname);
     75 
     76     memset (&hints, 0, sizeof(hints));
     77     hints.ai_flags = AI_CANONNAME;
     78 
     79     error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
     80     if (error)
     81 	return copy_hostname (context, orig_hostname, new_hostname);
     82     for (a = ai; a != NULL; a = a->ai_next) {
     83 	if (a->ai_canonname != NULL) {
     84 	    *new_hostname = strdup (a->ai_canonname);
     85 	    freeaddrinfo (ai);
     86 	    if (*new_hostname == NULL)
     87 		return krb5_enomem(context);
     88 	    else
     89 		return 0;
     90 	}
     91     }
     92     freeaddrinfo (ai);
     93     return copy_hostname (context, orig_hostname, new_hostname);
     94 }
     95 
     96 /*
     97  * handle the case of the hostname being unresolvable and thus identical
     98  */
     99 
    100 static krb5_error_code
    101 vanilla_hostname (krb5_context context,
    102 		  const char *orig_hostname,
    103 		  char **new_hostname,
    104 		  char ***realms)
    105 {
    106     krb5_error_code ret;
    107 
    108     ret = copy_hostname (context, orig_hostname, new_hostname);
    109     if (ret)
    110 	return ret;
    111     strlwr (*new_hostname);
    112 
    113     ret = krb5_get_host_realm (context, *new_hostname, realms);
    114     if (ret) {
    115 	free (*new_hostname);
    116 	return ret;
    117     }
    118     return 0;
    119 }
    120 
    121 /**
    122  * krb5_expand_hostname_realms() expands orig_hostname to a name we
    123  * believe to be a hostname in newly allocated space in new_hostname
    124  * and return the realms new_hostname is believed to belong to in
    125  * realms.
    126  *
    127  * @param context a Keberos context
    128  * @param orig_hostname hostname to canonicalise.
    129  * @param new_hostname output hostname, caller must free hostname with
    130  *        krb5_xfree().
    131  * @param realms output possible realms, is an array that is terminated
    132  *        with NULL. Caller must free with krb5_free_host_realm().
    133  *
    134  * @return Return an error code or 0, see krb5_get_error_message().
    135  *
    136  * @ingroup krb5_support
    137  */
    138 
    139 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    140 krb5_expand_hostname_realms (krb5_context context,
    141 			     const char *orig_hostname,
    142 			     char **new_hostname,
    143 			     char ***realms)
    144 {
    145     struct addrinfo *ai, *a, hints;
    146     int error;
    147     krb5_error_code ret = 0;
    148 
    149     if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0)
    150 	return vanilla_hostname (context, orig_hostname, new_hostname,
    151 				 realms);
    152 
    153     memset (&hints, 0, sizeof(hints));
    154     hints.ai_flags = AI_CANONNAME;
    155 
    156     error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
    157     if (error)
    158 	return vanilla_hostname (context, orig_hostname, new_hostname,
    159 				 realms);
    160 
    161     for (a = ai; a != NULL; a = a->ai_next) {
    162 	if (a->ai_canonname != NULL) {
    163 	    ret = copy_hostname (context, a->ai_canonname, new_hostname);
    164 	    if (ret) {
    165 		freeaddrinfo (ai);
    166 		return ret;
    167 	    }
    168 	    strlwr (*new_hostname);
    169 	    ret = krb5_get_host_realm (context, *new_hostname, realms);
    170 	    if (ret == 0) {
    171 		freeaddrinfo (ai);
    172 		return 0;
    173 	    }
    174 	    free (*new_hostname);
    175 	}
    176     }
    177     freeaddrinfo(ai);
    178     return vanilla_hostname (context, orig_hostname, new_hostname, realms);
    179 }
    180