LinuxThe Pluggable Authentication Modules (PAM) integrate several authentication schemes into an API which is used on several platforms, including Linux, to perform authentication and authorization for services such as login, ssh access, etc. One of these modules is Novell’s which authenticates against eDirectory and caches users’ credentials locally. This module is available on Suse Linux Enterprise Desktop (SLED) and is enabled with its Linux User Management (LUM) modules. A PAM configuration for such an installation starts off with

    auth      sufficient
    account   sufficient
    password  sufficient
    session   optional

Wanting to get hold of the credentials entered by a user, in order to subsequently mount a remote file system with them, I found a nifty little set of tools written by John Newbigin; Linux Enhanced SMBFS describes a PAM module avec a small daemon which can be used to do just that (I’m only interested in John’s and smbpwman code; the rest I don’t use). retrieves the user’s credentials from the PAM stack and passes them to a small daemon (smbpwman) via a Unix domain socket. The daemon is forked and executed if it isn’t running, and it keeps the credentials in core, allowing them to be retrieved by a process allowed to open said socket. A sample is located in the smbpwtest program. Stacking into PAM is easy enough and well documented on John’s page. Unfortunately, the needs a sufficient to operate, meaning, that if it succeeds, the auth stack terminates; I tried using optional or required twice, once before and once after which works, but it has a side effect of taking excessively long if and when a user mistypes her password. John was kind enough to answer my query, but his solution didn’t seem to help me, so I hacked in some code to have prompt for credentials; it then passes them down the stack, enabling subsequent modules to retrieve them. My PAM stack now specifies

    auth  required
    auth  sufficient use_first_pass
    ... queries the credentials and stores them, even if they are incorrect. Following that, checks them, and it either succeeds or fails as before. I’m attaching my tiny patch here, but I make no guarantees as to its safety for general consumption.

*** pam_smbpw.c.original	2007-04-26 10:59:30.000000000 +0200
--- pam_smbpw.c	2007-04-26 11:24:08.000000000 +0200
*** 11,16 ****
--- 11,18 ----
  #include <security/pam_modules.h>
+ #include <security/_pam_macros.h>
+ #include <security/pam_ext.h>
  #include "../smbpw.h"
*** 69,74 ****
--- 71,94 ----
  	pam_get_user(pamh, &user, NULL);
  	_pam_log(LOG_DEBUG, "The user is %s\n", user); 
+ /* JPM */
+ 	{
+ 		char *resp = NULL;
+ 		char *token;
+ 		r = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &resp,
+ 			"Password.", user);
+ 		if (r != PAM_SUCCESS) {
+ 			_pam_drop(r);
+ 			return ((r == PAM_CONV_AGAIN)
+ 		}
+ 		pam_set_item(pamh, PAM_AUTHTOK, resp);
+ 		_pam_log(LOG_DEBUG, "JPJP: %s", resp);
+ 	}
+ /* JPM */
  	r = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&authtok);
  	if(r != PAM_SUCCESS)

It seems to work, but I haven’t as yet scrutinized it for bugs and other evil thingies. Use at your own risk. :-)

Linux, Security, and CLI :: 09 May 2007 :: e-mail