su: Make it setuid root, ask for a password, and accept a username
It asks for a password only if you are not root, obviously.
This commit is contained in:
parent
477af66cdc
commit
5aba1c5f15
@ -17,6 +17,7 @@ build: $(REAL_APPS)
|
|||||||
install: $(REAL_APPS)
|
install: $(REAL_APPS)
|
||||||
@mkdir -p $(LUNA_ROOT)/initrd/bin
|
@mkdir -p $(LUNA_ROOT)/initrd/bin
|
||||||
cp $(REAL_APPS) $(LUNA_ROOT)/initrd/bin
|
cp $(REAL_APPS) $(LUNA_ROOT)/initrd/bin
|
||||||
|
@chmod a+s $(LUNA_ROOT)/initrd/bin/su
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(APPS_BIN)/*
|
rm -f $(APPS_BIN)/*
|
@ -1,9 +1,10 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
char* default_argv[] = {"/bin/sh", NULL};
|
|
||||||
|
|
||||||
void run_program(char** argv)
|
void run_program(char** argv)
|
||||||
{
|
{
|
||||||
execv(argv[0], argv);
|
execv(argv[0], argv);
|
||||||
@ -12,26 +13,64 @@ void run_program(char** argv)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void strip_newline(char* str)
|
||||||
|
{
|
||||||
|
size_t len = strlen(str);
|
||||||
|
if (str[len - 1] == '\n') str[len - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s [uid] [command | sh]\n", argv[0]);
|
fprintf(stderr, "Usage: %s [username] [command | login shell]\n", argv[0]);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setuid(atoi(argv[1])) < 0)
|
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)
|
||||||
{
|
{
|
||||||
perror("setuid");
|
perror("setuid");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setgid(atoi(argv[1])) < 0)
|
if (setgid(user->pw_gid) < 0)
|
||||||
{
|
{
|
||||||
perror("setgid");
|
perror("setgid");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* default_argv[] = {user->pw_shell, NULL};
|
||||||
|
|
||||||
if (argc == 2) run_program(default_argv);
|
if (argc == 2) run_program(default_argv);
|
||||||
else
|
else
|
||||||
run_program(argv + 2);
|
run_program(argv + 2);
|
||||||
|
Loading…
Reference in New Issue
Block a user