summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-01-12 20:17:07 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-01-12 20:17:07 +0100
commit5a92d28f74951356705d4e6698b9315980911f87 (patch)
tree611eaa003bee194aa0cdd1333d6ad5483c3c4625
parent1344b312402d3b831f2839f4a58190fd4fa380f0 (diff)
downloadgnutls-5a92d28f74951356705d4e6698b9315980911f87.tar.gz
When resuming no extensions were parsed thus the safe
renegotiation extension was ignored as well causing a false detection of unsafe session. Corrected by making a special class of extensions called RESUMED. Those are parsed even when resuming (normally we don't do it to prevent clients overwriting capabilities and credentials).
-rw-r--r--lib/gnutls_extensions.c2
-rw-r--r--lib/gnutls_handshake.c53
-rw-r--r--lib/includes/gnutls/gnutls.h.in3
-rw-r--r--tests/resume.c21
4 files changed, 71 insertions, 8 deletions
diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c
index 4e9db89e7c..2e8ad07f45 100644
--- a/lib/gnutls_extensions.c
+++ b/lib/gnutls_extensions.c
@@ -324,7 +324,7 @@ _gnutls_ext_init (void)
ret = gnutls_ext_register (GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
"SAFE_RENEGOTIATION",
- GNUTLS_EXT_TLS,
+ GNUTLS_EXT_RESUMED,
_gnutls_safe_renegotiation_recv_params,
_gnutls_safe_renegotiation_send_params);
if (ret != GNUTLS_E_SUCCESS)
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 9830278762..3620a2991a 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -450,6 +450,33 @@ _gnutls_read_client_hello (gnutls_session_t session, opaque * data,
if (ret == 0)
{ /* resumed! */
+ /* Parse only the safe renegotiation extension
+ * We don't want to parse any other extensions since
+ * we don't want new extension values to overwrite the
+ * resumed ones.
+ */
+
+ /* move forward to extensions */
+ DECR_LEN (len, 2);
+ suite_size = _gnutls_read_uint16 (&data[pos]);
+ pos += 2;
+
+ DECR_LEN (len, suite_size);
+ pos += suite_size;
+
+ DECR_LEN (len, 1);
+ comp_size = data[pos++]; /* z is the number of compression methods */
+ DECR_LEN (len, comp_size);
+ pos += comp_size;
+
+ ret = _gnutls_parse_extensions (session, GNUTLS_EXT_RESUMED,
+ &data[pos], len);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
resume_copy_required_values (session);
session->internals.resumed = RESUME_TRUE;
@@ -504,9 +531,16 @@ _gnutls_read_client_hello (gnutls_session_t session, opaque * data,
return ret;
}
+ ret = _gnutls_parse_extensions (session, GNUTLS_EXT_RESUMED,
+ &data[pos], len);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
ret = _gnutls_parse_extensions (session, GNUTLS_EXT_TLS,
&data[pos], len);
- /* len is the rest of the parsed length */
if (ret < 0)
{
gnutls_assert ();
@@ -1718,9 +1752,21 @@ _gnutls_read_server_hello (gnutls_session_t session,
*/
if (_gnutls_client_check_if_resuming
(session, &data[pos], session_id_len) == 0)
- return 0;
- pos += session_id_len;
+ {
+ pos += session_id_len + 2 + 1;
+ DECR_LEN (len, 2+1);
+
+ ret = _gnutls_parse_extensions (session, GNUTLS_EXT_RESUMED,
+ &data[pos], len);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+ return 0;
+ }
+ pos += session_id_len;
/* Check if the given cipher suite is supported and copy
* it to the session.
@@ -1752,7 +1798,6 @@ _gnutls_read_server_hello (gnutls_session_t session,
*/
ret = _gnutls_parse_extensions (session, GNUTLS_EXT_ANY,
&data[pos], len);
- /* len is the rest of the parsed length */
if (ret < 0)
{
gnutls_assert ();
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index cbcf493332..ea691e6667 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -511,7 +511,8 @@ extern "C" {
{
GNUTLS_EXT_ANY,
GNUTLS_EXT_APPLICATION,
- GNUTLS_EXT_TLS
+ GNUTLS_EXT_TLS,
+ GNUTLS_EXT_RESUMED, /* parse even if resuming */
} gnutls_ext_parse_type_t;
int gnutls_ext_register (int type,
diff --git a/tests/resume.c b/tests/resume.c
index c52c1d6bed..80a4c7d82e 100644
--- a/tests/resume.c
+++ b/tests/resume.c
@@ -58,6 +58,8 @@ struct params_res
int expect_resume;
};
+pid_t child;
+
struct params_res resume_tests[] = {
{"try to resume from db", 50, 0, 0, 1},
#ifdef ENABLE_SESSION_TICKET
@@ -75,6 +77,12 @@ struct params_res resume_tests[] = {
#define MSG "Hello TLS"
static void
+tls_log_func (int level, const char *str)
+{
+ fprintf (stderr, "%s |<%d>| %s", child ? "server" : "client", level, str);
+}
+
+static void
client (struct params_res *params)
{
int ret, sd, ii;
@@ -89,6 +97,11 @@ client (struct params_res *params)
int t;
gnutls_datum_t session_data;
+ if (debug)
+ {
+ gnutls_global_set_log_function (tls_log_func);
+ gnutls_global_set_log_level (4);
+ }
gnutls_global_init ();
gnutls_anon_allocate_client_credentials (&anoncred);
@@ -336,8 +349,13 @@ server (struct params_res *params)
/* this must be called once in the program, it is mostly for the server.
*/
- gnutls_global_init ();
+ if (debug)
+ {
+ gnutls_global_set_log_function (tls_log_func);
+ gnutls_global_set_log_level (4);
+ }
+ gnutls_global_init ();
gnutls_anon_allocate_server_credentials (&anoncred);
success ("Launched, generating DH parameters...\n");
@@ -430,7 +448,6 @@ server (struct params_res *params)
void
doit (void)
{
- pid_t child;
int i;
for (i = 0; resume_tests[i].desc; i++)