udo/src/main.c

116 lines
2.6 KiB
C

#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;
}