diff options
author | Alan Dunn <amdunn@gmail.com> | 2014-04-19 14:20:00 -0500 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2015-01-20 20:23:19 +0100 |
commit | 6b7f275c32418a1a38b6f01466299469f9995f4c (patch) | |
tree | d7a19e02a5cdeb9a54d3ea31991669a9eafee2ec /tests/unittests | |
parent | 4bde48bb2e32774533ac0d45485fa6109f3cb891 (diff) | |
download | libssh-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.txt | 3 | ||||
-rw-r--r-- | tests/unittests/torture_server_x11.c | 211 |
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; +} + |