nndm.c (1696B)
1 #include <errno.h> 2 #include <grp.h> 3 #include <pwd.h> 4 #include <stdarg.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/types.h> 9 #include <unistd.h> 10 11 void 12 die(const char *fmt, ...) { 13 va_list ap; 14 15 va_start(ap, fmt); 16 vfprintf(stderr, fmt, ap); 17 va_end(ap); 18 exit(1); 19 } 20 21 int 22 main(int argc, char **argv) { 23 24 // Check arguments 25 if(argc < 3) 26 die("Usage: nndm <user> <command> <args> ..."); 27 28 char * user = argv[1]; 29 char ** cmd = malloc((argc - 1) * sizeof(char *)); 30 memcpy(cmd, &argv[2], (argc - 2) * sizeof(char *)); 31 cmd[argc - 2] = NULL; 32 33 // Drop privileges 34 struct passwd *pwd; 35 uid_t uid; 36 gid_t gid; 37 char env[5][256] = {"HOME=", "SHELL=", "PATH=", "LOGNAME=", "USER="}; 38 39 char *path = getenv("PATH"); 40 41 if(!(pwd = getpwnam(user))) die("Couldn't find user: %s\n", strerror(errno)); 42 uid = pwd->pw_uid; 43 gid = pwd->pw_gid; 44 45 strcat(env[0], pwd->pw_dir); 46 strcat(env[1], pwd->pw_shell); 47 strcat(env[2], path); 48 strcat(env[3], user); 49 strcat(env[4], user); 50 51 int ngroups = 16; 52 gid_t * groups = malloc(ngroups * sizeof(gid_t *)); 53 if(getgrouplist(user, gid, groups, &ngroups) < 0) { 54 groups = realloc(groups, ngroups * sizeof(gid_t *)); 55 (void) getgrouplist(user, gid, groups, &ngroups); 56 } 57 58 if(setgroups(ngroups, groups) < 0) die("Couldn't set groups: %s\n", strerror(errno)); 59 if(setgid(gid) < 0) die("Couldn't set gid: %s\n", strerror(errno)); 60 if(setuid(uid) < 0) die("Couldn't set uid: %s\n", strerror(errno)); 61 62 if(chdir(pwd->pw_dir) < 0) die("Couldn't set working directory: %s\n", strerror(errno)); 63 64 execvpe(cmd[0], (char **)cmd, (char *[6]){env[0], env[1], env[2], env[3], env[4], NULL}); 65 66 die("Couldn't execve %s: %s\n", cmd[0], strerror(errno)); 67 }