Skip to content

Commit

Permalink
handle host.docker.internal #79
Browse files Browse the repository at this point in the history
allowed hosts #71
  • Loading branch information
joegasewicz committed Dec 23, 2024
1 parent f1375e1 commit b0ae526
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 25 deletions.
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ dequeue messages off the queue.
| `--log-level` | Default is `none` (No logging) | `--log-level none` |
| | Debugging level logging (includes all logs) | `--log-level debug` |
| `--daemon` | Run ForestMQ in daemon mode | `--daemon` |

| `--hosts` | Add a list of allowed hosts | `--hosts localhost,127.0.0.1` |
### Options
#### Provider Options:
- `message` - A string, bytes or JSON object.
Expand Down Expand Up @@ -83,13 +83,7 @@ ForestMQ will respond with the following JSON response
```

### Security
Currently, ForestMQ provides the following security features
*Users will be able to define their own list of hosts in the next release*
- Only allowed hosts can make requests to any of ForestMQ's endpoints.
- Allowed hosts:
- `localhost`
- `0.0.0.0`
- `127.0.0.1`
N/A


### Support
Expand Down
22 changes: 20 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ int main(int argc, char *argv[])
u_int16_t msg_size = FMQ_MESSAGE_SIZE;
u_int16_t port = FMQ_TCP_PORT;
int8_t log_level = FMQ_LOG_LEVEL_NONE;
char allowed_hosts[FMQ_ALLOWED_HOSTS_BYTES] = FMQ_DEFAULT_ALLOWED_HOSTS;
char user_hosts[FMQ_ALLOWED_HOSTS_BYTES] = FMQ_DEFAULT_ALLOWED_HOSTS;
char *allowed_hosts[FMQ_ALLOWED_HOSTS_BYTES];
bool run_as_daemon = false;
pid_t daemon_pid;
const char *FORESTMQ_DAEMON = getenv("FORESTMQ_DAEMON");
Expand Down Expand Up @@ -102,10 +103,20 @@ int main(int argc, char *argv[])
FMQ_LOGGER(FMQ_LOG_LEVEL_DEBUG, "Running ForestMQ in daemon mode\n");
}
}
if (strcmp(argv[i], "--hosts") == 0)
{
if (argc < i+1)
goto allowed_hosts_error;
char *allowed_hosts_char = argv[i+1];
if (allowed_hosts_char == NULL)
goto allowed_hosts_error;
strcpy(user_hosts, allowed_hosts_char);
FMQ_LOGGER(FMQ_LOG_LEVEL_DEBUG, "Allowed hosts set to %s\n", user_hosts);
}
}

FMQ_Queue *queue = FMQ_Queue_new(msg_size, log_level);
FMQ_Server *server = FMQ_Server_new(queue, port, log_level, run_as_daemon);
FMQ_Server *server = FMQ_Server_new(queue, port, log_level, run_as_daemon, user_hosts);
if (server->run_as_daemon)
{
daemon_pid = fork();
Expand Down Expand Up @@ -164,4 +175,11 @@ int main(int argc, char *argv[])
"\t`--log-level debug` - all logs\n"
);
exit(EXIT_FAILURE);
allowed_hosts_error:
printf(
"Arg Error:\n"
"--hosts should be set like the following:\n"
"\t`--hosts localhost,0.0.0.0`\n"
);
exit(EXIT_FAILURE);
}
48 changes: 39 additions & 9 deletions server.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,15 +215,15 @@ static char* get_req_method(enum evhttp_cmd_type cmd)
}
}

static void resp_callback(struct evhttp_request *req, void *queue)
static void resp_callback(struct evhttp_request *req, void *server)
{
const FMQ_Queue *q = (FMQ_Queue*)queue;
const FMQ_Server *s = (FMQ_Server*)server;
const FMQ_Queue *q = (FMQ_Queue*)s->queue;
struct evbuffer *reply = evbuffer_new(); // <-- Allocate storage for a new evbuffer.

const char *request_uri = evhttp_request_get_uri(req);
const char *request_host = evhttp_request_get_host(req);
const char *allowed_hosts[FMQ_ALLOWED_HOSTS_LENGTH] = {"localhost", "0.0.0.0", "127.0.0.1", "host.docker.internal"};
const bool host_allowed = check_allowed_hosts(request_host, allowed_hosts);
const bool host_allowed = check_allowed_hosts(request_host, s->allowed_hosts, s->allowed_hosts_len);

struct evhttp_uri *parsed_uri = evhttp_uri_parse(request_uri);
if (!parsed_uri)
Expand All @@ -250,16 +250,16 @@ static void resp_callback(struct evhttp_request *req, void *queue)
// check the method & path
if (strcmp(method, "POST") == 0 && strcmp(request_uri, "/provider") == 0)
{
provider_callback(req, reply, queue);
provider_callback(req, reply, s->queue);

}
else if (strcmp(method, "POST") == 0 && strcmp(request_uri, "/consumer") == 0)
{
consumer_callback(req, reply, queue);
consumer_callback(req, reply, s->queue);
}
else if (strcmp(method, "GET") == 0 && strcmp(request_uri, "/health") == 0)
{
health_callback(req, reply, queue);
health_callback(req, reply, s->queue);
}
else
{
Expand Down Expand Up @@ -296,7 +296,7 @@ static int start_server(FMQ_Server *s)

// evhttp_set_max_body_size() TODO
// handlers
evhttp_set_gencb(http_server, resp_callback, s->queue);
evhttp_set_gencb(http_server, resp_callback, s);
// Add SIGINT event

struct event *sig_int = evsignal_new(base, SIGINT, my_signal_event_cb, base);
Expand All @@ -312,13 +312,43 @@ static int start_server(FMQ_Server *s)
}

FMQ_Server *FMQ_Server_new(FMQ_Queue *queue, const uint16_t port,
const int8_t log_level, bool run_as_daemon)
const int8_t log_level, bool run_as_daemon, char *hosts)
{
FMQ_Server *server = (FMQ_Server*)malloc(sizeof(FMQ_Server));
server->queue = queue;
server->start = start_server;
server->port = port;
server->log_level = log_level;
server->run_as_daemon = run_as_daemon;
// allowed hosts
int maxTokens = 0; // get the number of hosts
for (int i = 0; hosts[i] != '\0'; i++)
{
if (hosts[i] == ',')
maxTokens++;
}
maxTokens++; // 1+ for the last host
server->allowed_hosts_len = maxTokens;
server->allowed_hosts = malloc(maxTokens * sizeof(char *));
if (server->allowed_hosts == NULL)
{
perror("server->allowed_hosts malloc fail");
exit(1);
}
int index = 0;
char *token;
char * delimiter = ",";
token = strtok(hosts, delimiter);
while (token != NULL)
{
server->allowed_hosts[index] = strdup(token);
if (server->allowed_hosts[index] == NULL)
{
perror("strdup failed for server->allowed_hosts");
exit(1);
}
index++;
token = strtok(NULL, delimiter);
}
return server;
}
5 changes: 3 additions & 2 deletions server.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ struct FMQ_Server
uint16_t port;
int8_t log_level;
bool run_as_daemon;
char *allowed_hosts[FMQ_ALLOWED_HOSTS_BYTES];
char **allowed_hosts;
int allowed_hosts_len;
};


FMQ_Server *FMQ_Server_new(FMQ_Queue *queue, const uint16_t port, int8_t log_level,
bool run_as_daemon);
bool run_as_daemon, char *hosts);

#endif //SERVER_H
7 changes: 4 additions & 3 deletions utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
/**
* Used to check if the current incoming request's host matches the allowed hosts array
* @param request_host
* @param allowed_hosts
* @param allowed_hosts
* @param allowed_hosts_len
* @return returns true if a single host matches the incoming requests host
*/
bool check_allowed_hosts(const char *request_host, const char *allowed_hosts[FMQ_ALLOWED_HOSTS_LENGTH])
bool check_allowed_hosts(const char *request_host, char **allowed_hosts, int allowed_hosts_len)
{
for (int i = 0; i < FMQ_ALLOWED_HOSTS_LENGTH; i++)
for (int i = 0; i < allowed_hosts_len; i++)
{
if (strcmp(request_host, allowed_hosts[i]) == 0)
{
Expand Down
3 changes: 2 additions & 1 deletion utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define UTILS_H


bool check_allowed_hosts(const char *request_host, const char *allowed_hosts[FMQ_ALLOWED_HOSTS_LENGTH]);
bool check_allowed_hosts(const char *request_host, char **allowed_hosts,
int allowed_hosts_len);

#endif //UTILS_H

0 comments on commit b0ae526

Please # to comment.