pam_radius_auth.c memory leaks?

Cesare Placanica ugengia-reg at yahoo.it
Thu Oct 1 16:01:34 CEST 2009


Hi,
I've written a little test application for pam_radius_auth.
Although in the following article:

http://developers.sun.com/solaris/articles/user_auth_solaris3.html

is written that *pam service modules are in charge of freeing pam_response messages*, I suspect that this is not happening.

Here is my test application and the memory debug using libumem:

gerace:1> ldd check_user
	libpam.so.1 =>	 /usr/dt/lib/libpam.so.1
	libumem.so.1 =>	 /lib/libumem.so.1
	libc.so.1 =>	 /lib/libc.so.1
	libcmd.so.1 =>	 /lib/libcmd.so.1
	libm.so.2 =>	 /lib/libm.so.2
	/platform/SUNW,A70/lib/libc_psr.so.1
gerace:2> uname -a
SunOS gerace 5.10 Generic_118833-03 sun4u sparc SUNW,A70
gerace:3> 
gerace:3> cat check_user.c
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <security/pam_appl.h>
#include "dprint.h"

/* pam conversation function */
extern int check_conv(int num_msg, struct pam_message **msg, struct pam_response **resp, void *app_data);

int main(int argc, char *argv[])
{
    struct pam_conv conv = { check_conv, NULL };
    pam_handle_t *ph;
    int error;

    if (argc == 1)
    {
        printf("pam_radius_auth testing utility\n\n");
        printf("Usage: %s user [trace_flag (0|1)]\n", argv[0]);
        exit(0);
    }
    if (argc == 3)
    {
        if (0 == strncmp(argv[2], "1", 2))
        {
            trace_flag = 1;
        }
    }
    if ((error = pam_start("ctms", argv[1], &conv, &ph)) != PAM_SUCCESS)
    {
        fprintf(stderr, "Call to pam_start failed: %s\n", pam_strerror(ph, error));
        exit(1);
    }
    for (;;)
    {
        error = pam_authenticate(ph, 0);
        if (error == PAM_SUCCESS)
        {
            printf("Password match.\n");
            break;
        }
        else
        {
            if (error == PAM_AUTHINFO_UNAVAIL)
            {
                printf("Server down\n");
                break;
            }
            else
            {
                printf("Password don't match.\n");
            }
        }
    }
    pam_end(ph, 0);
    return (0);
}
gerace:4> 
gerace:4> cat check_user_conv.c
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <security/pam_appl.h>
#include "dprint.h"

int check_conv(int num_msg, struct pam_message **msg, struct pam_response **resp, void *app_data)
{
    struct pam_message *m = *msg;
    struct pam_response *r;
    int i;
    char *ct_passwd = NULL;
    char *ct_pin = NULL;

    DPRINT("DEBUG: entering conversation function\n");
    if ((num_msg <= 0) || (num_msg >= PAM_MAX_NUM_MSG))
    {
        fprintf(stderr, "Invalid number of messages\n");
        *resp = NULL;
        return (PAM_CONV_ERR);
    }
    if ((*resp = r = calloc(num_msg, sizeof(struct pam_response))) == NULL)
        return (PAM_BUF_ERR);
    for (i = 0; i < num_msg; i++)
    {
        switch (m->msg_style)
        {
        case PAM_PROMPT_ECHO_OFF:
            if (m->msg)
            {
                DPRINT("DEBUG: PAM_PROMPT_ECHO_OFF server says %s\n", m->msg);
            }
            else
            {
                DPRINT("DEBUG: PAM_PROMPT_ECHO_OFF\n");
            }
            ct_passwd = getpassphrase("Enter password: ");
            r->resp = strdup(ct_passwd);
            m++;
            r++;
            break;
        case PAM_PROMPT_ECHO_ON:
            DPRINT("DEBUG: PAM_PROMPT_ECHO_ON\n");
            if (m->msg)
            {
                ct_pin = getpassphrase(m->msg);
                r->resp = strdup(ct_pin);
            }
            else
            {
                r->resp = NULL;
            }
            m++;
            r++;
            break;
        case PAM_ERROR_MSG:
            DPRINT("DEBUG: PAM_ERROR_MSG\n");
            if (m->msg)
                fprintf(stderr, "%s\n", m->msg);
            m++;
            r++;
            break;
        case PAM_TEXT_INFO:
            DPRINT("DEBUG: PAM_TEXT_INFO\n");
            if (m->msg)
                printf("%s\n", m->msg);
            m++;
            r++;
            break;
        }
    }
    return (PAM_SUCCESS);
}
gerace:6> 
gerace:6> 
gerace:6> setenv LD_PRELOAD libumem.so.1
gerace:7> setenv UMEM_DEBUG default
gerace:8> sudo mdb ./check_user
> ::sysbp _exit
> ::run SuperUser
Enter password: 
Password match.
mdb: stop on entry to _exit
mdb: target stopped at:
libc.so.1`exit+0x14:    ta        8
mdb: You've got symbols!
Loading modules: [ ld.so.1 libumem.so.1 libc.so.1 ]
> ::load libumem
> ::findleaks
CACHE     LEAKED   BUFCTL CALLER
00033b88       1 0003d518 libc.so.1`_nss_XbyY_buf_alloc+8
0002d188       1 00072000 libpam.so.1`run_stack+0xc8
----------------------------------------------------------------------
   Total       2 buffers, 1216 bytes
>
> 0003d518::bufctl_audit
            ADDR          BUFADDR        TIMESTAMP           THREAD
                            CACHE          LASTLOG         CONTENTS
           3d518            41480     13e5187aea2a                1
                            33b88                0                0
                 libumem.so.1`umem_cache_alloc+0x210
                 libumem.so.1`umem_alloc+0x60
                 libumem.so.1`malloc+0x28
                 libc.so.1`_nss_XbyY_buf_alloc+8
                 0xff1aa688
                 0xff1a6af4
                 0xff1a6750
                 0xff1a2e88
                 0xff1d0ce8
                 libpam.so.1`run_stack+0xc8
                 libpam.so.1`pam_authenticate+0x30
                 main+0x13c
                 _start+0x5c

> 00072000::bufctl_audit
            ADDR          BUFADDR        TIMESTAMP           THREAD
                            CACHE          LASTLOG         CONTENTS
           72000            75f80     13e5187ace6e                1
                            2d188                0                0
                 libumem.so.1`umem_cache_alloc+0x210
                 libumem.so.1`umem_alloc+0x60
                 libumem.so.1`malloc+0x28
                 libumem.so.1`calloc+0x58
                 0xff1a6acc
                 0xff1a6750
                 0xff1a2e88
                 0xff1d0ce8
                 libpam.so.1`run_stack+0xc8
                 libpam.so.1`pam_authenticate+0x30
                 main+0x13c
                 _start+0x5c

> ::quit

I suspect that the first leak is due the strdup function in the conversation function (check_conv), because memory allocation is in libc.
The second leak is the calloc in check_conv function.

There is a guideline to handle this memory issues for pam_response messages?

Regards,
Cesare 



      




More information about the Freeradius-Users mailing list