lazysphere/command/su.c

105 lines
2.3 KiB
C
Raw Normal View History

2023-05-15 01:43:02 +00:00
#include "command.h"
#include "lslib.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static struct {
bool clear_env;
bool update_env;
char* shell;
char* user;
} flags;
static bool restricted_shell(const char *shell) {
char *line;
int result = true;
while ((line = getusershell()) != NULL) {
if (strcmp(line, shell) == 0) {
result = false;
break;
}
}
endusershell();
return result;
}
static void help (void) {
printf("Usage: su [-lmp] [-s SH] [-] [USER [FILE ARGS]] \n\n");
printf("Run shell under USER (by default, root)\n\n");
printf("\t-,-l\tClear environment, go to home dir, run shell as login shell\n");
printf("\t-p,-m\tDo not set new $HOME, $SHELL, $USER, $LOGNAME\n");
printf("\t-s SH Shell\tto use instead of user's default\n");
}
static int short_arg (char c, char* next) {
switch (c) {
case 'l':
flags.clear_env = true;
break;
case 'p':
case 'm':
flags.update_env = false;
break;
case 's':
check_arg(next);
flags.shell = next;
return ARG_USED;
default:
return ARG_INVALID;
}
return ARG_UNUSED;
}
COMMAND (su) {
int start, res;
uid_t cur_uid;
struct passwd* pw;
flags.clear_env = false;
flags.update_env = true;
flags.shell = NULL;
flags.user = "root";
start = parse_args(argc, argv, help, short_arg, NULL);
if (start < argc && streql(argv[start], "-")) {
flags.clear_env = true;
start++;
}
if (start < argc)
flags.user = argv[start++];
pw = xgetpwnam(flags.user);
cur_uid = getuid();
if (cur_uid != 0) {
res = prompt_password(pw, "Password: ");
} else {
res = PASSWORD_VALID;
}
if (res != PASSWORD_VALID) {
error("invalid password");
}
if (flags.shell && cur_uid != 0 && pw->pw_shell && restricted_shell(pw->pw_shell)) {
error_s("using restricted shell");
flags.shell = NULL;
}
if (!flags.shell)
flags.shell = pw->pw_shell;
change_identity(pw);
setup_environment(flags.shell, flags.update_env, flags.clear_env, pw);
exec_shell(flags.shell, flags.clear_env, (const char**) &argv[start]);
return EXIT_FAILURE; /* */
}