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?
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);
}