Proper use of pam_get_item()

Jason Gerfen jason.gerfen at scl.utah.edu
Thu Nov 18 19:21:38 UTC 2004


Ok, nevermind list... I found a way to do it.  For anyone that is 
running into the same problem I was trying to obtain the username & 
password from the PAM libraries from withing a shared object or module 
here is a way:

compile with:
%>  gcc -fPIC -o pam_<name_of_file>.o -c pam_<name_of_file>.c
%>  ld --shared -x -lc -o pam_<name_of_file>.so pam_<name_of_file>.o -lpam

pam_<name_of_file>.c source

/* PAM includes */
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <security/pam_appl.h>

/* PAM definitions */
#define PAM_SM_ACCOUNT
#define PAM_SM_AUTH
#define PAM_SM_PASSWORD
#define PAM_SM_SESSION

/* PAM user data struct */
typedef struct usrData * udataptr;
struct usrData {
    const char * usrname;
    char * password;
} localUser;

/* Log events to syslog */
static void _pam_log(int err, const char *format, ...)
{
    va_list  args;

    va_start(args, format);
    openlog("PAM-<Name_of_module>", LOG_PID | LOG_NDELAY, LOG_SYSLOG);
    vsyslog(err, format, args);
    va_end(args);
    closelog();
}

/* These two functions re-used from pam_pwdfile.c who re-used them from 
pam_unix.c */
int converse( pam_handle_t *pamh,
                      int nargs,
                      struct pam_message **message,
                      struct pam_response **response )
{
    int retval;
    struct pam_conv *conv;

// Begin speaking with PAM, flaged with the PAM_CONV argument
    retval = pam_get_item(pamh, PAM_CONV,  (const void **) &conv ) ;
    if( retval == PAM_SUCCESS ) {
        retval = conv->conv( nargs,
                             ( const struct pam_message ** ) message,
                             response,
                             conv->appdata_ptr );
    }
    return retval;
}

int _set_auth_tok( pam_handle_t *pamh,
                   int flags, int argc,
                   const char **argv )
{
    int retval;
    char *p;

    struct pam_message msg[1],*pmsg[1];
    struct pam_response *resp;

    /* set up conversation call */

    pmsg[0] = &msg[0];
    msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
    msg[0].msg = "Password: ";
    resp = NULL;

// Call the converse function so we know we are speaking with PAM
    if( ( retval = converse( pamh, 1 , pmsg, &resp ) ) != PAM_SUCCESS )
        return retval;

    if( resp )
    {
        if( ( flags & PAM_DISALLOW_NULL_AUTHTOK ) &&
             resp[0].resp == NULL )
        {
            free( resp );
            return PAM_AUTH_ERR;
        }

        p = resp[ 0 ].resp;

        resp[ 0 ].resp = NULL;
}
    else
        return PAM_CONV_ERR;

    free( resp );
// Set our authentication arguments to retrieve username & passsword.
    pam_set_item( pamh, PAM_AUTHTOK, p );
    return PAM_SUCCESS;
}

/* Handle our authentication process */
PAM_EXTERN
int pam_sm_authenticate( pam_handle_t *pamh, int flags, int argc,
                         const char **argv )
{
    int retval, i;
    char user[15];
    const void ** password;

    struct pam_conv *conv = NULL;
    struct pam_message message;
    const struct pam_message *msg;
    struct pam_response **response;

/* Get our username from PAM */
    if( ( retval = pam_get_user( pamh, user, "PAM_RemoteKRB5 login: " ) 
!= PAM_SUCCESS ) ) {
        _pam_log( LOG_ERR, "Error: %s", pam_strerror( pamh, retval ) );
        return 1;
    } else {
        _pam_log( LOG_ERR, "User: %s", user );
    }

    /* PAM conversion stuff just to get to the bloody password */
    /* get password - code from pam_unix_auth.c */
    pam_get_item( pamh, PAM_AUTHTOK, ( void * ) password ) );
    if( !password ) {
// next we call our converse() function from within the _set_auth_tok() 
function
        retval = _set_auth_tok( pamh, flags, argc, argv );
        if( retval != PAM_SUCCESS ) {
            return retval;
        }
    }
    pam_get_item( pamh, PAM_AUTHTOK, ( void * ) password );

    if( ( retval = pam_get_item( pamh, PAM_AUTHTOK, ( void * ) password 
) ) != PAM_SUCCESS ) {
        _pam_log( LOG_ERR, "Error: %s", pam_strerror( pamh, retval ) );
        return retval;
    }
}

And there you go... you should have the username & password stored in 
user & password I hope this saves some people a whole lotta time.

[/snip]

-- 
Jason Gerfen
jason.gerfen at scl.utah.edu

"And remember... If the ladies
 don't find you handsome, they
 should at least find you handy..."
             ~The Red Green show




More information about the Pam-list mailing list