1 /* apreq.c AP-REQ functions
2 * Copyright (C) 2002, 2003 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
24 #define SHISHI_APREQ_DEFAULT_PVNO "5"
25 #define SHISHI_APREQ_DEFAULT_PVNO_LEN 0
26 #define SHISHI_APREQ_DEFAULT_MSG_TYPE "14" /* KRB_AP_REQ */
27 #define SHISHI_APREQ_DEFAULT_MSG_TYPE_LEN 0
28 #define SHISHI_APREQ_DEFAULT_AP_OPTIONS "\x00\x00\x00\x00"
29 #define SHISHI_APREQ_DEFAULT_AP_OPTIONS_LEN 32
30 #define SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO "5"
31 #define SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO_LEN 0
32 #define SHISHI_APREQ_DEFAULT_TICKET_REALM ""
33 #define SHISHI_APREQ_DEFAULT_TICKET_REALM_LEN 0
34 #define SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE "1" /* SHISHI_NT_PRINCIPAL */
35 #define SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE_LEN 0
36 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE "0"
37 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE_LEN 0
38 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO "0"
39 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO_LEN 0
40 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER ""
41 #define SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER_LEN 0
42 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE "0"
43 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE_LEN 0
44 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO "1"
45 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO_LEN 0
46 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER ""
47 #define SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER_LEN 0
51 * @handle: shishi handle as allocated by shishi_init().
53 * This function creates a new AP-REQ, populated with some default
56 * Return value: Returns the AP-REQ or NULL on failure.
59 shishi_apreq (Shishi
* handle
)
64 node
= shishi_asn1_apreq (handle
);
68 res
= shishi_asn1_write (handle
, node
, "pvno",
69 SHISHI_APREQ_DEFAULT_PVNO
,
70 SHISHI_APREQ_DEFAULT_PVNO_LEN
);
74 res
= shishi_asn1_write (handle
, node
, "msg-type",
75 SHISHI_APREQ_DEFAULT_MSG_TYPE
,
76 SHISHI_APREQ_DEFAULT_MSG_TYPE_LEN
);
80 res
= shishi_asn1_write (handle
, node
, "ap-options",
81 SHISHI_APREQ_DEFAULT_AP_OPTIONS
,
82 SHISHI_APREQ_DEFAULT_AP_OPTIONS_LEN
);
86 res
= shishi_asn1_write (handle
, node
, "ticket.tkt-vno",
87 SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO
,
88 SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO_LEN
);
92 res
= shishi_asn1_write (handle
, node
, "ticket.realm",
93 SHISHI_APREQ_DEFAULT_TICKET_REALM
,
94 SHISHI_APREQ_DEFAULT_TICKET_REALM_LEN
);
98 res
= shishi_asn1_write (handle
, node
, "ticket.realm",
99 SHISHI_APREQ_DEFAULT_TICKET_REALM
,
100 SHISHI_APREQ_DEFAULT_TICKET_REALM_LEN
);
101 if (res
!= SHISHI_OK
)
104 res
= shishi_asn1_write (handle
, node
, "ticket.sname.name-type",
105 SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE
,
106 SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE_LEN
);
107 if (res
!= SHISHI_OK
)
110 res
= shishi_asn1_write (handle
, node
, "ticket.enc-part.etype",
111 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE
,
112 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE_LEN
);
113 if (res
!= SHISHI_OK
)
116 res
= shishi_asn1_write (handle
, node
, "ticket.enc-part.kvno",
117 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO
,
118 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO_LEN
);
119 if (res
!= SHISHI_OK
)
122 res
= shishi_asn1_write (handle
, node
, "ticket.enc-part.cipher",
123 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER
,
124 SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER_LEN
);
125 if (res
!= SHISHI_OK
)
128 res
= shishi_asn1_write (handle
, node
, "authenticator.etype",
129 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE
,
130 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE_LEN
);
131 if (res
!= SHISHI_OK
)
134 res
= shishi_asn1_write (handle
, node
, "authenticator.kvno",
135 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO
,
136 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO_LEN
);
137 if (res
!= SHISHI_OK
)
140 res
= shishi_asn1_write (handle
, node
, "authenticator.cipher",
141 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER
,
142 SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER_LEN
);
143 if (res
!= SHISHI_OK
)
150 shishi_asn1_done (handle
, node
);
155 * shishi_apreq_print:
156 * @handle: shishi handle as allocated by shishi_init().
157 * @fh: file handle open for writing.
158 * @apreq: AP-REQ to print.
160 * Print ASCII armored DER encoding of AP-REQ to file.
162 * Return value: Returns SHISHI_OK iff successful.
165 shishi_apreq_print (Shishi
* handle
, FILE * fh
, Shishi_asn1 apreq
)
167 return _shishi_print_armored_data (handle
, fh
, apreq
, "AP-REQ", NULL
);
172 * @handle: shishi handle as allocated by shishi_init().
173 * @fh: file handle open for writing.
174 * @apreq: AP-REQ to save.
176 * Save DER encoding of AP-REQ to file.
178 * Return value: Returns SHISHI_OK iff successful.
181 shishi_apreq_save (Shishi
* handle
, FILE * fh
, Shishi_asn1 apreq
)
183 return _shishi_save_data (handle
, fh
, apreq
, "AP-REQ");
187 * shishi_apreq_to_file:
188 * @handle: shishi handle as allocated by shishi_init().
189 * @apreq: AP-REQ to save.
190 * @filetype: input variable specifying type of file to be written,
191 * see Shishi_filetype.
192 * @filename: input variable with filename to write to.
194 * Write AP-REQ to file in specified TYPE. The file will be
195 * truncated if it exists.
197 * Return value: Returns SHISHI_OK iff successful.
200 shishi_apreq_to_file (Shishi
* handle
, Shishi_asn1 apreq
,
201 int filetype
, char *filename
)
206 if (VERBOSE (handle
))
207 printf (_("Writing AP-REQ to %s...\n"), filename
);
209 fh
= fopen (filename
, "w");
211 return SHISHI_FOPEN_ERROR
;
213 if (VERBOSE (handle
))
214 printf (_("Writing AP-REQ in %s format...\n"),
215 filetype
== SHISHI_FILETYPE_TEXT
? "TEXT" : "DER");
217 if (filetype
== SHISHI_FILETYPE_TEXT
)
218 res
= shishi_apreq_print (handle
, fh
, apreq
);
220 res
= shishi_apreq_save (handle
, fh
, apreq
);
221 if (res
!= SHISHI_OK
)
226 return SHISHI_FCLOSE_ERROR
;
228 if (VERBOSE (handle
))
229 printf (_("Writing AP-REQ to %s...done\n"), filename
);
235 * shishi_apreq_parse:
236 * @handle: shishi handle as allocated by shishi_init().
237 * @fh: file handle open for reading.
238 * @apreq: output variable with newly allocated AP-REQ.
240 * Read ASCII armored DER encoded AP-REQ from file and populate given
243 * Return value: Returns SHISHI_OK iff successful.
246 shishi_apreq_parse (Shishi
* handle
, FILE * fh
, Shishi_asn1
* apreq
)
248 return _shishi_apreq_input (handle
, fh
, apreq
, 0);
253 * @handle: shishi handle as allocated by shishi_init().
254 * @fh: file handle open for reading.
255 * @apreq: output variable with newly allocated AP-REQ.
257 * Read DER encoded AP-REQ from file and populate given variable.
259 * Return value: Returns SHISHI_OK iff successful.
262 shishi_apreq_read (Shishi
* handle
, FILE * fh
, Shishi_asn1
* apreq
)
264 return _shishi_apreq_input (handle
, fh
, apreq
, 1);
268 * shishi_apreq_from_file:
269 * @handle: shishi handle as allocated by shishi_init().
270 * @apreq: output variable with newly allocated AP-REQ.
271 * @filetype: input variable specifying type of file to be read,
272 * see Shishi_filetype.
273 * @filename: input variable with filename to read from.
275 * Read AP-REQ from file in specified TYPE.
277 * Return value: Returns SHISHI_OK iff successful.
280 shishi_apreq_from_file (Shishi
* handle
, Shishi_asn1
* apreq
,
281 int filetype
, char *filename
)
286 if (VERBOSE (handle
))
287 printf (_("Reading AP-REQ from %s...\n"), filename
);
289 fh
= fopen (filename
, "r");
291 return SHISHI_FOPEN_ERROR
;
293 if (VERBOSE (handle
))
294 printf (_("Reading AP-REQ in %s format...\n"),
295 filetype
== SHISHI_FILETYPE_TEXT
? "TEXT" : "DER");
297 if (filetype
== SHISHI_FILETYPE_TEXT
)
298 res
= shishi_apreq_parse (handle
, fh
, apreq
);
300 res
= shishi_apreq_read (handle
, fh
, apreq
);
301 if (res
!= SHISHI_OK
)
306 return SHISHI_FCLOSE_ERROR
;
308 if (VERBOSE (handle
))
309 printf (_("Reading AP-REQ from %s...done\n"), filename
);
315 * shishi_apreq_set_authenticator:
316 * @handle: shishi handle as allocated by shishi_init().
317 * @apreq: AP-REQ to add authenticator field to.
318 * @etype: encryption type used to encrypt authenticator.
319 * @buf: input array with encrypted authenticator.
320 * @buflen: size of input array with encrypted authenticator.
322 * Set the encrypted authenticator field in the AP-REP. The encrypted
323 * data is usually created by calling shishi_encrypt() on the DER
324 * encoded authenticator. To save time, you may want to use
325 * shishi_apreq_add_authenticator() instead, which calculates the
326 * encrypted data and calls this function in one step.
331 shishi_apreq_set_authenticator (Shishi
* handle
,
333 int32_t etype
, char *buf
, int buflen
)
338 shishi_asn1_write (handle
, apreq
, "authenticator.cipher", buf
, buflen
);
339 if (res
!= SHISHI_OK
)
342 res
= shishi_asn1_write_int32 (handle
, apreq
, "authenticator.etype", etype
);
343 if (res
!= SHISHI_OK
)
350 * shishi_apreq_add_authenticator:
351 * @handle: shishi handle as allocated by shishi_init().
352 * @apreq: AP-REQ to add authenticator field to.
353 * @enckdcreppart: ticket information where the key is taken from.
354 * @authenticator: authenticator as allocated by shishi_authenticator().
356 * Encrypts DER encoded authenticator using key from ticket and store
359 * Return value: Returns SHISHI_OK iff successful.
362 shishi_apreq_add_authenticator (Shishi
* handle
,
365 int keyusage
, Shishi_asn1 authenticator
)
373 res
= shishi_new_a2d (handle
, authenticator
, &der
, &derlen
);
374 if (res
!= SHISHI_OK
)
376 shishi_error_printf (handle
, "Could not DER encode authenticator: %s\n",
377 shishi_strerror (res
));
381 res
= shishi_encrypt (handle
, key
, keyusage
, der
, derlen
, &buf
, &buflen
);
385 if (res
!= SHISHI_OK
)
387 shishi_error_printf (handle
, "Cannot encrypt authenticator.\n");
391 res
= shishi_apreq_set_authenticator (handle
, apreq
, shishi_key_type (key
),
398 * shishi_apreq_set_ticket:
399 * @handle: shishi handle as allocated by shishi_init().
400 * @apreq: AP-REQ to add ticket field to.
401 * @ticket: input ticket to copy into AP-REQ ticket field.
403 * Copy ticket into AP-REQ.
405 * Return value: Returns SHISHI_OK iff successful.
408 shishi_apreq_set_ticket (Shishi
* handle
, Shishi_asn1 apreq
,
413 unsigned char buf
[BUFSIZ
];
418 res
= shishi_asn1_read (handle
, ticket
, "tkt-vno", buf
, &buflen
);
419 if (res
!= SHISHI_OK
)
422 res
= shishi_asn1_write (handle
, apreq
, "ticket.tkt-vno", buf
, buflen
);
423 if (res
!= SHISHI_OK
)
427 res
= shishi_asn1_read (handle
, ticket
, "realm", buf
, &buflen
);
428 if (res
!= SHISHI_OK
)
431 res
= shishi_asn1_write (handle
, apreq
, "ticket.realm", buf
, buflen
);
432 if (res
!= SHISHI_OK
)
436 res
= shishi_asn1_read (handle
, ticket
, "sname.name-type", buf
, &buflen
);
437 if (res
!= SHISHI_OK
)
440 res
= shishi_asn1_write (handle
, apreq
, "ticket.sname.name-type",
442 if (res
!= SHISHI_OK
)
445 res
= shishi_asn1_number_of_elements (handle
, ticket
,
446 "sname.name-string", &n
);
447 if (res
!= SHISHI_OK
)
450 for (i
= 1; i
<= n
; i
++)
452 res
= shishi_asn1_write (handle
, apreq
,
453 "ticket.sname.name-string", "NEW", 1);
454 if (res
!= SHISHI_OK
)
458 asprintf (&format
, "sname.name-string.?%d", i
);
459 res
= shishi_asn1_read (handle
, ticket
, format
, buf
, &buflen
);
461 if (res
!= SHISHI_OK
)
464 asprintf (&format
, "ticket.sname.name-string.?%d", i
);
465 res
= shishi_asn1_write (handle
, apreq
, format
, buf
, buflen
);
467 if (res
!= SHISHI_OK
)
472 res
= shishi_asn1_read (handle
, ticket
, "enc-part.etype", buf
, &buflen
);
473 if (res
!= SHISHI_OK
)
476 res
= shishi_asn1_write (handle
, apreq
, "ticket.enc-part.etype",
478 if (res
!= SHISHI_OK
)
482 res
= shishi_asn1_read (handle
, ticket
, "enc-part.kvno", buf
, &buflen
);
483 if (res
!= SHISHI_OK
&& res
!= SHISHI_ASN1_NO_ELEMENT
)
486 if (res
== SHISHI_ASN1_NO_ELEMENT
)
487 res
= shishi_asn1_write (handle
, apreq
, "ticket.enc-part.kvno", NULL
, 0);
489 res
= shishi_asn1_write (handle
, apreq
, "ticket.enc-part.kvno",
491 if (res
!= SHISHI_OK
)
495 res
= shishi_asn1_read (handle
, ticket
, "enc-part.cipher", buf
, &buflen
);
496 if (res
!= SHISHI_OK
)
499 res
= shishi_asn1_write (handle
, apreq
, "ticket.enc-part.cipher",
501 if (res
!= SHISHI_OK
)
508 shishi_apreq_options (Shishi
* handle
, Shishi_asn1 apreq
, int *flags
)
510 return shishi_asn1_read_bitstring (handle
, apreq
, "ap-options", flags
);
514 shishi_apreq_use_session_key_p (Shishi
* handle
, Shishi_asn1 apreq
)
518 shishi_apreq_options (handle
, apreq
, &options
);
520 return options
& SHISHI_APOPTIONS_USE_SESSION_KEY
;
524 shishi_apreq_mutual_required_p (Shishi
* handle
, Shishi_asn1 apreq
)
528 shishi_apreq_options (handle
, apreq
, &options
);
530 return options
& SHISHI_APOPTIONS_MUTUAL_REQUIRED
;
534 shishi_apreq_options_set (Shishi
* handle
, Shishi_asn1 apreq
, int options
)
538 res
= shishi_asn1_write_bitstring (handle
, apreq
, "ap-options", options
);
539 if (res
!= SHISHI_OK
)
546 shishi_apreq_options_add (Shishi
* handle
, Shishi_asn1 apreq
, int option
)
551 res
= shishi_apreq_options (handle
, apreq
, &options
);
552 if (res
!= SHISHI_OK
)
557 res
= shishi_apreq_options_set (handle
, apreq
, options
);
558 if (res
!= SHISHI_OK
)
565 * shishi_kdcrep_get_enc_part_etype:
566 * @handle: shishi handle as allocated by shishi_init().
567 * @kdcrep: KDC-REP variable to get value from.
568 * @etype: output variable that holds the value.
570 * Extract KDC-REP.enc-part.etype.
572 * Return value: Returns SHISHI_OK iff successful.
575 shishi_apreq_get_authenticator_etype (Shishi
* handle
,
576 Shishi_asn1 apreq
, int32_t * etype
)
578 return shishi_asn1_read_int32 (handle
, apreq
, "authenticator.etype", etype
);
582 * shishi_apreq_get_ticket:
583 * @handle: shishi handle as allocated by shishi_init().
584 * @kdcrep: AP-REQ variable to get ticket from.
585 * @ticket: output variable to hold extracted ticket.
587 * Extract ticket from AP-REQ.
589 * Return value: Returns SHISHI_OK iff successful.
592 shishi_apreq_get_ticket (Shishi
* handle
,
593 Shishi_asn1 apreq
, Shishi_asn1
* ticket
)
595 unsigned char buf
[BUFSIZ
];
601 /* there's GOT to be an easier way to do this */
603 *ticket
= shishi_asn1_ticket (handle
);
605 return SHISHI_ASN1_ERROR
;
608 res
= shishi_asn1_read (handle
, apreq
, "ticket.tkt-vno", buf
, &buflen
);
609 if (res
!= SHISHI_OK
)
612 res
= shishi_asn1_write (handle
, *ticket
, "tkt-vno", buf
, buflen
);
613 if (res
!= SHISHI_OK
)
617 res
= shishi_asn1_read (handle
, apreq
, "ticket.realm", buf
, &buflen
);
618 if (res
!= SHISHI_OK
)
621 res
= shishi_asn1_write (handle
, *ticket
, "realm", buf
, buflen
);
622 if (res
!= SHISHI_OK
)
626 res
= shishi_asn1_read (handle
, apreq
, "ticket.sname.name-type",
628 if (res
!= SHISHI_OK
)
631 res
= shishi_asn1_write (handle
, *ticket
, "sname.name-type", buf
, buflen
);
632 if (res
!= SHISHI_OK
)
635 res
= shishi_asn1_number_of_elements (handle
, apreq
,
636 "ticket.sname.name-string", &n
);
637 if (res
!= SHISHI_OK
)
640 for (i
= 1; i
<= n
; i
++)
642 res
= shishi_asn1_write (handle
, *ticket
, "sname.name-string",
644 if (res
!= SHISHI_OK
)
648 asprintf (&format
, "ticket.sname.name-string.?%d", i
);
649 res
= shishi_asn1_read (handle
, apreq
, format
, buf
, &buflen
);
651 if (res
!= SHISHI_OK
)
654 asprintf (&format
, "sname.name-string.?%d", i
);
655 res
= shishi_asn1_write (handle
, *ticket
, format
, buf
, buflen
);
657 if (res
!= SHISHI_OK
)
662 res
= shishi_asn1_read (handle
, apreq
, "ticket.enc-part.etype",
664 if (res
!= SHISHI_OK
)
667 res
= shishi_asn1_write (handle
, *ticket
, "enc-part.etype", buf
, buflen
);
668 if (res
!= SHISHI_OK
)
672 res
= shishi_asn1_read (handle
, apreq
, "ticket.enc-part.kvno",
674 if (res
!= SHISHI_OK
&& res
!= SHISHI_ASN1_NO_ELEMENT
)
677 if (res
== SHISHI_ASN1_NO_ELEMENT
)
678 res
= shishi_asn1_write (handle
, *ticket
, "enc-part.kvno", NULL
, 0);
680 res
= shishi_asn1_write (handle
, *ticket
, "enc-part.kvno", buf
, buflen
);
681 if (res
!= SHISHI_OK
)
685 res
= shishi_asn1_read (handle
, apreq
, "ticket.enc-part.cipher",
687 if (res
!= SHISHI_OK
)
690 res
= shishi_asn1_write (handle
, *ticket
, "enc-part.cipher", buf
, buflen
);
691 if (res
!= SHISHI_OK
)
697 shishi_asn1_done (handle
, *ticket
);
702 shishi_apreq_decrypt (Shishi
* handle
,
705 int keyusage
, Shishi_asn1
* authenticator
)
715 res
= shishi_apreq_get_authenticator_etype (handle
, apreq
, &etype
);
716 if (res
!= SHISHI_OK
)
719 if (etype
!= shishi_key_type (key
))
720 return SHISHI_APREQ_BAD_KEYTYPE
;
723 res
= shishi_asn1_field (handle
, apreq
, cipher
, &cipherlen
,
724 "authenticator.cipher");
725 if (res
!= SHISHI_OK
)
728 res
= shishi_decrypt (handle
, key
, keyusage
,
729 cipher
, cipherlen
, &buf
, &buflen
);
731 if (res
!= SHISHI_OK
)
733 shishi_error_printf (handle
,
734 "decrypt fail, most likely wrong password\n");
735 return SHISHI_APREQ_DECRYPT_FAILED
;
738 /* The crypto is so 1980; no length indicator. Trim off pad bytes
739 until we can parse it. */
740 for (i
= 0; i
< 8; i
++)
742 if (VERBOSEASN1 (handle
))
743 printf ("Trying with %d pad in enckdcrep...\n", i
);
745 *authenticator
= shishi_der2asn1_authenticator (handle
, &buf
[0],
747 if (*authenticator
!= NULL
)
751 if (*authenticator
== NULL
)
753 shishi_error_printf (handle
, "Could not DER decode Authenticator. "
754 "Password probably correct (decrypt ok) though\n");
755 return SHISHI_ASN1_ERROR
;