|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.