Change GPLv2+ to GPLv3+.
[shishi.git] / lib / krberror.c
blobe2b71bf80b41379186f074debdc63e57c2461afa
1 /* krberror.c --- Functions related to KRB-ERROR packet.
2 * Copyright (C) 2002, 2003, 2004, 2006 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "internal.h"
24 /* Get _shishi_print_armored_data, etc. */
25 #include "diskio.h"
27 #define SHISHI_KRB_ERROR_DEFAULT_PVNO "5"
28 #define SHISHI_KRB_ERROR_DEFAULT_PVNO_LEN 0
29 #define SHISHI_KRB_ERROR_DEFAULT_MSG_TYPE "30"
30 #define SHISHI_KRB_ERROR_DEFAULT_MSG_TYPE_LEN 0
32 /**
33 * shishi_krberror:
34 * @handle: shishi handle as allocated by shishi_init().
36 * This function creates a new KRB-ERROR, populated with some default
37 * values.
39 * Return value: Returns the KRB-ERROR or NULL on failure.
40 **/
41 Shishi_asn1
42 shishi_krberror (Shishi * handle)
44 Shishi_asn1 krberror;
45 struct timeval tv;
46 int rc;
48 rc = gettimeofday (&tv, NULL);
49 if (rc != 0)
50 return NULL;
52 krberror = shishi_asn1_krberror (handle);
53 if (!krberror)
54 return NULL;
56 rc = shishi_asn1_write (handle, krberror, "pvno",
57 SHISHI_KRB_ERROR_DEFAULT_PVNO,
58 SHISHI_KRB_ERROR_DEFAULT_PVNO_LEN);
60 if (rc == SHISHI_OK)
61 rc = shishi_asn1_write (handle, krberror, "msg-type",
62 SHISHI_KRB_ERROR_DEFAULT_MSG_TYPE,
63 SHISHI_KRB_ERROR_DEFAULT_MSG_TYPE_LEN);
66 if (rc == SHISHI_OK)
67 rc = shishi_krberror_susec_set (handle, krberror, tv.tv_usec % 1000000);
69 if (rc == SHISHI_OK)
70 rc = shishi_asn1_write (handle, krberror, "stime",
71 shishi_generalize_now (handle), 0);
73 if (rc != SHISHI_OK)
75 shishi_error_printf (handle, "shishi_krberror() failed");
76 shishi_asn1_done (handle, krberror);
77 krberror = NULL;
80 return krberror;
83 /**
84 * shishi_krberror_print:
85 * @handle: shishi handle as allocated by shishi_init().
86 * @fh: file handle open for writing.
87 * @krberror: KRB-ERROR to print.
89 * Print ASCII armored DER encoding of KRB-ERROR to file.
91 * Return value: Returns SHISHI_OK iff successful.
92 **/
93 int
94 shishi_krberror_print (Shishi * handle, FILE * fh, Shishi_asn1 krberror)
96 return _shishi_print_armored_data (handle, fh, krberror, "KRB-ERROR", NULL);
99 /**
100 * shishi_krberror_save:
101 * @handle: shishi handle as allocated by shishi_init().
102 * @fh: file handle open for writing.
103 * @krberror: KRB-ERROR to save.
105 * Save DER encoding of KRB-ERROR to file.
107 * Return value: Returns SHISHI_OK iff successful.
110 shishi_krberror_save (Shishi * handle, FILE * fh, Shishi_asn1 krberror)
112 return _shishi_save_data (handle, fh, krberror, "KRB-ERROR");
116 * shishi_krberror_to_file:
117 * @handle: shishi handle as allocated by shishi_init().
118 * @krberror: KRB-ERROR to save.
119 * @filetype: input variable specifying type of file to be written,
120 * see Shishi_filetype.
121 * @filename: input variable with filename to write to.
123 * Write KRB-ERROR to file in specified TYPE. The file will be
124 * truncated if it exists.
126 * Return value: Returns SHISHI_OK iff successful.
129 shishi_krberror_to_file (Shishi * handle, Shishi_asn1 krberror,
130 int filetype, const char *filename)
132 FILE *fh;
133 int res;
135 if (VERBOSE (handle))
136 printf (_("Writing KRB-ERROR to %s...\n"), filename);
138 fh = fopen (filename, "w");
139 if (fh == NULL)
140 return SHISHI_FOPEN_ERROR;
142 if (VERBOSE (handle))
143 printf (_("Writing KRB-ERROR in %s format...\n"),
144 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
146 if (filetype == SHISHI_FILETYPE_TEXT)
147 res = shishi_krberror_print (handle, fh, krberror);
148 else
149 res = shishi_krberror_save (handle, fh, krberror);
150 if (res != SHISHI_OK)
151 return res;
153 res = fclose (fh);
154 if (res != 0)
155 return SHISHI_IO_ERROR;
157 if (VERBOSE (handle))
158 printf (_("Writing KRB-ERROR to %s...done\n"), filename);
160 return SHISHI_OK;
164 * shishi_krberror_parse:
165 * @handle: shishi handle as allocated by shishi_init().
166 * @fh: file handle open for reading.
167 * @krberror: output variable with newly allocated KRB-ERROR.
169 * Read ASCII armored DER encoded KRB-ERROR from file and populate given
170 * variable.
172 * Return value: Returns SHISHI_OK iff successful.
175 shishi_krberror_parse (Shishi * handle, FILE * fh, Shishi_asn1 * krberror)
177 return _shishi_krberror_input (handle, fh, krberror, 0);
181 * shishi_krberror_read:
182 * @handle: shishi handle as allocated by shishi_init().
183 * @fh: file handle open for reading.
184 * @krberror: output variable with newly allocated KRB-ERROR.
186 * Read DER encoded KRB-ERROR from file and populate given variable.
188 * Return value: Returns SHISHI_OK iff successful.
191 shishi_krberror_read (Shishi * handle, FILE * fh, Shishi_asn1 * krberror)
193 return _shishi_krberror_input (handle, fh, krberror, 1);
197 * shishi_krberror_from_file:
198 * @handle: shishi handle as allocated by shishi_init().
199 * @krberror: output variable with newly allocated KRB-ERROR.
200 * @filetype: input variable specifying type of file to be read,
201 * see Shishi_filetype.
202 * @filename: input variable with filename to read from.
204 * Read KRB-ERROR from file in specified TYPE.
206 * Return value: Returns SHISHI_OK iff successful.
209 shishi_krberror_from_file (Shishi * handle, Shishi_asn1 * krberror,
210 int filetype, const char *filename)
212 int res;
213 FILE *fh;
215 if (VERBOSE (handle))
216 printf (_("Reading KRB-ERROR from %s...\n"), filename);
218 fh = fopen (filename, "r");
219 if (fh == NULL)
220 return SHISHI_FOPEN_ERROR;
222 if (VERBOSE (handle))
223 printf (_("Reading KRB-ERROR in %s format...\n"),
224 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
226 if (filetype == SHISHI_FILETYPE_TEXT)
227 res = shishi_krberror_parse (handle, fh, krberror);
228 else
229 res = shishi_krberror_read (handle, fh, krberror);
230 if (res != SHISHI_OK)
231 return res;
233 res = fclose (fh);
234 if (res != 0)
235 return SHISHI_IO_ERROR;
237 if (VERBOSE (handle))
238 printf (_("Reading KRB-ERROR from %s...done\n"), filename);
240 return SHISHI_OK;
244 * shishi_krberror_build:
245 * @handle: shishi handle as allocated by shishi_init().
246 * @krberror: krberror as allocated by shishi_krberror().
248 * Finish KRB-ERROR, called before e.g. shishi_krberror_der. This
249 * function removes empty but OPTIONAL fields (such as cname), and
251 * Return value: Returns SHISHI_OK iff successful.
254 shishi_krberror_build (Shishi * handle, Shishi_asn1 krberror)
256 char *t;
257 size_t tmplen = sizeof (t);
258 char *tmp;
259 int32_t errc;
260 uint32_t usec;
261 int rc;
263 rc = shishi_krberror_ctime (handle, krberror, &t);
264 if (rc != SHISHI_OK &&
265 rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
266 return rc;
267 free (t);
268 if (rc == SHISHI_ASN1_NO_VALUE)
270 rc = shishi_krberror_remove_ctime (handle, krberror);
271 if (rc != SHISHI_OK)
272 return rc;
275 rc = shishi_krberror_cusec (handle, krberror, &usec);
276 if (rc != SHISHI_OK &&
277 rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
278 return rc;
279 if (rc == SHISHI_ASN1_NO_VALUE)
281 rc = shishi_krberror_remove_cusec (handle, krberror);
282 if (rc != SHISHI_OK)
283 return rc;
286 rc = shishi_krberror_crealm (handle, krberror, &tmp, &tmplen);
287 if (rc != SHISHI_OK &&
288 rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
289 return rc;
290 if (rc == SHISHI_OK)
291 free (tmp);
292 if (rc == SHISHI_ASN1_NO_VALUE)
294 rc = shishi_krberror_remove_crealm (handle, krberror);
295 if (rc != SHISHI_OK)
296 return rc;
299 rc = shishi_krberror_client (handle, krberror, &tmp, &tmplen);
300 if (rc != SHISHI_OK &&
301 rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
302 return rc;
303 if (rc == SHISHI_OK)
304 free (tmp);
305 if (rc == SHISHI_ASN1_NO_VALUE || (rc == SHISHI_OK && tmplen == 0))
307 rc = shishi_krberror_remove_cname (handle, krberror);
308 if (rc != SHISHI_OK)
309 return rc;
312 rc = shishi_krberror_realm (handle, krberror, &tmp, &tmplen);
313 if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_VALUE)
314 return rc;
315 if (rc == SHISHI_OK)
316 free (tmp);
317 if (rc == SHISHI_ASN1_NO_VALUE)
319 rc = shishi_krberror_set_realm (handle, krberror, "");
320 if (rc != SHISHI_OK)
321 return rc;
324 rc = shishi_krberror_server (handle, krberror, &tmp, &tmplen);
325 if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_VALUE)
326 return rc;
327 if (rc == SHISHI_OK)
328 free (tmp);
329 if (rc == SHISHI_ASN1_NO_VALUE || tmplen == 0)
331 rc = shishi_krberror_remove_sname (handle, krberror);
332 if (rc != SHISHI_OK)
333 return rc;
336 rc = shishi_krberror_edata (handle, krberror, &tmp, &tmplen);
337 if (rc != SHISHI_OK &&
338 rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
339 return rc;
340 if (rc == SHISHI_OK)
341 free (tmp);
342 if (rc == SHISHI_ASN1_NO_VALUE || (rc == SHISHI_OK && tmplen == 0))
344 rc = shishi_krberror_remove_edata (handle, krberror);
345 if (rc != SHISHI_OK)
346 return rc;
349 rc = shishi_krberror_errorcode (handle, krberror, &errc);
350 if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_VALUE)
351 return rc;
352 if (rc == SHISHI_ASN1_NO_VALUE)
354 rc = shishi_krberror_errorcode_set (handle, krberror,
355 SHISHI_KRB_ERR_GENERIC);
356 if (rc != SHISHI_OK)
357 return rc;
360 rc = shishi_krberror_etext (handle, krberror, &tmp, &tmplen);
361 if (rc != SHISHI_OK &&
362 rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
363 return rc;
364 if (rc == SHISHI_OK)
365 free (tmp);
366 if (rc == SHISHI_ASN1_NO_VALUE || (rc == SHISHI_OK && tmplen == 0))
368 if (shishi_krberror_errorcode_fast (handle, krberror) ==
369 SHISHI_KRB_ERR_GENERIC)
370 rc = shishi_krberror_set_etext (handle, krberror,
371 "Uninitialized error");
372 else
373 rc = shishi_krberror_remove_etext (handle, krberror);
374 if (rc != SHISHI_OK)
375 return rc;
378 return SHISHI_OK;
382 * shishi_krberror_der:
383 * @handle: shishi handle as allocated by shishi_init().
384 * @krberror: krberror as allocated by shishi_krberror().
385 * @out: output array with newly allocated DER encoding of KRB-ERROR.
386 * @outlen: length of output array with DER encoding of KRB-ERROR.
388 * DER encode KRB-ERROR. The caller must deallocate the OUT buffer.
390 * Return value: Returns SHISHI_OK iff successful.
393 shishi_krberror_der (Shishi * handle,
394 Shishi_asn1 krberror, char **out, size_t * outlen)
396 int rc;
398 rc = shishi_krberror_build (handle, krberror);
399 if (rc != SHISHI_OK)
400 return rc;
402 rc = shishi_asn1_to_der (handle, krberror, out, outlen);
403 if (rc != SHISHI_OK)
404 return rc;
406 return SHISHI_OK;
410 * shishi_krberror_crealm:
411 * @handle: shishi handle as allocated by shishi_init().
412 * @krberror: krberror as allocated by shishi_krberror().
413 * @realm: output array with newly allocated name of realm in KRB-ERROR.
414 * @realmlen: size of output array.
416 * Extract client realm from KRB-ERROR.
418 * Return value: Returns SHISHI_OK iff successful.
421 shishi_krberror_crealm (Shishi * handle,
422 Shishi_asn1 krberror, char **realm, size_t * realmlen)
424 return shishi_asn1_read (handle, krberror, "crealm", realm, realmlen);
428 * shishi_krberror_remove_crealm:
429 * @handle: shishi handle as allocated by shishi_init().
430 * @krberror: krberror as allocated by shishi_krberror().
432 * Remove client realm field in KRB-ERROR.
434 * Return value: Returns SHISHI_OK iff successful.
437 shishi_krberror_remove_crealm (Shishi * handle, Shishi_asn1 krberror)
439 int res;
441 res = shishi_asn1_write (handle, krberror, "crealm", NULL, 0);
442 if (res != SHISHI_OK)
443 return res;
445 return SHISHI_OK;
449 * shishi_krberror_set_crealm:
450 * @handle: shishi handle as allocated by shishi_init().
451 * @krberror: krberror as allocated by shishi_krberror().
452 * @crealm: input array with realm.
454 * Set realm field in krberror to specified value.
456 * Return value: Returns SHISHI_OK iff successful.
459 shishi_krberror_set_crealm (Shishi * handle,
460 Shishi_asn1 krberror, const char *crealm)
462 int res;
464 res = shishi_asn1_write (handle, krberror, "crealm", crealm, 0);
465 if (res != SHISHI_OK)
466 return res;
468 return SHISHI_OK;
472 * shishi_krberror_client:
473 * @handle: shishi handle as allocated by shishi_init().
474 * @krberror: krberror as allocated by shishi_krberror().
475 * @client: pointer to newly allocated zero terminated string containing
476 * principal name. May be %NULL (to only populate @clientlen).
477 * @clientlen: pointer to length of @client on output, excluding terminating
478 * zero. May be %NULL (to only populate @client).
480 * Return client principal name in KRB-ERROR.
482 * Return value: Returns SHISHI_OK iff successful.
485 shishi_krberror_client (Shishi * handle,
486 Shishi_asn1 krberror,
487 char **client, size_t * clientlen)
489 int rc;
491 rc = shishi_principal_name (handle, krberror, "cname", client, clientlen);
492 if (rc != SHISHI_OK)
493 return rc;
495 return SHISHI_OK;
499 * shishi_krberror_set_cname:
500 * @handle: shishi handle as allocated by shishi_init().
501 * @krberror: krberror as allocated by shishi_krberror().
502 * @name_type: type of principial, see Shishi_name_type, usually
503 * SHISHI_NT_UNKNOWN.
504 * @cname: input array with principal name.
506 * Set principal field in krberror to specified value.
508 * Return value: Returns SHISHI_OK iff successful.
511 shishi_krberror_set_cname (Shishi * handle,
512 Shishi_asn1 krberror,
513 Shishi_name_type name_type, const char *cname[])
515 int res;
517 res = shishi_principal_name_set (handle, krberror, "cname",
518 name_type, cname);
519 if (res != SHISHI_OK)
520 return res;
522 return SHISHI_OK;
526 * shishi_krberror_remove_cname:
527 * @handle: shishi handle as allocated by shishi_init().
528 * @krberror: krberror as allocated by shishi_krberror().
530 * Remove client realm field in KRB-ERROR.
532 * Return value: Returns SHISHI_OK iff successful.
535 shishi_krberror_remove_cname (Shishi * handle, Shishi_asn1 krberror)
537 int res;
539 res = shishi_asn1_write (handle, krberror, "cname", NULL, 0);
540 if (res != SHISHI_OK)
541 return res;
543 return SHISHI_OK;
547 * shishi_krberror_client_set:
548 * @handle: shishi handle as allocated by shishi_init().
549 * @krberror: Krberror to set client name field in.
550 * @client: zero-terminated string with principal name on RFC 1964 form.
552 * Set the client name field in the Krberror.
554 * Return value: Returns SHISHI_OK iff successful.
557 shishi_krberror_client_set (Shishi * handle,
558 Shishi_asn1 krberror, const char *client)
560 int res;
562 res = shishi_principal_set (handle, krberror, "cname", client);
563 if (res != SHISHI_OK)
564 return res;
566 return SHISHI_OK;
570 * shishi_krberror_realm:
571 * @handle: shishi handle as allocated by shishi_init().
572 * @krberror: krberror as allocated by shishi_krberror().
573 * @realm: output array with newly allocated name of realm in KRB-ERROR.
574 * @realmlen: size of output array.
576 * Extract (server) realm from KRB-ERROR.
578 * Return value: Returns SHISHI_OK iff successful.
581 shishi_krberror_realm (Shishi * handle,
582 Shishi_asn1 krberror, char **realm, size_t * realmlen)
584 return shishi_asn1_read (handle, krberror, "realm", realm, realmlen);
588 * shishi_krberror_set_realm:
589 * @handle: shishi handle as allocated by shishi_init().
590 * @krberror: krberror as allocated by shishi_krberror().
591 * @realm: input array with (server) realm.
593 * Set (server) realm field in krberror to specified value.
595 * Return value: Returns SHISHI_OK iff successful.
598 shishi_krberror_set_realm (Shishi * handle,
599 Shishi_asn1 krberror, const char *realm)
601 int res;
603 res = shishi_asn1_write (handle, krberror, "realm", realm, 0);
604 if (res != SHISHI_OK)
605 return res;
607 return SHISHI_OK;
611 * shishi_krberror_server:
612 * @handle: shishi handle as allocated by shishi_init().
613 * @krberror: krberror as allocated by shishi_krberror().
614 * @server: pointer to newly allocated zero terminated string containing
615 * server name. May be %NULL (to only populate @serverlen).
616 * @serverlen: pointer to length of @server on output, excluding terminating
617 * zero. May be %NULL (to only populate @server).
619 * Return server principal name in KRB-ERROR.
621 * Return value: Returns SHISHI_OK iff successful.
624 shishi_krberror_server (Shishi * handle,
625 Shishi_asn1 krberror,
626 char **server, size_t * serverlen)
628 int rc;
630 rc = shishi_principal_name (handle, krberror, "sname", server, serverlen);
631 if (rc != SHISHI_OK)
632 return rc;
634 return SHISHI_OK;
638 * shishi_krberror_remove_sname:
639 * @handle: shishi handle as allocated by shishi_init().
640 * @krberror: Krberror to set server name field in.
642 * Remove server name field in KRB-ERROR. (Since it is not marked
643 * OPTIONAL in the ASN.1 profile, what is done is to set the name-type
644 * to UNKNOWN and make sure the name-string sequence is empty.)
646 * Return value: Returns SHISHI_OK iff successful.
649 shishi_krberror_remove_sname (Shishi * handle, Shishi_asn1 krberror)
651 int res;
653 res = shishi_asn1_write_int32 (handle, krberror, "sname.name-type",
654 SHISHI_NT_UNKNOWN);
655 if (res != SHISHI_OK)
656 return res;
658 res = shishi_asn1_write (handle, krberror, "sname.name-string", NULL, 0);
659 if (res != SHISHI_OK)
660 return res;
662 return SHISHI_OK;
666 * shishi_krberror_set_sname:
667 * @handle: shishi handle as allocated by shishi_init().
668 * @krberror: krberror as allocated by shishi_krberror().
669 * @name_type: type of principial, see Shishi_name_type, usually
670 * SHISHI_NT_UNKNOWN.
671 * @sname: input array with principal name.
673 * Set principal field in krberror to specified value.
675 * Return value: Returns SHISHI_OK iff successful.
678 shishi_krberror_set_sname (Shishi * handle,
679 Shishi_asn1 krberror,
680 Shishi_name_type name_type, const char *sname[])
682 int res;
684 res = shishi_principal_name_set (handle, krberror, "sname",
685 name_type, sname);
686 if (res != SHISHI_OK)
687 return res;
689 return SHISHI_OK;
693 * shishi_krberror_server_set:
694 * @handle: shishi handle as allocated by shishi_init().
695 * @krberror: Krberror to set server name field in.
696 * @server: zero-terminated string with principal name on RFC 1964 form.
698 * Set the server name field in the Krberror.
700 * Return value: Returns SHISHI_OK iff successful.
703 shishi_krberror_server_set (Shishi * handle,
704 Shishi_asn1 krberror, const char *server)
706 int res;
708 res = shishi_principal_set (handle, krberror, "sname", server);
709 if (res != SHISHI_OK)
710 return res;
712 return SHISHI_OK;
716 * shishi_krberror_ctime:
717 * @handle: shishi handle as allocated by shishi_init().
718 * @krberror: Krberror to set client name field in.
719 * @t: newly allocated zero-terminated output array with client time.
721 * Extract client time from KRB-ERROR.
723 * Return value: Returns SHISHI_OK iff successful.
726 shishi_krberror_ctime (Shishi * handle, Shishi_asn1 krberror, char **t)
728 return shishi_time (handle, krberror, "ctime", t);
732 * shishi_krberror_ctime_set:
733 * @handle: shishi handle as allocated by shishi_init().
734 * @krberror: Krberror as allocated by shishi_krberror().
735 * @t: string with generalized time value to store in Krberror.
737 * Store client time in Krberror.
739 * Return value: Returns SHISHI_OK iff successful.
742 shishi_krberror_ctime_set (Shishi * handle,
743 Shishi_asn1 krberror, const char *t)
745 int res;
747 if (t)
748 res = shishi_asn1_write (handle, krberror, "ctime",
749 t, SHISHI_GENERALIZEDTIME_LENGTH);
750 else
751 res = shishi_asn1_write (handle, krberror, "ctime", NULL, 0);
752 if (res != SHISHI_OK)
753 return res;
755 return SHISHI_OK;
759 * shishi_krberror_remove_ctime:
760 * @handle: shishi handle as allocated by shishi_init().
761 * @krberror: Krberror as allocated by shishi_krberror().
763 * Remove client time field in Krberror.
765 * Return value: Returns SHISHI_OK iff successful.
768 shishi_krberror_remove_ctime (Shishi * handle, Shishi_asn1 krberror)
770 int res;
772 res = shishi_asn1_write (handle, krberror, "ctime", NULL, 0);
773 if (res != SHISHI_OK)
774 return res;
776 return SHISHI_OK;
780 * shishi_krberror_cusec:
781 * @handle: shishi handle as allocated by shishi_init().
782 * @krberror: Krberror as allocated by shishi_krberror().
783 * @cusec: output integer with client microseconds field.
785 * Extract client microseconds field from Krberror.
787 * Return value: Returns SHISHI_OK iff successful.
790 shishi_krberror_cusec (Shishi * handle, Shishi_asn1 krberror,
791 uint32_t * cusec)
793 int res;
795 res = shishi_asn1_read_uint32 (handle, krberror, "cusec", cusec);
796 if (res != SHISHI_OK)
797 return res;
799 return SHISHI_OK;
803 * shishi_krberror_cusec_set:
804 * @handle: shishi handle as allocated by shishi_init().
805 * @krberror: krberror as allocated by shishi_krberror().
806 * @cusec: client microseconds to set in krberror, 0-999999.
808 * Set the cusec field in the Krberror.
810 * Return value: Returns SHISHI_OK iff successful.
813 shishi_krberror_cusec_set (Shishi * handle,
814 Shishi_asn1 krberror, uint32_t cusec)
816 int res;
818 res = shishi_asn1_write_uint32 (handle, krberror, "cusec", cusec);
819 if (res != SHISHI_OK)
820 return res;
822 return SHISHI_OK;
826 * shishi_krberror_remove_cusec:
827 * @handle: shishi handle as allocated by shishi_init().
828 * @krberror: Krberror as allocated by shishi_krberror().
830 * Remove client usec field in Krberror.
832 * Return value: Returns SHISHI_OK iff successful.
835 shishi_krberror_remove_cusec (Shishi * handle, Shishi_asn1 krberror)
837 int res;
839 res = shishi_asn1_write (handle, krberror, "cusec", NULL, 0);
840 if (res != SHISHI_OK)
841 return res;
843 return SHISHI_OK;
847 * shishi_krberror_stime:
848 * @handle: shishi handle as allocated by shishi_init().
849 * @krberror: Krberror to set client name field in.
850 * @t: newly allocated zero-terminated output array with server time.
852 * Extract server time from KRB-ERROR.
854 * Return value: Returns SHISHI_OK iff successful.
857 shishi_krberror_stime (Shishi * handle, Shishi_asn1 krberror, char **t)
859 return shishi_time (handle, krberror, "stime", t);
863 * shishi_krberror_stime_set:
864 * @handle: shishi handle as allocated by shishi_init().
865 * @krberror: Krberror as allocated by shishi_krberror().
866 * @t: string with generalized time value to store in Krberror.
868 * Store server time in Krberror.
870 * Return value: Returns SHISHI_OK iff successful.
873 shishi_krberror_stime_set (Shishi * handle,
874 Shishi_asn1 krberror, const char *t)
876 int res;
878 res = shishi_asn1_write (handle, krberror, "stime",
879 t, SHISHI_GENERALIZEDTIME_LENGTH);
880 if (res != SHISHI_OK)
881 return res;
883 return SHISHI_OK;
887 * shishi_krberror_susec:
888 * @handle: shishi handle as allocated by shishi_init().
889 * @krberror: Krberror as allocated by shishi_krberror().
890 * @susec: output integer with server microseconds field.
892 * Extract server microseconds field from Krberror.
894 * Return value: Returns SHISHI_OK iff successful.
897 shishi_krberror_susec (Shishi * handle,
898 Shishi_asn1 krberror, uint32_t * susec)
900 int res;
902 res = shishi_asn1_read_uint32 (handle, krberror, "susec", susec);
903 if (res != SHISHI_OK)
904 return res;
906 return SHISHI_OK;
910 * shishi_krberror_susec_set:
911 * @handle: shishi handle as allocated by shishi_init().
912 * @krberror: krberror as allocated by shishi_krberror().
913 * @susec: server microseconds to set in krberror, 0-999999.
915 * Set the susec field in the Krberror.
917 * Return value: Returns SHISHI_OK iff successful.
920 shishi_krberror_susec_set (Shishi * handle,
921 Shishi_asn1 krberror, uint32_t susec)
923 int res;
925 res = shishi_asn1_write_uint32 (handle, krberror, "susec", susec);
926 if (res != SHISHI_OK)
927 return res;
929 return SHISHI_OK;
933 * shishi_krberror_errorcode:
934 * @handle: shishi handle as allocated by shishi_init().
935 * @krberror: KRB-ERROR structure with error code.
936 * @errorcode: output integer KRB-ERROR error code.
938 * Extract error code from KRB-ERROR.
940 * Return value: Returns SHISHI_OK iff successful.
943 shishi_krberror_errorcode (Shishi * handle,
944 Shishi_asn1 krberror, int32_t * errorcode)
946 return shishi_asn1_read_int32 (handle, krberror, "error-code", errorcode);
950 * shishi_krberror_errorcode_fast:
951 * @handle: shishi handle as allocated by shishi_init().
952 * @krberror: KRB-ERROR structure with error code.
954 * Get error code from KRB-ERROR, without error checking.
956 * Return value: Return error code (see shishi_krberror_errorcode())
957 * directly, or -1 on error.
960 shishi_krberror_errorcode_fast (Shishi * handle, Shishi_asn1 krberror)
962 int i;
964 if (shishi_krberror_errorcode (handle, krberror, &i) != SHISHI_OK)
965 i = -1;
967 return i;
971 * shishi_krberror_errorcode_set:
972 * @handle: shishi handle as allocated by shishi_init().
973 * @krberror: KRB-ERROR structure with error code to set.
974 * @errorcode: new error code to set in krberror.
976 * Set the error-code field to a new error code.
978 * Return value: Returns SHISHI_OK iff successful.
981 shishi_krberror_errorcode_set (Shishi * handle,
982 Shishi_asn1 krberror, int errorcode)
984 int res;
986 res = shishi_asn1_write_int32 (handle, krberror, "error-code", errorcode);
987 if (res != SHISHI_OK)
988 return res;
990 return SHISHI_OK;
994 * shishi_krberror_etext:
995 * @handle: shishi handle as allocated by shishi_init().
996 * @krberror: KRB-ERROR structure with error code.
997 * @etext: output array with newly allocated error text.
998 * @etextlen: output length of error text.
1000 * Extract additional error text from server (possibly empty).
1002 * Return value: Returns SHISHI_OK iff successful.
1005 shishi_krberror_etext (Shishi * handle, Shishi_asn1 krberror,
1006 char **etext, size_t * etextlen)
1008 return shishi_asn1_read (handle, krberror, "e-text", etext, etextlen);
1012 * shishi_krberror_set_etext:
1013 * @handle: shishi handle as allocated by shishi_init().
1014 * @krberror: krberror as allocated by shishi_krberror().
1015 * @etext: input array with error text to set.
1017 * Set error text (e-text) field in KRB-ERROR to specified value.
1019 * Return value: Returns SHISHI_OK iff successful.
1022 shishi_krberror_set_etext (Shishi * handle,
1023 Shishi_asn1 krberror, const char *etext)
1025 int res;
1027 res = shishi_asn1_write (handle, krberror, "e-text", etext, 0);
1028 if (res != SHISHI_OK)
1029 return res;
1031 return SHISHI_OK;
1035 * shishi_krberror_remove_etext:
1036 * @handle: shishi handle as allocated by shishi_init().
1037 * @krberror: krberror as allocated by shishi_krberror().
1039 * Remove error text (e-text) field in KRB-ERROR.
1041 * Return value: Returns SHISHI_OK iff successful.
1044 shishi_krberror_remove_etext (Shishi * handle, Shishi_asn1 krberror)
1046 int res;
1048 res = shishi_asn1_write (handle, krberror, "e-text", NULL, 0);
1049 if (res != SHISHI_OK)
1050 return res;
1052 return SHISHI_OK;
1056 * shishi_krberror_edata:
1057 * @handle: shishi handle as allocated by shishi_init().
1058 * @krberror: KRB-ERROR structure with error code.
1059 * @edata: output array with newly allocated error data.
1060 * @edatalen: output length of error data.
1062 * Extract additional error data from server (possibly empty).
1064 * Return value: Returns SHISHI_OK iff successful.
1067 shishi_krberror_edata (Shishi * handle, Shishi_asn1 krberror,
1068 char **edata, size_t * edatalen)
1070 return shishi_asn1_read (handle, krberror, "e-data", edata, edatalen);
1074 * shishi_krberror_methoddata:
1075 * @handle: shishi handle as allocated by shishi_init().
1076 * @krberror: KRB-ERROR structure with error code.
1077 * @methoddata: output ASN.1 METHOD-DATA.
1079 * Extract METHOD-DATA ASN.1 object from the e-data field. The e-data
1080 * field will only contain a METHOD-DATA if the krberror error code is
1081 * %SHISHI_KDC_ERR_PREAUTH_REQUIRED.
1083 * Return value: Returns SHISHI_OK iff successful.
1086 shishi_krberror_methoddata (Shishi * handle, Shishi_asn1 krberror,
1087 Shishi_asn1 *methoddata)
1089 int rc;
1091 *methoddata = NULL;
1093 if (shishi_krberror_errorcode_fast (handle, krberror)
1094 == SHISHI_KDC_ERR_PREAUTH_REQUIRED)
1096 char *buf;
1097 size_t len;
1099 rc = shishi_krberror_edata (handle, krberror, &buf, &len);
1100 if (rc != SHISHI_OK)
1101 return rc;
1103 *methoddata = shishi_der2asn1_methoddata (handle, buf, len);
1104 free (buf);
1105 if (!*methoddata)
1106 return SHISHI_ASN1_ERROR;
1109 return SHISHI_OK;
1113 * shishi_krberror_set_edata:
1114 * @handle: shishi handle as allocated by shishi_init().
1115 * @krberror: krberror as allocated by shishi_krberror().
1116 * @edata: input array with error text to set.
1118 * Set error text (e-data) field in KRB-ERROR to specified value.
1120 * Return value: Returns SHISHI_OK iff successful.
1123 shishi_krberror_set_edata (Shishi * handle,
1124 Shishi_asn1 krberror, const char *edata)
1126 int res;
1128 res = shishi_asn1_write (handle, krberror, "e-data", edata, 0);
1129 if (res != SHISHI_OK)
1130 return res;
1132 return SHISHI_OK;
1136 * shishi_krberror_remove_edata:
1137 * @handle: shishi handle as allocated by shishi_init().
1138 * @krberror: krberror as allocated by shishi_krberror().
1140 * Remove error text (e-data) field in KRB-ERROR.
1142 * Return value: Returns SHISHI_OK iff successful.
1145 shishi_krberror_remove_edata (Shishi * handle, Shishi_asn1 krberror)
1147 int res;
1149 res = shishi_asn1_write (handle, krberror, "e-data", NULL, 0);
1150 if (res != SHISHI_OK)
1151 return res;
1153 return SHISHI_OK;
1157 * shishi_krberror_pretty_print:
1158 * @handle: shishi handle as allocated by shishi_init().
1159 * @fh: file handle opened for writing.
1160 * @krberror: KRB-ERROR structure with error code.
1162 * Print KRB-ERROR error condition and some explanatory text to file
1163 * descriptor.
1165 * Return value: Returns SHISHI_OK iff successful.
1168 shishi_krberror_pretty_print (Shishi * handle, FILE * fh,
1169 Shishi_asn1 krberror)
1171 char *buf;
1172 size_t len;
1173 int res;
1175 if (VERBOSEASN1 (handle))
1176 shishi_krberror_print (handle, fh, krberror);
1178 if (shishi_krberror_errorcode_fast (handle, krberror) ==
1179 SHISHI_KRB_ERR_GENERIC)
1181 fprintf (fh, "Generic error from server:\n");
1183 res = shishi_krberror_etext (handle, krberror, &buf, &len);
1184 if (res == SHISHI_OK && len > 0)
1186 buf[len] = '\0';
1187 fprintf (fh, "%s\n", buf);
1188 free (buf);
1191 else
1193 fprintf (fh, "Error code from server:\n%s\n",
1194 shishi_krberror_message (handle, krberror));
1196 res = shishi_krberror_etext (handle, krberror, &buf, &len);
1197 if (res == SHISHI_OK && len > 0)
1199 buf[len] = '\0';
1200 fprintf (fh, "Additional error message from server:\n%s\n", buf);
1201 free (buf);
1204 if (shishi_krberror_errorcode_fast (handle, krberror) ==
1205 SHISHI_KDC_ERR_PREAUTH_REQUIRED)
1207 Shishi_asn1 pas;
1208 size_t i, n;
1210 res = shishi_krberror_methoddata (handle, krberror, &pas);
1211 if (res != SHISHI_OK)
1212 return res;
1214 if (VERBOSEASN1 (handle))
1215 shishi_methoddata_print (handle, stdout, pas);
1217 res = shishi_asn1_number_of_elements (handle, pas, "", &n);
1218 if (res == SHISHI_OK)
1220 fprintf (fh, "Types of PA-DATA in KRB-ERROR: ");
1222 for (i = 1; i <= n; i++)
1224 char *format = xasprintf ("?%d.padata-type", i);
1225 int32_t padatatype;
1227 if (i > 1)
1228 fprintf (fh, ", ");
1230 res = shishi_asn1_read_int32 (handle, pas, format,
1231 &padatatype);
1232 if (res == SHISHI_OK)
1233 printf ("%d", padatatype);
1235 free (format);
1238 fprintf (fh, ".\n");
1241 shishi_asn1_done (handle, pas);
1246 return SHISHI_OK;
1249 struct krb_error_msgs
1251 int errorcode;
1252 const char *message;
1255 static const struct krb_error_msgs
1256 _shishi_krberror_messages[SHISHI_LAST_ERROR_CODE] = {
1257 {SHISHI_KDC_ERR_NONE,
1258 N_("No error")},
1259 {SHISHI_KDC_ERR_NAME_EXP,
1260 N_("Client's entry in database has expired")},
1261 {SHISHI_KDC_ERR_SERVICE_EXP,
1262 N_("Server's entry in database has expired")},
1263 {SHISHI_KDC_ERR_BAD_PVNO,
1264 N_("Requested protocol version number not supported")},
1265 {SHISHI_KDC_ERR_C_OLD_MAST_KVNO,
1266 N_("Client's key encrypted in old master key")},
1267 {SHISHI_KDC_ERR_S_OLD_MAST_KVNO,
1268 N_("Server's key encrypted in old master key")},
1269 {SHISHI_KDC_ERR_C_PRINCIPAL_UNKNOWN,
1270 N_("Client not found in database")},
1271 {SHISHI_KDC_ERR_S_PRINCIPAL_UNKNOWN,
1272 N_("Server not found in database")},
1273 {SHISHI_KDC_ERR_PRINCIPAL_NOT_UNIQUE,
1274 N_("Multiple principal entries in database")},
1275 {SHISHI_KDC_ERR_NULL_KEY,
1276 N_("The client or server has a null key")},
1277 {SHISHI_KDC_ERR_CANNOT_POSTDATE,
1278 N_("Ticket not eligible for postdating")},
1279 {SHISHI_KDC_ERR_NEVER_VALID,
1280 N_("Requested start time is later than end time")},
1281 {SHISHI_KDC_ERR_POLICY,
1282 N_("KDC policy rejects request")},
1283 {SHISHI_KDC_ERR_BADOPTION,
1284 N_("KDC cannot accommodate requested option")},
1285 {SHISHI_KDC_ERR_ETYPE_NOSUPP,
1286 N_("KDC has no support for encryption type")},
1287 {SHISHI_KDC_ERR_SUMTYPE_NOSUPP,
1288 N_("KDC has no support for checksum type")},
1289 {SHISHI_KDC_ERR_PADATA_TYPE_NOSUPP,
1290 N_("KDC has no support for padata type")},
1291 {SHISHI_KDC_ERR_TRTYPE_NOSUPP,
1292 N_("KDC has no support for transited type")},
1293 {SHISHI_KDC_ERR_CLIENT_REVOKED,
1294 N_("Clients credentials have been revoked")},
1295 {SHISHI_KDC_ERR_SERVICE_REVOKED,
1296 N_("Credentials for server have been revoked")},
1297 {SHISHI_KDC_ERR_TGT_REVOKED,
1298 N_("TGT has been revoked")},
1299 {SHISHI_KDC_ERR_CLIENT_NOTYET,
1300 N_("Client not yet valid - try again later")},
1301 {SHISHI_KDC_ERR_SERVICE_NOTYET,
1302 N_("Server not yet valid - try again later")},
1303 {SHISHI_KDC_ERR_KEY_EXPIRED,
1304 N_("Password has expired ")},
1305 {SHISHI_KDC_ERR_PREAUTH_FAILED,
1306 N_("Pre-authentication information was invalid")},
1307 {SHISHI_KDC_ERR_PREAUTH_REQUIRED,
1308 N_("Additional pre-authentication required")},
1309 {SHISHI_KDC_ERR_SERVER_NOMATCH,
1310 N_("Requested server and ticket don't match")},
1311 {SHISHI_KDC_ERR_MUST_USE_USER2USER,
1312 N_("Server principal valid for user2user only")},
1313 {SHISHI_KDC_ERR_PATH_NOT_ACCPETED,
1314 N_("KDC Policy rejects transited path")},
1315 {SHISHI_KDC_ERR_SVC_UNAVAILABLE,
1316 N_("A service is not available")},
1317 {SHISHI_KRB_AP_ERR_BAD_INTEGRITY,
1318 N_("Integrity check on decrypted field failed")},
1319 {SHISHI_KRB_AP_ERR_TKT_EXPIRED,
1320 N_("Ticket expired")},
1321 {SHISHI_KRB_AP_ERR_TKT_NYV,
1322 N_("Ticket not yet valid")},
1323 {SHISHI_KRB_AP_ERR_REPEAT,
1324 N_("Request is a replay")},
1325 {SHISHI_KRB_AP_ERR_NOT_US,
1326 N_("The ticket isn't for us")},
1327 {SHISHI_KRB_AP_ERR_BADMATCH,
1328 N_("Ticket and authenticator don't match")},
1329 {SHISHI_KRB_AP_ERR_SKEW,
1330 N_("Clock skew too great")},
1331 {SHISHI_KRB_AP_ERR_BADADDR,
1332 N_("Incorrect net address")},
1333 {SHISHI_KRB_AP_ERR_BADVERSION,
1334 N_("Protocol version mismatch")},
1335 {SHISHI_KRB_AP_ERR_MSG_TYPE,
1336 N_("Invalid msg type")},
1337 {SHISHI_KRB_AP_ERR_MODIFIED,
1338 N_("Message stream modified")},
1339 {SHISHI_KRB_AP_ERR_BADORDER,
1340 N_("Message out of order")},
1341 {SHISHI_KRB_AP_ERR_BADKEYVER,
1342 N_("Specified version of key is not available")},
1343 {SHISHI_KRB_AP_ERR_NOKEY,
1344 N_("Service key not available")},
1345 {SHISHI_KRB_AP_ERR_MUT_FAIL,
1346 N_("Mutual authentication failed")},
1347 {SHISHI_KRB_AP_ERR_BADDIRECTION,
1348 N_("Incorrect message direction")},
1349 {SHISHI_KRB_AP_ERR_METHOD,
1350 N_("Alternative authentication method required")},
1351 {SHISHI_KRB_AP_ERR_BADSEQ,
1352 N_("Incorrect sequence number in message")},
1353 {SHISHI_KRB_AP_ERR_INAPP_CKSUM,
1354 N_("Inappropriate type of checksum in message")},
1355 {SHISHI_KRB_AP_PATH_NOT_ACCEPTED,
1356 N_("Policy rejects transited path")},
1357 {SHISHI_KRB_ERR_RESPONSE_TOO_BIG,
1358 N_("Response too big for UDP, retry with TCP")},
1359 {SHISHI_KRB_ERR_GENERIC,
1360 N_("Generic error (description in e-text)")},
1361 {SHISHI_KRB_ERR_FIELD_TOOLONG,
1362 N_("Field is too long for this implementation")},
1363 {SHISHI_KDC_ERROR_CLIENT_NOT_TRUSTED,
1364 N_("(pkinit)")},
1365 {SHISHI_KDC_ERROR_KDC_NOT_TRUSTED,
1366 N_("(pkinit)")},
1367 {SHISHI_KDC_ERROR_INVALID_SIG,
1368 N_("(pkinit)")},
1369 {SHISHI_KDC_ERR_KEY_TOO_WEAK,
1370 N_("(pkinit)")},
1371 {SHISHI_KDC_ERR_CERTIFICATE_MISMATCH,
1372 N_("(pkinit)")},
1373 {SHISHI_KRB_AP_ERR_NO_TGT,
1374 N_("(user-to-user)")},
1375 {SHISHI_KDC_ERR_WRONG_REALM,
1376 N_("(user-to-user)")},
1377 {SHISHI_KRB_AP_ERR_USER_TO_USER_REQUIRED,
1378 N_("(user-to-user)")},
1379 {SHISHI_KDC_ERR_CANT_VERIFY_CERTIFICATE,
1380 N_("(pkinit)")},
1381 {SHISHI_KDC_ERR_INVALID_CERTIFICATE,
1382 N_("(pkinit)")},
1383 {SHISHI_KDC_ERR_REVOKED_CERTIFICATE,
1384 N_("(pkinit)")},
1385 {SHISHI_KDC_ERR_REVOCATION_STATUS_UNKNOWN,
1386 N_("(pkinit)")},
1387 {SHISHI_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE,
1388 N_("(pkinit)")},
1389 {SHISHI_KDC_ERR_CLIENT_NAME_MISMATCH,
1390 N_("(pkinit)")},
1391 {SHISHI_KDC_ERR_KDC_NAME_MISMATCH,
1392 N_("(pkinit)")}
1396 * shishi_krberror_errorcode_message:
1397 * @handle: shishi handle as allocated by shishi_init().
1398 * @errorcode: integer KRB-ERROR error code.
1400 * Get human readable string describing KRB-ERROR code.
1402 * Return value: Return a string describing error code. This function
1403 * will always return a string even if the error code
1404 * isn't known.
1406 const char *
1407 shishi_krberror_errorcode_message (Shishi * handle, int errorcode)
1409 int i;
1410 char *p;
1412 for (i = 0; i < SHISHI_LAST_ERROR_CODE; i++)
1414 if (errorcode == _shishi_krberror_messages[i].errorcode)
1415 return _(_shishi_krberror_messages[i].message);
1418 /* XXX memory leak */
1419 asprintf (&p, _("Unknown KRB-ERROR error code %d."), errorcode);
1420 return p;
1424 * shishi_krberror_message:
1425 * @handle: shishi handle as allocated by shishi_init().
1426 * @krberror: KRB-ERROR structure with error code.
1428 * Extract error code (see shishi_krberror_errorcode_fast()) and
1429 * return error message (see shishi_krberror_errorcode_message()).
1431 * Return value: Return a string describing error code. This function
1432 * will always return a string even if the error code
1433 * isn't known.
1435 const char *
1436 shishi_krberror_message (Shishi * handle, Shishi_asn1 krberror)
1438 return shishi_krberror_errorcode_message
1439 (handle, shishi_krberror_errorcode_fast (handle, krberror));