You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

问题原因

  1. 会话状态的误解:ssh_get_status返回的0对应SSH_SESSION_STATE_CONNECTED,仅表示TCP连接和SSH协议握手完成,和用户认证是否成功无关,你混淆了连接状态与认证状态。
  2. 认证判断逻辑错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 16:24:51