xref: /freebsd/crypto/heimdal/lib/krb5/krbhst.c (revision 5e9cd1ae3e10592ed70e7575551cba1bbab04d84)
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