diff --git a/Makefile b/Makefile index 3d18b24..0db18bc 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ OBJS := \ argparse_client.o \ argparse_edit.o \ argparse_server.o \ + blacklist.o \ client.o \ editor.o \ file_encryption.o \ diff --git a/blacklist.c b/blacklist.c index a8495f0..5762684 100644 --- a/blacklist.c +++ b/blacklist.c @@ -1,6 +1,6 @@ /* luksrku - Tool to remotely unlock LUKS disks using TLS. - Copyright (C) 2016-2016 Johannes Bauer + Copyright (C) 2016-2019 Johannes Bauer This file is part of luksrku. @@ -30,25 +30,23 @@ static struct blacklist_entry_t blacklist[BLACKLIST_ENTRY_COUNT]; -static double gettime(void) { +static double now(void) { struct timeval tv; if (gettimeofday(&tv, NULL)) { return 0; } - double now = tv.tv_sec + (tv.tv_usec * 1e-6); - return now; + return tv.tv_sec + (tv.tv_usec * 1e-6); } static bool blacklist_entry_expired(int index) { - double now = gettime(); - return now > blacklist[index].entered + BLACKLIST_ENTRY_TIMEOUT_SECS; + return now() > blacklist[index].entered + BLACKLIST_ENTRY_TIMEOUT_SECS; } void blacklist_ip(uint32_t ip) { for (int i = 0; i < BLACKLIST_ENTRY_COUNT; i++) { if (blacklist_entry_expired(i)) { blacklist[i].ip = ip; - blacklist[i].entered = gettime(); + blacklist[i].entered = now(); return; } } @@ -62,4 +60,3 @@ bool is_ip_blacklisted(uint32_t ip) { } return false; } - diff --git a/blacklist.h b/blacklist.h index 0261b47..b704adf 100644 --- a/blacklist.h +++ b/blacklist.h @@ -1,6 +1,6 @@ /* luksrku - Tool to remotely unlock LUKS disks using TLS. - Copyright (C) 2016-2016 Johannes Bauer + Copyright (C) 2016-2019 Johannes Bauer This file is part of luksrku. @@ -27,6 +27,9 @@ #include #include +#define BLACKLIST_ENTRY_COUNT 32 +#define BLACKLIST_ENTRY_TIMEOUT_SECS 60 + struct blacklist_entry_t { uint32_t ip; double entered; diff --git a/global.h b/global.h index 2ddc470..7728723 100644 --- a/global.h +++ b/global.h @@ -51,9 +51,6 @@ /* In what interval the server should broadcast that it's waiting for unlocking */ #define WAITING_MESSAGE_BROADCAST_INTERVAL_MILLISECONDS 1000 -#define BLACKLIST_ENTRY_COUNT 16 -#define BLACKLIST_ENTRY_TIMEOUT_SECS 120 - #define staticassert(cond) _Static_assert((cond), #cond) #endif diff --git a/server.c b/server.c index 2f3c698..a1c8702 100644 --- a/server.c +++ b/server.c @@ -48,6 +48,7 @@ #include "keydb.h" #include "signals.h" #include "udp.h" +#include "blacklist.h" struct keyserver_t { struct keydb_t* keydb; @@ -178,7 +179,23 @@ static void udp_handler_thread(void *vctx) { if (!wait_udp_query(client->udp_sd, client->port, &rx_msg, &origin, 1000)) { continue; } - fprintf(stderr, "RXED! query\n"); + + log_msg(LLVL_TRACE, "Recevied UDP query message from %d.%d.%d.%d:%d", PRINTF_FORMAT_IP(&origin), ntohs(origin.sin_port)); + + /* Ensure that we only reply to this host once every minute */ + const uint32_t ipv4 = origin.sin_addr.s_addr; + if (is_ip_blacklisted(ipv4)) { + continue; + } + blacklist_ip(ipv4); + + /* Check if we have this host in our database */ + if (keydb_get_host_by_uuid(client->keydb, rx_msg.host_uuid)) { + /* Yes, it is. Notify the client who's asking that we have their key. */ + struct udp_response_t tx_msg; + memcpy(tx_msg.magic, UDP_MESSAGE_MAGIC, UDP_MESSAGE_MAGIC_SIZE); + send_udp_message(client->udp_sd, &origin, &tx_msg, sizeof(tx_msg), true); + } } } diff --git a/udp.c b/udp.c index 8228c40..5d9a2fb 100644 --- a/udp.c +++ b/udp.c @@ -62,26 +62,34 @@ int create_udp_socket(unsigned int listen_port, bool send_broadcast) { return sd; } -bool wait_udp_message(int sd, int port, void *data, unsigned int max_length, struct sockaddr_in *source, unsigned int timeout_millis) { +bool wait_udp_message(int sd, int port, void *data, unsigned int length, struct sockaddr_in *source, unsigned int timeout_millis) { fprintf(stderr, "RECV...\n"); socklen_t socklen = sizeof(struct sockaddr_in); - ssize_t rx_bytes = recvfrom(sd,data, max_length, 0, (struct sockaddr*)source, &socklen); + ssize_t rx_bytes = recvfrom(sd,data, length, 0, (struct sockaddr*)source, &socklen); fprintf(stderr, "RECV %ld\n", rx_bytes); + return rx_bytes == length; +} + +bool send_udp_message(int sd, struct sockaddr_in *destination, const void *data, unsigned int length, bool is_response) { + int flags = is_response ? MSG_CONFIRM : 0; + ssize_t tx_bytes = sendto(sd, data, length, flags, (struct sockaddr*)destination, sizeof(struct sockaddr_in)); + if (tx_bytes < 0) { + log_libc(LLVL_ERROR, "Unable to sendto(2)"); + return false; + } else if (tx_bytes != length) { + log_libc(LLVL_ERROR, "Unable to sendto(2) the complete message, %d bytes sent, but %u requested.", tx_bytes, length); + return false; + } return true; } bool send_udp_broadcast_message(int sd, int port, const void *data, unsigned int length) { - struct sockaddr_in destination; - memset(&destination, 0, sizeof(struct sockaddr_in)); - destination.sin_family = AF_INET; - destination.sin_port = htons(port); - destination.sin_addr.s_addr = htonl(INADDR_BROADCAST); - - if (sendto(sd, data, length, 0, (struct sockaddr *)&destination, sizeof(struct sockaddr_in)) < 0) { - log_libc(LLVL_ERROR, "Unable to sendto(2)"); - return false; - } - return true; + struct sockaddr_in destination = { + .sin_family = AF_INET, + .sin_port = htons(port), + .sin_addr.s_addr = htonl(INADDR_BROADCAST), + }; + return send_udp_message(sd, &destination, data, length, false); } bool wait_udp_query(int sd, int port, struct udp_query_t *query, struct sockaddr_in *source, unsigned int timeout_millis) { diff --git a/udp.h b/udp.h index c34a489..1ae0e43 100644 --- a/udp.h +++ b/udp.h @@ -29,7 +29,8 @@ /*************** AUTO GENERATED SECTION FOLLOWS ***************/ int create_udp_socket(unsigned int listen_port, bool send_broadcast); -bool wait_udp_message(int sd, int port, void *data, unsigned int max_length, struct sockaddr_in *source, unsigned int timeout_millis); +bool wait_udp_message(int sd, int port, void *data, unsigned int length, struct sockaddr_in *source, unsigned int timeout_millis); +bool send_udp_message(int sd, struct sockaddr_in *destination, const void *data, unsigned int length, bool is_response); bool send_udp_broadcast_message(int sd, int port, const void *data, unsigned int length); bool wait_udp_query(int sd, int port, struct udp_query_t *query, struct sockaddr_in *source, unsigned int timeout_millis); /*************** AUTO GENERATED SECTION ENDS ***************/ diff --git a/util.h b/util.h index c7564f8..a568612 100644 --- a/util.h +++ b/util.h @@ -28,7 +28,7 @@ #include #include -#define PRINTF_FORMAT_IP(saddrptr) (saddrptr->sin_addr.s_addr >> 0) & 0xff, (saddrptr->sin_addr.s_addr >> 8) & 0xff, (saddrptr->sin_addr.s_addr >> 16) & 0xff, (saddrptr->sin_addr.s_addr >> 24) & 0xff +#define PRINTF_FORMAT_IP(saddrptr) ((saddrptr)->sin_addr.s_addr >> 0) & 0xff, ((saddrptr)->sin_addr.s_addr >> 8) & 0xff, ((saddrptr)->sin_addr.s_addr >> 16) & 0xff, ((saddrptr)->sin_addr.s_addr >> 24) & 0xff /*************** AUTO GENERATED SECTION FOLLOWS ***************/ bool query_passphrase(const char *prompt, char *passphrase, unsigned int passphrase_maxsize);