Add.
[shishi.git] / lib / authenticator.c
blob45a8948183a140e62dc2bbb08531158e535a3366
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;
43 node = shishi_asn1_authenticator (handle);
44 if (!node)
45 return NULL;
47 res = shishi_asn1_write (handle, node, "authenticator-vno", "5", 0);
48 if (res != SHISHI_OK)
49 goto error;
51 res = shishi_authenticator_set_crealm (handle, node,
52 shishi_realm_default (handle));
53 if (res != SHISHI_OK)
54 goto error;
56 res = shishi_authenticator_client_set (handle, node,
57 shishi_principal_default (handle));
58 if (res != SHISHI_OK)
59 goto error;
61 gettimeofday (&tv, &tz);
62 res = shishi_authenticator_cusec_set (handle, node, tv.tv_usec % 1000000);
63 if (res != SHISHI_OK)
64 goto error;
66 res = shishi_asn1_write (handle, node, "ctime",
67 shishi_generalize_time (handle, time (NULL)), 0);
68 if (res != SHISHI_OK)
69 goto error;
71 res = shishi_asn1_write (handle, node, "subkey", NULL, 0);
72 if (res != SHISHI_OK)
73 goto error;
75 res = shishi_asn1_write (handle, node, "seq-number", NULL, 0);
76 if (res != SHISHI_OK)
77 goto error;
79 return node;
81 error:
82 shishi_asn1_done (handle, node);
83 return NULL;
86 /**
87 * shishi_authenticator_print:
88 * @handle: shishi handle as allocated by shishi_init().
89 * @fh: file handle open for writing.
90 * @authenticator: authenticator as allocated by shishi_authenticator().
92 * Print ASCII armored DER encoding of authenticator to file.
94 * Return value: Returns SHISHI_OK iff successful.
95 **/
96 int
97 shishi_authenticator_print (Shishi * handle,
98 FILE * fh, Shishi_asn1 authenticator)
100 return _shishi_print_armored_data (handle, fh, authenticator,
101 "Authenticator", NULL);
105 * shishi_authenticator_save:
106 * @handle: shishi handle as allocated by shishi_init().
107 * @fh: file handle open for writing.
108 * @authenticator: authenticator as allocated by shishi_authenticator().
110 * Save DER encoding of authenticator to file.
112 * Return value: Returns SHISHI_OK iff successful.
115 shishi_authenticator_save (Shishi * handle,
116 FILE * fh, Shishi_asn1 authenticator)
118 return _shishi_save_data (handle, fh, authenticator, "Authenticator");
122 * shishi_authenticator_to_file:
123 * @handle: shishi handle as allocated by shishi_init().
124 * @authenticator: Authenticator to save.
125 * @filetype: input variable specifying type of file to be written,
126 * see Shishi_filetype.
127 * @filename: input variable with filename to write to.
129 * Write Authenticator to file in specified TYPE. The file will be
130 * truncated if it exists.
132 * Return value: Returns SHISHI_OK iff successful.
135 shishi_authenticator_to_file (Shishi * handle, Shishi_asn1 authenticator,
136 int filetype, char *filename)
138 FILE *fh;
139 int res;
141 if (VERBOSE (handle))
142 printf (_("Writing Authenticator to %s...\n"), filename);
144 fh = fopen (filename, "w");
145 if (fh == NULL)
146 return SHISHI_FOPEN_ERROR;
148 if (VERBOSE (handle))
149 printf (_("Writing Authenticator in %s format...\n"),
150 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
152 if (filetype == SHISHI_FILETYPE_TEXT)
153 res = shishi_authenticator_print (handle, fh, authenticator);
154 else
155 res = shishi_authenticator_save (handle, fh, authenticator);
156 if (res != SHISHI_OK)
157 return res;
159 res = fclose (fh);
160 if (res != 0)
161 return SHISHI_FCLOSE_ERROR;
163 if (VERBOSE (handle))
164 printf (_("Writing Authenticator to %s...done\n"), filename);
166 return SHISHI_OK;
170 * shishi_authenticator_parse:
171 * @handle: shishi handle as allocated by shishi_init().
172 * @fh: file handle open for reading.
173 * @authenticator: output variable with newly allocated authenticator.
175 * Read ASCII armored DER encoded authenticator from file and populate
176 * given authenticator variable.
178 * Return value: Returns SHISHI_OK iff successful.
181 shishi_authenticator_parse (Shishi * handle,
182 FILE * fh, Shishi_asn1 * authenticator)
184 return _shishi_authenticator_input (handle, fh, authenticator, 0);
188 * shishi_authenticator_read:
189 * @handle: shishi handle as allocated by shishi_init().
190 * @fh: file handle open for reading.
191 * @authenticator: output variable with newly allocated authenticator.
193 * Read DER encoded authenticator from file and populate given
194 * authenticator variable.
196 * Return value: Returns SHISHI_OK iff successful.
199 shishi_authenticator_read (Shishi * handle,
200 FILE * fh, Shishi_asn1 * authenticator)
202 return _shishi_authenticator_input (handle, fh, authenticator, 1);
206 * shishi_authenticator_from_file:
207 * @handle: shishi handle as allocated by shishi_init().
208 * @authenticator: output variable with newly allocated Authenticator.
209 * @filetype: input variable specifying type of file to be read,
210 * see Shishi_filetype.
211 * @filename: input variable with filename to read from.
213 * Read Authenticator from file in specified TYPE.
215 * Return value: Returns SHISHI_OK iff successful.
218 shishi_authenticator_from_file (Shishi * handle, Shishi_asn1 * authenticator,
219 int filetype, char *filename)
221 int res;
222 FILE *fh;
224 if (VERBOSE (handle))
225 printf (_("Reading Authenticator from %s...\n"), filename);
227 fh = fopen (filename, "r");
228 if (fh == NULL)
229 return SHISHI_FOPEN_ERROR;
231 if (VERBOSE (handle))
232 printf (_("Reading Authenticator in %s format...\n"),
233 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
235 if (filetype == SHISHI_FILETYPE_TEXT)
236 res = shishi_authenticator_parse (handle, fh, authenticator);
237 else
238 res = shishi_authenticator_read (handle, fh, authenticator);
239 if (res != SHISHI_OK)
240 return res;
242 res = fclose (fh);
243 if (res != 0)
244 return SHISHI_FCLOSE_ERROR;
246 if (VERBOSE (handle))
247 printf (_("Reading Authenticator from %s...done\n"), filename);
249 return SHISHI_OK;
253 * shishi_authenticator_set_crealm:
254 * @handle: shishi handle as allocated by shishi_init().
255 * @authenticator: authenticator as allocated by shishi_authenticator().
256 * @crealm: input array with realm.
258 * Set realm field in authenticator to specified value.
260 * Return value: Returns SHISHI_OK iff successful.
263 shishi_authenticator_set_crealm (Shishi * handle,
264 Shishi_asn1 authenticator,
265 const char *crealm)
267 int res;
269 res = shishi_asn1_write (handle, authenticator, "crealm", crealm, 0);
270 if (res != SHISHI_OK)
271 return res;
273 return SHISHI_OK;
277 * shishi_authenticator_set_cname:
278 * @handle: shishi handle as allocated by shishi_init().
279 * @authenticator: authenticator as allocated by shishi_authenticator().
280 * @name_type: type of principial, see Shishi_name_type, usually
281 * SHISHI_NT_UNKNOWN.
282 * @principal: input array with principal name.
284 * Set principal field in authenticator to specified value.
286 * Return value: Returns SHISHI_OK iff successful.
289 shishi_authenticator_set_cname (Shishi * handle,
290 Shishi_asn1 authenticator,
291 Shishi_name_type name_type,
292 const char *cname[])
294 int res;
296 res = shishi_principal_name_set (handle, authenticator, "cname",
297 name_type, cname);
298 if (res != SHISHI_OK)
299 return res;
301 return SHISHI_OK;
305 * shishi_authenticator_client_set:
306 * @handle: shishi handle as allocated by shishi_init().
307 * @kdcrep: Authenticator to set client name field in.
308 * @name: zero-terminated string with principal name on RFC 1964 form.
310 * Set the client name field in the Authenticator.
312 * Return value: Returns SHISHI_OK iff successful.
315 shishi_authenticator_client_set (Shishi * handle,
316 Shishi_asn1 authenticator,
317 const char *client)
319 int res;
321 res = shishi_principal_set (handle, authenticator, "cname", client);
322 if (res != SHISHI_OK)
323 return res;
325 return SHISHI_OK;
329 shishi_authenticator_ctime_get (Shishi * handle,
330 Shishi_asn1 authenticator, char *ctime)
332 int len;
333 int res;
335 len = GENERALIZEDTIME_TIME_LEN + 1;
336 res = shishi_asn1_field (handle, authenticator, ctime, &len, "ctime");
337 if (res == SHISHI_OK && len == GENERALIZEDTIME_TIME_LEN)
338 ctime[len] = '\0';
340 return res;
344 * shishi_authenticator_ctime_set:
345 * @handle: shishi handle as allocated by shishi_init().
346 * @authenticator: Authenticator as allocated by shishi_authenticator().
347 * @ctime: string with generalized time value to store in Authenticator.
349 * Store client time in Authenticator.
351 * Return value: Returns SHISHI_OK iff successful.
354 shishi_authenticator_ctime_set (Shishi * handle,
355 Shishi_asn1 authenticator, char *ctime)
357 int res;
359 res = shishi_asn1_write (handle, authenticator, "ctime",
360 ctime, GENERALIZEDTIME_TIME_LEN);
361 if (res != SHISHI_OK)
362 return res;
364 return SHISHI_OK;
368 * shishi_authenticator_cusec_get:
369 * @handle: shishi handle as allocated by shishi_init().
370 * @authenticator: Authenticator as allocated by shishi_authenticator().
371 * @cusec: output integer with client microseconds field.
373 * Extract client microseconds field from Authenticator.
375 * Return value: Returns SHISHI_OK iff successful.
378 shishi_authenticator_cusec_get (Shishi * handle,
379 Shishi_asn1 authenticator, int *cusec)
381 int res;
383 res = shishi_asn1_read_integer (handle, authenticator, "cusec", cusec);
384 if (res != SHISHI_OK)
385 return res;
387 return res;
391 * shishi_authenticator_cusec_set:
392 * @handle: shishi handle as allocated by shishi_init().
393 * @authenticator: authenticator as allocated by shishi_authenticator().
394 * @cusec: client microseconds to set in authenticator, 0-999999.
396 * Set the cusec field in the Authenticator.
398 * Return value: Returns SHISHI_OK iff successful.
401 shishi_authenticator_cusec_set (Shishi * handle,
402 Shishi_asn1 authenticator, int cusec)
404 int res;
406 res = shishi_asn1_write_integer (handle, authenticator, "cusec", cusec);
407 if (res != SHISHI_OK)
408 return res;
410 return SHISHI_OK;
414 shishi_authenticator_cname_get (Shishi * handle,
415 Shishi_asn1 authenticator,
416 char *cname, int *cnamelen)
418 return shishi_principal_name_get (handle, authenticator,
419 "cname", cname, cnamelen);
423 shishi_authenticator_cnamerealm_get (Shishi * handle,
424 Shishi_asn1 authenticator,
425 char *cnamerealm, int *cnamerealmlen)
427 return shishi_principal_name_realm_get (handle, authenticator,
428 "cname",
429 authenticator,
430 "crealm",
431 cnamerealm, cnamerealmlen);
435 shishi_authenticator_remove_cksum (Shishi * handle, Shishi_asn1 authenticator)
437 int res;
439 /* XXX remove this function */
441 res = shishi_asn1_write (handle, authenticator, "cksum", NULL, 0);
442 if (res != SHISHI_OK)
443 return res;
445 return SHISHI_OK;
449 * shishi_authenticator_cksum:
450 * @handle: shishi handle as allocated by shishi_init().
451 * @authenticator: authenticator as allocated by shishi_authenticator().
452 * @cksumtype: output checksum type.
453 * @cksum: output checksum data from authenticator.
454 * @cksumlen: on input, maximum size of output checksum data buffer,
455 * on output, actual size of output checksum data buffer.
457 * Read checksum value from authenticator.
459 * Return value: Returns SHISHI_OK iff successful.
462 shishi_authenticator_cksum (Shishi * handle,
463 Shishi_asn1 authenticator,
464 int32_t * cksumtype,
465 char *cksum, size_t * cksumlen)
467 int res;
469 res = shishi_asn1_read_int32 (handle, authenticator,
470 "cksum.cksumtype", cksumtype);
471 if (res != SHISHI_OK)
472 return res;
474 res = shishi_asn1_field (handle, authenticator, cksum, cksumlen,
475 "cksum.checksum");
476 if (res != SHISHI_OK)
477 return res;
479 return SHISHI_OK;
483 * shishi_authenticator_set_cksum:
484 * @handle: shishi handle as allocated by shishi_init().
485 * @authenticator: authenticator as allocated by shishi_authenticator().
486 * @cksumtype: input checksum type to store in authenticator.
487 * @cksum: input checksum data to store in authenticator.
488 * @cksumlen: size of input checksum data to store in authenticator.
490 * Store checksum value in authenticator. A checksum is usually created
491 * by calling shishi_checksum() on some application specific data using
492 * the key from the ticket that is being used. To save time, you may
493 * want to use shishi_authenticator_add_cksum() instead, which calculates
494 * the checksum and calls this function in one step.
496 * Return value: Returns SHISHI_OK iff successful.
499 shishi_authenticator_set_cksum (Shishi * handle,
500 Shishi_asn1 authenticator,
501 int32_t cksumtype,
502 char *cksum, size_t cksumlen)
504 int res;
506 res = shishi_asn1_write_int32 (handle, authenticator,
507 "cksum.cksumtype", cksumtype);
508 if (res != SHISHI_OK)
509 return res;
511 res = shishi_asn1_write (handle, authenticator, "cksum.checksum",
512 cksum, cksumlen);
513 if (res != SHISHI_OK)
514 return res;
516 return SHISHI_OK;
520 * shishi_authenticator_add_cksum:
521 * @handle: shishi handle as allocated by shishi_init().
522 * @authenticator: authenticator as allocated by shishi_authenticator().
523 * @enckdcreppart: ticket information where the key is taken from.
524 * @data: input array with data to calculate checksum on.
525 * @datalen: size of input array with data to calculate checksum on.
527 * Calculate checksum for data and store it in the authenticator.
529 * Return value: Returns SHISHI_OK iff successful.
532 shishi_authenticator_add_cksum (Shishi * handle,
533 Shishi_asn1 authenticator,
534 Shishi_key * key,
535 int keyusage, char *data, int datalen)
537 int res;
539 if (data && datalen > 0)
541 char *cksum;
542 int cksumlen;
543 int cksumtype = shishi_cipher_defaultcksumtype (shishi_key_type (key));
545 res = shishi_checksum (handle, key, keyusage, cksumtype,
546 data, datalen, &cksum, &cksumlen);
547 if (res != SHISHI_OK)
548 return res;
550 res = shishi_authenticator_set_cksum (handle, authenticator,
551 cksumtype, cksum, cksumlen);
552 free (cksum);
554 else
555 res = shishi_authenticator_remove_cksum (handle, authenticator);
557 return res;
561 * shishi_authenticator_clear_authorizationdata:
562 * @handle: shishi handle as allocated by shishi_init().
563 * @authenticator: Authenticator as allocated by shishi_authenticator().
565 * Remove the authorization-data field from Authenticator.
567 * Return value: Returns SHISHI_OK iff successful.
570 shishi_authenticator_clear_authorizationdata (Shishi * handle,
571 Shishi_asn1 authenticator)
573 int res;
575 res = shishi_asn1_write (handle, authenticator,
576 "authorization-data", NULL, 0);
577 if (res != SHISHI_OK)
578 return SHISHI_ASN1_ERROR;
580 return SHISHI_OK;
584 * shishi_authenticator_add_authorizationdata:
585 * @handle: shishi handle as allocated by shishi_init().
586 * @authenticator: authenticator as allocated by shishi_authenticator().
587 * @adtype: input authorization data type to add.
588 * @addata: input authorization data to add.
589 * @addatalen: size of input authorization data to add.
591 * Add authorization data to authenticator.
593 * Return value: Returns SHISHI_OK iff successful.
596 shishi_authenticator_add_authorizationdata (Shishi * handle,
597 Shishi_asn1 authenticator,
598 int adtype,
599 char *addata, int addatalen)
601 char *format;
602 int res;
603 int i;
605 res = shishi_asn1_write (handle, authenticator,
606 "authorization-data", "NEW", 1);
607 if (res != SHISHI_OK)
608 return res;
610 res = shishi_asn1_number_of_elements (handle, authenticator,
611 "authorization-data", &i);
612 if (res != SHISHI_OK)
613 return res;
615 asprintf (&format, "authorization-data.?%d.ad-type", i);
616 res = shishi_asn1_write_integer (handle, authenticator, format, adtype);
617 if (res != SHISHI_OK)
619 free (format);
620 return res;
623 sprintf (format, "authorization-data.?%d.ad-data", i);
624 res = shishi_asn1_write (handle, authenticator, format, addata, addatalen);
625 free (format);
626 if (res != SHISHI_OK)
627 return res;
629 return SHISHI_OK;
633 * shishi_authenticator_authorizationdata:
634 * @handle: shishi handle as allocated by shishi_init().
635 * @authenticator: authenticator as allocated by shishi_authenticator().
636 * @adtype: output authorization data type.
637 * @addata: output authorization data.
638 * @addatalen: on input, maximum size of output authorization data,
639 on output, actual size of authorization data.
640 * @nth: element number of authorization-data to extract.
642 * Extract n:th authorization data from authenticator. The first
643 * field is 1.
645 * Return value: Returns SHISHI_OK iff successful.
648 shishi_authenticator_authorizationdata (Shishi * handle,
649 Shishi_asn1 authenticator,
650 int *adtype,
651 char *addata, int *addatalen, int nth)
653 char *format;
654 int res;
655 int i;
657 res = shishi_asn1_number_of_elements (handle, authenticator,
658 "authorization-data", &i);
659 if (res != SHISHI_OK)
660 return SHISHI_ASN1_ERROR;
662 if (nth > i)
663 return SHISHI_OUT_OF_RANGE;
665 asprintf (&format, "authorization-data.?%d.ad-type", nth);
666 res = shishi_asn1_read_int32 (handle, authenticator, format, adtype);
667 free (format);
668 if (res != SHISHI_OK)
669 return res;
671 asprintf (&format, "authorization-data.?%d.ad-data", i);
672 res = shishi_asn1_field (handle, authenticator, addata, addatalen, format);
673 free (format);
674 if (res != SHISHI_OK)
675 return res;
677 return SHISHI_OK;