1 /* 2 * Copyright (c) 1997, 1998, 1999 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.23 1999/12/11 23:14:25 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 static krb5_error_code 62 srv_find_realm(krb5_context context, char ***res, int *count, 63 const char *realm, const char *proto, const char *service) 64 { 65 char domain[1024]; 66 char alt_domain[1024]; 67 krb5_error_code ret; 68 struct dns_reply *r; 69 struct resource_record *rr; 70 71 snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm); 72 73 r = dns_lookup(domain, "srv"); 74 if(r == NULL && context->srv_try_rfc2052) { 75 snprintf(alt_domain, sizeof(alt_domain), "%s.%s.%s.", 76 service, proto, realm); 77 r = dns_lookup(alt_domain, "srv"); 78 } 79 if(r == NULL && context->srv_try_txt) 80 r = dns_lookup(domain, "txt"); 81 if(r == NULL && context->srv_try_rfc2052 && context->srv_try_txt) 82 r = dns_lookup(alt_domain, "txt"); 83 if(r == NULL) 84 return 0; 85 86 for(rr = r->head; rr; rr = rr->next){ 87 if(rr->type == T_SRV){ 88 char buf[1024]; 89 char **tmp; 90 91 tmp = realloc(*res, (*count + 1) * sizeof(**res)); 92 if (tmp == NULL) 93 return ENOMEM; 94 *res = tmp; 95 snprintf (buf, sizeof(buf), 96 "%s/%s:%u", 97 proto, 98 rr->u.srv->target, 99 rr->u.srv->port); 100 ret = add_string(res, count, buf); 101 if(ret) 102 return ret; 103 }else if(rr->type == T_TXT) { 104 ret = add_string(res, count, rr->u.txt); 105 if(ret) 106 return ret; 107 } 108 } 109 dns_free_data(r); 110 return 0; 111 } 112 113 /* 114 * lookup the servers for realm `realm', looking for the config string 115 * `conf_string' in krb5.conf or for `serv_string' in SRV records. 116 * return a malloc-ed list of servers in hostlist. 117 */ 118 119 static krb5_error_code 120 get_krbhst (krb5_context context, 121 const krb5_realm *realm, 122 const char *conf_string, 123 const char *serv_string, 124 char ***hostlist) 125 { 126 char **res, **r; 127 int count; 128 krb5_error_code ret; 129 130 res = krb5_config_get_strings(context, NULL, 131 "realms", *realm, conf_string, NULL); 132 for(r = res, count = 0; r && *r; r++, count++); 133 134 if(context->srv_lookup) { 135 char *s[] = { "udp", "tcp", "http" }, **q; 136 for(q = s; q < s + sizeof(s) / sizeof(s[0]); q++) { 137 ret = srv_find_realm(context, &res, &count, *realm, *q, 138 serv_string); 139 if(ret) { 140 krb5_config_free_strings(res); 141 return ret; 142 } 143 } 144 } 145 146 if(count == 0) { 147 char buf[1024]; 148 snprintf(buf, sizeof(buf), "kerberos.%s", *realm); 149 ret = add_string(&res, &count, buf); 150 if(ret) { 151 krb5_config_free_strings(res); 152 return ret; 153 } 154 } 155 add_string(&res, &count, NULL); 156 *hostlist = res; 157 return 0; 158 } 159 160 krb5_error_code 161 krb5_get_krb_admin_hst (krb5_context context, 162 const krb5_realm *realm, 163 char ***hostlist) 164 { 165 return get_krbhst (context, realm, "admin_server", "kerberos-adm", 166 hostlist); 167 } 168 169 krb5_error_code 170 krb5_get_krb_changepw_hst (krb5_context context, 171 const krb5_realm *realm, 172 char ***hostlist) 173 { 174 return get_krbhst (context, realm, "admin_server", "kpasswd", 175 hostlist); 176 } 177 178 krb5_error_code 179 krb5_get_krbhst (krb5_context context, 180 const krb5_realm *realm, 181 char ***hostlist) 182 { 183 return get_krbhst (context, realm, "kdc", "kerberos", hostlist); 184 } 185 186 krb5_error_code 187 krb5_free_krbhst (krb5_context context, 188 char **hostlist) 189 { 190 char **p; 191 192 for (p = hostlist; *p; ++p) 193 free (*p); 194 free (hostlist); 195 return 0; 196 } 197