summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-02-11 16:10:31 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-02-16 09:59:59 +0100
commit87de44f70d9d848b91f4a6b86fb12b7b8a8633ac (patch)
treedafd59b16d07650c15ca1dad4bd60623cd06b38a
parentb0f739c644b4182742bbb5f1485897aabeda6169 (diff)
downloadgnutls-87de44f70d9d848b91f4a6b86fb12b7b8a8633ac.tar.gz
Ensure that session resumption does not occur when ext master secret status changes
That is we make sure the server doesn't resume when: 1. Original session had extended master secret but not advertised in resumed 2. Original session did not have extended master secret but is advertised in resumed Relates #69
-rw-r--r--lib/db.c15
-rw-r--r--lib/db.h2
-rw-r--r--lib/ext/session_ticket.c9
-rw-r--r--lib/handshake.c99
4 files changed, 61 insertions, 64 deletions
diff --git a/lib/db.c b/lib/db.c
index 2554251f28..1955cd096a 100644
--- a/lib/db.c
+++ b/lib/db.c
@@ -251,6 +251,15 @@ int _gnutls_server_register_current_session(gnutls_session_t session)
return ret;
}
+int _gnutls_check_resumed_params(gnutls_session_t session)
+{
+ if (session->internals.resumed_security_parameters.ext_master_secret !=
+ session->security_parameters.ext_master_secret)
+ return gnutls_assert_val(GNUTLS_E_INVALID_SESSION);
+
+ return 0;
+}
+
int
_gnutls_server_restore_session(gnutls_session_t session,
uint8_t * session_id, int session_id_size)
@@ -301,9 +310,9 @@ _gnutls_server_restore_session(gnutls_session_t session,
return ret;
}
- /* Force the state of ext_master_secret based on the resumed parameters */
- if (session->internals.resumed_security_parameters.ext_master_secret != 0)
- session->security_parameters.ext_master_secret = 1;
+ ret = _gnutls_check_resumed_params(session);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
return 0;
}
diff --git a/lib/db.h b/lib/db.h
index 9c168fd6ea..153c094529 100644
--- a/lib/db.h
+++ b/lib/db.h
@@ -25,4 +25,6 @@ int _gnutls_server_restore_session(gnutls_session_t session,
uint8_t * session_id,
int session_id_size);
+int _gnutls_check_resumed_params(gnutls_session_t session);
+
#define PACKED_SESSION_MAGIC ((0xfadebadd)+(GNUTLS_VERSION_NUMBER))
diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c
index 58f1bbacab..edbbf81564 100644
--- a/lib/ext/session_ticket.c
+++ b/lib/ext/session_ticket.c
@@ -34,6 +34,7 @@
#include <extensions.h>
#include <constate.h>
#include <dtls.h>
+#include "db.h"
#ifdef ENABLE_SESSION_TICKETS
@@ -57,7 +58,7 @@ static void session_ticket_deinit_data(extension_priv_data_t priv);
const extension_entry_st ext_mod_session_ticket = {
.name = "SESSION TICKET",
.type = GNUTLS_EXTENSION_SESSION_TICKET,
- .parse_type = GNUTLS_EXT_MANDATORY,
+ .parse_type = GNUTLS_EXT_TLS,
.recv_func = session_ticket_recv_params,
.send_func = session_ticket_send_params,
@@ -144,6 +145,12 @@ decrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv,
goto cleanup;
}
+ ret = _gnutls_check_resumed_params(session);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
session->internals.resumed = RESUME_TRUE;
ret = 0;
diff --git a/lib/handshake.c b/lib/handshake.c
index 3d7a153493..8fa0b24a11 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2000-2014 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2015-2016 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -475,15 +476,14 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
{
uint8_t session_id_len;
int pos = 0, ret;
- uint16_t suite_size, comp_size;
+ uint16_t suite_size, comp_size, ext_size;
gnutls_protocol_t adv_version;
int neg_version, sret = 0;
int len = datalen;
uint8_t major, minor;
- uint8_t *suite_ptr, *comp_ptr, *session_id;
+ uint8_t *suite_ptr, *comp_ptr, *session_id, *ext_ptr;
DECR_LEN(len, 2);
-
_gnutls_handshake_log("HSK[%p]: Client's version: %d.%d\n",
session, data[pos], data[pos + 1]);
@@ -541,6 +541,38 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
pos += cookie_size;
}
+ /* move forward to extensions and store other vals */
+ DECR_LEN(len, 2);
+ suite_size = _gnutls_read_uint16(&data[pos]);
+ pos += 2;
+
+ suite_ptr = &data[pos];
+ DECR_LEN(len, suite_size);
+ pos += suite_size;
+
+ DECR_LEN(len, 1);
+ comp_size = data[pos++]; /* the number of compression methods */
+
+ comp_ptr = &data[pos];
+ DECR_LEN(len, comp_size);
+ pos += comp_size;
+
+ ext_ptr = &data[pos];
+ ext_size = len;
+
+ /* Parse only the mandatory to read extensions for resumption.
+ * We don't want to parse any other extensions since
+ * we don't want new extension values to override the
+ * resumed ones.
+ */
+ ret =
+ _gnutls_parse_extensions(session, GNUTLS_EXT_MANDATORY,
+ ext_ptr, ext_size);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
ret =
_gnutls_server_restore_session(session, session_id,
session_id_len);
@@ -549,33 +581,6 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
session->internals.resumption_requested = 1;
if (ret == 0) { /* resumed using default TLS resumption! */
- /* 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_MANDATORY,
- &data[pos], len);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
ret = resume_copy_required_values(session);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -592,32 +597,13 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
session->internals.resumed = RESUME_FALSE;
}
- /* Remember ciphersuites for later
- */
- DECR_LEN(len, 2);
- suite_size = _gnutls_read_uint16(&data[pos]);
- pos += 2;
-
- DECR_LEN(len, suite_size);
- suite_ptr = &data[pos];
- pos += suite_size;
-
- /* Point to the compression methods
- */
- DECR_LEN(len, 1);
- comp_size = data[pos++]; /* z is the number of compression methods */
-
- DECR_LEN(len, comp_size);
- comp_ptr = &data[pos];
- pos += comp_size;
-
/* Parse the extensions (if any)
*
* Unconditionally try to parse extensions; safe renegotiation uses them in
* sslv3 and higher, even though sslv3 doesn't officially support them.
*/
ret = _gnutls_parse_extensions(session, GNUTLS_EXT_APPLICATION,
- &data[pos], len);
+ ext_ptr, ext_size);
/* len is the rest of the parsed length */
if (ret < 0) {
gnutls_assert();
@@ -631,16 +617,9 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
return sret;
}
- ret = _gnutls_parse_extensions(session, GNUTLS_EXT_MANDATORY,
- &data[pos], len);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
+ /* Session tickets are parsed in this point */
ret =
- _gnutls_parse_extensions(session, GNUTLS_EXT_TLS, &data[pos],
- len);
+ _gnutls_parse_extensions(session, GNUTLS_EXT_TLS, ext_ptr, ext_size);
if (ret < 0) {
gnutls_assert();
return ret;