문제

Background
I am developing a module using the PAM specification and I would like to test one of the pam functions (specifically pam_sm_authenticate) to make sure that the helper functions that I have implement play nice with the specification.

The pam_sm_[authenticate, acct_mgmt...etc.] series functions all take the same parameters.

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

I am having trouble mocking struct pam_handle, but need to as this structure will contain information vital to authenticating users.

Using PAM header information from the internet (pam_appl.h and pam_private.h) I have attempted to use the structure directly as pam_handle_t normalPamh; and populate it myself, but when I try to I get the following error:

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

I would really like to test my module to make sure that I haven't done anything that will cause segmentation faults and that I'm using memory within reasonable limits, but I am having trouble doing so because I can't mock this structure.

Question
How do I mock the pam_handle_t struct?

도움이 되었습니까?

해결책 2

I found some open source software that does exactly what I need it to.

It's called pamtester and it compiles on a number of *nix systems.

Once it's installed you can run it like:

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

It will take care of everything else that is needed to establish user credentials.

I wanted to use it in automated testing through C, so I wrapped a lot of the calls in a bash script where I could specify input I wanted to change like user and ruser.

The problem is passwords need to be entered when the program asks for it. I solved this using popen in my C source.

Here is an example of what I did for reference. It's not perfect, but for anyone else that might run into a similar situation this might serve as a starting point.

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

More information about the use of this program is available by downloading the source and reading it's README file.

다른 팁

It sounds like, the headers you're referring to declare the pam-handle type along the lines of:

typedef struct pam_handle pam_handle_t;

However the actual definition of the struct pam_handle is NOT part of the headers you describe. To mock it, you would need to specify the actual structure before writing any code that code accessing the struct pam_handle members (whatever they are). I.E:

In your interface definitions, you "post-pone" the structure definition, by using handle only:

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

In your test code, where you modify handle-members for testing purposes, you have to define it, e.g.

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

Update: The structure seems to be defined in libpam/pam_private.h, so including that file in your test-code ought to be sufficient. Note the header is "private", so your actual implementation should of course NOT use this.

Hope that helps!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top