2 * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
36 RCSID("$Id: get_host.c,v 1.48 1999/12/02 16:58:41 joda Exp $");
38 static struct host_list {
39 struct krb_host *this;
40 struct host_list *next;
43 static int krb_port = 0;
46 free_hosts(struct host_list *h)
61 parse_address(char *address, enum krb_host_proto *proto,
62 char **host, int *port)
65 int default_port = krb_port;
67 if(strncmp(address, "http://", 7) == 0){
72 p = strchr(address, '/');
75 strlcpy (prot, address,
76 min(p - address + 1, sizeof(prot)));
77 if(strcasecmp(prot, "udp") == 0)
79 else if(strcasecmp(prot, "tcp") == 0)
81 else if(strcasecmp(prot, "http") == 0) {
85 krb_warning("Unknown protocol `%s', Using default `udp'.\n",
93 *host = malloc(q - p + 1);
96 strlcpy (*host, p, q - p + 1);
99 struct servent *sp = getservbyname(q, NULL);
101 *port = ntohs(sp->s_port);
103 if(sscanf(q, "%d", port) != 1){
104 krb_warning("Bad port specification `%s', using port %d.",
110 *port = default_port;
113 *host = malloc(q - p + 1);
116 strlcpy (*host, p, q - p + 1);
127 add_host(const char *realm, char *address, int admin, int validate)
129 struct krb_host *host;
130 struct host_list *p, **last = &hosts;
132 host = (struct krb_host*)malloc(sizeof(struct krb_host));
135 if(parse_address(address, &host->proto, &host->host, &host->port) < 0) {
141 krb_warning("Getting host entry for %s...", host->host);
142 if (gethostbyname(host->host) == NULL) {
144 krb_warning("Didn't get it.\n");
149 else if (krb_dns_debug)
150 krb_warning("Got it.\n");
153 for(p = hosts; p; p = p->next){
154 if(strcmp(realm, p->this->realm) == 0 &&
155 strcmp(host->host, p->this->host) == 0 &&
156 host->proto == p->this->proto &&
157 host->port == p->this->port){
164 host->realm = strdup(realm);
165 if (host->realm == NULL) {
170 p = (struct host_list*)malloc(sizeof(struct host_list));
184 read_file(const char *filename, const char *r)
188 FILE *f = fopen(filename, "r");
192 while(fgets(line, sizeof(line), f) != NULL) {
193 char *realm, *address, *admin;
196 realm = strtok_r (line, " \t\n\r", &save);
199 if (strcmp(realm, r))
201 address = strtok_r (NULL, " \t\n\r", &save);
204 admin = strtok_r (NULL, " \t\n\r", &save);
207 admin != NULL && strcasecmp(admin, "admin") == 0,
217 read_cellservdb (const char *filename, const char *realm)
220 FILE *f = fopen (filename, "r");
225 while (fgets (line, sizeof(line), f) != NULL) {
227 && strncasecmp (line + 1, realm, strlen(realm)) == 0) {
228 while (fgets (line, sizeof(line), f) != NULL && *line != '>') {
231 if (line [strlen(line) - 1] == '\n')
232 line [strlen(line) - 1] = '\0';
234 hash = strchr (line, '#');
237 && add_host (realm, hash + 1, 0, 0) == 0)
249 init_hosts(char *realm)
252 char file[MaxPathLen];
255 * proto should really be NULL, but there are libraries out there
256 * that don't like that so we use "udp" instead.
259 krb_port = ntohs(k_getportbyname (KRB_SERVICE, "udp", htons(KRB_PORT)));
260 for(i = 0; krb_get_krbconf(i, file, sizeof(file)) == 0; i++) {
261 j = read_file(file, realm);
268 srv_find_realm(char *realm, char *proto, char *service)
272 struct resource_record *rr;
274 roken_mconcat(&domain, 1024, service, ".", proto, ".", realm, ".", NULL);
279 r = dns_lookup(domain, "srv");
281 r = dns_lookup(domain, "txt");
286 for(rr = r->head; rr; rr = rr->next){
287 if(rr->type == T_SRV){
295 rr->u.srv->port) < sizeof(buf))
296 add_host(realm, buf, 0, 0);
297 }else if(rr->type == T_TXT)
298 add_host(realm, rr->u.txt, 0, 0);
305 krb_get_host(int nth, const char *realm, int admin)
308 static char orealm[REALM_SZ];
310 if(orealm[0] == 0 || strcmp(realm, orealm)){
311 /* quick optimization */
312 if(realm && realm[0]){
313 strlcpy (orealm, realm, sizeof(orealm));
315 int ret = krb_get_lrealm(orealm, 1);
325 if (init_hosts(orealm) < nth) {
326 srv_find_realm(orealm, "udp", KRB_SERVICE);
327 srv_find_realm(orealm, "tcp", KRB_SERVICE);
328 srv_find_realm(orealm, "http", KRB_SERVICE);
334 asprintf(&host, "kerberos.%s.", orealm);
340 add_host(orealm, host, 1, 1);
344 asprintf(&host, "kerberos-%d.%s.", i, orealm);
347 && add_host(orealm, host, 0, 1) == 0);
352 read_cellservdb ("/usr/vice/etc/CellServDB", orealm);
353 read_cellservdb ("/usr/arla/etc/CellServDB", orealm);
357 for(p = hosts; p; p = p->next){
358 if(strcmp(orealm, p->this->realm) == 0 &&
359 (!admin || p->this->admin)) {
370 krb_get_krbhst(char *host, char *realm, int nth)
372 struct krb_host *p = krb_get_host(nth, realm, 0);
375 strlcpy (host, p->host, MaxHostNameLen);
380 krb_get_admhst(char *host, char *realm, int nth)
382 struct krb_host *p = krb_get_host(nth, realm, 1);
385 strlcpy (host, p->host, MaxHostNameLen);