aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-11-07 12:59:31 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-11-07 12:59:31 +0000
commit2ec94a7ee84969dd8b206e1363be8ea58fd6779e (patch)
tree298a47492387a0166cf85a80a7e064a22c383372
parentb0150d299f80b8d0245bd419c78a40a013f03e0c (diff)
downloadbusybox-w32-2ec94a7ee84969dd8b206e1363be8ea58fd6779e.tar.gz
busybox-w32-2ec94a7ee84969dd8b206e1363be8ea58fd6779e.tar.bz2
busybox-w32-2ec94a7ee84969dd8b206e1363be8ea58fd6779e.zip
login: fix /etc/nologin handling (should prohibit non-root LOGINS,
not running login by non-root). minor code shrink. function old new delta login_main 1669 1602 -67
-rw-r--r--loginutils/login.c80
1 files changed, 44 insertions, 36 deletions
diff --git a/loginutils/login.c b/loginutils/login.c
index 861382f12..70e3b1333 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -52,7 +52,7 @@ static char* short_tty;
52 * command line flags. 52 * command line flags.
53 */ 53 */
54 54
55static void read_or_build_utent(struct utmp *utptr, int picky) 55static void read_or_build_utent(struct utmp *utptr, int run_by_root)
56{ 56{
57 struct utmp *ut; 57 struct utmp *ut;
58 pid_t pid = getpid(); 58 pid_t pid = getpid();
@@ -60,30 +60,33 @@ static void read_or_build_utent(struct utmp *utptr, int picky)
60 setutent(); 60 setutent();
61 61
62 /* First, try to find a valid utmp entry for this process. */ 62 /* First, try to find a valid utmp entry for this process. */
63 while ((ut = getutent())) 63 /* If there is one, just use it. */
64 if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] && 64 while ((ut = getutent()) != NULL)
65 (ut->ut_type == LOGIN_PROCESS || ut->ut_type == USER_PROCESS)) 65 if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0]
66 break; 66 && (ut->ut_type == LOGIN_PROCESS || ut->ut_type == USER_PROCESS)
67 ) {
68 *utptr = *ut; /* struct copy */
69 if (run_by_root) /* why only for root? */
70 memset(utptr->ut_host, 0, sizeof(utptr->ut_host));
71 return;
72 }
67 73
68 /* If there is one, just use it, otherwise create a new one. */ 74// Why? Do we require non-root to exec login from another
69 if (ut) { 75// former login process (e.g. login shell)? Some login's have
70 *utptr = *ut; 76// login shells as children, so it won't work...
71 } else { 77// if (!run_by_root)
72 if (picky) 78// bb_error_msg_and_die("no utmp entry found");
73 bb_error_msg_and_die("no utmp entry found"); 79
74 80 /* Otherwise create a new one. */
75 memset(utptr, 0, sizeof(*utptr)); 81 memset(utptr, 0, sizeof(*utptr));
76 utptr->ut_type = LOGIN_PROCESS; 82 utptr->ut_type = LOGIN_PROCESS;
77 utptr->ut_pid = pid; 83 utptr->ut_pid = pid;
78 strncpy(utptr->ut_line, short_tty, sizeof(utptr->ut_line)); 84 strncpy(utptr->ut_line, short_tty, sizeof(utptr->ut_line));
79 /* This one is only 4 chars wide. Try to fit something 85 /* This one is only 4 chars wide. Try to fit something
80 * remotely meaningful by skipping "tty"... */ 86 * remotely meaningful by skipping "tty"... */
81 strncpy(utptr->ut_id, short_tty + 3, sizeof(utptr->ut_id)); 87 strncpy(utptr->ut_id, short_tty + 3, sizeof(utptr->ut_id));
82 strncpy(utptr->ut_user, "LOGIN", sizeof(utptr->ut_user)); 88 strncpy(utptr->ut_user, "LOGIN", sizeof(utptr->ut_user));
83 utptr->ut_tv.tv_sec = time(NULL); 89 utptr->ut_tv.tv_sec = time(NULL);
84 }
85 if (!picky) /* root login */
86 memset(utptr->ut_host, 0, sizeof(utptr->ut_host));
87} 90}
88 91
89/* 92/*
@@ -109,7 +112,7 @@ static void write_utent(struct utmp *utptr, const char *username)
109#endif 112#endif
110} 113}
111#else /* !ENABLE_FEATURE_UTMP */ 114#else /* !ENABLE_FEATURE_UTMP */
112#define read_or_build_utent(utptr, picky) ((void)0) 115#define read_or_build_utent(utptr, run_by_root) ((void)0)
113#define write_utent(utptr, username) ((void)0) 116#define write_utent(utptr, username) ((void)0)
114#endif /* !ENABLE_FEATURE_UTMP */ 117#endif /* !ENABLE_FEATURE_UTMP */
115 118
@@ -225,7 +228,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
225 char *fromhost; 228 char *fromhost;
226 char username[USERNAME_SIZE]; 229 char username[USERNAME_SIZE];
227 const char *tmp; 230 const char *tmp;
228 int amroot; 231 int run_by_root;
229 unsigned opt; 232 unsigned opt;
230 int count = 0; 233 int count = 0;
231 struct passwd *pw; 234 struct passwd *pw;
@@ -248,8 +251,9 @@ int login_main(int argc UNUSED_PARAM, char **argv)
248 signal(SIGALRM, alarm_handler); 251 signal(SIGALRM, alarm_handler);
249 alarm(TIMEOUT); 252 alarm(TIMEOUT);
250 253
251 /* More of suid paranoia if called by non-root */ 254 /* More of suid paranoia if called by non-root: */
252 amroot = !sanitize_env_if_suid(); /* Clear dangerous stuff, set PATH */ 255 /* Clear dangerous stuff, set PATH */
256 run_by_root = !sanitize_env_if_suid();
253 257
254 /* Mandatory paranoia for suid applet: 258 /* Mandatory paranoia for suid applet:
255 * ensure that fd# 0,1,2 are opened (at least to /dev/null) 259 * ensure that fd# 0,1,2 are opened (at least to /dev/null)
@@ -259,7 +263,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
259 263
260 opt = getopt32(argv, "f:h:p", &opt_user, &opt_host); 264 opt = getopt32(argv, "f:h:p", &opt_user, &opt_host);
261 if (opt & LOGIN_OPT_f) { 265 if (opt & LOGIN_OPT_f) {
262 if (!amroot) 266 if (!run_by_root)
263 bb_error_msg_and_die("-f is for root only"); 267 bb_error_msg_and_die("-f is for root only");
264 safe_strncpy(username, opt_user, sizeof(username)); 268 safe_strncpy(username, opt_user, sizeof(username));
265 } 269 }
@@ -278,7 +282,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
278 short_tty = full_tty + 5; 282 short_tty = full_tty + 5;
279 } 283 }
280 284
281 read_or_build_utent(&utent, !amroot); 285 read_or_build_utent(&utent, run_by_root);
282 286
283 if (opt & LOGIN_OPT_h) { 287 if (opt & LOGIN_OPT_h) {
284 USE_FEATURE_UTMP( 288 USE_FEATURE_UTMP(
@@ -396,10 +400,12 @@ int login_main(int argc UNUSED_PARAM, char **argv)
396 return EXIT_FAILURE; 400 return EXIT_FAILURE;
397 } 401 }
398 username[0] = '\0'; 402 username[0] = '\0';
399 } 403 } /* while (1) */
400 404
401 alarm(0); 405 alarm(0);
402 if (!amroot) 406 /* We can ignore /etc/nologin if we are logging in as root,
407 * it doesn't matter whether we are run by root or not */
408 if (pw->pw_uid != 0)
403 die_if_nologin(); 409 die_if_nologin();
404 410
405 write_utent(&utent, username); 411 write_utent(&utent, username);
@@ -433,7 +439,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
433 fchmod(0, 0600); 439 fchmod(0, 0600);
434 440
435 /* We trust environment only if we run by root */ 441 /* We trust environment only if we run by root */
436 if (ENABLE_LOGIN_SCRIPTS && amroot) { 442 if (ENABLE_LOGIN_SCRIPTS && run_by_root) {
437 char *t_argv[2]; 443 char *t_argv[2];
438 444
439 t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT"); 445 t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT");
@@ -479,14 +485,16 @@ int login_main(int argc UNUSED_PARAM, char **argv)
479 // bb_setpgrp(); 485 // bb_setpgrp();
480 // If this stuff is really needed, add it and explain why! 486 // If this stuff is really needed, add it and explain why!
481 487
482 /* set signals to defaults */ 488 /* Set signals to defaults */
483 signal(SIGALRM, SIG_DFL); 489 /*signal(SIGALRM, SIG_DFL); - not needed, we already set it
490 * to non-SIG_IGN, and on exec such signals are reset to SIG_DFL */
491
484 /* Is this correct? This way user can ctrl-c out of /etc/profile, 492 /* Is this correct? This way user can ctrl-c out of /etc/profile,
485 * potentially creating security breach (tested with bash 3.0). 493 * potentially creating security breach (tested with bash 3.0).
486 * But without this, bash 3.0 will not enable ctrl-c either. 494 * But without this, bash 3.0 will not enable ctrl-c either.
487 * Maybe bash is buggy? 495 * Maybe bash is buggy?
488 * Need to find out what standards say about /bin/login - 496 * Need to find out what standards say about /bin/login -
489 * should it leave SIGINT etc enabled or disabled? */ 497 * should we leave SIGINT etc enabled or disabled? */
490 signal(SIGINT, SIG_DFL); 498 signal(SIGINT, SIG_DFL);
491 499
492 /* Exec login shell with no additional parameters */ 500 /* Exec login shell with no additional parameters */