1 /* authenticator.c functions for authenticators
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
25 * shishi_authenticator:
26 * @handle: shishi handle as allocated by shishi_init().
28 * This function creates a new Authenticator, populated with some
29 * default values. It uses the current time as returned by the system
30 * for the ctime and cusec fields.
32 * Return value: Returns the authenticator or NULL on
36 shishi_authenticator (Shishi
* handle
)
39 Shishi_asn1 node
= NULL
;
43 node
= shishi_asn1_authenticator (handle
);
47 res
= shishi_asn1_write (handle
, node
, "authenticator-vno", "5", 0);
51 res
= shishi_authenticator_set_crealm (handle
, node
,
52 shishi_realm_default (handle
));
56 res
= shishi_authenticator_client_set (handle
, node
,
57 shishi_principal_default (handle
));
61 gettimeofday (&tv
, &tz
);
62 res
= shishi_authenticator_cusec_set (handle
, node
, tv
.tv_usec
% 1000000);
66 res
= shishi_asn1_write (handle
, node
, "ctime",
67 shishi_generalize_time (handle
, time (NULL
)), 0);
71 res
= shishi_asn1_write (handle
, node
, "seq-number", NULL
, 0);
78 shishi_asn1_done (handle
, node
);
83 * shishi_authenticator_subkey:
84 * @handle: shishi handle as allocated by shishi_init().
86 * This function creates a new Authenticator, populated with some
87 * default values. It uses the current time as returned by the system
88 * for the ctime and cusec fields. It adds a random subkey.
90 * Return value: Returns the authenticator or NULL on
94 shishi_authenticator_subkey (Shishi
* handle
)
99 node
= shishi_authenticator (handle
);
103 res
= shishi_authenticator_add_random_subkey (handle
, node
);
104 if (res
!= SHISHI_OK
)
111 * shishi_authenticator_print:
112 * @handle: shishi handle as allocated by shishi_init().
113 * @fh: file handle open for writing.
114 * @authenticator: authenticator as allocated by shishi_authenticator().
116 * Print ASCII armored DER encoding of authenticator to file.
118 * Return value: Returns SHISHI_OK iff successful.
121 shishi_authenticator_print (Shishi
* handle
,
122 FILE * fh
, Shishi_asn1 authenticator
)
124 return _shishi_print_armored_data (handle
, fh
, authenticator
,
125 "Authenticator", NULL
);
129 * shishi_authenticator_save:
130 * @handle: shishi handle as allocated by shishi_init().
131 * @fh: file handle open for writing.
132 * @authenticator: authenticator as allocated by shishi_authenticator().
134 * Save DER encoding of authenticator to file.
136 * Return value: Returns SHISHI_OK iff successful.
139 shishi_authenticator_save (Shishi
* handle
,
140 FILE * fh
, Shishi_asn1 authenticator
)
142 return _shishi_save_data (handle
, fh
, authenticator
, "Authenticator");
146 * shishi_authenticator_to_file:
147 * @handle: shishi handle as allocated by shishi_init().
148 * @authenticator: Authenticator to save.
149 * @filetype: input variable specifying type of file to be written,
150 * see Shishi_filetype.
151 * @filename: input variable with filename to write to.
153 * Write Authenticator to file in specified TYPE. The file will be
154 * truncated if it exists.
156 * Return value: Returns SHISHI_OK iff successful.
159 shishi_authenticator_to_file (Shishi
* handle
, Shishi_asn1 authenticator
,
160 int filetype
, char *filename
)
165 if (VERBOSE (handle
))
166 printf (_("Writing Authenticator to %s...\n"), filename
);
168 fh
= fopen (filename
, "w");
170 return SHISHI_FOPEN_ERROR
;
172 if (VERBOSE (handle
))
173 printf (_("Writing Authenticator in %s format...\n"),
174 filetype
== SHISHI_FILETYPE_TEXT
? "TEXT" : "DER");
176 if (filetype
== SHISHI_FILETYPE_TEXT
)
177 res
= shishi_authenticator_print (handle
, fh
, authenticator
);
179 res
= shishi_authenticator_save (handle
, fh
, authenticator
);
180 if (res
!= SHISHI_OK
)
185 return SHISHI_FCLOSE_ERROR
;
187 if (VERBOSE (handle
))
188 printf (_("Writing Authenticator to %s...done\n"), filename
);
194 * shishi_authenticator_parse:
195 * @handle: shishi handle as allocated by shishi_init().
196 * @fh: file handle open for reading.
197 * @authenticator: output variable with newly allocated authenticator.
199 * Read ASCII armored DER encoded authenticator from file and populate
200 * given authenticator variable.
202 * Return value: Returns SHISHI_OK iff successful.
205 shishi_authenticator_parse (Shishi
* handle
,
206 FILE * fh
, Shishi_asn1
* authenticator
)
208 return _shishi_authenticator_input (handle
, fh
, authenticator
, 0);
212 * shishi_authenticator_read:
213 * @handle: shishi handle as allocated by shishi_init().
214 * @fh: file handle open for reading.
215 * @authenticator: output variable with newly allocated authenticator.
217 * Read DER encoded authenticator from file and populate given
218 * authenticator variable.
220 * Return value: Returns SHISHI_OK iff successful.
223 shishi_authenticator_read (Shishi
* handle
,
224 FILE * fh
, Shishi_asn1
* authenticator
)
226 return _shishi_authenticator_input (handle
, fh
, authenticator
, 1);
230 * shishi_authenticator_from_file:
231 * @handle: shishi handle as allocated by shishi_init().
232 * @authenticator: output variable with newly allocated Authenticator.
233 * @filetype: input variable specifying type of file to be read,
234 * see Shishi_filetype.
235 * @filename: input variable with filename to read from.
237 * Read Authenticator from file in specified TYPE.
239 * Return value: Returns SHISHI_OK iff successful.
242 shishi_authenticator_from_file (Shishi
* handle
, Shishi_asn1
* authenticator
,
243 int filetype
, char *filename
)
248 if (VERBOSE (handle
))
249 printf (_("Reading Authenticator from %s...\n"), filename
);
251 fh
= fopen (filename
, "r");
253 return SHISHI_FOPEN_ERROR
;
255 if (VERBOSE (handle
))
256 printf (_("Reading Authenticator in %s format...\n"),
257 filetype
== SHISHI_FILETYPE_TEXT
? "TEXT" : "DER");
259 if (filetype
== SHISHI_FILETYPE_TEXT
)
260 res
= shishi_authenticator_parse (handle
, fh
, authenticator
);
262 res
= shishi_authenticator_read (handle
, fh
, authenticator
);
263 if (res
!= SHISHI_OK
)
268 return SHISHI_FCLOSE_ERROR
;
270 if (VERBOSE (handle
))
271 printf (_("Reading Authenticator from %s...done\n"), filename
);
277 * shishi_authenticator_set_crealm:
278 * @handle: shishi handle as allocated by shishi_init().
279 * @authenticator: authenticator as allocated by shishi_authenticator().
280 * @crealm: input array with realm.
282 * Set realm field in authenticator to specified value.
284 * Return value: Returns SHISHI_OK iff successful.
287 shishi_authenticator_set_crealm (Shishi
* handle
,
288 Shishi_asn1 authenticator
,
293 res
= shishi_asn1_write (handle
, authenticator
, "crealm", crealm
, 0);
294 if (res
!= SHISHI_OK
)
301 * shishi_authenticator_set_cname:
302 * @handle: shishi handle as allocated by shishi_init().
303 * @authenticator: authenticator as allocated by shishi_authenticator().
304 * @name_type: type of principial, see Shishi_name_type, usually
306 * @cname: input array with principal name.
308 * Set principal field in authenticator to specified value.
310 * Return value: Returns SHISHI_OK iff successful.
313 shishi_authenticator_set_cname (Shishi
* handle
,
314 Shishi_asn1 authenticator
,
315 Shishi_name_type name_type
,
320 res
= shishi_principal_name_set (handle
, authenticator
, "cname",
322 if (res
!= SHISHI_OK
)
329 * shishi_authenticator_client_set:
330 * @handle: shishi handle as allocated by shishi_init().
331 * @authenticator: Authenticator to set client name field in.
332 * @client: zero-terminated string with principal name on RFC 1964 form.
334 * Set the client name field in the Authenticator.
336 * Return value: Returns SHISHI_OK iff successful.
339 shishi_authenticator_client_set (Shishi
* handle
,
340 Shishi_asn1 authenticator
,
345 res
= shishi_principal_set (handle
, authenticator
, "cname", client
);
346 if (res
!= SHISHI_OK
)
353 shishi_authenticator_ctime_get (Shishi
* handle
,
354 Shishi_asn1 authenticator
, char *ctime
)
359 len
= GENERALIZEDTIME_TIME_LEN
+ 1;
360 res
= shishi_asn1_read (handle
, authenticator
, "ctime", ctime
, &len
);
361 if (res
== SHISHI_OK
&& len
== GENERALIZEDTIME_TIME_LEN
)
368 * shishi_authenticator_ctime_set:
369 * @handle: shishi handle as allocated by shishi_init().
370 * @authenticator: Authenticator as allocated by shishi_authenticator().
371 * @ctime: string with generalized time value to store in Authenticator.
373 * Store client time in Authenticator.
375 * Return value: Returns SHISHI_OK iff successful.
378 shishi_authenticator_ctime_set (Shishi
* handle
,
379 Shishi_asn1 authenticator
, char *ctime
)
383 res
= shishi_asn1_write (handle
, authenticator
, "ctime",
384 ctime
, GENERALIZEDTIME_TIME_LEN
);
385 if (res
!= SHISHI_OK
)
392 * shishi_authenticator_cusec_get:
393 * @handle: shishi handle as allocated by shishi_init().
394 * @authenticator: Authenticator as allocated by shishi_authenticator().
395 * @cusec: output integer with client microseconds field.
397 * Extract client microseconds field from Authenticator.
399 * Return value: Returns SHISHI_OK iff successful.
402 shishi_authenticator_cusec_get (Shishi
* handle
,
403 Shishi_asn1 authenticator
, int *cusec
)
407 res
= shishi_asn1_read_uint32 (handle
, authenticator
, "cusec", cusec
);
408 if (res
!= SHISHI_OK
)
415 * shishi_authenticator_cusec_set:
416 * @handle: shishi handle as allocated by shishi_init().
417 * @authenticator: authenticator as allocated by shishi_authenticator().
418 * @cusec: client microseconds to set in authenticator, 0-999999.
420 * Set the cusec field in the Authenticator.
422 * Return value: Returns SHISHI_OK iff successful.
425 shishi_authenticator_cusec_set (Shishi
* handle
,
426 Shishi_asn1 authenticator
, int cusec
)
430 res
= shishi_asn1_write_uint32 (handle
, authenticator
, "cusec", cusec
);
431 if (res
!= SHISHI_OK
)
438 shishi_authenticator_cname_get (Shishi
* handle
,
439 Shishi_asn1 authenticator
,
440 char *cname
, int *cnamelen
)
442 return shishi_principal_name_get (handle
, authenticator
,
443 "cname", cname
, cnamelen
);
447 shishi_authenticator_cnamerealm_get (Shishi
* handle
,
448 Shishi_asn1 authenticator
,
449 char *cnamerealm
, int *cnamerealmlen
)
451 return shishi_principal_name_realm_get (handle
, authenticator
,
455 cnamerealm
, cnamerealmlen
);
459 shishi_authenticator_remove_cksum (Shishi
* handle
, Shishi_asn1 authenticator
)
463 /* XXX remove this function */
465 res
= shishi_asn1_write (handle
, authenticator
, "cksum", NULL
, 0);
466 if (res
!= SHISHI_OK
)
473 * shishi_authenticator_cksum:
474 * @handle: shishi handle as allocated by shishi_init().
475 * @authenticator: authenticator as allocated by shishi_authenticator().
476 * @cksumtype: output checksum type.
477 * @cksum: output checksum data from authenticator.
478 * @cksumlen: on input, maximum size of output checksum data buffer,
479 * on output, actual size of output checksum data buffer.
481 * Read checksum value from authenticator.
483 * Return value: Returns SHISHI_OK iff successful.
486 shishi_authenticator_cksum (Shishi
* handle
,
487 Shishi_asn1 authenticator
,
489 char *cksum
, size_t * cksumlen
)
493 res
= shishi_asn1_read_int32 (handle
, authenticator
,
494 "cksum.cksumtype", cksumtype
);
495 if (res
!= SHISHI_OK
)
498 res
= shishi_asn1_read (handle
, authenticator
, "cksum.checksum",
500 if (res
!= SHISHI_OK
)
507 * shishi_authenticator_set_cksum:
508 * @handle: shishi handle as allocated by shishi_init().
509 * @authenticator: authenticator as allocated by shishi_authenticator().
510 * @cksumtype: input checksum type to store in authenticator.
511 * @cksum: input checksum data to store in authenticator.
512 * @cksumlen: size of input checksum data to store in authenticator.
514 * Store checksum value in authenticator. A checksum is usually created
515 * by calling shishi_checksum() on some application specific data using
516 * the key from the ticket that is being used. To save time, you may
517 * want to use shishi_authenticator_add_cksum() instead, which calculates
518 * the checksum and calls this function in one step.
520 * Return value: Returns SHISHI_OK iff successful.
523 shishi_authenticator_set_cksum (Shishi
* handle
,
524 Shishi_asn1 authenticator
,
526 char *cksum
, size_t cksumlen
)
530 res
= shishi_asn1_write_int32 (handle
, authenticator
,
531 "cksum.cksumtype", cksumtype
);
532 if (res
!= SHISHI_OK
)
535 res
= shishi_asn1_write (handle
, authenticator
, "cksum.checksum",
537 if (res
!= SHISHI_OK
)
544 * shishi_authenticator_add_cksum:
545 * @handle: shishi handle as allocated by shishi_init().
546 * @authenticator: authenticator as allocated by shishi_authenticator().
547 * @key: key to to use for encryption.
548 * @keyusage: kerberos key usage value to use in encryption.
549 * @data: input array with data to calculate checksum on.
550 * @datalen: size of input array with data to calculate checksum on.
552 * Calculate checksum for data and store it in the authenticator.
554 * Return value: Returns SHISHI_OK iff successful.
557 shishi_authenticator_add_cksum (Shishi
* handle
,
558 Shishi_asn1 authenticator
,
560 int keyusage
, char *data
, int datalen
)
562 return shishi_authenticator_add_cksum_type (handle
, authenticator
, key
,
564 shishi_cipher_defaultcksumtype
565 (shishi_key_type (key
)),
570 * shishi_authenticator_add_cksum_type:
571 * @handle: shishi handle as allocated by shishi_init().
572 * @authenticator: authenticator as allocated by shishi_authenticator().
573 * @key: key to to use for encryption.
574 * @keyusage: kerberos key usage value to use in encryption.
575 * @cksumtype: checksum to type to calculate checksum.
576 * @data: input array with data to calculate checksum on.
577 * @datalen: size of input array with data to calculate checksum on.
579 * Calculate checksum for data and store it in the authenticator.
581 * Return value: Returns SHISHI_OK iff successful.
584 shishi_authenticator_add_cksum_type (Shishi
* handle
,
585 Shishi_asn1 authenticator
,
587 int keyusage
, int cksumtype
,
588 char *data
, int datalen
)
592 if (data
&& datalen
> 0)
597 res
= shishi_checksum (handle
, key
, keyusage
, cksumtype
,
598 data
, datalen
, &cksum
, &cksumlen
);
599 if (res
!= SHISHI_OK
)
602 res
= shishi_authenticator_set_cksum (handle
, authenticator
,
603 cksumtype
, cksum
, cksumlen
);
607 res
= shishi_authenticator_remove_cksum (handle
, authenticator
);
613 * shishi_authenticator_clear_authorizationdata:
614 * @handle: shishi handle as allocated by shishi_init().
615 * @authenticator: Authenticator as allocated by shishi_authenticator().
617 * Remove the authorization-data field from Authenticator.
619 * Return value: Returns SHISHI_OK iff successful.
622 shishi_authenticator_clear_authorizationdata (Shishi
* handle
,
623 Shishi_asn1 authenticator
)
627 res
= shishi_asn1_write (handle
, authenticator
,
628 "authorization-data", NULL
, 0);
629 if (res
!= SHISHI_OK
)
630 return SHISHI_ASN1_ERROR
;
636 * shishi_authenticator_add_authorizationdata:
637 * @handle: shishi handle as allocated by shishi_init().
638 * @authenticator: authenticator as allocated by shishi_authenticator().
639 * @adtype: input authorization data type to add.
640 * @addata: input authorization data to add.
641 * @addatalen: size of input authorization data to add.
643 * Add authorization data to authenticator.
645 * Return value: Returns SHISHI_OK iff successful.
648 shishi_authenticator_add_authorizationdata (Shishi
* handle
,
649 Shishi_asn1 authenticator
,
651 char *addata
, int addatalen
)
657 res
= shishi_asn1_write (handle
, authenticator
,
658 "authorization-data", "NEW", 1);
659 if (res
!= SHISHI_OK
)
662 res
= shishi_asn1_number_of_elements (handle
, authenticator
,
663 "authorization-data", &i
);
664 if (res
!= SHISHI_OK
)
667 asprintf (&format
, "authorization-data.?%d.ad-type", i
);
668 res
= shishi_asn1_write_integer (handle
, authenticator
, format
, adtype
);
669 if (res
!= SHISHI_OK
)
675 sprintf (format
, "authorization-data.?%d.ad-data", i
);
676 res
= shishi_asn1_write (handle
, authenticator
, format
, addata
, addatalen
);
678 if (res
!= SHISHI_OK
)
685 * shishi_authenticator_authorizationdata:
686 * @handle: shishi handle as allocated by shishi_init().
687 * @authenticator: authenticator as allocated by shishi_authenticator().
688 * @adtype: output authorization data type.
689 * @addata: output authorization data.
690 * @addatalen: on input, maximum size of output authorization data,
691 * on output, actual size of authorization data.
692 * @nth: element number of authorization-data to extract.
694 * Extract n:th authorization data from authenticator. The first
697 * Return value: Returns SHISHI_OK iff successful.
700 shishi_authenticator_authorizationdata (Shishi
* handle
,
701 Shishi_asn1 authenticator
,
703 char *addata
, int *addatalen
, int nth
)
709 res
= shishi_asn1_number_of_elements (handle
, authenticator
,
710 "authorization-data", &i
);
711 if (res
!= SHISHI_OK
)
712 return SHISHI_ASN1_ERROR
;
715 return SHISHI_OUT_OF_RANGE
;
717 asprintf (&format
, "authorization-data.?%d.ad-type", nth
);
718 res
= shishi_asn1_read_int32 (handle
, authenticator
, format
, adtype
);
720 if (res
!= SHISHI_OK
)
723 asprintf (&format
, "authorization-data.?%d.ad-data", i
);
724 res
= shishi_asn1_read (handle
, authenticator
, format
, addata
, addatalen
);
726 if (res
!= SHISHI_OK
)
733 * shishi_authenticator_remove_subkey:
734 * @handle: shishi handle as allocated by shishi_init().
735 * @authenticator: authenticator as allocated by shishi_authenticator().
737 * Remove subkey from the authenticator.
739 * Return value: Returns SHISHI_OK iff successful.
742 shishi_authenticator_remove_subkey (Shishi
* handle
, Shishi_asn1 authenticator
)
746 res
= shishi_asn1_write (handle
, authenticator
, "subkey", NULL
, 0);
747 if (res
!= SHISHI_OK
)
754 * shishi_authenticator_get_subkey:
755 * @handle: shishi handle as allocated by shishi_init().
756 * @authenticator: authenticator as allocated by shishi_authenticator().
757 * @subkey: output newly allocated subkey from authenticator.
759 * Read subkey value from authenticator.
761 * Return value: Returns SHISHI_OK if successful or SHISHI_ASN1_NO_ELEMENT
762 * if subkey is not present.
765 shishi_authenticator_get_subkey (Shishi
* handle
,
766 Shishi_asn1 authenticator
,
767 Shishi_key
** subkey
)
775 res
= shishi_asn1_number_of_elements (handle
, authenticator
,
777 if (res
!= SHISHI_OK
)
780 res
= shishi_asn1_read_int32 (handle
, authenticator
,
781 "subkey.keytype", &subkeytype
);
782 if (res
!= SHISHI_OK
)
785 res
= shishi_asn1_read2 (handle
, authenticator
, "subkey.keyvalue",
786 &subkeyvalue
, &subkeylen
);
787 if (res
!= SHISHI_OK
)
790 res
= shishi_key (handle
, subkey
);
791 if (res
!= SHISHI_OK
)
794 shishi_key_type_set (*subkey
, subkeytype
);
795 shishi_key_value_set (*subkey
, subkeyvalue
);
801 * shishi_authenticator_set_subkey:
802 * @handle: shishi handle as allocated by shishi_init().
803 * @authenticator: authenticator as allocated by shishi_authenticator().
804 * @subkeytype: input subkey type to store in authenticator.
805 * @subkey: input subkey data to store in authenticator.
806 * @subkeylen: size of input subkey data to store in authenticator.
808 * Store subkey value in authenticator. A subkey is usually created
809 * by calling shishi_key_random() using the default encryption type of
810 * the key from the ticket that is being used. To save time, you may
811 * want to use shishi_authenticator_add_subkey() instead, which calculates
812 * the subkey and calls this function in one step.
814 * Return value: Returns SHISHI_OK iff successful.
817 shishi_authenticator_set_subkey (Shishi
* handle
,
818 Shishi_asn1 authenticator
,
820 char *subkey
, size_t subkeylen
)
824 res
= shishi_asn1_write_int32 (handle
, authenticator
,
825 "subkey.keytype", subkeytype
);
826 if (res
!= SHISHI_OK
)
829 res
= shishi_asn1_write (handle
, authenticator
, "subkey.keyvalue",
831 if (res
!= SHISHI_OK
)
838 * shishi_authenticator_add_random_subkey:
839 * @handle: shishi handle as allocated by shishi_init().
840 * @authenticator: authenticator as allocated by shishi_authenticator().
842 * Generate random subkey and store it in the authenticator.
844 * Return value: Returns SHISHI_OK iff successful.
847 shishi_authenticator_add_random_subkey (Shishi
* handle
,
848 Shishi_asn1 authenticator
)
854 res
= shishi_cfg_clientkdcetype (handle
, &etypes
);
858 res
= shishi_key_random (handle
, etypes
[0], &subkey
);
859 if (res
!= SHISHI_OK
)
862 res
= shishi_authenticator_set_subkey (handle
, authenticator
,
863 shishi_key_type (subkey
),
864 shishi_key_value (subkey
),
865 shishi_key_length (subkey
));
867 shishi_key_done (subkey
);
873 * shishi_authenticator_add_subkey:
874 * @handle: shishi handle as allocated by shishi_init().
875 * @authenticator: authenticator as allocated by shishi_authenticator().
876 * @subkey: subkey to add to authenticator.
878 * Store subkey in the authenticator.
880 * Return value: Returns SHISHI_OK iff successful.
883 shishi_authenticator_add_subkey (Shishi
* handle
,
884 Shishi_asn1 authenticator
,
890 res
= shishi_cfg_clientkdcetype (handle
, &etypes
);
891 if (res
!= SHISHI_OK
)
894 res
= shishi_authenticator_set_subkey (handle
, authenticator
,
895 shishi_key_type (subkey
),
896 shishi_key_value (subkey
),
897 shishi_key_length (subkey
));