Question

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?

Was it helpful?

Solution 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.

OTHER TIPS

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top