summaryrefslogtreecommitdiff
blob: 3eab29d2d0cb3a379df7717850027ea4d1be0b44 (plain)
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
http://bugs.gentoo.org/336449
Patch contributed by Jan Sembera <fis@bofh.cz>

In my environment, I'd like to use pam_skey as optional authentication
measure that wouldn't replace the password, but would complement it.
Ie. when the user sets the S/Key, he should be afterwards asked to
provide the S/Key _and_ his password, without the possibility to just
enter his password and circumvent S/Keys. On the other hand, when the
user doesn't have S/Key set, he should be able to login with his
password only.

Why PAM would generally allow this, with the current internals of
pam_skey, this setup isn't possible. You simply cannot distinguish
between "user has no S/Key set" case (it returns IGNORE) and "user
doesn't want to provide S/Key" (it returns IGNORE as well).

I'm attaching a patch that will add option require_skey to pam_skey.
When this option is set, module will require the user to successfully
authenticate using S/key, and will return IGNORE only in case the user
didn't set up his key. If this option isn't provided, the behaviour of
the module doesn't change.

--- pam_skey-orig/README
+++ pam_skey/README
@@ -21,7 +21,7 @@
 - The options accepted by the pam_skey.so module are different, as
   described below.
 
-Four options are accepted by the pam_skey.so module:
+Five options are accepted by the pam_skey.so module:
   debug                  - This option turns on debug logging.
   try_first_pass         - This option tells the module to first try using
                            the authentication token passed from the
@@ -44,6 +44,12 @@
 			   cause the module to pass the given password to the
 			   next module in the authentication stack (usually
 			   pam_unix.so with the try_first_pass option).
+  require_skey           - This options tells the module to require S/Key
+			   authentication if the user has S/Key set.  When
+			   this option is set, it is possible to require both
+			   S/Key and another authentication method (like
+			   password) for successful login.  This is mutually
+			   exclusive with no_default_skey.
 
 The exact behavior of pam_skey.so is detailed below:
 
@@ -54,21 +60,22 @@
    if it is a valid response to the current S/Key challenge.  If so,
    return PAM_SUCCESS.
  3a. If the token is invalid and use_first_pass is enabled, return
-     PAM_IGNORE.
+     PAM_IGNORE (or PAM_AUTHERR if require_skey is set).
 4. If no_default_skey is enabled, issue a "Password: " prompt.
  4a. If the response is anything besides "s/key" (case insensitive),
      store it as the authentication token and return PAM_IGNORE.
 5. Display the current S/Key challenge and request a response, with
-   input not echoed.  If no_default_skey is enabled, this will only be
-   an S/Key response request; otherwise, it will request either an
-   S/Key response or a system passsword.
+   input not echoed.  If no_default_skey or require_skey is enabled,
+   this will only be an S/Key response request; otherwise, it will
+   request either an S/Key response or a system passsword.
  5a. If an empty response is given, request the S/Key response again,
      this time with input echoed.
  5b. If the response is a valid S/Key response, return PAM_SUCCESS.
      Otherwise, return PAM_AUTHERR.
 6. If the response is a valid S/Key response, return PAM_SUCCESS.
-7. Otherwise, if no_default_skey is enabled (the user specifically
-   requested "s/key" authentication), return PAM_AUTHERR.
+7. Otherwise, if no_default_skey is enabled (and the user specifically
+   requested "s/key" authentication), or if require_skey is enabled,
+   return PAM_AUTHERR.
 8. Otherwise, store the response as the authentication token and
    return PAM_IGNORE.
 
--- pam_skey-orig/pam_skey.c
+++ pam_skey/pam_skey.c
@@ -110,7 +110,7 @@
       if (skey_passcheck(username, response) != -1) {
 	return PAM_SUCCESS;
       } else if (mod_opt & _MOD_USE_FIRST_PASS) {
-	return PAM_IGNORE;
+	return (mod_opt & _MOD_REQUIRE_SKEY) ? PAM_AUTH_ERR : PAM_IGNORE;
       }
     } else if (mod_opt & _MOD_USE_FIRST_PASS) {
       return PAM_AUTHTOK_RECOVER_ERR;
@@ -138,7 +138,7 @@
     return PAM_AUTHINFO_UNAVAIL;
   }
 
-  if (mod_opt & _MOD_NO_DEFAULT_SKEY)
+  if ((mod_opt & _MOD_NO_DEFAULT_SKEY) || (mod_opt & _MOD_REQUIRE_SKEY))
     status = mod_talk_touser(pamh, mod_opt, challenge, QUERY_RESPONSE, 0, &response);
   else
     status = mod_talk_touser(pamh, mod_opt, challenge, QUERY_RESPONSE_OR_PASSWORD, 0, &response);
@@ -166,7 +166,7 @@
     return PAM_SUCCESS;
   }
 
-  if (mod_opt & _MOD_NO_DEFAULT_SKEY) {
+  if ((mod_opt & _MOD_NO_DEFAULT_SKEY) || (mod_opt & _MOD_REQUIRE_SKEY)) {
     _pam_delete(response);
     return PAM_AUTH_ERR;
   }
--- pam_skey-orig/pam_skey.h
+++ pam_skey/pam_skey.h
@@ -78,13 +78,14 @@
 #define _MOD_TRY_FIRST_PASS  0x0002	/* Attempt using PAM_AUTHTOK */
 #define _MOD_USE_FIRST_PASS  0x0004	/* Only use PAM_AUTHTOK */
 #define _MOD_NO_DEFAULT_SKEY 0x0008	/* Don't use S/Key by default */
+#define _MOD_REQUIRE_SKEY    0x0010	/* Require S/Key if set */
 
 /* Setup defaults - use echo off only */
 #define _MOD_DEFAULT_FLAG   _MOD_NONE_ON
 #define _MOD_DEFAULT_MASK   _MOD_ALL_ON
 
 /* Number of parameters currently known */
-#define _MOD_ARGS           4
+#define _MOD_ARGS           5
 
 /* Structure for flexible argument parsing */
 typedef struct
@@ -101,5 +102,6 @@
   {"debug",            _MOD_ALL_ON,                   _MOD_DEBUG},
   {"try_first_pass",   _MOD_ALL_ON,                   _MOD_TRY_FIRST_PASS},
   {"use_first_pass",   _MOD_ALL_ON,                   _MOD_USE_FIRST_PASS},
-  {"no_default_skey",  _MOD_ALL_ON,                   _MOD_NO_DEFAULT_SKEY}
+  {"no_default_skey",  _MOD_ALL_ON & ~_MOD_REQUIRE_SKEY, _MOD_NO_DEFAULT_SKEY},
+  {"require_skey",     _MOD_ALL_ON & ~_MOD_NO_DEFAULT_SKEY, _MOD_REQUIRE_SKEY}
 };