Introduce --max-bcast-errs command line option

This enables luksrku to terminate if a certain number of broadcast
attempts has failed (usually due to unavailable networking), therefore
enabling a second method of unlocking LUKS disks (e.g., by manually
entering the password on the console).
This commit is contained in:
Johannes Bauer 2016-09-24 15:58:52 +02:00
parent 192df4470e
commit 6089d98721
4 changed files with 44 additions and 22 deletions

View File

@ -34,31 +34,36 @@ enum longopts_t {
LONGOPT_MODE_CLIENT, LONGOPT_MODE_CLIENT,
LONGOPT_PORT, LONGOPT_PORT,
LONGOPT_KEYDB, LONGOPT_KEYDB,
LONGOPT_UNLOCK_CNT LONGOPT_UNLOCK_CNT,
LONGOPT_MAX_BCAST_ERRS
}; };
void print_syntax(const char *pgmname) { 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, "%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, " (-p, --port=PORT) (--max-bcast-errs=CNT) (-v, --verbose)\n");
fprintf(stderr, "\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, " -c, --client-mode Specifies client mode, i.e., that this host will unlock the LUKS\n");
fprintf(stderr, " of a different machine.\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, " -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, " presence via UDP broadcasts and then receive the LUKS credentials\n");
fprintf(stderr, " from a peer.\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, " -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 host,\n"); fprintf(stderr, " mode, this contains only one entry (specifying the UUID of the\n");
fprintf(stderr, " the PSK and the UUIDs and names of the disks to be unlocked), while\n"); fprintf(stderr, " host, the PSK and the UUIDs and names of the disks to be\n");
fprintf(stderr, " in client mode this may contain multiple entries (to unlock many\n"); fprintf(stderr, " unlocked), while in client mode this may contain multiple entries\n");
fprintf(stderr, " different peers) and also contains the LUKS credentials for the\n"); fprintf(stderr, " (to unlock many different peers) and also contains the LUKS\n");
fprintf(stderr, " respective disks.\n"); fprintf(stderr, " credentials for the respective disks.\n");
fprintf(stderr, " -u, --unlock=CNT Specifies the maximum number of unlocking actions that are taken. In\n"); fprintf(stderr, " -u, --unlock=CNT Specifies the maximum number of unlocking actions that are taken.\n");
fprintf(stderr, " client mode, this defaults to 1. In server mode, it defaults to\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). Zero\n"); fprintf(stderr, " infinite (or until all disks have successfully been unlocked).\n");
fprintf(stderr, " means infinite.\n"); fprintf(stderr, " Zero means infinite.\n");
fprintf(stderr, " -p, --port=PORT Specifies the port on which is listened for UDP broadcasts and also\n"); fprintf(stderr, " -p, --port=PORT Specifies the port on which is listened for UDP broadcasts and\n");
fprintf(stderr, " the port on which TCP requests are sent out (the two are always\n"); fprintf(stderr, " also the port on which TCP requests are sent out (the two are\n");
fprintf(stderr, " identical). Default port ist 23170.\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, " -v, --verbose Increase logging verbosity.\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
@ -71,6 +76,9 @@ static void set_default_arguments(struct options_t *options) {
/* Default, overwritten later by fill_default_arguments() */ /* Default, overwritten later by fill_default_arguments() */
options->unlock_cnt = -1; 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) { static void fill_default_arguments(struct options_t *options) {
@ -117,6 +125,7 @@ bool parse_cmdline_arguments(struct options_t *options, int argc, char **argv) {
{ "port", required_argument, 0, LONGOPT_PORT }, { "port", required_argument, 0, LONGOPT_PORT },
{ "keydb", required_argument, 0, LONGOPT_KEYDB }, { "keydb", required_argument, 0, LONGOPT_KEYDB },
{ "unlock", required_argument, 0, LONGOPT_UNLOCK_CNT }, { "unlock", required_argument, 0, LONGOPT_UNLOCK_CNT },
{ "max-bcast-errs", required_argument, 0, LONGOPT_MAX_BCAST_ERRS },
{ 0 } { 0 }
}; };
@ -155,6 +164,10 @@ bool parse_cmdline_arguments(struct options_t *options, int argc, char **argv) {
options->unlock_cnt = atoi(optarg); options->unlock_cnt = atoi(optarg);
break; break;
case LONGOPT_MAX_BCAST_ERRS:
options->max_broadcast_errs = atoi(optarg);
break;
case -1: case -1:
/* Out of arguments */ /* Out of arguments */
parse = false; parse = false;

View File

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

View File

@ -61,6 +61,7 @@ hpp.add([ "-s", "--server-mode" ], "Specifies server mode, i.e., that this host
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([ "-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([ "-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([ "-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([ "-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([ "--max-bcast-errs=CNT" ], "This is the number of UDP broadcast attempts luksrku will make before giving up. Usually this is because sendto(2) fails when the network is configured improperly. Giving up in this case enables manual key entry. This defaults to 5 tries.")
hpp.add([ "-v", "--verbose" ], "Increase logging verbosity.") hpp.add([ "-v", "--verbose" ], "Increase logging verbosity.")
for (index, line) in enumerate(hpp.format_params()): for (index, line) in enumerate(hpp.format_params()):
if index == 0: if index == 0:

View File

@ -209,12 +209,19 @@ 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); log_msg(LLVL_DEBUG, "Created listening socket on port %d", options->port);
int tries = 0; int tries = 0;
int failed_broadcast_cnt = 0;
while ((options->unlock_cnt == 0) || (tries < options->unlock_cnt)) { while ((options->unlock_cnt == 0) || (tries < options->unlock_cnt)) {
struct sockaddr_in addr; struct sockaddr_in addr;
unsigned int len = sizeof(addr); unsigned int len = sizeof(addr);
log_msg(LLVL_DEBUG, "Waiting for incoming connection..."); log_msg(LLVL_DEBUG, "Waiting for incoming connection...");
announce_waiting_message(udp_sock, options->port, key); if (!announce_waiting_message(udp_sock, options->port, key)) {
failed_broadcast_cnt++;
if ((options->max_broadcast_errs != 0) && (failed_broadcast_cnt >= options->max_broadcast_errs)) {
log_msg(LLVL_ERROR, "Too many broadcast errors, aborting. Network unavailable?");
break;
}
}
if (!socket_wait_acceptable(tcp_sock, WAITING_MESSAGE_BROADCAST_INTERVAL_MILLISECONDS)) { if (!socket_wait_acceptable(tcp_sock, WAITING_MESSAGE_BROADCAST_INTERVAL_MILLISECONDS)) {
/* No connection pending, timeout. */ /* No connection pending, timeout. */
continue; continue;