From 6b7f275c32418a1a38b6f01466299469f9995f4c Mon Sep 17 00:00:00 2001 From: Alan Dunn Date: Sat, 19 Apr 2014 14:20:00 -0500 Subject: 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 Reviewed-by: Andreas Schneider --- tests/unittests/CMakeLists.txt | 3 + tests/unittests/torture_server_x11.c | 211 +++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 tests/unittests/torture_server_x11.c (limited to 'tests') 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 +#include +#include + +#include +#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; +} + -- cgit