Fix.
[shishi.git] / lib / authenticator.c
blob91c27ec1040b9ca9176678fa8ffd49a0237d4e1e
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
22 #include "internal.h"
24 /**
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
33 * failure.
34 **/
35 Shishi_asn1
36 shishi_authenticator (Shishi * handle)
38 int res;
39 Shishi_asn1 node = NULL;
40 struct timeval tv;
41 struct timezone tz;
42 char usec[BUFSIZ];
44 node = shishi_asn1_authenticator (handle);
45 if (!node)
46 return NULL;
48 res = shishi_asn1_write (handle, node, "authenticator-vno", "5", 0);
49 if (res != SHISHI_OK)
50 goto error;
52 res = shishi_authenticator_set_crealm (handle, node,
53 shishi_realm_default (handle));
54 if (res != SHISHI_OK)
55 goto error;
57 res = shishi_authenticator_client_set (handle, node,
58 shishi_principal_default (handle));
59 if (res != SHISHI_OK)
60 goto error;
62 gettimeofday (&tv, &tz);
63 res = shishi_authenticator_cusec_set (handle, node, tv.tv_usec % 1000000);
64 if (res != SHISHI_OK)
65 goto error;
67 res = shishi_asn1_write (handle, node, "ctime",
68 shishi_generalize_time (handle, time (NULL)), 0);
69 if (res != SHISHI_OK)
70 goto error;
72 res = shishi_asn1_write (handle, node, "subkey", NULL, 0);
73 if (res != SHISHI_OK)
74 goto error;
76 res = shishi_asn1_write (handle, node, "seq-number", NULL, 0);
77 if (res != SHISHI_OK)
78 goto error;
80 return node;
82 error:
83 shishi_asn1_done (handle, node);
84 return NULL;
87 /**
88 * shishi_authenticator_print:
89 * @handle: shishi handle as allocated by shishi_init().
90 * @fh: file handle open for writing.
91 * @authenticator: authenticator as allocated by shishi_authenticator().
93 * Print ASCII armored DER encoding of authenticator to file.
95 * Return value: Returns SHISHI_OK iff successful.
96 **/
97 int
98 shishi_authenticator_print (Shishi * handle,
99 FILE * fh, Shishi_asn1 authenticator)
101 return _shishi_print_armored_data (handle, fh, authenticator,
102 "Authenticator", NULL);
106 * shishi_authenticator_save:
107 * @handle: shishi handle as allocated by shishi_init().
108 * @fh: file handle open for writing.
109 * @authenticator: authenticator as allocated by shishi_authenticator().
111 * Save DER encoding of authenticator to file.
113 * Return value: Returns SHISHI_OK iff successful.
116 shishi_authenticator_save (Shishi * handle,
117 FILE * fh, Shishi_asn1 authenticator)
119 return _shishi_save_data (handle, fh, authenticator, "Authenticator");
123 * shishi_authenticator_to_file:
124 * @handle: shishi handle as allocated by shishi_init().
125 * @authenticator: Authenticator to save.
126 * @filetype: input variable specifying type of file to be written,
127 * see Shishi_filetype.
128 * @filename: input variable with filename to write to.
130 * Write Authenticator to file in specified TYPE. The file will be
131 * truncated if it exists.
133 * Return value: Returns SHISHI_OK iff successful.
136 shishi_authenticator_to_file (Shishi * handle, Shishi_asn1 authenticator,
137 int filetype, char *filename)
139 FILE *fh;
140 int res;
142 if (VERBOSE (handle))
143 printf (_("Writing Authenticator to %s...\n"), filename);
145 fh = fopen (filename, "w");
146 if (fh == NULL)
147 return SHISHI_FOPEN_ERROR;
149 if (VERBOSE (handle))
150 printf (_("Writing Authenticator in %s format...\n"),
151 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
153 if (filetype == SHISHI_FILETYPE_TEXT)
154 res = shishi_authenticator_print (handle, fh, authenticator);
155 else
156 res = shishi_authenticator_save (handle, fh, authenticator);
157 if (res != SHISHI_OK)
158 return res;
160 res = fclose (fh);
161 if (res != 0)
162 return SHISHI_FCLOSE_ERROR;
164 if (VERBOSE (handle))
165 printf (_("Writing Authenticator to %s...done\n"), filename);
167 return SHISHI_OK;
171 * shishi_authenticator_parse:
172 * @handle: shishi handle as allocated by shishi_init().
173 * @fh: file handle open for reading.
174 * @authenticator: output variable with newly allocated authenticator.
176 * Read ASCII armored DER encoded authenticator from file and populate
177 * given authenticator variable.
179 * Return value: Returns SHISHI_OK iff successful.
182 shishi_authenticator_parse (Shishi * handle,
183 FILE * fh, Shishi_asn1 * authenticator)
185 return _shishi_authenticator_input (handle, fh, authenticator, 0);
189 * shishi_authenticator_read:
190 * @handle: shishi handle as allocated by shishi_init().
191 * @fh: file handle open for reading.
192 * @authenticator: output variable with newly allocated authenticator.
194 * Read DER encoded authenticator from file and populate given
195 * authenticator variable.
197 * Return value: Returns SHISHI_OK iff successful.
200 shishi_authenticator_read (Shishi * handle,
201 FILE * fh, Shishi_asn1 * authenticator)
203 return _shishi_authenticator_input (handle, fh, authenticator, 1);
207 * shishi_authenticator_from_file:
208 * @handle: shishi handle as allocated by shishi_init().
209 * @authenticator: output variable with newly allocated Authenticator.
210 * @filetype: input variable specifying type of file to be read,
211 * see Shishi_filetype.
212 * @filename: input variable with filename to read from.
214 * Read Authenticator from file in specified TYPE.
216 * Return value: Returns SHISHI_OK iff successful.
219 shishi_authenticator_from_file (Shishi * handle, Shishi_asn1 * authenticator,
220 int filetype, char *filename)
222 int res;
223 FILE *fh;
225 if (VERBOSE (handle))
226 printf (_("Reading Authenticator from %s...\n"), filename);
228 fh = fopen (filename, "r");
229 if (fh == NULL)
230 return SHISHI_FOPEN_ERROR;
232 if (VERBOSE (handle))
233 printf (_("Reading Authenticator in %s format...\n"),
234 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
236 if (filetype == SHISHI_FILETYPE_TEXT)
237 res = shishi_authenticator_parse (handle, fh, authenticator);
238 else
239 res = shishi_authenticator_read (handle, fh, authenticator);
240 if (res != SHISHI_OK)
241 return res;
243 res = fclose (fh);
244 if (res != 0)
245 return SHISHI_FCLOSE_ERROR;
247 if (VERBOSE (handle))
248 printf (_("Reading Authenticator from %s...done\n"), filename);
250 return SHISHI_OK;
254 * shishi_authenticator_set_crealm:
255 * @handle: shishi handle as allocated by shishi_init().
256 * @authenticator: authenticator as allocated by shishi_authenticator().
257 * @crealm: input array with realm.
259 * Set realm field in authenticator to specified value.
261 * Return value: Returns SHISHI_OK iff successful.
264 shishi_authenticator_set_crealm (Shishi * handle,
265 Shishi_asn1 authenticator,
266 const char *crealm)
268 int res;
270 res = shishi_asn1_write (handle, authenticator, "crealm",
271 crealm, 0);
272 if (res != SHISHI_OK)
273 return res;
275 return SHISHI_OK;
279 * shishi_authenticator_set_cname:
280 * @handle: shishi handle as allocated by shishi_init().
281 * @authenticator: authenticator as allocated by shishi_authenticator().
282 * @name_type: type of principial, see Shishi_name_type, usually
283 * SHISHI_NT_UNKNOWN.
284 * @principal: input array with principal name.
286 * Set principal field in authenticator to specified value.
288 * Return value: Returns SHISHI_OK iff successful.
291 shishi_authenticator_set_cname (Shishi * handle,
292 Shishi_asn1 authenticator,
293 Shishi_name_type name_type,
294 const char *cname[])
296 int res;
298 res = shishi_principal_name_set (handle, authenticator, "cname",
299 name_type, cname);
300 if (res != SHISHI_OK)
301 return res;
303 return SHISHI_OK;
307 * shishi_authenticator_client_set:
308 * @handle: shishi handle as allocated by shishi_init().
309 * @kdcrep: Authenticator to set client name field in.
310 * @name: zero-terminated string with principal name on RFC 1964 form.
312 * Set the client name field in the Authenticator.
314 * Return value: Returns SHISHI_OK iff successful.
317 shishi_authenticator_client_set (Shishi * handle,
318 Shishi_asn1 authenticator,
319 const char *client)
321 int res;
323 res = shishi_principal_set (handle, authenticator, "cname", client);
324 if (res != SHISHI_OK)
325 return res;
327 return SHISHI_OK;
331 shishi_authenticator_ctime_get (Shishi * handle,
332 Shishi_asn1 authenticator, char *ctime)
334 int len;
335 int res;
337 len = GENERALIZEDTIME_TIME_LEN + 1;
338 res = shishi_asn1_field (handle, authenticator,
339 ctime, &len, "ctime");
340 if (res == SHISHI_OK && len == GENERALIZEDTIME_TIME_LEN)
341 ctime[len] = '\0';
343 return res;
347 * shishi_authenticator_ctime_set:
348 * @handle: shishi handle as allocated by shishi_init().
349 * @authenticator: Authenticator as allocated by shishi_authenticator().
350 * @ctime: string with generalized time value to store in Authenticator.
352 * Store client time in Authenticator.
354 * Return value: Returns SHISHI_OK iff successful.
357 shishi_authenticator_ctime_set (Shishi * handle,
358 Shishi_asn1 authenticator,
359 char *ctime)
361 int res;
363 res = shishi_asn1_write (handle, authenticator, "ctime",
364 ctime, GENERALIZEDTIME_TIME_LEN);
365 if (res != SHISHI_OK)
366 return res;
368 return SHISHI_OK;
372 * shishi_authenticator_cusec_get:
373 * @handle: shishi handle as allocated by shishi_init().
374 * @authenticator: Authenticator as allocated by shishi_authenticator().
375 * @cusec: output integer with client microseconds field.
377 * Extract client microseconds field from Authenticator.
379 * Return value: Returns SHISHI_OK iff successful.
382 shishi_authenticator_cusec_get (Shishi * handle,
383 Shishi_asn1 authenticator,
384 int *cusec)
386 int res;
388 res = shishi_asn1_read_integer (handle, authenticator, "cusec", cusec);
389 if (res != SHISHI_OK)
390 return res;
392 return res;
396 * shishi_authenticator_cusec_set:
397 * @handle: shishi handle as allocated by shishi_init().
398 * @authenticator: authenticator as allocated by shishi_authenticator().
399 * @cusec: client microseconds to set in authenticator, 0-999999.
401 * Set the cusec field in the Authenticator.
403 * Return value: Returns SHISHI_OK iff successful.
406 shishi_authenticator_cusec_set (Shishi * handle,
407 Shishi_asn1 authenticator,
408 int cusec)
410 int res;
412 res = shishi_asn1_write_integer (handle, authenticator, "cusec", cusec);
413 if (res != SHISHI_OK)
414 return res;
416 return SHISHI_OK;
420 shishi_authenticator_cname_get (Shishi * handle,
421 Shishi_asn1 authenticator,
422 char *cname, int *cnamelen)
424 return shishi_principal_name_get (handle, authenticator,
425 "cname", cname, cnamelen);
429 shishi_authenticator_cnamerealm_get (Shishi * handle,
430 Shishi_asn1 authenticator,
431 char *cnamerealm, int *cnamerealmlen)
433 return shishi_principal_name_realm_get (handle, authenticator,
434 "cname",
435 authenticator,
436 "crealm",
437 cnamerealm, cnamerealmlen);
441 shishi_authenticator_remove_cksum (Shishi * handle, Shishi_asn1 authenticator)
443 int res;
445 /* XXX remove this function */
447 res = shishi_asn1_write (handle, authenticator, "cksum",
448 NULL, 0);
449 if (res != SHISHI_OK)
450 return res;
452 return SHISHI_OK;
456 * shishi_authenticator_cksum:
457 * @handle: shishi handle as allocated by shishi_init().
458 * @authenticator: authenticator as allocated by shishi_authenticator().
459 * @cksumtype: output checksum type.
460 * @cksum: output checksum data from authenticator.
461 * @cksumlen: on input, maximum size of output checksum data buffer,
462 * on output, actual size of output checksum data buffer.
464 * Read checksum value from authenticator.
466 * Return value: Returns SHISHI_OK iff successful.
469 shishi_authenticator_cksum (Shishi * handle,
470 Shishi_asn1 authenticator,
471 int *cksumtype, char *cksum, size_t * cksumlen)
473 int res;
475 res = shishi_asn1_integer_field (handle, authenticator, cksumtype,
476 "cksum.cksumtype");
477 if (res != SHISHI_OK)
478 return res;
480 res = shishi_asn1_field (handle, authenticator, cksum, cksumlen,
481 "cksum.checksum");
482 if (res != SHISHI_OK)
483 return res;
485 return SHISHI_OK;
489 * shishi_authenticator_set_cksum:
490 * @handle: shishi handle as allocated by shishi_init().
491 * @authenticator: authenticator as allocated by shishi_authenticator().
492 * @cksumtype: input checksum type to store in authenticator.
493 * @cksum: input checksum data to store in authenticator.
494 * @cksumlen: size of input checksum data to store in authenticator.
496 * Store checksum value in authenticator. A checksum is usually created
497 * by calling shishi_checksum() on some application specific data using
498 * the key from the ticket that is being used. To save time, you may
499 * want to use shishi_authenticator_add_cksum() instead, which calculates
500 * the checksum and calls this function in one step.
502 * Return value: Returns SHISHI_OK iff successful.
505 shishi_authenticator_set_cksum (Shishi * handle,
506 Shishi_asn1 authenticator,
507 int cksumtype, char *cksum, int cksumlen)
509 int res;
511 res = shishi_asn1_write_integer (handle, authenticator,
512 "cksum.cksumtype", cksumtype);
513 if (res != SHISHI_OK)
514 return SHISHI_ASN1_ERROR;
516 res = shishi_asn1_write (handle, authenticator, "cksum.checksum",
517 cksum, cksumlen);
518 if (res != SHISHI_OK)
519 return SHISHI_ASN1_ERROR;
521 return SHISHI_OK;
525 * shishi_authenticator_add_cksum:
526 * @handle: shishi handle as allocated by shishi_init().
527 * @authenticator: authenticator as allocated by shishi_authenticator().
528 * @enckdcreppart: ticket information where the key is taken from.
529 * @data: input array with data to calculate checksum on.
530 * @datalen: size of input array with data to calculate checksum on.
532 * Calculate checksum for data and store it in the authenticator.
534 * Return value: Returns SHISHI_OK iff successful.
537 shishi_authenticator_add_cksum (Shishi * handle,
538 Shishi_asn1 authenticator,
539 Shishi_key * key,
540 int keyusage, char *data, int datalen)
542 int res;
544 if (data && datalen > 0)
546 char cksum[BUFSIZ];
547 int cksumlen;
548 int cksumtype = shishi_cipher_defaultcksumtype (shishi_key_type (key));
550 cksumlen = sizeof (cksum);
551 res = shishi_checksum (handle, key, keyusage, cksumtype,
552 data, datalen, cksum, &cksumlen);
553 if (res != SHISHI_OK)
554 return res;
556 res = shishi_authenticator_set_cksum (handle, authenticator,
557 cksumtype, cksum, cksumlen);
559 else
560 res = shishi_authenticator_remove_cksum (handle, authenticator);
562 return res;
566 * shishi_authenticator_clear_authorizationdata:
567 * @handle: shishi handle as allocated by shishi_init().
568 * @authenticator: Authenticator as allocated by shishi_authenticator().
570 * Remove the authorization-data field from Authenticator.
572 * Return value: Returns SHISHI_OK iff successful.
575 shishi_authenticator_clear_authorizationdata (Shishi * handle,
576 Shishi_asn1 authenticator)
578 int res;
580 res = shishi_asn1_write (handle, authenticator,
581 "authorization-data", NULL, 0);
582 if (res != SHISHI_OK)
583 return SHISHI_ASN1_ERROR;
585 return SHISHI_OK;
589 * shishi_authenticator_add_authorizationdata:
590 * @handle: shishi handle as allocated by shishi_init().
591 * @authenticator: authenticator as allocated by shishi_authenticator().
592 * @adtype: input authorization data type to add.
593 * @addata: input authorization data to add.
594 * @addatalen: size of input authorization data to add.
596 * Add authorization data to authenticator.
598 * Return value: Returns SHISHI_OK iff successful.
601 shishi_authenticator_add_authorizationdata (Shishi * handle,
602 Shishi_asn1 authenticator,
603 int adtype,
604 char *addata, int addatalen)
606 char format[BUFSIZ];
607 char buf[BUFSIZ];
608 int res;
609 int i;
611 res = shishi_asn1_write (handle, authenticator,
612 "authorization-data", "NEW", 1);
613 if (res != SHISHI_OK)
614 return res;
616 res = shishi_asn1_number_of_elements (handle, authenticator,
617 "authorization-data",
618 &i);
619 if (res != SHISHI_OK)
620 return res;
622 sprintf (buf, "%d", adtype);
623 sprintf (format, "authorization-data.?%d.ad-type", i);
624 res = shishi_asn1_write (handle, authenticator, format, buf, 0);
625 if (res != SHISHI_OK)
626 return res;
628 sprintf (format, "authorization-data.?%d.ad-data", i);
629 res = shishi_asn1_write (handle, authenticator, format, addata, addatalen);
630 if (res != SHISHI_OK)
631 return res;
633 return SHISHI_OK;
637 * shishi_authenticator_authorizationdata:
638 * @handle: shishi handle as allocated by shishi_init().
639 * @authenticator: authenticator as allocated by shishi_authenticator().
640 * @adtype: output authorization data type.
641 * @addata: output authorization data.
642 * @addatalen: on input, maximum size of output authorization data,
643 on output, actual size of authorization data.
644 * @nth: element number of authorization-data to extract.
646 * Extract n:th authorization data from authenticator. The first
647 * field is 1.
649 * Return value: Returns SHISHI_OK iff successful.
652 shishi_authenticator_authorizationdata (Shishi * handle,
653 Shishi_asn1 authenticator,
654 int *adtype,
655 char *addata, int *addatalen, int nth)
657 char *format;
658 int res;
659 int i;
661 res = shishi_asn1_number_of_elements (handle, authenticator,
662 "authorization-data",
663 &i);
664 if (res != SHISHI_OK)
665 return SHISHI_ASN1_ERROR;
667 if (nth > i)
668 return SHISHI_OUT_OF_RANGE;
670 shishi_asprintf (&format, "authorization-data.?%d.ad-type",
671 nth);
672 res = shishi_asn1_integer_field (handle, authenticator, adtype, format);
673 free (format);
674 if (res != SHISHI_OK)
675 return res;
677 shishi_asprintf (&format, "authorization-data.?%d.ad-data",
679 res = shishi_asn1_field (handle, authenticator, addata, addatalen, format);
680 free (format);
681 if (res != SHISHI_OK)
682 return res;
684 return SHISHI_OK;