summaryrefslogtreecommitdiffstats
path: root/crypto/kerberosIV/lib/krb/get_host.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/kerberosIV/lib/krb/get_host.c')
-rw-r--r--crypto/kerberosIV/lib/krb/get_host.c387
1 files changed, 387 insertions, 0 deletions
diff --git a/crypto/kerberosIV/lib/krb/get_host.c b/crypto/kerberosIV/lib/krb/get_host.c
new file mode 100644
index 0000000..0eb2224
--- /dev/null
+++ b/crypto/kerberosIV/lib/krb/get_host.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "krb_locl.h"
+
+RCSID("$Id: get_host.c,v 1.48 1999/12/02 16:58:41 joda Exp $");
+
+static struct host_list {
+ struct krb_host *this;
+ struct host_list *next;
+} *hosts;
+
+static int krb_port = 0;
+
+static void
+free_hosts(struct host_list *h)
+{
+ struct host_list *t;
+ while(h){
+ if(h->this->realm)
+ free(h->this->realm);
+ if(h->this->host)
+ free(h->this->host);
+ t = h;
+ h = h->next;
+ free(t);
+ }
+}
+
+static int
+parse_address(char *address, enum krb_host_proto *proto,
+ char **host, int *port)
+{
+ char *p, *q;
+ int default_port = krb_port;
+ *proto = PROTO_UDP;
+ if(strncmp(address, "http://", 7) == 0){
+ p = address + 7;
+ *proto = PROTO_HTTP;
+ default_port = 80;
+ }else{
+ p = strchr(address, '/');
+ if(p){
+ char prot[32];
+ strlcpy (prot, address,
+ min(p - address + 1, sizeof(prot)));
+ if(strcasecmp(prot, "udp") == 0)
+ *proto = PROTO_UDP;
+ else if(strcasecmp(prot, "tcp") == 0)
+ *proto = PROTO_TCP;
+ else if(strcasecmp(prot, "http") == 0) {
+ *proto = PROTO_HTTP;
+ default_port = 80;
+ } else
+ krb_warning("Unknown protocol `%s', Using default `udp'.\n",
+ prot);
+ p++;
+ }else
+ p = address;
+ }
+ q = strchr(p, ':');
+ if(q) {
+ *host = malloc(q - p + 1);
+ if (*host == NULL)
+ return -1;
+ strlcpy (*host, p, q - p + 1);
+ q++;
+ {
+ struct servent *sp = getservbyname(q, NULL);
+ if(sp)
+ *port = ntohs(sp->s_port);
+ else
+ if(sscanf(q, "%d", port) != 1){
+ krb_warning("Bad port specification `%s', using port %d.",
+ q, krb_port);
+ *port = krb_port;
+ }
+ }
+ } else {
+ *port = default_port;
+ q = strchr(p, '/');
+ if (q) {
+ *host = malloc(q - p + 1);
+ if (*host == NULL)
+ return -1;
+ strlcpy (*host, p, q - p + 1);
+ } else {
+ *host = strdup(p);
+ if(*host == NULL)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+add_host(const char *realm, char *address, int admin, int validate)
+{
+ struct krb_host *host;
+ struct host_list *p, **last = &hosts;
+
+ host = (struct krb_host*)malloc(sizeof(struct krb_host));
+ if (host == NULL)
+ return 1;
+ if(parse_address(address, &host->proto, &host->host, &host->port) < 0) {
+ free(host);
+ return 1;
+ }
+ if (validate) {
+ if (krb_dns_debug)
+ krb_warning("Getting host entry for %s...", host->host);
+ if (gethostbyname(host->host) == NULL) {
+ if (krb_dns_debug)
+ krb_warning("Didn't get it.\n");
+ free(host->host);
+ free(host);
+ return 1;
+ }
+ else if (krb_dns_debug)
+ krb_warning("Got it.\n");
+ }
+ host->admin = admin;
+ for(p = hosts; p; p = p->next){
+ if(strcmp(realm, p->this->realm) == 0 &&
+ strcmp(host->host, p->this->host) == 0 &&
+ host->proto == p->this->proto &&
+ host->port == p->this->port){
+ free(host->host);
+ free(host);
+ return 1;
+ }
+ last = &p->next;
+ }
+ host->realm = strdup(realm);
+ if (host->realm == NULL) {
+ free(host->host);
+ free(host);
+ return 1;
+ }
+ p = (struct host_list*)malloc(sizeof(struct host_list));
+ if (p == NULL) {
+ free(host->realm);
+ free(host->host);
+ free(host);
+ return 1;
+ }
+ p->this = host;
+ p->next = NULL;
+ *last = p;
+ return 0;
+}
+
+static int
+read_file(const char *filename, const char *r)
+{
+ char line[1024];
+ int nhosts = 0;
+ FILE *f = fopen(filename, "r");
+
+ if(f == NULL)
+ return -1;
+ while(fgets(line, sizeof(line), f) != NULL) {
+ char *realm, *address, *admin;
+ char *save;
+
+ realm = strtok_r (line, " \t\n\r", &save);
+ if (realm == NULL)
+ continue;
+ if (strcmp(realm, r))
+ continue;
+ address = strtok_r (NULL, " \t\n\r", &save);
+ if (address == NULL)
+ continue;
+ admin = strtok_r (NULL, " \t\n\r", &save);
+ if (add_host(realm,
+ address,
+ admin != NULL && strcasecmp(admin, "admin") == 0,
+ 0) == 0)
+ ++nhosts;
+ }
+ fclose(f);
+ return nhosts;
+}
+
+#if 0
+static int
+read_cellservdb (const char *filename, const char *realm)
+{
+ char line[1024];
+ FILE *f = fopen (filename, "r");
+ int nhosts = 0;
+
+ if (f == NULL)
+ return -1;
+ while (fgets (line, sizeof(line), f) != NULL) {
+ if (line[0] == '>'
+ && strncasecmp (line + 1, realm, strlen(realm)) == 0) {
+ while (fgets (line, sizeof(line), f) != NULL && *line != '>') {
+ char *hash;
+
+ if (line [strlen(line) - 1] == '\n')
+ line [strlen(line) - 1] = '\0';
+
+ hash = strchr (line, '#');
+
+ if (hash != NULL
+ && add_host (realm, hash + 1, 0, 0) == 0)
+ ++nhosts;
+ }
+ break;
+ }
+ }
+ fclose (f);
+ return nhosts;
+}
+#endif
+
+static int
+init_hosts(char *realm)
+{
+ int i, j, ret = 0;
+ char file[MaxPathLen];
+
+ /*
+ * proto should really be NULL, but there are libraries out there
+ * that don't like that so we use "udp" instead.
+ */
+
+ krb_port = ntohs(k_getportbyname (KRB_SERVICE, "udp", htons(KRB_PORT)));
+ for(i = 0; krb_get_krbconf(i, file, sizeof(file)) == 0; i++) {
+ j = read_file(file, realm);
+ if (j > 0) ret += j;
+ }
+ return ret;
+}
+
+static void
+srv_find_realm(char *realm, char *proto, char *service)
+{
+ char *domain;
+ struct dns_reply *r;
+ struct resource_record *rr;
+
+ roken_mconcat(&domain, 1024, service, ".", proto, ".", realm, ".", NULL);
+
+ if(domain == NULL)
+ return;
+
+ r = dns_lookup(domain, "srv");
+ if(r == NULL)
+ r = dns_lookup(domain, "txt");
+ if(r == NULL){
+ free(domain);
+ return;
+ }
+ for(rr = r->head; rr; rr = rr->next){
+ if(rr->type == T_SRV){
+ char buf[1024];
+
+ if (snprintf (buf,
+ sizeof(buf),
+ "%s/%s:%u",
+ proto,
+ rr->u.srv->target,
+ rr->u.srv->port) < sizeof(buf))
+ add_host(realm, buf, 0, 0);
+ }else if(rr->type == T_TXT)
+ add_host(realm, rr->u.txt, 0, 0);
+ }
+ dns_free_data(r);
+ free(domain);
+}
+
+struct krb_host*
+krb_get_host(int nth, const char *realm, int admin)
+{
+ struct host_list *p;
+ static char orealm[REALM_SZ];
+
+ if(orealm[0] == 0 || strcmp(realm, orealm)){
+ /* quick optimization */
+ if(realm && realm[0]){
+ strlcpy (orealm, realm, sizeof(orealm));
+ }else{
+ int ret = krb_get_lrealm(orealm, 1);
+ if(ret != KSUCCESS)
+ return NULL;
+ }
+
+ if(hosts){
+ free_hosts(hosts);
+ hosts = NULL;
+ }
+
+ if (init_hosts(orealm) < nth) {
+ srv_find_realm(orealm, "udp", KRB_SERVICE);
+ srv_find_realm(orealm, "tcp", KRB_SERVICE);
+ srv_find_realm(orealm, "http", KRB_SERVICE);
+
+ {
+ char *host;
+ int i = 0;
+
+ asprintf(&host, "kerberos.%s.", orealm);
+ if (host == NULL) {
+ free_hosts(hosts);
+ hosts = NULL;
+ return NULL;
+ }
+ add_host(orealm, host, 1, 1);
+ do {
+ i++;
+ free(host);
+ asprintf(&host, "kerberos-%d.%s.", i, orealm);
+ } while(host != NULL
+ && i < 100000
+ && add_host(orealm, host, 0, 1) == 0);
+ free(host);
+ }
+ }
+#if 0
+ read_cellservdb ("/usr/vice/etc/CellServDB", orealm);
+ read_cellservdb ("/usr/arla/etc/CellServDB", orealm);
+#endif
+ }
+
+ for(p = hosts; p; p = p->next){
+ if(strcmp(orealm, p->this->realm) == 0 &&
+ (!admin || p->this->admin)) {
+ if(nth == 1)
+ return p->this;
+ else
+ nth--;
+ }
+ }
+ return NULL;
+}
+
+int
+krb_get_krbhst(char *host, char *realm, int nth)
+{
+ struct krb_host *p = krb_get_host(nth, realm, 0);
+ if(p == NULL)
+ return KFAILURE;
+ strlcpy (host, p->host, MaxHostNameLen);
+ return KSUCCESS;
+}
+
+int
+krb_get_admhst(char *host, char *realm, int nth)
+{
+ struct krb_host *p = krb_get_host(nth, realm, 1);
+ if(p == NULL)
+ return KFAILURE;
+ strlcpy (host, p->host, MaxHostNameLen);
+ return KSUCCESS;
+}
OpenPOWER on IntegriCloud