2 * $Id: send_to_kdc.c,v 1.3 2001-03-28 22:42:46 samnoble Exp $
4 * Copyright (c) 1990,1994 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
9 * $Source: /home/ralph/netatalk/rsync/netatalk/etc/uams/uams_krb4/send_to_kdc.c,v $
12 * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
14 * For copying and distribution information, please see the file
19 static char rcsid_send_to_kdc_c[] =
20 "$Id: send_to_kdc.c,v 1.3 2001-03-28 22:42:46 samnoble Exp $";
23 #if defined( HAVE_CONFIG_H )
29 #include <mit-copyright.h>
38 #include <sys/types.h>
40 #include <sys/uio.h> /* struct iovec to make lint happy */
42 #include <sys/socket.h>
43 #include <netinet/in.h>
47 #define S_AD_SZ sizeof(struct sockaddr_in)
51 extern char *malloc(), *calloc(), *realloc();
55 /* CLIENT_KRB_TIMEOUT indicates the time to wait before
56 * retrying a server. It's defined in "krb.h".
58 static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0};
59 static char *prog = "send_to_kdc";
63 * This file contains two routines, send_to_kdc() and send_recv().
64 * send_recv() is a static routine used by send_to_kdc().
68 * send_to_kdc() sends a message to the Kerberos authentication
69 * server(s) in the given realm and returns the reply message.
70 * The "pkt" argument points to the message to be sent to Kerberos;
71 * the "rpkt" argument will be filled in with Kerberos' reply.
72 * The "realm" argument indicates the realm of the Kerberos server(s)
73 * to transact with. If the realm is null, the local realm is used.
75 * If more than one Kerberos server is known for a given realm,
76 * different servers will be queried until one of them replies.
77 * Several attempts (retries) are made for each server before
80 * If an answer was received from a Kerberos host, KSUCCESS is
81 * returned. The following errors can be returned:
83 * SKDC_CANT - can't get local realm
84 * - can't find "kerberos" in /etc/services database
88 * - couldn't find any Kerberos host
90 * SKDC_RETRY - couldn't get an answer from any Kerberos server,
91 * after several retries
94 send_to_kdc(pkt,rpkt,realm)
100 int no_host; /* was a kerberos host found? */
104 struct sockaddr_in to;
105 struct hostent *host, *hostlist;
107 char krbhst[MAX_HSTNM];
108 char lrealm[REALM_SZ];
111 * If "realm" is non-null, use that, otherwise get the
115 (void) strcpy(lrealm, realm);
117 if (krb_get_lrealm(lrealm,1)) {
119 fprintf(stderr, "%s: can't get local realm\n", prog);
123 printf("lrealm is %s\n", lrealm);
124 if (krb_udp_port == 0) {
125 register struct servent *sp;
126 if ((sp = getservbyname("kerberos","udp")) == 0) {
128 fprintf(stderr, "%s: Can't get kerberos/udp service\n",
132 krb_udp_port = sp->s_port;
134 printf("krb_udp_port is %d\n", krb_udp_port);
136 memset(&to, 0, S_AD_SZ);
137 hostlist = (struct hostent *) malloc(sizeof(struct hostent));
139 return (/*errno */SKDC_CANT);
140 if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
142 fprintf(stderr,"%s: Can't open socket\n", prog);
145 /* from now on, exit through rtn label for cleanup */
148 /* get an initial allocation */
150 for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) {
152 printf("Getting host entry for %s...",krbhst);
153 (void) fflush(stdout);
155 host = gethostbyname(krbhst);
158 host ? "Got it" : "Didn't get it");
159 (void) fflush(stdout);
163 no_host = 0; /* found at least one */
165 /* preserve host network address to check later
166 * (would be better to preserve *all* addresses,
167 * take care of that later)
169 hostlist = (struct hostent *)
170 realloc((char *)hostlist,
172 sizeof(struct hostent)*(n_hosts+1));
174 return /*errno */SKDC_CANT;
175 memcpy(&hostlist[n_hosts-1], host, sizeof(struct hostent));
176 host = &hostlist[n_hosts-1];
177 cp = malloc((unsigned)host->h_length);
179 retval = /*errno */SKDC_CANT;
182 memcpy(cp, host->h_addr, host->h_length);
183 /* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2
184 (or worse) only return one name ... */
185 #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
186 host->h_addr_list = (char **)malloc(sizeof(char *));
187 if (!host->h_addr_list) {
188 retval = /*errno */SKDC_CANT;
191 #endif /* ULTRIX022 || SunOS */
193 memset(&hostlist[n_hosts], 0, sizeof(struct hostent));
194 to.sin_family = host->h_addrtype;
195 memcpy(&to.sin_addr, host->h_addr, host->h_length);
196 to.sin_port = krb_udp_port;
197 if (send_recv(pkt, rpkt, f, &to, hostlist)) {
202 printf("Timeout, error, or wrong descriptor\n");
203 (void) fflush(stdout);
208 fprintf(stderr, "%s: can't find any Kerberos host.\n",
213 /* retry each host in sequence */
214 for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) {
215 for (host = hostlist; host->h_name != (char *)NULL; host++) {
216 to.sin_family = host->h_addrtype;
217 memcpy(&to.sin_addr, host->h_addr, host->h_length);
218 if (send_recv(pkt, rpkt, f, &to, hostlist)) {
228 register struct hostent *hp;
229 for (hp = hostlist; hp->h_name; hp++)
230 #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
231 if (hp->h_addr_list) {
232 #endif /* ULTRIX022 || SunOS */
235 #if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
236 free((char *)hp->h_addr_list);
238 #endif /* ULTRIX022 || SunOS */
239 free((char *)hostlist);
245 * try to send out and receive message.
246 * return 1 on success, 0 on failure
249 static send_recv(pkt,rpkt,f,_to,addrs)
253 struct sockaddr_in *_to;
254 struct hostent *addrs;
257 register struct hostent *hp;
258 struct sockaddr_in from;
263 if (_to->sin_family == AF_INET)
264 printf("Sending message to %s...",
265 inet_ntoa(_to->sin_addr));
267 printf("Sending message...");
268 (void) fflush(stdout);
270 if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0,
271 (struct sockaddr *)_to,
272 S_AD_SZ)) != pkt->length) {
274 printf("sent only %d/%d\n",numsent, pkt->length);
278 printf("Sent\nWaiting for reply...");
279 (void) fflush(stdout);
284 /* select - either recv is ready, or timeout */
285 /* see if timeout or error or wrong descriptor */
286 if (select(f + 1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 1
287 || !FD_ISSET(f, &readfds)) {
289 fprintf(stderr, "select failed: readfds=%x",
295 sin_size = sizeof(from);
296 if (( rc = recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0,
297 (struct sockaddr *)&from, &sin_size)) < 0) {
304 printf("received packet from %s\n", inet_ntoa(from.sin_addr));
307 for (hp = addrs; hp->h_name != (char *)NULL; hp++) {
308 if (!memcmp(hp->h_addr, (char *)&from.sin_addr.s_addr,
311 printf("Received it\n");
312 (void) fflush(stdout);
318 "packet not from %x\n",
322 fprintf(stderr, "%s: received packet from wrong host! (%x)\n",
323 "send_to_kdc(send_rcv)", from.sin_addr.s_addr);
327 #endif /* UAM_AFSKRB */