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