Add.
[shishi.git] / lib / ticket.c
blob59efbd956841f8d2ce57985fc25a862d5e7311bf
1 /* ticket.c --- Low-level ASN.1 Ticket handling.
2 * Copyright (C) 2002, 2003, 2004, 2006 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "internal.h"
24 #define SHISHI_TICKET_DEFAULT_TKTVNO "5"
25 #define SHISHI_TICKET_DEFAULT_TKTVNO_LEN 0
27 /**
28 * shishi_ticket:
29 * @handle: shishi handle as allocated by shishi_init().
31 * This function creates a new ASN.1 Ticket, populated with some
32 * default values.
34 * Return value: Returns the ticket or NULL on failure.
35 **/
36 Shishi_asn1
37 shishi_ticket (Shishi * handle)
39 Shishi_asn1 node = NULL;
40 int rc;
42 node = shishi_asn1_ticket (handle);
43 if (!node)
44 return NULL;
46 rc = shishi_asn1_write (handle, node, "tkt-vno",
47 SHISHI_TICKET_DEFAULT_TKTVNO,
48 SHISHI_TICKET_DEFAULT_TKTVNO_LEN);
49 if (rc != SHISHI_OK)
50 goto error;
52 return node;
54 error:
55 shishi_asn1_done (handle, node);
56 return NULL;
59 /**
60 * shishi_ticket_realm_get:
61 * @handle: shishi handle as allocated by shishi_init().
62 * @ticket: input variable with ticket info.
63 * @realm: output array with newly allocated name of realm in ticket.
64 * @realmlen: size of output array.
66 * Extract realm from ticket.
68 * Return value: Returns SHISHI_OK iff successful.
69 **/
70 int
71 shishi_ticket_realm_get (Shishi * handle,
72 Shishi_asn1 ticket, char **realm, size_t * realmlen)
74 return shishi_asn1_read (handle, ticket, "realm", realm, realmlen);
77 /**
78 * shishi_ticket_realm_set:
79 * @handle: shishi handle as allocated by shishi_init().
80 * @ticket: input variable with ticket info.
81 * @realm: input array with name of realm.
83 * Set the realm field in the Ticket.
85 * Return value: Returns SHISHI_OK iff successful.
86 **/
87 int
88 shishi_ticket_realm_set (Shishi * handle, Shishi_asn1 ticket,
89 const char *realm)
91 int res;
93 res = shishi_asn1_write (handle, ticket, "realm", realm, 0);
94 if (res != SHISHI_OK)
95 return res;
97 return SHISHI_OK;
101 * shishi_ticket_server:
102 * @handle: Shishi library handle create by shishi_init().
103 * @ticket: ASN.1 Ticket variable to get server name from.
104 * @server: pointer to newly allocated zero terminated string containing
105 * principal name. May be %NULL (to only populate @serverlen).
106 * @serverlen: pointer to length of @server on output, excluding terminating
107 * zero. May be %NULL (to only populate @server).
109 * Represent server principal name in Ticket as zero-terminated
110 * string. The string is allocate by this function, and it is the
111 * responsibility of the caller to deallocate it. Note that the
112 * output length @serverlen does not include the terminating zero.
114 * Return value: Returns SHISHI_OK iff successful.
117 shishi_ticket_server (Shishi * handle, Shishi_asn1 ticket,
118 char **server, size_t * serverlen)
120 return shishi_principal_name (handle, ticket, "sname", server, serverlen);
124 * shishi_ticket_sname_set:
125 * @handle: shishi handle as allocated by shishi_init().
126 * @ticket: Ticket variable to set server name field in.
127 * @name_type: type of principial, see Shishi_name_type, usually
128 * SHISHI_NT_UNKNOWN.
129 * @sname: input array with principal name.
131 * Set the server name field in the Ticket.
133 * Return value: Returns SHISHI_OK iff successful.
136 shishi_ticket_sname_set (Shishi * handle,
137 Shishi_asn1 ticket,
138 Shishi_name_type name_type, char *sname[])
140 int res = SHISHI_OK;
141 char *buf;
142 int i;
144 asprintf (&buf, "%d", name_type);
145 res = shishi_asn1_write (handle, ticket, "sname.name-type", buf, 0);
146 free (buf);
147 if (res != SHISHI_OK)
148 return res;
150 res = shishi_asn1_write (handle, ticket, "sname.name-string", NULL, 0);
151 if (res != SHISHI_OK)
152 return res;
154 i = 1;
155 while (sname[i - 1])
157 res = shishi_asn1_write (handle, ticket, "sname.name-string", "NEW", 1);
158 if (res != SHISHI_OK)
159 return res;
161 asprintf (&buf, "sname.name-string.?%d", i);
162 res = shishi_asn1_write (handle, ticket, buf, sname[i - 1], 0);
163 free (buf);
164 if (res != SHISHI_OK)
165 return res;
167 i++;
170 return SHISHI_OK;
174 shishi_ticket_set_server (Shishi * handle,
175 Shishi_asn1 ticket, const char *server)
177 char *tmpserver;
178 char **serverbuf;
179 char *tokptr;
180 int res;
181 int i;
183 tmpserver = xstrdup (server);
184 serverbuf = xmalloc (sizeof (*serverbuf));
186 for (i = 0;
187 (serverbuf[i] = strtok_r (i == 0 ? tmpserver : NULL, "/", &tokptr));
188 i++)
190 serverbuf = xrealloc (serverbuf, (i + 2) * sizeof (*serverbuf));
192 res = shishi_ticket_sname_set (handle, ticket,
193 SHISHI_NT_PRINCIPAL, serverbuf);
194 if (res != SHISHI_OK)
196 fprintf (stderr, _("Could not set sname: %s\n"), shishi_error (handle));
197 return res;
199 free (serverbuf);
200 free (tmpserver);
202 return SHISHI_OK;
206 shishi_ticket_srealmserver_set (Shishi * handle,
207 Shishi_asn1 ticket,
208 const char *realm, const char *server)
210 int res;
212 res = shishi_ticket_realm_set (handle, ticket, realm);
213 if (res != SHISHI_OK)
214 return res;
216 res = shishi_ticket_set_server (handle, ticket, server);
217 if (res != SHISHI_OK)
218 return res;
220 return SHISHI_OK;
224 * shishi_ticket_get_enc_part_etype:
225 * @handle: shishi handle as allocated by shishi_init().
226 * @ticket: Ticket variable to get value from.
227 * @etype: output variable that holds the value.
229 * Extract Ticket.enc-part.etype.
231 * Return value: Returns SHISHI_OK iff successful.
234 shishi_ticket_get_enc_part_etype (Shishi * handle,
235 Shishi_asn1 ticket, int32_t * etype)
237 int res;
239 res = shishi_asn1_read_int32 (handle, ticket, "enc-part.etype", etype);
241 return res;
245 shishi_ticket_decrypt (Shishi * handle,
246 Shishi_asn1 ticket,
247 Shishi_key * key, Shishi_asn1 * encticketpart)
249 int res;
250 int i;
251 char *buf;
252 size_t buflen;
253 char *cipher;
254 size_t cipherlen;
255 int etype;
257 res = shishi_ticket_get_enc_part_etype (handle, ticket, &etype);
258 if (res != SHISHI_OK)
259 return res;
261 if (etype != shishi_key_type (key))
262 return SHISHI_TICKET_BAD_KEYTYPE;
264 res = shishi_asn1_read (handle, ticket, "enc-part.cipher",
265 &cipher, &cipherlen);
266 if (res != SHISHI_OK)
267 return res;
269 res = shishi_decrypt (handle, key, SHISHI_KEYUSAGE_ENCTICKETPART,
270 cipher, cipherlen, &buf, &buflen);
271 free (cipher);
272 if (res != SHISHI_OK)
274 shishi_error_printf (handle,
275 "Ticket decrypt failed, wrong password?\n");
276 return SHISHI_TICKET_DECRYPT_FAILED;
279 /* The crypto is so 1980; no length indicator. Trim off pad bytes
280 until we can parse it. */
281 for (i = 0; i < 8; i++)
283 if (VERBOSEASN1 (handle))
284 printf ("Trying with %d pad in enckdcrep...\n", i);
286 *encticketpart = shishi_der2asn1_encticketpart (handle, &buf[0],
287 buflen - i);
288 if (*encticketpart != NULL)
289 break;
292 if (*encticketpart == NULL)
294 shishi_error_printf (handle, "Could not DER decode EncTicketPart. "
295 "Password probably correct (decrypt ok) though\n");
296 return SHISHI_ASN1_ERROR;
299 return SHISHI_OK;
303 * shishi_ticket_set_enc_part:
304 * @handle: shishi handle as allocated by shishi_init().
305 * @ticket: Ticket to add enc-part field to.
306 * @etype: encryption type used to encrypt enc-part.
307 * @kvno: key version number.
308 * @buf: input array with encrypted enc-part.
309 * @buflen: size of input array with encrypted enc-part.
311 * Set the encrypted enc-part field in the Ticket. The encrypted data
312 * is usually created by calling shishi_encrypt() on the DER encoded
313 * enc-part. To save time, you may want to use
314 * shishi_ticket_add_enc_part() instead, which calculates the
315 * encrypted data and calls this function in one step.
317 * Return value: Returns SHISHI_OK iff successful.
320 shishi_ticket_set_enc_part (Shishi * handle,
321 Shishi_asn1 ticket,
322 int32_t etype, uint32_t kvno,
323 const char *buf, size_t buflen)
325 int res = SHISHI_OK;
327 res = shishi_asn1_write (handle, ticket, "enc-part.cipher", buf, buflen);
328 if (res != SHISHI_OK)
329 return res;
331 res = shishi_asn1_write_int32 (handle, ticket, "enc-part.etype", etype);
332 if (res != SHISHI_OK)
333 return res;
335 if (kvno == UINT32_MAX)
336 res = shishi_asn1_write (handle, ticket, "enc-part.kvno", NULL, 0);
337 else
338 res = shishi_asn1_write_uint32 (handle, ticket, "enc-part.kvno", kvno);
339 if (res != SHISHI_OK)
340 return res;
342 return SHISHI_OK;
346 * shishi_ticket_add_enc_part:
347 * @handle: shishi handle as allocated by shishi_init().
348 * @ticket: Ticket to add enc-part field to.
349 * @key: key used to encrypt enc-part.
350 * @encticketpart: EncTicketPart to add.
352 * Encrypts DER encoded EncTicketPart using key and stores it in the
353 * Ticket.
355 * Return value: Returns SHISHI_OK iff successful.
358 shishi_ticket_add_enc_part (Shishi * handle,
359 Shishi_asn1 ticket,
360 Shishi_key * key, Shishi_asn1 encticketpart)
362 int res = SHISHI_OK;
363 char *buf;
364 size_t buflen;
365 char *der;
366 size_t derlen;
368 res = shishi_asn1_to_der (handle, encticketpart, &der, &derlen);
369 if (res != SHISHI_OK)
371 shishi_error_printf (handle, "Could not DER encode encticketpart: %s\n",
372 shishi_strerror (res));
373 return res;
376 res = shishi_encrypt (handle, key, SHISHI_KEYUSAGE_ENCTICKETPART,
377 der, derlen, &buf, &buflen);
379 free (der);
381 if (res != SHISHI_OK)
383 shishi_error_printf (handle,
384 "Cannot encrypt encrypted part of ticket\n");
385 return res;
388 res = shishi_ticket_set_enc_part (handle, ticket, shishi_key_type (key),
389 shishi_key_version (key), buf, buflen);
391 free (buf);
393 return res;