1
0
Fork 0
mirror of https://gitlab.com/niansa/execontrol.git synced 2025-03-06 20:48:26 +01:00
execontrol/whitelist.c
2023-02-11 16:31:42 +00:00

143 lines
4.6 KiB
C

#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
// Custom getline() implementation because the std one somehow didn't work
ssize_t my_getline(char **out, size_t *out_size, FILE *in) {
size_t out_idx = 0;
// Allocate buffer if needed
if (*out == NULL) {
*out = malloc(1);
*out_size = 1;
}
// Loop until \n
for (;;) {
// Read single character
char c;
if (fread(&c, 1, 1, in) < 0 || feof(in)) {
return -1;
}
// Add it to buffer
if (*out_size < out_idx + 1) {
(*out_size)++;
*out = realloc(*out, *out_size);
}
(*out)[out_idx++] = c;
// Break on \n
if (c == '\n') {
break;
}
}
// Return success
return out_idx + 1;
}
char **read_whitelist(const char *whitelist_path) {
// Open file
FILE *whitelist_file = fopen(whitelist_path, "r");
// Read line for line
size_t whitelist_size = sizeof(char**)*2,
whitelist_top = 0;
char **whitelist = malloc(whitelist_size);
while (!feof(whitelist_file)) {
char *executable = NULL;
size_t executable_len;
if (my_getline(&executable, &executable_len, whitelist_file) >= 0 && executable_len != 0) {
executable[executable_len-1] = '\0';
printf("Added to whitelist: <%zu> %s\n", executable_len, executable);
if (whitelist_top*sizeof(char**) >= whitelist_size-1) {
whitelist_size = (whitelist_top+6)*sizeof(char**);
whitelist = realloc(whitelist, whitelist_size);
}
whitelist[whitelist_top++] = executable;
}
}
// Clean up
whitelist[whitelist_top] = NULL;
fclose(whitelist_file);
return whitelist;
}
void free_whitelist(char **whitelist) {
for (char **item = whitelist; *item != NULL; item++) {
free(*item);
}
free(whitelist);
}
int main(int argc, char **argv) {
// Check arguments
if (argc < 3) {
fprintf(stderr, "Usage: %s <pipe> <whitelist>\n", argv[0]);
return -EINVAL;
}
// Get arguments
char *control_pipe_path = argv[1],
*whitelist_path = argv[2];
size_t control_pipe_path_len = strlen(control_pipe_path);
// Open control pipe
char *control_pipe_full_path[] = {
malloc(control_pipe_path_len+sizeof(".out")),
malloc(control_pipe_path_len+sizeof(".in"))
};
memcpy(control_pipe_full_path[0], control_pipe_path, control_pipe_path_len);
memcpy(control_pipe_full_path[1], control_pipe_path, control_pipe_path_len);
memcpy(control_pipe_full_path[0]+control_pipe_path_len, ".out", sizeof(".out"));
memcpy(control_pipe_full_path[1]+control_pipe_path_len, ".in", sizeof(".in"));
mkfifo(control_pipe_full_path[0], 0600);
mkfifo(control_pipe_full_path[1], 0600);
FILE *control_pipe[] = {
fopen(control_pipe_full_path[0], "rb"),
fopen(control_pipe_full_path[1], "wb")
};
free(control_pipe_full_path[0]);
free(control_pipe_full_path[1]);
// Read whitelist
char **whitelist = read_whitelist(whitelist_path);
// Read each command
for (;;) {
// Read command
struct execontrol_request request;
do_checked(fread, &request, sizeof(request), 1, control_pipe[0]);
// Process command
switch (request.cmd) {
case EXECONTROL_CAN_EXEC: {
// Read executable name
char *executable = NULL;
size_t executable_len;
do_checked(getdelim, &executable, &executable_len, '\0', control_pipe[0]);
printf("Got CAN_EXEC request for file: %s\nChecking whitelist... ", executable);
// Check if file is in whitelist
int whitelisted = 0;
for (char **item = whitelist; *item != NULL; item++) {
if (strcmp(*item, executable) == 0) {
whitelisted = 1;
printf("Hit!\n");
break;
}
}
if (!whitelisted) {
printf("Miss.\n");
}
// Act accordingly
struct execontrol_response response = {
.error = whitelisted?EXECONTROL_OKAY:EXECONTROL_UNSPECIFIED_ERROR
};
do_checked(fwrite, &response, sizeof(response), 1, control_pipe[1]);
// Clean up
free(executable);
} break;
}
// Flush response down the pipe
do_checked(fflush, control_pipe[1]);
}
// Clean up
free_whitelist(whitelist);
}