2024-01-13 22:18:21 +00:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <signal.h>
|
2024-01-20 17:28:02 +00:00
|
|
|
#include <termios.h>
|
2024-01-13 22:18:21 +00:00
|
|
|
#include "pw_check.h"
|
|
|
|
|
2024-01-20 17:28:02 +00:00
|
|
|
#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-01-13 22:18:21 +00:00
|
|
|
void login(const struct passwd *pw) {
|
2024-02-03 15:36:30 +00:00
|
|
|
char *shell = (pw->pw_shell[0] == '\0') ? "/bin/sh" : pw->pw_shell;
|
2024-01-13 22:18:21 +00:00
|
|
|
|
|
|
|
setenv("HOME", pw->pw_dir, 1);
|
|
|
|
setenv("SHELL", shell, 1);
|
|
|
|
setenv("USER", pw->pw_name, 1);
|
|
|
|
setenv("LOGNAME", pw->pw_name, 1);
|
2024-01-21 10:07:27 +00:00
|
|
|
setenv("PATH", "/bin", 1);
|
2024-01-13 22:18:21 +00:00
|
|
|
|
|
|
|
if (chdir(pw->pw_dir) < 0) {
|
|
|
|
fprintf(stderr, "login: %s\n", strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
execlp(shell, shell, "-l", NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct passwd *proccess_input(char *hostname) {
|
|
|
|
static char user[512];
|
|
|
|
static char psswd[512];
|
|
|
|
|
|
|
|
/* Username */
|
2024-01-21 10:07:27 +00:00
|
|
|
printf("Login on %s: ", hostname);
|
|
|
|
fflush(stdout);
|
2024-03-27 19:04:17 +00:00
|
|
|
|
|
|
|
off_t ret = 0;
|
|
|
|
if ((ret = read(STDIN_FILENO, user, sizeof(user))) <= 0)
|
2024-01-13 22:18:21 +00:00
|
|
|
return NULL;
|
|
|
|
|
2024-03-27 19:04:17 +00:00
|
|
|
user[ret - 1] = '\0';
|
|
|
|
|
2024-01-13 22:18:21 +00:00
|
|
|
struct passwd *pw = getpwnam(user);
|
|
|
|
if (!pw) {
|
|
|
|
fprintf(stderr, "login: Incorrent username\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Password */
|
2024-01-21 10:07:27 +00:00
|
|
|
printf("Password: ");
|
|
|
|
fflush(stdout);
|
2024-01-20 17:28:02 +00:00
|
|
|
if (hide_input(STDIN_FILENO, 1))
|
|
|
|
return NULL;
|
|
|
|
|
2024-03-27 19:04:17 +00:00
|
|
|
if ((ret = read(STDIN_FILENO, psswd, sizeof(psswd))) <= 0)
|
2024-01-13 22:18:21 +00:00
|
|
|
return NULL;
|
|
|
|
|
2024-03-27 19:04:17 +00:00
|
|
|
psswd[ret - 1] = '\0';
|
2024-01-21 10:07:27 +00:00
|
|
|
printf("\n");
|
2024-01-13 22:18:21 +00:00
|
|
|
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);
|
2024-01-20 17:28:02 +00:00
|
|
|
hide_input(STDIN_FILENO, 0);
|
2024-01-13 22:18:21 +00:00
|
|
|
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;
|
|
|
|
}
|