12
12
#include <string.h>
13
13
#include <unistd.h>
14
14
#include <syslog.h>
15
+ #include <time.h>
15
16
#include <pwd.h>
16
17
#include <shadow.h>
17
18
@@ -25,12 +26,90 @@ IO_LOOP(write_loop, write, const)
25
26
#define AUTH_PASSED TCB_MAGIC
26
27
#define AUTH_FAILED 1
27
28
29
+ enum {
30
+ ACCT_0 = 0 ,
31
+ ACCT_1 ,
32
+ ACCT_2 ,
33
+ ACCT_3 ,
34
+ ACCT_4 ,
35
+ ACCT_5 ,
36
+ ACCT_6 ,
37
+ ACCT_7 ,
38
+ ACCT_SUCCESS = 255
39
+ };
40
+
28
41
static void zeroise (char * str )
29
42
{
30
43
while (* str )
31
44
* (str ++ ) = '\0' ;
32
45
}
33
46
47
+ static int unix_getspnam (struct spwd * * spw , const struct passwd * pw , int shadow )
48
+ {
49
+ if (shadow ) {
50
+ * spw = getspnam (pw -> pw_name );
51
+ endspent ();
52
+ return 0 ;
53
+ }
54
+
55
+ return 1 ;
56
+ }
57
+
58
+ static int acct_shadow (const void * void_user , int shadow )
59
+ {
60
+ int daysleft ;
61
+ time_t curdays ;
62
+ const char * user = void_user ;
63
+ struct passwd * pw ;
64
+ struct spwd * spw = NULL ;
65
+
66
+ pw = getpwnam (user );
67
+ endpwent ();
68
+ if (pw ) {
69
+ uid_t uid = getuid ();
70
+ if (uid != pw -> pw_uid && uid != 0 )
71
+ return ACCT_1 ;
72
+ }
73
+ if (!pw )
74
+ return ACCT_1 ; /* shouldn't happen */
75
+ if (!shadow && strcmp (pw -> pw_passwd , "x" )
76
+ && strcmp (pw -> pw_passwd , "*NP*" ))
77
+ return ACCT_SUCCESS ;
78
+
79
+ if (unix_getspnam (& spw , pw , shadow ))
80
+ return ACCT_1 ;
81
+
82
+ if (!spw )
83
+ return ACCT_2 ;
84
+
85
+ curdays = time (NULL ) / (60 * 60 * 24 );
86
+ syslog (LOG_DEBUG , "today is %ld, last change %ld" ,
87
+ curdays , spw -> sp_lstchg );
88
+ if ((curdays > spw -> sp_expire ) && (spw -> sp_expire != -1 ))
89
+ return ACCT_3 ;
90
+
91
+ if ((curdays > (spw -> sp_lstchg + spw -> sp_max + spw -> sp_inact )) &&
92
+ (spw -> sp_max != -1 ) && (spw -> sp_inact != -1 ) &&
93
+ (spw -> sp_lstchg != 0 ))
94
+ return ACCT_4 ;
95
+
96
+ syslog (LOG_DEBUG , "when was the last change" );
97
+ if (spw -> sp_lstchg == 0 )
98
+ return ACCT_5 ;
99
+
100
+ if (((spw -> sp_lstchg + spw -> sp_max ) < curdays ) &&
101
+ (spw -> sp_max != -1 ))
102
+ return ACCT_6 ;
103
+
104
+ if ((curdays > (spw -> sp_lstchg + spw -> sp_max - spw -> sp_warn )) &&
105
+ (spw -> sp_max != -1 ) && (spw -> sp_warn != -1 )) {
106
+ daysleft = (spw -> sp_lstchg + spw -> sp_max ) - curdays ;
107
+ return ACCT_7 + 256 * daysleft ;
108
+ }
109
+
110
+ return ACCT_SUCCESS ;
111
+ }
112
+
34
113
static int unix_verify_password (const char * user , const char * pass , int nullok )
35
114
{
36
115
struct passwd * pw ;
@@ -89,27 +168,36 @@ static int is_two_strings(char *data, unsigned int len)
89
168
return (1 + strlen (data ) < len );
90
169
}
91
170
92
- int main ( void )
171
+ static int acctverify ( int shadow )
93
172
{
94
- char option [8 ];
95
- char userandpass [MAX_DATA_LENGTH + 1 ];
96
- int datalen , nullok , retval ;
173
+ int datalen , retval ;
174
+ char username [MAX_DATA_LENGTH + 1 ];
97
175
98
- openlog ( "tcb_chkpwd" , LOG_CONS | LOG_PID , LOG_AUTH ) ;
176
+ retval = ACCT_0 ;
99
177
100
- if (isatty (STDIN_FILENO ) || isatty (STDOUT_FILENO )) {
101
- syslog (LOG_NOTICE , "inappropriate use by UID %d" , getuid ());
102
- return 1 ;
103
- }
178
+ /* read the user from stdin (a pipe from the PAM module) */
179
+ datalen = read_loop (STDIN_FILENO , username , MAX_DATA_LENGTH );
180
+ if (datalen < 0 )
181
+ syslog (LOG_DEBUG , "no username supplied" );
182
+ else if (datalen >= MAX_DATA_LENGTH )
183
+ syslog (LOG_DEBUG , "username too long" );
184
+ else
185
+ retval = acct_shadow (username , shadow );
104
186
105
- /* read the nullok/nonull option */
106
- memset (option , 0 , sizeof (option ));
107
- if (read_loop (STDIN_FILENO , option , sizeof (option )) <= 0 ) {
108
- syslog (LOG_DEBUG , "no option supplied" );
187
+ memset (username , 0 , sizeof (username ));
188
+
189
+ /* return pass or fail */
190
+ if (write_loop (STDOUT_FILENO , (char * )& retval , sizeof (retval )) ==
191
+ sizeof (retval ))
192
+ return retval == ACCT_SUCCESS ? 0 : 1 ;
193
+ else
109
194
return 1 ;
110
- }
111
- option [sizeof (option ) - 1 ] = '\0' ;
112
- nullok = !strcmp (option , "nullok" );
195
+ }
196
+
197
+ static int passverify (int nullok )
198
+ {
199
+ int datalen , retval ;
200
+ char userandpass [MAX_DATA_LENGTH + 1 ];
113
201
114
202
retval = AUTH_FAILED ;
115
203
@@ -134,3 +222,38 @@ int main(void)
134
222
else
135
223
return 1 ;
136
224
}
225
+
226
+ int main (int argc , char * argv [])
227
+ {
228
+ char option [8 ];
229
+ int flag , retval = 1 ;
230
+
231
+ openlog ("tcb_chkpwd" , LOG_CONS | LOG_PID , LOG_AUTH );
232
+
233
+ if (argc != 2 || isatty (STDIN_FILENO ) || isatty (STDOUT_FILENO )) {
234
+ syslog (LOG_NOTICE , "inappropriate use by UID %d" , getuid ());
235
+ goto out ;
236
+ }
237
+
238
+ /* read the applicable option from pipe */
239
+ memset (option , 0 , sizeof (option ));
240
+ if (read_loop (STDIN_FILENO , option , sizeof (option )) <= 0 ) {
241
+ syslog (LOG_DEBUG , "no option supplied" );
242
+ goto out ;
243
+ }
244
+ option [sizeof (option ) - 1 ] = '\0' ;
245
+
246
+ if (!strcmp (argv [1 ], "chkacct" )) {
247
+ flag = !strcmp (option , "shadow" );
248
+ retval = acctverify (flag );
249
+ goto out ;
250
+ }
251
+
252
+ if (!strcmp (argv [1 ], "chkpwd" )) {
253
+ flag = !strcmp (option , "nullok" );
254
+ retval = passverify (flag );
255
+ }
256
+
257
+ out :
258
+ return retval ;
259
+ }
0 commit comments