SSH会话状态异常求助:PAM登录延迟测试程序问题排查
问题排查:libssh程序错误识别SSH认证状态
我配置了PAM实现失败登录后延迟显示新登录提示,随后用基于libssh的C程序测试该行为——程序尝试连接远程服务器并测量登录提示间隔时间。但程序输出显示会话状态为0(成功),且错误的用户名密码被判定为“认证成功”,这和实际情况不符(服务器无对应用户,也没交换密钥)。需要排查原因,让程序能返回正确的SSH会话状态(比如连接超时、连接拒绝,和控制台操作一致)。
测试代码
#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; ssh_session session; int rc; int session_status; const char *server_banner; session = ssh_new(); const char *host = "10.11.12.13"; const char *username = "baduser"; const char *password = "badpass"; ssh_options_set(session, SSH_OPTIONS_HOST, host); ssh_options_set(session, SSH_OPTIONS_USER, username); clock_gettime(CLOCK_REALTIME, &start); rc = ssh_connect(session); session_status = ssh_get_status(session); printf("Session status: %d\n", session_status); server_banner = ssh_get_serverbanner(session); printf("Server banner: %s\n", server_banner); if (rc != SSH_OK) { fprintf(stderr, "Error connecting to %s: %s\n", host, ssh_get_error(session)); ssh_free(session); exit(-1); } printf("Return Code is: %d\n", rc); if (ssh_userauth_password(session, NULL, password) != SSH_AUTH_ERROR) { fprintf(stderr, "Authentication succeeded with incorrect password.\n"); } else { fprintf(stderr, "Authentication failed with incorrect password.\n"); } clock_gettime(CLOCK_REALTIME, &finish); ssh_disconnect(session); ssh_free(session); double time_spent = (finish.tv_sec - start.tv_sec) + (finish.tv_nsec - start.tv_nsec) / BILLION; printf("Elapsed time: %.4f seconds.\n", time_spent); return (0); }
程序输出
Session status: 0 Server banner: SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.8 Return Code is: 0 Authentication succeeded with incorrect password. Elapsed time: 2.2801 seconds.
问题原因
- 会话状态的误解:
ssh_get_status返回的0对应SSH_SESSION_STATE_CONNECTED,仅表示TCP连接和SSH协议握手完成,和用户认证是否成功无关,你混淆了连接状态与认证状态。 - 认证判断逻辑错误:
ssh_userauth_password的返回值不止SSH_AUTH_ERROR,还包括SSH_AUTH_SUCCESS、SSH_AUTH_PARTIAL等。你只判断了“不等于SSH_AUTH_ERROR”就认定认证成功,当服务器支持多种认证方式、密码认证失败但还有其他方式可用时,会返回SSH_AUTH_PARTIAL,此时代码会误判为成功。
修复方案
1. 修正认证状态判断
把认证逻辑改为精确判断SSH_AUTH_SUCCESS,同时输出详细错误信息:
int auth_rc = ssh_userauth_password(session, NULL, password); if (auth_rc == SSH_AUTH_SUCCESS) { fprintf(stderr, "Authentication succeeded.\n"); } else if (auth_rc == SSH_AUTH_ERROR) { fprintf(stderr, "Authentication failed: %s\n", ssh_get_error(session)); } else { fprintf(stderr, "Authentication partial, other methods available.\n"); }
2. 明确连接与认证的区别
ssh_connect返回SSH_OK仅代表底层连接建立,不代表用户已通过认证。认证状态必须通过ssh_userauth_password的返回值来判断。
3. 修复后的完整代码
#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; ssh_session session; int rc; int session_status; const char *server_banner; session = ssh_new(); const char *host = "10.11.12.13"; const char *username = "baduser"; const char *password = "badpass"; ssh_options_set(session, SSH_OPTIONS_HOST, host); ssh_options_set(session, SSH_OPTIONS_USER, username); clock_gettime(CLOCK_REALTIME, &start); rc = ssh_connect(session); session_status = ssh_get_status(session); printf("Session status: %d (0 = SSH_SESSION_STATE_CONNECTED)\n", session_status); server_banner = ssh_get_serverbanner(session); printf("Server banner: %s\n", server_banner); if (rc != SSH_OK) { fprintf(stderr, "Error connecting to %s: %s\n", host, ssh_get_error(session)); ssh_free(session); exit(-1); } printf("Connection return code: %d (SSH_OK)\n", rc); int auth_rc = ssh_userauth_password(session, NULL, password); if (auth_rc == SSH_AUTH_SUCCESS) { fprintf(stderr, "Authentication succeeded.\n"); } else if (auth_rc == SSH_AUTH_ERROR) { fprintf(stderr, "Authentication failed: %s\n", ssh_get_error(session)); } else { fprintf(stderr, "Authentication partial, other authentication methods available.\n"); } clock_gettime(CLOCK_REALTIME, &finish); ssh_disconnect(session); ssh_free(session); double time_spent = (finish.tv_sec - start.tv_sec) + (finish.tv_nsec - start.tv_nsec) / BILLION; printf("Elapsed time: %.4f seconds.\n", time_spent); return (0); }
内容的提问来源于stack exchange,提问作者AbreQueVoy
相关产品推荐
相关产品推荐

