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 - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html

