1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
# Error Handling
s2n-tls functions that return 'int' return 0 to indicate success and -1 to indicate
failure. s2n-tls functions that return pointer types return NULL in the case of
failure. When an s2n-tls function returns a failure, s2n_errno will be set to a value
corresponding to the error. This error value can be translated into a string
explaining the error in English by calling `s2n_strerror(s2n_errno, "EN")`.
A string containing human readable error name, can be generated with `s2n_strerror_name()`.
A string containing internal debug information, including filename and line number, can be generated with `s2n_strerror_debug()`.
This string is useful to include when reporting issues to the s2n-tls development team.
Example:
```
if (s2n_config_set_cipher_preferences(config, prefs) < 0) {
printf("Setting cipher prefs failed! %s : %s", s2n_strerror(s2n_errno, "EN"), s2n_strerror_debug(s2n_errno, "EN"));
return -1;
}
```
**NOTE**: To avoid possible confusion, s2n_errno should be cleared after processing an error: `s2n_errno = S2N_ERR_T_OK`
When using s2n-tls outside of `C`, the address of the thread-local `s2n_errno` may be obtained by calling the `s2n_errno_location()` function.
This will ensure that the same TLS mechanisms are used with which s2n-tls was compiled.
## Error Types
s2n-tls organizes errors into different "types" to allow applications to handle error values without catching all possibilities.
Applications using non-blocking I/O should check the error type to determine if the I/O operation failed because it would block or for some other error. To retrieve the type for a given error use `s2n_error_get_type()`.
Applications should perform any error handling logic using these high level types:
Here's an example that handles errors based on type:
```c
#define SUCCESS 0
#define FAILURE 1
#define RETRY 2
s2n_errno = S2N_ERR_T_OK;
if (s2n_negotiate(conn, &blocked) < 0) {
switch(s2n_error_get_type(s2n_errno)) {
case S2N_ERR_T_BLOCKED:
/* Blocked, come back later */
return RETRY;
case S2N_ERR_T_CLOSED:
return SUCCESS;
case S2N_ERR_T_IO:
handle_io_err(errno);
return FAILURE;
case S2N_ERR_T_PROTO:
handle_proto_err();
return FAILURE;
case S2N_ERR_T_ALERT:
log_alert(s2n_connection_get_alert(conn));
return FAILURE;
/* Everything else */
default:
log_other_error();
return FAILURE;
}
}
```
### Blinding
Blinding is a mitigation against timing side-channels which in some cases can leak information about encrypted data. By default s2n-tls will cause a thread to sleep between 10 and 30 seconds whenever tampering is detected.
Setting the `S2N_SELF_SERVICE_BLINDING` option with `s2n_connection_set_blinding()` turns off this behavior. This is useful for applications that are handling many connections in a single thread. In that case, if `s2n_recv()` or `s2n_negotiate()` return an error, self-service applications must call `s2n_connection_get_delay()` and pause activity on the connection for the specified number of nanoseconds before calling `close()` or `shutdown()`. `s2n_shutdown()` will fail if called before the blinding delay elapses.
### Stacktraces
s2n-tls has an mechanism to capture stacktraces when errors occur.
This mechanism is off by default, but can be enabled in code by calling `s2n_stack_traces_enabled_set()`.
It can be enabled globally by setting the environment variable `S2N_PRINT_STACKTRACE=1`.
Call `s2n_print_stacktrace()` to print your stacktrace.
**Note:** Enabling stacktraces can significantly slow down unit tests, causing failures on tests (such as `s2n_cbc_verify`) that measure the timing of events.
|