diff options
Diffstat (limited to 'toys/other/login.c')
-rw-r--r-- | toys/other/login.c | 286 |
1 files changed, 134 insertions, 152 deletions
diff --git a/toys/other/login.c b/toys/other/login.c index a9e7562c..72d7063e 100644 --- a/toys/other/login.c +++ b/toys/other/login.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * login.c - Start a session on the system. +/* login.c - Start a session on the system. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> * @@ -10,15 +8,15 @@ USE_LOGIN(NEWTOY(login, ">1fph:", TOYFLAG_BIN)) config LOGIN - bool "login" - default y - help - usage: login [-p] [-h host] [[-f] username] - - Establish a new session with the system. - -p Preserve environment - -h The name of the remote host for this login - -f Do not perform authentication + bool "login" + default y + help + usage: login [-p] [-h host] [[-f] username] + + Establish a new session with the system. + -p Preserve environment + -h The name of the remote host for this login + -f Do not perform authentication */ #define FOR_login @@ -30,215 +28,199 @@ config LOGIN #define HOSTNAME_SIZE 32 GLOBALS( - char *hostname; + char *hostname; ) static void login_timeout_handler(int sig __attribute__((unused))) { - printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT); - exit(0); + printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT); + exit(0); } static char *forbid[] = { - "BASH_ENV", - "ENV", - "HOME", - "IFS", - "LD_LIBRARY_PATH", - "LD_PRELOAD", - "LD_TRACE_LOADED_OBJECTS", - "LD_BIND_NOW", - "LD_AOUT_LIBRARY_PATH", - "LD_AOUT_PRELOAD", - "LD_NOWARN", - "LD_KEEPDIR", - "SHELL", - NULL + "BASH_ENV", "ENV", "HOME", "IFS", "LD_LIBRARY_PATH", "LD_PRELOAD", + "LD_TRACE_LOADED_OBJECTS", "LD_BIND_NOW", "LD_AOUT_LIBRARY_PATH", + "LD_AOUT_PRELOAD", "LD_NOWARN", "LD_KEEPDIR", "SHELL", NULL }; int verify_password(char * pwd) { - char *pass; + char *pass; - if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1; - if (!pwd) return 1; - if (pwd[0] == '!' || pwd[0] == '*') return 1; + if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1; + if (!pwd) return 1; + if (pwd[0] == '!' || pwd[0] == '*') return 1; - pass = crypt(toybuf, pwd); - if (pass && !strcmp(pass, pwd)) return 0; + pass = crypt(toybuf, pwd); + if (pass && !strcmp(pass, pwd)) return 0; - return 1; + return 1; } void read_user(char * buff, int size) { - char hostname[HOSTNAME_SIZE+1]; - int i = 0; - hostname[HOSTNAME_SIZE] = 0; - if(!gethostname(hostname, HOSTNAME_SIZE)) fputs(hostname, stdout); - - fputs(" login: ", stdout); - fflush(stdout); - - do { - buff[0] = getchar(); - if (buff[0] == EOF) - exit(EXIT_FAILURE); - } while (isblank(buff[0])); - - if (buff[0] != '\n') - if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin)) - _exit(1); - - while(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++; - buff[i] = 0; + char hostname[HOSTNAME_SIZE+1]; + int i = 0; + hostname[HOSTNAME_SIZE] = 0; + if(!gethostname(hostname, HOSTNAME_SIZE)) fputs(hostname, stdout); + + fputs(" login: ", stdout); + fflush(stdout); + + do { + buff[0] = getchar(); + if (buff[0] == EOF) exit(EXIT_FAILURE); + } while (isblank(buff[0])); + + if (buff[0] != '\n') if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin)) _exit(1); + + while(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++; + buff[i] = 0; } void handle_nologin(void) { - int fd = open("/etc/nologin", O_RDONLY); - int size; - if (fd == -1) return; - - size = readall(fd, toybuf,sizeof(toybuf)-1); - toybuf[size] = 0; - if (!size) puts("System closed for routine maintenance\n"); - else puts(toybuf); - - close(fd); - fflush(stdout); - exit(EXIT_FAILURE); + int fd = open("/etc/nologin", O_RDONLY); + int size; + if (fd == -1) return; + + size = readall(fd, toybuf,sizeof(toybuf)-1); + toybuf[size] = 0; + if (!size) puts("System closed for routine maintenance\n"); + else puts(toybuf); + + close(fd); + fflush(stdout); + exit(EXIT_FAILURE); } void handle_motd(void) { - int fd = open("/etc/motd", O_RDONLY); - int size; - if (fd == -1) return; + int fd = open("/etc/motd", O_RDONLY); + int size; + if (fd == -1) return; - size = readall(fd, toybuf,sizeof(toybuf)-1); - toybuf[size] = 0; - puts(toybuf); + size = readall(fd, toybuf,sizeof(toybuf)-1); + toybuf[size] = 0; + puts(toybuf); - close(fd); - fflush(stdout); + close(fd); + fflush(stdout); } int change_identity(const struct passwd *pwd) { - if (initgroups(pwd->pw_name,pwd->pw_gid)) return 1; - if (setgid(pwd->pw_uid)) return 1; - if (setuid(pwd->pw_uid)) return 1; + if (initgroups(pwd->pw_name,pwd->pw_gid)) return 1; + if (setgid(pwd->pw_uid)) return 1; + if (setuid(pwd->pw_uid)) return 1; - return 0; + return 0; } void spawn_shell(const char *shell) { - const char * exec_name = strrchr(shell,'/'); - if (exec_name) exec_name++; - else exec_name = shell; + const char * exec_name = strrchr(shell,'/'); + if (exec_name) exec_name++; + else exec_name = shell; - snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell); - execl(shell, toybuf, NULL); - error_exit("Failed to spawn shell"); + snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell); + execl(shell, toybuf, NULL); + error_exit("Failed to spawn shell"); } void setup_environment(const struct passwd *pwd, int clear_env) { - if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir); - - if (clear_env) { - const char * term = getenv("TERM"); - clearenv(); - if (term) setenv("TERM", term, 1); - } - - setenv("USER", pwd->pw_name, 1); - setenv("LOGNAME", pwd->pw_name, 1); - setenv("HOME", pwd->pw_dir, 1); - setenv("SHELL", pwd->pw_shell, 1); + if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir); + + if (clear_env) { + const char * term = getenv("TERM"); + clearenv(); + if (term) setenv("TERM", term, 1); + } + + setenv("USER", pwd->pw_name, 1); + setenv("LOGNAME", pwd->pw_name, 1); + setenv("HOME", pwd->pw_dir, 1); + setenv("SHELL", pwd->pw_shell, 1); } void login_main(void) { - int f_flag = toys.optflags & FLAG_f; - int h_flag = toys.optflags & FLAG_h; - char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss; - struct passwd * pwd = NULL; - struct spwd * spwd = NULL; - int auth_fail_cnt = 0; + int f_flag = toys.optflags & FLAG_f; + int h_flag = toys.optflags & FLAG_h; + char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss; + struct passwd * pwd = NULL; + struct spwd * spwd = NULL; + int auth_fail_cnt = 0; - if (f_flag && toys.optc != 1) - error_exit("-f requires username"); + if (f_flag && toys.optc != 1) error_exit("-f requires username"); - if (geteuid()) error_exit("not root"); + if (geteuid()) error_exit("not root"); - if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty"); + if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty"); - openlog("login", LOG_PID | LOG_CONS, LOG_AUTH); - signal(SIGALRM, login_timeout_handler); - alarm(LOGIN_TIMEOUT); + openlog("login", LOG_PID | LOG_CONS, LOG_AUTH); + signal(SIGALRM, login_timeout_handler); + alarm(LOGIN_TIMEOUT); - for (ss = forbid; *ss; ss++) unsetenv(*ss); + for (ss = forbid; *ss; ss++) unsetenv(*ss); - while (1) { - tcflush(0, TCIFLUSH); + while (1) { + tcflush(0, TCIFLUSH); - username[USER_NAME_MAX_SIZE] = 0; - if (toys.optargs[0]) - strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE); - else { - read_user(username, USER_NAME_MAX_SIZE+1); - if (username[0] == 0) continue; - } + username[USER_NAME_MAX_SIZE] = 0; + if (toys.optargs[0]) strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE); + else { + read_user(username, USER_NAME_MAX_SIZE+1); + if (username[0] == 0) continue; + } - pwd = getpwnam(username); - if (!pwd) goto query_pass; // Non-existing user + pwd = getpwnam(username); + if (!pwd) goto query_pass; // Non-existing user - if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*') - goto query_pass; // Locked account + if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*') + goto query_pass; // Locked account - if (f_flag) break; // Pre-authenticated + if (f_flag) break; // Pre-authenticated - if (!pwd->pw_passwd[0]) break; // Password-less account + if (!pwd->pw_passwd[0]) break; // Password-less account - pass = pwd->pw_passwd; - if (pwd->pw_passwd[0] == 'x') { - spwd = getspnam (username); - if (spwd) pass = spwd->sp_pwdp; - } + pass = pwd->pw_passwd; + if (pwd->pw_passwd[0] == 'x') { + spwd = getspnam (username); + if (spwd) pass = spwd->sp_pwdp; + } query_pass: - if (!verify_password(pass)) break; + if (!verify_password(pass)) break; - f_flag = 0; - syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, - ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); + f_flag = 0; + syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); - sleep(LOGIN_FAIL_TIMEOUT); - puts("Login incorrect"); + sleep(LOGIN_FAIL_TIMEOUT); + puts("Login incorrect"); - if (++auth_fail_cnt == 3) - error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt); + if (++auth_fail_cnt == 3) + error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt); - username[0] = 0; - pwd = NULL; - spwd = NULL; - } + username[0] = 0; + pwd = NULL; + spwd = NULL; + } - alarm(0); + alarm(0); - if (pwd->pw_uid) handle_nologin(); + if (pwd->pw_uid) handle_nologin(); - if (change_identity(pwd)) error_exit("Failed to change identity"); + if (change_identity(pwd)) error_exit("Failed to change identity"); - setup_environment(pwd, !(toys.optflags & FLAG_p)); + setup_environment(pwd, !(toys.optflags & FLAG_p)); - handle_motd(); + handle_motd(); - syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, - ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); + syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); - spawn_shell(pwd->pw_shell); + spawn_shell(pwd->pw_shell); } |