grimoire/c/ninjutsu.c

73 lines
1.6 KiB
C

#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifndef NINJUTSU_SEC_GROUP
#ifdef __APPLE__
#define NINJUTSU_SEC_GROUP "staff"
#else
#define NINJUTSU_SEC_GROUP "wheel"
#endif
#endif
#define NINJUTSU_SEC_EUID 0
int main(int argc, char **argv) {
if(argc < 2) {
fprintf(stderr, "no command provided\n");
return 1;
} else if(NINJUTSU_SEC_EUID != geteuid()) {
fprintf(stderr, "permissions are incorrect\n");
return 1;
}
struct passwd *entry = getpwuid(getuid());
if(!entry) {
fprintf(stderr, "unable to get passwd entry: %s\n", strerror(errno));
return 1;
}
int groups[NGROUPS_MAX] = { 0 };
int groups_sz = NGROUPS_MAX;
if(getgrouplist(entry->pw_name, entry->pw_gid, groups, &groups_sz) < 0) {
fprintf(stderr, "unable to get full group list\n");
}
struct group *group = getgrnam(NINJUTSU_SEC_GROUP);
if(!group) {
fprintf(stderr, "unable to get group entry: %s\n", strerror(errno));
return 1;
}
uint8_t idx = 0;
uint8_t found_group = 0;
for(; idx < groups_sz; idx += 1) {
if(group->gr_gid == (unsigned int) groups[idx]) {
found_group = 1;
break;
}
}
if(!found_group) {
fprintf(stderr, "I'm sorry, %s. I'm afraid I can't do that.\n", entry->pw_name);
return 1;
} else if(setuid(geteuid()) < 0) {
fprintf(stderr, "could not set uid: %s\n", strerror(errno));
return 1;
} else if(execvp(*(argv + 1), argv + 1) < 0) {
fprintf(stderr, "could not run command: %s\n", strerror(errno));
return 1;
}
return 1;
}