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 created this task.Mon, Oct 28, 8:27 AM
slydder updated the task description. (Show Details)
slydder updated the task description. (Show Details)