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>
21 #include "afs/sysincludes.h"
22 #include "afsincludes.h"
27 #include "rxkad/lifetimes.h"
29 #else /* defined(UKERNEL) */
31 #include <sys/types.h>
35 #include <netinet/in.h>
41 #include "lifetimes.h"
43 #endif /* defined(UKERNEL) */
45 /* This union is used to insure we allocate enough space for a key
46 * schedule even if we are linked against a library that uses OpenSSL's
47 * larger representation. This is necessary so we don't lose if an
48 * application uses both rxkad and openssl.
50 union Key_schedule_safe {
51 Key_schedule schedule;
58 } openssl_schedule[16];
61 #define getstr(name,min) \
62 slen = strlen(ticket); \
63 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
64 strcpy (name, ticket); \
68 decode_athena_ticket(char *ticket, int ticketLen, char *name, char *inst,
69 char *realm, afs_int32 * host,
70 struct ktc_encryptionKey *sessionKey, afs_uint32 * start,
73 char *ticketBeg = ticket;
77 unsigned char lifetime;
78 char sname[MAXKTCNAMELEN]; /* these aren't used, */
79 char sinst[MAXKTCNAMELEN]; /* but are in the ticket */
86 memcpy(host, ticket, sizeof(*host));
87 ticket += sizeof(*host);
88 *host = ktohl(flags, *host);
90 memcpy(sessionKey, ticket, sizeof(struct ktc_encryptionKey));
91 ticket += sizeof(struct ktc_encryptionKey);
94 memcpy(start, ticket, sizeof(*start));
95 ticket += sizeof(*start);
96 *start = ktohl(flags, *start);
97 *end = life_to_time(*start, lifetime);
102 tlen = ticket - ticketBeg;
103 if ((round_up_to_ebs(tlen) != ticketLen) && (ticketLen != 56))
108 /* This is called to interpret a ticket. It is assumed that the necessary keys
109 have been added so that the key version number in the ticket will indicate a
110 valid key for decrypting the ticket. The various fields inside the ticket
111 are copied into the return arguments. An error code indicate some problem
112 interpreting the ticket and the values of the output parameters are
116 tkt_DecodeTicket(char *asecret, afs_int32 ticketLen,
117 struct ktc_encryptionKey *key, char *name, char *inst,
118 char *cell, char *sessionKey, afs_int32 * host,
119 afs_int32 * start, afs_int32 * end)
121 char clear_ticket[MAXKTCTICKETLEN];
123 union Key_schedule_safe schedule;
127 return RXKADBADTICKET; /* no ticket */
128 if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */
129 (ticketLen > MAXKTCTICKETLEN) || /* maximum legal ticket size */
130 ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */
131 return RXKADBADTICKET;
133 if (key_sched(key, schedule.schedule))
136 ticket = clear_ticket;
137 pcbc_encrypt(asecret, ticket, ticketLen, schedule.schedule, key, DECRYPT);
140 decode_athena_ticket(ticket, ticketLen, name, inst, cell, host,
141 sessionKey, start, end);
144 return RXKADBADTICKET;
146 code = tkt_CheckTimes(*start, *end, time(0));
152 return RXKADBADTICKET;
157 /* This makes a Kerberos ticket */
159 char *ticket; * ticket is constructed here *
160 int *ticketLen; * output length of finished ticket *
161 struct ktc_encryptionKey *key; * key ticket should be sealed with *
162 char *name; * user of this ticket *
164 char *cell; * cell of authentication *
165 afs_uint32 start,end; * life of ticket *
166 struct ktc_encryptionKey *sessionKey; * session key invented for ticket *
167 afs_uint32 host; * caller's host address *
168 char *sname; * server *
172 #define putstr(name,min) \
173 slen = strlen(name); \
174 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
175 strcpy (ticket, name); \
177 #define putint(num) num = htonl(num);\
178 memcpy(ticket, &num, sizeof(num));\
179 ticket += sizeof(num)
182 assemble_athena_ticket(char *ticket, int *ticketLen, char *name, char *inst,
183 char *realm, afs_int32 host,
184 struct ktc_encryptionKey *sessionKey, afs_uint32 start,
185 afs_uint32 end, char *sname, char *sinst)
187 char *ticketBeg = ticket;
191 *ticket++ = 0; /* flags, always send net-byte-order */
197 memcpy(ticket, sessionKey, sizeof(struct ktc_encryptionKey));
198 ticket += sizeof(struct ktc_encryptionKey);
200 life = time_to_life(start, end);
209 *ticketLen = ticket - ticketBeg;
214 tkt_MakeTicket(char *ticket, int *ticketLen, struct ktc_encryptionKey *key,
215 char *name, char *inst, char *cell, afs_uint32 start,
216 afs_uint32 end, struct ktc_encryptionKey *sessionKey,
217 afs_uint32 host, char *sname, char *sinst)
220 union Key_schedule_safe schedule;
222 *ticketLen = 0; /* in case we return early */
224 assemble_athena_ticket(ticket, ticketLen, name, inst, cell, host,
225 sessionKey, start, end, sname, sinst);
226 *ticketLen = round_up_to_ebs(*ticketLen); /* round up */
231 if (code = key_sched(key, schedule.schedule)) {
232 printf("In tkt_MakeTicket: key_sched returned %d\n", code);
235 pcbc_encrypt(ticket, ticket, *ticketLen, schedule.schedule, key, ENCRYPT);
239 /* This is just a routine that checks the consistency of ticket lifetimes. It
240 returns three values: */
241 /* -2 means the times are inconsistent or ticket has expired
242 -1 means the ticket has recently expired.
243 0 means the times are consistent but start time is in the (near) future.
244 1 means the start time is in the past and the end time is infinity.
245 2 means the start time is past and the end time is in the future
246 and the lifetime is within the legal limit.
250 tkt_CheckTimes(afs_uint32 start, afs_uint32 end, afs_uint32 now)
255 return -2; /* zero or negative lifetime */
256 if (start > now + KTC_TIME_UNCERTAINTY + MAXKTCTICKETLIFETIME)
257 return -2; /* starts too far in the future? */
258 if ((start != 0) && (end != NEVERDATE)
259 && (end - start > MAXKTCTICKETLIFETIME))
260 return -2; /* too long a life */
261 if ((end != NEVERDATE) && (end + KTC_TIME_UNCERTAINTY < now)) { /* expired */
263 && (now - start > MAXKTCTICKETLIFETIME + 24 * 60 * 60))
266 return -1; /* expired only recently */
268 if ((start == 0) || (start - KTC_TIME_UNCERTAINTY <= now))
271 active = 0; /* start time not yet arrived */
273 if ((start == 0) || (end == NEVERDATE))
274 return active; /* no expiration time */
275 return active * 2; /* ticket valid */
279 ktohl(char flags, afs_int32 l)
282 unsigned char *lp = (unsigned char *)&l;
284 hl = *lp + (*(lp + 1) << 8) + (*(lp + 2) << 16) + (*(lp + 3) << 24);
290 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
291 * returns the corresponding end time. There are four simple cases to be
292 * handled. The first is a life of 0xff, meaning no expiration, and results in
293 * an end time of 0xffffffff. The second is when life is less than the values
294 * covered by the table. In this case, the end time is the start time plus the
295 * number of 5 minute intervals specified by life. The third case returns
296 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
297 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
298 * table to extract the lifetime in seconds, which is added to start to produce
302 life_to_time(afs_uint32 start, unsigned char life)
306 if (life == TKTLIFENOEXPIRE)
308 if (life < TKTLIFEMINFIXED)
309 return start + life * 5 * 60;
310 if (life > TKTLIFEMAXFIXED)
311 return start + MAXTKTLIFETIME;
312 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
313 return start + realLife;
316 /* time_to_life - takes start and end times for the ticket and returns a
317 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
318 * lifetimes above 127*5minutes. First, the special case of (end ==
319 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
320 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
321 * less than the first table entry are handled by rounding the requested
322 * lifetime *up* to the next 5 minute interval. The final step is to search
323 * the table for the smallest entry *greater than or equal* to the requested
324 * entry. The actual code is prepared to handle the case where the table is
325 * unordered but that it an unnecessary frill. */
328 time_to_life(afs_uint32 start, afs_uint32 end)
330 int lifetime = end - start;
334 if (end == NEVERDATE)
335 return TKTLIFENOEXPIRE;
336 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
338 if (lifetime < tkt_lifetimes[0])
339 return (lifetime + 5 * 60 - 1) / (5 * 60);
341 best = MAXKTCTICKETLIFETIME;
342 for (i = 0; i < TKTLIFENUMFIXED; i++)
343 if (tkt_lifetimes[i] >= lifetime) {
344 int diff = tkt_lifetimes[i] - lifetime;
352 return best_i + TKTLIFEMINFIXED;