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>
19 #include "afs/sysincludes.h"
20 #include "afsincludes.h"
25 #include "rxkad/lifetimes.h"
27 #else /* defined(UKERNEL) */
29 #include <sys/types.h>
33 #include <netinet/in.h>
39 #include "lifetimes.h"
41 #endif /* defined(UKERNEL) */
43 /* This union is used to insure we allocate enough space for a key
44 * schedule even if we are linked against a library that uses OpenSSL's
45 * larger representation. This is necessary so we don't lose if an
46 * application uses both rxkad and openssl.
48 union Key_schedule_safe {
49 Key_schedule schedule;
56 } openssl_schedule[16];
59 #define getstr(name,min) \
60 slen = strlen(ticket); \
61 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
62 strcpy (name, ticket); \
66 decode_athena_ticket(char *ticket, int ticketLen, char *name, char *inst,
67 char *realm, afs_int32 * host,
68 struct ktc_encryptionKey *sessionKey, afs_uint32 * start,
71 char *ticketBeg = ticket;
75 unsigned char lifetime;
76 char sname[MAXKTCNAMELEN]; /* these aren't used, */
77 char sinst[MAXKTCNAMELEN]; /* but are in the ticket */
84 memcpy(host, ticket, sizeof(*host));
85 ticket += sizeof(*host);
86 *host = ktohl(flags, *host);
88 memcpy(sessionKey, ticket, sizeof(struct ktc_encryptionKey));
89 ticket += sizeof(struct ktc_encryptionKey);
92 memcpy(start, ticket, sizeof(*start));
93 ticket += sizeof(*start);
94 *start = ktohl(flags, *start);
95 *end = life_to_time(*start, lifetime);
100 tlen = ticket - ticketBeg;
101 if ((round_up_to_ebs(tlen) != ticketLen) && (ticketLen != 56))
106 /* This is called to interpret a ticket. It is assumed that the necessary keys
107 have been added so that the key version number in the ticket will indicate a
108 valid key for decrypting the ticket. The various fields inside the ticket
109 are copied into the return arguments. An error code indicate some problem
110 interpreting the ticket and the values of the output parameters are
114 tkt_DecodeTicket(char *asecret, afs_int32 ticketLen,
115 struct ktc_encryptionKey *key, char *name, char *inst,
116 char *cell, char *sessionKey, afs_int32 * host,
117 afs_int32 * start, afs_int32 * end)
119 char clear_ticket[MAXKTCTICKETLEN];
121 union Key_schedule_safe schedule;
125 return RXKADBADTICKET; /* no ticket */
126 if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */
127 (ticketLen > MAXKTCTICKETLEN) || /* maximum legal ticket size */
128 ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */
129 return RXKADBADTICKET;
131 if (key_sched(key, schedule.schedule))
134 ticket = clear_ticket;
135 pcbc_encrypt(asecret, ticket, ticketLen, schedule.schedule, key, DECRYPT);
138 decode_athena_ticket(ticket, ticketLen, name, inst, cell, host,
139 sessionKey, start, end);
142 return RXKADBADTICKET;
144 code = tkt_CheckTimes(*start, *end, time(0));
150 return RXKADBADTICKET;
155 /* This makes a Kerberos ticket */
157 char *ticket; * ticket is constructed here *
158 int *ticketLen; * output length of finished ticket *
159 struct ktc_encryptionKey *key; * key ticket should be sealed with *
160 char *name; * user of this ticket *
162 char *cell; * cell of authentication *
163 afs_uint32 start,end; * life of ticket *
164 struct ktc_encryptionKey *sessionKey; * session key invented for ticket *
165 afs_uint32 host; * caller's host address *
166 char *sname; * server *
170 #define putstr(name,min) \
171 slen = strlen(name); \
172 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
173 strcpy (ticket, name); \
175 #define putint(num) num = htonl(num);\
176 memcpy(ticket, &num, sizeof(num));\
177 ticket += sizeof(num)
180 assemble_athena_ticket(char *ticket, int *ticketLen, char *name, char *inst,
181 char *realm, afs_int32 host,
182 struct ktc_encryptionKey *sessionKey, afs_uint32 start,
183 afs_uint32 end, char *sname, char *sinst)
185 char *ticketBeg = ticket;
189 *ticket++ = 0; /* flags, always send net-byte-order */
195 memcpy(ticket, sessionKey, sizeof(struct ktc_encryptionKey));
196 ticket += sizeof(struct ktc_encryptionKey);
198 life = time_to_life(start, end);
207 *ticketLen = ticket - ticketBeg;
212 tkt_MakeTicket(char *ticket, int *ticketLen, struct ktc_encryptionKey *key,
213 char *name, char *inst, char *cell, afs_uint32 start,
214 afs_uint32 end, struct ktc_encryptionKey *sessionKey,
215 afs_uint32 host, char *sname, char *sinst)
218 union Key_schedule_safe schedule;
220 *ticketLen = 0; /* in case we return early */
222 assemble_athena_ticket(ticket, ticketLen, name, inst, cell, host,
223 sessionKey, start, end, sname, sinst);
224 *ticketLen = round_up_to_ebs(*ticketLen); /* round up */
229 if ((code = key_sched(key, schedule.schedule))) {
230 printf("In tkt_MakeTicket: key_sched returned %d\n", code);
233 pcbc_encrypt(ticket, ticket, *ticketLen, schedule.schedule, key, ENCRYPT);
237 /* This is just a routine that checks the consistency of ticket lifetimes. It
238 returns three values: */
239 /* -2 means the times are inconsistent or ticket has expired
240 -1 means the ticket has recently expired.
241 0 means the times are consistent but start time is in the (near) future.
242 1 means the start time is in the past and the end time is infinity.
243 2 means the start time is past and the end time is in the future
244 and the lifetime is within the legal limit.
248 tkt_CheckTimes(afs_uint32 start, afs_uint32 end, afs_uint32 now)
253 return -2; /* zero or negative lifetime */
254 if (start > now + KTC_TIME_UNCERTAINTY + MAXKTCTICKETLIFETIME)
255 return -2; /* starts too far in the future? */
256 if ((start != 0) && (end != NEVERDATE)
257 && (end - start > MAXKTCTICKETLIFETIME))
258 return -2; /* too long a life */
259 if ((end != NEVERDATE) && (end + KTC_TIME_UNCERTAINTY < now)) { /* expired */
261 && (now - start > MAXKTCTICKETLIFETIME + 24 * 60 * 60))
264 return -1; /* expired only recently */
266 if ((start == 0) || (start - KTC_TIME_UNCERTAINTY <= now))
269 active = 0; /* start time not yet arrived */
271 if ((start == 0) || (end == NEVERDATE))
272 return active; /* no expiration time */
273 return active * 2; /* ticket valid */
277 ktohl(char flags, afs_int32 l)
280 unsigned char *lp = (unsigned char *)&l;
282 hl = *lp + (*(lp + 1) << 8) + (*(lp + 2) << 16) + (*(lp + 3) << 24);
288 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
289 * returns the corresponding end time. There are four simple cases to be
290 * handled. The first is a life of 0xff, meaning no expiration, and results in
291 * an end time of 0xffffffff. The second is when life is less than the values
292 * covered by the table. In this case, the end time is the start time plus the
293 * number of 5 minute intervals specified by life. The third case returns
294 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
295 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
296 * table to extract the lifetime in seconds, which is added to start to produce
300 life_to_time(afs_uint32 start, unsigned char life)
304 if (life == TKTLIFENOEXPIRE)
306 if (life < TKTLIFEMINFIXED)
307 return start + life * 5 * 60;
308 if (life > TKTLIFEMAXFIXED)
309 return start + MAXTKTLIFETIME;
310 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
311 return start + realLife;
314 /* time_to_life - takes start and end times for the ticket and returns a
315 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
316 * lifetimes above 127*5minutes. First, the special case of (end ==
317 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
318 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
319 * less than the first table entry are handled by rounding the requested
320 * lifetime *up* to the next 5 minute interval. The final step is to search
321 * the table for the smallest entry *greater than or equal* to the requested
322 * entry. The actual code is prepared to handle the case where the table is
323 * unordered but that it an unnecessary frill. */
326 time_to_life(afs_uint32 start, afs_uint32 end)
328 int lifetime = end - start;
332 if (end == NEVERDATE)
333 return TKTLIFENOEXPIRE;
334 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
336 if (lifetime < tkt_lifetimes[0])
337 return (lifetime + 5 * 60 - 1) / (5 * 60);
339 best = MAXKTCTICKETLIFETIME;
340 for (i = 0; i < TKTLIFENUMFIXED; i++)
341 if (tkt_lifetimes[i] >= lifetime) {
342 int diff = tkt_lifetimes[i] - lifetime;
350 return best_i + TKTLIFEMINFIXED;