|
|
1.1 ! root 1: /* ! 2: * $Source: /usr/src/kerberosIV/krb/RCS/krb_get_in_tkt.c,v $ ! 3: * $Author: kfall $ ! 4: * ! 5: * Copyright 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_krb_get_in_tkt_c = ! 14: "$Header: /usr/src/kerberosIV/krb/RCS/krb_get_in_tkt.c,v 4.20 90/06/25 20:56:45 kfall Exp $"; ! 15: #endif /* lint */ ! 16: ! 17: #include <mit-copyright.h> ! 18: #include <des.h> ! 19: #include <krb.h> ! 20: #include <prot.h> ! 21: ! 22: #include <stdio.h> ! 23: #include <strings.h> ! 24: #include <errno.h> ! 25: ! 26: /* use the bsd time.h struct defs for PC too! */ ! 27: #include <sys/time.h> ! 28: #include <sys/types.h> ! 29: ! 30: int swap_bytes; ! 31: ! 32: /* ! 33: * decrypt_tkt(): Given user, instance, realm, passwd, key_proc ! 34: * and the cipher text sent from the KDC, decrypt the cipher text ! 35: * using the key returned by key_proc. ! 36: */ ! 37: ! 38: static int decrypt_tkt(user, instance, realm, arg, key_proc, cipp) ! 39: char *user; ! 40: char *instance; ! 41: char *realm; ! 42: char *arg; ! 43: int (*key_proc)(); ! 44: KTEXT *cipp; ! 45: { ! 46: KTEXT cip = *cipp; ! 47: C_Block key; /* Key for decrypting cipher */ ! 48: Key_schedule key_s; ! 49: ! 50: #ifndef NOENCRYPTION ! 51: /* Attempt to decrypt it */ ! 52: #endif ! 53: ! 54: /* generate a key */ ! 55: ! 56: { ! 57: register int rc; ! 58: rc = (*key_proc)(user,instance,realm,arg,key); ! 59: if (rc) ! 60: return(rc); ! 61: } ! 62: ! 63: #ifndef NOENCRYPTION ! 64: key_sched(key,key_s); ! 65: pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat, ! 66: (long) cip->length,key_s,key,0); ! 67: #endif /* !NOENCRYPTION */ ! 68: /* Get rid of all traces of key */ ! 69: bzero((char *)key,sizeof(key)); ! 70: bzero((char *)key_s,sizeof(key_s)); ! 71: ! 72: return(0); ! 73: } ! 74: ! 75: /* ! 76: * krb_get_in_tkt() gets a ticket for a given principal to use a given ! 77: * service and stores the returned ticket and session key for future ! 78: * use. ! 79: * ! 80: * The "user", "instance", and "realm" arguments give the identity of ! 81: * the client who will use the ticket. The "service" and "sinstance" ! 82: * arguments give the identity of the server that the client wishes ! 83: * to use. (The realm of the server is the same as the Kerberos server ! 84: * to whom the request is sent.) The "life" argument indicates the ! 85: * desired lifetime of the ticket; the "key_proc" argument is a pointer ! 86: * to the routine used for getting the client's private key to decrypt ! 87: * the reply from Kerberos. The "decrypt_proc" argument is a pointer ! 88: * to the routine used to decrypt the reply from Kerberos; and "arg" ! 89: * is an argument to be passed on to the "key_proc" routine. ! 90: * ! 91: * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it ! 92: * returns an error code: If an AUTH_MSG_ERR_REPLY packet is returned ! 93: * by Kerberos, then the error code it contains is returned. Other ! 94: * error codes returned by this routine include INTK_PROT to indicate ! 95: * wrong protocol version, INTK_BADPW to indicate bad password (if ! 96: * decrypted ticket didn't make sense), INTK_ERR if the ticket was for ! 97: * the wrong server or the ticket store couldn't be initialized. ! 98: * ! 99: * The format of the message sent to Kerberos is as follows: ! 100: * ! 101: * Size Variable Field ! 102: * ---- -------- ----- ! 103: * ! 104: * 1 byte KRB_PROT_VERSION protocol version number ! 105: * 1 byte AUTH_MSG_KDC_REQUEST | message type ! 106: * HOST_BYTE_ORDER local byte order in lsb ! 107: * string user client's name ! 108: * string instance client's instance ! 109: * string realm client's realm ! 110: * 4 bytes tlocal.tv_sec timestamp in seconds ! 111: * 1 byte life desired lifetime ! 112: * string service service's name ! 113: * string sinstance service's instance ! 114: */ ! 115: ! 116: krb_get_in_tkt(user, instance, realm, service, sinstance, life, ! 117: key_proc, decrypt_proc, arg) ! 118: char *user; ! 119: char *instance; ! 120: char *realm; ! 121: char *service; ! 122: char *sinstance; ! 123: int life; ! 124: int (*key_proc)(); ! 125: int (*decrypt_proc)(); ! 126: char *arg; ! 127: { ! 128: KTEXT_ST pkt_st; ! 129: KTEXT pkt = &pkt_st; /* Packet to KDC */ ! 130: KTEXT_ST rpkt_st; ! 131: KTEXT rpkt = &rpkt_st; /* Returned packet */ ! 132: KTEXT_ST cip_st; ! 133: KTEXT cip = &cip_st; /* Returned Ciphertext */ ! 134: KTEXT_ST tkt_st; ! 135: KTEXT tkt = &tkt_st; /* Current ticket */ ! 136: C_Block ses; /* Session key for tkt */ ! 137: int kvno; /* Kvno for session key */ ! 138: unsigned char *v = pkt->dat; /* Prot vers no */ ! 139: unsigned char *t = (pkt->dat+1); /* Prot msg type */ ! 140: ! 141: char s_name[SNAME_SZ]; ! 142: char s_instance[INST_SZ]; ! 143: char rlm[REALM_SZ]; ! 144: int lifetime; ! 145: int msg_byte_order; ! 146: int kerror; ! 147: unsigned long exp_date; ! 148: char *ptr; ! 149: ! 150: struct timeval t_local; ! 151: ! 152: unsigned long rep_err_code; ! 153: ! 154: unsigned long kdc_time; /* KDC time */ ! 155: ! 156: /* BUILD REQUEST PACKET */ ! 157: ! 158: /* Set up the fixed part of the packet */ ! 159: *v = (unsigned char) KRB_PROT_VERSION; ! 160: *t = (unsigned char) AUTH_MSG_KDC_REQUEST; ! 161: *t |= HOST_BYTE_ORDER; ! 162: ! 163: /* Now for the variable info */ ! 164: (void) strcpy((char *)(pkt->dat+2),user); /* aname */ ! 165: pkt->length = 3 + strlen(user); ! 166: (void) strcpy((char *)(pkt->dat+pkt->length), ! 167: instance); /* instance */ ! 168: pkt->length += 1 + strlen(instance); ! 169: (void) strcpy((char *)(pkt->dat+pkt->length),realm); /* realm */ ! 170: pkt->length += 1 + strlen(realm); ! 171: ! 172: (void) gettimeofday(&t_local,(struct timezone *) 0); ! 173: /* timestamp */ ! 174: bcopy((char *)&(t_local.tv_sec),(char *)(pkt->dat+pkt->length), 4); ! 175: pkt->length += 4; ! 176: ! 177: *(pkt->dat+(pkt->length)++) = (char) life; ! 178: (void) strcpy((char *)(pkt->dat+pkt->length),service); ! 179: pkt->length += 1 + strlen(service); ! 180: (void) strcpy((char *)(pkt->dat+pkt->length),sinstance); ! 181: pkt->length += 1 + strlen(sinstance); ! 182: ! 183: rpkt->length = 0; ! 184: ! 185: /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */ ! 186: ! 187: if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror); ! 188: ! 189: /* check packet version of the returned packet */ ! 190: if (pkt_version(rpkt) != KRB_PROT_VERSION) ! 191: return(INTK_PROT); ! 192: ! 193: /* Check byte order */ ! 194: msg_byte_order = pkt_msg_type(rpkt) & 1; ! 195: swap_bytes = 0; ! 196: if (msg_byte_order != HOST_BYTE_ORDER) { ! 197: swap_bytes++; ! 198: } ! 199: ! 200: switch (pkt_msg_type(rpkt) & ~1) { ! 201: case AUTH_MSG_KDC_REPLY: ! 202: break; ! 203: case AUTH_MSG_ERR_REPLY: ! 204: bcopy(pkt_err_code(rpkt),(char *) &rep_err_code,4); ! 205: if (swap_bytes) swap_u_long(rep_err_code); ! 206: return((int)rep_err_code); ! 207: default: ! 208: return(INTK_PROT); ! 209: } ! 210: ! 211: /* EXTRACT INFORMATION FROM RETURN PACKET */ ! 212: ! 213: /* get the principal's expiration date */ ! 214: bcopy(pkt_x_date(rpkt),(char *) &exp_date,sizeof(exp_date)); ! 215: if (swap_bytes) swap_u_long(exp_date); ! 216: ! 217: /* Extract the ciphertext */ ! 218: cip->length = pkt_clen(rpkt); /* let clen do the swap */ ! 219: ! 220: if ((cip->length < 0) || (cip->length > sizeof(cip->dat))) ! 221: return(INTK_ERR); /* no appropriate error code ! 222: currently defined for INTK_ */ ! 223: /* copy information from return packet into "cip" */ ! 224: bcopy((char *) pkt_cipher(rpkt),(char *)(cip->dat),cip->length); ! 225: ! 226: /* Attempt to decrypt the reply. */ ! 227: if (decrypt_proc == NULL) ! 228: decrypt_proc = decrypt_tkt; ! 229: (*decrypt_proc)(user, instance, realm, arg, key_proc, &cip); ! 230: ! 231: ptr = (char *) cip->dat; ! 232: ! 233: /* extract session key */ ! 234: bcopy(ptr,(char *)ses,8); ! 235: ptr += 8; ! 236: ! 237: if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) ! 238: return(INTK_BADPW); ! 239: ! 240: /* extract server's name */ ! 241: (void) strcpy(s_name,ptr); ! 242: ptr += strlen(s_name) + 1; ! 243: ! 244: if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) ! 245: return(INTK_BADPW); ! 246: ! 247: /* extract server's instance */ ! 248: (void) strcpy(s_instance,ptr); ! 249: ptr += strlen(s_instance) + 1; ! 250: ! 251: if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) ! 252: return(INTK_BADPW); ! 253: ! 254: /* extract server's realm */ ! 255: (void) strcpy(rlm,ptr); ! 256: ptr += strlen(rlm) + 1; ! 257: ! 258: /* extract ticket lifetime, server key version, ticket length */ ! 259: /* be sure to avoid sign extension on lifetime! */ ! 260: lifetime = (unsigned char) ptr[0]; ! 261: kvno = (unsigned char) ptr[1]; ! 262: tkt->length = (unsigned char) ptr[2]; ! 263: ptr += 3; ! 264: ! 265: if ((tkt->length < 0) || ! 266: ((tkt->length + (ptr - (char *) cip->dat)) > cip->length)) ! 267: return(INTK_BADPW); ! 268: ! 269: /* extract ticket itself */ ! 270: bcopy(ptr,(char *)(tkt->dat),tkt->length); ! 271: ptr += tkt->length; ! 272: ! 273: if (strcmp(s_name, service) || strcmp(s_instance, sinstance) || ! 274: strcmp(rlm, realm)) /* not what we asked for */ ! 275: return(INTK_ERR); /* we need a better code here XXX */ ! 276: ! 277: /* check KDC time stamp */ ! 278: bcopy(ptr,(char *)&kdc_time,4); /* Time (coarse) */ ! 279: if (swap_bytes) swap_u_long(kdc_time); ! 280: ! 281: ptr += 4; ! 282: ! 283: (void) gettimeofday(&t_local,(struct timezone *) 0); ! 284: if (abs((int)(t_local.tv_sec - kdc_time)) > CLOCK_SKEW) { ! 285: return(RD_AP_TIME); /* XXX should probably be better ! 286: code */ ! 287: } ! 288: ! 289: /* initialize ticket cache */ ! 290: if (in_tkt(user,instance) != KSUCCESS) ! 291: return(INTK_ERR); ! 292: ! 293: /* stash ticket, session key, etc. for future use */ ! 294: if (kerror = save_credentials(s_name, s_instance, rlm, ses, ! 295: lifetime, kvno, tkt, t_local.tv_sec)) ! 296: return(kerror); ! 297: ! 298: return(INTK_OK); ! 299: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.