1 /* kdcreq.c Key distribution (AS/TGS) request 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_KDCREQ_DEFAULT_PVNO "5"
25 #define SHISHI_KDCREQ_DEFAULT_PVNO_LEN 0
26 #define SHISHI_AS_REQ_DEFAULT_MSG_TYPE "10"
27 #define SHISHI_AS_REQ_DEFAULT_MSG_TYPE_LEN 0
28 #define SHISHI_TGS_REQ_DEFAULT_MSG_TYPE "12"
29 #define SHISHI_TGS_REQ_DEFAULT_MSG_TYPE_LEN 0
30 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS "\x00\x00\x00\x00"
31 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS_LEN 32
32 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE "1" /* SHISHI_NT_PRINCIPAL */
33 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE_LEN 0
34 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_TILL ""
35 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_TILL_LEN 1
38 _shishi_kdcreq (Shishi
* handle
, int as
)
42 const char *servicebuf
[3];
46 node
= shishi_asn1_asreq (handle
);
48 node
= shishi_asn1_tgsreq (handle
);
52 res
= shishi_asn1_write (handle
, node
, "pvno",
53 SHISHI_KDCREQ_DEFAULT_PVNO
,
54 SHISHI_KDCREQ_DEFAULT_PVNO_LEN
);
59 res
= shishi_asn1_write (handle
, node
, "msg-type",
60 SHISHI_AS_REQ_DEFAULT_MSG_TYPE
,
61 SHISHI_AS_REQ_DEFAULT_MSG_TYPE_LEN
);
63 res
= shishi_asn1_write (handle
, node
, "msg-type",
64 SHISHI_TGS_REQ_DEFAULT_MSG_TYPE
,
65 SHISHI_TGS_REQ_DEFAULT_MSG_TYPE_LEN
);
69 res
= shishi_asn1_write (handle
, node
, "req-body.kdc-options",
70 SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS
,
71 SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS_LEN
);
76 res
= shishi_kdcreq_set_cname (handle
, node
, SHISHI_NT_PRINCIPAL
,
77 shishi_principal_default (handle
));
79 res
= shishi_asn1_write (handle
, node
, "req-body.cname", NULL
, 0);
83 res
= shishi_kdcreq_set_realm (handle
, node
, shishi_realm_default (handle
));
87 servicebuf
[0] = "krbtgt";
88 servicebuf
[1] = shishi_realm_default (handle
);
90 res
= shishi_kdcreq_set_sname (handle
, node
,
91 SHISHI_NT_PRINCIPAL
, servicebuf
);
95 res
= shishi_asn1_write (handle
, node
, "req-body.sname.name-type",
96 SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE
,
97 SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE_LEN
);
101 res
= shishi_asn1_write (handle
, node
, "req-body.till",
102 shishi_generalize_time (handle
,
104 handle
->ticketlife
), 0);
105 if (res
!= SHISHI_OK
)
108 shishi_randomize (handle
, &noncebuf
[0], sizeof (noncebuf
));
109 res
= shishi_asn1_write (handle
, node
, "req-body.nonce", noncebuf
,
111 if (res
!= SHISHI_OK
)
114 res
= shishi_kdcreq_set_etype (handle
, node
, handle
->clientkdcetypes
,
115 handle
->nclientkdcetypes
);
116 if (res
!= SHISHI_OK
)
119 res
= shishi_asn1_write (handle
, node
, "req-body.addresses", NULL
, 0);
120 if (res
!= SHISHI_OK
)
123 res
= shishi_asn1_write (handle
, node
,
124 "req-body.enc-authorization-data", NULL
, 0);
125 if (res
!= SHISHI_OK
)
129 shishi_asn1_write (handle
, node
, "req-body.additional-tickets", NULL
, 0);
130 if (res
!= SHISHI_OK
)
136 shishi_asn1_done (handle
, node
);
142 * @handle: shishi handle as allocated by shishi_init().
144 * This function creates a new AS-REQ, populated with some default
147 * Return value: Returns the AS-REQ or NULL on failure.
150 shishi_asreq (Shishi
* handle
)
152 return _shishi_kdcreq (handle
, 1);
157 * @handle: shishi handle as allocated by shishi_init().
159 * This function creates a new TGS-REQ, populated with some default
162 * Return value: Returns the TGS-REQ or NULL on failure.
165 shishi_tgsreq (Shishi
* handle
)
167 return _shishi_kdcreq (handle
, 0);
171 * shishi_kdcreq_print:
172 * @handle: shishi handle as allocated by shishi_init().
173 * @fh: file handle open for writing.
174 * @kdcreq: KDC-REQ to print.
176 * Print ASCII armored DER encoding of KDC-REQ to file.
178 * Return value: Returns SHISHI_OK iff successful.
181 shishi_kdcreq_print (Shishi
* handle
, FILE * fh
, Shishi_asn1 kdcreq
)
183 return _shishi_print_armored_data (handle
, fh
, kdcreq
, "KDC-REQ", NULL
);
187 * shishi_kdcreq_save:
188 * @handle: shishi handle as allocated by shishi_init().
189 * @fh: file handle open for writing.
190 * @kdcreq: KDC-REQ to save.
192 * Print DER encoding of KDC-REQ to file.
194 * Return value: Returns SHISHI_OK iff successful.
197 shishi_kdcreq_save (Shishi
* handle
, FILE * fh
, Shishi_asn1 kdcreq
)
199 return _shishi_save_data (handle
, fh
, kdcreq
, "KDC-REQ");
203 * shishi_kdcreq_to_file:
204 * @handle: shishi handle as allocated by shishi_init().
205 * @kdcreq: KDC-REQ to save.
206 * @filetype: input variable specifying type of file to be written,
207 * see Shishi_filetype.
208 * @filename: input variable with filename to write to.
210 * Write KDC-REQ to file in specified TYPE. The file will be truncated
213 * Return value: Returns SHISHI_OK iff successful.
216 shishi_kdcreq_to_file (Shishi
* handle
, Shishi_asn1 kdcreq
,
217 int filetype
, char *filename
)
222 if (VERBOSE (handle
))
223 printf (_("Writing KDC-REQ to %s...\n"), filename
);
225 fh
= fopen (filename
, "w");
227 return SHISHI_FOPEN_ERROR
;
229 if (VERBOSE (handle
))
230 printf (_("Writing KDC-REQ in %s format...\n"),
231 filetype
== SHISHI_FILETYPE_TEXT
? "TEXT" : "DER");
233 if (filetype
== SHISHI_FILETYPE_TEXT
)
234 res
= shishi_kdcreq_print (handle
, fh
, kdcreq
);
236 res
= shishi_kdcreq_save (handle
, fh
, kdcreq
);
237 if (res
!= SHISHI_OK
)
242 return SHISHI_FCLOSE_ERROR
;
244 if (VERBOSE (handle
))
245 printf (_("Writing KDC-REQ to %s...done\n"), filename
);
251 * shishi_kdcreq_parse:
252 * @handle: shishi handle as allocated by shishi_init().
253 * @fh: file handle open for reading.
254 * @kdcreq: output variable with newly allocated KDC-REQ.
256 * Read ASCII armored DER encoded KDC-REQ from file and populate given
259 * Return value: Returns SHISHI_OK iff successful.
262 shishi_kdcreq_parse (Shishi
* handle
, FILE * fh
, Shishi_asn1
* kdcreq
)
264 return _shishi_kdcreq_input (handle
, fh
, kdcreq
, 0);
268 * shishi_kdcreq_read:
269 * @handle: shishi handle as allocated by shishi_init().
270 * @fh: file handle open for reading.
271 * @kdcreq: output variable with newly allocated KDC-REQ.
273 * Read DER encoded KDC-REQ from file and populate given variable.
275 * Return value: Returns SHISHI_OK iff successful.
278 shishi_kdcreq_read (Shishi
* handle
, FILE * fh
, Shishi_asn1
* kdcreq
)
280 return _shishi_kdcreq_input (handle
, fh
, kdcreq
, 1);
284 * shishi_kdcreq_from_file:
285 * @handle: shishi handle as allocated by shishi_init().
286 * @kdcreq: output variable with newly allocated KDC-REQ.
287 * @filetype: input variable specifying type of file to be read,
288 * see Shishi_filetype.
289 * @filename: input variable with filename to read from.
291 * Read KDC-REQ from file in specified TYPE.
293 * Return value: Returns SHISHI_OK iff successful.
296 shishi_kdcreq_from_file (Shishi
* handle
, Shishi_asn1
* kdcreq
,
297 int filetype
, char *filename
)
302 if (VERBOSE (handle
))
303 printf (_("Reading KDC-REQ from %s...\n"), filename
);
305 fh
= fopen (filename
, "r");
307 return SHISHI_FOPEN_ERROR
;
309 if (VERBOSE (handle
))
310 printf (_("Reading KDC-REQ in %s format...\n"),
311 filetype
== SHISHI_FILETYPE_TEXT
? "TEXT" : "DER");
313 if (filetype
== SHISHI_FILETYPE_TEXT
)
314 res
= shishi_kdcreq_parse (handle
, fh
, kdcreq
);
316 res
= shishi_kdcreq_read (handle
, fh
, kdcreq
);
317 if (res
!= SHISHI_OK
)
322 return SHISHI_FCLOSE_ERROR
;
324 if (VERBOSE (handle
))
325 printf (_("Reading KDC-REQ from %s...done\n"), filename
);
331 shishi_kdcreq_nonce (Shishi
* handle
, Shishi_asn1 kdcreq
, uint32_t * nonce
)
335 res
= shishi_asn1_read_uint32 (handle
, kdcreq
, "req-body.nonce", nonce
);
336 if (res
!= SHISHI_OK
)
343 * shishi_kdcreq_set_cname:
344 * @handle: shishi handle as allocated by shishi_init().
345 * @kdcreq: KDC-REQ variable to set client name field in.
346 * @name_type: type of principial, see Shishi_name_type, usually
348 * @principal: input array with principal name.
350 * Set the client name field in the KDC-REQ.
352 * Return value: Returns SHISHI_OK iff successful.
355 shishi_kdcreq_set_cname (Shishi
* handle
,
357 Shishi_name_type name_type
, const char *principal
)
361 res
= shishi_principal_set (handle
, kdcreq
, "req-body.cname", principal
);
362 if (res
!= SHISHI_OK
)
369 shishi_kdcreq_cname_get (Shishi
* handle
,
370 Shishi_asn1 kdcreq
, char *cname
, size_t * cnamelen
)
372 return shishi_principal_name_get (handle
, kdcreq
,
373 "req-body.cname", cname
, cnamelen
);
377 shishi_asreq_cnamerealm_get (Shishi
* handle
,
379 char *cnamerealm
, size_t * cnamerealmlen
)
381 return shishi_principal_name_realm_get (handle
, asreq
,
382 "req-body.cname", asreq
,
384 cnamerealm
, cnamerealmlen
);
388 shishi_kdcreq_realm_get (Shishi
* handle
, Shishi_asn1 kdcreq
,
389 char *realm
, int *realmlen
)
391 return shishi_asn1_read_optional (handle
, kdcreq
, "req-body.realm",
396 * shishi_kdcreq_set_realm:
397 * @handle: shishi handle as allocated by shishi_init().
398 * @kdcreq: KDC-REQ variable to set realm field in.
399 * @realm: input array with name of realm.
401 * Set the realm field in the KDC-REQ.
403 * Return value: Returns SHISHI_OK iff successful.
406 shishi_kdcreq_set_realm (Shishi
* handle
, Shishi_asn1 kdcreq
,
411 res
= shishi_asn1_write (handle
, kdcreq
, "req-body.realm", realm
, 0);
412 if (res
!= SHISHI_OK
)
419 shishi_kdcreq_sname_get (Shishi
* handle
,
420 Shishi_asn1 kdcreq
, char *sname
, size_t * snamelen
)
422 return shishi_principal_name_get (handle
, kdcreq
,
423 "req-body.sname", sname
, snamelen
);
427 shishi_kdcreq_snamerealm_get (Shishi
* handle
,
429 char *snamerealm
, size_t * snamerealmlen
)
431 return shishi_principal_name_realm_get (handle
, kdcreq
,
432 "req-body.sname", kdcreq
,
434 snamerealm
, snamerealmlen
);
438 * shishi_kdcreq_set_sname:
439 * @handle: shishi handle as allocated by shishi_init().
440 * @kdcreq: KDC-REQ variable to set server name field in.
441 * @name_type: type of principial, see Shishi_name_type, usually
443 * @sname: input array with principal name.
445 * Set the server name field in the KDC-REQ.
447 * Return value: Returns SHISHI_OK iff successful.
450 shishi_kdcreq_set_sname (Shishi
* handle
,
452 Shishi_name_type name_type
, const char *sname
[])
456 res
= shishi_principal_name_set (handle
, kdcreq
, "req-body.sname",
458 if (res
!= SHISHI_OK
)
465 shishi_kdcreq_set_server (Shishi
* handle
, Shishi_asn1 req
,
470 res
= shishi_principal_set (handle
, req
, "req-body.sname", server
);
471 if (res
!= SHISHI_OK
)
478 shishi_kdcreq_set_realmserver (Shishi
* handle
,
479 Shishi_asn1 req
, char *realm
, char *server
)
483 res
= shishi_kdcreq_set_realm (handle
, req
, realm
);
484 if (res
!= SHISHI_OK
)
487 res
= shishi_kdcreq_set_server (handle
, req
, server
);
488 if (res
!= SHISHI_OK
)
495 * shishi_kdcreq_etype:
496 * @handle: shishi handle as allocated by shishi_init().
497 * @kdcreq: KDC-REQ variable to get etype field from.
498 * @etype: output encryption type.
499 * @netype: element number to return.
501 * Return the netype:th encryption type from KDC-REQ. The first etype
504 * Return value: Returns SHISHI_OK iff etype successful set.
507 shishi_kdcreq_etype (Shishi
* handle
,
508 Shishi_asn1 kdcreq
, int32_t * etype
, int netype
)
513 asprintf (&buf
, "req-body.etype.?%d", netype
);
514 res
= shishi_asn1_read_int32 (handle
, kdcreq
, buf
, etype
);
515 if (res
!= SHISHI_OK
)
522 * shishi_kdcreq_set_etype:
523 * @handle: shishi handle as allocated by shishi_init().
524 * @kdcreq: KDC-REQ variable to set etype field in.
525 * @etype: input array with encryption types.
526 * @netype: number of elements in input array with encryption types.
528 * Set the list of supported or wanted encryption types in the
529 * request. The list should be sorted in priority order.
531 * Return value: Returns SHISHI_OK iff successful.
534 shishi_kdcreq_set_etype (Shishi
* handle
,
535 Shishi_asn1 kdcreq
, int32_t * etype
, int netype
)
541 res
= shishi_asn1_write (handle
, kdcreq
, "req-body.etype", NULL
, 0);
542 if (res
!= SHISHI_OK
)
545 for (i
= 1; i
<= netype
; i
++)
547 res
= shishi_asn1_write (handle
, kdcreq
, "req-body.etype", "NEW", 1);
548 if (res
!= SHISHI_OK
)
551 asprintf (&buf
, "req-body.etype.?%d", i
);
552 res
= shishi_asn1_write_int32 (handle
, kdcreq
, buf
, etype
[i
- 1]);
554 if (res
!= SHISHI_OK
)
562 shishi_kdcreq_options (Shishi
* handle
, Shishi_asn1 kdcreq
, int *flags
)
564 return shishi_asn1_read_bitstring (handle
, kdcreq
,
565 "req-body.kdc-options", flags
);
569 shishi_kdcreq_renewable_p (Shishi
* handle
, Shishi_asn1 kdcreq
)
573 shishi_kdcreq_options (handle
, kdcreq
, &options
);
575 return options
& SHISHI_KDCOPTIONS_RENEWABLE
;
579 shishi_kdcreq_options_set (Shishi
* handle
, Shishi_asn1 kdcreq
, int options
)
583 res
= shishi_asn1_write_bitstring (handle
, kdcreq
,
584 "req-body.kdc-options", options
);
585 if (res
!= SHISHI_OK
)
592 shishi_kdcreq_options_add (Shishi
* handle
, Shishi_asn1 kdcreq
, int option
)
597 res
= shishi_kdcreq_options (handle
, kdcreq
, &options
);
598 if (res
!= SHISHI_OK
)
603 res
= shishi_kdcreq_options_set (handle
, kdcreq
, options
);
604 if (res
!= SHISHI_OK
)
611 * shishi_kdcreq_clear_padata:
612 * @handle: shishi handle as allocated by shishi_init().
613 * @kdcreq: KDC-REQ to remove PA-DATA from.
615 * Remove the padata field from KDC-REQ.
617 * Return value: Returns SHISHI_OK iff successful.
620 shishi_kdcreq_clear_padata (Shishi
* handle
, Shishi_asn1 kdcreq
)
624 res
= shishi_asn1_write (handle
, kdcreq
, "padata", NULL
, 0);
625 if (res
!= SHISHI_OK
)
632 * shishi_kdcreq_get_padata:
633 * @handle: shishi handle as allocated by shishi_init().
634 * @kdcreq: KDC-REQ to get PA-DATA from.
635 * @padatatype: type of PA-DATA, see Shishi_padata_type.
636 * @out: output array with newly allocated PA-DATA value.
637 * @outlen: size of output array with PA-DATA value.
639 * Get pre authentication data (PA-DATA) from KDC-REQ. Pre
640 * authentication data is used to pass various information to KDC,
641 * such as in case of a SHISHI_PA_TGS_REQ padatatype the AP-REQ that
642 * authenticates the user to get the ticket.
644 * Return value: Returns SHISHI_OK iff successful.
647 shishi_kdcreq_get_padata (Shishi
* handle
,
649 Shishi_padata_type padatatype
,
650 char **out
, size_t *outlen
)
656 res
= shishi_asn1_number_of_elements (handle
, kdcreq
, "padata", &n
);
657 if (res
!= SHISHI_OK
)
663 for (i
= 1; i
<= n
; i
++)
667 asprintf (&format
, "padata.?%d.padata-type", i
);
668 res
= shishi_asn1_read_int32 (handle
, kdcreq
, format
, &patype
);
670 if (res
!= SHISHI_OK
)
673 if (patype
== (int32_t)padatatype
)
675 asprintf (&format
, "padata.?%d.padata-value", i
);
676 res
= shishi_asn1_read2 (handle
, kdcreq
, format
, out
, outlen
);
678 if (res
!= SHISHI_OK
)
688 * shishi_kdcreq_get_padata_tgs:
689 * @handle: shishi handle as allocated by shishi_init().
690 * @kdcreq: KDC-REQ to get PA-TGS-REQ from.
691 * @apreq: Output variable with newly allocated AP-REQ.
693 * Extract TGS pre-authentication data from KDC-REQ. The data is an
694 * AP-REQ that authenticates the request. This function call
695 * shishi_kdcreq_get_padata() with a SHISHI_PA_TGS_REQ padatatype and
696 * DER decode the result (if any).
698 * Return value: Returns SHISHI_OK iff successful.
701 shishi_kdcreq_get_padata_tgs (Shishi
* handle
,
709 if (VERBOSE (handle
))
710 printf ("Extracting AP-REQ from KDC-REQ...\n");
712 rc
= shishi_kdcreq_get_padata (handle
, kdcreq
, SHISHI_PA_TGS_REQ
,
717 *apreq
= shishi_der2asn1_apreq (handle
, der
, derlen
);
719 return SHISHI_ASN1_ERROR
;
721 if (VERBOSEASN1 (handle
))
722 shishi_apreq_print (handle
, stdout
, *apreq
);
728 * shishi_kdcreq_add_padata:
729 * @handle: shishi handle as allocated by shishi_init().
730 * @kdcreq: KDC-REQ to add PA-DATA to.
731 * @padatatype: type of PA-DATA, see Shishi_padata_type.
732 * @data: input array with PA-DATA value.
733 * @datalen: size of input array with PA-DATA value.
735 * Add new pre authentication data (PA-DATA) to KDC-REQ. This is used
736 * to pass various information to KDC, such as in case of a
737 * SHISHI_PA_TGS_REQ padatatype the AP-REQ that authenticates the user
738 * to get the ticket. (But also see shishi_kdcreq_add_padata_tgs()
739 * which takes an AP-REQ directly.)
741 * Return value: Returns SHISHI_OK iff successful.
744 shishi_kdcreq_add_padata (Shishi
* handle
,
746 int padatatype
, char *data
, int datalen
)
752 res
= shishi_asn1_write (handle
, kdcreq
, "padata", "NEW", 1);
753 if (res
!= SHISHI_OK
)
756 res
= shishi_asn1_number_of_elements (handle
, kdcreq
, "padata", &i
);
757 if (res
!= SHISHI_OK
)
760 asprintf (&format
, "padata.?%d.padata-value", i
);
761 res
= shishi_asn1_write (handle
, kdcreq
, format
, data
, datalen
);
763 if (res
!= SHISHI_OK
)
766 asprintf (&format
, "padata.?%d.padata-type", i
);
767 res
= shishi_asn1_write_uint32 (handle
, kdcreq
, format
, padatatype
);
769 if (res
!= SHISHI_OK
)
776 * shishi_kdcreq_add_padata_tgs:
777 * @handle: shishi handle as allocated by shishi_init().
778 * @kdcreq: KDC-REQ to add PA-DATA to.
779 * @apreq: AP-REQ to add as PA-DATA.
781 * Add TGS pre-authentication data to KDC-REQ. The data is an AP-REQ
782 * that authenticates the request. This functions simply DER encodes
783 * the AP-REQ and calls shishi_kdcreq_add_padata() with a
784 * SHISHI_PA_TGS_REQ padatatype.
786 * Return value: Returns SHISHI_OK iff successful.
789 shishi_kdcreq_add_padata_tgs (Shishi
* handle
,
790 Shishi_asn1 kdcreq
, Shishi_asn1 apreq
)
796 res
= shishi_new_a2d (handle
, apreq
, &data
, &datalen
);
797 if (res
!= SHISHI_OK
)
799 shishi_error_printf (handle
, "Could not DER encode AP-REQ: %s\n",
800 shishi_strerror (res
));
804 res
= shishi_kdcreq_add_padata (handle
, kdcreq
,
805 SHISHI_PA_TGS_REQ
, data
, datalen
);
807 if (res
!= SHISHI_OK
)
814 shishi_kdcreq_build (Shishi
* handle
, Shishi_asn1 kdcreq
)
818 if (VERBOSE (handle
))
819 printf ("Building KDC-REQ...\n");
821 if (shishi_asn1_read_empty_p (handle
, kdcreq
, "req-body.rtime"))
823 res
= shishi_asn1_write (handle
, kdcreq
, "req-body.rtime", NULL
, 0);
824 if (res
!= SHISHI_OK
)
826 shishi_error_printf (handle
, "Could not write rtime\n");
831 if (shishi_asn1_read_empty_p (handle
, kdcreq
, "req-body.from"))
833 res
= shishi_asn1_write (handle
, kdcreq
, "req-body.from", NULL
, 0);
834 if (res
!= SHISHI_OK
)
836 shishi_error_printf (handle
, "Could not write from\n");