Add.
[shishi.git] / lib / ticket.c
blob0c16373222f8411facb0e508c8d774b334400626
1 /* ticket.c --- Low-level ASN.1 Ticket handling.
2 * Copyright (C) 2002, 2003, 2004, 2006, 2007 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, see http://www.gnu.org/licenses or write
18 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19 * Floor, Boston, MA 02110-1301, USA
23 #include "internal.h"
25 #define SHISHI_TICKET_DEFAULT_TKTVNO "5"
26 #define SHISHI_TICKET_DEFAULT_TKTVNO_LEN 0
28 /**
29 * shishi_ticket:
30 * @handle: shishi handle as allocated by shishi_init().
32 * This function creates a new ASN.1 Ticket, populated with some
33 * default values.
35 * Return value: Returns the ticket or NULL on failure.
36 **/
37 Shishi_asn1
38 shishi_ticket (Shishi * handle)
40 Shishi_asn1 node = NULL;
41 int rc;
43 node = shishi_asn1_ticket (handle);
44 if (!node)
45 return NULL;
47 rc = shishi_asn1_write (handle, node, "tkt-vno",
48 SHISHI_TICKET_DEFAULT_TKTVNO,
49 SHISHI_TICKET_DEFAULT_TKTVNO_LEN);
50 if (rc != SHISHI_OK)
51 goto error;
53 return node;
55 error:
56 shishi_asn1_done (handle, node);
57 return NULL;
60 /**
61 * shishi_ticket_realm_get:
62 * @handle: shishi handle as allocated by shishi_init().
63 * @ticket: input variable with ticket info.
64 * @realm: output array with newly allocated name of realm in ticket.
65 * @realmlen: size of output array.
67 * Extract realm from ticket.
69 * Return value: Returns SHISHI_OK iff successful.
70 **/
71 int
72 shishi_ticket_realm_get (Shishi * handle,
73 Shishi_asn1 ticket, char **realm, size_t * realmlen)
75 return shishi_asn1_read (handle, ticket, "realm", realm, realmlen);
78 /**
79 * shishi_ticket_realm_set:
80 * @handle: shishi handle as allocated by shishi_init().
81 * @ticket: input variable with ticket info.
82 * @realm: input array with name of realm.
84 * Set the realm field in the Ticket.
86 * Return value: Returns SHISHI_OK iff successful.
87 **/
88 int
89 shishi_ticket_realm_set (Shishi * handle, Shishi_asn1 ticket,
90 const char *realm)
92 int res;
94 res = shishi_asn1_write (handle, ticket, "realm", realm, 0);
95 if (res != SHISHI_OK)
96 return res;
98 return SHISHI_OK;
102 * shishi_ticket_server:
103 * @handle: Shishi library handle create by shishi_init().
104 * @ticket: ASN.1 Ticket variable to get server name from.
105 * @server: pointer to newly allocated zero terminated string containing
106 * principal name. May be %NULL (to only populate @serverlen).
107 * @serverlen: pointer to length of @server on output, excluding terminating
108 * zero. May be %NULL (to only populate @server).
110 * Represent server principal name in Ticket as zero-terminated
111 * string. The string is allocate by this function, and it is the
112 * responsibility of the caller to deallocate it. Note that the
113 * output length @serverlen does not include the terminating zero.
115 * Return value: Returns SHISHI_OK iff successful.
118 shishi_ticket_server (Shishi * handle, Shishi_asn1 ticket,
119 char **server, size_t * serverlen)
121 return shishi_principal_name (handle, ticket, "sname", server, serverlen);
125 * shishi_ticket_sname_set:
126 * @handle: shishi handle as allocated by shishi_init().
127 * @ticket: Ticket variable to set server name field in.
128 * @name_type: type of principial, see Shishi_name_type, usually
129 * SHISHI_NT_UNKNOWN.
130 * @sname: input array with principal name.
132 * Set the server name field in the Ticket.
134 * Return value: Returns SHISHI_OK iff successful.
137 shishi_ticket_sname_set (Shishi * handle,
138 Shishi_asn1 ticket,
139 Shishi_name_type name_type, char *sname[])
141 int res = SHISHI_OK;
142 char *buf;
143 int i;
145 asprintf (&buf, "%d", name_type);
146 res = shishi_asn1_write (handle, ticket, "sname.name-type", buf, 0);
147 free (buf);
148 if (res != SHISHI_OK)
149 return res;
151 res = shishi_asn1_write (handle, ticket, "sname.name-string", NULL, 0);
152 if (res != SHISHI_OK)
153 return res;
155 i = 1;
156 while (sname[i - 1])
158 res = shishi_asn1_write (handle, ticket, "sname.name-string", "NEW", 1);
159 if (res != SHISHI_OK)
160 return res;
162 asprintf (&buf, "sname.name-string.?%d", i);
163 res = shishi_asn1_write (handle, ticket, buf, sname[i - 1], 0);
164 free (buf);
165 if (res != SHISHI_OK)
166 return res;
168 i++;
171 return SHISHI_OK;
175 shishi_ticket_set_server (Shishi * handle,
176 Shishi_asn1 ticket, const char *server)
178 char *tmpserver;
179 char **serverbuf;
180 char *tokptr;
181 int res;
182 int i;
184 tmpserver = xstrdup (server);
185 serverbuf = xmalloc (sizeof (*serverbuf));
187 for (i = 0;
188 (serverbuf[i] = strtok_r (i == 0 ? tmpserver : NULL, "/", &tokptr));
189 i++)
191 serverbuf = xrealloc (serverbuf, (i + 2) * sizeof (*serverbuf));
193 res = shishi_ticket_sname_set (handle, ticket,
194 SHISHI_NT_PRINCIPAL, serverbuf);
195 if (res != SHISHI_OK)
197 fprintf (stderr, _("Could not set sname: %s\n"), shishi_error (handle));
198 return res;
200 free (serverbuf);
201 free (tmpserver);
203 return SHISHI_OK;
207 shishi_ticket_srealmserver_set (Shishi * handle,
208 Shishi_asn1 ticket,
209 const char *realm, const char *server)
211 int res;
213 res = shishi_ticket_realm_set (handle, ticket, realm);
214 if (res != SHISHI_OK)
215 return res;
217 res = shishi_ticket_set_server (handle, ticket, server);
218 if (res != SHISHI_OK)
219 return res;
221 return SHISHI_OK;
225 * shishi_ticket_get_enc_part_etype:
226 * @handle: shishi handle as allocated by shishi_init().
227 * @ticket: Ticket variable to get value from.
228 * @etype: output variable that holds the value.
230 * Extract Ticket.enc-part.etype.
232 * Return value: Returns SHISHI_OK iff successful.
235 shishi_ticket_get_enc_part_etype (Shishi * handle,
236 Shishi_asn1 ticket, int32_t * etype)
238 int res;
240 res = shishi_asn1_read_int32 (handle, ticket, "enc-part.etype", etype);
242 return res;
246 shishi_ticket_decrypt (Shishi * handle,
247 Shishi_asn1 ticket,
248 Shishi_key * key, Shishi_asn1 * encticketpart)
250 int res;
251 int i;
252 char *buf;
253 size_t buflen;
254 char *cipher;
255 size_t cipherlen;
256 int etype;
258 res = shishi_ticket_get_enc_part_etype (handle, ticket, &etype);
259 if (res != SHISHI_OK)
260 return res;
262 if (etype != shishi_key_type (key))
263 return SHISHI_TICKET_BAD_KEYTYPE;
265 res = shishi_asn1_read (handle, ticket, "enc-part.cipher",
266 &cipher, &cipherlen);
267 if (res != SHISHI_OK)
268 return res;
270 res = shishi_decrypt (handle, key, SHISHI_KEYUSAGE_ENCTICKETPART,
271 cipher, cipherlen, &buf, &buflen);
272 free (cipher);
273 if (res != SHISHI_OK)
275 shishi_error_printf (handle,
276 "Ticket decrypt failed, wrong password?\n");
277 return SHISHI_TICKET_DECRYPT_FAILED;
280 /* The crypto is so 1980; no length indicator. Trim off pad bytes
281 until we can parse it. */
282 for (i = 0; i < 8; i++)
284 if (VERBOSEASN1 (handle))
285 printf ("Trying with %d pad in enckdcrep...\n", i);
287 *encticketpart = shishi_der2asn1_encticketpart (handle, &buf[0],
288 buflen - i);
289 if (*encticketpart != NULL)
290 break;
293 if (*encticketpart == NULL)
295 shishi_error_printf (handle, "Could not DER decode EncTicketPart. "
296 "Password probably correct (decrypt ok) though\n");
297 return SHISHI_ASN1_ERROR;
300 return SHISHI_OK;
304 * shishi_ticket_set_enc_part:
305 * @handle: shishi handle as allocated by shishi_init().
306 * @ticket: Ticket to add enc-part field to.
307 * @etype: encryption type used to encrypt enc-part.
308 * @kvno: key version number.
309 * @buf: input array with encrypted enc-part.
310 * @buflen: size of input array with encrypted enc-part.
312 * Set the encrypted enc-part field in the Ticket. The encrypted data
313 * is usually created by calling shishi_encrypt() on the DER encoded
314 * enc-part. To save time, you may want to use
315 * shishi_ticket_add_enc_part() instead, which calculates the
316 * encrypted data and calls this function in one step.
318 * Return value: Returns SHISHI_OK iff successful.
321 shishi_ticket_set_enc_part (Shishi * handle,
322 Shishi_asn1 ticket,
323 int32_t etype, uint32_t kvno,
324 const char *buf, size_t buflen)
326 int res = SHISHI_OK;
328 res = shishi_asn1_write (handle, ticket, "enc-part.cipher", buf, buflen);
329 if (res != SHISHI_OK)
330 return res;
332 res = shishi_asn1_write_int32 (handle, ticket, "enc-part.etype", etype);
333 if (res != SHISHI_OK)
334 return res;
336 if (kvno == UINT32_MAX)
337 res = shishi_asn1_write (handle, ticket, "enc-part.kvno", NULL, 0);
338 else
339 res = shishi_asn1_write_uint32 (handle, ticket, "enc-part.kvno", kvno);
340 if (res != SHISHI_OK)
341 return res;
343 return SHISHI_OK;
347 * shishi_ticket_add_enc_part:
348 * @handle: shishi handle as allocated by shishi_init().
349 * @ticket: Ticket to add enc-part field to.
350 * @key: key used to encrypt enc-part.
351 * @encticketpart: EncTicketPart to add.
353 * Encrypts DER encoded EncTicketPart using key and stores it in the
354 * Ticket.
356 * Return value: Returns SHISHI_OK iff successful.
359 shishi_ticket_add_enc_part (Shishi * handle,
360 Shishi_asn1 ticket,
361 Shishi_key * key, Shishi_asn1 encticketpart)
363 int res = SHISHI_OK;
364 char *buf;
365 size_t buflen;
366 char *der;
367 size_t derlen;
369 res = shishi_asn1_to_der (handle, encticketpart, &der, &derlen);
370 if (res != SHISHI_OK)
372 shishi_error_printf (handle, "Could not DER encode encticketpart: %s\n",
373 shishi_strerror (res));
374 return res;
377 res = shishi_encrypt (handle, key, SHISHI_KEYUSAGE_ENCTICKETPART,
378 der, derlen, &buf, &buflen);
380 free (der);
382 if (res != SHISHI_OK)
384 shishi_error_printf (handle,
385 "Cannot encrypt encrypted part of ticket\n");
386 return res;
389 res = shishi_ticket_set_enc_part (handle, ticket, shishi_key_type (key),
390 shishi_key_version (key), buf, buflen);
392 free (buf);
394 return res;