Pam on Solaris 2.6

Pam on Solaris 2.6

Post by Mark G. Adam » Thu, 01 Jul 1999 04:00:00



Greetings.

I'm having a problem using PAM on Sparc Solaris 2.6. Specifically, the
appdata_ptr in the conv structure which I pass to pam_start() isn't
getting passed on to the conv function when called. Is there a known
problem with this? Note that I do have the two recommended PAM patches
applied.

I've attached a short program below which demonstrates this behaviour.
Note that it works properly on x86/Linux. On Solaris, the warning about
appdata_ptr being null is always displayed.

Am I missing something, or is this a bug in PAM on Solaris 2.6?

Thanks.

//Mark
--
Mark G. Adams
Software Developer
LivePage Corporation
Waterloo, Ontario, Canada

-----------------
#include <stdio.h>
#include <stdlib.h>
#include <security/pam_appl.h>

int livepage_conv(int num_msg,
                  const struct pam_message **msg,
                  struct pam_response **resp,
                  void *appdata_ptr) {
    struct pam_response *p = NULL;
    int i,j,ret = PAM_CONV_ERR;

    if( !appdata_ptr ) {
        printf( "Warning: appdata_ptr is NULL.\n" );
    }
    /* Allocate the array to be returned and zero it */
    p = (struct pam_response *)malloc( sizeof( struct pam_response ) *
                                                num_msg );
    memset( p, '\0', sizeof( struct pam_response ) * num_msg );
    /* Cycle through each message (should only just get 1, but let's be
       thorough */
    for( i = 0; i < num_msg; i++ ) {
        switch( msg[i]->msg_style ) {
            case PAM_PROMPT_ECHO_OFF:
            case PAM_PROMPT_ECHO_ON:
                if( !appdata_ptr ) {
                    appdata_ptr = "";
                }
                p[i].resp = (char *)malloc( sizeof( char ) *
                                 ( strlen( (char *)appdata_ptr ) + 1 ) );
                /* Just in case */
                if( p[i].resp == NULL ) {
                    for( j = 0; j < i; j++ ) {
                        if( p[j].resp != NULL ) {
                            free( p[j].resp );
                        }
                    }
                    goto done;
                }
                strcpy( p[i].resp, (char *)appdata_ptr );
                break;
            default:
                /* We simply ignore text */
                break;
        }
    }
    *resp = p;
    ret = PAM_SUCCESS;
 done:
    if( (ret != PAM_SUCCESS ) && ( p != NULL ) ) {
        free( p );
    }
    return ret;

Quote:}

int main( int argc, char *argv[] ) {
    pam_handle_t *pamh = NULL;
    struct pam_conv conv;
    int retval;

    if( ( argc < 2 ) || ( argc > 3 ) ) {
        printf( "Syntax: pamtest <user> [<password>]\n" );
        return 1;
    }
    conv.conv = livepage_conv;
    if( argc == 3 ) {
        conv.appdata_ptr = (void *)argv[ 2 ];
    } else {
        conv.appdata_ptr = NULL;
    }
    if( ( retval = pam_start( "myservice", argv[ 1 ], &conv, &pamh ) )
!=
        PAM_SUCCESS ) {
        printf( "Pam error: %s\n", pam_strerror( NULL, retval ) );
        return 1;
    }
    if( ( retval = pam_authenticate( pamh, 0 ) ) != PAM_SUCCESS ) {
        printf( "Pam error: %s\n", pam_strerror( pamh, retval ) );
        pam_end( pamh, retval );
        return 1;
    }
    if( ( retval = pam_acct_mgmt( pamh, 0 ) ) != PAM_SUCCESS ) {
        printf( "Pam error: %s\n", pam_strerror( pamh, retval ) );
        pam_end( pamh, retval );
        return 1;
    }
    printf( "Authorized.\n" );
    pam_end( pamh, retval);
    return 0;

Quote:}