如何模拟pam_handle结构

时间:2014-04-16 07:17:40

标签: c unit-testing struct mocking pam

背景
我正在使用PAM规范开发一个模块,我想测试一个pam函数(特别是pam_sm_authenticate),以确保我实现的辅助函数与规范一致。

pam_sm_ [authenticate,acct_mgmt ......等]系列函数都采用相同的参数。

int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)  

我在模拟struct pam_handle时遇到问题,但需要这个结构包含对验证用户至关重要的信息。

使用来自互联网的PAM标题信息(pam_appl.hpam_private.h)我试图直接将结构用作pam_handle_t normalPamh;并自己填充,但是当我尝试获取以下错误:

error: aggregate 'pam_handle_t normalPamh' has incomplete type and cannot be defined  

我真的想测试我的模块,以确保我没有做任何会导致分段错误的事情,并且我在合理范围内使用内存,但我这样做是因为我无法模拟这个结构。

问题
我如何模拟pam_handle_t结构?

2 个答案:

答案 0 :(得分:1)

听起来,你所指的标题声明了pam-handle类型:

typedef struct pam_handle pam_handle_t;

但是struct pam_handle的实际定义不是您描述的标题的一部分。要模拟它,您需要在编写代码访问struct pam_handle成员的任何代码(无论它们是什么)之前指定实际结构。即:

在您的界面定义中,您只使用句柄“结束”结构定义:

int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv);

在您的测试代码中,为了测试目的而修改句柄成员,您必须对其进行定义,例如

#include "interface_to_be_tested.h"
// declare the pam_handle
struct pam_handle 
{
  // provide definition of struct-members here
};
...
// Test code here

更新:结构似乎是在libpam / pam_private.h中定义的,因此在测试代码中包含该文件应该足够了。请注意标题是“私有的”,因此您的实际实现当然不应该使用它。

希望有所帮助!

答案 1 :(得分:0)

我发现了一些完全符合我需要的开源软件。

它被称为pamtester,它在许多* nix系统上编译。

安装完成后,您可以像以下一样运行它:

pamtester -v -I user=test01@test.com -I rhost=192.168.2.150 dovecot test01@test.com "authenticate(PAM_ESTABLISH_CRED)"  

它将处理建立用户凭据所需的所有其他内容。

我想通过C在自动化测试中使用它,所以我在bash脚本中包含了很多调用,我可以在其中指定我想要改变的输入,如user和ruser。

问题是当程序要求输入密码时需要输入密码。我在C源代码中使用popen解决了这个问题。

以下是我做的参考示例。这并不完美,但对于可能遇到类似情况的其他人来说,这可能是一个起点。

int testPamSmAuthenticate(char * username, char * hostname, char * password) {
    //--------------------------------------
    // declarations
    //--------------------------------------
    char testCommand[512];
    char passwordPromptResponse[128];
    char resultLine[3];
    FILE * testFile;

    //--------------------------------------
    // declarations
    //--------------------------------------
    sprintf(testCommand, "%s %s %s", PAM_TEST_SCRIPT_PATH, username, hostname);
    sprintf(passwordPromptResponse, "%s\n", password);

    //--------------------------------------
    // run the command and enter a password
    //--------------------------------------
    if (!(testFile = popen(testCommand, "w"))){
        return(1);
    }
    fputs(passwordPromptResponse, testFile);
    pclose(testFile);

    //--------------------------------------
    // get the output of the command from
    // the text file written by bash
    //--------------------------------------
    testFile = fopen(PAM_TEST_RESULT_PATH, "r");
    while (fgets(resultLine, sizeof(resultLine), testFile)) {
        printf("%s", resultLine); 
    }
    fclose(testFile);

    //--------------------------------------
    // evaulate and return a code
    // 1 == authentication good
    // 0 == authentication bad
    //--------------------------------------
    if (strchr(resultLine, '0')) {
        printf("Authentication successful!\n");
        return(1);
    }
    printf("Authentication failed!\n");
    return(0);
}  

有关使用此程序的更多信息,请下载源代码并阅读其自述文件。