Hi,
This is regarding an issue which I am facing in pam_setcred.
The problem is that in the attached code for pam_setcred I am getting PAM_SUCCESS for pam_setcred even if I set the PAM_USER to an unknown
user using pam_set_item.
Also I am not able to generate an error return for pam_setcred apart from calling it with a NULL for pamh.
Please let me know whether I am doing something wrong.
Regards Rohit
----------------------------------------------------------- gcc -lpam -lpam_misc -o pam_setcred pam_setcred.c
/etc/pam.d/tet_conf #%PAM-1.0 auth required pam_unix.so account required pam_unix.so use_first_pass password required pam_pwdb.so session required pam_pwdb.so
------------------------------------------------------------
#include <stdio.h> #include <security/pam_appl.h> #include <security/pam_misc.h> #define private static #define public /*******************************************************************/ private void tc1(); private void tc2(); private void tc3(); private pam_handle_t *pamh; private struct pam_conv pamc; struct mapping { int flag; char *desc; }; private struct mapping flags[] = { { PAM_ESTABLISH_CRED, "PAM_ESTABLISH_CRED" }, { PAM_DELETE_CRED, "PAM_DELETE_CRED" }, { PAM_REINITIALIZE_CRED, "PAM_REINITIALIZE_CRED" }, { PAM_REFRESH_CRED, "PAM_REFRESH_CRED" } }; private int login_conv(int num_msg, const struct pam_message **m, struct pam_response **r, void *appdata_ptr); private void clean_tests(); /*******************************************************************/ int main() { int retval; printf(" starting tests pam_set_cred \n"); pamh = NULL; pamc.conv = &login_conv; pamc.appdata_ptr = NULL; retval = pam_start("/etc/pam.d/tet_conf", getenv("USER"), &pamc, &pamh); if (retval != PAM_SUCCESS) { printf(" pam_start returned %s when expected to succeed \n", pam_strerror(NULL, retval)); return 0; } retval = pam_authenticate(pamh, 0); if (retval != PAM_SUCCESS) { printf(" pam_authenticate returned %s when expected to succeed \n", pam_strerror(pamh, retval)); return 0; } tc1(); tc2(); tc3(); clean_tests(); return 0; } private void clean_tests() { if (pamh) { pam_end(pamh,0); } printf(" end of tests pam_set_cred \n"); return; } /* * tc1() : * This test case checks the interface pam_setcred with * proper parameters. Expected return value is PAM_SUCCESS */ private void tc1() { int retval; int count; int index; printf("\n Entering tc1 \n"); count = sizeof(flags) / sizeof(struct mapping); printf(" count : %d \n",count); for (index = 0; index < count; index++) { retval = pam_setcred(pamh, flags[index].flag); if (retval != PAM_SUCCESS) { printf(" pam_setcred returned %s for flag %s \n", pam_strerror(pamh, retval), flags[index].desc); } } printf(" Exiting tc1 \n"); return; } /* * tc2() : * This test case tests the interface pam_setcred with NULL for * pamh. The return value should not be PAM_SUCCESS. */ private void tc2() { int retval; int count; int index; printf("\n Entering tc2 \n"); count = sizeof(flags) / sizeof(struct mapping); printf(" count : %d \n",count); for (index = 0; index < count; index++) { retval = pam_setcred(NULL, flags[index].flag); if (retval == PAM_SUCCESS) { printf(" pam_setcred returned %s for %s with NULL pamh \n", pam_strerror(pamh, retval), flags[index].desc); } } printf(" Exiting tc2 \n"); return; } /* * tc3() : * This test case checks the interface pam_setcred by replacing * PAM_USER with NULL pointer using pam_set_item. Expected * return value is PAM_USER_UNKNOWN */ private void tc3() { int retval; char *value = NULL; char *orig_value = NULL; printf("\n Entering tc3 \n"); retval = pam_get_item(pamh, PAM_USER, (const void **)&value); if (retval == PAM_SUCCESS ) { if (value != NULL) { orig_value = strdup(value); if (orig_value) { retval = pam_set_item(pamh, PAM_USER, "lssvanya"); if (retval != PAM_SUCCESS ) { printf(" pam_acct_mgmt: pam_set_item failed \n"); free(orig_value); printf(" Exiting tc3 \n"); return; } } else { printf(" pam_acct_mgmt: strdup returned NULL \n"); printf(" Exiting tc3 \n"); return; } } else { printf(" pam_acct_mgmt: pam_get_item returned NULL \n"); printf(" Exiting tc3 \n"); return; } } else { printf(" pam_acct_mgmt: pam_get_item failed \n"); printf(" Exiting tc3 \n"); return; } retval = pam_get_item(pamh, PAM_USER, (const void **)&value); if (retval == PAM_SUCCESS) { printf(" User : %s \n", value); } retval = pam_setcred(pamh, 0); pam_set_item(pamh, PAM_USER, orig_value); /* What to do if this set fails */ free(orig_value); if (retval != PAM_USER_UNKNOWN) { printf(" pam_setcred did not return PAM_USER_UNKNOWN for unknown user \n"); printf(" return value is %s \n", pam_strerror(pamh, retval)); printf(" Exiting tc3 \n"); return; } printf(" Exiting tc3 \n"); return; } /* * login_conv(): * This routine is called to get the username and password * required for authenticating the user. Currently the * username and password are got from the configuration files * to avoid user intervention. */ private int login_conv(int num_msg, const struct pam_message **m, struct pam_response **r, void *appdata_ptr) { char buf[PAM_MAX_RESP_SIZE]; char *temp; struct pam_response *reply; int count; printf(" In login conv \n"); reply = (struct pam_response *) calloc(num_msg, sizeof (struct pam_response)); if (reply == NULL) { return PAM_BUF_ERR; } for (count = 0; count < num_msg; count++) { reply[count].resp_retcode = 0; reply[count].resp = NULL; switch (m[count]->msg_style) { case PAM_PROMPT_ECHO_OFF: reply[count].resp = strdup(getpass(m[count]->msg)); if (reply[count].resp == NULL) { fputs(" getpass failed \n", stdout); } break; case PAM_PROMPT_ECHO_ON: (void)fputs(m[count]->msg,stdout); fgets(buf,PAM_MAX_RESP_SIZE,stdin); temp = strstr(buf,"\n"); *temp = '\0'; reply[count].resp = strdup(buf); break; case PAM_ERROR_MSG: (void)fputs(m[count]->msg,stdout); break; case PAM_TEXT_INFO: (void)fputs(m[count]->msg,stdout); break; default: break; } } *r = reply; return PAM_SUCCESS; }