From 704272cfebe809ac3d674b03653f89a3ba077a39 Mon Sep 17 00:00:00 2001 From: TriMill Date: Tue, 8 Nov 2022 00:21:44 -0500 Subject: [PATCH] initial commit --- .gitignore | 1 + Makefile | 19 +++++++++ README.md | 19 +++++++++ pam.d_udo | 4 ++ src/main.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.h | 14 +++++++ 6 files changed, 172 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 pam.d_udo create mode 100644 src/main.c create mode 100644 src/main.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e56e04 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..112e9b3 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +CFLAGS=-O3 -Wall -lpam -lpam_misc +BIN=udo + +all: + mkdir -p bin + gcc $(CFLAGS) $(wildcard src/*.c) -o bin/udo + +install: all + cp bin/udo /usr/local/bin/udo + chown root:root /usr/local/bin/udo + chmod 6755 /usr/local/bin/udo + cp pam.d_udo /etc/pam.d/udo + +uninstall: + rm /usr/local/bin/udo + rm /etc/pam.d/udo + +clean: + rm -r bin/* diff --git a/README.md b/README.md new file mode 100644 index 0000000..502c79e --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# udo + +`udo` is an extremely stripped-down sudo/doas imitation. + +## config + +the config file is located at `/etc/udo.conf`. it is a space-separated list of UIDs that are allowed to use `udo`. this file should probably contain `0` at some point. + +## installation + +`sudo make install` + +## uninstallation + +`sudo make uninstall`, but why would you want to? + +## why does it segfault? + +it only segfaults if you have done something wrong. do not do wrong things. diff --git a/pam.d_udo b/pam.d_udo new file mode 100644 index 0000000..b98216b --- /dev/null +++ b/pam.d_udo @@ -0,0 +1,4 @@ +#%PAM-1.0 +auth include system-auth +account include system-auth +session include system-auth diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..7adbc05 --- /dev/null +++ b/src/main.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include "main.h" +#include +#include +#include + +int main(int argc, char** argv) { + if(argc == 1) { + printf("insufficient\n"); + return 0; + } + uid_t uid = getuid(); + Config config = load_config(); + + struct passwd* pwd = getpwuid(uid); + char* user = pwd->pw_name; + + int result = validate(user); + if(result) { + return 2; + } + + char* cmd = argv[1]; + char* args[argc]; + + for(int i = 0; i < argc-1; i++) { + args[i] = malloc(strlen(argv[i+1])); + strcpy(args[i], argv[i+1]); + } + args[argc-1] = NULL; + + if(allowed(uid, &config)) { + setuid(geteuid()); + setgid(getegid()); + int x = execvp(cmd, args); + return x; + } else { + fprintf(stderr, "nope\n"); + return 1; + } +} + +int validate(char* user) { + pam_handle_t *pamh = NULL; + struct pam_conv conv = {misc_conv, NULL}; + + int status = pam_start("udo", user, &conv, &pamh); + if(status != PAM_SUCCESS) { + printf("bad: %d\n", status); + return 1; + } + + status = pam_authenticate(pamh, 0); + if(status != PAM_SUCCESS) { + printf("wrong: %d\n", status); + return 1; + } + status = pam_acct_mgmt(pamh, 0); + + if (pam_end(pamh,status) != PAM_SUCCESS) { + pamh = NULL; + exit(2); + } + + if(status != PAM_SUCCESS) { + printf("don't: %d\n", status); + return 1; + } + return 0; +} + +int allowed(uid_t uid, Config* config) { + for(int i = 0; i < config->len; i++) { + if(config->uids[i] == uid) { + return 1; + } + } + return 0; +} + +Config load_config() { + FILE* fp = fopen("/etc/udo.conf", "r"); + char* contents = malloc(CHUNK_SIZE + 1); + int offset = 0; + char buf[CHUNK_SIZE]; + int read = CHUNK_SIZE; + while(read == CHUNK_SIZE) { + read = fread(buf, 1, CHUNK_SIZE, fp); + memcpy(contents + offset, buf, read); + offset += read; + if(read == CHUNK_SIZE) { + contents = realloc(contents, offset + CHUNK_SIZE + 1); + } + } + fclose(fp); + contents[offset] = '\0'; + + Config config; + config.uids = malloc(1 * sizeof(uid_t)); + config.len = 0; + + char* ctx; + char* word = strtok_r(contents, " ", &ctx); + while(word != NULL) { + uid_t uid = atoi(word); + config.uids = realloc(config.uids, (config.len+1) * sizeof(uid_t)); + config.uids[config.len++] = uid; + word = strtok_r(NULL, "\n", &ctx); + } + + return config; +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..9fab641 --- /dev/null +++ b/src/main.h @@ -0,0 +1,14 @@ +#include +#include + +#define CHUNK_SIZE 10 + +typedef struct { + uid_t* uids; + int len; +} Config; + +int main(int argc, char** argv); +int allowed(uid_t uid, Config* config); +int validate(char* user); +Config load_config();