|
|
1.1 ! root 1: /* ! 2: * $Source: /usr/src/kerberosIV/src/lib/krb/RCS/rd_req.c,v $ ! 3: * $Author: kfall $ ! 4: * ! 5: * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute ! 6: * of Technology. ! 7: * ! 8: * For copying and distribution information, please see the file ! 9: * <mit-copyright.h>. ! 10: */ ! 11: ! 12: #ifndef lint ! 13: static char *rcsid_rd_req_c = ! 14: "$Header: /usr/src/kerberosIV/src/lib/krb/RCS/rd_req.c,v 4.17 90/05/12 00:58:48 kfall Exp $"; ! 15: #endif /* lint */ ! 16: ! 17: #include <mit-copyright.h> ! 18: #include <des.h> ! 19: #include <krb.h> ! 20: #include <prot.h> ! 21: #include <sys/time.h> ! 22: #include <strings.h> ! 23: ! 24: extern int krb_ap_req_debug; ! 25: ! 26: static struct timeval t_local = { 0, 0 }; ! 27: ! 28: /* ! 29: * Keep the following information around for subsequent calls ! 30: * to this routine by the same server using the same key. ! 31: */ ! 32: ! 33: static Key_schedule serv_key; /* Key sched to decrypt ticket */ ! 34: static C_Block ky; /* Initialization vector */ ! 35: static int st_kvno; /* version number for this key */ ! 36: static char st_rlm[REALM_SZ]; /* server's realm */ ! 37: static char st_nam[ANAME_SZ]; /* service name */ ! 38: static char st_inst[INST_SZ]; /* server's instance */ ! 39: ! 40: /* ! 41: * This file contains two functions. krb_set_key() takes a DES ! 42: * key or password string and returns a DES key (either the original ! 43: * key, or the password converted into a DES key) and a key schedule ! 44: * for it. ! 45: * ! 46: * krb_rd_req() reads an authentication request and returns information ! 47: * about the identity of the requestor, or an indication that the ! 48: * identity information was not authentic. ! 49: */ ! 50: ! 51: /* ! 52: * krb_set_key() takes as its first argument either a DES key or a ! 53: * password string. The "cvt" argument indicates how the first ! 54: * argument "key" is to be interpreted: if "cvt" is null, "key" is ! 55: * taken to be a DES key; if "cvt" is non-null, "key" is taken to ! 56: * be a password string, and is converted into a DES key using ! 57: * string_to_key(). In either case, the resulting key is returned ! 58: * in the external static variable "ky". A key schedule is ! 59: * generated for "ky" and returned in the external static variable ! 60: * "serv_key". ! 61: * ! 62: * This routine returns the return value of des_key_sched. ! 63: * ! 64: * krb_set_key() needs to be in the same .o file as krb_rd_req() so that ! 65: * the key set by krb_set_key() is available in private storage for ! 66: * krb_rd_req(). ! 67: */ ! 68: ! 69: int ! 70: krb_set_key(key,cvt) ! 71: char *key; ! 72: int cvt; ! 73: { ! 74: #ifdef NOENCRYPTION ! 75: bzero(ky, sizeof(ky)); ! 76: return KSUCCESS; ! 77: #else /* Encrypt */ ! 78: if (cvt) ! 79: string_to_key(key,ky); ! 80: else ! 81: bcopy(key,(char *)ky,8); ! 82: return(des_key_sched(ky,serv_key)); ! 83: #endif /* NOENCRYPTION */ ! 84: } ! 85: ! 86: ! 87: /* ! 88: * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or ! 89: * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(), ! 90: * checks its integrity and returns a judgement as to the requestor's ! 91: * identity. ! 92: * ! 93: * The "authent" argument is a pointer to the received message. ! 94: * The "service" and "instance" arguments name the receiving server, ! 95: * and are used to get the service's ticket to decrypt the ticket ! 96: * in the message, and to compare against the server name inside the ! 97: * ticket. "from_addr" is the network address of the host from which ! 98: * the message was received; this is checked against the network ! 99: * address in the ticket. If "from_addr" is zero, the check is not ! 100: * performed. "ad" is an AUTH_DAT structure which is ! 101: * filled in with information about the sender's identity according ! 102: * to the authenticator and ticket sent in the message. Finally, ! 103: * "fn" contains the name of the file containing the server's key. ! 104: * (If "fn" is NULL, the server's key is assumed to have been set ! 105: * by krb_set_key(). If "fn" is the null string ("") the default ! 106: * file KEYFILE, defined in "krb.h", is used.) ! 107: * ! 108: * krb_rd_req() returns RD_AP_OK if the authentication information ! 109: * was genuine, or one of the following error codes (defined in ! 110: * "krb.h"): ! 111: * ! 112: * RD_AP_VERSION - wrong protocol version number ! 113: * RD_AP_MSG_TYPE - wrong message type ! 114: * RD_AP_UNDEC - couldn't decipher the message ! 115: * RD_AP_INCON - inconsistencies found ! 116: * RD_AP_BADD - wrong network address ! 117: * RD_AP_TIME - client time (in authenticator) ! 118: * too far off server time ! 119: * RD_AP_NYV - Kerberos time (in ticket) too ! 120: * far off server time ! 121: * RD_AP_EXP - ticket expired ! 122: * ! 123: * For the message format, see krb_mk_req(). ! 124: * ! 125: * Mutual authentication is not implemented. ! 126: */ ! 127: ! 128: krb_rd_req(authent,service,instance,from_addr,ad,fn) ! 129: register KTEXT authent; /* The received message */ ! 130: char *service; /* Service name */ ! 131: char *instance; /* Service instance */ ! 132: long from_addr; /* Net address of originating host */ ! 133: AUTH_DAT *ad; /* Structure to be filled in */ ! 134: char *fn; /* Filename to get keys from */ ! 135: { ! 136: static KTEXT_ST ticket; /* Temp storage for ticket */ ! 137: static KTEXT tkt = &ticket; ! 138: static KTEXT_ST req_id_st; /* Temp storage for authenticator */ ! 139: register KTEXT req_id = &req_id_st; ! 140: ! 141: char realm[REALM_SZ]; /* Realm of issuing kerberos */ ! 142: static Key_schedule seskey_sched; /* Key sched for session key */ ! 143: unsigned char skey[KKEY_SZ]; /* Session key from ticket */ ! 144: char sname[SNAME_SZ]; /* Service name from ticket */ ! 145: char iname[INST_SZ]; /* Instance name from ticket */ ! 146: char r_aname[ANAME_SZ]; /* Client name from authenticator */ ! 147: char r_inst[INST_SZ]; /* Client instance from authenticator */ ! 148: char r_realm[REALM_SZ]; /* Client realm from authenticator */ ! 149: unsigned int r_time_ms; /* Fine time from authenticator */ ! 150: unsigned long r_time_sec; /* Coarse time from authenticator */ ! 151: register char *ptr; /* For stepping through */ ! 152: unsigned long delta_t; /* Time in authenticator - local time */ ! 153: long tkt_age; /* Age of ticket */ ! 154: static int swap_bytes; /* Need to swap bytes? */ ! 155: static int mutual; /* Mutual authentication requested? */ ! 156: static unsigned char s_kvno;/* Version number of the server's key ! 157: * Kerberos used to encrypt ticket */ ! 158: int status; ! 159: ! 160: if (authent->length <= 0) ! 161: return(RD_AP_MODIFIED); ! 162: ! 163: ptr = (char *) authent->dat; ! 164: ! 165: /* get msg version, type and byte order, and server key version */ ! 166: ! 167: /* check version */ ! 168: if (KRB_PROT_VERSION != (unsigned int) *ptr++) ! 169: return(RD_AP_VERSION); ! 170: ! 171: /* byte order */ ! 172: swap_bytes = 0; ! 173: if ((*ptr & 1) != HOST_BYTE_ORDER) ! 174: swap_bytes++; ! 175: ! 176: /* check msg type */ ! 177: mutual = 0; ! 178: switch (*ptr++ & ~1) { ! 179: case AUTH_MSG_APPL_REQUEST: ! 180: break; ! 181: case AUTH_MSG_APPL_REQUEST_MUTUAL: ! 182: mutual++; ! 183: break; ! 184: default: ! 185: return(RD_AP_MSG_TYPE); ! 186: } ! 187: ! 188: #ifdef lint ! 189: /* XXX mutual is set but not used; why??? */ ! 190: /* this is a crock to get lint to shut up */ ! 191: if (mutual) ! 192: mutual = 0; ! 193: #endif /* lint */ ! 194: s_kvno = *ptr++; /* get server key version */ ! 195: (void) strcpy(realm,ptr); /* And the realm of the issuing KDC */ ! 196: ptr += strlen(ptr) + 1; /* skip the realm "hint" */ ! 197: ! 198: /* ! 199: * If "fn" is NULL, key info should already be set; don't ! 200: * bother with ticket file. Otherwise, check to see if we ! 201: * already have key info for the given server and key version ! 202: * (saved in the static st_* variables). If not, go get it ! 203: * from the ticket file. If "fn" is the null string, use the ! 204: * default ticket file. ! 205: */ ! 206: if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) || ! 207: strcmp(st_rlm,realm) || (st_kvno != s_kvno))) { ! 208: if (*fn == 0) fn = KEYFILE; ! 209: st_kvno = s_kvno; ! 210: #ifndef NOENCRYPTION ! 211: if (read_service_key(service,instance,realm,(int) s_kvno, ! 212: fn,(char *)skey)) ! 213: return(RD_AP_UNDEC); ! 214: if (status = krb_set_key((char *)skey,0)) ! 215: return(status); ! 216: #endif /* !NOENCRYPTION */ ! 217: (void) strcpy(st_rlm,realm); ! 218: (void) strcpy(st_nam,service); ! 219: (void) strcpy(st_inst,instance); ! 220: } ! 221: ! 222: /* Get ticket from authenticator */ ! 223: tkt->length = (int) *ptr++; ! 224: if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length) ! 225: return(RD_AP_MODIFIED); ! 226: bcopy(ptr+1,(char *)(tkt->dat),tkt->length); ! 227: ! 228: if (krb_ap_req_debug) ! 229: log("ticket->length: %d",tkt->length); ! 230: ! 231: #ifndef NOENCRYPTION ! 232: /* Decrypt and take apart ticket */ ! 233: #endif ! 234: ! 235: if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm, ! 236: &(ad->address),ad->session, &(ad->life), ! 237: &(ad->time_sec),sname,iname,ky,serv_key)) ! 238: return(RD_AP_UNDEC); ! 239: ! 240: if (krb_ap_req_debug) { ! 241: log("Ticket Contents."); ! 242: log(" Aname: %s.%s",ad->pname, ! 243: ((int)*(ad->prealm) ? ad->prealm : "Athena")); ! 244: log(" Service: %s%s%s",sname,((int)*iname ? "." : ""),iname); ! 245: } ! 246: ! 247: /* Extract the authenticator */ ! 248: req_id->length = (int) *(ptr++); ! 249: if ((req_id->length + (ptr + tkt->length - (char *) authent->dat)) > ! 250: authent->length) ! 251: return(RD_AP_MODIFIED); ! 252: bcopy(ptr + tkt->length, (char *)(req_id->dat),req_id->length); ! 253: ! 254: #ifndef NOENCRYPTION ! 255: /* And decrypt it with the session key from the ticket */ ! 256: if (krb_ap_req_debug) log("About to decrypt authenticator"); ! 257: key_sched(ad->session,seskey_sched); ! 258: pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, ! 259: (long) req_id->length, seskey_sched,ad->session,DES_DECRYPT); ! 260: if (krb_ap_req_debug) log("Done."); ! 261: #endif /* NOENCRYPTION */ ! 262: ! 263: #define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED); ! 264: ! 265: ptr = (char *) req_id->dat; ! 266: (void) strcpy(r_aname,ptr); /* Authentication name */ ! 267: ptr += strlen(r_aname)+1; ! 268: check_ptr(); ! 269: (void) strcpy(r_inst,ptr); /* Authentication instance */ ! 270: ptr += strlen(r_inst)+1; ! 271: check_ptr(); ! 272: (void) strcpy(r_realm,ptr); /* Authentication name */ ! 273: ptr += strlen(r_realm)+1; ! 274: check_ptr(); ! 275: bcopy(ptr,(char *)&ad->checksum,4); /* Checksum */ ! 276: ptr += 4; ! 277: check_ptr(); ! 278: if (swap_bytes) swap_u_long(ad->checksum); ! 279: r_time_ms = *(ptr++); /* Time (fine) */ ! 280: #ifdef lint ! 281: /* XXX r_time_ms is set but not used. why??? */ ! 282: /* this is a crock to get lint to shut up */ ! 283: if (r_time_ms) ! 284: r_time_ms = 0; ! 285: #endif /* lint */ ! 286: check_ptr(); ! 287: /* assume sizeof(r_time_sec) == 4 ?? */ ! 288: bcopy(ptr,(char *)&r_time_sec,4); /* Time (coarse) */ ! 289: if (swap_bytes) swap_u_long(r_time_sec); ! 290: ! 291: /* Check for authenticity of the request */ ! 292: if (krb_ap_req_debug) ! 293: log("Pname: %s %s",ad->pname,r_aname); ! 294: if (strcmp(ad->pname,r_aname) != 0) ! 295: return(RD_AP_INCON); ! 296: if (strcmp(ad->pinst,r_inst) != 0) ! 297: return(RD_AP_INCON); ! 298: if (krb_ap_req_debug) ! 299: log("Realm: %s %s",ad->prealm,r_realm); ! 300: if ((strcmp(ad->prealm,r_realm) != 0)) ! 301: return(RD_AP_INCON); ! 302: ! 303: if (krb_ap_req_debug) ! 304: log("Address: %d %d",ad->address,from_addr); ! 305: if (from_addr && (ad->address != from_addr)) ! 306: return(RD_AP_BADD); ! 307: ! 308: (void) gettimeofday(&t_local,(struct timezone *) 0); ! 309: delta_t = abs((int)(t_local.tv_sec - r_time_sec)); ! 310: if (delta_t > CLOCK_SKEW) { ! 311: if (krb_ap_req_debug) ! 312: log("Time out of range: %d - %d = %d", ! 313: t_local.tv_sec,r_time_sec,delta_t); ! 314: return(RD_AP_TIME); ! 315: } ! 316: ! 317: /* Now check for expiration of ticket */ ! 318: ! 319: tkt_age = t_local.tv_sec - ad->time_sec; ! 320: if (krb_ap_req_debug) ! 321: log("Time: %d Issue Date: %d Diff: %d Life %x", ! 322: t_local.tv_sec,ad->time_sec,tkt_age,ad->life); ! 323: ! 324: if (t_local.tv_sec < ad->time_sec) { ! 325: if ((ad->time_sec - t_local.tv_sec) > CLOCK_SKEW) ! 326: return(RD_AP_NYV); ! 327: } ! 328: else if ((t_local.tv_sec - ad->time_sec) > 5 * 60 * ad->life) ! 329: return(RD_AP_EXP); ! 330: ! 331: /* All seems OK */ ! 332: ad->reply.length = 0; ! 333: ! 334: return(RD_AP_OK); ! 335: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.