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 int etype
, char *buf
, int buflen
)
338 res
= shishi_asn1_write (handle
, apreq
, "authenticator.cipher",
340 if (res
!= SHISHI_OK
)
343 sprintf (format
, "%d", etype
);
344 res
= shishi_asn1_write (handle
, apreq
, "authenticator.etype",
346 if (res
!= SHISHI_OK
)
353 * shishi_apreq_add_authenticator:
354 * @handle: shishi handle as allocated by shishi_init().
355 * @apreq: AP-REQ to add authenticator field to.
356 * @enckdcreppart: ticket information where the key is taken from.
357 * @authenticator: authenticator as allocated by shishi_authenticator().
359 * Encrypts DER encoded authenticator using key from ticket and store
362 * Return value: Returns SHISHI_OK iff successful.
365 shishi_apreq_add_authenticator (Shishi
* handle
,
368 int keyusage
, Shishi_asn1 authenticator
)
376 res
= shishi_new_a2d (handle
, authenticator
, &der
, &derlen
);
377 if (res
!= SHISHI_OK
)
379 shishi_error_printf (handle
, "Could not DER encode authenticator: %s\n",
380 shishi_strerror (res
));
385 res
= shishi_encrypt (handle
, key
, keyusage
, der
, derlen
, buf
, &buflen
);
387 if (res
!= SHISHI_OK
)
389 shishi_error_printf (handle
, "des_encrypt fail\n");
393 res
= shishi_apreq_set_authenticator (handle
, apreq
, shishi_key_type (key
),
400 * shishi_apreq_set_ticket:
401 * @handle: shishi handle as allocated by shishi_init().
402 * @apreq: AP-REQ to add ticket field to.
403 * @ticket: input ticket to copy into AP-REQ ticket field.
405 * Copy ticket into AP-REQ.
407 * Return value: Returns SHISHI_OK iff successful.
410 shishi_apreq_set_ticket (Shishi
* handle
, Shishi_asn1 apreq
,
414 unsigned char format
[BUFSIZ
];
415 unsigned char buf
[BUFSIZ
];
420 res
= shishi_asn1_read (handle
, ticket
, "tkt-vno", buf
, &buflen
);
421 if (res
!= SHISHI_OK
)
424 res
= shishi_asn1_write (handle
, apreq
, "ticket.tkt-vno",
426 if (res
!= SHISHI_OK
)
430 res
= shishi_asn1_read (handle
, ticket
, "realm", buf
, &buflen
);
431 if (res
!= SHISHI_OK
)
434 res
= shishi_asn1_write (handle
, apreq
, "ticket.realm", buf
, buflen
);
435 if (res
!= SHISHI_OK
)
439 res
= shishi_asn1_read (handle
, ticket
, "sname.name-type",
441 if (res
!= SHISHI_OK
)
444 res
= shishi_asn1_write (handle
, apreq
, "ticket.sname.name-type",
446 if (res
!= SHISHI_OK
)
449 res
= shishi_asn1_number_of_elements (handle
, ticket
,
450 "sname.name-string", &n
);
451 if (res
!= SHISHI_OK
)
454 for (i
= 1; i
<= n
; i
++)
456 res
= shishi_asn1_write (handle
, apreq
,
457 "ticket.sname.name-string", "NEW", 1);
458 if (res
!= SHISHI_OK
)
461 sprintf (format
, "sname.name-string.?%d", i
);
463 res
= shishi_asn1_read (handle
, ticket
, format
, buf
, &buflen
);
464 if (res
!= SHISHI_OK
)
467 sprintf (format
, "ticket.sname.name-string.?%d", i
);
468 res
= shishi_asn1_write (handle
, apreq
, format
, buf
, buflen
);
469 if (res
!= SHISHI_OK
)
474 res
= shishi_asn1_read (handle
, ticket
, "enc-part.etype",
476 if (res
!= SHISHI_OK
)
479 res
= shishi_asn1_write (handle
, apreq
, "ticket.enc-part.etype",
481 if (res
!= SHISHI_OK
)
485 res
= shishi_asn1_read (handle
, ticket
, "enc-part.kvno",
487 if (res
!= SHISHI_OK
&& res
!= SHISHI_ASN1_NO_ELEMENT
)
490 if (res
== SHISHI_ASN1_NO_ELEMENT
)
491 res
= shishi_asn1_write (handle
, apreq
, "ticket.enc-part.kvno",
494 res
= shishi_asn1_write (handle
, apreq
, "ticket.enc-part.kvno",
496 if (res
!= SHISHI_OK
)
500 res
= shishi_asn1_read (handle
, ticket
, "enc-part.cipher",
502 if (res
!= SHISHI_OK
)
505 res
= shishi_asn1_write (handle
, apreq
, "ticket.enc-part.cipher",
507 if (res
!= SHISHI_OK
)
514 shishi_apreq_options (Shishi
* handle
, Shishi_asn1 apreq
, int *flags
)
516 int len
= sizeof (*flags
);
519 res
= shishi_asn1_field (handle
, apreq
, (char *) flags
, &len
,
525 shishi_apreq_use_session_key_p (Shishi
* handle
, Shishi_asn1 apreq
)
529 shishi_apreq_options (handle
, apreq
, &options
);
531 return options
& SHISHI_APOPTIONS_USE_SESSION_KEY
;
535 shishi_apreq_mutual_required_p (Shishi
* handle
, Shishi_asn1 apreq
)
539 shishi_apreq_options (handle
, apreq
, &options
);
541 return options
& SHISHI_APOPTIONS_MUTUAL_REQUIRED
;
545 shishi_apreq_options_set (Shishi
* handle
, Shishi_asn1 apreq
, int options
)
549 res
= shishi_asn1_write (handle
, apreq
, "ap-options",
551 SHISHI_APREQ_DEFAULT_AP_OPTIONS_LEN
);
552 if (res
!= SHISHI_OK
)
559 shishi_apreq_options_add (Shishi
* handle
, Shishi_asn1 apreq
, int option
)
564 res
= shishi_apreq_options (handle
, apreq
, &options
);
565 if (res
!= SHISHI_OK
)
570 res
= shishi_apreq_options_set (handle
, apreq
, options
);
571 if (res
!= SHISHI_OK
)
578 * shishi_kdcrep_get_enc_part_etype:
579 * @handle: shishi handle as allocated by shishi_init().
580 * @kdcrep: KDC-REP variable to get value from.
581 * @etype: output variable that holds the value.
583 * Extract KDC-REP.enc-part.etype.
585 * Return value: Returns SHISHI_OK iff successful.
588 shishi_apreq_get_authenticator_etype (Shishi
* handle
,
589 Shishi_asn1 apreq
, int *etype
)
591 return shishi_asn1_integer_field (handle
, apreq
, etype
,
592 "authenticator.etype");
596 * shishi_apreq_get_ticket:
597 * @handle: shishi handle as allocated by shishi_init().
598 * @kdcrep: AP-REQ variable to get ticket from.
599 * @ticket: output variable to hold extracted ticket.
601 * Extract ticket from AP-REQ.
603 * Return value: Returns SHISHI_OK iff successful.
606 shishi_apreq_get_ticket (Shishi
* handle
,
607 Shishi_asn1 apreq
, Shishi_asn1
* ticket
)
609 unsigned char buf
[BUFSIZ
];
610 unsigned char format
[BUFSIZ
];
615 /* there's GOT to be an easier way to do this */
617 *ticket
= shishi_asn1_ticket (handle
);
619 return SHISHI_ASN1_ERROR
;
622 res
= shishi_asn1_read (handle
, apreq
, "ticket.tkt-vno",
624 if (res
!= SHISHI_OK
)
627 res
= shishi_asn1_write (handle
, *ticket
, "tkt-vno", buf
, buflen
);
628 if (res
!= SHISHI_OK
)
632 res
= shishi_asn1_read (handle
, apreq
, "ticket.realm", buf
, &buflen
);
633 if (res
!= SHISHI_OK
)
636 res
= shishi_asn1_write (handle
, *ticket
, "realm", buf
, buflen
);
637 if (res
!= SHISHI_OK
)
641 res
= shishi_asn1_read (handle
, apreq
, "ticket.sname.name-type",
643 if (res
!= SHISHI_OK
)
646 res
= shishi_asn1_write (handle
, *ticket
, "sname.name-type",
648 if (res
!= SHISHI_OK
)
651 res
= shishi_asn1_number_of_elements (handle
, apreq
,
652 "ticket.sname.name-string",
654 if (res
!= SHISHI_OK
)
657 for (i
= 1; i
<= n
; i
++)
659 res
= shishi_asn1_write (handle
, *ticket
, "sname.name-string",
661 if (res
!= SHISHI_OK
)
664 sprintf (format
, "ticket.sname.name-string.?%d", i
);
666 res
= shishi_asn1_read (handle
, apreq
, format
, buf
, &buflen
);
667 if (res
!= SHISHI_OK
)
670 sprintf (format
, "sname.name-string.?%d", i
);
671 res
= shishi_asn1_write (handle
, *ticket
, format
, buf
, buflen
);
672 if (res
!= SHISHI_OK
)
677 res
= shishi_asn1_read (handle
, apreq
, "ticket.enc-part.etype",
679 if (res
!= SHISHI_OK
)
682 res
= shishi_asn1_write (handle
, *ticket
, "enc-part.etype",
684 if (res
!= SHISHI_OK
)
688 res
= shishi_asn1_read (handle
, apreq
, "ticket.enc-part.kvno",
690 if (res
!= SHISHI_OK
&& res
!= SHISHI_ASN1_NO_ELEMENT
)
693 if (res
== SHISHI_ASN1_NO_ELEMENT
)
694 res
= shishi_asn1_write (handle
, *ticket
, "enc-part.kvno",
697 res
= shishi_asn1_write (handle
, *ticket
, "enc-part.kvno",
699 if (res
!= SHISHI_OK
)
703 res
= shishi_asn1_read (handle
, apreq
, "ticket.enc-part.cipher",
705 if (res
!= SHISHI_OK
)
708 res
= shishi_asn1_write (handle
, *ticket
, "enc-part.cipher",
710 if (res
!= SHISHI_OK
)
716 shishi_asn1_done (handle
, *ticket
);
721 shishi_apreq_decrypt (Shishi
* handle
,
724 int keyusage
, Shishi_asn1
* authenticator
)
728 size_t buflen
= BUFSIZ
;
734 res
= shishi_apreq_get_authenticator_etype (handle
, apreq
, &etype
);
735 if (res
!= SHISHI_OK
)
738 if (etype
!= shishi_key_type (key
))
739 return SHISHI_APREQ_BAD_KEYTYPE
;
742 res
= shishi_asn1_field (handle
, apreq
, cipher
, &cipherlen
,
743 "authenticator.cipher");
744 if (res
!= SHISHI_OK
)
747 res
= shishi_decrypt (handle
, key
, keyusage
,
748 cipher
, cipherlen
, buf
, &buflen
);
750 if (res
!= SHISHI_OK
)
752 if (VERBOSE (handle
))
753 printf ("decrypt failed: %s\n", shishi_strerror_details (handle
));
754 shishi_error_printf (handle
,
755 "decrypt fail, most likely wrong password\n");
756 return SHISHI_APREQ_DECRYPT_FAILED
;
759 /* The crypto is so 1980; no length indicator. Trim off pad bytes
760 until we can parse it. */
761 for (i
= 0; i
< 8; i
++)
763 if (VERBOSEASN1 (handle
))
764 printf ("Trying with %d pad in enckdcrep...\n", i
);
766 *authenticator
= shishi_der2asn1_authenticator (handle
, &buf
[0],
768 if (*authenticator
!= NULL
)
772 if (*authenticator
== NULL
)
774 shishi_error_printf (handle
, "Could not DER decode Authenticator. "
775 "Password probably correct (decrypt ok) though\n");
776 return SHISHI_ASN1_ERROR
;