Line data Source code
1 : /*
2 : * Copyright (C) 2000-2012 Free Software Foundation, Inc.
3 : *
4 : * Author: Nikos Mavrogiannopoulos
5 : *
6 : * This file is part of GnuTLS.
7 : *
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.
12 : *
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.
17 : *
18 : * You should have received a copy of the GNU Lesser General Public License
19 : * along with this program. If not, see <https://www.gnu.org/licenses/>
20 : *
21 : */
22 :
23 : #include "gnutls_int.h"
24 : #include "errors.h"
25 : #include <record.h>
26 : #include <debug.h>
27 : #include "str.h"
28 :
29 : typedef struct {
30 : gnutls_alert_description_t alert;
31 : const char *name;
32 : const char *desc;
33 : } gnutls_alert_entry;
34 :
35 : #define ALERT_ENTRY(x,y) \
36 : {x, #x, y}
37 :
38 : static const gnutls_alert_entry sup_alerts[] = {
39 : ALERT_ENTRY(GNUTLS_A_CLOSE_NOTIFY, N_("Close notify")),
40 : ALERT_ENTRY(GNUTLS_A_UNEXPECTED_MESSAGE, N_("Unexpected message")),
41 : ALERT_ENTRY(GNUTLS_A_BAD_RECORD_MAC, N_("Bad record MAC")),
42 : ALERT_ENTRY(GNUTLS_A_DECRYPTION_FAILED, N_("Decryption failed")),
43 : ALERT_ENTRY(GNUTLS_A_RECORD_OVERFLOW, N_("Record overflow")),
44 : ALERT_ENTRY(GNUTLS_A_DECOMPRESSION_FAILURE,
45 : N_("Decompression failed")),
46 : ALERT_ENTRY(GNUTLS_A_HANDSHAKE_FAILURE, N_("Handshake failed")),
47 : ALERT_ENTRY(GNUTLS_A_BAD_CERTIFICATE, N_("Certificate is bad")),
48 : ALERT_ENTRY(GNUTLS_A_UNSUPPORTED_CERTIFICATE,
49 : N_("Certificate is not supported")),
50 : ALERT_ENTRY(GNUTLS_A_CERTIFICATE_REVOKED,
51 : N_("Certificate was revoked")),
52 : ALERT_ENTRY(GNUTLS_A_CERTIFICATE_EXPIRED,
53 : N_("Certificate is expired")),
54 : ALERT_ENTRY(GNUTLS_A_CERTIFICATE_UNKNOWN,
55 : N_("Unknown certificate")),
56 : ALERT_ENTRY(GNUTLS_A_ILLEGAL_PARAMETER, N_("Illegal parameter")),
57 : ALERT_ENTRY(GNUTLS_A_UNKNOWN_CA, N_("CA is unknown")),
58 : ALERT_ENTRY(GNUTLS_A_ACCESS_DENIED, N_("Access was denied")),
59 : ALERT_ENTRY(GNUTLS_A_DECODE_ERROR, N_("Decode error")),
60 : ALERT_ENTRY(GNUTLS_A_DECRYPT_ERROR, N_("Decrypt error")),
61 : ALERT_ENTRY(GNUTLS_A_EXPORT_RESTRICTION, N_("Export restriction")),
62 : ALERT_ENTRY(GNUTLS_A_PROTOCOL_VERSION,
63 : N_("Error in protocol version")),
64 : ALERT_ENTRY(GNUTLS_A_INSUFFICIENT_SECURITY,
65 : N_("Insufficient security")),
66 : ALERT_ENTRY(GNUTLS_A_USER_CANCELED, N_("User canceled")),
67 : ALERT_ENTRY(GNUTLS_A_SSL3_NO_CERTIFICATE,
68 : N_("No certificate (SSL 3.0)")),
69 : ALERT_ENTRY(GNUTLS_A_INTERNAL_ERROR, N_("Internal error")),
70 : ALERT_ENTRY(GNUTLS_A_INAPPROPRIATE_FALLBACK,
71 : N_("Inappropriate fallback")),
72 : ALERT_ENTRY(GNUTLS_A_NO_RENEGOTIATION,
73 : N_("No renegotiation is allowed")),
74 : ALERT_ENTRY(GNUTLS_A_CERTIFICATE_UNOBTAINABLE,
75 : N_("Could not retrieve the specified certificate")),
76 : ALERT_ENTRY(GNUTLS_A_UNSUPPORTED_EXTENSION,
77 : N_("An unsupported extension was sent")),
78 : ALERT_ENTRY(GNUTLS_A_UNRECOGNIZED_NAME,
79 : N_("The server name sent was not recognized")),
80 : ALERT_ENTRY(GNUTLS_A_UNKNOWN_PSK_IDENTITY,
81 : N_("The SRP/PSK username is missing or not known")),
82 : ALERT_ENTRY(GNUTLS_A_MISSING_EXTENSION,
83 : N_("An extension was expected but was not seen")),
84 : ALERT_ENTRY(GNUTLS_A_NO_APPLICATION_PROTOCOL,
85 : N_
86 : ("No supported application protocol could be negotiated")),
87 : ALERT_ENTRY(GNUTLS_A_CERTIFICATE_REQUIRED,
88 : N_("Certificate is required")),
89 : {0, NULL, NULL}
90 : };
91 :
92 : /**
93 : * gnutls_alert_get_name:
94 : * @alert: is an alert number.
95 : *
96 : * This function will return a string that describes the given alert
97 : * number, or %NULL. See gnutls_alert_get().
98 : *
99 : * Returns: string corresponding to #gnutls_alert_description_t value.
100 : **/
101 17759 : const char *gnutls_alert_get_name(gnutls_alert_description_t alert)
102 : {
103 17759 : const gnutls_alert_entry *p;
104 :
105 79059 : for (p = sup_alerts; p->desc != NULL; p++)
106 79059 : if (p->alert == alert)
107 17759 : return _(p->desc);
108 :
109 : return NULL;
110 : }
111 :
112 : /**
113 : * gnutls_alert_get_strname:
114 : * @alert: is an alert number.
115 : *
116 : * This function will return a string of the name of the alert.
117 : *
118 : * Returns: string corresponding to #gnutls_alert_description_t value.
119 : *
120 : * Since: 3.0
121 : **/
122 121 : const char *gnutls_alert_get_strname(gnutls_alert_description_t alert)
123 : {
124 121 : const gnutls_alert_entry *p;
125 :
126 3465 : for (p = sup_alerts; p->name != NULL; p++)
127 3376 : if (p->alert == alert)
128 : return p->name;
129 :
130 : return NULL;
131 : }
132 :
133 : /**
134 : * gnutls_alert_send:
135 : * @session: is a #gnutls_session_t type.
136 : * @level: is the level of the alert
137 : * @desc: is the alert description
138 : *
139 : * This function will send an alert to the peer in order to inform
140 : * him of something important (eg. his Certificate could not be verified).
141 : * If the alert level is Fatal then the peer is expected to close the
142 : * connection, otherwise he may ignore the alert and continue.
143 : *
144 : * The error code of the underlying record send function will be
145 : * returned, so you may also receive %GNUTLS_E_INTERRUPTED or
146 : * %GNUTLS_E_AGAIN as well.
147 : *
148 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
149 : * an error code is returned.
150 : **/
151 : int
152 17713 : gnutls_alert_send(gnutls_session_t session, gnutls_alert_level_t level,
153 : gnutls_alert_description_t desc)
154 : {
155 17713 : uint8_t data[2];
156 17713 : int ret;
157 17713 : const char *name;
158 :
159 17713 : data[0] = (uint8_t) level;
160 17713 : data[1] = (uint8_t) desc;
161 :
162 17713 : name = gnutls_alert_get_name((gnutls_alert_description_t) data[1]);
163 17713 : if (name == NULL)
164 0 : name = "(unknown)";
165 17713 : _gnutls_record_log("REC: Sending Alert[%d|%d] - %s\n", data[0],
166 : data[1], name);
167 :
168 17713 : if ((ret =
169 17713 : _gnutls_send_int(session, GNUTLS_ALERT, -1,
170 : EPOCH_WRITE_CURRENT, data, 2,
171 : MBUFFER_FLUSH)) >= 0)
172 : return 0;
173 : else
174 237 : return ret;
175 : }
176 :
177 : /**
178 : * gnutls_error_to_alert:
179 : * @err: is a negative integer
180 : * @level: the alert level will be stored there
181 : *
182 : * Get an alert depending on the error code returned by a gnutls
183 : * function. All alerts sent by this function should be considered
184 : * fatal. The only exception is when @err is %GNUTLS_E_REHANDSHAKE,
185 : * where a warning alert should be sent to the peer indicating that no
186 : * renegotiation will be performed.
187 : *
188 : * If there is no mapping to a valid alert the alert to indicate
189 : * internal error (%GNUTLS_A_INTERNAL_ERROR) is returned.
190 : *
191 : * Returns: the alert code to use for a particular error code.
192 : **/
193 5203 : int gnutls_error_to_alert(int err, int *level)
194 : {
195 5203 : int ret, _level = -1;
196 :
197 5203 : switch (err) { /* send appropriate alert */
198 : case GNUTLS_E_PK_SIG_VERIFY_FAILED:
199 : case GNUTLS_E_ERROR_IN_FINISHED_PACKET:
200 : ret = GNUTLS_A_DECRYPT_ERROR;
201 : _level = GNUTLS_AL_FATAL;
202 : break;
203 743 : case GNUTLS_E_DECRYPTION_FAILED:
204 : /* GNUTLS_A_DECRYPTION_FAILED is not sent, because
205 : * it is not defined in SSL3. Note that we must
206 : * not distinguish Decryption failures from mac
207 : * check failures, due to the possibility of some
208 : * attacks.
209 : */
210 743 : ret = GNUTLS_A_BAD_RECORD_MAC;
211 743 : _level = GNUTLS_AL_FATAL;
212 743 : break;
213 2639 : case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
214 : case GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH:
215 : case GNUTLS_E_NO_CERTIFICATE_FOUND:
216 : case GNUTLS_E_HANDSHAKE_TOO_LARGE:
217 2639 : ret = GNUTLS_A_DECODE_ERROR;
218 2639 : _level = GNUTLS_AL_FATAL;
219 2639 : break;
220 0 : case GNUTLS_E_DECOMPRESSION_FAILED:
221 0 : ret = GNUTLS_A_DECOMPRESSION_FAILURE;
222 0 : _level = GNUTLS_AL_FATAL;
223 0 : break;
224 453 : case GNUTLS_E_ILLEGAL_PARAMETER:
225 : case GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER:
226 : case GNUTLS_E_ILLEGAL_SRP_USERNAME:
227 : case GNUTLS_E_PK_INVALID_PUBKEY:
228 : case GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM:
229 : case GNUTLS_E_RECEIVED_DISALLOWED_NAME:
230 : case GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY:
231 453 : ret = GNUTLS_A_ILLEGAL_PARAMETER;
232 453 : _level = GNUTLS_AL_FATAL;
233 453 : break;
234 0 : case GNUTLS_E_UNKNOWN_SRP_USERNAME:
235 0 : ret = GNUTLS_A_UNKNOWN_PSK_IDENTITY;
236 0 : _level = GNUTLS_AL_FATAL;
237 0 : break;
238 17 : case GNUTLS_E_ASN1_ELEMENT_NOT_FOUND:
239 : case GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND:
240 : case GNUTLS_E_ASN1_DER_ERROR:
241 : case GNUTLS_E_ASN1_VALUE_NOT_FOUND:
242 : case GNUTLS_E_ASN1_GENERIC_ERROR:
243 : case GNUTLS_E_ASN1_VALUE_NOT_VALID:
244 : case GNUTLS_E_ASN1_TAG_ERROR:
245 : case GNUTLS_E_ASN1_TAG_IMPLICIT:
246 : case GNUTLS_E_ASN1_TYPE_ANY_ERROR:
247 : case GNUTLS_E_ASN1_SYNTAX_ERROR:
248 : case GNUTLS_E_ASN1_DER_OVERFLOW:
249 : case GNUTLS_E_CERTIFICATE_ERROR:
250 : case GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR:
251 17 : ret = GNUTLS_A_BAD_CERTIFICATE;
252 17 : _level = GNUTLS_AL_FATAL;
253 17 : break;
254 544 : case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
255 : case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
256 : case GNUTLS_E_NO_CIPHER_SUITES:
257 : case GNUTLS_E_NO_COMPRESSION_ALGORITHMS:
258 : case GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM:
259 : case GNUTLS_E_SAFE_RENEGOTIATION_FAILED:
260 : case GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL:
261 : case GNUTLS_E_UNKNOWN_PK_ALGORITHM:
262 : case GNUTLS_E_UNWANTED_ALGORITHM:
263 : case GNUTLS_E_NO_COMMON_KEY_SHARE:
264 : case GNUTLS_E_ECC_NO_SUPPORTED_CURVES:
265 : case GNUTLS_E_ECC_UNSUPPORTED_CURVE:
266 544 : ret = GNUTLS_A_HANDSHAKE_FAILURE;
267 544 : _level = GNUTLS_AL_FATAL;
268 544 : break;
269 0 : case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
270 0 : ret = GNUTLS_A_UNSUPPORTED_EXTENSION;
271 0 : _level = GNUTLS_AL_FATAL;
272 0 : break;
273 1 : case GNUTLS_E_MISSING_EXTENSION:
274 1 : ret = GNUTLS_A_MISSING_EXTENSION;
275 1 : _level = GNUTLS_AL_FATAL;
276 1 : break;
277 0 : case GNUTLS_E_USER_ERROR:
278 0 : ret = GNUTLS_A_USER_CANCELED;
279 0 : _level = GNUTLS_AL_FATAL;
280 0 : break;
281 230 : case GNUTLS_E_UNEXPECTED_PACKET:
282 : case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
283 : case GNUTLS_E_PREMATURE_TERMINATION:
284 230 : ret = GNUTLS_A_UNEXPECTED_MESSAGE;
285 230 : _level = GNUTLS_AL_FATAL;
286 230 : break;
287 0 : case GNUTLS_E_REHANDSHAKE:
288 : case GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED:
289 0 : ret = GNUTLS_A_NO_RENEGOTIATION;
290 0 : _level = GNUTLS_AL_WARNING;
291 0 : break;
292 59 : case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
293 59 : ret = GNUTLS_A_PROTOCOL_VERSION;
294 59 : _level = GNUTLS_AL_FATAL;
295 59 : break;
296 0 : case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
297 0 : ret = GNUTLS_A_UNSUPPORTED_CERTIFICATE;
298 0 : _level = GNUTLS_AL_FATAL;
299 0 : break;
300 17 : case GNUTLS_E_RECORD_OVERFLOW:
301 17 : ret = GNUTLS_A_RECORD_OVERFLOW;
302 17 : _level = GNUTLS_AL_FATAL;
303 17 : break;
304 0 : case GNUTLS_E_INTERNAL_ERROR:
305 : case GNUTLS_E_NO_TEMPORARY_DH_PARAMS:
306 : case GNUTLS_E_NO_TEMPORARY_RSA_PARAMS:
307 0 : ret = GNUTLS_A_INTERNAL_ERROR;
308 0 : _level = GNUTLS_AL_FATAL;
309 0 : break;
310 20 : case GNUTLS_E_INAPPROPRIATE_FALLBACK:
311 20 : ret = GNUTLS_A_INAPPROPRIATE_FALLBACK;
312 20 : _level = GNUTLS_AL_FATAL;
313 20 : break;
314 0 : case GNUTLS_E_OPENPGP_GETKEY_FAILED:
315 0 : ret = GNUTLS_A_CERTIFICATE_UNOBTAINABLE;
316 0 : _level = GNUTLS_AL_FATAL;
317 0 : break;
318 0 : case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
319 : case GNUTLS_E_SESSION_USER_ID_CHANGED:
320 : case GNUTLS_E_INSUFFICIENT_SECURITY:
321 0 : ret = GNUTLS_A_INSUFFICIENT_SECURITY;
322 0 : _level = GNUTLS_AL_FATAL;
323 0 : break;
324 2 : case GNUTLS_E_NO_APPLICATION_PROTOCOL:
325 2 : ret = GNUTLS_A_NO_APPLICATION_PROTOCOL;
326 2 : _level = GNUTLS_AL_FATAL;
327 2 : break;
328 2 : case GNUTLS_E_UNRECOGNIZED_NAME:
329 2 : ret = GNUTLS_A_UNRECOGNIZED_NAME;
330 2 : _level = GNUTLS_AL_FATAL;
331 2 : break;
332 3 : case GNUTLS_E_CERTIFICATE_REQUIRED:
333 3 : ret = GNUTLS_A_CERTIFICATE_REQUIRED;
334 3 : _level = GNUTLS_AL_FATAL;
335 3 : break;
336 232 : default:
337 232 : ret = GNUTLS_A_INTERNAL_ERROR;
338 232 : _level = GNUTLS_AL_FATAL;
339 232 : break;
340 : }
341 :
342 5203 : if (level != NULL)
343 5203 : *level = _level;
344 :
345 5203 : return ret;
346 : }
347 :
348 : /**
349 : * gnutls_alert_send_appropriate:
350 : * @session: is a #gnutls_session_t type.
351 : * @err: is an error code returned by another GnuTLS function
352 : *
353 : * Sends an alert to the peer depending on the error code returned by
354 : * a gnutls function. This function will call gnutls_error_to_alert()
355 : * to determine the appropriate alert to send.
356 : *
357 : * This function may also return %GNUTLS_E_AGAIN, or
358 : * %GNUTLS_E_INTERRUPTED.
359 : *
360 : * This function historically was always sending an alert to the
361 : * peer, even if @err was inappropriate to respond with an alert
362 : * (e.g., %GNUTLS_E_SUCCESS). Since 3.6.6 this function returns
363 : * success without transmitting any data on error codes that
364 : * should not result to an alert.
365 : *
366 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
367 : * an error code is returned.
368 : */
369 5232 : int gnutls_alert_send_appropriate(gnutls_session_t session, int err)
370 : {
371 5232 : int alert;
372 5232 : int level;
373 :
374 5232 : if (err != GNUTLS_E_REHANDSHAKE && (!gnutls_error_is_fatal(err) ||
375 : err == GNUTLS_E_FATAL_ALERT_RECEIVED))
376 30 : return gnutls_assert_val(0);
377 :
378 5203 : alert = gnutls_error_to_alert(err, &level);
379 :
380 5203 : return gnutls_alert_send(session, (gnutls_alert_level_t)level, alert);
381 : }
382 :
383 : /**
384 : * gnutls_alert_get:
385 : * @session: is a #gnutls_session_t type.
386 : *
387 : * This function will return the last alert number received. This
388 : * function should be called when %GNUTLS_E_WARNING_ALERT_RECEIVED or
389 : * %GNUTLS_E_FATAL_ALERT_RECEIVED errors are returned by a gnutls
390 : * function. The peer may send alerts if he encounters an error.
391 : * If no alert has been received the returned value is undefined.
392 : *
393 : * Returns: the last alert received, a
394 : * #gnutls_alert_description_t value.
395 : **/
396 1540 : gnutls_alert_description_t gnutls_alert_get(gnutls_session_t session)
397 : {
398 1540 : return (gnutls_alert_description_t)session->internals.last_alert;
399 : }
|