|
Lines 36-41
Link Here
|
| 36 |
#include <libgen.h> |
36 |
#include <libgen.h> |
| 37 |
#endif |
37 |
#endif |
| 38 |
|
38 |
|
|
|
39 |
#ifdef WITH_AIXAUTHENTICATE |
| 40 |
#include <userpw.h> |
| 41 |
#include <usersec.h> |
| 42 |
#endif |
| 43 |
|
| 39 |
#include "xmalloc.h" |
44 |
#include "xmalloc.h" |
| 40 |
#include "match.h" |
45 |
#include "match.h" |
| 41 |
#include "groupaccess.h" |
46 |
#include "groupaccess.h" |
|
Lines 51-59
Link Here
|
| 51 |
#include "misc.h" |
56 |
#include "misc.h" |
| 52 |
#include "bufaux.h" |
57 |
#include "bufaux.h" |
| 53 |
#include "packet.h" |
58 |
#include "packet.h" |
|
|
59 |
#include "sshlogin.h" |
| 54 |
|
60 |
|
| 55 |
/* import */ |
61 |
/* import */ |
| 56 |
extern ServerOptions options; |
62 |
extern ServerOptions options; |
|
|
63 |
extern Buffer expire_message; |
| 64 |
extern Buffer login_message; |
| 57 |
|
65 |
|
| 58 |
/* Debugging messages */ |
66 |
/* Debugging messages */ |
| 59 |
Buffer auth_debug; |
67 |
Buffer auth_debug; |
|
Lines 75-83
Link Here
|
| 75 |
const char *hostname = NULL, *ipaddr = NULL; |
83 |
const char *hostname = NULL, *ipaddr = NULL; |
| 76 |
char *shell; |
84 |
char *shell; |
| 77 |
int i; |
85 |
int i; |
| 78 |
#ifdef WITH_AIXAUTHENTICATE |
|
|
| 79 |
char *loginmsg; |
| 80 |
#endif /* WITH_AIXAUTHENTICATE */ |
| 81 |
#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \ |
86 |
#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \ |
| 82 |
!defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE) |
87 |
!defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE) |
| 83 |
struct spwd *spw; |
88 |
struct spwd *spw; |
|
Lines 88-122
Link Here
|
| 88 |
if (!pw || !pw->pw_name) |
93 |
if (!pw || !pw->pw_name) |
| 89 |
return 0; |
94 |
return 0; |
| 90 |
|
95 |
|
|
|
96 |
#define DAY (24L * 60 * 60) /* 1 day in seconds */ |
| 97 |
#define WEEK (DAY * 7) /* 1 week in seconds */ |
| 91 |
#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \ |
98 |
#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \ |
| 92 |
!defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE) |
99 |
!defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE) |
| 93 |
#define DAY (24L * 60 * 60) /* 1 day in seconds */ |
|
|
| 94 |
if ((spw = getspnam(pw->pw_name)) != NULL) { |
100 |
if ((spw = getspnam(pw->pw_name)) != NULL) { |
|
|
101 |
int daysleft; |
| 102 |
|
| 95 |
today = time(NULL) / DAY; |
103 |
today = time(NULL) / DAY; |
| 96 |
debug3("allowed_user: today %d sp_expire %d sp_lstchg %d" |
104 |
debug3("allowed_user: today %d sp_expire %d sp_lstchg %d" |
| 97 |
" sp_max %d", (int)today, (int)spw->sp_expire, |
105 |
" sp_max %d sp_warn %d", (int)today, (int)spw->sp_expire, |
| 98 |
(int)spw->sp_lstchg, (int)spw->sp_max); |
106 |
(int)spw->sp_lstchg, (int)spw->sp_max, (int)spw->sp_warn); |
| 99 |
|
107 |
|
| 100 |
/* |
108 |
/* |
| 101 |
* We assume account and password expiration occurs the |
109 |
* We assume account and password expiration occurs the |
| 102 |
* day after the day specified. |
110 |
* day after the day specified. |
| 103 |
*/ |
111 |
*/ |
| 104 |
if (spw->sp_expire != -1 && today > spw->sp_expire) { |
112 |
daysleft = spw->sp_expire - today; |
|
|
113 |
if (spw->sp_expire == -1) { |
| 114 |
debug3("account expiration disabled"); |
| 115 |
} else if (today > spw->sp_expire) { |
| 105 |
log("Account %.100s has expired", pw->pw_name); |
116 |
log("Account %.100s has expired", pw->pw_name); |
| 106 |
return 0; |
117 |
return 0; |
| 107 |
} |
118 |
} else if (daysleft <= spw->sp_warn) { |
|
|
119 |
char buf[256]; |
| 108 |
|
120 |
|
| 109 |
if (spw->sp_lstchg == 0) { |
121 |
debug3("account will expire in %d days", daysleft); |
|
|
122 |
snprintf(buf, sizeof(buf), |
| 123 |
"Your account will expire in %d day%s.\n", |
| 124 |
daysleft, daysleft == 1 ? "" : "s"); |
| 125 |
buffer_append(&login_message, buf, strlen(buf)); |
| 126 |
} |
| 127 |
|
| 128 |
#define PWCHG_FORCED "You must change your password now.\n" |
| 129 |
#define PWCHG_EXPIRED "Your password has expired, you must change it now.\n" |
| 130 |
daysleft = spw->sp_lstchg + spw->sp_max - today; |
| 131 |
if (spw->sp_max == -1) { |
| 132 |
debug3("password expiration disabled"); |
| 133 |
} else if (spw->sp_lstchg == 0) { |
| 110 |
log("User %.100s password has expired (root forced)", |
134 |
log("User %.100s password has expired (root forced)", |
| 111 |
pw->pw_name); |
135 |
pw->pw_name); |
| 112 |
return 0; |
136 |
flag_password_change_required(); |
| 113 |
} |
137 |
buffer_append(&expire_message, PWCHG_FORCED, |
| 114 |
|
138 |
sizeof(PWCHG_FORCED)); |
| 115 |
if (spw->sp_max != -1 && |
139 |
} else if (daysleft < 0) { |
| 116 |
today > spw->sp_lstchg + spw->sp_max) { |
|
|
| 117 |
log("User %.100s password has expired (password aged)", |
140 |
log("User %.100s password has expired (password aged)", |
| 118 |
pw->pw_name); |
141 |
pw->pw_name); |
| 119 |
return 0; |
142 |
flag_password_change_required(); |
|
|
143 |
buffer_append(&expire_message, PWCHG_EXPIRED, |
| 144 |
sizeof(PWCHG_EXPIRED)); |
| 145 |
} else if (daysleft <= spw->sp_warn) { |
| 146 |
char buf[256]; |
| 147 |
|
| 148 |
debug3("password will expire in %d days", daysleft); |
| 149 |
snprintf(buf, sizeof(buf), |
| 150 |
"Your password will expire in %d day%s.\n", |
| 151 |
daysleft, daysleft == 1 ? "" : "s"); |
| 152 |
buffer_append(&expire_message, buf, strlen(buf)); |
| 120 |
} |
153 |
} |
| 121 |
} |
154 |
} |
| 122 |
#endif |
155 |
#endif |
|
Lines 206-231
Link Here
|
| 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) { |
|
|
| 211 |
int loginrestrict_errno = errno; |
243 |
int loginrestrict_errno = errno; |
|
|
244 |
char *msg; |
| 212 |
|
245 |
|
| 213 |
if (loginmsg && *loginmsg) { |
246 |
/* check for AIX account restrictions */ |
| 214 |
/* Remove embedded newlines (if any) */ |
247 |
if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg) != 0) { |
| 215 |
char *p; |
248 |
if (msg && *msg) { |
| 216 |
for (p = loginmsg; *p; p++) { |
249 |
aix_remove_embedded_newlines(msg); |
| 217 |
if (*p == '\n') |
250 |
log("Login restricted for %s: %.100s", |
| 218 |
*p = ' '; |
251 |
pw->pw_name, msg); |
|
|
252 |
xfree(msg); |
| 219 |
} |
253 |
} |
| 220 |
/* Remove trailing newline */ |
254 |
|
| 221 |
*--p = '\0'; |
255 |
/* Don't fail if /etc/nologin set */ |
| 222 |
log("Login restricted for %s: %.100s", pw->pw_name, |
256 |
if (!(loginrestrict_errno == EPERM && |
| 223 |
loginmsg); |
257 |
stat(_PATH_NOLOGIN, &st) == 0)) |
| 224 |
} |
258 |
return 0; |
| 225 |
/* Don't fail if /etc/nologin set */ |
259 |
} |
| 226 |
if (!(loginrestrict_errno == EPERM && |
260 |
} |
| 227 |
stat(_PATH_NOLOGIN, &st) == 0)) |
261 |
|
| 228 |
return 0; |
262 |
|
|
|
263 |
/* |
| 264 |
* Check AIX password expiry. Only check when running as root. |
| 265 |
* Unpriv'ed users can't access /etc/security/passwd or |
| 266 |
* /etc/security/user so passwdexpired will always fail. |
| 267 |
*/ |
| 268 |
if (geteuid() == 0) { |
| 269 |
char *msg; |
| 270 |
int result, maxexpired; |
| 271 |
struct userpw *upw; |
| 272 |
|
| 273 |
/* check if password expired too long */ |
| 274 |
upw = getuserpw(pw->pw_name); |
| 275 |
result = getuserattr(pw->pw_name, S_MAXEXPIRED, &maxexpired, |
| 276 |
SEC_INT); |
| 277 |
if (upw != NULL && result == 0) { |
| 278 |
debug3("%s lastupdate %lu maxexpired %d wks time %d", |
| 279 |
__func__, upw->upw_lastupdate, maxexpired, |
| 280 |
(int)time(NULL)); |
| 281 |
if (maxexpired != -1 && upw->upw_lastupdate + |
| 282 |
(maxexpired*WEEK) <= time(NULL) ){ |
| 283 |
log("User %.100s password expired too long", |
| 284 |
pw->pw_name); |
| 285 |
return 0; |
| 286 |
} |
| 287 |
} |
| 288 |
|
| 289 |
result = passwdexpired(pw->pw_name, &msg); |
| 290 |
buffer_append(&expire_message, msg, strlen(msg)); |
| 291 |
if (msg && *msg) |
| 292 |
aix_remove_embedded_newlines(msg); |
| 293 |
debug3("AIX/passwdexpired returned %d msg %.100s", result, msg); |
| 294 |
|
| 295 |
switch (result) { |
| 296 |
case 0: /* success, password not expired */ |
| 297 |
break; |
| 298 |
case 1: /* expired, password change required */ |
| 299 |
flag_password_change_required(); |
| 300 |
break; |
| 301 |
default: /* user can't change(2) or other error (-1) */ |
| 302 |
log("Password can't be changed for user %s: " |
| 303 |
"%.100s", pw->pw_name, msg); |
| 304 |
if (msg) |
| 305 |
xfree(msg); |
| 306 |
return 0; |
| 307 |
} |
| 308 |
if (msg) |
| 309 |
xfree(msg); |
| 310 |
|
| 229 |
} |
311 |
} |
| 230 |
#endif /* WITH_AIXAUTHENTICATE */ |
312 |
#endif /* WITH_AIXAUTHENTICATE */ |
| 231 |
|
313 |
|
|
Lines 241-246
Link Here
|
| 241 |
return authctxt; |
323 |
return authctxt; |
| 242 |
} |
324 |
} |
| 243 |
|
325 |
|
|
|
326 |
/* |
| 327 |
* Generate last_login message and store for later display. This must be |
| 328 |
* called before login_login() is called and lastlog is updated. |
| 329 |
*/ |
| 330 |
void |
| 331 |
generate_login_message(const char *user, uid_t uid, const char *host) |
| 332 |
{ |
| 333 |
#ifdef WITH_AIXAUTHENTICATE |
| 334 |
char *msg; |
| 335 |
|
| 336 |
/* We don't have a pty yet, so just label the line as "ssh" */ |
| 337 |
if (loginsuccess(user, host, "ssh", &msg) >= 0) |
| 338 |
buffer_append(&login_message, msg, strlen(msg)); |
| 339 |
#elif !defined(NO_SSH_LASTLOG) |
| 340 |
if (options.print_lastlog) { |
| 341 |
char *time_string, lasthost[MAXHOSTNAMELEN], buf[256]; |
| 342 |
time_t last_login_time; |
| 343 |
|
| 344 |
last_login_time = get_last_login_time(uid, user, lasthost, |
| 345 |
sizeof(lasthost)); |
| 346 |
|
| 347 |
if (last_login_time != 0) { |
| 348 |
time_string = ctime(&last_login_time); |
| 349 |
if (strchr(time_string, '\n')) |
| 350 |
*strchr(time_string, '\n') = 0; |
| 351 |
if (strcmp(lasthost, "") == 0) |
| 352 |
snprintf(buf, sizeof(buf), |
| 353 |
"Last login: %s\r\n", |
| 354 |
time_string); |
| 355 |
else |
| 356 |
snprintf(buf, sizeof(buf), |
| 357 |
"Last login: %s from %s\r\n", |
| 358 |
time_string, lasthost); |
| 359 |
buffer_append(&login_message, buf, strlen(buf)); |
| 360 |
} |
| 361 |
} |
| 362 |
#endif |
| 363 |
} |
| 364 |
|
| 244 |
void |
365 |
void |
| 245 |
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) |
366 |
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) |
| 246 |
{ |
367 |
{ |
|
Lines 268-273
Link Here
|
| 268 |
get_remote_port(), |
389 |
get_remote_port(), |
| 269 |
info); |
390 |
info); |
| 270 |
|
391 |
|
|
|
392 |
if (authenticated && geteuid() == 0) |
| 393 |
generate_login_message(authctxt->user, authctxt->pw->pw_uid, |
| 394 |
get_canonical_hostname(options.verify_reverse_mapping)); |
| 271 |
#ifdef WITH_AIXAUTHENTICATE |
395 |
#ifdef WITH_AIXAUTHENTICATE |
| 272 |
if (authenticated == 0 && strcmp(method, "password") == 0) |
396 |
if (authenticated == 0 && strcmp(method, "password") == 0) |
| 273 |
loginfailed(authctxt->user, |
397 |
loginfailed(authctxt->user, |