sup.c (2591B)
1 /* pancake <nopcode.org> -- Copyleft 2009-2011 */ 2 3 #include <errno.h> 4 #include <unistd.h> 5 #include <stdio.h> 6 #include <string.h> 7 #include <stdlib.h> 8 #include <sys/stat.h> 9 10 #define HELP "sup [-hlv] [cmd ..]" 11 #define VERSION "sup 0.1 pancake <nopcode.org> copyleft 2011" 12 13 struct rule_t { 14 int uid; 15 int gid; 16 const char *cmd; 17 const char *path; 18 }; 19 20 #include "config.h" 21 22 static int die(int ret, const char *org, const char *str) { 23 fprintf (stderr, "%s%s%s\n", org?org:"", org?": ":"", str); 24 return ret; 25 } 26 27 static char *getpath(const char *str) { 28 struct stat st; 29 static char file[4096]; 30 char *p, *path = getenv ("PATH"); 31 if (path) 32 for (p = path; *p; p++) { 33 if (*p==':' && (p>path&&*(p-1)!='\\')) { 34 *p = 0; 35 snprintf (file, sizeof (file)-1, "%s/%s", path, str); 36 if (!lstat (file, &st)) 37 return file; 38 *p = ':'; 39 path = p+1; 40 } 41 } 42 return NULL; 43 } 44 45 int main(int argc, char **argv) { 46 const char *cmd; 47 int i, uid, gid, ret; 48 49 if (argc < 2 || !strcmp (argv[1], "-h")) 50 return die (1, NULL, HELP); 51 52 if (!strcmp (argv[1], "-v")) 53 return die (1, NULL, VERSION); 54 55 if (!strcmp (argv[1], "-l")) { 56 for (i = 0; rules[i].cmd != NULL; i++) 57 printf ("%d %d %10s %s\n", rules[i].uid, rules[i].gid, 58 rules[i].cmd, rules[i].path); 59 return 0; 60 } 61 62 uid = getuid (); 63 gid = getgid (); 64 65 for (i = 0; rules[i].cmd != NULL; i++) { 66 if (*rules[i].cmd=='*' || !strcmp (argv[1], rules[i].cmd)) { 67 #if ENFORCE 68 struct stat st; 69 if (*rules[i].path=='*') { 70 if (*argv[1]=='.' || *argv[1]=='/') 71 cmd = argv[1]; 72 else if (!(cmd = getpath (argv[1]))) 73 return die (1, "execv", "cannot find program"); 74 } else cmd = rules[i].path; 75 if (lstat (cmd, &st) == -1) 76 return die (1, "lstat", "cannot stat program"); 77 if (st.st_mode & 0222) 78 return die (1, "stat", "cannot run writable binaries."); 79 #endif 80 if (uid != SETUID && rules[i].uid != -1 && rules[i].uid != uid) 81 return die (1, "urule", "user does not match"); 82 83 if (gid != SETGID && rules[i].gid != -1 && rules[i].gid != gid) 84 return die (1, "grule", "group id does not match"); 85 86 if (setuid (SETUID) == -1 || setgid (SETGID) == -1 || 87 seteuid (SETUID) == -1 || setegid (SETGID) == -1) 88 return die (1, "set[e][ug]id", strerror (errno)); 89 #ifdef CHROOT 90 if (*CHROOT) 91 if (chdir (CHROOT) == -1 || chroot (".") == -1) 92 return die (1, "chroot", strerror (errno)); 93 if (*CHRDIR) 94 if (chdir (CHRDIR) == -1) 95 return die (1, "chdir", strerror (errno)); 96 #endif 97 ret = execv (cmd, argv+1); 98 return die (ret, "execv", strerror (errno)); 99 } 100 } 101 102 return die (1, NULL, "Sorry"); 103 }