Branch data Line data Source code
1 : : /* ticket.c --- Low-level ASN.1 Ticket handling.
2 : : * Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008 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 : :
25 : : #define SHISHI_TICKET_DEFAULT_TKTVNO "5"
26 : : #define SHISHI_TICKET_DEFAULT_TKTVNO_LEN 0
27 : :
28 : : /**
29 : : * shishi_ticket:
30 : : * @handle: shishi handle as allocated by shishi_init().
31 : : *
32 : : * This function creates a new ASN.1 Ticket, populated with some
33 : : * default values.
34 : : *
35 : : * Return value: Returns the ticket or NULL on failure.
36 : : **/
37 : : Shishi_asn1
38 : 2 : shishi_ticket (Shishi * handle)
39 : : {
40 : 2 : Shishi_asn1 node = NULL;
41 : : int rc;
42 : :
43 : 2 : node = shishi_asn1_ticket (handle);
44 [ - + ]: 2 : if (!node)
45 : 0 : return NULL;
46 : :
47 : 2 : rc = shishi_asn1_write (handle, node, "tkt-vno",
48 : : SHISHI_TICKET_DEFAULT_TKTVNO,
49 : : SHISHI_TICKET_DEFAULT_TKTVNO_LEN);
50 [ - + ]: 2 : if (rc != SHISHI_OK)
51 : 0 : goto error;
52 : :
53 : 2 : return node;
54 : :
55 : : error:
56 : 0 : shishi_asn1_done (handle, node);
57 : 2 : return NULL;
58 : : }
59 : :
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.
66 : : *
67 : : * Extract realm from ticket.
68 : : *
69 : : * Return value: Returns SHISHI_OK iff successful.
70 : : **/
71 : : int
72 : 0 : shishi_ticket_realm_get (Shishi * handle,
73 : : Shishi_asn1 ticket, char **realm, size_t * realmlen)
74 : : {
75 : 0 : return shishi_asn1_read (handle, ticket, "realm", realm, realmlen);
76 : : }
77 : :
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.
83 : : *
84 : : * Set the realm field in the Ticket.
85 : : *
86 : : * Return value: Returns SHISHI_OK iff successful.
87 : : **/
88 : : int
89 : 0 : shishi_ticket_realm_set (Shishi * handle, Shishi_asn1 ticket,
90 : : const char *realm)
91 : : {
92 : : int res;
93 : :
94 : 0 : res = shishi_asn1_write (handle, ticket, "realm", realm, 0);
95 [ # # ]: 0 : if (res != SHISHI_OK)
96 : 0 : return res;
97 : :
98 : 0 : return SHISHI_OK;
99 : : }
100 : :
101 : : /**
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).
109 : : *
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.
114 : : *
115 : : * Return value: Returns SHISHI_OK iff successful.
116 : : **/
117 : : int
118 : 8 : shishi_ticket_server (Shishi * handle, Shishi_asn1 ticket,
119 : : char **server, size_t * serverlen)
120 : : {
121 : 8 : return shishi_principal_name (handle, ticket, "sname", server, serverlen);
122 : : }
123 : :
124 : : /**
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.
131 : : *
132 : : * Set the server name field in the Ticket.
133 : : *
134 : : * Return value: Returns SHISHI_OK iff successful.
135 : : **/
136 : : int
137 : 0 : shishi_ticket_sname_set (Shishi * handle,
138 : : Shishi_asn1 ticket,
139 : : Shishi_name_type name_type, char *sname[])
140 : : {
141 : 0 : int res = SHISHI_OK;
142 : : char *buf;
143 : : int i;
144 : :
145 : 0 : asprintf (&buf, "%d", name_type);
146 : 0 : res = shishi_asn1_write (handle, ticket, "sname.name-type", buf, 0);
147 : 0 : free (buf);
148 [ # # ]: 0 : if (res != SHISHI_OK)
149 : 0 : return res;
150 : :
151 : 0 : res = shishi_asn1_write (handle, ticket, "sname.name-string", NULL, 0);
152 [ # # ]: 0 : if (res != SHISHI_OK)
153 : 0 : return res;
154 : :
155 : 0 : i = 1;
156 [ # # ]: 0 : while (sname[i - 1])
157 : : {
158 : 0 : res = shishi_asn1_write (handle, ticket, "sname.name-string", "NEW", 1);
159 [ # # ]: 0 : if (res != SHISHI_OK)
160 : 0 : return res;
161 : :
162 : 0 : asprintf (&buf, "sname.name-string.?%d", i);
163 : 0 : res = shishi_asn1_write (handle, ticket, buf, sname[i - 1], 0);
164 : 0 : free (buf);
165 [ # # ]: 0 : if (res != SHISHI_OK)
166 : 0 : return res;
167 : :
168 : 0 : i++;
169 : : }
170 : :
171 : 0 : return SHISHI_OK;
172 : : }
173 : :
174 : : int
175 : 0 : shishi_ticket_set_server (Shishi * handle,
176 : : Shishi_asn1 ticket, const char *server)
177 : : {
178 : : char *tmpserver;
179 : : char **serverbuf;
180 : 0 : char *tokptr = NULL;
181 : : int res;
182 : : int i;
183 : :
184 : 0 : tmpserver = xstrdup (server);
185 : 0 : serverbuf = xmalloc (sizeof (*serverbuf));
186 : :
187 [ # # ]: 0 : for (i = 0;
188 [ # # ]: 0 : (serverbuf[i] = strtok_r (i == 0 ? tmpserver : NULL, "/", &tokptr));
189 : 0 : i++)
190 : : {
191 : 0 : serverbuf = xrealloc (serverbuf, (i + 2) * sizeof (*serverbuf));
192 : : }
193 : 0 : res = shishi_ticket_sname_set (handle, ticket,
194 : : SHISHI_NT_PRINCIPAL, serverbuf);
195 [ # # ]: 0 : if (res != SHISHI_OK)
196 : : {
197 : 0 : fprintf (stderr, _("Could not set sname: %s\n"), shishi_error (handle));
198 : 0 : return res;
199 : : }
200 : 0 : free (serverbuf);
201 : 0 : free (tmpserver);
202 : :
203 : 0 : return SHISHI_OK;
204 : : }
205 : :
206 : : int
207 : 0 : shishi_ticket_srealmserver_set (Shishi * handle,
208 : : Shishi_asn1 ticket,
209 : : const char *realm, const char *server)
210 : : {
211 : : int res;
212 : :
213 : 0 : res = shishi_ticket_realm_set (handle, ticket, realm);
214 [ # # ]: 0 : if (res != SHISHI_OK)
215 : 0 : return res;
216 : :
217 : 0 : res = shishi_ticket_set_server (handle, ticket, server);
218 [ # # ]: 0 : if (res != SHISHI_OK)
219 : 0 : return res;
220 : :
221 : 0 : return SHISHI_OK;
222 : : }
223 : :
224 : : /**
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.
229 : : *
230 : : * Extract Ticket.enc-part.etype.
231 : : *
232 : : * Return value: Returns SHISHI_OK iff successful.
233 : : **/
234 : : int
235 : 2 : shishi_ticket_get_enc_part_etype (Shishi * handle,
236 : : Shishi_asn1 ticket, int32_t * etype)
237 : : {
238 : : int res;
239 : :
240 : 2 : res = shishi_asn1_read_int32 (handle, ticket, "enc-part.etype", etype);
241 : :
242 : 2 : return res;
243 : : }
244 : :
245 : : int
246 : 0 : shishi_ticket_decrypt (Shishi * handle,
247 : : Shishi_asn1 ticket,
248 : : Shishi_key * key, Shishi_asn1 * encticketpart)
249 : : {
250 : : int res;
251 : : int i;
252 : : char *buf;
253 : : size_t buflen;
254 : : char *cipher;
255 : : size_t cipherlen;
256 : : int etype;
257 : :
258 : 0 : res = shishi_ticket_get_enc_part_etype (handle, ticket, &etype);
259 [ # # ]: 0 : if (res != SHISHI_OK)
260 : 0 : return res;
261 : :
262 [ # # ]: 0 : if (etype != shishi_key_type (key))
263 : 0 : return SHISHI_TICKET_BAD_KEYTYPE;
264 : :
265 : 0 : res = shishi_asn1_read (handle, ticket, "enc-part.cipher",
266 : : &cipher, &cipherlen);
267 [ # # ]: 0 : if (res != SHISHI_OK)
268 : 0 : return res;
269 : :
270 : 0 : res = shishi_decrypt (handle, key, SHISHI_KEYUSAGE_ENCTICKETPART,
271 : : cipher, cipherlen, &buf, &buflen);
272 : 0 : free (cipher);
273 [ # # ]: 0 : if (res != SHISHI_OK)
274 : : {
275 : 0 : shishi_error_printf (handle,
276 : : "Ticket decrypt failed, wrong password?\n");
277 : 0 : return SHISHI_TICKET_DECRYPT_FAILED;
278 : : }
279 : :
280 : : /* The crypto is so 1980; no length indicator. Trim off pad bytes
281 : : until we can parse it. */
282 [ # # ]: 0 : for (i = 0; i < 8; i++)
283 : : {
284 [ # # ]: 0 : if (VERBOSEASN1 (handle))
285 : 0 : printf ("Trying with %d pad in enckdcrep...\n", i);
286 : :
287 : 0 : *encticketpart = shishi_der2asn1_encticketpart (handle, &buf[0],
288 : : buflen - i);
289 [ # # ]: 0 : if (*encticketpart != NULL)
290 : 0 : break;
291 : : }
292 : :
293 [ # # ]: 0 : if (*encticketpart == NULL)
294 : : {
295 : 0 : shishi_error_printf (handle, "Could not DER decode EncTicketPart. "
296 : : "Password probably correct (decrypt ok) though\n");
297 : 0 : return SHISHI_ASN1_ERROR;
298 : : }
299 : :
300 : 0 : return SHISHI_OK;
301 : : }
302 : :
303 : : /**
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.
311 : : *
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.
317 : : *
318 : : * Return value: Returns SHISHI_OK iff successful.
319 : : **/
320 : : int
321 : 0 : 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)
325 : : {
326 : 0 : int res = SHISHI_OK;
327 : :
328 : 0 : res = shishi_asn1_write (handle, ticket, "enc-part.cipher", buf, buflen);
329 [ # # ]: 0 : if (res != SHISHI_OK)
330 : 0 : return res;
331 : :
332 : 0 : res = shishi_asn1_write_int32 (handle, ticket, "enc-part.etype", etype);
333 [ # # ]: 0 : if (res != SHISHI_OK)
334 : 0 : return res;
335 : :
336 [ # # ]: 0 : if (kvno == UINT32_MAX)
337 : 0 : res = shishi_asn1_write (handle, ticket, "enc-part.kvno", NULL, 0);
338 : : else
339 : 0 : res = shishi_asn1_write_uint32 (handle, ticket, "enc-part.kvno", kvno);
340 [ # # ]: 0 : if (res != SHISHI_OK)
341 : 0 : return res;
342 : :
343 : 0 : return SHISHI_OK;
344 : : }
345 : :
346 : : /**
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.
352 : : *
353 : : * Encrypts DER encoded EncTicketPart using key and stores it in the
354 : : * Ticket.
355 : : *
356 : : * Return value: Returns SHISHI_OK iff successful.
357 : : **/
358 : : int
359 : 0 : shishi_ticket_add_enc_part (Shishi * handle,
360 : : Shishi_asn1 ticket,
361 : : Shishi_key * key, Shishi_asn1 encticketpart)
362 : : {
363 : 0 : int res = SHISHI_OK;
364 : : char *buf;
365 : : size_t buflen;
366 : : char *der;
367 : : size_t derlen;
368 : :
369 : 0 : res = shishi_asn1_to_der (handle, encticketpart, &der, &derlen);
370 [ # # ]: 0 : if (res != SHISHI_OK)
371 : : {
372 : 0 : shishi_error_printf (handle, "Could not DER encode encticketpart: %s\n",
373 : : shishi_strerror (res));
374 : 0 : return res;
375 : : }
376 : :
377 : 0 : res = shishi_encrypt (handle, key, SHISHI_KEYUSAGE_ENCTICKETPART,
378 : : der, derlen, &buf, &buflen);
379 : :
380 : 0 : free (der);
381 : :
382 [ # # ]: 0 : if (res != SHISHI_OK)
383 : : {
384 : 0 : shishi_error_printf (handle,
385 : : "Cannot encrypt encrypted part of ticket\n");
386 : 0 : return res;
387 : : }
388 : :
389 : 0 : res = shishi_ticket_set_enc_part (handle, ticket, shishi_key_type (key),
390 : : shishi_key_version (key), buf, buflen);
391 : :
392 : 0 : free (buf);
393 : :
394 : 0 : return res;
395 : : }
|