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,32 +34,37 @@ enum longopts_t {
LONGOPT_MODE_CLIENT,
LONGOPT_PORT,
LONGOPT_KEYDB,
LONGOPT_UNLOCK_CNT
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) (-v, --verbose)\n");
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 disk\n");
fprintf(stderr, " 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 host,\n");
fprintf(stderr, " the PSK and the UUIDs and names of the disks to be unlocked), while\n");
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). Default port ist 23170.\n");
fprintf(stderr, " -v, --verbose Increase logging verbosity.\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");
}
@ -71,6 +76,9 @@ static void set_default_arguments(struct options_t *options) {
/* 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) {
@ -117,6 +125,7 @@ bool parse_cmdline_arguments(struct options_t *options, int argc, char **argv) {
{ "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 }
};
@ -154,6 +163,10 @@ bool parse_cmdline_arguments(struct options_t *options, int argc, char **argv) {
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 */

View File

@ -38,6 +38,7 @@ struct options_t {
bool verbose;
const char *keydbfile;
int unlock_cnt;
int max_broadcast_errs;
};
/*************** 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([ "-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([ "--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.")
for (index, line) in enumerate(hpp.format_params()):
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);
int tries = 0;
int failed_broadcast_cnt = 0;
while ((options->unlock_cnt == 0) || (tries < options->unlock_cnt)) {
struct sockaddr_in addr;
unsigned int len = sizeof(addr);
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)) {
/* No connection pending, timeout. */
continue;