Change GPLv2+ to GPLv3+.
[shishi.git] / lib / tktccache.c
blob27edbeaf8fbc85fff60a23beb49707601fee9e9d
1 /* ccache.c --- Credential Cache compatibility ticket set handling.
2 * Copyright (C) 2002, 2003, 2004, 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 3 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 "internal.h"
23 #include "ccache.h"
25 /**
26 * shishi_tkts_default_ccache_guess:
27 * @handle: Shishi library handle create by shishi_init().
29 * Guesses the default ccache ticket filename; it is the contents of
30 * the environment variable KRB5CCNAME or /tmp/krb5cc_<UID> where
31 * <UID> is the user's identity in decimal, as returned by getuid().
33 * Return value: Returns default ccache filename as a string that has
34 * to be deallocated with free() by the caller.
35 **/
36 char *
37 shishi_tkts_default_ccache_guess (Shishi * handle)
39 char *envfile;
41 envfile = getenv ("KRB5CCNAME");
42 if (envfile)
43 return xstrdup (envfile);
45 return xasprintf("/tmp/krb5cc_%u", (unsigned long) getuid ());
48 /**
49 * shishi_tkts_default_ccache:
50 * @handle: Shishi library handle create by shishi_init().
52 * Get filename of default ccache filename.
54 * Return value: Returns the default ccache filename used in the
55 * library. The string is not a copy, so don't modify or deallocate
56 * it.
57 **/
58 const char *
59 shishi_tkts_default_ccache (Shishi * handle)
61 if (!handle->ccachedefault)
63 char *p;
65 p = shishi_tkts_default_ccache_guess (handle);
66 shishi_tkts_default_ccache_set (handle, p);
67 free (p);
70 return handle->ccachedefault;
73 /**
74 * shishi_tkts_default_ccache_set:
75 * @handle: Shishi library handle create by shishi_init().
76 * @ccache: string with new default ccache filename, or
77 * NULL to reset to default.
79 * Set the default ccache filename used in the library. The string is
80 * copied into the library, so you can dispose of the variable
81 * immediately after calling this function.
82 **/
83 void
84 shishi_tkts_default_ccache_set (Shishi * handle, const char *ccache)
86 if (handle->ccachedefault)
87 free (handle->ccachedefault);
88 if (ccache)
89 handle->ccachedefault = xstrdup (ccache);
90 else
91 handle->ccachedefault = NULL;
94 /**
95 * shishi_tkts_add_ccache_mem:
96 * @handle: shishi handle as allocated by shishi_init().
97 * @data: constant memory buffer with ccache of @len size.
98 * @len: size of memory buffer with ccache data.
99 * @tkts: allocated key set to store tickets in.
101 * Read tickets from a ccache data structure, and add them to the
102 * ticket set.
104 * The ccache format is proprietary, and this function support (at
105 * least) the 0x0504 format. See the section The Credential Cache
106 * Binary File Format in the Shishi manual for a description of the
107 * file format.
109 * Returns: Returns %SHISHI_CCACHE_ERROR if the data does not
110 * represent a valid ccache structure, and %SHISHI_OK on success.
113 shishi_tkts_add_ccache_mem (Shishi * handle,
114 const char *data, size_t len,
115 Shishi_tkts *tkts)
117 int rc = SHISHI_OK;
118 struct ccache ccache;
120 if (VERBOSENOISE (handle))
122 printf ("ccache len %d (0x%x)\n", len, len);
123 _shishi_hexprint (data, len);
126 rc = ccache_parse (data, len, &ccache);
127 if (rc < 0)
128 return SHISHI_CCACHE_ERROR;
130 if (VERBOSENOISE (handle))
131 ccache_print (&ccache);
133 while (ccache.credentialslen)
135 struct ccache_credential cred;
136 Shishi_tkt *tkt;
137 Shishi_asn1 ticket;
138 size_t n;
140 rc = ccache_parse_credential (ccache.credentials,
141 ccache.credentialslen, &cred, &n);
142 if (rc < 0)
143 return SHISHI_CCACHE_ERROR;
145 if (VERBOSENOISE (handle))
146 ccache_print_credential (&cred);
148 /* Sanity check credential first. */
150 if (shishi_cipher_keylen (cred.key.keytype) != cred.key.keylen)
151 continue;
153 ticket = shishi_der2asn1_ticket (handle, cred.ticket.data,
154 cred.ticket.length);
155 if (!ticket)
156 continue;
158 /* Let's create a new ticket... */
160 rc = shishi_tkt (handle, &tkt);
161 if (rc != SHISHI_OK)
162 return rc;
164 shishi_tkt_ticket_set (tkt, ticket);
167 char *cname[CCACHE_MAX_COMPONENTS + 1];
168 size_t i;
170 for (i = 0; i < cred.client.num_components
171 && i < CCACHE_MAX_COMPONENTS; i++)
172 cname[i] = cred.client.components[i].data;
173 cname[i] = NULL;
175 rc = shishi_kdcrep_crealm_set (handle,
176 shishi_tkt_kdcrep (tkt),
177 cred.client.realm.data);
178 if (rc != SHISHI_OK)
179 return rc;
181 rc = shishi_kdcrep_cname_set (handle,
182 shishi_tkt_kdcrep (tkt),
183 cred.client.name_type,
184 cname);
185 if (rc != SHISHI_OK)
186 return rc;
190 char *sname[CCACHE_MAX_COMPONENTS + 1];
191 size_t i;
193 for (i = 0; i < cred.server.num_components
194 && i < CCACHE_MAX_COMPONENTS; i++)
195 sname[i] = cred.server.components[i].data;
196 sname[i] = NULL;
198 rc = shishi_enckdcreppart_srealm_set (handle,
199 shishi_tkt_enckdcreppart (tkt),
200 cred.server.realm.data);
201 if (rc != SHISHI_OK)
202 return rc;
204 rc = shishi_enckdcreppart_sname_set (handle,
205 shishi_tkt_enckdcreppart (tkt),
206 cred.server.name_type,
207 sname);
208 if (rc != SHISHI_OK)
209 return rc;
212 rc = shishi_tkt_flags_set (tkt, cred.tktflags);
213 if (rc != SHISHI_OK)
214 return rc;
216 rc = shishi_enckdcreppart_authtime_set
217 (handle,
218 shishi_tkt_enckdcreppart (tkt),
219 shishi_generalize_time (handle, cred.authtime));
220 if (rc != SHISHI_OK)
221 return rc;
223 rc = shishi_enckdcreppart_starttime_set
224 (handle,
225 shishi_tkt_enckdcreppart (tkt),
226 cred.starttime ? shishi_generalize_time (handle, cred.starttime)
227 : NULL);
228 if (rc != SHISHI_OK)
229 return rc;
231 rc = shishi_enckdcreppart_endtime_set
232 (handle,
233 shishi_tkt_enckdcreppart (tkt),
234 shishi_generalize_time (handle, cred.endtime));
235 if (rc != SHISHI_OK)
236 return rc;
238 rc = shishi_enckdcreppart_renew_till_set
239 (handle,
240 shishi_tkt_enckdcreppart (tkt),
241 cred.renew_till ? shishi_generalize_time (handle, cred.renew_till)
242 : NULL);
243 if (rc != SHISHI_OK)
244 return rc;
247 uint32_t nonce = 0;
248 rc = shishi_enckdcreppart_nonce_set (handle,
249 shishi_tkt_enckdcreppart (tkt),
250 nonce);
251 if (rc != SHISHI_OK)
252 return rc;
255 rc = shishi_kdcrep_set_ticket (handle, shishi_tkt_kdcrep (tkt),
256 shishi_tkt_ticket (tkt));
257 if (rc != SHISHI_OK)
258 return rc;
260 rc = shishi_kdcrep_set_enc_part (handle, shishi_tkt_kdcrep (tkt),
261 0, 0, "", 0);
262 if (rc != SHISHI_OK)
263 return rc;
265 /* Add key. */
268 Shishi_key *key;
270 rc = shishi_key (handle, &key);
271 if (rc != SHISHI_OK)
272 return rc;
274 shishi_key_type_set (key, cred.key.keytype);
275 shishi_key_value_set (key, cred.key.keyvalue);
276 rc = shishi_tkt_key_set (tkt, key);
277 if (rc != SHISHI_OK)
278 return rc;
280 shishi_key_done (key);
283 /* Add new ticket to the set... */
285 rc = shishi_tkts_add (tkts, tkt);
286 if (rc != SHISHI_OK)
287 return rc;
289 ccache.credentials += n;
290 ccache.credentialslen -= n;
293 #if 0
295 char *data;
296 size_t len;
297 rc = shishi_tkts_to_ccache_mem (handle, tkts, &data, &len);
298 printf ("gaah res %d\n", rc);
300 #endif
302 return rc;
306 * shishi_tkts_add_ccache_file:
307 * @handle: shishi handle as allocated by shishi_init().
308 * @filename: name of file to read.
309 * @tkts: allocated ticket set to store tickets in.
311 * Read tickets from a ccache data structure, and add them to the
312 * ticket set.
314 * The ccache format is proprietary, and this function support (at
315 * least) the 0x0504 format. See the section The Credential Cache
316 * Binary File Format in the Shishi manual for a description of the
317 * file format.
319 * Returns: Returns %SHISHI_IO_ERROR if the file cannot be read,
320 * %SHISHI_CCACHE_ERROR if the data cannot be parsed as a valid ccache
321 * structure, and %SHISHI_OK on success.
324 shishi_tkts_add_ccache_file (Shishi * handle,
325 const char *filename,
326 Shishi_tkts *tkts)
328 size_t len;
329 char *ccache = read_file (filename, &len);
330 int rc;
332 if (!ccache)
333 return SHISHI_IO_ERROR;
335 rc = shishi_tkts_add_ccache_mem (handle, ccache, len, tkts);
337 free (ccache);
339 return rc;
343 * shishi_tkts_from_ccache_mem:
344 * @handle: shishi handle as allocated by shishi_init().
345 * @data: constant memory buffer with ccache of @len size.
346 * @len: size of memory buffer with ccache data.
347 * @outtkts: pointer to ticket set that will be allocated and populated,
348 * must be deallocated by caller on succes.
350 * Read tickets from a ccache data structure, and add them to the
351 * ticket set.
353 * The ccache format is proprietary, and this function support (at
354 * least) the 0x0504 format. See the section The Credential Cache
355 * Binary File Format in the Shishi manual for a description of the
356 * file format.
358 * Returns: Returns %SHISHI_CCACHE_ERROR if the data does not
359 * represent a valid ccache structure, and %SHISHI_OK on success.
362 shishi_tkts_from_ccache_mem (Shishi * handle,
363 const char *data, size_t len,
364 Shishi_tkts **outtkts)
366 int rc;
368 rc = shishi_tkts (handle, outtkts);
369 if (rc != SHISHI_OK)
370 return rc;
372 rc = shishi_tkts_add_ccache_mem (handle, data, len, *outtkts);
373 if (rc != SHISHI_OK)
375 shishi_tkts_done (outtkts);
376 return rc;
379 return SHISHI_OK;
383 * shishi_tkts_from_ccache_file:
384 * @handle: shishi handle as allocated by shishi_init().
385 * @filename: name of file to read.
386 * @outtkts: pointer to ticket set that will be allocated and populated,
387 * must be deallocated by caller on succes.
389 * Read tickets from a ccache data structure, and add them to the
390 * ticket set.
392 * The ccache format is proprietary, and this function support (at
393 * least) the 0x0504 format. See the section The Credential Cache
394 * Binary File Format in the Shishi manual for a description of the
395 * file format.
397 * Returns: Returns %SHISHI_IO_ERROR if the file cannot be read,
398 * %SHISHI_CCACHE_ERROR if the data cannot be parsed as a valid ccache
399 * structure, and %SHISHI_OK on success.
402 shishi_tkts_from_ccache_file (Shishi * handle,
403 const char *filename,
404 Shishi_tkts **outtkts)
406 int rc;
408 rc = shishi_tkts (handle, outtkts);
409 if (rc != SHISHI_OK)
410 return rc;
412 rc = shishi_tkts_add_ccache_file (handle, filename, *outtkts);
413 if (rc != SHISHI_OK)
415 shishi_tkts_done (outtkts);
416 return rc;
419 return SHISHI_OK;
423 shishi_tkt_to_ccache_mem (Shishi *handle,
424 Shishi_tkt *tkt,
425 char **data, size_t *len)
427 struct ccache_credential cred;
428 char tmp[1024];
429 size_t i;
430 int rc;
432 memset (&cred, 0, sizeof (cred));
434 rc = shishi_asn1_to_der (handle, shishi_tkt_ticket (tkt),
435 &cred.ticket.data, &cred.ticket.length);
436 if (rc != SHISHI_OK)
437 return rc;
439 /* Sanity check credential first. */
441 if (shishi_key_length (shishi_tkt_key (tkt)) > CCACHE_MAX_KEYLEN)
442 return SHISHI_CCACHE_ERROR;
444 rc = shishi_asn1_read (handle, shishi_tkt_kdcrep (tkt), "crealm",
445 &cred.client.realm.data,
446 &cred.client.realm.length);
447 if (rc != SHISHI_OK)
448 return rc;
450 rc = shishi_asn1_read (handle, shishi_tkt_enckdcreppart (tkt), "srealm",
451 &cred.server.realm.data,
452 &cred.server.realm.length);
453 if (rc != SHISHI_OK)
454 return rc;
456 #if 0
458 char *cname[CCACHE_MAX_COMPONENTS + 1];
459 size_t i;
461 for (i = 0; i < cred.client.num_components
462 && i < CCACHE_MAX_COMPONENTS; i++)
463 cname[i] = cred.client.components[i].data;
464 cname[i] = NULL;
466 rc = shishi_kdcrep_crealm_set (handle,
467 shishi_tkt_kdcrep (tkt),
468 cred.client.realm.data);
469 if (rc != SHISHI_OK)
470 return rc;
472 rc = shishi_kdcrep_cname_set (handle,
473 shishi_tkt_kdcrep (tkt),
474 cred.client.name_type,
475 cname);
476 if (rc != SHISHI_OK)
477 return rc;
481 char *sname[CCACHE_MAX_COMPONENTS + 1];
482 size_t i;
484 for (i = 0; i < cred.server.num_components
485 && i < CCACHE_MAX_COMPONENTS; i++)
486 sname[i] = cred.server.components[i].data;
487 sname[i] = NULL;
489 rc = shishi_enckdcreppart_srealm_set (handle,
490 shishi_tkt_enckdcreppart (tkt),
491 cred.server.realm.data);
492 if (rc != SHISHI_OK)
493 return rc;
495 rc = shishi_enckdcreppart_sname_set (handle,
496 shishi_tkt_enckdcreppart (tkt),
497 cred.server.name_type,
498 sname);
499 if (rc != SHISHI_OK)
500 return rc;
502 #endif
504 rc = shishi_tkt_flags (tkt, &cred.tktflags);
505 if (rc != SHISHI_OK)
506 return rc;
509 time_t t;
510 rc = shishi_ctime (handle, shishi_tkt_enckdcreppart (tkt),
511 "authtime", &t);
512 if (rc != SHISHI_OK)
513 return rc;
514 cred.authtime = t;
518 time_t t;
519 rc = shishi_ctime (handle, shishi_tkt_enckdcreppart (tkt),
520 "starttime", &t);
521 if (rc == SHISHI_ASN1_NO_ELEMENT)
522 cred.starttime = 0;
523 else if (rc != SHISHI_OK)
524 return rc;
525 cred.starttime = t;
529 time_t t;
530 rc = shishi_ctime (handle, shishi_tkt_enckdcreppart (tkt),
531 "endtime", &t);
532 if (rc != SHISHI_OK)
533 return rc;
534 cred.endtime = t;
538 time_t t;
539 rc = shishi_ctime (handle, shishi_tkt_enckdcreppart (tkt),
540 "renew-till", &t);
541 if (rc == SHISHI_ASN1_NO_ELEMENT)
542 cred.renew_till = 0;
543 else if (rc != SHISHI_OK)
544 return rc;
545 cred.renew_till = t;
548 cred.key.keylen = shishi_key_length (shishi_tkt_key (tkt));
549 cred.key.keytype = shishi_key_type (shishi_tkt_key (tkt));
550 memcpy (cred.key.storage, shishi_key_value (shishi_tkt_key (tkt)),
551 shishi_key_length (shishi_tkt_key (tkt)));
552 cred.key.keyvalue = &cred.key.storage[0];
554 i = 1024;
555 rc = ccache_pack_credential (&cred, tmp, &i);
556 printf ("rc %d len %d\n", rc, i);
559 struct ccache_credential foo;
560 size_t n;
562 rc = ccache_parse_credential (tmp, i, &foo, &n);
563 if (rc < 0)
564 return SHISHI_CCACHE_ERROR;
566 printf ("packed:");
567 ccache_print_credential (&foo);
569 _shishi_escapeprint (tmp, i);
574 shishi_tkts_to_ccache_mem (Shishi *handle,
575 Shishi_tkts *tkts,
576 char **data, size_t *len)
578 struct ccache info;
579 int rc = SHISHI_OK;
580 size_t i;
582 for (i = 0; i < shishi_tkts_size (tkts); i++)
584 Shishi_tkt *tkt = shishi_tkts_nth (tkts, i);
585 struct ccache_credential cred;
587 printf ("ccache %d\n", i);
589 if (!tkt)
590 return SHISHI_INVALID_TKTS;
592 rc = shishi_tkt_to_ccache_mem (handle, tkt, data, len);
593 printf ("f %d\n", rc);
596 #if 0
597 memset (&info, 0, sizeof (info));
599 rc = ccache_pack (&info, *data, *len);
600 printf ("pack res %d len %d\n", rc, *len);
601 #endif
603 return rc;