]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
gnutls-cli: enhanced tool for TLS1.3 options
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 20 Apr 2018 19:35:52 +0000 (21:35 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 4 May 2018 09:38:50 +0000 (11:38 +0200)
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>
src/cli-args.def
src/cli.c
src/common.c
src/inline_cmds.h
src/serv.c

index e883320c610b688b0169fedf619db3004c7413fc..89d4361dc4762a37c91ec77e470209c2f7c4c6b6 100644 (file)
@@ -367,6 +367,19 @@ flag = {
     doc      = "This option disables all TLS extensions. Deprecated option. Use the priority string.";
 };
 
+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>^";
index 27db30d7c19cf989d0e40329144f42786b7d1dbe..17869250e7c6c9f991fe5ef61f6e04b13d4caa38 100644 (file)
--- 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));
+                       }
                }
        }
 }
index a29f558cb02321cb1c0f9d18a36aeb97034cf58a..5e1b1a5582bcaad0e755a668e81994fd0619569c 100644 (file)
@@ -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**",
index 5cff93362a78b71a32464f6570014e7f9e1dc5e3..fd3dc48d28ce4845e1bdc786950e63a7eb225d78 100755 (executable)
@@ -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"},
 };
index b2de3dcc288298c9846df13026c0b905eaf90a4d..ab1a6e6c658284c01ae57f7d55cfdebaa14db0d9 100644 (file)
@@ -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);