clibssh

SSH login requests time out instead of receiving replies from a server


Here's a program that's supposed to test if a login delay when wrong passwords are given, set up on a target server is respected:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <libssh/libssh.h>

#define BILLION 1000000000.0

int main(void) {
    struct timespec start, finish;
    time_t t = time(NULL);

    ssh_session session;

    int rc;
    int session_status;
    session = ssh_new();

    const char *host = "127.0.0.1";
    const char *port = "22";
    const char *username = "user";
    const char *password = "pass";

    char *reply;

    ssh_options_set(session, SSH_OPTIONS_HOST, host);
    ssh_options_set(session, SSH_OPTIONS_PORT_STR, port);
    ssh_options_set(session, SSH_OPTIONS_USER, username);

    session_status = ssh_get_status(session);
    printf("Session status: %d\n", session_status);

    for (int i = 0; i < 4; ++i) {
        clock_gettime(CLOCK_REALTIME, &start);
        rc = ssh_connect(session);

        if (rc != SSH_OK) {
            fprintf(stderr, "Error connecting to %s: %s\n", host, ssh_get_error(session));
            ssh_free(session);
            exit(-1);
        }

        if (ssh_userauth_password(session, NULL, password) == SSH_AUTH_SUCCESS) {
            reply = "Authentication succeeded with incorrect password.";
        }
        else {
            reply = "Authentication failed with incorrect password.";
            fprintf(stderr, "Error authenticating with incorrect password: %s\n", ssh_get_error(session));
        }
        clock_gettime(CLOCK_REALTIME, &finish);

        double time_spent = (finish.tv_sec - start.tv_sec) + (finish.tv_nsec - start.tv_nsec) / BILLION;

        struct tm tm = *localtime(&start.tv_sec);
        printf("[%d-%02d-%02d %02d:%02d:%02d] Status:%s ",
                tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, reply);
        printf("Elapsed time: %.4f seconds.\n", time_spent);

        ssh_disconnect(session);
    }

    ssh_free(session);

    return (0);
}

However, I don't understand replies coming from the server: the delay in this specific case was set up to 30s, while the output is as follows:

Session status: 0
Error authenticating with incorrect password: Access denied for 'password'. Authentication that can continue: publickey,password
[2024-01-11 16:27:17] Status:Authentication failed with incorrect password. Elapsed time: 64.8060 seconds.
Error authenticating with incorrect password: Socket error: disconnected
[2024-01-11 16:28:22] Status:Authentication failed with incorrect password. Elapsed time: 120.0131 seconds.
Error authenticating with incorrect password: Socket error: disconnected
[2024-01-11 16:30:22] Status:Authentication failed with incorrect password. Elapsed time: 120.0148 seconds.
Error authenticating with incorrect password: Socket error: disconnected
[2024-01-11 16:32:22] Status:Authentication failed with incorrect password. Elapsed time: 120.0143 seconds.

It seems like the last three requests were terminated due to a timeout and only the first one got the response I expected.

How to refactor this program to actually measure time it takes to get another chance to provide username and password?


Solution

  • I wouldn't connect then disconnect, just connect and try authenticating with the same connection (just move connect and disconnect call outside the loop)

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <unistd.h>
    #include <libssh/libssh.h>
    
    #define BILLION 1000000000.0
    
    int main(void) {
        struct timespec start, finish;
        time_t t = time(NULL);
    
        ssh_session session;
    
        int rc;
        int session_status;
        session = ssh_new();
    
        const char *host = "127.0.0.1";
        const char *port = "22";
        const char *username = "user";
        const char *password = "pass";
    
        char *reply;
    
        ssh_options_set(session, SSH_OPTIONS_HOST, host);
        ssh_options_set(session, SSH_OPTIONS_PORT_STR, port);
        ssh_options_set(session, SSH_OPTIONS_USER, username);
    
        session_status = ssh_get_status(session);
        printf("Session status: %d\n", session_status);
    
        rc = ssh_connect(session); // <==
        for (int i = 0; i < 4; ++i) {
            clock_gettime(CLOCK_REALTIME, &start);
    
    
            if (rc != SSH_OK) {
                fprintf(stderr, "Error connecting to %s: %s\n", host, ssh_get_error(session));
                ssh_free(session);
                exit(-1);
            }
    
            if (ssh_userauth_password(session, NULL, password) == SSH_AUTH_SUCCESS) {
                reply = "Authentication succeeded with incorrect password.";
            }
            else {
                reply = "Authentication failed with incorrect password.";
                fprintf(stderr, "Error authenticating with incorrect password: %s\n", ssh_get_error(session));
            }
            clock_gettime(CLOCK_REALTIME, &finish);
    
            double time_spent = (finish.tv_sec - start.tv_sec) + (finish.tv_nsec - start.tv_nsec) / BILLION;
    
            struct tm tm = *localtime(&start.tv_sec);
            printf("[%d-%02d-%02d %02d:%02d:%02d] Status:%s ",
                    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, reply);
            printf("Elapsed time: %.4f seconds.\n", time_spent);
    
       
        }
        ssh_disconnect(session);// <==
        ssh_free(session);
    
        return (0);
    }