mirror of
https://github.com/libssh2/libssh2.git
synced 2025-12-24 19:37:49 +03:00
tests: retry KEX failures when using the WinCNG backend
Twice. This tests are flaky and we haven't figured out why. In the meantime use this workaround to test and log these issues, but also ensure that CI run aren't flagged red because of it. Also: - kex: add debug message when hostkey `sig_verify` fails, to help tracking WinCNG KEX failures. - test_ssh2: also add retry logic. I'm not quite sure this is correct. Please let me know. - session_fixture: bump up `src_path` slots to fit retries and show message when hitting the limit. - session_fixture: clear `kbd_password` static variable after use. - session_fixture: close and deinit socket after use. - session_fixture: deinit libssh2 after use. Ref: #804 #846 #979 #1012 #1015 Cherry-picked from #1017 Closes #1023
This commit is contained in:
16
src/kex.c
16
src/kex.c
@@ -352,6 +352,7 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session,
|
||||
/* Wait for KEX reply */
|
||||
struct string_buf buf;
|
||||
size_t host_key_len;
|
||||
int err;
|
||||
|
||||
rc = _libssh2_packet_require(session, packet_type_reply,
|
||||
&exchange_state->s_packet,
|
||||
@@ -619,10 +620,17 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session,
|
||||
_libssh2_sha_algo_ctx_final(sha_algo_value, exchange_hash_ctx,
|
||||
exchange_state->h_sig_comp);
|
||||
|
||||
if(session->hostkey->
|
||||
sig_verify(session, exchange_state->h_sig,
|
||||
exchange_state->h_sig_len, exchange_state->h_sig_comp,
|
||||
digest_len, &session->server_hostkey_abstract)) {
|
||||
err = session->hostkey->sig_verify(session,
|
||||
exchange_state->h_sig,
|
||||
exchange_state->h_sig_len,
|
||||
exchange_state->h_sig_comp,
|
||||
digest_len,
|
||||
&session->server_hostkey_abstract);
|
||||
|
||||
if(err) {
|
||||
_libssh2_debug((session, LIBSSH2_TRACE_KEX,
|
||||
"Failed hostkey sig_verify(): %s: %d",
|
||||
session->hostkey->name, err));
|
||||
ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
|
||||
"Unable to verify hostkey signature "
|
||||
"DH-SHA");
|
||||
|
||||
@@ -420,6 +420,18 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void close_socket_to_container(libssh2_socket_t sock)
|
||||
{
|
||||
if(sock != LIBSSH2_INVALID_SOCKET) {
|
||||
shutdown(sock, 2 /* SHUT_RDWR */);
|
||||
#ifdef WIN32
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static char *running_container_id = NULL;
|
||||
|
||||
int start_openssh_fixture(void)
|
||||
@@ -463,3 +475,8 @@ libssh2_socket_t open_socket_to_openssh_server(void)
|
||||
{
|
||||
return open_socket_to_container(running_container_id);
|
||||
}
|
||||
|
||||
void close_socket_to_openssh_server(libssh2_socket_t sock)
|
||||
{
|
||||
close_socket_to_container(sock);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
int start_openssh_fixture(void);
|
||||
void stop_openssh_fixture(void);
|
||||
libssh2_socket_t open_socket_to_openssh_server(void);
|
||||
void close_socket_to_openssh_server(libssh2_socket_t sock);
|
||||
int openssh_fixture_have_docker(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,16 +39,39 @@
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int exit_code = 1;
|
||||
int skipped;
|
||||
LIBSSH2_SESSION *session = start_session_fixture(&skipped);
|
||||
if(session) {
|
||||
exit_code = (test(session) == 0) ? 0 : 1;
|
||||
}
|
||||
else if(skipped) {
|
||||
fprintf(stderr, "Test skipped.\n");
|
||||
exit_code = 0;
|
||||
}
|
||||
stop_session_fixture();
|
||||
int exit_code;
|
||||
int retries = 0, retry = 0;
|
||||
|
||||
#ifdef LIBSSH2_WINCNG
|
||||
/* FIXME: Retry tests with WinCNG due to flakiness in hostkey
|
||||
verification: https://github.com/libssh2/libssh2/issues/804 */
|
||||
retries += 2;
|
||||
#endif
|
||||
|
||||
do {
|
||||
int skipped, rc;
|
||||
LIBSSH2_SESSION *session = start_session_fixture(&skipped, &rc);
|
||||
if(session) {
|
||||
exit_code = (test(session) == 0) ? 0 : 1;
|
||||
}
|
||||
else if(skipped) {
|
||||
fprintf(stderr, "Test skipped.\n");
|
||||
exit_code = 0;
|
||||
}
|
||||
else {
|
||||
exit_code = 1;
|
||||
}
|
||||
stop_session_fixture();
|
||||
if(exit_code == 0 ||
|
||||
#ifdef LIBSSH2_WINCNG
|
||||
rc != LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE ||
|
||||
#endif
|
||||
++retry > retries) {
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "Test failed (%d)! Retrying... %d / %d\n",
|
||||
rc, retry, retries);
|
||||
} while(1);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
@@ -65,16 +65,16 @@ static int connect_to_server(void)
|
||||
int rc;
|
||||
connected_socket = open_socket_to_openssh_server();
|
||||
if(connected_socket == LIBSSH2_INVALID_SOCKET) {
|
||||
return -1;
|
||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||
}
|
||||
|
||||
rc = libssh2_session_handshake(connected_session, connected_socket);
|
||||
if(rc) {
|
||||
print_last_session_error("libssh2_session_handshake");
|
||||
return -1;
|
||||
return libssh2_session_last_errno(connected_session);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return LIBSSH2_ERROR_NONE;
|
||||
}
|
||||
|
||||
static void setup_fixture_workdir(void)
|
||||
@@ -117,7 +117,7 @@ static char const *skip_crypt[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
LIBSSH2_SESSION *start_session_fixture(int *skipped)
|
||||
LIBSSH2_SESSION *start_session_fixture(int *skipped, int *err)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -125,6 +125,7 @@ LIBSSH2_SESSION *start_session_fixture(int *skipped)
|
||||
const char *mac = getenv("FIXTURE_TEST_MAC");
|
||||
|
||||
*skipped = 0;
|
||||
*err = LIBSSH2_ERROR_NONE;
|
||||
|
||||
if(crypt) {
|
||||
char const * const *cr;
|
||||
@@ -192,7 +193,8 @@ LIBSSH2_SESSION *start_session_fixture(int *skipped)
|
||||
libssh2_session_set_blocking(connected_session, 1);
|
||||
|
||||
rc = connect_to_server();
|
||||
if(rc) {
|
||||
if(rc != LIBSSH2_ERROR_NONE) {
|
||||
*err = rc;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -221,13 +223,17 @@ void stop_session_fixture(void)
|
||||
if(connected_session) {
|
||||
libssh2_session_disconnect(connected_session, "test ended");
|
||||
libssh2_session_free(connected_session);
|
||||
shutdown(connected_socket, 2);
|
||||
connected_session = NULL;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Cannot stop session - none started\n");
|
||||
}
|
||||
|
||||
close_socket_to_openssh_server(connected_socket);
|
||||
connected_socket = LIBSSH2_INVALID_SOCKET;
|
||||
|
||||
libssh2_exit();
|
||||
|
||||
stop_openssh_fixture();
|
||||
}
|
||||
|
||||
@@ -236,7 +242,7 @@ void stop_session_fixture(void)
|
||||
* variable, if found. It does so in a way that avoids leaking memory by using
|
||||
* a fixed number of static buffers.
|
||||
*/
|
||||
#define NUMPATHS 3
|
||||
#define NUMPATHS 32
|
||||
const char *srcdir_path(const char *file)
|
||||
{
|
||||
#ifdef WIN32
|
||||
@@ -246,6 +252,9 @@ const char *srcdir_path(const char *file)
|
||||
#endif
|
||||
static int curpath;
|
||||
char *p = getenv("srcdir");
|
||||
if(curpath >= NUMPATHS) {
|
||||
fprintf(stderr, "srcdir_path ran out of filepath slots.\n");
|
||||
}
|
||||
assert(curpath < NUMPATHS);
|
||||
if(p) {
|
||||
/* Ensure the final string is nul-terminated on Windows */
|
||||
@@ -315,6 +324,8 @@ int test_auth_keyboard(LIBSSH2_SESSION *session, int flags,
|
||||
(unsigned int)strlen(username),
|
||||
kbd_callback);
|
||||
|
||||
kbd_password = NULL;
|
||||
|
||||
if((flags & TEST_AUTH_SHOULDFAIL) != 0) {
|
||||
if(rc == 0) {
|
||||
fprintf(stderr, "Keyboard-interactive auth succeeded "
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
#include "libssh2_priv.h"
|
||||
|
||||
LIBSSH2_SESSION *start_session_fixture(int *skipped);
|
||||
LIBSSH2_SESSION *start_session_fixture(int *skipped, int *err);
|
||||
void stop_session_fixture(void);
|
||||
void print_last_session_error(const char *function);
|
||||
const char *srcdir_path(const char *file);
|
||||
|
||||
@@ -133,10 +133,28 @@ int main(int argc, char *argv[])
|
||||
|
||||
libssh2_session_set_blocking(session, 1);
|
||||
|
||||
rc = libssh2_session_handshake(session, sock);
|
||||
if(rc) {
|
||||
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
|
||||
goto shutdown;
|
||||
{
|
||||
int retries = 0, retry = 0;
|
||||
#ifdef LIBSSH2_WINCNG
|
||||
/* FIXME: Retry tests with WinCNG due to flakiness in hostkey
|
||||
verification: https://github.com/libssh2/libssh2/issues/804 */
|
||||
retries += 2;
|
||||
#endif
|
||||
do {
|
||||
rc = libssh2_session_handshake(session, sock);
|
||||
if(rc == 0) {
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
|
||||
if(
|
||||
#ifdef LIBSSH2_WINCNG
|
||||
rc != LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE ||
|
||||
#endif
|
||||
++retry > retries) {
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "Retrying... %d / %d\n", retry, retries);
|
||||
} while(1);
|
||||
}
|
||||
|
||||
/* At this point we have not yet authenticated. The first thing to do
|
||||
|
||||
Reference in New Issue
Block a user