Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / lib / gnutls_alert.c
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 <http://www.gnu.org/licenses/>
20  *
21  */
22
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <gnutls_record.h>
26 #include <debug.h>
27
28 /* I18n of error codes. */
29 #include "gettext.h"
30 #define _(String) dgettext (PACKAGE, String)
31 #define N_(String) gettext_noop (String)
32
33 typedef struct {
34         gnutls_alert_description_t alert;
35         const char *name;
36         const char *desc;
37 } gnutls_alert_entry;
38
39 #define ALERT_ENTRY(x,y) \
40   {x, #x, y}
41
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,
85                     N_
86                     ("No supported application protocol could be negotiated")),
87         {0, NULL, NULL}
88 };
89
90 /**
91  * gnutls_alert_get_name:
92  * @alert: is an alert number.
93  *
94  * This function will return a string that describes the given alert
95  * number, or %NULL.  See gnutls_alert_get().
96  *
97  * Returns: string corresponding to #gnutls_alert_description_t value.
98  **/
99 const char *gnutls_alert_get_name(gnutls_alert_description_t alert)
100 {
101         const gnutls_alert_entry *p;
102
103         for (p = sup_alerts; p->desc != NULL; p++)
104                 if (p->alert == alert)
105                         return _(p->desc);
106
107         return NULL;
108 }
109
110 /**
111  * gnutls_alert_get_strname:
112  * @alert: is an alert number.
113  *
114  * This function will return a string of the name of the alert.
115  *
116  * Returns: string corresponding to #gnutls_alert_description_t value.
117  *
118  * Since: 3.0
119  **/
120 const char *gnutls_alert_get_strname(gnutls_alert_description_t alert)
121 {
122         const gnutls_alert_entry *p;
123
124         for (p = sup_alerts; p->name != NULL; p++)
125                 if (p->alert == alert)
126                         return p->name;
127
128         return NULL;
129 }
130
131 /**
132  * gnutls_alert_send:
133  * @session: is a #gnutls_session_t structure.
134  * @level: is the level of the alert
135  * @desc: is the alert description
136  *
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.
141  *
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.
145  *
146  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
147  *   an error code is returned.
148  **/
149 int
150 gnutls_alert_send(gnutls_session_t session, gnutls_alert_level_t level,
151                   gnutls_alert_description_t desc)
152 {
153         uint8_t data[2];
154         int ret;
155         const char *name;
156
157         data[0] = (uint8_t) level;
158         data[1] = (uint8_t) desc;
159
160         name = gnutls_alert_get_name((int) data[1]);
161         if (name == NULL)
162                 name = "(unknown)";
163         _gnutls_record_log("REC: Sending Alert[%d|%d] - %s\n", data[0],
164                            data[1], name);
165
166         if ((ret =
167              _gnutls_send_int(session, GNUTLS_ALERT, -1,
168                               EPOCH_WRITE_CURRENT, data, 2,
169                               MBUFFER_FLUSH)) >= 0)
170                 return 0;
171         else
172                 return ret;
173 }
174
175 /**
176  * gnutls_error_to_alert:
177  * @err: is a negative integer
178  * @level: the alert level will be stored there
179  *
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.
185  *
186  * If there is no mapping to a valid alert the alert to indicate
187  * internal error is returned.
188  *
189  * Returns: the alert code to use for a particular error code.
190  **/
191 int gnutls_error_to_alert(int err, int *level)
192 {
193         int ret, _level = -1;
194
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
201                  * attacks.
202                  */
203                 ret = GNUTLS_A_BAD_RECORD_MAC;
204                 _level = GNUTLS_AL_FATAL;
205                 break;
206         case GNUTLS_E_DECOMPRESSION_FAILED:
207                 ret = GNUTLS_A_DECOMPRESSION_FAILURE;
208                 _level = GNUTLS_AL_FATAL;
209                 break;
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;
214                 break;
215         case GNUTLS_E_UNKNOWN_SRP_USERNAME:
216                 ret = GNUTLS_A_UNKNOWN_PSK_IDENTITY;
217                 _level = GNUTLS_AL_FATAL;
218                 break;
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;
233                 break;
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;
245                 break;
246         case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
247                 ret = GNUTLS_A_UNSUPPORTED_EXTENSION;
248                 _level = GNUTLS_AL_FATAL;
249                 break;
250         case GNUTLS_E_USER_ERROR:
251                 ret = GNUTLS_A_USER_CANCELED;
252                 _level = GNUTLS_AL_FATAL;
253                 break;
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;
259                 break;
260         case GNUTLS_E_REHANDSHAKE:
261         case GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED:
262                 ret = GNUTLS_A_NO_RENEGOTIATION;
263                 _level = GNUTLS_AL_WARNING;
264                 break;
265         case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
266                 ret = GNUTLS_A_PROTOCOL_VERSION;
267                 _level = GNUTLS_AL_FATAL;
268                 break;
269         case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
270                 ret = GNUTLS_A_UNSUPPORTED_CERTIFICATE;
271                 _level = GNUTLS_AL_FATAL;
272                 break;
273         case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
274                 ret = GNUTLS_A_RECORD_OVERFLOW;
275                 _level = GNUTLS_AL_FATAL;
276                 break;
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;
282                 break;
283         case GNUTLS_E_OPENPGP_GETKEY_FAILED:
284                 ret = GNUTLS_A_CERTIFICATE_UNOBTAINABLE;
285                 _level = GNUTLS_AL_FATAL;
286                 break;
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;
291                 break;
292         case GNUTLS_E_NO_APPLICATION_PROTOCOL:
293                 ret = GNUTLS_A_NO_APPLICATION_PROTOCOL;
294                 _level = GNUTLS_AL_FATAL;
295                 break;
296         default:
297                 ret = GNUTLS_A_INTERNAL_ERROR;
298                 _level = GNUTLS_AL_FATAL;
299                 break;
300         }
301
302         if (level != NULL)
303                 *level = _level;
304
305         return ret;
306 }
307
308 /**
309  * gnutls_alert_send_appropriate:
310  * @session: is a #gnutls_session_t structure.
311  * @err: is an integer
312  *
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.
316  *
317  * This function may also return %GNUTLS_E_AGAIN, or
318  * %GNUTLS_E_INTERRUPTED.
319  *
320  * If the return value is %GNUTLS_E_INVALID_REQUEST, then no alert has
321  * been sent to the peer.
322  *
323  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
324  *   an error code is returned.
325  */
326 int gnutls_alert_send_appropriate(gnutls_session_t session, int err)
327 {
328         int alert;
329         int level;
330
331         alert = gnutls_error_to_alert(err, &level);
332         if (alert < 0) {
333                 return alert;
334         }
335
336         return gnutls_alert_send(session, level, alert);
337 }
338
339 /**
340  * gnutls_alert_get:
341  * @session: is a #gnutls_session_t structure.
342  *
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.
348  *
349  * Returns: the last alert received, a
350  *   #gnutls_alert_description_t value.
351  **/
352 gnutls_alert_description_t gnutls_alert_get(gnutls_session_t session)
353 {
354         return session->internals.last_alert;
355 }