summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2018-04-20 21:35:52 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2018-05-04 11:38:50 +0200
commit6efa37cd6325eab32dff1bd9ef1b00b7eb6d0e73 (patch)
tree86fb953e5916462fd6e59751086419566d693cb3
parent45d6b748deaace67d61e248493b840cebb66630a (diff)
downloadgnutls-6efa37cd6325eab32dff1bd9ef1b00b7eb6d0e73.tar.gz
gnutls-cli: enhanced tool for TLS1.3 options
This patch allows a client to enable post-handshake authentication, perform re-key and restrict the sent key shares. Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
-rw-r--r--src/cli-args.def13
-rw-r--r--src/cli.c69
-rw-r--r--src/common.c14
-rwxr-xr-xsrc/inline_cmds.h4
-rw-r--r--src/serv.c12
5 files changed, 91 insertions, 21 deletions
diff --git a/src/cli-args.def b/src/cli-args.def
index e883320c61..89d4361dc4 100644
--- a/src/cli-args.def
+++ b/src/cli-args.def
@@ -368,6 +368,19 @@ flag = {
};
flag = {
+ name = single-key-share;
+ descrip = "Send a single key share under TLS1.3";
+ doc = "This option switches the default mode of sending multiple
+key shares, to send a single one (the top one).";
+};
+
+flag = {
+ name = post-handshake-auth;
+ descrip = "Enable post-handshake authentication under TLS1.3";
+ doc = "This option enables post-handshake authentication when under TLS1.3.";
+};
+
+flag = {
name = inline-commands;
descrip = "Inline commands of the form ^<cmd>^";
doc = "Enable inline commands of the form ^<cmd>^. The inline commands are expected to be in a line by themselves. The available commands are: resume and renegotiate.";
diff --git a/src/cli.c b/src/cli.c
index 27db30d7c1..17869250e7 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -116,7 +116,7 @@ static gnutls_certificate_credentials_t xcred;
/* prototypes */
-static void check_rehandshake(socket_st * socket, int ret);
+static void check_server_cmd(socket_st * socket, int ret);
static void init_global_tls_stuff(void);
static int cert_verify_ocsp(gnutls_session_t session);
@@ -714,7 +714,7 @@ static int handle_error(socket_st * hd, int err)
printf("*** Received alert [%d]: %s\n", alert, str);
}
- check_rehandshake(hd, err);
+ check_server_cmd(hd, err);
return ret;
}
@@ -805,6 +805,23 @@ static int try_rehandshake(socket_st * hd)
}
}
+static int try_rekey(socket_st * hd)
+{
+ int ret;
+
+ do {
+ ret = gnutls_session_key_update(hd->session, GNUTLS_KU_PEER);
+ } while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+
+ if (ret < 0) {
+ fprintf(stderr, "*** Rekey has failed: %s\n", gnutls_strerror(ret));
+ return ret;
+ } else {
+ printf("- Rekey was completed\n");
+ return 0;
+ }
+}
+
static int try_resume(socket_st * hd)
{
int ret, socket_flags = 0;
@@ -962,6 +979,8 @@ int run_inline_command(inline_cmds_st * cmd, socket_st * hd)
switch (cmd->cmd_found) {
case INLINE_COMMAND_RESUME:
return try_resume(hd);
+ case INLINE_COMMAND_REKEY:
+ return try_rekey(hd);
case INLINE_COMMAND_RENEGOTIATE:
return try_rehandshake(hd);
default:
@@ -1462,6 +1481,12 @@ static void cmd_parser(int argc, char **argv)
if (disable_extensions)
init_flags |= GNUTLS_NO_EXTENSIONS;
+ if (HAVE_OPT(SINGLE_KEY_SHARE))
+ init_flags |= GNUTLS_KEY_SHARE_TOP;
+
+ if (HAVE_OPT(POST_HANDSHAKE_AUTH))
+ init_flags |= GNUTLS_POST_HANDSHAKE_AUTH;
+
inline_commands = HAVE_OPT(INLINE_COMMANDS);
if (HAVE_OPT(INLINE_COMMANDS_PREFIX)) {
if (strlen(OPT_ARG(INLINE_COMMANDS_PREFIX)) > 1) {
@@ -1554,23 +1579,35 @@ static void cmd_parser(int argc, char **argv)
}
}
-static void check_rehandshake(socket_st * socket, int ret)
+static void check_server_cmd(socket_st * socket, int ret)
{
- if (socket->secure && ret == GNUTLS_E_REHANDSHAKE) {
- /* There is a race condition here. If application
- * data is sent after the rehandshake request,
- * the server thinks we ignored his request.
- * This is a bad design of this client.
- */
- printf("*** Received rehandshake request\n");
- /* gnutls_alert_send( session, GNUTLS_AL_WARNING, GNUTLS_A_NO_RENEGOTIATION); */
+ if (socket->secure) {
+ if (ret == GNUTLS_E_REHANDSHAKE) {
+ /* There is a race condition here. If application
+ * data is sent after the rehandshake request,
+ * the server thinks we ignored his request.
+ * This is a bad design of this client.
+ */
+ printf("*** Received rehandshake request\n");
+ /* gnutls_alert_send( session, GNUTLS_AL_WARNING, GNUTLS_A_NO_RENEGOTIATION); */
+
+ ret = do_handshake(socket);
- ret = do_handshake(socket);
+ if (ret == 0) {
+ printf("*** Rehandshake was performed.\n");
+ } else {
+ printf("*** Rehandshake Failed: %s\n", gnutls_strerror(ret));
+ }
+ } else if (ret == GNUTLS_E_REAUTH_REQUEST) {
+ do {
+ ret = gnutls_reauth(socket->session, 0);
+ } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
- if (ret == 0) {
- printf("*** Rehandshake was performed.\n");
- } else {
- printf("*** Rehandshake Failed.\n");
+ if (ret == 0) {
+ printf("*** Re-auth was performed.\n");
+ } else {
+ printf("*** Re-auth failed: %s\n", gnutls_strerror(ret));
+ }
}
}
}
diff --git a/src/common.c b/src/common.c
index a29f558cb0..5e1b1a5582 100644
--- a/src/common.c
+++ b/src/common.c
@@ -929,6 +929,20 @@ int check_command(gnutls_session_t session, const char *str)
"*** Sending rehandshake request\n");
gnutls_rehandshake(session);
return 1;
+ } else if (strncmp
+ (str, "**REAUTH**",
+ sizeof("**REAUTH**") - 1) == 0) {
+ fprintf(stderr,
+ "*** Sending re-auth request\n");
+ do {
+ ret = gnutls_reauth(session, 0);
+ } while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+ if (ret < 0) {
+ fprintf(stderr, "reauth: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+ return 1;
} else
if (strncmp
(str, "**HEARTBEAT**",
diff --git a/src/inline_cmds.h b/src/inline_cmds.h
index 5cff93362a..fd3dc48d28 100755
--- a/src/inline_cmds.h
+++ b/src/inline_cmds.h
@@ -40,7 +40,8 @@
*/
typedef enum INLINE_COMMAND { INLINE_COMMAND_NONE,
INLINE_COMMAND_RESUME,
- INLINE_COMMAND_RENEGOTIATE
+ INLINE_COMMAND_RENEGOTIATE,
+ INLINE_COMMAND_REKEY
} inline_command_t;
#define NUM_INLINE_COMMANDS 2
@@ -66,5 +67,6 @@ struct inline_command_definitions {
/* All inline commands will contain a trailing LF */
struct inline_command_definitions inline_commands_def[] = {
{INLINE_COMMAND_RESUME, "^resume^\n"},
+ {INLINE_COMMAND_REKEY, "^rekey^\n"},
{INLINE_COMMAND_RENEGOTIATE, "^renegotiate^\n"},
};
diff --git a/src/serv.c b/src/serv.c
index b2de3dcc28..ab1a6e6c65 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -380,9 +380,9 @@ gnutls_session_t initialize_session(int dtls)
priorities = "NORMAL";
if (dtls)
- gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM);
+ gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM | GNUTLS_POST_HANDSHAKE_AUTH);
else
- gnutls_init(&session, GNUTLS_SERVER);
+ gnutls_init(&session, GNUTLS_SERVER | GNUTLS_POST_HANDSHAKE_AUTH);
/* allow the use of private ciphersuites.
*/
@@ -944,8 +944,12 @@ get_response(gnutls_session_t session, char *request,
strip(request);
fprintf(stderr, "received: %s\n", request);
if (check_command(session, request)) {
- *response = NULL;
- *response_length = 0;
+ *response = strdup("Successfully executed command\n");
+ if (*response == NULL) {
+ fprintf(stderr, "Memory error\n");
+ exit(1);
+ }
+ *response_length = strlen(*response);
return;
}
*response = strdup(request);