• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.5/etc/uams/uams_krb4/
1/*
2 * $Id: send_to_kdc.c,v 1.4 2001-06-25 20:13:45 rufustfirefly Exp $
3 * $Author: rufustfirefly $
4 *
5 * Copyright (c) 1990,1994 Regents of The University of Michigan.
6 * All Rights Reserved.  See COPYRIGHT.
7 *
8 * $Source: /home/ralph/netatalk/rsync/netatalk/etc/uams/uams_krb4/send_to_kdc.c,v $
9 *
10 * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
11 *
12 * For copying and distribution information, please see the file
13 * <mit-copyright.h>.
14 */
15
16#ifndef lint
17static char rcsid_send_to_kdc_c[] =
18"$Id: send_to_kdc.c,v 1.4 2001-06-25 20:13:45 rufustfirefly Exp $";
19#endif /* lint */
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif /* HAVE_CONFIG_H */
24
25#ifdef UAM_AFSKRB
26
27#include <mit-copyright.h>
28
29#include <krb.h>
30#include <prot.h>
31
32#include <stdio.h>
33#include <string.h>
34#include <errno.h>
35#include <sys/time.h>
36#include <sys/types.h>
37#ifdef lint
38#include <sys/uio.h>            /* struct iovec to make lint happy */
39#endif /* lint */
40#include <sys/socket.h>
41#include <netinet/in.h>
42#include <netdb.h>
43#include <string.h>
44
45#define S_AD_SZ sizeof(struct sockaddr_in)
46
47extern int krb_debug;
48
49extern char *malloc(), *calloc(), *realloc();
50
51int krb_udp_port = 0;
52
53/* CLIENT_KRB_TIMEOUT indicates the time to wait before
54 * retrying a server.  It's defined in "krb.h".
55 */
56static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0};
57static char *prog = "send_to_kdc";
58static send_recv();
59
60/*
61 * This file contains two routines, send_to_kdc() and send_recv().
62 * send_recv() is a static routine used by send_to_kdc().
63 */
64
65/*
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.
72 *
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
76 * giving up entirely.
77 *
78 * If an answer was received from a Kerberos host, KSUCCESS is
79 * returned.  The following errors can be returned:
80 *
81 * SKDC_CANT    - can't get local realm
82 *              - can't find "kerberos" in /etc/services database
83 *              - can't open socket
84 *              - can't bind socket
85 *              - all ports in use
86 *              - couldn't find any Kerberos host
87 *
88 * SKDC_RETRY   - couldn't get an answer from any Kerberos server,
89 *		  after several retries
90 */
91
92send_to_kdc(pkt,rpkt,realm)
93    KTEXT pkt;
94    KTEXT rpkt;
95    char *realm;
96{
97    int i, f;
98    int no_host; /* was a kerberos host found? */
99    int retry;
100    int n_hosts;
101    int retval;
102    struct sockaddr_in to;
103    struct hostent *host, *hostlist;
104    char *cp;
105    char krbhst[MAX_HSTNM];
106    char lrealm[REALM_SZ];
107
108    /*
109     * If "realm" is non-null, use that, otherwise get the
110     * local realm.
111     */
112    if (realm)
113	(void) strcpy(lrealm, realm);
114    else
115	if (krb_get_lrealm(lrealm,1)) {
116	    if (krb_debug)
117		fprintf(stderr, "%s: can't get local realm\n", prog);
118	    return(SKDC_CANT);
119	}
120    if (krb_debug)
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) {
125            if (krb_debug)
126                fprintf(stderr, "%s: Can't get kerberos/udp service\n",
127                        prog);
128            return(SKDC_CANT);
129        }
130        krb_udp_port = sp->s_port;
131        if (krb_debug)
132            printf("krb_udp_port is %d\n", krb_udp_port);
133    }
134    memset(&to, 0, S_AD_SZ);
135    hostlist = (struct hostent *) malloc(sizeof(struct hostent));
136    if (!hostlist)
137        return (/*errno */SKDC_CANT);
138    if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
139        if (krb_debug)
140            fprintf(stderr,"%s: Can't open socket\n", prog);
141        return(SKDC_CANT);
142    }
143    /* from now on, exit through rtn label for cleanup */
144
145    no_host = 1;
146    /* get an initial allocation */
147    n_hosts = 0;
148    for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) {
149        if (krb_debug) {
150            printf("Getting host entry for %s...",krbhst);
151            (void) fflush(stdout);
152        }
153        host = gethostbyname(krbhst);
154        if (krb_debug) {
155            printf("%s.\n",
156                   host ? "Got it" : "Didn't get it");
157            (void) fflush(stdout);
158        }
159        if (!host)
160            continue;
161        no_host = 0;    /* found at least one */
162        n_hosts++;
163        /* preserve host network address to check later
164         * (would be better to preserve *all* addresses,
165         * take care of that later)
166         */
167        hostlist = (struct hostent *)
168            realloc((char *)hostlist,
169                    (unsigned)
170                    sizeof(struct hostent)*(n_hosts+1));
171        if (!hostlist)
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);
176        if (!cp) {
177            retval = /*errno */SKDC_CANT;
178            goto rtn;
179        }
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;
187            goto rtn;
188        }
189#endif /* ULTRIX022 || SunOS */
190        host->h_addr = cp;
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)) {
196            retval = KSUCCESS;
197            goto rtn;
198        }
199        if (krb_debug) {
200            printf("Timeout, error, or wrong descriptor\n");
201            (void) fflush(stdout);
202        }
203    }
204    if (no_host) {
205	if (krb_debug)
206	    fprintf(stderr, "%s: can't find any Kerberos host.\n",
207		    prog);
208        retval = SKDC_CANT;
209        goto rtn;
210    }
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)) {
217                retval = KSUCCESS;
218                goto rtn;
219            }
220        }
221    }
222    retval = SKDC_RETRY;
223rtn:
224    (void) close(f);
225    if (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 */
231                if (hp->h_addr)
232                    free(hp->h_addr);
233#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
234                free((char *)hp->h_addr_list);
235            }
236#endif /* ULTRIX022 || SunOS */
237        free((char *)hostlist);
238    }
239    return(retval);
240}
241
242/*
243 * try to send out and receive message.
244 * return 1 on success, 0 on failure
245 */
246
247static send_recv(pkt,rpkt,f,_to,addrs)
248    KTEXT pkt;
249    KTEXT rpkt;
250    int f;
251    struct sockaddr_in *_to;
252    struct hostent *addrs;
253{
254    fd_set readfds;
255    register struct hostent *hp;
256    struct sockaddr_in from;
257    int sin_size, rc;
258    int numsent;
259
260    if (krb_debug) {
261        if (_to->sin_family == AF_INET)
262            printf("Sending message to %s...",
263                   inet_ntoa(_to->sin_addr));
264        else
265            printf("Sending message...");
266        (void) fflush(stdout);
267    }
268    if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0,
269			  (struct sockaddr *)_to,
270                          S_AD_SZ)) != pkt->length) {
271        if (krb_debug)
272            printf("sent only %d/%d\n",numsent, pkt->length);
273        return 0;
274    }
275    if (krb_debug) {
276        printf("Sent\nWaiting for reply...");
277        (void) fflush(stdout);
278    }
279    FD_ZERO(&readfds);
280    FD_SET(f, &readfds);
281    errno = 0;
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)) {
286        if (krb_debug) {
287            fprintf(stderr, "select failed: readfds=%x",
288                    readfds);
289            perror("");
290        }
291        return 0;
292    }
293    sin_size = sizeof(from);
294    if (( rc = recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0,
295		 (struct sockaddr *)&from, &sin_size)) < 0) {
296        if (krb_debug)
297            perror("recvfrom");
298        return 0;
299    }
300    rpkt->length = rc;
301    if (krb_debug) {
302        printf("received packet from %s\n", inet_ntoa(from.sin_addr));
303        fflush(stdout);
304    }
305    for (hp = addrs; hp->h_name != (char *)NULL; hp++) {
306        if (!memcmp(hp->h_addr, (char *)&from.sin_addr.s_addr,
307                  hp->h_length)) {
308            if (krb_debug) {
309                printf("Received it\n");
310                (void) fflush(stdout);
311            }
312            return 1;
313        }
314        if (krb_debug)
315            fprintf(stderr,
316                    "packet not from %x\n",
317                    hp->h_addr);
318    }
319    if (krb_debug)
320        fprintf(stderr, "%s: received packet from wrong host! (%x)\n",
321                "send_to_kdc(send_rcv)", from.sin_addr.s_addr);
322    return 0;
323}
324
325#endif /* UAM_AFSKRB */
326