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