Change GPLv2+ to GPLv3+.
[shishi.git] / lib / apreq.c
blob9be58099520a69b73f7ed5f243a999a1593cbb20
1 /* apreq.c --- AP-REQ functions.
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 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 but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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 /* Get _shishi_print_armored_data, etc. */
26 #include "diskio.h"
28 #define SHISHI_APREQ_DEFAULT_PVNO "5"
29 #define SHISHI_APREQ_DEFAULT_PVNO_LEN 0
30 #define SHISHI_APREQ_DEFAULT_MSG_TYPE "14" /* KRB_AP_REQ */
31 #define SHISHI_APREQ_DEFAULT_MSG_TYPE_LEN 0
32 #define SHISHI_APREQ_DEFAULT_AP_OPTIONS "\x00\x00\x00\x00"
33 #define SHISHI_APREQ_DEFAULT_AP_OPTIONS_LEN 32
34 #define SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO "5"
35 #define SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO_LEN 0
36 #define SHISHI_APREQ_DEFAULT_TICKET_REALM ""
37 #define SHISHI_APREQ_DEFAULT_TICKET_REALM_LEN 0
38 #define SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE "1" /* SHISHI_NT_PRINCIPAL */
39 #define SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE_LEN 0
40 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE "0"
41 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE_LEN 0
42 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO "0"
43 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO_LEN 0
44 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER ""
45 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER_LEN 0
46 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE "0"
47 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE_LEN 0
48 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO "1"
49 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO_LEN 0
50 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER ""
51 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER_LEN 0
53 /**
54 * shishi_apreq:
55 * @handle: shishi handle as allocated by shishi_init().
57 * This function creates a new AP-REQ, populated with some default
58 * values.
60 * Return value: Returns the AP-REQ or NULL on failure.
61 **/
62 Shishi_asn1
63 shishi_apreq (Shishi * handle)
65 Shishi_asn1 node;
66 int res;
68 node = shishi_asn1_apreq (handle);
69 if (!node)
70 goto error;
72 res = shishi_asn1_write (handle, node, "pvno",
73 SHISHI_APREQ_DEFAULT_PVNO,
74 SHISHI_APREQ_DEFAULT_PVNO_LEN);
75 if (res != SHISHI_OK)
76 goto error;
78 res = shishi_asn1_write (handle, node, "msg-type",
79 SHISHI_APREQ_DEFAULT_MSG_TYPE,
80 SHISHI_APREQ_DEFAULT_MSG_TYPE_LEN);
81 if (res != SHISHI_OK)
82 goto error;
84 res = shishi_asn1_write (handle, node, "ap-options",
85 SHISHI_APREQ_DEFAULT_AP_OPTIONS,
86 SHISHI_APREQ_DEFAULT_AP_OPTIONS_LEN);
87 if (res != SHISHI_OK)
88 goto error;
90 res = shishi_asn1_write (handle, node, "ticket.tkt-vno",
91 SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO,
92 SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO_LEN);
93 if (res != SHISHI_OK)
94 goto error;
96 res = shishi_asn1_write (handle, node, "ticket.realm",
97 SHISHI_APREQ_DEFAULT_TICKET_REALM,
98 SHISHI_APREQ_DEFAULT_TICKET_REALM_LEN);
99 if (res != SHISHI_OK)
100 goto error;
102 res = shishi_asn1_write (handle, node, "ticket.realm",
103 SHISHI_APREQ_DEFAULT_TICKET_REALM,
104 SHISHI_APREQ_DEFAULT_TICKET_REALM_LEN);
105 if (res != SHISHI_OK)
106 goto error;
108 res = shishi_asn1_write (handle, node, "ticket.sname.name-type",
109 SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE,
110 SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE_LEN);
111 if (res != SHISHI_OK)
112 goto error;
114 res = shishi_asn1_write (handle, node, "ticket.enc-part.etype",
115 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE,
116 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE_LEN);
117 if (res != SHISHI_OK)
118 goto error;
120 res = shishi_asn1_write (handle, node, "ticket.enc-part.kvno",
121 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO,
122 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO_LEN);
123 if (res != SHISHI_OK)
124 goto error;
126 res = shishi_asn1_write (handle, node, "ticket.enc-part.cipher",
127 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER,
128 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER_LEN);
129 if (res != SHISHI_OK)
130 goto error;
132 res = shishi_asn1_write (handle, node, "authenticator.etype",
133 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE,
134 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE_LEN);
135 if (res != SHISHI_OK)
136 goto error;
138 res = shishi_asn1_write (handle, node, "authenticator.kvno",
139 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO,
140 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO_LEN);
141 if (res != SHISHI_OK)
142 goto error;
144 res = shishi_asn1_write (handle, node, "authenticator.cipher",
145 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER,
146 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER_LEN);
147 if (res != SHISHI_OK)
148 goto error;
150 return node;
152 error:
153 if (node)
154 shishi_asn1_done (handle, node);
155 return NULL;
159 * shishi_apreq_print:
160 * @handle: shishi handle as allocated by shishi_init().
161 * @fh: file handle open for writing.
162 * @apreq: AP-REQ to print.
164 * Print ASCII armored DER encoding of AP-REQ to file.
166 * Return value: Returns SHISHI_OK iff successful.
169 shishi_apreq_print (Shishi * handle, FILE * fh, Shishi_asn1 apreq)
171 return _shishi_print_armored_data (handle, fh, apreq, "AP-REQ", NULL);
175 * shishi_apreq_save:
176 * @handle: shishi handle as allocated by shishi_init().
177 * @fh: file handle open for writing.
178 * @apreq: AP-REQ to save.
180 * Save DER encoding of AP-REQ to file.
182 * Return value: Returns SHISHI_OK iff successful.
185 shishi_apreq_save (Shishi * handle, FILE * fh, Shishi_asn1 apreq)
187 return _shishi_save_data (handle, fh, apreq, "AP-REQ");
191 * shishi_apreq_to_file:
192 * @handle: shishi handle as allocated by shishi_init().
193 * @apreq: AP-REQ to save.
194 * @filetype: input variable specifying type of file to be written,
195 * see Shishi_filetype.
196 * @filename: input variable with filename to write to.
198 * Write AP-REQ to file in specified TYPE. The file will be
199 * truncated if it exists.
201 * Return value: Returns SHISHI_OK iff successful.
204 shishi_apreq_to_file (Shishi * handle, Shishi_asn1 apreq,
205 int filetype, const char *filename)
207 FILE *fh;
208 int res;
210 if (VERBOSE (handle))
211 printf (_("Writing AP-REQ to %s...\n"), filename);
213 fh = fopen (filename, "w");
214 if (fh == NULL)
215 return SHISHI_FOPEN_ERROR;
217 if (VERBOSE (handle))
218 printf (_("Writing AP-REQ in %s format...\n"),
219 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
221 if (filetype == SHISHI_FILETYPE_TEXT)
222 res = shishi_apreq_print (handle, fh, apreq);
223 else
224 res = shishi_apreq_save (handle, fh, apreq);
225 if (res != SHISHI_OK)
226 return res;
228 res = fclose (fh);
229 if (res != 0)
230 return SHISHI_IO_ERROR;
232 if (VERBOSE (handle))
233 printf (_("Writing AP-REQ to %s...done\n"), filename);
235 return SHISHI_OK;
239 * shishi_apreq_parse:
240 * @handle: shishi handle as allocated by shishi_init().
241 * @fh: file handle open for reading.
242 * @apreq: output variable with newly allocated AP-REQ.
244 * Read ASCII armored DER encoded AP-REQ from file and populate given
245 * variable.
247 * Return value: Returns SHISHI_OK iff successful.
250 shishi_apreq_parse (Shishi * handle, FILE * fh, Shishi_asn1 * apreq)
252 return _shishi_apreq_input (handle, fh, apreq, 0);
256 * shishi_apreq_read:
257 * @handle: shishi handle as allocated by shishi_init().
258 * @fh: file handle open for reading.
259 * @apreq: output variable with newly allocated AP-REQ.
261 * Read DER encoded AP-REQ from file and populate given variable.
263 * Return value: Returns SHISHI_OK iff successful.
266 shishi_apreq_read (Shishi * handle, FILE * fh, Shishi_asn1 * apreq)
268 return _shishi_apreq_input (handle, fh, apreq, 1);
272 * shishi_apreq_from_file:
273 * @handle: shishi handle as allocated by shishi_init().
274 * @apreq: output variable with newly allocated AP-REQ.
275 * @filetype: input variable specifying type of file to be read,
276 * see Shishi_filetype.
277 * @filename: input variable with filename to read from.
279 * Read AP-REQ from file in specified TYPE.
281 * Return value: Returns SHISHI_OK iff successful.
284 shishi_apreq_from_file (Shishi * handle, Shishi_asn1 * apreq,
285 int filetype, const char *filename)
287 int res;
288 FILE *fh;
290 if (VERBOSE (handle))
291 printf (_("Reading AP-REQ from %s...\n"), filename);
293 fh = fopen (filename, "r");
294 if (fh == NULL)
295 return SHISHI_FOPEN_ERROR;
297 if (VERBOSE (handle))
298 printf (_("Reading AP-REQ in %s format...\n"),
299 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
301 if (filetype == SHISHI_FILETYPE_TEXT)
302 res = shishi_apreq_parse (handle, fh, apreq);
303 else
304 res = shishi_apreq_read (handle, fh, apreq);
305 if (res != SHISHI_OK)
306 return res;
308 res = fclose (fh);
309 if (res != 0)
310 return SHISHI_IO_ERROR;
312 if (VERBOSE (handle))
313 printf (_("Reading AP-REQ from %s...done\n"), filename);
315 return SHISHI_OK;
319 * shishi_apreq_set_authenticator:
320 * @handle: shishi handle as allocated by shishi_init().
321 * @apreq: AP-REQ to add authenticator field to.
322 * @etype: encryption type used to encrypt authenticator.
323 * @kvno: version of the key used to encrypt authenticator.
324 * @buf: input array with encrypted authenticator.
325 * @buflen: size of input array with encrypted authenticator.
327 * Set the encrypted authenticator field in the AP-REP. The encrypted
328 * data is usually created by calling shishi_encrypt() on the DER
329 * encoded authenticator. To save time, you may want to use
330 * shishi_apreq_add_authenticator() instead, which calculates the
331 * encrypted data and calls this function in one step.
333 * Return value: Returns SHISHI_OK on success.
336 shishi_apreq_set_authenticator (Shishi * handle,
337 Shishi_asn1 apreq,
338 int32_t etype, uint32_t kvno,
339 const char *buf, size_t buflen)
341 int res;
343 res = shishi_asn1_write (handle, apreq, "authenticator.cipher",
344 buf, buflen);
345 if (res != SHISHI_OK)
346 return res;
348 if (kvno == UINT32_MAX)
349 res = shishi_asn1_write (handle, apreq, "authenticator.kvno", NULL, 0);
350 else
351 res = shishi_asn1_write_int32 (handle, apreq, "authenticator.kvno", kvno);
352 if (res != SHISHI_OK)
353 return res;
355 res = shishi_asn1_write_int32 (handle, apreq, "authenticator.etype", etype);
356 if (res != SHISHI_OK)
357 return res;
359 return SHISHI_OK;
363 * shishi_apreq_add_authenticator:
364 * @handle: shishi handle as allocated by shishi_init().
365 * @apreq: AP-REQ to add authenticator field to.
366 * @key: key to to use for encryption.
367 * @keyusage: cryptographic key usage value to use in encryption.
368 * @authenticator: authenticator as allocated by shishi_authenticator().
370 * Encrypts DER encoded authenticator using key and store it in the
371 * AP-REQ.
373 * Return value: Returns SHISHI_OK iff successful.
376 shishi_apreq_add_authenticator (Shishi * handle,
377 Shishi_asn1 apreq,
378 Shishi_key * key,
379 int keyusage, Shishi_asn1 authenticator)
381 int res;
382 char *buf;
383 size_t buflen;
384 char *der;
385 size_t derlen;
387 res = shishi_asn1_to_der (handle, authenticator, &der, &derlen);
388 if (res != SHISHI_OK)
390 shishi_error_printf (handle, "Could not DER encode authenticator: %s\n",
391 shishi_strerror (res));
392 return res;
395 res = shishi_encrypt (handle, key, keyusage, der, derlen, &buf, &buflen);
397 free (der);
399 if (res != SHISHI_OK)
401 shishi_error_printf (handle, "Cannot encrypt authenticator.\n");
402 return res;
405 res = shishi_apreq_set_authenticator (handle, apreq, shishi_key_type (key),
406 shishi_key_version (key),
407 buf, buflen);
409 return res;
413 * shishi_apreq_set_ticket:
414 * @handle: shishi handle as allocated by shishi_init().
415 * @apreq: AP-REQ to add ticket field to.
416 * @ticket: input ticket to copy into AP-REQ ticket field.
418 * Copy ticket into AP-REQ.
420 * Return value: Returns SHISHI_OK iff successful.
423 shishi_apreq_set_ticket (Shishi * handle, Shishi_asn1 apreq,
424 Shishi_asn1 ticket)
426 int res;
427 char *format;
428 char *buf;
429 size_t buflen, i, n;
431 res = shishi_asn1_read (handle, ticket, "tkt-vno", &buf, &buflen);
432 if (res != SHISHI_OK)
433 return res;
435 res = shishi_asn1_write (handle, apreq, "ticket.tkt-vno", buf, buflen);
436 free (buf);
437 if (res != SHISHI_OK)
438 return res;
440 res = shishi_asn1_read (handle, ticket, "realm", &buf, &buflen);
441 if (res != SHISHI_OK)
442 return res;
444 res = shishi_asn1_write (handle, apreq, "ticket.realm", buf, buflen);
445 free (buf);
446 if (res != SHISHI_OK)
447 return res;
449 res = shishi_asn1_read (handle, ticket, "sname.name-type", &buf, &buflen);
450 if (res != SHISHI_OK)
451 return res;
453 res = shishi_asn1_write (handle, apreq, "ticket.sname.name-type",
454 buf, buflen);
455 free (buf);
456 if (res != SHISHI_OK)
457 return res;
459 res = shishi_asn1_number_of_elements (handle, ticket,
460 "sname.name-string", &n);
461 if (res != SHISHI_OK)
462 return res;
464 for (i = 1; i <= n; i++)
466 res = shishi_asn1_write (handle, apreq,
467 "ticket.sname.name-string", "NEW", 1);
468 if (res != SHISHI_OK)
469 return res;
471 asprintf (&format, "sname.name-string.?%d", i);
472 res = shishi_asn1_read (handle, ticket, format, &buf, &buflen);
473 free (format);
474 if (res != SHISHI_OK)
475 return res;
477 asprintf (&format, "ticket.sname.name-string.?%d", i);
478 res = shishi_asn1_write (handle, apreq, format, buf, buflen);
479 free (format);
480 free (buf);
481 if (res != SHISHI_OK)
482 return res;
485 res = shishi_asn1_read (handle, ticket, "enc-part.etype", &buf, &buflen);
486 if (res != SHISHI_OK)
487 return res;
489 res = shishi_asn1_write (handle, apreq, "ticket.enc-part.etype",
490 buf, buflen);
491 free (buf);
492 if (res != SHISHI_OK)
493 return res;
495 res = shishi_asn1_read (handle, ticket, "enc-part.kvno", &buf, &buflen);
496 if (res != SHISHI_OK && res != SHISHI_ASN1_NO_ELEMENT)
497 return res;
499 if (res == SHISHI_ASN1_NO_ELEMENT)
500 res = shishi_asn1_write (handle, apreq, "ticket.enc-part.kvno", NULL, 0);
501 else
503 res = shishi_asn1_write (handle, apreq, "ticket.enc-part.kvno",
504 buf, buflen);
505 free (buf);
507 if (res != SHISHI_OK)
508 return res;
510 res = shishi_asn1_read (handle, ticket, "enc-part.cipher", &buf, &buflen);
511 if (res != SHISHI_OK)
512 return res;
514 res = shishi_asn1_write (handle, apreq, "ticket.enc-part.cipher",
515 buf, buflen);
516 free (buf);
517 if (res != SHISHI_OK)
518 return res;
520 return SHISHI_OK;
524 * shishi_apreq_options:
525 * @handle: shishi handle as allocated by shishi_init().
526 * @apreq: AP-REQ to get options from.
527 * @flags: Output integer containing options from AP-REQ.
529 * Extract the AP-Options from AP-REQ into output integer.
531 * Return value: Returns SHISHI_OK iff successful.
534 shishi_apreq_options (Shishi * handle, Shishi_asn1 apreq, uint32_t * flags)
536 return shishi_asn1_read_bitstring (handle, apreq, "ap-options", flags);
540 * shishi_apreq_use_session_key_p:
541 * @handle: shishi handle as allocated by shishi_init().
542 * @apreq: AP-REQ as allocated by shishi_apreq().
544 * Return non-0 iff the "Use session key" option is set in the AP-REQ.
546 * Return value: Returns SHISHI_OK iff successful.
549 shishi_apreq_use_session_key_p (Shishi * handle, Shishi_asn1 apreq)
551 uint32_t options = 0;
553 shishi_apreq_options (handle, apreq, &options);
555 return options & SHISHI_APOPTIONS_USE_SESSION_KEY;
559 * shishi_apreq_mutual_required_p:
560 * @handle: shishi handle as allocated by shishi_init().
561 * @apreq: AP-REQ as allocated by shishi_apreq().
563 * Return non-0 iff the "Mutual required" option is set in the AP-REQ.
565 * Return value: Returns SHISHI_OK iff successful.
568 shishi_apreq_mutual_required_p (Shishi * handle, Shishi_asn1 apreq)
570 uint32_t options = 0;
572 shishi_apreq_options (handle, apreq, &options);
574 return options & SHISHI_APOPTIONS_MUTUAL_REQUIRED;
578 * shishi_apreq_options_set:
579 * @handle: shishi handle as allocated by shishi_init().
580 * @apreq: AP-REQ as allocated by shishi_apreq().
581 * @options: Options to set in AP-REQ.
583 * Set the AP-Options in AP-REQ to indicate integer.
585 * Return value: Returns SHISHI_OK iff successful.
588 shishi_apreq_options_set (Shishi * handle, Shishi_asn1 apreq,
589 uint32_t options)
591 int res;
593 res = shishi_asn1_write_bitstring (handle, apreq, "ap-options", options);
594 if (res != SHISHI_OK)
595 return res;
597 return SHISHI_OK;
601 * shishi_apreq_options_add:
602 * @handle: shishi handle as allocated by shishi_init().
603 * @apreq: AP-REQ as allocated by shishi_apreq().
604 * @option: Options to add in AP-REQ.
606 * Add the AP-Options in AP-REQ. Options not set in input parameter
607 * @option are preserved in the AP-REQ.
609 * Return value: Returns SHISHI_OK iff successful.
612 shishi_apreq_options_add (Shishi * handle, Shishi_asn1 apreq, uint32_t option)
614 uint32_t options;
615 int res;
617 res = shishi_apreq_options (handle, apreq, &options);
618 if (res != SHISHI_OK)
619 return res;
621 options |= option;
623 res = shishi_apreq_options_set (handle, apreq, options);
624 if (res != SHISHI_OK)
625 return res;
627 return SHISHI_OK;
631 * shishi_apreq_options_remove:
632 * @handle: shishi handle as allocated by shishi_init().
633 * @apreq: AP-REQ as allocated by shishi_apreq().
634 * @option: Options to remove from AP-REQ.
636 * Remove the AP-Options from AP-REQ. Options not set in input
637 * parameter @option are preserved in the AP-REQ.
639 * Return value: Returns SHISHI_OK iff successful.
642 shishi_apreq_options_remove (Shishi * handle,
643 Shishi_asn1 apreq, uint32_t option)
645 uint32_t options;
646 int res;
648 res = shishi_apreq_options (handle, apreq, &options);
649 if (res != SHISHI_OK)
650 return res;
652 options &= ~(options & option);
654 res = shishi_apreq_options_set (handle, apreq, options);
655 if (res != SHISHI_OK)
656 return res;
658 return SHISHI_OK;
662 * shishi_apreq_get_authenticator_etype:
663 * @handle: shishi handle as allocated by shishi_init().
664 * @apreq: AP-REQ variable to get value from.
665 * @etype: output variable that holds the value.
667 * Extract AP-REQ.authenticator.etype.
669 * Return value: Returns SHISHI_OK iff successful.
672 shishi_apreq_get_authenticator_etype (Shishi * handle,
673 Shishi_asn1 apreq, int32_t * etype)
675 return shishi_asn1_read_int32 (handle, apreq, "authenticator.etype", etype);
679 * shishi_apreq_get_ticket:
680 * @handle: shishi handle as allocated by shishi_init().
681 * @apreq: AP-REQ variable to get ticket from.
682 * @ticket: output variable to hold extracted ticket.
684 * Extract ticket from AP-REQ.
686 * Return value: Returns SHISHI_OK iff successful.
689 shishi_apreq_get_ticket (Shishi * handle,
690 Shishi_asn1 apreq, Shishi_asn1 * ticket)
692 char *buf;
693 char *format;
694 size_t buflen, i, n;
695 int res;
697 /* there's GOT to be an easier way to do this */
699 *ticket = shishi_ticket (handle);
700 if (!*ticket)
701 return SHISHI_ASN1_ERROR;
703 res = shishi_asn1_read (handle, apreq, "ticket.tkt-vno", &buf, &buflen);
704 if (res != SHISHI_OK)
705 goto error;
707 res = shishi_asn1_write (handle, *ticket, "tkt-vno", buf, buflen);
708 free (buf);
709 if (res != SHISHI_OK)
710 goto error;
712 res = shishi_asn1_read (handle, apreq, "ticket.realm", &buf, &buflen);
713 if (res != SHISHI_OK)
714 goto error;
716 res = shishi_asn1_write (handle, *ticket, "realm", buf, buflen);
717 free (buf);
718 if (res != SHISHI_OK)
719 goto error;
721 res = shishi_asn1_read (handle, apreq, "ticket.sname.name-type",
722 &buf, &buflen);
723 if (res != SHISHI_OK)
724 goto error;
726 res = shishi_asn1_write (handle, *ticket, "sname.name-type", buf, buflen);
727 free (buf);
728 if (res != SHISHI_OK)
729 goto error;
731 res = shishi_asn1_number_of_elements (handle, apreq,
732 "ticket.sname.name-string", &n);
733 if (res != SHISHI_OK)
734 goto error;
736 for (i = 1; i <= n; i++)
738 res = shishi_asn1_write (handle, *ticket, "sname.name-string",
739 "NEW", 1);
740 if (res != SHISHI_OK)
741 goto error;
743 asprintf (&format, "ticket.sname.name-string.?%d", i);
744 res = shishi_asn1_read (handle, apreq, format, &buf, &buflen);
745 free (format);
746 if (res != SHISHI_OK)
747 goto error;
749 asprintf (&format, "sname.name-string.?%d", i);
750 res = shishi_asn1_write (handle, *ticket, format, buf, buflen);
751 free (format);
752 free (buf);
753 if (res != SHISHI_OK)
754 goto error;
757 res = shishi_asn1_read (handle, apreq, "ticket.enc-part.etype",
758 &buf, &buflen);
759 if (res != SHISHI_OK)
760 goto error;
762 res = shishi_asn1_write (handle, *ticket, "enc-part.etype", buf, buflen);
763 free (buf);
764 if (res != SHISHI_OK)
765 goto error;
767 res = shishi_asn1_read (handle, apreq, "ticket.enc-part.kvno",
768 &buf, &buflen);
769 if (res != SHISHI_OK && res != SHISHI_ASN1_NO_ELEMENT)
770 goto error;
772 if (res == SHISHI_ASN1_NO_ELEMENT)
773 res = shishi_asn1_write (handle, *ticket, "enc-part.kvno", NULL, 0);
774 else
776 res = shishi_asn1_write (handle, *ticket, "enc-part.kvno", buf, buflen);
777 free (buf);
779 if (res != SHISHI_OK)
780 goto error;
782 res = shishi_asn1_read (handle, apreq, "ticket.enc-part.cipher",
783 &buf, &buflen);
784 if (res != SHISHI_OK)
785 goto error;
787 res = shishi_asn1_write (handle, *ticket, "enc-part.cipher", buf, buflen);
788 free (buf);
789 if (res != SHISHI_OK)
790 goto error;
792 return SHISHI_OK;
794 error:
795 shishi_asn1_done (handle, *ticket);
796 return res;
800 shishi_apreq_decrypt (Shishi * handle,
801 Shishi_asn1 apreq,
802 Shishi_key * key,
803 int keyusage, Shishi_asn1 * authenticator)
805 int res;
806 int i;
807 char *buf;
808 size_t buflen;
809 char *cipher;
810 size_t cipherlen;
811 int etype;
813 res = shishi_apreq_get_authenticator_etype (handle, apreq, &etype);
814 if (res != SHISHI_OK)
815 return res;
817 if (etype != shishi_key_type (key))
818 return SHISHI_APREQ_BAD_KEYTYPE;
820 res = shishi_asn1_read (handle, apreq, "authenticator.cipher",
821 &cipher, &cipherlen);
822 if (res != SHISHI_OK)
823 return res;
825 res = shishi_decrypt (handle, key, keyusage,
826 cipher, cipherlen, &buf, &buflen);
827 free (cipher);
828 if (res != SHISHI_OK)
830 shishi_error_printf (handle,
831 "decrypt fail, most likely wrong password\n");
832 return SHISHI_APREQ_DECRYPT_FAILED;
835 /* The crypto is so 1980; no length indicator. Trim off pad bytes
836 until we can parse it. */
837 for (i = 0; i < 8; i++)
839 if (VERBOSEASN1 (handle))
840 printf ("Trying with %d pad in enckdcrep...\n", i);
842 *authenticator = shishi_der2asn1_authenticator (handle, &buf[0],
843 buflen - i);
844 if (*authenticator != NULL)
845 break;
848 if (*authenticator == NULL)
850 shishi_error_printf (handle, "Could not DER decode Authenticator. "
851 "Password probably correct (decrypt ok) though\n");
852 return SHISHI_ASN1_ERROR;
855 return SHISHI_OK;