diff options
Diffstat (limited to 'modules/pam_userdb/pam_userdb.c')
-rw-r--r-- | modules/pam_userdb/pam_userdb.c | 517 |
1 files changed, 0 insertions, 517 deletions
diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c deleted file mode 100644 index a796b15e..00000000 --- a/modules/pam_userdb/pam_userdb.c +++ /dev/null @@ -1,517 +0,0 @@ -/* pam_userdb module */ - -/* - * Written by Cristian Gafton <gafton@redhat.com> 1996/09/10 - * See the end of the file for Copyright Information - */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <syslog.h> -#include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#ifdef HAVE_CRYPT_H -#include <crypt.h> -#endif - -#include "pam_userdb.h" - -#ifdef HAVE_NDBM_H -# include <ndbm.h> -#else -# ifdef HAVE_DB_H -# define DB_DBM_HSEARCH 1 /* use the dbm interface */ -# include <db.h> -# else -# error "failed to find a libdb or equivalent" -# endif -#endif - -/* - * here, we make a definition for the externally accessible function - * in this file (this definition is required for static a module - * but strongly encouraged generally) it is used to instruct the - * modules include file to define the function prototypes. - */ - -#define PAM_SM_AUTH -#define PAM_SM_ACCOUNT - -#include <security/pam_modules.h> -#include <security/pam_ext.h> -#include <security/_pam_macros.h> - -/* - * Conversation function to obtain the user's password - */ -static int -obtain_authtok(pam_handle_t *pamh) -{ - 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; - } - - return retval; -} - -static int -_pam_parse (pam_handle_t *pamh, int argc, const char **argv, - const char **database, const char **cryptmode) -{ - 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 (!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 = (*argv) + 3; - if (**database == '\0') { - *database = NULL; - pam_syslog(pamh, LOG_ERR, - "db= specification missing argument - ignored"); - } - } - else if (!strncasecmp(*argv,"crypt=", 6)) - { - *cryptmode = (*argv) + 6; - if (**cryptmode == '\0') - pam_syslog(pamh, LOG_ERR, - "crypt= specification missing argument - ignored"); - } - else - { - pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); - } - } - - return ctrl; -} - - -/* - * Looks up an user name in a database and checks the password - * - * return values: - * 1 = User not found - * 0 = OK - * -1 = Password incorrect - * -2 = System error - */ -static int -user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, - const char *user, const char *pass, int ctrl) -{ - DBM *dbm; - datum key, data; - - /* Open the DB file. */ - dbm = dbm_open(database, O_RDONLY, 0644); - if (dbm == NULL) { - 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_syslog(pamh, LOG_INFO, "Database dump:"); - for (key = dbm_firstkey(dbm); key.dptr != NULL; - key = dbm_nextkey(dbm)) { - data = dbm_fetch(dbm, key); - pam_syslog(pamh, LOG_INFO, - "key[len=%d] = `%s', data[len=%d] = `%s'", - key.dsize, key.dptr, data.dsize, data.dptr); - } - } - - /* do some more init work */ - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - if (ctrl & PAM_KEY_ONLY_ARG) { - 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); - } - - if (key.dptr) { - data = dbm_fetch(dbm, key); - memset(key.dptr, 0, key.dsize); - free(key.dptr); - } - - if (ctrl & PAM_DEBUG_ARG) { - 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) { - int compare = 0; - - if (ctrl & PAM_KEY_ONLY_ARG) - { - dbm_close (dbm); - return 0; /* found it, data contents don't matter */ - } - - if (cryptmode && 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_syslog(pamh, LOG_INFO, "crypt() returned NULL"); - } - }; - - }; - - } else { - - /* Unknown password encryption method - - * default to plaintext password storage - */ - - 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 { - compare = strncmp(data.dptr, pass, data.dsize); - } - - 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"); - } - - } - - dbm_close(dbm); - if (compare == 0) - return 0; /* match */ - else - return -1; /* wrong */ - } else { - int saw_user = 0; - - if (ctrl & PAM_DEBUG_ARG) { - pam_syslog(pamh, LOG_INFO, "error returned by dbm_fetch: %m"); - } - - /* probably we should check dbm_error() here */ - - 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 ((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, - 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 */ - return -2; -} - -/* --- authentication management functions (only) --- */ - -PAM_EXTERN int -pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, - int argc, const char **argv) -{ - const char *username; - const void *password; - const char *database = NULL; - const char *cryptmode = NULL; - int retval = PAM_AUTH_ERR, ctrl; - - /* parse arguments */ - 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)) { - pam_syslog(pamh, LOG_ERR, "can not get the username"); - return PAM_SERVICE_ERR; - } - - 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_syslog(pamh, LOG_ERR, "can not obtain password from user"); - return retval; - } - } - - /* 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_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(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_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_syslog(pamh, LOG_NOTICE, - "user `%s' not found in the database", username); - return PAM_USER_UNKNOWN; - case 0: - /* Otherwise, the authentication looked good */ - pam_syslog(pamh, LOG_NOTICE, "user '%s' granted access", username); - return PAM_SUCCESS; - default: - /* we don't know anything about this return value */ - pam_syslog(pamh, LOG_ERR, - "internal module error (retval = %d, user = `%s'", - retval, username); - return PAM_SERVICE_ERR; - } - - /* should not be reached */ - return PAM_IGNORE; -} - -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 UNUSED, - int argc, const char **argv) -{ - const char *username; - const char *database = NULL; - const char *cryptmode = NULL; - int retval = PAM_AUTH_ERR, ctrl; - - /* parse arguments */ - ctrl = _pam_parse(pamh, argc, argv, &database, &cryptmode); - - /* Get the username */ - retval = pam_get_user(pamh, &username, NULL); - if ((retval != PAM_SUCCESS) || (!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(pamh, 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_syslog(pamh, LOG_ERR, - "internal module error (retval = %d, user = `%s'", - retval, username); - return PAM_SERVICE_ERR; - } - - return PAM_SUCCESS; -} - - -#ifdef PAM_STATIC - -/* static module data */ - -struct pam_module _pam_userdb_modstruct = { - "pam_userdb", - pam_sm_authenticate, - pam_sm_setcred, - pam_sm_acct_mgmt, - NULL, - NULL, - NULL, -}; - -#endif - -/* - * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1999 - * All rights reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ |