124 lines
2.3 KiB
C
124 lines
2.3 KiB
C
#include <pwd.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <termios.h>
|
|
#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;
|
|
}
|