oath-toolkit/42-null_usersfile_okay.patch
2024-10-16 17:33:55 +00:00

136 lines
4.9 KiB
Diff

From f69897e6e8b3881b9e470a384cefc41a851b2475 Mon Sep 17 00:00:00 2001
From: Luna <luna.dragon@suse.com>
Date: Mon, 9 Sep 2024 19:14:08 +0530
Subject: [PATCH 2/2] pam_oath: add null_usersfile_okay parameter to pam_oath
Co-authored-by: Jan Zerebecki <jzerebecki@suse.com>
Co-authored-by: Miika Alikirri <miika.alikirri@suse.com>
---
pam_oath/README | 10 ++++++++++
pam_oath/pam_oath.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/pam_oath/README b/pam_oath/README
index 9a8e7366..3c7da052 100644
--- a/pam_oath/README
+++ b/pam_oath/README
@@ -77,6 +77,7 @@ jas@mocca:~$ su
[pam_oath.c:parse_cfg(127)] alwaysok=1
[pam_oath.c:parse_cfg(128)] try_first_pass=0
[pam_oath.c:parse_cfg(129)] use_first_pass=0
+[pam_oath.c:parse_cfg(129)] no_usersfile_okay=0
[pam_oath.c:parse_cfg(130)] usersfile=/etc/users.oath
[pam_oath.c:parse_cfg(131)] digits=0
[pam_oath.c:parse_cfg(132)] window=20
@@ -144,6 +145,7 @@ jas@mocca:~$ su
[pam_oath.c:parse_cfg(127)] alwaysok=1
[pam_oath.c:parse_cfg(128)] try_first_pass=0
[pam_oath.c:parse_cfg(129)] use_first_pass=0
+[pam_oath.c:parse_cfg(129)] no_usersfile_okay=0
[pam_oath.c:parse_cfg(130)] usersfile=/etc/users.oath
[pam_oath.c:parse_cfg(131)] digits=6
[pam_oath.c:parse_cfg(132)] window=20
@@ -176,6 +178,7 @@ jas@mocca:~$ su
[pam_oath.c:parse_cfg(127)] alwaysok=1
[pam_oath.c:parse_cfg(128)] try_first_pass=0
[pam_oath.c:parse_cfg(129)] use_first_pass=0
+[pam_oath.c:parse_cfg(129)] no_usersfile_okay=0
[pam_oath.c:parse_cfg(130)] usersfile=/etc/users.oath
[pam_oath.c:parse_cfg(131)] digits=6
[pam_oath.c:parse_cfg(132)] window=20
@@ -213,6 +216,13 @@ List of all parameters
never prompt the user - if no password is
available or the password is not appropriate, the
user will be denied access.
+ "no_usersfile_okay": The argument no_usersfile_okay forces the module
+ to act as if the user is not present in the config,
+ if the config file does not exist. This has
+ security implications only use if you know what you
+ are doing. E.g. if the file is in a mount like home
+ and that fails to be mounted, then this will succeed
+ even if the OTP if configured for that user.
"usersfile": Specify filename where credentials are stored, for
example "/etc/users.oath". The placeholder values
diff --git a/pam_oath/pam_oath.c b/pam_oath/pam_oath.c
index 25eb83e6..72712b53 100644
--- a/pam_oath/pam_oath.c
+++ b/pam_oath/pam_oath.c
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <libgen.h>
#include <ctype.h>
#include <pwd.h>
#include <unistd.h>
@@ -72,6 +73,7 @@ struct cfg
int alwaysok;
int try_first_pass;
int use_first_pass;
+ int no_usersfile_okay;
char *usersfile;
unsigned digits;
unsigned window;
@@ -86,6 +88,7 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
cfg->alwaysok = 0;
cfg->try_first_pass = 0;
cfg->use_first_pass = 0;
+ cfg->no_usersfile_okay = 0;
cfg->usersfile = NULL;
cfg->digits = -1;
cfg->window = 5;
@@ -100,6 +103,8 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
cfg->try_first_pass = 1;
if (strcmp (argv[i], "use_first_pass") == 0)
cfg->use_first_pass = 1;
+ if (strcmp (argv[i], "no_usersfile_okay") == 0)
+ cfg->no_usersfile_okay = 1;
if (strncmp (argv[i], "usersfile=", 10) == 0)
cfg->usersfile = (char *) argv[i] + 10;
if (strncmp (argv[i], "digits=", 7) == 0)
@@ -126,6 +131,7 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
D (("alwaysok=%d", cfg->alwaysok));
D (("try_first_pass=%d", cfg->try_first_pass));
D (("use_first_pass=%d", cfg->use_first_pass));
+ D (("no_usersfile_okay=%d", cfg->no_usersfile_okay));
D (("usersfile=%s", cfg->usersfile ? cfg->usersfile : "(null)"));
D (("digits=%d", cfg->digits));
D (("window=%d", cfg->window));
@@ -292,6 +298,32 @@ pam_sm_authenticate (pam_handle_t *pamh,
}
DBG (("usersfile is %s", usersfile));
+ if (cfg.no_usersfile_okay)
+ {
+ char *ucopy, *base;
+ ucopy = strdup (usersfile);
+ base = dirname (ucopy);
+
+ /* make sure that the base dir exists so we are sure that, for example,
+ the user home directory is mounted. */
+ rc = access (base, F_OK);
+ free (ucopy);
+ if (rc != 0)
+ {
+ DBG (("Basepath of file cannot be accessed '%s'", usersfile));
+ retval = PAM_AUTH_ERR;
+ goto done;
+ }
+
+ if (access (usersfile, F_OK) != 0)
+ {
+ DBG (("no_usersfile_okay set and no userfile was found, authenticating..."));
+ retval = PAM_SUCCESS;
+ goto done;
+ }
+ }
+
+
// quick check to skip unconfigured users before prompting for password
{
time_t last_otp;
--
GitLab