micro-utils/src/loginutils/login/login.c

120 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 "get_string.h"
#include "pw_check.h"
#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;
}
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);
}
struct passwd *proccess_input(char *hostname) {
static char user[512];
static char psswd[512];
/* Username */
printf("Login on %s: ", hostname);
fflush(stdout);
if (!mu_get_string("login", user, sizeof(user)))
return NULL;
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 (!mu_get_string("login", psswd, sizeof(psswd)))
return NULL;
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;
}