initial commit
This commit is contained in:
commit
704272cfeb
6 changed files with 172 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/bin
|
19
Makefile
Normal file
19
Makefile
Normal file
|
@ -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/*
|
19
README.md
Normal file
19
README.md
Normal file
|
@ -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.
|
4
pam.d_udo
Normal file
4
pam.d_udo
Normal file
|
@ -0,0 +1,4 @@
|
|||
#%PAM-1.0
|
||||
auth include system-auth
|
||||
account include system-auth
|
||||
session include system-auth
|
115
src/main.c
Normal file
115
src/main.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "main.h"
|
||||
#include <pwd.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
|
||||
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;
|
||||
}
|
14
src/main.h
Normal file
14
src/main.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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();
|
Loading…
Reference in a new issue