From 0e8e42d0ea2fc0e098c0f811d4353eac1753e6a6 Mon Sep 17 00:00:00 2001 From: Johannes Bauer Date: Wed, 23 Oct 2019 21:54:10 +0200 Subject: [PATCH] Client and server commnunication now works We can send our little datagrams over and that works nicely. Need to consolidate the PSK session establishment into one shared function. --- Makefile | 6 ++-- client.c | 73 +++++++++++++++++++++++++++++++++++++++++--- keydb.c | 6 ++-- log.c | 1 + log.h | 3 +- server.c | 5 +++ signals.c | 35 +++++++++++++++++++++ signals.h | 33 ++++++++++++++++++++ testdata/client.bin | Bin 0 -> 1080 bytes testdata/server.bin | Bin 0 -> 2092 bytes 10 files changed, 151 insertions(+), 11 deletions(-) create mode 100644 signals.c create mode 100644 signals.h create mode 100644 testdata/client.bin create mode 100644 testdata/server.bin diff --git a/Makefile b/Makefile index ff13371..f0ff81a 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ 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 argparse_client.o client.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 signals.o parsers: $(PYPGMOPTS) -n edit parsers/parser_edit.py @@ -27,10 +27,10 @@ clean: rm -f $(OBJS) $(OBJS_CFG) luksrku test_s: luksrku - ./luksrku server -vv base + ./luksrku server -vv testdata/server.bin test_c: luksrku - ./luksrku client -vv export 127.0.0.1 + ./luksrku client -vv testdata/client.bin 127.0.0.1 .c.o: $(CC) $(CFLAGS) -c -o $@ $< diff --git a/client.c b/client.c index c260f7e..63b7fd9 100644 --- a/client.c +++ b/client.c @@ -41,6 +41,7 @@ #include "client.h" #include "blacklist.h" #include "keydb.h" +#include "uuid.h" #if 0 static const struct keydb_t *client_keydb; @@ -216,11 +217,53 @@ struct keyclient_t { const struct pgmopts_client_t *opts; struct keydb_t *keydb; bool volume_unlocked[MAX_VOLUMES_PER_HOST]; + unsigned char identifier[ASCII_UUID_BUFSIZE]; }; -static int psk_client_callback(SSL *ssl, const EVP_MD *md, const unsigned char **id, size_t *idlen, SSL_SESSION **sess) { - fprintf(stderr, "CLIENT CALLBACK\n"); - return 0; +static int psk_client_callback(SSL *ssl, const EVP_MD *md, const unsigned char **id, size_t *idlen, SSL_SESSION **sessptr) { + struct keyclient_t *key_client = (struct keyclient_t*)SSL_get_app_data(ssl); + *id = key_client->identifier; + *idlen = ASCII_UUID_CHARACTER_COUNT; + + SSL_SESSION *sess = SSL_SESSION_new(); + if (!sess) { + log_openssl(LLVL_ERROR, "Failed to create SSL_SESSION context for client."); + return 0; + } + + const uint8_t tls13_aes128gcmsha256_id[] = { 0x13, 0x01 }; + const SSL_CIPHER *cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id); + if (!cipher) { + log_openssl(LLVL_ERROR, "Unable to look up SSL_CIPHER for TLSv1.3-PSK"); + return 0; + } + + int return_value = 1; + do { + if (!SSL_SESSION_set1_master_key(sess, key_client->keydb->hosts[0].tls_psk, PSK_SIZE_BYTES)) { + log_openssl(LLVL_ERROR, "Failed to set TLSv1.3-PSK master key."); + return_value = 0; + break; + } + + if (!SSL_SESSION_set_cipher(sess, cipher)) { + log_openssl(LLVL_ERROR, "Failed to set TLSv1.3-PSK cipher."); + return_value = 0; + break; + } + + if (!SSL_SESSION_set_protocol_version(sess, TLS1_3_VERSION)) { + log_openssl(LLVL_ERROR, "Failed to set TLSv1.3-PSK protocol version."); + return_value = 0; + break; + } + } while (false); + + if (return_value) { + *sessptr = sess; + } + + return return_value; } static bool contact_keyserver_socket(struct keyclient_t *keyclient, int sd) { @@ -237,7 +280,24 @@ static bool contact_keyserver_socket(struct keyclient_t *keyclient, int sd) { SSL_set_app_data(ssl, keyclient); if (SSL_connect(ssl) == 1) { - fprintf(stderr, "OK\n"); + struct msg_t msg; + while (true) { + int bytes_read = SSL_read(ssl, &msg, sizeof(msg)); + if (bytes_read == 0) { + /* Server closed the connection. */ + break; + } + if (bytes_read != sizeof(msg)) { + log_openssl(LLVL_FATAL, "SSL_read returned %d bytes when we expected to read %d", bytes_read, sizeof(msg)); + break; + } + if (should_log(LLVL_TRACE)) { + char uuid_str[ASCII_UUID_BUFSIZE]; + sprintf_uuid(uuid_str, msg.volume_uuid); + log_msg(LLVL_TRACE, "Received LUKS key to unlock volume with UUID %s", uuid_str); + } + } + OPENSSL_cleanse(&msg, sizeof(msg)); } else { log_openssl(LLVL_FATAL, "SSL_connect failed"); } @@ -292,7 +352,7 @@ static bool contact_keyserver_hostname(struct keyclient_t *keyclient, const char } struct sockaddr_in *sin_address = (struct sockaddr_in*)result->ai_addr; - log_msg(LLVL_DEBUG, "Resolved %s to %d.%d.%d.%d", hostname, PRINTF_FORMAT_IP(sin_address)); + log_msg(LLVL_TRACE, "Resolved %s to %d.%d.%d.%d", hostname, PRINTF_FORMAT_IP(sin_address)); bool success = contact_keyserver_ipv4(keyclient, sin_address, keyclient->opts->port); @@ -334,6 +394,9 @@ bool keyclient_start(const struct pgmopts_client_t *opts) { break; } + /* Transcribe the host UUID to ASCII so we only have to do this once */ + sprintf_uuid((char*)keyclient.identifier, host->host_uuid); + log_msg(LLVL_DEBUG, "Attempting to unlock %d volumes of host \"%s\".", host->volume_count, host->host_name); if (opts->hostname) { if (!contact_keyserver_hostname(&keyclient, opts->hostname)) { diff --git a/keydb.c b/keydb.c index b6b0f3e..6c93930 100644 --- a/keydb.c +++ b/keydb.c @@ -74,8 +74,10 @@ struct keydb_t* keydb_export_public(struct host_entry_t *host) { } void keydb_free(struct keydb_t *keydb) { - OPENSSL_cleanse(keydb, keydb_getsize(keydb)); - free(keydb); + if (keydb) { + OPENSSL_cleanse(keydb, keydb_getsize(keydb)); + free(keydb); + } } static int keydb_get_volume_index_by_name(struct host_entry_t *host, const char *devmapper_name) { diff --git a/log.c b/log.c index 5e9dbc1..d31eed1 100644 --- a/log.c +++ b/log.c @@ -37,6 +37,7 @@ static const char *loglvl_names[] = { [LLVL_WARNING] = "WARNING", [LLVL_INFO] = "INFO", [LLVL_DEBUG] = "DEBUG", + [LLVL_TRACE] = "TRACE", }; void log_setlvl(enum loglvl_t level) { diff --git a/log.h b/log.h index 703dc6b..903097d 100644 --- a/log.h +++ b/log.h @@ -31,7 +31,8 @@ enum loglvl_t { LLVL_ERROR = 1, LLVL_WARNING = 2, LLVL_INFO = 3, - LLVL_DEBUG = 4 + LLVL_DEBUG = 4, + LLVL_TRACE = 5, }; /*************** AUTO GENERATED SECTION FOLLOWS ***************/ diff --git a/server.c b/server.c index 422a337..71ad413 100644 --- a/server.c +++ b/server.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ #include "uuid.h" #include "thread.h" #include "keydb.h" +#include "signals.h" static int create_tcp_server_socket(int port) { int s; @@ -370,6 +372,9 @@ bool keyserver_start(const struct pgmopts_server_t *opts) { struct keydb_t* keydb = NULL; struct generic_tls_ctx_t gctx = { 0 }; do { + /* We ignore SIGPIPE or the server will die when clients disconnect suddenly */ + ignore_signal(SIGPIPE); + /* Load key database first */ keydb = keydb_read(opts->filename); if (!keydb) { diff --git a/signals.c b/signals.c new file mode 100644 index 0000000..143e6de --- /dev/null +++ b/signals.c @@ -0,0 +1,35 @@ +/* + 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 +*/ + +#include +#include +#include "signals.h" + +bool ignore_signal(int signum) { + struct sigaction action = { + .sa_handler = SIG_IGN, + .sa_flags = SA_RESTART, + }; + sigemptyset(&action.sa_mask); + return sigaction(signum, &action, NULL) == 0; +} diff --git a/signals.h b/signals.h new file mode 100644 index 0000000..72398b5 --- /dev/null +++ b/signals.h @@ -0,0 +1,33 @@ +/* + 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 +*/ + +#ifndef __SIGNALS_H__ +#define __SIGNALS_H__ + +#include + +/*************** AUTO GENERATED SECTION FOLLOWS ***************/ +bool ignore_signal(int signum); +/*************** AUTO GENERATED SECTION ENDS ***************/ + +#endif diff --git a/testdata/client.bin b/testdata/client.bin new file mode 100644 index 0000000000000000000000000000000000000000..a06751bd31d35c372364509b31b0ee41cf03ee84 GIT binary patch literal 1080 zcmV-81jqXU000000RRC1+!7YbSF55maI!w{@S@@w4~y}w* zv)qmWvIS$;bE*w=w-L)D%Z54C1Or3AToWu5`qXYpWo}XA6eKRAe1rh|-NGOP86L_t zALM;d9RqO?CqyME4uRbD|1h>_XGMH-cFABmiw%8Z^0yZzf|T4%W#eToP2ttD$!@f+ z$eS6jwmP~q*K4zgL1#_|;5otm6eBCHiKNI-Pcw z@bSvBv8c4RP&RM$+&ckB;-qd($+PI$Nb=hErvo7f4$XVm#4D*dyiUKZi7nc7UBGDs z4ja1VxB8Iuv7VTUhZA_~k!fD)h&iI54`QzC3UEZ8_mKf!DilD!1w041{&B>sX>qCz z$(fI&Cq;cefaN_-2V{yljD0lme9;oyxl!dyNrkfO+UrO=!neZ@Fo+vx=YG91xM4yT z*e{%*vO}7A?G%K3#aur`*Qjtq-e%qdc^k2=TYA8u@%(WK{fJibjM`Jo0xu4%Sy28% zeQc-*c|XKQ`w0=VTgIVJnty=Mw^m|2rwj z&*TThQ5CMe$A0HZxN5zgwD*S9N^SJ#dhT-A-soXlcBDo~|Gs4w(#w&u|X!)x8%-Dckv952Xs8P{Gs7iIWE9 zk!lLb!~4=hx0Nbb@a9)S5jaYRvBsqw?8z$&IDQ5n40(Hd3*tk#&`^Fz8_lucymnSZ5KHxel!2zPIo$-TyF)4Zw$Gf{P!Qyo%&Vl-pzJU!eh{pj=NR8a@}t_ yrKi?PVsdG1-O_a=dwN$(?P|h&p>D_|9u3bQEJ-X|%8YT`X|Z}c%4-wWy5gAioEf+P literal 0 HcmV?d00001 diff --git a/testdata/server.bin b/testdata/server.bin new file mode 100644 index 0000000000000000000000000000000000000000..facc703b5e8749422ede79d5662e4173306a21b2 GIT binary patch literal 2092 zcmV+{2-Eig000000RR9(4jwfbP#j9)>p`Yj_T{Yp=9G=iqu*4}7+^Ek1YxY$WAG=cCNt${UteR-WI5M1GUB{NIL;22zB)%wbV+1w*P z6*gN8OK`V3TNIoc!bcs1_L>0DqEKTe$0m9WBdj@Q9>{h z5Fp>(!sIx(kCItzV1sCnS-V7(ErtpJa$xWF`?37F`0}?1sfh6MO;)%o-LfAN*9JR2 zG3hUx^Xc0N(;C2-HZRjF2gZOoYjlCz9HpHUE?R{EiyN<6)aJ;%2S#zbT4H!kvjvk@ zGc}Ye50cLt8#Cc}+ZJPE!N2U3z6BKjpqyys`cVwFa_VK!h*20y>FQSrcn7u;JJCZ>MJ2`;?<36vW`adQ5=gKrqNx4Qj>0IHWg8n%R*FARm{-ducZ)?%z-QqLq=;u5}Ct7_h8%KDrY4OlclOtap|K z_5BNgJMCk0v5ZXGguakF)kVwfjxD87T-*3TO+`zoz&arb6^297@%HMX@FL)H< zW+f211?*e<+cRbfq`(9w{h^08AO@IubRB-7_rU=1MyH?Z0m)yZMP-*!8bi(4g2H8i*LpUuYs!q9avzlV@ES;*-iTzD3z*y@We zJyKzpQrm;SK?zb|xLE1P`0+e0NC&~ohpCXfI94ZXn79pRoZ8i_##5-`G>bY5kM2d_CTj!3$u942T>*G(EI!#Ua9Xyiz zL*6ox@1ICLH^Tdhd38~Ud}I5Xh@?eCO9nL~TTaY#9!~`dRKmxl5Hc;-5og>0MYZBB zSGF)#%KK^)&%GvWk~Pk3Jx9o0?@Z4|sM2;!@ut|JZVY>X~kk=SJXjL z-m0R%Kp%lHK4ucex{sf!dUz^J8w}9(GvX)Qb^W1&QT^ibeWKVc?2HlG2_P*F4MR$b zSm$53{wE<<0zPTlHd$MYElsBY9-SjL6iw)OT3sKhzdk4C*={6Jml3XP;fr=>s}6f$ zB~GdP%o_n5d;U#C9BINjo1EML(&i+;K?|vly5fp$Bksa`f4e`#g~^!7y?v9^c*_MS zg;rwMAqVs8%b$a)dr9yYMI?5&2GJPI(%rKElIyZ_swYmQpn5xFVeU+jy=iuQp-4V+@8!BNWNp&85 zHBM%(-)yWS6G|ZX@H$!-4GQf{)C_QfG;)@r^HZlnGUPrSY7*v>I|2(5V&UUAAldc( zHUy8Y^cRQlEJZHkGHlEI1+=XTBgbcZ&hIbItMeYtT)6}Vhyjl(4%1P)wwK=FEe zgH1D%>Jd&?DoRF}iQn6fG~k=Wyo>sSx3^2!>&17MuwO;n#`l0I3$v706W8}9Pc%)H z)y!CNmHQ#d%RDVzWgpX~{-ZUnZu{{3sHR7umqr|;v5lRI*1vU>)SFG(=(IkME(-p4 z?Vl1WRRyjgAfj_q72JLt?O0>~p#6}}J**E1r#2Dl`C{$(Sna{d*BAon^L;V}`tT<3 zhB9RNP0CT`fLcrC9CGUr>UzEoA2OT zuuSaalFF&ZpEg{n4g-w?T30{9(9#jhh|Y|dad*;*bga8yuy;O5FJv^QVpP^#em1D4 z&1M4^T!Q?$#Vogp_rA9A8p*x9oKIhUov^bH{(v~bPMBcY%S0c{O;~1-hzxj`kp)q= zB=-nIP8`d0u<$13CI8=T^r|Q+%hZcK_J%a@d6RsOay`Sk=Amx>LvPQy()d=M3+JBG zk+kjnx&|K-Krek8nl4gAwb5{$s5Qg7z%pKAGHRjrW%}`PWkHW+NfqwEscsY{y6wL& Wswf~NM;J8oC1|w#jl4K@6BZy8Zwu4_ literal 0 HcmV?d00001