|
|
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.