diff options
Diffstat (limited to 'loginutils')
| -rw-r--r-- | loginutils/login.c | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/loginutils/login.c b/loginutils/login.c index bddc0f533..53d3e528b 100644 --- a/loginutils/login.c +++ b/loginutils/login.c | |||
| @@ -239,9 +239,14 @@ int login_main(int argc, char **argv) | |||
| 239 | char full_tty[TTYNAME_SIZE]; | 239 | char full_tty[TTYNAME_SIZE]; |
| 240 | USE_SELINUX(security_context_t user_sid = NULL;) | 240 | USE_SELINUX(security_context_t user_sid = NULL;) |
| 241 | USE_FEATURE_UTMP(struct utmp utent;) | 241 | USE_FEATURE_UTMP(struct utmp utent;) |
| 242 | USE_PAM(pam_handle_t *pamh;) | 242 | #if ENABLE_PAM |
| 243 | USE_PAM(int pamret;) | 243 | int pamret; |
| 244 | USE_PAM(const char *failed_msg;) | 244 | pam_handle_t *pamh; |
| 245 | const char *pamuser; | ||
| 246 | const char *failed_msg; | ||
| 247 | struct passwd pwdstruct; | ||
| 248 | char pwdbuf[256]; | ||
| 249 | #endif | ||
| 245 | 250 | ||
| 246 | short_tty = full_tty; | 251 | short_tty = full_tty; |
| 247 | username[0] = '\0'; | 252 | username[0] = '\0'; |
| @@ -297,18 +302,18 @@ int login_main(int argc, char **argv) | |||
| 297 | #if ENABLE_PAM | 302 | #if ENABLE_PAM |
| 298 | pamret = pam_start("login", username, &conv, &pamh); | 303 | pamret = pam_start("login", username, &conv, &pamh); |
| 299 | if (pamret != PAM_SUCCESS) { | 304 | if (pamret != PAM_SUCCESS) { |
| 300 | failed_msg = "pam_start"; | 305 | failed_msg = "start"; |
| 301 | goto pam_auth_failed; | 306 | goto pam_auth_failed; |
| 302 | } | 307 | } |
| 303 | /* set TTY (so things like securetty work) */ | 308 | /* set TTY (so things like securetty work) */ |
| 304 | pamret = pam_set_item(pamh, PAM_TTY, short_tty); | 309 | pamret = pam_set_item(pamh, PAM_TTY, short_tty); |
| 305 | if (pamret != PAM_SUCCESS) { | 310 | if (pamret != PAM_SUCCESS) { |
| 306 | failed_msg = "pam_set_item(TTY)"; | 311 | failed_msg = "set_item(TTY)"; |
| 307 | goto pam_auth_failed; | 312 | goto pam_auth_failed; |
| 308 | } | 313 | } |
| 309 | pamret = pam_authenticate(pamh, 0); | 314 | pamret = pam_authenticate(pamh, 0); |
| 310 | if (pamret != PAM_SUCCESS) { | 315 | if (pamret != PAM_SUCCESS) { |
| 311 | failed_msg = "pam_authenticate"; | 316 | failed_msg = "authenticate"; |
| 312 | goto pam_auth_failed; | 317 | goto pam_auth_failed; |
| 313 | /* TODO: or just "goto auth_failed" | 318 | /* TODO: or just "goto auth_failed" |
| 314 | * since user seems to enter wrong password | 319 | * since user seems to enter wrong password |
| @@ -318,28 +323,42 @@ int login_main(int argc, char **argv) | |||
| 318 | /* check that the account is healthy */ | 323 | /* check that the account is healthy */ |
| 319 | pamret = pam_acct_mgmt(pamh, 0); | 324 | pamret = pam_acct_mgmt(pamh, 0); |
| 320 | if (pamret != PAM_SUCCESS) { | 325 | if (pamret != PAM_SUCCESS) { |
| 321 | failed_msg = "account setup"; | 326 | failed_msg = "acct_mgmt"; |
| 322 | goto pam_auth_failed; | 327 | goto pam_auth_failed; |
| 323 | } | 328 | } |
| 324 | /* read user back */ | 329 | /* read user back */ |
| 325 | { | 330 | pamuser = NULL; |
| 326 | const char *pamuser; | 331 | /* gcc: "dereferencing type-punned pointer breaks aliasing rules..." |
| 327 | /* gcc: "dereferencing type-punned pointer breaks aliasing rules..." | 332 | * thus we cast to (void*) */ |
| 328 | * thus we cast to (void*) */ | 333 | if (pam_get_item(pamh, PAM_USER, (void*)&pamuser) != PAM_SUCCESS) { |
| 329 | if (pam_get_item(pamh, PAM_USER, (void*)&pamuser) != PAM_SUCCESS) { | 334 | failed_msg = "get_item(USER)"; |
| 330 | failed_msg = "pam_get_item(USER)"; | 335 | goto pam_auth_failed; |
| 331 | goto pam_auth_failed; | ||
| 332 | } | ||
| 333 | safe_strncpy(username, pamuser, sizeof(username)); | ||
| 334 | } | 336 | } |
| 335 | /* If we get here, the user was authenticated, and is | 337 | if (!pamuser || !pamuser[0]) |
| 336 | * granted access. */ | 338 | goto auth_failed; |
| 337 | pw = getpwnam(username); | 339 | safe_strncpy(username, pamuser, sizeof(username)); |
| 338 | if (pw) | 340 | /* Don't use "pw = getpwnam(username);", |
| 339 | break; | 341 | * PAM is said to be capable of destroying static storage |
| 340 | goto auth_failed; | 342 | * used by getpwnam(). We are using safe(r) function */ |
| 343 | pw = NULL; | ||
| 344 | getpwnam_r(username, &pwdstruct, pwdbuf, sizeof(pwdbuf), &pw); | ||
| 345 | if (!pw) | ||
| 346 | goto auth_failed; | ||
| 347 | pamret = pam_open_session(pamh, 0); | ||
| 348 | if (pamret != PAM_SUCCESS) { | ||
| 349 | failed_msg = "open_session"; | ||
| 350 | goto pam_auth_failed; | ||
| 351 | } | ||
| 352 | pamret = pam_setcred(pamh, PAM_ESTABLISH_CRED); | ||
| 353 | if (pamret != PAM_SUCCESS) { | ||
| 354 | failed_msg = "setcred"; | ||
| 355 | goto pam_auth_failed; | ||
| 356 | } | ||
| 357 | break; /* success, continue login process */ | ||
| 358 | |||
| 341 | pam_auth_failed: | 359 | pam_auth_failed: |
| 342 | bb_error_msg("%s failed: %s (%d)", failed_msg, pam_strerror(pamh, pamret), pamret); | 360 | bb_error_msg("pam_%s call failed: %s (%d)", failed_msg, |
| 361 | pam_strerror(pamh, pamret), pamret); | ||
| 343 | safe_strncpy(username, "UNKNOWN", sizeof(username)); | 362 | safe_strncpy(username, "UNKNOWN", sizeof(username)); |
| 344 | #else /* not PAM */ | 363 | #else /* not PAM */ |
| 345 | pw = getpwnam(username); | 364 | pw = getpwnam(username); |
