Following is a patch to add two features to the pam_userdb module: - Store encrypted passwords instead of plaintext. The configuration parameter "crypt" activates this feature. - "username_in_password" configuration parameter. This feature allows to specify in the password the username used to validate. For example, you can do something like this: ssh -l gate@gateway.mydomain.com Password: username password (Not visible!) This is useful in gateways to authenticate users without giving each user his/her own account (for security). If you think these features are interesting enough I will send you a new patch for the documentation (someone will check my english... :-)) Any comments? ---BEGIN PATCH--- *** orig/pam-0.72/modules/pam_userdb/pam_userdb.c Mon May 15 14:44:07 2000 --- new/pam-0.72/modules/pam_userdb/pam_userdb.c Wed Oct 11 11:26:39 2000 *************** *** 8,13 **** --- 8,14 ---- #include <features.h> #include <stdlib.h> + #include <stdio.h> #include <unistd.h> #include <string.h> #include <syslog.h> *************** *** 16,21 **** --- 17,23 ---- #include <sys/stat.h> #include <fcntl.h> #include <errno.h> + #include <crypt.h> #if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))) #include <db1/ndbm.h> *************** *** 54,59 **** --- 56,62 ---- } char * database = NULL; + char * as_user = NULL; static int ctrl = 0; static int _pam_parse(int argc, const char **argv) *************** *** 73,78 **** --- 76,85 ---- ctrl |= PAM_USE_AUTHTOK_ARG; else if (!strcasecmp(*argv, "unknown_ok")) ctrl |= PAM_UNKNOWN_OK_ARG; + else if (!strcasecmp(*argv, "user_in_password")) + ctrl |= PAM_USER_IN_PASSWORD; + else if (!strcasecmp(*argv, "crypt")) + ctrl |= PAM_CRYPT; else if (!strncasecmp(*argv,"db=", 3)) { database = strdup((*argv) + 3); if (database == NULL) *************** *** 99,111 **** * -1 = Password incorrect * -2 = System error */ ! static int user_lookup(const char *user, const char *pass) { DBM *dbm; datum key, data; char *key_only_buf = NULL; int key_only_len = 0; if (ctrl & PAM_KEY_ONLY) { /* set up a buffer for the username and password pair */ key_only_len = strlen(user) + strlen(pass) + 2; --- 106,138 ---- * -1 = Password incorrect * -2 = System error */ ! static int user_lookup(const char *user, const char *pass, ! pam_handle_t *pamh) { DBM *dbm; datum key, data; char *key_only_buf = NULL; int key_only_len = 0; + if (ctrl & PAM_USER_IN_PASSWORD) { + char * real_pass = strchr(pass, ' '); + if (real_pass && (key_only_len = real_pass - pass)) { + char * user_env; + + user = pass; + pass = real_pass + 1; + + user_env = alloca(22 + key_only_len); + strcpy(user_env, "PAM_USER_IN_PASSWORD="); + strncat(user_env + 21, user, key_only_len); + pam_putenv(pamh, user_env); + + if (ctrl & PAM_DEBUG_ARG) { + _pam_log(LOG_INFO, "put_env: '%s'", user_env); + } + } + } + if (ctrl & PAM_KEY_ONLY) { /* set up a buffer for the username and password pair */ key_only_len = strlen(user) + strlen(pass) + 2; *************** *** 150,156 **** key.dsize = key_only_len; } else { (const char *) key.dptr = user; ! key.dsize = strlen(user); } data = dbm_fetch(dbm, key); --- 177,183 ---- key.dsize = key_only_len; } else { (const char *) key.dptr = user; ! key.dsize = key_only_len ? key_only_len : strlen(user); } data = dbm_fetch(dbm, key); *************** *** 167,172 **** --- 194,203 ---- compare = 0; } else if (ctrl & PAM_ICASE_ARG) { compare = strncasecmp(pass, data.dptr, data.dsize); + } else if (ctrl & PAM_CRYPT) { + char salt[3] = "xx"; + strncpy(salt, data.dptr, 2); + compare = strncmp(crypt(pass,salt), data.dptr, data.dsize); } else { compare = strncmp(pass, data.dptr, data.dsize); } *************** *** 288,294 **** username, password); /* Now use the username to look up password in the database file */ ! retval = user_lookup(username, password); switch (retval) { case -2: /* some sort of system error. The log was already printed */ --- 319,325 ---- username, password); /* Now use the username to look up password in the database file */ ! retval = user_lookup(username, password, pamh); switch (retval) { case -2: /* some sort of system error. The log was already printed */ *** orig/pam-0.72/modules/pam_userdb/pam_userdb.h Mon Jan 3 19:08:45 2000 --- new/pam-0.72/modules/pam_userdb/pam_userdb.h Tue Oct 10 17:18:02 2000 *************** *** 13,18 **** --- 13,20 ---- #define PAM_USE_AUTHTOK_ARG (1 << 4) #define PAM_UNKNOWN_OK_ARG (1 << 5) #define PAM_KEY_ONLY (1 << 6) + #define PAM_USER_IN_PASSWORD (1 << 7) + #define PAM_CRYPT (1 << 8) /* Usefull macros */ #define x_strdup(s) ( (s) ? strdup(s):NULL ) ---END PATCH--- Jose _______________________________________________________________________________ Jose A. Rodriguez OOO Universitat Politecnica de Catalunya (UPC) josear@ac.upc.es OOO Departament d'Arquitectura de Computadors Tel. 6990 OOO -*- LCAC -*- UPC