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