aboutsummaryrefslogtreecommitdiff
path: root/tests/unittests
diff options
context:
space:
mode:
authorAlan Dunn <amdunn@gmail.com>2014-04-19 14:20:00 -0500
committerAndreas Schneider <asn@cryptomilk.org>2015-01-20 20:23:19 +0100
commit6b7f275c32418a1a38b6f01466299469f9995f4c (patch)
treed7a19e02a5cdeb9a54d3ea31991669a9eafee2ec /tests/unittests
parent4bde48bb2e32774533ac0d45485fa6109f3cb891 (diff)
downloadlibssh-6b7f275c32418a1a38b6f01466299469f9995f4c.tar.gz
libssh-6b7f275c32418a1a38b6f01466299469f9995f4c.tar.xz
libssh-6b7f275c32418a1a38b6f01466299469f9995f4c.zip
tests: Add torture_server_x11 test.
torture_server_x11 tests whether a libssh server can correctly parse an X11 request. Signed-off-by: Alan Dunn <amdunn@gmail.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Diffstat (limited to 'tests/unittests')
-rw-r--r--tests/unittests/CMakeLists.txt3
-rw-r--r--tests/unittests/torture_server_x11.c211
2 files changed, 214 insertions, 0 deletions
diff --git a/tests/unittests/CMakeLists.txt b/tests/unittests/CMakeLists.txt
index 38203991..a5c0d9bc 100644
--- a/tests/unittests/CMakeLists.txt
+++ b/tests/unittests/CMakeLists.txt
@@ -15,4 +15,7 @@ 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 AND Threads_FOUND)
+ add_cmocka_test(torture_server_x11 torture_server_x11.c ${TORTURE_LIBRARY})
+ endif (WITH_SERVER AND Threads_FOUND)
endif (UNIX AND NOT WIN32)
diff --git a/tests/unittests/torture_server_x11.c b/tests/unittests/torture_server_x11.c
new file mode 100644
index 00000000..29190869
--- /dev/null
+++ b/tests/unittests/torture_server_x11.c
@@ -0,0 +1,211 @@
+#define LIBSSH_STATIC
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include <libssh/libssh.h>
+#include "torture.h"
+
+#define TEST_SERVER_PORT 2222
+
+struct hostkey_state {
+ const char *hostkey;
+ char *hostkey_path;
+ int fd;
+};
+
+static void setup(void **state) {
+ struct hostkey_state *h;
+
+ h = malloc(sizeof(struct hostkey_state));
+ assert_non_null(h);
+
+ h->hostkey_path = strdup("/tmp/libssh_hostkey_XXXXXX");
+
+ h->fd = mkstemp(h->hostkey_path);
+ assert_return_code(h->fd, errno);
+ close(h->fd);
+
+ h->hostkey = torture_get_testkey(SSH_KEYTYPE_ECDSA, 512, 0);
+
+ torture_write_file(h->hostkey_path, h->hostkey);
+
+ *state = h;
+}
+
+static void teardown(void **state) {
+ struct hostkey_state *h = (struct hostkey_state *)*state;
+
+ unlink(h->hostkey);
+}
+
+/* For x11_screen_number, need something that is not equal to htonl
+ itself */
+static const uint32_t x11_screen_number = 1;
+
+static void *client_thread(void *arg) {
+ unsigned int test_port = TEST_SERVER_PORT;
+ int rc;
+ ssh_session session;
+ ssh_channel channel;
+
+ /* unused */
+ (void)arg;
+
+ session = torture_ssh_session("localhost",
+ &test_port,
+ "foo", "bar");
+ assert_non_null(session);
+
+ channel = ssh_channel_new(session);
+ assert_non_null(channel);
+
+ 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) {
+ struct hostkey_state *h = (struct hostkey_state *)*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
+ };
+
+ 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_SERVER_PORT, h->hostkey_path);
+ assert_non_null(sshbind);
+
+ /* Get client to connect */
+ rc = pthread_create(&client_pthread, NULL, client_thread, NULL);
+ assert_return_code(rc, errno);
+
+ 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);
+}
+
+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;
+}
+