summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>2019-02-15 10:40:56 +1100
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>2019-03-26 16:46:38 +1100
commit1ad18bf128c4edfae76adaffd9c7801355f29b91 (patch)
tree40808aac6ec04d42c62eb445f99c286372a29b06
parentf583f0cf35fc227db5f73ecd04daf7702735b740 (diff)
downloadtalos-petitboot-1ad18bf128c4edfae76adaffd9c7801355f29b91.zip
talos-petitboot-1ad18bf128c4edfae76adaffd9c7801355f29b91.tar.gz
ui/ncurses: Add prompt for LUKS device password
Implement device_add() in cui_client_ops and use this interface to recognise when the server notifies the client of an encrypted device. A "device header" will be created for this device and added to the menu with no associated boot options. The nc-auth prompt is extended to ask for a disk password when the device header for an encrypted device is selected. Assuming the password is correct pb-discover will remove the original device and notify the client about the newly opened device, which will be reflected in the menu. Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
-rw-r--r--ui/common/discover-client.c25
-rw-r--r--ui/common/discover-client.h3
-rw-r--r--ui/ncurses/nc-auth.c30
-rw-r--r--ui/ncurses/nc-auth.h1
-rw-r--r--ui/ncurses/nc-cui.c165
-rw-r--r--ui/ncurses/nc-cui.h3
6 files changed, 219 insertions, 8 deletions
diff --git a/ui/common/discover-client.c b/ui/common/discover-client.c
index e7dfb83..6dda2d3 100644
--- a/ui/common/discover-client.c
+++ b/ui/common/discover-client.c
@@ -552,3 +552,28 @@ int discover_client_send_set_password(struct discover_client *client,
pb_log("sending auth message..\n");
return pb_protocol_write_message(client->fd, message);
}
+
+int discover_client_send_open_luks_device(struct discover_client *client,
+ char *password, char *device_id)
+{
+ struct pb_protocol_message *message;
+ struct auth_message auth_msg;
+ int len;
+
+ auth_msg.op = AUTH_MSG_DECRYPT;
+ auth_msg.decrypt_dev.password = password;
+ auth_msg.decrypt_dev.device_id = device_id;
+
+ len = pb_protocol_authenticate_len(&auth_msg);
+
+ message = pb_protocol_create_message(client,
+ PB_PROTOCOL_ACTION_AUTHENTICATE, len);
+ if (!message)
+ return -1;
+
+ pb_log("serialising auth message..\n");
+ pb_protocol_serialise_authenticate(&auth_msg, message->payload, len);
+
+ pb_log("sending auth message..\n");
+ return pb_protocol_write_message(client->fd, message);
+}
diff --git a/ui/common/discover-client.h b/ui/common/discover-client.h
index 9b56dcb..183d193 100644
--- a/ui/common/discover-client.h
+++ b/ui/common/discover-client.h
@@ -113,6 +113,9 @@ int discover_client_send_authenticate(struct discover_client *client,
/* Set a new system password, authenticating with the current password */
int discover_client_send_set_password(struct discover_client *client,
char *password, char *new_password);
+/* Send a password to open an encrypted device */
+int discover_client_send_open_luks_device(struct discover_client *client,
+ char *password, char *device_id);
/* send a temporary autoboot override */
int discover_client_send_temp_autoboot(struct discover_client *client,
diff --git a/ui/ncurses/nc-auth.c b/ui/ncurses/nc-auth.c
index 5bfda8b..227c57b 100644
--- a/ui/ncurses/nc-auth.c
+++ b/ui/ncurses/nc-auth.c
@@ -42,6 +42,7 @@ struct auth_screen {
void (*process_key)(struct nc_scr *, int);
bool set_password;
+ const struct device *dev;
void (*callback)(struct nc_scr *);
int offset_y;
int label_x;
@@ -144,6 +145,9 @@ static void ok_click(void *arg)
if (screen->set_password) {
new_password = widget_textbox_get_value(screen->widgets.new_f);
rc = cui_send_set_password(screen->cui, password, new_password);
+ } else if (screen->dev) {
+ rc = cui_send_open_luks_device(screen->cui, password,
+ screen->dev->id);
} else
rc = cui_send_authenticate(screen->cui, password);
@@ -194,6 +198,7 @@ static void auth_screen_layout_widgets(struct auth_screen *screen)
static void auth_screen_draw(struct auth_screen *screen)
{
struct nc_widgetset *set;
+ char *label;
set = widgetset_create(screen, screen->scr.main_ncw,
screen->scr.sub_ncw);
@@ -203,10 +208,20 @@ static void auth_screen_draw(struct auth_screen *screen)
}
screen->widgetset = set;
- screen->widgets.title_a_l = widget_new_label(set, 0, 0,
- _("This action requires authorisation."));
- screen->widgets.title_b_l = widget_new_label(set, 0, 0,
- _("Please enter the system password."));
+ if (screen->dev) {
+ label = talloc_asprintf(screen,
+ _("Opening encrypted device %s"),
+ screen->dev->id);
+ screen->widgets.title_a_l = widget_new_label(set, 0, 0, label);
+ screen->widgets.title_b_l = widget_new_label(set, 0, 0,
+ _("Please enter the disk password."));
+ talloc_free(label);
+ } else {
+ screen->widgets.title_a_l = widget_new_label(set, 0, 0,
+ _("This action requires authorisation."));
+ screen->widgets.title_b_l = widget_new_label(set, 0, 0,
+ _("Please enter the system password."));
+ }
screen->widgets.password_f = widget_new_textbox_hidden(set, 0, 0,
COLS - 20 - 20, "", true);
@@ -236,6 +251,7 @@ static int auth_screen_destroy(void *arg)
struct auth_screen *auth_screen_init(struct cui *cui,
WINDOW *parent, bool set_password,
+ const struct device *dev,
void (*callback)(struct nc_scr *),
void (*on_exit)(struct cui *))
{
@@ -246,6 +262,11 @@ struct auth_screen *auth_screen_init(struct cui *cui,
if (!cui || !parent)
return NULL;
+ if (set_password && dev) {
+ pb_log_fn("Incorrect parameters (set_password and device)\n");
+ return NULL;
+ }
+
screen = talloc_zero(cui, struct auth_screen);
if (!screen)
return NULL;
@@ -254,6 +275,7 @@ struct auth_screen *auth_screen_init(struct cui *cui,
screen->cui = cui;
screen->return_scr = cui->current;
screen->set_password = set_password;
+ screen->dev = dev;
screen->callback = callback;
screen->on_exit = on_exit;
screen->label_x = 5;
diff --git a/ui/ncurses/nc-auth.h b/ui/ncurses/nc-auth.h
index e8e4148..0473c92 100644
--- a/ui/ncurses/nc-auth.h
+++ b/ui/ncurses/nc-auth.h
@@ -24,6 +24,7 @@ struct auth_screen;
struct auth_screen *auth_screen_init(struct cui *cui,
WINDOW *pad, bool set_password,
+ const struct device *dev,
void (callback)(struct nc_scr *),
void (*on_exit)(struct cui *));
diff --git a/ui/ncurses/nc-cui.c b/ui/ncurses/nc-cui.c
index d80e2c3..bd2eb68 100644
--- a/ui/ncurses/nc-cui.c
+++ b/ui/ncurses/nc-cui.c
@@ -360,7 +360,7 @@ static int menu_reinit_execute(struct pmenu_item *item)
return 0;
cui->auth_screen = auth_screen_init(cui, cui->current->main_ncw,
- false, menu_reinit_cb, cui_auth_exit);
+ false, NULL, menu_reinit_cb, cui_auth_exit);
if (cui->auth_screen)
cui_set_current(cui, auth_screen_scr(cui->auth_screen));
@@ -407,6 +407,35 @@ static int cui_boot_check(struct pmenu_item *item)
return 0;
}
+static void cui_luks_cb(struct nc_scr *scr)
+{
+ struct cui_opt_data *cod;
+ struct pmenu_item *item;
+ struct pmenu *menu;
+ struct cui *cui;
+
+ menu = pmenu_from_scr(scr);
+ item = pmenu_find_selected(menu);
+ cod = cod_from_item(item);
+ cui = cui_from_item(item);
+
+ cui_show_open_luks(cui, scr->main_ncw, cod->dev);
+}
+
+static int cui_open_luks_device(struct pmenu_item *item)
+{
+ struct cui_opt_data *cod = cod_from_item(item);
+ struct cui *cui = cui_from_item(item);
+
+ if (discover_client_authenticated(cui->client))
+ cui_show_open_luks(cui, item->pmenu->scr.main_ncw, cod->dev);
+ else
+ cui_show_auth(cui, item->pmenu->scr.main_ncw, false,
+ cui_luks_cb);
+
+ return 0;
+}
+
static void cui_boot_editor_on_exit(struct cui *cui,
struct pmenu_item *item,
struct pb_boot_data *bd)
@@ -707,13 +736,28 @@ void cui_show_auth(struct cui *cui, WINDOW *parent, bool set_password,
if (cui->auth_screen)
return;
- cui->auth_screen = auth_screen_init(cui, parent, set_password,
+ cui->auth_screen = auth_screen_init(cui, parent, set_password, NULL,
callback, cui_auth_exit);
if (cui->auth_screen)
cui_set_current(cui, auth_screen_scr(cui->auth_screen));
}
+void cui_show_open_luks(struct cui *cui, WINDOW *parent,
+ const struct device *dev)
+{
+ if (!cui->current)
+ return;
+
+ if (cui->auth_screen)
+ return;
+
+ cui->auth_screen = auth_screen_init(cui, parent, false, dev,
+ NULL, cui_auth_exit);
+
+ if (cui->auth_screen)
+ cui_set_current(cui, auth_screen_scr(cui->auth_screen));
+}
/**
* cui_set_current - Set the currently active screen and redraw it.
*/
@@ -899,7 +943,7 @@ static void cui_handle_resize(struct cui *cui)
}
/**
- * cui_device_add - Client device_add callback.
+ * cui_boot_option_add - Client boot_option_add callback.
*
* Creates menu_items for all the device boot_options and inserts those
* menu_items into the main menu. Redraws the main menu if it is active.
@@ -1081,6 +1125,113 @@ static int cui_boot_option_add(struct device *dev, struct boot_option *opt,
}
/**
+ * cui_device_add - Client device_add callback
+ *
+ * For ncurses this is only used to specially handle encrypted devices and
+ * create a special device header for them.
+ * Normal devices are handled as part of the cui_boot_option_add() process.
+ */
+static int cui_device_add(struct device *dev, void *arg)
+{
+ struct cui *cui = cui_from_arg(arg);
+ struct pmenu *menu = cui->main;
+ struct pmenu_item *dev_hdr;
+ unsigned int insert_pt, i;
+ struct cui_opt_data *cod;
+ struct blockdev_info *bd;
+ struct system_info *sys;
+ int result, rows, cols;
+ ITEM *selected;
+ char *name;
+
+ /* Nothing to do */
+ if (dev->type != DEVICE_TYPE_LUKS) {
+ pb_log("Ignoring dev %s with type %s\n",
+ dev->id, device_type_display_name(dev->type));
+ return 0;
+ }
+
+ pb_log("Creating header for encrypted device %s\n", dev->id);
+
+ /* Create a dev_hdr for the encrypted device */
+ /* Find block info */
+ sys = cui->sysinfo;
+ name = NULL;
+ for (i = 0; sys && i < sys->n_blockdevs; i++) {
+ bd = sys->blockdevs[i];
+ if (!strcmp(dev->id, bd->name)) {
+ name = talloc_asprintf(menu, "[%s: %s / %s]",
+ device_type_display_name(dev->type),
+ bd->name, bd->uuid);
+ break;
+ }
+ }
+ if (!name) {
+ name = talloc_asprintf(menu, "[%s: \"%s\"]",
+ device_type_display_name(dev->type),
+ dev->id);
+ }
+
+ dev_hdr = pmenu_item_create(menu, name);
+ if (!dev_hdr) {
+ pb_log_fn("Failed to create header item\n");
+ return -1;
+ }
+ talloc_free(name);
+
+ dev_hdr->on_execute = cui_open_luks_device;
+
+ cod = talloc_zero(dev_hdr, struct cui_opt_data);
+ cod->name = talloc_strdup(dev_hdr, dev->id);
+ cod->dev = dev;
+ dev_hdr->data = cod;
+
+ if (cui->current == &cui->main->scr)
+ nc_scr_unpost(cui->current);
+
+ /* This disconnects items array from menu. */
+ result = set_menu_items(menu->ncm, NULL);
+
+ if (result) {
+ pb_log_fn("set_menu_items failed: %d\n", result);
+ return -1;
+ }
+
+ insert_pt = pmenu_grow(menu, 1);
+ pmenu_item_insert(menu, dev_hdr, insert_pt);
+ pb_log("Added header for encrypted device %s\n", dev->id);
+
+ selected = current_item(menu->ncm);
+ menu_format(menu->ncm, &rows, &cols);
+
+ /* Re-attach the items array. */
+ result = set_menu_items(menu->ncm, menu->items);
+
+ if (result)
+ pb_log_fn("set_menu_items failed: %d\n", result);
+
+ if (!item_visible(selected)) {
+ int idx, top;
+
+ top = top_row(menu->ncm);
+ idx = item_index(selected);
+
+ /* If our index is above the current top row, align
+ * us to the new top. Otherwise, align us to the new
+ * bottom */
+ top = top < idx ? idx - rows + 1 : idx;
+
+ set_top_row(menu->ncm, top);
+ set_current_item(menu->ncm, selected);
+ }
+
+ if (cui->current == &menu->scr)
+ nc_scr_post(cui->current);
+
+ return 0;
+}
+
+/**
* cui_device_remove - Client device remove callback.
*
* Removes all the menu_items for the device from the main menu and redraws the
@@ -1482,6 +1633,12 @@ int cui_send_set_password(struct cui *cui, char *password, char *new_password)
new_password);
}
+int cui_send_open_luks_device(struct cui *cui, char *password, char *device_id)
+{
+ return discover_client_send_open_luks_device(cui->client, password,
+ device_id);
+}
+
void cui_send_reinit(struct cui *cui)
{
discover_client_send_reinit(cui->client);
@@ -1629,7 +1786,7 @@ fail_setup:
}
static struct discover_client_ops cui_client_ops = {
- .device_add = NULL,
+ .device_add = cui_device_add,
.boot_option_add = cui_boot_option_add,
.device_remove = cui_device_remove,
.plugin_option_add = cui_plugin_option_add,
diff --git a/ui/ncurses/nc-cui.h b/ui/ncurses/nc-cui.h
index 8fa27aa..039aa92 100644
--- a/ui/ncurses/nc-cui.h
+++ b/ui/ncurses/nc-cui.h
@@ -101,11 +101,14 @@ void cui_show_plugin(struct pmenu_item *item);
void cui_show_plugin_menu(struct cui *cui);
void cui_show_auth(struct cui *cui, WINDOW *parent, bool set_password,
void (*callback)(struct nc_scr *));
+void cui_show_open_luks(struct cui *cui, WINDOW *parent,
+ const struct device *dev);
int cui_send_config(struct cui *cui, struct config *config);
int cui_send_url(struct cui *cui, char *url);
int cui_send_plugin_install(struct cui *cui, char *file);
int cui_send_authenticate(struct cui *cui, char *password);
int cui_send_set_password(struct cui *cui, char *password, char *new_password);
+int cui_send_open_luks_device(struct cui *cui, char *password, char *device_id);
void cui_send_reinit(struct cui *cui);
/* convenience routines */
OpenPOWER on IntegriCloud