1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
From: Sam Hartman <hartmans@debian.org>
Date: Mon, 11 Sep 2023 14:00:42 -0600
Subject: _pam_include
Patch to implement an @include directive for use in pam.d config files.
Authors: Jan Christoph Nordholz <hesso@pool.math.tu-berlin.de>
Upstream status: not yet submitted
---
libpam/pam_handlers.c | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
index 1f1917b..c7045d2 100644
--- a/libpam/pam_handlers.c
+++ b/libpam/pam_handlers.c
@@ -123,6 +123,10 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
module_type = PAM_T_ACCT;
} else if (!strcasecmp("password", tok)) {
module_type = PAM_T_PASS;
+ } else if (!strcasecmp("@include", tok)) {
+ pam_include = 1;
+ module_type = requested_module_type;
+ goto parsing_done;
} else {
/* Illegal module type */
D(("_pam_init_handlers: bad module type: %s", tok));
@@ -193,8 +197,10 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
_pam_set_default_control(actions, _PAM_ACTION_BAD);
}
+parsing_done:
tok = _pam_StrTok(NULL, " \n\t", &nexttok);
if (pam_include) {
+ struct stat include_dir;
if (substack) {
res = _pam_add_handler(pamh, PAM_HT_SUBSTACK, other,
stack_level, module_type, actions, tok,
@@ -205,13 +211,35 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
return PAM_ABORT;
}
}
- if (_pam_load_conf_file(pamh, tok, this_service, module_type,
- stack_level + substack
+ if (tok[0] == '/') {
+ if (_pam_load_conf_file(pamh, tok, this_service,
+ module_type, stack_level + substack
+#ifdef PAM_READ_BOTH_CONFS
+ , !other
+#endif /* PAM_READ_BOTH_CONFS */
+ ) == PAM_SUCCESS)
+ continue;
+ }
+ else if (!stat(PAM_CONFIG_D, &include_dir)
+ && S_ISDIR(include_dir.st_mode))
+ {
+ char *include_file;
+ if (asprintf (&include_file, PAM_CONFIG_DF, tok) < 0) {
+ pam_syslog(pamh, LOG_CRIT, "asprintf failed");
+ return PAM_ABORT;
+ }
+ if (_pam_load_conf_file(pamh, include_file, this_service,
+ module_type, stack_level + substack
#ifdef PAM_READ_BOTH_CONFS
, !other
#endif /* PAM_READ_BOTH_CONFS */
- ) == PAM_SUCCESS)
- continue;
+ ) == PAM_SUCCESS)
+ {
+ free(include_file);
+ continue;
+ }
+ free(include_file);
+ }
_pam_set_default_control(actions, _PAM_ACTION_BAD);
mod_path = NULL;
handler_type = PAM_HT_MUST_FAIL;
|