2020-12-07 10:49:21 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <locale.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <arpa/inet.h>
|
2020-12-08 06:43:53 +00:00
|
|
|
#include <sys/prctl.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <linux/seccomp.h>
|
2020-12-07 10:49:21 +00:00
|
|
|
|
|
|
|
#define LOGF(x, ...) do { logf_impl(x, __FILE__, __LINE__, __func__, __VA_ARGS__); } while(0);
|
|
|
|
#define LOG(x) do { log_impl(x, __FILE__, __LINE__, __func__); } while(0);
|
|
|
|
#define DEFAULT_PORT 9305
|
|
|
|
#define MBUF_SIZE 2048
|
|
|
|
|
|
|
|
const char *SOCKET_ERROR = "Socket-fout";
|
|
|
|
|
|
|
|
typedef struct mbuf {
|
|
|
|
/// Internal buffer
|
|
|
|
char buffer[MBUF_SIZE];
|
|
|
|
/// Socket/file descriptor
|
|
|
|
int sock;
|
|
|
|
/// Read position
|
|
|
|
size_t rpos,
|
|
|
|
/// Write position
|
|
|
|
wpos;
|
|
|
|
|
|
|
|
} mbuf_t;
|
|
|
|
|
2020-12-08 06:43:53 +00:00
|
|
|
const char *log_path = "/var/log/kerstman.log";
|
|
|
|
FILE *log_file = NULL;
|
|
|
|
|
2020-12-07 10:49:21 +00:00
|
|
|
void log_impl(const char *message, const char *file, int line, const char *func) {
|
2020-12-08 06:43:53 +00:00
|
|
|
fprintf(log_file, "%s:%d:%s: %s\n", file, line, func, message);
|
|
|
|
fflush(log_file);
|
2020-12-07 10:49:21 +00:00
|
|
|
}
|
|
|
|
void logf_impl(const char *message, const char *file, int line, const char *func, ...) {
|
|
|
|
va_list args;
|
|
|
|
va_start(args, func);
|
2020-12-08 06:43:53 +00:00
|
|
|
fprintf(log_file, "%s:%d %s: ", file, line, func);
|
|
|
|
vfprintf(log_file, message, args);
|
|
|
|
fprintf(log_file, "\n");
|
2020-12-07 10:49:21 +00:00
|
|
|
va_end(args);
|
2020-12-08 06:43:53 +00:00
|
|
|
fflush(log_file);
|
2020-12-07 10:49:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int quit_if_fail(int err, const char *failMessage) {
|
|
|
|
if (err < 0) {
|
|
|
|
int no = errno;
|
|
|
|
size_t stringSize = strlen(failMessage) + strlen(strerror(no)) + 2;
|
|
|
|
char *msg = (char *) malloc(stringSize);
|
|
|
|
strcpy(msg, failMessage);
|
|
|
|
strcat(msg, ": ");
|
|
|
|
strcat(msg, strerror(no));
|
|
|
|
LOG(msg);
|
|
|
|
free(msg);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
mbuf_t *mbuf_create(void) {
|
|
|
|
mbuf_t *res = malloc(sizeof(mbuf_t));
|
|
|
|
res->rpos = 0;
|
|
|
|
res->wpos = 0;
|
|
|
|
res->sock = -1;
|
|
|
|
memset(res->buffer, 0, MBUF_SIZE * sizeof(char));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads until it encounters `c` from the given socket
|
|
|
|
*
|
|
|
|
* `c` is not included in the output. The output is null-terminated.
|
|
|
|
*
|
|
|
|
* @param c The character to stop reading
|
|
|
|
* @param out A pointer to allocated memory where the read line can be stored.
|
|
|
|
* @param max_size The max size.
|
|
|
|
*/
|
|
|
|
int mbuf_read_until(mbuf_t *buf, char c, char *out, size_t max_size) {
|
|
|
|
size_t i = 0;
|
|
|
|
ssize_t n;
|
|
|
|
|
|
|
|
while (i < max_size) {
|
|
|
|
if (buf->rpos == buf->wpos) {
|
|
|
|
size_t wpos = buf->wpos % MBUF_SIZE;
|
|
|
|
if ((n = read(buf->sock, buf->buffer + wpos, MBUF_SIZE - wpos)) < 0) {
|
|
|
|
if (errno == EINTR) continue;
|
|
|
|
return -1;
|
|
|
|
} else if (n == 0) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
buf->wpos += n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out[i++] = buf->buffer[buf->rpos++ % MBUF_SIZE];
|
|
|
|
if (out[i - 1] == c) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == max_size) {
|
|
|
|
errno = EOVERFLOW;
|
|
|
|
//LOGF("Buffer is te klein (bijts gelezen %d > %d)", i, max_size);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
out[i - 1] = '\0';
|
|
|
|
return i - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_trommel() {
|
|
|
|
//TODO: implement
|
|
|
|
}
|
|
|
|
|
|
|
|
int do_handshake(mbuf_t *mbuf) {
|
|
|
|
char buf[1024];
|
|
|
|
if (mbuf_read_until(mbuf, '\n', buf, sizeof(buf)) < 0) return -1;
|
|
|
|
int reslen = strlen(buf) - strlen("e gaat 'ie?");
|
|
|
|
if (reslen < 2 || (reslen & 1)) {
|
|
|
|
errno = EPROTO;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t response_size = reslen + 4;
|
|
|
|
char *response = (char *) malloc(response_size);
|
|
|
|
response[0] = '\0';
|
|
|
|
reslen /= 2;
|
|
|
|
for (int i = 0; i < reslen; i++) {
|
|
|
|
strcat(response, "go");
|
|
|
|
}
|
|
|
|
strcat(response, "ed\n");
|
|
|
|
if (write(mbuf->sock, response, response_size) < 0) return -1;
|
|
|
|
free(response);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int do_command_loop(mbuf_t *mbuf) {
|
|
|
|
char buf[1024];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
if ( (len = mbuf_read_until(mbuf, '\n', buf, sizeof(buf))) < 0) return -1;
|
|
|
|
if (len == 0) return 0;
|
|
|
|
LOGF("COMMANDO: %s", buf);
|
|
|
|
if (strcmp(buf, "trommel") == 0) {
|
|
|
|
const char *ok = "oké\n";
|
|
|
|
write(mbuf->sock, ok, strlen(ok) * sizeof(char));
|
|
|
|
} else if (strcmp(buf, "ping") == 0) {
|
|
|
|
write(mbuf->sock, "pong\n", 5 * sizeof(char));
|
|
|
|
} else {
|
|
|
|
const char *mesg = "onbekend commando\n";
|
|
|
|
write(mbuf->sock, mesg, strlen(mesg) * sizeof(char));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
2020-12-08 06:43:53 +00:00
|
|
|
log_file = stderr;
|
2020-12-07 10:49:21 +00:00
|
|
|
if (argc < 3) {
|
|
|
|
const char *format = "GEBRUIK: %s [ADRES] [POORT]";
|
|
|
|
size_t length = strlen(argv[0]) + strlen(format);
|
|
|
|
char *msg = (char *) malloc(length);
|
|
|
|
snprintf(msg, length, format, argv[0]);
|
|
|
|
LOG(msg);
|
|
|
|
free(msg);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
LOG("Kerstezel starten");
|
|
|
|
|
2020-12-08 06:43:53 +00:00
|
|
|
// Daemonize
|
|
|
|
pid_t pid;
|
|
|
|
pid = quit_if_fail(fork(), "Kon niet vorken");
|
|
|
|
if (pid > 0) exit(EXIT_SUCCESS);
|
|
|
|
quit_if_fail(chdir("/"), "Kon werkmap niet veranderen");
|
|
|
|
quit_if_fail(setsid(), "Kon sid niet veranderen");
|
|
|
|
|
|
|
|
// Zorg ervoor dat de daemon geen TTY kan bemachtigen
|
|
|
|
pid = quit_if_fail(fork(), "Kon niet vorken");
|
|
|
|
if (pid > 0) exit(EXIT_SUCCESS);
|
|
|
|
|
|
|
|
log_file = fopen(log_path, "a");
|
|
|
|
if (log_file == NULL) {
|
|
|
|
// Kan niet loggen lol
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
close(STDIN_FILENO);
|
|
|
|
close(STDOUT_FILENO);
|
|
|
|
close(STDERR_FILENO);
|
|
|
|
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT) < 0) {
|
|
|
|
LOGF("Kon seccomp niet aanroepen: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-07 10:49:21 +00:00
|
|
|
struct addrinfo hints, *servinfo, *p;
|
|
|
|
|
|
|
|
memset(&hints, 0, sizeof(struct addrinfo));
|
|
|
|
hints.ai_family = AF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
|
|
|
|
int res, res2;
|
|
|
|
if ((res = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
|
|
|
|
LOGF("Fout bij het herleiden van de gastheernaam: %s", gai_strerror(res));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
mbuf_t *buf = mbuf_create();
|
|
|
|
|
|
|
|
char address[INET6_ADDRSTRLEN] = {0};
|
|
|
|
for (p = servinfo; p != NULL; p = p->ai_next) {
|
|
|
|
void *ptr = NULL;
|
|
|
|
switch(p->ai_family) {
|
|
|
|
case AF_INET:
|
|
|
|
ptr = &((struct sockaddr_in *) p->ai_addr)->sin_addr;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
ptr = &((struct sockaddr_in6 *) p->ai_addr)->sin6_addr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (inet_ntop(p->ai_family, ptr, address, p->ai_addrlen) == NULL) {
|
|
|
|
LOGF("Kon adres niet omzetten: %s", strerror(errno));
|
|
|
|
} else {
|
|
|
|
LOGF("Verbinden met %s", address);
|
|
|
|
}
|
|
|
|
res = socket(p->ai_family, SOCK_STREAM, 0);
|
|
|
|
if (res < 0) continue;
|
|
|
|
res2 = connect(res, p->ai_addr, sizeof(address));
|
|
|
|
if (res2 == 0) break;
|
|
|
|
}
|
|
|
|
buf->sock = res;
|
|
|
|
|
|
|
|
quit_if_fail(res, "Kon niet verbinden");
|
|
|
|
//(void) quit_if_fail(connect(buf->sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)), "Kon niet verbinden");
|
|
|
|
|
|
|
|
(void) quit_if_fail(do_handshake(buf), "Handenschudden mislukt");
|
|
|
|
LOG("Handjeschudden voltooid")
|
|
|
|
(void) quit_if_fail(do_command_loop(buf), "Fout");
|
|
|
|
LOG("De andere kant heeft de verbinding verbroken");
|
|
|
|
free(buf);
|
|
|
|
return 0;
|
|
|
|
}
|