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
10 #include <afsconfig.h>
12 #include "afs/param.h"
14 #include <afs/param.h>
20 #include "afs/sysincludes.h"
21 #include "afsincludes.h"
26 #include "rxkad/lifetimes.h"
28 #else /* defined(UKERNEL) */
30 #include <sys/types.h>
34 #include <netinet/in.h>
46 #include "lifetimes.h"
48 #endif /* defined(UKERNEL) */
50 /* static prototypes */
51 static int decode_athena_ticket (char *ticket, int ticketLen, char *name,
52 char *inst, char *realm, afs_int32 *host, struct ktc_encryptionKey *sessionKey,
53 afs_uint32 *start, afs_uint32 *end);
54 static int assemble_athena_ticket (char *ticket, int *ticketLen, char *name,
55 char *inst, char *realm, afs_int32 host, struct ktc_encryptionKey *sessionKey,
56 afs_uint32 start, afs_uint32 end, char *sname, char *sinst);
58 #define ANDREWFLAGSVALUE (0x80)
59 #define TICKET_LABEL "TicketEnd"
61 /* This is called to interpret a ticket. It is assumed that the necessary keys
62 have been added so that the key version number in the ticket will indicate a
63 valid key for decrypting the ticket. The various fields inside the ticket
64 are copied into the return arguments. An error code indicate some problem
65 interpreting the ticket and the values of the output parameters are
68 int tkt_DecodeTicket (char *asecret, afs_int32 ticketLen,
69 struct ktc_encryptionKey *key, char *name, char *inst, char *cell,
70 char *sessionKey, afs_int32 *host, afs_int32 *start, afs_int32 *end)
71 { char clear_ticket[MAXKTCTICKETLEN];
73 Key_schedule schedule;
74 /* unsigned char flags; */
77 if (ticketLen == 0) return RXKADBADTICKET; /* no ticket */
78 if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */
79 ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */
80 return RXKADBADTICKET;
82 if (key_sched (key, schedule)) return RXKADBADKEY;
84 ticket = clear_ticket;
85 pcbc_encrypt (asecret, ticket, ticketLen, schedule, key, DECRYPT);
87 /* flags = *ticket; */ /* get the first byte: the flags */
89 if (flags == ANDREWFLAGSVALUE) {
90 code = decode_andrew_ticket (ticket, ticketLen, name, inst, cell,
91 host, sessionKey, start, end);
93 code = decode_athena_ticket (ticket, ticketLen, name, inst, cell,
94 host, sessionKey, start, end);
99 code = decode_athena_ticket (ticket, ticketLen, name, inst, cell,
100 host, sessionKey, start, end);
102 code = decode_andrew_ticket (ticket, ticketLen, name, inst, cell,
103 host, sessionKey, start, end);
104 flags = ANDREWFLAGSVALUE;
108 code = decode_athena_ticket
109 (ticket, ticketLen, name, inst, cell, host, sessionKey, start, end);
113 if (code) return RXKADBADTICKET;
114 if (tkt_CheckTimes (*start, *end, time(0)) < -1) return RXKADBADTICKET;
119 /* This makes a Kerberos ticket */
121 char *ticket; * ticket is constructed here *
122 int *ticketLen; * output length of finished ticket *
123 struct ktc_encryptionKey *key; * key ticket should be sealed with *
124 char *name; * user of this ticket *
126 char *cell; * cell of authentication *
127 afs_uint32 start,end; * life of ticket *
128 struct ktc_encryptionKey *sessionKey; * session key invented for ticket *
129 afs_uint32 host; * caller's host address *
130 char *sname; * server *
134 int tkt_MakeTicket (char *ticket, int *ticketLen,
135 struct ktc_encryptionKey *key, char *name, char *inst, char *cell,
136 afs_uint32 start, afs_uint32 end, struct ktc_encryptionKey *sessionKey,
137 afs_uint32 host, char *sname, char *sinst)
139 Key_schedule schedule;
141 *ticketLen = 0; /* in case we return early */
142 code = assemble_athena_ticket (ticket, ticketLen, name, inst, cell,
143 host, sessionKey, start, end, sname, sinst);
144 *ticketLen = round_up_to_ebs(*ticketLen); /* round up */
148 if ((code = key_sched (key, schedule))) {
149 printf ("In tkt_MakeTicket: key_sched returned %d\n", code);
152 pcbc_encrypt (ticket, ticket, *ticketLen, schedule, key, ENCRYPT);
156 #define getstr(name,min) \
157 slen = strlen(ticket); \
158 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
159 strcpy (name, ticket); \
162 static int decode_athena_ticket (char *ticket, int ticketLen, char *name,
163 char *inst, char *realm, afs_int32 *host, struct ktc_encryptionKey *sessionKey,
164 afs_uint32 *start, afs_uint32 *end)
165 { char *ticketBeg = ticket;
169 unsigned char lifetime;
170 char sname[MAXKTCNAMELEN]; /* these aren't used, */
171 char sinst[MAXKTCNAMELEN]; /* but are in the ticket */
178 memcpy(host, ticket, sizeof (*host));
179 ticket += sizeof(*host);
180 *host = ktohl (flags, *host);
182 memcpy(sessionKey, ticket, sizeof (struct ktc_encryptionKey));
183 ticket += sizeof (struct ktc_encryptionKey);
185 lifetime = *ticket++;
186 memcpy(start, ticket, sizeof (*start));
187 ticket += sizeof(*start);
188 *start = ktohl (flags, *start);
189 *end = life_to_time (*start, lifetime);
194 tlen = ticket - ticketBeg;
195 if ((round_up_to_ebs(tlen) != ticketLen) && (ticketLen != 56)) return -1;
199 #define putstr(name,min) \
200 slen = strlen(name); \
201 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
202 strcpy (ticket, name); \
204 #define putint(num) num = htonl(num);\
205 memcpy(ticket, &num, sizeof(num));\
206 ticket += sizeof(num)
208 static int assemble_athena_ticket (char *ticket, int *ticketLen, char *name,
209 char *inst, char *realm, afs_int32 host, struct ktc_encryptionKey *sessionKey,
210 afs_uint32 start, afs_uint32 end, char *sname, char *sinst)
211 { char *ticketBeg = ticket;
215 *ticket++ = 0; /* flags, always send net-byte-order */
221 memcpy(ticket, sessionKey, sizeof(struct ktc_encryptionKey));
222 ticket += sizeof(struct ktc_encryptionKey);
224 life = time_to_life (start, end);
225 if (life == 0) return -1;
232 *ticketLen = ticket - ticketBeg;
236 /* This is just a routine that checks the consistency of ticket lifetimes. It
237 returns three values: */
238 /* -2 means the times are inconsistent or ticket has expired
239 -1 means the ticket has recently expired.
240 0 means the times are consistent but start time is in the (near) future.
241 1 means the start time is in the past and the end time is infinity.
242 2 means the start time is past and the end time is in the future
243 and the lifetime is within the legal limit.
246 int tkt_CheckTimes (afs_uint32 start, afs_uint32 end, afs_uint32 now)
249 if (start >= end) return -2; /* zero or negative lifetime */
250 if (start > now+KTC_TIME_UNCERTAINTY+MAXKTCTICKETLIFETIME)
251 return -2; /* starts too far in the future? */
252 if ((start != 0) && (end != NEVERDATE) &&
253 (end-start > MAXKTCTICKETLIFETIME)) return -2; /* too long a life */
254 if ((end != NEVERDATE) && (end+KTC_TIME_UNCERTAINTY < now)) { /* expired */
255 if ((start != 0) && (now - start > MAXKTCTICKETLIFETIME + 24*60*60))
257 else return -1; /* expired only recently */
259 if ((start == 0) || (start-KTC_TIME_UNCERTAINTY <= now)) active = 1;
260 else active = 0; /* start time not yet arrived */
262 if ((start == 0) || (end == NEVERDATE))
263 return active; /* no expiration time */
264 return active*2; /* ticket valid */
267 afs_int32 ktohl (char flags, afs_int32 l)
270 unsigned char *lp = (unsigned char *)&l;
272 hl = *lp + (*(lp+1) << 8) + (*(lp+2) << 16) + (*(lp+3) << 24);
278 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
279 * returns the corresponding end time. There are four simple cases to be
280 * handled. The first is a life of 0xff, meaning no expiration, and results in
281 * an end time of 0xffffffff. The second is when life is less than the values
282 * covered by the table. In this case, the end time is the start time plus the
283 * number of 5 minute intervals specified by life. The third case returns
284 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
285 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
286 * table to extract the lifetime in seconds, which is added to start to produce
289 afs_uint32 life_to_time (afs_uint32 start, unsigned char life)
292 if (life == TKTLIFENOEXPIRE) return NEVERDATE;
293 if (life < TKTLIFEMINFIXED) return start + life*5*60;
294 if (life > TKTLIFEMAXFIXED) return start + MAXTKTLIFETIME;
295 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
296 return start + realLife;
299 /* time_to_life - takes start and end times for the ticket and returns a
300 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
301 * lifetimes above 127*5minutes. First, the special case of (end ==
302 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
303 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
304 * less than the first table entry are handled by rounding the requested
305 * lifetime *up* to the next 5 minute interval. The final step is to search
306 * the table for the smallest entry *greater than or equal* to the requested
307 * entry. The actual code is prepared to handle the case where the table is
308 * unordered but that it an unnecessary frill. */
310 unsigned char time_to_life (afs_uint32 start, afs_uint32 end)
311 { int lifetime = end-start;
315 if (end == NEVERDATE) return TKTLIFENOEXPIRE;
316 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0)) return 0;
317 if (lifetime < tkt_lifetimes[0]) return (lifetime + 5*60-1) / (5*60);
319 best = MAXKTCTICKETLIFETIME;
320 for (i=0; i<TKTLIFENUMFIXED; i++)
321 if (tkt_lifetimes[i] >= lifetime) {
322 int diff = tkt_lifetimes[i]-lifetime;
327 if (best_i < 0) return 0;
328 return best_i+TKTLIFEMINFIXED;