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
14 /* This modified from the code in kerberos/src/lib/krb/tf_util.c. */
17 * This file contains routines for manipulating the ticket cache file.
19 * The ticket file is in the following format:
21 * principal's name (null-terminated string)
22 * principal's instance (null-terminated string)
29 * Where "CREDENTIAL_x" consists of the following fixed-length
30 * fields from the CREDENTIALS structure (see "krb.h"):
32 * char service[ANAME_SZ]
33 * char instance[INST_SZ]
34 * char realm[REALM_SZ]
39 * afs_int32 issue_date
44 /* Inspite of what the above comment suggests the fields are not fixed length
45 but null terminated as you might figure, except for the ticket which is
46 preceded by a 4 byte length. All fields in host order. 890306 */
47 #include <afsconfig.h>
48 #include <afs/param.h>
68 #include <sys/types.h>
75 #ifndef WORDS_BIGENDIAN
76 /* This was taken from jhutz's patch for heimdal krb4. It only
77 * applies to little endian systems. Big endian systems have a
78 * less elegant solution documented below.
80 * This record is written after every real ticket, to ensure that
81 * both 32- and 64-bit readers will perceive the next real ticket
82 * as starting in the same place. This record looks like a ticket
83 * with the following properties:
85 * ============ ================= =================
89 * session key 002E2E00 xxxxxxxx xxxxxxxx 00000000
92 * ticket 12 nulls 4 nulls
95 static unsigned char align_rec[] = {
96 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00, 0x2e,
97 0x2e, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
99 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 #else /* AFSLITTLE_ENDIAN */
106 /* This was taken from asedeno's patch for MIT Kerberos. These
107 * alignment records are for big endian systems. We need more of them
108 * because the portion of the 64-bit issue_date that overlaps with the
109 * start of a ticket on 32-bit systems contains an unpredictable
110 * number of NULL bytes. Preceeding these records is a second copy of
111 * the 32-bit issue_date. The srealm for the alignment records is
112 * always one of ".." or "?.."
116 * This is actually two alignment records since both 32- and 64-bit
117 * readers will agree on everything in the first record up through the
118 * issue_date size, except where sname starts.
119 * Field (1) 32-bit 64-bit
120 * ============ ================= =================
124 * session key 00000000 xxxxxxxx 00000000 xxxxxxxx
127 * ticket 4 nulls 4 nulls
130 * Field (2) 32-bit 64-bit
131 * ============ ================= =================
135 * session key 002E2E00 xxxxxxxx xxxxxxxx 00000000
138 * ticket 12 nulls 4 nulls
142 static unsigned char align_rec_0[] = {
143 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00,
148 0x00, 0x2e, 0x2e, 0x00, 0xff, 0xff, 0xff, 0xff,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00
156 * Field 32-bit 64-bit
157 * ============ ================= =================
158 * sname "x" |"xx"|"xxx" "."
159 * sinst "xx."|"x."|"." ".."
161 * session key 2E2E2E00 xxxxxxxx xxxxxxxx 00000000
164 * ticket 12 nulls 4 nulls
167 static unsigned char align_rec_1[] = {
168 0x2e, 0x00, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e,
169 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 * Field 32-bit 64-bit
178 * ============ ================= =================
179 * sname "x" |"x" |"xx" ".."
180 * sinst "" |"x" |"" ""
181 * srealm "x.."|".."|".." ".."
182 * session key 002E2E00 xxxxxxxx xxxxxxxx 00000000
185 * ticket 12 nulls 4 nulls
188 static unsigned char align_rec_2[] = {
189 0x2e, 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0xff,
190 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
192 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
197 * Things break here for 32-bit krb4 libraries that don't
198 * understand this alignment record. We can't really do
199 * anything about the fact that the three strings ended
200 * in the duplicate timestamp. The good news is that this
201 * only happens once every 0x1000000 seconds, once roughly
202 * every six and a half months. We'll live.
204 * Discussion on the krbdev list has suggested the
205 * issue_date be incremented by one in this case to avoid
206 * the problem. I'm leaving this here just in case.
208 * Field 32-bit 64-bit
209 * ============ ================= =================
213 * session key 2E00002E 2E00FFFF xxxx0000 0000xxxx
215 * kvno 4294901760 917504
216 * ticket 14 nulls 4 nulls
220 static unsigned char align_rec_3[] = {
221 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0xff, 0xff,
222 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
223 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
228 #endif /* AFSLITTLE_ENDIAN */
231 krb_write_ticket_file(realm)
234 char ticket_file[AFSDIR_PATH_MAX];
240 struct ktc_principal client, server;
241 struct ktc_token token;
243 if ((strlen(realm) >= sizeof(client.cell)))
245 strcpy(server.name, KA_TGS_NAME);
246 strcpy(server.instance, realm);
247 lcstring(server.cell, realm, sizeof(server.cell));
249 code = ktc_GetToken(&server, &token, sizeof(struct ktc_token), &client);
253 /* Use the KRBTKFILE environment variable if it exists, otherwise fall
254 * back upon /tmp/tkt(uid}.
256 if (tf_name = (char *)getenv("KRBTKFILE"))
257 (void)sprintf(ticket_file, "%s", tf_name);
259 (void)sprintf(ticket_file, "%s/tkt%d", gettmpdir(), getuid());
260 fd = open(ticket_file, O_WRONLY + O_CREAT + O_TRUNC, 0700);
264 /* write client name as file header */
266 count = strlen(client.name) + 1;
267 if (write(fd, client.name, count) != count)
270 count = strlen(client.instance) + 1;
271 if (write(fd, client.instance, count) != count)
274 /* Write the ticket and associated data */
276 count = strlen(server.name) + 1;
277 if (write(fd, server.name, count) != count)
280 count = strlen(server.instance) + 1;
281 if (write(fd, server.instance, count) != count)
284 ucstring(server.cell, server.cell, sizeof(server.cell));
285 count = strlen(server.cell) + 1;
286 if (write(fd, server.cell, count) != count)
289 if (write(fd, (char *)&token.sessionKey, 8) != 8)
292 lifetime = time_to_life(token.startTime, token.endTime);
293 if (write(fd, (char *)&lifetime, sizeof(int)) != sizeof(int))
297 if (write(fd, (char *)&kvno, sizeof(int)) != sizeof(int))
300 if (write(fd, (char *)&(token.ticketLen), sizeof(int)) != sizeof(int))
303 count = token.ticketLen;
304 if (write(fd, (char *)(token.ticket), count) != count)
307 if (write(fd, (char *)&(token.startTime), sizeof(afs_int32))
308 != sizeof(afs_int32))
313 /* Alignment Record, from MIT Kerberos */
314 #ifndef WORDS_BIGENDIAN
315 if (write(fd, align_rec, sizeof(align_rec)) != sizeof(align_rec))
317 #else /* AFSLITTLE_ENDIAN */
320 if (0 == (token.startTime & 0xff000000))
322 if (0 == (token.startTime & 0x00ff0000))
324 if (0 == (token.startTime & 0x0000ff00))
326 if (0 == (token.startTime & 0x000000ff))
332 if (write(fd, (char *) token.startTime, sizeof(afs_int32))
333 != sizeof(afs_int32))
335 if (write(fd, align_rec_0, sizeof(align_rec_0))
336 != sizeof(align_rec_0))
342 if (write(fd, (char *) &token.startTime, sizeof(afs_int32))
343 != sizeof(afs_int32))
345 if (write(fd, align_rec_1, sizeof(align_rec_1))
346 != sizeof(align_rec_1))
351 /* Three NULLS are troublesome but rare. We'll just pretend
352 * they don't exist by decrementing the token.startTime.
357 if (write(fd, (char *) &token.startTime, sizeof(afs_int32))
358 != sizeof(afs_int32))
360 if (write(fd, align_rec_2, sizeof(align_rec_2))
361 != sizeof(align_rec_2))
369 #endif /* AFSLITTLE_ENDIAN */