PATCH: crypt(3) password support for pam_userdb

Paul Walmsley paul at booyaka.com
Fri Aug 20 02:11:06 UTC 2004


Hello, 

while converting a PureFTPd installation to vsftpd, we needed pam_userdb
to authenticate against crypt(3)'d passwords stored in its password
database.  The following patch against pam_userdb in Linux-PAM-0.77
implements this. 

After this patch is installed, the default behavior is to use plaintext
passwords, the same as the current version of pam_userdb.  But if
'crypt=crypt' is included in the PAM service configuration file,
pam_userdb will expect to find crypted passwords in its database.

Comments welcome.


- Paul


diff -ru Linux-PAM-0.77-old/modules/pam_userdb/Makefile Linux-PAM-0.77/modules/pam_userdb/Makefile
--- Linux-PAM-0.77-old/modules/pam_userdb/Makefile	2001-05-08 01:03:55.000000000 -0500
+++ Linux-PAM-0.77/modules/pam_userdb/Makefile	2004-08-19 20:51:52.000000000 -0500
@@ -24,6 +24,11 @@
 endif
 endif
 
+ifeq ($(HAVE_LIBCRYPT),yes)
+  MODULE_SIMPLE_EXTRALIBS += -lcrypt
+endif
+
+
 ifeq ($(WHICH_DB),none)
 
 include ../dont_makefile
diff -ru Linux-PAM-0.77-old/modules/pam_userdb/pam_userdb.c Linux-PAM-0.77/modules/pam_userdb/pam_userdb.c
--- Linux-PAM-0.77-old/modules/pam_userdb/pam_userdb.c	2001-11-25 21:27:40.000000000 -0600
+++ Linux-PAM-0.77/modules/pam_userdb/pam_userdb.c	2004-08-19 20:51:52.000000000 -0500
@@ -57,6 +57,7 @@
 }
 
 char * database	 = NULL;
+char * cryptmode = NULL;
 static int ctrl	 = 0;
 
 static int _pam_parse(int argc, const char **argv)
@@ -77,6 +78,11 @@
 	      if (database == NULL)
 		  _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"",
 			   *argv);
+	  } else if (!strncasecmp(*argv,"crypt=", 6)) {
+	      cryptmode = strdup((*argv) + 6);
+	      if (cryptmode == NULL)
+		  _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"",
+			   *argv);
 	  } else {
                _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
           }
@@ -138,15 +144,58 @@
 
     if (data.dptr != NULL) {
 	int compare = 0;
-	
-	if (strlen(pass) != data.dsize) {
+
+	if (strncasecmp(cryptmode, "crypt", 5) == 0) {
+
+	  /* crypt(3) password storage */
+
+	  char *cryptpw;
+	  char salt[2];
+
+	  if (data.dsize != 13) {
+	    compare = -2;
+	  } else if (ctrl & PAM_ICASE_ARG) {
+	    compare = -2;
+	  } else {
+	    salt[0] = *data.dptr;
+	    salt[1] = *(data.dptr + 1);
+
+	    cryptpw = crypt (pass, salt);
+
+	    if (cryptpw) {
+	      compare = strncasecmp (data.dptr, cryptpw, data.dsize);
+	    } else {
+	      compare = -2;
+	      if (ctrl & PAM_DEBUG_ARG) {    
+		_pam_log(LOG_INFO, "crypt() returned NULL");
+	      }
+	    };
+
+	  };
+
+	} else {
+	  
+	  /* Unknown password encryption method -
+	   * default to plaintext password storage
+	   */
+
+	  if (strlen(pass) != data.dsize) {
 	    compare = 1;
-	} else if (ctrl & PAM_ICASE_ARG) {
+	  } else if (ctrl & PAM_ICASE_ARG) {
 	    compare = strncasecmp(data.dptr, pass, data.dsize);
-	} else {
+	  } else {
 	    compare = strncmp(data.dptr, pass, data.dsize);
+	  }
+
+	  if (strncasecmp(cryptmode, "none", 4) && ctrl & PAM_DEBUG_ARG) {    
+	    _pam_log(LOG_INFO, "invalid value for crypt parameter: %s",
+		     cryptmode);
+	    _pam_log(LOG_INFO, "defaulting to plaintext password mode");
+	  }
+
 	}
-	dbm_close(dbm);
+
+	  dbm_close(dbm);
 	if (compare == 0)
 	    return 0; /* match */
 	else
diff -ru Linux-PAM-0.77-old/modules/pam_userdb/README Linux-PAM-0.77/modules/pam_userdb/README
--- Linux-PAM-0.77-old/modules/pam_userdb/README	2000-06-20 17:12:09.000000000 -0500
+++ Linux-PAM-0.77/modules/pam_userdb/README	2004-08-19 20:51:52.000000000 -0500
@@ -9,9 +9,17 @@
 	db=[path]	use the [path] database for performing lookup. There
 			is no default; the module will return PAM_IGNORE if
 			no database is provided.
-			
+
+	crypt=[mode]	indicates whether encrypted or plaintext passwords
+	                are stored in the database.  If [mode] is "crypt", 
+			passwords should be stored in the database in 
+		        crypt(3) form.	If [mode] is "none" or any other 
+	                value, passwords should be stored in the database in
+			plaintext.
+
 	icase		make the password verification to be case insensitive
 			(ie when working with registration numbers and such)
+			only works with plaintext password storage.
 
 	dump		dump all the entries in the database to the log (eek,
 			don't do this by default!)





More information about the Pam-list mailing list