summaryrefslogtreecommitdiffstats
path: root/crypto/kerberosIV/lib/krb/send_to_kdc.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/kerberosIV/lib/krb/send_to_kdc.c')
-rw-r--r--crypto/kerberosIV/lib/krb/send_to_kdc.c533
1 files changed, 0 insertions, 533 deletions
diff --git a/crypto/kerberosIV/lib/krb/send_to_kdc.c b/crypto/kerberosIV/lib/krb/send_to_kdc.c
deleted file mode 100644
index 4fc2c95..0000000
--- a/crypto/kerberosIV/lib/krb/send_to_kdc.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- Copyright (C) 1989 by the Massachusetts Institute of Technology
-
- Export of this software from the United States of America is assumed
- to require a specific license from the United States Government.
- It is the responsibility of any person or organization contemplating
- export to obtain such a license before exporting.
-
-WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
-distribute this software and its documentation for any purpose and
-without fee is hereby granted, provided that the above copyright
-notice appear in all copies and that both that copyright notice and
-this permission notice appear in supporting documentation, and that
-the name of M.I.T. not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior
-permission. M.I.T. makes no representations about the suitability of
-this software for any purpose. It is provided "as is" without express
-or implied warranty.
-
- */
-
-#include "krb_locl.h"
-#include <base64.h>
-
-RCSID("$Id: send_to_kdc.c,v 1.71.2.1 2000/10/10 12:47:21 assar Exp $");
-
-struct host {
- struct sockaddr_in addr;
- const char *hostname;
- enum krb_host_proto proto;
-};
-
-static int send_recv(KTEXT pkt, KTEXT rpkt, struct host *host);
-
-/*
- * send_to_kdc() sends a message to the Kerberos authentication
- * server(s) in the given realm and returns the reply message.
- * The "pkt" argument points to the message to be sent to Kerberos;
- * the "rpkt" argument will be filled in with Kerberos' reply.
- * The "realm" argument indicates the realm of the Kerberos server(s)
- * to transact with. If the realm is null, the local realm is used.
- *
- * If more than one Kerberos server is known for a given realm,
- * different servers will be queried until one of them replies.
- * Several attempts (retries) are made for each server before
- * giving up entirely.
- *
- * If an answer was received from a Kerberos host, KSUCCESS is
- * returned. The following errors can be returned:
- *
- * SKDC_CANT - can't get local realm
- * - can't find "kerberos" in /etc/services database
- * - can't open socket
- * - can't bind socket
- * - all ports in use
- * - couldn't find any Kerberos host
- *
- * SKDC_RETRY - couldn't get an answer from any Kerberos server,
- * after several retries
- */
-
-/* always use the admin server */
-static int krb_use_admin_server_flag = 0;
-
-static int client_timeout = -1;
-
-int
-krb_use_admin_server(int flag)
-{
- int old = krb_use_admin_server_flag;
- krb_use_admin_server_flag = flag;
- return old;
-}
-
-#define PROXY_VAR "krb4_proxy"
-
-static int
-expand (struct host **ptr, size_t sz)
-{
- void *tmp;
-
- tmp = realloc (*ptr, sz) ;
- if (tmp == NULL)
- return SKDC_CANT;
- *ptr = tmp;
- return 0;
-}
-
-int
-send_to_kdc(KTEXT pkt, KTEXT rpkt, const char *realm)
-{
- int i;
- int no_host; /* was a kerberos host found? */
- int retry;
- int n_hosts;
- int retval;
- struct hostent *host;
- char lrealm[REALM_SZ];
- struct krb_host *k_host;
- struct host *hosts = malloc(sizeof(*hosts));
- const char *proxy = krb_get_config_string (PROXY_VAR);
-
- if (hosts == NULL)
- return SKDC_CANT;
-
- if (client_timeout == -1) {
- const char *to;
-
- client_timeout = CLIENT_KRB_TIMEOUT;
- to = krb_get_config_string ("kdc_timeout");
- if (to != NULL) {
- int tmp;
- char *end;
-
- tmp = strtol (to, &end, 0);
- if (end != to)
- client_timeout = tmp;
- }
- }
-
- /*
- * If "realm" is non-null, use that, otherwise get the
- * local realm.
- */
- if (realm == NULL) {
- if (krb_get_lrealm(lrealm,1)) {
- if (krb_debug)
- krb_warning("send_to_kdc: can't get local realm\n");
- return(SKDC_CANT);
- }
- realm = lrealm;
- }
- if (krb_debug)
- krb_warning("lrealm is %s\n", realm);
-
- no_host = 1;
- /* get an initial allocation */
- n_hosts = 0;
- for (i = 1;
- (k_host = krb_get_host(i, realm, krb_use_admin_server_flag));
- ++i) {
- char *p;
- char **addr_list;
- int j;
- int n_addrs;
- struct host *tmp;
-
- if (k_host->proto == PROTO_HTTP && proxy != NULL) {
- n_addrs = 1;
- no_host = 0;
-
- retval = expand (&hosts, (n_hosts + n_addrs) * sizeof(*hosts));
- if (retval)
- goto rtn;
-
- memset (&hosts[n_hosts].addr, 0, sizeof(struct sockaddr_in));
- hosts[n_hosts].addr.sin_port = htons(k_host->port);
- hosts[n_hosts].proto = k_host->proto;
- hosts[n_hosts].hostname = k_host->host;
- } else {
- if (krb_debug)
- krb_warning("Getting host entry for %s...", k_host->host);
- host = gethostbyname(k_host->host);
- if (krb_debug) {
- krb_warning("%s.\n",
- host ? "Got it" : "Didn't get it");
- }
- if (host == NULL)
- continue;
- no_host = 0; /* found at least one */
-
- n_addrs = 0;
- for (addr_list = host->h_addr_list;
- *addr_list != NULL;
- ++addr_list)
- ++n_addrs;
-
- retval = expand (&hosts, (n_hosts + n_addrs) * sizeof(*hosts));
- if (retval)
- goto rtn;
-
- for (addr_list = host->h_addr_list, j = 0;
- (p = *addr_list) != NULL;
- ++addr_list, ++j) {
- memset (&hosts[n_hosts + j].addr, 0,
- sizeof(struct sockaddr_in));
- hosts[n_hosts + j].addr.sin_family = host->h_addrtype;
- hosts[n_hosts + j].addr.sin_port = htons(k_host->port);
- hosts[n_hosts + j].proto = k_host->proto;
- hosts[n_hosts + j].hostname = k_host->host;
- memcpy(&hosts[n_hosts + j].addr.sin_addr, p,
- sizeof(struct in_addr));
- }
- }
-
- for (j = 0; j < n_addrs; ++j) {
- if (send_recv(pkt, rpkt, &hosts[n_hosts + j])) {
- retval = KSUCCESS;
- goto rtn;
- }
- if (krb_debug) {
- krb_warning("Timeout, error, or wrong descriptor\n");
- }
- }
- n_hosts += j;
- }
- if (no_host) {
- if (krb_debug)
- krb_warning("send_to_kdc: can't find any Kerberos host.\n");
- retval = SKDC_CANT;
- goto rtn;
- }
- /* retry each host in sequence */
- for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) {
- for (i = 0; i < n_hosts; ++i) {
- if (send_recv(pkt, rpkt, &hosts[i])) {
- retval = KSUCCESS;
- goto rtn;
- }
- }
- }
- retval = SKDC_RETRY;
-rtn:
- free(hosts);
- return(retval);
-}
-
-static int
-udp_socket(void)
-{
- return socket(AF_INET, SOCK_DGRAM, 0);
-}
-
-static int
-udp_connect(int s, struct host *host)
-{
- if(krb_debug) {
- krb_warning("connecting to %s (%s) udp, port %d\n",
- host->hostname,
- inet_ntoa(host->addr.sin_addr),
- ntohs(host->addr.sin_port));
- }
- return connect(s, (struct sockaddr*)&host->addr, sizeof(host->addr));
-}
-
-static int
-udp_send(int s, struct host *host, KTEXT pkt)
-{
- if(krb_debug) {
- krb_warning("sending %d bytes to %s (%s), udp port %d\n",
- pkt->length,
- host->hostname,
- inet_ntoa(host->addr.sin_addr),
- ntohs(host->addr.sin_port));
- }
- return send(s, pkt->dat, pkt->length, 0);
-}
-
-static int
-tcp_socket(void)
-{
- return socket(AF_INET, SOCK_STREAM, 0);
-}
-
-static int
-tcp_connect(int s, struct host *host)
-{
- if(krb_debug) {
- krb_warning("connecting to %s (%s), tcp port %d\n",
- host->hostname,
- inet_ntoa(host->addr.sin_addr),
- ntohs(host->addr.sin_port));
- }
- return connect(s, (struct sockaddr*)&host->addr, sizeof(host->addr));
-}
-
-static int
-tcp_send(int s, struct host *host, KTEXT pkt)
-{
- unsigned char len[4];
-
- if(krb_debug) {
- krb_warning("sending %d bytes to %s (%s), tcp port %d\n",
- pkt->length,
- host->hostname,
- inet_ntoa(host->addr.sin_addr),
- ntohs(host->addr.sin_port));
- }
- krb_put_int(pkt->length, len, sizeof(len), 4);
- if(send(s, len, sizeof(len), 0) != sizeof(len))
- return -1;
- return send(s, pkt->dat, pkt->length, 0);
-}
-
-static int
-udptcp_recv(void *buf, size_t len, KTEXT rpkt)
-{
- int pktlen = min(len, MAX_KTXT_LEN);
-
- if(krb_debug)
- krb_warning("recieved %lu bytes on udp/tcp socket\n",
- (unsigned long)len);
- memcpy(rpkt->dat, buf, pktlen);
- rpkt->length = pktlen;
- return 0;
-}
-
-static int
-url_parse(const char *url, char *host, size_t len, short *port)
-{
- const char *p;
- size_t n;
-
- if(strncmp(url, "http://", 7))
- return -1;
- url += 7;
- p = strchr(url, ':');
- if(p) {
- char *end;
-
- *port = htons(strtol(p + 1, &end, 0));
- if (end == p + 1)
- return -1;
- n = p - url;
- } else {
- *port = k_getportbyname ("http", "tcp", htons(80));
- p = strchr(url, '/');
- if (p)
- n = p - url;
- else
- n = strlen(url);
- }
- if (n >= len)
- return -1;
- memcpy(host, url, n);
- host[n] = '\0';
- return 0;
-}
-
-static int
-http_connect(int s, struct host *host)
-{
- const char *proxy = krb_get_config_string(PROXY_VAR);
- char proxy_host[MaxHostNameLen];
- short port;
- struct hostent *hp;
- struct sockaddr_in sin;
-
- if(proxy == NULL) {
- if(krb_debug)
- krb_warning("Not using proxy.\n");
- return tcp_connect(s, host);
- }
- if(url_parse(proxy, proxy_host, sizeof(proxy_host), &port) < 0)
- return -1;
- hp = gethostbyname(proxy_host);
- if(hp == NULL)
- return -1;
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
- sin.sin_port = port;
- if(krb_debug) {
- krb_warning("connecting to proxy on %s (%s) port %d\n",
- proxy_host, inet_ntoa(sin.sin_addr), ntohs(port));
- }
- return connect(s, (struct sockaddr*)&sin, sizeof(sin));
-}
-
-static int
-http_send(int s, struct host *host, KTEXT pkt)
-{
- const char *proxy = krb_get_config_string (PROXY_VAR);
- char *str;
- char *msg;
-
- if(base64_encode(pkt->dat, pkt->length, &str) < 0)
- return -1;
- if(proxy != NULL) {
- if(krb_debug) {
- krb_warning("sending %d bytes to %s, tcp port %d (via proxy)\n",
- pkt->length,
- host->hostname,
- ntohs(host->addr.sin_port));
- }
- asprintf(&msg, "GET http://%s:%d/%s HTTP/1.0\r\n\r\n",
- host->hostname,
- ntohs(host->addr.sin_port),
- str);
- } else {
- if(krb_debug) {
- krb_warning("sending %d bytes to %s (%s), http port %d\n",
- pkt->length,
- host->hostname,
- inet_ntoa(host->addr.sin_addr),
- ntohs(host->addr.sin_port));
- }
- asprintf(&msg, "GET %s HTTP/1.0\r\n\r\n", str);
- }
- free(str);
-
- if (msg == NULL)
- return -1;
-
- if(send(s, msg, strlen(msg), 0) != strlen(msg)){
- free(msg);
- return -1;
- }
- free(msg);
- return 0;
-}
-
-static int
-http_recv(void *buf, size_t len, KTEXT rpkt)
-{
- char *p;
- char *tmp = malloc(len + 1);
-
- if (tmp == NULL)
- return -1;
- memcpy(tmp, buf, len);
- tmp[len] = 0;
- p = strstr(tmp, "\r\n\r\n");
- if(p == NULL){
- free(tmp);
- return -1;
- }
- p += 4;
- if(krb_debug)
- krb_warning("recieved %lu bytes on http socket\n",
- (unsigned long)((tmp + len) - p));
- if((tmp + len) - p > MAX_KTXT_LEN) {
- free(tmp);
- return -1;
- }
- if (strncasecmp (tmp, "HTTP/1.0 2", 10) != 0
- && strncasecmp (tmp, "HTTP/1.1 2", 10) != 0) {
- free (tmp);
- return -1;
- }
- memcpy(rpkt->dat, p, (tmp + len) - p);
- rpkt->length = (tmp + len) - p;
- free(tmp);
- return 0;
-}
-
-static struct proto_descr {
- int proto;
- int stream_flag;
- int (*socket)(void);
- int (*connect)(int, struct host *host);
- int (*send)(int, struct host *host, KTEXT);
- int (*recv)(void*, size_t, KTEXT);
-} protos[] = {
- { PROTO_UDP, 0, udp_socket, udp_connect, udp_send, udptcp_recv },
- { PROTO_TCP, 1, tcp_socket, tcp_connect, tcp_send, udptcp_recv },
- { PROTO_HTTP, 1, tcp_socket, http_connect, http_send, http_recv }
-};
-
-static int
-send_recv(KTEXT pkt, KTEXT rpkt, struct host *host)
-{
- int i;
- int s;
- unsigned char buf[MAX_KTXT_LEN];
- int offset = 0;
-
- for(i = 0; i < sizeof(protos) / sizeof(protos[0]); i++){
- if(protos[i].proto == host->proto)
- break;
- }
- if(i == sizeof(protos) / sizeof(protos[0]))
- return FALSE;
- if((s = (*protos[i].socket)()) < 0)
- return FALSE;
- if((*protos[i].connect)(s, host) < 0) {
- close(s);
- return FALSE;
- }
- if((*protos[i].send)(s, host, pkt) < 0) {
- close(s);
- return FALSE;
- }
- do{
- fd_set readfds;
- struct timeval timeout;
- int len;
- timeout.tv_sec = client_timeout;
- timeout.tv_usec = 0;
- FD_ZERO(&readfds);
- if (s >= FD_SETSIZE) {
- if (krb_debug)
- krb_warning("fd too large\n");
- close (s);
- return FALSE;
- }
- FD_SET(s, &readfds);
-
- /* select - either recv is ready, or timeout */
- /* see if timeout or error or wrong descriptor */
- if(select(s + 1, &readfds, 0, 0, &timeout) < 1
- || !FD_ISSET(s, &readfds)) {
- if (krb_debug)
- krb_warning("select failed: errno = %d\n", errno);
- close(s);
- return FALSE;
- }
- len = recv(s, buf + offset, sizeof(buf) - offset, 0);
- if (len < 0) {
- close(s);
- return FALSE;
- }
- if(len == 0)
- break;
- offset += len;
- } while(protos[i].stream_flag);
- close(s);
- if((*protos[i].recv)(buf, offset, rpkt) < 0)
- return FALSE;
- return TRUE;
-}
-
-/* The configuration line "hosts: dns files" in /etc/nsswitch.conf is
- * rumored to avoid triggering this bug. */
-#if defined(linux) && defined(HAVE__DNS_GETHOSTBYNAME) && 0
-/* Linux libc 5.3 is broken probably somewhere in nsw_hosts.o,
- * for now keep this kludge. */
-static
-struct hostent *gethostbyname(const char *name)
-{
- return (void *)_dns_gethostbyname(name);
-}
-#endif
OpenPOWER on IntegriCloud