aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIker Pedrosa <ipedrosa@redhat.com>2022-04-20 10:08:40 +0200
committerIker Pedrosa <ipedrosa@redhat.com>2022-05-24 13:26:49 +0200
commitfc867a9e22eac2c9a0ed0577776bba4df21c9aad (patch)
treec6530a416bd83be00ac260dd86cbd533981f0664
parent9bcbe96d9e82a23d983c0618178a8dc25596ac2d (diff)
downloadpam-fc867a9e22eac2c9a0ed0577776bba4df21c9aad.tar.gz
pam-fc867a9e22eac2c9a0ed0577776bba4df21c9aad.tar.bz2
pam-fc867a9e22eac2c9a0ed0577776bba4df21c9aad.zip
faillock: load configuration from file
* modules/pam_faillock/main.c: Load configuration from file * modules/pam_faillock/pam_faillock: Improve tally directory management * modules/pam_faillock/faillock_config.c: Print errors * modules/pam_faillock/faillock_config.h: Extend options structure and define get_tally_dir(). * modules/pam_faillock/Makefile.am: Compile faillock_config.c for faillock binary. * modules/pam_faillock/faillock.8.xml: Update with the new configuration option. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1978029 Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
-rw-r--r--modules/pam_faillock/Makefile.am2
-rw-r--r--modules/pam_faillock/faillock.8.xml21
-rw-r--r--modules/pam_faillock/faillock_config.c49
-rw-r--r--modules/pam_faillock/faillock_config.h4
-rw-r--r--modules/pam_faillock/main.c51
-rw-r--r--modules/pam_faillock/pam_faillock.c15
6 files changed, 109 insertions, 33 deletions
diff --git a/modules/pam_faillock/Makefile.am b/modules/pam_faillock/Makefile.am
index a0f0efa8..ca73bd05 100644
--- a/modules/pam_faillock/Makefile.am
+++ b/modules/pam_faillock/Makefile.am
@@ -45,7 +45,7 @@ securelib_LTLIBRARIES = pam_faillock.la
sbin_PROGRAMS = faillock
pam_faillock_la_SOURCES = pam_faillock.c faillock.c faillock_config.c
-faillock_SOURCES = main.c faillock.c
+faillock_SOURCES = main.c faillock.c faillock_config.c
if ENABLE_REGENERATE_MAN
dist_noinst_DATA = README
diff --git a/modules/pam_faillock/faillock.8.xml b/modules/pam_faillock/faillock.8.xml
index 6c20593c..81d2107c 100644
--- a/modules/pam_faillock/faillock.8.xml
+++ b/modules/pam_faillock/faillock.8.xml
@@ -57,12 +57,29 @@
<variablelist>
<varlistentry>
<term>
+ <option>--conf <replaceable>/path/to/config-file</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ The file where the configuration is located. The default is
+ <filename>/etc/security/faillock.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
<option>--dir <replaceable>/path/to/tally-directory</replaceable></option>
</term>
<listitem>
<para>
- The directory where the user files with the failure records are kept. The
- default is <filename>/var/run/faillock</filename>.
+ The directory where the user files with the failure records are kept.
+ </para>
+ <para>
+ 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
+ <filename>/var/run/faillock</filename> is used.
</para>
</listitem>
</varlistentry>
diff --git a/modules/pam_faillock/faillock_config.c b/modules/pam_faillock/faillock_config.c
index 8740b826..0d14aad1 100644
--- a/modules/pam_faillock/faillock_config.c
+++ b/modules/pam_faillock/faillock_config.c
@@ -46,12 +46,35 @@
#include <security/pam_modules.h>
#include "faillock_config.h"
+#include "faillock.h"
#define FAILLOCK_DEFAULT_CONF SCONFIGDIR "/faillock.conf"
#ifdef VENDOR_SCONFIGDIR
#define VENDOR_FAILLOCK_DEFAULT_CONF VENDOR_SCONFIGDIR "/faillock.conf"
#endif
+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)
@@ -149,16 +172,21 @@ set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name,
{
if (strcmp(name, "dir") == 0) {
if (value[0] != '/') {
- pam_syslog(pamh, LOG_ERR,
- "Tally directory is not absolute path (%s); keeping default", value);
+ 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) {
- pam_syslog(pamh, LOG_ERR,
+ config_log(pamh, LOG_ERR,
"Bad number supplied for deny argument");
}
}
@@ -166,7 +194,7 @@ set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name,
unsigned int temp;
if (sscanf(value, "%u", &temp) != 1 ||
temp > MAX_TIME_INTERVAL) {
- pam_syslog(pamh, LOG_ERR,
+ config_log(pamh, LOG_ERR,
"Bad number supplied for fail_interval argument");
} else {
opts->fail_interval = temp;
@@ -180,7 +208,7 @@ set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name,
}
else if (sscanf(value, "%u", &temp) != 1 ||
temp > MAX_TIME_INTERVAL) {
- pam_syslog(pamh, LOG_ERR,
+ config_log(pamh, LOG_ERR,
"Bad number supplied for unlock_time argument");
}
else {
@@ -195,7 +223,7 @@ set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name,
}
else if (sscanf(value, "%u", &temp) != 1 ||
temp > MAX_TIME_INTERVAL) {
- pam_syslog(pamh, LOG_ERR,
+ config_log(pamh, LOG_ERR,
"Bad number supplied for root_unlock_time argument");
} else {
opts->root_unlock_time = temp;
@@ -206,7 +234,7 @@ set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name,
opts->admin_group = strdup(value);
if (opts->admin_group == NULL) {
opts->fatal_error = 1;
- pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m");
+ config_log(pamh, LOG_CRIT, "Error allocating memory: %m");
}
}
else if (strcmp(name, "even_deny_root") == 0) {
@@ -228,6 +256,11 @@ set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name,
opts->flags |= FAILLOCK_FLAG_NO_DELAY;
}
else {
- pam_syslog(pamh, LOG_ERR, "Unknown option: %s", name);
+ 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 --git a/modules/pam_faillock/faillock_config.h b/modules/pam_faillock/faillock_config.h
index 81aa6654..db2851f5 100644
--- a/modules/pam_faillock/faillock_config.h
+++ b/modules/pam_faillock/faillock_config.h
@@ -75,11 +75,15 @@ struct options {
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 --git a/modules/pam_faillock/main.c b/modules/pam_faillock/main.c
index ea6329ca..35208870 100644
--- a/modules/pam_faillock/main.c
+++ b/modules/pam_faillock/main.c
@@ -51,32 +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;
@@ -94,6 +102,21 @@ args_parse(int argc, char **argv, struct options *opts)
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;
}
@@ -111,10 +134,11 @@ do_user(struct options *opts, const char *user)
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) {
@@ -195,8 +219,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 --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c
index 0a5b6b62..ddbb90e7 100644
--- a/modules/pam_faillock/pam_faillock.c
+++ b/modules/pam_faillock/pam_faillock.c
@@ -72,7 +72,6 @@ args_parse(pam_handle_t *pamh, int argc, const char **argv,
memset(opts, 0, sizeof(*opts));
- opts->dir = strdup(FAILLOCK_DEFAULT_TALLYDIR);
opts->deny = 3;
opts->fail_interval = 900;
opts->unlock_time = 600;
@@ -130,11 +129,6 @@ args_parse(pam_handle_t *pamh, int argc, const char **argv,
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;
@@ -193,10 +187,11 @@ check_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies
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;
@@ -270,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);
@@ -291,9 +287,10 @@ write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies
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) {