2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * Revision 2.3 90/08/31 16:19:53
14 * Revision 2.2 90/08/20 10:21:25
15 * Include permit_xprt.h.
16 * Cleanup; prune log, flush andrew style ticket functions.
18 * Revision 2.1 90/08/07 19:33:44
19 * Start with clean version to sync test and dev trees.
23 #include "../afs/param.h"
24 #include "../afs/sysincludes.h"
25 #include "../afs/afsincludes.h"
26 #include "../afs/stds.h"
27 #include "../rx/xdr.h"
29 #include "../des/des.h"
30 #include "../afs/lifetimes.h"
31 #include "../afs/rxkad.h"
33 #include "../afs/permit_xprt.h"
34 #else /* defined(UKERNEL) */
35 #include <afs/param.h>
37 #include <sys/types.h>
41 #include <netinet/in.h>
46 #include "lifetimes.h"
49 #include "../permit_xprt.h"
50 #endif /* defined(UKERNEL) */
53 extern afs_int32 ktohl();
54 extern afs_uint32 life_to_time();
55 extern unsigned char time_to_life();
57 static int decode_athena_ticket();
58 static int assemble_athena_ticket();
60 #define ANDREWFLAGSVALUE (0x80)
61 #define TICKET_LABEL "TicketEnd"
63 /* This is called to interpret a ticket. It is assumed that the necessary keys
64 have been added so that the key version number in the ticket will indicate a
65 valid key for decrypting the ticket. The various fields inside the ticket
66 are copied into the return arguments. An error code indicate some problem
67 interpreting the ticket and the values of the output parameters are
70 int tkt_DecodeTicket (asecret, ticketLen, key,
71 name, inst, cell, sessionKey, host, start, end)
74 struct ktc_encryptionKey *key;
82 { char clear_ticket[MAXKTCTICKETLEN];
84 Key_schedule schedule;
85 /* unsigned char flags; */
88 if (ticketLen == 0) return RXKADBADTICKET; /* no ticket */
89 if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */
90 ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */
91 return RXKADBADTICKET;
93 if (key_sched (key, schedule)) return RXKADBADKEY;
95 ticket = clear_ticket;
96 pcbc_encrypt (asecret, ticket, ticketLen, schedule, key, DECRYPT);
98 /* flags = *ticket; */ /* get the first byte: the flags */
100 if (flags == ANDREWFLAGSVALUE) {
101 code = decode_andrew_ticket (ticket, ticketLen, name, inst, cell,
102 host, sessionKey, start, end);
104 code = decode_athena_ticket (ticket, ticketLen, name, inst, cell,
105 host, sessionKey, start, end);
110 code = decode_athena_ticket (ticket, ticketLen, name, inst, cell,
111 host, sessionKey, start, end);
113 code = decode_andrew_ticket (ticket, ticketLen, name, inst, cell,
114 host, sessionKey, start, end);
115 flags = ANDREWFLAGSVALUE;
119 code = decode_athena_ticket
120 (ticket, ticketLen, name, inst, cell, host, sessionKey, start, end);
124 if (code) return RXKADBADTICKET;
125 if (tkt_CheckTimes (*start, *end, time(0)) < -1) return RXKADBADTICKET;
130 /* This makes a Kerberos ticket */
132 int tkt_MakeTicket (ticket, ticketLen, key, name, inst, cell,
133 start, end, sessionKey, host, sname, sinst)
134 char *ticket; /* ticket is constructed here */
135 int *ticketLen; /* output length of finished ticket */
136 struct ktc_encryptionKey *key; /* key ticket should be sealed with */
137 char *name; /* user of this ticket */
139 char *cell; /* cell of authentication */
140 afs_uint32 start,end; /* life of ticket */
141 struct ktc_encryptionKey *sessionKey; /* session key invented for ticket */
142 afs_uint32 host; /* caller's host address */
143 char *sname; /* server */
146 Key_schedule schedule;
148 *ticketLen = 0; /* in case we return early */
149 code = assemble_athena_ticket (ticket, ticketLen, name, inst, cell,
150 host, sessionKey, start, end, sname, sinst);
151 *ticketLen = round_up_to_ebs(*ticketLen); /* round up */
155 if (code = key_sched (key, schedule)) {
156 printf ("In tkt_MakeTicket: key_sched returned %d\n", code);
159 pcbc_encrypt (ticket, ticket, *ticketLen, schedule, key, ENCRYPT);
163 #define getstr(name,min) \
164 slen = strlen(ticket); \
165 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
166 strcpy (name, ticket); \
169 static int decode_athena_ticket (ticket, ticketLen, name, inst, realm,
170 host, sessionKey, start, end)
177 struct ktc_encryptionKey *sessionKey;
180 { char *ticketBeg = ticket;
184 unsigned char lifetime;
185 char sname[MAXKTCNAMELEN]; /* these aren't used, */
186 char sinst[MAXKTCNAMELEN]; /* but are in the ticket */
193 bcopy (ticket, host, sizeof (*host));
194 ticket += sizeof(*host);
195 *host = ktohl (flags, *host);
197 bcopy (ticket, sessionKey, sizeof (struct ktc_encryptionKey));
198 ticket += sizeof (struct ktc_encryptionKey);
200 lifetime = *ticket++;
201 bcopy (ticket, start, sizeof (*start));
202 ticket += sizeof(*start);
203 *start = ktohl (flags, *start);
204 *end = life_to_time (*start, lifetime);
209 tlen = ticket - ticketBeg;
210 if ((round_up_to_ebs(tlen) != ticketLen) && (ticketLen != 56)) return -1;
214 #define putstr(name,min) \
215 slen = strlen(name); \
216 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
217 strcpy (ticket, name); \
219 #define putint(num) num = htonl(num);\
220 bcopy (&num, ticket, sizeof(num));\
221 ticket += sizeof(num)
223 static int assemble_athena_ticket (ticket, ticketLen, name, inst, realm,
224 host, sessionKey, start, end, sname, sinst)
231 struct ktc_encryptionKey *sessionKey;
236 { char *ticketBeg = ticket;
240 *ticket++ = 0; /* flags, always send net-byte-order */
246 bcopy (sessionKey, ticket, sizeof(struct ktc_encryptionKey));
247 ticket += sizeof(struct ktc_encryptionKey);
249 life = time_to_life (start, end);
250 if (life == 0) return -1;
257 *ticketLen = ticket - ticketBeg;
261 /* This is just a routine that checks the consistency of ticket lifetimes. It
262 returns three values: */
263 /* -2 means the times are inconsistent or ticket has expired
264 -1 means the ticket has recently expired.
265 0 means the times are consistent but start time is in the (near) future.
266 1 means the start time is in the past and the end time is infinity.
267 2 means the start time is past and the end time is in the future
268 and the lifetime is within the legal limit.
271 int tkt_CheckTimes (start, end, now)
277 if (start >= end) return -2; /* zero or negative lifetime */
278 if (start > now+KTC_TIME_UNCERTAINTY+MAXKTCTICKETLIFETIME)
279 return -2; /* starts too far in the future? */
280 if ((start != 0) && (end != NEVERDATE) &&
281 (end-start > MAXKTCTICKETLIFETIME)) return -2; /* too long a life */
282 if ((end != NEVERDATE) && (end+KTC_TIME_UNCERTAINTY < now)) { /* expired */
283 if ((start != 0) && (now - start > MAXKTCTICKETLIFETIME + 24*60*60))
285 else return -1; /* expired only recently */
287 if ((start == 0) || (start-KTC_TIME_UNCERTAINTY <= now)) active = 1;
288 else active = 0; /* start time not yet arrived */
290 if ((start == 0) || (end == NEVERDATE))
291 return active; /* no expiration time */
292 return active*2; /* ticket valid */
295 afs_int32 ktohl (flags, l)
300 unsigned char *lp = (unsigned char *)&l;
302 hl = *lp + (*(lp+1) << 8) + (*(lp+2) << 16) + (*(lp+3) << 24);
308 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
309 * returns the corresponding end time. There are four simple cases to be
310 * handled. The first is a life of 0xff, meaning no expiration, and results in
311 * an end time of 0xffffffff. The second is when life is less than the values
312 * covered by the table. In this case, the end time is the start time plus the
313 * number of 5 minute intervals specified by life. The third case returns
314 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
315 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
316 * table to extract the lifetime in seconds, which is added to start to produce
319 afs_uint32 life_to_time (start, life)
324 if (life == TKTLIFENOEXPIRE) return NEVERDATE;
325 if (life < TKTLIFEMINFIXED) return start + life*5*60;
326 if (life > TKTLIFEMAXFIXED) return start + MAXTKTLIFETIME;
327 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
328 return start + realLife;
331 /* time_to_life - takes start and end times for the ticket and returns a
332 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
333 * lifetimes above 127*5minutes. First, the special case of (end ==
334 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
335 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
336 * less than the first table entry are handled by rounding the requested
337 * lifetime *up* to the next 5 minute interval. The final step is to search
338 * the table for the smallest entry *greater than or equal* to the requested
339 * entry. The actual code is prepared to handle the case where the table is
340 * unordered but that it an unnecessary frill. */
342 unsigned char time_to_life (start, end)
345 { int lifetime = end-start;
349 if (end == NEVERDATE) return TKTLIFENOEXPIRE;
350 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0)) return 0;
351 if (lifetime < tkt_lifetimes[0]) return (lifetime + 5*60-1) / (5*60);
353 best = MAXKTCTICKETLIFETIME;
354 for (i=0; i<TKTLIFENUMFIXED; i++)
355 if (tkt_lifetimes[i] >= lifetime) {
356 int diff = tkt_lifetimes[i]-lifetime;
361 if (best_i < 0) return 0;
362 return best_i+TKTLIFEMINFIXED;