Annotation of 43BSDReno/kerberosIV/krb/send_to_kdc.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.