1 /* 2 * Copyright (c) 1997 - 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 #include <resolve.h> 36 37 RCSID("$Id: krbhst.c,v 1.26 2001/05/14 06:14:49 assar Exp $"); 38 39 /* 40 * assuming that `*res' contains `*count' strings, add a copy of `string'. 41 */ 42 43 static int 44 add_string(krb5_context context, char ***res, int *count, const char *string) 45 { 46 char **tmp = realloc(*res, (*count + 1) * sizeof(**res)); 47 48 if(tmp == NULL) { 49 krb5_set_error_string (context, "malloc: out of memory"); 50 return ENOMEM; 51 } 52 *res = tmp; 53 if(string) { 54 tmp[*count] = strdup(string); 55 if(tmp[*count] == NULL) { 56 krb5_set_error_string (context, "malloc: out of memory"); 57 return ENOMEM; 58 } 59 } else 60 tmp[*count] = NULL; 61 (*count)++; 62 return 0; 63 } 64 65 /* 66 * do a SRV lookup for `realm, proto, service' returning the result 67 * in `res, count' 68 */ 69 70 static krb5_error_code 71 srv_find_realm(krb5_context context, char ***res, int *count, 72 const char *realm, const char *proto, const char *service) 73 { 74 char domain[1024]; 75 char alt_domain[1024]; 76 krb5_error_code ret; 77 struct dns_reply *r; 78 struct resource_record *rr; 79 80 snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm); 81 82 r = dns_lookup(domain, "srv"); 83 if(r == NULL && context->srv_try_rfc2052) { 84 snprintf(alt_domain, sizeof(alt_domain), "%s.%s.%s.", 85 service, proto, realm); 86 r = dns_lookup(alt_domain, "srv"); 87 } 88 if(r == NULL && context->srv_try_txt) 89 r = dns_lookup(domain, "txt"); 90 if(r == NULL && context->srv_try_rfc2052 && context->srv_try_txt) 91 r = dns_lookup(alt_domain, "txt"); 92 if(r == NULL) 93 return 0; 94 95 for(rr = r->head; rr; rr = rr->next){ 96 if(rr->type == T_SRV){ 97 char buf[1024]; 98 char **tmp; 99 100 tmp = realloc(*res, (*count + 1) * sizeof(**res)); 101 if (tmp == NULL) { 102 krb5_set_error_string (context, "malloc: out of memory"); 103 return ENOMEM; 104 } 105 *res = tmp; 106 snprintf (buf, sizeof(buf), 107 "%s/%s:%u", 108 proto, 109 rr->u.srv->target, 110 rr->u.srv->port); 111 ret = add_string(context, res, count, buf); 112 if(ret) 113 return ret; 114 }else if(rr->type == T_TXT) { 115 ret = add_string(context, res, count, rr->u.txt); 116 if(ret) 117 return ret; 118 } 119 } 120 dns_free_data(r); 121 return 0; 122 } 123 124 /* 125 * lookup the servers for realm `realm', looking for the config string 126 * `conf_string' in krb5.conf or for `serv_string' in SRV records. 127 * return a malloc-ed list of servers in hostlist. 128 */ 129 130 static krb5_error_code 131 get_krbhst (krb5_context context, 132 const krb5_realm *realm, 133 const char *conf_string, 134 const char *serv_string, 135 char ***hostlist) 136 { 137 char **res, **r; 138 int count; 139 krb5_error_code ret; 140 141 res = krb5_config_get_strings(context, NULL, 142 "realms", *realm, conf_string, NULL); 143 for(r = res, count = 0; r && *r; r++, count++); 144 145 if(count == 0 && context->srv_lookup) { 146 char *s[] = { "udp", "tcp", "http" }, **q; 147 for(q = s; q < s + sizeof(s) / sizeof(s[0]); q++) { 148 ret = srv_find_realm(context, &res, &count, *realm, *q, 149 serv_string); 150 if(ret) { 151 krb5_config_free_strings(res); 152 return ret; 153 } 154 } 155 } 156 157 if(count == 0) { 158 char buf[1024]; 159 snprintf(buf, sizeof(buf), "kerberos.%s", *realm); 160 ret = add_string(context, &res, &count, buf); 161 if(ret) { 162 krb5_config_free_strings(res); 163 return ret; 164 } 165 } 166 add_string(context, &res, &count, NULL); 167 *hostlist = res; 168 return 0; 169 } 170 171 /* 172 * set `hostlist' to a malloced list of kadmin servers. 173 */ 174 175 krb5_error_code 176 krb5_get_krb_admin_hst (krb5_context context, 177 const krb5_realm *realm, 178 char ***hostlist) 179 { 180 return get_krbhst (context, realm, "admin_server", "kerberos-adm", 181 hostlist); 182 } 183 184 /* 185 * set `hostlist' to a malloced list of changepw servers. 186 */ 187 188 krb5_error_code 189 krb5_get_krb_changepw_hst (krb5_context context, 190 const krb5_realm *realm, 191 char ***hostlist) 192 { 193 krb5_error_code ret; 194 195 ret = get_krbhst (context, realm, "kpasswd_server", "kpasswd", 196 hostlist); 197 if (ret) 198 return ret; 199 ret = get_krbhst (context, realm, "admin_server", "kpasswd", 200 hostlist); 201 return ret; 202 } 203 204 /* 205 * set `hostlist' to a malloced list of kerberos servers. 206 */ 207 208 krb5_error_code 209 krb5_get_krbhst (krb5_context context, 210 const krb5_realm *realm, 211 char ***hostlist) 212 { 213 return get_krbhst (context, realm, "kdc", "kerberos", hostlist); 214 } 215 216 /* 217 * free all memory associated with `hostlist' 218 */ 219 220 krb5_error_code 221 krb5_free_krbhst (krb5_context context, 222 char **hostlist) 223 { 224 char **p; 225 226 for (p = hostlist; *p; ++p) 227 free (*p); 228 free (hostlist); 229 return 0; 230 } 231