commit 836d0723d883384c1ea8e1b4c3fd23eced9c8043
parent 8078fe60673809c9ce32dd85613e9f96d7278742
Author: pancake <unknown>
Date:   Thu, 31 Mar 2011 20:56:00 +0200
* Find binaries in PATH when specified in path '*'
* Check return value of lstat
Diffstat:
2 files changed, 39 insertions(+), 11 deletions(-)
diff --git a/config.def.h b/config.def.h
@@ -14,6 +14,7 @@ static struct rule_t rules[] = {
 	{ USER, GROUP, "ifconfig", "/sbin/ifconfig" },
 	{ USER, GROUP, "ls", "/bin/ls" },
 	{ USER, GROUP, "wifi", "/root/wifi.sh" },
-	{ USER, GROUP, "", ""}, // allow to run any program
+	{ USER, GROUP, "cp", "*"}, // allow to run this program in PATH
+	{ USER, GROUP, "*", "*"}, // allow to run any program in PATH
 	{ 0 },
 };
diff --git a/sup.c b/sup.c
@@ -1,13 +1,14 @@
-/* pancake <nopcode.org> -- Copyleft 2009 */
+/* pancake <nopcode.org> -- Copyleft 2009-2011 */
 
 #include <errno.h>
-#include <stdio.h>
 #include <unistd.h>
+#include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 #include <sys/stat.h>
 
 #define HELP "sup [-hlv] [cmd ..]"
-#define VERSION "sup 0.1 pancake <nopcode.org> copyleft 2009"
+#define VERSION "sup 0.1 pancake <nopcode.org> copyleft 2011"
 
 struct rule_t {
 	int uid;
@@ -19,11 +20,30 @@ struct rule_t {
 #include "config.h"
 
 static int die(int ret, const char *org, const char *str) {
-	fprintf (stderr, "%s%s%s\n", org, org?": ":"", str);
+	fprintf (stderr, "%s%s%s\n", org?org:"", org?": ":"", str);
 	return ret;
 }
 
+static char *getpath(const char *str) {
+	struct stat st;
+	static char file[4096];
+	char *p, *path = getenv ("PATH");
+	if (path)
+	for (p = path; *p; p++) {
+		if (*p==':' && (p>path&&*(p-1)!='\\')) {
+			*p = 0;
+			snprintf (file, sizeof (file)-1, "%s/%s", path, str);
+			if (!lstat (file, &st))
+				return file;
+			*p = ':';
+			path = p+1;
+		}
+	}
+	return NULL;
+}
+
 int main(int argc, char **argv) {
+	const char *cmd;
 	int i, uid, gid, ret;
 
 	if (argc < 2 || !strcmp (argv[1], "-h"))
@@ -43,18 +63,25 @@ int main(int argc, char **argv) {
 	gid = getgid ();
 
 	for (i = 0; rules[i].cmd != NULL; i++) {
-		if (!rules[i].cmd[0] || !strcmp (argv[1], rules[i].cmd)) {
+		if (*rules[i].cmd=='*' || !strcmp (argv[1], rules[i].cmd)) {
 #if ENFORCE	
 			struct stat st;
-			lstat (rules[i].path, &st);
+			if (*rules[i].path=='*') {
+				if (*argv[1]=='.' || *argv[1]=='/')
+					cmd = argv[1];
+				else if (!(cmd = getpath (argv[1])))
+					return die (1, "execv", "cannot find program");
+			} else cmd = rules[i].path;
+			if (lstat (cmd, &st) == -1)
+				return die (1, "lstat", "cannot stat program");
 			if (st.st_mode & 0222)
-				return die (1, "stat", "Cannot run writable binaries.");
+				return die (1, "stat", "cannot run writable binaries.");
 #endif
 			if (uid != SETUID && rules[i].uid != -1 && rules[i].uid != uid)
-				return die (1, "urule", "User does not match");
+				return die (1, "urule", "user does not match");
 
 			if (gid != SETGID && rules[i].gid != -1 && rules[i].gid != gid)
-				return die (1, "grule", "Group id does not match");
+				return die (1, "grule", "group id does not match");
 
 			if (setuid (SETUID) == -1 || setgid (SETGID) == -1 ||
 			    seteuid (SETUID) == -1 || setegid (SETGID) == -1)
@@ -67,7 +94,7 @@ int main(int argc, char **argv) {
 				if (chdir (CHRDIR) == -1)
 					return die (1, "chdir", strerror (errno));
 #endif
-			ret = execv (*rules[i].path? rules[i].path:argv[1], argv+1);
+			ret = execv (cmd, argv+1);
 			return die (ret, "execv", strerror (errno));
 		}
 	}