Implemented unlock cnt and blacklist

Can now unlock a specified number of hosts as specified on the command
line (e.g., if you want a luksrku client run indefinitely) and also used
the already implemented blacklisting functionality (i.e., if an
unlocking is unsuccessful, it is retried in 120 seconds, not
immediately, as not to spam servers with illegal credentials).
This commit is contained in:
Johannes Bauer 2016-09-24 11:45:58 +02:00
parent 180b747d24
commit 0d4d2220b2
5 changed files with 60 additions and 13 deletions

View File

@ -37,6 +37,7 @@
#include "cmdline.h"
#include "msg.h"
#include "client.h"
#include "blacklist.h"
static const struct keydb_t *client_keydb;
@ -144,6 +145,18 @@ static bool parse_announcement(const struct options_t *options, const struct soc
return false;
}
/* We know the server. But maybe we've already tried to contact them and
* therefore they're blacklisted for a certain period of time. Check this
* now (we don't want to spam servers with maybe invalid passphrases). */
uint32_t ip = peer_addr->sin_addr.s_addr;
if (is_ip_blacklisted(ip)) {
log_msg(LLVL_DEBUG, "%d.%d.%d.%d is currently blacklisted for %d seconds.", PRINTF_FORMAT_IP(peer_addr), BLACKLIST_ENTRY_TIMEOUT_SECS);
return false;
} else {
/* Blacklist for next time */
blacklist_ip(ip);
}
char destination_address[32];
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);
@ -177,14 +190,15 @@ bool dtls_client(const struct keydb_t *keydb, const struct options_t *options) {
return false;
}
while (true) {
int tries = 0;
while ((options->unlock_cnt == 0) || (tries < options->unlock_cnt)) {
uint8_t rxbuf[2048];
struct sockaddr_in peer_addr;
socklen_t addr_size = sizeof(peer_addr);
int rxlen = recvfrom(sd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&peer_addr, &addr_size);
if (rxlen == sizeof(struct announcement_t)) {
if (parse_announcement(options, &peer_addr, (struct announcement_t*)rxbuf)) {
break;
tries++;
}
}
}

View File

@ -33,12 +33,13 @@ enum longopts_t {
LONGOPT_MODE_SERVER,
LONGOPT_MODE_CLIENT,
LONGOPT_PORT,
LONGOPT_KEYDB
LONGOPT_KEYDB,
LONGOPT_UNLOCK_CNT
};
void print_syntax(const char *pgmname) {
fprintf(stderr, "%s (-c, --client-mode) (-s, --server-mode) (-k, --keydb=FILE) (-p, --port=PORT)\n", pgmname);
fprintf(stderr, " (-v, --verbose)\n");
fprintf(stderr, "%s (-c, --client-mode) (-s, --server-mode) (-k, --keydb=FILE) (-u, --unlock=CNT)\n", pgmname);
fprintf(stderr, " (-p, --port=PORT) (-v, --verbose)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -c, --client-mode Specifies client mode, i.e., that this host will unlock the LUKS disk\n");
fprintf(stderr, " of a different machine.\n");
@ -51,9 +52,13 @@ void print_syntax(const char *pgmname) {
fprintf(stderr, " in client mode this may contain multiple entries (to unlock many\n");
fprintf(stderr, " different peers) and also contains the LUKS credentials for the\n");
fprintf(stderr, " respective disks.\n");
fprintf(stderr, " -u, --unlock=CNT Specifies the maximum number of unlocking actions that are taken. In\n");
fprintf(stderr, " client mode, this defaults to 1. In server mode, it defaults to\n");
fprintf(stderr, " infinite (or until all disks have successfully been unlocked). Zero\n");
fprintf(stderr, " means infinite.\n");
fprintf(stderr, " -p, --port=PORT Specifies the port on which is listened for UDP broadcasts and also\n");
fprintf(stderr, " the port on which TCP requests are sent out (the two are always\n");
fprintf(stderr, " identical).\n");
fprintf(stderr, " identical). Default port ist 23170.\n");
fprintf(stderr, " -v, --verbose Increase logging verbosity.\n");
fprintf(stderr, "\n");
}
@ -63,6 +68,20 @@ static void set_default_arguments(struct options_t *options) {
/* Default port :-) echo -n LUKS | md5sum | cut -c -5 */
options->port = 23170;
/* Default, overwritten later by fill_default_arguments() */
options->unlock_cnt = -1;
}
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) {
@ -81,6 +100,10 @@ static bool check_arguments(const struct options_t *options) {
return false;
}
if (options->unlock_cnt < 0) {
fprintf(stderr, "Unlock count must be a positive integer.\n");
return false;
}
return true;
}
@ -93,13 +116,14 @@ bool parse_cmdline_arguments(struct options_t *options, int argc, char **argv) {
{ "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 },
{ 0 }
};
bool success = true;
bool parse = true;
do {
int c = getopt_long(argc, argv, "vscp:k:", long_options, NULL);
int c = getopt_long(argc, argv, "vscp:k:u:", long_options, NULL);
switch (c) {
case LONGOPT_VERBOSE:
case 'v':
@ -126,6 +150,11 @@ bool parse_cmdline_arguments(struct options_t *options, int argc, char **argv) {
options->keydbfile = optarg;
break;
case LONGOPT_UNLOCK_CNT:
case 'u':
options->unlock_cnt = atoi(optarg);
break;
case -1:
/* Out of arguments */
parse = false;
@ -145,5 +174,6 @@ bool parse_cmdline_arguments(struct options_t *options, int argc, char **argv) {
}
} while (parse);
fill_default_arguments(options);
return success && check_arguments(options);
}

View File

@ -37,6 +37,7 @@ struct options_t {
int port;
bool verbose;
const char *keydbfile;
int unlock_cnt;
};
/*************** AUTO GENERATED SECTION FOLLOWS ***************/

View File

@ -59,11 +59,12 @@ hpp = HelpPagePrinter()
hpp.add([ "-c", "--client-mode" ], "Specifies client mode, i.e., that this host will unlock the LUKS disk of a different machine.")
hpp.add([ "-s", "--server-mode" ], "Specifies server mode, i.e., that this host will announce its presence via UDP broadcasts and then receive the LUKS credentials from a peer.")
hpp.add([ "-k", "--keydb=FILE" ], "Gives the binary key database file which will be used. In server mode, this contains only one entry (specifying the UUID of the host, the PSK and the UUIDs and names of the disks to be unlocked), while in client mode this may contain multiple entries (to unlock many different peers) and also contains the LUKS credentials for the respective disks.")
hpp.add([ "-p", "--port=PORT" ], "Specifies the port on which is listened for UDP broadcasts and also the port on which TCP requests are sent out (the two are always identical).")
hpp.add([ "-u", "--unlock=CNT" ], "Specifies the maximum number of unlocking actions that are taken. In client mode, this defaults to 1. In server mode, it defaults to infinite (or until all disks have successfully been unlocked). Zero means infinite.")
hpp.add([ "-p", "--port=PORT" ], "Specifies the port on which is listened for UDP broadcasts and also the port on which TCP requests are sent out (the two are always identical). Default port ist 23170.")
hpp.add([ "-v", "--verbose" ], "Increase logging verbosity.")
for (index, line) in enumerate(hpp.format_params()):
if index == 0:
print("fprintf(stderr, \"%%s%s\\n\", argv[0]);" % (line))
print("fprintf(stderr, \"%%s%s\\n\", pgmname);" % (line))
else:
print("fprintf(stderr, \" %s\\n\");" % (line))
print("fprintf(stderr, \"\\n\");")

View File

@ -208,7 +208,8 @@ bool dtls_server(const struct keyentry_t *key, const struct options_t *options)
}
log_msg(LLVL_DEBUG, "Created listening socket on port %d", options->port);
while (true) {
int tries = 0;
while ((options->unlock_cnt == 0) || (tries < options->unlock_cnt)) {
struct sockaddr_in addr;
unsigned int len = sizeof(addr);
@ -229,13 +230,13 @@ bool dtls_server(const struct keyentry_t *key, const struct options_t *options)
return false;
}
SSL *ssl = SSL_new(gctx.ctx);
SSL_set_fd(ssl, client);
if (SSL_accept(ssl) <= 0) {
ERR_print_errors_fp(stderr);
} else {
tries++;
log_msg(LLVL_DEBUG, "Client connected, waiting for data...");
while (true) {
struct msg_t msg;