Coverage Report

Created: 2023-03-26 08:33

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