2
* $Id: send_to_kdc.c,v 1.4 2001/06/25 20:13:45 rufustfirefly Exp $
3
* $Author: rufustfirefly $
5
* Copyright (c) 1990,1994 Regents of The University of Michigan.
6
* All Rights Reserved. See COPYRIGHT.
8
* $Source: /cvsroot/netatalk/netatalk/etc/uams/uams_krb4/send_to_kdc.c,v $
10
* Copyright 1987, 1988 by the Massachusetts Institute of Technology.
12
* For copying and distribution information, please see the file
17
static char rcsid_send_to_kdc_c[] =
18
"$Id: send_to_kdc.c,v 1.4 2001/06/25 20:13:45 rufustfirefly Exp $";
23
#endif /* HAVE_CONFIG_H */
27
#include <mit-copyright.h>
36
#include <sys/types.h>
38
#include <sys/uio.h> /* struct iovec to make lint happy */
40
#include <sys/socket.h>
41
#include <netinet/in.h>
45
#define S_AD_SZ sizeof(struct sockaddr_in)
49
extern char *malloc(), *calloc(), *realloc();
53
/* CLIENT_KRB_TIMEOUT indicates the time to wait before
54
* retrying a server. It's defined in "krb.h".
56
static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0};
57
static char *prog = "send_to_kdc";
61
* This file contains two routines, send_to_kdc() and send_recv().
62
* send_recv() is a static routine used by send_to_kdc().
66
* send_to_kdc() sends a message to the Kerberos authentication
67
* server(s) in the given realm and returns the reply message.
68
* The "pkt" argument points to the message to be sent to Kerberos;
69
* the "rpkt" argument will be filled in with Kerberos' reply.
70
* The "realm" argument indicates the realm of the Kerberos server(s)
71
* to transact with. If the realm is null, the local realm is used.
73
* If more than one Kerberos server is known for a given realm,
74
* different servers will be queried until one of them replies.
75
* Several attempts (retries) are made for each server before
78
* If an answer was received from a Kerberos host, KSUCCESS is
79
* returned. The following errors can be returned:
81
* SKDC_CANT - can't get local realm
82
* - can't find "kerberos" in /etc/services database
86
* - couldn't find any Kerberos host
88
* SKDC_RETRY - couldn't get an answer from any Kerberos server,
89
* after several retries
92
send_to_kdc(pkt,rpkt,realm)
98
int no_host; /* was a kerberos host found? */
102
struct sockaddr_in to;
103
struct hostent *host, *hostlist;
105
char krbhst[MAX_HSTNM];
106
char lrealm[REALM_SZ];
109
* If "realm" is non-null, use that, otherwise get the
113
(void) strcpy(lrealm, realm);
115
if (krb_get_lrealm(lrealm,1)) {
117
fprintf(stderr, "%s: can't get local realm\n", prog);
121
printf("lrealm is %s\n", lrealm);
122
if (krb_udp_port == 0) {
123
register struct servent *sp;
124
if ((sp = getservbyname("kerberos","udp")) == 0) {
126
fprintf(stderr, "%s: Can't get kerberos/udp service\n",
130
krb_udp_port = sp->s_port;
132
printf("krb_udp_port is %d\n", krb_udp_port);
134
memset(&to, 0, S_AD_SZ);
135
hostlist = (struct hostent *) malloc(sizeof(struct hostent));
137
return (/*errno */SKDC_CANT);
138
if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
140
fprintf(stderr,"%s: Can't open socket\n", prog);
143
/* from now on, exit through rtn label for cleanup */
146
/* get an initial allocation */
148
for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) {
150
printf("Getting host entry for %s...",krbhst);
151
(void) fflush(stdout);
153
host = gethostbyname(krbhst);
156
host ? "Got it" : "Didn't get it");
157
(void) fflush(stdout);
161
no_host = 0; /* found at least one */
163
/* preserve host network address to check later
164
* (would be better to preserve *all* addresses,
165
* take care of that later)
167
hostlist = (struct hostent *)
168
realloc((char *)hostlist,
170
sizeof(struct hostent)*(n_hosts+1));
172
return /*errno */SKDC_CANT;
173
memcpy(&hostlist[n_hosts-1], host, sizeof(struct hostent));
174
host = &hostlist[n_hosts-1];
175
cp = malloc((unsigned)host->h_length);
177
retval = /*errno */SKDC_CANT;
180
memcpy(cp, host->h_addr, host->h_length);
181
/* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2
182
(or worse) only return one name ... */
183
#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
184
host->h_addr_list = (char **)malloc(sizeof(char *));
185
if (!host->h_addr_list) {
186
retval = /*errno */SKDC_CANT;
189
#endif /* ULTRIX022 || SunOS */
191
memset(&hostlist[n_hosts], 0, sizeof(struct hostent));
192
to.sin_family = host->h_addrtype;
193
memcpy(&to.sin_addr, host->h_addr, host->h_length);
194
to.sin_port = krb_udp_port;
195
if (send_recv(pkt, rpkt, f, &to, hostlist)) {
200
printf("Timeout, error, or wrong descriptor\n");
201
(void) fflush(stdout);
206
fprintf(stderr, "%s: can't find any Kerberos host.\n",
211
/* retry each host in sequence */
212
for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) {
213
for (host = hostlist; host->h_name != (char *)NULL; host++) {
214
to.sin_family = host->h_addrtype;
215
memcpy(&to.sin_addr, host->h_addr, host->h_length);
216
if (send_recv(pkt, rpkt, f, &to, hostlist)) {
226
register struct hostent *hp;
227
for (hp = hostlist; hp->h_name; hp++)
228
#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
229
if (hp->h_addr_list) {
230
#endif /* ULTRIX022 || SunOS */
233
#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
234
free((char *)hp->h_addr_list);
236
#endif /* ULTRIX022 || SunOS */
237
free((char *)hostlist);
243
* try to send out and receive message.
244
* return 1 on success, 0 on failure
247
static send_recv(pkt,rpkt,f,_to,addrs)
251
struct sockaddr_in *_to;
252
struct hostent *addrs;
255
register struct hostent *hp;
256
struct sockaddr_in from;
261
if (_to->sin_family == AF_INET)
262
printf("Sending message to %s...",
263
inet_ntoa(_to->sin_addr));
265
printf("Sending message...");
266
(void) fflush(stdout);
268
if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0,
269
(struct sockaddr *)_to,
270
S_AD_SZ)) != pkt->length) {
272
printf("sent only %d/%d\n",numsent, pkt->length);
276
printf("Sent\nWaiting for reply...");
277
(void) fflush(stdout);
282
/* select - either recv is ready, or timeout */
283
/* see if timeout or error or wrong descriptor */
284
if (select(f + 1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 1
285
|| !FD_ISSET(f, &readfds)) {
287
fprintf(stderr, "select failed: readfds=%x",
293
sin_size = sizeof(from);
294
if (( rc = recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0,
295
(struct sockaddr *)&from, &sin_size)) < 0) {
302
printf("received packet from %s\n", inet_ntoa(from.sin_addr));
305
for (hp = addrs; hp->h_name != (char *)NULL; hp++) {
306
if (!memcmp(hp->h_addr, (char *)&from.sin_addr.s_addr,
309
printf("Received it\n");
310
(void) fflush(stdout);
316
"packet not from %x\n",
320
fprintf(stderr, "%s: received packet from wrong host! (%x)\n",
321
"send_to_kdc(send_rcv)", from.sin_addr.s_addr);
325
#endif /* UAM_AFSKRB */