diff options
Diffstat (limited to 'Linux-PAM/modules/pam_userdb/pam_userdb.c')
-rw-r--r-- | Linux-PAM/modules/pam_userdb/pam_userdb.c | 247 |
1 files changed, 137 insertions, 110 deletions
diff --git a/Linux-PAM/modules/pam_userdb/pam_userdb.c b/Linux-PAM/modules/pam_userdb/pam_userdb.c index 86c7238b..a796b15e 100644 --- a/Linux-PAM/modules/pam_userdb/pam_userdb.c +++ b/Linux-PAM/modules/pam_userdb/pam_userdb.c @@ -1,12 +1,11 @@ /* pam_userdb module */ /* - * $Id: pam_userdb.c,v 1.7 2004/09/28 13:48:47 kukuk Exp $ * Written by Cristian Gafton <gafton@redhat.com> 1996/09/10 * See the end of the file for Copyright Information */ -#include <security/_pam_aconf.h> +#include "config.h" #include <stdio.h> #include <stdlib.h> @@ -18,6 +17,9 @@ #include <sys/stat.h> #include <fcntl.h> #include <errno.h> +#ifdef HAVE_CRYPT_H +#include <crypt.h> +#endif #include "pam_userdb.h" @@ -43,23 +45,46 @@ #define PAM_SM_ACCOUNT #include <security/pam_modules.h> +#include <security/pam_ext.h> +#include <security/_pam_macros.h> -/* some syslogging */ - -static void _pam_log(int err, const char *format, ...) +/* + * Conversation function to obtain the user's password + */ +static int +obtain_authtok(pam_handle_t *pamh) { - va_list args; + char *resp; + const void *item; + int retval; + + retval = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &resp, _("Password: ")); + + if (retval != PAM_SUCCESS) + return retval; + + if (resp == NULL) + return PAM_CONV_ERR; + + /* set the auth token */ + retval = pam_set_item(pamh, PAM_AUTHTOK, resp); + + /* clean it up */ + _pam_overwrite(resp); + _pam_drop(resp); + + if ( (retval != PAM_SUCCESS) || + (retval = pam_get_item(pamh, PAM_AUTHTOK, &item)) + != PAM_SUCCESS ) { + return retval; + } - va_start(args, format); - openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); - va_end(args); - closelog(); + return retval; } static int -_pam_parse (int argc, const char **argv, - char **database, char **cryptmode) +_pam_parse (pam_handle_t *pamh, int argc, const char **argv, + const char **database, const char **cryptmode) { int ctrl; @@ -81,25 +106,29 @@ _pam_parse (int argc, const char **argv, ctrl |= PAM_UNKNOWN_OK_ARG; else if (!strcasecmp(*argv, "key_only")) ctrl |= PAM_KEY_ONLY_ARG; + else if (!strcasecmp(*argv, "use_first_pass")) + ctrl |= PAM_USE_FPASS_ARG; + else if (!strcasecmp(*argv, "try_first_pass")) + ctrl |= PAM_TRY_FPASS_ARG; else if (!strncasecmp(*argv,"db=", 3)) { - *database = strdup((*argv) + 3); - if ((*database == NULL) || (strlen (*database) == 0)) - _pam_log(LOG_ERR, - "pam_parse: could not parse argument \"%s\"", - *argv); + *database = (*argv) + 3; + if (**database == '\0') { + *database = NULL; + pam_syslog(pamh, LOG_ERR, + "db= specification missing argument - ignored"); + } } else if (!strncasecmp(*argv,"crypt=", 6)) { - *cryptmode = strdup((*argv) + 6); - if ((*cryptmode == NULL) || (strlen (*cryptmode) == 0)) - _pam_log(LOG_ERR, - "pam_parse: could not parse argument \"%s\"", - *argv); + *cryptmode = (*argv) + 6; + if (**cryptmode == '\0') + pam_syslog(pamh, LOG_ERR, + "crypt= specification missing argument - ignored"); } else { - _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); + pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } } @@ -117,7 +146,7 @@ _pam_parse (int argc, const char **argv, * -2 = System error */ static int -user_lookup (const char *database, const char *cryptmode, +user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, const char *user, const char *pass, int ctrl) { DBM *dbm; @@ -126,19 +155,20 @@ user_lookup (const char *database, const char *cryptmode, /* Open the DB file. */ dbm = dbm_open(database, O_RDONLY, 0644); if (dbm == NULL) { - _pam_log(LOG_ERR, "user_lookup: could not open database `%s'", - database); + pam_syslog(pamh, LOG_ERR, + "user_lookup: could not open database `%s': %m", database); return -2; } /* dump out the database contents for debugging */ if (ctrl & PAM_DUMP_ARG) { - _pam_log(LOG_INFO, "Database dump:"); + pam_syslog(pamh, LOG_INFO, "Database dump:"); for (key = dbm_firstkey(dbm); key.dptr != NULL; key = dbm_nextkey(dbm)) { data = dbm_fetch(dbm, key); - _pam_log(LOG_INFO, "key[len=%d] = `%s', data[len=%d] = `%s'", - key.dsize, key.dptr, data.dsize, data.dptr); + pam_syslog(pamh, LOG_INFO, + "key[len=%d] = `%s', data[len=%d] = `%s'", + key.dsize, key.dptr, data.dsize, data.dptr); } } @@ -146,9 +176,10 @@ user_lookup (const char *database, const char *cryptmode, memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); if (ctrl & PAM_KEY_ONLY_ARG) { - key.dptr = malloc(strlen(user) + 1 + strlen(pass) + 1); - sprintf(key.dptr, "%s-%s", user, pass); - key.dsize = strlen(key.dptr); + if (asprintf(&key.dptr, "%s-%s", user, pass) < 0) + key.dptr = NULL; + else + key.dsize = strlen(key.dptr); } else { key.dptr = x_strdup(user); key.dsize = strlen(user); @@ -161,8 +192,9 @@ user_lookup (const char *database, const char *cryptmode, } if (ctrl & PAM_DEBUG_ARG) { - _pam_log(LOG_INFO, "password in database is [%p]`%s', len is %d", - data.dptr, (char *) data.dptr, data.dsize); + pam_syslog(pamh, LOG_INFO, + "password in database is [%p]`%.*s', len is %d", + data.dptr, data.dsize, (char *) data.dptr, data.dsize); } if (data.dptr != NULL) { @@ -174,7 +206,7 @@ user_lookup (const char *database, const char *cryptmode, return 0; /* found it, data contents don't matter */ } - if (strncasecmp(cryptmode, "crypt", 5) == 0) { + if (cryptmode && strncasecmp(cryptmode, "crypt", 5) == 0) { /* crypt(3) password storage */ @@ -196,7 +228,7 @@ user_lookup (const char *database, const char *cryptmode, } else { compare = -2; if (ctrl & PAM_DEBUG_ARG) { - _pam_log(LOG_INFO, "crypt() returned NULL"); + pam_syslog(pamh, LOG_INFO, "crypt() returned NULL"); } }; @@ -208,18 +240,19 @@ user_lookup (const char *database, const char *cryptmode, * default to plaintext password storage */ - if (strlen(pass) != data.dsize) { - compare = 1; /* wrong password len -> wrong password */ - } else if (ctrl & PAM_ICASE_ARG) { + if (strlen(pass) != (size_t)data.dsize) { + compare = 1; /* wrong password len -> wrong password */ + } 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"); + if (cryptmode && strncasecmp(cryptmode, "none", 4) + && (ctrl & PAM_DEBUG_ARG)) { + pam_syslog(pamh, LOG_INFO, "invalid value for crypt parameter: %s", + cryptmode); + pam_syslog(pamh, LOG_INFO, "defaulting to plaintext password mode"); } } @@ -233,8 +266,7 @@ user_lookup (const char *database, const char *cryptmode, int saw_user = 0; if (ctrl & PAM_DEBUG_ARG) { - _pam_log(LOG_INFO, "error returned by dbm_fetch: %s", - strerror(errno)); + pam_syslog(pamh, LOG_INFO, "error returned by dbm_fetch: %m"); } /* probably we should check dbm_error() here */ @@ -257,7 +289,7 @@ user_lookup (const char *database, const char *cryptmode, /* if we have the divider where we expect it to be... */ if (key.dptr[strlen(user)] == '-') { saw_user = 1; - if (key.dsize == strlen(user) + 1 + strlen(pass)) { + if ((size_t)key.dsize == strlen(user) + 1 + strlen(pass)) { if (ctrl & PAM_ICASE_ARG) { /* compare the password portion (case insensitive)*/ compare = strncasecmp(key.dptr + strlen(user) + 1, @@ -290,91 +322,86 @@ user_lookup (const char *database, const char *cryptmode, /* --- authentication management functions (only) --- */ -PAM_EXTERN -int pam_sm_authenticate(pam_handle_t *pamh, int flags, - int argc, const char **argv) +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, + int argc, const char **argv) { const char *username; - const char *password; - char *database = NULL; - char *cryptmode = NULL; + const void *password; + const char *database = NULL; + const char *cryptmode = NULL; int retval = PAM_AUTH_ERR, ctrl; /* parse arguments */ - ctrl = _pam_parse(argc, argv, &database, &cryptmode); - if ((database == NULL) || (strlen(database) == 0)) { - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_DEBUG,"can not get the database name"); + ctrl = _pam_parse(pamh, argc, argv, &database, &cryptmode); + if (database == NULL) { + pam_syslog(pamh, LOG_ERR, "can not get the database name"); return PAM_SERVICE_ERR; } /* Get the username */ retval = pam_get_user(pamh, &username, NULL); if ((retval != PAM_SUCCESS) || (!username)) { - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_DEBUG,"can not get the username"); + pam_syslog(pamh, LOG_ERR, "can not get the username"); return PAM_SERVICE_ERR; } - /* Converse just to be sure we have a password */ - retval = conversation(pamh); - if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "could not obtain password for `%s'", - username); - return PAM_CONV_ERR; - } - - /* Check if we got a password. The docs say that if we didn't have one, - * and use_authtok was specified as an argument, that we converse with the - * user anyway, so check for one and handle a failure for that case. If - * use_authtok wasn't specified, then we've already asked once and needn't - * do so again. */ - retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &password); - if ((retval != PAM_SUCCESS) && ((ctrl & PAM_USE_AUTHTOK_ARG) != 0)) { - retval = conversation(pamh); + if ((ctrl & PAM_USE_FPASS_ARG) == 0 && (ctrl & PAM_TRY_FPASS_ARG) == 0) { + /* Converse to obtain a password */ + retval = obtain_authtok(pamh); if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "could not obtain password for `%s'", - username); - return PAM_CONV_ERR; + pam_syslog(pamh, LOG_ERR, "can not obtain password from user"); + return retval; } } - /* Get the password */ - retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password); - if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "Could not retrieve user's password"); - return -2; + /* Check if we got a password */ + retval = pam_get_item(pamh, PAM_AUTHTOK, &password); + if (retval != PAM_SUCCESS || password == NULL) { + if ((ctrl & PAM_TRY_FPASS_ARG) != 0) { + /* Converse to obtain a password */ + retval = obtain_authtok(pamh); + if (retval != PAM_SUCCESS) { + pam_syslog(pamh, LOG_ERR, "can not obtain password from user"); + return retval; + } + retval = pam_get_item(pamh, PAM_AUTHTOK, &password); + } + if (retval != PAM_SUCCESS || password == NULL) { + pam_syslog(pamh, LOG_ERR, "can not recover user password"); + return PAM_AUTHTOK_RECOVERY_ERR; + } } if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_INFO, "Verify user `%s' with password `%s'", - username, password); + pam_syslog(pamh, LOG_INFO, "Verify user `%s' with a password", + username); /* Now use the username to look up password in the database file */ - retval = user_lookup(database, cryptmode, username, password, ctrl); + retval = user_lookup(pamh, database, cryptmode, username, password, ctrl); switch (retval) { case -2: /* some sort of system error. The log was already printed */ return PAM_SERVICE_ERR; case -1: /* incorrect password */ - _pam_log(LOG_WARNING, - "user `%s' denied access (incorrect password)", - username); + pam_syslog(pamh, LOG_WARNING, + "user `%s' denied access (incorrect password)", + username); return PAM_AUTH_ERR; case 1: /* the user does not exist in the database */ if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_NOTICE, "user `%s' not found in the database", - username); + pam_syslog(pamh, LOG_NOTICE, + "user `%s' not found in the database", username); return PAM_USER_UNKNOWN; case 0: /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", username); + pam_syslog(pamh, LOG_NOTICE, "user '%s' granted access", username); return PAM_SUCCESS; default: /* we don't know anything about this return value */ - _pam_log(LOG_ERR, + pam_syslog(pamh, LOG_ERR, "internal module error (retval = %d, user = `%s'", retval, username); return PAM_SERVICE_ERR; @@ -384,34 +411,34 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, return PAM_IGNORE; } -PAM_EXTERN -int pam_sm_setcred(pam_handle_t *pamh, int flags, - int argc, const char **argv) +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED, + int argc UNUSED, const char **argv UNUSED) { return PAM_SUCCESS; } -PAM_EXTERN -int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) +PAM_EXTERN int +pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED, + int argc, const char **argv) { const char *username; - char *database = NULL; - char *cryptmode = NULL; + const char *database = NULL; + const char *cryptmode = NULL; int retval = PAM_AUTH_ERR, ctrl; /* parse arguments */ - ctrl = _pam_parse(argc, argv, &database, &cryptmode); + ctrl = _pam_parse(pamh, argc, argv, &database, &cryptmode); /* Get the username */ retval = pam_get_user(pamh, &username, NULL); if ((retval != PAM_SUCCESS) || (!username)) { - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_DEBUG,"can not get the username"); + pam_syslog(pamh, LOG_ERR,"can not get the username"); return PAM_SERVICE_ERR; } /* Now use the username to look up password in the database file */ - retval = user_lookup(database, cryptmode, username, "", ctrl); + retval = user_lookup(pamh, database, cryptmode, username, "", ctrl); switch (retval) { case -2: /* some sort of system error. The log was already printed */ @@ -427,10 +454,10 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) return PAM_USER_UNKNOWN; default: /* we don't know anything about this return value */ - _pam_log(LOG_ERR, - "internal module error (retval = %d, user = `%s'", - retval, username); - return PAM_SERVICE_ERR; + pam_syslog(pamh, LOG_ERR, + "internal module error (retval = %d, user = `%s'", + retval, username); + return PAM_SERVICE_ERR; } return PAM_SUCCESS; |