Use new libtasn1 API.
[shishi.git] / lib / krberror.c
blob76c7b4e33f379cfcf60e49bcd830b20cec1d3612
1 /* krberror.c Functions related to KRB-ERROR packet.
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_krberror:
26 * @handle: shishi handle as allocated by shishi_init().
28 * This function creates a new KRB-ERROR, populated with some default
29 * values.
31 * Return value: Returns the KRB-ERROR or NULL on failure.
32 **/
33 Shishi_asn1
34 shishi_krberror (Shishi * handle)
36 Shishi_asn1 node;
38 node = shishi_asn1_krberror (handle);
39 if (!node)
40 return NULL;
42 return node;
45 /**
46 * shishi_krberror_print:
47 * @handle: shishi handle as allocated by shishi_init().
48 * @fh: file handle open for writing.
49 * @krberror: KRB-ERROR to print.
51 * Print ASCII armored DER encoding of KRB-ERROR to file.
53 * Return value: Returns SHISHI_OK iff successful.
54 **/
55 int
56 shishi_krberror_print (Shishi * handle, FILE * fh, Shishi_asn1 krberror)
58 return _shishi_print_armored_data (handle, fh, krberror, "KRB-ERROR", NULL);
61 /**
62 * shishi_krberror_save:
63 * @handle: shishi handle as allocated by shishi_init().
64 * @fh: file handle open for writing.
65 * @krberror: KRB-ERROR to save.
67 * Save DER encoding of KRB-ERROR to file.
69 * Return value: Returns SHISHI_OK iff successful.
70 **/
71 int
72 shishi_krberror_save (Shishi * handle, FILE * fh, Shishi_asn1 krberror)
74 return _shishi_save_data (handle, fh, krberror, "KRB-ERROR");
77 /**
78 * shishi_krberror_to_file:
79 * @handle: shishi handle as allocated by shishi_init().
80 * @krberror: KRB-ERROR to save.
81 * @filetype: input variable specifying type of file to be written,
82 * see Shishi_filetype.
83 * @filename: input variable with filename to write to.
85 * Write KRB-ERROR to file in specified TYPE. The file will be
86 * truncated if it exists.
88 * Return value: Returns SHISHI_OK iff successful.
89 **/
90 int
91 shishi_krberror_to_file (Shishi * handle, Shishi_asn1 krberror,
92 int filetype, char *filename)
94 FILE *fh;
95 int res;
97 if (VERBOSE (handle))
98 printf (_("Writing KRB-ERROR to %s...\n"), filename);
100 fh = fopen (filename, "w");
101 if (fh == NULL)
102 return SHISHI_FOPEN_ERROR;
104 if (VERBOSE (handle))
105 printf (_("Writing KRB-ERROR in %s format...\n"),
106 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
108 if (filetype == SHISHI_FILETYPE_TEXT)
109 res = shishi_krberror_print (handle, fh, krberror);
110 else
111 res = shishi_krberror_save (handle, fh, krberror);
112 if (res != SHISHI_OK)
113 return res;
115 res = fclose (fh);
116 if (res != 0)
117 return SHISHI_FCLOSE_ERROR;
119 if (VERBOSE (handle))
120 printf (_("Writing KRB-ERROR to %s...done\n"), filename);
122 return SHISHI_OK;
126 * shishi_krberror_parse:
127 * @handle: shishi handle as allocated by shishi_init().
128 * @fh: file handle open for reading.
129 * @krberror: output variable with newly allocated KRB-ERROR.
131 * Read ASCII armored DER encoded KRB-ERROR from file and populate given
132 * variable.
134 * Return value: Returns SHISHI_OK iff successful.
137 shishi_krberror_parse (Shishi * handle, FILE * fh, Shishi_asn1 * krberror)
139 return _shishi_krberror_input (handle, fh, krberror, 0);
143 * shishi_krberror_read:
144 * @handle: shishi handle as allocated by shishi_init().
145 * @fh: file handle open for reading.
146 * @krberror: output variable with newly allocated KRB-ERROR.
148 * Read DER encoded KRB-ERROR from file and populate given variable.
150 * Return value: Returns SHISHI_OK iff successful.
153 shishi_krberror_read (Shishi * handle, FILE * fh, Shishi_asn1 * krberror)
155 return _shishi_krberror_input (handle, fh, krberror, 1);
159 * shishi_krberror_from_file:
160 * @handle: shishi handle as allocated by shishi_init().
161 * @krberror: output variable with newly allocated KRB-ERROR.
162 * @filetype: input variable specifying type of file to be read,
163 * see Shishi_filetype.
164 * @filename: input variable with filename to read from.
166 * Read KRB-ERROR from file in specified TYPE.
168 * Return value: Returns SHISHI_OK iff successful.
171 shishi_krberror_from_file (Shishi * handle, Shishi_asn1 * krberror,
172 int filetype, char *filename)
174 int res;
175 FILE *fh;
177 if (VERBOSE (handle))
178 printf (_("Reading KRB-ERROR from %s...\n"), filename);
180 fh = fopen (filename, "r");
181 if (fh == NULL)
182 return SHISHI_FOPEN_ERROR;
184 if (VERBOSE (handle))
185 printf (_("Reading KRB-ERROR in %s format...\n"),
186 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
188 if (filetype == SHISHI_FILETYPE_TEXT)
189 res = shishi_krberror_parse (handle, fh, krberror);
190 else
191 res = shishi_krberror_read (handle, fh, krberror);
192 if (res != SHISHI_OK)
193 return res;
195 res = fclose (fh);
196 if (res != 0)
197 return SHISHI_FCLOSE_ERROR;
199 if (VERBOSE (handle))
200 printf (_("Reading KRB-ERROR from %s...done\n"), filename);
202 return SHISHI_OK;
205 struct krb_error_msgs
207 int errorcode;
208 char *message;
211 enum krb_error_codes
213 KDC_ERR_NONE = 0,
214 KDC_ERR_NAME_EXP = 1,
215 KDC_ERR_SERVICE_EXP = 2,
216 KDC_ERR_BAD_PVNO = 3,
217 KDC_ERR_C_OLD_MAST_KVNO = 4,
218 KDC_ERR_S_OLD_MAST_KVNO = 5,
219 KDC_ERR_C_PRINCIPAL_UNKNOWN = 6,
220 KDC_ERR_S_PRINCIPAL_UNKNOWN = 7,
221 KDC_ERR_PRINCIPAL_NOT_UNIQUE = 8,
222 KDC_ERR_NULL_KEY = 9,
223 KDC_ERR_CANNOT_POSTDATE = 10,
224 KDC_ERR_NEVER_VALID = 11,
225 KDC_ERR_POLICY = 12,
226 KDC_ERR_BADOPTION = 13,
227 KDC_ERR_ETYPE_NOSUPP = 14,
228 KDC_ERR_SUMTYPE_NOSUPP = 15,
229 KDC_ERR_PADATA_TYPE_NOSUPP = 16,
230 KDC_ERR_TRTYPE_NOSUPP = 17,
231 KDC_ERR_CLIENT_REVOKED = 18,
232 KDC_ERR_SERVICE_REVOKED = 19,
233 KDC_ERR_TGT_REVOKED = 20,
234 KDC_ERR_CLIENT_NOTYET = 21,
235 KDC_ERR_SERVICE_NOTYET = 22,
236 KDC_ERR_KEY_EXPIRED = 23,
237 KDC_ERR_PREAUTH_FAILED = 24,
238 KDC_ERR_PREAUTH_REQUIRED = 25,
239 KDC_ERR_SERVER_NOMATCH = 26,
240 KDC_ERR_MUST_USE_USER2USER = 27,
241 KDC_ERR_PATH_NOT_ACCPETED = 28,
242 KDC_ERR_SVC_UNAVAILABLE = 29,
243 KRB_AP_ERR_BAD_INTEGRITY = 31,
244 KRB_AP_ERR_TKT_EXPIRED = 32,
245 KRB_AP_ERR_TKT_NYV = 33,
246 KRB_AP_ERR_REPEAT = 34,
247 KRB_AP_ERR_NOT_US = 35,
248 KRB_AP_ERR_BADMATCH = 36,
249 KRB_AP_ERR_SKEW = 37,
250 KRB_AP_ERR_BADADDR = 38,
251 KRB_AP_ERR_BADVERSION = 39,
252 KRB_AP_ERR_MSG_TYPE = 40,
253 KRB_AP_ERR_MODIFIED = 41,
254 KRB_AP_ERR_BADORDER = 42,
255 KRB_AP_ERR_BADKEYVER = 44,
256 KRB_AP_ERR_NOKEY = 45,
257 KRB_AP_ERR_MUT_FAIL = 46,
258 KRB_AP_ERR_BADDIRECTION = 47,
259 KRB_AP_ERR_METHOD = 48,
260 KRB_AP_ERR_BADSEQ = 49,
261 KRB_AP_ERR_INAPP_CKSUM = 50,
262 KRB_AP_PATH_NOT_ACCEPTED = 51,
263 KRB_ERR_RESPONSE_TOO_BIG = 52,
264 KRB_ERR_GENERIC = 60,
265 KRB_ERR_FIELD_TOOLONG = 61,
266 KDC_ERROR_CLIENT_NOT_TRUSTED = 62,
267 KDC_ERROR_KDC_NOT_TRUSTED = 63,
268 KDC_ERROR_INVALID_SIG = 64,
269 KDC_ERR_KEY_TOO_WEAK = 65,
270 KDC_ERR_CERTIFICATE_MISMATCH = 66,
271 KRB_AP_ERR_NO_TGT = 67,
272 KDC_ERR_WRONG_REALM = 68,
273 KRB_AP_ERR_USER_TO_USER_REQUIRED = 69,
274 KDC_ERR_CANT_VERIFY_CERTIFICATE = 70,
275 KDC_ERR_INVALID_CERTIFICATE = 71,
276 KDC_ERR_REVOKED_CERTIFICATE = 72,
277 KDC_ERR_REVOCATION_STATUS_UNKNOWN = 73,
278 KDC_ERR_REVOCATION_STATUS_UNAVAILABLE = 74,
279 KDC_ERR_CLIENT_NAME_MISMATCH = 75,
280 KDC_ERR_KDC_NAME_MISMATCH = 76,
281 KDC_ERR_SIZE = 77
284 struct krb_error_msgs _shishi_krberror_messages[KDC_ERR_SIZE] = {
285 {KDC_ERR_NONE, "No error"},
286 {KDC_ERR_NAME_EXP, "Client's entry in database has expired"},
287 {KDC_ERR_SERVICE_EXP, "Server's entry in database has expired"},
288 {KDC_ERR_BAD_PVNO, "Requested protocol version number not supported"},
289 {KDC_ERR_C_OLD_MAST_KVNO, "Client's key encrypted in old master key"},
290 {KDC_ERR_S_OLD_MAST_KVNO, "Server's key encrypted in old master key"},
291 {KDC_ERR_C_PRINCIPAL_UNKNOWN, "Client not found in Kerberos database"},
292 {KDC_ERR_S_PRINCIPAL_UNKNOWN, "Server not found in Kerberos database"},
293 {KDC_ERR_PRINCIPAL_NOT_UNIQUE, "Multiple principal entries in database"},
294 {KDC_ERR_NULL_KEY, "The client or server has a null key"},
295 {KDC_ERR_CANNOT_POSTDATE, "Ticket not eligible for postdating"},
296 {KDC_ERR_NEVER_VALID, "Requested start time is later than end time"},
297 {KDC_ERR_POLICY, "KDC policy rejects request"},
298 {KDC_ERR_BADOPTION, "KDC cannot accommodate requested option"},
299 {KDC_ERR_ETYPE_NOSUPP, "KDC has no support for encryption type"},
300 {KDC_ERR_SUMTYPE_NOSUPP, "KDC has no support for checksum type"},
301 {KDC_ERR_PADATA_TYPE_NOSUPP, "KDC has no support for padata type"},
302 {KDC_ERR_TRTYPE_NOSUPP, "KDC has no support for transited type"},
303 {KDC_ERR_CLIENT_REVOKED, "Clients credentials have been revoked"},
304 {KDC_ERR_SERVICE_REVOKED, "Credentials for server have been revoked"},
305 {KDC_ERR_TGT_REVOKED, "TGT has been revoked"},
306 {KDC_ERR_CLIENT_NOTYET, "Client not yet valid - try again later"},
307 {KDC_ERR_SERVICE_NOTYET, "Server not yet valid - try again later"},
308 {KDC_ERR_KEY_EXPIRED, "Password has expired "},
309 {KDC_ERR_PREAUTH_FAILED, "Pre-authentication information was invalid"},
310 {KDC_ERR_PREAUTH_REQUIRED, "Additional pre-authenticationrequired [40]"},
311 {KDC_ERR_SERVER_NOMATCH, "Requested server and ticket don't match"},
312 {KDC_ERR_MUST_USE_USER2USER, "Server principal valid for user2user only"},
313 {KDC_ERR_PATH_NOT_ACCPETED, "KDC Policy rejects transited path"},
314 {KDC_ERR_SVC_UNAVAILABLE, "A service is not available"},
315 {KRB_AP_ERR_BAD_INTEGRITY, "Integrity check on decrypted field failed"},
316 {KRB_AP_ERR_TKT_EXPIRED, "Ticket expired"},
317 {KRB_AP_ERR_TKT_NYV, "Ticket not yet valid"},
318 {KRB_AP_ERR_REPEAT, "Request is a replay"},
319 {KRB_AP_ERR_NOT_US, "The ticket isn't for us"},
320 {KRB_AP_ERR_BADMATCH, "Ticket and authenticator don't match"},
321 {KRB_AP_ERR_SKEW, "Clock skew too great"},
322 {KRB_AP_ERR_BADADDR, "Incorrect net address"},
323 {KRB_AP_ERR_BADVERSION, "Protocol version mismatch"},
324 {KRB_AP_ERR_MSG_TYPE, "Invalid msg type"},
325 {KRB_AP_ERR_MODIFIED, "Message stream modified"},
326 {KRB_AP_ERR_BADORDER, "Message out of order"},
327 {KRB_AP_ERR_BADKEYVER, "Specified version of key is not available"},
328 {KRB_AP_ERR_NOKEY, "Service key not available"},
329 {KRB_AP_ERR_MUT_FAIL, "Mutual authentication failed"},
330 {KRB_AP_ERR_BADDIRECTION, "Incorrect message direction"},
331 {KRB_AP_ERR_METHOD, "Alternative authentication method required"},
332 {KRB_AP_ERR_BADSEQ, "Incorrect sequence number in message"},
333 {KRB_AP_ERR_INAPP_CKSUM, "Inappropriate type of checksum in message"},
334 {KRB_AP_PATH_NOT_ACCEPTED, "Policy rejects transited path"},
335 {KRB_ERR_RESPONSE_TOO_BIG, "Response too big for UDP, retry with TCP"},
336 {KRB_ERR_GENERIC, "Generic error (description in e-text)"},
337 {KRB_ERR_FIELD_TOOLONG, "Field is too long for this implementation"},
338 {KDC_ERROR_CLIENT_NOT_TRUSTED, "(pkinit)"},
339 {KDC_ERROR_KDC_NOT_TRUSTED, "(pkinit)"},
340 {KDC_ERROR_INVALID_SIG, "(pkinit)"},
341 {KDC_ERR_KEY_TOO_WEAK, "(pkinit)"},
342 {KDC_ERR_CERTIFICATE_MISMATCH, "(pkinit)"},
343 {KRB_AP_ERR_NO_TGT, "(user-to-user)"},
344 {KDC_ERR_WRONG_REALM, "(user-to-user)"},
345 {KRB_AP_ERR_USER_TO_USER_REQUIRED, "(user-to-user)"},
346 {KDC_ERR_CANT_VERIFY_CERTIFICATE, "(pkinit)"},
347 {KDC_ERR_INVALID_CERTIFICATE, "(pkinit)"},
348 {KDC_ERR_REVOKED_CERTIFICATE, "(pkinit)"},
349 {KDC_ERR_REVOCATION_STATUS_UNKNOWN, "(pkinit)"},
350 {KDC_ERR_REVOCATION_STATUS_UNAVAILABLE, "(pkinit)"},
351 {KDC_ERR_CLIENT_NAME_MISMATCH, "(pkinit)"},
352 {KDC_ERR_KDC_NAME_MISMATCH, "(pkinit)"}
356 * shishi_krberror_errorcode_message:
357 * @handle: shishi handle as allocated by shishi_init().
358 * @errorcode: integer KRB-ERROR error code.
360 * Return value: Return a string describing error code. This function
361 * will always return a string even if the error code
362 * isn't known.
364 const char *
365 shishi_krberror_errorcode_message (Shishi * handle, int errorcode)
367 int i;
368 char *p;
370 for (i = 0; i < KDC_ERR_SIZE; i++)
372 if (errorcode == _shishi_krberror_messages[i].errorcode)
373 return _(_shishi_krberror_messages[i].message);
376 /* XXX memory leak */
377 shishi_asprintf (&p, _("Unknown KRB-ERROR error code %d."), errorcode);
378 return p;
382 * shishi_krberror_errorcode:
383 * @handle: shishi handle as allocated by shishi_init().
384 * @krberror: KRB-ERROR structure with error code.
385 * @errorcode: output integer KRB-ERROR error code.
387 * Extract error code from KRB-ERROR.
389 * Return value: Returns SHISHI_OK iff successful.
392 shishi_krberror_errorcode (Shishi * handle,
393 Shishi_asn1 krberror, int *errorcode)
395 return shishi_asn1_integer_field (handle, krberror, errorcode,
396 "error-code");
400 * shishi_krberror_errorcode_fast:
401 * @handle: shishi handle as allocated by shishi_init().
402 * @krberror: KRB-ERROR structure with error code.
404 * Return value: Return error code (see shishi_krberror_errorcode())
405 * directly, or -1 on error.
408 shishi_krberror_errorcode_fast (Shishi * handle, Shishi_asn1 krberror)
410 int i;
412 if (shishi_krberror_errorcode (handle, krberror, &i) != SHISHI_OK)
413 i = -1;
415 return i;
419 * shishi_krberror_etext:
420 * @handle: shishi handle as allocated by shishi_init().
421 * @krberror: KRB-ERROR structure with error code.
422 * @etext: output array with error text.
423 * @etextlen: on input, maximum size of output array with error text,
424 * on output, actual size of output array with error text.
426 * Extract additional error text from server (possibly empty).
428 * Return value: Returns SHISHI_OK iff successful.
431 shishi_krberror_etext (Shishi * handle, Shishi_asn1 krberror,
432 char *etext, size_t * etextlen)
434 return shishi_asn1_optional_field (handle, krberror, etext, etextlen,
435 "e-text");
439 * shishi_krberror_message:
440 * @handle: shishi handle as allocated by shishi_init().
441 * @krberror: KRB-ERROR structure with error code.
443 * Extract error code (see shishi_krberror_errorcode_fast()) and
444 * return error message (see shishi_krberror_errorcode_message()).
446 * Return value: Return a string describing error code. This function
447 * will always return a string even if the error code
448 * isn't known.
450 const char *
451 shishi_krberror_message (Shishi * handle, Shishi_asn1 krberror)
453 return shishi_krberror_errorcode_message
454 (handle, shishi_krberror_errorcode_fast (handle, krberror));
458 * shishi_krberror_pretty_print:
459 * @handle: shishi handle as allocated by shishi_init().
460 * @fh: file handle opened for writing.
461 * @krberror: KRB-ERROR structure with error code.
463 * Print KRB-ERROR error condition and some explanatory text to file
464 * descriptor.
466 * Return value: Returns SHISHI_OK iff successful.
469 shishi_krberror_pretty_print (Shishi * handle, FILE * fh,
470 Shishi_asn1 krberror)
472 char buf[BUFSIZ];
473 size_t len = BUFSIZ;
474 int res;
476 if (VERBOSEASN1 (handle))
477 shishi_krberror_print (handle, fh, krberror);
479 fprintf (fh, "Kerberos error code from server:\n%s\n",
480 shishi_krberror_message (handle, krberror));
482 res = shishi_krberror_etext (handle, krberror, buf, &len);
483 buf[len] = '\0';
484 if (res == SHISHI_OK && len > 0)
485 fprintf (fh, "Additional Kerberos error message from server:\n%s\n", buf);
488 return SHISHI_OK;