Started with server implementation
Running into issues with TLSv1.3-PSK. Connection establishment does not work at the moment.
This commit is contained in:
parent
667ff55af1
commit
969eae12c7
3
Makefile
3
Makefile
@ -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/
|
||||
|
@ -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");
|
||||
|
@ -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
182
argparse_server.c
Normal 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
38
argparse_server.h
Normal 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
194
cmdline.c
@ -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);
|
||||
}
|
50
cmdline.h
50
cmdline.h
@ -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
|
6
editor.c
6
editor.c
@ -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;
|
||||
|
28
editor.h
28
editor.h
@ -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
|
||||
|
@ -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
35
msg.c
@ -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
12
msg.h
@ -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
|
||||
|
13
openssl.c
13
openssl.c
@ -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;
|
||||
}
|
||||
|
@ -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
6
parsers/parser_server.py
Executable 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.")
|
40
pgmopts.c
40
pgmopts.c
@ -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);
|
||||
|
@ -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
145
server.c
@ -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;
|
||||
}
|
||||
|
5
server.h
5
server.h
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user