diff options
author | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 12:47:05 -0800 |
---|---|---|
committer | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 12:47:05 -0800 |
commit | 4c51da22e068907adb7857d50f5109a467c94d7c (patch) | |
tree | becf5fbae5dfcbe8896355f59042dc8eaefa7f37 /Linux-PAM/modules/pam_userdb/pam_userdb.c | |
parent | efd31890b5ed496a5a00c08a262da240e66a4ddc (diff) | |
parent | ab9e8ba11f464fc083fc65a0bc695d60ebc86f3e (diff) | |
download | pam-4c51da22e068907adb7857d50f5109a467c94d7c.tar.gz pam-4c51da22e068907adb7857d50f5109a467c94d7c.tar.bz2 pam-4c51da22e068907adb7857d50f5109a467c94d7c.zip |
New upstream version 0.79
Diffstat (limited to 'Linux-PAM/modules/pam_userdb/pam_userdb.c')
-rw-r--r-- | Linux-PAM/modules/pam_userdb/pam_userdb.c | 291 |
1 files changed, 237 insertions, 54 deletions
diff --git a/Linux-PAM/modules/pam_userdb/pam_userdb.c b/Linux-PAM/modules/pam_userdb/pam_userdb.c index 337d217b..86c7238b 100644 --- a/Linux-PAM/modules/pam_userdb/pam_userdb.c +++ b/Linux-PAM/modules/pam_userdb/pam_userdb.c @@ -1,13 +1,14 @@ /* pam_userdb module */ - + /* - * $Id: pam_userdb.c,v 1.1.1.2 2002/09/15 20:09:03 hartmans Exp $ + * $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 <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> @@ -56,33 +57,53 @@ static void _pam_log(int err, const char *format, ...) closelog(); } -char * database = NULL; -static int ctrl = 0; - -static int _pam_parse(int argc, const char **argv) +static int +_pam_parse (int argc, const char **argv, + char **database, char **cryptmode) { - /* step through arguments */ - for (ctrl = 0; argc-- > 0; ++argv) { - - /* generic options */ - - if (!strcmp(*argv,"debug")) - ctrl |= PAM_DEBUG_ARG; - else if (!strcasecmp(*argv, "icase")) - ctrl |= PAM_ICASE_ARG; - else if (!strcasecmp(*argv, "dump")) - ctrl |= PAM_DUMP_ARG; - else if (!strncasecmp(*argv,"db=", 3)) { - database = strdup((*argv) + 3); - if (database == NULL) - _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"", - *argv); - } else { - _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); - } - } + int ctrl; + + *database = NULL; + *cryptmode = NULL; + + /* step through arguments */ + for (ctrl = 0; argc-- > 0; ++argv) + { + /* generic options */ + + if (!strcmp(*argv,"debug")) + ctrl |= PAM_DEBUG_ARG; + else if (!strcasecmp(*argv, "icase")) + ctrl |= PAM_ICASE_ARG; + else if (!strcasecmp(*argv, "dump")) + ctrl |= PAM_DUMP_ARG; + else if (!strcasecmp(*argv, "unknown_ok")) + ctrl |= PAM_UNKNOWN_OK_ARG; + else if (!strcasecmp(*argv, "key_only")) + ctrl |= PAM_KEY_ONLY_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); + } + 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); + } + else + { + _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); + } + } - return ctrl; + return ctrl; } @@ -95,7 +116,9 @@ static int _pam_parse(int argc, const char **argv) * -1 = Password incorrect * -2 = System error */ -static int user_lookup(const char *user, const char *pass) +static int +user_lookup (const char *database, const char *cryptmode, + const char *user, const char *pass, int ctrl) { DBM *dbm; datum key, data; @@ -108,7 +131,8 @@ static int user_lookup(const char *user, const char *pass) return -2; } - if (ctrl &PAM_DUMP_ARG) { + /* dump out the database contents for debugging */ + if (ctrl & PAM_DUMP_ARG) { _pam_log(LOG_INFO, "Database dump:"); for (key = dbm_firstkey(dbm); key.dptr != NULL; key = dbm_nextkey(dbm)) { @@ -116,14 +140,19 @@ static int user_lookup(const char *user, const char *pass) _pam_log(LOG_INFO, "key[len=%d] = `%s', data[len=%d] = `%s'", key.dsize, key.dptr, data.dsize, data.dptr); } - } - /* do some more init work */ + } + /* do some more init work */ memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); - key.dptr = x_strdup(user); - key.dsize = strlen(user); - user = NULL; + 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); + } else { + key.dptr = x_strdup(user); + key.dsize = strlen(user); + } if (key.dptr) { data = dbm_fetch(dbm, key); @@ -138,27 +167,121 @@ static int user_lookup(const char *user, const char *pass) if (data.dptr != NULL) { int compare = 0; - + + if (ctrl & PAM_KEY_ONLY_ARG) + { + dbm_close (dbm); + return 0; /* found it, data contents don't matter */ + } + + 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; + compare = 1; /* wrong password len -> wrong password */ } else if (ctrl & PAM_ICASE_ARG) { compare = strncasecmp(data.dptr, pass, data.dsize); } 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); if (compare == 0) return 0; /* match */ else return -1; /* wrong */ } else { - if (ctrl & PAM_DEBUG_ARG) { + int saw_user = 0; + + if (ctrl & PAM_DEBUG_ARG) { _pam_log(LOG_INFO, "error returned by dbm_fetch: %s", strerror(errno)); } - dbm_close(dbm); + /* probably we should check dbm_error() here */ - return 1; /* not found */ + + if ((ctrl & PAM_KEY_ONLY_ARG) == 0) { + dbm_close(dbm); + return 1; /* not key_only, so no entry => no entry for the user */ + } + + /* now handle the key_only case */ + for (key = dbm_firstkey(dbm); + key.dptr != NULL; + key = dbm_nextkey(dbm)) { + int compare; + /* first compare the user portion (case sensitive) */ + compare = strncmp(key.dptr, user, strlen(user)); + if (compare == 0) { + /* assume failure */ + compare = -1; + /* 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 (ctrl & PAM_ICASE_ARG) { + /* compare the password portion (case insensitive)*/ + compare = strncasecmp(key.dptr + strlen(user) + 1, + pass, + strlen(pass)); + } else { + /* compare the password portion (case sensitive) */ + compare = strncmp(key.dptr + strlen(user) + 1, + pass, + strlen(pass)); + } + } + } + if (compare == 0) { + dbm_close(dbm); + return 0; /* match */ + } + } + } + dbm_close(dbm); + if (saw_user) + return -1; /* saw the user, but password mismatch */ + else + return 1; /* not found */ } /* NOT REACHED */ @@ -173,10 +296,17 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, { const char *username; const char *password; - int retval = PAM_AUTH_ERR; - + char *database = NULL; + char *cryptmode = NULL; + int retval = PAM_AUTH_ERR, ctrl; + /* parse arguments */ - ctrl = _pam_parse(argc, argv); + 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"); + return PAM_SERVICE_ERR; + } /* Get the username */ retval = pam_get_user(pamh, &username, NULL); @@ -185,32 +315,47 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, _pam_log(LOG_DEBUG,"can not get the username"); return PAM_SERVICE_ERR; } - - /* Converse just to be sure we have the password */ + + /* 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 -2; + 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 (retval != PAM_SUCCESS) { + _pam_log(LOG_ERR, "could not obtain password for `%s'", + username); + return PAM_CONV_ERR; + } + } + /* Get the password */ retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password); if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "Could not retrive user's password"); + _pam_log(LOG_ERR, "Could not retrieve user's password"); return -2; } - + if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_INFO, "Verify user `%s' with password `%s'", username, password); - + /* Now use the username to look up password in the database file */ - retval = user_lookup(username, password); + retval = user_lookup(database, cryptmode, username, password, ctrl); switch (retval) { case -2: /* some sort of system error. The log was already printed */ - return PAM_SERVICE_ERR; + return PAM_SERVICE_ERR; case -1: /* incorrect password */ _pam_log(LOG_WARNING, @@ -247,9 +392,47 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, } PAM_EXTERN -int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, - int argc, const char **argv) +int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { + const char *username; + char *database = NULL; + char *cryptmode = NULL; + int retval = PAM_AUTH_ERR, ctrl; + + /* parse arguments */ + ctrl = _pam_parse(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"); + return PAM_SERVICE_ERR; + } + + /* Now use the username to look up password in the database file */ + retval = user_lookup(database, cryptmode, username, "", ctrl); + switch (retval) { + case -2: + /* some sort of system error. The log was already printed */ + return PAM_SERVICE_ERR; + case -1: + /* incorrect password, but we don't care */ + /* FALL THROUGH */ + case 0: + /* authentication succeeded. dumbest password ever. */ + return PAM_SUCCESS; + case 1: + /* the user does not exist in the database */ + 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; + } + return PAM_SUCCESS; } @@ -262,7 +445,7 @@ struct pam_module _pam_userdb_modstruct = { "pam_userdb", pam_sm_authenticate, pam_sm_setcred, - NULL, + pam_sm_acct_mgmt, NULL, NULL, NULL, |