Started with server implementation

Running into issues with TLSv1.3-PSK. Connection establishment does not
work at the moment.
This commit is contained in:
Johannes Bauer 2019-10-23 13:18:51 +02:00
parent 667ff55af1
commit 969eae12c7
19 changed files with 448 additions and 326 deletions

View File

@ -11,10 +11,11 @@ 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
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
parsers:
$(PYPGMOPTS) -n edit parsers/parser_edit.py
$(PYPGMOPTS) -n server parsers/parser_server.py
install: all
cp luksrku $(INSTALL_PREFIX)sbin/

View File

@ -5,7 +5,7 @@
*
* Do not edit it by hand, your changes will be overwritten.
*
* Generated at: 2019-10-23 09:40:28
* Generated at: 2019-10-23 10:06:43
*/
#include <stdint.h>
@ -110,6 +110,8 @@ bool argparse_edit_parse(int argc, char **argv, argparse_edit_callback_t argumen
void argparse_edit_show_syntax(void) {
fprintf(stderr, "usage: luksrku edit [-v] [filename]\n");
fprintf(stderr, "\n");
fprintf(stderr, "Edits a luksrks key database.\n");
fprintf(stderr, "\n");
fprintf(stderr, "positional arguments:\n");
fprintf(stderr, " filename Database file to edit.\n");
fprintf(stderr, "\n");

View File

@ -5,7 +5,7 @@
*
* Do not edit it by hand, your changes will be overwritten.
*
* Generated at: 2019-10-23 09:40:28
* Generated at: 2019-10-23 10:06:43
*/
#ifndef __ARGPARSE_EDIT_H__

182
argparse_server.c Normal file
View File

@ -0,0 +1,182 @@
/*
* 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 10:06:43
*/
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <stdarg.h>
#include <string.h>
#include "argparse_server.h"
static enum argparse_server_option_t last_parsed_option;
static char last_error_message[256];
static const char *option_texts[] = {
[ARG_SERVER_PORT] = "-p / --port",
[ARG_SERVER_SILENT] = "-s / --silent",
[ARG_SERVER_VERBOSE] = "-v / --verbose",
[ARG_SERVER_FILENAME] = "filename",
};
enum argparse_server_option_internal_t {
ARG_SERVER_PORT_SHORT = 'p',
ARG_SERVER_SILENT_SHORT = 's',
ARG_SERVER_VERBOSE_SHORT = 'v',
ARG_SERVER_PORT_LONG = 1000,
ARG_SERVER_SILENT_LONG = 1001,
ARG_SERVER_VERBOSE_LONG = 1002,
ARG_SERVER_FILENAME_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_server_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_server_parse(int argc, char **argv, argparse_server_callback_t argument_callback, argparse_server_plausibilization_callback_t plausibilization_callback) {
last_parsed_option = ARGPARSE_SERVER_NO_OPTION;
const char *short_options = "p:sv";
struct option long_options[] = {
{ "port", required_argument, 0, ARG_SERVER_PORT_LONG },
{ "silent", no_argument, 0, ARG_SERVER_SILENT_LONG },
{ "verbose", no_argument, 0, ARG_SERVER_VERBOSE_LONG },
{ "filename", required_argument, 0, ARG_SERVER_FILENAME_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_server_option_internal_t arg = (enum argparse_server_option_internal_t)optval;
switch (arg) {
case ARG_SERVER_PORT_SHORT:
case ARG_SERVER_PORT_LONG:
last_parsed_option = ARG_SERVER_PORT;
if (!argument_callback(ARG_SERVER_PORT, optarg, errmsg_callback)) {
return false;
}
break;
case ARG_SERVER_SILENT_SHORT:
case ARG_SERVER_SILENT_LONG:
last_parsed_option = ARG_SERVER_SILENT;
if (!argument_callback(ARG_SERVER_SILENT, optarg, errmsg_callback)) {
return false;
}
break;
case ARG_SERVER_VERBOSE_SHORT:
case ARG_SERVER_VERBOSE_LONG:
last_parsed_option = ARG_SERVER_VERBOSE;
if (!argument_callback(ARG_SERVER_VERBOSE, optarg, errmsg_callback)) {
return false;
}
break;
default:
last_parsed_option = ARGPARSE_SERVER_NO_OPTION;
errmsg_callback("unrecognized option supplied");
return false;
}
}
const int positional_argument_cnt = argc - optind;
last_parsed_option = ARGPARSE_SERVER_POSITIONAL_ARG;
if (positional_argument_cnt != 1) {
errmsg_callback("expected exactly 1 positional argument, but %d given.", positional_argument_cnt);
return false;
}
int positional_index = optind;
last_parsed_option = ARG_SERVER_FILENAME;
if (!argument_callback(ARG_SERVER_FILENAME, argv[positional_index++], errmsg_callback)) {
return false;
}
if (plausibilization_callback) {
if (!plausibilization_callback(errmsg_option_callback)) {
return false;
}
}
return true;
}
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, "\n");
fprintf(stderr, "positional arguments:\n");
fprintf(stderr, " filename Database file to load keys from.\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, " -s, --silent Do not answer UDP queries for clients trying to find a\n");
fprintf(stderr, " key server, only serve key database using TCP.\n");
fprintf(stderr, " -v, --verbose Increase verbosity. Can be specified multiple times.\n");
}
void argparse_server_parse_or_quit(int argc, char **argv, argparse_server_callback_t argument_callback, argparse_server_plausibilization_callback_t plausibilization_callback) {
if (!argparse_server_parse(argc, argv, argument_callback, plausibilization_callback)) {
if (last_parsed_option > ARGPARSE_SERVER_POSITIONAL_ARG) {
if (last_error_message[0]) {
fprintf(stderr, "luksrku server: error parsing argument %s -- %s\n", option_texts[last_parsed_option], last_error_message);
} else {
fprintf(stderr, "luksrku server: error parsing argument %s -- no details available\n", option_texts[last_parsed_option]);
}
} else if (last_parsed_option == ARGPARSE_SERVER_POSITIONAL_ARG) {
fprintf(stderr, "luksrku server: error parsing optional arguments -- %s\n", last_error_message);
}
argparse_server_show_syntax();
exit(EXIT_FAILURE);
}
}
#ifdef __ARGPARSE_MAIN__
/* gcc -D __ARGPARSE_MAIN__ -O2 -Wall -o argparse argparse_server.c
*/
static const char *option_enum_to_str(enum argparse_server_option_t option) {
switch (option) {
case ARG_SERVER_PORT: return "ARG_SERVER_PORT";
case ARG_SERVER_SILENT: return "ARG_SERVER_SILENT";
case ARG_SERVER_VERBOSE: return "ARG_SERVER_VERBOSE";
case ARG_SERVER_FILENAME: return "ARG_SERVER_FILENAME";
}
return "UNKNOWN";
}
bool arg_print_callback(enum argparse_server_option_t option, const char *value, argparse_server_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_server_parse_or_quit(argc, argv, arg_print_callback, NULL);
return 0;
}
#endif

38
argparse_server.h Normal file
View File

@ -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 10:06:43
*/
#ifndef __ARGPARSE_SERVER_H__
#define __ARGPARSE_SERVER_H__
#include <stdbool.h>
#define ARGPARSE_SERVER_DEFAULT_PORT 23170
#define ARGPARSE_SERVER_DEFAULT_VERBOSE 0
#define ARGPARSE_SERVER_NO_OPTION 0
#define ARGPARSE_SERVER_POSITIONAL_ARG 1
enum argparse_server_option_t {
ARG_SERVER_PORT = 2,
ARG_SERVER_SILENT = 3,
ARG_SERVER_VERBOSE = 4,
ARG_SERVER_FILENAME = 5,
};
typedef void (*argparse_server_errmsg_callback_t)(const char *errmsg, ...);
typedef void (*argparse_server_errmsg_option_callback_t)(enum argparse_server_option_t error_option, const char *errmsg, ...);
typedef bool (*argparse_server_callback_t)(enum argparse_server_option_t option, const char *value, argparse_server_errmsg_callback_t errmsg_callback);
typedef bool (*argparse_server_plausibilization_callback_t)(argparse_server_errmsg_option_callback_t errmsg_callback);
bool argparse_server_parse(int argc, char **argv, argparse_server_callback_t argument_callback, argparse_server_plausibilization_callback_t plausibilization_callback);
void argparse_server_show_syntax(void);
void argparse_server_parse_or_quit(int argc, char **argv, argparse_server_callback_t argument_callback, argparse_server_plausibilization_callback_t plausibilization_callback);
#endif

194
cmdline.c
View File

@ -1,194 +0,0 @@
/*
luksrku - Tool to remotely unlock LUKS disks using TLS.
Copyright (C) 2016-2016 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 <JohannesBauer@gmx.de>
*/
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <stdlib.h>
#include "cmdline.h"
#include "global.h"
enum longopts_t {
LONGOPT_VERBOSE,
LONGOPT_MODE_SERVER,
LONGOPT_MODE_CLIENT,
LONGOPT_PORT,
LONGOPT_KEYDB,
LONGOPT_UNLOCK_CNT,
LONGOPT_MAX_BCAST_ERRS
};
void print_syntax(const char *pgmname) {
fprintf(stderr, "%s (-c, --client-mode) (-s, --server-mode) (-k, --keydb=FILE) (-u, --unlock=CNT)\n", pgmname);
fprintf(stderr, " (-p, --port=PORT) (--max-bcast-errs=CNT) (-v, --verbose)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -c, --client-mode Specifies client mode, i.e., that this host will unlock the LUKS\n");
fprintf(stderr, " disk of a different machine.\n");
fprintf(stderr, " -s, --server-mode Specifies server mode, i.e., that this host will announce its\n");
fprintf(stderr, " presence via UDP broadcasts and then receive the LUKS credentials\n");
fprintf(stderr, " from a peer.\n");
fprintf(stderr, " -k, --keydb=FILE Gives the binary key database file which will be used. In server\n");
fprintf(stderr, " mode, this contains only one entry (specifying the UUID of the\n");
fprintf(stderr, " host, the PSK and the UUIDs and names of the disks to be\n");
fprintf(stderr, " unlocked), while in client mode this may contain multiple entries\n");
fprintf(stderr, " (to unlock many different peers) and also contains the LUKS\n");
fprintf(stderr, " credentials for the respective disks.\n");
fprintf(stderr, " -u, --unlock=CNT Specifies the maximum number of unlocking actions that are taken.\n");
fprintf(stderr, " In client mode, this defaults to 1. In server mode, it defaults to\n");
fprintf(stderr, " infinite (or until all disks have successfully been unlocked).\n");
fprintf(stderr, " Zero means infinite.\n");
fprintf(stderr, " -p, --port=PORT Specifies the port on which is listened for UDP broadcasts and\n");
fprintf(stderr, " also the port on which TCP requests are sent out (the two are\n");
fprintf(stderr, " always identical). Default port ist 23170.\n");
fprintf(stderr, " --max-bcast-errs=CNT This is the number of UDP broadcast attempts luksrku will make\n");
fprintf(stderr, " before giving up. Usually this is because sendto(2) fails when the\n");
fprintf(stderr, " network is configured improperly. Giving up in this case enables\n");
fprintf(stderr, " manual key entry. This defaults to 5 tries.\n");
fprintf(stderr, " -v, --verbose Increase logging verbosity.\n");
fprintf(stderr, "\n");
fprintf(stderr, "luksrku version: " BUILD_REVISION "\n");
}
static void set_default_arguments(struct options_t *options) {
memset(options, 0, sizeof(struct options_t));
/* Default port :-) echo -n LUKS | md5sum | cut -c -5 */
options->port = 23170;
/* Default, overwritten later by fill_default_arguments() */
options->unlock_cnt = -1;
/* Give up after 5 failed broadcast attempts */
options->max_broadcast_errs = 5;
}
static void fill_default_arguments(struct options_t *options) {
/* Set default unlock count */
if (options->unlock_cnt == -1) {
if (options->mode == CLIENT_MODE) {
options->unlock_cnt = 1;
} else if (options->mode == SERVER_MODE) {
options->unlock_cnt = 0;
}
}
}
static bool check_arguments(const struct options_t *options) {
if (options->mode == UNDEFINED) {
fprintf(stderr, "Must specify client or server mode.\n");
return false;
}
if (options->keydbfile == NULL) {
fprintf(stderr, "Must specify a key database file.\n");
return false;
}
if ((options->port < 1) || (options->port > 65535)) {
fprintf(stderr, "Valid port range is 1-65535.\n");
return false;
}
if (options->unlock_cnt < 0) {
fprintf(stderr, "Unlock count must be a positive integer.\n");
return false;
}
return true;
}
bool parse_cmdline_arguments(struct options_t *options, int argc, char **argv) {
set_default_arguments(options);
struct option long_options[] = {
{ "verbose", no_argument, 0, LONGOPT_VERBOSE },
{ "server-mode", no_argument, 0, LONGOPT_MODE_SERVER },
{ "client-mode", no_argument, 0, LONGOPT_MODE_CLIENT },
{ "port", required_argument, 0, LONGOPT_PORT },
{ "keydb", required_argument, 0, LONGOPT_KEYDB },
{ "unlock", required_argument, 0, LONGOPT_UNLOCK_CNT },
{ "max-bcast-errs", required_argument, 0, LONGOPT_MAX_BCAST_ERRS },
{ 0 }
};
bool success = true;
bool parse = true;
do {
int c = getopt_long(argc, argv, "vscp:k:u:", long_options, NULL);
switch (c) {
case LONGOPT_VERBOSE:
case 'v':
options->verbose = true;
break;
case LONGOPT_MODE_SERVER:
case 's':
options->mode = SERVER_MODE;
break;
case LONGOPT_MODE_CLIENT:
case 'c':
options->mode = CLIENT_MODE;
break;
case LONGOPT_PORT:
case 'p':
options->port = atoi(optarg);
break;
case LONGOPT_KEYDB:
case 'k':
options->keydbfile = optarg;
break;
case LONGOPT_UNLOCK_CNT:
case 'u':
options->unlock_cnt = atoi(optarg);
break;
case LONGOPT_MAX_BCAST_ERRS:
options->max_broadcast_errs = atoi(optarg);
break;
case -1:
/* Out of arguments */
parse = false;
break;
case '?':
/* Syntax error */
parse = false;
success = false;
break;
default:
fprintf(stderr, "Programming error: unexpected getopt return value %d.\n", c);
parse = false;
success = false;
break;
}
} while (parse);
fill_default_arguments(options);
return success && check_arguments(options);
}

View File

@ -1,50 +0,0 @@
/*
luksrku - Tool to remotely unlock LUKS disks using TLS.
Copyright (C) 2016-2016 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 <JohannesBauer@gmx.de>
*/
#ifndef __CMDLINE_H__
#define __CMDLINE_H__
#include <stdbool.h>
enum mode_t {
UNDEFINED = 0,
SERVER_MODE,
CLIENT_MODE
};
struct options_t {
enum mode_t mode;
int port;
bool verbose;
const char *keydbfile;
int unlock_cnt;
int max_broadcast_errs;
};
/*************** AUTO GENERATED SECTION FOLLOWS ***************/
enum longopts_t;
void print_syntax(const char *pgmname);
bool parse_cmdline_arguments(struct options_t *options, int argc, char **argv);
/*************** AUTO GENERATED SECTION ENDS ***************/
#endif

View File

@ -486,13 +486,13 @@ static enum cmd_returncode_t execute_command(const struct editor_command_t *cmd,
}
}
bool editor_start(const char *edit_filename) {
bool editor_start(const struct pgmopts_edit_t *opts) {
struct editor_context_t editor_context = {
.running = true,
};
if (edit_filename) {
char *filename = strdup(edit_filename);
if (opts->filename) {
char *filename = strdup(opts->filename);
if (!filename) {
log_libc(LLVL_ERROR, "Unable to strdup(3)");
return false;

View File

@ -1,8 +1,34 @@
/*
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 <JohannesBauer@gmx.de>
*/
#ifndef __EDITOR_H__
#define __EDITOR_H__
#include <stdint.h>
#include "pgmopts.h"
/*************** AUTO GENERATED SECTION FOLLOWS ***************/
bool editor_start(const char *edit_filename);
bool editor_start(const struct pgmopts_edit_t *opts);
/*************** AUTO GENERATED SECTION ENDS ***************/
#endif

View File

@ -30,18 +30,18 @@
#include "pgmopts.h"
#include "editor.h"
#include "openssl.h"
#include "server.h"
#if OPENSSL_VERSION_NUMBER < 0x010100000
#error "luksrku requires at least OpenSSL v1.1 to work."
#endif
static int main_edit(const struct pgmopts_edit_t *opts) {
editor_start(opts->filename);
return 0;
return editor_start(opts) ? 0 : 1;
}
static int main_server(const struct pgmopts_server_t *opts) {
return 0;
return keyserver_start(opts) ? 0 : 1;
}
static int main_client(const struct pgmopts_client_t *opts) {

35
msg.c
View File

@ -1,35 +0,0 @@
/*
luksrku - Tool to remotely unlock LUKS disks using TLS.
Copyright (C) 2016-2016 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 <JohannesBauer@gmx.de>
*/
#include <arpa/inet.h>
#include "msg.h"
void msg_to_nbo(struct msg_t *msg) {
msg->passphrase_length = htonl(msg->passphrase_length);
}
void msg_to_hbo(struct msg_t *msg) {
msg->passphrase_length = ntohl(msg->passphrase_length);
}

12
msg.h
View File

@ -33,16 +33,10 @@ struct announcement_t {
} __attribute__ ((packed));
struct msg_t {
uint8_t disk_uuid[16];
uint32_t passphrase_length;
uint8_t passphrase[MAX_PASSPHRASE_LENGTH];
uint8_t volume_uuid[16];
uint8_t luks_passphrase_raw[LUKS_PASSPHRASE_RAW_SIZE_BYTES];
} __attribute__ ((packed));
staticassert(sizeof(struct msg_t) == 16 + 4 + MAX_PASSPHRASE_LENGTH);
/*************** AUTO GENERATED SECTION FOLLOWS ***************/
void msg_to_nbo(struct msg_t *msg);
void msg_to_hbo(struct msg_t *msg);
/*************** AUTO GENERATED SECTION ENDS ***************/
staticassert(sizeof(struct msg_t) == 16 + LUKS_PASSPHRASE_RAW_SIZE_BYTES);
#endif

View File

@ -74,17 +74,19 @@ bool create_generic_tls_context(struct generic_tls_ctx_t *gctx, bool server) {
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_COMPRESSION | SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
SSL_CTX_set_options(gctx->ctx, flags);
if (!SSL_CTX_set_min_proto_version(gctx->ctx, TLS1_2_VERSION)) {
if (!SSL_CTX_set_min_proto_version(gctx->ctx, TLS1_3_VERSION)) {
log_openssl(LLVL_FATAL, "Cannot set TLS generic context minimal version.");
return false;
}
if (!SSL_CTX_set_max_proto_version(gctx->ctx, TLS1_2_VERSION)) {
if (!SSL_CTX_set_max_proto_version(gctx->ctx, TLS1_3_VERSION)) {
log_openssl(LLVL_FATAL, "Cannot set TLS generic context maximal version.");
return false;
}
if (!SSL_CTX_set_cipher_list(gctx->ctx, "ECDHE-PSK-CHACHA20-POLY1305")) {
/* SSL_CTX_set_ciphersuites for TLSv1.3
* SSL_CTX_set_cipher_list for TLS v1.2 and below */
if (!SSL_CTX_set_ciphersuites(gctx->ctx, "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384")) {
log_openssl(LLVL_FATAL, "Cannot set TLS generic context cipher suites.");
return false;
}
@ -92,13 +94,14 @@ bool create_generic_tls_context(struct generic_tls_ctx_t *gctx, bool server) {
/* In the cipher suite we're using, none of these should be used anyways
* (PSK); however for the future we want to have proper crypto here as
* well. */
#if 0
if (!SSL_CTX_set1_sigalgs_list(gctx->ctx, "ECDSA+SHA256:RSA+SHA256:ECDSA+SHA384:RSA+SHA384:ECDSA+SHA512:RSA+SHA512")) {
log_openssl(LLVL_FATAL, "Cannot set TLS generic context signature algorithms.");
return false;
}
#endif
/* TODO: When X448 becomes available, include it here. */
if (!SSL_CTX_set1_curves_list(gctx->ctx, "X25519")) {
if (!SSL_CTX_set1_curves_list(gctx->ctx, "X448:X25519")) {
log_openssl(LLVL_FATAL, "Cannot set TLS generic context ECDHE curves.");
return false;
}

View File

@ -1,4 +1,4 @@
import argparse
parser = argparse.ArgumentParser(prog = "luksrku edit", description = "", add_help = False)
parser = argparse.ArgumentParser(prog = "luksrku edit", description = "Edits a luksrks key database.", add_help = False)
parser.add_argument("-v", "--verbose", action = "count", default = 0, help = "Increase verbosity. Can be specified multiple times.")
parser.add_argument("filename", metavar = "filename", nargs = "?", type = str, help = "Database file to edit.")

6
parsers/parser_server.py Executable file
View File

@ -0,0 +1,6 @@
import argparse
parser = argparse.ArgumentParser(prog = "luksrku server", description = "Starts an 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.")
parser.add_argument("filename", metavar = "filename", help = "Database file to load keys from.")

View File

@ -24,9 +24,11 @@
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "pgmopts.h"
#include "argparse_edit.h"
#include "argparse_server.h"
static struct pgmopts_t pgmopts_rw = {
};
@ -46,6 +48,9 @@ static void show_syntax(const char *errmsg, int argc, char **argv) {
}
static bool edit_callback(enum argparse_edit_option_t option, const char *value, argparse_edit_errmsg_callback_t errmsg_callback) {
pgmopts_rw.edit = (struct pgmopts_edit_t){
.verbosity = ARGPARSE_EDIT_DEFAULT_VERBOSE,
};
switch (option) {
case ARG_EDIT_FILENAME:
pgmopts_rw.edit.filename = value;
@ -58,10 +63,40 @@ static bool edit_callback(enum argparse_edit_option_t option, const char *value,
return true;
}
static bool server_callback(enum argparse_server_option_t option, const char *value, argparse_server_errmsg_callback_t errmsg_callback) {
pgmopts_rw.server = (struct pgmopts_server_t){
.port = ARGPARSE_SERVER_DEFAULT_PORT,
.verbosity = ARGPARSE_SERVER_DEFAULT_VERBOSE,
.answer_udp_queries = true,
};
switch (option) {
case ARG_SERVER_FILENAME:
pgmopts_rw.server.filename = value;
break;
case ARG_SERVER_PORT:
pgmopts_rw.server.port = atoi(value);
break;
case ARG_SERVER_SILENT:
pgmopts_rw.server.answer_udp_queries = false;
break;
case ARG_SERVER_VERBOSE:
pgmopts_rw.server.verbosity++;
break;
}
return true;
}
static void parse_pgmopts_edit(int argc, char **argv) {
argparse_edit_parse_or_quit(argc - 1, argv + 1, edit_callback, NULL);
}
static void parse_pgmopts_server(int argc, char **argv) {
argparse_server_parse_or_quit(argc - 1, argv + 1, server_callback, NULL);
}
void parse_pgmopts_or_quit(int argc, char **argv) {
if (argc < 2) {
show_syntax("no command supplied", argc, argv);
@ -69,9 +104,12 @@ void parse_pgmopts_or_quit(int argc, char **argv) {
}
const char *command = argv[1];
if (!strcmp(command, "edit")) {
if (!strcasecmp(command, "edit")) {
pgmopts_rw.pgm = PGM_EDIT;
parse_pgmopts_edit(argc, argv);
} else if (!strcasecmp(command, "server")) {
pgmopts_rw.pgm = PGM_SERVER;
parse_pgmopts_server(argc, argv);
} else {
show_syntax("unsupported command supplied", argc, argv);
exit(EXIT_FAILURE);

View File

@ -38,6 +38,9 @@ struct pgmopts_edit_t {
};
struct pgmopts_server_t {
const char *filename;
unsigned int port;
bool answer_udp_queries;
unsigned int verbosity;
};

145
server.c
View File

@ -37,29 +37,13 @@
#include "log.h"
#include "openssl.h"
#include "global.h"
#include "keyfile.h"
#include "msg.h"
#include "util.h"
#include "cmdline.h"
#include "server.h"
#include "luks.h"
#include "pgmopts.h"
static const struct keyentry_t *server_key;
static unsigned int psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len) {
if (max_psk_len < PSK_SIZE_BYTES) {
log_msg(LLVL_FATAL, "Server error: max_psk_len too small.");
return 0;
}
if (strcmp(identity, CLIENT_PSK_IDENTITY)) {
log_msg(LLVL_FATAL, "Server error: client identity '%s' unexpected (expected '%s').", identity, CLIENT_PSK_IDENTITY);
return 0;
}
memcpy(psk, server_key->psk, PSK_SIZE_BYTES);
return PSK_SIZE_BYTES;
}
static int create_tcp_socket(int port) {
static int create_tcp_server_socket(int port) {
int s;
struct sockaddr_in addr;
@ -91,6 +75,11 @@ static int create_tcp_socket(int port) {
return s;
}
#if 0
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. */
@ -175,7 +164,7 @@ static bool all_disks_unlocked(const struct keyentry_t *keyentry) {
return true;
}
bool tls_server(const struct keyentry_t *key, const struct options_t *options) {
static bool tls_server(const struct keyentry_t *key, const struct options_t *options) {
if (all_disks_unlocked(key)) {
log_msg(LLVL_INFO, "Starting of server not necessary, all disks already unlocked.");
return true;
@ -298,4 +287,122 @@ bool tls_server(const struct keyentry_t *key, const struct options_t *options) {
free_generic_tls_context(&gctx);
return true;
}
#endif
#if 0
static unsigned int psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len) {
if (max_psk_len < PSK_SIZE_BYTES) {
log_msg(LLVL_FATAL, "Server error: max_psk_len too small.");
return 0;
}
if (strcmp(identity, CLIENT_PSK_IDENTITY)) {
log_msg(LLVL_FATAL, "Server error: client identity '%s' unexpected (expected '%s').", identity, CLIENT_PSK_IDENTITY);
return 0;
}
// memcpy(psk, server_key->psk, PSK_SIZE_BYTES);
return PSK_SIZE_BYTES;
}
#endif
static int psk_server_callback(SSL *ssl, const unsigned char *identity, size_t identity_len, SSL_SESSION **sessptr) {
fprintf(stderr, "PSK server SSL %p identity %s len %ld sess %p\n", ssl, identity, identity_len, *sessptr);
SSL_SESSION *sess = SSL_SESSION_new();
SSL_SESSION_set1_master_key(sess, (const unsigned char*)"\x00\x11\x22", 3);
SSL_SESSION_set_cipher(sess, SSL_get_pending_cipher(ssl));
//const SSL_CIPHER *cipher = SSL_CIPHER_find(ssl, TLS13_AES_256_GCM_SHA384_BYTES);
//SSL_SESSION_set_cipher(sess, cipher);
SSL_SESSION_set_protocol_version(sess, TLS1_3_VERSION);
*sessptr = sess;
return 1;
}
struct client_ctx_t {
struct generic_tls_ctx_t *gctx;
int fd;
};
static void *client_handler_thread(void *vctx) {
struct client_ctx_t *client = (struct client_ctx_t*)vctx;
SSL *ssl = SSL_new(client->gctx->ctx);
SSL_set_fd(ssl, client->fd);
if (SSL_accept(ssl) <= 0) {
ERR_print_errors_fp(stderr);
} else {
log_msg(LLVL_DEBUG, "Client connected, waiting for data...");
}
shutdown(client->fd, SHUT_RDWR);
close(client->fd);
free(client);
return NULL;
}
bool keyserver_start(const struct pgmopts_server_t *opts) {
struct generic_tls_ctx_t gctx;
if (!create_generic_tls_context(&gctx, true)) {
log_msg(LLVL_FATAL, "Failed to create OpenSSL server context.");
return false;
}
SSL_CTX_set_psk_find_session_callback(gctx.ctx, psk_server_callback);
int tcp_sock = create_tcp_server_socket(opts->port);
if (tcp_sock == -1) {
log_msg(LLVL_ERROR, "Cannot start server without server socket.");
free_generic_tls_context(&gctx);
return false;
}
while (true) {
struct sockaddr_in addr;
unsigned int len = sizeof(addr);
int client = accept(tcp_sock, (struct sockaddr*)&addr, &len);
if (client < 0) {
log_libc(LLVL_ERROR, "Unable to accept(2)");
close(tcp_sock);
free_generic_tls_context(&gctx);
return false;
}
/* Client has connected, fire up client thread. */
struct client_ctx_t *client_ctx = calloc(1, sizeof(struct client_ctx_t));
if (!client_ctx) {
log_libc(LLVL_FATAL, "Unable to malloc(3) client ctx");
close(tcp_sock);
free_generic_tls_context(&gctx);
return false;
}
client_ctx->gctx = &gctx;
client_ctx->fd = client;
pthread_t thread;
pthread_attr_t attrs;
if (pthread_attr_init(&attrs)) {
log_libc(LLVL_FATAL, "Unable to pthread_attr_init(3)");
close(tcp_sock);
free_generic_tls_context(&gctx);
return false;
}
if (pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED)) {
log_libc(LLVL_FATAL, "Unable to pthread_attr_setdetachstate(3)");
close(tcp_sock);
free_generic_tls_context(&gctx);
return false;
}
if (pthread_create(&thread, &attrs, client_handler_thread, client_ctx)) {
log_libc(LLVL_FATAL, "Unable to pthread_create(3) a client thread");
close(tcp_sock);
free_generic_tls_context(&gctx);
return false;
}
}
free_generic_tls_context(&gctx);
return true;
}

View File

@ -24,11 +24,12 @@
#ifndef __SERVER_H__
#define __SERVER_H__
#include <stdbool.h>
#include "keydb.h"
#include "cmdline.h"
#include "pgmopts.h"
/*************** AUTO GENERATED SECTION FOLLOWS ***************/
bool dtls_server(const struct keyentry_t *key, const struct options_t *options);
bool keyserver_start(const struct pgmopts_server_t *opts);
/*************** AUTO GENERATED SECTION ENDS ***************/
#endif