]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
tests: check behavior on the extension hello flags
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Tue, 12 Sep 2017 08:12:41 +0000 (10:12 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 19 Feb 2018 14:29:33 +0000 (15:29 +0100)
That is, verify whether the various combinations of
GNUTLS_EXT_FLAG_CLIENT_HELLO,
GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO
work as expected with regards to sending and receiving
extensions.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
tests/tls-session-ext-register.c

index 4d1e2459e1be83de2acfc4bbd94f6003a8597cbc..89620de82dcb11f784b515d57ab15922be8ef8c8 100644 (file)
@@ -15,9 +15,8 @@
  * 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 General Public License
- * along with GnuTLS; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ * 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/>
  */
 
 /* This program tests whether an extension is exchanged when registered
@@ -49,6 +48,7 @@ int main(int argc, char **argv)
 #endif
 #include <unistd.h>
 #include <gnutls/gnutls.h>
+#include <assert.h>
 
 #include "utils.h"
 #include "cert-common.h"
@@ -69,19 +69,34 @@ static int TLSEXT_TYPE_server_sent          = 0;
 static int TLSEXT_TYPE_server_received         = 0;
 static int ign_extension_called = 0;
 
+static void reset_vars(void)
+{
+       TLSEXT_TYPE_client_sent = 0;
+       TLSEXT_TYPE_client_received = 0;
+       TLSEXT_TYPE_server_sent = 0;
+       TLSEXT_TYPE_server_received = 0;
+       ign_extension_called = 0;
+}
+
 static const unsigned char ext_data[] =
 {      
        0xFE,
        0xED
 };
 
+#define myfail(fmt, ...) \
+       fail("%s: "fmt, name, ##__VA_ARGS__)
+
 static int ext_recv_client_params(gnutls_session_t session, const unsigned char *buf, size_t buflen)
 {
+       const char *name;
+       name = gnutls_session_get_ptr(session);
+
        if (buflen != sizeof(ext_data))
-               fail("ext_recv_client_params: Invalid input buffer length\n");
+               myfail("ext_recv_client_params: Invalid input buffer length\n");
 
        if (memcmp(buf, ext_data, sizeof(ext_data)) != 0)
-               fail("ext_recv_client_params: Invalid input buffer data\n");
+               myfail("ext_recv_client_params: Invalid input buffer data\n");
 
        TLSEXT_TYPE_client_received = 1;
 
@@ -110,11 +125,15 @@ static int ext_send_client_ign_params(gnutls_session_t session, gnutls_buffer_t
 
 static int ext_recv_server_params(gnutls_session_t session, const unsigned char *buf, size_t buflen)
 {
+       const char *name;
+
+       name = gnutls_session_get_ptr(session);
+
        if (buflen != sizeof(ext_data))
-               fail("ext_recv_server_params: Invalid input buffer length\n");
+               myfail("ext_recv_server_params: Invalid input buffer length\n");
 
        if (memcmp(buf, ext_data, sizeof(ext_data)) != 0)
-               fail("ext_recv_server_params: Invalid input buffer data\n");
+               myfail("ext_recv_server_params: Invalid input buffer data\n");
 
        TLSEXT_TYPE_server_received = 1;
 
@@ -128,29 +147,25 @@ static int ext_send_server_params(gnutls_session_t session, gnutls_buffer_t extd
        return sizeof(ext_data);
 }
 
-static void client(int sd)
+static void client(int sd, const char *name, const char *prio, unsigned flags, unsigned expected_ok)
 {
        int ret;
        gnutls_session_t session;
        gnutls_certificate_credentials_t clientx509cred;
        void *p;
 
-       global_init();
-       gnutls_global_set_log_function(tls_log_func);
-       if (debug)
-               gnutls_global_set_log_level(4711);
-
        side = "client";
 
-       gnutls_certificate_allocate_credentials(&clientx509cred);
+       assert(gnutls_certificate_allocate_credentials(&clientx509cred) >= 0);
 
        /* Initialize TLS session
         */
-       gnutls_init(&session, GNUTLS_CLIENT);
+       assert(gnutls_init(&session, GNUTLS_CLIENT) >= 0);
+       gnutls_session_set_ptr(session, (void*)name);
 
        /* Use default priorities */
-       gnutls_priority_set_direct(session, "PERFORMANCE:+ANON-ECDH:+ANON-DH",
-                                  NULL);
+       assert(gnutls_priority_set_direct(session, prio,
+                                  NULL)>=0);
 
        /* put the anonymous credentials to the current session
         */
@@ -160,149 +175,161 @@ static void client(int sd)
        gnutls_transport_set_int(session, sd);
        gnutls_handshake_set_timeout(session, 20 * 1000);
 
-       ret = gnutls_session_ext_register(session, "ext_ign", TLSEXT_TYPE_IGN, GNUTLS_EXT_TLS, ext_recv_client_ign_params, ext_send_client_ign_params, NULL, NULL, NULL, 0);
+       ret = gnutls_session_ext_register(session, "ext_ign", TLSEXT_TYPE_IGN, GNUTLS_EXT_TLS, ext_recv_client_ign_params, ext_send_client_ign_params, NULL, NULL, NULL, flags);
        if (ret < 0)
-               fail("client: register extension\n");
+               myfail("client: register extension\n");
 
-       ret = gnutls_session_ext_register(session, "ext_client", TLSEXT_TYPE_SAMPLE, GNUTLS_EXT_TLS, ext_recv_client_params, ext_send_client_params, NULL, NULL, NULL, 0);
+       ret = gnutls_session_ext_register(session, "ext_client", TLSEXT_TYPE_SAMPLE, GNUTLS_EXT_TLS, ext_recv_client_params, ext_send_client_params, NULL, NULL, NULL, flags);
        if (ret < 0)
-               fail("client: register extension\n");
+               myfail("client: register extension\n");
 
        /* Perform the TLS handshake
         */
        ret = gnutls_handshake(session);
 
        if (ret < 0) {
-               fail("client: Handshake failed\n");
-               gnutls_perror(ret);
+               if (!expected_ok) {
+                       if (debug)
+                               success("client: handshake failed as expected: %s\n", gnutls_strerror(ret));
+               } else {
+                       myfail("client: Handshake failed: %s\n", gnutls_strerror(ret));
+               }
                goto end;
        } else {
                if (debug)
                        success("client: Handshake was completed\n");
        }
 
-       if (TLSEXT_TYPE_client_sent != 1 || TLSEXT_TYPE_client_received != 1)
-               fail("client: extension not properly sent/received\n");
+       if (TLSEXT_TYPE_client_sent != 1 || TLSEXT_TYPE_client_received != 1) {
+               if (expected_ok) {
+                       myfail("client: extension not properly sent/received\n");
+               } else {
+                       goto end;
+               }
+       }
 
        ret = gnutls_ext_get_data(session, TLSEXT_TYPE_SAMPLE, &p);
        if (ret < 0) {
-               fail("gnutls_ext_get_data: %s\n", gnutls_strerror(ret));
+               myfail("gnutls_ext_get_data: %s\n", gnutls_strerror(ret));
        }
 
        if (p != session) {
-               fail("client: gnutls_ext_get_data failed\n");
+               myfail("client: gnutls_ext_get_data failed\n");
        }
 
        if (ign_extension_called == 0) {
-               fail("registered ign extension was not called\n");
+               myfail("registered ign extension was not called\n");
        }
 
        gnutls_bye(session, GNUTLS_SHUT_RDWR);
 
+       if (!expected_ok)
+               myfail("client: expected failure but succeeded!\n");
+
 end:
        close(sd);
 
        gnutls_deinit(session);
 
        gnutls_certificate_free_credentials(clientx509cred);
-
-       gnutls_global_deinit();
 }
 
-static void server(int sd)
+static void server(int sd, const char *name, const char *prio, unsigned flags, unsigned expected_ok)
 {
        gnutls_certificate_credentials_t serverx509cred;
        int ret;
        gnutls_session_t session;
-       unsigned i;
-
-       /* this must be called once in the program
-        */
-       global_init();
-       gnutls_global_set_log_function(tls_log_func);
-       if (debug)
-               gnutls_global_set_log_level(4711);
 
        side = "server";
 
-       gnutls_certificate_allocate_credentials(&serverx509cred);
-       gnutls_certificate_set_x509_key_mem(serverx509cred,
+       assert(gnutls_certificate_allocate_credentials(&serverx509cred)>=0);
+       assert(gnutls_certificate_set_x509_key_mem(serverx509cred,
                                            &server_cert, &server_key,
-                                           GNUTLS_X509_FMT_PEM);
+                                           GNUTLS_X509_FMT_PEM) >= 0);
 
-       gnutls_init(&session, GNUTLS_SERVER);
+       assert(gnutls_init(&session, GNUTLS_SERVER) >= 0);
+       gnutls_session_set_ptr(session, (void*)name);
 
        /* avoid calling all the priority functions, since the defaults
         * are adequate.
         */
-       gnutls_priority_set_direct(session, "PERFORMANCE:+ANON-ECDH:+ANON-DH",
-                                  NULL);
+       assert(gnutls_priority_set_direct(session, prio,
+                                  NULL) >= 0);
 
        gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
                                serverx509cred);
 
-       gnutls_session_ext_register(session, "ext_server", TLSEXT_TYPE_SAMPLE, GNUTLS_EXT_TLS, ext_recv_server_params, ext_send_server_params, NULL, NULL, NULL, 0);
+       assert(gnutls_session_ext_register(session, "ext_server", TLSEXT_TYPE_SAMPLE, GNUTLS_EXT_TLS, ext_recv_server_params, ext_send_server_params, NULL, NULL, NULL, flags) >= 0);
 
        gnutls_transport_set_int(session, sd);
        gnutls_handshake_set_timeout(session, 20 * 1000);
 
        ret = gnutls_handshake(session);
        if (ret < 0) {
-               close(sd);
-               gnutls_deinit(session);
-               fail("server: Handshake has failed (%s)\n\n",
-                    gnutls_strerror(ret));
+               if (!expected_ok) {
+                       if (debug)
+                               success("server: handshake failed as expected: %s\n", gnutls_strerror(ret));
+                       goto cleanup;
+               } else {
+                       close(sd);
+                       gnutls_deinit(session);
+                       myfail("server: Handshake has failed (%s)\n",
+                            gnutls_strerror(ret));
+               }
                return;
        }
        if (debug)
                success("server: Handshake was completed\n");
 
-       if (TLSEXT_TYPE_server_sent != 1 || TLSEXT_TYPE_server_received != 1)
-               fail("server: extension not properly sent/received\n");
+
+       if (TLSEXT_TYPE_server_sent != 1 || TLSEXT_TYPE_server_received != 1) {
+               if (expected_ok)
+                       myfail("server: extension not properly sent/received\n");
+               else
+                       goto cleanup;
+       }
 
        /* do not wait for the peer to close the connection.
         */
        gnutls_bye(session, GNUTLS_SHUT_WR);
 
-       /* check whether we can crash the library by adding many extensions */
-       for (i=0;i<64;i++) {
-               ret = gnutls_ext_register("ext_serverxx", TLSEXT_TYPE_SAMPLE+i+1, GNUTLS_EXT_TLS, ext_recv_server_params, ext_send_server_params, NULL, NULL, NULL);
-               if (ret < 0) {
-                       success("failed registering extension no %d (expected)\n", i+1);
-                       break;
-               }
-       }
+       if (!expected_ok)
+               myfail("server: expected failure but succeeded!\n");
 
+ cleanup:
        close(sd);
        gnutls_deinit(session);
 
        gnutls_certificate_free_credentials(serverx509cred);
 
-       gnutls_global_deinit();
-
        if (debug)
                success("server: finished\n");
 }
 
-void doit(void)
+#define try_common(name, prio, flags, sok, cok) \
+       try(name, prio, flags, flags, sok, cok)
+
+static void try(const char *name, const char *prio, unsigned server_flags,
+               unsigned client_flags, unsigned server_ok, unsigned client_ok)
 {
        pid_t child;
        int sockets[2];
        int err;
 
-       signal(SIGPIPE, SIG_IGN);
+       success("Testing: %s: ", name);
+       reset_vars();
 
        err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
        if (err == -1) {
                perror("socketpair");
-               fail("socketpair failed\n");
+               myfail("socketpair failed\n");
                return;
        }
 
        child = fork();
        if (child < 0) {
                perror("fork");
-               fail("fork");
+               myfail("fork");
                return;
        }
 
@@ -310,12 +337,52 @@ void doit(void)
                int status;
                /* parent */
                close(sockets[1]);
-               server(sockets[0]);
+               server(sockets[0], name, prio, server_flags, server_ok);
                wait(&status);
+               check_wait_status(status);
+               success("ok");
        } else {
                close(sockets[0]);
-               client(sockets[1]);
+               client(sockets[1], name, prio, client_flags, client_ok);
+               _exit(0);
        }
+
+       success("\n");
+}
+
+void doit(void)
+{
+       unsigned i;
+       int ret;
+
+       signal(SIGPIPE, SIG_IGN);
+
+       global_init();
+       gnutls_global_set_log_function(tls_log_func);
+       if (debug)
+               gnutls_global_set_log_level(5);
+
+       try_common("TLS1.2 both ways (default)", "NORMAL:+ANON-ECDH:-VERS-TLS-ALL:+VERS-TLS1.2", 0, 1, 1);
+       try_common("TLS1.2 both ways", "NORMAL:+ANON-ECDH:-VERS-TLS-ALL:+VERS-TLS1.2", GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, 1, 1);
+
+       try_common("TLS1.2 client only", "NORMAL:+ANON-ECDH:-VERS-TLS-ALL:+VERS-TLS1.2", GNUTLS_EXT_FLAG_CLIENT_HELLO, 0, 0);
+       try_common("TLS1.2 client and TLS 1.3 server", "NORMAL:+ANON-ECDH:-VERS-TLS-ALL:+VERS-TLS1.2", GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO, 0, 0);
+       try_common("TLS1.2 server only", "NORMAL:+ANON-ECDH:-VERS-TLS-ALL:+VERS-TLS1.2", GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, 0, 0);
+
+       try("TLS1.2 client rejects", "NORMAL:+ANON-ECDH:-VERS-TLS-ALL:+VERS-TLS1.2", GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, GNUTLS_EXT_FLAG_CLIENT_HELLO, 0, 0);
+       try("TLS1.2 never on client hello", "NORMAL:+ANON-ECDH:-VERS-TLS-ALL:+VERS-TLS1.2", GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, GNUTLS_EXT_FLAG_CLIENT_HELLO, 0, 0);
+
+       /* check whether we can crash the library by adding many extensions */
+       success("Testing: register many global extensions\n");
+       for (i=0;i<64;i++) {
+               ret = gnutls_ext_register("ext_serverxx", TLSEXT_TYPE_SAMPLE+i+1, GNUTLS_EXT_TLS, ext_recv_server_params, ext_send_server_params, NULL, NULL, NULL);
+               if (ret < 0) {
+                       success("failed registering extension no %d (expected)\n", i+1);
+                       break;
+               }
+       }
+
+       gnutls_global_deinit();
 }
 
 #endif                         /* _WIN32 */