diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml --- Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100 +++ Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml 2022-05-25 15:30:33.700518571 +0200 @@ -57,12 +57,29 @@ + + + + + The file where the configuration is located. The default is + /etc/security/faillock.conf. + + + + + - The directory where the user files with the failure records are kept. The - default is /var/run/faillock. + The directory where the user files with the failure records are kept. + + + The priority to set this option is to use the value provided + from the command line. If this isn't provided, then the value + from the configuration file is used. Finally, if neither of + them has been provided, then + /var/run/faillock is used. diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c --- Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file 2022-05-25 15:30:33.699518564 +0200 +++ Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c 2022-05-25 15:30:33.700518571 +0200 @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2022 Tomas Mraz + * Copyright (c) 2022 Iker Pedrosa + * + * 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. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "faillock_config.h" +#include "faillock.h" + +#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf" + +static void PAM_FORMAT((printf, 3, 4)) PAM_NONNULL((3)) +config_log(const pam_handle_t *pamh, int priority, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + if (pamh) { + pam_vsyslog(pamh, priority, fmt, args); + } else { + char *buf = NULL; + + if (vasprintf(&buf, fmt, args) < 0) { + fprintf(stderr, "vasprintf: %m"); + va_end(args); + return; + } + fprintf(stderr, "%s\n", buf); + free(buf); + } + va_end(args); +} + +/* parse a single configuration file */ +int +read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile) +{ + char linebuf[FAILLOCK_CONF_MAX_LINELEN+1]; + const char *fname = (cfgfile != NULL) ? cfgfile : FAILLOCK_DEFAULT_CONF; + FILE *f = fopen(fname, "r"); + +#ifdef VENDOR_FAILLOCK_DEFAULT_CONF + if (f == NULL && errno == ENOENT && cfgfile == NULL) { + /* + * If the default configuration file in /etc does not exist, + * try the vendor configuration file as fallback. + */ + f = fopen(VENDOR_FAILLOCK_DEFAULT_CONF, "r"); + } +#endif /* VENDOR_FAILLOCK_DEFAULT_CONF */ + + if (f == NULL) { + /* ignore non-existent default config file */ + if (errno == ENOENT && cfgfile == NULL) + return PAM_SUCCESS; + return PAM_SERVICE_ERR; + } + + while (fgets(linebuf, sizeof(linebuf), f) != NULL) { + size_t len; + char *ptr; + char *name; + int eq; + + len = strlen(linebuf); + /* len cannot be 0 unless there is a bug in fgets */ + if (len && linebuf[len - 1] != '\n' && !feof(f)) { + (void) fclose(f); + return PAM_SERVICE_ERR; + } + + if ((ptr=strchr(linebuf, '#')) != NULL) { + *ptr = '\0'; + } else { + ptr = linebuf + len; + } + + /* drop terminating whitespace including the \n */ + while (ptr > linebuf) { + if (!isspace(*(ptr-1))) { + *ptr = '\0'; + break; + } + --ptr; + } + + /* skip initial whitespace */ + for (ptr = linebuf; isspace(*ptr); ptr++); + if (*ptr == '\0') + continue; + + /* grab the key name */ + eq = 0; + name = ptr; + while (*ptr != '\0') { + if (isspace(*ptr) || *ptr == '=') { + eq = *ptr == '='; + *ptr = '\0'; + ++ptr; + break; + } + ++ptr; + } + + /* grab the key value */ + while (*ptr != '\0') { + if (*ptr != '=' || eq) { + if (!isspace(*ptr)) { + break; + } + } else { + eq = 1; + } + ++ptr; + } + + /* set the key:value pair on opts */ + set_conf_opt(pamh, opts, name, ptr); + } + + (void)fclose(f); + return PAM_SUCCESS; +} + +void +set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, + const char *value) +{ + if (strcmp(name, "dir") == 0) { + if (value[0] != '/') { + config_log(pamh, LOG_ERR, + "Tally directory is not absolute path (%s); keeping value", + value); + } else { + free(opts->dir); + opts->dir = strdup(value); + if (opts->dir == NULL) { + opts->fatal_error = 1; + config_log(pamh, LOG_CRIT, "Error allocating memory: %m"); + } + } + } + else if (strcmp(name, "deny") == 0) { + if (sscanf(value, "%hu", &opts->deny) != 1) { + config_log(pamh, LOG_ERR, + "Bad number supplied for deny argument"); + } + } + else if (strcmp(name, "fail_interval") == 0) { + unsigned int temp; + if (sscanf(value, "%u", &temp) != 1 || + temp > MAX_TIME_INTERVAL) { + config_log(pamh, LOG_ERR, + "Bad number supplied for fail_interval argument"); + } else { + opts->fail_interval = temp; + } + } + else if (strcmp(name, "unlock_time") == 0) { + unsigned int temp; + + if (strcmp(value, "never") == 0) { + opts->unlock_time = 0; + } + else if (sscanf(value, "%u", &temp) != 1 || + temp > MAX_TIME_INTERVAL) { + config_log(pamh, LOG_ERR, + "Bad number supplied for unlock_time argument"); + } + else { + opts->unlock_time = temp; + } + } + else if (strcmp(name, "root_unlock_time") == 0) { + unsigned int temp; + + if (strcmp(value, "never") == 0) { + opts->root_unlock_time = 0; + } + else if (sscanf(value, "%u", &temp) != 1 || + temp > MAX_TIME_INTERVAL) { + config_log(pamh, LOG_ERR, + "Bad number supplied for root_unlock_time argument"); + } else { + opts->root_unlock_time = temp; + } + } + else if (strcmp(name, "admin_group") == 0) { + free(opts->admin_group); + opts->admin_group = strdup(value); + if (opts->admin_group == NULL) { + opts->fatal_error = 1; + config_log(pamh, LOG_CRIT, "Error allocating memory: %m"); + } + } + else if (strcmp(name, "even_deny_root") == 0) { + opts->flags |= FAILLOCK_FLAG_DENY_ROOT; + } + else if (strcmp(name, "audit") == 0) { + opts->flags |= FAILLOCK_FLAG_AUDIT; + } + else if (strcmp(name, "silent") == 0) { + opts->flags |= FAILLOCK_FLAG_SILENT; + } + else if (strcmp(name, "no_log_info") == 0) { + opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; + } + else if (strcmp(name, "local_users_only") == 0) { + opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY; + } + else if (strcmp(name, "nodelay") == 0) { + opts->flags |= FAILLOCK_FLAG_NO_DELAY; + } + else { + config_log(pamh, LOG_ERR, "Unknown option: %s", name); + } +} + +const char *get_tally_dir(const struct options *opts) +{ + return (opts->dir != NULL) ? opts->dir : FAILLOCK_DEFAULT_TALLYDIR; +} diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h --- Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file 2022-05-25 15:30:33.699518564 +0200 +++ Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h 2022-05-25 15:30:33.700518571 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022 Tomas Mraz + * Copyright (c) 2022 Iker Pedrosa + * + * 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. + */ + +/* + * faillock_config.h - load configuration options from file + * + */ + +#ifndef _FAILLOCK_CONFIG_H +#define _FAILLOCK_CONFIG_H + +#include +#include +#include + +#include + +#define FAILLOCK_FLAG_DENY_ROOT 0x1 +#define FAILLOCK_FLAG_AUDIT 0x2 +#define FAILLOCK_FLAG_SILENT 0x4 +#define FAILLOCK_FLAG_NO_LOG_INFO 0x8 +#define FAILLOCK_FLAG_UNLOCKED 0x10 +#define FAILLOCK_FLAG_LOCAL_ONLY 0x20 +#define FAILLOCK_FLAG_NO_DELAY 0x40 + +#define FAILLOCK_CONF_MAX_LINELEN 1023 +#define MAX_TIME_INTERVAL 604800 /* 7 days */ + +struct options { + unsigned int action; + unsigned int flags; + unsigned short deny; + unsigned int fail_interval; + unsigned int unlock_time; + unsigned int root_unlock_time; + char *dir; + const char *user; + char *admin_group; + int failures; + uint64_t latest_time; + uid_t uid; + int is_admin; + uint64_t now; + int fatal_error; + + unsigned int reset; + const char *progname; +}; + +int read_config_file(pam_handle_t *pamh, struct options *opts, + const char *cfgfile); +void set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, + const char *value); +const char *get_tally_dir(const struct options *opts); + +#endif /* _FAILLOCK_CONFIG_H */ diff -up Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/main.c --- Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100 +++ Linux-PAM-1.5.1/modules/pam_faillock/main.c 2022-05-25 15:37:05.801216176 +0200 @@ -51,33 +51,40 @@ #define AUDIT_NO_ID ((unsigned int) -1) #endif +#include "pam_inline.h" #include "faillock.h" - -struct options { - unsigned int reset; - const char *dir; - const char *user; - const char *progname; -}; +#include "faillock_config.h" static int args_parse(int argc, char **argv, struct options *opts) { int i; + int rv; + const char *dir = NULL; + const char *conf = NULL; + memset(opts, 0, sizeof(*opts)); - opts->dir = FAILLOCK_DEFAULT_TALLYDIR; opts->progname = argv[0]; for (i = 1; i < argc; ++i) { - - if (strcmp(argv[i], "--dir") == 0) { + if (strcmp(argv[i], "--conf") == 0) { + ++i; + if (i >= argc || strlen(argv[i]) == 0) { + fprintf(stderr, "%s: No configuration file supplied.\n", + argv[0]); + return -1; + } + conf = argv[i]; + } + else if (strcmp(argv[i], "--dir") == 0) { ++i; if (i >= argc || strlen(argv[i]) == 0) { - fprintf(stderr, "%s: No directory supplied.\n", argv[0]); + fprintf(stderr, "%s: No records directory supplied.\n", + argv[0]); return -1; } - opts->dir = argv[i]; + dir = argv[i]; } else if (strcmp(argv[i], "--user") == 0) { ++i; @@ -85,7 +92,7 @@ args_parse(int argc, char **argv, struct fprintf(stderr, "%s: No user name supplied.\n", argv[0]); return -1; } - opts->user = argv[i]; + opts->user = argv[i]; } else if (strcmp(argv[i], "--reset") == 0) { opts->reset = 1; @@ -95,6 +102,21 @@ args_parse(int argc, char **argv, struct return -1; } } + + if ((rv = read_config_file(NULL, opts, conf)) != PAM_SUCCESS) { + fprintf(stderr, "Configuration file missing or broken"); + return rv; + } + + if (dir != NULL) { + free(opts->dir); + opts->dir = strdup(dir); + if (opts->dir == NULL) { + fprintf(stderr, "Error allocating memory: %m"); + return -1; + } + } + return 0; } @@ -112,10 +134,11 @@ do_user(struct options *opts, const char int rv; struct tally_data tallies; struct passwd *pwd; + const char *dir = get_tally_dir(opts); pwd = getpwnam(user); - fd = open_tally(opts->dir, user, pwd != NULL ? pwd->pw_uid : 0, 0); + fd = open_tally(dir, user, pwd != NULL ? pwd->pw_uid : 0, 0); if (fd == -1) { if (errno == ENOENT) { @@ -191,8 +214,9 @@ do_allusers(struct options *opts) { struct dirent **userlist; int rv, i; + const char *dir = get_tally_dir(opts); - rv = scandir(opts->dir, &userlist, NULL, alphasort); + rv = scandir(dir, &userlist, NULL, alphasort); if (rv < 0) { fprintf(stderr, "%s: Error reading tally directory: %m\n", opts->progname); return 2; diff -up Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am --- Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100 +++ Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am 2022-05-25 15:30:33.700518571 +0200 @@ -20,7 +20,7 @@ TESTS = $(dist_check_SCRIPTS) securelibdir = $(SECUREDIR) secureconfdir = $(SCONFIGDIR) -noinst_HEADERS = faillock.h +noinst_HEADERS = faillock.h faillock_config.h AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ $(WARN_CFLAGS) @@ -41,8 +41,8 @@ dist_secureconf_DATA = faillock.conf securelib_LTLIBRARIES = pam_faillock.la sbin_PROGRAMS = faillock -pam_faillock_la_SOURCES = pam_faillock.c faillock.c -faillock_SOURCES = main.c faillock.c +pam_faillock_la_SOURCES = pam_faillock.c faillock.c faillock_config.c +faillock_SOURCES = main.c faillock.c faillock_config.c if ENABLE_REGENERATE_MAN dist_noinst_DATA = README diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c --- Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100 +++ Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c 2022-05-25 15:33:03.885551825 +0200 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -56,55 +55,12 @@ #include "pam_inline.h" #include "faillock.h" +#include "faillock_config.h" #define FAILLOCK_ACTION_PREAUTH 0 #define FAILLOCK_ACTION_AUTHSUCC 1 #define FAILLOCK_ACTION_AUTHFAIL 2 -#define FAILLOCK_FLAG_DENY_ROOT 0x1 -#define FAILLOCK_FLAG_AUDIT 0x2 -#define FAILLOCK_FLAG_SILENT 0x4 -#define FAILLOCK_FLAG_NO_LOG_INFO 0x8 -#define FAILLOCK_FLAG_UNLOCKED 0x10 -#define FAILLOCK_FLAG_LOCAL_ONLY 0x20 -#define FAILLOCK_FLAG_NO_DELAY 0x40 - -#define MAX_TIME_INTERVAL 604800 /* 7 days */ -#define FAILLOCK_CONF_MAX_LINELEN 1023 - -static const char default_faillock_conf[] = FAILLOCK_DEFAULT_CONF; - -struct options { - unsigned int action; - unsigned int flags; - unsigned short deny; - unsigned int fail_interval; - unsigned int unlock_time; - unsigned int root_unlock_time; - char *dir; - const char *user; - char *admin_group; - int failures; - uint64_t latest_time; - uid_t uid; - int is_admin; - uint64_t now; - int fatal_error; -}; - -static int read_config_file( - pam_handle_t *pamh, - struct options *opts, - const char *cfgfile -); - -static void set_conf_opt( - pam_handle_t *pamh, - struct options *opts, - const char *name, - const char *value -); - static int args_parse(pam_handle_t *pamh, int argc, const char **argv, int flags, struct options *opts) @@ -112,11 +68,10 @@ args_parse(pam_handle_t *pamh, int argc, int i; int config_arg_index = -1; int rv; - const char *conf = default_faillock_conf; + const char *conf = NULL; memset(opts, 0, sizeof(*opts)); - opts->dir = strdup(FAILLOCK_DEFAULT_TALLYDIR); opts->deny = 3; opts->fail_interval = 900; opts->unlock_time = 600; @@ -174,185 +129,11 @@ args_parse(pam_handle_t *pamh, int argc, if (flags & PAM_SILENT) opts->flags |= FAILLOCK_FLAG_SILENT; - if (opts->dir == NULL) { - pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); - opts->fatal_error = 1; - } - if (opts->fatal_error) return PAM_BUF_ERR; return PAM_SUCCESS; } -/* parse a single configuration file */ -static int -read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile) -{ - FILE *f; - char linebuf[FAILLOCK_CONF_MAX_LINELEN+1]; - - f = fopen(cfgfile, "r"); - if (f == NULL) { - /* ignore non-existent default config file */ - if (errno == ENOENT && cfgfile == default_faillock_conf) - return PAM_SUCCESS; - return PAM_SERVICE_ERR; - } - - while (fgets(linebuf, sizeof(linebuf), f) != NULL) { - size_t len; - char *ptr; - char *name; - int eq; - - len = strlen(linebuf); - /* len cannot be 0 unless there is a bug in fgets */ - if (len && linebuf[len - 1] != '\n' && !feof(f)) { - (void) fclose(f); - return PAM_SERVICE_ERR; - } - - if ((ptr=strchr(linebuf, '#')) != NULL) { - *ptr = '\0'; - } else { - ptr = linebuf + len; - } - - /* drop terminating whitespace including the \n */ - while (ptr > linebuf) { - if (!isspace(*(ptr-1))) { - *ptr = '\0'; - break; - } - --ptr; - } - - /* skip initial whitespace */ - for (ptr = linebuf; isspace(*ptr); ptr++); - if (*ptr == '\0') - continue; - - /* grab the key name */ - eq = 0; - name = ptr; - while (*ptr != '\0') { - if (isspace(*ptr) || *ptr == '=') { - eq = *ptr == '='; - *ptr = '\0'; - ++ptr; - break; - } - ++ptr; - } - - /* grab the key value */ - while (*ptr != '\0') { - if (*ptr != '=' || eq) { - if (!isspace(*ptr)) { - break; - } - } else { - eq = 1; - } - ++ptr; - } - - /* set the key:value pair on opts */ - set_conf_opt(pamh, opts, name, ptr); - } - - (void)fclose(f); - return PAM_SUCCESS; -} - -static void -set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const char *value) -{ - if (strcmp(name, "dir") == 0) { - if (value[0] != '/') { - pam_syslog(pamh, LOG_ERR, - "Tally directory is not absolute path (%s); keeping default", value); - } else { - free(opts->dir); - opts->dir = strdup(value); - } - } - else if (strcmp(name, "deny") == 0) { - if (sscanf(value, "%hu", &opts->deny) != 1) { - pam_syslog(pamh, LOG_ERR, - "Bad number supplied for deny argument"); - } - } - else if (strcmp(name, "fail_interval") == 0) { - unsigned int temp; - if (sscanf(value, "%u", &temp) != 1 || - temp > MAX_TIME_INTERVAL) { - pam_syslog(pamh, LOG_ERR, - "Bad number supplied for fail_interval argument"); - } else { - opts->fail_interval = temp; - } - } - else if (strcmp(name, "unlock_time") == 0) { - unsigned int temp; - - if (strcmp(value, "never") == 0) { - opts->unlock_time = 0; - } - else if (sscanf(value, "%u", &temp) != 1 || - temp > MAX_TIME_INTERVAL) { - pam_syslog(pamh, LOG_ERR, - "Bad number supplied for unlock_time argument"); - } - else { - opts->unlock_time = temp; - } - } - else if (strcmp(name, "root_unlock_time") == 0) { - unsigned int temp; - - if (strcmp(value, "never") == 0) { - opts->root_unlock_time = 0; - } - else if (sscanf(value, "%u", &temp) != 1 || - temp > MAX_TIME_INTERVAL) { - pam_syslog(pamh, LOG_ERR, - "Bad number supplied for root_unlock_time argument"); - } else { - opts->root_unlock_time = temp; - } - } - else if (strcmp(name, "admin_group") == 0) { - free(opts->admin_group); - opts->admin_group = strdup(value); - if (opts->admin_group == NULL) { - opts->fatal_error = 1; - pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); - } - } - else if (strcmp(name, "even_deny_root") == 0) { - opts->flags |= FAILLOCK_FLAG_DENY_ROOT; - } - else if (strcmp(name, "audit") == 0) { - opts->flags |= FAILLOCK_FLAG_AUDIT; - } - else if (strcmp(name, "silent") == 0) { - opts->flags |= FAILLOCK_FLAG_SILENT; - } - else if (strcmp(name, "no_log_info") == 0) { - opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; - } - else if (strcmp(name, "local_users_only") == 0) { - opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY; - } - else if (strcmp(name, "nodelay") == 0) { - opts->flags |= FAILLOCK_FLAG_NO_DELAY; - } - else { - pam_syslog(pamh, LOG_ERR, "Unknown option: %s", name); - } -} - static int check_local_user (pam_handle_t *pamh, const char *user) { @@ -406,10 +187,11 @@ check_tally(pam_handle_t *pamh, struct o unsigned int i; uint64_t latest_time; int failures; + const char *dir = get_tally_dir(opts); opts->now = time(NULL); - tfd = open_tally(opts->dir, opts->user, opts->uid, 0); + tfd = open_tally(dir, opts->user, opts->uid, 0); *fd = tfd; @@ -483,9 +265,10 @@ static void reset_tally(pam_handle_t *pamh, struct options *opts, int *fd) { int rv; + const char *dir = get_tally_dir(opts); if (*fd == -1) { - *fd = open_tally(opts->dir, opts->user, opts->uid, 1); + *fd = open_tally(dir, opts->user, opts->uid, 1); } else { while ((rv=ftruncate(*fd, 0)) == -1 && errno == EINTR); @@ -504,9 +287,10 @@ write_tally(pam_handle_t *pamh, struct o unsigned int oldest; uint64_t oldtime; const void *source = NULL; + const char *dir = get_tally_dir(opts); if (*fd == -1) { - *fd = open_tally(opts->dir, opts->user, opts->uid, 1); + *fd = open_tally(dir, opts->user, opts->uid, 1); } if (*fd == -1) { if (errno == EACCES) { diff --git a/modules/pam_faillock/faillock.h b/modules/pam_faillock/faillock.h index b22a9dfb..0ea0ffba 100644 --- a/modules/pam_faillock/faillock.h +++ b/modules/pam_faillock/faillock.h diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock.h.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock.h --- Linux-PAM-1.5.1/modules/pam_faillock/faillock.h.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100 +++ Linux-PAM-1.5.1/modules/pam_faillock/faillock.h 2022-05-25 15:33:03.885551825 +0200 @@ -67,7 +67,6 @@ struct tally_data { }; #define FAILLOCK_DEFAULT_TALLYDIR "/var/run/faillock" -#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf" int open_tally(const char *dir, const char *user, uid_t uid, int create); int read_tally(int fd, struct tally_data *tallies);