Luna/apps/src/su.c

77 lines
1.5 KiB
C
Raw Normal View History

#include <errno.h>
#include <pwd.h>
2022-10-28 15:52:46 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2022-10-28 15:52:46 +00:00
#include <unistd.h>
void run_program(char** argv)
{
execv(argv[0], argv);
perror("execv");
exit(EXIT_FAILURE);
}
void strip_newline(char* str)
{
size_t len = strlen(str);
if (str[len - 1] == '\n') str[len - 1] = 0;
}
2022-10-28 15:52:46 +00:00
int main(int argc, char** argv)
{
if (argc == 1)
{
fprintf(stderr, "Usage: %s [username] [command | login shell]\n", argv[0]);
2022-10-28 15:52:46 +00:00
return EXIT_FAILURE;
}
if (getuid() != 0)
{
fprintf(stderr, "%s must be setuid root", argv[0]);
return EXIT_FAILURE;
}
struct passwd* user = getpwnam(argv[1]);
if (!user)
{
if (errno) perror("getpwnam");
else
fprintf(stderr, "Unknown user %s\n", argv[1]);
return EXIT_FAILURE;
}
if (getuid() != geteuid()) // we were started from a non-root user
{
printf("Password: ");
char buf[BUFSIZ];
fgets(buf, BUFSIZ, stdin);
strip_newline(buf);
putchar('\n');
if (strcmp(buf, user->pw_passwd) != 0)
{
fprintf(stderr, "Invalid password\n");
return EXIT_FAILURE;
}
}
if (setuid(user->pw_uid) < 0)
2022-10-28 15:52:46 +00:00
{
perror("setuid");
return EXIT_FAILURE;
}
if (setgid(user->pw_gid) < 0)
2022-10-28 15:55:56 +00:00
{
perror("setgid");
return EXIT_FAILURE;
}
char* default_argv[] = {user->pw_shell, NULL};
2022-10-28 15:52:46 +00:00
if (argc == 2) run_program(default_argv);
else
run_program(argv + 2);
}