Home | History | Annotate | Line # | Download | only in krb5
expand_hostname.c revision 1.1.1.1
      1 /*	$NetBSD: expand_hostname.c,v 1.1.1.1 2011/04/13 18:15:33 elric 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 	krb5_set_error_message(context, ENOMEM,
     46 			       N_("malloc: out of memory", ""));
     47 	return ENOMEM;
     48     }
     49     strlwr (*new_hostname);
     50     return 0;
     51 }
     52 
     53 /**
     54  * krb5_expand_hostname() tries to make orig_hostname into a more
     55  * canonical one in the newly allocated space returned in
     56  * new_hostname.
     57 
     58  * @param context a Keberos context
     59  * @param orig_hostname hostname to canonicalise.
     60  * @param new_hostname output hostname, caller must free hostname with
     61  *        krb5_xfree().
     62  *
     63  * @return Return an error code or 0, see krb5_get_error_message().
     64  *
     65  * @ingroup krb5_support
     66  */
     67 
     68 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     69 krb5_expand_hostname (krb5_context context,
     70 		      const char *orig_hostname,
     71 		      char **new_hostname)
     72 {
     73     struct addrinfo *ai, *a, hints;
     74     int error;
     75 
     76     if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0)
     77 	return copy_hostname (context, orig_hostname, new_hostname);
     78 
     79     memset (&hints, 0, sizeof(hints));
     80     hints.ai_flags = AI_CANONNAME;
     81 
     82     error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
     83     if (error)
     84 	return copy_hostname (context, orig_hostname, new_hostname);
     85     for (a = ai; a != NULL; a = a->ai_next) {
     86 	if (a->ai_canonname != NULL) {
     87 	    *new_hostname = strdup (a->ai_canonname);
     88 	    freeaddrinfo (ai);
     89 	    if (*new_hostname == NULL) {
     90 		krb5_set_error_message(context, ENOMEM,
     91 				       N_("malloc: out of memory", ""));
     92 		return ENOMEM;
     93 	    } else {
     94 		return 0;
     95 	    }
     96 	}
     97     }
     98     freeaddrinfo (ai);
     99     return copy_hostname (context, orig_hostname, new_hostname);
    100 }
    101 
    102 /*
    103  * handle the case of the hostname being unresolvable and thus identical
    104  */
    105 
    106 static krb5_error_code
    107 vanilla_hostname (krb5_context context,
    108 		  const char *orig_hostname,
    109 		  char **new_hostname,
    110 		  char ***realms)
    111 {
    112     krb5_error_code ret;
    113 
    114     ret = copy_hostname (context, orig_hostname, new_hostname);
    115     if (ret)
    116 	return ret;
    117     strlwr (*new_hostname);
    118 
    119     ret = krb5_get_host_realm (context, *new_hostname, realms);
    120     if (ret) {
    121 	free (*new_hostname);
    122 	return ret;
    123     }
    124     return 0;
    125 }
    126 
    127 /**
    128  * krb5_expand_hostname_realms() expands orig_hostname to a name we
    129  * believe to be a hostname in newly allocated space in new_hostname
    130  * and return the realms new_hostname is believed to belong to in
    131  * realms.
    132  *
    133  * @param context a Keberos context
    134  * @param orig_hostname hostname to canonicalise.
    135  * @param new_hostname output hostname, caller must free hostname with
    136  *        krb5_xfree().
    137  * @param realms output possible realms, is an array that is terminated
    138  *        with NULL. Caller must free with krb5_free_host_realm().
    139  *
    140  * @return Return an error code or 0, see krb5_get_error_message().
    141  *
    142  * @ingroup krb5_support
    143  */
    144 
    145 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    146 krb5_expand_hostname_realms (krb5_context context,
    147 			     const char *orig_hostname,
    148 			     char **new_hostname,
    149 			     char ***realms)
    150 {
    151     struct addrinfo *ai, *a, hints;
    152     int error;
    153     krb5_error_code ret = 0;
    154 
    155     if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0)
    156 	return vanilla_hostname (context, orig_hostname, new_hostname,
    157 				 realms);
    158 
    159     memset (&hints, 0, sizeof(hints));
    160     hints.ai_flags = AI_CANONNAME;
    161 
    162     error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
    163     if (error)
    164 	return vanilla_hostname (context, orig_hostname, new_hostname,
    165 				 realms);
    166 
    167     for (a = ai; a != NULL; a = a->ai_next) {
    168 	if (a->ai_canonname != NULL) {
    169 	    ret = copy_hostname (context, a->ai_canonname, new_hostname);
    170 	    if (ret) {
    171 		freeaddrinfo (ai);
    172 		return ret;
    173 	    }
    174 	    strlwr (*new_hostname);
    175 	    ret = krb5_get_host_realm (context, *new_hostname, realms);
    176 	    if (ret == 0) {
    177 		freeaddrinfo (ai);
    178 		return 0;
    179 	    }
    180 	    free (*new_hostname);
    181 	}
    182     }
    183     freeaddrinfo(ai);
    184     return vanilla_hostname (context, orig_hostname, new_hostname, realms);
    185 }
    186