1b528cefcSMark Murray /*
2ae771770SStanislav Sedov * Copyright (c) 2001 - 2003 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "krb5_locl.h"
35b528cefcSMark Murray #include <resolve.h>
36c19800e8SDoug Rabson #include "locate_plugin.h"
37b528cefcSMark Murray
38b528cefcSMark Murray static int
string_to_proto(const char * string)394137ff4cSJacques Vidrine string_to_proto(const char *string)
40b528cefcSMark Murray {
414137ff4cSJacques Vidrine if(strcasecmp(string, "udp") == 0)
424137ff4cSJacques Vidrine return KRB5_KRBHST_UDP;
434137ff4cSJacques Vidrine else if(strcasecmp(string, "tcp") == 0)
444137ff4cSJacques Vidrine return KRB5_KRBHST_TCP;
454137ff4cSJacques Vidrine else if(strcasecmp(string, "http") == 0)
464137ff4cSJacques Vidrine return KRB5_KRBHST_HTTP;
474137ff4cSJacques Vidrine return -1;
48b528cefcSMark Murray }
49b528cefcSMark Murray
505e9cd1aeSAssar Westerlund /*
514137ff4cSJacques Vidrine * set `res' and `count' to the result of looking up SRV RR in DNS for
524137ff4cSJacques Vidrine * `proto', `proto', `realm' using `dns_type'.
534137ff4cSJacques Vidrine * if `port' != 0, force that port number
545e9cd1aeSAssar Westerlund */
555e9cd1aeSAssar Westerlund
56b528cefcSMark Murray static krb5_error_code
srv_find_realm(krb5_context context,krb5_krbhst_info *** res,int * count,const char * realm,const char * dns_type,const char * proto,const char * service,int port)574137ff4cSJacques Vidrine srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count,
584137ff4cSJacques Vidrine const char *realm, const char *dns_type,
594137ff4cSJacques Vidrine const char *proto, const char *service, int port)
60b528cefcSMark Murray {
61b528cefcSMark Murray char domain[1024];
62ae771770SStanislav Sedov struct rk_dns_reply *r;
63ae771770SStanislav Sedov struct rk_resource_record *rr;
644137ff4cSJacques Vidrine int num_srv;
654137ff4cSJacques Vidrine int proto_num;
664137ff4cSJacques Vidrine int def_port;
674137ff4cSJacques Vidrine
68c19800e8SDoug Rabson *res = NULL;
69c19800e8SDoug Rabson *count = 0;
70c19800e8SDoug Rabson
714137ff4cSJacques Vidrine proto_num = string_to_proto(proto);
724137ff4cSJacques Vidrine if(proto_num < 0) {
73ae771770SStanislav Sedov krb5_set_error_message(context, EINVAL,
74ae771770SStanislav Sedov N_("unknown protocol `%s' to lookup", ""),
75ae771770SStanislav Sedov proto);
764137ff4cSJacques Vidrine return EINVAL;
774137ff4cSJacques Vidrine }
784137ff4cSJacques Vidrine
794137ff4cSJacques Vidrine if(proto_num == KRB5_KRBHST_HTTP)
804137ff4cSJacques Vidrine def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80));
814137ff4cSJacques Vidrine else if(port == 0)
824137ff4cSJacques Vidrine def_port = ntohs(krb5_getportbyname (context, service, proto, 88));
834137ff4cSJacques Vidrine else
844137ff4cSJacques Vidrine def_port = port;
85b528cefcSMark Murray
86b528cefcSMark Murray snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm);
87b528cefcSMark Murray
88ae771770SStanislav Sedov r = rk_dns_lookup(domain, dns_type);
89ae771770SStanislav Sedov if(r == NULL) {
90ae771770SStanislav Sedov _krb5_debug(context, 0,
91ae771770SStanislav Sedov "DNS lookup failed domain: %s", domain);
924137ff4cSJacques Vidrine return KRB5_KDC_UNREACH;
93ae771770SStanislav Sedov }
94b528cefcSMark Murray
954137ff4cSJacques Vidrine for(num_srv = 0, rr = r->head; rr; rr = rr->next)
96ae771770SStanislav Sedov if(rr->type == rk_ns_t_srv)
974137ff4cSJacques Vidrine num_srv++;
98b528cefcSMark Murray
99*ed549cb0SCy Schubert if (num_srv == 0) {
100*ed549cb0SCy Schubert _krb5_debug(context, 0,
101*ed549cb0SCy Schubert "DNS SRV RR lookup domain nodata: %s", domain);
102*ed549cb0SCy Schubert return KRB5_KDC_UNREACH;
103*ed549cb0SCy Schubert }
104*ed549cb0SCy Schubert
1054137ff4cSJacques Vidrine *res = malloc(num_srv * sizeof(**res));
1064137ff4cSJacques Vidrine if(*res == NULL) {
107ae771770SStanislav Sedov rk_dns_free_data(r);
108ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
109ae771770SStanislav Sedov N_("malloc: out of memory", ""));
110b528cefcSMark Murray return ENOMEM;
111adb0ddaeSAssar Westerlund }
1124137ff4cSJacques Vidrine
113ae771770SStanislav Sedov rk_dns_srv_order(r);
1144137ff4cSJacques Vidrine
1154137ff4cSJacques Vidrine for(num_srv = 0, rr = r->head; rr; rr = rr->next)
116ae771770SStanislav Sedov if(rr->type == rk_ns_t_srv) {
1174137ff4cSJacques Vidrine krb5_krbhst_info *hi;
118bbd80c28SJacques Vidrine size_t len = strlen(rr->u.srv->target);
119bbd80c28SJacques Vidrine
120bbd80c28SJacques Vidrine hi = calloc(1, sizeof(*hi) + len);
1214137ff4cSJacques Vidrine if(hi == NULL) {
122ae771770SStanislav Sedov rk_dns_free_data(r);
1234137ff4cSJacques Vidrine while(--num_srv >= 0)
1244137ff4cSJacques Vidrine free((*res)[num_srv]);
1254137ff4cSJacques Vidrine free(*res);
126c19800e8SDoug Rabson *res = NULL;
1274137ff4cSJacques Vidrine return ENOMEM;
128b528cefcSMark Murray }
1294137ff4cSJacques Vidrine (*res)[num_srv++] = hi;
1304137ff4cSJacques Vidrine
1314137ff4cSJacques Vidrine hi->proto = proto_num;
1324137ff4cSJacques Vidrine
1334137ff4cSJacques Vidrine hi->def_port = def_port;
1344137ff4cSJacques Vidrine if (port != 0)
1354137ff4cSJacques Vidrine hi->port = port;
1364137ff4cSJacques Vidrine else
1374137ff4cSJacques Vidrine hi->port = rr->u.srv->port;
1384137ff4cSJacques Vidrine
139bbd80c28SJacques Vidrine strlcpy(hi->hostname, rr->u.srv->target, len + 1);
140b528cefcSMark Murray }
1414137ff4cSJacques Vidrine
1424137ff4cSJacques Vidrine *count = num_srv;
1434137ff4cSJacques Vidrine
144ae771770SStanislav Sedov rk_dns_free_data(r);
145b528cefcSMark Murray return 0;
146b528cefcSMark Murray }
147b528cefcSMark Murray
1484137ff4cSJacques Vidrine
1494137ff4cSJacques Vidrine struct krb5_krbhst_data {
1504137ff4cSJacques Vidrine char *realm;
1514137ff4cSJacques Vidrine unsigned int flags;
1524137ff4cSJacques Vidrine int def_port;
1534137ff4cSJacques Vidrine int port; /* hardwired port number if != 0 */
1544137ff4cSJacques Vidrine #define KD_CONFIG 1
1554137ff4cSJacques Vidrine #define KD_SRV_UDP 2
1564137ff4cSJacques Vidrine #define KD_SRV_TCP 4
1574137ff4cSJacques Vidrine #define KD_SRV_HTTP 8
1584137ff4cSJacques Vidrine #define KD_FALLBACK 16
1594137ff4cSJacques Vidrine #define KD_CONFIG_EXISTS 32
160c19800e8SDoug Rabson #define KD_LARGE_MSG 64
161c19800e8SDoug Rabson #define KD_PLUGIN 128
1624137ff4cSJacques Vidrine krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *,
1634137ff4cSJacques Vidrine krb5_krbhst_info**);
1644137ff4cSJacques Vidrine
1654137ff4cSJacques Vidrine unsigned int fallback_count;
1664137ff4cSJacques Vidrine
1674137ff4cSJacques Vidrine struct krb5_krbhst_info *hosts, **index, **end;
1684137ff4cSJacques Vidrine };
1694137ff4cSJacques Vidrine
1704137ff4cSJacques Vidrine static krb5_boolean
krbhst_empty(const struct krb5_krbhst_data * kd)1714137ff4cSJacques Vidrine krbhst_empty(const struct krb5_krbhst_data *kd)
1724137ff4cSJacques Vidrine {
1734137ff4cSJacques Vidrine return kd->index == &kd->hosts;
1744137ff4cSJacques Vidrine }
1754137ff4cSJacques Vidrine
176b528cefcSMark Murray /*
177c19800e8SDoug Rabson * Return the default protocol for the `kd' (either TCP or UDP)
178c19800e8SDoug Rabson */
179c19800e8SDoug Rabson
180c19800e8SDoug Rabson static int
krbhst_get_default_proto(struct krb5_krbhst_data * kd)181c19800e8SDoug Rabson krbhst_get_default_proto(struct krb5_krbhst_data *kd)
182c19800e8SDoug Rabson {
183c19800e8SDoug Rabson if (kd->flags & KD_LARGE_MSG)
184c19800e8SDoug Rabson return KRB5_KRBHST_TCP;
185c19800e8SDoug Rabson return KRB5_KRBHST_UDP;
186c19800e8SDoug Rabson }
187c19800e8SDoug Rabson
188ae771770SStanislav Sedov /*
189ae771770SStanislav Sedov *
190ae771770SStanislav Sedov */
191ae771770SStanislav Sedov
192ae771770SStanislav Sedov const char *
_krb5_krbhst_get_realm(krb5_krbhst_handle handle)193ae771770SStanislav Sedov _krb5_krbhst_get_realm(krb5_krbhst_handle handle)
194ae771770SStanislav Sedov {
195ae771770SStanislav Sedov return handle->realm;
196ae771770SStanislav Sedov }
197c19800e8SDoug Rabson
198c19800e8SDoug Rabson /*
1994137ff4cSJacques Vidrine * parse `spec' into a krb5_krbhst_info, defaulting the port to `def_port'
2004137ff4cSJacques Vidrine * and forcing it to `port' if port != 0
201b528cefcSMark Murray */
202b528cefcSMark Murray
2034137ff4cSJacques Vidrine static struct krb5_krbhst_info*
parse_hostspec(krb5_context context,struct krb5_krbhst_data * kd,const char * spec,int def_port,int port)204c19800e8SDoug Rabson parse_hostspec(krb5_context context, struct krb5_krbhst_data *kd,
205c19800e8SDoug Rabson const char *spec, int def_port, int port)
206b528cefcSMark Murray {
207ae771770SStanislav Sedov const char *p = spec, *q;
2084137ff4cSJacques Vidrine struct krb5_krbhst_info *hi;
209b528cefcSMark Murray
2104137ff4cSJacques Vidrine hi = calloc(1, sizeof(*hi) + strlen(spec));
2114137ff4cSJacques Vidrine if(hi == NULL)
2124137ff4cSJacques Vidrine return NULL;
213b528cefcSMark Murray
214c19800e8SDoug Rabson hi->proto = krbhst_get_default_proto(kd);
2154137ff4cSJacques Vidrine
2164137ff4cSJacques Vidrine if(strncmp(p, "http://", 7) == 0){
2174137ff4cSJacques Vidrine hi->proto = KRB5_KRBHST_HTTP;
2184137ff4cSJacques Vidrine p += 7;
2194137ff4cSJacques Vidrine } else if(strncmp(p, "http/", 5) == 0) {
2204137ff4cSJacques Vidrine hi->proto = KRB5_KRBHST_HTTP;
2214137ff4cSJacques Vidrine p += 5;
2224137ff4cSJacques Vidrine def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80));
2234137ff4cSJacques Vidrine }else if(strncmp(p, "tcp/", 4) == 0){
2244137ff4cSJacques Vidrine hi->proto = KRB5_KRBHST_TCP;
2254137ff4cSJacques Vidrine p += 4;
2264137ff4cSJacques Vidrine } else if(strncmp(p, "udp/", 4) == 0) {
2274137ff4cSJacques Vidrine p += 4;
228b528cefcSMark Murray }
229b528cefcSMark Murray
230ae771770SStanislav Sedov if (p[0] == '[' && (q = strchr(p, ']')) != NULL) {
231ae771770SStanislav Sedov /* if address looks like [foo:bar] or [foo:bar]: its a ipv6
232ae771770SStanislav Sedov adress, strip of [] */
233ae771770SStanislav Sedov memcpy(hi->hostname, &p[1], q - p - 1);
234ae771770SStanislav Sedov hi->hostname[q - p - 1] = '\0';
235ae771770SStanislav Sedov p = q + 1;
236ae771770SStanislav Sedov /* get trailing : */
237ae771770SStanislav Sedov if (p[0] == ':')
238ae771770SStanislav Sedov p++;
239ae771770SStanislav Sedov } else if(strsep_copy(&p, ":", hi->hostname, strlen(spec) + 1) < 0) {
240ae771770SStanislav Sedov /* copy everything before : */
2414137ff4cSJacques Vidrine free(hi);
2424137ff4cSJacques Vidrine return NULL;
2434137ff4cSJacques Vidrine }
2444137ff4cSJacques Vidrine /* get rid of trailing /, and convert to lower case */
2454137ff4cSJacques Vidrine hi->hostname[strcspn(hi->hostname, "/")] = '\0';
2464137ff4cSJacques Vidrine strlwr(hi->hostname);
2474137ff4cSJacques Vidrine
2484137ff4cSJacques Vidrine hi->port = hi->def_port = def_port;
249ae771770SStanislav Sedov if(p != NULL && p[0]) {
2504137ff4cSJacques Vidrine char *end;
2514137ff4cSJacques Vidrine hi->port = strtol(p, &end, 0);
2524137ff4cSJacques Vidrine if(end == p) {
2534137ff4cSJacques Vidrine free(hi);
2544137ff4cSJacques Vidrine return NULL;
255b528cefcSMark Murray }
256b528cefcSMark Murray }
2574137ff4cSJacques Vidrine if (port)
2584137ff4cSJacques Vidrine hi->port = port;
2594137ff4cSJacques Vidrine return hi;
2604137ff4cSJacques Vidrine }
2614137ff4cSJacques Vidrine
262c19800e8SDoug Rabson void
_krb5_free_krbhst_info(krb5_krbhst_info * hi)263c19800e8SDoug Rabson _krb5_free_krbhst_info(krb5_krbhst_info *hi)
2644137ff4cSJacques Vidrine {
2654137ff4cSJacques Vidrine if (hi->ai != NULL)
2664137ff4cSJacques Vidrine freeaddrinfo(hi->ai);
2674137ff4cSJacques Vidrine free(hi);
2684137ff4cSJacques Vidrine }
2694137ff4cSJacques Vidrine
270c19800e8SDoug Rabson krb5_error_code
_krb5_krbhost_info_move(krb5_context context,krb5_krbhst_info * from,krb5_krbhst_info ** to)271c19800e8SDoug Rabson _krb5_krbhost_info_move(krb5_context context,
272c19800e8SDoug Rabson krb5_krbhst_info *from,
273c19800e8SDoug Rabson krb5_krbhst_info **to)
274c19800e8SDoug Rabson {
275c19800e8SDoug Rabson size_t hostnamelen = strlen(from->hostname);
276c19800e8SDoug Rabson /* trailing NUL is included in structure */
277c19800e8SDoug Rabson *to = calloc(1, sizeof(**to) + hostnamelen);
278c19800e8SDoug Rabson if(*to == NULL) {
279ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
280ae771770SStanislav Sedov N_("malloc: out of memory", ""));
281c19800e8SDoug Rabson return ENOMEM;
282c19800e8SDoug Rabson }
283c19800e8SDoug Rabson
284c19800e8SDoug Rabson (*to)->proto = from->proto;
285c19800e8SDoug Rabson (*to)->port = from->port;
286c19800e8SDoug Rabson (*to)->def_port = from->def_port;
287c19800e8SDoug Rabson (*to)->ai = from->ai;
288c19800e8SDoug Rabson from->ai = NULL;
289c19800e8SDoug Rabson (*to)->next = NULL;
290c19800e8SDoug Rabson memcpy((*to)->hostname, from->hostname, hostnamelen + 1);
291c19800e8SDoug Rabson return 0;
292c19800e8SDoug Rabson }
293c19800e8SDoug Rabson
294c19800e8SDoug Rabson
2954137ff4cSJacques Vidrine static void
append_host_hostinfo(struct krb5_krbhst_data * kd,struct krb5_krbhst_info * host)2964137ff4cSJacques Vidrine append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host)
2974137ff4cSJacques Vidrine {
2984137ff4cSJacques Vidrine struct krb5_krbhst_info *h;
2994137ff4cSJacques Vidrine
3004137ff4cSJacques Vidrine for(h = kd->hosts; h; h = h->next)
3014137ff4cSJacques Vidrine if(h->proto == host->proto &&
3024137ff4cSJacques Vidrine h->port == host->port &&
3034137ff4cSJacques Vidrine strcmp(h->hostname, host->hostname) == 0) {
304c19800e8SDoug Rabson _krb5_free_krbhst_info(host);
3054137ff4cSJacques Vidrine return;
3064137ff4cSJacques Vidrine }
3074137ff4cSJacques Vidrine *kd->end = host;
3084137ff4cSJacques Vidrine kd->end = &host->next;
3094137ff4cSJacques Vidrine }
3104137ff4cSJacques Vidrine
3114137ff4cSJacques Vidrine static krb5_error_code
append_host_string(krb5_context context,struct krb5_krbhst_data * kd,const char * host,int def_port,int port)3124137ff4cSJacques Vidrine append_host_string(krb5_context context, struct krb5_krbhst_data *kd,
3134137ff4cSJacques Vidrine const char *host, int def_port, int port)
3144137ff4cSJacques Vidrine {
3154137ff4cSJacques Vidrine struct krb5_krbhst_info *hi;
3164137ff4cSJacques Vidrine
317c19800e8SDoug Rabson hi = parse_hostspec(context, kd, host, def_port, port);
3184137ff4cSJacques Vidrine if(hi == NULL)
3194137ff4cSJacques Vidrine return ENOMEM;
3204137ff4cSJacques Vidrine
3214137ff4cSJacques Vidrine append_host_hostinfo(kd, hi);
322b528cefcSMark Murray return 0;
323b528cefcSMark Murray }
324b528cefcSMark Murray
3255e9cd1aeSAssar Westerlund /*
3264137ff4cSJacques Vidrine * return a readable representation of `host' in `hostname, hostlen'
3274137ff4cSJacques Vidrine */
3284137ff4cSJacques Vidrine
329ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_krbhst_format_string(krb5_context context,const krb5_krbhst_info * host,char * hostname,size_t hostlen)3304137ff4cSJacques Vidrine krb5_krbhst_format_string(krb5_context context, const krb5_krbhst_info *host,
3314137ff4cSJacques Vidrine char *hostname, size_t hostlen)
3324137ff4cSJacques Vidrine {
3334137ff4cSJacques Vidrine const char *proto = "";
3344137ff4cSJacques Vidrine char portstr[7] = "";
3354137ff4cSJacques Vidrine if(host->proto == KRB5_KRBHST_TCP)
3364137ff4cSJacques Vidrine proto = "tcp/";
3374137ff4cSJacques Vidrine else if(host->proto == KRB5_KRBHST_HTTP)
3384137ff4cSJacques Vidrine proto = "http://";
3394137ff4cSJacques Vidrine if(host->port != host->def_port)
3404137ff4cSJacques Vidrine snprintf(portstr, sizeof(portstr), ":%d", host->port);
3414137ff4cSJacques Vidrine snprintf(hostname, hostlen, "%s%s%s", proto, host->hostname, portstr);
3424137ff4cSJacques Vidrine return 0;
3434137ff4cSJacques Vidrine }
3444137ff4cSJacques Vidrine
3454137ff4cSJacques Vidrine /*
3464137ff4cSJacques Vidrine * create a getaddrinfo `hints' based on `proto'
3474137ff4cSJacques Vidrine */
3484137ff4cSJacques Vidrine
3494137ff4cSJacques Vidrine static void
make_hints(struct addrinfo * hints,int proto)3504137ff4cSJacques Vidrine make_hints(struct addrinfo *hints, int proto)
3514137ff4cSJacques Vidrine {
3524137ff4cSJacques Vidrine memset(hints, 0, sizeof(*hints));
3534137ff4cSJacques Vidrine hints->ai_family = AF_UNSPEC;
3544137ff4cSJacques Vidrine switch(proto) {
3554137ff4cSJacques Vidrine case KRB5_KRBHST_UDP :
3564137ff4cSJacques Vidrine hints->ai_socktype = SOCK_DGRAM;
3574137ff4cSJacques Vidrine break;
3584137ff4cSJacques Vidrine case KRB5_KRBHST_HTTP :
3594137ff4cSJacques Vidrine case KRB5_KRBHST_TCP :
3604137ff4cSJacques Vidrine hints->ai_socktype = SOCK_STREAM;
3614137ff4cSJacques Vidrine break;
3624137ff4cSJacques Vidrine }
3634137ff4cSJacques Vidrine }
3644137ff4cSJacques Vidrine
365ae771770SStanislav Sedov /**
366ae771770SStanislav Sedov * Return an `struct addrinfo *' for a KDC host.
367ae771770SStanislav Sedov *
368ae771770SStanislav Sedov * Returns an the struct addrinfo in in that corresponds to the
369ae771770SStanislav Sedov * information in `host'. free:ing is handled by krb5_krbhst_free, so
370ae771770SStanislav Sedov * the returned ai must not be released.
371ae771770SStanislav Sedov *
372ae771770SStanislav Sedov * @ingroup krb5
3734137ff4cSJacques Vidrine */
3744137ff4cSJacques Vidrine
375ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_krbhst_get_addrinfo(krb5_context context,krb5_krbhst_info * host,struct addrinfo ** ai)3764137ff4cSJacques Vidrine krb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host,
3774137ff4cSJacques Vidrine struct addrinfo **ai)
3784137ff4cSJacques Vidrine {
379ae771770SStanislav Sedov int ret = 0;
3804137ff4cSJacques Vidrine
3814137ff4cSJacques Vidrine if (host->ai == NULL) {
382ae771770SStanislav Sedov struct addrinfo hints;
383ae771770SStanislav Sedov char portstr[NI_MAXSERV];
384ae771770SStanislav Sedov char *hostname = host->hostname;
385ae771770SStanislav Sedov
3864137ff4cSJacques Vidrine snprintf (portstr, sizeof(portstr), "%d", host->port);
387ae771770SStanislav Sedov make_hints(&hints, host->proto);
388ae771770SStanislav Sedov
389ae771770SStanislav Sedov /**
390ae771770SStanislav Sedov * First try this as an IP address, this allows us to add a
391ae771770SStanislav Sedov * dot at the end to stop using the search domains.
392ae771770SStanislav Sedov */
393ae771770SStanislav Sedov
394ae771770SStanislav Sedov hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
395ae771770SStanislav Sedov
3964137ff4cSJacques Vidrine ret = getaddrinfo(host->hostname, portstr, &hints, &host->ai);
397ae771770SStanislav Sedov if (ret == 0)
398ae771770SStanislav Sedov goto out;
399ae771770SStanislav Sedov
400ae771770SStanislav Sedov /**
401ae771770SStanislav Sedov * If the hostname contains a dot, assumes it's a FQDN and
402ae771770SStanislav Sedov * don't use search domains since that might be painfully slow
403ae771770SStanislav Sedov * when machine is disconnected from that network.
404ae771770SStanislav Sedov */
405ae771770SStanislav Sedov
406ae771770SStanislav Sedov hints.ai_flags &= ~(AI_NUMERICHOST);
407ae771770SStanislav Sedov
408ae771770SStanislav Sedov if (strchr(hostname, '.') && hostname[strlen(hostname) - 1] != '.') {
409ae771770SStanislav Sedov ret = asprintf(&hostname, "%s.", host->hostname);
410ae771770SStanislav Sedov if (ret < 0 || hostname == NULL)
411ae771770SStanislav Sedov return ENOMEM;
4124137ff4cSJacques Vidrine }
413ae771770SStanislav Sedov
414ae771770SStanislav Sedov ret = getaddrinfo(hostname, portstr, &hints, &host->ai);
415ae771770SStanislav Sedov if (hostname != host->hostname)
416ae771770SStanislav Sedov free(hostname);
417ae771770SStanislav Sedov if (ret) {
418ae771770SStanislav Sedov ret = krb5_eai_to_heim_errno(ret, errno);
419ae771770SStanislav Sedov goto out;
420ae771770SStanislav Sedov }
421ae771770SStanislav Sedov }
422ae771770SStanislav Sedov out:
4234137ff4cSJacques Vidrine *ai = host->ai;
424ae771770SStanislav Sedov return ret;
4254137ff4cSJacques Vidrine }
4264137ff4cSJacques Vidrine
4274137ff4cSJacques Vidrine static krb5_boolean
get_next(struct krb5_krbhst_data * kd,krb5_krbhst_info ** host)4284137ff4cSJacques Vidrine get_next(struct krb5_krbhst_data *kd, krb5_krbhst_info **host)
4294137ff4cSJacques Vidrine {
4304137ff4cSJacques Vidrine struct krb5_krbhst_info *hi = *kd->index;
4314137ff4cSJacques Vidrine if(hi != NULL) {
4324137ff4cSJacques Vidrine *host = hi;
4334137ff4cSJacques Vidrine kd->index = &(*kd->index)->next;
4344137ff4cSJacques Vidrine return TRUE;
4354137ff4cSJacques Vidrine }
4364137ff4cSJacques Vidrine return FALSE;
4374137ff4cSJacques Vidrine }
4384137ff4cSJacques Vidrine
4394137ff4cSJacques Vidrine static void
srv_get_hosts(krb5_context context,struct krb5_krbhst_data * kd,const char * proto,const char * service)4404137ff4cSJacques Vidrine srv_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
4414137ff4cSJacques Vidrine const char *proto, const char *service)
4424137ff4cSJacques Vidrine {
443ae771770SStanislav Sedov krb5_error_code ret;
4444137ff4cSJacques Vidrine krb5_krbhst_info **res;
4454137ff4cSJacques Vidrine int count, i;
4464137ff4cSJacques Vidrine
447ae771770SStanislav Sedov ret = srv_find_realm(context, &res, &count, kd->realm, "SRV", proto, service,
448ae771770SStanislav Sedov kd->port);
449ae771770SStanislav Sedov _krb5_debug(context, 2, "searching DNS for realm %s %s.%s -> %d",
450ae771770SStanislav Sedov kd->realm, proto, service, ret);
451ae771770SStanislav Sedov if (ret)
452c19800e8SDoug Rabson return;
4534137ff4cSJacques Vidrine for(i = 0; i < count; i++)
4544137ff4cSJacques Vidrine append_host_hostinfo(kd, res[i]);
4554137ff4cSJacques Vidrine free(res);
4564137ff4cSJacques Vidrine }
4574137ff4cSJacques Vidrine
4584137ff4cSJacques Vidrine /*
4594137ff4cSJacques Vidrine * read the configuration for `conf_string', defaulting to kd->def_port and
4604137ff4cSJacques Vidrine * forcing it to `kd->port' if kd->port != 0
4614137ff4cSJacques Vidrine */
4624137ff4cSJacques Vidrine
4634137ff4cSJacques Vidrine static void
config_get_hosts(krb5_context context,struct krb5_krbhst_data * kd,const char * conf_string)4644137ff4cSJacques Vidrine config_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
4654137ff4cSJacques Vidrine const char *conf_string)
4664137ff4cSJacques Vidrine {
4674137ff4cSJacques Vidrine int i;
4684137ff4cSJacques Vidrine char **hostlist;
4694137ff4cSJacques Vidrine hostlist = krb5_config_get_strings(context, NULL,
4704137ff4cSJacques Vidrine "realms", kd->realm, conf_string, NULL);
4714137ff4cSJacques Vidrine
472ae771770SStanislav Sedov _krb5_debug(context, 2, "configuration file for realm %s%s found",
473ae771770SStanislav Sedov kd->realm, hostlist ? "" : " not");
474ae771770SStanislav Sedov
4754137ff4cSJacques Vidrine if(hostlist == NULL)
4764137ff4cSJacques Vidrine return;
4774137ff4cSJacques Vidrine kd->flags |= KD_CONFIG_EXISTS;
4784137ff4cSJacques Vidrine for(i = 0; hostlist && hostlist[i] != NULL; i++)
4794137ff4cSJacques Vidrine append_host_string(context, kd, hostlist[i], kd->def_port, kd->port);
4804137ff4cSJacques Vidrine
4814137ff4cSJacques Vidrine krb5_config_free_strings(hostlist);
4824137ff4cSJacques Vidrine }
4834137ff4cSJacques Vidrine
4844137ff4cSJacques Vidrine /*
4854137ff4cSJacques Vidrine * as a fallback, look for `serv_string.kd->realm' (typically
4864137ff4cSJacques Vidrine * kerberos.REALM, kerberos-1.REALM, ...
4874137ff4cSJacques Vidrine * `port' is the default port for the service, and `proto' the
4884137ff4cSJacques Vidrine * protocol
4894137ff4cSJacques Vidrine */
4904137ff4cSJacques Vidrine
4914137ff4cSJacques Vidrine static krb5_error_code
fallback_get_hosts(krb5_context context,struct krb5_krbhst_data * kd,const char * serv_string,int port,int proto)4924137ff4cSJacques Vidrine fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
4934137ff4cSJacques Vidrine const char *serv_string, int port, int proto)
4944137ff4cSJacques Vidrine {
495ae771770SStanislav Sedov char *host = NULL;
4964137ff4cSJacques Vidrine int ret;
4974137ff4cSJacques Vidrine struct addrinfo *ai;
4984137ff4cSJacques Vidrine struct addrinfo hints;
4994137ff4cSJacques Vidrine char portstr[NI_MAXSERV];
5004137ff4cSJacques Vidrine
501ae771770SStanislav Sedov _krb5_debug(context, 2, "fallback lookup %d for realm %s (service %s)",
502ae771770SStanislav Sedov kd->fallback_count, kd->realm, serv_string);
503ae771770SStanislav Sedov
504c19800e8SDoug Rabson /*
505c19800e8SDoug Rabson * Don't try forever in case the DNS server keep returning us
506c19800e8SDoug Rabson * entries (like wildcard entries or the .nu TLD)
507c19800e8SDoug Rabson */
508c19800e8SDoug Rabson if(kd->fallback_count >= 5) {
509c19800e8SDoug Rabson kd->flags |= KD_FALLBACK;
510c19800e8SDoug Rabson return 0;
511c19800e8SDoug Rabson }
512c19800e8SDoug Rabson
5134137ff4cSJacques Vidrine if(kd->fallback_count == 0)
514ae771770SStanislav Sedov ret = asprintf(&host, "%s.%s.", serv_string, kd->realm);
5154137ff4cSJacques Vidrine else
516ae771770SStanislav Sedov ret = asprintf(&host, "%s-%d.%s.",
5174137ff4cSJacques Vidrine serv_string, kd->fallback_count, kd->realm);
5184137ff4cSJacques Vidrine
519ae771770SStanislav Sedov if (ret < 0 || host == NULL)
5204137ff4cSJacques Vidrine return ENOMEM;
5214137ff4cSJacques Vidrine
5224137ff4cSJacques Vidrine make_hints(&hints, proto);
5234137ff4cSJacques Vidrine snprintf(portstr, sizeof(portstr), "%d", port);
5244137ff4cSJacques Vidrine ret = getaddrinfo(host, portstr, &hints, &ai);
5254137ff4cSJacques Vidrine if (ret) {
5264137ff4cSJacques Vidrine /* no more hosts, so we're done here */
5274137ff4cSJacques Vidrine free(host);
5284137ff4cSJacques Vidrine kd->flags |= KD_FALLBACK;
5294137ff4cSJacques Vidrine } else {
5304137ff4cSJacques Vidrine struct krb5_krbhst_info *hi;
5314137ff4cSJacques Vidrine size_t hostlen = strlen(host);
5324137ff4cSJacques Vidrine
5334137ff4cSJacques Vidrine hi = calloc(1, sizeof(*hi) + hostlen);
5344137ff4cSJacques Vidrine if(hi == NULL) {
5354137ff4cSJacques Vidrine free(host);
5364137ff4cSJacques Vidrine return ENOMEM;
5374137ff4cSJacques Vidrine }
5384137ff4cSJacques Vidrine
5394137ff4cSJacques Vidrine hi->proto = proto;
5404137ff4cSJacques Vidrine hi->port = hi->def_port = port;
5414137ff4cSJacques Vidrine hi->ai = ai;
542c19800e8SDoug Rabson memmove(hi->hostname, host, hostlen);
543c19800e8SDoug Rabson hi->hostname[hostlen] = '\0';
5444137ff4cSJacques Vidrine free(host);
5454137ff4cSJacques Vidrine append_host_hostinfo(kd, hi);
5464137ff4cSJacques Vidrine kd->fallback_count++;
5474137ff4cSJacques Vidrine }
5484137ff4cSJacques Vidrine return 0;
5494137ff4cSJacques Vidrine }
5504137ff4cSJacques Vidrine
551c19800e8SDoug Rabson /*
552c19800e8SDoug Rabson * Fetch hosts from plugin
553c19800e8SDoug Rabson */
554c19800e8SDoug Rabson
555c19800e8SDoug Rabson static krb5_error_code
add_locate(void * ctx,int type,struct sockaddr * addr)556c19800e8SDoug Rabson add_locate(void *ctx, int type, struct sockaddr *addr)
557c19800e8SDoug Rabson {
558c19800e8SDoug Rabson struct krb5_krbhst_info *hi;
559c19800e8SDoug Rabson struct krb5_krbhst_data *kd = ctx;
560c19800e8SDoug Rabson char host[NI_MAXHOST], port[NI_MAXSERV];
561c19800e8SDoug Rabson struct addrinfo hints, *ai;
562c19800e8SDoug Rabson socklen_t socklen;
563c19800e8SDoug Rabson size_t hostlen;
564c19800e8SDoug Rabson int ret;
565c19800e8SDoug Rabson
566c19800e8SDoug Rabson socklen = socket_sockaddr_size(addr);
567c19800e8SDoug Rabson
568c19800e8SDoug Rabson ret = getnameinfo(addr, socklen, host, sizeof(host), port, sizeof(port),
569c19800e8SDoug Rabson NI_NUMERICHOST|NI_NUMERICSERV);
570c19800e8SDoug Rabson if (ret != 0)
571c19800e8SDoug Rabson return 0;
572c19800e8SDoug Rabson
573c19800e8SDoug Rabson make_hints(&hints, krbhst_get_default_proto(kd));
574c19800e8SDoug Rabson ret = getaddrinfo(host, port, &hints, &ai);
575c19800e8SDoug Rabson if (ret)
576c19800e8SDoug Rabson return 0;
577c19800e8SDoug Rabson
578c19800e8SDoug Rabson hostlen = strlen(host);
579c19800e8SDoug Rabson
580c19800e8SDoug Rabson hi = calloc(1, sizeof(*hi) + hostlen);
581c19800e8SDoug Rabson if(hi == NULL)
582c19800e8SDoug Rabson return ENOMEM;
583c19800e8SDoug Rabson
584c19800e8SDoug Rabson hi->proto = krbhst_get_default_proto(kd);
585c19800e8SDoug Rabson hi->port = hi->def_port = socket_get_port(addr);
586c19800e8SDoug Rabson hi->ai = ai;
587c19800e8SDoug Rabson memmove(hi->hostname, host, hostlen);
588c19800e8SDoug Rabson hi->hostname[hostlen] = '\0';
589c19800e8SDoug Rabson append_host_hostinfo(kd, hi);
590c19800e8SDoug Rabson
591c19800e8SDoug Rabson return 0;
592c19800e8SDoug Rabson }
593c19800e8SDoug Rabson
594c19800e8SDoug Rabson static void
plugin_get_hosts(krb5_context context,struct krb5_krbhst_data * kd,enum locate_service_type type)595c19800e8SDoug Rabson plugin_get_hosts(krb5_context context,
596c19800e8SDoug Rabson struct krb5_krbhst_data *kd,
597c19800e8SDoug Rabson enum locate_service_type type)
598c19800e8SDoug Rabson {
599c19800e8SDoug Rabson struct krb5_plugin *list = NULL, *e;
600c19800e8SDoug Rabson krb5_error_code ret;
601c19800e8SDoug Rabson
602ae771770SStanislav Sedov ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA,
603ae771770SStanislav Sedov KRB5_PLUGIN_LOCATE, &list);
604c19800e8SDoug Rabson if(ret != 0 || list == NULL)
605c19800e8SDoug Rabson return;
606c19800e8SDoug Rabson
607c19800e8SDoug Rabson for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) {
608c19800e8SDoug Rabson krb5plugin_service_locate_ftable *service;
609c19800e8SDoug Rabson void *ctx;
610c19800e8SDoug Rabson
611c19800e8SDoug Rabson service = _krb5_plugin_get_symbol(e);
612c19800e8SDoug Rabson if (service->minor_version != 0)
613c19800e8SDoug Rabson continue;
614c19800e8SDoug Rabson
615c19800e8SDoug Rabson (*service->init)(context, &ctx);
616c19800e8SDoug Rabson ret = (*service->lookup)(ctx, type, kd->realm, 0, 0, add_locate, kd);
617c19800e8SDoug Rabson (*service->fini)(ctx);
618ae771770SStanislav Sedov if (ret && ret != KRB5_PLUGIN_NO_HANDLE) {
619ae771770SStanislav Sedov krb5_set_error_message(context, ret,
620ae771770SStanislav Sedov N_("Locate plugin failed to lookup realm %s: %d", ""),
621ae771770SStanislav Sedov kd->realm, ret);
622c19800e8SDoug Rabson break;
623ae771770SStanislav Sedov } else if (ret == 0) {
624ae771770SStanislav Sedov _krb5_debug(context, 2, "plugin found result for realm %s", kd->realm);
625ae771770SStanislav Sedov kd->flags |= KD_CONFIG_EXISTS;
626c19800e8SDoug Rabson }
627ae771770SStanislav Sedov
628c19800e8SDoug Rabson }
629c19800e8SDoug Rabson _krb5_plugin_free(list);
630c19800e8SDoug Rabson }
631c19800e8SDoug Rabson
632c19800e8SDoug Rabson /*
633c19800e8SDoug Rabson *
634c19800e8SDoug Rabson */
635c19800e8SDoug Rabson
6364137ff4cSJacques Vidrine static krb5_error_code
kdc_get_next(krb5_context context,struct krb5_krbhst_data * kd,krb5_krbhst_info ** host)6374137ff4cSJacques Vidrine kdc_get_next(krb5_context context,
6384137ff4cSJacques Vidrine struct krb5_krbhst_data *kd,
6394137ff4cSJacques Vidrine krb5_krbhst_info **host)
6404137ff4cSJacques Vidrine {
6414137ff4cSJacques Vidrine krb5_error_code ret;
6424137ff4cSJacques Vidrine
643c19800e8SDoug Rabson if ((kd->flags & KD_PLUGIN) == 0) {
644c19800e8SDoug Rabson plugin_get_hosts(context, kd, locate_service_kdc);
645c19800e8SDoug Rabson kd->flags |= KD_PLUGIN;
646c19800e8SDoug Rabson if(get_next(kd, host))
647c19800e8SDoug Rabson return 0;
648c19800e8SDoug Rabson }
649c19800e8SDoug Rabson
6504137ff4cSJacques Vidrine if((kd->flags & KD_CONFIG) == 0) {
6514137ff4cSJacques Vidrine config_get_hosts(context, kd, "kdc");
6524137ff4cSJacques Vidrine kd->flags |= KD_CONFIG;
6534137ff4cSJacques Vidrine if(get_next(kd, host))
6544137ff4cSJacques Vidrine return 0;
6554137ff4cSJacques Vidrine }
6564137ff4cSJacques Vidrine
657ae771770SStanislav Sedov if (kd->flags & KD_CONFIG_EXISTS) {
658ae771770SStanislav Sedov _krb5_debug(context, 1,
659ae771770SStanislav Sedov "Configuration exists for realm %s, wont go to DNS",
660ae771770SStanislav Sedov kd->realm);
661ae771770SStanislav Sedov return KRB5_KDC_UNREACH;
662ae771770SStanislav Sedov }
6634137ff4cSJacques Vidrine
6644137ff4cSJacques Vidrine if(context->srv_lookup) {
665c19800e8SDoug Rabson if((kd->flags & KD_SRV_UDP) == 0 && (kd->flags & KD_LARGE_MSG) == 0) {
6664137ff4cSJacques Vidrine srv_get_hosts(context, kd, "udp", "kerberos");
6674137ff4cSJacques Vidrine kd->flags |= KD_SRV_UDP;
6684137ff4cSJacques Vidrine if(get_next(kd, host))
6694137ff4cSJacques Vidrine return 0;
6704137ff4cSJacques Vidrine }
6714137ff4cSJacques Vidrine
6724137ff4cSJacques Vidrine if((kd->flags & KD_SRV_TCP) == 0) {
6734137ff4cSJacques Vidrine srv_get_hosts(context, kd, "tcp", "kerberos");
6744137ff4cSJacques Vidrine kd->flags |= KD_SRV_TCP;
6754137ff4cSJacques Vidrine if(get_next(kd, host))
6764137ff4cSJacques Vidrine return 0;
6774137ff4cSJacques Vidrine }
6784137ff4cSJacques Vidrine if((kd->flags & KD_SRV_HTTP) == 0) {
6794137ff4cSJacques Vidrine srv_get_hosts(context, kd, "http", "kerberos");
6804137ff4cSJacques Vidrine kd->flags |= KD_SRV_HTTP;
6814137ff4cSJacques Vidrine if(get_next(kd, host))
6824137ff4cSJacques Vidrine return 0;
6834137ff4cSJacques Vidrine }
6844137ff4cSJacques Vidrine }
6854137ff4cSJacques Vidrine
6864137ff4cSJacques Vidrine while((kd->flags & KD_FALLBACK) == 0) {
6874137ff4cSJacques Vidrine ret = fallback_get_hosts(context, kd, "kerberos",
688c19800e8SDoug Rabson kd->def_port,
689c19800e8SDoug Rabson krbhst_get_default_proto(kd));
6904137ff4cSJacques Vidrine if(ret)
6914137ff4cSJacques Vidrine return ret;
6924137ff4cSJacques Vidrine if(get_next(kd, host))
6934137ff4cSJacques Vidrine return 0;
6944137ff4cSJacques Vidrine }
6954137ff4cSJacques Vidrine
696ae771770SStanislav Sedov _krb5_debug(context, 0, "No KDC entries found for %s", kd->realm);
697ae771770SStanislav Sedov
6984137ff4cSJacques Vidrine return KRB5_KDC_UNREACH; /* XXX */
6994137ff4cSJacques Vidrine }
7004137ff4cSJacques Vidrine
7014137ff4cSJacques Vidrine static krb5_error_code
admin_get_next(krb5_context context,struct krb5_krbhst_data * kd,krb5_krbhst_info ** host)7024137ff4cSJacques Vidrine admin_get_next(krb5_context context,
7034137ff4cSJacques Vidrine struct krb5_krbhst_data *kd,
7044137ff4cSJacques Vidrine krb5_krbhst_info **host)
7054137ff4cSJacques Vidrine {
7064137ff4cSJacques Vidrine krb5_error_code ret;
7074137ff4cSJacques Vidrine
708c19800e8SDoug Rabson if ((kd->flags & KD_PLUGIN) == 0) {
709c19800e8SDoug Rabson plugin_get_hosts(context, kd, locate_service_kadmin);
710c19800e8SDoug Rabson kd->flags |= KD_PLUGIN;
711c19800e8SDoug Rabson if(get_next(kd, host))
712c19800e8SDoug Rabson return 0;
713c19800e8SDoug Rabson }
714c19800e8SDoug Rabson
7154137ff4cSJacques Vidrine if((kd->flags & KD_CONFIG) == 0) {
7164137ff4cSJacques Vidrine config_get_hosts(context, kd, "admin_server");
7174137ff4cSJacques Vidrine kd->flags |= KD_CONFIG;
7184137ff4cSJacques Vidrine if(get_next(kd, host))
7194137ff4cSJacques Vidrine return 0;
7204137ff4cSJacques Vidrine }
7214137ff4cSJacques Vidrine
722ae771770SStanislav Sedov if (kd->flags & KD_CONFIG_EXISTS) {
723ae771770SStanislav Sedov _krb5_debug(context, 1,
724ae771770SStanislav Sedov "Configuration exists for realm %s, wont go to DNS",
725ae771770SStanislav Sedov kd->realm);
726ae771770SStanislav Sedov return KRB5_KDC_UNREACH;
727ae771770SStanislav Sedov }
7284137ff4cSJacques Vidrine
7294137ff4cSJacques Vidrine if(context->srv_lookup) {
7304137ff4cSJacques Vidrine if((kd->flags & KD_SRV_TCP) == 0) {
7314137ff4cSJacques Vidrine srv_get_hosts(context, kd, "tcp", "kerberos-adm");
7324137ff4cSJacques Vidrine kd->flags |= KD_SRV_TCP;
7334137ff4cSJacques Vidrine if(get_next(kd, host))
7344137ff4cSJacques Vidrine return 0;
7354137ff4cSJacques Vidrine }
7364137ff4cSJacques Vidrine }
7374137ff4cSJacques Vidrine
7384137ff4cSJacques Vidrine if (krbhst_empty(kd)
7394137ff4cSJacques Vidrine && (kd->flags & KD_FALLBACK) == 0) {
7404137ff4cSJacques Vidrine ret = fallback_get_hosts(context, kd, "kerberos",
741c19800e8SDoug Rabson kd->def_port,
742c19800e8SDoug Rabson krbhst_get_default_proto(kd));
7434137ff4cSJacques Vidrine if(ret)
7444137ff4cSJacques Vidrine return ret;
7454137ff4cSJacques Vidrine kd->flags |= KD_FALLBACK;
7464137ff4cSJacques Vidrine if(get_next(kd, host))
7474137ff4cSJacques Vidrine return 0;
7484137ff4cSJacques Vidrine }
7494137ff4cSJacques Vidrine
750ae771770SStanislav Sedov _krb5_debug(context, 0, "No admin entries found for realm %s", kd->realm);
751ae771770SStanislav Sedov
7524137ff4cSJacques Vidrine return KRB5_KDC_UNREACH; /* XXX */
7534137ff4cSJacques Vidrine }
7544137ff4cSJacques Vidrine
7554137ff4cSJacques Vidrine static krb5_error_code
kpasswd_get_next(krb5_context context,struct krb5_krbhst_data * kd,krb5_krbhst_info ** host)7564137ff4cSJacques Vidrine kpasswd_get_next(krb5_context context,
7574137ff4cSJacques Vidrine struct krb5_krbhst_data *kd,
7584137ff4cSJacques Vidrine krb5_krbhst_info **host)
7594137ff4cSJacques Vidrine {
7608373020dSJacques Vidrine krb5_error_code ret;
7618373020dSJacques Vidrine
762c19800e8SDoug Rabson if ((kd->flags & KD_PLUGIN) == 0) {
763c19800e8SDoug Rabson plugin_get_hosts(context, kd, locate_service_kpasswd);
764c19800e8SDoug Rabson kd->flags |= KD_PLUGIN;
765c19800e8SDoug Rabson if(get_next(kd, host))
766c19800e8SDoug Rabson return 0;
767c19800e8SDoug Rabson }
768c19800e8SDoug Rabson
7694137ff4cSJacques Vidrine if((kd->flags & KD_CONFIG) == 0) {
7704137ff4cSJacques Vidrine config_get_hosts(context, kd, "kpasswd_server");
771c19800e8SDoug Rabson kd->flags |= KD_CONFIG;
7724137ff4cSJacques Vidrine if(get_next(kd, host))
7734137ff4cSJacques Vidrine return 0;
7744137ff4cSJacques Vidrine }
7754137ff4cSJacques Vidrine
776ae771770SStanislav Sedov if (kd->flags & KD_CONFIG_EXISTS) {
777ae771770SStanislav Sedov _krb5_debug(context, 1,
778ae771770SStanislav Sedov "Configuration exists for realm %s, wont go to DNS",
779ae771770SStanislav Sedov kd->realm);
780ae771770SStanislav Sedov return KRB5_KDC_UNREACH;
781ae771770SStanislav Sedov }
7824137ff4cSJacques Vidrine
7834137ff4cSJacques Vidrine if(context->srv_lookup) {
7844137ff4cSJacques Vidrine if((kd->flags & KD_SRV_UDP) == 0) {
7854137ff4cSJacques Vidrine srv_get_hosts(context, kd, "udp", "kpasswd");
7864137ff4cSJacques Vidrine kd->flags |= KD_SRV_UDP;
7874137ff4cSJacques Vidrine if(get_next(kd, host))
7884137ff4cSJacques Vidrine return 0;
7894137ff4cSJacques Vidrine }
790c19800e8SDoug Rabson if((kd->flags & KD_SRV_TCP) == 0) {
791c19800e8SDoug Rabson srv_get_hosts(context, kd, "tcp", "kpasswd");
792c19800e8SDoug Rabson kd->flags |= KD_SRV_TCP;
793c19800e8SDoug Rabson if(get_next(kd, host))
794c19800e8SDoug Rabson return 0;
795c19800e8SDoug Rabson }
7964137ff4cSJacques Vidrine }
7974137ff4cSJacques Vidrine
7984137ff4cSJacques Vidrine /* no matches -> try admin */
7994137ff4cSJacques Vidrine
8004137ff4cSJacques Vidrine if (krbhst_empty(kd)) {
8014137ff4cSJacques Vidrine kd->flags = 0;
8024137ff4cSJacques Vidrine kd->port = kd->def_port;
8034137ff4cSJacques Vidrine kd->get_next = admin_get_next;
8048373020dSJacques Vidrine ret = (*kd->get_next)(context, kd, host);
8058373020dSJacques Vidrine if (ret == 0)
806c19800e8SDoug Rabson (*host)->proto = krbhst_get_default_proto(kd);
8078373020dSJacques Vidrine return ret;
8084137ff4cSJacques Vidrine }
8094137ff4cSJacques Vidrine
810ae771770SStanislav Sedov _krb5_debug(context, 0, "No kpasswd entries found for realm %s", kd->realm);
811ae771770SStanislav Sedov
812ae771770SStanislav Sedov return KRB5_KDC_UNREACH;
8134137ff4cSJacques Vidrine }
8144137ff4cSJacques Vidrine
8154137ff4cSJacques Vidrine static krb5_error_code
krb524_get_next(krb5_context context,struct krb5_krbhst_data * kd,krb5_krbhst_info ** host)8164137ff4cSJacques Vidrine krb524_get_next(krb5_context context,
8174137ff4cSJacques Vidrine struct krb5_krbhst_data *kd,
8184137ff4cSJacques Vidrine krb5_krbhst_info **host)
8194137ff4cSJacques Vidrine {
820c19800e8SDoug Rabson if ((kd->flags & KD_PLUGIN) == 0) {
821c19800e8SDoug Rabson plugin_get_hosts(context, kd, locate_service_krb524);
822c19800e8SDoug Rabson kd->flags |= KD_PLUGIN;
823c19800e8SDoug Rabson if(get_next(kd, host))
824c19800e8SDoug Rabson return 0;
825c19800e8SDoug Rabson }
826c19800e8SDoug Rabson
8274137ff4cSJacques Vidrine if((kd->flags & KD_CONFIG) == 0) {
8284137ff4cSJacques Vidrine config_get_hosts(context, kd, "krb524_server");
8294137ff4cSJacques Vidrine if(get_next(kd, host))
8304137ff4cSJacques Vidrine return 0;
8314137ff4cSJacques Vidrine kd->flags |= KD_CONFIG;
8324137ff4cSJacques Vidrine }
8334137ff4cSJacques Vidrine
834ae771770SStanislav Sedov if (kd->flags & KD_CONFIG_EXISTS) {
835ae771770SStanislav Sedov _krb5_debug(context, 1,
836ae771770SStanislav Sedov "Configuration exists for realm %s, wont go to DNS",
837ae771770SStanislav Sedov kd->realm);
838ae771770SStanislav Sedov return KRB5_KDC_UNREACH;
839ae771770SStanislav Sedov }
8404137ff4cSJacques Vidrine
8414137ff4cSJacques Vidrine if(context->srv_lookup) {
8424137ff4cSJacques Vidrine if((kd->flags & KD_SRV_UDP) == 0) {
8434137ff4cSJacques Vidrine srv_get_hosts(context, kd, "udp", "krb524");
8444137ff4cSJacques Vidrine kd->flags |= KD_SRV_UDP;
8454137ff4cSJacques Vidrine if(get_next(kd, host))
8464137ff4cSJacques Vidrine return 0;
8474137ff4cSJacques Vidrine }
8484137ff4cSJacques Vidrine
8494137ff4cSJacques Vidrine if((kd->flags & KD_SRV_TCP) == 0) {
8504137ff4cSJacques Vidrine srv_get_hosts(context, kd, "tcp", "krb524");
8514137ff4cSJacques Vidrine kd->flags |= KD_SRV_TCP;
8524137ff4cSJacques Vidrine if(get_next(kd, host))
8534137ff4cSJacques Vidrine return 0;
8544137ff4cSJacques Vidrine }
8554137ff4cSJacques Vidrine }
8564137ff4cSJacques Vidrine
8574137ff4cSJacques Vidrine /* no matches -> try kdc */
8584137ff4cSJacques Vidrine
8594137ff4cSJacques Vidrine if (krbhst_empty(kd)) {
8604137ff4cSJacques Vidrine kd->flags = 0;
8614137ff4cSJacques Vidrine kd->port = kd->def_port;
8624137ff4cSJacques Vidrine kd->get_next = kdc_get_next;
8634137ff4cSJacques Vidrine return (*kd->get_next)(context, kd, host);
8644137ff4cSJacques Vidrine }
8654137ff4cSJacques Vidrine
866ae771770SStanislav Sedov _krb5_debug(context, 0, "No kpasswd entries found for realm %s", kd->realm);
867ae771770SStanislav Sedov
868ae771770SStanislav Sedov return KRB5_KDC_UNREACH;
8694137ff4cSJacques Vidrine }
8704137ff4cSJacques Vidrine
8714137ff4cSJacques Vidrine static struct krb5_krbhst_data*
common_init(krb5_context context,const char * service,const char * realm,int flags)8724137ff4cSJacques Vidrine common_init(krb5_context context,
873ae771770SStanislav Sedov const char *service,
874c19800e8SDoug Rabson const char *realm,
875c19800e8SDoug Rabson int flags)
8764137ff4cSJacques Vidrine {
8774137ff4cSJacques Vidrine struct krb5_krbhst_data *kd;
8784137ff4cSJacques Vidrine
8794137ff4cSJacques Vidrine if((kd = calloc(1, sizeof(*kd))) == NULL)
8804137ff4cSJacques Vidrine return NULL;
8814137ff4cSJacques Vidrine
8824137ff4cSJacques Vidrine if((kd->realm = strdup(realm)) == NULL) {
8834137ff4cSJacques Vidrine free(kd);
8844137ff4cSJacques Vidrine return NULL;
8854137ff4cSJacques Vidrine }
8864137ff4cSJacques Vidrine
887ae771770SStanislav Sedov _krb5_debug(context, 2, "Trying to find service %s for realm %s flags %x",
888ae771770SStanislav Sedov service, realm, flags);
889ae771770SStanislav Sedov
890c19800e8SDoug Rabson /* For 'realms' without a . do not even think of going to DNS */
891c19800e8SDoug Rabson if (!strchr(realm, '.'))
892c19800e8SDoug Rabson kd->flags |= KD_CONFIG_EXISTS;
893c19800e8SDoug Rabson
894c19800e8SDoug Rabson if (flags & KRB5_KRBHST_FLAGS_LARGE_MSG)
895c19800e8SDoug Rabson kd->flags |= KD_LARGE_MSG;
8964137ff4cSJacques Vidrine kd->end = kd->index = &kd->hosts;
8974137ff4cSJacques Vidrine return kd;
8984137ff4cSJacques Vidrine }
8994137ff4cSJacques Vidrine
9004137ff4cSJacques Vidrine /*
9014137ff4cSJacques Vidrine * initialize `handle' to look for hosts of type `type' in realm `realm'
9024137ff4cSJacques Vidrine */
9034137ff4cSJacques Vidrine
904ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_krbhst_init(krb5_context context,const char * realm,unsigned int type,krb5_krbhst_handle * handle)9054137ff4cSJacques Vidrine krb5_krbhst_init(krb5_context context,
9064137ff4cSJacques Vidrine const char *realm,
9074137ff4cSJacques Vidrine unsigned int type,
9084137ff4cSJacques Vidrine krb5_krbhst_handle *handle)
9094137ff4cSJacques Vidrine {
910c19800e8SDoug Rabson return krb5_krbhst_init_flags(context, realm, type, 0, handle);
911c19800e8SDoug Rabson }
912c19800e8SDoug Rabson
913ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_krbhst_init_flags(krb5_context context,const char * realm,unsigned int type,int flags,krb5_krbhst_handle * handle)914c19800e8SDoug Rabson krb5_krbhst_init_flags(krb5_context context,
915c19800e8SDoug Rabson const char *realm,
916c19800e8SDoug Rabson unsigned int type,
917c19800e8SDoug Rabson int flags,
918c19800e8SDoug Rabson krb5_krbhst_handle *handle)
919c19800e8SDoug Rabson {
9204137ff4cSJacques Vidrine struct krb5_krbhst_data *kd;
921c19800e8SDoug Rabson krb5_error_code (*next)(krb5_context, struct krb5_krbhst_data *,
9224137ff4cSJacques Vidrine krb5_krbhst_info **);
9234137ff4cSJacques Vidrine int def_port;
924ae771770SStanislav Sedov const char *service;
9254137ff4cSJacques Vidrine
9264137ff4cSJacques Vidrine switch(type) {
9274137ff4cSJacques Vidrine case KRB5_KRBHST_KDC:
928c19800e8SDoug Rabson next = kdc_get_next;
9294137ff4cSJacques Vidrine def_port = ntohs(krb5_getportbyname (context, "kerberos", "udp", 88));
930ae771770SStanislav Sedov service = "kdc";
9314137ff4cSJacques Vidrine break;
9324137ff4cSJacques Vidrine case KRB5_KRBHST_ADMIN:
933c19800e8SDoug Rabson next = admin_get_next;
9344137ff4cSJacques Vidrine def_port = ntohs(krb5_getportbyname (context, "kerberos-adm",
9354137ff4cSJacques Vidrine "tcp", 749));
936ae771770SStanislav Sedov service = "admin";
9374137ff4cSJacques Vidrine break;
9384137ff4cSJacques Vidrine case KRB5_KRBHST_CHANGEPW:
939c19800e8SDoug Rabson next = kpasswd_get_next;
9404137ff4cSJacques Vidrine def_port = ntohs(krb5_getportbyname (context, "kpasswd", "udp",
9414137ff4cSJacques Vidrine KPASSWD_PORT));
942ae771770SStanislav Sedov service = "change_password";
9434137ff4cSJacques Vidrine break;
9444137ff4cSJacques Vidrine case KRB5_KRBHST_KRB524:
945c19800e8SDoug Rabson next = krb524_get_next;
9464137ff4cSJacques Vidrine def_port = ntohs(krb5_getportbyname (context, "krb524", "udp", 4444));
947ae771770SStanislav Sedov service = "524";
9484137ff4cSJacques Vidrine break;
9494137ff4cSJacques Vidrine default:
950ae771770SStanislav Sedov krb5_set_error_message(context, ENOTTY,
951ae771770SStanislav Sedov N_("unknown krbhst type (%u)", ""), type);
9524137ff4cSJacques Vidrine return ENOTTY;
9534137ff4cSJacques Vidrine }
954ae771770SStanislav Sedov if((kd = common_init(context, service, realm, flags)) == NULL)
9554137ff4cSJacques Vidrine return ENOMEM;
956c19800e8SDoug Rabson kd->get_next = next;
9574137ff4cSJacques Vidrine kd->def_port = def_port;
9584137ff4cSJacques Vidrine *handle = kd;
9594137ff4cSJacques Vidrine return 0;
9604137ff4cSJacques Vidrine }
9614137ff4cSJacques Vidrine
9624137ff4cSJacques Vidrine /*
9634137ff4cSJacques Vidrine * return the next host information from `handle' in `host'
9644137ff4cSJacques Vidrine */
9654137ff4cSJacques Vidrine
966ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_krbhst_next(krb5_context context,krb5_krbhst_handle handle,krb5_krbhst_info ** host)9674137ff4cSJacques Vidrine krb5_krbhst_next(krb5_context context,
9684137ff4cSJacques Vidrine krb5_krbhst_handle handle,
9694137ff4cSJacques Vidrine krb5_krbhst_info **host)
9704137ff4cSJacques Vidrine {
9714137ff4cSJacques Vidrine if(get_next(handle, host))
9724137ff4cSJacques Vidrine return 0;
9734137ff4cSJacques Vidrine
9744137ff4cSJacques Vidrine return (*handle->get_next)(context, handle, host);
9754137ff4cSJacques Vidrine }
9764137ff4cSJacques Vidrine
9774137ff4cSJacques Vidrine /*
9784137ff4cSJacques Vidrine * return the next host information from `handle' as a host name
9794137ff4cSJacques Vidrine * in `hostname' (or length `hostlen)
9804137ff4cSJacques Vidrine */
9814137ff4cSJacques Vidrine
982ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_krbhst_next_as_string(krb5_context context,krb5_krbhst_handle handle,char * hostname,size_t hostlen)9834137ff4cSJacques Vidrine krb5_krbhst_next_as_string(krb5_context context,
9844137ff4cSJacques Vidrine krb5_krbhst_handle handle,
9854137ff4cSJacques Vidrine char *hostname,
9864137ff4cSJacques Vidrine size_t hostlen)
9874137ff4cSJacques Vidrine {
9884137ff4cSJacques Vidrine krb5_error_code ret;
9894137ff4cSJacques Vidrine krb5_krbhst_info *host;
9904137ff4cSJacques Vidrine ret = krb5_krbhst_next(context, handle, &host);
9914137ff4cSJacques Vidrine if(ret)
9924137ff4cSJacques Vidrine return ret;
9934137ff4cSJacques Vidrine return krb5_krbhst_format_string(context, host, hostname, hostlen);
9944137ff4cSJacques Vidrine }
9954137ff4cSJacques Vidrine
9964137ff4cSJacques Vidrine
997ae771770SStanislav Sedov KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_krbhst_reset(krb5_context context,krb5_krbhst_handle handle)9984137ff4cSJacques Vidrine krb5_krbhst_reset(krb5_context context, krb5_krbhst_handle handle)
9994137ff4cSJacques Vidrine {
10004137ff4cSJacques Vidrine handle->index = &handle->hosts;
10014137ff4cSJacques Vidrine }
10024137ff4cSJacques Vidrine
1003ae771770SStanislav Sedov KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_krbhst_free(krb5_context context,krb5_krbhst_handle handle)10044137ff4cSJacques Vidrine krb5_krbhst_free(krb5_context context, krb5_krbhst_handle handle)
10054137ff4cSJacques Vidrine {
10064137ff4cSJacques Vidrine krb5_krbhst_info *h, *next;
10074137ff4cSJacques Vidrine
10084137ff4cSJacques Vidrine if (handle == NULL)
10094137ff4cSJacques Vidrine return;
10104137ff4cSJacques Vidrine
10114137ff4cSJacques Vidrine for (h = handle->hosts; h != NULL; h = next) {
10124137ff4cSJacques Vidrine next = h->next;
1013c19800e8SDoug Rabson _krb5_free_krbhst_info(h);
10144137ff4cSJacques Vidrine }
10154137ff4cSJacques Vidrine
10164137ff4cSJacques Vidrine free(handle->realm);
10174137ff4cSJacques Vidrine free(handle);
10184137ff4cSJacques Vidrine }
10194137ff4cSJacques Vidrine
10204137ff4cSJacques Vidrine /* backwards compatibility ahead */
10214137ff4cSJacques Vidrine
10224137ff4cSJacques Vidrine static krb5_error_code
gethostlist(krb5_context context,const char * realm,unsigned int type,char *** hostlist)10234137ff4cSJacques Vidrine gethostlist(krb5_context context, const char *realm,
10244137ff4cSJacques Vidrine unsigned int type, char ***hostlist)
10254137ff4cSJacques Vidrine {
10264137ff4cSJacques Vidrine krb5_error_code ret;
10274137ff4cSJacques Vidrine int nhost = 0;
10284137ff4cSJacques Vidrine krb5_krbhst_handle handle;
10294137ff4cSJacques Vidrine char host[MAXHOSTNAMELEN];
10304137ff4cSJacques Vidrine krb5_krbhst_info *hostinfo;
10314137ff4cSJacques Vidrine
10324137ff4cSJacques Vidrine ret = krb5_krbhst_init(context, realm, type, &handle);
10334137ff4cSJacques Vidrine if (ret)
10344137ff4cSJacques Vidrine return ret;
10354137ff4cSJacques Vidrine
10364137ff4cSJacques Vidrine while(krb5_krbhst_next(context, handle, &hostinfo) == 0)
10374137ff4cSJacques Vidrine nhost++;
1038c19800e8SDoug Rabson if(nhost == 0) {
1039ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_KDC_UNREACH,
1040ae771770SStanislav Sedov N_("No KDC found for realm %s", ""), realm);
10414137ff4cSJacques Vidrine return KRB5_KDC_UNREACH;
1042c19800e8SDoug Rabson }
10434137ff4cSJacques Vidrine *hostlist = calloc(nhost + 1, sizeof(**hostlist));
10444137ff4cSJacques Vidrine if(*hostlist == NULL) {
10454137ff4cSJacques Vidrine krb5_krbhst_free(context, handle);
10464137ff4cSJacques Vidrine return ENOMEM;
10474137ff4cSJacques Vidrine }
10484137ff4cSJacques Vidrine
10494137ff4cSJacques Vidrine krb5_krbhst_reset(context, handle);
10504137ff4cSJacques Vidrine nhost = 0;
10514137ff4cSJacques Vidrine while(krb5_krbhst_next_as_string(context, handle,
10524137ff4cSJacques Vidrine host, sizeof(host)) == 0) {
10534137ff4cSJacques Vidrine if(((*hostlist)[nhost++] = strdup(host)) == NULL) {
10544137ff4cSJacques Vidrine krb5_free_krbhst(context, *hostlist);
10554137ff4cSJacques Vidrine krb5_krbhst_free(context, handle);
10564137ff4cSJacques Vidrine return ENOMEM;
10574137ff4cSJacques Vidrine }
10584137ff4cSJacques Vidrine }
1059ae771770SStanislav Sedov (*hostlist)[nhost] = NULL;
10604137ff4cSJacques Vidrine krb5_krbhst_free(context, handle);
10614137ff4cSJacques Vidrine return 0;
10624137ff4cSJacques Vidrine }
10634137ff4cSJacques Vidrine
10644137ff4cSJacques Vidrine /*
10654137ff4cSJacques Vidrine * return an malloced list of kadmin-hosts for `realm' in `hostlist'
10665e9cd1aeSAssar Westerlund */
10675e9cd1aeSAssar Westerlund
1068ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_krb_admin_hst(krb5_context context,const krb5_realm * realm,char *** hostlist)1069b528cefcSMark Murray krb5_get_krb_admin_hst (krb5_context context,
1070b528cefcSMark Murray const krb5_realm *realm,
1071b528cefcSMark Murray char ***hostlist)
1072b528cefcSMark Murray {
10734137ff4cSJacques Vidrine return gethostlist(context, *realm, KRB5_KRBHST_ADMIN, hostlist);
1074b528cefcSMark Murray }
1075b528cefcSMark Murray
10765e9cd1aeSAssar Westerlund /*
10774137ff4cSJacques Vidrine * return an malloced list of changepw-hosts for `realm' in `hostlist'
10785e9cd1aeSAssar Westerlund */
10795e9cd1aeSAssar Westerlund
1080ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_krb_changepw_hst(krb5_context context,const krb5_realm * realm,char *** hostlist)1081b528cefcSMark Murray krb5_get_krb_changepw_hst (krb5_context context,
1082b528cefcSMark Murray const krb5_realm *realm,
1083b528cefcSMark Murray char ***hostlist)
1084b528cefcSMark Murray {
10854137ff4cSJacques Vidrine return gethostlist(context, *realm, KRB5_KRBHST_CHANGEPW, hostlist);
1086b528cefcSMark Murray }
1087b528cefcSMark Murray
10885e9cd1aeSAssar Westerlund /*
10894137ff4cSJacques Vidrine * return an malloced list of 524-hosts for `realm' in `hostlist'
10904137ff4cSJacques Vidrine */
10914137ff4cSJacques Vidrine
1092ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_krb524hst(krb5_context context,const krb5_realm * realm,char *** hostlist)10934137ff4cSJacques Vidrine krb5_get_krb524hst (krb5_context context,
10944137ff4cSJacques Vidrine const krb5_realm *realm,
10954137ff4cSJacques Vidrine char ***hostlist)
10964137ff4cSJacques Vidrine {
10974137ff4cSJacques Vidrine return gethostlist(context, *realm, KRB5_KRBHST_KRB524, hostlist);
10984137ff4cSJacques Vidrine }
10994137ff4cSJacques Vidrine
11004137ff4cSJacques Vidrine
11014137ff4cSJacques Vidrine /*
11024137ff4cSJacques Vidrine * return an malloced list of KDC's for `realm' in `hostlist'
11035e9cd1aeSAssar Westerlund */
11045e9cd1aeSAssar Westerlund
1105ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_krbhst(krb5_context context,const krb5_realm * realm,char *** hostlist)1106b528cefcSMark Murray krb5_get_krbhst (krb5_context context,
1107b528cefcSMark Murray const krb5_realm *realm,
1108b528cefcSMark Murray char ***hostlist)
1109b528cefcSMark Murray {
11104137ff4cSJacques Vidrine return gethostlist(context, *realm, KRB5_KRBHST_KDC, hostlist);
1111b528cefcSMark Murray }
1112b528cefcSMark Murray
11135e9cd1aeSAssar Westerlund /*
11144137ff4cSJacques Vidrine * free all the memory allocated in `hostlist'
11155e9cd1aeSAssar Westerlund */
11165e9cd1aeSAssar Westerlund
1117ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_free_krbhst(krb5_context context,char ** hostlist)1118b528cefcSMark Murray krb5_free_krbhst (krb5_context context,
1119b528cefcSMark Murray char **hostlist)
1120b528cefcSMark Murray {
1121b528cefcSMark Murray char **p;
1122b528cefcSMark Murray
1123b528cefcSMark Murray for (p = hostlist; *p; ++p)
1124b528cefcSMark Murray free (*p);
1125b528cefcSMark Murray free (hostlist);
1126b528cefcSMark Murray return 0;
1127b528cefcSMark Murray }
1128