|
|
1.1 root 1: /*
2: * $Source: /usr/src/kerberosIV/krb/RCS/send_to_kdc.c,v $
3: * $Author: kfall $
4: *
5: * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
6: *
7: * For copying and distribution information, please see the file
8: * <mit-copyright.h>.
9: */
10:
11: #ifndef lint
12: static char rcsid_send_to_kdc_c[] =
13: "$Id: send_to_kdc.c,v 4.21 90/06/25 20:57:21 kfall Exp $";
14: #endif /* lint */
15:
16: #include <mit-copyright.h>
17:
18: #include <des.h>
19: #include <krb.h>
20: #include <prot.h>
21:
22: #include <stdio.h>
23: #include <errno.h>
24: #include <sys/time.h>
25: #include <sys/types.h>
26: #ifdef lint
27: #include <sys/uio.h> /* struct iovec to make lint happy */
28: #endif /* lint */
29: #include <sys/socket.h>
30: #include <netinet/in.h>
31: #include <netdb.h>
32: #include <strings.h>
33:
34: #define S_AD_SZ sizeof(struct sockaddr_in)
35:
36: extern int errno;
37: extern int krb_debug;
38:
39: extern char *malloc(), *calloc(), *realloc();
40:
41: int krb_udp_port = 0;
42:
43: /* CLIENT_KRB_TIMEOUT indicates the time to wait before
44: * retrying a server. It's defined in "krb.h".
45: */
46: static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0};
47: static char *prog = "send_to_kdc";
48: static send_recv();
49:
50: /*
51: * This file contains two routines, send_to_kdc() and send_recv().
52: * send_recv() is a static routine used by send_to_kdc().
53: */
54:
55: /*
56: * send_to_kdc() sends a message to the Kerberos authentication
57: * server(s) in the given realm and returns the reply message.
58: * The "pkt" argument points to the message to be sent to Kerberos;
59: * the "rpkt" argument will be filled in with Kerberos' reply.
60: * The "realm" argument indicates the realm of the Kerberos server(s)
61: * to transact with. If the realm is null, the local realm is used.
62: *
63: * If more than one Kerberos server is known for a given realm,
64: * different servers will be queried until one of them replies.
65: * Several attempts (retries) are made for each server before
66: * giving up entirely.
67: *
68: * If an answer was received from a Kerberos host, KSUCCESS is
69: * returned. The following errors can be returned:
70: *
71: * SKDC_CANT - can't get local realm
72: * - can't find "kerberos" in /etc/services database
73: * - can't open socket
74: * - can't bind socket
75: * - all ports in use
76: * - couldn't find any Kerberos host
77: *
78: * SKDC_RETRY - couldn't get an answer from any Kerberos server,
79: * after several retries
80: */
81:
82: send_to_kdc(pkt,rpkt,realm)
83: KTEXT pkt;
84: KTEXT rpkt;
85: char *realm;
86: {
87: int i, f;
88: int no_host; /* was a kerberos host found? */
89: int retry;
90: int n_hosts;
91: int retval;
92: struct sockaddr_in to;
93: struct hostent *host, *hostlist;
94: char *cp;
95: char krbhst[MAX_HSTNM];
96: char lrealm[REALM_SZ];
97:
98: /*
99: * If "realm" is non-null, use that, otherwise get the
100: * local realm.
101: */
102: if (realm)
103: (void) strcpy(lrealm, realm);
104: else
105: if (krb_get_lrealm(lrealm,1)) {
106: if (krb_debug)
107: fprintf(stderr, "%s: can't get local realm\n", prog);
108: return(SKDC_CANT);
109: }
110: if (krb_debug)
111: printf("lrealm is %s\n", lrealm);
112: if (krb_udp_port == 0) {
113: register struct servent *sp;
114: if ((sp = getservbyname("kerberos","udp")) == 0) {
115: if (krb_debug)
116: fprintf(stderr, "%s: Can't get kerberos/udp service\n",
117: prog);
118: return(SKDC_CANT);
119: }
120: krb_udp_port = sp->s_port;
121: if (krb_debug)
122: printf("krb_udp_port is %d\n", krb_udp_port);
123: }
124: bzero((char *)&to, S_AD_SZ);
125: hostlist = (struct hostent *) malloc(sizeof(struct hostent));
126: if (!hostlist)
127: return (/*errno */SKDC_CANT);
128: if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
129: if (krb_debug)
130: fprintf(stderr,"%s: Can't open socket\n", prog);
131: return(SKDC_CANT);
132: }
133: /* from now on, exit through rtn label for cleanup */
134:
135: no_host = 1;
136: /* get an initial allocation */
137: n_hosts = 0;
138: for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) {
139: if (krb_debug) {
140: printf("Getting host entry for %s...",krbhst);
141: (void) fflush(stdout);
142: }
143: host = gethostbyname(krbhst);
144: if (krb_debug) {
145: printf("%s.\n",
146: host ? "Got it" : "Didn't get it");
147: (void) fflush(stdout);
148: }
149: if (!host)
150: continue;
151: no_host = 0; /* found at least one */
152: n_hosts++;
153: /* preserve host network address to check later
154: * (would be better to preserve *all* addresses,
155: * take care of that later)
156: */
157: hostlist = (struct hostent *)
158: realloc((char *)hostlist,
159: (unsigned)
160: sizeof(struct hostent)*(n_hosts+1));
161: if (!hostlist)
162: return /*errno */SKDC_CANT;
163: bcopy((char *)host, (char *)&hostlist[n_hosts-1],
164: sizeof(struct hostent));
165: host = &hostlist[n_hosts-1];
166: cp = malloc((unsigned)host->h_length);
167: if (!cp) {
168: retval = /*errno */SKDC_CANT;
169: goto rtn;
170: }
171: bcopy((char *)host->h_addr, cp, host->h_length);
172: /* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2
173: (or worse) only return one name ... */
174: #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
175: host->h_addr_list = (char **)malloc(sizeof(char *));
176: if (!host->h_addr_list) {
177: retval = /*errno */SKDC_CANT;
178: goto rtn;
179: }
180: #endif /* ULTRIX022 || SunOS */
181: host->h_addr = cp;
182: bzero((char *)&hostlist[n_hosts],
183: sizeof(struct hostent));
184: to.sin_family = host->h_addrtype;
185: bcopy(host->h_addr, (char *)&to.sin_addr,
186: host->h_length);
187: to.sin_port = krb_udp_port;
188: if (send_recv(pkt, rpkt, f, &to, hostlist)) {
189: retval = KSUCCESS;
190: goto rtn;
191: }
192: if (krb_debug) {
193: printf("Timeout, error, or wrong descriptor\n");
194: (void) fflush(stdout);
195: }
196: }
197: if (no_host) {
198: if (krb_debug)
199: fprintf(stderr, "%s: can't find any Kerberos host.\n",
200: prog);
201: retval = SKDC_CANT;
202: goto rtn;
203: }
204: /* retry each host in sequence */
205: for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) {
206: for (host = hostlist; host->h_name != (char *)NULL; host++) {
207: to.sin_family = host->h_addrtype;
208: bcopy(host->h_addr, (char *)&to.sin_addr,
209: host->h_length);
210: if (send_recv(pkt, rpkt, f, &to, hostlist)) {
211: retval = KSUCCESS;
212: goto rtn;
213: }
214: }
215: }
216: retval = SKDC_RETRY;
217: rtn:
218: (void) close(f);
219: if (hostlist) {
220: register struct hostent *hp;
221: for (hp = hostlist; hp->h_name; hp++)
222: #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
223: if (hp->h_addr_list) {
224: #endif /* ULTRIX022 || SunOS */
225: if (hp->h_addr)
226: free(hp->h_addr);
227: #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
228: free((char *)hp->h_addr_list);
229: }
230: #endif /* ULTRIX022 || SunOS */
231: free((char *)hostlist);
232: }
233: return(retval);
234: }
235:
236: /*
237: * try to send out and receive message.
238: * return 1 on success, 0 on failure
239: */
240:
241: static send_recv(pkt,rpkt,f,_to,addrs)
242: KTEXT pkt;
243: KTEXT rpkt;
244: int f;
245: struct sockaddr_in *_to;
246: struct hostent *addrs;
247: {
248: fd_set readfds;
249: register struct hostent *hp;
250: struct sockaddr_in from;
251: int sin_size;
252: int numsent;
253:
254: if (krb_debug) {
255: if (_to->sin_family == AF_INET)
256: printf("Sending message to %s...",
257: inet_ntoa(_to->sin_addr));
258: else
259: printf("Sending message...");
260: (void) fflush(stdout);
261: }
262: if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0,
263: (struct sockaddr *)_to,
264: S_AD_SZ)) != pkt->length) {
265: if (krb_debug)
266: printf("sent only %d/%d\n",numsent, pkt->length);
267: return 0;
268: }
269: if (krb_debug) {
270: printf("Sent\nWaiting for reply...");
271: (void) fflush(stdout);
272: }
273: FD_ZERO(&readfds);
274: FD_SET(f, &readfds);
275: errno = 0;
276: /* select - either recv is ready, or timeout */
277: /* see if timeout or error or wrong descriptor */
278: if (select(f + 1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 1
279: || !FD_ISSET(f, &readfds)) {
280: if (krb_debug) {
281: fprintf(stderr, "select failed: readfds=%x",
282: readfds);
283: perror("");
284: }
285: return 0;
286: }
287: sin_size = sizeof(from);
288: if (recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0,
289: (struct sockaddr *)&from, &sin_size)
290: < 0) {
291: if (krb_debug)
292: perror("recvfrom");
293: return 0;
294: }
295: if (krb_debug) {
296: printf("received packet from %s\n", inet_ntoa(from.sin_addr));
297: fflush(stdout);
298: }
299: for (hp = addrs; hp->h_name != (char *)NULL; hp++) {
300: if (!bcmp(hp->h_addr, (char *)&from.sin_addr.s_addr,
301: hp->h_length)) {
302: if (krb_debug) {
303: printf("Received it\n");
304: (void) fflush(stdout);
305: }
306: return 1;
307: }
308: if (krb_debug)
309: fprintf(stderr,
310: "packet not from %x\n",
311: hp->h_addr);
312: }
313: if (krb_debug)
314: fprintf(stderr, "%s: received packet from wrong host! (%x)\n",
315: "send_to_kdc(send_rcv)", from.sin_addr.s_addr);
316: return 0;
317: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.