From patchwork Fri Feb 15 00:36:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Mendoza-Jonas X-Patchwork-Id: 1042545 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 440vV024Xgz9s5c for ; Fri, 15 Feb 2019 11:37:12 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="aHcJRp9D"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="YvEwIDZ0"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 440vV008g4zDqXW for ; Fri, 15 Feb 2019 11:37:12 +1100 (AEDT) X-Original-To: petitboot@lists.ozlabs.org Delivered-To: petitboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=mendozajonas.com (client-ip=66.111.4.26; helo=out2-smtp.messagingengine.com; envelope-from=sam@mendozajonas.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="aHcJRp9D"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="YvEwIDZ0"; dkim-atps=neutral Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 440vTH4nF4zDqVf for ; Fri, 15 Feb 2019 11:36:35 +1100 (AEDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id D200122710; Thu, 14 Feb 2019 19:36:31 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Thu, 14 Feb 2019 19:36:31 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= mendozajonas.com; h=from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; s=fm2; bh=9Dq8QNbOBf8EaZy4sSNDCusnIHBw9JNrUP/0IuvgA0Y=; b=aHcJR p9Dz5WDJjk/wl04IwQADjyGssruljUR9CgDSi0+thhpfXDozax5AAOW/CG8mySNX /Q4nRYRU1G7CPNA8kgHRvmoz7D75r/zjt4nNyEIRdyCeS5Z5K3/rVugWzNQbZ8uU +DjoGONokixISMLaYCNI2OtTvnv1F3/vFhDzeyr7CF8YZ0XODRWayF44cWt7dNkx EVMa6chE8dHo48gD/tsROqv1bUF99p9P52hYXToUgTNKFDGlf+vq2MpHX6ghE0fD /CRGQEq27q4i/aaqyxyQ6933QU9eVekZnnnKK2XSd8OsrUsGXnsAO+CCaosxJ0Fh I6kvbIcP2ZbXRNH2A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=9Dq8QNbOBf8EaZy4sSNDCusnIHBw9JNrUP/0IuvgA0Y=; b=YvEwIDZ0 GbbuQpGLnO6OhI8OyRRHZAyoTmdD1HnxuUydPGaTh4D7ZYJxdG+OiuF1+AnbGTSF wS6ymIJU7nyqlec1rLbUfUG/EJ8ZLuixuHptbTPasd/NHO8nX0Hgoj+8Hj7LN8ZF VLLoKMWGSt2GJkXMeQjWdxc1wB2Rwch7pKtGiesHIW/hLACXknFmr6R4xm/AP1tH 0dSQguIoNwhDIwY0axE6yKjaDv0JQW9HYz59FwrbVtSKWxm47Q37VmV9QX0Bnso4 6cY60KXyOYnCgQ/U6EvQsiWwCawwunKKRSIzyKPI9+/ZPqoovRnuLO51qu75pqnr 66BEVDEQoe9fcA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtledruddtiedgvdduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfquhhtnecuuegrihhlohhuthemucef tddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpe furghmuhgvlhcuofgvnhguohiirgdqlfhonhgrshcuoehsrghmsehmvghnughoiigrjhho nhgrshdrtghomheqnecukfhppeduvddvrdelledrkedvrddutdenucfrrghrrghmpehmrg hilhhfrhhomhepshgrmhesmhgvnhguohiirghjohhnrghsrdgtohhmnecuvehluhhsthgv rhfuihiivgepfe X-ME-Proxy: Received: from v4.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id 02757E4046; Thu, 14 Feb 2019 19:36:29 -0500 (EST) From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [PATCH 5/5] ui/ncurses: Add prompt for LUKS device password Date: Fri, 15 Feb 2019 11:36:03 +1100 Message-Id: <20190215003603.16285-6-sam@mendozajonas.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190215003603.16285-1-sam@mendozajonas.com> References: <20190215003603.16285-1-sam@mendozajonas.com> MIME-Version: 1.0 X-BeenThere: petitboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Petitboot bootloader development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Samuel Mendoza-Jonas Errors-To: petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Petitboot" 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 --- ui/common/discover-client.c | 25 ++++++ ui/common/discover-client.h | 3 + ui/ncurses/nc-auth.c | 30 ++++++- ui/ncurses/nc-auth.h | 1 + ui/ncurses/nc-cui.c | 166 +++++++++++++++++++++++++++++++++++- ui/ncurses/nc-cui.h | 3 + 6 files changed, 220 insertions(+), 8 deletions(-) diff --git a/ui/common/discover-client.c b/ui/common/discover-client.c index e7dfb831..6dda2d32 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 9b56dcb7..183d1935 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 5bfda8b4..227c57bf 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 e8e41482..0473c922 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 d80e2c3e..ae5e9bc6 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. @@ -1080,6 +1124,114 @@ static int cui_boot_option_add(struct device *dev, struct boot_option *opt, return 0; } +/** + * 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. * @@ -1482,6 +1634,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 +1787,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 8fa27aa7..039aa922 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 */