Annotation of 43BSDReno/kerberosIV/krb/send_to_kdc.c, revision 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.