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>
11 #include <afs/param.h>
16 #include <sys/types.h>
20 #include <netinet/in.h>
24 #include <des_prototypes.h>
27 #include "lifetimes.h"
30 /* This union is used to insure we allocate enough space for a key
31 * schedule even if we are linked against a library that uses OpenSSL's
32 * larger representation. This is necessary so we don't lose if an
33 * application uses both rxkad and openssl.
35 union Key_schedule_safe {
36 Key_schedule schedule;
43 } openssl_schedule[16];
46 #define getstr(name,min) \
47 slen = strlen(ticket); \
48 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
49 strcpy (name, ticket); \
53 decode_athena_ticket(char *ticket, int ticketLen, char *name, char *inst,
54 char *realm, afs_int32 * host,
55 struct ktc_encryptionKey *sessionKey, afs_uint32 * start,
58 char *ticketBeg = ticket;
62 unsigned char lifetime;
63 char sname[MAXKTCNAMELEN]; /* these aren't used, */
64 char sinst[MAXKTCNAMELEN]; /* but are in the ticket */
71 memcpy(host, ticket, sizeof(*host));
72 ticket += sizeof(*host);
73 *host = ktohl(flags, *host);
75 memcpy(sessionKey, ticket, sizeof(struct ktc_encryptionKey));
76 ticket += sizeof(struct ktc_encryptionKey);
79 memcpy(start, ticket, sizeof(*start));
80 ticket += sizeof(*start);
81 *start = ktohl(flags, *start);
82 *end = life_to_time(*start, lifetime);
87 tlen = ticket - ticketBeg;
88 if ((round_up_to_ebs(tlen) != ticketLen) && (ticketLen != 56))
93 /* This is called to interpret a ticket. It is assumed that the necessary keys
94 have been added so that the key version number in the ticket will indicate a
95 valid key for decrypting the ticket. The various fields inside the ticket
96 are copied into the return arguments. An error code indicate some problem
97 interpreting the ticket and the values of the output parameters are
101 tkt_DecodeTicket(char *asecret, afs_int32 ticketLen,
102 struct ktc_encryptionKey *key, char *name, char *inst,
103 char *cell, struct ktc_encryptionKey *sessionKey, afs_int32 * host,
104 afs_uint32 * start, afs_uint32 * end)
106 char clear_ticket[MAXKTCTICKETLEN];
108 union Key_schedule_safe schedule;
112 return RXKADBADTICKET; /* no ticket */
113 if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */
114 (ticketLen > MAXKTCTICKETLEN) || /* maximum legal ticket size */
115 ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */
116 return RXKADBADTICKET;
118 if (key_sched(ktc_to_cblock(key), schedule.schedule))
121 ticket = clear_ticket;
122 pcbc_encrypt(asecret, ticket, ticketLen, schedule.schedule, ktc_to_cblockptr(key), DECRYPT);
125 decode_athena_ticket(ticket, ticketLen, name, inst, cell, host,
126 (struct ktc_encryptionKey *)sessionKey, start, end);
129 return RXKADBADTICKET;
131 code = tkt_CheckTimes(*start, *end, time(0));
137 return RXKADBADTICKET;
142 /* This makes a Kerberos ticket */
144 char *ticket; * ticket is constructed here *
145 int *ticketLen; * output length of finished ticket *
146 struct ktc_encryptionKey *key; * key ticket should be sealed with *
147 char *name; * user of this ticket *
149 char *cell; * cell of authentication *
150 afs_uint32 start,end; * life of ticket *
151 struct ktc_encryptionKey *sessionKey; * session key invented for ticket *
152 afs_uint32 host; * caller's host address *
153 char *sname; * server *
157 #define putstr(name,min) \
158 slen = strlen(name); \
159 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
160 strcpy (ticket, name); \
162 #define putint(num) num = htonl(num);\
163 memcpy(ticket, &num, sizeof(num));\
164 ticket += sizeof(num)
167 assemble_athena_ticket(char *ticket, int *ticketLen, char *name, char *inst,
168 char *realm, afs_int32 host,
169 struct ktc_encryptionKey *sessionKey, afs_uint32 start,
170 afs_uint32 end, char *sname, char *sinst)
172 char *ticketBeg = ticket;
176 *ticket++ = 0; /* flags, always send net-byte-order */
182 memcpy(ticket, sessionKey, sizeof(struct ktc_encryptionKey));
183 ticket += sizeof(struct ktc_encryptionKey);
185 life = time_to_life(start, end);
194 *ticketLen = ticket - ticketBeg;
199 tkt_MakeTicket(char *ticket, int *ticketLen, struct ktc_encryptionKey *key,
200 char *name, char *inst, char *cell, afs_uint32 start,
201 afs_uint32 end, struct ktc_encryptionKey *sessionKey,
202 afs_uint32 host, char *sname, char *sinst)
205 union Key_schedule_safe schedule;
207 *ticketLen = 0; /* in case we return early */
209 assemble_athena_ticket(ticket, ticketLen, name, inst, cell, host,
210 sessionKey, start, end, sname, sinst);
211 *ticketLen = round_up_to_ebs(*ticketLen); /* round up */
216 if ((code = key_sched(ktc_to_cblock(key), schedule.schedule))) {
217 printf("In tkt_MakeTicket: key_sched returned %d\n", code);
220 pcbc_encrypt(ticket, ticket, *ticketLen, schedule.schedule, ktc_to_cblockptr(key), ENCRYPT);
224 /* This is just a routine that checks the consistency of ticket lifetimes. It
225 returns three values: */
226 /* -2 means the times are inconsistent or ticket has expired
227 -1 means the ticket has recently expired.
228 0 means the times are consistent but start time is in the (near) future.
229 1 means the start time is in the past and the end time is infinity.
230 2 means the start time is past and the end time is in the future
231 and the lifetime is within the legal limit.
235 tkt_CheckTimes(afs_uint32 start, afs_uint32 end, afs_uint32 now)
240 return -2; /* zero or negative lifetime */
241 if (start > now + KTC_TIME_UNCERTAINTY + MAXKTCTICKETLIFETIME)
242 return -2; /* starts too far in the future? */
243 if ((start != 0) && (end != NEVERDATE)
244 && (end - start > MAXKTCTICKETLIFETIME))
245 return -2; /* too long a life */
246 if ((end != NEVERDATE) && (end + KTC_TIME_UNCERTAINTY < now)) { /* expired */
248 && (now - start > MAXKTCTICKETLIFETIME + 24 * 60 * 60))
251 return -1; /* expired only recently */
253 if ((start == 0) || (start - KTC_TIME_UNCERTAINTY <= now))
256 active = 0; /* start time not yet arrived */
258 if ((start == 0) || (end == NEVERDATE))
259 return active; /* no expiration time */
260 return active * 2; /* ticket valid */
264 ktohl(char flags, afs_int32 l)
267 unsigned char *lp = (unsigned char *)&l;
269 hl = *lp + (*(lp + 1) << 8) + (*(lp + 2) << 16) + (*(lp + 3) << 24);
275 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
276 * returns the corresponding end time. There are four simple cases to be
277 * handled. The first is a life of 0xff, meaning no expiration, and results in
278 * an end time of 0xffffffff. The second is when life is less than the values
279 * covered by the table. In this case, the end time is the start time plus the
280 * number of 5 minute intervals specified by life. The third case returns
281 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
282 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
283 * table to extract the lifetime in seconds, which is added to start to produce
287 life_to_time(afs_uint32 start, unsigned char life)
291 if (life == TKTLIFENOEXPIRE)
293 if (life < TKTLIFEMINFIXED)
294 return start + life * 5 * 60;
295 if (life > TKTLIFEMAXFIXED)
296 return start + MAXTKTLIFETIME;
297 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
298 return start + realLife;
301 /* time_to_life - takes start and end times for the ticket and returns a
302 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
303 * lifetimes above 127*5minutes. First, the special case of (end ==
304 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
305 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
306 * less than the first table entry are handled by rounding the requested
307 * lifetime *up* to the next 5 minute interval. The final step is to search
308 * the table for the smallest entry *greater than or equal* to the requested
309 * entry. The actual code is prepared to handle the case where the table is
310 * unordered but that it an unnecessary frill. */
313 time_to_life(afs_uint32 start, afs_uint32 end)
315 int lifetime = end - start;
319 if (end == NEVERDATE)
320 return TKTLIFENOEXPIRE;
321 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
323 if (lifetime < tkt_lifetimes[0])
324 return (lifetime + 5 * 60 - 1) / (5 * 60);
326 best = MAXKTCTICKETLIFETIME;
327 for (i = 0; i < TKTLIFENUMFIXED; i++)
328 if (tkt_lifetimes[i] >= lifetime) {
329 int diff = tkt_lifetimes[i] - lifetime;
337 return best_i + TKTLIFEMINFIXED;