100 lines
1.9 KiB
C++
100 lines
1.9 KiB
C++
#include <bits/termios.h>
|
|
#include <os/ArgumentParser.h>
|
|
#include <pwd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
|
|
static struct termios orig;
|
|
|
|
void restore_terminal()
|
|
{
|
|
ioctl(fileno(stdin), TCSETS, &orig);
|
|
}
|
|
|
|
char* getpass()
|
|
{
|
|
fputs("Password: ", stdout);
|
|
|
|
if (ioctl(fileno(stdin), TCGETS, &orig) < 0)
|
|
{
|
|
perror("ioctl(TCGETS)");
|
|
return nullptr;
|
|
}
|
|
|
|
atexit(restore_terminal);
|
|
|
|
struct termios tc = orig;
|
|
tc.c_lflag &= ~ECHO;
|
|
if (ioctl(fileno(stdin), TCSETS, &tc) < 0)
|
|
{
|
|
perror("ioctl(TCSETS)");
|
|
return nullptr;
|
|
}
|
|
|
|
static char buf[1024];
|
|
char* rc = fgets(buf, sizeof(buf), stdin);
|
|
|
|
restore_terminal();
|
|
putchar('\n');
|
|
|
|
if (!rc)
|
|
{
|
|
perror("fgets");
|
|
return nullptr;
|
|
}
|
|
|
|
char* newline = strrchr(rc, '\n');
|
|
if (newline) *newline = 0;
|
|
|
|
return buf;
|
|
}
|
|
|
|
Result<int> luna_main(int argc, char** argv)
|
|
{
|
|
StringView name;
|
|
|
|
if (geteuid() != 0)
|
|
{
|
|
fprintf(stderr, "su must be setuid root!\n");
|
|
return 1;
|
|
}
|
|
|
|
os::ArgumentParser parser;
|
|
parser.add_description("Switch to a different user (by default, root)."_sv);
|
|
parser.add_system_program_info("su"_sv);
|
|
parser.add_positional_argument(name, "name"_sv, "root"_sv);
|
|
parser.parse(argc, argv);
|
|
|
|
struct passwd* entry = getpwnam(name.chars());
|
|
if (!entry)
|
|
{
|
|
fprintf(stderr, "su: user %s not found!\n", name.chars());
|
|
return 1;
|
|
}
|
|
|
|
if (getuid() != geteuid() && *entry->pw_passwd)
|
|
{
|
|
char* pass = getpass();
|
|
if (!pass) return 1;
|
|
|
|
if (strcmp(pass, entry->pw_passwd))
|
|
{
|
|
fprintf(stderr, "Wrong password!\n");
|
|
return 1;
|
|
}
|
|
|
|
memset(pass, 0, strlen(pass));
|
|
}
|
|
|
|
setgid(entry->pw_gid);
|
|
setuid(entry->pw_uid);
|
|
|
|
chdir(entry->pw_dir);
|
|
|
|
execl(entry->pw_shell, entry->pw_shell, NULL);
|
|
|
|
return 1;
|
|
}
|