1 /* ccache.c --- Read MIT style Kerberos Credential Cache file.
2 * Copyright (C) 2006, 2007 Simon Josefsson
4 * This file is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This file is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this file; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 /* See ccache.txt for a description of the file format.
26 * This implementation do not support addresses nor auth-data right
31 get_uint8 (const char **data
, size_t * len
, uint8_t * i
)
33 const char *p
= *data
;
43 get_uint16 (const char **data
, size_t * len
, uint16_t * i
)
45 const char *p
= *data
;
48 *i
= p
[0] << 8 | p
[1];
55 get_uint32 (const char **data
, size_t * len
, uint32_t * i
)
57 const char *p
= *data
;
60 *i
= ((p
[0] << 24) & 0xFF000000)
61 | ((p
[1] << 16) & 0xFF0000) | ((p
[2] << 8) & 0xFF00) | (p
[3] & 0xFF);
68 get_uint32_swapped (const char **data
, size_t * len
, uint32_t * i
)
70 const char *p
= *data
;
73 *i
= ((p
[3] << 24) & 0xFF000000)
74 | ((p
[2] << 16) & 0xFF0000) | ((p
[1] << 8) & 0xFF00) | (p
[0] & 0xFF);
81 put_uint8 (uint8_t i
, char **data
, size_t * len
)
91 put_uint16 (uint16_t i
, char **data
, size_t * len
)
95 *(*data
)++ = (i
>> 8) & 0xFF;
102 put_uint32 (uint32_t i
, char **data
, size_t * len
)
106 *(*data
)++ = (i
>> 24) & 0xFF;
107 *(*data
)++ = (i
>> 16) & 0xFF;
108 *(*data
)++ = (i
>> 8) & 0xFF;
115 put_uint32_swapped (uint32_t i
, char **data
, size_t * len
)
120 *(*data
)++ = (i
>> 8) & 0xFF;
121 *(*data
)++ = (i
>> 16) & 0xFF;
122 *(*data
)++ = (i
>> 24) & 0xFF;
128 parse_principal (const char **data
, size_t * len
,
129 struct ccache_principal
*out
)
134 rc
= get_uint32 (data
, len
, &out
->name_type
);
138 rc
= get_uint32 (data
, len
, &out
->num_components
);
142 if (out
->num_components
>= CCACHE_MAX_COMPONENTS
)
145 rc
= get_uint32 (data
, len
, &out
->realm
.length
);
149 if (*len
< out
->realm
.length
)
151 out
->realm
.data
= *data
;
152 *data
+= out
->realm
.length
;
153 *len
-= out
->realm
.length
;
155 /* Make sure realm will be zero terminated. This limits component
156 lengths to 2^24 bytes. */
157 if (**(char**)data
!= '\0')
160 for (n
= 0; n
< out
->num_components
; n
++)
162 rc
= get_uint32 (data
, len
, &out
->components
[n
].length
);
166 if (*len
< out
->components
[n
].length
)
168 out
->components
[n
].data
= *data
;
169 *data
+= out
->components
[n
].length
;
170 *len
-= out
->components
[n
].length
;
172 /* Make sure component is zero terminated. This limits the
173 length of the next component to 2^24 bytes. Note that you'll
174 have to test after the last component elsewhere. */
175 if (*len
> 0 && **(char**)data
!= '\0')
183 skip_address (const char **data
, size_t * len
)
189 rc
= get_uint16 (data
, len
, &addrtype
);
193 rc
= get_uint32 (data
, len
, &addrlen
);
206 skip_authdata (const char **data
, size_t * len
)
208 uint16_t authdatatype
;
209 uint32_t authdatalen
;
212 rc
= get_uint16 (data
, len
, &authdatatype
);
216 rc
= get_uint32 (data
, len
, &authdatalen
);
220 if (*len
< authdatalen
)
222 *data
+= authdatalen
;
229 parse_credential (const char **data
, size_t * len
,
230 struct ccache_credential
*out
)
232 struct ccache_principal princ
;
233 uint32_t num_address
;
234 uint32_t num_authdata
;
237 rc
= parse_principal (data
, len
, &out
->client
);
241 /* Make sure the last component is zero terminated. This limits the
242 next name-type to 2^24 bytes. */
243 if (*len
> 0 && **(char**)data
!= '\0')
246 rc
= parse_principal (data
, len
, &out
->server
);
250 /* Make sure the last component is zero terminated. This limits the
251 next key-type to lower 1 byte. */
252 if (*len
> 0 && **(char**)data
!= '\0')
255 rc
= get_uint16 (data
, len
, &out
->key
.keytype
);
259 rc
= get_uint16 (data
, len
, &out
->key
.etype
);
263 rc
= get_uint16 (data
, len
, &out
->key
.keylen
);
267 if (*len
< out
->key
.keylen
)
270 out
->key
.keyvalue
= *data
;
272 *data
+= out
->key
.keylen
;
273 *len
-= out
->key
.keylen
;
275 rc
= get_uint32 (data
, len
, &out
->authtime
);
279 rc
= get_uint32 (data
, len
, &out
->starttime
);
283 rc
= get_uint32 (data
, len
, &out
->endtime
);
287 rc
= get_uint32 (data
, len
, &out
->renew_till
);
291 rc
= get_uint8 (data
, len
, &out
->is_skey
);
295 rc
= get_uint32_swapped (data
, len
, &out
->tktflags
);
299 rc
= get_uint32 (data
, len
, &num_address
);
303 for (; num_address
; num_address
--)
305 /* XXX Don't just skip data. */
306 rc
= skip_address (data
, len
);
311 rc
= get_uint32 (data
, len
, &num_authdata
);
315 for (; num_authdata
; num_authdata
--)
317 /* XXX Don't just skip data. */
318 rc
= skip_authdata (data
, len
);
323 rc
= get_uint32 (data
, len
, &out
->ticket
.length
);
327 if (*len
< out
->ticket
.length
)
329 out
->ticket
.data
= *data
;
330 *data
+= out
->ticket
.length
;
331 *len
-= out
->ticket
.length
;
333 rc
= get_uint32 (data
, len
, &out
->second_ticket
.length
);
337 if (*len
< out
->second_ticket
.length
)
339 out
->second_ticket
.data
= *data
;
340 *data
+= out
->second_ticket
.length
;
341 *len
-= out
->second_ticket
.length
;
347 ccache_parse (const char *data
, size_t len
, struct ccache
*out
)
352 rc
= get_uint16 (&data
, &len
, &out
->file_format_version
);
356 rc
= get_uint16 (&data
, &len
, &out
->headerlen
);
360 if (len
< out
->headerlen
)
363 data
+= out
->headerlen
;
364 len
-= out
->headerlen
;
366 rc
= parse_principal (&data
, &len
, &out
->default_principal
);
370 out
->credentials
= data
;
371 out
->credentialslen
= len
;
377 ccache_parse_credential (const char *data
, size_t len
,
378 struct ccache_credential
*out
, size_t * n
)
380 size_t savelen
= len
;
381 int rc
= parse_credential (&data
, &len
, out
);
391 pack_principal (struct ccache_principal
*princ
,
392 char **out
, size_t * len
)
398 rc
= put_uint32 (princ
->name_type
, out
, len
);
402 rc
= put_uint32 (princ
->num_components
, out
, len
);
406 if (princ
->num_components
>= CCACHE_MAX_COMPONENTS
)
409 rc
= put_uint32 (princ
->realm
.length
, out
, len
);
413 if (*len
< princ
->realm
.length
)
415 memcpy (*out
, princ
->realm
.data
, princ
->realm
.length
);
416 *out
+= princ
->realm
.length
;
417 *len
-= princ
->realm
.length
;
419 for (n
= 0; n
< princ
->num_components
; n
++)
421 rc
= put_uint32 (princ
->components
[n
].length
, out
, len
);
425 if (*len
< princ
->components
[n
].length
)
427 memcpy (*out
, princ
->components
[n
].data
, princ
->components
[n
].length
);
428 *out
+= princ
->components
[n
].length
;
429 *len
-= princ
->components
[n
].length
;
436 pack_credential (struct ccache_credential
*cred
,
437 char **out
, size_t *len
)
439 struct ccache_principal princ
;
440 uint32_t num_address
;
441 uint32_t num_authdata
;
444 rc
= pack_principal (&cred
->client
, out
, len
);
448 rc
= pack_principal (&cred
->server
, out
, len
);
452 rc
= put_uint16 (cred
->key
.keytype
, out
, len
);
456 rc
= put_uint16 (cred
->key
.etype
, out
, len
);
460 rc
= put_uint16 (cred
->key
.keylen
, out
, len
);
464 if (*len
< cred
->key
.keylen
)
467 memcpy (*out
, cred
->key
.keyvalue
, cred
->key
.keylen
);
469 *out
+= cred
->key
.keylen
;
470 *len
-= cred
->key
.keylen
;
472 rc
= put_uint32 (cred
->authtime
, out
, len
);
476 rc
= put_uint32 (cred
->starttime
, out
, len
);
480 rc
= put_uint32 (cred
->endtime
, out
, len
);
484 rc
= put_uint32 (cred
->renew_till
, out
, len
);
488 rc
= put_uint8 (0, out
, len
);
492 rc
= put_uint32_swapped (cred
->tktflags
, out
, len
);
496 /* XXX Write addresses. */
497 rc
= put_uint32 (0, out
, len
);
501 /* XXX Write auth-data. */
502 rc
= put_uint32 (0, out
, len
);
506 rc
= put_uint32 (cred
->ticket
.length
, out
, len
);
510 if (*len
< cred
->ticket
.length
)
512 memcpy (*out
, cred
->ticket
.data
, cred
->ticket
.length
);
513 *out
+= cred
->ticket
.length
;
514 *len
-= cred
->ticket
.length
;
516 rc
= put_uint32 (cred
->second_ticket
.length
, out
, len
);
520 if (*len
< cred
->second_ticket
.length
)
522 memcpy (*out
, cred
->second_ticket
.data
, cred
->second_ticket
.length
);
523 *out
+= cred
->second_ticket
.length
;
524 *len
-= cred
->second_ticket
.length
;
530 ccache_pack_credential (struct ccache_credential
*cred
,
531 char *out
, size_t *len
)
533 size_t savelen
= *len
;
534 int rc
= pack_credential (cred
, &out
, len
);
539 *len
= savelen
- *len
;
544 ccache_pack (struct ccache
*info
, char *data
, size_t *len
)
546 size_t savelen
= *len
;
549 rc
= put_uint16 (info
->file_format_version
550 ? info
->file_format_version
: 0x0504, &data
, len
);
554 rc
= put_uint16 (info
->headerlen
, &data
, len
);
558 if (*len
< info
->headerlen
)
560 memcpy (data
, info
->header
, info
->headerlen
);
561 data
+= info
->headerlen
;
562 *len
-= info
->headerlen
;
564 rc
= pack_principal (&info
->default_principal
, &data
, len
);
568 *len
= savelen
- *len
;
572 #if defined (TEST) || defined (ENABLE_PRINT)
574 ccache_print (struct ccache
*ccache
)
578 printf ("file_format_version %04x\n", ccache
->file_format_version
);
579 printf ("headerlen %04x\n", ccache
->headerlen
);
580 printf ("default_principal\n");
581 ccache_print_principal (&ccache
->default_principal
);
585 ccache_print_principal (struct ccache_principal
*princ
)
589 printf ("\tname_type %04x\n", princ
->name_type
);
590 printf ("\tnum_components %04x\n", princ
->num_components
);
591 printf ("\trealmlen %04x\n", princ
->realm
.length
);
592 printf ("\trealm %.*s\n", princ
->realm
.length
, princ
->realm
.data
);
594 for (n
= 0; n
< princ
->num_components
; n
++)
596 printf ("\t\tcomponentlen %04x\n", princ
->components
[n
].length
);
597 printf ("\t\tcomponent %.*s\n", princ
->components
[n
].length
,
598 princ
->components
[n
].data
);
603 ccache_print_credential (struct ccache_credential
*cred
)
606 printf ("\tclient:\n");
607 ccache_print_principal (&cred
->client
);
608 printf ("\tserver:\n");
609 ccache_print_principal (&cred
->server
);
611 printf ("\t\tkeytype %04x\n", cred
->key
.keytype
);
612 printf ("\t\tetype %04x\n", cred
->key
.etype
);
613 printf ("\t\tkeylen %04x\n", cred
->key
.keylen
);
614 printf ("\t\tkey value: ");
615 for (i
= 0; i
< cred
->key
.keylen
; i
++)
616 printf ("%02x", ((char *) cred
->key
.keyvalue
)[i
] & 0xFF);
618 printf ("\ttimes:\n");
619 printf ("\t\tauthtime %04x\n", cred
->authtime
);
620 printf ("\t\tstarttime %04x\n", cred
->starttime
);
621 printf ("\t\tendtime %04x\n", cred
->endtime
);
622 printf ("\t\trenew_till %04x\n", cred
->renew_till
);
623 printf ("\tis_skey %04x\n", cred
->is_skey
);
624 printf ("\ttktflags %04x\n", cred
->tktflags
);
625 printf ("\tticketlen %04x\n", cred
->ticket
.length
);
626 printf ("\tsecond_ticketlen %04x\n", cred
->second_ticket
.length
);
632 main (int argc
, char *argv
[])
638 struct ccache ccache
;
639 struct ccache_credential cred
;
644 printf ("Usage: %s <krb5ccache-file>\n", argv
[0]);
648 fh
= fopen (argv
[1], "rb");
651 puts ("Error: cannot open file");
655 len
= fread (buf
, 1, sizeof (buf
), fh
);
657 if (len
>= sizeof (buf
))
659 puts ("Error: file too large");
663 rc
= ccache_parse (buf
, len
, &ccache
);
666 puts ("Error: syntax error");
670 ccache_print (&ccache
);
672 while (ccache
.credentialslen
)
676 rc
= ccache_parse_credential (ccache
.credentials
,
677 ccache
.credentialslen
, &cred
, &n
);
680 printf ("Error: cannot parse credential %d\n", i
);
684 printf ("\nCredential %d:\n", i
++);
686 ccache_print_credential (&cred
);
688 ccache
.credentials
+= n
;
689 ccache
.credentialslen
-= n
;
694 puts ("Error: cannot close file");