diff options
Diffstat (limited to 'auth.c')
-rw-r--r-- | auth.c | 158 |
1 files changed, 102 insertions, 56 deletions
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: auth.c,v 1.46 2002/11/04 10:07:53 markus Exp $"); | 26 | RCSID("$OpenBSD: auth.c,v 1.49 2003/08/26 09:58:43 markus Exp $"); |
27 | 27 | ||
28 | #ifdef HAVE_LOGIN_H | 28 | #ifdef HAVE_LOGIN_H |
29 | #include <login.h> | 29 | #include <login.h> |
@@ -54,6 +54,7 @@ RCSID("$OpenBSD: auth.c,v 1.46 2002/11/04 10:07:53 markus Exp $"); | |||
54 | 54 | ||
55 | /* import */ | 55 | /* import */ |
56 | extern ServerOptions options; | 56 | extern ServerOptions options; |
57 | extern Buffer loginmsg; | ||
57 | 58 | ||
58 | /* Debugging messages */ | 59 | /* Debugging messages */ |
59 | Buffer auth_debug; | 60 | Buffer auth_debug; |
@@ -72,26 +73,25 @@ int | |||
72 | allowed_user(struct passwd * pw) | 73 | allowed_user(struct passwd * pw) |
73 | { | 74 | { |
74 | struct stat st; | 75 | struct stat st; |
75 | const char *hostname = NULL, *ipaddr = NULL; | 76 | const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL; |
76 | char *shell; | 77 | char *shell; |
77 | int i; | 78 | int i; |
78 | #ifdef WITH_AIXAUTHENTICATE | 79 | #if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) |
79 | char *loginmsg; | 80 | struct spwd *spw = NULL; |
80 | #endif /* WITH_AIXAUTHENTICATE */ | ||
81 | #if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \ | ||
82 | !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE) | ||
83 | struct spwd *spw; | ||
84 | time_t today; | ||
85 | #endif | 81 | #endif |
86 | 82 | ||
87 | /* Shouldn't be called if pw is NULL, but better safe than sorry... */ | 83 | /* Shouldn't be called if pw is NULL, but better safe than sorry... */ |
88 | if (!pw || !pw->pw_name) | 84 | if (!pw || !pw->pw_name) |
89 | return 0; | 85 | return 0; |
90 | 86 | ||
91 | #if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \ | 87 | #if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) |
92 | !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE) | 88 | if (!options.use_pam) |
89 | spw = getspnam(pw->pw_name); | ||
90 | #ifdef HAS_SHADOW_EXPIRE | ||
93 | #define DAY (24L * 60 * 60) /* 1 day in seconds */ | 91 | #define DAY (24L * 60 * 60) /* 1 day in seconds */ |
94 | if ((spw = getspnam(pw->pw_name)) != NULL) { | 92 | if (!options.use_pam && spw != NULL) { |
93 | time_t today; | ||
94 | |||
95 | today = time(NULL) / DAY; | 95 | today = time(NULL) / DAY; |
96 | debug3("allowed_user: today %d sp_expire %d sp_lstchg %d" | 96 | debug3("allowed_user: today %d sp_expire %d sp_lstchg %d" |
97 | " sp_max %d", (int)today, (int)spw->sp_expire, | 97 | " sp_max %d", (int)today, (int)spw->sp_expire, |
@@ -102,25 +102,58 @@ allowed_user(struct passwd * pw) | |||
102 | * day after the day specified. | 102 | * day after the day specified. |
103 | */ | 103 | */ |
104 | if (spw->sp_expire != -1 && today > spw->sp_expire) { | 104 | if (spw->sp_expire != -1 && today > spw->sp_expire) { |
105 | log("Account %.100s has expired", pw->pw_name); | 105 | logit("Account %.100s has expired", pw->pw_name); |
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | if (spw->sp_lstchg == 0) { | 109 | if (spw->sp_lstchg == 0) { |
110 | log("User %.100s password has expired (root forced)", | 110 | logit("User %.100s password has expired (root forced)", |
111 | pw->pw_name); | 111 | pw->pw_name); |
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
114 | 114 | ||
115 | if (spw->sp_max != -1 && | 115 | if (spw->sp_max != -1 && |
116 | today > spw->sp_lstchg + spw->sp_max) { | 116 | today > spw->sp_lstchg + spw->sp_max) { |
117 | log("User %.100s password has expired (password aged)", | 117 | logit("User %.100s password has expired (password aged)", |
118 | pw->pw_name); | 118 | pw->pw_name); |
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | } | 121 | } |
122 | #endif /* HAS_SHADOW_EXPIRE */ | ||
123 | #endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */ | ||
124 | |||
125 | /* grab passwd field for locked account check */ | ||
126 | #if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) | ||
127 | if (spw != NULL) | ||
128 | passwd = spw->sp_pwdp; | ||
129 | #else | ||
130 | passwd = pw->pw_passwd; | ||
122 | #endif | 131 | #endif |
123 | 132 | ||
133 | /* check for locked account */ | ||
134 | if (!options.use_pam && passwd && *passwd) { | ||
135 | int locked = 0; | ||
136 | |||
137 | #ifdef LOCKED_PASSWD_STRING | ||
138 | if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0) | ||
139 | locked = 1; | ||
140 | #endif | ||
141 | #ifdef LOCKED_PASSWD_PREFIX | ||
142 | if (strncmp(passwd, LOCKED_PASSWD_PREFIX, | ||
143 | strlen(LOCKED_PASSWD_PREFIX)) == 0) | ||
144 | locked = 1; | ||
145 | #endif | ||
146 | #ifdef LOCKED_PASSWD_SUBSTR | ||
147 | if (strstr(passwd, LOCKED_PASSWD_SUBSTR)) | ||
148 | locked = 1; | ||
149 | #endif | ||
150 | if (locked) { | ||
151 | logit("User %.100s not allowed because account is locked", | ||
152 | pw->pw_name); | ||
153 | return 0; | ||
154 | } | ||
155 | } | ||
156 | |||
124 | /* | 157 | /* |
125 | * Get the shell from the password data. An empty shell field is | 158 | * Get the shell from the password data. An empty shell field is |
126 | * legal, and means /bin/sh. | 159 | * legal, and means /bin/sh. |
@@ -129,19 +162,19 @@ allowed_user(struct passwd * pw) | |||
129 | 162 | ||
130 | /* deny if shell does not exists or is not executable */ | 163 | /* deny if shell does not exists or is not executable */ |
131 | if (stat(shell, &st) != 0) { | 164 | if (stat(shell, &st) != 0) { |
132 | log("User %.100s not allowed because shell %.100s does not exist", | 165 | logit("User %.100s not allowed because shell %.100s does not exist", |
133 | pw->pw_name, shell); | 166 | pw->pw_name, shell); |
134 | return 0; | 167 | return 0; |
135 | } | 168 | } |
136 | if (S_ISREG(st.st_mode) == 0 || | 169 | if (S_ISREG(st.st_mode) == 0 || |
137 | (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { | 170 | (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { |
138 | log("User %.100s not allowed because shell %.100s is not executable", | 171 | logit("User %.100s not allowed because shell %.100s is not executable", |
139 | pw->pw_name, shell); | 172 | pw->pw_name, shell); |
140 | return 0; | 173 | return 0; |
141 | } | 174 | } |
142 | 175 | ||
143 | if (options.num_deny_users > 0 || options.num_allow_users > 0) { | 176 | if (options.num_deny_users > 0 || options.num_allow_users > 0) { |
144 | hostname = get_canonical_hostname(options.verify_reverse_mapping); | 177 | hostname = get_canonical_hostname(options.use_dns); |
145 | ipaddr = get_remote_ipaddr(); | 178 | ipaddr = get_remote_ipaddr(); |
146 | } | 179 | } |
147 | 180 | ||
@@ -150,7 +183,7 @@ allowed_user(struct passwd * pw) | |||
150 | for (i = 0; i < options.num_deny_users; i++) | 183 | for (i = 0; i < options.num_deny_users; i++) |
151 | if (match_user(pw->pw_name, hostname, ipaddr, | 184 | if (match_user(pw->pw_name, hostname, ipaddr, |
152 | options.deny_users[i])) { | 185 | options.deny_users[i])) { |
153 | log("User %.100s not allowed because listed in DenyUsers", | 186 | logit("User %.100s not allowed because listed in DenyUsers", |
154 | pw->pw_name); | 187 | pw->pw_name); |
155 | return 0; | 188 | return 0; |
156 | } | 189 | } |
@@ -163,7 +196,7 @@ allowed_user(struct passwd * pw) | |||
163 | break; | 196 | break; |
164 | /* i < options.num_allow_users iff we break for loop */ | 197 | /* i < options.num_allow_users iff we break for loop */ |
165 | if (i >= options.num_allow_users) { | 198 | if (i >= options.num_allow_users) { |
166 | log("User %.100s not allowed because not listed in AllowUsers", | 199 | logit("User %.100s not allowed because not listed in AllowUsers", |
167 | pw->pw_name); | 200 | pw->pw_name); |
168 | return 0; | 201 | return 0; |
169 | } | 202 | } |
@@ -171,7 +204,7 @@ allowed_user(struct passwd * pw) | |||
171 | if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { | 204 | if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { |
172 | /* Get the user's group access list (primary and supplementary) */ | 205 | /* Get the user's group access list (primary and supplementary) */ |
173 | if (ga_init(pw->pw_name, pw->pw_gid) == 0) { | 206 | if (ga_init(pw->pw_name, pw->pw_gid) == 0) { |
174 | log("User %.100s not allowed because not in any group", | 207 | logit("User %.100s not allowed because not in any group", |
175 | pw->pw_name); | 208 | pw->pw_name); |
176 | return 0; | 209 | return 0; |
177 | } | 210 | } |
@@ -181,7 +214,7 @@ allowed_user(struct passwd * pw) | |||
181 | if (ga_match(options.deny_groups, | 214 | if (ga_match(options.deny_groups, |
182 | options.num_deny_groups)) { | 215 | options.num_deny_groups)) { |
183 | ga_free(); | 216 | ga_free(); |
184 | log("User %.100s not allowed because a group is listed in DenyGroups", | 217 | logit("User %.100s not allowed because a group is listed in DenyGroups", |
185 | pw->pw_name); | 218 | pw->pw_name); |
186 | return 0; | 219 | return 0; |
187 | } | 220 | } |
@@ -193,7 +226,7 @@ allowed_user(struct passwd * pw) | |||
193 | if (!ga_match(options.allow_groups, | 226 | if (!ga_match(options.allow_groups, |
194 | options.num_allow_groups)) { | 227 | options.num_allow_groups)) { |
195 | ga_free(); | 228 | ga_free(); |
196 | log("User %.100s not allowed because none of user's groups are listed in AllowGroups", | 229 | logit("User %.100s not allowed because none of user's groups are listed in AllowGroups", |
197 | pw->pw_name); | 230 | pw->pw_name); |
198 | return 0; | 231 | return 0; |
199 | } | 232 | } |
@@ -206,26 +239,23 @@ allowed_user(struct passwd * pw) | |||
206 | * PermitRootLogin to control logins via ssh), or if running as | 239 | * PermitRootLogin to control logins via ssh), or if running as |
207 | * non-root user (since loginrestrictions will always fail). | 240 | * non-root user (since loginrestrictions will always fail). |
208 | */ | 241 | */ |
209 | if ((pw->pw_uid != 0) && (geteuid() == 0) && | 242 | if ((pw->pw_uid != 0) && (geteuid() == 0)) { |
210 | loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) { | 243 | char *msg; |
211 | int loginrestrict_errno = errno; | 244 | |
212 | 245 | if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg) != 0) { | |
213 | if (loginmsg && *loginmsg) { | 246 | int loginrestrict_errno = errno; |
214 | /* Remove embedded newlines (if any) */ | 247 | |
215 | char *p; | 248 | if (msg && *msg) { |
216 | for (p = loginmsg; *p; p++) { | 249 | buffer_append(&loginmsg, msg, strlen(msg)); |
217 | if (*p == '\n') | 250 | aix_remove_embedded_newlines(msg); |
218 | *p = ' '; | 251 | logit("Login restricted for %s: %.100s", |
252 | pw->pw_name, msg); | ||
219 | } | 253 | } |
220 | /* Remove trailing newline */ | 254 | /* Don't fail if /etc/nologin set */ |
221 | *--p = '\0'; | 255 | if (!(loginrestrict_errno == EPERM && |
222 | log("Login restricted for %s: %.100s", pw->pw_name, | 256 | stat(_PATH_NOLOGIN, &st) == 0)) |
223 | loginmsg); | 257 | return 0; |
224 | } | 258 | } |
225 | /* Don't fail if /etc/nologin set */ | ||
226 | if (!(loginrestrict_errno == EPERM && | ||
227 | stat(_PATH_NOLOGIN, &st) == 0)) | ||
228 | return 0; | ||
229 | } | 259 | } |
230 | #endif /* WITH_AIXAUTHENTICATE */ | 260 | #endif /* WITH_AIXAUTHENTICATE */ |
231 | 261 | ||
@@ -252,7 +282,7 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) | |||
252 | !authctxt->valid || | 282 | !authctxt->valid || |
253 | authctxt->failures >= AUTH_FAIL_LOG || | 283 | authctxt->failures >= AUTH_FAIL_LOG || |
254 | strcmp(method, "password") == 0) | 284 | strcmp(method, "password") == 0) |
255 | authlog = log; | 285 | authlog = logit; |
256 | 286 | ||
257 | if (authctxt->postponed) | 287 | if (authctxt->postponed) |
258 | authmsg = "Postponed"; | 288 | authmsg = "Postponed"; |
@@ -268,13 +298,10 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) | |||
268 | get_remote_port(), | 298 | get_remote_port(), |
269 | info); | 299 | info); |
270 | 300 | ||
271 | #ifdef WITH_AIXAUTHENTICATE | 301 | #ifdef CUSTOM_FAILED_LOGIN |
272 | if (authenticated == 0 && strcmp(method, "password") == 0) | 302 | if (authenticated == 0 && strcmp(method, "password") == 0) |
273 | loginfailed(authctxt->user, | 303 | record_failed_login(authctxt->user, "ssh"); |
274 | get_canonical_hostname(options.verify_reverse_mapping), | 304 | #endif |
275 | "ssh"); | ||
276 | #endif /* WITH_AIXAUTHENTICATE */ | ||
277 | |||
278 | } | 305 | } |
279 | 306 | ||
280 | /* | 307 | /* |
@@ -293,12 +320,12 @@ auth_root_allowed(char *method) | |||
293 | break; | 320 | break; |
294 | case PERMIT_FORCED_ONLY: | 321 | case PERMIT_FORCED_ONLY: |
295 | if (forced_command) { | 322 | if (forced_command) { |
296 | log("Root login accepted for forced command."); | 323 | logit("Root login accepted for forced command."); |
297 | return 1; | 324 | return 1; |
298 | } | 325 | } |
299 | break; | 326 | break; |
300 | } | 327 | } |
301 | log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr()); | 328 | logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr()); |
302 | return 0; | 329 | return 0; |
303 | } | 330 | } |
304 | 331 | ||
@@ -390,7 +417,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, | |||
390 | (stat(user_hostfile, &st) == 0) && | 417 | (stat(user_hostfile, &st) == 0) && |
391 | ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || | 418 | ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || |
392 | (st.st_mode & 022) != 0)) { | 419 | (st.st_mode & 022) != 0)) { |
393 | log("Authentication refused for %.100s: " | 420 | logit("Authentication refused for %.100s: " |
394 | "bad owner or modes for %.200s", | 421 | "bad owner or modes for %.200s", |
395 | pw->pw_name, user_hostfile); | 422 | pw->pw_name, user_hostfile); |
396 | } else { | 423 | } else { |
@@ -494,12 +521,10 @@ getpwnamallow(const char *user) | |||
494 | 521 | ||
495 | pw = getpwnam(user); | 522 | pw = getpwnam(user); |
496 | if (pw == NULL) { | 523 | if (pw == NULL) { |
497 | log("Illegal user %.100s from %.100s", | 524 | logit("Illegal user %.100s from %.100s", |
498 | user, get_remote_ipaddr()); | 525 | user, get_remote_ipaddr()); |
499 | #ifdef WITH_AIXAUTHENTICATE | 526 | #ifdef CUSTOM_FAILED_LOGIN |
500 | loginfailed(user, | 527 | record_failed_login(user, "ssh"); |
501 | get_canonical_hostname(options.verify_reverse_mapping), | ||
502 | "ssh"); | ||
503 | #endif | 528 | #endif |
504 | return (NULL); | 529 | return (NULL); |
505 | } | 530 | } |
@@ -564,3 +589,24 @@ auth_debug_reset(void) | |||
564 | auth_debug_init = 1; | 589 | auth_debug_init = 1; |
565 | } | 590 | } |
566 | } | 591 | } |
592 | |||
593 | struct passwd * | ||
594 | fakepw(void) | ||
595 | { | ||
596 | static struct passwd fake; | ||
597 | |||
598 | memset(&fake, 0, sizeof(fake)); | ||
599 | fake.pw_name = "NOUSER"; | ||
600 | fake.pw_passwd = | ||
601 | "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK"; | ||
602 | fake.pw_gecos = "NOUSER"; | ||
603 | fake.pw_uid = -1; | ||
604 | fake.pw_gid = -1; | ||
605 | #ifdef HAVE_PW_CLASS_IN_PASSWD | ||
606 | fake.pw_class = ""; | ||
607 | #endif | ||
608 | fake.pw_dir = "/nonexist"; | ||
609 | fake.pw_shell = "/nonexist"; | ||
610 | |||
611 | return (&fake); | ||
612 | } | ||