blob: d2cc66882ee4e61700faa3d070cd0a5bb247dcba [file] [log] [blame]
Andrew Geissler87ddd3e2021-01-28 18:27:13 -06001From b6545b83f94c5fb7aec1478b8d458a1393f479c8 Mon Sep 17 00:00:00 2001
2From: "Maxin B. John" <maxin.john@intel.com>
3Date: Wed, 25 May 2016 14:12:25 +0300
4Subject: [PATCH] pam_unix: support 'nullok_secure' option
5
6Debian patch to add a new 'nullok_secure' option to pam_unix,
7which accepts users with null passwords only when the applicant is
8connected from a tty listed in /etc/securetty.
9
10Authors: Sam Hartman <hartmans@debian.org>,
11 Steve Langasek <vorlon@debian.org>
12
13Upstream-Status: Pending
14
15Signed-off-by: Ming Liu <ming.liu@windriver.com>
16Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
17Signed-off-by: Maxin B. John <maxin.john@intel.com>
18---
19 modules/pam_unix/Makefile.am | 3 ++-
20 modules/pam_unix/pam_unix.8.xml | 19 ++++++++++++++++++-
21 modules/pam_unix/support.c | 40 +++++++++++++++++++++++++++++++++++-----
22 modules/pam_unix/support.h | 8 ++++++--
23 4 files changed, 61 insertions(+), 9 deletions(-)
24
25diff --git a/modules/pam_unix/Makefile.am b/modules/pam_unix/Makefile.am
26index 56df178..2bba460 100644
27--- a/modules/pam_unix/Makefile.am
28+++ b/modules/pam_unix/Makefile.am
29@@ -30,7 +30,8 @@ if HAVE_VERSIONING
30 pam_unix_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
31 endif
32 pam_unix_la_LIBADD = $(top_builddir)/libpam/libpam.la \
33- @LIBCRYPT@ @LIBSELINUX@ @TIRPC_LIBS@ @NSL_LIBS@
34+ @LIBCRYPT@ @LIBSELINUX@ @TIRPC_LIBS@ @NSL_LIBS@ \
35+ ../pam_securetty/tty_secure.lo
36
37 securelib_LTLIBRARIES = pam_unix.la
38
39diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml
40index 1b318f1..be0330e 100644
41--- a/modules/pam_unix/pam_unix.8.xml
42+++ b/modules/pam_unix/pam_unix.8.xml
43@@ -159,7 +159,24 @@
44 <para>
45 The default action of this module is to not permit the
46 user access to a service if their official password is blank.
47- The <option>nullok</option> argument overrides this default.
48+ The <option>nullok</option> argument overrides this default
49+ and allows any user with a blank password to access the
50+ service.
51+ </para>
52+ </listitem>
53+ </varlistentry>
54+ <varlistentry>
55+ <term>
56+ <option>nullok_secure</option>
57+ </term>
58+ <listitem>
59+ <para>
60+ The default action of this module is to not permit the
61+ user access to a service if their official password is blank.
62+ The <option>nullok_secure</option> argument overrides this
63+ default and allows any user with a blank password to access
64+ the service as long as the value of PAM_TTY is set to one of
65+ the values found in /etc/securetty.
66 </para>
67 </listitem>
68 </varlistentry>
69diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
70index fc8595e..29e3341 100644
71--- a/modules/pam_unix/support.c
72+++ b/modules/pam_unix/support.c
73@@ -183,13 +183,22 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
74 /* now parse the arguments to this module */
75
76 for (; argc-- > 0; ++argv) {
77+ int sl;
78
79 D(("pam_unix arg: %s", *argv));
80
81 for (j = 0; j < UNIX_CTRLS_; ++j) {
82- if (unix_args[j].token
83- && !strncmp(*argv, unix_args[j].token, strlen(unix_args[j].token))) {
84- break;
85+ if (unix_args[j].token) {
86+ sl = strlen(unix_args[j].token);
87+ if (unix_args[j].token[sl-1] == '=') {
88+ /* exclude argument from comparison */
89+ if (!strncmp(*argv, unix_args[j].token, sl))
90+ break;
91+ } else {
92+ /* compare full strings */
93+ if (!strcmp(*argv, unix_args[j].token))
94+ break;
95+ }
96 }
97 }
98
99@@ -560,6 +569,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
100 if (child == 0) {
101 static char *envp[] = { NULL };
102 const char *args[] = { NULL, NULL, NULL, NULL };
103+ int nullok = off(UNIX__NONULL, ctrl);
104
105 /* XXX - should really tidy up PAM here too */
106
107@@ -587,7 +597,16 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
108 /* exec binary helper */
109 args[0] = CHKPWD_HELPER;
110 args[1] = user;
111- if (off(UNIX__NONULL, ctrl)) { /* this means we've succeeded */
112+ if (on(UNIX_NULLOK_SECURE, ctrl)) {
113+ const void *uttyname;
114+ retval = pam_get_item(pamh, PAM_TTY, &uttyname);
115+ if (retval != PAM_SUCCESS || uttyname == NULL
116+ || _pammodutil_tty_secure(pamh, (const char *)uttyname) != PAM_SUCCESS) {
117+ nullok = 0;
118+ }
119+ }
120+
121+ if (nullok) {
122 args[2]="nullok";
123 } else {
124 args[2]="nonull";
125@@ -672,6 +691,17 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
126 if (on(UNIX__NONULL, ctrl))
127 return 0; /* will fail but don't let on yet */
128
129+ if (on(UNIX_NULLOK_SECURE, ctrl)) {
130+ int retval2;
131+ const void *uttyname;
132+ retval2 = pam_get_item(pamh, PAM_TTY, &uttyname);
133+ if (retval2 != PAM_SUCCESS || uttyname == NULL)
134+ return 0;
135+
136+ if (_pammodutil_tty_secure(pamh, (const char *)uttyname) != PAM_SUCCESS)
137+ return 0;
138+ }
139+
140 /* UNIX passwords area */
141
142 retval = get_pwd_hash(pamh, name, &pwd, &salt);
143@@ -758,7 +788,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
144 }
145 }
146 } else {
147- retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl));
148+ retval = verify_pwd_hash(p, salt, _unix_blankpasswd(pamh, ctrl, name));
149 }
150
151 if (retval == PAM_SUCCESS) {
152diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
153index b4c279c..8da4a8e 100644
154--- a/modules/pam_unix/support.h
155+++ b/modules/pam_unix/support.h
156@@ -98,8 +98,9 @@ typedef struct {
157 #define UNIX_QUIET 28 /* Don't print informational messages */
158 #define UNIX_NO_PASS_EXPIRY 29 /* Don't check for password expiration if not used for authentication */
159 #define UNIX_DES 30 /* DES, default */
160+#define UNIX_NULLOK_SECURE 31 /* NULL passwords allowed only on secure ttys */
161 /* -------------- */
162-#define UNIX_CTRLS_ 31 /* number of ctrl arguments defined */
163+#define UNIX_CTRLS_ 32 /* number of ctrl arguments defined */
164
165 #define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl))
166
167@@ -117,7 +118,7 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
168 /* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0},
169 /* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200, 0},
170 /* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400, 0},
171-/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0},
172+/* UNIX__NONULL */ {NULL, _ALL_ON_^(02000000000), 01000, 0},
173 /* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0},
174 /* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0},
175 /* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0},
176@@ -139,6 +140,7 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
177 /* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0},
178 /* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0},
179 /* UNIX_DES */ {"des", _ALL_ON_^(0260420000), 0, 1},
180+/* UNIX_NULLOK_SECURE */ {"nullok_secure", _ALL_ON_^(01000), 02000000000, 0},
181 };
182
183 #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
184@@ -172,6 +174,8 @@ extern int _unix_read_password(pam_handle_t * pamh
185 ,const char *data_name
186 ,const void **pass);
187
188+extern int _pammodutil_tty_secure(const pam_handle_t *pamh, const char *uttyname);
189+
190 extern int _unix_run_verify_binary(pam_handle_t *pamh,
191 unsigned int ctrl, const char *user, int *daysleft);
192 #endif /* _PAM_UNIX_SUPPORT_H */
193--
1942.4.0
195