minor update to the fix.
[gnutls.git] / lib / gnutls_alert.c
blobaffdff2c8552789e171dc26b4ead70a57a456774
1 /*
2 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2010 Free
3 * Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_record.h>
29 #include <debug.h>
31 /* I18n of error codes. */
32 #include "gettext.h"
33 #define _(String) dgettext (PACKAGE, String)
34 #define N_(String) gettext_noop (String)
36 typedef struct
38 gnutls_alert_description_t alert;
39 const char *desc;
40 } gnutls_alert_entry;
42 static const gnutls_alert_entry sup_alerts[] = {
43 {GNUTLS_A_CLOSE_NOTIFY, N_("Close notify")},
44 {GNUTLS_A_UNEXPECTED_MESSAGE, N_("Unexpected message")},
45 {GNUTLS_A_BAD_RECORD_MAC, N_("Bad record MAC")},
46 {GNUTLS_A_DECRYPTION_FAILED, N_("Decryption failed")},
47 {GNUTLS_A_RECORD_OVERFLOW, N_("Record overflow")},
48 {GNUTLS_A_DECOMPRESSION_FAILURE, N_("Decompression failed")},
49 {GNUTLS_A_HANDSHAKE_FAILURE, N_("Handshake failed")},
50 {GNUTLS_A_BAD_CERTIFICATE, N_("Certificate is bad")},
51 {GNUTLS_A_UNSUPPORTED_CERTIFICATE, N_("Certificate is not supported")},
52 {GNUTLS_A_CERTIFICATE_REVOKED, N_("Certificate was revoked")},
53 {GNUTLS_A_CERTIFICATE_EXPIRED, N_("Certificate is expired")},
54 {GNUTLS_A_CERTIFICATE_UNKNOWN, N_("Unknown certificate")},
55 {GNUTLS_A_ILLEGAL_PARAMETER, N_("Illegal parameter")},
56 {GNUTLS_A_UNKNOWN_CA, N_("CA is unknown")},
57 {GNUTLS_A_ACCESS_DENIED, N_("Access was denied")},
58 {GNUTLS_A_DECODE_ERROR, N_("Decode error")},
59 {GNUTLS_A_DECRYPT_ERROR, N_("Decrypt error")},
60 {GNUTLS_A_EXPORT_RESTRICTION, N_("Export restriction")},
61 {GNUTLS_A_PROTOCOL_VERSION, N_("Error in protocol version")},
62 {GNUTLS_A_INSUFFICIENT_SECURITY, N_("Insufficient security")},
63 {GNUTLS_A_USER_CANCELED, N_("User canceled")},
64 {GNUTLS_A_INTERNAL_ERROR, N_("Internal error")},
65 {GNUTLS_A_NO_RENEGOTIATION, N_("No renegotiation is allowed")},
66 {GNUTLS_A_CERTIFICATE_UNOBTAINABLE,
67 N_("Could not retrieve the specified certificate")},
68 {GNUTLS_A_UNSUPPORTED_EXTENSION, N_("An unsupported extension was sent")},
69 {GNUTLS_A_UNRECOGNIZED_NAME,
70 N_("The server name sent was not recognized")},
71 {GNUTLS_A_UNKNOWN_PSK_IDENTITY,
72 N_("The SRP/PSK username is missing or not known")},
73 {GNUTLS_A_INNER_APPLICATION_FAILURE,
74 N_("Inner application negotiation failed")},
75 {GNUTLS_A_INNER_APPLICATION_VERIFICATION,
76 N_("Inner application verification failed")},
77 {0, NULL}
80 /**
81 * gnutls_alert_get_name:
82 * @alert: is an alert number #gnutls_session_t structure.
84 * This function will return a string that describes the given alert
85 * number, or %NULL. See gnutls_alert_get().
87 * Returns: string corresponding to #gnutls_alert_description_t value.
88 **/
89 const char *
90 gnutls_alert_get_name (gnutls_alert_description_t alert)
92 const gnutls_alert_entry *p;
94 for (p = sup_alerts; p->desc != NULL; p++)
95 if (p->alert == alert)
96 return _(p->desc);
98 return NULL;
102 * gnutls_alert_send:
103 * @session: is a #gnutls_session_t structure.
104 * @level: is the level of the alert
105 * @desc: is the alert description
107 * This function will send an alert to the peer in order to inform
108 * him of something important (eg. his Certificate could not be verified).
109 * If the alert level is Fatal then the peer is expected to close the
110 * connection, otherwise he may ignore the alert and continue.
112 * The error code of the underlying record send function will be
113 * returned, so you may also receive %GNUTLS_E_INTERRUPTED or
114 * %GNUTLS_E_AGAIN as well.
116 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
117 * an error code is returned.
120 gnutls_alert_send (gnutls_session_t session, gnutls_alert_level_t level,
121 gnutls_alert_description_t desc)
123 uint8_t data[2];
124 int ret;
125 const char *name;
127 data[0] = (uint8_t) level;
128 data[1] = (uint8_t) desc;
130 name = gnutls_alert_get_name ((int) data[1]);
131 if (name == NULL)
132 name = "(unknown)";
133 _gnutls_record_log ("REC: Sending Alert[%d|%d] - %s\n", data[0],
134 data[1], name);
136 if ((ret =
137 _gnutls_send_int (session, GNUTLS_ALERT, -1, EPOCH_WRITE_CURRENT, data,
138 2, MBUFFER_FLUSH)) >= 0)
139 return 0;
140 else
141 return ret;
145 * gnutls_error_to_alert:
146 * @err: is a negative integer
147 * @level: the alert level will be stored there
149 * Get an alert depending on the error code returned by a gnutls
150 * function. All alerts sent by this function should be considered
151 * fatal. The only exception is when @err is %GNUTLS_E_REHANDSHAKE,
152 * where a warning alert should be sent to the peer indicating that no
153 * renegotiation will be performed.
155 * If there is no mapping to a valid alert the alert to indicate
156 * internal error is returned.
158 * Returns: the alert code to use for a particular error code.
161 gnutls_error_to_alert (int err, int *level)
163 int ret, _level = -1;
165 switch (err)
166 { /* send appropriate alert */
167 case GNUTLS_E_DECRYPTION_FAILED:
168 /* GNUTLS_A_DECRYPTION_FAILED is not sent, because
169 * it is not defined in SSL3. Note that we must
170 * not distinguish Decryption failures from mac
171 * check failures, due to the possibility of some
172 * attacks.
174 ret = GNUTLS_A_BAD_RECORD_MAC;
175 _level = GNUTLS_AL_FATAL;
176 break;
177 case GNUTLS_E_DECOMPRESSION_FAILED:
178 ret = GNUTLS_A_DECOMPRESSION_FAILURE;
179 _level = GNUTLS_AL_FATAL;
180 break;
181 case GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER:
182 case GNUTLS_E_ILLEGAL_SRP_USERNAME:
183 ret = GNUTLS_A_ILLEGAL_PARAMETER;
184 _level = GNUTLS_AL_FATAL;
185 break;
186 case GNUTLS_E_UNKNOWN_SRP_USERNAME:
187 ret = GNUTLS_A_UNKNOWN_PSK_IDENTITY;
188 _level = GNUTLS_AL_FATAL;
189 break;
190 case GNUTLS_E_ASN1_ELEMENT_NOT_FOUND:
191 case GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND:
192 case GNUTLS_E_ASN1_DER_ERROR:
193 case GNUTLS_E_ASN1_VALUE_NOT_FOUND:
194 case GNUTLS_E_ASN1_GENERIC_ERROR:
195 case GNUTLS_E_ASN1_VALUE_NOT_VALID:
196 case GNUTLS_E_ASN1_TAG_ERROR:
197 case GNUTLS_E_ASN1_TAG_IMPLICIT:
198 case GNUTLS_E_ASN1_TYPE_ANY_ERROR:
199 case GNUTLS_E_ASN1_SYNTAX_ERROR:
200 case GNUTLS_E_ASN1_DER_OVERFLOW:
201 case GNUTLS_E_CERTIFICATE_ERROR:
202 ret = GNUTLS_A_BAD_CERTIFICATE;
203 _level = GNUTLS_AL_FATAL;
204 break;
205 case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
206 case GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM:
207 case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
208 case GNUTLS_E_NO_CIPHER_SUITES:
209 case GNUTLS_E_NO_COMPRESSION_ALGORITHMS:
210 case GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM:
211 case GNUTLS_E_SAFE_RENEGOTIATION_FAILED:
212 case GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL:
213 ret = GNUTLS_A_HANDSHAKE_FAILURE;
214 _level = GNUTLS_AL_FATAL;
215 break;
216 case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
217 ret = GNUTLS_A_UNSUPPORTED_EXTENSION;
218 _level = GNUTLS_AL_FATAL;
219 break;
220 case GNUTLS_E_UNEXPECTED_PACKET:
221 case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
222 ret = GNUTLS_A_UNEXPECTED_MESSAGE;
223 _level = GNUTLS_AL_FATAL;
224 break;
225 case GNUTLS_E_REHANDSHAKE:
226 case GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED:
227 ret = GNUTLS_A_NO_RENEGOTIATION;
228 _level = GNUTLS_AL_WARNING;
229 break;
230 case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
231 ret = GNUTLS_A_PROTOCOL_VERSION;
232 _level = GNUTLS_AL_FATAL;
233 break;
234 case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
235 ret = GNUTLS_A_UNSUPPORTED_CERTIFICATE;
236 _level = GNUTLS_AL_FATAL;
237 break;
238 case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
239 ret = GNUTLS_A_RECORD_OVERFLOW;
240 _level = GNUTLS_AL_FATAL;
241 break;
242 case GNUTLS_E_INTERNAL_ERROR:
243 case GNUTLS_E_NO_TEMPORARY_DH_PARAMS:
244 case GNUTLS_E_NO_TEMPORARY_RSA_PARAMS:
245 ret = GNUTLS_A_INTERNAL_ERROR;
246 _level = GNUTLS_AL_FATAL;
247 break;
248 case GNUTLS_E_OPENPGP_GETKEY_FAILED:
249 ret = GNUTLS_A_CERTIFICATE_UNOBTAINABLE;
250 _level = GNUTLS_AL_FATAL;
251 break;
252 case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
253 case GNUTLS_E_NO_CERTIFICATE_FOUND:
254 ret = GNUTLS_A_INSUFFICIENT_SECURITY;
255 _level = GNUTLS_AL_FATAL;
256 break;
257 default:
258 ret = GNUTLS_A_INTERNAL_ERROR;
259 _level = GNUTLS_AL_FATAL;
260 break;
263 if (level != NULL)
264 *level = _level;
266 return ret;
270 * gnutls_alert_send_appropriate:
271 * @session: is a #gnutls_session_t structure.
272 * @err: is an integer
274 * Sends an alert to the peer depending on the error code returned by
275 * a gnutls function. This function will call gnutls_error_to_alert()
276 * to determine the appropriate alert to send.
278 * This function may also return %GNUTLS_E_AGAIN, or
279 * %GNUTLS_E_INTERRUPTED.
281 * If the return value is %GNUTLS_E_INVALID_REQUEST, then no alert has
282 * been sent to the peer.
284 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
285 * an error code is returned.
288 gnutls_alert_send_appropriate (gnutls_session_t session, int err)
290 int alert;
291 int level;
293 alert = gnutls_error_to_alert (err, &level);
294 if (alert < 0)
296 return alert;
299 return gnutls_alert_send (session, level, alert);
303 * gnutls_alert_get:
304 * @session: is a #gnutls_session_t structure.
306 * This function will return the last alert number received. This
307 * function should be called if %GNUTLS_E_WARNING_ALERT_RECEIVED or
308 * %GNUTLS_E_FATAL_ALERT_RECEIVED has been returned by a gnutls
309 * function. The peer may send alerts if he thinks some things were
310 * not right. Check gnutls.h for the available alert descriptions.
312 * If no alert has been received the returned value is undefined.
314 * Returns: returns the last alert received, a
315 * #gnutls_alert_description_t value.
317 gnutls_alert_description_t
318 gnutls_alert_get (gnutls_session_t session)
320 return session->internals.last_alert;