Skip to content

Commit c10c8ba

Browse files
committed
options: Allow multiple --key parameters.
This allows multiple --key parameters on the command line to match a single device. For example: tool --key /dev/sda1:key:trykey1 --key /dev/sda1:key:trykey2 would try "trykey1" and "trykey2" against /dev/sda1.
1 parent 530d0be commit c10c8ba

File tree

3 files changed

+67
-21
lines changed

3 files changed

+67
-21
lines changed

options/decrypt.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
#include <stdio.h>
2727
#include <stdlib.h>
2828
#include <string.h>
29+
#include <libintl.h>
30+
#include <error.h>
31+
#include <assert.h>
2932

3033
#include "c-ctype.h"
3134

@@ -74,21 +77,37 @@ inspect_do_decrypt (guestfs_h *g, struct key_store *ks)
7477
if (partitions == NULL)
7578
exit (EXIT_FAILURE);
7679

77-
int need_rescan = 0;
78-
size_t i;
80+
int need_rescan = 0, r;
81+
size_t i, j;
82+
7983
for (i = 0; partitions[i] != NULL; ++i) {
8084
CLEANUP_FREE char *type = guestfs_vfs_type (g, partitions[i]);
8185
if (type && STREQ (type, "crypto_LUKS")) {
8286
char mapname[32];
8387
make_mapname (partitions[i], mapname, sizeof mapname);
8488

85-
CLEANUP_FREE char *key = get_key (ks, partitions[i]);
86-
/* XXX Should we call guestfs_luks_open_ro if readonly flag
87-
* is set? This might break 'mount_ro'.
88-
*/
89-
if (guestfs_luks_open (g, partitions[i], key, mapname) == -1)
90-
exit (EXIT_FAILURE);
91-
89+
CLEANUP_FREE_STRING_LIST char **keys = get_keys (ks, partitions[i]);
90+
assert (guestfs_int_count_strings (keys) > 0);
91+
92+
/* Try each key in turn. */
93+
for (j = 0; keys[j] != NULL; ++j) {
94+
/* XXX Should we call guestfs_luks_open_ro if readonly flag
95+
* is set? This might break 'mount_ro'.
96+
*/
97+
guestfs_push_error_handler (g, NULL, NULL);
98+
r = guestfs_luks_open (g, partitions[i], keys[j], mapname);
99+
guestfs_pop_error_handler (g);
100+
if (r == 0)
101+
goto opened;
102+
}
103+
error (EXIT_FAILURE, 0,
104+
_("could not find key to open LUKS encrypted %s.\n\n"
105+
"Try using --key on the command line.\n\n"
106+
"Original error: %s (%d)"),
107+
partitions[i], guestfs_last_error (g),
108+
guestfs_last_errno (g));
109+
110+
opened:
92111
need_rescan = 1;
93112
}
94113
}

options/keys.c

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,32 @@ read_first_line_from_file (const char *filename)
121121
return ret;
122122
}
123123

124-
char *
125-
get_key (struct key_store *ks, const char *device)
124+
/* Return the key(s) matching this particular device from the
125+
* keystore. There may be multiple. If none are read from the
126+
* keystore, ask the user.
127+
*/
128+
char **
129+
get_keys (struct key_store *ks, const char *device)
126130
{
127-
size_t i;
131+
size_t i, j, len;
132+
char **r;
133+
char *s;
134+
135+
/* We know the returned list must have at least one element and not
136+
* more than ks->nr_keys.
137+
*/
138+
len = 1;
139+
if (ks)
140+
len = MIN (1, ks->nr_keys);
141+
r = calloc (len+1, sizeof (char *));
142+
if (r == NULL)
143+
error (EXIT_FAILURE, errno, "calloc");
144+
145+
j = 0;
128146

129147
if (ks) {
130148
for (i = 0; i < ks->nr_keys; ++i) {
131149
struct key_store_key *key = &ks->keys[i];
132-
char *s;
133150

134151
if (STRNEQ (key->device, device))
135152
continue;
@@ -139,17 +156,25 @@ get_key (struct key_store *ks, const char *device)
139156
s = strdup (key->string.s);
140157
if (!s)
141158
error (EXIT_FAILURE, errno, "strdup");
142-
return s;
159+
r[j++] = s;
160+
break;
143161
case key_file:
144-
return read_first_line_from_file (key->file.name);
162+
s = read_first_line_from_file (key->file.name);
163+
r[j++] = s;
164+
break;
145165
}
146-
147-
/* Key not found in the key store, ask the user for it. */
148-
break;
149166
}
150167
}
151168

152-
return read_key (device);
169+
if (j == 0) {
170+
/* Key not found in the key store, ask the user for it. */
171+
s = read_key (device);
172+
if (!s)
173+
error (EXIT_FAILURE, 0, _("could not read key from user"));
174+
r[0] = s;
175+
}
176+
177+
return r;
153178
}
154179

155180
struct key_store *

options/options.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ struct mp {
104104

105105
/* A key in the key store. */
106106
struct key_store_key {
107-
/* The device this key refers to. */
107+
/* The device this key refers to. There may be multiple matching
108+
* devices in the list.
109+
*/
108110
char *device;
109111

110112
enum {
@@ -146,7 +148,7 @@ extern void print_inspect_prompt (void);
146148

147149
/* in key.c */
148150
extern char *read_key (const char *param);
149-
extern char *get_key (struct key_store *ks, const char *device);
151+
extern char **get_keys (struct key_store *ks, const char *device);
150152
extern struct key_store *key_store_add_from_selector (struct key_store *ks, const char *selector);
151153
extern struct key_store *key_store_import_key (struct key_store *ks, const struct key_store_key *key);
152154
extern void free_key_store (struct key_store *ks);

0 commit comments

Comments
 (0)