Branch data Line data Source code
1 : : /* ccache.c --- Read MIT style Kerberos Credential Cache file.
2 : : * Copyright (C) 2006, 2007, 2008 Simon Josefsson
3 : : *
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.
8 : : *
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.
13 : : *
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
18 : : *
19 : : */
20 : :
21 : : #include "ccache.h"
22 : : #include <stdio.h>
23 : :
24 : : /* See ccache.txt for a description of the file format. Currently
25 : : this implementation do not support addresses nor auth-data. */
26 : :
27 : : static int
28 : 2 : get_uint8 (const char **data, size_t * len, uint8_t * i)
29 : : {
30 : 2 : const char *p = *data;
31 [ - + ]: 2 : if (*len < 1)
32 : 0 : return -1;
33 : 2 : *i = p[0];
34 : 2 : *data += 1;
35 : 2 : *len -= 1;
36 : 2 : return 0;
37 : : }
38 : :
39 : : static int
40 : 8 : get_uint16 (const char **data, size_t * len, uint16_t * i)
41 : : {
42 : 8 : const char *p = *data;
43 [ - + ]: 8 : if (*len < 2)
44 : 0 : return -1;
45 : 8 : *i = p[0] << 8 | p[1];
46 : 8 : *data += 2;
47 : 8 : *len -= 2;
48 : 8 : return 0;
49 : : }
50 : :
51 : : static int
52 : 38 : get_uint32 (const char **data, size_t * len, uint32_t * i)
53 : : {
54 : 38 : const char *p = *data;
55 [ - + ]: 38 : if (*len < 4)
56 : 0 : return -1;
57 : 76 : *i = ((p[0] << 24) & 0xFF000000)
58 : 38 : | ((p[1] << 16) & 0xFF0000) | ((p[2] << 8) & 0xFF00) | (p[3] & 0xFF);
59 : 38 : *data += 4;
60 : 38 : *len -= 4;
61 : 38 : return 0;
62 : : }
63 : :
64 : : static int
65 : 2 : get_uint32_swapped (const char **data, size_t * len, uint32_t * i)
66 : : {
67 : 2 : const char *p = *data;
68 [ - + ]: 2 : if (*len < 4)
69 : 0 : return -1;
70 : 4 : *i = ((p[3] << 24) & 0xFF000000)
71 : 2 : | ((p[2] << 16) & 0xFF0000) | ((p[1] << 8) & 0xFF00) | (p[0] & 0xFF);
72 : 2 : *data += 4;
73 : 2 : *len -= 4;
74 : 2 : return 0;
75 : : }
76 : :
77 : : static int
78 : 0 : put_uint8 (uint8_t i, char **data, size_t * len)
79 : : {
80 [ # # ]: 0 : if (*len < 1)
81 : 0 : return -1;
82 : 0 : *(*data)++ = i;
83 : 0 : *len -= 1;
84 : 0 : return 0;
85 : : }
86 : :
87 : : static int
88 : 0 : put_uint16 (uint16_t i, char **data, size_t * len)
89 : : {
90 [ # # ]: 0 : if (*len < 2)
91 : 0 : return -1;
92 : 0 : *(*data)++ = (i >> 8) & 0xFF;
93 : 0 : *(*data)++ = i;
94 : 0 : *len -= 2;
95 : 0 : return 0;
96 : : }
97 : :
98 : : static int
99 : 0 : put_uint32 (uint32_t i, char **data, size_t * len)
100 : : {
101 [ # # ]: 0 : if (*len < 4)
102 : 0 : return -1;
103 : 0 : *(*data)++ = (i >> 24) & 0xFF;
104 : 0 : *(*data)++ = (i >> 16) & 0xFF;
105 : 0 : *(*data)++ = (i >> 8) & 0xFF;
106 : 0 : *(*data)++ = i;
107 : 0 : *len -= 4;
108 : 0 : return 0;
109 : : }
110 : :
111 : : static int
112 : 0 : put_uint32_swapped (uint32_t i, char **data, size_t * len)
113 : : {
114 [ # # ]: 0 : if (*len < 4)
115 : 0 : return -1;
116 : 0 : *(*data)++ = i;
117 : 0 : *(*data)++ = (i >> 8) & 0xFF;
118 : 0 : *(*data)++ = (i >> 16) & 0xFF;
119 : 0 : *(*data)++ = (i >> 24) & 0xFF;
120 : 0 : *len -= 4;
121 : 0 : return 0;
122 : : }
123 : :
124 : : static int
125 : 5 : parse_principal (const char **data, size_t * len,
126 : : struct ccache_principal *out)
127 : : {
128 : : size_t n;
129 : : int rc;
130 : :
131 : 5 : rc = get_uint32 (data, len, &out->name_type);
132 [ - + ]: 5 : if (rc < 0)
133 : 0 : return rc;
134 : :
135 : 5 : rc = get_uint32 (data, len, &out->num_components);
136 [ - + ]: 5 : if (rc < 0)
137 : 0 : return rc;
138 : :
139 [ - + ]: 5 : if (out->num_components >= CCACHE_MAX_COMPONENTS)
140 : 0 : return -1;
141 : :
142 : 5 : rc = get_uint32 (data, len, &out->realm.length);
143 [ - + ]: 5 : if (rc < 0)
144 : 0 : return rc;
145 : :
146 [ - + ]: 5 : if (*len < out->realm.length)
147 : 0 : return -1;
148 : 5 : out->realm.data = (char *) *data;
149 : 5 : *data += out->realm.length;
150 : 5 : *len -= out->realm.length;
151 : :
152 : : /* Make sure realm will be zero terminated. This limits component
153 : : lengths to 2^24 bytes. */
154 [ - + ]: 5 : if (**(char **) data != '\0')
155 : 0 : return -1;
156 : :
157 [ + + ]: 12 : for (n = 0; n < out->num_components; n++)
158 : : {
159 : 7 : rc = get_uint32 (data, len, &out->components[n].length);
160 [ - + ]: 7 : if (rc < 0)
161 : 0 : return rc;
162 : :
163 [ - + ]: 7 : if (*len < out->components[n].length)
164 : 0 : return -1;
165 : 7 : out->components[n].data = (char *) *data;
166 : 7 : *data += out->components[n].length;
167 : 7 : *len -= out->components[n].length;
168 : :
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 [ + - ][ - + ]: 7 : if (*len > 0 && **(char **) data != '\0')
173 : 0 : return -1;
174 : : }
175 : :
176 : 5 : return 0;
177 : : }
178 : :
179 : : static int
180 : 0 : skip_address (const char **data, size_t * len)
181 : : {
182 : : uint16_t addrtype;
183 : : uint32_t addrlen;
184 : : int rc;
185 : :
186 : 0 : rc = get_uint16 (data, len, &addrtype);
187 [ # # ]: 0 : if (rc < 0)
188 : 0 : return rc;
189 : :
190 : 0 : rc = get_uint32 (data, len, &addrlen);
191 [ # # ]: 0 : if (rc < 0)
192 : 0 : return rc;
193 : :
194 [ # # ]: 0 : if (*len < addrlen)
195 : 0 : return -1;
196 : 0 : *data += addrlen;
197 : 0 : *len -= addrlen;
198 : :
199 : 0 : return 0;
200 : : }
201 : :
202 : : static int
203 : 0 : skip_authdata (const char **data, size_t * len)
204 : : {
205 : : uint16_t authdatatype;
206 : : uint32_t authdatalen;
207 : : int rc;
208 : :
209 : 0 : rc = get_uint16 (data, len, &authdatatype);
210 [ # # ]: 0 : if (rc < 0)
211 : 0 : return rc;
212 : :
213 : 0 : rc = get_uint32 (data, len, &authdatalen);
214 [ # # ]: 0 : if (rc < 0)
215 : 0 : return rc;
216 : :
217 [ # # ]: 0 : if (*len < authdatalen)
218 : 0 : return -1;
219 : 0 : *data += authdatalen;
220 : 0 : *len -= authdatalen;
221 : :
222 : 0 : return 0;
223 : : }
224 : :
225 : : static int
226 : 2 : parse_credential (const char **data, size_t * len,
227 : : struct ccache_credential *out)
228 : : {
229 : : uint32_t num_address;
230 : : uint32_t num_authdata;
231 : : int rc;
232 : :
233 : 2 : rc = parse_principal (data, len, &out->client);
234 [ - + ]: 2 : if (rc < 0)
235 : 0 : return rc;
236 : :
237 : : /* Make sure the last component is zero terminated. This limits the
238 : : next name-type to 2^24 bytes. */
239 [ + - ][ - + ]: 2 : if (*len > 0 && **(char **) data != '\0')
240 : 0 : return -1;
241 : :
242 : 2 : rc = parse_principal (data, len, &out->server);
243 [ - + ]: 2 : if (rc < 0)
244 : 0 : return rc;
245 : :
246 : : /* Make sure the last component is zero terminated. This limits the
247 : : next key-type to lower 1 byte. */
248 [ + - ][ - + ]: 2 : if (*len > 0 && **(char **) data != '\0')
249 : 0 : return -1;
250 : :
251 : 2 : rc = get_uint16 (data, len, &out->key.keytype);
252 [ - + ]: 2 : if (rc < 0)
253 : 0 : return rc;
254 : :
255 : 2 : rc = get_uint16 (data, len, &out->key.etype);
256 [ - + ]: 2 : if (rc < 0)
257 : 0 : return rc;
258 : :
259 : 2 : rc = get_uint16 (data, len, &out->key.keylen);
260 [ - + ]: 2 : if (rc < 0)
261 : 0 : return rc;
262 : :
263 [ - + ]: 2 : if (*len < out->key.keylen)
264 : 0 : return -1;
265 : :
266 : 2 : out->key.keyvalue = (char *) *data;
267 : :
268 : 2 : *data += out->key.keylen;
269 : 2 : *len -= out->key.keylen;
270 : :
271 : 2 : rc = get_uint32 (data, len, &out->authtime);
272 [ - + ]: 2 : if (rc < 0)
273 : 0 : return rc;
274 : :
275 : 2 : rc = get_uint32 (data, len, &out->starttime);
276 [ - + ]: 2 : if (rc < 0)
277 : 0 : return rc;
278 : :
279 : 2 : rc = get_uint32 (data, len, &out->endtime);
280 [ - + ]: 2 : if (rc < 0)
281 : 0 : return rc;
282 : :
283 : 2 : rc = get_uint32 (data, len, &out->renew_till);
284 [ - + ]: 2 : if (rc < 0)
285 : 0 : return rc;
286 : :
287 : 2 : rc = get_uint8 (data, len, &out->is_skey);
288 [ - + ]: 2 : if (rc < 0)
289 : 0 : return rc;
290 : :
291 : 2 : rc = get_uint32_swapped (data, len, &out->tktflags);
292 [ - + ]: 2 : if (rc < 0)
293 : 0 : return rc;
294 : :
295 : 2 : rc = get_uint32 (data, len, &num_address);
296 [ - + ]: 2 : if (rc < 0)
297 : 0 : return rc;
298 : :
299 [ - + ]: 2 : for (; num_address; num_address--)
300 : : {
301 : : /* XXX Don't just skip data. */
302 : 0 : rc = skip_address (data, len);
303 [ # # ]: 0 : if (rc < 0)
304 : 0 : return rc;
305 : : }
306 : :
307 : 2 : rc = get_uint32 (data, len, &num_authdata);
308 [ - + ]: 2 : if (rc < 0)
309 : 0 : return rc;
310 : :
311 [ - + ]: 2 : for (; num_authdata; num_authdata--)
312 : : {
313 : : /* XXX Don't just skip data. */
314 : 0 : rc = skip_authdata (data, len);
315 [ # # ]: 0 : if (rc < 0)
316 : 0 : return rc;
317 : : }
318 : :
319 : 2 : rc = get_uint32 (data, len, &out->ticket.length);
320 [ - + ]: 2 : if (rc < 0)
321 : 0 : return rc;
322 : :
323 [ - + ]: 2 : if (*len < out->ticket.length)
324 : 0 : return -1;
325 : 2 : out->ticket.data = (char *) *data;
326 : 2 : *data += out->ticket.length;
327 : 2 : *len -= out->ticket.length;
328 : :
329 : 2 : rc = get_uint32 (data, len, &out->second_ticket.length);
330 [ - + ]: 2 : if (rc < 0)
331 : 0 : return rc;
332 : :
333 [ - + ]: 2 : if (*len < out->second_ticket.length)
334 : 0 : return -1;
335 : 2 : out->second_ticket.data = (char *) *data;
336 : 2 : *data += out->second_ticket.length;
337 : 2 : *len -= out->second_ticket.length;
338 : :
339 : 2 : return 0;
340 : : }
341 : :
342 : : int
343 : 1 : ccache_parse (const char *data, size_t len, struct ccache *out)
344 : : {
345 : : int rc;
346 : :
347 : 1 : rc = get_uint16 (&data, &len, &out->file_format_version);
348 [ - + ]: 1 : if (rc < 0)
349 : 0 : return rc;
350 : :
351 : 1 : rc = get_uint16 (&data, &len, &out->headerlen);
352 [ - + ]: 1 : if (rc < 0)
353 : 0 : return rc;
354 : :
355 [ - + ]: 1 : if (len < out->headerlen)
356 : 0 : return -1;
357 : 1 : out->header = (char *) data;
358 : 1 : data += out->headerlen;
359 : 1 : len -= out->headerlen;
360 : :
361 : 1 : rc = parse_principal (&data, &len, &out->default_principal);
362 [ - + ]: 1 : if (rc < 0)
363 : 0 : return rc;
364 : :
365 : 1 : out->credentials = (char *) data;
366 : 1 : out->credentialslen = len;
367 : :
368 : 1 : return 0;
369 : : }
370 : :
371 : : int
372 : 2 : ccache_parse_credential (const char *data, size_t len,
373 : : struct ccache_credential *out, size_t * n)
374 : : {
375 : 2 : size_t savelen = len;
376 : 2 : int rc = parse_credential (&data, &len, out);
377 : :
378 [ - + ]: 2 : if (rc < 0)
379 : 0 : return rc;
380 : :
381 : 2 : *n = savelen - len;
382 : 2 : return 0;
383 : : }
384 : :
385 : : static int
386 : 0 : pack_principal (struct ccache_principal *princ, char **out, size_t * len)
387 : : {
388 : : size_t n;
389 : : int rc;
390 : :
391 : 0 : rc = put_uint32 (princ->name_type, out, len);
392 [ # # ]: 0 : if (rc < 0)
393 : 0 : return rc;
394 : :
395 : 0 : rc = put_uint32 (princ->num_components, out, len);
396 [ # # ]: 0 : if (rc < 0)
397 : 0 : return rc;
398 : :
399 [ # # ]: 0 : if (princ->num_components >= CCACHE_MAX_COMPONENTS)
400 : 0 : return -1;
401 : :
402 : 0 : rc = put_uint32 (princ->realm.length, out, len);
403 [ # # ]: 0 : if (rc < 0)
404 : 0 : return rc;
405 : :
406 [ # # ]: 0 : if (*len < princ->realm.length)
407 : 0 : return -1;
408 : 0 : memcpy (*out, princ->realm.data, princ->realm.length);
409 : 0 : *out += princ->realm.length;
410 : 0 : *len -= princ->realm.length;
411 : :
412 [ # # ]: 0 : for (n = 0; n < princ->num_components; n++)
413 : : {
414 : 0 : rc = put_uint32 (princ->components[n].length, out, len);
415 [ # # ]: 0 : if (rc < 0)
416 : 0 : return rc;
417 : :
418 [ # # ]: 0 : if (*len < princ->components[n].length)
419 : 0 : return -1;
420 : 0 : memcpy (*out, princ->components[n].data, princ->components[n].length);
421 : 0 : *out += princ->components[n].length;
422 : 0 : *len -= princ->components[n].length;
423 : : }
424 : :
425 : 0 : return 0;
426 : : }
427 : :
428 : : static int
429 : 0 : pack_credential (struct ccache_credential *cred, char **out, size_t * len)
430 : : {
431 : : int rc;
432 : :
433 : 0 : rc = pack_principal (&cred->client, out, len);
434 [ # # ]: 0 : if (rc < 0)
435 : 0 : return rc;
436 : :
437 : 0 : rc = pack_principal (&cred->server, out, len);
438 [ # # ]: 0 : if (rc < 0)
439 : 0 : return rc;
440 : :
441 : 0 : rc = put_uint16 (cred->key.keytype, out, len);
442 [ # # ]: 0 : if (rc < 0)
443 : 0 : return rc;
444 : :
445 : 0 : rc = put_uint16 (cred->key.etype, out, len);
446 [ # # ]: 0 : if (rc < 0)
447 : 0 : return rc;
448 : :
449 : 0 : rc = put_uint16 (cred->key.keylen, out, len);
450 [ # # ]: 0 : if (rc < 0)
451 : 0 : return rc;
452 : :
453 [ # # ]: 0 : if (*len < cred->key.keylen)
454 : 0 : return -1;
455 : :
456 : 0 : memcpy (*out, cred->key.keyvalue, cred->key.keylen);
457 : :
458 : 0 : *out += cred->key.keylen;
459 : 0 : *len -= cred->key.keylen;
460 : :
461 : 0 : rc = put_uint32 (cred->authtime, out, len);
462 [ # # ]: 0 : if (rc < 0)
463 : 0 : return rc;
464 : :
465 : 0 : rc = put_uint32 (cred->starttime, out, len);
466 [ # # ]: 0 : if (rc < 0)
467 : 0 : return rc;
468 : :
469 : 0 : rc = put_uint32 (cred->endtime, out, len);
470 [ # # ]: 0 : if (rc < 0)
471 : 0 : return rc;
472 : :
473 : 0 : rc = put_uint32 (cred->renew_till, out, len);
474 [ # # ]: 0 : if (rc < 0)
475 : 0 : return rc;
476 : :
477 : 0 : rc = put_uint8 (0, out, len);
478 [ # # ]: 0 : if (rc < 0)
479 : 0 : return rc;
480 : :
481 : 0 : rc = put_uint32_swapped (cred->tktflags, out, len);
482 [ # # ]: 0 : if (rc < 0)
483 : 0 : return rc;
484 : :
485 : : /* XXX Write addresses. */
486 : 0 : rc = put_uint32 (0, out, len);
487 [ # # ]: 0 : if (rc < 0)
488 : 0 : return rc;
489 : :
490 : : /* XXX Write auth-data. */
491 : 0 : rc = put_uint32 (0, out, len);
492 [ # # ]: 0 : if (rc < 0)
493 : 0 : return rc;
494 : :
495 : 0 : rc = put_uint32 (cred->ticket.length, out, len);
496 [ # # ]: 0 : if (rc < 0)
497 : 0 : return rc;
498 : :
499 [ # # ]: 0 : if (*len < cred->ticket.length)
500 : 0 : return -1;
501 : 0 : memcpy (*out, cred->ticket.data, cred->ticket.length);
502 : 0 : *out += cred->ticket.length;
503 : 0 : *len -= cred->ticket.length;
504 : :
505 : 0 : rc = put_uint32 (cred->second_ticket.length, out, len);
506 [ # # ]: 0 : if (rc < 0)
507 : 0 : return rc;
508 : :
509 [ # # ]: 0 : if (*len < cred->second_ticket.length)
510 : 0 : return -1;
511 : 0 : memcpy (*out, cred->second_ticket.data, cred->second_ticket.length);
512 : 0 : *out += cred->second_ticket.length;
513 : 0 : *len -= cred->second_ticket.length;
514 : :
515 : 0 : return 0;
516 : : }
517 : :
518 : : int
519 : 0 : ccache_pack_credential (struct ccache_credential *cred,
520 : : char *out, size_t * len)
521 : : {
522 : 0 : size_t savelen = *len;
523 : 0 : int rc = pack_credential (cred, &out, len);
524 : :
525 [ # # ]: 0 : if (rc < 0)
526 : 0 : return rc;
527 : :
528 : 0 : *len = savelen - *len;
529 : 0 : return 0;
530 : : }
531 : :
532 : : int
533 : 0 : ccache_pack (struct ccache *info, char *data, size_t * len)
534 : : {
535 : 0 : size_t savelen = *len;
536 : : int rc;
537 : :
538 [ # # ]: 0 : rc = put_uint16 (info->file_format_version
539 : 0 : ? info->file_format_version : 0x0504, &data, len);
540 [ # # ]: 0 : if (rc < 0)
541 : 0 : return rc;
542 : :
543 : 0 : rc = put_uint16 (info->headerlen, &data, len);
544 [ # # ]: 0 : if (rc < 0)
545 : 0 : return rc;
546 : :
547 [ # # ]: 0 : if (*len < info->headerlen)
548 : 0 : return -1;
549 : 0 : memcpy (data, info->header, info->headerlen);
550 : 0 : data += info->headerlen;
551 : 0 : *len -= info->headerlen;
552 : :
553 : 0 : rc = pack_principal (&info->default_principal, &data, len);
554 [ # # ]: 0 : if (rc < 0)
555 : 0 : return rc;
556 : :
557 : 0 : *len = savelen - *len;
558 : 0 : return 0;
559 : : }
560 : :
561 : : void
562 : 0 : ccache_print (struct ccache *ccache)
563 : : {
564 : 0 : printf ("file_format_version %04x\n", ccache->file_format_version);
565 : 0 : printf ("headerlen %04x\n", ccache->headerlen);
566 : 0 : printf ("default_principal\n");
567 : 0 : ccache_print_principal (&ccache->default_principal);
568 : 0 : }
569 : :
570 : : void
571 : 0 : ccache_print_principal (struct ccache_principal *princ)
572 : : {
573 : : size_t n;
574 : :
575 : 0 : printf ("\tname_type %04x\n", princ->name_type);
576 : 0 : printf ("\tnum_components %04x\n", princ->num_components);
577 : 0 : printf ("\trealmlen %04x\n", princ->realm.length);
578 : 0 : printf ("\trealm %.*s\n", princ->realm.length, princ->realm.data);
579 : :
580 [ # # ]: 0 : for (n = 0; n < princ->num_components; n++)
581 : : {
582 : 0 : printf ("\t\tcomponentlen %04x\n", princ->components[n].length);
583 : 0 : printf ("\t\tcomponent %.*s\n", princ->components[n].length,
584 : : princ->components[n].data);
585 : : }
586 : 0 : }
587 : :
588 : : void
589 : 0 : ccache_print_credential (struct ccache_credential *cred)
590 : : {
591 : : size_t i;
592 : 0 : printf ("\tclient:\n");
593 : 0 : ccache_print_principal (&cred->client);
594 : 0 : printf ("\tserver:\n");
595 : 0 : ccache_print_principal (&cred->server);
596 : 0 : printf ("\tkey:\n");
597 : 0 : printf ("\t\tkeytype %04x\n", cred->key.keytype);
598 : 0 : printf ("\t\tetype %04x\n", cred->key.etype);
599 : 0 : printf ("\t\tkeylen %04x\n", cred->key.keylen);
600 : 0 : printf ("\t\tkey value: ");
601 [ # # ]: 0 : for (i = 0; i < cred->key.keylen; i++)
602 : 0 : printf ("%02x", ((char *) cred->key.keyvalue)[i] & 0xFF);
603 : 0 : printf ("\n");
604 : 0 : printf ("\ttimes:\n");
605 : 0 : printf ("\t\tauthtime %04x\n", cred->authtime);
606 : 0 : printf ("\t\tstarttime %04x\n", cred->starttime);
607 : 0 : printf ("\t\tendtime %04x\n", cred->endtime);
608 : 0 : printf ("\t\trenew_till %04x\n", cred->renew_till);
609 : 0 : printf ("\tis_skey %04x\n", cred->is_skey);
610 : 0 : printf ("\ttktflags %04x\n", cred->tktflags);
611 : 0 : printf ("\tticketlen %04x\n", cred->ticket.length);
612 : 0 : printf ("\tsecond_ticketlen %04x\n", cred->second_ticket.length);
613 : 0 : }
614 : :
615 : : #ifdef TEST
616 : : int
617 : : main (int argc, char *argv[])
618 : : {
619 : : char buf[10240];
620 : : size_t len;
621 : : FILE *fh;
622 : : int rc;
623 : : struct ccache ccache;
624 : : struct ccache_credential cred;
625 : : size_t i = 0;
626 : :
627 : : if (argc <= 1)
628 : : {
629 : : printf ("Usage: %s <krb5ccache-file>\n", argv[0]);
630 : : return 1;
631 : : }
632 : :
633 : : fh = fopen (argv[1], "rb");
634 : : if (!fh)
635 : : {
636 : : puts ("Error: cannot open file");
637 : : return 1;
638 : : }
639 : :
640 : : len = fread (buf, 1, sizeof (buf), fh);
641 : :
642 : : if (len >= sizeof (buf))
643 : : {
644 : : puts ("Error: file too large");
645 : : return 1;
646 : : }
647 : :
648 : : rc = ccache_parse (buf, len, &ccache);
649 : : if (rc < 0)
650 : : {
651 : : puts ("Error: syntax error");
652 : : return 1;
653 : : }
654 : :
655 : : ccache_print (&ccache);
656 : :
657 : : while (ccache.credentialslen)
658 : : {
659 : : size_t n;
660 : :
661 : : rc = ccache_parse_credential (ccache.credentials,
662 : : ccache.credentialslen, &cred, &n);
663 : : if (rc < 0)
664 : : {
665 : : printf ("Error: cannot parse credential %d\n", i);
666 : : return rc;
667 : : }
668 : :
669 : : printf ("\nCredential %d:\n", i++);
670 : :
671 : : ccache_print_credential (&cred);
672 : :
673 : : ccache.credentials += n;
674 : : ccache.credentialslen -= n;
675 : : }
676 : :
677 : : if (fclose (fh))
678 : : {
679 : : puts ("Error: cannot close file");
680 : : return 1;
681 : : }
682 : :
683 : : return 0;
684 : : }
685 : : #endif
|