]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Splitted safe renegotiation capabilities to
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 1 Jun 2010 14:02:34 +0000 (16:02 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 1 Jun 2010 14:10:03 +0000 (16:10 +0200)
%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.

12 files changed:
doc/announce.txt
doc/gnutls.texi
doc/manpages/gnutls-cli.1
doc/manpages/gnutls-serv.1
lib/ext_safe_renegotiation.c
lib/gnutls_handshake.c
lib/gnutls_int.h
lib/gnutls_priority.c
lib/gnutls_state.c
tests/safe-renegotiation/srn1.c
tests/safe-renegotiation/srn5.c
tests/safe-renegotiation/testsrn

index 599f203ab03951107a6a0fd2406daa10a180ea44..0e6b61f9ba901a5b7dc495f8161468156949cbec 100644 (file)
@@ -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.
 
index daef0ff880cf34e270b185b08e43ba7595f799cc..7e4c3ca1a282577abf683e64867420d2893aaf40 100644 (file)
@@ -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
 
index 61a68926c089c9777e531d3b22db86a0baa60d4d..9d1208e5678038ea07452998155216a71dbb79f7 100644 (file)
@@ -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
index a70b8d53ded2c62ebe6999eba9fe72f9a41d45dd..0edb53e3443ebcd1a3b0808384320f31fd2acec4 100644 (file)
@@ -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
index 1ee88ef20b8cb8d7c9990512e3dd57f258384335..14392b34ab82ef46198c20c2cc14b5f5b2b20848 100644 (file)
@@ -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;
index cd2378b985cdb7dc98c668067d635fc255e170c4..a5972541075910f45c96c4d0a42a0f45209c139c 100644 (file)
@@ -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);
index 3cea93ac9e8c16af6f98bc8ba980f8738cab1e50..3d23f94b04815b3f3c8b87780c1b8690f36f6c36 100644 (file)
@@ -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;
 };
index 659f93304e3139f23d47f8d71964cc780d01dcaf..319f0972f8a0e54a42b4c92c7c5372ccb69c3d46 100644 (file)
@@ -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;
index edaad9abd88f1960bb477931e15b8f877faa6beb..0420edf2e9f3afe6ffa278c13447359f5c7d37a7 100644 (file)
@@ -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;
 }
index ff05790bc51906a663b36fe3500205bdd442f0f9..8cc0d5c213a3c604c2cf87ef2188606b1607398b 100644 (file)
@@ -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);
index dcaf1cae1381eac6e8e20b7691e41fadddca2f0d..477ebb75a04306b7cd08010bb5564ef785c47cbf 100644 (file)
@@ -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) ||
index c7c9b4ff80c4d54c27d41996c4a2cb49b5ffb02d..8df797c6e641426638bed43e21fa555892f8d28b 100755 (executable)
@@ -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