#include #include #include #include #include #include #include #include #include #include "pw_check.h" #define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL) static int hide_input(int fd, int flag) { struct termios term; if (tcgetattr(fd, &term) < 0) return 1; if (flag) term.c_lflag &= ~ECHOFLAGS; else term.c_lflag |= ECHOFLAGS; if (tcsetattr(fd, TCSAFLUSH, &term) < 0) return 1; return 0; } static void login(const struct passwd *pw) { char *shell = (pw->pw_shell[0] == '\0') ? "/bin/sh" : pw->pw_shell; setenv("HOME", pw->pw_dir, 1); setenv("SHELL", shell, 1); setenv("USER", pw->pw_name, 1); setenv("LOGNAME", pw->pw_name, 1); setenv("PATH", "/bin", 1); if (chdir(pw->pw_dir) < 0) { fprintf(stderr, "login: %s\n", strerror(errno)); return; } execlp(shell, shell, "-l", NULL); } static struct passwd *proccess_input(char *hostname) { static char user[512]; static char psswd[512]; /* Username */ printf("Login on %s: ", hostname); fflush(stdout); off_t ret = 0; if ((ret = read(STDIN_FILENO, user, sizeof(user))) <= 0) return NULL; user[ret - 1] = '\0'; struct passwd *pw = getpwnam(user); if (!pw) { fprintf(stderr, "login: Incorrent username\n"); return NULL; } /* Password */ printf("Password: "); fflush(stdout); if (hide_input(STDIN_FILENO, 1)) return NULL; if ((ret = read(STDIN_FILENO, psswd, sizeof(psswd))) <= 0) return NULL; psswd[ret - 1] = '\0'; printf("\n"); if (pw_check("login", pw, psswd)) { memset(psswd, '\0', sizeof(psswd)); return NULL; } memset(psswd, '\0', sizeof(psswd)); return pw; } int main(void) { if ((!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO))) { fprintf(stderr, "login: no tty\n"); return 1; } /* For prompt */ char hostname[HOST_NAME_MAX + 1]; if (gethostname(hostname, sizeof(hostname)) < 0) { fprintf(stderr, "login: %s\n", strerror(errno)); return 1; } signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); struct passwd *pw = proccess_input(hostname); hide_input(STDIN_FILENO, 0); if (!pw) return 1; /* Start */ if (setgid(pw->pw_gid) < 0) { fprintf(stderr, "login: %s\n", strerror(errno)); return 1; } if (setuid(pw->pw_uid) < 0) { fprintf(stderr, "login: %s\n", strerror(errno)); return 1; } login(pw); return 0; }