implemented shell wrapper
commands are now run in a subshell, this is often needed for chains of commands where it is not the main command to need the privilege but a subcommand does, for example us echo 30 > /sys/class/backlight/*/brightness it is not echo that needs the elevated privilege but the redirection '>' does.
This commit is contained in:
parent
704914f4cb
commit
37c594c1bd
109
us.c
109
us.c
@ -33,8 +33,10 @@
|
||||
|
||||
static void usage (void);
|
||||
static int perm_set (const char *, const char *);
|
||||
static int authenticate (const char *);
|
||||
|
||||
// FIXME: misc_conv is a separate library, should stick to plain PAM
|
||||
// FIXME: misc_conv is a separate library, should stick to plain PAM or make
|
||||
// our own pam module
|
||||
static struct pam_conv conv = {misc_conv, NULL};
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
@ -66,14 +68,16 @@ int main (int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// Copy argv and argc
|
||||
int c_argc = argc - optind;
|
||||
/*
|
||||
int c_argc = argc - optind + 2;
|
||||
char **c_argv = malloc((c_argc + 1) * sizeof(char *));
|
||||
if (!c_argv) {
|
||||
fprintf(stderr, "malloc: %s\n", strerror(errno));
|
||||
goto fail_end;
|
||||
}
|
||||
for (int i = 0; optind < argc; i++, optind++) {
|
||||
c_argv[0] = shell;
|
||||
c_argv[1] = "-c";
|
||||
for (int i = 2; optind < argc; i++, optind++) {
|
||||
c_argv[i] = strdup(argv[optind]);
|
||||
if (!c_argv[i]) {
|
||||
fprintf(stderr, "getpwid: %s\n", strerror(errno));
|
||||
@ -81,45 +85,50 @@ int main (int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
c_argc[c_argv] = NULL;
|
||||
*/
|
||||
|
||||
if (c_argc == 0) {
|
||||
usage();
|
||||
exit(EINVAL);
|
||||
/* Set argc and argv */
|
||||
// TODO: get the right shell for the user (it is in the passwd struct)
|
||||
char *shell = "/bin/sh";
|
||||
char *command, **c_argv;
|
||||
int size, popind = optind;
|
||||
int c_argc = 3; // /bin/sh -c command
|
||||
|
||||
c_argv = malloc((c_argc + 1) * sizeof(char *));
|
||||
if (!c_argv) {
|
||||
fprintf(stderr, "malloc: %s\n", strerror(errno));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
for (size = 0; optind < argc; optind++)
|
||||
size += strlen(argv[optind]) + 1;
|
||||
command = malloc(sizeof(char) * size);
|
||||
if (!command) {
|
||||
fprintf(stderr, "malloc: %s\n", strerror(errno));
|
||||
exit(errno);
|
||||
}
|
||||
for (optind = popind; optind < argc; optind++) {
|
||||
strcat(command, argv[optind]);
|
||||
strcat(command, " ");
|
||||
}
|
||||
|
||||
c_argv[0] = shell;
|
||||
// FIXME: this should be optional if size is zero: we want just a shell
|
||||
c_argv[1] = "-c";
|
||||
c_argv[2] = command;
|
||||
c_argv[c_argc] = NULL;
|
||||
|
||||
/* Authenticate */
|
||||
uid_t ruid = getuid();
|
||||
struct passwd *pw = getpwuid(ruid);
|
||||
if (!pw) {
|
||||
fprintf(stderr, "getpwid: %s\n", strerror(errno));
|
||||
exit(errno);
|
||||
return errno;
|
||||
}
|
||||
const char *uname = pw->pw_name;
|
||||
if (authenticate(uname) != PAM_SUCCESS)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
pam_handle_t *pamh;
|
||||
int pam_err, count = 0;
|
||||
pam_err = pam_start("User Switcher", uname, &conv, &pamh);
|
||||
if (pam_err != PAM_SUCCESS) {
|
||||
fprintf(stderr, "pam_start: %s\n", pam_strerror(pamh, pam_err));
|
||||
exit(pam_err);
|
||||
}
|
||||
|
||||
do {
|
||||
pam_err = pam_authenticate(pamh, 0);
|
||||
if (pam_err != PAM_SUCCESS)
|
||||
printf("Auth failed: %s\n", pam_strerror(pamh, pam_err));
|
||||
count++;
|
||||
} while (pam_err != PAM_SUCCESS && count < 4);
|
||||
if (pam_err != PAM_SUCCESS) {
|
||||
fprintf(stderr, "better luck next time\n");
|
||||
pam_end(pamh, pam_err);
|
||||
exit(pam_err);
|
||||
}
|
||||
// FIXME: check again for the validity of the login for more security
|
||||
// as in: https://docs.oracle.com/cd/E19120-01/open.solaris/819-2145/pam-20/index.html
|
||||
// FIXME: ^C [SIGINT] will interrupt this call possibly causing a
|
||||
// vulnerability
|
||||
|
||||
pam_end(pamh, pam_err);
|
||||
// TODO: clean up env
|
||||
|
||||
errno = 0;
|
||||
@ -130,7 +139,7 @@ int main (int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Execute the command */
|
||||
if (execvp(*c_argv, c_argv) == -1) // execvp searches in path
|
||||
if (execv(*c_argv, c_argv) == -1) // execvp searches in path
|
||||
fprintf(stderr, "execv: %s\n", strerror(errno));
|
||||
|
||||
/* Cleanup and return */
|
||||
@ -231,3 +240,35 @@ static int perm_set (const char *user, const char *group)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int authenticate (const char *uname)
|
||||
{
|
||||
pam_handle_t *pamh;
|
||||
int pam_err, count = 0;
|
||||
pam_err = pam_start("User Switcher", uname, &conv, &pamh);
|
||||
if (pam_err != PAM_SUCCESS) {
|
||||
fprintf(stderr, "pam_start: %s\n", pam_strerror(pamh, pam_err));
|
||||
return pam_err;
|
||||
}
|
||||
|
||||
do {
|
||||
pam_err = pam_authenticate(pamh, 0);
|
||||
if (pam_err != PAM_SUCCESS)
|
||||
printf("Auth failed: %s\n", pam_strerror(pamh, pam_err));
|
||||
// FIXME: count gets ignored because authentication service has
|
||||
// a set amount of retries giving an error:
|
||||
// Have exhausted maximum number of retries for service
|
||||
count++;
|
||||
} while (pam_err != PAM_SUCCESS && count < 4);
|
||||
if (pam_err != PAM_SUCCESS) {
|
||||
fprintf(stderr, "better luck next time\n");
|
||||
pam_end(pamh, pam_err);
|
||||
return pam_err;
|
||||
}
|
||||
// FIXME: check again for the validity of the login for more security
|
||||
// as in: https://docs.oracle.com/cd/E19120-01/open.solaris/819-2145/pam-20/index.html
|
||||
// FIXME: ^C [SIGINT] will interrupt this call possibly causing a
|
||||
// vulnerability
|
||||
|
||||
return pam_end(pamh, pam_err);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user