summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2018-05-18 13:48:13 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2018-05-18 13:48:13 +0000
commit4d7b69cc5e9e740d7a27ca1e4be359fff8797e3b (patch)
treebf9a12d81c1469c6aefa896393bd95f95cdea7f4
parentfef953e7028ae14821e30a47201b77422d5be6b3 (diff)
parentf41df13ec8b77414ff8e682d8234c089bd24e7e9 (diff)
downloadgnutls-4d7b69cc5e9e740d7a27ca1e4be359fff8797e3b.tar.gz
Merge branch 'tmp-prohibit-tls-dtls-mix' into 'master'
Added the notion of TLS-only and DTLS-only extensions Closes #440 See merge request gnutls/gnutls!634
-rw-r--r--doc/cha-gtls-app.texi2
-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/extv.c50
-rw-r--r--lib/hello_ext.c73
-rw-r--r--lib/hello_ext.h12
-rw-r--r--lib/includes/gnutls/gnutls.h.in9
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/gnutls_ext_raw_parse.c4
-rw-r--r--tests/gnutls_ext_raw_parse_dtls.c292
-rw-r--r--tests/tls-ext-not-in-dtls.c288
29 files changed, 746 insertions, 65 deletions
diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi
index c775f4b2c1..05e1e03a49 100644
--- a/doc/cha-gtls-app.texi
+++ b/doc/cha-gtls-app.texi
@@ -1604,7 +1604,7 @@ handshake_hook_func(gnutls_session_t session, unsigned int htype,
assert(when == GNUTLS_HOOK_PRE);
ret = gnutls_ext_raw_parse(NULL, ext_hook_func, msg,
- GNUTLS_EXT_RAW_FLAG_CLIENT_HELLO);
+ GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO);
assert(ret >= 0);
gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
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/extv.c b/lib/extv.c
index 0abfd370fb..88b723ef39 100644
--- a/lib/extv.c
+++ b/lib/extv.c
@@ -83,13 +83,13 @@ int _gnutls_extv_parse(void *ctx,
* @ctx: a pointer to pass to callback function
* @cb: callback function to process each extension found
* @data: TLS extension data
- * @flags: should be zero or %GNUTLS_EXT_RAW_FLAG_CLIENT_HELLO
+ * @flags: should be zero or %GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO or %GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO
*
* This function iterates through the TLS extensions as passed in
* @data, passing the individual extension data to callback. The
* @data must conform to Extension extensions<0..2^16-1> format.
*
- * If flags is %GNUTLS_EXT_RAW_FLAG_CLIENT_HELLO then this function
+ * If flags is %GNUTLS_EXT_RAW_TLS_FLAG_CLIENT_HELLO then this function
* will parse the extension data from the position, as if the packet in
* @data is a client hello (without record or handshake headers) -
* as provided by gnutls_handshake_set_hook_function().
@@ -104,7 +104,7 @@ int _gnutls_extv_parse(void *ctx,
int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb,
const gnutls_datum_t *data, unsigned int flags)
{
- if (flags & GNUTLS_EXT_RAW_FLAG_CLIENT_HELLO) {
+ if (flags & GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO) {
ssize_t size = data->size;
size_t len;
uint8_t *p = data->data;
@@ -141,6 +141,50 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb,
return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
return _gnutls_extv_parse(ctx, cb, p, size);
+ } else if (flags & GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO) {
+ ssize_t size = data->size;
+ size_t len;
+ uint8_t *p = data->data;
+
+ DECR_LEN(size, HANDSHAKE_SESSION_ID_POS);
+
+ if (p[0] != 254)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+
+ p += HANDSHAKE_SESSION_ID_POS;
+
+ /* skip session id */
+ DECR_LEN(size, 1);
+ len = p[0];
+ p++;
+ DECR_LEN(size, len);
+ p += len;
+
+ /* skip cookie */
+ DECR_LEN(size, 1);
+ len = p[0];
+ p++;
+ DECR_LEN(size, len);
+ p += len;
+
+ /* CipherSuites */
+ DECR_LEN(size, 2);
+ len = _gnutls_read_uint16(p);
+ p += 2;
+ DECR_LEN(size, len);
+ p += len;
+
+ /* legacy_compression_methods */
+ DECR_LEN(size, 1);
+ len = p[0];
+ p++;
+ DECR_LEN(size, len);
+ p += len;
+
+ if (size <= 0)
+ return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
+ return _gnutls_extv_parse(ctx, cb, p, size);
}
if (flags != 0)
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 139355b0cb..fd3b07af78 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -2724,7 +2724,8 @@ typedef int (*gnutls_ext_pack_func) (gnutls_ext_priv_data_t data,
typedef int (*gnutls_ext_unpack_func) (gnutls_buffer_t packed_data,
gnutls_ext_priv_data_t *data);
-#define GNUTLS_EXT_RAW_FLAG_CLIENT_HELLO 1
+#define GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO 1
+#define GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO (1<<1)
typedef int (*gnutls_ext_raw_process_func)(void *ctx, unsigned tls_id, const unsigned char *data, unsigned data_size);
int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb,
const gnutls_datum_t *data, unsigned int flags);
@@ -2760,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.
*/
@@ -2770,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 4243c5befe..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 \
@@ -193,7 +193,7 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei
x509sign-verify-error rng-op-nonce rng-op-random rng-op-key x509-dn-decode-compat \
ip-check mini-x509-ipaddr trust-store base64-raw random-art dhex509self \
dss-sig-val sign-pk-api tls-session-ext-override mini-record-pad \
- tls13-server-kx-neg
+ tls13-server-kx-neg gnutls_ext_raw_parse_dtls
if HAVE_SECCOMP_TESTS
ctests += dtls-with-seccomp tls-with-seccomp dtls-client-with-seccomp tls-client-with-seccomp
diff --git a/tests/gnutls_ext_raw_parse.c b/tests/gnutls_ext_raw_parse.c
index 8f1801fb8a..2ffbb77896 100644
--- a/tests/gnutls_ext_raw_parse.c
+++ b/tests/gnutls_ext_raw_parse.c
@@ -51,7 +51,7 @@ int main()
#include "cert-common.h"
#include "tls13/ext-parse.h"
-/* This program tests gnutls_ext_raw_parse with GNUTLS_EXT_RAW_FLAG_CLIENT_HELLO
+/* This program tests gnutls_ext_raw_parse with GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO
* flag.
*/
@@ -110,7 +110,7 @@ static int handshake_callback(gnutls_session_t session, unsigned int htype,
if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO && post) {
if (bare_version) {
- ret = gnutls_ext_raw_parse(NULL, ext_callback, msg, GNUTLS_EXT_RAW_FLAG_CLIENT_HELLO);
+ ret = gnutls_ext_raw_parse(NULL, ext_callback, msg, GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO);
} else {
unsigned pos;
gnutls_datum_t mmsg;
diff --git a/tests/gnutls_ext_raw_parse_dtls.c b/tests/gnutls_ext_raw_parse_dtls.c
new file mode 100644
index 0000000000..6efbb119ba
--- /dev/null
+++ b/tests/gnutls_ext_raw_parse_dtls.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 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 <string.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 <time.h>
+#include <gnutls/gnutls.h>
+#include <signal.h>
+#include <assert.h>
+
+#include "utils.h"
+#include "cert-common.h"
+#include "tls13/ext-parse.h"
+
+/* This program tests gnutls_ext_raw_parse with GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO
+ * flag.
+ */
+
+#define HOSTNAME "example.com"
+
+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 unsigned found_server_name = 0;
+static unsigned found_status_req = 0;
+
+static int ext_callback(void *ctx, unsigned tls_id, const unsigned char *data, unsigned size)
+{
+ if (tls_id == 0) { /* server name */
+ /* very interesting extension, 4 bytes of sizes
+ * and 1 byte of type. */
+ unsigned esize = (data[0] << 8) | data[1];
+ assert(esize == strlen(HOSTNAME)+3);
+
+ size -= 2;
+ data += 2;
+
+ assert(data[0] == 0);
+ data++;
+ size--;
+
+ esize = (data[0] << 8) | data[1];
+
+ assert(esize == strlen(HOSTNAME));
+ data += 2;
+ size -= 2;
+
+ assert(memcmp(data, HOSTNAME, strlen(HOSTNAME)) == 0);
+ found_server_name = 1;
+ } else if (tls_id == 5) {
+ found_status_req = 1;
+ } else {
+ if (debug)
+ success("found extension: %u\n", tls_id);
+ }
+ return 0;
+}
+
+static int handshake_callback(gnutls_session_t session, unsigned int htype,
+ unsigned post, unsigned int incoming, const gnutls_datum_t *msg)
+{
+ int ret;
+
+ if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO && post) {
+ ret = gnutls_ext_raw_parse(NULL, ext_callback, msg, GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO);
+
+ assert(ret >= 0);
+ }
+ return 0;
+}
+
+static void client(int fd)
+{
+ int ret;
+ gnutls_certificate_credentials_t x509_cred;
+ gnutls_session_t session;
+
+ global_init();
+
+ if (debug) {
+ gnutls_global_set_log_function(client_log_func);
+ gnutls_global_set_log_level(7);
+ }
+
+ gnutls_certificate_allocate_credentials(&x509_cred);
+
+ /* Initialize TLS session
+ */
+ gnutls_init(&session, GNUTLS_CLIENT|GNUTLS_DATAGRAM);
+ gnutls_handshake_set_timeout(session, 20 * 1000);
+
+ assert(gnutls_priority_set_direct(session, "NORMAL:-VERS-ALL:+VERS-DTLS1.2", NULL)>= 0);
+
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+ gnutls_transport_set_int(session, fd);
+ assert(gnutls_server_name_set(session, GNUTLS_NAME_DNS, HOSTNAME, strlen(HOSTNAME))>=0);
+
+ /* Perform the TLS handshake
+ */
+ do {
+ ret = gnutls_handshake(session);
+ }
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+ if (ret == GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM) {
+ /* success */
+ goto end;
+ }
+
+ if (ret < 0) {
+ fail("client: Handshake failed: %s\n", gnutls_strerror(ret));
+ } else {
+ if (debug)
+ success("client: Handshake was completed\n");
+ }
+
+ if (debug)
+ success("client: TLS version is: %s\n",
+ gnutls_protocol_get_name
+ (gnutls_protocol_get_version(session)));
+
+ gnutls_bye(session, GNUTLS_SHUT_WR);
+
+ end:
+
+ close(fd);
+
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ gnutls_global_deinit();
+}
+
+
+static void server(int fd)
+{
+ int ret;
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t x509_cred;
+
+ /* this must be called once in the program
+ */
+ global_init();
+
+ if (debug) {
+ gnutls_global_set_log_function(server_log_func);
+ gnutls_global_set_log_level(4711);
+ }
+
+ gnutls_certificate_allocate_credentials(&x509_cred);
+ gnutls_certificate_set_x509_key_mem(x509_cred, &server_cert,
+ &server_key,
+ GNUTLS_X509_FMT_PEM);
+
+ gnutls_init(&session, GNUTLS_SERVER|GNUTLS_DATAGRAM);
+ gnutls_handshake_set_timeout(session, 20 * 1000);
+
+ gnutls_handshake_set_hook_function(session, GNUTLS_HANDSHAKE_CLIENT_HELLO,
+ GNUTLS_HOOK_POST,
+ handshake_callback);
+
+ assert(gnutls_priority_set_direct(session, "NORMAL:-VERS-ALL:+VERS-DTLS1.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) {
+ /* failure is expected here */
+ goto end;
+ }
+
+ if (debug)
+ success("server: Handshake was completed\n");
+
+ if (debug)
+ success("server: TLS version is: %s\n",
+ gnutls_protocol_get_name
+ (gnutls_protocol_get_version(session)));
+
+ assert(found_server_name != 0);
+ assert(found_status_req != 0);
+
+ gnutls_bye(session, GNUTLS_SHUT_WR);
+
+ end:
+ close(fd);
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ gnutls_global_deinit();
+
+ if (debug)
+ success("server: finished\n");
+}
+
+static void ch_handler(int sig)
+{
+ return;
+}
+
+void doit(void)
+{
+ int fd[2];
+ int ret, status = 0;
+ pid_t child;
+
+ signal(SIGCHLD, ch_handler);
+ signal(SIGPIPE, SIG_IGN);
+
+ 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]);
+ waitpid(child, &status, 0);
+ check_wait_status(status);
+ } else {
+ close(fd[0]);
+ client(fd[1]);
+ exit(0);
+ }
+
+ return;
+}
+
+
+#endif /* _WIN32 */
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 */