Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/loginutils/login.c
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/loginutils/login.c
r2725 r3232 3 3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 */ 5 6 //usage:#define login_trivial_usage 7 //usage: "[-p] [-h HOST] [[-f] USER]" 8 //usage:#define login_full_usage "\n\n" 9 //usage: "Begin a new session on the system\n" 10 //usage: "\n -f Don't authenticate (user already authenticated)" 11 //usage: "\n -h Name of the remote host" 12 //usage: "\n -p Preserve environment" 13 5 14 #include "libbb.h" 6 15 #include <syslog.h> 7 #if ENABLE_FEATURE_UTMP8 # include <utmp.h> /* USER_PROCESS */9 #endif10 16 #include <sys/resource.h> 11 17 … … 32 38 TIMEOUT = 60, 33 39 EMPTY_USERNAME_COUNT = 10, 34 USERNAME_SIZE = 32, 40 /* Some users found 32 chars limit to be too low: */ 41 USERNAME_SIZE = 64, 35 42 TTYNAME_SIZE = 32, 36 43 }; 37 44 38 static char* short_tty; 45 struct globals { 46 struct termios tty_attrs; 47 } FIX_ALIASING; 48 #define G (*(struct globals*)&bb_common_bufsiz1) 49 #define INIT_G() do { } while (0) 50 39 51 40 52 #if ENABLE_FEATURE_NOLOGIN … … 69 81 70 82 #if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM 71 static int check_securetty( void)83 static int check_securetty(const char *short_tty) 72 84 { 73 85 char *buf = (char*)"/etc/securetty"; /* any non-NULL is ok */ … … 84 96 } 85 97 #else 86 static ALWAYS_INLINE int check_securetty( void) { return 1; }98 static ALWAYS_INLINE int check_securetty(const char *short_tty UNUSED_PARAM) { return 1; } 87 99 #endif 88 100 … … 137 149 #endif 138 150 151 #if ENABLE_LOGIN_SESSION_AS_CHILD && ENABLE_PAM 152 static void login_pam_end(pam_handle_t *pamh) 153 { 154 int pamret; 155 156 pamret = pam_setcred(pamh, PAM_DELETE_CRED); 157 if (pamret != PAM_SUCCESS) { 158 bb_error_msg("pam_%s failed: %s (%d)", "setcred", 159 pam_strerror(pamh, pamret), pamret); 160 } 161 pamret = pam_close_session(pamh, 0); 162 if (pamret != PAM_SUCCESS) { 163 bb_error_msg("pam_%s failed: %s (%d)", "close_session", 164 pam_strerror(pamh, pamret), pamret); 165 } 166 pamret = pam_end(pamh, pamret); 167 if (pamret != PAM_SUCCESS) { 168 bb_error_msg("pam_%s failed: %s (%d)", "end", 169 pam_strerror(pamh, pamret), pamret); 170 } 171 } 172 #endif /* ENABLE_PAM */ 173 139 174 static void get_username_or_die(char *buf, int size_buf) 140 175 { … … 180 215 static void alarm_handler(int sig UNUSED_PARAM) 181 216 { 182 /* This is the escape hatch! 217 /* This is the escape hatch! Poor serial line users and the like 183 218 * arrive here when their connection is broken. 184 219 * We don't want to block here */ 185 ndelay_on(1); 186 printf("\r\nLogin timed out after %d seconds\r\n", TIMEOUT); 220 ndelay_on(STDOUT_FILENO); 221 /* Test for correct attr restoring: 222 * run "getty 0 -" from a shell, enter bogus username, stop at 223 * password prompt, let it time out. Without the tcsetattr below, 224 * when you are back at shell prompt, echo will be still off. 225 */ 226 tcsetattr_stdin_TCSANOW(&G.tty_attrs); 227 printf("\r\nLogin timed out after %u seconds\r\n", TIMEOUT); 187 228 fflush_all(); 188 229 /* unix API is brain damaged regarding O_NONBLOCK, 189 230 * we should undo it, or else we can affect other processes */ 190 ndelay_off( 1);231 ndelay_off(STDOUT_FILENO); 191 232 _exit(EXIT_SUCCESS); 192 233 } … … 202 243 char *fromhost; 203 244 char username[USERNAME_SIZE]; 204 const char *shell;205 245 int run_by_root; 206 246 unsigned opt; … … 210 250 char *opt_user = opt_user; /* for compiler */ 211 251 char *full_tty; 252 char *short_tty; 212 253 IF_SELINUX(security_context_t user_sid = NULL;) 213 254 #if ENABLE_PAM … … 218 259 struct passwd pwdstruct; 219 260 char pwdbuf[256]; 220 #endif 221 222 username[0] = '\0'; 223 signal(SIGALRM, alarm_handler); 224 alarm(TIMEOUT); 261 char **pamenv; 262 #endif 263 #if ENABLE_LOGIN_SESSION_AS_CHILD 264 pid_t child_pid; 265 #endif 266 267 INIT_G(); 225 268 226 269 /* More of suid paranoia if called by non-root: */ … … 234 277 bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE | DAEMON_CLOSE_EXTRA_FDS, NULL); 235 278 279 username[0] = '\0'; 236 280 opt = getopt32(argv, "f:h:p", &opt_user, &opt_host); 237 281 if (opt & LOGIN_OPT_f) { … … 244 288 safe_strncpy(username, argv[0], sizeof(username)); 245 289 246 /* Let's find out and memorize our tty */ 247 if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) 290 /* Save tty attributes - and by doing it, check that it's indeed a tty */ 291 if (tcgetattr(STDIN_FILENO, &G.tty_attrs) < 0 292 || !isatty(STDOUT_FILENO) 293 /*|| !isatty(STDERR_FILENO) - no, guess some people might want to redirect this */ 294 ) { 248 295 return EXIT_FAILURE; /* Must be a terminal */ 296 } 297 298 /* We install timeout handler only _after_ we saved G.tty_attrs */ 299 signal(SIGALRM, alarm_handler); 300 alarm(TIMEOUT); 301 302 /* Find out and memorize our tty name */ 249 303 full_tty = xmalloc_ttyname(STDIN_FILENO); 250 304 if (!full_tty) … … 282 336 goto pam_auth_failed; 283 337 } 284 pamret = pam_authenticate(pamh, 0); 285 if (pamret != PAM_SUCCESS) { 286 failed_msg = "authenticate"; 287 goto pam_auth_failed; 288 /* TODO: or just "goto auth_failed" 289 * since user seems to enter wrong password 290 * (in this case pamret == 7) 291 */ 338 /* set RHOST */ 339 if (opt_host) { 340 pamret = pam_set_item(pamh, PAM_RHOST, opt_host); 341 if (pamret != PAM_SUCCESS) { 342 failed_msg = "set_item(RHOST)"; 343 goto pam_auth_failed; 344 } 345 } 346 if (!(opt & LOGIN_OPT_f)) { 347 pamret = pam_authenticate(pamh, 0); 348 if (pamret != PAM_SUCCESS) { 349 failed_msg = "authenticate"; 350 goto pam_auth_failed; 351 /* TODO: or just "goto auth_failed" 352 * since user seems to enter wrong password 353 * (in this case pamret == 7) 354 */ 355 } 292 356 } 293 357 /* check that the account is healthy */ … … 346 410 break; /* -f USER: success without asking passwd */ 347 411 348 if (pw->pw_uid == 0 && !check_securetty( ))412 if (pw->pw_uid == 0 && !check_securetty(short_tty)) 349 413 goto auth_failed; 350 414 … … 353 417 break; 354 418 fake_it: 355 /* authorization takes place here */ 419 /* Password reading and authorization takes place here. 420 * Note that reads (in no-echo mode) trash tty attributes. 421 * If we get interrupted by SIGALRM, we need to restore attrs. 422 */ 356 423 if (correct_password(pw)) 357 424 break; … … 359 426 auth_failed: 360 427 opt &= ~LOGIN_OPT_f; 361 bb_do_delay( FAIL_DELAY);428 bb_do_delay(LOGIN_FAIL_DELAY); 362 429 /* TODO: doesn't sound like correct English phrase to me */ 363 430 puts("Login incorrect"); … … 380 447 die_if_nologin(); 381 448 382 IF_SELINUX(initselinux(username, full_tty, &user_sid)); 449 #if ENABLE_LOGIN_SESSION_AS_CHILD 450 child_pid = vfork(); 451 if (child_pid != 0) { 452 if (child_pid < 0) 453 bb_perror_msg("vfork"); 454 else { 455 if (safe_waitpid(child_pid, NULL, 0) == -1) 456 bb_perror_msg("waitpid"); 457 update_utmp(child_pid, DEAD_PROCESS, NULL, NULL, NULL); 458 } 459 IF_PAM(login_pam_end(pamh);) 460 return 0; 461 } 462 #endif 463 464 IF_SELINUX(initselinux(username, full_tty, &user_sid);) 383 465 384 466 /* Try these, but don't complain if they fail. … … 394 476 395 477 change_identity(pw); 396 shell = pw->pw_shell; 397 if (!shell || !shell[0]) 398 shell = DEFAULT_SHELL; 399 setup_environment(shell, 478 setup_environment(pw->pw_shell, 400 479 (!(opt & LOGIN_OPT_p) * SETUP_ENV_CLEARENV) + SETUP_ENV_CHANGEENV, 401 480 pw); 481 482 #if ENABLE_PAM 483 /* Modules such as pam_env will setup the PAM environment, 484 * which should be copied into the new environment. */ 485 pamenv = pam_getenvlist(pamh); 486 if (pamenv) while (*pamenv) { 487 putenv(*pamenv); 488 pamenv++; 489 } 490 #endif 402 491 403 492 motd(); … … 435 524 436 525 /* Exec login shell with no additional parameters */ 437 run_shell( shell, 1, NULL, NULL);526 run_shell(pw->pw_shell, 1, NULL, NULL); 438 527 439 528 /* return EXIT_FAILURE; - not reached */
Note:
See TracChangeset
for help on using the changeset viewer.