Use GPL instead of LGPL.
[shishi.git] / lib / ticket.c
blobc1d57fc0f7e489ff463746ad86ac24dac9651108
1 /* ticket.c ticket handling
2 * Copyright (C) 2002 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "internal.h"
24 struct Shishi_ticket
26 Shishi *handle;
27 char *principal;
28 ASN1_TYPE ticket;
29 ASN1_TYPE enckdcreppart;
30 Shishi_key *key;
33 int
34 shishi_ticket_realm_get (Shishi * handle,
35 ASN1_TYPE ticket, char *realm, int *realmlen)
37 return _shishi_asn1_field (handle, ticket, realm, realmlen, "Ticket.realm");
40 int
41 shishi_ticket_sname_get (Shishi * handle,
42 ASN1_TYPE ticket, char *server, int *serverlen)
44 return shishi_principal_name_get (handle, ticket, "Ticket.sname",
45 server, serverlen);
48 int
49 shishi_ticket_snamerealm_get (Shishi * handle,
50 ASN1_TYPE ticket,
51 char *serverrealm, int *serverrealmlen)
53 return shishi_principal_name_realm_get (handle, ticket, "Ticket.sname",
54 ticket, "Ticket.realm",
55 serverrealm, serverrealmlen);
58 /**
59 * shishi_asn1ticket_get_enc_part_etype:
60 * @handle: shishi handle as allocated by shishi_init().
61 * @kdcrep: Ticket variable to get value from.
62 * @etype: output variable that holds the value.
64 * Extract Ticket.enc-part.etype.
66 * Return value: Returns SHISHI_OK iff successful.
67 **/
68 int
69 shishi_asn1ticket_get_enc_part_etype (Shishi * handle,
70 ASN1_TYPE ticket, int *etype)
72 int buflen;
73 int res;
75 *etype = 0;
76 buflen = sizeof (*etype);
77 res = _shishi_asn1_field (handle, ticket,
78 (char *) etype, &buflen, "Ticket.enc-part.etype");
80 return res;
83 /**
84 * shishi_ticket_principal:
85 * @handle: shishi handle as allocated by shishi_init().
86 * @ticket: input variable with ticket info.
88 * Return value: Returns client principal of ticket.
89 **/
90 char *
91 shishi_ticket_principal (Shishi_ticket * ticket)
93 return ticket->principal ? ticket->principal : "<none>";
96 /**
97 * shishi_ticket_ticket:
98 * @handle: shishi handle as allocated by shishi_init().
99 * @ticket: input variable with ticket info.
101 * Return value: Returns actual ticket.
103 ASN1_TYPE
104 shishi_ticket_ticket (Shishi_ticket * ticket)
106 return ticket->ticket;
110 * shishi_ticket_enckdcreppart:
111 * @handle: shishi handle as allocated by shishi_init().
112 * @ticket: input variable with ticket info.
114 * Return value: Returns auxilliary ticket information.
116 ASN1_TYPE
117 shishi_ticket_enckdcreppart (Shishi_ticket * ticket)
119 return ticket->enckdcreppart;
123 * shishi_ticket_key:
124 * @ticket: input variable with ticket info.
126 * Return value: Returns key extracted from enckdcreppart.
128 Shishi_key *
129 shishi_ticket_key (Shishi_ticket * ticket)
131 if (!ticket->key)
133 int res;
135 res = shishi_enckdcreppart_get_key (ticket->handle,
136 shishi_ticket_enckdcreppart (ticket),
137 &ticket->key);
138 if (res != SHISHI_OK)
139 return NULL;
142 return ticket->key;
146 * shishi_ticket:
147 * @handle: shishi handle as allocated by shishi_init().
148 * @principal: input variable with client principal of ticket.
149 * @ticket: input variable with ticket.
150 * @enckdcreppart: input variable with auxilliary ticket information.
152 * Create a new ticket handle.
154 * Return value: Returns new ticket handle, or %NULL on error.
156 Shishi_ticket *
157 shishi_ticket (Shishi * handle, char *principal,
158 ASN1_TYPE ticket, ASN1_TYPE enckdcreppart)
160 Shishi_ticket *tkt;
162 tkt = malloc (sizeof (*tkt));
163 if (tkt == NULL)
164 return NULL;
166 memset(tkt, 0, sizeof(*tkt));
168 tkt->handle = handle;
169 tkt->principal = principal;
170 tkt->ticket = ticket;
171 tkt->enckdcreppart = enckdcreppart;
173 return tkt;
177 shishi_ticket_flags (Shishi_ticket * ticket, int *flags)
179 int len = sizeof (*flags);
180 int res;
181 *flags = 0;
182 res = _shishi_asn1_field (ticket->handle, ticket->enckdcreppart,
183 (char *) flags, &len, "EncKDCRepPart.flags");
184 return res;
188 shishi_ticket_forwardable_p (Shishi_ticket * ticket)
190 int flags = 0;
192 shishi_ticket_flags (ticket, &flags);
194 return flags & SHISHI_TICKETFLAGS_FORWARDABLE;
198 shishi_ticket_forwarded_p (Shishi_ticket * ticket)
200 int flags = 0;
202 shishi_ticket_flags (ticket, &flags);
204 return flags & SHISHI_TICKETFLAGS_FORWARDED;
208 shishi_ticket_proxiable_p (Shishi_ticket * ticket)
210 int flags = 0;
212 shishi_ticket_flags (ticket, &flags);
214 return flags & SHISHI_TICKETFLAGS_PROXIABLE;
218 shishi_ticket_proxy_p (Shishi_ticket * ticket)
220 int flags = 0;
222 shishi_ticket_flags (ticket, &flags);
224 return flags & SHISHI_TICKETFLAGS_PROXY;
228 shishi_ticket_may_postdate_p (Shishi_ticket * ticket)
230 int flags = 0;
232 shishi_ticket_flags (ticket, &flags);
234 return flags & SHISHI_TICKETFLAGS_MAY_POSTDATE;
238 shishi_ticket_postdated_p (Shishi_ticket * ticket)
240 int flags = 0;
242 shishi_ticket_flags (ticket, &flags);
244 return flags & SHISHI_TICKETFLAGS_POSTDATED;
248 shishi_ticket_invalid_p (Shishi_ticket * ticket)
250 int flags = 0;
252 shishi_ticket_flags (ticket, &flags);
254 return flags & SHISHI_TICKETFLAGS_INVALID;
258 shishi_ticket_renewable_p (Shishi_ticket * ticket)
260 int flags = 0;
262 shishi_ticket_flags (ticket, &flags);
264 return flags & SHISHI_TICKETFLAGS_RENEWABLE;
268 shishi_ticket_initial_p (Shishi_ticket * ticket)
270 int flags = 0;
272 shishi_ticket_flags (ticket, &flags);
274 return flags & SHISHI_TICKETFLAGS_INITIAL;
278 shishi_ticket_pre_authent_p (Shishi_ticket * ticket)
280 int flags = 0;
282 shishi_ticket_flags (ticket, &flags);
284 return flags & SHISHI_TICKETFLAGS_PRE_AUTHENT;
288 shishi_ticket_hw_authent_p (Shishi_ticket * ticket)
290 int flags = 0;
292 shishi_ticket_flags (ticket, &flags);
294 return flags & SHISHI_TICKETFLAGS_HW_AUTHENT;
298 shishi_ticket_transited_policy_checked_p (Shishi_ticket * ticket)
300 int flags = 0;
302 shishi_ticket_flags (ticket, &flags);
304 return flags & SHISHI_TICKETFLAGS_TRANSITED_POLICY_CHECKED;
308 shishi_ticket_ok_as_delegate_p (Shishi_ticket * ticket)
310 int flags = 0;
312 shishi_ticket_flags (ticket, &flags);
314 return flags & SHISHI_TICKETFLAGS_OK_AS_DELEGATE;
318 shishi_ticket_realm (Shishi_ticket * ticket, const char *realm, int *realmlen)
320 return shishi_ticket_realm_get (ticket->handle, ticket->ticket,
321 realm, realmlen);
325 shishi_ticket_server (Shishi_ticket * ticket,
326 const char *service, int *servicelen)
328 return shishi_ticket_sname_get (ticket->handle, ticket->ticket,
329 service, servicelen);
333 shishi_ticket_server_p (Shishi_ticket * ticket, const char *service)
335 char *buf;
336 int buflen;
337 int res;
339 buflen = strlen (service) + 1;
340 buf = malloc (buflen);
341 if (buf == NULL)
342 return 0;
344 res = shishi_ticket_server (ticket, buf, &buflen);
345 if (res != SHISHI_OK)
347 free (buf);
348 return 0;
350 buf[buflen] = '\0';
352 if (strcmp (service, buf) != 0)
354 free (buf);
355 return 0;
358 free (buf);
360 return 1;
364 shishi_ticket_server_realm (Shishi_ticket * ticket,
365 char *servicerealm, int *servicerealmlen)
367 return shishi_ticket_snamerealm_get (ticket->handle, ticket->ticket,
368 servicerealm, servicerealmlen);
372 shishi_ticket_keytype (Shishi_ticket * ticket, int *etype)
374 return _shishi_asn1_integer_field (ticket->handle,
375 ticket->enckdcreppart, etype,
376 "EncKDCRepPart.key.keytype");
380 shishi_ticket_authtime (Shishi_ticket * ticket,
381 char *authtime, int *authtimelen)
383 return _shishi_asn1_field (ticket->handle, ticket->enckdcreppart,
384 authtime, authtimelen, "EncKDCRepPart.authtime");
387 time_t
388 shishi_ticket_authctime (Shishi_ticket * ticket)
390 char authtime[GENERALIZEDTIME_TIME_LEN + 1];
391 int authtimelen;
392 time_t t;
393 int res;
395 authtimelen = sizeof (authtime);
396 res = shishi_ticket_authtime (ticket, authtime, &authtimelen);
397 if (res != SHISHI_OK)
398 return (time_t) - 1;
400 authtime[GENERALIZEDTIME_TIME_LEN] = '\0';
402 t = shishi_generalize_ctime (ticket->handle, authtime);
404 return t;
408 shishi_ticket_starttime (Shishi_ticket * ticket,
409 char *starttime, int *starttimelen)
411 return _shishi_asn1_optional_field (ticket->handle, ticket->enckdcreppart,
412 starttime, starttimelen,
413 "EncKDCRepPart.starttime");
416 time_t
417 shishi_ticket_startctime (Shishi_ticket * ticket)
419 char starttime[GENERALIZEDTIME_TIME_LEN + 1];
420 int starttimelen;
421 time_t t;
422 int res;
424 starttimelen = sizeof (starttime);
425 res = shishi_ticket_starttime (ticket, starttime, &starttimelen);
426 if (res != SHISHI_OK || starttimelen == 0)
427 return (time_t) - 1;
429 starttime[GENERALIZEDTIME_TIME_LEN] = '\0';
431 t = shishi_generalize_ctime (ticket->handle, starttime);
433 return t;
437 shishi_ticket_endtime (Shishi_ticket * ticket, char *endtime, int *endtimelen)
439 return _shishi_asn1_field (ticket->handle, ticket->enckdcreppart,
440 endtime, endtimelen, "EncKDCRepPart.endtime");
443 time_t
444 shishi_ticket_endctime (Shishi_ticket * ticket)
446 char endtime[GENERALIZEDTIME_TIME_LEN + 1];
447 int endtimelen;
448 time_t t;
449 int res;
451 endtimelen = sizeof (endtime);
452 res = shishi_ticket_endtime (ticket, endtime, &endtimelen);
453 if (res != SHISHI_OK)
454 return (time_t) - 1;
456 endtime[GENERALIZEDTIME_TIME_LEN] = '\0';
458 t = shishi_generalize_ctime (ticket->handle, endtime);
460 return t;
464 shishi_ticket_renew_till (Shishi_ticket * ticket,
465 char *renewtill, int *renewtilllen)
467 return _shishi_asn1_optional_field (ticket->handle, ticket->enckdcreppart,
468 renewtill, renewtilllen,
469 "EncKDCRepPart.renew-till");
472 time_t
473 shishi_ticket_renew_tillc (Shishi_ticket * ticket)
475 char renewtill[GENERALIZEDTIME_TIME_LEN + 1];
476 int renewtilllen;
477 time_t t;
478 int res;
480 renewtilllen = sizeof (renewtill);
481 res = shishi_ticket_renew_till (ticket, renewtill, &renewtilllen);
482 if (res != SHISHI_OK || renewtilllen == 0)
483 return (time_t) - 1;
485 renewtill[GENERALIZEDTIME_TIME_LEN] = '\0';
487 t = shishi_generalize_ctime (ticket->handle, renewtill);
489 return t;
493 shishi_ticket_valid_at_time_p (Shishi_ticket * ticket, time_t now)
495 time_t starttime, endtime;
497 starttime = shishi_ticket_startctime (ticket);
498 if (starttime == (time_t) - 1)
499 starttime = shishi_ticket_authctime (ticket);
500 endtime = shishi_ticket_endctime (ticket);
502 return starttime <= now && now <= endtime;
506 shishi_ticket_valid_now_p (Shishi_ticket * ticket)
508 return shishi_ticket_valid_at_time_p (ticket, time (NULL));
512 shishi_ticket_print (Shishi_ticket * ticket, FILE * fh)
514 char buf[BUFSIZ];
515 char *p;
516 int buflen;
517 int etype, flags;
518 int res;
519 time_t t;
521 printf ("%s:\n", shishi_ticket_principal (ticket));
523 t = shishi_ticket_authctime (ticket);
524 printf (_("Authtime:\t%s"), ctime (&t));
526 t = shishi_ticket_startctime (ticket);
527 if (t != (time_t) - 1)
528 printf (_("Starttime:\t%s"), ctime (&t));
530 t = shishi_ticket_endctime (ticket);
531 p = ctime (&t);
532 p[strlen (p) - 1] = '\0';
533 printf (_("Endtime:\t%s\t%s\n"), p,
534 shishi_ticket_valid_now_p (ticket) ? "valid" : "EXPIRED");
536 t = shishi_ticket_renew_tillc (ticket);
537 if (t != (time_t) - 1)
538 printf (_("Renewable until:\t%s"), ctime (&t));
540 buflen = sizeof (buf);
541 buf[0] = '\0';
542 res = shishi_ticket_server (ticket, buf, &buflen);
543 if (res != SHISHI_OK)
544 return res;
545 buf[buflen] = '\0';
546 printf (_("Service:\t%s\n"), buf);
548 res = shishi_ticket_keytype (ticket, &etype);
549 if (res != SHISHI_OK)
550 return res;
551 printf (_("Key type:\t%s (%d)\n"), shishi_cipher_name (etype), etype);
553 res = shishi_ticket_flags (ticket, &flags);
554 if (res != SHISHI_OK)
555 return res;
556 printf (_
557 ("Flags:\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n"),
558 flags, shishi_ticket_forwardable_p (ticket) ? "FORWARDABLE" :
559 "", shishi_ticket_forwarded_p (ticket) ? "FORWARDED" : "",
560 shishi_ticket_proxiable_p (ticket) ? "PROXIABLE" : "",
561 shishi_ticket_proxy_p (ticket) ? "PROXY" : "",
562 shishi_ticket_may_postdate_p (ticket) ? "MAYPOSTDATE" : "",
563 shishi_ticket_postdated_p (ticket) ? "POSTDATED" : "",
564 shishi_ticket_invalid_p (ticket) ? "INVALID" : "",
565 shishi_ticket_renewable_p (ticket) ? "RENEWABLE" : "",
566 shishi_ticket_initial_p (ticket) ? "INITIAL" : "",
567 shishi_ticket_pre_authent_p (ticket) ? "PREAUTHENT" : "",
568 shishi_ticket_hw_authent_p (ticket) ? "HWAUTHENT" : "",
569 shishi_ticket_transited_policy_checked_p (ticket) ?
570 "TRANSITEDPOLICYCHECKED" : "",
571 shishi_ticket_ok_as_delegate_p (ticket) ? "OKASDELEGATE" : "");
575 return SHISHI_OK;
579 shishi_ticket_decrypt (Shishi * handle,
580 ASN1_TYPE ticket,
581 Shishi_key *key,
582 ASN1_TYPE * encticketpart)
584 int res;
585 int i, len;
586 int buflen = BUFSIZ;
587 unsigned char buf[BUFSIZ];
588 unsigned char cipher[BUFSIZ];
589 int realmlen = BUFSIZ;
590 int cipherlen;
591 int etype;
593 res = shishi_asn1ticket_get_enc_part_etype (handle, ticket, &etype);
594 if (res != SHISHI_OK)
595 return res;
597 if (etype != shishi_key_type(key))
598 return SHISHI_KDCREP_BAD_KEYTYPE;
600 cipherlen = BUFSIZ;
601 res = _shishi_asn1_field (handle, ticket, cipher, &cipherlen,
602 "Ticket.enc-part.cipher");
603 if (res != SHISHI_OK)
604 return res;
606 res = shishi_decrypt (handle, key, SHISHI_KEYUSAGE_KDCREP_TICKET,
607 cipher, cipherlen, buf, &buflen);
609 if (res != SHISHI_OK)
611 if (VERBOSE (handle))
612 printf ("des_decrypt failed: %s\n", shishi_strerror_details (handle));
613 shishi_error_printf (handle,
614 "des_decrypt fail, most likely wrong password\n");
615 return res;
618 /* The crypto is so 1980; no length indicator. Trim off pad bytes
619 until we can parse it. */
620 for (i = 0; i < 8; i++)
622 if (VERBOSEASN1 (handle))
623 printf ("Trying with %d pad in enckdcrep...\n", i);
625 *encticketpart = shishi_d2a_encticketpart (handle, &buf[0], buflen - i);
626 if (*encticketpart != ASN1_TYPE_EMPTY)
627 break;
630 if (*encticketpart == ASN1_TYPE_EMPTY)
632 shishi_error_printf (handle, "Could not DER decode EncTicketPart. "
633 "Password probably correct (decrypt ok) though\n");
634 return SHISHI_ASN1_ERROR;
637 return SHISHI_OK;