1 /* krberror.c --- Functions related to KRB-ERROR packet.
2  * Copyright (C) 2002-2013 Simon Josefsson
3  *
4  * This file is part of Shishi.
5  *
6  * Shishi is free software; you can redistribute it and/or modify it
7  * 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.
10  *
11  * Shishi is distributed in the hope that it will be useful, but
12  * 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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Shishi; if not, see http://www.gnu.org/licenses or write
18  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19  * Floor, Boston, MA 02110-1301, USA
20  *
21  */
22 
23 #include "internal.h"
24 
25 /* Get _shishi_print_armored_data, etc. */
26 #include "diskio.h"
27 
28 #define SHISHI_KRB_ERROR_DEFAULT_PVNO      "5"
29 #define SHISHI_KRB_ERROR_DEFAULT_PVNO_LEN  0
30 #define SHISHI_KRB_ERROR_DEFAULT_MSG_TYPE      "30"
31 #define SHISHI_KRB_ERROR_DEFAULT_MSG_TYPE_LEN  0
32 
33 /**
34  * shishi_krberror:
35  * @handle: shishi handle as allocated by shishi_init().
36  *
37  * This function creates a new KRB-ERROR, populated with some default
38  * values.
39  *
40  * Return value: Returns the KRB-ERROR or NULL on failure.
41  **/
42 Shishi_asn1
shishi_krberror(Shishi * handle)43 shishi_krberror (Shishi * handle)
44 {
45   Shishi_asn1 krberror;
46   struct timeval tv;
47   int rc;
48 
49   rc = gettimeofday (&tv, NULL);
50   if (rc != 0)
51     return NULL;
52 
53   krberror = shishi_asn1_krberror (handle);
54   if (!krberror)
55     return NULL;
56 
57   rc = shishi_asn1_write (handle, krberror, "pvno",
58 			  SHISHI_KRB_ERROR_DEFAULT_PVNO,
59 			  SHISHI_KRB_ERROR_DEFAULT_PVNO_LEN);
60 
61   if (rc == SHISHI_OK)
62     rc = shishi_asn1_write (handle, krberror, "msg-type",
63 			    SHISHI_KRB_ERROR_DEFAULT_MSG_TYPE,
64 			    SHISHI_KRB_ERROR_DEFAULT_MSG_TYPE_LEN);
65 
66 
67   if (rc == SHISHI_OK)
68     rc = shishi_krberror_susec_set (handle, krberror, tv.tv_usec % 1000000);
69 
70   if (rc == SHISHI_OK)
71     rc = shishi_asn1_write (handle, krberror, "stime",
72 			    shishi_generalize_now (handle), 0);
73 
74   if (rc != SHISHI_OK)
75     {
76       shishi_error_printf (handle, "shishi_krberror() failed");
77       shishi_asn1_done (handle, krberror);
78       krberror = NULL;
79     }
80 
81   return krberror;
82 }
83 
84 /**
85  * shishi_krberror_print:
86  * @handle: shishi handle as allocated by shishi_init().
87  * @fh: file handle open for writing.
88  * @krberror: KRB-ERROR to print.
89  *
90  * Print ASCII armored DER encoding of KRB-ERROR to file.
91  *
92  * Return value: Returns SHISHI_OK iff successful.
93  **/
94 int
shishi_krberror_print(Shishi * handle,FILE * fh,Shishi_asn1 krberror)95 shishi_krberror_print (Shishi * handle, FILE * fh, Shishi_asn1 krberror)
96 {
97   return _shishi_print_armored_data (handle, fh, krberror, "KRB-ERROR", NULL);
98 }
99 
100 /**
101  * shishi_krberror_save:
102  * @handle: shishi handle as allocated by shishi_init().
103  * @fh: file handle open for writing.
104  * @krberror: KRB-ERROR to save.
105  *
106  * Save DER encoding of KRB-ERROR to file.
107  *
108  * Return value: Returns SHISHI_OK iff successful.
109  **/
110 int
shishi_krberror_save(Shishi * handle,FILE * fh,Shishi_asn1 krberror)111 shishi_krberror_save (Shishi * handle, FILE * fh, Shishi_asn1 krberror)
112 {
113   return _shishi_save_data (handle, fh, krberror, "KRB-ERROR");
114 }
115 
116 /**
117  * shishi_krberror_to_file:
118  * @handle: shishi handle as allocated by shishi_init().
119  * @krberror: KRB-ERROR to save.
120  * @filetype: input variable specifying type of file to be written,
121  *            see Shishi_filetype.
122  * @filename: input variable with filename to write to.
123  *
124  * Write KRB-ERROR to file in specified TYPE.  The file will be
125  * truncated if it exists.
126  *
127  * Return value: Returns SHISHI_OK iff successful.
128  **/
129 int
shishi_krberror_to_file(Shishi * handle,Shishi_asn1 krberror,int filetype,const char * filename)130 shishi_krberror_to_file (Shishi * handle, Shishi_asn1 krberror,
131 			 int filetype, const char *filename)
132 {
133   FILE *fh;
134   int res;
135 
136   if (VERBOSE (handle))
137     printf (_("Writing KRB-ERROR to %s...\n"), filename);
138 
139   fh = fopen (filename, "w");
140   if (fh == NULL)
141     return SHISHI_FOPEN_ERROR;
142 
143   if (VERBOSE (handle))
144     printf (_("Writing KRB-ERROR in %s format...\n"),
145 	    filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
146 
147   if (filetype == SHISHI_FILETYPE_TEXT)
148     res = shishi_krberror_print (handle, fh, krberror);
149   else
150     res = shishi_krberror_save (handle, fh, krberror);
151   if (res != SHISHI_OK)
152     return res;
153 
154   res = fclose (fh);
155   if (res != 0)
156     return SHISHI_IO_ERROR;
157 
158   if (VERBOSE (handle))
159     printf (_("Writing KRB-ERROR to %s...done\n"), filename);
160 
161   return SHISHI_OK;
162 }
163 
164 /**
165  * shishi_krberror_parse:
166  * @handle: shishi handle as allocated by shishi_init().
167  * @fh: file handle open for reading.
168  * @krberror: output variable with newly allocated KRB-ERROR.
169  *
170  * Read ASCII armored DER encoded KRB-ERROR from file and populate given
171  * variable.
172  *
173  * Return value: Returns SHISHI_OK iff successful.
174  **/
175 int
shishi_krberror_parse(Shishi * handle,FILE * fh,Shishi_asn1 * krberror)176 shishi_krberror_parse (Shishi * handle, FILE * fh, Shishi_asn1 * krberror)
177 {
178   return _shishi_krberror_input (handle, fh, krberror, 0);
179 }
180 
181 /**
182  * shishi_krberror_read:
183  * @handle: shishi handle as allocated by shishi_init().
184  * @fh: file handle open for reading.
185  * @krberror: output variable with newly allocated KRB-ERROR.
186  *
187  * Read DER encoded KRB-ERROR from file and populate given variable.
188  *
189  * Return value: Returns SHISHI_OK iff successful.
190  **/
191 int
shishi_krberror_read(Shishi * handle,FILE * fh,Shishi_asn1 * krberror)192 shishi_krberror_read (Shishi * handle, FILE * fh, Shishi_asn1 * krberror)
193 {
194   return _shishi_krberror_input (handle, fh, krberror, 1);
195 }
196 
197 /**
198  * shishi_krberror_from_file:
199  * @handle: shishi handle as allocated by shishi_init().
200  * @krberror: output variable with newly allocated KRB-ERROR.
201  * @filetype: input variable specifying type of file to be read,
202  *            see Shishi_filetype.
203  * @filename: input variable with filename to read from.
204  *
205  * Read KRB-ERROR from file in specified TYPE.
206  *
207  * Return value: Returns SHISHI_OK iff successful.
208  **/
209 int
shishi_krberror_from_file(Shishi * handle,Shishi_asn1 * krberror,int filetype,const char * filename)210 shishi_krberror_from_file (Shishi * handle, Shishi_asn1 * krberror,
211 			   int filetype, const char *filename)
212 {
213   int res;
214   FILE *fh;
215 
216   if (VERBOSE (handle))
217     printf (_("Reading KRB-ERROR from %s...\n"), filename);
218 
219   fh = fopen (filename, "r");
220   if (fh == NULL)
221     return SHISHI_FOPEN_ERROR;
222 
223   if (VERBOSE (handle))
224     printf (_("Reading KRB-ERROR in %s format...\n"),
225 	    filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
226 
227   if (filetype == SHISHI_FILETYPE_TEXT)
228     res = shishi_krberror_parse (handle, fh, krberror);
229   else
230     res = shishi_krberror_read (handle, fh, krberror);
231   if (res != SHISHI_OK)
232     return res;
233 
234   res = fclose (fh);
235   if (res != 0)
236     return SHISHI_IO_ERROR;
237 
238   if (VERBOSE (handle))
239     printf (_("Reading KRB-ERROR from %s...done\n"), filename);
240 
241   return SHISHI_OK;
242 }
243 
244 /**
245  * shishi_krberror_build:
246  * @handle: shishi handle as allocated by shishi_init().
247  * @krberror: krberror as allocated by shishi_krberror().
248  *
249  * Finish KRB-ERROR, called before e.g. shishi_krberror_der.  This
250  * function removes empty but OPTIONAL fields (such as cname), and
251  *
252  * Return value: Returns SHISHI_OK iff successful.
253  **/
254 int
shishi_krberror_build(Shishi * handle,Shishi_asn1 krberror)255 shishi_krberror_build (Shishi * handle, Shishi_asn1 krberror)
256 {
257   char *t;
258   size_t tmplen = sizeof (t);
259   char *tmp;
260   int32_t errc;
261   uint32_t usec;
262   int rc;
263 
264   rc = shishi_krberror_ctime (handle, krberror, &t);
265   if (rc != SHISHI_OK &&
266       rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
267     return rc;
268   free (t);
269   if (rc == SHISHI_ASN1_NO_VALUE)
270     {
271       rc = shishi_krberror_remove_ctime (handle, krberror);
272       if (rc != SHISHI_OK)
273 	return rc;
274     }
275 
276   rc = shishi_krberror_cusec (handle, krberror, &usec);
277   if (rc != SHISHI_OK &&
278       rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
279     return rc;
280   if (rc == SHISHI_ASN1_NO_VALUE)
281     {
282       rc = shishi_krberror_remove_cusec (handle, krberror);
283       if (rc != SHISHI_OK)
284 	return rc;
285     }
286 
287   rc = shishi_krberror_crealm (handle, krberror, &tmp, &tmplen);
288   if (rc != SHISHI_OK &&
289       rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
290     return rc;
291   if (rc == SHISHI_OK)
292     free (tmp);
293   if (rc == SHISHI_ASN1_NO_VALUE)
294     {
295       rc = shishi_krberror_remove_crealm (handle, krberror);
296       if (rc != SHISHI_OK)
297 	return rc;
298     }
299 
300   rc = shishi_krberror_client (handle, krberror, &tmp, &tmplen);
301   if (rc != SHISHI_OK &&
302       rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
303     return rc;
304   if (rc == SHISHI_OK)
305     free (tmp);
306   if (rc == SHISHI_ASN1_NO_VALUE || (rc == SHISHI_OK && tmplen == 0))
307     {
308       rc = shishi_krberror_remove_cname (handle, krberror);
309       if (rc != SHISHI_OK)
310 	return rc;
311     }
312 
313   rc = shishi_krberror_realm (handle, krberror, &tmp, &tmplen);
314   if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_VALUE)
315     return rc;
316   if (rc == SHISHI_OK)
317     free (tmp);
318   if (rc == SHISHI_ASN1_NO_VALUE)
319     {
320       rc = shishi_krberror_set_realm (handle, krberror, "");
321       if (rc != SHISHI_OK)
322 	return rc;
323     }
324 
325   rc = shishi_krberror_server (handle, krberror, &tmp, &tmplen);
326   if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_VALUE)
327     return rc;
328   if (rc == SHISHI_OK)
329     free (tmp);
330   if (rc == SHISHI_ASN1_NO_VALUE || tmplen == 0)
331     {
332       rc = shishi_krberror_remove_sname (handle, krberror);
333       if (rc != SHISHI_OK)
334 	return rc;
335     }
336 
337   rc = shishi_krberror_edata (handle, krberror, &tmp, &tmplen);
338   if (rc != SHISHI_OK &&
339       rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
340     return rc;
341   if (rc == SHISHI_OK)
342     free (tmp);
343   if (rc == SHISHI_ASN1_NO_VALUE || (rc == SHISHI_OK && tmplen == 0))
344     {
345       rc = shishi_krberror_remove_edata (handle, krberror);
346       if (rc != SHISHI_OK)
347 	return rc;
348     }
349 
350   rc = shishi_krberror_errorcode (handle, krberror, &errc);
351   if (rc != SHISHI_OK && rc != SHISHI_ASN1_NO_VALUE)
352     return rc;
353   if (rc == SHISHI_ASN1_NO_VALUE)
354     {
355       rc = shishi_krberror_errorcode_set (handle, krberror,
356 					  SHISHI_KRB_ERR_GENERIC);
357       if (rc != SHISHI_OK)
358 	return rc;
359     }
360 
361   rc = shishi_krberror_etext (handle, krberror, &tmp, &tmplen);
362   if (rc != SHISHI_OK &&
363       rc != SHISHI_ASN1_NO_ELEMENT && rc != SHISHI_ASN1_NO_VALUE)
364     return rc;
365   if (rc == SHISHI_OK)
366     free (tmp);
367   if (rc == SHISHI_ASN1_NO_VALUE || (rc == SHISHI_OK && tmplen == 0))
368     {
369       if (shishi_krberror_errorcode_fast (handle, krberror) ==
370 	  SHISHI_KRB_ERR_GENERIC)
371 	rc = shishi_krberror_set_etext (handle, krberror,
372 					"Uninitialized error");
373       else
374 	rc = shishi_krberror_remove_etext (handle, krberror);
375       if (rc != SHISHI_OK)
376 	return rc;
377     }
378 
379   return SHISHI_OK;
380 }
381 
382 /**
383  * shishi_krberror_der:
384  * @handle: shishi handle as allocated by shishi_init().
385  * @krberror: krberror as allocated by shishi_krberror().
386  * @out: output array with newly allocated DER encoding of KRB-ERROR.
387  * @outlen: length of output array with DER encoding of KRB-ERROR.
388  *
389  * DER encode KRB-ERROR.  The caller must deallocate the OUT buffer.
390  *
391  * Return value: Returns SHISHI_OK iff successful.
392  **/
393 int
shishi_krberror_der(Shishi * handle,Shishi_asn1 krberror,char ** out,size_t * outlen)394 shishi_krberror_der (Shishi * handle,
395 		     Shishi_asn1 krberror, char **out, size_t * outlen)
396 {
397   int rc;
398 
399   rc = shishi_krberror_build (handle, krberror);
400   if (rc != SHISHI_OK)
401     return rc;
402 
403   rc = shishi_asn1_to_der (handle, krberror, out, outlen);
404   if (rc != SHISHI_OK)
405     return rc;
406 
407   return SHISHI_OK;
408 }
409 
410 /**
411  * shishi_krberror_crealm:
412  * @handle: shishi handle as allocated by shishi_init().
413  * @krberror: krberror as allocated by shishi_krberror().
414  * @realm: output array with newly allocated name of realm in KRB-ERROR.
415  * @realmlen: size of output array.
416  *
417  * Extract client realm from KRB-ERROR.
418  *
419  * Return value: Returns SHISHI_OK iff successful.
420  **/
421 int
shishi_krberror_crealm(Shishi * handle,Shishi_asn1 krberror,char ** realm,size_t * realmlen)422 shishi_krberror_crealm (Shishi * handle,
423 			Shishi_asn1 krberror, char **realm, size_t * realmlen)
424 {
425   return shishi_asn1_read (handle, krberror, "crealm", realm, realmlen);
426 }
427 
428 /**
429  * shishi_krberror_remove_crealm:
430  * @handle: shishi handle as allocated by shishi_init().
431  * @krberror: krberror as allocated by shishi_krberror().
432  *
433  * Remove client realm field in KRB-ERROR.
434  *
435  * Return value: Returns SHISHI_OK iff successful.
436  **/
437 int
shishi_krberror_remove_crealm(Shishi * handle,Shishi_asn1 krberror)438 shishi_krberror_remove_crealm (Shishi * handle, Shishi_asn1 krberror)
439 {
440   int res;
441 
442   res = shishi_asn1_write (handle, krberror, "crealm", NULL, 0);
443   if (res != SHISHI_OK)
444     return res;
445 
446   return SHISHI_OK;
447 }
448 
449 /**
450  * shishi_krberror_set_crealm:
451  * @handle: shishi handle as allocated by shishi_init().
452  * @krberror: krberror as allocated by shishi_krberror().
453  * @crealm: input array with realm.
454  *
455  * Set realm field in krberror to specified value.
456  *
457  * Return value: Returns SHISHI_OK iff successful.
458  **/
459 int
shishi_krberror_set_crealm(Shishi * handle,Shishi_asn1 krberror,const char * crealm)460 shishi_krberror_set_crealm (Shishi * handle,
461 			    Shishi_asn1 krberror, const char *crealm)
462 {
463   int res;
464 
465   res = shishi_asn1_write (handle, krberror, "crealm", crealm, 0);
466   if (res != SHISHI_OK)
467     return res;
468 
469   return SHISHI_OK;
470 }
471 
472 /**
473  * shishi_krberror_client:
474  * @handle: shishi handle as allocated by shishi_init().
475  * @krberror: krberror as allocated by shishi_krberror().
476  * @client: pointer to newly allocated zero terminated string containing
477  *   principal name.  May be %NULL (to only populate @clientlen).
478  * @clientlen: pointer to length of @client on output, excluding terminating
479  *   zero.  May be %NULL (to only populate @client).
480  *
481  * Return client principal name in KRB-ERROR.
482  *
483  * Return value: Returns SHISHI_OK iff successful.
484  **/
485 int
shishi_krberror_client(Shishi * handle,Shishi_asn1 krberror,char ** client,size_t * clientlen)486 shishi_krberror_client (Shishi * handle,
487 			Shishi_asn1 krberror,
488 			char **client, size_t * clientlen)
489 {
490   int rc;
491 
492   rc = shishi_principal_name (handle, krberror, "cname", client, clientlen);
493   if (rc != SHISHI_OK)
494     return rc;
495 
496   return SHISHI_OK;
497 }
498 
499 /**
500  * shishi_krberror_set_cname:
501  * @handle: shishi handle as allocated by shishi_init().
502  * @krberror: krberror as allocated by shishi_krberror().
503  * @name_type: type of principial, see Shishi_name_type, usually
504  *             SHISHI_NT_UNKNOWN.
505  * @cname: input array with principal name.
506  *
507  * Set principal field in krberror to specified value.
508  *
509  * Return value: Returns SHISHI_OK iff successful.
510  **/
511 int
shishi_krberror_set_cname(Shishi * handle,Shishi_asn1 krberror,Shishi_name_type name_type,const char * cname[])512 shishi_krberror_set_cname (Shishi * handle,
513 			   Shishi_asn1 krberror,
514 			   Shishi_name_type name_type, const char *cname[])
515 {
516   int res;
517 
518   res = shishi_principal_name_set (handle, krberror, "cname",
519 				   name_type, cname);
520   if (res != SHISHI_OK)
521     return res;
522 
523   return SHISHI_OK;
524 }
525 
526 /**
527  * shishi_krberror_remove_cname:
528  * @handle: shishi handle as allocated by shishi_init().
529  * @krberror: krberror as allocated by shishi_krberror().
530  *
531  * Remove client realm field in KRB-ERROR.
532  *
533  * Return value: Returns SHISHI_OK iff successful.
534  **/
535 int
shishi_krberror_remove_cname(Shishi * handle,Shishi_asn1 krberror)536 shishi_krberror_remove_cname (Shishi * handle, Shishi_asn1 krberror)
537 {
538   int res;
539 
540   res = shishi_asn1_write (handle, krberror, "cname", NULL, 0);
541   if (res != SHISHI_OK)
542     return res;
543 
544   return SHISHI_OK;
545 }
546 
547 /**
548  * shishi_krberror_client_set:
549  * @handle: shishi handle as allocated by shishi_init().
550  * @krberror: Krberror to set client name field in.
551  * @client: zero-terminated string with principal name on RFC 1964 form.
552  *
553  * Set the client name field in the Krberror.
554  *
555  * Return value: Returns SHISHI_OK iff successful.
556  **/
557 int
shishi_krberror_client_set(Shishi * handle,Shishi_asn1 krberror,const char * client)558 shishi_krberror_client_set (Shishi * handle,
559 			    Shishi_asn1 krberror, const char *client)
560 {
561   int res;
562 
563   res = shishi_principal_set (handle, krberror, "cname", client);
564   if (res != SHISHI_OK)
565     return res;
566 
567   return SHISHI_OK;
568 }
569 
570 /**
571  * shishi_krberror_realm:
572  * @handle: shishi handle as allocated by shishi_init().
573  * @krberror: krberror as allocated by shishi_krberror().
574  * @realm: output array with newly allocated name of realm in KRB-ERROR.
575  * @realmlen: size of output array.
576  *
577  * Extract (server) realm from KRB-ERROR.
578  *
579  * Return value: Returns SHISHI_OK iff successful.
580  **/
581 int
shishi_krberror_realm(Shishi * handle,Shishi_asn1 krberror,char ** realm,size_t * realmlen)582 shishi_krberror_realm (Shishi * handle,
583 		       Shishi_asn1 krberror, char **realm, size_t * realmlen)
584 {
585   return shishi_asn1_read (handle, krberror, "realm", realm, realmlen);
586 }
587 
588 /**
589  * shishi_krberror_set_realm:
590  * @handle: shishi handle as allocated by shishi_init().
591  * @krberror: krberror as allocated by shishi_krberror().
592  * @realm: input array with (server) realm.
593  *
594  * Set (server) realm field in krberror to specified value.
595  *
596  * Return value: Returns SHISHI_OK iff successful.
597  **/
598 int
shishi_krberror_set_realm(Shishi * handle,Shishi_asn1 krberror,const char * realm)599 shishi_krberror_set_realm (Shishi * handle,
600 			   Shishi_asn1 krberror, const char *realm)
601 {
602   int res;
603 
604   res = shishi_asn1_write (handle, krberror, "realm", realm, 0);
605   if (res != SHISHI_OK)
606     return res;
607 
608   return SHISHI_OK;
609 }
610 
611 /**
612  * shishi_krberror_server:
613  * @handle: shishi handle as allocated by shishi_init().
614  * @krberror: krberror as allocated by shishi_krberror().
615  * @server: pointer to newly allocated zero terminated string containing
616  *   server name.  May be %NULL (to only populate @serverlen).
617  * @serverlen: pointer to length of @server on output, excluding terminating
618  *   zero.  May be %NULL (to only populate @server).
619  *
620  * Return server principal name in KRB-ERROR.
621  *
622  * Return value: Returns SHISHI_OK iff successful.
623  **/
624 int
shishi_krberror_server(Shishi * handle,Shishi_asn1 krberror,char ** server,size_t * serverlen)625 shishi_krberror_server (Shishi * handle,
626 			Shishi_asn1 krberror,
627 			char **server, size_t * serverlen)
628 {
629   int rc;
630 
631   rc = shishi_principal_name (handle, krberror, "sname", server, serverlen);
632   if (rc != SHISHI_OK)
633     return rc;
634 
635   return SHISHI_OK;
636 }
637 
638 /**
639  * shishi_krberror_remove_sname:
640  * @handle: shishi handle as allocated by shishi_init().
641  * @krberror: Krberror to set server name field in.
642  *
643  * Remove server name field in KRB-ERROR.  (Since it is not marked
644  * OPTIONAL in the ASN.1 profile, what is done is to set the name-type
645  * to UNKNOWN and make sure the name-string sequence is empty.)
646  *
647  * Return value: Returns SHISHI_OK iff successful.
648  **/
649 int
shishi_krberror_remove_sname(Shishi * handle,Shishi_asn1 krberror)650 shishi_krberror_remove_sname (Shishi * handle, Shishi_asn1 krberror)
651 {
652   int res;
653 
654   res = shishi_asn1_write_int32 (handle, krberror, "sname.name-type",
655 				 SHISHI_NT_UNKNOWN);
656   if (res != SHISHI_OK)
657     return res;
658 
659   res = shishi_asn1_write (handle, krberror, "sname.name-string", NULL, 0);
660   if (res != SHISHI_OK)
661     return res;
662 
663   return SHISHI_OK;
664 }
665 
666 /**
667  * shishi_krberror_set_sname:
668  * @handle: shishi handle as allocated by shishi_init().
669  * @krberror: krberror as allocated by shishi_krberror().
670  * @name_type: type of principial, see Shishi_name_type, usually
671  *             SHISHI_NT_UNKNOWN.
672  * @sname: input array with principal name.
673  *
674  * Set principal field in krberror to specified value.
675  *
676  * Return value: Returns SHISHI_OK iff successful.
677  **/
678 int
shishi_krberror_set_sname(Shishi * handle,Shishi_asn1 krberror,Shishi_name_type name_type,const char * sname[])679 shishi_krberror_set_sname (Shishi * handle,
680 			   Shishi_asn1 krberror,
681 			   Shishi_name_type name_type, const char *sname[])
682 {
683   int res;
684 
685   res = shishi_principal_name_set (handle, krberror, "sname",
686 				   name_type, sname);
687   if (res != SHISHI_OK)
688     return res;
689 
690   return SHISHI_OK;
691 }
692 
693 /**
694  * shishi_krberror_server_set:
695  * @handle: shishi handle as allocated by shishi_init().
696  * @krberror: Krberror to set server name field in.
697  * @server: zero-terminated string with principal name on RFC 1964 form.
698  *
699  * Set the server name field in the Krberror.
700  *
701  * Return value: Returns SHISHI_OK iff successful.
702  **/
703 int
shishi_krberror_server_set(Shishi * handle,Shishi_asn1 krberror,const char * server)704 shishi_krberror_server_set (Shishi * handle,
705 			    Shishi_asn1 krberror, const char *server)
706 {
707   int res;
708 
709   res = shishi_principal_set (handle, krberror, "sname", server);
710   if (res != SHISHI_OK)
711     return res;
712 
713   return SHISHI_OK;
714 }
715 
716 /**
717  * shishi_krberror_ctime:
718  * @handle: shishi handle as allocated by shishi_init().
719  * @krberror: Krberror to set client name field in.
720  * @t: newly allocated zero-terminated output array with client time.
721  *
722  * Extract client time from KRB-ERROR.
723  *
724  * Return value: Returns SHISHI_OK iff successful.
725  **/
726 int
shishi_krberror_ctime(Shishi * handle,Shishi_asn1 krberror,char ** t)727 shishi_krberror_ctime (Shishi * handle, Shishi_asn1 krberror, char **t)
728 {
729   return shishi_time (handle, krberror, "ctime", t);
730 }
731 
732 /**
733  * shishi_krberror_ctime_set:
734  * @handle: shishi handle as allocated by shishi_init().
735  * @krberror: Krberror as allocated by shishi_krberror().
736  * @t: string with generalized time value to store in Krberror.
737  *
738  * Store client time in Krberror.
739  *
740  * Return value: Returns SHISHI_OK iff successful.
741  **/
742 int
shishi_krberror_ctime_set(Shishi * handle,Shishi_asn1 krberror,const char * t)743 shishi_krberror_ctime_set (Shishi * handle,
744 			   Shishi_asn1 krberror, const char *t)
745 {
746   int res;
747 
748   if (t)
749     res = shishi_asn1_write (handle, krberror, "ctime",
750 			     t, SHISHI_GENERALIZEDTIME_LENGTH);
751   else
752     res = shishi_asn1_write (handle, krberror, "ctime", NULL, 0);
753   if (res != SHISHI_OK)
754     return res;
755 
756   return SHISHI_OK;
757 }
758 
759 /**
760  * shishi_krberror_remove_ctime:
761  * @handle: shishi handle as allocated by shishi_init().
762  * @krberror: Krberror as allocated by shishi_krberror().
763  *
764  * Remove client time field in Krberror.
765  *
766  * Return value: Returns SHISHI_OK iff successful.
767  **/
768 int
shishi_krberror_remove_ctime(Shishi * handle,Shishi_asn1 krberror)769 shishi_krberror_remove_ctime (Shishi * handle, Shishi_asn1 krberror)
770 {
771   int res;
772 
773   res = shishi_asn1_write (handle, krberror, "ctime", NULL, 0);
774   if (res != SHISHI_OK)
775     return res;
776 
777   return SHISHI_OK;
778 }
779 
780 /**
781  * shishi_krberror_cusec:
782  * @handle: shishi handle as allocated by shishi_init().
783  * @krberror: Krberror as allocated by shishi_krberror().
784  * @cusec: output integer with client microseconds field.
785  *
786  * Extract client microseconds field from Krberror.
787  *
788  * Return value: Returns SHISHI_OK iff successful.
789  **/
790 int
shishi_krberror_cusec(Shishi * handle,Shishi_asn1 krberror,uint32_t * cusec)791 shishi_krberror_cusec (Shishi * handle, Shishi_asn1 krberror,
792 		       uint32_t * cusec)
793 {
794   int res;
795 
796   res = shishi_asn1_read_uint32 (handle, krberror, "cusec", cusec);
797   if (res != SHISHI_OK)
798     return res;
799 
800   return SHISHI_OK;
801 }
802 
803 /**
804  * shishi_krberror_cusec_set:
805  * @handle: shishi handle as allocated by shishi_init().
806  * @krberror: krberror as allocated by shishi_krberror().
807  * @cusec: client microseconds to set in krberror, 0-999999.
808  *
809  * Set the cusec field in the Krberror.
810  *
811  * Return value: Returns SHISHI_OK iff successful.
812  **/
813 int
shishi_krberror_cusec_set(Shishi * handle,Shishi_asn1 krberror,uint32_t cusec)814 shishi_krberror_cusec_set (Shishi * handle,
815 			   Shishi_asn1 krberror, uint32_t cusec)
816 {
817   int res;
818 
819   res = shishi_asn1_write_uint32 (handle, krberror, "cusec", cusec);
820   if (res != SHISHI_OK)
821     return res;
822 
823   return SHISHI_OK;
824 }
825 
826 /**
827  * shishi_krberror_remove_cusec:
828  * @handle: shishi handle as allocated by shishi_init().
829  * @krberror: Krberror as allocated by shishi_krberror().
830  *
831  * Remove client usec field in Krberror.
832  *
833  * Return value: Returns SHISHI_OK iff successful.
834  **/
835 int
shishi_krberror_remove_cusec(Shishi * handle,Shishi_asn1 krberror)836 shishi_krberror_remove_cusec (Shishi * handle, Shishi_asn1 krberror)
837 {
838   int res;
839 
840   res = shishi_asn1_write (handle, krberror, "cusec", NULL, 0);
841   if (res != SHISHI_OK)
842     return res;
843 
844   return SHISHI_OK;
845 }
846 
847 /**
848  * shishi_krberror_stime:
849  * @handle: shishi handle as allocated by shishi_init().
850  * @krberror: Krberror to set client name field in.
851  * @t: newly allocated zero-terminated output array with server time.
852  *
853  * Extract server time from KRB-ERROR.
854  *
855  * Return value: Returns SHISHI_OK iff successful.
856  **/
857 int
shishi_krberror_stime(Shishi * handle,Shishi_asn1 krberror,char ** t)858 shishi_krberror_stime (Shishi * handle, Shishi_asn1 krberror, char **t)
859 {
860   return shishi_time (handle, krberror, "stime", t);
861 }
862 
863 /**
864  * shishi_krberror_stime_set:
865  * @handle: shishi handle as allocated by shishi_init().
866  * @krberror: Krberror as allocated by shishi_krberror().
867  * @t: string with generalized time value to store in Krberror.
868  *
869  * Store server time in Krberror.
870  *
871  * Return value: Returns SHISHI_OK iff successful.
872  **/
873 int
shishi_krberror_stime_set(Shishi * handle,Shishi_asn1 krberror,const char * t)874 shishi_krberror_stime_set (Shishi * handle,
875 			   Shishi_asn1 krberror, const char *t)
876 {
877   int res;
878 
879   res = shishi_asn1_write (handle, krberror, "stime",
880 			   t, SHISHI_GENERALIZEDTIME_LENGTH);
881   if (res != SHISHI_OK)
882     return res;
883 
884   return SHISHI_OK;
885 }
886 
887 /**
888  * shishi_krberror_susec:
889  * @handle: shishi handle as allocated by shishi_init().
890  * @krberror: Krberror as allocated by shishi_krberror().
891  * @susec: output integer with server microseconds field.
892  *
893  * Extract server microseconds field from Krberror.
894  *
895  * Return value: Returns SHISHI_OK iff successful.
896  **/
897 int
shishi_krberror_susec(Shishi * handle,Shishi_asn1 krberror,uint32_t * susec)898 shishi_krberror_susec (Shishi * handle,
899 		       Shishi_asn1 krberror, uint32_t * susec)
900 {
901   int res;
902 
903   res = shishi_asn1_read_uint32 (handle, krberror, "susec", susec);
904   if (res != SHISHI_OK)
905     return res;
906 
907   return SHISHI_OK;
908 }
909 
910 /**
911  * shishi_krberror_susec_set:
912  * @handle: shishi handle as allocated by shishi_init().
913  * @krberror: krberror as allocated by shishi_krberror().
914  * @susec: server microseconds to set in krberror, 0-999999.
915  *
916  * Set the susec field in the Krberror.
917  *
918  * Return value: Returns SHISHI_OK iff successful.
919  **/
920 int
shishi_krberror_susec_set(Shishi * handle,Shishi_asn1 krberror,uint32_t susec)921 shishi_krberror_susec_set (Shishi * handle,
922 			   Shishi_asn1 krberror, uint32_t susec)
923 {
924   int res;
925 
926   res = shishi_asn1_write_uint32 (handle, krberror, "susec", susec);
927   if (res != SHISHI_OK)
928     return res;
929 
930   return SHISHI_OK;
931 }
932 
933 /**
934  * shishi_krberror_errorcode:
935  * @handle: shishi handle as allocated by shishi_init().
936  * @krberror: KRB-ERROR structure with error code.
937  * @errorcode: output integer KRB-ERROR error code.
938  *
939  * Extract error code from KRB-ERROR.
940  *
941  * Return value: Returns SHISHI_OK iff successful.
942  **/
943 int
shishi_krberror_errorcode(Shishi * handle,Shishi_asn1 krberror,int32_t * errorcode)944 shishi_krberror_errorcode (Shishi * handle,
945 			   Shishi_asn1 krberror, int32_t * errorcode)
946 {
947   return shishi_asn1_read_int32 (handle, krberror, "error-code", errorcode);
948 }
949 
950 /**
951  * shishi_krberror_errorcode_fast:
952  * @handle: shishi handle as allocated by shishi_init().
953  * @krberror: KRB-ERROR structure with error code.
954  *
955  * Get error code from KRB-ERROR, without error checking.
956  *
957  * Return value: Return error code (see shishi_krberror_errorcode())
958  *               directly, or -1 on error.
959  **/
960 int
shishi_krberror_errorcode_fast(Shishi * handle,Shishi_asn1 krberror)961 shishi_krberror_errorcode_fast (Shishi * handle, Shishi_asn1 krberror)
962 {
963   int i;
964 
965   if (shishi_krberror_errorcode (handle, krberror, &i) != SHISHI_OK)
966     i = -1;
967 
968   return i;
969 }
970 
971 /**
972  * shishi_krberror_errorcode_set:
973  * @handle: shishi handle as allocated by shishi_init().
974  * @krberror: KRB-ERROR structure with error code to set.
975  * @errorcode: new error code to set in krberror.
976  *
977  * Set the error-code field to a new error code.
978  *
979  * Return value: Returns SHISHI_OK iff successful.
980  **/
981 int
shishi_krberror_errorcode_set(Shishi * handle,Shishi_asn1 krberror,int errorcode)982 shishi_krberror_errorcode_set (Shishi * handle,
983 			       Shishi_asn1 krberror, int errorcode)
984 {
985   int res;
986 
987   res = shishi_asn1_write_int32 (handle, krberror, "error-code", errorcode);
988   if (res != SHISHI_OK)
989     return res;
990 
991   return SHISHI_OK;
992 }
993 
994 /**
995  * shishi_krberror_etext:
996  * @handle: shishi handle as allocated by shishi_init().
997  * @krberror: KRB-ERROR structure with error code.
998  * @etext: output array with newly allocated error text.
999  * @etextlen: output length of error text.
1000  *
1001  * Extract additional error text from server (possibly empty).
1002  *
1003  * Return value: Returns SHISHI_OK iff successful.
1004  **/
1005 int
shishi_krberror_etext(Shishi * handle,Shishi_asn1 krberror,char ** etext,size_t * etextlen)1006 shishi_krberror_etext (Shishi * handle, Shishi_asn1 krberror,
1007 		       char **etext, size_t * etextlen)
1008 {
1009   return shishi_asn1_read (handle, krberror, "e-text", etext, etextlen);
1010 }
1011 
1012 /**
1013  * shishi_krberror_set_etext:
1014  * @handle: shishi handle as allocated by shishi_init().
1015  * @krberror: krberror as allocated by shishi_krberror().
1016  * @etext: input array with error text to set.
1017  *
1018  * Set error text (e-text) field in KRB-ERROR to specified value.
1019  *
1020  * Return value: Returns SHISHI_OK iff successful.
1021  **/
1022 int
shishi_krberror_set_etext(Shishi * handle,Shishi_asn1 krberror,const char * etext)1023 shishi_krberror_set_etext (Shishi * handle,
1024 			   Shishi_asn1 krberror, const char *etext)
1025 {
1026   int res;
1027 
1028   res = shishi_asn1_write (handle, krberror, "e-text", etext, 0);
1029   if (res != SHISHI_OK)
1030     return res;
1031 
1032   return SHISHI_OK;
1033 }
1034 
1035 /**
1036  * shishi_krberror_remove_etext:
1037  * @handle: shishi handle as allocated by shishi_init().
1038  * @krberror: krberror as allocated by shishi_krberror().
1039  *
1040  * Remove error text (e-text) field in KRB-ERROR.
1041  *
1042  * Return value: Returns SHISHI_OK iff successful.
1043  **/
1044 int
shishi_krberror_remove_etext(Shishi * handle,Shishi_asn1 krberror)1045 shishi_krberror_remove_etext (Shishi * handle, Shishi_asn1 krberror)
1046 {
1047   int res;
1048 
1049   res = shishi_asn1_write (handle, krberror, "e-text", NULL, 0);
1050   if (res != SHISHI_OK)
1051     return res;
1052 
1053   return SHISHI_OK;
1054 }
1055 
1056 /**
1057  * shishi_krberror_edata:
1058  * @handle: shishi handle as allocated by shishi_init().
1059  * @krberror: KRB-ERROR structure with error code.
1060  * @edata: output array with newly allocated error data.
1061  * @edatalen: output length of error data.
1062  *
1063  * Extract additional error data from server (possibly empty).
1064  *
1065  * Return value: Returns SHISHI_OK iff successful.
1066  **/
1067 int
shishi_krberror_edata(Shishi * handle,Shishi_asn1 krberror,char ** edata,size_t * edatalen)1068 shishi_krberror_edata (Shishi * handle, Shishi_asn1 krberror,
1069 		       char **edata, size_t * edatalen)
1070 {
1071   return shishi_asn1_read (handle, krberror, "e-data", edata, edatalen);
1072 }
1073 
1074 /**
1075  * shishi_krberror_methoddata:
1076  * @handle: shishi handle as allocated by shishi_init().
1077  * @krberror: KRB-ERROR structure with error code.
1078  * @methoddata: output ASN.1 METHOD-DATA.
1079  *
1080  * Extract METHOD-DATA ASN.1 object from the e-data field.  The e-data
1081  * field will only contain a METHOD-DATA if the krberror error code is
1082  * %SHISHI_KDC_ERR_PREAUTH_REQUIRED.
1083  *
1084  * Return value: Returns SHISHI_OK iff successful.
1085  **/
1086 int
shishi_krberror_methoddata(Shishi * handle,Shishi_asn1 krberror,Shishi_asn1 * methoddata)1087 shishi_krberror_methoddata (Shishi * handle, Shishi_asn1 krberror,
1088 			    Shishi_asn1 * methoddata)
1089 {
1090   int rc;
1091 
1092   *methoddata = NULL;
1093 
1094   if (shishi_krberror_errorcode_fast (handle, krberror)
1095       == SHISHI_KDC_ERR_PREAUTH_REQUIRED)
1096     {
1097       char *buf;
1098       size_t len;
1099 
1100       rc = shishi_krberror_edata (handle, krberror, &buf, &len);
1101       if (rc != SHISHI_OK)
1102 	return rc;
1103 
1104       *methoddata = shishi_der2asn1_methoddata (handle, buf, len);
1105       free (buf);
1106       if (!*methoddata)
1107 	return SHISHI_ASN1_ERROR;
1108     }
1109 
1110   return SHISHI_OK;
1111 }
1112 
1113 /**
1114  * shishi_krberror_set_edata:
1115  * @handle: shishi handle as allocated by shishi_init().
1116  * @krberror: krberror as allocated by shishi_krberror().
1117  * @edata: input array with error text to set.
1118  *
1119  * Set error text (e-data) field in KRB-ERROR to specified value.
1120  *
1121  * Return value: Returns SHISHI_OK iff successful.
1122  **/
1123 int
shishi_krberror_set_edata(Shishi * handle,Shishi_asn1 krberror,const char * edata)1124 shishi_krberror_set_edata (Shishi * handle,
1125 			   Shishi_asn1 krberror, const char *edata)
1126 {
1127   int res;
1128 
1129   res = shishi_asn1_write (handle, krberror, "e-data", edata, 0);
1130   if (res != SHISHI_OK)
1131     return res;
1132 
1133   return SHISHI_OK;
1134 }
1135 
1136 /**
1137  * shishi_krberror_remove_edata:
1138  * @handle: shishi handle as allocated by shishi_init().
1139  * @krberror: krberror as allocated by shishi_krberror().
1140  *
1141  * Remove error text (e-data) field in KRB-ERROR.
1142  *
1143  * Return value: Returns SHISHI_OK iff successful.
1144  **/
1145 int
shishi_krberror_remove_edata(Shishi * handle,Shishi_asn1 krberror)1146 shishi_krberror_remove_edata (Shishi * handle, Shishi_asn1 krberror)
1147 {
1148   int res;
1149 
1150   res = shishi_asn1_write (handle, krberror, "e-data", NULL, 0);
1151   if (res != SHISHI_OK)
1152     return res;
1153 
1154   return SHISHI_OK;
1155 }
1156 
1157 /**
1158  * shishi_krberror_pretty_print:
1159  * @handle: shishi handle as allocated by shishi_init().
1160  * @fh: file handle opened for writing.
1161  * @krberror: KRB-ERROR structure with error code.
1162  *
1163  * Print KRB-ERROR error condition and some explanatory text to file
1164  * descriptor.
1165  *
1166  * Return value: Returns SHISHI_OK iff successful.
1167  **/
1168 int
shishi_krberror_pretty_print(Shishi * handle,FILE * fh,Shishi_asn1 krberror)1169 shishi_krberror_pretty_print (Shishi * handle, FILE * fh,
1170 			      Shishi_asn1 krberror)
1171 {
1172   char *buf;
1173   size_t len;
1174   int res;
1175 
1176   if (VERBOSEASN1 (handle))
1177     shishi_krberror_print (handle, fh, krberror);
1178 
1179   if (shishi_krberror_errorcode_fast (handle, krberror) ==
1180       SHISHI_KRB_ERR_GENERIC)
1181     {
1182       fprintf (fh, "Generic error from server:\n");
1183 
1184       res = shishi_krberror_etext (handle, krberror, &buf, &len);
1185       if (res == SHISHI_OK && len > 0)
1186 	{
1187 	  buf[len] = '\0';
1188 	  fprintf (fh, "%s\n", buf);
1189 	  free (buf);
1190 	}
1191     }
1192   else
1193     {
1194       fprintf (fh, "Error code from server:\n%s\n",
1195 	       shishi_krberror_message (handle, krberror));
1196 
1197       res = shishi_krberror_etext (handle, krberror, &buf, &len);
1198       if (res == SHISHI_OK && len > 0)
1199 	{
1200 	  buf[len] = '\0';
1201 	  fprintf (fh, "Additional error message from server:\n%s\n", buf);
1202 	  free (buf);
1203 	}
1204 
1205       if (shishi_krberror_errorcode_fast (handle, krberror) ==
1206 	  SHISHI_KDC_ERR_PREAUTH_REQUIRED)
1207 	{
1208 	  Shishi_asn1 pas;
1209 	  size_t i, n;
1210 
1211 	  res = shishi_krberror_methoddata (handle, krberror, &pas);
1212 	  if (res != SHISHI_OK)
1213 	    return res;
1214 
1215 	  if (VERBOSEASN1 (handle))
1216 	    shishi_methoddata_print (handle, stdout, pas);
1217 
1218 	  res = shishi_asn1_number_of_elements (handle, pas, "", &n);
1219 	  if (res == SHISHI_OK)
1220 	    {
1221 	      fprintf (fh, "Types of PA-DATA in KRB-ERROR: ");
1222 
1223 	      for (i = 1; i <= n; i++)
1224 		{
1225 		  char *format = xasprintf ("?%ld.padata-type", i);
1226 		  int32_t padatatype;
1227 
1228 		  if (i > 1)
1229 		    fprintf (fh, ", ");
1230 
1231 		  res = shishi_asn1_read_int32 (handle, pas, format,
1232 						&padatatype);
1233 		  if (res == SHISHI_OK)
1234 		    printf ("%d", padatatype);
1235 
1236 		  free (format);
1237 		}
1238 
1239 	      fprintf (fh, ".\n");
1240 	    }
1241 
1242 	  shishi_asn1_done (handle, pas);
1243 	}
1244     }
1245 
1246 
1247   return SHISHI_OK;
1248 }
1249 
1250 struct krb_error_msgs
1251 {
1252   int errorcode;
1253   const char *message;
1254 };
1255 
1256 static const struct krb_error_msgs
1257   _shishi_krberror_messages[SHISHI_LAST_ERROR_CODE] = {
1258   {SHISHI_KDC_ERR_NONE,
1259    N_("No error")},
1260   {SHISHI_KDC_ERR_NAME_EXP,
1261    N_("Client's entry in database has expired")},
1262   {SHISHI_KDC_ERR_SERVICE_EXP,
1263    N_("Server's entry in database has expired")},
1264   {SHISHI_KDC_ERR_BAD_PVNO,
1265    N_("Requested protocol version number not supported")},
1266   {SHISHI_KDC_ERR_C_OLD_MAST_KVNO,
1267    N_("Client's key encrypted in old master key")},
1268   {SHISHI_KDC_ERR_S_OLD_MAST_KVNO,
1269    N_("Server's key encrypted in old master key")},
1270   {SHISHI_KDC_ERR_C_PRINCIPAL_UNKNOWN,
1271    N_("Client not found in database")},
1272   {SHISHI_KDC_ERR_S_PRINCIPAL_UNKNOWN,
1273    N_("Server not found in database")},
1274   {SHISHI_KDC_ERR_PRINCIPAL_NOT_UNIQUE,
1275    N_("Multiple principal entries in database")},
1276   {SHISHI_KDC_ERR_NULL_KEY,
1277    N_("The client or server has a null key")},
1278   {SHISHI_KDC_ERR_CANNOT_POSTDATE,
1279    N_("Ticket not eligible for postdating")},
1280   {SHISHI_KDC_ERR_NEVER_VALID,
1281    N_("Requested start time is later than end time")},
1282   {SHISHI_KDC_ERR_POLICY,
1283    N_("KDC policy rejects request")},
1284   {SHISHI_KDC_ERR_BADOPTION,
1285    N_("KDC cannot accommodate requested option")},
1286   {SHISHI_KDC_ERR_ETYPE_NOSUPP,
1287    N_("KDC has no support for encryption type")},
1288   {SHISHI_KDC_ERR_SUMTYPE_NOSUPP,
1289    N_("KDC has no support for checksum type")},
1290   {SHISHI_KDC_ERR_PADATA_TYPE_NOSUPP,
1291    N_("KDC has no support for padata type")},
1292   {SHISHI_KDC_ERR_TRTYPE_NOSUPP,
1293    N_("KDC has no support for transited type")},
1294   {SHISHI_KDC_ERR_CLIENT_REVOKED,
1295    N_("Clients credentials have been revoked")},
1296   {SHISHI_KDC_ERR_SERVICE_REVOKED,
1297    N_("Credentials for server have been revoked")},
1298   {SHISHI_KDC_ERR_TGT_REVOKED,
1299    N_("TGT has been revoked")},
1300   {SHISHI_KDC_ERR_CLIENT_NOTYET,
1301    N_("Client not yet valid - try again later")},
1302   {SHISHI_KDC_ERR_SERVICE_NOTYET,
1303    N_("Server not yet valid - try again later")},
1304   {SHISHI_KDC_ERR_KEY_EXPIRED,
1305    N_("Password has expired ")},
1306   {SHISHI_KDC_ERR_PREAUTH_FAILED,
1307    N_("Pre-authentication information was invalid")},
1308   {SHISHI_KDC_ERR_PREAUTH_REQUIRED,
1309    N_("Additional pre-authentication required")},
1310   {SHISHI_KDC_ERR_SERVER_NOMATCH,
1311    N_("Requested server and ticket don't match")},
1312   {SHISHI_KDC_ERR_MUST_USE_USER2USER,
1313    N_("Server principal valid for user2user only")},
1314   {SHISHI_KDC_ERR_PATH_NOT_ACCPETED,
1315    N_("KDC Policy rejects transited path")},
1316   {SHISHI_KDC_ERR_SVC_UNAVAILABLE,
1317    N_("A service is not available")},
1318   {SHISHI_KRB_AP_ERR_BAD_INTEGRITY,
1319    N_("Integrity check on decrypted field failed")},
1320   {SHISHI_KRB_AP_ERR_TKT_EXPIRED,
1321    N_("Ticket expired")},
1322   {SHISHI_KRB_AP_ERR_TKT_NYV,
1323    N_("Ticket not yet valid")},
1324   {SHISHI_KRB_AP_ERR_REPEAT,
1325    N_("Request is a replay")},
1326   {SHISHI_KRB_AP_ERR_NOT_US,
1327    N_("The ticket isn't for us")},
1328   {SHISHI_KRB_AP_ERR_BADMATCH,
1329    N_("Ticket and authenticator don't match")},
1330   {SHISHI_KRB_AP_ERR_SKEW,
1331    N_("Clock skew too great")},
1332   {SHISHI_KRB_AP_ERR_BADADDR,
1333    N_("Incorrect net address")},
1334   {SHISHI_KRB_AP_ERR_BADVERSION,
1335    N_("Protocol version mismatch")},
1336   {SHISHI_KRB_AP_ERR_MSG_TYPE,
1337    N_("Invalid msg type")},
1338   {SHISHI_KRB_AP_ERR_MODIFIED,
1339    N_("Message stream modified")},
1340   {SHISHI_KRB_AP_ERR_BADORDER,
1341    N_("Message out of order")},
1342   {SHISHI_KRB_AP_ERR_BADKEYVER,
1343    N_("Specified version of key is not available")},
1344   {SHISHI_KRB_AP_ERR_NOKEY,
1345    N_("Service key not available")},
1346   {SHISHI_KRB_AP_ERR_MUT_FAIL,
1347    N_("Mutual authentication failed")},
1348   {SHISHI_KRB_AP_ERR_BADDIRECTION,
1349    N_("Incorrect message direction")},
1350   {SHISHI_KRB_AP_ERR_METHOD,
1351    N_("Alternative authentication method required")},
1352   {SHISHI_KRB_AP_ERR_BADSEQ,
1353    N_("Incorrect sequence number in message")},
1354   {SHISHI_KRB_AP_ERR_INAPP_CKSUM,
1355    N_("Inappropriate type of checksum in message")},
1356   {SHISHI_KRB_AP_PATH_NOT_ACCEPTED,
1357    N_("Policy rejects transited path")},
1358   {SHISHI_KRB_ERR_RESPONSE_TOO_BIG,
1359    N_("Response too big for UDP, retry with TCP")},
1360   {SHISHI_KRB_ERR_GENERIC,
1361    N_("Generic error (description in e-text)")},
1362   {SHISHI_KRB_ERR_FIELD_TOOLONG,
1363    N_("Field is too long for this implementation")},
1364   {SHISHI_KDC_ERROR_CLIENT_NOT_TRUSTED,
1365    N_("(pkinit)")},
1366   {SHISHI_KDC_ERROR_KDC_NOT_TRUSTED,
1367    N_("(pkinit)")},
1368   {SHISHI_KDC_ERROR_INVALID_SIG,
1369    N_("(pkinit)")},
1370   {SHISHI_KDC_ERR_KEY_TOO_WEAK,
1371    N_("(pkinit)")},
1372   {SHISHI_KDC_ERR_CERTIFICATE_MISMATCH,
1373    N_("(pkinit)")},
1374   {SHISHI_KRB_AP_ERR_NO_TGT,
1375    N_("(user-to-user)")},
1376   {SHISHI_KDC_ERR_WRONG_REALM,
1377    N_("(user-to-user)")},
1378   {SHISHI_KRB_AP_ERR_USER_TO_USER_REQUIRED,
1379    N_("(user-to-user)")},
1380   {SHISHI_KDC_ERR_CANT_VERIFY_CERTIFICATE,
1381    N_("(pkinit)")},
1382   {SHISHI_KDC_ERR_INVALID_CERTIFICATE,
1383    N_("(pkinit)")},
1384   {SHISHI_KDC_ERR_REVOKED_CERTIFICATE,
1385    N_("(pkinit)")},
1386   {SHISHI_KDC_ERR_REVOCATION_STATUS_UNKNOWN,
1387    N_("(pkinit)")},
1388   {SHISHI_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE,
1389    N_("(pkinit)")},
1390   {SHISHI_KDC_ERR_CLIENT_NAME_MISMATCH,
1391    N_("(pkinit)")},
1392   {SHISHI_KDC_ERR_KDC_NAME_MISMATCH,
1393    N_("(pkinit)")}
1394 };
1395 
1396 /**
1397  * shishi_krberror_errorcode_message:
1398  * @handle: shishi handle as allocated by shishi_init().
1399  * @errorcode: integer KRB-ERROR error code.
1400  *
1401  * Get human readable string describing KRB-ERROR code.
1402  *
1403  * Return value: Return a string describing error code.  This function
1404  *               will always return a string even if the error code
1405  *               isn't known.
1406  **/
1407 const char *
shishi_krberror_errorcode_message(Shishi * handle,int errorcode)1408 shishi_krberror_errorcode_message (Shishi * handle, int errorcode)
1409 {
1410   int i;
1411   char *p;
1412 
1413   for (i = 0; i < SHISHI_LAST_ERROR_CODE; i++)
1414     {
1415       if (errorcode == _shishi_krberror_messages[i].errorcode)
1416 	return _(_shishi_krberror_messages[i].message);
1417     }
1418 
1419   /* XXX memory leak */
1420   asprintf (&p, _("Unknown KRB-ERROR error code %d."), errorcode);
1421   return p;
1422 }
1423 
1424 /**
1425  * shishi_krberror_message:
1426  * @handle: shishi handle as allocated by shishi_init().
1427  * @krberror: KRB-ERROR structure with error code.
1428  *
1429  * Extract error code (see shishi_krberror_errorcode_fast()) and
1430  * return error message (see shishi_krberror_errorcode_message()).
1431  *
1432  * Return value: Return a string describing error code.  This function
1433  *               will always return a string even if the error code
1434  *               isn't known.
1435  **/
1436 const char *
shishi_krberror_message(Shishi * handle,Shishi_asn1 krberror)1437 shishi_krberror_message (Shishi * handle, Shishi_asn1 krberror)
1438 {
1439   return shishi_krberror_errorcode_message
1440     (handle, shishi_krberror_errorcode_fast (handle, krberror));
1441 }
1442