1 /* tkts.c --- Ticket set handling.
2 * Copyright (C) 2002-2013 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 *
shishi_tkts_default_file_guess(Shishi * handle)46 shishi_tkts_default_file_guess (Shishi * handle)
47 {
48 char *envfile;
49
50 envfile = getenv ("SHISHI_TICKETS");
51 if (envfile)
52 return xstrdup (envfile);
53
54 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 *
shishi_tkts_default_file(Shishi * handle)68 shishi_tkts_default_file (Shishi * handle)
69 {
70 if (!handle->tktsdefaultfile)
71 {
72 char *p;
73
74 p = shishi_tkts_default_file_guess (handle);
75 shishi_tkts_default_file_set (handle, p);
76 free (p);
77 }
78
79 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
shishi_tkts_default_file_set(Shishi * handle,const char * tktsfile)93 shishi_tkts_default_file_set (Shishi * handle, const char *tktsfile)
94 {
95 free (handle->tktsdefaultfile);
96 if (tktsfile)
97 handle->tktsdefaultfile = xstrdup (tktsfile);
98 else
99 handle->tktsdefaultfile = NULL;
100 }
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 *
shishi_tkts_default(Shishi * handle)111 shishi_tkts_default (Shishi * handle)
112 {
113 if (handle->tkts == NULL &&
114 (shishi_tkts (handle, &handle->tkts) != SHISHI_OK))
115 handle->tkts = NULL;
116
117 return handle->tkts;
118 }
119
120 int
shishi_tkts_default_to_file(Shishi_tkts * tkts)121 shishi_tkts_default_to_file (Shishi_tkts * tkts)
122 {
123 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
shishi_tkts(Shishi * handle,Shishi_tkts ** tkts)136 shishi_tkts (Shishi * handle, Shishi_tkts ** tkts)
137 {
138 *tkts = xcalloc (1, sizeof (**tkts));
139
140 (*tkts)->handle = handle;
141
142 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
shishi_tkts_done(Shishi_tkts ** tkts)154 shishi_tkts_done (Shishi_tkts ** tkts)
155 {
156 if (!tkts || !*tkts)
157 return;
158
159 if ((*tkts)->tkts)
160 free ((*tkts)->tkts);
161 free (*tkts);
162
163 *tkts = NULL;
164
165 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
shishi_tkts_size(Shishi_tkts * tkts)177 shishi_tkts_size (Shishi_tkts * tkts)
178 {
179 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 *
shishi_tkts_nth(Shishi_tkts * tkts,int ticketno)195 shishi_tkts_nth (Shishi_tkts * tkts, int ticketno)
196 {
197 if (tkts == NULL || ticketno >= tkts->ntkts)
198 return NULL;
199
200 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
shishi_tkts_remove(Shishi_tkts * tkts,int ticketno)215 shishi_tkts_remove (Shishi_tkts * tkts, int ticketno)
216 {
217 if (!tkts)
218 return SHISHI_INVALID_TKTS;
219
220 if (ticketno >= tkts->ntkts)
221 return SHISHI_OK;
222
223 if (ticketno < tkts->ntkts)
224 memmove (&tkts->tkts[ticketno], &tkts->tkts[ticketno + 1],
225 sizeof (*tkts->tkts) * (tkts->ntkts - ticketno - 1));
226
227 --tkts->ntkts;
228
229 if (tkts->ntkts > 0)
230 {
231 tkts->tkts = xrealloc (tkts->tkts, sizeof (*tkts->tkts) * tkts->ntkts);
232 }
233 else
234 {
235 free (tkts->tkts);
236 tkts->tkts = NULL;
237 }
238
239 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
shishi_tkts_add(Shishi_tkts * tkts,Shishi_tkt * tkt)254 shishi_tkts_add (Shishi_tkts * tkts, Shishi_tkt * tkt)
255 {
256 if (!tkt)
257 return SHISHI_INVALID_TICKET;
258
259 if (tkts->ntkts++ == 0)
260 tkts->tkts = xmalloc (sizeof (*tkts->tkts));
261 else
262 tkts->tkts = xrealloc (tkts->tkts, sizeof (*tkts->tkts) * tkts->ntkts);
263
264 tkts->tkts[tkts->ntkts - 1] = tkt;
265
266 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
shishi_tkts_new(Shishi_tkts * tkts,Shishi_asn1 ticket,Shishi_asn1 enckdcreppart,Shishi_asn1 kdcrep)285 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 tkt = shishi_tkt2 (tkts->handle, ticket, enckdcreppart, kdcrep);
294
295 res = shishi_tkts_add (tkts, tkt);
296 if (res != SHISHI_OK)
297 {
298 free (tkt);
299 return res;
300 }
301
302 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
shishi_tkts_read(Shishi_tkts * tkts,FILE * fh)315 shishi_tkts_read (Shishi_tkts * tkts, FILE * fh)
316 {
317 int res;
318
319 res = SHISHI_OK;
320 while (!feof (fh))
321 {
322 Shishi_asn1 ticket;
323 Shishi_asn1 enckdcreppart;
324 Shishi_asn1 kdcrep;
325
326 res = shishi_kdcrep_parse (tkts->handle, fh, &kdcrep);
327 if (res != SHISHI_OK)
328 {
329 res = SHISHI_OK;
330 break;
331 }
332
333 res = shishi_enckdcreppart_parse (tkts->handle, fh, &enckdcreppart);
334 if (res != SHISHI_OK)
335 break;
336
337 res = shishi_ticket_parse (tkts->handle, fh, &ticket);
338 if (res != SHISHI_OK)
339 break;
340
341 /* XXX Who will de-allocate these? */
342 res = shishi_tkts_new (tkts, ticket, enckdcreppart, kdcrep);
343 if (res != SHISHI_OK)
344 break;
345
346 if (VERBOSEASN1 (tkts->handle))
347 {
348 printf ("Read ticket for principal `':\n");
349 shishi_kdcrep_print (tkts->handle, stdout, kdcrep);
350 shishi_enckdcreppart_print (tkts->handle, stdout, enckdcreppart);
351 shishi_ticket_print (tkts->handle, stdout, ticket);
352 }
353 }
354
355 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
shishi_tkts_from_file(Shishi_tkts * tkts,const char * filename)368 shishi_tkts_from_file (Shishi_tkts * tkts, const char *filename)
369 {
370 FILE *fh;
371 int res;
372
373 fh = fopen (filename, "r");
374 if (fh == NULL)
375 return SHISHI_FOPEN_ERROR;
376
377 res = shishi_tkts_read (tkts, fh);
378 if (res != SHISHI_OK)
379 {
380 fclose (fh);
381 return res;
382 }
383
384 res = fclose (fh);
385 if (res != 0)
386 return SHISHI_IO_ERROR;
387
388 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
shishi_tkts_write(Shishi_tkts * tkts,FILE * fh)401 shishi_tkts_write (Shishi_tkts * tkts, FILE * fh)
402 {
403 int res;
404 int i;
405
406 if (!tkts)
407 return SHISHI_INVALID_TKTS;
408
409 for (i = 0; i < tkts->ntkts; i++)
410 {
411 res = shishi_kdcrep_print
412 (tkts->handle, fh, shishi_tkt_kdcrep (tkts->tkts[i]));
413 if (res != SHISHI_OK)
414 {
415 shishi_error_printf (tkts->handle,
416 "Could not print ticket: %s",
417 shishi_error (tkts->handle));
418 return res;
419 }
420
421 res = shishi_enckdcreppart_print
422 (tkts->handle, fh, shishi_tkt_enckdcreppart (tkts->tkts[i]));
423 if (res != SHISHI_OK)
424 {
425 shishi_error_printf (tkts->handle,
426 "Could not print ticket: %s",
427 shishi_error (tkts->handle));
428 return res;
429 }
430
431 res = shishi_ticket_print (tkts->handle, fh,
432 shishi_tkt_ticket (tkts->tkts[i]));
433 if (res != SHISHI_OK)
434 {
435 shishi_error_printf (tkts->handle,
436 "Could not print ticket: %s",
437 shishi_error (tkts->handle));
438 return res;
439 }
440
441 fprintf (fh, "\n\n");
442 }
443
444 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
shishi_tkts_expire(Shishi_tkts * tkts)456 shishi_tkts_expire (Shishi_tkts * tkts)
457 {
458 int warn = 0;
459 int i = 0;
460
461 if (!tkts)
462 return SHISHI_INVALID_TKTS;
463
464 while (i < tkts->ntkts)
465 {
466 if (shishi_tkt_expired_p (tkts->tkts[i]))
467 {
468 warn++;
469 shishi_tkts_remove (tkts, i);
470 }
471 else
472 i++;
473 }
474
475 if (VERBOSE (tkts->handle) && warn)
476 shishi_warn (tkts->handle,
477 ngettext ("removed %d expired ticket\n",
478 "removed %d expired tickets\n", warn), warn);
479
480 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
shishi_tkts_to_file(Shishi_tkts * tkts,const char * filename)493 shishi_tkts_to_file (Shishi_tkts * tkts, const char *filename)
494 {
495 FILE *fh;
496 int res;
497
498 fh = fopen (filename, "w");
499 if (fh == NULL)
500 return SHISHI_FOPEN_ERROR;
501
502 res = shishi_tkts_write (tkts, fh);
503 if (res != SHISHI_OK)
504 {
505 fclose (fh);
506 return res;
507 }
508
509 res = fclose (fh);
510 if (res != 0)
511 return SHISHI_IO_ERROR;
512
513 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
shishi_tkts_print_for_service(Shishi_tkts * tkts,FILE * fh,const char * service)528 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 found = 0;
536 for (i = 0; i < shishi_tkts_size (tkts); i++)
537 {
538 Shishi_tkt *tkt = shishi_tkts_nth (tkts, i);
539
540 if (service)
541 {
542 char *buf;
543
544 res = shishi_tkt_server (tkt, &buf, NULL);
545 if (res != SHISHI_OK)
546 continue;
547
548 if (strcmp (service, buf) != 0)
549 {
550 free (buf);
551 continue;
552 }
553
554 free (buf);
555 }
556
557 printf ("\n");
558 shishi_tkt_pretty_print (shishi_tkts_nth (tkts, i), fh);
559 found++;
560 }
561
562 if (found)
563 {
564 printf (ngettext ("\n%d ticket found.\n", "\n%d tickets found.\n",
565 found), found);
566 }
567 else
568 {
569 if (service)
570 printf ("\nNo matching tickets found.\n");
571 else
572 printf ("\nNo tickets found.\n");
573 }
574
575 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
shishi_tkts_print(Shishi_tkts * tkts,FILE * fh)588 shishi_tkts_print (Shishi_tkts * tkts, FILE * fh)
589 {
590 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
shishi_tkt_match_p(Shishi_tkt * tkt,Shishi_tkts_hint * hint)603 shishi_tkt_match_p (Shishi_tkt * tkt, Shishi_tkts_hint * hint)
604 {
605 if (hint->server && !shishi_tkt_server_p (tkt, hint->server))
606 return 0;
607
608 if (hint->client && !shishi_tkt_client_p (tkt, hint->client))
609 return 0;
610
611 if (!(hint->flags & SHISHI_TKTSHINTFLAGS_ACCEPT_EXPIRED) &&
612 !shishi_tkt_valid_now_p (tkt))
613 return 0;
614
615 if ((hint->tktflags & SHISHI_TICKETFLAGS_FORWARDABLE) &&
616 !shishi_tkt_forwardable_p (tkt))
617 return 0;
618
619 if ((hint->tktflags & SHISHI_TICKETFLAGS_FORWARDED) &&
620 !shishi_tkt_forwarded_p (tkt))
621 return 0;
622
623 if ((hint->tktflags & SHISHI_TICKETFLAGS_RENEWABLE) &&
624 !shishi_tkt_renewable_p (tkt))
625 return 0;
626
627 if ((hint->tktflags & SHISHI_TICKETFLAGS_PROXIABLE) &&
628 !shishi_tkt_proxiable_p (tkt))
629 return 0;
630
631 if ((hint->tktflags & SHISHI_TICKETFLAGS_PROXY) &&
632 !shishi_tkt_proxy_p (tkt))
633 return 0;
634
635 if (hint->etype && !shishi_tkt_keytype_p (tkt, hint->etype))
636 return 0;
637
638 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 *
shishi_tkts_find(Shishi_tkts * tkts,Shishi_tkts_hint * hint)681 shishi_tkts_find (Shishi_tkts * tkts, Shishi_tkts_hint * hint)
682 {
683 int i;
684
685 if (!tkts)
686 return NULL;
687
688 if (VERBOSENOISE (tkts->handle))
689 {
690 fprintf (stderr, "Searching tickets... ");
691 if (hint->server)
692 fprintf (stderr, "server=`%s' ", hint->server);
693 if (hint->client)
694 fprintf (stderr, "client=`%s' ", hint->client);
695 fprintf (stderr, "\n");
696 }
697
698 for (i = hint->startpos; i < tkts->ntkts; i++)
699 {
700 if (!shishi_tkt_match_p (tkts->tkts[i], hint))
701 continue;
702
703 hint->startpos = i + 1;
704 return tkts->tkts[i];
705 }
706
707 hint->startpos = i;
708 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 *
shishi_tkts_find_for_clientserver(Shishi_tkts * tkts,const char * client,const char * server)723 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 memset (&hint, 0, sizeof (hint));
730 hint.server = (char *) server;
731 hint.client = (char *) client;
732
733 tkt = shishi_tkts_find (tkts, &hint);
734
735 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 *
shishi_tkts_find_for_server(Shishi_tkts * tkts,const char * server)750 shishi_tkts_find_for_server (Shishi_tkts * tkts, const char *server)
751 {
752 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
act_hint_on_kdcreq(Shishi * handle,Shishi_tkts_hint * hint,Shishi_asn1 kdcreq)758 act_hint_on_kdcreq (Shishi * handle,
759 Shishi_tkts_hint * hint, Shishi_asn1 kdcreq)
760 {
761 time_t starttime = hint->starttime ? hint->starttime : time (NULL);
762 time_t endtime = hint->endtime ? hint->endtime :
763 starttime + handle->ticketlife;
764 time_t renew_till = hint->renew_till ? hint->renew_till :
765 starttime + handle->renewlife;
766 int rc;
767
768 if (hint->starttime)
769 {
770 rc = shishi_asn1_write (handle, kdcreq, "req-body.from",
771 shishi_generalize_time (handle, starttime), 0);
772 if (rc != SHISHI_OK)
773 {
774 shishi_error_printf (handle, "Cannot set starttime: %s",
775 shishi_strerror (rc));
776 return rc;
777 }
778 }
779
780 if (hint->endtime)
781 {
782 rc = shishi_asn1_write (handle, kdcreq, "req-body.till",
783 shishi_generalize_time (handle, endtime), 0);
784 if (rc != SHISHI_OK)
785 {
786 shishi_error_printf (handle, "Cannot set endtime: %s",
787 shishi_strerror (rc));
788 return rc;
789 }
790 }
791
792 if (hint->tktflags & SHISHI_TICKETFLAGS_FORWARDABLE)
793 {
794 rc = shishi_kdcreq_options_add (handle, kdcreq,
795 SHISHI_KDCOPTIONS_FORWARDABLE);
796 if (rc != SHISHI_OK)
797 goto done;
798 }
799
800 if (hint->tktflags & SHISHI_TICKETFLAGS_FORWARDED)
801 {
802 rc = shishi_kdcreq_options_add (handle, kdcreq,
803 SHISHI_KDCOPTIONS_FORWARDED);
804 if (rc != SHISHI_OK)
805 goto done;
806 }
807
808 if (hint->tktflags & SHISHI_TICKETFLAGS_RENEWABLE)
809 {
810 rc = shishi_kdcreq_options_add (handle, kdcreq,
811 SHISHI_KDCOPTIONS_RENEWABLE);
812 if (rc != SHISHI_OK)
813 goto done;
814
815 rc = shishi_asn1_write (handle, kdcreq, "req-body.rtime",
816 shishi_generalize_time (handle, renew_till), 0);
817 if (rc != SHISHI_OK)
818 {
819 shishi_error_printf (handle, "Cannot set renewtill: %s",
820 shishi_strerror (rc));
821 return rc;
822 }
823 }
824
825 if (hint->tktflags & SHISHI_TICKETFLAGS_PROXIABLE)
826 {
827 rc = shishi_kdcreq_options_add (handle, kdcreq,
828 SHISHI_KDCOPTIONS_PROXIABLE);
829 if (rc != SHISHI_OK)
830 goto done;
831 }
832
833 if (hint->tktflags & SHISHI_TICKETFLAGS_PROXY)
834 {
835 rc = shishi_kdcreq_options_add (handle, kdcreq,
836 SHISHI_KDCOPTIONS_PROXY);
837 if (rc != SHISHI_OK)
838 goto done;
839 }
840
841
842 if (hint->etype)
843 {
844 rc = shishi_kdcreq_set_etype (handle, kdcreq, &hint->etype, 1);
845 if (rc != SHISHI_OK)
846 goto done;
847 }
848
849 return SHISHI_OK;
850
851 done:
852 shishi_error_printf (handle, "Cannot set KDC Options: %s",
853 shishi_strerror (rc));
854 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
set_tgtflags_based_on_hint(Shishi_tkts_hint * tkthint,Shishi_tkts_hint * tgthint)862 set_tgtflags_based_on_hint (Shishi_tkts_hint * tkthint,
863 Shishi_tkts_hint * tgthint)
864 {
865 if (tkthint->tktflags & SHISHI_TICKETFLAGS_FORWARDABLE)
866 tgthint->tktflags |= SHISHI_TICKETFLAGS_FORWARDABLE;
867
868 if (tkthint->tktflags & SHISHI_TICKETFLAGS_FORWARDED)
869 tgthint->tktflags |= SHISHI_TICKETFLAGS_FORWARDABLE;
870
871 if (tkthint->tktflags & SHISHI_TICKETFLAGS_PROXIABLE)
872 tgthint->tktflags |= SHISHI_TICKETFLAGS_PROXIABLE;
873
874 if (tkthint->tktflags & SHISHI_TICKETFLAGS_PROXY)
875 tgthint->tktflags |= SHISHI_TICKETFLAGS_PROXIABLE;
876
877 if (tkthint->tktflags & SHISHI_TICKETFLAGS_RENEWABLE)
878 tgthint->tktflags |= SHISHI_TICKETFLAGS_RENEWABLE;
879
880 if (tkthint->kdcoptions & SHISHI_KDCOPTIONS_RENEW)
881 tgthint->tktflags |= SHISHI_TICKETFLAGS_RENEWABLE;
882
883 if (tkthint->endtime)
884 tgthint->endtime = tkthint->endtime;
885
886 if (tkthint->passwd)
887 tgthint->passwd = tkthint->passwd;
888
889 if (tkthint->preauthetype)
890 tgthint->preauthetype = tkthint->preauthetype;
891
892 if (tkthint->preauthsalt)
893 {
894 tgthint->preauthsalt = tkthint->preauthsalt;
895 tgthint->preauthsaltlen = tkthint->preauthsaltlen;
896 }
897
898 if (tkthint->preauths2kparams)
899 {
900 tgthint->preauths2kparams = tkthint->preauths2kparams;
901 tgthint->preauths2kparamslen = tkthint->preauths2kparamslen;
902 }
903 }
904
905 /* Pre-authenticate request, based on LOCHINT. Currently only
906 PA-ENC-TIMESTAMP is supported. */
907 static int
do_preauth(Shishi_tkts * tkts,Shishi_tkts_hint * lochint,Shishi_as * as)908 do_preauth (Shishi_tkts * tkts, Shishi_tkts_hint * lochint, Shishi_as * as)
909 {
910 int rc = SHISHI_OK;
911
912 if (lochint->preauthetype)
913 {
914 Shishi_key *key;
915 char *user;
916
917 /* XXX Don't prompt for password here? */
918
919 rc = shishi_asreq_clientrealm (tkts->handle, shishi_as_req (as),
920 &user, NULL);
921 if (rc != SHISHI_OK)
922 return rc;
923
924 if (lochint->passwd == NULL)
925 {
926 rc = shishi_prompt_password (tkts->handle, &lochint->passwd,
927 "Enter password for `%s': ", user);
928 if (rc != SHISHI_OK)
929 return rc;
930 }
931
932 if (!lochint->preauthsalt)
933 {
934 rc = shishi_derive_default_salt (tkts->handle, user,
935 &lochint->preauthsalt);
936 if (rc != SHISHI_OK)
937 return rc;
938
939 lochint->preauthsaltlen = strlen (lochint->preauthsalt);
940 }
941
942 rc = shishi_key_from_string (tkts->handle, lochint->preauthetype,
943 lochint->passwd, strlen (lochint->passwd),
944 lochint->preauthsalt,
945 lochint->preauthsaltlen,
946 lochint->preauths2kparams, &key);
947 if (rc != SHISHI_OK)
948 return rc;
949
950 rc = shishi_kdcreq_add_padata_preauth (tkts->handle,
951 shishi_as_req (as), key);
952 }
953
954 return rc;
955 }
956
957 /* Handle ETYPE-INFO and ETYPE-INFO2 pre-auth data. */
958 static int
recover_preauth_info(Shishi_tkts * tkts,Shishi_as * as,Shishi_tkts_hint * lochint,Shishi_asn1 einfos,bool isinfo2,bool * retry)959 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 size_t foundpos = SIZE_MAX;
965 size_t i, n;
966 int rc;
967
968 shishi_verbose (tkts->handle, "Found INFO-ETYPE(2) pre-auth hints");
969
970 if (VERBOSEASN1 (tkts->handle))
971 {
972 if (isinfo2)
973 shishi_etype_info2_print (tkts->handle, stdout, einfos);
974 else
975 shishi_etype_info_print (tkts->handle, stdout, einfos);
976 }
977
978 if (lochint->preauthetype)
979 {
980 shishi_verbose (tkts->handle, "Pre-auth data already specified");
981 return SHISHI_OK;
982 }
983
984 rc = shishi_asn1_number_of_elements (tkts->handle, einfos, "", &n);
985 if (rc != SHISHI_OK)
986 return rc;
987
988 for (i = 1; i <= n; i++)
989 {
990 char *format;
991 int32_t etype;
992
993 format = xasprintf ("?%d.etype", i);
994 rc = shishi_asn1_read_int32 (tkts->handle, einfos, format, &etype);
995 free (format);
996 if (rc == SHISHI_OK)
997 {
998 size_t j;
999
1000 shishi_verbose (tkts->handle, "Server has etype %d", etype);
1001
1002 for (j = 0; j < tkts->handle->nclientkdcetypes; j++)
1003 {
1004 if (etype == tkts->handle->clientkdcetypes[j])
1005 {
1006 if (j < foundpos && VERBOSENOISE (tkts->handle))
1007 {
1008 shishi_verbose (tkts->handle, "New best etype %d",
1009 etype);
1010
1011 /* XXX mem leak. */
1012
1013 format = xasprintf ("?%d.salt", i);
1014 rc = shishi_asn1_read (tkts->handle, einfos, format,
1015 &lochint->preauthsalt,
1016 &lochint->preauthsaltlen);
1017 free (format);
1018 if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_ELEMENT)
1019 return rc;
1020
1021 if (isinfo2)
1022 {
1023 format = xasprintf ("?%d.s2kparams", i);
1024 rc = shishi_asn1_read (tkts->handle, einfos, format,
1025 &lochint->preauths2kparams,
1026 &lochint->preauths2kparamslen);
1027 free (format);
1028 if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_ELEMENT)
1029 return rc;
1030 }
1031 }
1032
1033 foundpos = MIN (foundpos, j);
1034 }
1035 }
1036 }
1037 }
1038
1039 if (foundpos != SIZE_MAX)
1040 {
1041 lochint->preauthetype = tkts->handle->clientkdcetypes[foundpos];
1042
1043 shishi_verbose (tkts->handle, "Best pre-auth etype was %d",
1044 lochint->preauthetype);
1045
1046 *retry = true;
1047 }
1048
1049 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
recover_preauth(Shishi_tkts * tkts,Shishi_as * as,Shishi_tkts_hint * lochint,bool * retry)1058 recover_preauth (Shishi_tkts * tkts,
1059 Shishi_as * as, Shishi_tkts_hint * lochint, bool * retry)
1060 {
1061 Shishi_asn1 krberror = shishi_as_krberror (as);
1062 Shishi_asn1 pas;
1063 size_t i, n;
1064 int rc;
1065
1066 *retry = false;
1067
1068 shishi_verbose (tkts->handle, "Server requests pre-auth data");
1069
1070 rc = shishi_krberror_methoddata (tkts->handle, krberror, &pas);
1071 if (rc != SHISHI_OK)
1072 return rc;
1073
1074 rc = shishi_asn1_number_of_elements (tkts->handle, pas, "", &n);
1075 if (rc == SHISHI_OK)
1076 {
1077 for (i = 1; i <= n; i++)
1078 {
1079 char *format = xasprintf ("?%d.padata-type", i);
1080 int32_t padatatype;
1081
1082 rc = shishi_asn1_read_int32 (tkts->handle, pas, format,
1083 &padatatype);
1084 free (format);
1085 if (rc == SHISHI_OK)
1086 {
1087 shishi_verbose (tkts->handle, "Looking at pa-type %d",
1088 padatatype);
1089
1090 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 format = xasprintf ("?%d.padata-value", i);
1103 rc = shishi_asn1_read (tkts->handle, pas, format,
1104 &der, &len);
1105 free (format);
1106 if (rc != SHISHI_OK)
1107 {
1108 shishi_error_printf (tkts->handle,
1109 "Can't extract PA-DATA value");
1110 continue;
1111 }
1112
1113 if (padatatype == SHISHI_PA_ETYPE_INFO)
1114 einfos = shishi_der2asn1_etype_info (tkts->handle,
1115 der, len);
1116 else
1117 einfos = shishi_der2asn1_etype_info2 (tkts->handle,
1118 der, len);
1119 free (der);
1120 if (!einfos)
1121 {
1122 shishi_error_printf (tkts->handle,
1123 "Can't DER decode PA-DATA");
1124 continue;
1125 }
1126
1127 rc = recover_preauth_info
1128 (tkts, as, lochint, einfos,
1129 padatatype == SHISHI_PA_ETYPE_INFO2, retry);
1130 if (rc != SHISHI_OK)
1131 {
1132 shishi_error_printf (tkts->handle,
1133 "Could not use pre-auth data: %s",
1134 shishi_strerror (rc));
1135 continue;
1136 }
1137
1138 shishi_asn1_done (tkts->handle, einfos);
1139 }
1140 break;
1141
1142 default:
1143 break;
1144 }
1145 }
1146 }
1147 }
1148
1149 shishi_asn1_done (tkts->handle, pas);
1150
1151 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 *
shishi_tkts_get_tgt(Shishi_tkts * tkts,Shishi_tkts_hint * hint)1173 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 memset (&lochint, 0, sizeof (lochint));
1183 asprintf (&lochint.server, "krbtgt/%s", hint->serverrealm ?
1184 hint->serverrealm : shishi_realm_default (tkts->handle));
1185 set_tgtflags_based_on_hint (hint, &lochint);
1186
1187 tgt = shishi_tkts_find (tkts, &lochint);
1188
1189 free (lochint.server);
1190 lochint.server = NULL;
1191
1192 if (tgt)
1193 return tgt;
1194
1195 if (hint->flags & SHISHI_TKTSHINTFLAGS_NON_INTERACTIVE)
1196 return NULL;
1197
1198 again:
1199 rc = shishi_as (tkts->handle, &as);
1200 if (rc == SHISHI_OK)
1201 rc = act_hint_on_kdcreq (tkts->handle, &lochint, shishi_as_req (as));
1202 if (rc == SHISHI_OK)
1203 rc = do_preauth (tkts, &lochint, as);
1204 if (rc == SHISHI_OK)
1205 rc = shishi_as_req_build (as);
1206 if (rc == SHISHI_OK)
1207 rc = shishi_as_sendrecv_hint (as, &lochint);
1208 if (rc == SHISHI_OK)
1209 rc = shishi_as_rep_process (as, NULL, lochint.passwd);
1210 if (rc == SHISHI_GOT_KRBERROR
1211 && shishi_krberror_errorcode_fast (tkts->handle,
1212 shishi_as_krberror (as))
1213 == SHISHI_KDC_ERR_PREAUTH_REQUIRED)
1214 {
1215 bool retry = false;
1216
1217 rc = recover_preauth (tkts, as, &lochint, &retry);
1218 if (rc != SHISHI_OK)
1219 return NULL;
1220
1221 if (retry)
1222 {
1223 shishi_as_done (as);
1224 goto again;
1225 }
1226
1227 shishi_error_printf (tkts->handle, "Unsupported pre-auth required");
1228 return NULL;
1229 }
1230 if (rc != SHISHI_OK)
1231 {
1232 shishi_error_printf (tkts->handle,
1233 "AS exchange failed: %s\n%s\n",
1234 shishi_strerror (rc), shishi_error (tkts->handle));
1235 return NULL;
1236 }
1237
1238 /* XXX free lochint members */
1239
1240 tgt = shishi_as_tkt (as);
1241 if (!tgt)
1242 {
1243 shishi_error_printf (tkts->handle, "No ticket in AS-REP");
1244 return NULL;
1245 }
1246
1247 if (VERBOSENOISE (tkts->handle))
1248 {
1249 printf ("Received ticket granting ticket:\n");
1250 shishi_tkt_pretty_print (tgt, stdout);
1251 }
1252
1253 rc = shishi_tkts_add (tkts, tgt);
1254 if (rc != SHISHI_OK)
1255 printf ("Could not add ticket: %s", shishi_strerror (rc));
1256
1257 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 *
shishi_tkts_get_tgs(Shishi_tkts * tkts,Shishi_tkts_hint * hint,Shishi_tkt * tgt)1276 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 rc = shishi_tgs (tkts->handle, &tgs);
1284 shishi_tgs_tgtkt_set (tgs, tgt);
1285 if (rc == SHISHI_OK)
1286 rc = act_hint_on_kdcreq (tkts->handle, hint, shishi_tgs_req (tgs));
1287 if (rc == SHISHI_OK)
1288 rc = shishi_tgs_set_server (tgs, hint->server);
1289 if (rc == SHISHI_OK)
1290 rc = shishi_tgs_req_build (tgs);
1291 if (rc == SHISHI_OK)
1292 rc = shishi_tgs_sendrecv_hint (tgs, hint);
1293 if (rc == SHISHI_OK)
1294 rc = shishi_tgs_rep_process (tgs);
1295 if (rc != SHISHI_OK)
1296 {
1297 shishi_error_printf (tkts->handle,
1298 "TGS exchange failed: %s\n%s\n",
1299 shishi_strerror (rc), shishi_error (tkts->handle));
1300 if (rc == SHISHI_GOT_KRBERROR)
1301 shishi_krberror_pretty_print (tkts->handle, stdout,
1302 shishi_tgs_krberror (tgs));
1303 return NULL;
1304 }
1305
1306 tkt = shishi_tgs_tkt (tgs);
1307 if (!tkt)
1308 {
1309 shishi_error_printf (tkts->handle, "No ticket in TGS-REP?!: %s",
1310 shishi_error (tkts->handle));
1311 return NULL;
1312 }
1313
1314 if (VERBOSENOISE (tkts->handle))
1315 {
1316 printf ("Received ticket:\n");
1317 shishi_tkt_pretty_print (tkt, stdout);
1318 }
1319
1320 rc = shishi_tkts_add (tkts, tkt);
1321 if (rc != SHISHI_OK)
1322 printf ("Could not add ticket: %s", shishi_strerror (rc));
1323
1324 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 be found.
1331 *
1332 * Get a ticket matching given characteristics. This function first
1333 * looks in the ticket set for a ticket, then tries to find a
1334 * suitable TGT, possibly via an AS exchange, using
1335 * shishi_tkts_get_tgt(), and then uses that TGT in a TGS exchange to
1336 * get the ticket.
1337 *
1338 * Currently this function does 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 *
shishi_tkts_get(Shishi_tkts * tkts,Shishi_tkts_hint * hint)1344 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 hint->startpos = 0;
1350 tkt = shishi_tkts_find (tkts, hint);
1351 if (tkt)
1352 return tkt;
1353
1354 tgt = shishi_tkts_get_tgt (tkts, hint);
1355 if (!tgt)
1356 {
1357 shishi_error_printf (tkts->handle, "Could not get TGT for ticket.");
1358 return NULL;
1359 }
1360
1361 if (shishi_tkt_match_p (tgt, hint))
1362 return tgt;
1363
1364 tkt = shishi_tkts_get_tgs (tkts, hint, tgt);
1365 if (!tkt)
1366 {
1367 shishi_error_printf (tkts->handle, "Could not get ticket using TGT.");
1368 return NULL;
1369 }
1370
1371 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 *
shishi_tkts_get_for_clientserver(Shishi_tkts * tkts,const char * client,const char * server)1386 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 memset (&hint, 0, sizeof (hint));
1393 hint.client = (char *) client;
1394 hint.server = (char *) server;
1395
1396 tkt = shishi_tkts_get (tkts, &hint);
1397
1398 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 to the given server and
1407 * for the default principal client. See shishi_tkts_get().
1408 *
1409 * Return value: Returns a ticket if found, or NULL.
1410 **/
1411 Shishi_tkt *
shishi_tkts_get_for_server(Shishi_tkts * tkts,const char * server)1412 shishi_tkts_get_for_server (Shishi_tkts * tkts, const char *server)
1413 {
1414 return shishi_tkts_get_for_clientserver
1415 (tkts, shishi_principal_default (tkts->handle), server);
1416 }
1417
1418 /**
1419 * shishi_tkts_get_for_localservicepasswd:
1420 * @tkts: ticket set handle as allocated by shishi_tkts().
1421 * @service: service name to get ticket for.
1422 * @passwd: password for the default client principal.
1423 *
1424 * Short-hand function for getting a ticket to the given
1425 * local service, and for the default principal client.
1426 * The latter's password is given as argument.
1427 * See shishi_tkts_get().
1428 *
1429 * Return value: Returns a ticket if found, or NULL otherwise.
1430 **/
1431 Shishi_tkt *
shishi_tkts_get_for_localservicepasswd(Shishi_tkts * tkts,const char * service,const char * passwd)1432 shishi_tkts_get_for_localservicepasswd (Shishi_tkts * tkts,
1433 const char *service,
1434 const char *passwd)
1435 {
1436 Shishi_tkt *tkt;
1437 Shishi_tkts_hint hint;
1438
1439 memset (&hint, 0, sizeof (hint));
1440 hint.client = (char *) shishi_principal_default (tkts->handle);
1441 hint.server = shishi_server_for_local_service (tkts->handle, service);
1442 hint.passwd = (char *) passwd;
1443
1444 tkt = shishi_tkts_get (tkts, &hint);
1445
1446 free (hint.server);
1447
1448 return tkt;
1449 }
1450