diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-06-01 16:02:34 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-06-01 16:09:27 +0200 |
commit | 1875dca5e0f6d7d0a12d9827335b7f4b8a7a2b8e (patch) | |
tree | 210e27f0af33a300d7e785b61a3542f17f3c9e48 | |
parent | 1f9e950b8b25c0607e4631db952e357d1d839b78 (diff) | |
download | gnutls-1875dca5e0f6d7d0a12d9827335b7f4b8a7a2b8e.tar.gz |
Splitted safe renegotiation capabilities to
%SAFE_RENEGOTIATION: will enable safe renegotiation. This is the most
secure and recommended option for clients. However this will prevent from
connecting to legacy servers.
%PARTIAL_RENEGOTIATION: Prevents renegotiation with clients and servers not
supporting the safe renegotiation extension. (this is the default)
%UNSAFE_RENEGOTIATION: Permits (re-)handshakes even unsafe ones.
-rw-r--r-- | doc/announce.txt | 13 | ||||
-rw-r--r-- | doc/gnutls.texi | 24 | ||||
-rw-r--r-- | doc/manpages/gnutls-cli.1 | 9 | ||||
-rw-r--r-- | doc/manpages/gnutls-serv.1 | 10 | ||||
-rw-r--r-- | lib/ext_safe_renegotiation.c | 4 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 20 | ||||
-rw-r--r-- | lib/gnutls_int.h | 12 | ||||
-rw-r--r-- | lib/gnutls_priority.c | 50 | ||||
-rw-r--r-- | lib/gnutls_state.c | 2 | ||||
-rw-r--r-- | tests/safe-renegotiation/srn1.c | 2 | ||||
-rw-r--r-- | tests/safe-renegotiation/srn5.c | 6 | ||||
-rwxr-xr-x | tests/safe-renegotiation/testsrn | 4 |
12 files changed, 70 insertions, 86 deletions
diff --git a/doc/announce.txt b/doc/announce.txt index 599f203ab0..0e6b61f9ba 100644 --- a/doc/announce.txt +++ b/doc/announce.txt @@ -299,16 +299,15 @@ strings. The priority strings can be used by applications (gnutls_priority_set) and end users (e.g., `--priority' parameter to `gnutls-cli' and `gnutls-serv'). -The `%UNSAFE_RENEGOTIATION' priority string requests what is today the +The `%PARTIAL_RENEGOTIATION' priority string requests what is today the default behaviour, i.e., that handshakes without the safe renegotiation extension is permitted. To make more use of the extension, you may provide the `%SAFE_RENEGOTIATION' priority string. In this mode, -clients will require that the server supports the extension for the -initial handshake, and servers will require that the client supports -the extension for renegotiated handshakes. If you want to make a -server refuse even initial handshakes without the safe renegotiation -extension, use the `%INITIAL_SAFE_RENEGOTIATION' priority string. It -is possible to disable use of the extension completely by using the +clients and servers will require that the peer supports the extension for +the initial handshakes. To allow unsafe rengotiation the +`%UNSAFE_RENEGOTIATION' priority string is available. This will send +the extension if supported by peer but will never mandate it. +It is possible to disable use of the extension completely by using the `%DISABLE_SAFE_RENEGOTIATION' priority string however this is recommended against except for debugging. diff --git a/doc/gnutls.texi b/doc/gnutls.texi index daef0ff880..7e4c3ca1a2 100644 --- a/doc/gnutls.texi +++ b/doc/gnutls.texi @@ -1280,7 +1280,6 @@ Note that it is easy to configure clients to always require the safe renegotiation extension from servers (see below on the %SAFE_RENEGOTIATION priority string). - To modify the default behaviour, we have introduced some new priority strings. The priority strings can be used by applications (@pxref{gnutls_priority_set}) and end users (e.g., @code{--priority} @@ -1288,16 +1287,15 @@ parameter to @code{gnutls-cli} and @code{gnutls-serv}). The @code{%UNSAFE_RENEGOTIATION} priority string permits (re-)handshakes even when the safe renegotiation extension was not -negotiated. The @code{%SAFE_RENEGOTIATION} priority string makes -client require the extension for every handshake and servers will refuse -renegotiation without it. - -To enforce your clients to upgrade to a version that supports safe -renegotiation the %INITIAL_SAFE_RENEGOTIATION priority string should -be used at server side. This will deny any (re-)handshakes unless the -client supports the extension. This however will prevent all clients -that do not support the extension from connecting to server, even if -they do not use renegotiation. +negotiated. The default behavior is @code{%PARTIAL_RENEGOTIATION} that will +prevent renegotiation with clients and servers not supporting the +extension. This is secure for servers but leaves clients vulnerable +to some attacks, but this is a tradeoff between security and compatibility +with old servers. The @code{%SAFE_RENEGOTIATION} priority string makes +clients and servers require the extension for every handshake. The latter +is the most secure option for clients, at the cost of not being able +to connect to legacy servers. Servers will also deny clients that +do not support the extension from connecting. It is possible to disable use of the extension completely, in both clients and servers, by using the @code{%DISABLE_SAFE_RENEGOTIATION} @@ -1308,10 +1306,10 @@ The default values if the flags above are not specified are: @table @code @item Server: -%SAFE_RENEGOTIATION +%PARTIAL_RENEGOTIATION @item Client: -%UNSAFE_RENEGOTIATION +%PARTIAL_RENEGOTIATION @end table diff --git a/doc/manpages/gnutls-cli.1 b/doc/manpages/gnutls-cli.1 index 61a68926c0..9d1208e567 100644 --- a/doc/manpages/gnutls-cli.1 +++ b/doc/manpages/gnutls-cli.1 @@ -78,9 +78,14 @@ Special keywords: "%SSL3_RECORD_VERSION" force SSL3.0 record version in the first client hello. This is to avoid buggy servers from terminating connection. .IP -"%UNSAFE_RENEGOTIATION" will enable unsafe renegotiation (default) +"%UNSAFE_RENEGOTIATION" Permits (re-)handshakes even unsafe ones. .IP -"%SAFE_RENEGOTIATION" will enable safe renegotiation. +"%PARTIAL_RENEGOTIATION" Prevents renegotiation with clients and servers not +supporting the safe renegotiation extension. (default) +.IP +"%SAFE_RENEGOTIATION" will enable safe renegotiation. This is the most +secure and recommended option for clients. However this will prevent from +connecting to legacy servers. .IP To avoid collisions in order to specify a compression algorithm in this string you have to prefix it with "COMP-", protocol versions diff --git a/doc/manpages/gnutls-serv.1 b/doc/manpages/gnutls-serv.1 index a70b8d53de..0edb53e344 100644 --- a/doc/manpages/gnutls-serv.1 +++ b/doc/manpages/gnutls-serv.1 @@ -75,12 +75,14 @@ Special keywords: .IP "%COMPAT" will enable compatibility features for a server. .IP -"%UNSAFE_RENEGOTIATION" will enable unsafe renegotiation (default). +"%UNSAFE_RENEGOTIATION" Permits (re-)handshakes even unsafe ones. .IP -"%SAFE_RENEGOTIATION" will enable safe renegotiation. +"%PARTIAL_RENEGOTIATION" Prevents renegotiation with clients and servers not +supporting the safe renegotiation extension. (default) .IP -"%INITIAL_SAFE_RENEGOTIATION" will force initial safe negotiation even if -renegotiation wasn't requested. +"%SAFE_RENEGOTIATION" will enable safe renegotiation. This is the most +secure and recommended option for clients. However this will prevent from +connecting to legacy servers. .IP To avoid collisions in order to specify a compression algorithm in this string you have to prefix it with "COMP-", protocol versions diff --git a/lib/ext_safe_renegotiation.c b/lib/ext_safe_renegotiation.c index 1ee88ef20b..14392b34ab 100644 --- a/lib/ext_safe_renegotiation.c +++ b/lib/ext_safe_renegotiation.c @@ -37,7 +37,7 @@ _gnutls_safe_renegotiation_recv_params (gnutls_session_t session, DECR_LEN (data_size, len + 1 /* count the first byte and payload */ ); - if (session->internals.priorities.disable_safe_renegotiation != 0) + if (session->internals.priorities.sr == SR_DISABLED) { gnutls_assert (); return 0; @@ -85,7 +85,7 @@ _gnutls_safe_renegotiation_send_params (gnutls_session_t session, ssize_t data_size = _data_size; tls_ext_st *ext = &session->security_parameters.extensions; - if (session->internals.priorities.disable_safe_renegotiation != 0) + if (session->internals.priorities.sr == SR_DISABLED) { gnutls_assert (); return 0; diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index cd2378b985..a597254107 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -864,7 +864,7 @@ _gnutls_server_select_suite (gnutls_session_t session, opaque * data, /* First, check for safe renegotiation SCSV. */ - if (session->internals.priorities.disable_safe_renegotiation == 0) + if (session->internals.priorities.sr != SR_DISABLED) { int offset; @@ -2337,7 +2337,7 @@ _gnutls_recv_hello (gnutls_session_t session, opaque * data, int datalen) } } - if (session->internals.priorities.disable_safe_renegotiation != 0) + if (session->internals.priorities.sr == SR_DISABLED) { gnutls_assert (); return ret; @@ -2386,7 +2386,7 @@ _gnutls_recv_hello (gnutls_session_t session, opaque * data, int datalen) _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n", session); } - else /* safe renegotiation not received... */ + else /* safe renegotiation not received... */ { if (session->internals.connection_using_safe_renegotiation) { @@ -2398,10 +2398,10 @@ _gnutls_recv_hello (gnutls_session_t session, opaque * data, int datalen) } /* Clients can't tell if it's an initial negotiation */ - if (session->internals.initial_negotiation_completed || - session->security_parameters.entity == GNUTLS_CLIENT) + if (session->internals.initial_negotiation_completed) { - if (session->internals.priorities.unsafe_renegotiation != 0) + + if (session->internals.priorities.sr < SR_PARTIAL) { _gnutls_handshake_log ("HSK[%p]: Allowing unsafe (re)negotiation\n", session); @@ -2411,16 +2411,12 @@ _gnutls_recv_hello (gnutls_session_t session, opaque * data, int datalen) gnutls_assert (); _gnutls_handshake_log ("HSK[%p]: Denying unsafe (re)negotiation\n", session); - if (session->security_parameters.entity == GNUTLS_SERVER) - /* send no renegotiation alert */ - return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED; - else - return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED; } } else { - if (session->internals.priorities.initial_safe_renegotiation == 0) + if (session->internals.priorities.sr < SR_SAFE) { _gnutls_handshake_log ("HSK[%p]: Allowing unsafe initial negotiation\n", session); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 3cea93ac9e..3d23f94b04 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -451,6 +451,13 @@ typedef struct unsigned int algorithms; } priority_st; +typedef enum { + SR_DISABLED, + SR_UNSAFE, + SR_PARTIAL, + SR_SAFE, +} safe_renegotiation_t; + /* For the external api */ struct gnutls_priority_st { @@ -464,10 +471,7 @@ struct gnutls_priority_st /* to disable record padding */ int no_padding:1; - int unsafe_renegotiation:1; - int initial_safe_renegotiation:1; - int disable_safe_renegotiation:1; - int safe_renegotiation_set:1; /* whether the priority string set any renegotiation parameters */ + safe_renegotiation_t sr; int ssl3_record_version; int additional_verify_flags; }; diff --git a/lib/gnutls_priority.c b/lib/gnutls_priority.c index 659f93304e..319f0972f8 100644 --- a/lib/gnutls_priority.c +++ b/lib/gnutls_priority.c @@ -448,21 +448,6 @@ gnutls_priority_set (gnutls_session_t session, gnutls_priority_t priority) memcpy (&session->internals.priorities, priority, sizeof (struct gnutls_priority_st)); - /* Hack. Because we want to differentiate the behavior of server - * and client with regards to safe renegotiation. If a server didn't - * have either SAFE_RENEGOTIATION or UNSAFE_RENEGOTIATION set the - * safe renegotiation will be the default. This (as well as the - * safe_renegotiation_set flag) has to be removed once safe - * renegotiation is default in both server and client side. - */ - if (session->security_parameters.entity == GNUTLS_SERVER) - { - if (session->internals.priorities.safe_renegotiation_set == 0) - { - session->internals.priorities.unsafe_renegotiation = 0; - } - } - /* set the current version to the first in the chain. * This will be overridden later. */ @@ -537,20 +522,20 @@ gnutls_priority_set (gnutls_session_t session, gnutls_priority_t priority) * * "%COMPAT" will enable compatibility features for a server. * + * "%DISABLE_SAFE_RENEGOTIATION" will disable safe renegotiation completely. Do not use + * unless you know what you are doing. Testing purposes only. + * * "%UNSAFE_RENEGOTIATION" will allow unsafe renegotiation (this is now * the default for clients, but will change once more servers support the safe renegotiation * TLS fix). * - * "%SAFE_RENEGOTIATION" will allow safe renegotiation only (this is the - * default for servers - that will reject clients trying to perform an - * unsafe renegotiation). - * - * "%INITIAL_SAFE_RENEGOTIATION" will force initial safe negotiation even if - * renegotiation wasn't requested. Only valid for server side and implies - * "%SAFE_RENEGOTIATION". + * "%PARTIAL_SAFE_RENEGOTIATION" In server side it will enable safe renegotiation + * and will protect all clients from known attacks, but will not prevent insecure clients + * from connecting. In client side it will disallow from renegotiating with an insecure server + * but will not prevent connecting to one (this leaves the client vulnerable to attacks). * - * "%DISABLE_SAFE_RENEGOTIATION" will disable safe renegotiation completely. Do not use - * unless you know what you are doing. Testing purposes only. + * "%SAFE_RENEGOTIATION" will enforce safe renegotiation. Clients and Servers will refuse + * to talk to an insecure peer. * * "%SSL3_RECORD_VERSION" will use SSL3.0 record version in client hello. * @@ -597,7 +582,7 @@ gnutls_priority_init (gnutls_priority_t * priority_cache, /* for now unsafe renegotiation is default on everyone. To be removed * when we make it the default. */ - (*priority_cache)->unsafe_renegotiation = 1; + (*priority_cache)->sr = SR_PARTIAL; if (priorities == NULL) priorities = "NORMAL"; @@ -749,26 +734,21 @@ gnutls_priority_init (gnutls_priority_t * priority_cache, else if (strcasecmp (&broken_list[i][1], "UNSAFE_RENEGOTIATION") == 0) { - (*priority_cache)->unsafe_renegotiation = 1; - (*priority_cache)->safe_renegotiation_set = 1; + (*priority_cache)->sr = SR_UNSAFE; } else if (strcasecmp (&broken_list[i][1], "SAFE_RENEGOTIATION") == 0) { - (*priority_cache)->unsafe_renegotiation = 0; - (*priority_cache)->safe_renegotiation_set = 1; + (*priority_cache)->sr = SR_SAFE; } else if (strcasecmp (&broken_list[i][1], - "INITIAL_SAFE_RENEGOTIATION") == 0) + "PARTIAL_RENEGOTIATION") == 0) { - (*priority_cache)->unsafe_renegotiation = 0; - (*priority_cache)->initial_safe_renegotiation = 1; - (*priority_cache)->safe_renegotiation_set = 1; + (*priority_cache)->sr = SR_PARTIAL; } else if (strcasecmp (&broken_list[i][1], "DISABLE_SAFE_RENEGOTIATION") == 0) { - (*priority_cache)->disable_safe_renegotiation = 1; - (*priority_cache)->safe_renegotiation_set = 1; + (*priority_cache)->sr = SR_DISABLED; } else goto error; diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index edaad9abd8..0420edf2e9 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -353,7 +353,7 @@ gnutls_init (gnutls_session_t * session, gnutls_connection_end_t con_end) /* emulate old gnutls behavior for old applications that do not use the priority_* * functions. */ - (*session)->internals.priorities.unsafe_renegotiation = 1; + (*session)->internals.priorities.sr = SR_PARTIAL; return 0; } diff --git a/tests/safe-renegotiation/srn1.c b/tests/safe-renegotiation/srn1.c index ff05790bc5..8cc0d5c213 100644 --- a/tests/safe-renegotiation/srn1.c +++ b/tests/safe-renegotiation/srn1.c @@ -184,7 +184,7 @@ main (int argc, char *argv[]) GNUTLS_X509_FMT_PEM); gnutls_init (&server, GNUTLS_SERVER); gnutls_credentials_set (server, GNUTLS_CRD_CERTIFICATE, serverx509cred); - gnutls_priority_set_direct (server, "NORMAL:%INITIAL_SAFE_RENEGOTIATION", + gnutls_priority_set_direct (server, "NORMAL:%SAFE_RENEGOTIATION", NULL); gnutls_transport_set_push_function (server, server_push); gnutls_transport_set_pull_function (server, server_pull); diff --git a/tests/safe-renegotiation/srn5.c b/tests/safe-renegotiation/srn5.c index dcaf1cae13..477ebb75a0 100644 --- a/tests/safe-renegotiation/srn5.c +++ b/tests/safe-renegotiation/srn5.c @@ -296,12 +296,12 @@ main (int argc, char *argv[]) } while ( /* Not done: */ - !(cret == GNUTLS_E_AGAIN - && sret == GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED) + !(sret == GNUTLS_E_AGAIN + && cret == GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED) /* No error: */ && (cret == GNUTLS_E_AGAIN || sret == GNUTLS_E_AGAIN)); - if (cret != GNUTLS_E_AGAIN && sret != GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED) + if (sret != GNUTLS_E_AGAIN && cret != GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED) exit_code = 1; if (gnutls_safe_renegotiation_status (client) || diff --git a/tests/safe-renegotiation/testsrn b/tests/safe-renegotiation/testsrn index c7c9b4ff80..8df797c6e6 100755 --- a/tests/safe-renegotiation/testsrn +++ b/tests/safe-renegotiation/testsrn @@ -33,7 +33,7 @@ fail() { echo "Checking Safe renegotiation" -$SERV -p $PORT --echo --priority NORMAL:+ANON-DH:%SAFE_RENEGOTIATION --dhparams $srcdir/params.dh >/dev/null 2>&1 & +$SERV -p $PORT --echo --priority NORMAL:+ANON-DH:%PARTIAL_RENEGOTIATION --dhparams $srcdir/params.dh >/dev/null 2>&1 & pid=$! # give the server a chance to initialize @@ -58,7 +58,7 @@ $CLI -p $PORT 127.0.0.1 --rehandshake --priority NORMAL:+ANON-DH:%DISABLE_SAFE_R kill $pid wait -$SERV -p $PORT --echo --priority NORMAL:+ANON-DH:%INITIAL_SAFE_RENEGOTIATION --dhparams $srcdir/params.dh >/dev/null 2>&1 & +$SERV -p $PORT --echo --priority NORMAL:+ANON-DH:%SAFE_RENEGOTIATION --dhparams $srcdir/params.dh >/dev/null 2>&1 & pid=$! # give the server a chance to initialize |