summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2018-05-07 09:52:32 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2018-05-17 13:54:03 +0200
commitf41df13ec8b77414ff8e682d8234c089bd24e7e9 (patch)
treebf9a12d81c1469c6aefa896393bd95f95cdea7f4
parent9c0b15a08a48b72fe63ccd5b046ff9199212d10b (diff)
downloadgnutls-f41df13ec8b77414ff8e682d8234c089bd24e7e9.tar.gz
handshake: do not send TLS extensions under DTLS and vice versatmp-prohibit-tls-dtls-mix
That is, introduce the notion of TLS-only and DTLS-only extensions, providing a framework to prevent sending extensions which are registered for example for TLS 1.3, under DTLS and vice versa. Resolves #440 Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/ext/alpn.c5
-rw-r--r--lib/ext/cookie.c4
-rw-r--r--lib/ext/dumbfw.c3
-rw-r--r--lib/ext/ecc.c8
-rw-r--r--lib/ext/etm.c4
-rw-r--r--lib/ext/ext_master_secret.c4
-rw-r--r--lib/ext/heartbeat.c4
-rw-r--r--lib/ext/key_share.c4
-rw-r--r--lib/ext/max_record.c4
-rw-r--r--lib/ext/post_handshake.c3
-rw-r--r--lib/ext/pre_shared_key.c2
-rw-r--r--lib/ext/psk_ke_modes.c2
-rw-r--r--lib/ext/safe_renegotiation.c4
-rw-r--r--lib/ext/server_name.c4
-rw-r--r--lib/ext/session_ticket.c4
-rw-r--r--lib/ext/signature.c3
-rw-r--r--lib/ext/srp.c3
-rw-r--r--lib/ext/srtp.c4
-rw-r--r--lib/ext/status_request.c3
-rw-r--r--lib/ext/supported_versions.c5
-rw-r--r--lib/hello_ext.c73
-rw-r--r--lib/hello_ext.h12
-rw-r--r--lib/includes/gnutls/gnutls.h.in6
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/tls-ext-not-in-dtls.c288
25 files changed, 401 insertions, 57 deletions
diff --git a/lib/ext/alpn.c b/lib/ext/alpn.c
index bac3ccb68f..24e7153a59 100644
--- a/lib/ext/alpn.c
+++ b/lib/ext/alpn.c
@@ -40,8 +40,9 @@ const hello_ext_entry_st ext_mod_alpn = {
.gid = GNUTLS_EXTENSION_ALPN,
/* this extension must be parsed even on resumption */
.parse_type = GNUTLS_EXT_MANDATORY,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_EE|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS |
+ GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_EE |
+ GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.recv_func = _gnutls_alpn_recv_params,
.send_func = _gnutls_alpn_send_params,
.deinit_func = _gnutls_alpn_deinit_data,
diff --git a/lib/ext/cookie.c b/lib/ext/cookie.c
index eff4f1890d..1da7b0382f 100644
--- a/lib/ext/cookie.c
+++ b/lib/ext/cookie.c
@@ -39,9 +39,9 @@ const hello_ext_entry_st ext_mod_cookie = {
.name = "Cookie",
.tls_id = 44,
.gid = GNUTLS_EXTENSION_COOKIE,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_HRR|GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_HRR | GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST,
.parse_type = GNUTLS_EXT_MANDATORY, /* force parsing prior to EXT_TLS extensions */
-
.recv_func = cookie_recv_params,
.send_func = cookie_send_params,
.pack_func = NULL,
diff --git a/lib/ext/dumbfw.c b/lib/ext/dumbfw.c
index 4e56192337..adb3a18381 100644
--- a/lib/ext/dumbfw.c
+++ b/lib/ext/dumbfw.c
@@ -41,8 +41,7 @@ const hello_ext_entry_st ext_mod_dumbfw = {
.tls_id = 21,
.gid = GNUTLS_EXTENSION_DUMBFW,
.parse_type = GNUTLS_EXT_APPLICATION,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO,
.recv_func = NULL,
.send_func = _gnutls_dumbfw_send_params,
.pack_func = NULL,
diff --git a/lib/ext/ecc.c b/lib/ext/ecc.c
index 50cd862211..164b6150db 100644
--- a/lib/ext/ecc.c
+++ b/lib/ext/ecc.c
@@ -54,8 +54,8 @@ const hello_ext_entry_st ext_mod_supported_ecc = {
.tls_id = 10,
.gid = GNUTLS_EXTENSION_SUPPORTED_ECC,
.parse_type = GNUTLS_EXT_TLS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_EE|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.recv_func = _gnutls_supported_ecc_recv_params,
.send_func = _gnutls_supported_ecc_send_params,
.pack_func = NULL,
@@ -69,8 +69,8 @@ const hello_ext_entry_st ext_mod_supported_ecc_pf = {
.tls_id = 11,
.gid = GNUTLS_EXTENSION_SUPPORTED_ECC_PF,
.parse_type = GNUTLS_EXT_TLS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS |
+ GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.recv_func = _gnutls_supported_ecc_pf_recv_params,
.send_func = _gnutls_supported_ecc_pf_send_params,
.pack_func = NULL,
diff --git a/lib/ext/etm.c b/lib/ext/etm.c
index ca4638b7e9..ad542771d1 100644
--- a/lib/ext/etm.c
+++ b/lib/ext/etm.c
@@ -40,8 +40,8 @@ const hello_ext_entry_st ext_mod_etm = {
.tls_id = 22,
.gid = GNUTLS_EXTENSION_ETM,
.parse_type = GNUTLS_EXT_MANDATORY,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.recv_func = _gnutls_ext_etm_recv_params,
.send_func = _gnutls_ext_etm_send_params,
.pack_func = NULL,
diff --git a/lib/ext/ext_master_secret.c b/lib/ext/ext_master_secret.c
index 16feac4ea0..c9ee5cfe8c 100644
--- a/lib/ext/ext_master_secret.c
+++ b/lib/ext/ext_master_secret.c
@@ -40,8 +40,8 @@ const hello_ext_entry_st ext_mod_ext_master_secret = {
.tls_id = 23,
.gid = GNUTLS_EXTENSION_EXT_MASTER_SECRET,
.parse_type = GNUTLS_EXT_MANDATORY,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS|GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.recv_func = _gnutls_ext_master_secret_recv_params,
.send_func = _gnutls_ext_master_secret_send_params,
.pack_func = NULL,
diff --git a/lib/ext/heartbeat.c b/lib/ext/heartbeat.c
index 0772ec5e1f..13b7cf2e84 100644
--- a/lib/ext/heartbeat.c
+++ b/lib/ext/heartbeat.c
@@ -527,8 +527,8 @@ const hello_ext_entry_st ext_mod_heartbeat = {
.tls_id = 15,
.gid = GNUTLS_EXTENSION_HEARTBEAT,
.parse_type = GNUTLS_EXT_TLS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_EE|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.recv_func = _gnutls_heartbeat_recv_params,
.send_func = _gnutls_heartbeat_send_params,
.pack_func = _gnutls_heartbeat_pack,
diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c
index c46f0c733e..5802e47679 100644
--- a/lib/ext/key_share.c
+++ b/lib/ext/key_share.c
@@ -48,8 +48,8 @@ const hello_ext_entry_st ext_mod_key_share = {
.tls_id = 51,
.gid = GNUTLS_EXTENSION_KEY_SHARE,
.parse_type = _GNUTLS_EXT_TLS_POST_CS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO|GNUTLS_EXT_FLAG_HRR,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO |
+ GNUTLS_EXT_FLAG_HRR,
.recv_func = key_share_recv_params,
.send_func = key_share_send_params,
.pack_func = NULL,
diff --git a/lib/ext/max_record.c b/lib/ext/max_record.c
index 9fbd94e72d..8314d16193 100644
--- a/lib/ext/max_record.c
+++ b/lib/ext/max_record.c
@@ -52,8 +52,8 @@ const hello_ext_entry_st ext_mod_max_record_size = {
.tls_id = 1,
.gid = GNUTLS_EXTENSION_MAX_RECORD_SIZE,
.parse_type = GNUTLS_EXT_TLS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_EE|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.recv_func = _gnutls_max_record_recv_params,
.send_func = _gnutls_max_record_send_params,
.pack_func = _gnutls_max_record_pack,
diff --git a/lib/ext/post_handshake.c b/lib/ext/post_handshake.c
index 97b94afef8..ff9df4b9a9 100644
--- a/lib/ext/post_handshake.c
+++ b/lib/ext/post_handshake.c
@@ -41,8 +41,7 @@ const hello_ext_entry_st ext_mod_post_handshake = {
.tls_id = 49,
.gid = GNUTLS_EXTENSION_POST_HANDSHAKE,
.parse_type = GNUTLS_EXT_TLS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO,
.recv_func = _gnutls_post_handshake_recv_params,
.send_func = _gnutls_post_handshake_send_params,
.pack_func = NULL,
diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c
index 21dd6069c7..0d3468c40d 100644
--- a/lib/ext/pre_shared_key.c
+++ b/lib/ext/pre_shared_key.c
@@ -498,7 +498,7 @@ const hello_ext_entry_st ext_pre_shared_key = {
.tls_id = 41,
.gid = GNUTLS_EXTENSION_PRE_SHARED_KEY,
.parse_type = GNUTLS_EXT_TLS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO,
.send_func = _gnutls_psk_send_params,
.recv_func = _gnutls_psk_recv_params
};
diff --git a/lib/ext/psk_ke_modes.c b/lib/ext/psk_ke_modes.c
index 4427f552c9..af136fd3ca 100644
--- a/lib/ext/psk_ke_modes.c
+++ b/lib/ext/psk_ke_modes.c
@@ -184,7 +184,7 @@ const hello_ext_entry_st ext_psk_ke_modes = {
.tls_id = 45,
.gid = GNUTLS_EXTENSION_PSK_KE_MODES,
.parse_type = GNUTLS_EXT_TLS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO,
.send_func = psk_ke_modes_send_params,
.recv_func = psk_ke_modes_recv_params
};
diff --git a/lib/ext/safe_renegotiation.c b/lib/ext/safe_renegotiation.c
index 7fb80b4dc4..26d25165bc 100644
--- a/lib/ext/safe_renegotiation.c
+++ b/lib/ext/safe_renegotiation.c
@@ -35,9 +35,9 @@ const hello_ext_entry_st ext_mod_sr = {
.name = "Safe Renegotiation",
.tls_id = 65281,
.gid = GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.parse_type = GNUTLS_EXT_MANDATORY,
-
.recv_func = _gnutls_sr_recv_params,
.send_func = _gnutls_sr_send_params,
.pack_func = NULL,
diff --git a/lib/ext/server_name.c b/lib/ext/server_name.c
index e640e57a52..1f9f3814f1 100644
--- a/lib/ext/server_name.c
+++ b/lib/ext/server_name.c
@@ -44,9 +44,9 @@ const hello_ext_entry_st ext_mod_server_name = {
.name = "Server Name Indication",
.tls_id = 0,
.gid = GNUTLS_EXTENSION_SERVER_NAME,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_EE|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.parse_type = GNUTLS_EXT_MANDATORY,
-
.recv_func = _gnutls_server_name_recv_params,
.send_func = _gnutls_server_name_send_params,
.pack_func = _gnutls_hello_ext_default_pack,
diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c
index 7e0a0b2f8d..69dc138a42 100644
--- a/lib/ext/session_ticket.c
+++ b/lib/ext/session_ticket.c
@@ -63,9 +63,9 @@ const hello_ext_entry_st ext_mod_session_ticket = {
.name = "Session Ticket",
.tls_id = 35,
.gid = GNUTLS_EXTENSION_SESSION_TICKET,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.parse_type = GNUTLS_EXT_TLS,
-
.recv_func = session_ticket_recv_params,
.send_func = session_ticket_send_params,
.pack_func = session_ticket_pack,
diff --git a/lib/ext/signature.c b/lib/ext/signature.c
index 7bf2761fdf..a0e6e20b89 100644
--- a/lib/ext/signature.c
+++ b/lib/ext/signature.c
@@ -53,9 +53,8 @@ const hello_ext_entry_st ext_mod_sig = {
.name = "Signature Algorithms",
.tls_id = 13,
.gid = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO,
.parse_type = GNUTLS_EXT_TLS,
-
.recv_func = _gnutls_signature_algorithm_recv_params,
.send_func = _gnutls_signature_algorithm_send_params,
.pack_func = signature_algorithms_pack,
diff --git a/lib/ext/srp.c b/lib/ext/srp.c
index 2c1ab90d1a..73c7936655 100644
--- a/lib/ext/srp.c
+++ b/lib/ext/srp.c
@@ -47,8 +47,7 @@ const hello_ext_entry_st ext_mod_srp = {
.tls_id = 12,
.gid = GNUTLS_EXTENSION_SRP,
.parse_type = GNUTLS_EXT_TLS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO,
-
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO,
.recv_func = _gnutls_srp_recv_params,
.send_func = _gnutls_srp_send_params,
.pack_func = _gnutls_srp_pack,
diff --git a/lib/ext/srtp.c b/lib/ext/srtp.c
index 811d5419b5..b55ca29753 100644
--- a/lib/ext/srtp.c
+++ b/lib/ext/srtp.c
@@ -43,9 +43,9 @@ const hello_ext_entry_st ext_mod_srtp = {
.name = "SRTP",
.tls_id = 14,
.gid = GNUTLS_EXTENSION_SRTP,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_EE|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.parse_type = GNUTLS_EXT_APPLICATION,
-
.recv_func = _gnutls_srtp_recv_params,
.send_func = _gnutls_srtp_send_params,
.pack_func = _gnutls_srtp_pack,
diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c
index 550b4307d3..f238a8fbcb 100644
--- a/lib/ext/status_request.c
+++ b/lib/ext/status_request.c
@@ -326,7 +326,8 @@ const hello_ext_entry_st ext_mod_status_request = {
.name = "OCSP Status Request",
.tls_id = STATUS_REQUEST_TLS_ID,
.gid = GNUTLS_EXTENSION_STATUS_REQUEST,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
+ GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
.parse_type = _GNUTLS_EXT_TLS_POST_CS,
.recv_func = _gnutls_status_request_recv_params,
.send_func = _gnutls_status_request_send_params,
diff --git a/lib/ext/supported_versions.c b/lib/ext/supported_versions.c
index e2857c5e84..f1a85022b6 100644
--- a/lib/ext/supported_versions.c
+++ b/lib/ext/supported_versions.c
@@ -41,10 +41,9 @@ const hello_ext_entry_st ext_mod_supported_versions = {
.name = "Supported Versions",
.tls_id = 43,
.gid = GNUTLS_EXTENSION_SUPPORTED_VERSIONS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO|
- GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO|GNUTLS_EXT_FLAG_HRR,
+ .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
+ GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | GNUTLS_EXT_FLAG_HRR|GNUTLS_EXT_FLAG_TLS,
.parse_type = GNUTLS_EXT_VERSION_NEG, /* force parsing prior to EXT_TLS extensions */
-
.recv_func = supported_versions_recv_params,
.send_func = supported_versions_send_params,
.pack_func = NULL,
diff --git a/lib/hello_ext.c b/lib/hello_ext.c
index 57583231a3..d61f846f51 100644
--- a/lib/hello_ext.c
+++ b/lib/hello_ext.c
@@ -208,12 +208,21 @@ int hello_ext_parse(void *_ctx, unsigned tls_id, const uint8_t *data, unsigned d
ext = tls_id_to_ext_entry(session, tls_id, ctx->parse_type);
if (ext == NULL || ext->recv_func == NULL) {
- if (ext) {
- _gnutls_hard_log
- ("EXT[%p]: Ignoring extension '%s/%d'\n", session,
- ext->name, (int)tls_id);
+ goto ignore;
+ }
+
+ /* we do not hard fail when extensions defined for TLS are used for
+ * DTLS and vice-versa. They may extend their role in the future. */
+ if (IS_DTLS(session)) {
+ if (!(ext->validity & GNUTLS_EXT_FLAG_DTLS)) {
+ gnutls_assert();
+ goto ignore;
+ }
+ } else {
+ if (!(ext->validity & GNUTLS_EXT_FLAG_TLS)) {
+ gnutls_assert();
+ goto ignore;
}
- return 0;
}
if (session->security_parameters.entity == GNUTLS_CLIENT) {
@@ -250,6 +259,14 @@ int hello_ext_parse(void *_ctx, unsigned tls_id, const uint8_t *data, unsigned d
}
return 0;
+
+ ignore:
+ if (ext) {
+ _gnutls_handshake_log
+ ("EXT[%p]: Ignoring extension '%s/%d'\n", session,
+ ext->name, (int)tls_id);
+ }
+ return 0;
}
int
@@ -261,6 +278,8 @@ _gnutls_parse_hello_extensions(gnutls_session_t session,
int ret;
hello_ext_ctx_st ctx;
+ msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
+
ctx.session = session;
ctx.msg = msg;
ctx.parse_type = parse_type;
@@ -290,11 +309,20 @@ int hello_ext_send(void *_ctx, gnutls_buffer_st *buf)
return 0;
}
+ if (IS_DTLS(session)) {
+ if (!(p->validity & GNUTLS_EXT_FLAG_DTLS)) {
+ gnutls_assert();
+ goto skip;
+ }
+ } else {
+ if (!(p->validity & GNUTLS_EXT_FLAG_TLS)) {
+ gnutls_assert();
+ goto skip;
+ }
+ }
+
if ((ctx->msg & p->validity) == 0) {
- _gnutls_hard_log("EXT[%p]: Not sending extension (%s/%d) for '%s'\n", session,
- p->name, (int)p->tls_id,
- ext_msg_validity_to_str(ctx->msg));
- return 0;
+ goto skip;
} else {
_gnutls_handshake_log("EXT[%p]: Preparing extension (%s/%d) for '%s'\n", session,
p->name, (int)p->tls_id,
@@ -335,6 +363,12 @@ int hello_ext_send(void *_ctx, gnutls_buffer_st *buf)
}
return ret;
+
+ skip:
+ _gnutls_handshake_log("EXT[%p]: Not sending extension (%s/%d) for '%s'\n", session,
+ p->name, (int)p->tls_id,
+ ext_msg_validity_to_str(ctx->msg));
+ return 0;
}
int
@@ -347,6 +381,8 @@ _gnutls_gen_hello_extensions(gnutls_session_t session,
size_t i;
hello_ext_ctx_st ctx;
+ msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
+
ctx.session = session;
ctx.msg = msg;
ctx.parse_type = parse_type;
@@ -752,7 +788,8 @@ gnutls_ext_register(const char *name, int id, gnutls_ext_parse_type_t parse_type
tmp_mod->deinit_func = deinit_func;
tmp_mod->pack_func = pack_func;
tmp_mod->unpack_func = unpack_func;
- tmp_mod->validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO|GNUTLS_EXT_FLAG_EE;
+ tmp_mod->validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
+ GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS;
assert(extfunc[gid] == NULL);
extfunc[gid] = tmp_mod;
@@ -760,9 +797,9 @@ gnutls_ext_register(const char *name, int id, gnutls_ext_parse_type_t parse_type
return 0;
}
-#define VALIDITY_MASK (GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO| \
- GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO| \
- GNUTLS_EXT_FLAG_EE|GNUTLS_EXT_FLAG_HRR)
+#define VALIDITY_MASK (GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO | \
+ GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | \
+ GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_HRR)
/**
* gnutls_session_ext_register:
@@ -854,7 +891,15 @@ gnutls_session_ext_register(gnutls_session_t session,
tmp_mod.validity = flags;
if ((tmp_mod.validity & VALIDITY_MASK) == 0) {
- tmp_mod.validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO|GNUTLS_EXT_FLAG_EE;
+ tmp_mod.validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
+ GNUTLS_EXT_FLAG_EE;
+ }
+
+ if ((tmp_mod.validity & (GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS)) == 0) {
+ if (IS_DTLS(session))
+ tmp_mod.validity |= GNUTLS_EXT_FLAG_DTLS;
+ else
+ tmp_mod.validity |= GNUTLS_EXT_FLAG_TLS;
}
exts = gnutls_realloc(session->internals.rexts, (session->internals.rexts_size+1)*sizeof(*exts));
diff --git a/lib/hello_ext.h b/lib/hello_ext.h
index f0fcf056c7..ac0a4613a7 100644
--- a/lib/hello_ext.h
+++ b/lib/hello_ext.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2015-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -52,10 +53,17 @@ int _gnutls_hello_ext_get_resumed_priv(gnutls_session_t session,
extensions_t ext,
gnutls_ext_priv_data_t * data);
+#define GNUTLS_EXT_FLAG_MSG_MASK (GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO| \
+ GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_HRR)
+
+/* these flags can only be set in the extensions, but cannot be requested;
+ * they are handled internally by the hello parsing/generating functions. */
+#define GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK ~(GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS)
+
/* obtain the message this extension was received at */
inline static gnutls_ext_flags_t _gnutls_ext_get_msg(gnutls_session_t session)
{
- return session->internals.ext_msg;
+ return session->internals.ext_msg & GNUTLS_EXT_FLAG_MSG_MASK;
}
inline static void _gnutls_ext_set_msg(gnutls_session_t session, gnutls_ext_flags_t msg)
@@ -86,6 +94,8 @@ int _gnutls_hello_ext_unpack(gnutls_session_t session,
inline static const char *ext_msg_validity_to_str(gnutls_ext_flags_t msg)
{
+ msg &= GNUTLS_EXT_FLAG_MSG_MASK;
+
switch(msg) {
case GNUTLS_EXT_FLAG_CLIENT_HELLO:
return "client hello";
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index b6473b98b5..fd3b07af78 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -2761,6 +2761,8 @@ typedef enum {
* @GNUTLS_EXT_FLAG_EE: This extension can be present in encrypted extensions message
* @GNUTLS_EXT_FLAG_HRR: This extension can be present in hello retry request message
* @GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST: When flag is present, this extension will be send even if the server didn't advertise it. An extension of this type is the Cookie TLS1.3 extension.
+ * @GNUTLS_EXT_FLAG_DTLS: This extension can be present under DTLS; otherwise ignored.
+ * @GNUTLS_EXT_FLAG_TLS: This extension can be present under TLS; otherwise ignored.
*
* Enumeration of different TLS extension registration flags.
*/
@@ -2771,7 +2773,9 @@ typedef enum {
GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO = (1<<3),
GNUTLS_EXT_FLAG_EE = (1<<4), /* ENCRYPTED */
GNUTLS_EXT_FLAG_HRR = (1<<5),
- GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST = (1<<6)
+ GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST = (1<<6),
+ GNUTLS_EXT_FLAG_TLS = (1<<7),
+ GNUTLS_EXT_FLAG_DTLS = (1<<8)
} gnutls_ext_flags_t;
/* Register a custom tls extension
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f29da98724..290387bdac 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -180,7 +180,7 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei
safe-renegotiation/srn0 safe-renegotiation/srn1 safe-renegotiation/srn2 \
safe-renegotiation/srn3 safe-renegotiation/srn4 safe-renegotiation/srn5 \
rsa-illegal-import set_x509_ocsp_multi_invalid set_key set_x509_key_file_ocsp_multi2 \
- set_x509_ocsp_multi_unknown set_x509_ocsp_multi_pem \
+ set_x509_ocsp_multi_unknown set_x509_ocsp_multi_pem tls-ext-not-in-dtls \
set_key_utf8 set_x509_key_utf8 insecure_key handshake-large-packet \
client_dsa_key server_ecdsa_key tls-session-ext-register tls-session-supplemental \
multi-alerts naked-alerts pkcs7-cat-parse set_known_dh_params_x509 \
diff --git a/tests/tls-ext-not-in-dtls.c b/tests/tls-ext-not-in-dtls.c
new file mode 100644
index 0000000000..1bbf2e2887
--- /dev/null
+++ b/tests/tls-ext-not-in-dtls.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2017-2018 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_WIN32)
+
+int main()
+{
+ exit(77);
+}
+
+#else
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/dtls.h>
+#include <signal.h>
+#include <string.h>
+#include <assert.h>
+
+#include "utils.h"
+#include "cert-common.h"
+
+enum {
+TEST_DEF_HANDHAKE,
+TEST_CUSTOM_EXT
+};
+
+/* This program tests whether the Post Handshake Auth extension is
+ * present in the client hello, and whether it is missing from server
+ * hello. In addition it contains basic functionality test for
+ * post handshake authentication.
+ */
+
+static void server_log_func(int level, const char *str)
+{
+ fprintf(stderr, "server|<%d>| %s", level, str);
+}
+
+static void client_log_func(int level, const char *str)
+{
+ fprintf(stderr, "client|<%d>| %s", level, str);
+}
+
+static int ext_send(gnutls_session_t session, gnutls_buffer_t extdata)
+{
+ gnutls_buffer_append_data(extdata, "\xff", 1);
+ return 0;
+}
+
+static int ext_recv(gnutls_session_t session, const unsigned char *buf, size_t buflen)
+{
+ return 0;
+}
+
+#define TLS_EXT_IMPL_DTLS 0xfeee
+#define TLS_EXT_EXPL_TLS 0xfeea
+
+static void client(int fd, int type)
+{
+ int ret;
+ gnutls_certificate_credentials_t x509_cred;
+ gnutls_session_t session;
+
+ assert(gnutls_global_init() >= 0);
+
+ gnutls_global_set_log_function(client_log_func);
+
+ assert(gnutls_certificate_allocate_credentials(&x509_cred) >= 0);
+
+ assert(gnutls_init(&session, GNUTLS_CLIENT|GNUTLS_DATAGRAM) >= 0);
+
+ if (type == TEST_CUSTOM_EXT) {
+ assert(gnutls_session_ext_register(session, "implicit-dtls", TLS_EXT_IMPL_DTLS, GNUTLS_EXT_TLS, ext_recv, ext_send, NULL, NULL, NULL, GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO|GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO)>=0);
+ assert(gnutls_session_ext_register(session, "explicit-tls", TLS_EXT_EXPL_TLS, GNUTLS_EXT_TLS, ext_recv, ext_send, NULL, NULL, NULL, GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO|GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO|GNUTLS_EXT_FLAG_TLS)>=0);
+ }
+
+ gnutls_handshake_set_timeout(session, 20 * 1000);
+
+ assert(gnutls_priority_set_direct(session, "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.0", NULL) >= 0);
+
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+ gnutls_transport_set_int(session, fd);
+
+ do {
+ ret = gnutls_handshake(session);
+ }
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+ if (ret < 0)
+ fail("handshake: %s\n", gnutls_strerror(ret));
+
+ close(fd);
+
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ gnutls_global_deinit();
+}
+
+#define TLS_EXT_KEY_SHARE 51
+#define TLS_EXT_POST_HANDSHAKE 49
+
+struct ext_ctx_st {
+ int extno;
+ int found;
+};
+
+static int parse_ext(void *ctx, unsigned tls_id, const unsigned char *data, unsigned data_size)
+{
+ struct ext_ctx_st *s = ctx;
+
+ if (s->extno == (int)tls_id)
+ s->found = 1;
+
+ return 0;
+}
+
+static unsigned find_client_extension(const gnutls_datum_t *msg, int extno)
+{
+ int ret;
+ struct ext_ctx_st s;
+
+ memset(&s, 0, sizeof(s));
+ s.extno = extno;
+
+ ret = gnutls_ext_raw_parse(&s, parse_ext, msg, GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO);
+ assert(ret>=0);
+
+ if (s.found)
+ return 1;
+
+ return 0;
+}
+
+static int hellos_callback(gnutls_session_t session, unsigned int htype,
+ unsigned post, unsigned int incoming, const gnutls_datum_t *msg)
+{
+ int *type;
+
+ if (htype != GNUTLS_HANDSHAKE_CLIENT_HELLO || post != GNUTLS_HOOK_PRE)
+ return 0;
+
+ type = gnutls_session_get_ptr(session);
+
+ if (find_client_extension(msg, TLS_EXT_KEY_SHARE))
+ fail("Key share extension seen in client hello!\n");
+
+ if (find_client_extension(msg, TLS_EXT_POST_HANDSHAKE))
+ fail("Key share extension seen in client hello!\n");
+
+ if (*type == TEST_CUSTOM_EXT) {
+ if (!find_client_extension(msg, TLS_EXT_IMPL_DTLS))
+ fail("Implicit DTLS extension not seen in client hello!\n");
+
+ if (find_client_extension(msg, TLS_EXT_EXPL_TLS))
+ fail("Explicit TLS extension seen in client hello!\n");
+ }
+
+ return 0;
+}
+
+static void server(int fd, int type)
+{
+ int ret;
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t x509_cred;
+
+ assert(gnutls_global_init() >= 0);
+
+ gnutls_global_set_log_function(server_log_func);
+
+ assert(gnutls_certificate_allocate_credentials(&x509_cred) >= 0);
+ assert(gnutls_certificate_set_x509_key_mem(x509_cred, &server_cert,
+ &server_key,
+ GNUTLS_X509_FMT_PEM) >= 0);
+
+ assert(gnutls_init(&session, GNUTLS_SERVER|GNUTLS_POST_HANDSHAKE_AUTH|GNUTLS_DATAGRAM) >= 0);
+
+ gnutls_handshake_set_timeout(session, 20 * 1000);
+ gnutls_handshake_set_hook_function(session, GNUTLS_HANDSHAKE_ANY,
+ GNUTLS_HOOK_BOTH,
+ hellos_callback);
+
+ gnutls_session_set_ptr(session, &type);
+ assert(gnutls_priority_set_direct(session, "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3:+VERS-TLS1.2", NULL) >= 0);
+
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+ gnutls_transport_set_int(session, fd);
+
+ do {
+ ret = gnutls_handshake(session);
+ } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+ if (ret != 0)
+ fail("handshake failed: %s\n", gnutls_strerror(ret));
+
+ close(fd);
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ gnutls_global_deinit();
+}
+
+static void ch_handler(int sig)
+{
+ int status;
+ wait(&status);
+ check_wait_status(status);
+ return;
+}
+
+static
+void start(const char *name, int type)
+{
+ int fd[2];
+ int ret;
+ pid_t child;
+
+ signal(SIGCHLD, ch_handler);
+ success("%s\n", name);
+
+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
+ if (ret < 0) {
+ perror("socketpair");
+ exit(1);
+ }
+
+ child = fork();
+ if (child < 0) {
+ perror("fork");
+ fail("fork");
+ exit(1);
+ }
+
+ if (child) {
+ /* parent */
+ close(fd[1]);
+ server(fd[0], type);
+ kill(child, SIGTERM);
+ } else {
+ close(fd[0]);
+ client(fd[1], type);
+ exit(0);
+ }
+
+}
+
+void doit(void) {
+ start("check default extensions", TEST_DEF_HANDHAKE);
+ start("check registered extensions", TEST_CUSTOM_EXT);
+}
+
+#endif /* _WIN32 */