diff options
Diffstat (limited to 'modules/pam_tally')
-rw-r--r-- | modules/pam_tally/.cvsignore | 2 | ||||
-rw-r--r-- | modules/pam_tally/Makefile | 103 | ||||
-rw-r--r-- | modules/pam_tally/README | 95 | ||||
-rw-r--r-- | modules/pam_tally/faillog.h | 55 | ||||
-rw-r--r-- | modules/pam_tally/pam_tally.c | 735 | ||||
-rw-r--r-- | modules/pam_tally/pam_tally_app.c | 7 |
6 files changed, 0 insertions, 997 deletions
diff --git a/modules/pam_tally/.cvsignore b/modules/pam_tally/.cvsignore deleted file mode 100644 index e1a4f48f..00000000 --- a/modules/pam_tally/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -dynamic -pam_tally diff --git a/modules/pam_tally/Makefile b/modules/pam_tally/Makefile deleted file mode 100644 index 1c5106e3..00000000 --- a/modules/pam_tally/Makefile +++ /dev/null @@ -1,103 +0,0 @@ -# -# $Id$ -# -# This Makefile controls a build process of $(TITLE) module and -# application for Linux-PAM. You should not modify this Makefile -# (unless you know what you are doing!). -# -# - -include ../../Make.Rules - -TITLE=pam_tally - -# -## Additional rules for making (and moving) the application added. -## Assuming that all modules' applications are called $TITLE -# - -LIBSRC = $(TITLE).c -LIBOBJ = $(TITLE).o -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -APPSRC = $(TITLE)_app.c -APPOBJ = $(TITLE)_app.o -APPOBJD = $(addprefix dynamic/,$(APPOBJ)) -APPOBJS = $(addprefix static/,$(APPOBJ)) - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - - -ifdef DYNAMIC -LIBSHARED = $(TITLE).so -endif - -ifdef STATIC -LIBSTATIC = lib$(TITLE).o -endif - -APPLICATION = $(TITLE) -APPMODE = 755 - -####################### don't edit below ####################### - -all: dirs $(LIBSHARED) $(LIBSTATIC) register $(APPLICATION) - -dirs: -ifdef DYNAMIC - $(MKDIR) ./dynamic -endif -ifdef STATIC - $(MKDIR) ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) - -$(APPLICATION): $(APPOBJD) $(TITLE).c - $(CC) $(CFLAGS) -o $@ $(APPOBJD) $(LOADLIBES) - -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) - -$(APPLICATION): $(APPOBJS) $(TITLE).c - $(CC) $(CFLAGS) -o $@ $(APPOBJS) $(LOADLIBES) -endif - -install: all - $(MKDIR) $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) -endif - $(MKDIR) $(FAKEROOT)$(SUPLEMENTED) - $(INSTALL) -m $(APPMODE) $(APPLICATION) $(FAKEROOT)$(SUPLEMENTED) - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so - rm -f $(FAKEROOT)$(SUPLEMENTED)/$(TITLE) - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) $(APPOBJD) $(APPOBJS) core *~ - rm -f *.a *.o *.so *.bak dynamic/* static/* $(APPLICATION) - rm -rf dynamic static - -.c.o: - $(CC) $(CFLAGS) -c $< diff --git a/modules/pam_tally/README b/modules/pam_tally/README deleted file mode 100644 index 4c421648..00000000 --- a/modules/pam_tally/README +++ /dev/null @@ -1,95 +0,0 @@ -SUMMARY: - pam_tally: - - Maintains a count of attempted accesses, can reset count on success, - can deny access if too many attempts fail. - - Options: - - * onerr=[succeed|fail] (if something weird happens - such as unable to open the file, what to do?) - * file=/where/to/keep/counts (default /var/log/faillog) - - (auth) - Authentication phase increments attempted login counter. - * no_magic_root (root DOES increment counter. Use for - daemon-based stuff, like telnet/rsh/login) - - (account) - Account phase can deny access and/or reset attempts counter. - * deny=n (deny access if tally for this user exceeds n; - The presence of deny=n changes the default for - reset/no_reset to reset, unless the user trying to - gain access is root and the no_magic_root option - has NOT been specified.) - - * no_magic_root (access attempts by root DON'T ignore deny. - Use this for daemon-based stuff, like telnet/rsh/login) - * even_deny_root_account (Root can become unavailable. BEWARE. - Note that magic root trying to gain root bypasses this, - but normal users can be locked out.) - - * reset (reset count to 0 on successful entry, even for - magic root) - * no_reset (don't reset count on successful entry) - This is the default unless deny exists and the - user attempting access is NOT magic root. - - * per_user (If /var/log/faillog contains a non-zero - .fail_max field for this user then use it - instead of deny=n parameter) - - * no_lock_time (Don't use .fail_locktime filed in - /var/log/faillog for this user) - - Also checks to make sure that the counts file is a plain - file and not world writable. - - - Tim Baverstock <warwick@sable.demon.co.uk>, v0.1 5 March 1997 - -LONGER: - -pam_tally comes in two parts: pam_tally.so and pam_tally. - -pam_tally.so sits in a pam config file, in the auth and account sections. - -In the auth section, it increments a per-uid counter for each attempted -login, in the account section, it denies access if attempted logins -exceed some threashold and/or resets that counter to zero on successful -login. - -Root is treated specially: - -1. When a process already running as root tries to access some service, the -access is `magic', and bypasses pam_tally's checks: handy for `su'ing from -root into an account otherwise blocked. However, for services like telnet or -login which always effectively run from the root account, root (ie everyone) -shouldn't be granted this magic status, and the flag `no_magic_root' should -be set in this situation, as noted in the summary above. [This option may -be obsolete, with `sufficient root' processing.] - -2. Normally, failed attempts to access root will NOT cause the root -account to become blocked, to prevent denial-of-service: if your users aren't -given shell accounts and root may only login via `su' or at the machine -console (not telnet/rsh, etc), this is safe. If you really want root to be -blocked for some given service, use even_deny_root_account. - -pam_tally is an (optional) application which can be used to interrogate and -manipulate the counter file. It can display users' counts, set individual -counts, or clear all counts. Setting artificially high counts may be useful -for blocking users without changing their passwords. I found it useful to -clear all counts every midnight from a cron.. - -The counts file is organised as a binary-word array, indexed by uid. You -can probably make sense of it with `od', if you don't want to use the -supplied application. - -BUGS: - -pam_tally is very dependant on getpw*(): a database of usernames -would be much more flexible. - -The (4.0 Redhat) utilities seem to do funny things with uid, and I'm -not wholly sure I understood what I should have been doing anyway so -the `keep a count of current logins' bit has been #ifdef'd out and you -can only reset the counter on successful authentication, for now. diff --git a/modules/pam_tally/faillog.h b/modules/pam_tally/faillog.h deleted file mode 100644 index 7f704713..00000000 --- a/modules/pam_tally/faillog.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 1989 - 1994, Julianne Frances Haugh - * 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, this list of conditions and the following disclaimer. - * 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. Neither the name of Julianne F. Haugh nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. - */ - -/* - * faillog.h - login failure logging file format - * - * $Id$ - * - * The login failure file is maintained by login(1) and faillog(8) - * Each record in the file represents a separate UID and the file - * is indexed in that fashion. - */ - -#ifndef _FAILLOG_H -#define _FAILLOG_H - -struct faillog { - short fail_cnt; /* failures since last success */ - short fail_max; /* failures before turning account off */ - char fail_line[12]; /* last failure occured here */ - time_t fail_time; /* last failure occured then */ - /* - * If nonzero, the account will be re-enabled if there are no - * failures for fail_locktime seconds since last failure. - */ - long fail_locktime; -}; - -#endif diff --git a/modules/pam_tally/pam_tally.c b/modules/pam_tally/pam_tally.c deleted file mode 100644 index 3da37f40..00000000 --- a/modules/pam_tally/pam_tally.c +++ /dev/null @@ -1,735 +0,0 @@ -/* - * pam_tally.c - * - * $Id$ - */ - - -/* By Tim Baverstock <warwick@mmm.co.uk>, Multi Media Machine Ltd. - * 5 March 1997 - * - * Stuff stolen from pam_rootok and pam_listfile - */ - -#include <security/_pam_aconf.h> - -#if defined(MAIN) && defined(MEMORY_DEBUG) -# undef exit -#endif /* defined(MAIN) && defined(MEMORY_DEBUG) */ - -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <stdarg.h> -#include <stdlib.h> -#include <syslog.h> -#include <pwd.h> -#include <time.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> -#include "faillog.h" - -#ifndef TRUE -#define TRUE 1L -#define FALSE 0L -#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 -/* #define PAM_SM_SESSION */ -/* #define PAM_SM_PASSWORD */ - -#include <security/pam_modules.h> - -/*---------------------------------------------------------------------*/ - -#define DEFAULT_LOGFILE "/var/log/faillog" -#define MODULE_NAME "pam_tally" - -enum TALLY_RESET { - TALLY_RESET_DEFAULT, - TALLY_RESET_RESET, - TALLY_RESET_NO_RESET -}; - -#define tally_t unsigned short int -#define TALLY_FMT "%hu" -#define TALLY_HI ((tally_t)~0L) - -#define UID_FMT "%hu" - -#ifndef FILENAME_MAX -# define FILENAME_MAX MAXPATHLEN -#endif - -struct fail_s { - struct faillog fs_faillog; -#ifndef MAIN - time_t fs_fail_time; -#endif /* ndef MAIN */ -}; - -/*---------------------------------------------------------------------*/ - -/* some syslogging */ - -static void _pam_log(int err, const char *format, ...) -{ - va_list args; - va_start(args, format); - -#ifdef MAIN - vfprintf(stderr,format,args); - fprintf(stderr,"\n"); -#else - openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); - closelog(); -#endif - va_end(args); -} - -/*---------------------------------------------------------------------*/ - -/* --- Support function: get uid (and optionally username) from PAM or - cline_user --- */ - -#ifdef MAIN -static char *cline_user=0; /* cline_user is used in the administration prog */ -#endif - -static int pam_get_uid( pam_handle_t *pamh, uid_t *uid, const char **userp ) - { - const char *user; - struct passwd *pw; - -#ifdef MAIN - user = cline_user; -#else - pam_get_user( pamh, &user, NULL ); -#endif - - if ( !user || !*user ) { - _pam_log(LOG_ERR, MODULE_NAME ": pam_get_uid; user?"); - return PAM_AUTH_ERR; - } - - if ( ! ( pw = getpwnam( user ) ) ) { - _pam_log(LOG_ERR,MODULE_NAME ": pam_get_uid; no such user %s",user); - return PAM_USER_UNKNOWN; - } - - if ( uid ) *uid = pw->pw_uid; - if ( userp ) *userp = user; - return PAM_SUCCESS; - } - -/*---------------------------------------------------------------------*/ - -/* --- Support function: open/create tallyfile and return tally for uid --- */ - -/* If on entry *tally==TALLY_HI, tallyfile is opened READONLY */ -/* Otherwise, if on entry tallyfile doesn't exist, creation is attempted. */ - -static int get_tally( tally_t *tally, - uid_t uid, - const char *filename, - FILE **TALLY, - struct fail_s *fsp) - { - struct stat fileinfo; - int lstat_ret = lstat(filename,&fileinfo); - - if ( lstat_ret && *tally!=TALLY_HI ) { - int oldmask = umask(077); - *TALLY=fopen(filename, "a"); - /* Create file, or append-open in pathological case. */ - umask(oldmask); - if ( !*TALLY ) { - _pam_log(LOG_ALERT, "Couldn't create %s",filename); - return PAM_AUTH_ERR; - } - lstat_ret = fstat(fileno(*TALLY),&fileinfo); - fclose(*TALLY); - } - - if ( lstat_ret ) { - _pam_log(LOG_ALERT, "Couldn't stat %s",filename); - return PAM_AUTH_ERR; - } - - if((fileinfo.st_mode & S_IWOTH) || !S_ISREG(fileinfo.st_mode)) { - /* If the file is world writable or is not a - normal file, return error */ - _pam_log(LOG_ALERT, - "%s is either world writable or not a normal file", - filename); - return PAM_AUTH_ERR; - } - - if ( ! ( *TALLY = fopen(filename,(*tally!=TALLY_HI)?"r+":"r") ) ) { - _pam_log(LOG_ALERT, "Error opening %s for update", filename); - -/* Discovering why account service fails: e/uid are target user. - * - * perror(MODULE_NAME); - * fprintf(stderr,"uid %d euid %d\n",getuid(), geteuid()); - */ - return PAM_AUTH_ERR; - } - - if ( fseek( *TALLY, uid * sizeof(struct faillog), SEEK_SET ) ) { - _pam_log(LOG_ALERT, "fseek failed %s", filename); - return PAM_AUTH_ERR; - } - - if ( fileinfo.st_size <= uid * sizeof(struct faillog) ) { - - memset(fsp, 0, sizeof(struct faillog)); - *tally=0; - fsp->fs_faillog.fail_time = time(NULL); - - } else if (( fread((char *) &fsp->fs_faillog, - sizeof(struct faillog), 1, *TALLY) )==0 ) { - - *tally=0; /* Assuming a gappy filesystem */ - - } else { - - *tally = fsp->fs_faillog.fail_cnt; - - } - - return PAM_SUCCESS; - } - -/*---------------------------------------------------------------------*/ - -/* --- Support function: update and close tallyfile with tally!=TALLY_HI --- */ - -static int set_tally( tally_t tally, - uid_t uid, - const char *filename, - FILE **TALLY, - struct fail_s *fsp) - { - if ( tally!=TALLY_HI ) - { - if ( fseek( *TALLY, uid * sizeof(struct faillog), SEEK_SET ) ) { - _pam_log(LOG_ALERT, "fseek failed %s", filename); - return PAM_AUTH_ERR; - } - fsp->fs_faillog.fail_cnt = tally; - if (fwrite((char *) &fsp->fs_faillog, - sizeof(struct faillog), 1, *TALLY)==0 ) { - _pam_log(LOG_ALERT, "tally update (fwrite) failed.", filename); - return PAM_AUTH_ERR; - } - } - - if ( fclose(*TALLY) ) { - _pam_log(LOG_ALERT, "tally update (fclose) failed.", filename); - return PAM_AUTH_ERR; - } - *TALLY=NULL; - return PAM_SUCCESS; - } - -/*---------------------------------------------------------------------*/ - -/* --- PAM bits --- */ - -#ifndef MAIN - -#define PAM_FUNCTION(name) \ - PAM_EXTERN int name (pam_handle_t *pamh,int flags,int argc,const char **argv) - -#define RETURN_ERROR(i) return ((fail_on_error)?(i):(PAM_SUCCESS)) - -/*---------------------------------------------------------------------*/ - -/* --- tally bump function: bump tally for uid by (signed) inc --- */ - -static int tally_bump (int inc, - pam_handle_t *pamh, - int flags, - int argc, - const char **argv) { - uid_t uid; - - int - fail_on_error = FALSE; - tally_t - tally = 0; /* !TALLY_HI --> Log opened for update */ - - char - no_magic_root = FALSE; - - char - filename[ FILENAME_MAX ] = DEFAULT_LOGFILE; - - /* Should probably decode the parameters before anything else. */ - - { - for ( ; argc-- > 0; ++argv ) { - - /* generic options.. um, ignored. :] */ - - if ( ! strcmp( *argv, "no_magic_root" ) ) { - no_magic_root = TRUE; - } - else if ( ! strncmp( *argv, "file=", 5 ) ) { - char const - *from = (*argv)+5; - char - *to = filename; - if ( *from!='/' || strlen(from)>FILENAME_MAX-1 ) { - _pam_log(LOG_ERR, - MODULE_NAME ": filename not /rooted or too long; ", - *argv); - RETURN_ERROR( PAM_AUTH_ERR ); - } - while ( ( *to++ = *from++ ) ); - } - else if ( ! strcmp( *argv, "onerr=fail" ) ) { - fail_on_error=TRUE; - } - else if ( ! strcmp( *argv, "onerr=succeed" ) ) { - fail_on_error=FALSE; - } - else { - _pam_log(LOG_ERR, MODULE_NAME ": unknown option; %s",*argv); - } - } /* for() */ - } - - { - FILE - *TALLY = NULL; - const char - *user = NULL, - *remote_host = NULL, - *cur_tty = NULL; - struct fail_s fs, *fsp = &fs; - - int i=pam_get_uid(pamh, &uid, &user); - if ( i != PAM_SUCCESS ) RETURN_ERROR( i ); - - i=get_tally( &tally, uid, filename, &TALLY, fsp ); - - /* to remember old fail time (for locktime) */ - fsp->fs_fail_time = fsp->fs_faillog.fail_time; - fsp->fs_faillog.fail_time = time(NULL); - (void) pam_get_item(pamh, PAM_RHOST, (const void **)&remote_host); - if (!remote_host) { - - (void) pam_get_item(pamh, PAM_TTY, (const void **)&cur_tty); - if (!cur_tty) { - strncpy(fsp->fs_faillog.fail_line, "unknown", - sizeof(fsp->fs_faillog.fail_line) - 1); - fsp->fs_faillog.fail_line[sizeof(fsp->fs_faillog.fail_line)-1] = 0; - } else { - strncpy(fsp->fs_faillog.fail_line, cur_tty, - sizeof(fsp->fs_faillog.fail_line)-1); - fsp->fs_faillog.fail_line[sizeof(fsp->fs_faillog.fail_line)-1] = 0; - } - - } else { - strncpy(fsp->fs_faillog.fail_line, remote_host, - (size_t)sizeof(fsp->fs_faillog.fail_line)); - fsp->fs_faillog.fail_line[sizeof(fsp->fs_faillog.fail_line)-1] = 0; - } - if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } - - if ( no_magic_root || getuid() ) { /* no_magic_root kills uid test */ - - tally+=inc; - - if ( tally==TALLY_HI ) { /* Overflow *and* underflow. :) */ - tally-=inc; - _pam_log(LOG_ALERT,"Tally %sflowed for user %s", - (inc<0)?"under":"over",user); - } - } - - i=set_tally( tally, uid, filename, &TALLY, fsp ); - if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } - } - - return PAM_SUCCESS; -} - -/*---------------------------------------------------------------------*/ - -/* --- authentication management functions (only) --- */ - -#ifdef PAM_SM_AUTH - -PAM_FUNCTION( pam_sm_authenticate ) { - return tally_bump( 1, pamh, flags, argc, argv); -} - -/* --- Seems to need this function. Ho hum. --- */ - -PAM_FUNCTION( pam_sm_setcred ) { return PAM_SUCCESS; } - -#endif - -/*---------------------------------------------------------------------*/ - -/* --- session management functions (only) --- */ - -/* - * Unavailable until .so files can be suid - */ - -#ifdef PAM_SM_SESSION - -/* To maintain a balance-tally of successful login/outs */ - -PAM_FUNCTION( pam_sm_open_session ) { - return tally_bump( 1, pamh, flags, argc, argv); -} - -PAM_FUNCTION( pam_sm_close_session ) { - return tally_bump(-1, pamh, flags, argc, argv); -} - -#endif - -/*---------------------------------------------------------------------*/ - -/* --- authentication management functions (only) --- */ - -#ifdef PAM_SM_AUTH - -/* To lock out a user with an unacceptably high tally */ - -PAM_FUNCTION( pam_sm_acct_mgmt ) { - uid_t - uid; - - int - fail_on_error = FALSE; - tally_t - deny = 0; - tally_t - tally = 0; /* !TALLY_HI --> Log opened for update */ - - char - no_magic_root = FALSE, - even_deny_root_account = FALSE; - char per_user = FALSE; /* if true then deny=.fail_max for user */ - char no_lock_time = FALSE; /* if true then don't use .fail_locktime */ - - const char - *user = NULL; - - enum TALLY_RESET - reset = TALLY_RESET_DEFAULT; - - char - filename[ FILENAME_MAX ] = DEFAULT_LOGFILE; - - /* Should probably decode the parameters before anything else. */ - - { - for ( ; argc-- > 0; ++argv ) { - - /* generic options.. um, ignored. :] */ - - if ( ! strcmp( *argv, "no_magic_root" ) ) { - no_magic_root = TRUE; - } - else if ( ! strcmp( *argv, "even_deny_root_account" ) ) { - even_deny_root_account = TRUE; - } - else if ( ! strcmp( *argv, "reset" ) ) { - reset = TALLY_RESET_RESET; - } - else if ( ! strcmp( *argv, "no_reset" ) ) { - reset = TALLY_RESET_NO_RESET; - } - else if ( ! strncmp( *argv, "file=", 5 ) ) { - char const - *from = (*argv)+5; - char - *to = filename; - if ( *from != '/' || strlen(from) > FILENAME_MAX-1 ) { - _pam_log(LOG_ERR, - MODULE_NAME ": filename not /rooted or too long; ", - *argv); - RETURN_ERROR( PAM_AUTH_ERR ); - } - while ( ( *to++ = *from++ ) ); - } - else if ( ! strncmp( *argv, "deny=", 5 ) ) { - if ( sscanf((*argv)+5,TALLY_FMT,&deny) != 1 ) { - _pam_log(LOG_ERR,"bad number supplied; %s",*argv); - RETURN_ERROR( PAM_AUTH_ERR ); - } - } - else if ( ! strcmp( *argv, "onerr=fail" ) ) { - fail_on_error=TRUE; - } - else if ( ! strcmp( *argv, "onerr=succeed" ) ) { - fail_on_error=FALSE; - } - else if ( ! strcmp( *argv, "per_user" ) ) - { - per_user = TRUE; - } - else if ( ! strcmp( *argv, "no_lock_time") ) - { - no_lock_time = TRUE; - } - else { - _pam_log(LOG_ERR, MODULE_NAME ": unknown option; %s",*argv); - } - } /* for() */ - } - - { - struct fail_s fs, *fsp = &fs; - FILE *TALLY=0; - int i=pam_get_uid(pamh, &uid, &user); - if ( i != PAM_SUCCESS ) RETURN_ERROR( i ); - - i=get_tally( &tally, uid, filename, &TALLY, fsp ); - if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } - - if ( no_magic_root || getuid() ) { /* no_magic_root kills uid test */ - - /* To deny or not to deny; that is the question */ - - /* if there's .fail_max entry and per_user=TRUE then deny=.fail_max */ - - if ( (fsp->fs_faillog.fail_max) && (per_user) ) { - deny = fsp->fs_faillog.fail_max; - } - if (fsp->fs_faillog.fail_locktime && fsp->fs_fail_time - && (!no_lock_time) ) - { - if ( (fsp->fs_faillog.fail_locktime + fsp->fs_fail_time) > time(NULL) ) - { - _pam_log(LOG_NOTICE, - "user %s ("UID_FMT") has time limit [%lds left]" - " since last failure.", - user,uid, - fsp->fs_fail_time+fsp->fs_faillog.fail_locktime - -time(NULL)); - return PAM_AUTH_ERR; - } - } - if ( - ( deny != 0 ) && /* deny==0 means no deny */ - ( tally > deny ) && /* tally>deny means exceeded */ - ( even_deny_root_account || uid ) /* even_deny stops uid check */ - ) { - _pam_log(LOG_NOTICE,"user %s ("UID_FMT") tally "TALLY_FMT", deny "TALLY_FMT, - user, uid, tally, deny); - return PAM_AUTH_ERR; /* Only unconditional failure */ - } - - /* resets for explicit reset - * or by default if deny exists and not magic-root - */ - - if ( ( reset == TALLY_RESET_RESET ) || - ( reset == TALLY_RESET_DEFAULT && deny ) ) { tally=0; } - } - else /* is magic root */ { - - /* Magic root skips deny test... */ - - /* Magic root only resets on explicit reset, regardless of deny */ - - if ( reset == TALLY_RESET_RESET ) { tally=0; } - } - if (tally == 0) - { - fsp->fs_faillog.fail_time = (time_t) 0; - strcpy(fsp->fs_faillog.fail_line, ""); - } - i=set_tally( tally, uid, filename, &TALLY, fsp ); - if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); } - } - - return PAM_SUCCESS; -} - -#endif /* #ifdef PAM_SM_AUTH */ - -/*-----------------------------------------------------------------------*/ - -#ifdef PAM_STATIC - -/* static module data */ - -struct pam_module _pam_tally_modstruct = { - MODULE_NAME, -#ifdef PAM_SM_AUTH - pam_sm_authenticate, - pam_sm_setcred, -#else - NULL, - NULL, -#endif -#ifdef PAM_SM_ACCOUNT - pam_sm_acct_mgmt, -#else - NULL, -#endif -#ifdef PAM_SM_SESSION - pam_sm_open_session, - pam_sm_close_session, -#else - NULL, - NULL, -#endif -#ifdef PAM_SM_PASSWORD - pam_sm_chauthtok, -#else - NULL, -#endif -}; - -#endif /* #ifdef PAM_STATIC */ - -/*-----------------------------------------------------------------------*/ - -#else /* #ifndef MAIN */ - -static const char *cline_filename = DEFAULT_LOGFILE; -static tally_t cline_reset = TALLY_HI; /* Default is `interrogate only' */ -static int cline_quiet = 0; - -/* - * Not going to link with pamlib just for these.. :) - */ - -static const char * pam_errors( int i ) { - switch (i) { - case PAM_AUTH_ERR: return "Authentication error"; - case PAM_SERVICE_ERR: return "Service error"; - case PAM_USER_UNKNOWN: return "Unknown user"; - default: return "Unknown error"; - } -} - -static int getopts( int argc, char **argv ) { - const char *pname = *argv; - for ( ; *argv ; (void)(*argv && ++argv) ) { - if ( !strcmp (*argv,"--file") ) cline_filename=*++argv; - else if ( !strncmp(*argv,"--file=",7) ) cline_filename=*argv+7; - else if ( !strcmp (*argv,"--user") ) cline_user=*++argv; - else if ( !strncmp(*argv,"--user=",7) ) cline_user=*argv+7; - else if ( !strcmp (*argv,"--reset") ) cline_reset=0; - else if ( !strncmp(*argv,"--reset=",8)) { - if ( sscanf(*argv+8,TALLY_FMT,&cline_reset) != 1 ) - fprintf(stderr,"%s: Bad number given to --reset=\n",pname), exit(0); - } - else if ( !strcmp (*argv,"--quiet") ) cline_quiet=1; - else { - fprintf(stderr,"%s: Unrecognised option %s\n",pname,*argv); - return FALSE; - } - } - return TRUE; -} - -int main ( int argc, char **argv ) { - - struct fail_s fs, *fsp = &fs; - - if ( ! getopts( argc, argv+1 ) ) { - printf("%s: [--file rooted-filename] [--user username] " - "[--reset[=n]] [--quiet]\n", - *argv); - exit(0); - } - - umask(077); - - /* - * Major difference between individual user and all users: - * --user just handles one user, just like PAM. - * --user=* handles all users, sniffing cline_filename for nonzeros - */ - - if ( cline_user ) { - uid_t uid; - tally_t tally=cline_reset; - FILE *TALLY=0; - int i=pam_get_uid( NULL, &uid, NULL); - if ( i != PAM_SUCCESS ) { - fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); - exit(0); - } - - i=get_tally( &tally, uid, cline_filename, &TALLY, fsp ); - if ( i != PAM_SUCCESS ) { - if (TALLY) fclose(TALLY); - fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); - exit(0); - } - - if ( !cline_quiet ) - printf("User %s\t("UID_FMT")\t%s "TALLY_FMT"\n",cline_user,uid, - (cline_reset!=TALLY_HI)?"had":"has",tally); - - i=set_tally( cline_reset, uid, cline_filename, &TALLY, fsp ); - if ( i != PAM_SUCCESS ) { - if (TALLY) fclose(TALLY); - fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); - exit(0); - } - } - else /* !cline_user (ie, operate on all users) */ { - FILE *TALLY=fopen(cline_filename, "r"); - uid_t uid=0; - if ( !TALLY ) perror(*argv), exit(0); - - for ( ; !feof(TALLY); uid++ ) { - tally_t tally; - struct passwd *pw; - if ( ! fread((char *) &fsp->fs_faillog, - sizeof (struct faillog), 1, TALLY) - || ! fsp->fs_faillog.fail_cnt ) { - continue; - } - tally = fsp->fs_faillog.fail_cnt; - - if ( ( pw=getpwuid(uid) ) ) { - printf("User %s\t("UID_FMT")\t%s "TALLY_FMT"\n",pw->pw_name,uid, - (cline_reset!=TALLY_HI)?"had":"has",tally); - } - else { - printf("User [NONAME]\t("UID_FMT")\t%s "TALLY_FMT"\n",uid, - (cline_reset!=TALLY_HI)?"had":"has",tally); - } - } - fclose(TALLY); - if ( cline_reset!=0 && cline_reset!=TALLY_HI ) { - fprintf(stderr,"%s: Can't reset all users to non-zero\n",*argv); - } - else if ( !cline_reset ) { - TALLY=fopen(cline_filename, "w"); - if ( !TALLY ) perror(*argv), exit(0); - fclose(TALLY); - } - } - return 0; -} - - -#endif diff --git a/modules/pam_tally/pam_tally_app.c b/modules/pam_tally/pam_tally_app.c deleted file mode 100644 index 9e6e1faf..00000000 --- a/modules/pam_tally/pam_tally_app.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - # This seemed like such a good idea at the time. :) - */ - -#define MAIN -#include "pam_tally.c" - |