diff --git a/Makefile b/Makefile index f275d14..ab46c8e 100644 --- a/Makefile +++ b/Makefile @@ -11,11 +11,12 @@ PYPGMOPTS := ../Python/pypgmopts/pypgmopts LDFLAGS := `pkg-config --libs openssl` -OBJS := luksrku.o editor.o util.o log.o keydb.o file_encryption.o uuid.o argparse_edit.o pgmopts.o openssl.o server.o argparse_server.o thread.o +OBJS := luksrku.o editor.o util.o log.o keydb.o file_encryption.o uuid.o argparse_edit.o pgmopts.o openssl.o server.o argparse_server.o thread.o argparse_client.o client.o parsers: $(PYPGMOPTS) -n edit parsers/parser_edit.py $(PYPGMOPTS) -n server parsers/parser_server.py + $(PYPGMOPTS) -n client parsers/parser_client.py install: all cp luksrku $(INSTALL_PREFIX)sbin/ diff --git a/argparse_client.c b/argparse_client.c new file mode 100644 index 0000000..62d6e52 --- /dev/null +++ b/argparse_client.c @@ -0,0 +1,186 @@ +/* + * This file was AUTO-GENERATED by pypgmopts. + * + * https://github.com/johndoe31415/pypgmopts + * + * Do not edit it by hand, your changes will be overwritten. + * + * Generated at: 2019-10-23 20:13:13 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "argparse_client.h" + +static enum argparse_client_option_t last_parsed_option; +static char last_error_message[256]; +static const char *option_texts[] = { + [ARG_CLIENT_PORT] = "-p / --port", + [ARG_CLIENT_VERBOSE] = "-v / --verbose", + [ARG_CLIENT_FILENAME] = "filename", + [ARG_CLIENT_HOSTNAME] = "hostname", +}; + +enum argparse_client_option_internal_t { + ARG_CLIENT_PORT_SHORT = 'p', + ARG_CLIENT_VERBOSE_SHORT = 'v', + ARG_CLIENT_PORT_LONG = 1000, + ARG_CLIENT_VERBOSE_LONG = 1001, + ARG_CLIENT_FILENAME_LONG = 1002, + ARG_CLIENT_HOSTNAME_LONG = 1003, +}; + +static void errmsg_callback(const char *errmsg, ...) { + va_list ap; + va_start(ap, errmsg); + vsnprintf(last_error_message, sizeof(last_error_message), errmsg, ap); + va_end(ap); +} + +static void errmsg_option_callback(enum argparse_client_option_t error_option, const char *errmsg, ...) { + last_parsed_option = error_option; + + va_list ap; + va_start(ap, errmsg); + vsnprintf(last_error_message, sizeof(last_error_message), errmsg, ap); + va_end(ap); +} + +bool argparse_client_parse(int argc, char **argv, argparse_client_callback_t argument_callback, argparse_client_plausibilization_callback_t plausibilization_callback) { + last_parsed_option = ARGPARSE_CLIENT_NO_OPTION; + const char *short_options = "p:v"; + struct option long_options[] = { + { "port", required_argument, 0, ARG_CLIENT_PORT_LONG }, + { "verbose", no_argument, 0, ARG_CLIENT_VERBOSE_LONG }, + { "filename", required_argument, 0, ARG_CLIENT_FILENAME_LONG }, + { "hostname", required_argument, 0, ARG_CLIENT_HOSTNAME_LONG }, + { 0 } + }; + + while (true) { + int optval = getopt_long(argc, argv, short_options, long_options, NULL); + if (optval == -1) { + break; + } + last_error_message[0] = 0; + enum argparse_client_option_internal_t arg = (enum argparse_client_option_internal_t)optval; + switch (arg) { + case ARG_CLIENT_PORT_SHORT: + case ARG_CLIENT_PORT_LONG: + last_parsed_option = ARG_CLIENT_PORT; + if (!argument_callback(ARG_CLIENT_PORT, optarg, errmsg_callback)) { + return false; + } + break; + + case ARG_CLIENT_VERBOSE_SHORT: + case ARG_CLIENT_VERBOSE_LONG: + last_parsed_option = ARG_CLIENT_VERBOSE; + if (!argument_callback(ARG_CLIENT_VERBOSE, optarg, errmsg_callback)) { + return false; + } + break; + + default: + last_parsed_option = ARGPARSE_CLIENT_NO_OPTION; + errmsg_callback("unrecognized option supplied"); + return false; + } + } + + const int positional_argument_cnt = argc - optind; + const int flexible_positional_args_cnt = positional_argument_cnt - 1; + last_parsed_option = ARGPARSE_CLIENT_POSITIONAL_ARG; + if (positional_argument_cnt < 1) { + errmsg_callback("expected a minimum of 1 positional argument, but %d given.", positional_argument_cnt); + return false; + } + if (positional_argument_cnt > 2) { + errmsg_callback("expected a maximum of 2 positional arguments, but %d given.", positional_argument_cnt); + return false; + } + + int positional_index = optind; + last_parsed_option = ARG_CLIENT_FILENAME; + if (!argument_callback(ARG_CLIENT_FILENAME, argv[positional_index++], errmsg_callback)) { + return false; + } + last_parsed_option = ARG_CLIENT_HOSTNAME; + for (int i = 0; i < flexible_positional_args_cnt; i++) { + if (!argument_callback(ARG_CLIENT_HOSTNAME, argv[positional_index++], errmsg_callback)) { + return false; + } + } + + if (plausibilization_callback) { + if (!plausibilization_callback(errmsg_option_callback)) { + return false; + } + } + return true; +} + +void argparse_client_show_syntax(void) { + fprintf(stderr, "usage: luksrku client [-p port] [-v] filename [hostname]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Connects to a luksrku key server and unlocks local LUKS volumes.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "positional arguments:\n"); + fprintf(stderr, " filename Exported database file to load TLS-PSKs and list of\n"); + fprintf(stderr, " disks from.\n"); + fprintf(stderr, " hostname When hostname is given, auto-searching for suitable\n"); + fprintf(stderr, " servers is disabled and only a connection to the given\n"); + fprintf(stderr, " hostname is attempted.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "optional arguments:\n"); + fprintf(stderr, " -p port, --port port Port that is used for both UDP and TCP communication.\n"); + fprintf(stderr, " Defaults to 23170.\n"); + fprintf(stderr, " -v, --verbose Increase verbosity. Can be specified multiple times.\n"); +} + +void argparse_client_parse_or_quit(int argc, char **argv, argparse_client_callback_t argument_callback, argparse_client_plausibilization_callback_t plausibilization_callback) { + if (!argparse_client_parse(argc, argv, argument_callback, plausibilization_callback)) { + if (last_parsed_option > ARGPARSE_CLIENT_POSITIONAL_ARG) { + if (last_error_message[0]) { + fprintf(stderr, "luksrku client: error parsing argument %s -- %s\n", option_texts[last_parsed_option], last_error_message); + } else { + fprintf(stderr, "luksrku client: error parsing argument %s -- no details available\n", option_texts[last_parsed_option]); + } + } else if (last_parsed_option == ARGPARSE_CLIENT_POSITIONAL_ARG) { + fprintf(stderr, "luksrku client: error parsing optional arguments -- %s\n", last_error_message); + } + argparse_client_show_syntax(); + exit(EXIT_FAILURE); + } +} + +#ifdef __ARGPARSE_MAIN__ +/* gcc -D __ARGPARSE_MAIN__ -O2 -Wall -o argparse argparse_client.c +*/ + +static const char *option_enum_to_str(enum argparse_client_option_t option) { + switch (option) { + case ARG_CLIENT_PORT: return "ARG_CLIENT_PORT"; + case ARG_CLIENT_VERBOSE: return "ARG_CLIENT_VERBOSE"; + case ARG_CLIENT_FILENAME: return "ARG_CLIENT_FILENAME"; + case ARG_CLIENT_HOSTNAME: return "ARG_CLIENT_HOSTNAME"; + } + return "UNKNOWN"; +} + +bool arg_print_callback(enum argparse_client_option_t option, const char *value, argparse_client_errmsg_callback_t errmsg_callback) { + fprintf(stderr, "%s = \"%s\"\n", option_enum_to_str(option), value); + return true; +} + +int main(int argc, char **argv) { + argparse_client_parse_or_quit(argc, argv, arg_print_callback, NULL); + return 0; +} +#endif diff --git a/argparse_client.h b/argparse_client.h new file mode 100644 index 0000000..b152d0c --- /dev/null +++ b/argparse_client.h @@ -0,0 +1,38 @@ +/* + * This file was AUTO-GENERATED by pypgmopts. + * + * https://github.com/johndoe31415/pypgmopts + * + * Do not edit it by hand, your changes will be overwritten. + * + * Generated at: 2019-10-23 20:13:13 + */ + +#ifndef __ARGPARSE_CLIENT_H__ +#define __ARGPARSE_CLIENT_H__ + +#include + +#define ARGPARSE_CLIENT_DEFAULT_PORT 23170 +#define ARGPARSE_CLIENT_DEFAULT_VERBOSE 0 + +#define ARGPARSE_CLIENT_NO_OPTION 0 +#define ARGPARSE_CLIENT_POSITIONAL_ARG 1 + +enum argparse_client_option_t { + ARG_CLIENT_PORT = 2, + ARG_CLIENT_VERBOSE = 3, + ARG_CLIENT_FILENAME = 4, + ARG_CLIENT_HOSTNAME = 5, +}; + +typedef void (*argparse_client_errmsg_callback_t)(const char *errmsg, ...); +typedef void (*argparse_client_errmsg_option_callback_t)(enum argparse_client_option_t error_option, const char *errmsg, ...); +typedef bool (*argparse_client_callback_t)(enum argparse_client_option_t option, const char *value, argparse_client_errmsg_callback_t errmsg_callback); +typedef bool (*argparse_client_plausibilization_callback_t)(argparse_client_errmsg_option_callback_t errmsg_callback); + +bool argparse_client_parse(int argc, char **argv, argparse_client_callback_t argument_callback, argparse_client_plausibilization_callback_t plausibilization_callback); +void argparse_client_show_syntax(void); +void argparse_client_parse_or_quit(int argc, char **argv, argparse_client_callback_t argument_callback, argparse_client_plausibilization_callback_t plausibilization_callback); + +#endif diff --git a/argparse_edit.c b/argparse_edit.c index 86c7f51..bcce7e3 100644 --- a/argparse_edit.c +++ b/argparse_edit.c @@ -5,7 +5,7 @@ * * Do not edit it by hand, your changes will be overwritten. * - * Generated at: 2019-10-23 10:06:43 + * Generated at: 2019-10-23 20:13:13 */ #include diff --git a/argparse_edit.h b/argparse_edit.h index 95c00bd..d723043 100644 --- a/argparse_edit.h +++ b/argparse_edit.h @@ -5,7 +5,7 @@ * * Do not edit it by hand, your changes will be overwritten. * - * Generated at: 2019-10-23 10:06:43 + * Generated at: 2019-10-23 20:13:13 */ #ifndef __ARGPARSE_EDIT_H__ diff --git a/argparse_server.c b/argparse_server.c index 226b5f9..4497507 100644 --- a/argparse_server.c +++ b/argparse_server.c @@ -5,7 +5,7 @@ * * Do not edit it by hand, your changes will be overwritten. * - * Generated at: 2019-10-23 10:06:43 + * Generated at: 2019-10-23 20:13:13 */ #include @@ -127,7 +127,7 @@ bool argparse_server_parse(int argc, char **argv, argparse_server_callback_t arg void argparse_server_show_syntax(void) { fprintf(stderr, "usage: luksrku server [-p port] [-s] [-v] filename\n"); fprintf(stderr, "\n"); - fprintf(stderr, "Starts an luksrku key server.\n"); + fprintf(stderr, "Starts a luksrku key server.\n"); fprintf(stderr, "\n"); fprintf(stderr, "positional arguments:\n"); fprintf(stderr, " filename Database file to load keys from.\n"); diff --git a/argparse_server.h b/argparse_server.h index 3b049d1..c13b5bc 100644 --- a/argparse_server.h +++ b/argparse_server.h @@ -5,7 +5,7 @@ * * Do not edit it by hand, your changes will be overwritten. * - * Generated at: 2019-10-23 10:06:43 + * Generated at: 2019-10-23 20:13:13 */ #ifndef __ARGPARSE_SERVER_H__ diff --git a/client.c b/client.c index 03e8b0e..38cf557 100644 --- a/client.c +++ b/client.c @@ -32,13 +32,12 @@ #include "log.h" #include "openssl.h" -#include "keyfile.h" #include "util.h" -#include "cmdline.h" #include "msg.h" #include "client.h" #include "blacklist.h" +#if 0 static const struct keydb_t *client_keydb; static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len) { @@ -166,7 +165,7 @@ static bool parse_announcement(const struct options_t *options, const struct soc return true; } -bool tls_client(const struct keydb_t *keydb, const struct options_t *options) { +static bool tls_client(const struct keydb_t *keydb, const struct options_t *options) { client_keydb = keydb; int sd = socket(AF_INET, SOCK_DGRAM, 0); @@ -206,3 +205,8 @@ bool tls_client(const struct keydb_t *keydb, const struct options_t *options) { return true; } +#endif + +bool keyclient_start(const struct pgmopts_client_t *opts) { + return true; +} diff --git a/client.h b/client.h index c92667b..ceb1649 100644 --- a/client.h +++ b/client.h @@ -24,11 +24,11 @@ #ifndef __CLIENT_H__ #define __CLIENT_H__ -#include "keyfile.h" -#include "cmdline.h" +#include +#include "pgmopts.h" /*************** AUTO GENERATED SECTION FOLLOWS ***************/ -bool dtls_client(const struct keydb_t *keydb, const struct options_t *options); +bool keyclient_start(const struct pgmopts_client_t *opts); /*************** AUTO GENERATED SECTION ENDS ***************/ #endif diff --git a/luksrku.c b/luksrku.c index bd53a5c..3921f9b 100644 --- a/luksrku.c +++ b/luksrku.c @@ -31,6 +31,7 @@ #include "editor.h" #include "openssl.h" #include "server.h" +#include "client.h" #if OPENSSL_VERSION_NUMBER < 0x010100000 #error "luksrku requires at least OpenSSL v1.1 to work." @@ -47,7 +48,8 @@ static int main_server(const struct pgmopts_server_t *opts) { } static int main_client(const struct pgmopts_client_t *opts) { - return 0; + log_setlvl(LOGLEVEL_DEFAULT + opts->verbosity); + return keyclient_start(opts) ? 0 : 1; } int main(int argc, char **argv) { diff --git a/parsers/parser_client.py b/parsers/parser_client.py new file mode 100755 index 0000000..159d0aa --- /dev/null +++ b/parsers/parser_client.py @@ -0,0 +1,6 @@ +import argparse +parser = argparse.ArgumentParser(prog = "luksrku client", description = "Connects to a luksrku key server and unlocks local LUKS volumes.", add_help = False) +parser.add_argument("-p", "--port", metavar = "port", default = 23170, help = "Port that is used for both UDP and TCP communication. Defaults to %(default)d.") +parser.add_argument("-v", "--verbose", action = "count", default = 0, help = "Increase verbosity. Can be specified multiple times.") +parser.add_argument("filename", metavar = "filename", help = "Exported database file to load TLS-PSKs and list of disks from.") +parser.add_argument("hostname", metavar = "hostname", nargs = "?", help = "When hostname is given, auto-searching for suitable servers is disabled and only a connection to the given hostname is attempted.") diff --git a/parsers/parser_server.py b/parsers/parser_server.py index 97b7951..f051267 100755 --- a/parsers/parser_server.py +++ b/parsers/parser_server.py @@ -1,5 +1,5 @@ import argparse -parser = argparse.ArgumentParser(prog = "luksrku server", description = "Starts an luksrku key server.", add_help = False) +parser = argparse.ArgumentParser(prog = "luksrku server", description = "Starts a luksrku key server.", add_help = False) parser.add_argument("-p", "--port", metavar = "port", default = 23170, help = "Port that is used for both UDP and TCP communication. Defaults to %(default)d.") parser.add_argument("-s", "--silent", action = "store_true", help = "Do not answer UDP queries for clients trying to find a key server, only serve key database using TCP.") parser.add_argument("-v", "--verbose", action = "count", default = 0, help = "Increase verbosity. Can be specified multiple times.") diff --git a/pgmopts.c b/pgmopts.c index 80f4cbb..810448e 100644 --- a/pgmopts.c +++ b/pgmopts.c @@ -29,6 +29,7 @@ #include "pgmopts.h" #include "argparse_edit.h" #include "argparse_server.h" +#include "argparse_client.h" static struct pgmopts_t pgmopts_rw; const struct pgmopts_t *pgmopts = &pgmopts_rw; @@ -80,6 +81,27 @@ static bool server_callback(enum argparse_server_option_t option, const char *va return true; } +static bool client_callback(enum argparse_client_option_t option, const char *value, argparse_client_errmsg_callback_t errmsg_callback) { + switch (option) { + case ARG_CLIENT_FILENAME: + pgmopts_rw.client.filename = value; + break; + + case ARG_CLIENT_HOSTNAME: + pgmopts_rw.client.hostname = value; + break; + + case ARG_CLIENT_PORT: + pgmopts_rw.client.port = atoi(value); + break; + + case ARG_CLIENT_VERBOSE: + pgmopts_rw.client.verbosity++; + break; + } + return true; +} + static void parse_pgmopts_edit(int argc, char **argv) { pgmopts_rw.edit = (struct pgmopts_edit_t){ .verbosity = ARGPARSE_EDIT_DEFAULT_VERBOSE, @@ -96,6 +118,14 @@ static void parse_pgmopts_server(int argc, char **argv) { argparse_server_parse_or_quit(argc - 1, argv + 1, server_callback, NULL); } +static void parse_pgmopts_client(int argc, char **argv) { + pgmopts_rw.client = (struct pgmopts_client_t){ + .port = ARGPARSE_SERVER_DEFAULT_PORT, + .verbosity = ARGPARSE_SERVER_DEFAULT_VERBOSE, + }; + argparse_client_parse_or_quit(argc - 1, argv + 1, client_callback, NULL); +} + void parse_pgmopts_or_quit(int argc, char **argv) { if (argc < 2) { show_syntax("no command supplied", argc, argv); @@ -109,6 +139,9 @@ void parse_pgmopts_or_quit(int argc, char **argv) { } else if (!strcasecmp(command, "server")) { pgmopts_rw.pgm = PGM_SERVER; parse_pgmopts_server(argc, argv); + } else if (!strcasecmp(command, "client")) { + pgmopts_rw.pgm = PGM_CLIENT; + parse_pgmopts_client(argc, argv); } else { show_syntax("unsupported command supplied", argc, argv); exit(EXIT_FAILURE); diff --git a/pgmopts.h b/pgmopts.h index 21f047d..5085c49 100644 --- a/pgmopts.h +++ b/pgmopts.h @@ -45,6 +45,9 @@ struct pgmopts_server_t { }; struct pgmopts_client_t { + const char *filename; + const char *hostname; + unsigned int port; unsigned int verbosity; }; diff --git a/server.c b/server.c index e71258c..ebcfd6f 100644 --- a/server.c +++ b/server.c @@ -44,6 +44,7 @@ #include "pgmopts.h" #include "uuid.h" #include "thread.h" +#include "keydb.h" static int create_tcp_server_socket(int port) { int s; @@ -82,65 +83,6 @@ static const struct keyentry_t *server_key; -/* Wait for the socket to become acceptable or time out after given number of - * milliseconds. Return true if acceptable socket is present or false if - * timeout occured. */ -static bool socket_wait_acceptable(int sd, int timeout_millis) { - struct timeval tv; - memset(&tv, 0, sizeof(tv)); - tv.tv_usec = timeout_millis * 1000; - - fd_set fds; - FD_ZERO(&fds); - FD_SET(sd, &fds); - - int result = select(sd + 1, &fds, NULL, NULL, &tv); - return result != 0; -} - -static int create_udp_socket(void) { - int sd = socket(AF_INET, SOCK_DGRAM, 0); - if (sd < 0) { - log_libc(LLVL_ERROR, "Unable to create UDP server socket(2)"); - return -1; - } - { - 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; - } - } - - - return sd; -} - -static bool send_udp_broadcast_message(int sd, int port, const void *data, 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; -} - -static bool announce_waiting_message(int sd, int port, const struct keyentry_t *key) { - struct announcement_t msg; - const uint8_t magic[16] = CLIENT_ANNOUNCE_MAGIC; - memset(&msg, 0, sizeof(msg)); - memcpy(msg.magic, magic, 16); - memcpy(msg.host_uuid, key->host_uuid, 16); - - return send_udp_broadcast_message(sd, port, &msg, sizeof(msg)); -} - static bool unlock_disk(const struct diskentry_t *disk, const uint8_t *passphrase, int passphrase_length) { char ascii_uuid[40]; sprintf_uuid(ascii_uuid, disk->disk_uuid); diff --git a/server.h b/server.h index 9bd8805..763e2f9 100644 --- a/server.h +++ b/server.h @@ -25,7 +25,6 @@ #define __SERVER_H__ #include -#include "keydb.h" #include "pgmopts.h" /*************** AUTO GENERATED SECTION FOLLOWS ***************/