Save ticket pointers.
[shishi.git] / lib / ccache.c
blob6a62620a4e7eeba2663155ec2ca1b1c09fa3e6f1
1 /* ccache.c --- Read MIT style Kerberos Credential Cache file.
2 * Copyright (C) 2006 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "ccache.h"
23 #include <stdio.h>
25 /* See ccache.txt for a description of the file format. */
27 static int
28 get_uint8 (const void **data, size_t * len, uint8_t * i)
30 const char *p = *data;
31 if (*len < 1)
32 return -1;
33 *i = p[0];
34 *data += 1;
35 *len -= 1;
36 return 0;
39 static int
40 get_uint16 (const void **data, size_t * len, uint16_t * i)
42 const char *p = *data;
43 if (*len < 2)
44 return -1;
45 *i = p[0] << 8 | p[1];
46 *data += 2;
47 *len -= 2;
48 return 0;
51 static int
52 get_uint32 (const void **data, size_t * len, uint32_t * i)
54 const char *p = *data;
55 if (*len < 4)
56 return -1;
57 *i = ((p[0] << 24) & 0xFF000000)
58 | ((p[1] << 16) & 0xFF0000) | ((p[2] << 8) & 0xFF00) | (p[3] & 0xFF);
59 *data += 4;
60 *len -= 4;
61 return 0;
64 static int
65 parse_principal (const void **data, size_t * len,
66 struct ccache_principal *out)
68 size_t n;
69 int rc;
71 rc = get_uint32 (data, len, &out->name_type);
72 if (rc < 0)
73 return rc;
75 rc = get_uint32 (data, len, &out->num_components);
76 if (rc < 0)
77 return rc;
79 if (out->num_components >= CCACHE_MAX_COMPONENTS)
80 return -1;
82 rc = get_uint32 (data, len, &out->realm.length);
83 if (rc < 0)
84 return rc;
86 if (*len < out->realm.length)
87 return -1;
88 out->realm.data = *data;
89 *data += out->realm.length;
90 *len -= out->realm.length;
92 for (n = 0; n < out->num_components; n++)
94 rc = get_uint32 (data, len, &out->components[n].length);
95 if (rc < 0)
96 return rc;
98 if (*len < out->components[n].length)
99 return -1;
100 out->components[n].data = *data;
101 *data += out->components[n].length;
102 *len -= out->components[n].length;
105 return 0;
108 static int
109 skip_address (const void **data, size_t * len)
111 uint16_t addrtype;
112 uint32_t addrlen;
113 int rc;
115 rc = get_uint16 (data, len, &addrtype);
116 if (rc < 0)
117 return rc;
119 rc = get_uint32 (data, len, &addrlen);
120 if (rc < 0)
121 return rc;
123 if (*len < addrlen)
124 return -1;
125 *data += addrlen;
126 *len -= addrlen;
128 return 0;
131 static int
132 skip_authdata (const void **data, size_t * len)
134 uint16_t authdatatype;
135 uint32_t authdatalen;
136 int rc;
138 rc = get_uint16 (data, len, &authdatatype);
139 if (rc < 0)
140 return rc;
142 rc = get_uint32 (data, len, &authdatalen);
143 if (rc < 0)
144 return rc;
146 if (*len < authdatalen)
147 return -1;
148 *data += authdatalen;
149 *len -= authdatalen;
151 return 0;
154 static int
155 parse_credential (const void **data, size_t * len,
156 struct ccache_credential *out)
158 struct ccache_principal princ;
159 uint32_t num_address;
160 uint32_t num_authdata;
161 int rc;
163 rc = parse_principal (data, len, &out->client);
164 if (rc < 0)
165 return rc;
167 rc = parse_principal (data, len, &out->server);
168 if (rc < 0)
169 return rc;
171 rc = get_uint16 (data, len, &out->key.keytype);
172 if (rc < 0)
173 return rc;
175 rc = get_uint16 (data, len, &out->key.etype);
176 if (rc < 0)
177 return rc;
179 rc = get_uint16 (data, len, &out->key.keylen);
180 if (rc < 0)
181 return rc;
183 if (*len < out->key.keylen)
184 return -1;
186 out->key.keyvalue = *data;
188 *data += out->key.keylen;
189 *len -= out->key.keylen;
191 rc = get_uint32 (data, len, &out->authtime);
192 if (rc < 0)
193 return rc;
195 rc = get_uint32 (data, len, &out->starttime);
196 if (rc < 0)
197 return rc;
199 rc = get_uint32 (data, len, &out->endtime);
200 if (rc < 0)
201 return rc;
203 rc = get_uint32 (data, len, &out->renew_till);
204 if (rc < 0)
205 return rc;
207 rc = get_uint8 (data, len, &out->is_skey);
208 if (rc < 0)
209 return rc;
211 rc = get_uint32 (data, len, &out->tktflags);
212 if (rc < 0)
213 return rc;
215 rc = get_uint32 (data, len, &num_address);
216 if (rc < 0)
217 return rc;
219 for (; num_address; num_address--)
221 /* XXX Don't just skip data. */
222 rc = skip_address (data, len);
223 if (rc < 0)
224 return rc;
227 rc = get_uint32 (data, len, &num_authdata);
228 if (rc < 0)
229 return rc;
231 for (; num_authdata; num_authdata--)
233 /* XXX Don't just skip data. */
234 rc = skip_authdata (data, len);
235 if (rc < 0)
236 return rc;
239 rc = get_uint32 (data, len, &out->ticket.length);
240 if (rc < 0)
241 return rc;
243 if (*len < out->ticket.length)
244 return -1;
245 out->ticket.data = *data;
246 *data += out->ticket.length;
247 *len -= out->ticket.length;
249 rc = get_uint32 (data, len, &out->second_ticket.length);
250 if (rc < 0)
251 return rc;
253 if (*len < out->second_ticket.length)
254 return -1;
255 out->second_ticket.data = *data;
256 *data += out->second_ticket.length;
257 *len -= out->second_ticket.length;
259 return 0;
263 ccache_parse (const void *data, size_t len, struct ccache *out)
265 size_t pos = 0;
266 int rc;
268 rc = get_uint16 (&data, &len, &out->file_format_version);
269 if (rc < 0)
270 return rc;
272 rc = get_uint16 (&data, &len, &out->headerlen);
273 if (rc < 0)
274 return rc;
276 out->header = data;
278 if (len < out->headerlen)
279 return -1;
280 data += out->headerlen;
281 len -= out->headerlen;
283 rc = parse_principal (&data, &len, &out->default_principal);
284 if (rc < 0)
285 return rc;
287 out->credentials = data;
288 out->credentialslen = len;
290 return 0;
294 ccache_parse_credential (const void *data, size_t len,
295 struct ccache_credential *out, size_t * n)
297 size_t savelen = len;
298 int rc = parse_credential (&data, &len, out);
300 if (rc < 0)
301 return rc;
303 *n = savelen - len;
304 return 0;
307 void
308 ccache_print (struct ccache *ccache)
310 size_t n;
312 printf ("file_format_version %04x\n", ccache->file_format_version);
313 printf ("headerlen %04x\n", ccache->headerlen);
314 printf ("default_principal\n");
315 ccache_print_principal (&ccache->default_principal);
318 void
319 ccache_print_principal (struct ccache_principal *princ)
321 size_t n;
323 printf ("\tname_type %04x\n", princ->name_type);
324 printf ("\tnum_components %04x\n", princ->num_components);
325 printf ("\trealmlen %04x\n", princ->realm.length);
326 printf ("\trealm %.*s\n", princ->realm.length, princ->realm.data);
328 for (n = 0; n < princ->num_components; n++)
330 printf ("\t\tcomponentlen %04x\n", princ->components[n].length);
331 printf ("\t\tcomponent %.*s\n", princ->components[n].length,
332 princ->components[n].data);
336 void
337 ccache_print_credential (struct ccache_credential *cred)
339 size_t i;
340 printf ("\tclient:\n");
341 ccache_print_principal (&cred->client);
342 printf ("\tserver:\n");
343 ccache_print_principal (&cred->server);
344 printf ("\tkey:\n");
345 printf ("\t\tkeytype %04x\n", cred->key.keytype);
346 printf ("\t\tetype %04x\n", cred->key.etype);
347 printf ("\t\tkeylen %04x\n", cred->key.keylen);
348 printf ("\t\tkey value: ");
349 for (i = 0; i < cred->key.keylen; i++)
350 printf ("%02x", ((char *) cred->key.keyvalue)[i] & 0xFF);
351 printf ("\n");
352 printf ("\ttimes:\n");
353 printf ("\t\tauthtime %04x\n", cred->authtime);
354 printf ("\t\tstarttime %04x\n", cred->starttime);
355 printf ("\t\tendtime %04x\n", cred->endtime);
356 printf ("\t\trenew_till %04x\n", cred->renew_till);
357 printf ("\tis_skey %04x\n", cred->is_skey);
358 printf ("\ttktflags_skey %04x\n", cred->tktflags);
359 printf ("\tticketlen %04x\n", cred->ticket.length);
360 printf ("\tsecond_ticketlen %04x\n", cred->second_ticket.length);
363 #ifdef TEST
365 main (int argc, char *argv[])
367 char buf[10240];
368 size_t len;
369 FILE *fh;
370 int rc;
371 struct ccache ccache;
372 struct ccache_credential cred;
373 size_t i = 0;
375 if (argc <= 1)
377 printf ("Usage: %s <krb5ccache-file>\n", argv[0]);
378 return 1;
381 fh = fopen (argv[1], "rb");
382 if (!fh)
384 puts ("Error: cannot open file");
385 return 1;
388 len = fread (buf, 1, sizeof (buf), fh);
390 if (len >= sizeof (buf))
392 puts ("Error: file too large");
393 return 1;
396 rc = ccache_parse (buf, len, &ccache);
397 if (rc < 0)
399 puts ("Error: syntax error");
400 return 1;
403 ccache_print (&ccache);
405 while (ccache.credentialslen)
407 size_t n;
409 rc = ccache_parse_credential (ccache.credentials,
410 ccache.credentialslen, &cred, &n);
411 if (rc < 0)
413 printf ("Error: cannot parse credential %d\n", i);
414 return rc;
417 printf ("\nCredential %d:\n", i++);
419 ccache_print_credential (&cred);
421 ccache.credentials += n;
422 ccache.credentialslen -= n;
425 if (fclose (fh))
427 puts ("Error: cannot close file");
428 return 1;
431 return 0;
433 #endif