diff options
| author | Mattias Andrée <maandree@kth.se> | 2021-01-31 14:04:54 +0100 | 
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2021-01-31 14:05:23 +0100 | 
| commit | 2a189d522c0c22c77a8a95ab16f3bf46cdab8926 (patch) | |
| tree | c3330eb02ced21c3da8d4d83df9515d204693cd4 | |
| download | asroot-2a189d522c0c22c77a8a95ab16f3bf46cdab8926.tar.gz asroot-2a189d522c0c22c77a8a95ab16f3bf46cdab8926.tar.bz2 asroot-2a189d522c0c22c77a8a95ab16f3bf46cdab8926.tar.xz | |
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | LICENSE | 15 | ||||
| -rw-r--r-- | Makefile | 29 | ||||
| -rw-r--r-- | arg.h | 45 | ||||
| -rw-r--r-- | asroot.c | 180 | ||||
| -rw-r--r-- | config.mk | 6 | 
6 files changed, 280 insertions, 0 deletions
| diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c48cd59 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*\#* +*~ +*.o +*.su +/asroot @@ -0,0 +1,15 @@ +ISC License + +© 2021 Mattias Andrée <maandree@kth.se> + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9bbde8c --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +.POSIX: + +CONFIGFILE = config.mk +include $(CONFIGFILE) + +all: asroot +asroot.o: asroot.c arg.h + +asroot: asroot.o +	$(CC) -o $@ asroot.o $(LDFLAGS) + +install: asroot +	mkdir -p -- "$(DESTDIR)$(PREFIX)/bin/" +	mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man8/" +	cp -- asroot "$(DESTDIR)$(PREFIX)/bin/asroot" +	cp -- asroot.8 "$(DESTDIR)$(MANPREFIX)/man8/asroot.8" + +post-install: +	chown -- 'root:wheel' "$(DESTDIR)$(PREFIX)/bin/asroot" +	chmod -- 4750 "$(DESTDIR)$(PREFIX)/bin/asroot" + +uninstall: +	-rm -f -- "$(DESTDIR)$(PREFIX)/bin/asroot" +	-rm -f -- "$(DESTDIR)$(MANPREFIX)/man8/asroot.8" + +clean: +	-rm -f -- asroot.o asroot + +.PHONY: all install post-install uninstall clean @@ -0,0 +1,45 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN	for (argv0 = *argv, argv++, argc--;\ +					argv[0] && argv[0][0] && argv[0][1];\ +					argc--, argv++) {\ +				char argc_;\ +				char **argv_;\ +				int brk_;\ +				if (argv[0][0] == '-') {\ +					if (argv[0][1] == '-' && argv[0][2] == '\0') {\ +						argv++;\ +						argc--;\ +						break;\ +					}\ +					for (brk_ = 0, argv[0]++, argv_ = argv;\ +							argv[0][0] && !brk_;\ +							argv[0]++) {\ +						if (argv_ != argv)\ +							break;\ +						argc_ = argv[0][0];\ +						switch (argc_) + +#define ARGEND				}\ +				} else {\ +					break;\ +				}\ +			} + +#define EARGF(x)	((argv[0][1] == '\0' && argv[1] == NULL)?\ +				((x), abort(), (char *)0) :\ +				(brk_ = 1, (argv[0][1] != '\0')?\ +					(&argv[0][1]) :\ +					(argc--, argv++, argv[0]))) + + +#endif diff --git a/asroot.c b/asroot.c new file mode 100644 index 0000000..5f03b42 --- /dev/null +++ b/asroot.c @@ -0,0 +1,180 @@ +#include <errno.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "arg.h" + + +char *argv0; + +extern char **environ; + +static const char *env_whitelist[] = { +	"DISPLAY=", +	"WAYLAND_DISPLAY=", +	"PATH=", +	"TERM=", +	"COLORTERM=", +	"XAUTHORITY=", +	"LANG=", +	"LANGUAGE=", +	"LOCALE=", +	"LC_CTYPE=", +	"LC_NUMERIC=", +	"LC_TIME=", +	"LC_COLLATE=", +	"LC_MONETARY=", +	"LC_MESSAGES=", +	"LC_PAPER=", +	"LC_NAME=", +	"LC_ADDRESS=", +	"LC_TELEPHONE=", +	"LC_MEASUREMENT=", +	"LC_IDENTIFICATION=", +	"LC_ALL=", +	"LOCPATH=", +	"NLSPATH=", +	"TZ=", +	"TZDIR=", +	"SDL_VIDEO_FULLSCREEN_DISPLAY=", +	"EDITOR=", +	"VISUAL=", +	"BROWSER=", +	"DESKTOP_SESSION=", +	"LS_COLORS=", +	"GTK_THEME=", +	"QT_STYLE_OVERRIDE=", +	"PWD=", +	"OLDPWD=", +	"JAVA_HOME=", +	"_JAVA_AWT_WM_NONREPARENTING=", +	"_JAVA_OPTIONS=", +	"MAIN_ALSA_MIXER=", +	"MAIN_ALSA_CARD=", +	"XDG_SEAT=", +	"XDG_SESSION_TYPE=", +	"XDG_SESSION_CLASS=", +	"XDG_VTNR=", +	"XDG_SESSION_ID=", +	"XDG_DATA_DIRS=", +	"XDG_CONFIG_DIRS=", +	"MANPATH=", +	"INFODIR=", +	"PAGER=", +	"ftp_proxy=", +	"http_proxy=", +	NULL +}; + + +static void +usage(void) +{ +	fprintf(stderr, "usage: %s [-e] command [argument] ...\n", argv0); +	exit(125); +} + + +int +main(int argc, char *argv[]) +{ +	int keep_env = 0; +	char **new_environ = NULL; +	size_t i, j, n, len; +	struct passwd *pw; + +	ARGBEGIN { +	case 'e': +		keep_env = 1; +		break; +	default: +		usage(); +	} ARGEND; + +	if (!argc) +		usage(); + +	/* TODO check password */ + +	if (setgid(0)) { +		fprintf(stderr, "%s: setgid 0: %s\n", argv0, strerror(errno)); +		return 125; +	} +	if (setuid(0)) { +		fprintf(stderr, "%s: setuid 0: %s\n", argv0, strerror(errno)); +		return 125; +	} + +	if (!keep_env) { +		new_environ = calloc(sizeof(env_whitelist) / sizeof(*env_whitelist) + 5, sizeof(*env_whitelist)); +		if (!new_environ) { +			fprintf(stderr, "%s: calloc %zu %zu: %s\n", +			        argv0, sizeof(env_whitelist) / sizeof(*env_whitelist) + 5, sizeof(*env_whitelist), strerror(errno)); +			return errno == ENOENT ? 127 : 126; +		} +		for (i = 0, n = 0; env_whitelist[i]; i++) { +			len = strlen(env_whitelist[i]); +			for (j = 0; environ[j]; j++) { +				if (!strncmp(environ[j], env_whitelist[i], len)) { +					new_environ[n++] = environ[j]; +					break; +				} +			} +		} +		errno = 0; +		pw = getpwuid(0); +		if (!pw) { +			if (errno) +				fprintf(stderr, "%s: getpwuid 0: %s\n", argv0, strerror(errno)); +			else +				fprintf(stderr, "%s: cannot find root user\n", argv0); +			exit(125); +		} +		if (pw->pw_dir && *pw->pw_dir) { +			len = strlen(pw->pw_dir); +			len += sizeof("HOME="); +			new_environ[n] = malloc(len); +			if (!new_environ[n]) +				fprintf(stderr, "%s: malloc %zu: %s\n", argv0, len, strerror(errno)); +			stpcpy(stpcpy(new_environ[n++], "HOME="), pw->pw_dir); +		} +		if (pw->pw_name && *pw->pw_name) { +			len = strlen(pw->pw_name); +			len += sizeof("LOGNAME="); +			new_environ[n] = malloc(len); +			if (!new_environ[n]) +				fprintf(stderr, "%s: malloc %zu: %s\n", argv0, len, strerror(errno)); +			stpcpy(stpcpy(new_environ[n++], "LOGNAME="), pw->pw_name); + +			len -= sizeof("LOGNAME="); +			len += sizeof("USER="); +			new_environ[n] = malloc(len); +			if (!new_environ[n]) +				fprintf(stderr, "%s: malloc %zu: %s\n", argv0, len, strerror(errno)); +			stpcpy(stpcpy(new_environ[n++], "USER="), pw->pw_name); + +			len -= sizeof("USER="); +			len += sizeof("MAIL=/var/spool/mail/"); +			new_environ[n] = malloc(len); +			if (!new_environ[n]) +				fprintf(stderr, "%s: malloc %zu: %s\n", argv0, len, strerror(errno)); +			stpcpy(stpcpy(new_environ[n++], "MAIL=/var/spool/mail/"), pw->pw_name); +		} +		if (pw->pw_shell && *pw->pw_shell) { +			len = strlen(pw->pw_dir); +			len += sizeof("SHELL="); +			new_environ[n] = malloc(len); +			if (!new_environ[n]) +				fprintf(stderr, "%s: malloc %zu: %s\n", argv0, len, strerror(errno)); +			stpcpy(stpcpy(new_environ[n++], "SHELL="), pw->pw_dir); +		} +		new_environ[n] = NULL; +	} + +	execvpe(argv[0], argv, new_environ ? new_environ : environ); +	fprintf(stderr, "%s: execvpe %s: %s\n", argv0, argv[0], strerror(errno)); +	return errno == ENOENT ? 127 : 126; +} diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..1f3b2b5 --- /dev/null +++ b/config.mk @@ -0,0 +1,6 @@ +PREFIX    = /usr +MANPREFIX = $(PREFIX)/share/man + +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE +CFLAGS   = -std=c99 -Wall -O2 $(CPPFLAGS) +LDFLAGS  = -s | 
