Integrate editor properly from command line

Now have a way to invoke the editor functionality from the command line
and also provisions to include the server and client parsers.
This commit is contained in:
Johannes Bauer 2019-10-23 11:34:40 +02:00
parent ecbf3827ca
commit 667ff55af1
12 changed files with 407 additions and 22 deletions

9
.gitignore vendored
View File

@ -1,11 +1,4 @@
.*.swp
*.o
luksrku
luksrku-config
openssl-1.1.0a.tar.gz
openssl-1.1.0a
client.bin
client.txt
server.bin
server.txt
__pycache__

View File

@ -1,4 +1,4 @@
.PHONY: all clean test testclient install
.PHONY: all clean test testclient install parsers
all: luksrku
BUILD_REVISION := $(shell git describe --abbrev=10 --dirty --always --tags)
@ -7,10 +7,14 @@ CFLAGS := -Wall -Wextra -Wshadow -Wswitch -Wpointer-arith -Wcast-qual -Wstrict-p
CFLAGS += -O3 -std=c11 -pthread -D_POSIX_SOURCE -D_XOPEN_SOURCE=500 -DBUILD_REVISION='"$(BUILD_REVISION)"'
CFLAGS += `pkg-config --cflags openssl`
CFLAGS += -ggdb3 -DDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak
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
OBJS := luksrku.o editor.o util.o log.o keydb.o file_encryption.o uuid.o argparse_edit.o pgmopts.o openssl.o
parsers:
$(PYPGMOPTS) -n edit parsers/parser_edit.py
install: all
cp luksrku $(INSTALL_PREFIX)sbin/

157
argparse_edit.c Normal file
View File

@ -0,0 +1,157 @@
/*
* 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 09:40:28
*/
#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_edit.h"
static enum argparse_edit_option_t last_parsed_option;
static char last_error_message[256];
static const char *option_texts[] = {
[ARG_EDIT_VERBOSE] = "-v / --verbose",
[ARG_EDIT_FILENAME] = "filename",
};
enum argparse_edit_option_internal_t {
ARG_EDIT_VERBOSE_SHORT = 'v',
ARG_EDIT_VERBOSE_LONG = 1000,
ARG_EDIT_FILENAME_LONG = 1001,
};
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_edit_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_edit_parse(int argc, char **argv, argparse_edit_callback_t argument_callback, argparse_edit_plausibilization_callback_t plausibilization_callback) {
last_parsed_option = ARGPARSE_EDIT_NO_OPTION;
const char *short_options = "v";
struct option long_options[] = {
{ "verbose", no_argument, 0, ARG_EDIT_VERBOSE_LONG },
{ "filename", required_argument, 0, ARG_EDIT_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_edit_option_internal_t arg = (enum argparse_edit_option_internal_t)optval;
switch (arg) {
case ARG_EDIT_VERBOSE_SHORT:
case ARG_EDIT_VERBOSE_LONG:
last_parsed_option = ARG_EDIT_VERBOSE;
if (!argument_callback(ARG_EDIT_VERBOSE, optarg, errmsg_callback)) {
return false;
}
break;
default:
last_parsed_option = ARGPARSE_EDIT_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 - 0;
last_parsed_option = ARGPARSE_EDIT_POSITIONAL_ARG;
if (positional_argument_cnt < 0) {
errmsg_callback("expected a minimum of 0 positional arguments, but %d given.", positional_argument_cnt);
return false;
}
if (positional_argument_cnt > 1) {
errmsg_callback("expected a maximum of 1 positional argument, but %d given.", positional_argument_cnt);
return false;
}
int positional_index = optind;
last_parsed_option = ARG_EDIT_FILENAME;
for (int i = 0; i < flexible_positional_args_cnt; i++) {
if (!argument_callback(ARG_EDIT_FILENAME, argv[positional_index++], errmsg_callback)) {
return false;
}
}
if (plausibilization_callback) {
if (!plausibilization_callback(errmsg_option_callback)) {
return false;
}
}
return true;
}
void argparse_edit_show_syntax(void) {
fprintf(stderr, "usage: luksrku edit [-v] [filename]\n");
fprintf(stderr, "\n");
fprintf(stderr, "positional arguments:\n");
fprintf(stderr, " filename Database file to edit.\n");
fprintf(stderr, "\n");
fprintf(stderr, "optional arguments:\n");
fprintf(stderr, " -v, --verbose Increase verbosity. Can be specified multiple times.\n");
}
void argparse_edit_parse_or_quit(int argc, char **argv, argparse_edit_callback_t argument_callback, argparse_edit_plausibilization_callback_t plausibilization_callback) {
if (!argparse_edit_parse(argc, argv, argument_callback, plausibilization_callback)) {
if (last_parsed_option > ARGPARSE_EDIT_POSITIONAL_ARG) {
if (last_error_message[0]) {
fprintf(stderr, "luksrku edit: error parsing argument %s -- %s\n", option_texts[last_parsed_option], last_error_message);
} else {
fprintf(stderr, "luksrku edit: error parsing argument %s -- no details available\n", option_texts[last_parsed_option]);
}
} else if (last_parsed_option == ARGPARSE_EDIT_POSITIONAL_ARG) {
fprintf(stderr, "luksrku edit: error parsing optional arguments -- %s\n", last_error_message);
}
argparse_edit_show_syntax();
exit(EXIT_FAILURE);
}
}
#ifdef __ARGPARSE_MAIN__
/* gcc -D __ARGPARSE_MAIN__ -O2 -Wall -o argparse argparse_edit.c
*/
static const char *option_enum_to_str(enum argparse_edit_option_t option) {
switch (option) {
case ARG_EDIT_VERBOSE: return "ARG_EDIT_VERBOSE";
case ARG_EDIT_FILENAME: return "ARG_EDIT_FILENAME";
}
return "UNKNOWN";
}
bool arg_print_callback(enum argparse_edit_option_t option, const char *value, argparse_edit_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_edit_parse_or_quit(argc, argv, arg_print_callback, NULL);
return 0;
}
#endif

35
argparse_edit.h Normal file
View File

@ -0,0 +1,35 @@
/*
* 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 09:40:28
*/
#ifndef __ARGPARSE_EDIT_H__
#define __ARGPARSE_EDIT_H__
#include <stdbool.h>
#define ARGPARSE_EDIT_DEFAULT_VERBOSE 0
#define ARGPARSE_EDIT_NO_OPTION 0
#define ARGPARSE_EDIT_POSITIONAL_ARG 1
enum argparse_edit_option_t {
ARG_EDIT_VERBOSE = 2,
ARG_EDIT_FILENAME = 3,
};
typedef void (*argparse_edit_errmsg_callback_t)(const char *errmsg, ...);
typedef void (*argparse_edit_errmsg_option_callback_t)(enum argparse_edit_option_t error_option, const char *errmsg, ...);
typedef bool (*argparse_edit_callback_t)(enum argparse_edit_option_t option, const char *value, argparse_edit_errmsg_callback_t errmsg_callback);
typedef bool (*argparse_edit_plausibilization_callback_t)(argparse_edit_errmsg_option_callback_t errmsg_callback);
bool argparse_edit_parse(int argc, char **argv, argparse_edit_callback_t argument_callback, argparse_edit_plausibilization_callback_t plausibilization_callback);
void argparse_edit_show_syntax(void);
void argparse_edit_parse_or_quit(int argc, char **argv, argparse_edit_callback_t argument_callback, argparse_edit_plausibilization_callback_t plausibilization_callback);
#endif

View File

@ -69,7 +69,7 @@ static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identi
return PSK_SIZE_BYTES;
}
static int dtls_client_connect(const struct keyentry_t *keyentry, const char *host_port) {
static int tls_client_connect(const struct keyentry_t *keyentry, const char *host_port) {
struct generic_tls_ctx_t gctx;
create_generic_tls_context(&gctx, false);
@ -162,11 +162,11 @@ static bool parse_announcement(const struct options_t *options, const struct soc
snprintf(destination_address, sizeof(destination_address) - 1, "%d.%d.%d.%d:%d", PRINTF_FORMAT_IP(peer_addr), options->port);
log_msg(LLVL_DEBUG, "Trying to connect to %s in order to transmit keys", destination_address);
dtls_client_connect(keyentry, destination_address);
tls_client_connect(keyentry, destination_address);
return true;
}
bool dtls_client(const struct keydb_t *keydb, const struct options_t *options) {
bool tls_client(const struct keydb_t *keydb, const struct options_t *options) {
client_keydb = keydb;
int sd = socket(AF_INET, SOCK_DGRAM, 0);

View File

@ -31,6 +31,7 @@
#include "util.h"
#include "keydb.h"
#include "uuid.h"
#include "log.h"
#define MAX_COMMAND_ALIAS_COUNT 2
@ -485,11 +486,28 @@ static enum cmd_returncode_t execute_command(const struct editor_command_t *cmd,
}
}
void editor_start(void) {
bool editor_start(const char *edit_filename) {
struct editor_context_t editor_context = {
.running = true,
};
if (edit_filename) {
char *filename = strdup(edit_filename);
if (!filename) {
log_libc(LLVL_ERROR, "Unable to strdup(3)");
return false;
}
char *tokens[2] = {
"open",
filename,
};
enum cmd_returncode_t result = execute_command(find_command(tokens[0]), &editor_context, 2, tokens);
free(filename);
if (result != COMMAND_SUCCESS) {
return false;
}
}
while (editor_context.running) {
char command_buffer[256];
printf("> ");
@ -547,4 +565,5 @@ void editor_start(void) {
keydb_free(editor_context.keydb);
}
OPENSSL_cleanse(&editor_context, sizeof(editor_context));
return true;
}

View File

@ -2,7 +2,7 @@
#define __EDITOR_H__
/*************** AUTO GENERATED SECTION FOLLOWS ***************/
void editor_start(void);
bool editor_start(const char *edit_filename);
/*************** AUTO GENERATED SECTION ENDS ***************/
#endif

View File

@ -27,15 +27,50 @@
#include "openssl.h"
#include "log.h"
#include "pgmopts.h"
#include "editor.h"
#include "openssl.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;
}
static int main_server(const struct pgmopts_server_t *opts) {
return 0;
}
static int main_client(const struct pgmopts_client_t *opts) {
return 0;
}
int main(int argc, char **argv) {
#ifdef DEBUG
fprintf(stderr, "WARNING: This has been compiled in DEBUG mode and uses reduced security.\n");
#endif
parse_pgmopts_or_quit(argc, argv);
if (!openssl_init()) {
log_msg(LLVL_FATAL, "Could not initialize OpenSSL.");
exit(EXIT_FAILURE);
}
switch (pgmopts->pgm) {
case PGM_EDIT:
return main_edit(&pgmopts->edit);
case PGM_SERVER:
return main_server(&pgmopts->server);
case PGM_CLIENT:
return main_client(&pgmopts->client);
}
return 0;
#if 0
struct options_t options;
@ -47,10 +82,6 @@ int main(int argc, char **argv) {
log_setlvl(LLVL_DEBUG);
}
if (!openssl_init()) {
log_msg(LLVL_FATAL, "Could not initialize OpenSSL.");
exit(EXIT_FAILURE);
}
struct keydb_t keydb;
bool success = true;
@ -87,13 +118,13 @@ int main(int argc, char **argv) {
}
if (!dtls_server(keydb_getentry(&keydb, 0), &options)) {
log_msg(LLVL_FATAL, "Failed to start DTLS server.");
log_msg(LLVL_FATAL, "Failed to start TLS server.");
success = false;
break;
}
} else {
if (!dtls_client(&keydb, &options)) {
log_msg(LLVL_FATAL, "Failed to connect DTLS client.");
log_msg(LLVL_FATAL, "Failed to connect TLS client.");
success = false;
break;
}

4
parsers/parser_edit.py Executable file
View File

@ -0,0 +1,4 @@
import argparse
parser = argparse.ArgumentParser(prog = "luksrku edit", description = "", 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.")

79
pgmopts.c Normal file
View File

@ -0,0 +1,79 @@
/*
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>
*/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include "pgmopts.h"
#include "argparse_edit.h"
static struct pgmopts_t pgmopts_rw = {
};
const struct pgmopts_t *pgmopts = &pgmopts_rw;
static void show_syntax(const char *errmsg, int argc, char **argv) {
if (errmsg) {
fprintf(stderr, "error: %s\n", errmsg);
fprintf(stderr, "\n");
}
fprintf(stderr, "Available commands:\n");
fprintf(stderr, " %s edit Interactively edit a key database\n", argv[0]);
fprintf(stderr, " %s server Start a key server process\n", argv[0]);
fprintf(stderr, " %s client Unlock LUKS volumes by querying a key server\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "For futher help: %s (command) --help\n", argv[0]);
}
static bool edit_callback(enum argparse_edit_option_t option, const char *value, argparse_edit_errmsg_callback_t errmsg_callback) {
switch (option) {
case ARG_EDIT_FILENAME:
pgmopts_rw.edit.filename = value;
break;
case ARG_EDIT_VERBOSE:
pgmopts_rw.edit.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);
}
void parse_pgmopts_or_quit(int argc, char **argv) {
if (argc < 2) {
show_syntax("no command supplied", argc, argv);
exit(EXIT_FAILURE);
}
const char *command = argv[1];
if (!strcmp(command, "edit")) {
pgmopts_rw.pgm = PGM_EDIT;
parse_pgmopts_edit(argc, argv);
} else {
show_syntax("unsupported command supplied", argc, argv);
exit(EXIT_FAILURE);
}
}

63
pgmopts.h Normal file
View File

@ -0,0 +1,63 @@
/*
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 __PGMOPTS_H__
#define __PGMOPTS_H__
#include <stdbool.h>
enum pgmopts_pgm_t {
PGM_EDIT,
PGM_SERVER,
PGM_CLIENT,
};
struct pgmopts_edit_t {
const char *filename;
unsigned int verbosity;
};
struct pgmopts_server_t {
unsigned int verbosity;
};
struct pgmopts_client_t {
unsigned int verbosity;
};
struct pgmopts_t {
enum pgmopts_pgm_t pgm;
union {
struct pgmopts_edit_t edit;
struct pgmopts_server_t server;
struct pgmopts_client_t client;
};
};
extern const struct pgmopts_t *pgmopts;
/*************** AUTO GENERATED SECTION FOLLOWS ***************/
void parse_pgmopts_or_quit(int argc, char **argv);
/*************** AUTO GENERATED SECTION ENDS ***************/
#endif

View File

@ -175,7 +175,7 @@ static bool all_disks_unlocked(const struct keyentry_t *keyentry) {
return true;
}
bool dtls_server(const struct keyentry_t *key, const struct options_t *options) {
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;