Page MenuHomePhabricator

Reusing a session results in timeout at user_auth_password
Open, Needs TriagePublic

Description

If the ssh_session instance is reused after a ssh_disconnect call the next ssh_userauth_password will fail with error SSH_AUTH_AGAIN after a timeout (even when blocking mode is used).

Tested with: libssh 0.9.0

Sample app:

#include <stdio.h>
#include <libssh/libssh.h>

// build: gcc -g -lssh ssh-session-reuse.c -o ssh-session-reuse
int main(int argc, char *argv[])
{
    long timeout = 10;
    const char *hostname = "localhost";
    const char *user = "demo";
    const char *password = "12345";
    int rc;

    rc = ssh_init();
    if (rc != 0) {
        return 1;
    }

    ssh_session session = ssh_new();

    if (!session) {
        goto cleanup;
    }

    // explicitly set blocking mode
    ssh_set_blocking(session, 1);
    // Set hostname
    if (ssh_options_set(session, SSH_OPTIONS_HOST, hostname) < 0)
        goto cleanup;

    // Set timeout
    if (ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &timeout) < 0)
        goto cleanup;

    if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
        goto cleanup;
    }

    // first try
    rc = ssh_connect(session);
    if (rc != SSH_OK) {
        printf("Connection error: %d - %s\n", rc, ssh_get_error(session));
        goto cleanup;
    }
    rc = ssh_userauth_password(session, NULL, password);
    if (rc == SSH_AUTH_SUCCESS) {
        printf("Success\n");

    } else {
        printf("Failed authenticating: %d - %s\n", rc, ssh_get_error(session));
    }

    ssh_disconnect(session);

    // second try
    rc = ssh_connect(session);
    if (rc != SSH_OK) {
        printf("Connection error: %d - %s\n", rc, ssh_get_error(session));
        goto cleanup;
    }
    rc = ssh_userauth_password(session, NULL, password);
    // rc will be SSH_AUTH_AGAIN
    if (rc == SSH_AUTH_SUCCESS) {
        printf("Success\n");

    } else {
        printf("Failed authenticating: %d - %s\n", rc, ssh_get_error(session));
    }

    ssh_disconnect(session);

cleanup:
    ssh_free(session);

    ssh_finalize();
    return 0;
}

Hint: after a short debugging it seams that struct auth from struct ssh_session_struct is not reset at ssh_disconnect.
Adding the following to ssh_disconnect seams that fixes the issue:

session->auth.service_state = SSH_AUTH_SERVICE_NONE;
session->auth.state = SSH_AUTH_SERVICE_NONE;

Event Timeline

slydder updated the task description. (Show Details)
slydder updated the task description. (Show Details)

AFAIK, this was fixed with T194. Can you recheck if you can still reproduce the issue with latest release/master?

Hello @slydder , could you confirm if you were able to reproduce it with the latest release/master? if not, we could close this. Thank you.