diff --git a/Makefile b/Makefile index eb96166..3d18b24 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,7 @@ OBJS := \ server.o \ signals.o \ thread.o \ + udp.o \ util.o \ uuid.o diff --git a/server.c b/server.c index 7e26b4a..bb88461 100644 --- a/server.c +++ b/server.c @@ -47,6 +47,14 @@ #include "thread.h" #include "keydb.h" #include "signals.h" +#include "udp.h" + +struct keyserver_t { + struct keydb_t* keydb; + struct generic_tls_ctx_t gctx; + const struct pgmopts_server_t *opts; + int tcp_sd, udp_sd; +}; struct client_thread_ctx_t { struct generic_tls_ctx_t *gctx; @@ -55,11 +63,10 @@ struct client_thread_ctx_t { int fd; }; -struct keyserver_t { - struct keydb_t* keydb; - struct generic_tls_ctx_t gctx; - const struct pgmopts_server_t *opts; - int tcp_sd; +struct udp_listen_thread_ctx_t { + const struct keydb_t *keydb; + int udp_sd; + unsigned int port; }; static int create_tcp_server_socket(int port) { @@ -162,11 +169,24 @@ static void client_handler_thread(void *vctx) { close(client->fd); } +static void udp_handler_thread(void *vctx) { + struct udp_listen_thread_ctx_t *client = (struct udp_listen_thread_ctx_t*)vctx; + + while (true) { + struct udp_query_t rx_msg; + if (!wait_udp_broadcast_message(client->udp_sd, client->port, &rx_msg, sizeof(rx_msg), 1000)) { + continue; + } + fprintf(stderr, "RXED!\n"); + } +} + bool keyserver_start(const struct pgmopts_server_t *opts) { bool success = true; struct keyserver_t keyserver = { .opts = opts, .tcp_sd = -1, + .udp_sd = -1, }; do { /* We ignore SIGPIPE or the server will die when clients disconnect suddenly */ @@ -201,6 +221,25 @@ bool keyserver_start(const struct pgmopts_server_t *opts) { break; } + if (opts->answer_udp_queries) { + keyserver.udp_sd = create_udp_socket(opts->port, false); + if (keyserver.udp_sd == -1) { + success = false; + break; + } + + struct udp_listen_thread_ctx_t udp_thread_ctx = { + .keydb = keyserver.keydb, + .udp_sd = keyserver.udp_sd, + .port = keyserver.opts->port, + }; + if (!pthread_create_detached_thread(udp_handler_thread, &udp_thread_ctx, sizeof(udp_thread_ctx))) { + log_libc(LLVL_FATAL, "Unable to create detached thread for UDP messages."); + success = false; + break; + } + } + while (true) { struct sockaddr_in addr; unsigned int len = sizeof(addr); @@ -218,12 +257,15 @@ bool keyserver_start(const struct pgmopts_server_t *opts) { .fd = client, }; if (!pthread_create_detached_thread(client_handler_thread, &client_ctx, sizeof(client_ctx))) { - log_libc(LLVL_FATAL, "Unable to create detached thread."); + log_libc(LLVL_FATAL, "Unable to create detached thread for client."); success = false; break; } } } while (false); + if (keyserver.udp_sd != -1) { + close(keyserver.udp_sd); + } if (keyserver.tcp_sd != -1) { close(keyserver.tcp_sd); } diff --git a/udp.c b/udp.c new file mode 100644 index 0000000..259e9cb --- /dev/null +++ b/udp.c @@ -0,0 +1,89 @@ +/* + luksrku - Tool to remotely unlock LUKS disks using TLS. + Copyright (C) 2016-2019 Johannes Bauer + + This file is part of luksrku. + + luksrku is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; this program is ONLY licensed under + version 3 of the License, later versions are explicitly excluded. + + luksrku is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with luksrku; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Johannes Bauer +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "udp.h" + +int create_udp_socket(unsigned int listen_port, bool send_broadcast) { + int sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0) { + log_libc(LLVL_ERROR, "Unable to create UDP server socket(2)"); + return -1; + } + if (send_broadcast) { + int value = 1; + if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value))) { + log_libc(LLVL_ERROR, "Unable to set UDP socket in broadcast mode using setsockopt(2)"); + close(sd); + return -1; + } + } + + if (listen_port) { + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(listen_port), + .sin_addr.s_addr = htonl(INADDR_ANY), + }; + if (bind(sd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + log_libc(LLVL_ERROR, "Unable to bind UDP socket to listen to port %d", listen_port); + close(sd); + return -1; + } + } + + return sd; +} + +bool wait_udp_broadcast_message(int sd, int port, void *data, unsigned int max_length, unsigned int timeout_millis) { + struct sockaddr_storage src_addr; + socklen_t src_addr_len = sizeof(src_addr); + + fprintf(stderr, "RECV...\n"); + ssize_t count=recvfrom(sd,data, max_length,0,(struct sockaddr*)&src_addr,&src_addr_len); + fprintf(stderr, "RECV %ld\n", count); + + 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; +} diff --git a/udp.h b/udp.h new file mode 100644 index 0000000..6dcb1d8 --- /dev/null +++ b/udp.h @@ -0,0 +1,35 @@ +/* + luksrku - Tool to remotely unlock LUKS disks using TLS. + Copyright (C) 2016-2019 Johannes Bauer + + This file is part of luksrku. + + luksrku is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; this program is ONLY licensed under + version 3 of the License, later versions are explicitly excluded. + + luksrku is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with luksrku; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Johannes Bauer +*/ + +#ifndef __UDP_H__ +#define __UDP_H__ + +#include + +/*************** AUTO GENERATED SECTION FOLLOWS ***************/ +int create_udp_socket(unsigned int listen_port, bool send_broadcast); +bool wait_udp_broadcast_message(int sd, int port, void *data, unsigned int max_length, unsigned int timeout_millis); +bool send_udp_broadcast_message(int sd, int port, const void *data, unsigned int length); +/*************** AUTO GENERATED SECTION ENDS ***************/ + +#endif