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 3 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, see http://www.gnu.org/licenses or
16 * write to the Free Software Foundation, Inc., 51 Franklin Street,
17 * Fifth Floor, Boston, MA 02110-1301, USA
24 /* See ccache.txt for a description of the file format. Currently
25 this implementation do not support addresses nor auth-data. */
28 get_uint8 (const char **data
, size_t * len
, uint8_t * i
)
30 const char *p
= *data
;
40 get_uint16 (const char **data
, size_t * len
, uint16_t * i
)
42 const char *p
= *data
;
45 *i
= p
[0] << 8 | p
[1];
52 get_uint32 (const char **data
, size_t * len
, uint32_t * i
)
54 const char *p
= *data
;
57 *i
= ((p
[0] << 24) & 0xFF000000)
58 | ((p
[1] << 16) & 0xFF0000) | ((p
[2] << 8) & 0xFF00) | (p
[3] & 0xFF);
65 get_uint32_swapped (const char **data
, size_t * len
, uint32_t * i
)
67 const char *p
= *data
;
70 *i
= ((p
[3] << 24) & 0xFF000000)
71 | ((p
[2] << 16) & 0xFF0000) | ((p
[1] << 8) & 0xFF00) | (p
[0] & 0xFF);
78 put_uint8 (uint8_t i
, char **data
, size_t * len
)
88 put_uint16 (uint16_t i
, char **data
, size_t * len
)
92 *(*data
)++ = (i
>> 8) & 0xFF;
99 put_uint32 (uint32_t i
, char **data
, size_t * len
)
103 *(*data
)++ = (i
>> 24) & 0xFF;
104 *(*data
)++ = (i
>> 16) & 0xFF;
105 *(*data
)++ = (i
>> 8) & 0xFF;
112 put_uint32_swapped (uint32_t i
, char **data
, size_t * len
)
117 *(*data
)++ = (i
>> 8) & 0xFF;
118 *(*data
)++ = (i
>> 16) & 0xFF;
119 *(*data
)++ = (i
>> 24) & 0xFF;
125 parse_principal (const char **data
, size_t * len
,
126 struct ccache_principal
*out
)
131 rc
= get_uint32 (data
, len
, &out
->name_type
);
135 rc
= get_uint32 (data
, len
, &out
->num_components
);
139 if (out
->num_components
>= CCACHE_MAX_COMPONENTS
)
142 rc
= get_uint32 (data
, len
, &out
->realm
.length
);
146 if (*len
< out
->realm
.length
)
148 out
->realm
.data
= *data
;
149 *data
+= out
->realm
.length
;
150 *len
-= out
->realm
.length
;
152 /* Make sure realm will be zero terminated. This limits component
153 lengths to 2^24 bytes. */
154 if (**(char**)data
!= '\0')
157 for (n
= 0; n
< out
->num_components
; n
++)
159 rc
= get_uint32 (data
, len
, &out
->components
[n
].length
);
163 if (*len
< out
->components
[n
].length
)
165 out
->components
[n
].data
= *data
;
166 *data
+= out
->components
[n
].length
;
167 *len
-= out
->components
[n
].length
;
169 /* Make sure component is zero terminated. This limits the
170 length of the next component to 2^24 bytes. Note that you'll
171 have to test after the last component elsewhere. */
172 if (*len
> 0 && **(char**)data
!= '\0')
180 skip_address (const char **data
, size_t * len
)
186 rc
= get_uint16 (data
, len
, &addrtype
);
190 rc
= get_uint32 (data
, len
, &addrlen
);
203 skip_authdata (const char **data
, size_t * len
)
205 uint16_t authdatatype
;
206 uint32_t authdatalen
;
209 rc
= get_uint16 (data
, len
, &authdatatype
);
213 rc
= get_uint32 (data
, len
, &authdatalen
);
217 if (*len
< authdatalen
)
219 *data
+= authdatalen
;
226 parse_credential (const char **data
, size_t * len
,
227 struct ccache_credential
*out
)
229 struct ccache_principal princ
;
230 uint32_t num_address
;
231 uint32_t num_authdata
;
234 rc
= parse_principal (data
, len
, &out
->client
);
238 /* Make sure the last component is zero terminated. This limits the
239 next name-type to 2^24 bytes. */
240 if (*len
> 0 && **(char**)data
!= '\0')
243 rc
= parse_principal (data
, len
, &out
->server
);
247 /* Make sure the last component is zero terminated. This limits the
248 next key-type to lower 1 byte. */
249 if (*len
> 0 && **(char**)data
!= '\0')
252 rc
= get_uint16 (data
, len
, &out
->key
.keytype
);
256 rc
= get_uint16 (data
, len
, &out
->key
.etype
);
260 rc
= get_uint16 (data
, len
, &out
->key
.keylen
);
264 if (*len
< out
->key
.keylen
)
267 out
->key
.keyvalue
= *data
;
269 *data
+= out
->key
.keylen
;
270 *len
-= out
->key
.keylen
;
272 rc
= get_uint32 (data
, len
, &out
->authtime
);
276 rc
= get_uint32 (data
, len
, &out
->starttime
);
280 rc
= get_uint32 (data
, len
, &out
->endtime
);
284 rc
= get_uint32 (data
, len
, &out
->renew_till
);
288 rc
= get_uint8 (data
, len
, &out
->is_skey
);
292 rc
= get_uint32_swapped (data
, len
, &out
->tktflags
);
296 rc
= get_uint32 (data
, len
, &num_address
);
300 for (; num_address
; num_address
--)
302 /* XXX Don't just skip data. */
303 rc
= skip_address (data
, len
);
308 rc
= get_uint32 (data
, len
, &num_authdata
);
312 for (; num_authdata
; num_authdata
--)
314 /* XXX Don't just skip data. */
315 rc
= skip_authdata (data
, len
);
320 rc
= get_uint32 (data
, len
, &out
->ticket
.length
);
324 if (*len
< out
->ticket
.length
)
326 out
->ticket
.data
= *data
;
327 *data
+= out
->ticket
.length
;
328 *len
-= out
->ticket
.length
;
330 rc
= get_uint32 (data
, len
, &out
->second_ticket
.length
);
334 if (*len
< out
->second_ticket
.length
)
336 out
->second_ticket
.data
= *data
;
337 *data
+= out
->second_ticket
.length
;
338 *len
-= out
->second_ticket
.length
;
344 ccache_parse (const char *data
, size_t len
, struct ccache
*out
)
349 rc
= get_uint16 (&data
, &len
, &out
->file_format_version
);
353 rc
= get_uint16 (&data
, &len
, &out
->headerlen
);
357 if (len
< out
->headerlen
)
360 data
+= out
->headerlen
;
361 len
-= out
->headerlen
;
363 rc
= parse_principal (&data
, &len
, &out
->default_principal
);
367 out
->credentials
= data
;
368 out
->credentialslen
= len
;
374 ccache_parse_credential (const char *data
, size_t len
,
375 struct ccache_credential
*out
, size_t * n
)
377 size_t savelen
= len
;
378 int rc
= parse_credential (&data
, &len
, out
);
388 pack_principal (struct ccache_principal
*princ
,
389 char **out
, size_t * len
)
395 rc
= put_uint32 (princ
->name_type
, out
, len
);
399 rc
= put_uint32 (princ
->num_components
, out
, len
);
403 if (princ
->num_components
>= CCACHE_MAX_COMPONENTS
)
406 rc
= put_uint32 (princ
->realm
.length
, out
, len
);
410 if (*len
< princ
->realm
.length
)
412 memcpy (*out
, princ
->realm
.data
, princ
->realm
.length
);
413 *out
+= princ
->realm
.length
;
414 *len
-= princ
->realm
.length
;
416 for (n
= 0; n
< princ
->num_components
; n
++)
418 rc
= put_uint32 (princ
->components
[n
].length
, out
, len
);
422 if (*len
< princ
->components
[n
].length
)
424 memcpy (*out
, princ
->components
[n
].data
, princ
->components
[n
].length
);
425 *out
+= princ
->components
[n
].length
;
426 *len
-= princ
->components
[n
].length
;
433 pack_credential (struct ccache_credential
*cred
,
434 char **out
, size_t *len
)
436 struct ccache_principal princ
;
437 uint32_t num_address
;
438 uint32_t num_authdata
;
441 rc
= pack_principal (&cred
->client
, out
, len
);
445 rc
= pack_principal (&cred
->server
, out
, len
);
449 rc
= put_uint16 (cred
->key
.keytype
, out
, len
);
453 rc
= put_uint16 (cred
->key
.etype
, out
, len
);
457 rc
= put_uint16 (cred
->key
.keylen
, out
, len
);
461 if (*len
< cred
->key
.keylen
)
464 memcpy (*out
, cred
->key
.keyvalue
, cred
->key
.keylen
);
466 *out
+= cred
->key
.keylen
;
467 *len
-= cred
->key
.keylen
;
469 rc
= put_uint32 (cred
->authtime
, out
, len
);
473 rc
= put_uint32 (cred
->starttime
, out
, len
);
477 rc
= put_uint32 (cred
->endtime
, out
, len
);
481 rc
= put_uint32 (cred
->renew_till
, out
, len
);
485 rc
= put_uint8 (0, out
, len
);
489 rc
= put_uint32_swapped (cred
->tktflags
, out
, len
);
493 /* XXX Write addresses. */
494 rc
= put_uint32 (0, out
, len
);
498 /* XXX Write auth-data. */
499 rc
= put_uint32 (0, out
, len
);
503 rc
= put_uint32 (cred
->ticket
.length
, out
, len
);
507 if (*len
< cred
->ticket
.length
)
509 memcpy (*out
, cred
->ticket
.data
, cred
->ticket
.length
);
510 *out
+= cred
->ticket
.length
;
511 *len
-= cred
->ticket
.length
;
513 rc
= put_uint32 (cred
->second_ticket
.length
, out
, len
);
517 if (*len
< cred
->second_ticket
.length
)
519 memcpy (*out
, cred
->second_ticket
.data
, cred
->second_ticket
.length
);
520 *out
+= cred
->second_ticket
.length
;
521 *len
-= cred
->second_ticket
.length
;
527 ccache_pack_credential (struct ccache_credential
*cred
,
528 char *out
, size_t *len
)
530 size_t savelen
= *len
;
531 int rc
= pack_credential (cred
, &out
, len
);
536 *len
= savelen
- *len
;
541 ccache_pack (struct ccache
*info
, char *data
, size_t *len
)
543 size_t savelen
= *len
;
546 rc
= put_uint16 (info
->file_format_version
547 ? info
->file_format_version
: 0x0504, &data
, len
);
551 rc
= put_uint16 (info
->headerlen
, &data
, len
);
555 if (*len
< info
->headerlen
)
557 memcpy (data
, info
->header
, info
->headerlen
);
558 data
+= info
->headerlen
;
559 *len
-= info
->headerlen
;
561 rc
= pack_principal (&info
->default_principal
, &data
, len
);
565 *len
= savelen
- *len
;
570 ccache_print (struct ccache
*ccache
)
574 printf ("file_format_version %04x\n", ccache
->file_format_version
);
575 printf ("headerlen %04x\n", ccache
->headerlen
);
576 printf ("default_principal\n");
577 ccache_print_principal (&ccache
->default_principal
);
581 ccache_print_principal (struct ccache_principal
*princ
)
585 printf ("\tname_type %04x\n", princ
->name_type
);
586 printf ("\tnum_components %04x\n", princ
->num_components
);
587 printf ("\trealmlen %04x\n", princ
->realm
.length
);
588 printf ("\trealm %.*s\n", princ
->realm
.length
, princ
->realm
.data
);
590 for (n
= 0; n
< princ
->num_components
; n
++)
592 printf ("\t\tcomponentlen %04x\n", princ
->components
[n
].length
);
593 printf ("\t\tcomponent %.*s\n", princ
->components
[n
].length
,
594 princ
->components
[n
].data
);
599 ccache_print_credential (struct ccache_credential
*cred
)
602 printf ("\tclient:\n");
603 ccache_print_principal (&cred
->client
);
604 printf ("\tserver:\n");
605 ccache_print_principal (&cred
->server
);
607 printf ("\t\tkeytype %04x\n", cred
->key
.keytype
);
608 printf ("\t\tetype %04x\n", cred
->key
.etype
);
609 printf ("\t\tkeylen %04x\n", cred
->key
.keylen
);
610 printf ("\t\tkey value: ");
611 for (i
= 0; i
< cred
->key
.keylen
; i
++)
612 printf ("%02x", ((char *) cred
->key
.keyvalue
)[i
] & 0xFF);
614 printf ("\ttimes:\n");
615 printf ("\t\tauthtime %04x\n", cred
->authtime
);
616 printf ("\t\tstarttime %04x\n", cred
->starttime
);
617 printf ("\t\tendtime %04x\n", cred
->endtime
);
618 printf ("\t\trenew_till %04x\n", cred
->renew_till
);
619 printf ("\tis_skey %04x\n", cred
->is_skey
);
620 printf ("\ttktflags %04x\n", cred
->tktflags
);
621 printf ("\tticketlen %04x\n", cred
->ticket
.length
);
622 printf ("\tsecond_ticketlen %04x\n", cred
->second_ticket
.length
);
627 main (int argc
, char *argv
[])
633 struct ccache ccache
;
634 struct ccache_credential cred
;
639 printf ("Usage: %s <krb5ccache-file>\n", argv
[0]);
643 fh
= fopen (argv
[1], "rb");
646 puts ("Error: cannot open file");
650 len
= fread (buf
, 1, sizeof (buf
), fh
);
652 if (len
>= sizeof (buf
))
654 puts ("Error: file too large");
658 rc
= ccache_parse (buf
, len
, &ccache
);
661 puts ("Error: syntax error");
665 ccache_print (&ccache
);
667 while (ccache
.credentialslen
)
671 rc
= ccache_parse_credential (ccache
.credentials
,
672 ccache
.credentialslen
, &cred
, &n
);
675 printf ("Error: cannot parse credential %d\n", i
);
679 printf ("\nCredential %d:\n", i
++);
681 ccache_print_credential (&cred
);
683 ccache
.credentials
+= n
;
684 ccache
.credentialslen
-= n
;
689 puts ("Error: cannot close file");