2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <gnutls_record.h>
28 /* I18n of error codes. */
30 #define _(String) dgettext (PACKAGE, String)
31 #define N_(String) gettext_noop (String)
34 gnutls_alert_description_t alert;
39 #define ALERT_ENTRY(x,y) \
42 static const gnutls_alert_entry sup_alerts[] = {
43 ALERT_ENTRY(GNUTLS_A_CLOSE_NOTIFY, N_("Close notify")),
44 ALERT_ENTRY(GNUTLS_A_UNEXPECTED_MESSAGE, N_("Unexpected message")),
45 ALERT_ENTRY(GNUTLS_A_BAD_RECORD_MAC, N_("Bad record MAC")),
46 ALERT_ENTRY(GNUTLS_A_DECRYPTION_FAILED, N_("Decryption failed")),
47 ALERT_ENTRY(GNUTLS_A_RECORD_OVERFLOW, N_("Record overflow")),
48 ALERT_ENTRY(GNUTLS_A_DECOMPRESSION_FAILURE,
49 N_("Decompression failed")),
50 ALERT_ENTRY(GNUTLS_A_HANDSHAKE_FAILURE, N_("Handshake failed")),
51 ALERT_ENTRY(GNUTLS_A_BAD_CERTIFICATE, N_("Certificate is bad")),
52 ALERT_ENTRY(GNUTLS_A_UNSUPPORTED_CERTIFICATE,
53 N_("Certificate is not supported")),
54 ALERT_ENTRY(GNUTLS_A_CERTIFICATE_REVOKED,
55 N_("Certificate was revoked")),
56 ALERT_ENTRY(GNUTLS_A_CERTIFICATE_EXPIRED,
57 N_("Certificate is expired")),
58 ALERT_ENTRY(GNUTLS_A_CERTIFICATE_UNKNOWN,
59 N_("Unknown certificate")),
60 ALERT_ENTRY(GNUTLS_A_ILLEGAL_PARAMETER, N_("Illegal parameter")),
61 ALERT_ENTRY(GNUTLS_A_UNKNOWN_CA, N_("CA is unknown")),
62 ALERT_ENTRY(GNUTLS_A_ACCESS_DENIED, N_("Access was denied")),
63 ALERT_ENTRY(GNUTLS_A_DECODE_ERROR, N_("Decode error")),
64 ALERT_ENTRY(GNUTLS_A_DECRYPT_ERROR, N_("Decrypt error")),
65 ALERT_ENTRY(GNUTLS_A_EXPORT_RESTRICTION, N_("Export restriction")),
66 ALERT_ENTRY(GNUTLS_A_PROTOCOL_VERSION,
67 N_("Error in protocol version")),
68 ALERT_ENTRY(GNUTLS_A_INSUFFICIENT_SECURITY,
69 N_("Insufficient security")),
70 ALERT_ENTRY(GNUTLS_A_USER_CANCELED, N_("User canceled")),
71 ALERT_ENTRY(GNUTLS_A_SSL3_NO_CERTIFICATE,
72 N_("No certificate (SSL 3.0)")),
73 ALERT_ENTRY(GNUTLS_A_INTERNAL_ERROR, N_("Internal error")),
74 ALERT_ENTRY(GNUTLS_A_NO_RENEGOTIATION,
75 N_("No renegotiation is allowed")),
76 ALERT_ENTRY(GNUTLS_A_CERTIFICATE_UNOBTAINABLE,
77 N_("Could not retrieve the specified certificate")),
78 ALERT_ENTRY(GNUTLS_A_UNSUPPORTED_EXTENSION,
79 N_("An unsupported extension was sent")),
80 ALERT_ENTRY(GNUTLS_A_UNRECOGNIZED_NAME,
81 N_("The server name sent was not recognized")),
82 ALERT_ENTRY(GNUTLS_A_UNKNOWN_PSK_IDENTITY,
83 N_("The SRP/PSK username is missing or not known")),
84 ALERT_ENTRY(GNUTLS_A_NO_APPLICATION_PROTOCOL,
86 ("No supported application protocol could be negotiated")),
91 * gnutls_alert_get_name:
92 * @alert: is an alert number.
94 * This function will return a string that describes the given alert
95 * number, or %NULL. See gnutls_alert_get().
97 * Returns: string corresponding to #gnutls_alert_description_t value.
99 const char *gnutls_alert_get_name(gnutls_alert_description_t alert)
101 const gnutls_alert_entry *p;
103 for (p = sup_alerts; p->desc != NULL; p++)
104 if (p->alert == alert)
111 * gnutls_alert_get_strname:
112 * @alert: is an alert number.
114 * This function will return a string of the name of the alert.
116 * Returns: string corresponding to #gnutls_alert_description_t value.
120 const char *gnutls_alert_get_strname(gnutls_alert_description_t alert)
122 const gnutls_alert_entry *p;
124 for (p = sup_alerts; p->name != NULL; p++)
125 if (p->alert == alert)
133 * @session: is a #gnutls_session_t structure.
134 * @level: is the level of the alert
135 * @desc: is the alert description
137 * This function will send an alert to the peer in order to inform
138 * him of something important (eg. his Certificate could not be verified).
139 * If the alert level is Fatal then the peer is expected to close the
140 * connection, otherwise he may ignore the alert and continue.
142 * The error code of the underlying record send function will be
143 * returned, so you may also receive %GNUTLS_E_INTERRUPTED or
144 * %GNUTLS_E_AGAIN as well.
146 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
147 * an error code is returned.
150 gnutls_alert_send(gnutls_session_t session, gnutls_alert_level_t level,
151 gnutls_alert_description_t desc)
157 data[0] = (uint8_t) level;
158 data[1] = (uint8_t) desc;
160 name = gnutls_alert_get_name((int) data[1]);
163 _gnutls_record_log("REC: Sending Alert[%d|%d] - %s\n", data[0],
167 _gnutls_send_int(session, GNUTLS_ALERT, -1,
168 EPOCH_WRITE_CURRENT, data, 2,
169 MBUFFER_FLUSH)) >= 0)
176 * gnutls_error_to_alert:
177 * @err: is a negative integer
178 * @level: the alert level will be stored there
180 * Get an alert depending on the error code returned by a gnutls
181 * function. All alerts sent by this function should be considered
182 * fatal. The only exception is when @err is %GNUTLS_E_REHANDSHAKE,
183 * where a warning alert should be sent to the peer indicating that no
184 * renegotiation will be performed.
186 * If there is no mapping to a valid alert the alert to indicate
187 * internal error is returned.
189 * Returns: the alert code to use for a particular error code.
191 int gnutls_error_to_alert(int err, int *level)
193 int ret, _level = -1;
195 switch (err) { /* send appropriate alert */
196 case GNUTLS_E_DECRYPTION_FAILED:
197 /* GNUTLS_A_DECRYPTION_FAILED is not sent, because
198 * it is not defined in SSL3. Note that we must
199 * not distinguish Decryption failures from mac
200 * check failures, due to the possibility of some
203 ret = GNUTLS_A_BAD_RECORD_MAC;
204 _level = GNUTLS_AL_FATAL;
206 case GNUTLS_E_DECOMPRESSION_FAILED:
207 ret = GNUTLS_A_DECOMPRESSION_FAILURE;
208 _level = GNUTLS_AL_FATAL;
210 case GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER:
211 case GNUTLS_E_ILLEGAL_SRP_USERNAME:
212 ret = GNUTLS_A_ILLEGAL_PARAMETER;
213 _level = GNUTLS_AL_FATAL;
215 case GNUTLS_E_UNKNOWN_SRP_USERNAME:
216 ret = GNUTLS_A_UNKNOWN_PSK_IDENTITY;
217 _level = GNUTLS_AL_FATAL;
219 case GNUTLS_E_ASN1_ELEMENT_NOT_FOUND:
220 case GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND:
221 case GNUTLS_E_ASN1_DER_ERROR:
222 case GNUTLS_E_ASN1_VALUE_NOT_FOUND:
223 case GNUTLS_E_ASN1_GENERIC_ERROR:
224 case GNUTLS_E_ASN1_VALUE_NOT_VALID:
225 case GNUTLS_E_ASN1_TAG_ERROR:
226 case GNUTLS_E_ASN1_TAG_IMPLICIT:
227 case GNUTLS_E_ASN1_TYPE_ANY_ERROR:
228 case GNUTLS_E_ASN1_SYNTAX_ERROR:
229 case GNUTLS_E_ASN1_DER_OVERFLOW:
230 case GNUTLS_E_CERTIFICATE_ERROR:
231 ret = GNUTLS_A_BAD_CERTIFICATE;
232 _level = GNUTLS_AL_FATAL;
234 case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
235 case GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM:
236 case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
237 case GNUTLS_E_NO_CIPHER_SUITES:
238 case GNUTLS_E_NO_COMPRESSION_ALGORITHMS:
239 case GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM:
240 case GNUTLS_E_SAFE_RENEGOTIATION_FAILED:
241 case GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL:
242 case GNUTLS_E_UNKNOWN_PK_ALGORITHM:
243 ret = GNUTLS_A_HANDSHAKE_FAILURE;
244 _level = GNUTLS_AL_FATAL;
246 case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
247 ret = GNUTLS_A_UNSUPPORTED_EXTENSION;
248 _level = GNUTLS_AL_FATAL;
250 case GNUTLS_E_USER_ERROR:
251 ret = GNUTLS_A_USER_CANCELED;
252 _level = GNUTLS_AL_FATAL;
254 case GNUTLS_E_UNEXPECTED_PACKET:
255 case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
256 case GNUTLS_E_PREMATURE_TERMINATION:
257 ret = GNUTLS_A_UNEXPECTED_MESSAGE;
258 _level = GNUTLS_AL_FATAL;
260 case GNUTLS_E_REHANDSHAKE:
261 case GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED:
262 ret = GNUTLS_A_NO_RENEGOTIATION;
263 _level = GNUTLS_AL_WARNING;
265 case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
266 ret = GNUTLS_A_PROTOCOL_VERSION;
267 _level = GNUTLS_AL_FATAL;
269 case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
270 ret = GNUTLS_A_UNSUPPORTED_CERTIFICATE;
271 _level = GNUTLS_AL_FATAL;
273 case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
274 ret = GNUTLS_A_RECORD_OVERFLOW;
275 _level = GNUTLS_AL_FATAL;
277 case GNUTLS_E_INTERNAL_ERROR:
278 case GNUTLS_E_NO_TEMPORARY_DH_PARAMS:
279 case GNUTLS_E_NO_TEMPORARY_RSA_PARAMS:
280 ret = GNUTLS_A_INTERNAL_ERROR;
281 _level = GNUTLS_AL_FATAL;
283 case GNUTLS_E_OPENPGP_GETKEY_FAILED:
284 ret = GNUTLS_A_CERTIFICATE_UNOBTAINABLE;
285 _level = GNUTLS_AL_FATAL;
287 case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
288 case GNUTLS_E_NO_CERTIFICATE_FOUND:
289 ret = GNUTLS_A_INSUFFICIENT_SECURITY;
290 _level = GNUTLS_AL_FATAL;
292 case GNUTLS_E_NO_APPLICATION_PROTOCOL:
293 ret = GNUTLS_A_NO_APPLICATION_PROTOCOL;
294 _level = GNUTLS_AL_FATAL;
297 ret = GNUTLS_A_INTERNAL_ERROR;
298 _level = GNUTLS_AL_FATAL;
309 * gnutls_alert_send_appropriate:
310 * @session: is a #gnutls_session_t structure.
311 * @err: is an integer
313 * Sends an alert to the peer depending on the error code returned by
314 * a gnutls function. This function will call gnutls_error_to_alert()
315 * to determine the appropriate alert to send.
317 * This function may also return %GNUTLS_E_AGAIN, or
318 * %GNUTLS_E_INTERRUPTED.
320 * If the return value is %GNUTLS_E_INVALID_REQUEST, then no alert has
321 * been sent to the peer.
323 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
324 * an error code is returned.
326 int gnutls_alert_send_appropriate(gnutls_session_t session, int err)
331 alert = gnutls_error_to_alert(err, &level);
336 return gnutls_alert_send(session, level, alert);
341 * @session: is a #gnutls_session_t structure.
343 * This function will return the last alert number received. This
344 * function should be called when %GNUTLS_E_WARNING_ALERT_RECEIVED or
345 * %GNUTLS_E_FATAL_ALERT_RECEIVED errors are returned by a gnutls
346 * function. The peer may send alerts if he encounters an error.
347 * If no alert has been received the returned value is undefined.
349 * Returns: the last alert received, a
350 * #gnutls_alert_description_t value.
352 gnutls_alert_description_t gnutls_alert_get(gnutls_session_t session)
354 return session->internals.last_alert;