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>
47 #include "lifetimes.h"
49 #endif /* defined(UKERNEL) */
51 /* This union is used to insure we allocate enough space for a key
52 * schedule even if we are linked against a library that uses OpenSSL's
53 * larger representation. This is necessary so we don't lose if an
54 * application uses both rxkad and openssl.
56 union Key_schedule_safe {
57 Key_schedule schedule;
64 } openssl_schedule[16];
67 #define getstr(name,min) \
68 slen = strlen(ticket); \
69 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
70 strcpy (name, ticket); \
74 decode_athena_ticket(char *ticket, int ticketLen, char *name, char *inst,
75 char *realm, afs_int32 * host,
76 struct ktc_encryptionKey *sessionKey, afs_uint32 * start,
79 char *ticketBeg = ticket;
83 unsigned char lifetime;
84 char sname[MAXKTCNAMELEN]; /* these aren't used, */
85 char sinst[MAXKTCNAMELEN]; /* but are in the ticket */
92 memcpy(host, ticket, sizeof(*host));
93 ticket += sizeof(*host);
94 *host = ktohl(flags, *host);
96 memcpy(sessionKey, ticket, sizeof(struct ktc_encryptionKey));
97 ticket += sizeof(struct ktc_encryptionKey);
100 memcpy(start, ticket, sizeof(*start));
101 ticket += sizeof(*start);
102 *start = ktohl(flags, *start);
103 *end = life_to_time(*start, lifetime);
108 tlen = ticket - ticketBeg;
109 if ((round_up_to_ebs(tlen) != ticketLen) && (ticketLen != 56))
114 /* This is called to interpret a ticket. It is assumed that the necessary keys
115 have been added so that the key version number in the ticket will indicate a
116 valid key for decrypting the ticket. The various fields inside the ticket
117 are copied into the return arguments. An error code indicate some problem
118 interpreting the ticket and the values of the output parameters are
122 tkt_DecodeTicket(char *asecret, afs_int32 ticketLen,
123 struct ktc_encryptionKey *key, char *name, char *inst,
124 char *cell, char *sessionKey, afs_int32 * host,
125 afs_int32 * start, afs_int32 * end)
127 char clear_ticket[MAXKTCTICKETLEN];
129 union Key_schedule_safe schedule;
133 return RXKADBADTICKET; /* no ticket */
134 if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */
135 (ticketLen > MAXKTCTICKETLEN) || /* maximum legal ticket size */
136 ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */
137 return RXKADBADTICKET;
139 if (key_sched(key, schedule.schedule))
142 ticket = clear_ticket;
143 pcbc_encrypt(asecret, ticket, ticketLen, schedule.schedule, key, DECRYPT);
146 decode_athena_ticket(ticket, ticketLen, name, inst, cell, host,
147 sessionKey, start, end);
150 return RXKADBADTICKET;
152 code = tkt_CheckTimes(*start, *end, time(0));
158 return RXKADBADTICKET;
163 /* This makes a Kerberos ticket */
165 char *ticket; * ticket is constructed here *
166 int *ticketLen; * output length of finished ticket *
167 struct ktc_encryptionKey *key; * key ticket should be sealed with *
168 char *name; * user of this ticket *
170 char *cell; * cell of authentication *
171 afs_uint32 start,end; * life of ticket *
172 struct ktc_encryptionKey *sessionKey; * session key invented for ticket *
173 afs_uint32 host; * caller's host address *
174 char *sname; * server *
178 #define putstr(name,min) \
179 slen = strlen(name); \
180 if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \
181 strcpy (ticket, name); \
183 #define putint(num) num = htonl(num);\
184 memcpy(ticket, &num, sizeof(num));\
185 ticket += sizeof(num)
188 assemble_athena_ticket(char *ticket, int *ticketLen, char *name, char *inst,
189 char *realm, afs_int32 host,
190 struct ktc_encryptionKey *sessionKey, afs_uint32 start,
191 afs_uint32 end, char *sname, char *sinst)
193 char *ticketBeg = ticket;
197 *ticket++ = 0; /* flags, always send net-byte-order */
203 memcpy(ticket, sessionKey, sizeof(struct ktc_encryptionKey));
204 ticket += sizeof(struct ktc_encryptionKey);
206 life = time_to_life(start, end);
215 *ticketLen = ticket - ticketBeg;
220 tkt_MakeTicket(char *ticket, int *ticketLen, struct ktc_encryptionKey *key,
221 char *name, char *inst, char *cell, afs_uint32 start,
222 afs_uint32 end, struct ktc_encryptionKey *sessionKey,
223 afs_uint32 host, char *sname, char *sinst)
226 union Key_schedule_safe schedule;
228 *ticketLen = 0; /* in case we return early */
230 assemble_athena_ticket(ticket, ticketLen, name, inst, cell, host,
231 sessionKey, start, end, sname, sinst);
232 *ticketLen = round_up_to_ebs(*ticketLen); /* round up */
237 if (code = key_sched(key, schedule.schedule)) {
238 printf("In tkt_MakeTicket: key_sched returned %d\n", code);
241 pcbc_encrypt(ticket, ticket, *ticketLen, schedule.schedule, key, ENCRYPT);
245 /* This is just a routine that checks the consistency of ticket lifetimes. It
246 returns three values: */
247 /* -2 means the times are inconsistent or ticket has expired
248 -1 means the ticket has recently expired.
249 0 means the times are consistent but start time is in the (near) future.
250 1 means the start time is in the past and the end time is infinity.
251 2 means the start time is past and the end time is in the future
252 and the lifetime is within the legal limit.
256 tkt_CheckTimes(afs_uint32 start, afs_uint32 end, afs_uint32 now)
261 return -2; /* zero or negative lifetime */
262 if (start > now + KTC_TIME_UNCERTAINTY + MAXKTCTICKETLIFETIME)
263 return -2; /* starts too far in the future? */
264 if ((start != 0) && (end != NEVERDATE)
265 && (end - start > MAXKTCTICKETLIFETIME))
266 return -2; /* too long a life */
267 if ((end != NEVERDATE) && (end + KTC_TIME_UNCERTAINTY < now)) { /* expired */
269 && (now - start > MAXKTCTICKETLIFETIME + 24 * 60 * 60))
272 return -1; /* expired only recently */
274 if ((start == 0) || (start - KTC_TIME_UNCERTAINTY <= now))
277 active = 0; /* start time not yet arrived */
279 if ((start == 0) || (end == NEVERDATE))
280 return active; /* no expiration time */
281 return active * 2; /* ticket valid */
285 ktohl(char flags, afs_int32 l)
288 unsigned char *lp = (unsigned char *)&l;
290 hl = *lp + (*(lp + 1) << 8) + (*(lp + 2) << 16) + (*(lp + 3) << 24);
296 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
297 * returns the corresponding end time. There are four simple cases to be
298 * handled. The first is a life of 0xff, meaning no expiration, and results in
299 * an end time of 0xffffffff. The second is when life is less than the values
300 * covered by the table. In this case, the end time is the start time plus the
301 * number of 5 minute intervals specified by life. The third case returns
302 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
303 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
304 * table to extract the lifetime in seconds, which is added to start to produce
308 life_to_time(afs_uint32 start, unsigned char life)
312 if (life == TKTLIFENOEXPIRE)
314 if (life < TKTLIFEMINFIXED)
315 return start + life * 5 * 60;
316 if (life > TKTLIFEMAXFIXED)
317 return start + MAXTKTLIFETIME;
318 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
319 return start + realLife;
322 /* time_to_life - takes start and end times for the ticket and returns a
323 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
324 * lifetimes above 127*5minutes. First, the special case of (end ==
325 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
326 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
327 * less than the first table entry are handled by rounding the requested
328 * lifetime *up* to the next 5 minute interval. The final step is to search
329 * the table for the smallest entry *greater than or equal* to the requested
330 * entry. The actual code is prepared to handle the case where the table is
331 * unordered but that it an unnecessary frill. */
334 time_to_life(afs_uint32 start, afs_uint32 end)
336 int lifetime = end - start;
340 if (end == NEVERDATE)
341 return TKTLIFENOEXPIRE;
342 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
344 if (lifetime < tkt_lifetimes[0])
345 return (lifetime + 5 * 60 - 1) / (5 * 60);
347 best = MAXKTCTICKETLIFETIME;
348 for (i = 0; i < TKTLIFENUMFIXED; i++)
349 if (tkt_lifetimes[i] >= lifetime) {
350 int diff = tkt_lifetimes[i] - lifetime;
358 return best_i + TKTLIFEMINFIXED;