diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3fb68738..ca9f89c5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,6 +31,9 @@ add_library(${TORTURE_LIBRARY} torture_pki.c torture_cmocka.c) target_link_libraries(${TORTURE_LIBRARY} ${TORTURE_LINK_LIBRARIES}) +target_compile_options(${TORTURE_LIBRARY} PRIVATE + -DSSH_PING_EXECUTABLE="${CMAKE_CURRENT_BINARY_DIR}/ssh_ping" +) if (ARGP_LIBRARY) target_link_libraries(${TORTURE_LIBRARY} @@ -87,6 +90,11 @@ if (CLIENT_TESTING) chroot_wrapper ) + # ssh_ping + add_executable(ssh_ping ssh_ping.c) + target_compile_options(ssh_ping PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) + target_link_libraries(ssh_ping ${LIBSSH_SHARED_LIBRARY}) + # homedir will be used in passwd set(HOMEDIR ${CMAKE_CURRENT_BINARY_DIR}/home) diff --git a/tests/ssh_ping.c b/tests/ssh_ping.c new file mode 100644 index 00000000..c9b5dad5 --- /dev/null +++ b/tests/ssh_ping.c @@ -0,0 +1,67 @@ +/* ssh_ping.c */ +/* +Copyright 2018 Red Hat, Inc + +Author: Jakub Jelen + +This file is part of the SSH Library + +You are free to copy this file, modify it in any way, consider it being public +domain. This does not apply to the rest of the library though, but it is +allowed to cut-and-paste working code from this file to any license of +program. +The goal is to show the API in action. It's not a reference on how terminal +clients must be made or how a client should react. +*/ + +#include +#include +#include + +int main(int argc, char **argv) +{ + const char *banner = NULL; + ssh_session session = NULL; + int rc = 1; + + if (argc < 1 || argv[1] == NULL) { + fprintf(stderr, "Error: Need an argument (hostname)\n"); + goto out; + } + + session = ssh_new(); + if (session == NULL) { + goto out; + } + + rc = ssh_options_set(session, SSH_OPTIONS_HOST, argv[1]); + if (rc < 0) { + goto out; + } + + /* The automatic username is not available under uid wrapper */ + rc = ssh_options_set(session, SSH_OPTIONS_USER, "ping"); + if (rc < 0) { + goto out; + } + + rc = ssh_connect(session); + if (rc != SSH_OK) { + fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session)); + goto out; + } + + banner = ssh_get_serverbanner(session); + if (banner == NULL) { + fprintf(stderr, "Did not receive SSH banner\n"); + goto out; + } + + printf("%s", banner); + rc = 0; + +out: + ssh_free(session); + return rc; +} + diff --git a/tests/torture.c b/tests/torture.c index 95da3c67..23b1d1fd 100644 --- a/tests/torture.c +++ b/tests/torture.c @@ -42,6 +42,7 @@ #include "torture.h" #include "torture_key.h" +#include "libssh/misc.h" /* for pattern matching */ #include "match.c" @@ -696,6 +697,24 @@ static void torture_setup_create_sshd_config(void **state) torture_write_file(s->srv_config, sshd_config); } +static int torture_wait_for_daemon(unsigned int seconds) +{ + struct ssh_timestamp start; + int rc; + + ssh_timestamp_init(&start); + + while (!ssh_timeout_elapsed(&start, seconds * 1000)) { + rc = system(SSH_PING_EXECUTABLE " " TORTURE_SSH_SERVER); + if (rc == 0) { + return 0; + } + /* Wait 200 ms before retrying */ + usleep(200 * 1000); + } + return 1; +} + void torture_setup_sshd_server(void **state) { struct torture_state *s; @@ -718,11 +737,12 @@ void torture_setup_sshd_server(void **state) rc = system(sshd_start_cmd); assert_return_code(rc, errno); - /* Give the process 500ms time to initialize and start */ - usleep(500 * 1000); - setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1); unsetenv("PAM_WRAPPER"); + + /* Wait until the sshd is ready to accept connections */ + rc = torture_wait_for_daemon(5); + assert_int_equal(rc, 0); } void torture_teardown_socket_dir(void **state)