[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 4/4] tests: Add torture_server test


torture_server tests whether a libssh server can correctly parse an
X11 request.

Signed-off-by: Alan Dunn <amdunn@xxxxxxxxx>
---
 tests/unittests/CMakeLists.txt   |    4 +
 tests/unittests/torture_server.c |  193 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 197 insertions(+)
 create mode 100644 tests/unittests/torture_server.c

diff --git a/tests/unittests/CMakeLists.txt b/tests/unittests/CMakeLists.txt
index 3820399..7f06a6d 100644
--- a/tests/unittests/CMakeLists.txt
+++ b/tests/unittests/CMakeLists.txt
@@ -15,4 +15,8 @@ if (UNIX AND NOT WIN32)
     add_cmocka_test(torture_rand torture_rand.c ${TORTURE_LIBRARY})
     # requires /dev/null
     add_cmocka_test(torture_channel torture_channel.c ${TORTURE_LIBRARY})
+    if (WITH_SERVER)
+        # requires pthread, ssh-keygen
+        add_cmocka_test(torture_server torture_server.c ${TORTURE_LIBRARY})
+    endif (WITH_SERVER)
 endif (UNIX AND NOT WIN32)
diff --git a/tests/unittests/torture_server.c b/tests/unittests/torture_server.c
new file mode 100644
index 0000000..6e4da67
--- /dev/null
+++ b/tests/unittests/torture_server.c
@@ -0,0 +1,193 @@
+#define LIBSSH_STATIC
+#include <pthread.h>
+
+#include <libssh/libssh.h>
+#include "torture.h"
+
+static void setup(void **state) {
+    int rc;
+
+    /* unused */
+    (void)state;
+
+    rc = torture_setup_rsa_key();
+    assert_int_equal(rc, 0);
+}
+
+/* For x11_screen_number, need something that is not equal to htonl
+   itself */
+static const uint32_t x11_screen_number = 1;
+static const unsigned int test_port = 2222;
+
+static void *client_thread(void *arg) {
+    int rc;
+    ssh_session session;
+    ssh_channel channel;
+
+    /* unused */
+    (void)arg;
+
+    session = torture_ssh_session("localhost", &test_port,
+                                  "foo", "bar");
+    assert_true(session != NULL);
+
+    channel = ssh_channel_new(session);
+    assert_true(channel != NULL);
+
+    rc = ssh_channel_open_session(channel);
+    assert_int_equal(rc, SSH_OK);
+
+    rc = ssh_channel_request_x11(channel, 0, NULL, NULL,
+                                 (uint32_t)x11_screen_number);
+    assert_int_equal(rc, SSH_OK);
+
+    ssh_free(session);
+    return NULL;
+}
+
+static int auth_password_accept(ssh_session session,
+                                const char *user,
+                                const char *password,
+                                void *userdata) {
+    /* unused */
+    (void)session;
+    (void)user;
+    (void)password;
+    (void)userdata;
+
+    return SSH_AUTH_SUCCESS;
+}
+
+struct channel_data {
+    int req_seen;
+    uint32_t screen_number;
+};
+
+static void ssh_channel_x11_req(ssh_session session,
+                                ssh_channel channel,
+                                int single_connection,
+                                const char *auth_protocol,
+                                const char *auth_cookie,
+                                uint32_t screen_number,
+                                void *userdata) {
+    struct channel_data *channel_data = userdata;
+
+    /* unused */
+    (void)session;
+    (void)channel;
+    (void)single_connection;
+    (void)auth_protocol;
+    (void)auth_cookie;
+
+    /* We've seen an x11 request.  Record the screen number */
+    channel_data->req_seen = 1;
+    channel_data->screen_number = screen_number;
+}
+
+static ssh_channel channel_open(ssh_session session, void *userdata) {
+    ssh_channel channel = NULL;
+    ssh_channel_callbacks channel_cb = userdata;
+
+    /* unused */
+    (void)userdata;
+
+    channel = ssh_channel_new(session);
+    if (channel == NULL) {
+        goto out;
+    }
+    ssh_set_channel_callbacks(channel, channel_cb);
+
+ out:
+    return channel;
+}
+
+static void test_ssh_channel_request_x11(void **state) {
+    int rc, event_rc;
+    pthread_t client_pthread;
+    ssh_bind sshbind;
+    ssh_session server;
+    ssh_event event;
+
+    struct channel_data channel_data;
+    struct ssh_channel_callbacks_struct channel_cb = {
+        .userdata = &channel_data,
+        .channel_x11_req_function = ssh_channel_x11_req
+    };
+    struct ssh_server_callbacks_struct server_cb = {
+        .userdata = &channel_cb,
+        .auth_password_function = auth_password_accept,
+        .channel_open_request_session_function = channel_open
+    };
+
+    /* unused */
+    (void)state;
+
+    memset(&channel_data, 0, sizeof(channel_data));
+    ssh_callbacks_init(&channel_cb);
+    ssh_callbacks_init(&server_cb);
+
+    /* Create server */
+    sshbind = torture_ssh_bind("localhost", test_port, LIBSSH_RSA_TESTKEY);
+    assert_true(sshbind != NULL);
+
+    /* Get client to connect */
+    rc = pthread_create(&client_pthread, NULL, client_thread, NULL);
+    assert_int_equal(rc, 0);
+
+    server = ssh_new();
+    assert_true(server != NULL);
+
+    rc = ssh_bind_accept(sshbind, server);
+    assert_int_equal(rc, SSH_OK);
+
+    /* Handle client connection */
+    ssh_set_server_callbacks(server, &server_cb);
+
+    rc = ssh_handle_key_exchange(server);
+    assert_int_equal(rc, SSH_OK);
+
+    event = ssh_event_new();
+    assert_true(event != NULL);
+
+    ssh_event_add_session(event, server);
+
+    event_rc = SSH_OK;
+    while (!channel_data.req_seen && event_rc == SSH_OK) {
+        event_rc = ssh_event_dopoll(event, -1);
+    }
+
+    /* Cleanup */
+    ssh_event_free(event);
+    ssh_free(server);
+    ssh_bind_free(sshbind);
+
+    rc = pthread_join(client_pthread, NULL);
+    assert_int_equal(rc, 0);
+
+    assert_true(channel_data.req_seen);
+    assert_int_equal(channel_data.screen_number,
+                     x11_screen_number);
+}
+
+static void teardown(void **state) {
+    /* unused */
+    (void)state;
+
+    unlink(LIBSSH_RSA_TESTKEY);
+    unlink(LIBSSH_RSA_TESTKEY ".pub");
+}
+
+int torture_run_tests(void) {
+    int rc;
+    const UnitTest tests[] = {
+        unit_test_setup_teardown(test_ssh_channel_request_x11,
+                                 setup,
+                                 teardown)
+    };
+
+    ssh_threads_set_callbacks(ssh_threads_get_pthread());
+    ssh_init();
+    rc = run_tests(tests);
+    ssh_finalize();
+    return rc;
+}
-- 
1.7.9.5


References:
[PATCH 0/4] Fix incorrectly passed X11 request screen numberAlan Dunn <amdunn@xxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org