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"
25 #include "rxkad/lifetimes.h"
27 #include "des/des_prototypes.h"
29 #else /* defined(UKERNEL) */
31 #include <sys/types.h>
35 #include <netinet/in.h>
39 #include <des_prototypes.h>
42 #include "lifetimes.h"
44 #endif /* defined(UKERNEL) */
46 /* This union is used to insure we allocate enough space for a key
47 * schedule even if we are linked against a library that uses OpenSSL's
48 * larger representation. This is necessary so we don't lose if an
49 * application uses both rxkad and openssl.
51 union Key_schedule_safe {
52 Key_schedule schedule;
59 } openssl_schedule[16];
62 #define getstr(name,min) \
63 slen = strlen(ticket); \
64 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
65 strcpy (name, ticket); \
69 decode_athena_ticket(char *ticket, int ticketLen, char *name, char *inst,
70 char *realm, afs_int32 * host,
71 struct ktc_encryptionKey *sessionKey, afs_uint32 * start,
74 char *ticketBeg = ticket;
78 unsigned char lifetime;
79 char sname[MAXKTCNAMELEN]; /* these aren't used, */
80 char sinst[MAXKTCNAMELEN]; /* but are in the ticket */
87 memcpy(host, ticket, sizeof(*host));
88 ticket += sizeof(*host);
89 *host = ktohl(flags, *host);
91 memcpy(sessionKey, ticket, sizeof(struct ktc_encryptionKey));
92 ticket += sizeof(struct ktc_encryptionKey);
95 memcpy(start, ticket, sizeof(*start));
96 ticket += sizeof(*start);
97 *start = ktohl(flags, *start);
98 *end = life_to_time(*start, lifetime);
103 tlen = ticket - ticketBeg;
104 if ((round_up_to_ebs(tlen) != ticketLen) && (ticketLen != 56))
109 /* This is called to interpret a ticket. It is assumed that the necessary keys
110 have been added so that the key version number in the ticket will indicate a
111 valid key for decrypting the ticket. The various fields inside the ticket
112 are copied into the return arguments. An error code indicate some problem
113 interpreting the ticket and the values of the output parameters are
117 tkt_DecodeTicket(char *asecret, afs_int32 ticketLen,
118 struct ktc_encryptionKey *key, char *name, char *inst,
119 char *cell, struct ktc_encryptionKey *sessionKey, afs_int32 * host,
120 afs_int32 * start, afs_int32 * end)
122 char clear_ticket[MAXKTCTICKETLEN];
124 union Key_schedule_safe schedule;
128 return RXKADBADTICKET; /* no ticket */
129 if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */
130 (ticketLen > MAXKTCTICKETLEN) || /* maximum legal ticket size */
131 ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */
132 return RXKADBADTICKET;
134 if (key_sched(ktc_to_cblock(key), schedule.schedule))
137 ticket = clear_ticket;
138 pcbc_encrypt(asecret, ticket, ticketLen, schedule.schedule, ktc_to_cblockptr(key), DECRYPT);
141 decode_athena_ticket(ticket, ticketLen, name, inst, cell, host,
142 (struct ktc_encryptionKey *)sessionKey, start, end);
145 return RXKADBADTICKET;
147 code = tkt_CheckTimes(*start, *end, time(0));
153 return RXKADBADTICKET;
158 /* This makes a Kerberos ticket */
160 char *ticket; * ticket is constructed here *
161 int *ticketLen; * output length of finished ticket *
162 struct ktc_encryptionKey *key; * key ticket should be sealed with *
163 char *name; * user of this ticket *
165 char *cell; * cell of authentication *
166 afs_uint32 start,end; * life of ticket *
167 struct ktc_encryptionKey *sessionKey; * session key invented for ticket *
168 afs_uint32 host; * caller's host address *
169 char *sname; * server *
173 #define putstr(name,min) \
174 slen = strlen(name); \
175 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
176 strcpy (ticket, name); \
178 #define putint(num) num = htonl(num);\
179 memcpy(ticket, &num, sizeof(num));\
180 ticket += sizeof(num)
183 assemble_athena_ticket(char *ticket, int *ticketLen, char *name, char *inst,
184 char *realm, afs_int32 host,
185 struct ktc_encryptionKey *sessionKey, afs_uint32 start,
186 afs_uint32 end, char *sname, char *sinst)
188 char *ticketBeg = ticket;
192 *ticket++ = 0; /* flags, always send net-byte-order */
198 memcpy(ticket, sessionKey, sizeof(struct ktc_encryptionKey));
199 ticket += sizeof(struct ktc_encryptionKey);
201 life = time_to_life(start, end);
210 *ticketLen = ticket - ticketBeg;
215 tkt_MakeTicket(char *ticket, int *ticketLen, struct ktc_encryptionKey *key,
216 char *name, char *inst, char *cell, afs_uint32 start,
217 afs_uint32 end, struct ktc_encryptionKey *sessionKey,
218 afs_uint32 host, char *sname, char *sinst)
221 union Key_schedule_safe schedule;
223 *ticketLen = 0; /* in case we return early */
225 assemble_athena_ticket(ticket, ticketLen, name, inst, cell, host,
226 sessionKey, start, end, sname, sinst);
227 *ticketLen = round_up_to_ebs(*ticketLen); /* round up */
232 if ((code = key_sched(ktc_to_cblock(key), schedule.schedule))) {
233 printf("In tkt_MakeTicket: key_sched returned %d\n", code);
236 pcbc_encrypt(ticket, ticket, *ticketLen, schedule.schedule, ktc_to_cblockptr(key), ENCRYPT);
240 /* This is just a routine that checks the consistency of ticket lifetimes. It
241 returns three values: */
242 /* -2 means the times are inconsistent or ticket has expired
243 -1 means the ticket has recently expired.
244 0 means the times are consistent but start time is in the (near) future.
245 1 means the start time is in the past and the end time is infinity.
246 2 means the start time is past and the end time is in the future
247 and the lifetime is within the legal limit.
251 tkt_CheckTimes(afs_uint32 start, afs_uint32 end, afs_uint32 now)
256 return -2; /* zero or negative lifetime */
257 if (start > now + KTC_TIME_UNCERTAINTY + MAXKTCTICKETLIFETIME)
258 return -2; /* starts too far in the future? */
259 if ((start != 0) && (end != NEVERDATE)
260 && (end - start > MAXKTCTICKETLIFETIME))
261 return -2; /* too long a life */
262 if ((end != NEVERDATE) && (end + KTC_TIME_UNCERTAINTY < now)) { /* expired */
264 && (now - start > MAXKTCTICKETLIFETIME + 24 * 60 * 60))
267 return -1; /* expired only recently */
269 if ((start == 0) || (start - KTC_TIME_UNCERTAINTY <= now))
272 active = 0; /* start time not yet arrived */
274 if ((start == 0) || (end == NEVERDATE))
275 return active; /* no expiration time */
276 return active * 2; /* ticket valid */
280 ktohl(char flags, afs_int32 l)
283 unsigned char *lp = (unsigned char *)&l;
285 hl = *lp + (*(lp + 1) << 8) + (*(lp + 2) << 16) + (*(lp + 3) << 24);
291 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
292 * returns the corresponding end time. There are four simple cases to be
293 * handled. The first is a life of 0xff, meaning no expiration, and results in
294 * an end time of 0xffffffff. The second is when life is less than the values
295 * covered by the table. In this case, the end time is the start time plus the
296 * number of 5 minute intervals specified by life. The third case returns
297 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
298 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
299 * table to extract the lifetime in seconds, which is added to start to produce
303 life_to_time(afs_uint32 start, unsigned char life)
307 if (life == TKTLIFENOEXPIRE)
309 if (life < TKTLIFEMINFIXED)
310 return start + life * 5 * 60;
311 if (life > TKTLIFEMAXFIXED)
312 return start + MAXTKTLIFETIME;
313 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
314 return start + realLife;
317 /* time_to_life - takes start and end times for the ticket and returns a
318 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
319 * lifetimes above 127*5minutes. First, the special case of (end ==
320 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
321 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
322 * less than the first table entry are handled by rounding the requested
323 * lifetime *up* to the next 5 minute interval. The final step is to search
324 * the table for the smallest entry *greater than or equal* to the requested
325 * entry. The actual code is prepared to handle the case where the table is
326 * unordered but that it an unnecessary frill. */
329 time_to_life(afs_uint32 start, afs_uint32 end)
331 int lifetime = end - start;
335 if (end == NEVERDATE)
336 return TKTLIFENOEXPIRE;
337 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
339 if (lifetime < tkt_lifetimes[0])
340 return (lifetime + 5 * 60 - 1) / (5 * 60);
342 best = MAXKTCTICKETLIFETIME;
343 for (i = 0; i < TKTLIFENUMFIXED; i++)
344 if (tkt_lifetimes[i] >= lifetime) {
345 int diff = tkt_lifetimes[i] - lifetime;
353 return best_i + TKTLIFEMINFIXED;