Here's the deal. My work has it's own ldap server (we'll call it ldap1), and normal users authenticate against it using pam_ldap. It's been determined, however, that we'd like to allow other users to come in as "guest" users of some kind, by some kind of authentication to another ldap server (we'll call it ldap2). So, it's been my job to write a custom PAM module to bind against ldap2, and if it succeeds, change the user's name to "nobody". Everything seems to work when I'm using the "login"service, but when I try KDM, some interesting things happen.
First, I can't get the change of user to "nobody" to "stick" when using the KDM pam stack. Inside the pam_sm_authenticate() function, I am able to set it (PAM_USER) using pam_set_item(), which returns PAM_SUCCESS, but once I get to pam_sm_setcred(), PAM_USER has somehow reverted to the username that the user supplied. Inside pam_sm_setcred(), I try to set it again, again using pam_set_item(), and again it returns a PAM_SUCCESS, but if I check it again, it has reverted again. I don't know what's going on.
Second, even though I've removed the line with pam_ldap from the /etc/pam.d/kdm file, somehow the user is still getting credentials (uid, gid, home directory, etc) from ldap1. Is this the result of some other player, like nss_ldap?
Anyway, I'm at a loss, so anything anyone could give me would be great.
Thans again,
Lloyd Brown
P.S. I'm attaching a text file with some code and debugging output. I hope that it will help.
Relevant code:
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
int ret;
char *username = NULL;
char *authtok = NULL;
char *base_dn = NULL;
char *base_dn_format = NULL;
LDAP *ldap_server = NULL;
char *ldap_host = NULL;
int ldap_port = 0;
char *generic_username = NULL;
FILE *input_file = NULL;
char *input_buffer = malloc(BUFFER_SIZE);
char *tmp_buffer = NULL;
char *tok = NULL;
char *temppointer = NULL;
char *tempstring = NULL;
//read configuration file here
//(don't worry. this part works.)
//debugging
D(("generic username found: %s", generic_username));
D(("base dn format found: %s", base_dn_format));
D(("ldap host found: %s", ldap_host));
D(("ldap port found: %i", ldap_port));
//TODO: check sanity of variables
D(("Attempting to retrieve user name"));
ret = pam_get_user(pamh, (const char **)&username, NULL);
if(ret != PAM_SUCCESS) {
D(("Error while retrieving user name: %s", pam_strerror(pamh, ret)));
return PAM_AUTH_ERR;
}
D(("Found username: %s", username));
if(!strcmp(username, "root")) {
//we want to ignore root;
D(("Ignoring root user"));
return PAM_IGNORE;
}
//get user's authtoken (ie password)
ret = pam_get_item(pamh, PAM_AUTHTOK, (void*) &authtok);
if(ret != PAM_SUCCESS) {
D(("Error while retrieving user's authentication token: %s",
pam_strerror(pamh, ret)));
return PAM_AUTH_ERR;
}
if(authtok[0] =='\0' || authtok[0] == '\n') {
//disallow anonymous binds through blank passwords
D(("Error while retrieving authtok. Blank password supplied."));
return PAM_AUTH_ERR;
}
//build dn
base_dn = malloc(strlen(base_dn_format) + strlen(username));
ret = sprintf(base_dn, base_dn_format, username);
D(("base_dn formed: %s", base_dn));
//open ldap connection
D(("Connecting to ldap server: %s:%i", ldap_host, ldap_port));
ldap_server = ldap_init(ldap_host, ldap_port);
if(ldap_server == NULL) {
D(("An error has occured while connecting to the ldap server %s:%i",
ldap_host, ldap_port));
return PAM_AUTH_ERR;
} else {
D(("Connection to ldap server %s:%i succeeded", ldap_host, ldap_port));
}
//try to bind using dn and password
ret = ldap_simple_bind_s(ldap_server, base_dn, authtok);
//D(("Result of ldap_simple_bind_s(): %s", ldap_error(ret)));
if(ret == LDAP_SUCCESS) {
D(("Bind to ldap server succeeded:"));
} else {
D(("Error while binding to ldap server: %s", ldap_err2string(ret)));
return PAM_AUTH_ERR;
}
D(("Attempting to set PAM_USER to '%s'", generic_username));
ret = pam_set_item(pamh, PAM_USER, (const void *)generic_username);
if (ret == PAM_SUCCESS) {
D(("PAM_USER set successfully"));
} else {
D(("PAM_USER setting function returned with an error"));
}
//setting PAM_GUEST_LDAP_USER to generic_username
D(("Attempting to set PAM_GUEST_LDAP_USER to '%s'", generic_username));
ret = pam_set_data(pamh, "PAM_GUEST_LDAP_USER", generic_username, NULL);
if (ret == PAM_SUCCESS) {
D(("PAM_GUEST_LDAP_USER data set successfully"));
} else {
D(("PAM_GUEST_LDAP_USER data not set successfully"));
}
D(("Attempting to retrieve user name again"));
ret = pam_get_user(pamh, (const char **)&username, NULL);
if(ret != PAM_SUCCESS) {
D(("Error while retrieving user name: %s", pam_strerror(pamh, ret)));
return PAM_AUTH_ERR;
}
D(("Found username: %s", username));
D(("Returning PAM_SUCCESS for pam_sm_authenticate()"));
free(base_dn);
return PAM_SUCCESS;
}
PAM_EXTERN
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
char *username = NULL;
char *generic_name = NULL;
int ret;
D(("Attempting to retrieve user name"));
ret = pam_get_user(pamh, (const char **)&username, NULL);
if(ret != PAM_SUCCESS) {
D(("Error while retrieving user name: %s", pam_strerror(pamh, ret)));
return PAM_AUTH_ERR;
}
D(("Found username: %s", username));
D(("Retrieving the generic username from PAM_GUEST_LDAP_USER"));
ret = pam_get_data(pamh, "PAM_GUEST_LDAP_USER", (const void**) &generic_name);
if(ret != PAM_SUCCESS) {
D(("Error while retrieving generic username: %s", pam_strerror(pamh, ret)));
return PAM_AUTH_ERR;
}
D(("Found generic username: %s", generic_name));
D(("(Re)setting PAM_USER to '%s'", generic_name));
ret = pam_set_data(pamh, "PAM_GUEST_LDAP_USER", generic_name, NULL);
if(ret != PAM_SUCCESS) {
D(("Error occured while (re)setting PAM_USER: %s", pam_strerror(pamh, ret)));
return PAM_AUTH_ERR;
}
D(("Attempting to retrieve user name again"));
ret = pam_get_user(pamh, (const char **)&username, NULL);
if(ret != PAM_SUCCESS) {
D(("Error while retrieving user name: %s", pam_strerror(pamh, ret)));
return PAM_AUTH_ERR;
}
D(("Found username: %s", username));
return PAM_SUCCESS;
}
---------------------------------------------------------------
Debugging output:
Using kdm:
[pam_guest_ldap.c:pam_sm_authenticate(114)] generic username found: nobody
[pam_guest_ldap.c:pam_sm_authenticate(115)] base dn format found:
uid=%s,ou=people,o=BYU.edu
[pam_guest_ldap.c:pam_sm_authenticate(116)] ldap host found: ldap.byu.edu
[pam_guest_ldap.c:pam_sm_authenticate(117)] ldap port found: 389
[pam_guest_ldap.c:pam_sm_authenticate(121)] Attempting to retrieve user name
[pam_guest_ldap.c:pam_sm_authenticate(127)] Found username: ltb9
[pam_guest_ldap.c:pam_sm_authenticate(156)] base_dn formed:
uid=ltb9,ou=people,o=BYU.edu
[pam_guest_ldap.c:pam_sm_authenticate(161)] Connecting to ldap server: ldap.byu.edu:389
[pam_guest_ldap.c:pam_sm_authenticate(167)] Connection to ldap server ldap.byu.edu:389
succeeded
[pam_guest_ldap.c:pam_sm_authenticate(175)] Bind to ldap server succeeded:
[pam_guest_ldap.c:pam_sm_authenticate(183)] Attempting to set PAM_USER to 'nobody'
[pam_guest_ldap.c:pam_sm_authenticate(186)] PAM_USER set successfully
[pam_guest_ldap.c:pam_sm_authenticate(192)] Attempting to set PAM_GUEST_LDAP_USER to
'nobody'
[pam_guest_ldap.c:pam_sm_authenticate(195)] PAM_GUEST_LDAP_USER data set successfully
[pam_guest_ldap.c:pam_sm_authenticate(200)] Attempting to retrieve user name again
[pam_guest_ldap.c:pam_sm_authenticate(206)] Found username: nobody
[pam_guest_ldap.c:pam_sm_authenticate(208)] Returning PAM_SUCCESS for
pam_sm_authenticate()
[pam_guest_ldap.c:pam_sm_setcred(221)] Attempting to retrieve user name
[pam_guest_ldap.c:pam_sm_setcred(227)] Found username: ltb9
[pam_guest_ldap.c:pam_sm_setcred(229)] Retrieving the generic username from
PAM_GUEST_LDAP_USER
[pam_guest_ldap.c:pam_sm_setcred(235)] Found generic username: nobody
[pam_guest_ldap.c:pam_sm_setcred(238)] (Re)setting PAM_USER to 'nobody'
[pam_guest_ldap.c:pam_sm_setcred(245)] Attempting to retrieve user name again
[pam_guest_ldap.c:pam_sm_setcred(251)] Found username: ltb9
using login:
[pam_guest_ldap.c:pam_sm_authenticate(114)] generic username found: nobody
[pam_guest_ldap.c:pam_sm_authenticate(115)] base dn format found:
uid=%s,ou=people,o=BYU.edu
[pam_guest_ldap.c:pam_sm_authenticate(116)] ldap host found: ldap.byu.edu
[pam_guest_ldap.c:pam_sm_authenticate(117)] ldap port found: 389
[pam_guest_ldap.c:pam_sm_authenticate(121)] Attempting to retrieve user name
[pam_guest_ldap.c:pam_sm_authenticate(127)] Found username: ltb9
[pam_guest_ldap.c:pam_sm_authenticate(156)] base_dn formed:
uid=ltb9,ou=people,o=BYU.edu
[pam_guest_ldap.c:pam_sm_authenticate(161)] Connecting to ldap server: ldap.byu.edu:389
[pam_guest_ldap.c:pam_sm_authenticate(167)] Connection to ldap server ldap.byu.edu:389
succeeded
[pam_guest_ldap.c:pam_sm_authenticate(175)] Bind to ldap server succeeded:
[pam_guest_ldap.c:pam_sm_authenticate(183)] Attempting to set PAM_USER to 'nobody'
[pam_guest_ldap.c:pam_sm_authenticate(186)] PAM_USER set successfully
[pam_guest_ldap.c:pam_sm_authenticate(192)] Attempting to set PAM_GUEST_LDAP_USER to
'nobody'
[pam_guest_ldap.c:pam_sm_authenticate(195)] PAM_GUEST_LDAP_USER data set successfully
[pam_guest_ldap.c:pam_sm_authenticate(200)] Attempting to retrieve user name again
[pam_guest_ldap.c:pam_sm_authenticate(206)] Found username: nobody
[pam_guest_ldap.c:pam_sm_authenticate(208)] Returning PAM_SUCCESS for
pam_sm_authenticate()
[pam_guest_ldap.c:pam_sm_setcred(221)] Attempting to retrieve user name
[pam_guest_ldap.c:pam_sm_setcred(227)] Found username: nobody
[pam_guest_ldap.c:pam_sm_setcred(229)] Retrieving the generic username from
PAM_GUEST_LDAP_USER
[pam_guest_ldap.c:pam_sm_setcred(235)] Found generic username: nobody
[pam_guest_ldap.c:pam_sm_setcred(238)] (Re)setting PAM_USER to 'nobody'
[pam_guest_ldap.c:pam_sm_setcred(245)] Attempting to retrieve user name again
[pam_guest_ldap.c:pam_sm_setcred(251)] Found username: nobody
____________________ BYU Unix Users Group http://uug.byu.edu/ ___________________________________________________________________ List Info: http://uug.byu.edu/cgi-bin/mailman/listinfo/uug-list
