diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-11-07 12:59:31 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-11-07 12:59:31 +0000 |
commit | 2ec94a7ee84969dd8b206e1363be8ea58fd6779e (patch) | |
tree | 298a47492387a0166cf85a80a7e064a22c383372 | |
parent | b0150d299f80b8d0245bd419c78a40a013f03e0c (diff) | |
download | busybox-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.c | 80 |
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 | ||
55 | static void read_or_build_utent(struct utmp *utptr, int picky) | 55 | static 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 */ |