mirror of
https://gitlab.com/niansa/execontrol.git
synced 2025-03-06 20:48:26 +01:00
143 lines
4.6 KiB
C
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);
|
|
}
|