|
|
1.1 ! root 1: /* ! 2: * $Source: /usr/src/kerberosIV/src/lib/krb/RCS/recvauth.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_recvauth_c[] = ! 13: "$Header: /usr/src/kerberosIV/src/lib/krb/RCS/recvauth.c,v 4.4 90/05/12 00:58:56 kfall Exp $"; ! 14: #endif lint ! 15: ! 16: #include <mit-copyright.h> ! 17: ! 18: #include <des.h> ! 19: #include <krb.h> ! 20: #include <sys/types.h> ! 21: #include <netinet/in.h> ! 22: #include <syslog.h> ! 23: #include <errno.h> ! 24: #include <stdio.h> ! 25: #include <strings.h> ! 26: ! 27: ! 28: #define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN ! 29: chars */ ! 30: ! 31: /* ! 32: * If the protocol changes, you will need to change the version string ! 33: * and make appropriate changes in krb_sendauth.c ! 34: * be sure to support old versions of krb_sendauth! ! 35: */ ! 36: ! 37: extern int errno; ! 38: ! 39: /* ! 40: * krb_recvauth() reads (and optionally responds to) a message sent ! 41: * using krb_sendauth(). The "options" argument is a bit-field of ! 42: * selected options (see "sendauth.c" for options description). ! 43: * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL ! 44: * (mutual authentication requested). The "fd" argument supplies ! 45: * a file descriptor to read from (and write to, if mutual authenti- ! 46: * cation is requested). ! 47: * ! 48: * Part of the received message will be a Kerberos ticket sent by the ! 49: * client; this is read into the "ticket" argument. The "service" and ! 50: * "instance" arguments supply the server's Kerberos name. If the ! 51: * "instance" argument is the string "*", it is treated as a wild card ! 52: * and filled in during the krb_rd_req() call (see read_service_key()). ! 53: * ! 54: * The "faddr" and "laddr" give the sending (client) and receiving ! 55: * (local server) network addresses. ("laddr" may be left NULL unless ! 56: * mutual authentication is requested, in which case it must be set.) ! 57: * ! 58: * The authentication information extracted from the message is returned ! 59: * in "kdata". The "filename" argument indicates the file where the ! 60: * server's key can be found. (It is passed on to krb_rd_req().) If ! 61: * left null, the default "/etc/srvtab" will be used. ! 62: * ! 63: * If mutual authentication is requested, the session key schedule must ! 64: * be computed in order to reply; this schedule is returned in the ! 65: * "schedule" argument. A string containing the application version ! 66: * number from the received message is returned in "version", which ! 67: * should be large enough to hold a KRB_SENDAUTH_VLEN-character string. ! 68: * ! 69: * See krb_sendauth() for the format of the received client message. ! 70: * ! 71: * This routine supports another client format, for backward ! 72: * compatibility, consisting of: ! 73: * ! 74: * Size Variable Field ! 75: * ---- -------- ----- ! 76: * ! 77: * string tmp_buf, tkt_len length of ticket, in ! 78: * ascii ! 79: * ! 80: * char ' ' (space char) separator ! 81: * ! 82: * tkt_len ticket->dat the ticket ! 83: * ! 84: * This old-style version does not support mutual authentication. ! 85: * ! 86: * krb_recvauth() first reads the protocol version string from the ! 87: * given file descriptor. If it doesn't match the current protocol ! 88: * version (KRB_SENDAUTH_VERS), the old-style format is assumed. In ! 89: * that case, the string of characters up to the first space is read ! 90: * and interpreted as the ticket length, then the ticket is read. ! 91: * ! 92: * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth() ! 93: * next reads the application protocol version string. Then the ! 94: * ticket length and ticket itself are read. ! 95: * ! 96: * The ticket is decrypted and checked by the call to krb_rd_req(). ! 97: * If no mutual authentication is required, the result of the ! 98: * krb_rd_req() call is retured by this routine. If mutual authenti- ! 99: * cation is required, a message in the following format is returned ! 100: * on "fd": ! 101: * ! 102: * Size Variable Field ! 103: * ---- -------- ----- ! 104: * ! 105: * 4 bytes tkt_len length of ticket or -1 ! 106: * if error occurred ! 107: * ! 108: * priv_len tmp_buf "private" message created ! 109: * by krb_mk_priv() which ! 110: * contains the incremented ! 111: * checksum sent by the client ! 112: * encrypted in the session ! 113: * key. (This field is not ! 114: * present in case of error.) ! 115: * ! 116: * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some ! 117: * other error code is returned. ! 118: */ ! 119: ! 120: int ! 121: krb_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata, ! 122: filename, schedule, version) ! 123: long options; /* bit-pattern of options */ ! 124: int fd; /* file descr. to read from */ ! 125: KTEXT ticket; /* storage for client's ticket */ ! 126: char *service; /* service expected */ ! 127: char *instance; /* inst expected (may be filled in) */ ! 128: struct sockaddr_in *faddr; /* address of foreign host on fd */ ! 129: struct sockaddr_in *laddr; /* local address */ ! 130: AUTH_DAT *kdata; /* kerberos data (returned) */ ! 131: char *filename; /* name of file with service keys */ ! 132: Key_schedule schedule; /* key schedule (return) */ ! 133: char *version; /* version string (filled in) */ ! 134: { ! 135: ! 136: int i, cc, old_vers = 0; ! 137: char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */ ! 138: char *cp; ! 139: int rem; ! 140: long tkt_len, priv_len; ! 141: u_long cksum; ! 142: u_char tmp_buf[1024]; ! 143: ! 144: /* read the protocol version number */ ! 145: if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) != ! 146: KRB_SENDAUTH_VLEN) ! 147: return(errno); ! 148: krb_vers[KRB_SENDAUTH_VLEN] = '\0'; ! 149: ! 150: /* check version string */ ! 151: if (strcmp(krb_vers,KRB_SENDAUTH_VERS)) { ! 152: /* Assume the old version of sendkerberosdata: send ascii ! 153: length, ' ', and ticket. */ ! 154: if (options & KOPT_DO_MUTUAL) ! 155: return(KFAILURE); /* XXX can't do old style with mutual auth */ ! 156: old_vers = 1; ! 157: ! 158: /* copy what we have read into tmp_buf */ ! 159: (void) bcopy(krb_vers, (char *) tmp_buf, KRB_SENDAUTH_VLEN); ! 160: ! 161: /* search for space, and make it a null */ ! 162: for (i = 0; i < KRB_SENDAUTH_VLEN; i++) ! 163: if (tmp_buf[i]== ' ') { ! 164: tmp_buf[i] = '\0'; ! 165: /* point cp to the beginning of the real ticket */ ! 166: cp = (char *) &tmp_buf[i+1]; ! 167: break; ! 168: } ! 169: ! 170: if (i == KRB_SENDAUTH_VLEN) ! 171: /* didn't find the space, keep reading to find it */ ! 172: for (; i<20; i++) { ! 173: if (read(fd, (char *)&tmp_buf[i], 1) != 1) { ! 174: return(KFAILURE); ! 175: } ! 176: if (tmp_buf[i] == ' ') { ! 177: tmp_buf[i] = '\0'; ! 178: /* point cp to the beginning of the real ticket */ ! 179: cp = (char *) &tmp_buf[i+1]; ! 180: break; ! 181: } ! 182: } ! 183: ! 184: tkt_len = (long) atoi((char *) tmp_buf); ! 185: ! 186: /* sanity check the length */ ! 187: if ((i==20)||(tkt_len<=0)||(tkt_len>MAX_KTXT_LEN)) ! 188: return(KFAILURE); ! 189: ! 190: if (i < KRB_SENDAUTH_VLEN) { ! 191: /* since we already got the space, and part of the ticket, ! 192: we read fewer bytes to get the rest of the ticket */ ! 193: if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN), ! 194: (int) (tkt_len - KRB_SENDAUTH_VLEN + 1 + i)) ! 195: != (int)(tkt_len - KRB_SENDAUTH_VLEN + 1 + i)) ! 196: return(errno); ! 197: } else { ! 198: if (krb_net_read(fd, (char *)(tmp_buf+i), (int)tkt_len) != ! 199: (int) tkt_len) ! 200: return(errno); ! 201: } ! 202: ticket->length = tkt_len; ! 203: /* copy the ticket into the struct */ ! 204: (void) bcopy(cp, (char *) ticket->dat, ticket->length); ! 205: ! 206: } else { ! 207: /* read the application version string */ ! 208: if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) != ! 209: KRB_SENDAUTH_VLEN) ! 210: return(errno); ! 211: version[KRB_SENDAUTH_VLEN] = '\0'; ! 212: ! 213: /* get the length of the ticket */ ! 214: if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) != ! 215: sizeof(tkt_len)) ! 216: return(errno); ! 217: ! 218: /* sanity check */ ! 219: ticket->length = ntohl((unsigned long)tkt_len); ! 220: if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) { ! 221: if (options & KOPT_DO_MUTUAL) { ! 222: rem = KFAILURE; ! 223: goto mutual_fail; ! 224: } else ! 225: return(KFAILURE); /* XXX there may still be junk on the fd? */ ! 226: } ! 227: ! 228: /* read the ticket */ ! 229: if (krb_net_read(fd, (char *) ticket->dat, ticket->length) ! 230: != ticket->length) ! 231: return(errno); ! 232: } ! 233: /* ! 234: * now have the ticket. decrypt it to get the authenticated ! 235: * data. ! 236: */ ! 237: rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr, ! 238: kdata,filename); ! 239: ! 240: if (old_vers) return(rem); /* XXX can't do mutual with old client */ ! 241: ! 242: /* if we are doing mutual auth, compose a response */ ! 243: if (options & KOPT_DO_MUTUAL) { ! 244: if (rem != KSUCCESS) ! 245: /* the krb_rd_req failed */ ! 246: goto mutual_fail; ! 247: ! 248: /* add one to the (formerly) sealed checksum, and re-seal it ! 249: for return to the client */ ! 250: cksum = kdata->checksum + 1; ! 251: cksum = htonl(cksum); ! 252: #ifndef NOENCRYPTION ! 253: key_sched(kdata->session,schedule); ! 254: #endif /* !NOENCRYPTION */ ! 255: priv_len = krb_mk_priv((unsigned char *)&cksum, ! 256: tmp_buf, ! 257: (unsigned long) sizeof(cksum), ! 258: schedule, ! 259: kdata->session, ! 260: laddr, ! 261: faddr); ! 262: if (priv_len < 0) { ! 263: /* re-sealing failed; notify the client */ ! 264: rem = KFAILURE; /* XXX */ ! 265: mutual_fail: ! 266: priv_len = -1; ! 267: tkt_len = htonl((unsigned long) priv_len); ! 268: /* a length of -1 is interpreted as an authentication ! 269: failure by the client */ ! 270: if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len))) ! 271: != sizeof(tkt_len)) ! 272: return(cc); ! 273: return(rem); ! 274: } else { ! 275: /* re-sealing succeeded, send the private message */ ! 276: tkt_len = htonl((unsigned long)priv_len); ! 277: if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len))) ! 278: != sizeof(tkt_len)) ! 279: return(cc); ! 280: if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len)) ! 281: != (int) priv_len) ! 282: return(cc); ! 283: } ! 284: } ! 285: return(rem); ! 286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.