Update gnulib files.
[shishi.git] / lib / tktccache.c
blob12fb0451870b5f74e644ac52cdde7439efbd4385
1 /* ccache.c --- Credential Cache compatibility ticket set handling.
2 * Copyright (C) 2002, 2003, 2004, 2006, 2007 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify it
7 * 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, but
12 * 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, see http://www.gnu.org/licenses or write
18 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19 * Floor, Boston, MA 02110-1301, USA
23 #include "internal.h"
24 #include "ccache.h"
26 /**
27 * shishi_tkts_default_ccache_guess:
28 * @handle: Shishi library handle create by shishi_init().
30 * Guesses the default ccache ticket filename; it is the contents of
31 * the environment variable KRB5CCNAME or /tmp/krb5cc_<UID> where
32 * <UID> is the user's identity in decimal, as returned by getuid().
34 * Return value: Returns default ccache filename as a string that has
35 * to be deallocated with free() by the caller.
36 **/
37 char *
38 shishi_tkts_default_ccache_guess (Shishi * handle)
40 char *envfile;
42 envfile = getenv ("KRB5CCNAME");
43 if (envfile)
44 return xstrdup (envfile);
46 return xasprintf("/tmp/krb5cc_%u", (unsigned long) getuid ());
49 /**
50 * shishi_tkts_default_ccache:
51 * @handle: Shishi library handle create by shishi_init().
53 * Get filename of default ccache filename.
55 * Return value: Returns the default ccache filename used in the
56 * library. The string is not a copy, so don't modify or deallocate
57 * it.
58 **/
59 const char *
60 shishi_tkts_default_ccache (Shishi * handle)
62 if (!handle->ccachedefault)
64 char *p;
66 p = shishi_tkts_default_ccache_guess (handle);
67 shishi_tkts_default_ccache_set (handle, p);
68 free (p);
71 return handle->ccachedefault;
74 /**
75 * shishi_tkts_default_ccache_set:
76 * @handle: Shishi library handle create by shishi_init().
77 * @ccache: string with new default ccache filename, or
78 * NULL to reset to default.
80 * Set the default ccache filename used in the library. The string is
81 * copied into the library, so you can dispose of the variable
82 * immediately after calling this function.
83 **/
84 void
85 shishi_tkts_default_ccache_set (Shishi * handle, const char *ccache)
87 if (handle->ccachedefault)
88 free (handle->ccachedefault);
89 if (ccache)
90 handle->ccachedefault = xstrdup (ccache);
91 else
92 handle->ccachedefault = NULL;
95 /**
96 * shishi_tkts_add_ccache_mem:
97 * @handle: shishi handle as allocated by shishi_init().
98 * @data: constant memory buffer with ccache of @len size.
99 * @len: size of memory buffer with ccache data.
100 * @tkts: allocated key set to store tickets in.
102 * Read tickets from a ccache data structure, and add them to the
103 * ticket set.
105 * The ccache format is proprietary, and this function support (at
106 * least) the 0x0504 format. See the section The Credential Cache
107 * Binary File Format in the Shishi manual for a description of the
108 * file format.
110 * Returns: Returns %SHISHI_CCACHE_ERROR if the data does not
111 * represent a valid ccache structure, and %SHISHI_OK on success.
114 shishi_tkts_add_ccache_mem (Shishi * handle,
115 const char *data, size_t len,
116 Shishi_tkts *tkts)
118 int rc = SHISHI_OK;
119 struct ccache ccache;
121 if (VERBOSENOISE (handle))
123 printf ("ccache len %d (0x%x)\n", len, len);
124 _shishi_hexprint (data, len);
127 rc = ccache_parse (data, len, &ccache);
128 if (rc < 0)
129 return SHISHI_CCACHE_ERROR;
131 if (VERBOSENOISE (handle))
132 ccache_print (&ccache);
134 while (ccache.credentialslen)
136 struct ccache_credential cred;
137 Shishi_tkt *tkt;
138 Shishi_asn1 ticket;
139 size_t n;
141 rc = ccache_parse_credential (ccache.credentials,
142 ccache.credentialslen, &cred, &n);
143 if (rc < 0)
144 return SHISHI_CCACHE_ERROR;
146 if (VERBOSENOISE (handle))
147 ccache_print_credential (&cred);
149 /* Sanity check credential first. */
151 if (shishi_cipher_keylen (cred.key.keytype) != cred.key.keylen)
152 continue;
154 ticket = shishi_der2asn1_ticket (handle, cred.ticket.data,
155 cred.ticket.length);
156 if (!ticket)
157 continue;
159 /* Let's create a new ticket... */
161 rc = shishi_tkt (handle, &tkt);
162 if (rc != SHISHI_OK)
163 return rc;
165 shishi_tkt_ticket_set (tkt, ticket);
168 char *cname[CCACHE_MAX_COMPONENTS + 1];
169 size_t i;
171 for (i = 0; i < cred.client.num_components
172 && i < CCACHE_MAX_COMPONENTS; i++)
173 cname[i] = cred.client.components[i].data;
174 cname[i] = NULL;
176 rc = shishi_kdcrep_crealm_set (handle,
177 shishi_tkt_kdcrep (tkt),
178 cred.client.realm.data);
179 if (rc != SHISHI_OK)
180 return rc;
182 rc = shishi_kdcrep_cname_set (handle,
183 shishi_tkt_kdcrep (tkt),
184 cred.client.name_type,
185 cname);
186 if (rc != SHISHI_OK)
187 return rc;
191 char *sname[CCACHE_MAX_COMPONENTS + 1];
192 size_t i;
194 for (i = 0; i < cred.server.num_components
195 && i < CCACHE_MAX_COMPONENTS; i++)
196 sname[i] = cred.server.components[i].data;
197 sname[i] = NULL;
199 rc = shishi_enckdcreppart_srealm_set (handle,
200 shishi_tkt_enckdcreppart (tkt),
201 cred.server.realm.data);
202 if (rc != SHISHI_OK)
203 return rc;
205 rc = shishi_enckdcreppart_sname_set (handle,
206 shishi_tkt_enckdcreppart (tkt),
207 cred.server.name_type,
208 sname);
209 if (rc != SHISHI_OK)
210 return rc;
213 rc = shishi_tkt_flags_set (tkt, cred.tktflags);
214 if (rc != SHISHI_OK)
215 return rc;
217 rc = shishi_enckdcreppart_authtime_set
218 (handle,
219 shishi_tkt_enckdcreppart (tkt),
220 shishi_generalize_time (handle, cred.authtime));
221 if (rc != SHISHI_OK)
222 return rc;
224 rc = shishi_enckdcreppart_starttime_set
225 (handle,
226 shishi_tkt_enckdcreppart (tkt),
227 cred.starttime ? shishi_generalize_time (handle, cred.starttime)
228 : NULL);
229 if (rc != SHISHI_OK)
230 return rc;
232 rc = shishi_enckdcreppart_endtime_set
233 (handle,
234 shishi_tkt_enckdcreppart (tkt),
235 shishi_generalize_time (handle, cred.endtime));
236 if (rc != SHISHI_OK)
237 return rc;
239 rc = shishi_enckdcreppart_renew_till_set
240 (handle,
241 shishi_tkt_enckdcreppart (tkt),
242 cred.renew_till ? shishi_generalize_time (handle, cred.renew_till)
243 : NULL);
244 if (rc != SHISHI_OK)
245 return rc;
248 uint32_t nonce = 0;
249 rc = shishi_enckdcreppart_nonce_set (handle,
250 shishi_tkt_enckdcreppart (tkt),
251 nonce);
252 if (rc != SHISHI_OK)
253 return rc;
256 rc = shishi_kdcrep_set_ticket (handle, shishi_tkt_kdcrep (tkt),
257 shishi_tkt_ticket (tkt));
258 if (rc != SHISHI_OK)
259 return rc;
261 rc = shishi_kdcrep_set_enc_part (handle, shishi_tkt_kdcrep (tkt),
262 0, 0, "", 0);
263 if (rc != SHISHI_OK)
264 return rc;
266 /* Add key. */
269 Shishi_key *key;
271 rc = shishi_key (handle, &key);
272 if (rc != SHISHI_OK)
273 return rc;
275 shishi_key_type_set (key, cred.key.keytype);
276 shishi_key_value_set (key, cred.key.keyvalue);
277 rc = shishi_tkt_key_set (tkt, key);
278 if (rc != SHISHI_OK)
279 return rc;
281 shishi_key_done (key);
284 /* Add new ticket to the set... */
286 rc = shishi_tkts_add (tkts, tkt);
287 if (rc != SHISHI_OK)
288 return rc;
290 ccache.credentials += n;
291 ccache.credentialslen -= n;
294 #if 0
296 char *data;
297 size_t len;
298 rc = shishi_tkts_to_ccache_mem (handle, tkts, &data, &len);
299 printf ("gaah res %d\n", rc);
301 #endif
303 return rc;
307 * shishi_tkts_add_ccache_file:
308 * @handle: shishi handle as allocated by shishi_init().
309 * @filename: name of file to read.
310 * @tkts: allocated ticket set to store tickets in.
312 * Read tickets from a ccache data structure, and add them to the
313 * ticket set.
315 * The ccache format is proprietary, and this function support (at
316 * least) the 0x0504 format. See the section The Credential Cache
317 * Binary File Format in the Shishi manual for a description of the
318 * file format.
320 * Returns: Returns %SHISHI_IO_ERROR if the file cannot be read,
321 * %SHISHI_CCACHE_ERROR if the data cannot be parsed as a valid ccache
322 * structure, and %SHISHI_OK on success.
325 shishi_tkts_add_ccache_file (Shishi * handle,
326 const char *filename,
327 Shishi_tkts *tkts)
329 size_t len;
330 char *ccache = read_file (filename, &len);
331 int rc;
333 if (!ccache)
334 return SHISHI_IO_ERROR;
336 rc = shishi_tkts_add_ccache_mem (handle, ccache, len, tkts);
338 free (ccache);
340 return rc;
344 * shishi_tkts_from_ccache_mem:
345 * @handle: shishi handle as allocated by shishi_init().
346 * @data: constant memory buffer with ccache of @len size.
347 * @len: size of memory buffer with ccache data.
348 * @outtkts: pointer to ticket set that will be allocated and populated,
349 * must be deallocated by caller on succes.
351 * Read tickets from a ccache data structure, and add them to the
352 * ticket set.
354 * The ccache format is proprietary, and this function support (at
355 * least) the 0x0504 format. See the section The Credential Cache
356 * Binary File Format in the Shishi manual for a description of the
357 * file format.
359 * Returns: Returns %SHISHI_CCACHE_ERROR if the data does not
360 * represent a valid ccache structure, and %SHISHI_OK on success.
363 shishi_tkts_from_ccache_mem (Shishi * handle,
364 const char *data, size_t len,
365 Shishi_tkts **outtkts)
367 int rc;
369 rc = shishi_tkts (handle, outtkts);
370 if (rc != SHISHI_OK)
371 return rc;
373 rc = shishi_tkts_add_ccache_mem (handle, data, len, *outtkts);
374 if (rc != SHISHI_OK)
376 shishi_tkts_done (outtkts);
377 return rc;
380 return SHISHI_OK;
384 * shishi_tkts_from_ccache_file:
385 * @handle: shishi handle as allocated by shishi_init().
386 * @filename: name of file to read.
387 * @outtkts: pointer to ticket set that will be allocated and populated,
388 * must be deallocated by caller on succes.
390 * Read tickets from a ccache data structure, and add them to the
391 * ticket set.
393 * The ccache format is proprietary, and this function support (at
394 * least) the 0x0504 format. See the section The Credential Cache
395 * Binary File Format in the Shishi manual for a description of the
396 * file format.
398 * Returns: Returns %SHISHI_IO_ERROR if the file cannot be read,
399 * %SHISHI_CCACHE_ERROR if the data cannot be parsed as a valid ccache
400 * structure, and %SHISHI_OK on success.
403 shishi_tkts_from_ccache_file (Shishi * handle,
404 const char *filename,
405 Shishi_tkts **outtkts)
407 int rc;
409 rc = shishi_tkts (handle, outtkts);
410 if (rc != SHISHI_OK)
411 return rc;
413 rc = shishi_tkts_add_ccache_file (handle, filename, *outtkts);
414 if (rc != SHISHI_OK)
416 shishi_tkts_done (outtkts);
417 return rc;
420 return SHISHI_OK;
424 shishi_tkt_to_ccache_mem (Shishi *handle,
425 Shishi_tkt *tkt,
426 char **data, size_t *len)
428 struct ccache_credential cred;
429 char tmp[1024];
430 size_t i;
431 int rc;
433 memset (&cred, 0, sizeof (cred));
435 rc = shishi_asn1_to_der (handle, shishi_tkt_ticket (tkt),
436 &cred.ticket.data, &cred.ticket.length);
437 if (rc != SHISHI_OK)
438 return rc;
440 /* Sanity check credential first. */
442 if (shishi_key_length (shishi_tkt_key (tkt)) > CCACHE_MAX_KEYLEN)
443 return SHISHI_CCACHE_ERROR;
445 rc = shishi_asn1_read (handle, shishi_tkt_kdcrep (tkt), "crealm",
446 &cred.client.realm.data,
447 &cred.client.realm.length);
448 if (rc != SHISHI_OK)
449 return rc;
451 rc = shishi_asn1_read (handle, shishi_tkt_enckdcreppart (tkt), "srealm",
452 &cred.server.realm.data,
453 &cred.server.realm.length);
454 if (rc != SHISHI_OK)
455 return rc;
457 #if 0
459 char *cname[CCACHE_MAX_COMPONENTS + 1];
460 size_t i;
462 for (i = 0; i < cred.client.num_components
463 && i < CCACHE_MAX_COMPONENTS; i++)
464 cname[i] = cred.client.components[i].data;
465 cname[i] = NULL;
467 rc = shishi_kdcrep_crealm_set (handle,
468 shishi_tkt_kdcrep (tkt),
469 cred.client.realm.data);
470 if (rc != SHISHI_OK)
471 return rc;
473 rc = shishi_kdcrep_cname_set (handle,
474 shishi_tkt_kdcrep (tkt),
475 cred.client.name_type,
476 cname);
477 if (rc != SHISHI_OK)
478 return rc;
482 char *sname[CCACHE_MAX_COMPONENTS + 1];
483 size_t i;
485 for (i = 0; i < cred.server.num_components
486 && i < CCACHE_MAX_COMPONENTS; i++)
487 sname[i] = cred.server.components[i].data;
488 sname[i] = NULL;
490 rc = shishi_enckdcreppart_srealm_set (handle,
491 shishi_tkt_enckdcreppart (tkt),
492 cred.server.realm.data);
493 if (rc != SHISHI_OK)
494 return rc;
496 rc = shishi_enckdcreppart_sname_set (handle,
497 shishi_tkt_enckdcreppart (tkt),
498 cred.server.name_type,
499 sname);
500 if (rc != SHISHI_OK)
501 return rc;
503 #endif
505 rc = shishi_tkt_flags (tkt, &cred.tktflags);
506 if (rc != SHISHI_OK)
507 return rc;
510 time_t t;
511 rc = shishi_ctime (handle, shishi_tkt_enckdcreppart (tkt),
512 "authtime", &t);
513 if (rc != SHISHI_OK)
514 return rc;
515 cred.authtime = t;
519 time_t t;
520 rc = shishi_ctime (handle, shishi_tkt_enckdcreppart (tkt),
521 "starttime", &t);
522 if (rc == SHISHI_ASN1_NO_ELEMENT)
523 cred.starttime = 0;
524 else if (rc != SHISHI_OK)
525 return rc;
526 cred.starttime = t;
530 time_t t;
531 rc = shishi_ctime (handle, shishi_tkt_enckdcreppart (tkt),
532 "endtime", &t);
533 if (rc != SHISHI_OK)
534 return rc;
535 cred.endtime = t;
539 time_t t;
540 rc = shishi_ctime (handle, shishi_tkt_enckdcreppart (tkt),
541 "renew-till", &t);
542 if (rc == SHISHI_ASN1_NO_ELEMENT)
543 cred.renew_till = 0;
544 else if (rc != SHISHI_OK)
545 return rc;
546 cred.renew_till = t;
549 cred.key.keylen = shishi_key_length (shishi_tkt_key (tkt));
550 cred.key.keytype = shishi_key_type (shishi_tkt_key (tkt));
551 memcpy (cred.key.storage, shishi_key_value (shishi_tkt_key (tkt)),
552 shishi_key_length (shishi_tkt_key (tkt)));
553 cred.key.keyvalue = &cred.key.storage[0];
555 i = 1024;
556 rc = ccache_pack_credential (&cred, tmp, &i);
557 printf ("rc %d len %d\n", rc, i);
560 struct ccache_credential foo;
561 size_t n;
563 rc = ccache_parse_credential (tmp, i, &foo, &n);
564 if (rc < 0)
565 return SHISHI_CCACHE_ERROR;
567 printf ("packed:");
568 ccache_print_credential (&foo);
570 _shishi_escapeprint (tmp, i);
575 shishi_tkts_to_ccache_mem (Shishi *handle,
576 Shishi_tkts *tkts,
577 char **data, size_t *len)
579 struct ccache info;
580 int rc = SHISHI_OK;
581 size_t i;
583 for (i = 0; i < shishi_tkts_size (tkts); i++)
585 Shishi_tkt *tkt = shishi_tkts_nth (tkts, i);
586 struct ccache_credential cred;
588 printf ("ccache %d\n", i);
590 if (!tkt)
591 return SHISHI_INVALID_TKTS;
593 rc = shishi_tkt_to_ccache_mem (handle, tkt, data, len);
594 printf ("f %d\n", rc);
597 #if 0
598 memset (&info, 0, sizeof (info));
600 rc = ccache_pack (&info, *data, *len);
601 printf ("pack res %d len %d\n", rc, *len);
602 #endif
604 return rc;