Branch data Line data Source code
1 : : /* tkts.c --- Ticket set handling.
2 : : * Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008, 2010 Simon Josefsson
3 : : *
4 : : * This file is part of Shishi.
5 : : *
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.
10 : : *
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.
15 : : *
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
20 : : *
21 : : */
22 : :
23 : : #include "internal.h"
24 : : #include <minmax.h>
25 : :
26 : : struct Shishi_tkts
27 : : {
28 : : Shishi *handle;
29 : : Shishi_tkt **tkts;
30 : : int ntkts;
31 : : };
32 : :
33 : : #define TICKET_FILE "tickets"
34 : :
35 : : /**
36 : : * shishi_tkts_default_file_guess:
37 : : * @handle: Shishi library handle create by shishi_init().
38 : : *
39 : : * Guesses the default ticket filename; it is $SHISHI_TICKETS,
40 : : * $SHISHI_HOME/tickets, or $HOME/.shishi/tickets.
41 : : *
42 : : * Return value: Returns default tkts filename as a string that
43 : : * has to be deallocated with free() by the caller.
44 : : **/
45 : : char *
46 : 2 : shishi_tkts_default_file_guess (Shishi * handle)
47 : : {
48 : : char *envfile;
49 : :
50 : 2 : envfile = getenv ("SHISHI_TICKETS");
51 [ - + ]: 2 : if (envfile)
52 : 0 : return xstrdup (envfile);
53 : :
54 : 2 : return shishi_cfg_userdirectory_file (handle, TICKET_FILE);
55 : : }
56 : :
57 : : /**
58 : : * shishi_tkts_default_file:
59 : : * @handle: Shishi library handle create by shishi_init().
60 : : *
61 : : * Get filename of default ticket set.
62 : : *
63 : : * Return value: Returns the default ticket set filename used in the
64 : : * library. The string is not a copy, so don't modify or deallocate
65 : : * it.
66 : : **/
67 : : const char *
68 : 3 : shishi_tkts_default_file (Shishi * handle)
69 : : {
70 [ + + ]: 3 : if (!handle->tktsdefaultfile)
71 : : {
72 : : char *p;
73 : :
74 : 2 : p = shishi_tkts_default_file_guess (handle);
75 : 2 : shishi_tkts_default_file_set (handle, p);
76 : 2 : free (p);
77 : : }
78 : :
79 : 3 : return handle->tktsdefaultfile;
80 : : }
81 : :
82 : : /**
83 : : * shishi_tkts_default_file_set:
84 : : * @handle: Shishi library handle create by shishi_init().
85 : : * @tktsfile: string with new default tkts file name, or
86 : : * NULL to reset to default.
87 : : *
88 : : * Set the default ticket set filename used in the library. The
89 : : * string is copied into the library, so you can dispose of the
90 : : * variable immediately after calling this function.
91 : : **/
92 : : void
93 : 18 : shishi_tkts_default_file_set (Shishi * handle, const char *tktsfile)
94 : : {
95 : 18 : free (handle->tktsdefaultfile);
96 [ + + ]: 18 : if (tktsfile)
97 : 3 : handle->tktsdefaultfile = xstrdup (tktsfile);
98 : : else
99 : 15 : handle->tktsdefaultfile = NULL;
100 : 18 : }
101 : :
102 : : /**
103 : : * shishi_tkts_default:
104 : : * @handle: Shishi library handle create by shishi_init().
105 : : *
106 : : * Get the default ticket set for library handle.
107 : : *
108 : : * Return value: Return the handle global ticket set.
109 : : **/
110 : : Shishi_tkts *
111 : 0 : shishi_tkts_default (Shishi * handle)
112 : : {
113 [ # # # # ]: 0 : if (handle->tkts == NULL &&
114 : 0 : (shishi_tkts (handle, &handle->tkts) != SHISHI_OK))
115 : 0 : handle->tkts = NULL;
116 : :
117 : 0 : return handle->tkts;
118 : : }
119 : :
120 : : int
121 : 0 : shishi_tkts_default_to_file (Shishi_tkts * tkts)
122 : : {
123 : 0 : return shishi_tkts_to_file (tkts, shishi_tkts_default_file (tkts->handle));
124 : : }
125 : :
126 : : /**
127 : : * shishi_tkts:
128 : : * @handle: shishi handle as allocated by shishi_init().
129 : : * @tkts: output pointer to newly allocated tkts handle.
130 : : *
131 : : * Get a new ticket set handle.
132 : : *
133 : : * Return value: Returns %SHISHI_OK iff successful.
134 : : **/
135 : : int
136 : 3 : shishi_tkts (Shishi * handle, Shishi_tkts ** tkts)
137 : : {
138 : 3 : *tkts = xcalloc (1, sizeof (**tkts));
139 : :
140 : 3 : (*tkts)->handle = handle;
141 : :
142 : 3 : return SHISHI_OK;
143 : : }
144 : :
145 : : /**
146 : : * shishi_tkts_done:
147 : : * @tkts: ticket set handle as allocated by shishi_tkts().
148 : : *
149 : : * Deallocates all resources associated with ticket set. The ticket
150 : : * set handle must not be used in calls to other shishi_tkts_*()
151 : : * functions after this.
152 : : **/
153 : : void
154 : 4 : shishi_tkts_done (Shishi_tkts ** tkts)
155 : : {
156 [ + + ][ - + ]: 4 : if (!tkts || !*tkts)
157 : 1 : return;
158 : :
159 [ + + ]: 3 : if ((*tkts)->tkts)
160 : 2 : free ((*tkts)->tkts);
161 : 3 : free (*tkts);
162 : :
163 : 3 : *tkts = NULL;
164 : :
165 : 4 : return;
166 : : }
167 : :
168 : : /**
169 : : * shishi_tkts_size:
170 : : * @tkts: ticket set handle as allocated by shishi_tkts().
171 : : *
172 : : * Get size of ticket set.
173 : : *
174 : : * Return value: Returns number of tickets stored in ticket set.
175 : : **/
176 : : int
177 : 11 : shishi_tkts_size (Shishi_tkts * tkts)
178 : : {
179 [ + - ]: 11 : return tkts ? tkts->ntkts : -1;
180 : : }
181 : :
182 : : /**
183 : : * shishi_tkts_nth:
184 : : * @tkts: ticket set handle as allocated by shishi_tkts().
185 : : * @ticketno: integer indicating requested ticket in ticket set.
186 : : *
187 : : * Get the n:th ticket in ticket set.
188 : : *
189 : : * Return value: Returns a ticket handle to the ticketno:th ticket in
190 : : * the ticket set, or NULL if ticket set is invalid or ticketno is
191 : : * out of bounds. The first ticket is ticketno 0, the second
192 : : * ticketno 1, and so on.
193 : : **/
194 : : Shishi_tkt *
195 : 11 : shishi_tkts_nth (Shishi_tkts * tkts, int ticketno)
196 : : {
197 [ + - ][ + + ]: 11 : if (tkts == NULL || ticketno >= tkts->ntkts)
198 : 3 : return NULL;
199 : :
200 : 11 : return tkts->tkts[ticketno];
201 : : }
202 : :
203 : : /**
204 : : * shishi_tkts_remove:
205 : : * @tkts: ticket set handle as allocated by shishi_tkts().
206 : : * @ticketno: ticket number of ticket in the set to remove. The first
207 : : * ticket is ticket number 0.
208 : : *
209 : : * Remove a ticket, indexed by @ticketno, in ticket set.
210 : : *
211 : : * Return value: %SHISHI_OK if successful or if @ticketno larger than
212 : : * size of ticket set.
213 : : **/
214 : : int
215 : 8 : shishi_tkts_remove (Shishi_tkts * tkts, int ticketno)
216 : : {
217 [ + + ]: 8 : if (!tkts)
218 : 1 : return SHISHI_INVALID_TKTS;
219 : :
220 [ + + ]: 7 : if (ticketno >= tkts->ntkts)
221 : 2 : return SHISHI_OK;
222 : :
223 [ + - ]: 5 : if (ticketno < tkts->ntkts)
224 : 5 : memmove (&tkts->tkts[ticketno], &tkts->tkts[ticketno + 1],
225 : 5 : sizeof (*tkts->tkts) * (tkts->ntkts - ticketno - 1));
226 : :
227 : 5 : --tkts->ntkts;
228 : :
229 [ + + ]: 5 : if (tkts->ntkts > 0)
230 : : {
231 : 3 : tkts->tkts = xrealloc (tkts->tkts, sizeof (*tkts->tkts) * tkts->ntkts);
232 : : }
233 : : else
234 : : {
235 : 2 : free (tkts->tkts);
236 : 2 : tkts->tkts = NULL;
237 : : }
238 : :
239 : 8 : return SHISHI_OK;
240 : : }
241 : :
242 : : /**
243 : : * shishi_tkts_add:
244 : : * @tkts: ticket set handle as allocated by shishi_tkts().
245 : : * @tkt: ticket to be added to ticket set.
246 : : *
247 : : * Add a ticket to the ticket set. Only the pointer is stored, so if
248 : : * you modify @tkt, the ticket in the ticket set will also be
249 : : * modified.
250 : : *
251 : : * Return value: Returns %SHISHI_OK iff successful.
252 : : **/
253 : : int
254 : 10 : shishi_tkts_add (Shishi_tkts * tkts, Shishi_tkt * tkt)
255 : : {
256 [ + + ]: 10 : if (!tkt)
257 : 1 : return SHISHI_INVALID_TICKET;
258 : :
259 [ + + ]: 9 : if (tkts->ntkts++ == 0)
260 : 4 : tkts->tkts = xmalloc (sizeof (*tkts->tkts));
261 : : else
262 : 5 : tkts->tkts = xrealloc (tkts->tkts, sizeof (*tkts->tkts) * tkts->ntkts);
263 : :
264 : 9 : tkts->tkts[tkts->ntkts - 1] = tkt;
265 : :
266 : 10 : return SHISHI_OK;
267 : : }
268 : :
269 : : /**
270 : : * shishi_tkts_new:
271 : : * @tkts: ticket set handle as allocated by shishi_tkts().
272 : : * @ticket: input ticket variable.
273 : : * @enckdcreppart: input ticket detail variable.
274 : : * @kdcrep: input KDC-REP variable.
275 : : *
276 : : * Allocate a new ticket and add it to the ticket set.
277 : : *
278 : : * Note that @ticket, @enckdcreppart and @kdcrep are stored by
279 : : * reference, so you must not de-allocate them before the ticket is
280 : : * removed from the ticket set and de-allocated.
281 : : *
282 : : * Return value: Returns %SHISHI_OK iff successful.
283 : : **/
284 : : int
285 : 4 : shishi_tkts_new (Shishi_tkts * tkts,
286 : : Shishi_asn1 ticket, Shishi_asn1 enckdcreppart,
287 : : Shishi_asn1 kdcrep)
288 : : {
289 : : Shishi_tkt *tkt;
290 : : int res;
291 : :
292 : : /* XXX Who will de-allocate these? */
293 : 4 : tkt = shishi_tkt2 (tkts->handle, ticket, enckdcreppart, kdcrep);
294 : :
295 : 4 : res = shishi_tkts_add (tkts, tkt);
296 [ - + ]: 4 : if (res != SHISHI_OK)
297 : : {
298 : 0 : free (tkt);
299 : 0 : return res;
300 : : }
301 : :
302 : 4 : return SHISHI_OK;
303 : : }
304 : :
305 : : /**
306 : : * shishi_tkts_read:
307 : : * @tkts: ticket set handle as allocated by shishi_tkts().
308 : : * @fh: file descriptor to read from.
309 : : *
310 : : * Read tickets from file descriptor and add them to the ticket set.
311 : : *
312 : : * Return value: Returns %SHISHI_OK iff successful.
313 : : **/
314 : : int
315 : 1 : shishi_tkts_read (Shishi_tkts * tkts, FILE * fh)
316 : : {
317 : : int res;
318 : :
319 : 1 : res = SHISHI_OK;
320 [ + - ]: 3 : while (!feof (fh))
321 : : {
322 : : Shishi_asn1 ticket;
323 : : Shishi_asn1 enckdcreppart;
324 : : Shishi_asn1 kdcrep;
325 : :
326 : 3 : res = shishi_kdcrep_parse (tkts->handle, fh, &kdcrep);
327 [ + + ]: 3 : if (res != SHISHI_OK)
328 : : {
329 : 1 : res = SHISHI_OK;
330 : 1 : break;
331 : : }
332 : :
333 : 2 : res = shishi_enckdcreppart_parse (tkts->handle, fh, &enckdcreppart);
334 [ - + ]: 2 : if (res != SHISHI_OK)
335 : 0 : break;
336 : :
337 : 2 : res = shishi_ticket_parse (tkts->handle, fh, &ticket);
338 [ - + ]: 2 : if (res != SHISHI_OK)
339 : 0 : break;
340 : :
341 : : /* XXX Who will de-allocate these? */
342 : 2 : res = shishi_tkts_new (tkts, ticket, enckdcreppart, kdcrep);
343 [ - + ]: 2 : if (res != SHISHI_OK)
344 : 0 : break;
345 : :
346 [ - + ]: 2 : if (VERBOSEASN1 (tkts->handle))
347 : : {
348 : 0 : printf ("Read ticket for principal `':\n");
349 : 0 : shishi_kdcrep_print (tkts->handle, stdout, kdcrep);
350 : 0 : shishi_enckdcreppart_print (tkts->handle, stdout, enckdcreppart);
351 : 0 : shishi_ticket_print (tkts->handle, stdout, ticket);
352 : : }
353 : : }
354 : :
355 : 1 : return res;
356 : : }
357 : :
358 : : /**
359 : : * shishi_tkts_from_file:
360 : : * @tkts: ticket set handle as allocated by shishi_tkts().
361 : : * @filename: filename to read tickets from.
362 : : *
363 : : * Read tickets from file and add them to the ticket set.
364 : : *
365 : : * Return value: Returns %SHISHI_OK iff successful.
366 : : **/
367 : : int
368 : 1 : shishi_tkts_from_file (Shishi_tkts * tkts, const char *filename)
369 : : {
370 : : FILE *fh;
371 : : int res;
372 : :
373 : 1 : fh = fopen (filename, "r");
374 [ - + ]: 1 : if (fh == NULL)
375 : 0 : return SHISHI_FOPEN_ERROR;
376 : :
377 : 1 : res = shishi_tkts_read (tkts, fh);
378 [ - + ]: 1 : if (res != SHISHI_OK)
379 : : {
380 : 0 : fclose (fh);
381 : 0 : return res;
382 : : }
383 : :
384 : 1 : res = fclose (fh);
385 [ - + ]: 1 : if (res != 0)
386 : 0 : return SHISHI_IO_ERROR;
387 : :
388 : 1 : return SHISHI_OK;
389 : : }
390 : :
391 : : /**
392 : : * shishi_tkts_write:
393 : : * @tkts: ticket set handle as allocated by shishi_tkts().
394 : : * @fh: file descriptor to write tickets to.
395 : : *
396 : : * Write tickets in set to file descriptor.
397 : : *
398 : : * Return value: Returns %SHISHI_OK iff successful.
399 : : **/
400 : : int
401 : 2 : shishi_tkts_write (Shishi_tkts * tkts, FILE * fh)
402 : : {
403 : : int res;
404 : : int i;
405 : :
406 [ - + ]: 2 : if (!tkts)
407 : 0 : return SHISHI_INVALID_TKTS;
408 : :
409 [ + + ]: 6 : for (i = 0; i < tkts->ntkts; i++)
410 : : {
411 : 4 : res = shishi_kdcrep_print
412 : 4 : (tkts->handle, fh, shishi_tkt_kdcrep (tkts->tkts[i]));
413 [ - + ]: 4 : if (res != SHISHI_OK)
414 : : {
415 : 0 : shishi_error_printf (tkts->handle,
416 : : "Could not print ticket: %s",
417 : : shishi_error (tkts->handle));
418 : 0 : return res;
419 : : }
420 : :
421 : 4 : res = shishi_enckdcreppart_print
422 : 4 : (tkts->handle, fh, shishi_tkt_enckdcreppart (tkts->tkts[i]));
423 [ - + ]: 4 : if (res != SHISHI_OK)
424 : : {
425 : 0 : shishi_error_printf (tkts->handle,
426 : : "Could not print ticket: %s",
427 : : shishi_error (tkts->handle));
428 : 0 : return res;
429 : : }
430 : :
431 : 4 : res = shishi_ticket_print (tkts->handle, fh,
432 : 4 : shishi_tkt_ticket (tkts->tkts[i]));
433 [ - + ]: 4 : if (res != SHISHI_OK)
434 : : {
435 : 0 : shishi_error_printf (tkts->handle,
436 : : "Could not print ticket: %s",
437 : : shishi_error (tkts->handle));
438 : 0 : return res;
439 : : }
440 : :
441 : 4 : fprintf (fh, "\n\n");
442 : : }
443 : :
444 : 2 : return SHISHI_OK;
445 : : }
446 : :
447 : : /**
448 : : * shishi_tkts_expire:
449 : : * @tkts: ticket set handle as allocated by shishi_tkts().
450 : : *
451 : : * Remove expired tickets from ticket set.
452 : : *
453 : : * Return value: Returns %SHISHI_OK iff successful.
454 : : **/
455 : : int
456 : 0 : shishi_tkts_expire (Shishi_tkts * tkts)
457 : : {
458 : 0 : int warn = 0;
459 : 0 : int i = 0;
460 : :
461 [ # # ]: 0 : if (!tkts)
462 : 0 : return SHISHI_INVALID_TKTS;
463 : :
464 [ # # ]: 0 : while (i < tkts->ntkts)
465 : : {
466 [ # # ]: 0 : if (shishi_tkt_expired_p (tkts->tkts[i]))
467 : : {
468 : 0 : warn++;
469 : 0 : shishi_tkts_remove (tkts, i);
470 : : }
471 : : else
472 : 0 : i++;
473 : : }
474 : :
475 [ # # ][ # # ]: 0 : if (VERBOSE (tkts->handle) && warn)
476 : 0 : shishi_warn (tkts->handle,
477 : 0 : ngettext ("removed %d expired ticket\n",
478 : : "removed %d expired tickets\n", warn), warn);
479 : :
480 : 0 : return SHISHI_OK;
481 : : }
482 : :
483 : : /**
484 : : * shishi_tkts_to_file:
485 : : * @tkts: ticket set handle as allocated by shishi_tkts().
486 : : * @filename: filename to write tickets to.
487 : : *
488 : : * Write tickets in set to file.
489 : : *
490 : : * Return value: Returns %SHISHI_OK iff successful.
491 : : **/
492 : : int
493 : 1 : shishi_tkts_to_file (Shishi_tkts * tkts, const char *filename)
494 : : {
495 : : FILE *fh;
496 : : int res;
497 : :
498 : 1 : fh = fopen (filename, "w");
499 [ - + ]: 1 : if (fh == NULL)
500 : 0 : return SHISHI_FOPEN_ERROR;
501 : :
502 : 1 : res = shishi_tkts_write (tkts, fh);
503 [ - + ]: 1 : if (res != SHISHI_OK)
504 : : {
505 : 0 : fclose (fh);
506 : 0 : return res;
507 : : }
508 : :
509 : 1 : res = fclose (fh);
510 [ - + ]: 1 : if (res != 0)
511 : 0 : return SHISHI_IO_ERROR;
512 : :
513 : 1 : return SHISHI_OK;
514 : : }
515 : :
516 : : /**
517 : : * shishi_tkts_print_for_service:
518 : : * @tkts: ticket set handle as allocated by shishi_tkts().
519 : : * @fh: file descriptor to print to.
520 : : * @service: service to limit tickets printed to, or NULL.
521 : : *
522 : : * Print description of tickets for specified service to file
523 : : * descriptor. If service is NULL, all tickets are printed.
524 : : *
525 : : * Return value: Returns %SHISHI_OK iff successful.
526 : : **/
527 : : int
528 : 1 : shishi_tkts_print_for_service (Shishi_tkts * tkts, FILE * fh,
529 : : const char *service)
530 : : {
531 : : int res;
532 : : int found;
533 : : int i;
534 : :
535 : 1 : found = 0;
536 [ + + ]: 3 : for (i = 0; i < shishi_tkts_size (tkts); i++)
537 : : {
538 : 2 : Shishi_tkt *tkt = shishi_tkts_nth (tkts, i);
539 : :
540 [ - + ]: 2 : if (service)
541 : : {
542 : : char *buf;
543 : :
544 : 0 : res = shishi_tkt_server (tkt, &buf, NULL);
545 [ # # ]: 0 : if (res != SHISHI_OK)
546 : 0 : continue;
547 : :
548 [ # # ]: 0 : if (strcmp (service, buf) != 0)
549 : : {
550 : 0 : free (buf);
551 : 0 : continue;
552 : : }
553 : :
554 : 0 : free (buf);
555 : : }
556 : :
557 : 2 : printf ("\n");
558 : 2 : shishi_tkt_pretty_print (shishi_tkts_nth (tkts, i), fh);
559 : 2 : found++;
560 : : }
561 : :
562 [ + - ]: 1 : if (found)
563 : : {
564 : 1 : printf (ngettext ("\n%d ticket found.\n", "\n%d tickets found.\n",
565 : : found), found);
566 : : }
567 : : else
568 : : {
569 [ # # ]: 0 : if (service)
570 : 0 : printf ("\nNo matching tickets found.\n");
571 : : else
572 : 0 : printf ("\nNo tickets found.\n");
573 : : }
574 : :
575 : 1 : return SHISHI_OK;
576 : : }
577 : :
578 : : /**
579 : : * shishi_tkts_print:
580 : : * @tkts: ticket set handle as allocated by shishi_tkts().
581 : : * @fh: file descriptor to print to.
582 : : *
583 : : * Print description of all tickets to file descriptor.
584 : : *
585 : : * Return value: Returns %SHISHI_OK iff successful.
586 : : **/
587 : : int
588 : 1 : shishi_tkts_print (Shishi_tkts * tkts, FILE * fh)
589 : : {
590 : 1 : return shishi_tkts_print_for_service (tkts, fh, NULL);
591 : : }
592 : :
593 : : /**
594 : : * shishi_tkt_match_p:
595 : : * @tkt: ticket to test hints on.
596 : : * @hint: structure with characteristics of ticket to be found.
597 : : *
598 : : * Test if a ticket matches specified hints.
599 : : *
600 : : * Return value: Returns 0 iff ticket fails to match given criteria.
601 : : **/
602 : : int
603 : 9 : shishi_tkt_match_p (Shishi_tkt * tkt, Shishi_tkts_hint * hint)
604 : : {
605 [ + + ][ + + ]: 9 : if (hint->server && !shishi_tkt_server_p (tkt, hint->server))
606 : 3 : return 0;
607 : :
608 [ + + ][ - + ]: 6 : if (hint->client && !shishi_tkt_client_p (tkt, hint->client))
609 : 0 : return 0;
610 : :
611 [ + + + - ]: 8 : if (!(hint->flags & SHISHI_TKTSHINTFLAGS_ACCEPT_EXPIRED) &&
612 : 2 : !shishi_tkt_valid_now_p (tkt))
613 : 2 : return 0;
614 : :
615 [ - + # # ]: 4 : if ((hint->tktflags & SHISHI_TICKETFLAGS_FORWARDABLE) &&
616 : 0 : !shishi_tkt_forwardable_p (tkt))
617 : 0 : return 0;
618 : :
619 [ - + # # ]: 4 : if ((hint->tktflags & SHISHI_TICKETFLAGS_FORWARDED) &&
620 : 0 : !shishi_tkt_forwarded_p (tkt))
621 : 0 : return 0;
622 : :
623 [ - + # # ]: 4 : if ((hint->tktflags & SHISHI_TICKETFLAGS_RENEWABLE) &&
624 : 0 : !shishi_tkt_renewable_p (tkt))
625 : 0 : return 0;
626 : :
627 [ - + # # ]: 4 : if ((hint->tktflags & SHISHI_TICKETFLAGS_PROXIABLE) &&
628 : 0 : !shishi_tkt_proxiable_p (tkt))
629 : 0 : return 0;
630 : :
631 [ - + # # ]: 4 : if ((hint->tktflags & SHISHI_TICKETFLAGS_PROXY) &&
632 : 0 : !shishi_tkt_proxy_p (tkt))
633 : 0 : return 0;
634 : :
635 [ - + ][ # # ]: 4 : if (hint->etype && !shishi_tkt_keytype_p (tkt, hint->etype))
636 : 0 : return 0;
637 : :
638 : 9 : return 1;
639 : : }
640 : :
641 : : /**
642 : : * shishi_tkts_find:
643 : : * @tkts: ticket set handle as allocated by shishi_tkts().
644 : : * @hint: structure with characteristics of ticket to be found.
645 : : *
646 : : * Search the ticketset sequentially (from ticket number 0 through all
647 : : * tickets in the set) for a ticket that fits the given
648 : : * characteristics. If a ticket is found, the hint->startpos field is
649 : : * updated to point to the next ticket in the set, so this function
650 : : * can be called repeatedly with the same hint argument in order to
651 : : * find all tickets matching a certain criterium. Note that if
652 : : * tickets are added to, or removed from, the ticketset during a query
653 : : * with the same hint argument, the hint->startpos field must be
654 : : * updated appropriately.
655 : : *
656 : : * Here is how you would typically use this function:
657 : : *
658 : : * Shishi_tkts_hint hint;
659 : : *
660 : : * Shishi_tkt tkt;
661 : : *
662 : : *
663 : : * memset(&hint, 0, sizeof(hint));
664 : : *
665 : : * hint.server = "imap/mail.example.org";
666 : : *
667 : : * tkt = shishi_tkts_find (shishi_tkts_default(handle), &hint);
668 : : *
669 : : * if (!tkt)
670 : : *
671 : : * printf("No ticket found...\n");
672 : : *
673 : : * else
674 : : *
675 : : * do_something_with_ticket (tkt);
676 : : *
677 : : * Return value: Returns a ticket if found, or NULL if no further
678 : : * matching tickets could be found.
679 : : **/
680 : : Shishi_tkt *
681 : 6 : shishi_tkts_find (Shishi_tkts * tkts, Shishi_tkts_hint * hint)
682 : : {
683 : : int i;
684 : :
685 [ - + ]: 6 : if (!tkts)
686 : 0 : return NULL;
687 : :
688 [ - + ]: 6 : if (VERBOSENOISE (tkts->handle))
689 : : {
690 : 0 : fprintf (stderr, "Searching tickets... ");
691 [ # # ]: 0 : if (hint->server)
692 : 0 : fprintf (stderr, "server=`%s' ", hint->server);
693 [ # # ]: 0 : if (hint->client)
694 : 0 : fprintf (stderr, "client=`%s' ", hint->client);
695 : 0 : fprintf (stderr, "\n");
696 : : }
697 : :
698 [ + + ]: 11 : for (i = hint->startpos; i < tkts->ntkts; i++)
699 : : {
700 [ + + ]: 9 : if (!shishi_tkt_match_p (tkts->tkts[i], hint))
701 : 5 : continue;
702 : :
703 : 4 : hint->startpos = i + 1;
704 : 4 : return tkts->tkts[i];
705 : : }
706 : :
707 : 2 : hint->startpos = i;
708 : 6 : return NULL;
709 : : }
710 : :
711 : : /**
712 : : * shishi_tkts_find_for_clientserver:
713 : : * @tkts: ticket set handle as allocated by shishi_tkts().
714 : : * @client: client name to find ticket for.
715 : : * @server: server name to find ticket for.
716 : : *
717 : : * Short-hand function for searching the ticket set for a ticket for
718 : : * the given client and server. See shishi_tkts_find().
719 : : *
720 : : * Return value: Returns a ticket if found, or NULL.
721 : : **/
722 : : Shishi_tkt *
723 : 0 : shishi_tkts_find_for_clientserver (Shishi_tkts * tkts,
724 : : const char *client, const char *server)
725 : : {
726 : : Shishi_tkts_hint hint;
727 : : Shishi_tkt *tkt;
728 : :
729 : 0 : memset (&hint, 0, sizeof (hint));
730 : 0 : hint.server = (char *) server;
731 : 0 : hint.client = (char *) client;
732 : :
733 : 0 : tkt = shishi_tkts_find (tkts, &hint);
734 : :
735 : 0 : return tkt;
736 : : }
737 : :
738 : : /**
739 : : * shishi_tkts_find_for_server:
740 : : * @tkts: ticket set handle as allocated by shishi_tkts().
741 : : * @server: server name to find ticket for.
742 : : *
743 : : * Short-hand function for searching the ticket set for a ticket for
744 : : * the given server using the default client principal. See
745 : : * shishi_tkts_find_for_clientserver() and shishi_tkts_find().
746 : : *
747 : : * Return value: Returns a ticket if found, or NULL.
748 : : **/
749 : : Shishi_tkt *
750 : 0 : shishi_tkts_find_for_server (Shishi_tkts * tkts, const char *server)
751 : : {
752 : 0 : return shishi_tkts_find_for_clientserver
753 : : (tkts, shishi_principal_default (tkts->handle), server);
754 : : }
755 : :
756 : : /* Set flags and times in KDC-REQ based on hint. */
757 : : static int
758 : 0 : act_hint_on_kdcreq (Shishi * handle,
759 : : Shishi_tkts_hint * hint, Shishi_asn1 kdcreq)
760 : : {
761 [ # # ]: 0 : time_t starttime = hint->starttime ? hint->starttime : time (NULL);
762 : 0 : time_t endtime = hint->endtime ? hint->endtime :
763 [ # # ]: 0 : starttime + handle->ticketlife;
764 : 0 : time_t renew_till = hint->renew_till ? hint->renew_till :
765 [ # # ]: 0 : starttime + handle->renewlife;
766 : : int rc;
767 : :
768 [ # # ]: 0 : if (hint->starttime)
769 : : {
770 : 0 : rc = shishi_asn1_write (handle, kdcreq, "req-body.from",
771 : : shishi_generalize_time (handle, starttime), 0);
772 [ # # ]: 0 : if (rc != SHISHI_OK)
773 : : {
774 : 0 : shishi_error_printf (handle, "Cannot set starttime: %s",
775 : : shishi_strerror (rc));
776 : 0 : return rc;
777 : : }
778 : : }
779 : :
780 [ # # ]: 0 : if (hint->endtime)
781 : : {
782 : 0 : rc = shishi_asn1_write (handle, kdcreq, "req-body.till",
783 : : shishi_generalize_time (handle, endtime), 0);
784 [ # # ]: 0 : if (rc != SHISHI_OK)
785 : : {
786 : 0 : shishi_error_printf (handle, "Cannot set endtime: %s",
787 : : shishi_strerror (rc));
788 : 0 : return rc;
789 : : }
790 : : }
791 : :
792 [ # # ]: 0 : if (hint->tktflags & SHISHI_TICKETFLAGS_FORWARDABLE)
793 : : {
794 : 0 : rc = shishi_kdcreq_options_add (handle, kdcreq,
795 : : SHISHI_KDCOPTIONS_FORWARDABLE);
796 [ # # ]: 0 : if (rc != SHISHI_OK)
797 : 0 : goto done;
798 : : }
799 : :
800 [ # # ]: 0 : if (hint->tktflags & SHISHI_TICKETFLAGS_FORWARDED)
801 : : {
802 : 0 : rc = shishi_kdcreq_options_add (handle, kdcreq,
803 : : SHISHI_KDCOPTIONS_FORWARDED);
804 [ # # ]: 0 : if (rc != SHISHI_OK)
805 : 0 : goto done;
806 : : }
807 : :
808 [ # # ]: 0 : if (hint->tktflags & SHISHI_TICKETFLAGS_RENEWABLE)
809 : : {
810 : 0 : rc = shishi_kdcreq_options_add (handle, kdcreq,
811 : : SHISHI_KDCOPTIONS_RENEWABLE);
812 [ # # ]: 0 : if (rc != SHISHI_OK)
813 : 0 : goto done;
814 : :
815 : 0 : rc = shishi_asn1_write (handle, kdcreq, "req-body.rtime",
816 : : shishi_generalize_time (handle, renew_till), 0);
817 [ # # ]: 0 : if (rc != SHISHI_OK)
818 : : {
819 : 0 : shishi_error_printf (handle, "Cannot set renewtill: %s",
820 : : shishi_strerror (rc));
821 : 0 : return rc;
822 : : }
823 : : }
824 : :
825 [ # # ]: 0 : if (hint->tktflags & SHISHI_TICKETFLAGS_PROXIABLE)
826 : : {
827 : 0 : rc = shishi_kdcreq_options_add (handle, kdcreq,
828 : : SHISHI_KDCOPTIONS_PROXIABLE);
829 [ # # ]: 0 : if (rc != SHISHI_OK)
830 : 0 : goto done;
831 : : }
832 : :
833 [ # # ]: 0 : if (hint->tktflags & SHISHI_TICKETFLAGS_PROXY)
834 : : {
835 : 0 : rc = shishi_kdcreq_options_add (handle, kdcreq,
836 : : SHISHI_KDCOPTIONS_PROXY);
837 [ # # ]: 0 : if (rc != SHISHI_OK)
838 : 0 : goto done;
839 : : }
840 : :
841 : :
842 [ # # ]: 0 : if (hint->etype)
843 : : {
844 : 0 : rc = shishi_kdcreq_set_etype (handle, kdcreq, &hint->etype, 1);
845 [ # # ]: 0 : if (rc != SHISHI_OK)
846 : 0 : goto done;
847 : : }
848 : :
849 : 0 : return SHISHI_OK;
850 : :
851 : : done:
852 : 0 : shishi_error_printf (handle, "Cannot set KDC Options: %s",
853 : : shishi_strerror (rc));
854 : 0 : return rc;
855 : : }
856 : :
857 : : /* Make sure the ticket granting ticket is suitable for the wanted
858 : : ticket. E.g., if the wanted ticket should be a PROXY ticket, the
859 : : ticket granting ticket must be a PROXIABLE ticket for things to
860 : : work. */
861 : : static void
862 : 0 : set_tgtflags_based_on_hint (Shishi_tkts_hint * tkthint,
863 : : Shishi_tkts_hint * tgthint)
864 : : {
865 [ # # ]: 0 : if (tkthint->tktflags & SHISHI_TICKETFLAGS_FORWARDABLE)
866 : 0 : tgthint->tktflags |= SHISHI_TICKETFLAGS_FORWARDABLE;
867 : :
868 [ # # ]: 0 : if (tkthint->tktflags & SHISHI_TICKETFLAGS_FORWARDED)
869 : 0 : tgthint->tktflags |= SHISHI_TICKETFLAGS_FORWARDABLE;
870 : :
871 [ # # ]: 0 : if (tkthint->tktflags & SHISHI_TICKETFLAGS_PROXIABLE)
872 : 0 : tgthint->tktflags |= SHISHI_TICKETFLAGS_PROXIABLE;
873 : :
874 [ # # ]: 0 : if (tkthint->tktflags & SHISHI_TICKETFLAGS_PROXY)
875 : 0 : tgthint->tktflags |= SHISHI_TICKETFLAGS_PROXIABLE;
876 : :
877 [ # # ]: 0 : if (tkthint->tktflags & SHISHI_TICKETFLAGS_RENEWABLE)
878 : 0 : tgthint->tktflags |= SHISHI_TICKETFLAGS_RENEWABLE;
879 : :
880 [ # # ]: 0 : if (tkthint->kdcoptions & SHISHI_KDCOPTIONS_RENEW)
881 : 0 : tgthint->tktflags |= SHISHI_TICKETFLAGS_RENEWABLE;
882 : :
883 [ # # ]: 0 : if (tkthint->endtime)
884 : 0 : tgthint->endtime = tkthint->endtime;
885 : :
886 [ # # ]: 0 : if (tkthint->passwd)
887 : 0 : tgthint->passwd = tkthint->passwd;
888 : :
889 [ # # ]: 0 : if (tkthint->preauthetype)
890 : 0 : tgthint->preauthetype = tkthint->preauthetype;
891 : :
892 [ # # ]: 0 : if (tkthint->preauthsalt)
893 : : {
894 : 0 : tgthint->preauthsalt = tkthint->preauthsalt;
895 : 0 : tgthint->preauthsaltlen = tkthint->preauthsaltlen;
896 : : }
897 : :
898 [ # # ]: 0 : if (tkthint->preauths2kparams)
899 : : {
900 : 0 : tgthint->preauths2kparams = tkthint->preauths2kparams;
901 : 0 : tgthint->preauths2kparamslen = tkthint->preauths2kparamslen;
902 : : }
903 : 0 : }
904 : :
905 : : /* Pre-authenticate request, based on LOCHINT. Currently only
906 : : PA-ENC-TIMESTAMP is supported. */
907 : : static int
908 : 0 : do_preauth (Shishi_tkts * tkts, Shishi_tkts_hint * lochint, Shishi_as * as)
909 : : {
910 : 0 : int rc = SHISHI_OK;
911 : :
912 [ # # ]: 0 : if (lochint->preauthetype)
913 : : {
914 : : Shishi_key *key;
915 : : char *user;
916 : :
917 : : /* XXX Don't prompt for password here? */
918 : :
919 : 0 : rc = shishi_asreq_clientrealm (tkts->handle, shishi_as_req (as),
920 : : &user, NULL);
921 [ # # ]: 0 : if (rc != SHISHI_OK)
922 : 0 : return rc;
923 : :
924 [ # # ]: 0 : if (lochint->passwd == NULL)
925 : : {
926 : 0 : rc = shishi_prompt_password (tkts->handle, &lochint->passwd,
927 : : "Enter password for `%s': ", user);
928 [ # # ]: 0 : if (rc != SHISHI_OK)
929 : 0 : return rc;
930 : : }
931 : :
932 [ # # ]: 0 : if (!lochint->preauthsalt)
933 : : {
934 : 0 : rc = shishi_derive_default_salt (tkts->handle, user,
935 : : &lochint->preauthsalt);
936 [ # # ]: 0 : if (rc != SHISHI_OK)
937 : 0 : return rc;
938 : :
939 : 0 : lochint->preauthsaltlen = strlen (lochint->preauthsalt);
940 : : }
941 : :
942 : 0 : rc = shishi_key_from_string (tkts->handle, lochint->preauthetype,
943 : 0 : lochint->passwd, strlen (lochint->passwd),
944 : 0 : lochint->preauthsalt,
945 : : lochint->preauthsaltlen,
946 : 0 : lochint->preauths2kparams, &key);
947 [ # # ]: 0 : if (rc != SHISHI_OK)
948 : 0 : return rc;
949 : :
950 : 0 : rc = shishi_kdcreq_add_padata_preauth (tkts->handle,
951 : : shishi_as_req (as), key);
952 : : }
953 : :
954 : 0 : return rc;
955 : : }
956 : :
957 : : /* Handle ETYPE-INFO and ETYPE-INFO2 pre-auth data. */
958 : : static int
959 : 0 : recover_preauth_info (Shishi_tkts * tkts,
960 : : Shishi_as * as,
961 : : Shishi_tkts_hint * lochint,
962 : : Shishi_asn1 einfos, bool isinfo2, bool * retry)
963 : : {
964 : 0 : size_t foundpos = SIZE_MAX;
965 : : size_t i, n;
966 : : int rc;
967 : :
968 : 0 : shishi_verbose (tkts->handle, "Found INFO-ETYPE(2) pre-auth hints");
969 : :
970 [ # # ]: 0 : if (VERBOSEASN1 (tkts->handle))
971 : : {
972 [ # # ]: 0 : if (isinfo2)
973 : 0 : shishi_etype_info2_print (tkts->handle, stdout, einfos);
974 : : else
975 : 0 : shishi_etype_info_print (tkts->handle, stdout, einfos);
976 : : }
977 : :
978 [ # # ]: 0 : if (lochint->preauthetype)
979 : : {
980 : 0 : shishi_verbose (tkts->handle, "Pre-auth data already specified");
981 : 0 : return SHISHI_OK;
982 : : }
983 : :
984 : 0 : rc = shishi_asn1_number_of_elements (tkts->handle, einfos, "", &n);
985 [ # # ]: 0 : if (rc != SHISHI_OK)
986 : 0 : return rc;
987 : :
988 [ # # ]: 0 : for (i = 1; i <= n; i++)
989 : : {
990 : : char *format;
991 : : int32_t etype;
992 : :
993 : 0 : format = xasprintf ("?%d.etype", i);
994 : 0 : rc = shishi_asn1_read_int32 (tkts->handle, einfos, format, &etype);
995 : 0 : free (format);
996 [ # # ]: 0 : if (rc == SHISHI_OK)
997 : : {
998 : : size_t j;
999 : :
1000 : 0 : shishi_verbose (tkts->handle, "Server has etype %d", etype);
1001 : :
1002 [ # # ]: 0 : for (j = 0; j < tkts->handle->nclientkdcetypes; j++)
1003 : : {
1004 [ # # ]: 0 : if (etype == tkts->handle->clientkdcetypes[j])
1005 : : {
1006 [ # # ][ # # ]: 0 : if (j < foundpos && VERBOSENOISE (tkts->handle))
1007 : : {
1008 : 0 : shishi_verbose (tkts->handle, "New best etype %d",
1009 : : etype);
1010 : :
1011 : : /* XXX mem leak. */
1012 : :
1013 : 0 : format = xasprintf ("?%d.salt", i);
1014 : 0 : rc = shishi_asn1_read (tkts->handle, einfos, format,
1015 : : &lochint->preauthsalt,
1016 : : &lochint->preauthsaltlen);
1017 : 0 : free (format);
1018 [ # # # # ]: 0 : if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_ELEMENT)
1019 : 0 : return rc;
1020 : :
1021 [ # # ]: 0 : if (isinfo2)
1022 : : {
1023 : 0 : format = xasprintf ("?%d.s2kparams", i);
1024 : 0 : rc = shishi_asn1_read (tkts->handle, einfos, format,
1025 : : &lochint->preauths2kparams,
1026 : : &lochint->preauths2kparamslen);
1027 : 0 : free (format);
1028 [ # # # # ]: 0 : if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_ELEMENT)
1029 : 0 : return rc;
1030 : : }
1031 : : }
1032 : :
1033 : 0 : foundpos = MIN (foundpos, j);
1034 : : }
1035 : : }
1036 : : }
1037 : : }
1038 : :
1039 [ # # ]: 0 : if (foundpos != SIZE_MAX)
1040 : : {
1041 : 0 : lochint->preauthetype = tkts->handle->clientkdcetypes[foundpos];
1042 : :
1043 : 0 : shishi_verbose (tkts->handle, "Best pre-auth etype was %d",
1044 : : lochint->preauthetype);
1045 : :
1046 : 0 : *retry = true;
1047 : : }
1048 : :
1049 : 0 : return SHISHI_OK;
1050 : : }
1051 : :
1052 : : /* Called when KDC refused with a NEED_PREAUTH error. This function
1053 : : should look at the METHOD-DATA, figure out what kind of pre-auth is
1054 : : requested, and if it is able to figure out how to recover from the
1055 : : error, set *RETRY to true and set any hints in LOCHINT that help
1056 : : do_preauth() compute the proper pre-auth data. */
1057 : : static int
1058 : 0 : recover_preauth (Shishi_tkts * tkts,
1059 : : Shishi_as * as, Shishi_tkts_hint * lochint, bool * retry)
1060 : : {
1061 : 0 : Shishi_asn1 krberror = shishi_as_krberror (as);
1062 : : Shishi_asn1 pas;
1063 : : size_t i, n;
1064 : : int rc;
1065 : :
1066 : 0 : *retry = false;
1067 : :
1068 : 0 : shishi_verbose (tkts->handle, "Server requests pre-auth data");
1069 : :
1070 : 0 : rc = shishi_krberror_methoddata (tkts->handle, krberror, &pas);
1071 [ # # ]: 0 : if (rc != SHISHI_OK)
1072 : 0 : return rc;
1073 : :
1074 : 0 : rc = shishi_asn1_number_of_elements (tkts->handle, pas, "", &n);
1075 [ # # ]: 0 : if (rc == SHISHI_OK)
1076 : : {
1077 [ # # ]: 0 : for (i = 1; i <= n; i++)
1078 : : {
1079 : 0 : char *format = xasprintf ("?%d.padata-type", i);
1080 : : int32_t padatatype;
1081 : :
1082 : 0 : rc = shishi_asn1_read_int32 (tkts->handle, pas, format,
1083 : : &padatatype);
1084 : 0 : free (format);
1085 [ # # ]: 0 : if (rc == SHISHI_OK)
1086 : : {
1087 : 0 : shishi_verbose (tkts->handle, "Looking at pa-type %d",
1088 : : padatatype);
1089 : :
1090 [ # # ]: 0 : switch (padatatype)
1091 : : {
1092 : : /* XXX Don't parse INFO structures if there is a
1093 : : INFO2. */
1094 : :
1095 : : case SHISHI_PA_ETYPE_INFO:
1096 : : case SHISHI_PA_ETYPE_INFO2:
1097 : : {
1098 : : char *der;
1099 : : size_t len;
1100 : : Shishi_asn1 einfos;
1101 : :
1102 : 0 : format = xasprintf ("?%d.padata-value", i);
1103 : 0 : rc = shishi_asn1_read (tkts->handle, pas, format,
1104 : : &der, &len);
1105 : 0 : free (format);
1106 [ # # ]: 0 : if (rc != SHISHI_OK)
1107 : : {
1108 : 0 : shishi_error_printf (tkts->handle,
1109 : : "Can't extract PA-DATA value");
1110 : 0 : continue;
1111 : : }
1112 : :
1113 [ # # ]: 0 : if (padatatype == SHISHI_PA_ETYPE_INFO)
1114 : 0 : einfos = shishi_der2asn1_etype_info (tkts->handle,
1115 : : der, len);
1116 : : else
1117 : 0 : einfos = shishi_der2asn1_etype_info2 (tkts->handle,
1118 : : der, len);
1119 : 0 : free (der);
1120 [ # # ]: 0 : if (!einfos)
1121 : : {
1122 : 0 : shishi_error_printf (tkts->handle,
1123 : : "Can't DER decode PA-DATA");
1124 : 0 : continue;
1125 : : }
1126 : :
1127 : 0 : rc = recover_preauth_info
1128 : : (tkts, as, lochint, einfos,
1129 : : padatatype == SHISHI_PA_ETYPE_INFO2, retry);
1130 [ # # ]: 0 : if (rc != SHISHI_OK)
1131 : : {
1132 : 0 : shishi_error_printf (tkts->handle,
1133 : : "Could not use pre-auth data: %s",
1134 : : shishi_strerror (rc));
1135 : 0 : continue;
1136 : : }
1137 : :
1138 : 0 : shishi_asn1_done (tkts->handle, einfos);
1139 : : }
1140 : : break;
1141 : :
1142 : : default:
1143 : : break;
1144 : : }
1145 : : }
1146 : : }
1147 : : }
1148 : :
1149 : 0 : shishi_asn1_done (tkts->handle, pas);
1150 : :
1151 : 0 : return SHISHI_OK;
1152 : : }
1153 : :
1154 : : /**
1155 : : * shishi_tkts_get_tgt:
1156 : : * @tkts: ticket set handle as allocated by shishi_tkts().
1157 : : * @hint: structure with characteristics of ticket to begot.
1158 : : *
1159 : : * Get a ticket granting ticket (TGT) suitable for acquiring ticket
1160 : : * matching the hint. I.e., get a TGT for the server realm in the
1161 : : * hint structure (hint->serverrealm), or the default realm if the
1162 : : * serverrealm field is NULL. Can result in AS exchange.
1163 : : *
1164 : : * Currently this function do not implement cross realm logic.
1165 : : *
1166 : : * This function is used by shishi_tkts_get(), which is probably what
1167 : : * you really want to use unless you have special needs.
1168 : : *
1169 : : * Return value: Returns a ticket granting ticket if successful, or
1170 : : * NULL if this function is unable to acquire on.
1171 : : **/
1172 : : Shishi_tkt *
1173 : 0 : shishi_tkts_get_tgt (Shishi_tkts * tkts, Shishi_tkts_hint * hint)
1174 : : {
1175 : : Shishi_tkts_hint lochint;
1176 : : Shishi_as *as;
1177 : : Shishi_tkt *tgt;
1178 : : int rc;
1179 : :
1180 : : /* XXX cross-realm operation */
1181 : :
1182 : 0 : memset (&lochint, 0, sizeof (lochint));
1183 [ # # ]: 0 : asprintf (&lochint.server, "krbtgt/%s", hint->serverrealm ?
1184 : 0 : hint->serverrealm : shishi_realm_default (tkts->handle));
1185 : 0 : set_tgtflags_based_on_hint (hint, &lochint);
1186 : :
1187 : 0 : tgt = shishi_tkts_find (tkts, &lochint);
1188 : :
1189 : 0 : free (lochint.server);
1190 : 0 : lochint.server = NULL;
1191 : :
1192 [ # # ]: 0 : if (tgt)
1193 : 0 : return tgt;
1194 : :
1195 [ # # ]: 0 : if (hint->flags & SHISHI_TKTSHINTFLAGS_NON_INTERACTIVE)
1196 : 0 : return NULL;
1197 : :
1198 : : again:
1199 : 0 : rc = shishi_as (tkts->handle, &as);
1200 [ # # ]: 0 : if (rc == SHISHI_OK)
1201 : 0 : rc = act_hint_on_kdcreq (tkts->handle, &lochint, shishi_as_req (as));
1202 [ # # ]: 0 : if (rc == SHISHI_OK)
1203 : 0 : rc = do_preauth (tkts, &lochint, as);
1204 [ # # ]: 0 : if (rc == SHISHI_OK)
1205 : 0 : rc = shishi_as_req_build (as);
1206 [ # # ]: 0 : if (rc == SHISHI_OK)
1207 : 0 : rc = shishi_as_sendrecv_hint (as, &lochint);
1208 [ # # ]: 0 : if (rc == SHISHI_OK)
1209 : 0 : rc = shishi_as_rep_process (as, NULL, lochint.passwd);
1210 [ # # # # ]: 0 : if (rc == SHISHI_GOT_KRBERROR
1211 : : && shishi_krberror_errorcode_fast (tkts->handle,
1212 : : shishi_as_krberror (as))
1213 : 0 : == SHISHI_KDC_ERR_PREAUTH_REQUIRED)
1214 : : {
1215 : 0 : bool retry = false;
1216 : :
1217 : 0 : rc = recover_preauth (tkts, as, &lochint, &retry);
1218 [ # # ]: 0 : if (rc != SHISHI_OK)
1219 : 0 : return NULL;
1220 : :
1221 [ # # ]: 0 : if (retry)
1222 : : {
1223 : 0 : shishi_as_done (as);
1224 : 0 : goto again;
1225 : : }
1226 : :
1227 : 0 : shishi_error_printf (tkts->handle, "Unsupported pre-auth required");
1228 : 0 : return NULL;
1229 : : }
1230 [ # # ]: 0 : if (rc != SHISHI_OK)
1231 : : {
1232 : 0 : shishi_error_printf (tkts->handle,
1233 : : "AS exchange failed: %s\n%s\n",
1234 : : shishi_strerror (rc), shishi_error (tkts->handle));
1235 : 0 : return NULL;
1236 : : }
1237 : :
1238 : : /* XXX free lochint members */
1239 : :
1240 : 0 : tgt = shishi_as_tkt (as);
1241 [ # # ]: 0 : if (!tgt)
1242 : : {
1243 : 0 : shishi_error_printf (tkts->handle, "No ticket in AS-REP");
1244 : 0 : return NULL;
1245 : : }
1246 : :
1247 [ # # ]: 0 : if (VERBOSENOISE (tkts->handle))
1248 : : {
1249 : 0 : printf ("Received ticket granting ticket:\n");
1250 : 0 : shishi_tkt_pretty_print (tgt, stdout);
1251 : : }
1252 : :
1253 : 0 : rc = shishi_tkts_add (tkts, tgt);
1254 [ # # ]: 0 : if (rc != SHISHI_OK)
1255 : 0 : printf ("Could not add ticket: %s", shishi_strerror (rc));
1256 : :
1257 : 0 : return tgt;
1258 : : }
1259 : :
1260 : : /**
1261 : : * shishi_tkts_get_tgs:
1262 : : * @tkts: ticket set handle as allocated by shishi_tkts().
1263 : : * @hint: structure with characteristics of ticket to begot.
1264 : : * @tgt: ticket granting ticket to use.
1265 : : *
1266 : : * Get a ticket via TGS exchange using specified ticket granting
1267 : : * ticket.
1268 : : *
1269 : : * This function is used by shishi_tkts_get(), which is probably what
1270 : : * you really want to use unless you have special needs.
1271 : : *
1272 : : * Return value: Returns a ticket if successful, or NULL if this
1273 : : * function is unable to acquire on.
1274 : : **/
1275 : : Shishi_tkt *
1276 : 0 : shishi_tkts_get_tgs (Shishi_tkts * tkts,
1277 : : Shishi_tkts_hint * hint, Shishi_tkt * tgt)
1278 : : {
1279 : : Shishi_tgs *tgs;
1280 : : Shishi_tkt *tkt;
1281 : : int rc;
1282 : :
1283 : 0 : rc = shishi_tgs (tkts->handle, &tgs);
1284 : 0 : shishi_tgs_tgtkt_set (tgs, tgt);
1285 [ # # ]: 0 : if (rc == SHISHI_OK)
1286 : 0 : rc = act_hint_on_kdcreq (tkts->handle, hint, shishi_tgs_req (tgs));
1287 [ # # ]: 0 : if (rc == SHISHI_OK)
1288 : 0 : rc = shishi_tgs_set_server (tgs, hint->server);
1289 [ # # ]: 0 : if (rc == SHISHI_OK)
1290 : 0 : rc = shishi_tgs_req_build (tgs);
1291 [ # # ]: 0 : if (rc == SHISHI_OK)
1292 : 0 : rc = shishi_tgs_sendrecv_hint (tgs, hint);
1293 [ # # ]: 0 : if (rc == SHISHI_OK)
1294 : 0 : rc = shishi_tgs_rep_process (tgs);
1295 [ # # ]: 0 : if (rc != SHISHI_OK)
1296 : : {
1297 : 0 : shishi_error_printf (tkts->handle,
1298 : : "TGS exchange failed: %s\n%s\n",
1299 : : shishi_strerror (rc), shishi_error (tkts->handle));
1300 [ # # ]: 0 : if (rc == SHISHI_GOT_KRBERROR)
1301 : 0 : shishi_krberror_pretty_print (tkts->handle, stdout,
1302 : : shishi_tgs_krberror (tgs));
1303 : 0 : return NULL;
1304 : : }
1305 : :
1306 : 0 : tkt = shishi_tgs_tkt (tgs);
1307 [ # # ]: 0 : if (!tkt)
1308 : : {
1309 : 0 : shishi_error_printf (tkts->handle, "No ticket in TGS-REP?!: %s",
1310 : : shishi_error (tkts->handle));
1311 : 0 : return NULL;
1312 : : }
1313 : :
1314 [ # # ]: 0 : if (VERBOSENOISE (tkts->handle))
1315 : : {
1316 : 0 : printf ("Received ticket:\n");
1317 : 0 : shishi_tkt_pretty_print (tkt, stdout);
1318 : : }
1319 : :
1320 : 0 : rc = shishi_tkts_add (tkts, tkt);
1321 [ # # ]: 0 : if (rc != SHISHI_OK)
1322 : 0 : printf ("Could not add ticket: %s", shishi_strerror (rc));
1323 : :
1324 : 0 : return tkt;
1325 : : }
1326 : :
1327 : : /**
1328 : : * shishi_tkts_get:
1329 : : * @tkts: ticket set handle as allocated by shishi_tkts().
1330 : : * @hint: structure with characteristics of ticket to begot.
1331 : : *
1332 : : * Get a ticket matching given characteristics. This function first
1333 : : * looks in the ticket set for the ticket, then tries to find a
1334 : : * suitable TGT, possibly via an AS exchange, using
1335 : : * shishi_tkts_get_tgt(), and then use that TGT in a TGS exchange to
1336 : : * get the ticket.
1337 : : *
1338 : : * Currently this function do not implement cross realm logic.
1339 : : *
1340 : : * Return value: Returns a ticket if found, or NULL if this function
1341 : : * is unable to get the ticket.
1342 : : **/
1343 : : Shishi_tkt *
1344 : 0 : shishi_tkts_get (Shishi_tkts * tkts, Shishi_tkts_hint * hint)
1345 : : {
1346 : : Shishi_tkt *tkt, *tgt;
1347 : :
1348 : : /* If we already have a matching ticket, avoid getting a new one. */
1349 : 0 : hint->startpos = 0;
1350 : 0 : tkt = shishi_tkts_find (tkts, hint);
1351 [ # # ]: 0 : if (tkt)
1352 : 0 : return tkt;
1353 : :
1354 : 0 : tgt = shishi_tkts_get_tgt (tkts, hint);
1355 [ # # ]: 0 : if (!tgt)
1356 : : {
1357 : 0 : shishi_error_printf (tkts->handle, "Could not get TGT for ticket.");
1358 : 0 : return NULL;
1359 : : }
1360 : :
1361 [ # # ]: 0 : if (shishi_tkt_match_p (tgt, hint))
1362 : 0 : return tgt;
1363 : :
1364 : 0 : tkt = shishi_tkts_get_tgs (tkts, hint, tgt);
1365 [ # # ]: 0 : if (!tkt)
1366 : : {
1367 : 0 : shishi_error_printf (tkts->handle, "Could not get ticket using TGT.");
1368 : 0 : return NULL;
1369 : : }
1370 : :
1371 : 0 : return tkt;
1372 : : }
1373 : :
1374 : : /**
1375 : : * shishi_tkts_get_for_clientserver:
1376 : : * @tkts: ticket set handle as allocated by shishi_tkts().
1377 : : * @client: client name to get ticket for.
1378 : : * @server: server name to get ticket for.
1379 : : *
1380 : : * Short-hand function for getting a ticket for the given client and
1381 : : * server. See shishi_tkts_get().
1382 : : *
1383 : : * Return value: Returns a ticket if found, or NULL.
1384 : : **/
1385 : : Shishi_tkt *
1386 : 0 : shishi_tkts_get_for_clientserver (Shishi_tkts * tkts,
1387 : : const char *client, const char *server)
1388 : : {
1389 : : Shishi_tkts_hint hint;
1390 : : Shishi_tkt *tkt;
1391 : :
1392 : 0 : memset (&hint, 0, sizeof (hint));
1393 : 0 : hint.client = (char *) client;
1394 : 0 : hint.server = (char *) server;
1395 : :
1396 : 0 : tkt = shishi_tkts_get (tkts, &hint);
1397 : :
1398 : 0 : return tkt;
1399 : : }
1400 : :
1401 : : /**
1402 : : * shishi_tkts_get_for_server:
1403 : : * @tkts: ticket set handle as allocated by shishi_tkts().
1404 : : * @server: server name to get ticket for.
1405 : : *
1406 : : * Short-hand function for getting a ticket for the given server and
1407 : : * the default principal client. See shishi_tkts_get().
1408 : : *
1409 : : * Return value: Returns a ticket if found, or NULL.
1410 : : **/
1411 : : Shishi_tkt *
1412 : 0 : shishi_tkts_get_for_server (Shishi_tkts * tkts, const char *server)
1413 : : {
1414 : 0 : return shishi_tkts_get_for_clientserver
1415 : : (tkts, shishi_principal_default (tkts->handle), server);
1416 : : }
1417 : :
1418 : : Shishi_tkt *
1419 : 0 : shishi_tkts_get_for_localservicepasswd (Shishi_tkts * tkts,
1420 : : const char *service,
1421 : : const char *passwd)
1422 : : {
1423 : : Shishi_tkt *tkt;
1424 : : Shishi_tkts_hint hint;
1425 : :
1426 : 0 : memset (&hint, 0, sizeof (hint));
1427 : 0 : hint.client = (char *) shishi_principal_default (tkts->handle);
1428 : 0 : hint.server = shishi_server_for_local_service (tkts->handle, service);
1429 : 0 : hint.passwd = (char *) passwd;
1430 : :
1431 : 0 : tkt = shishi_tkts_get (tkts, &hint);
1432 : :
1433 : 0 : free (hint.server);
1434 : :
1435 : 0 : return tkt;
1436 : : }
|