🔥 add luks ui

This commit is contained in:
Vladislav Nepogodin 2022-01-09 04:41:43 +04:00
parent 03453a9c6f
commit c03df0c549
No known key found for this signature in database
GPG Key ID: B62C3D10C54D5DA9
6 changed files with 259 additions and 7 deletions

View File

@ -89,6 +89,7 @@ add_executable(${PROJECT_NAME}
src/utils.cpp src/utils.hpp
src/widgets.cpp src/widgets.hpp
src/follow_process_log.hpp src/follow_process_log.cpp
src/crypto.cpp src/crypto.hpp
src/tui.cpp src/tui.hpp
src/main.cpp
)

View File

@ -49,6 +49,7 @@ src_files = files(
'src/utils.cpp', 'src/utils.hpp',
'src/widgets.cpp', 'src/widgets.hpp',
'src/follow_process_log.cpp', 'src/follow_process_log.hpp',
'src/crypto.cpp', 'src/crypto.hpp',
'src/tui.cpp', 'src/tui.hpp',
'src/main.cpp',
)

240
src/crypto.cpp Normal file
View File

@ -0,0 +1,240 @@
#include "crypto.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "widgets.hpp"
/* clang-format off */
#include <ftxui/component/component.hpp> // for Renderer, Button
#include <ftxui/component/component_options.hpp> // for ButtonOption
#include <ftxui/component/screen_interactive.hpp> // for Component, ScreenI...
#include <ftxui/dom/elements.hpp> // for operator|, size
/* clang-format on */
using namespace ftxui;
#ifdef NDEVENV
#include "follow_process_log.hpp"
#endif
namespace tui {
static constexpr auto luks_menu_body = "Devices and volumes encrypted using dm_crypt cannot be accessed or\neven seen without being unlocked via a key or password.";
static constexpr auto luks_menu_body2 = "A seperate boot partition without encryption or logical volume management\n(LVM - unless using BIOS Grub) is required.";
static constexpr auto luks_menu_body3 = "The Automatic option uses default encryption settings,\nand is recommended for beginners.\nOtherwise, it is possible to specify cypher and key size parameters manually.";
bool select_crypt_partition(const std::string_view& text) noexcept {
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& partitions = std::get<std::vector<std::string>>(config_data["PARTITIONS"]);
auto screen = ScreenInteractive::Fullscreen();
std::int32_t selected{};
bool success{};
auto ok_callback = [&] {
const auto& src = partitions[static_cast<std::size_t>(selected)];
const auto& lines = utils::make_multiline(src, false, " ");
config_data["PARTITION"] = lines[0];
success = true;
screen.ExitLoopClosure()();
};
const auto& content = fmt::format("\n{}\n", text);
detail::menu_widget(partitions, ok_callback, &selected, &screen, content, {.text_size = size(HEIGHT, GREATER_THAN, 1)});
return success;
}
bool get_cryptname(std::string& cryptname) noexcept {
std::string value{"cryptroot"};
static constexpr auto luks_cryptname_body = "\nSpecify a name for the encrypted block device.\n \nIt is not necessary to prefix it with /dev/mapper/.\nAn example has been provided.\n";
if (!detail::inputbox_widget(value, luks_cryptname_body, size(HEIGHT, GREATER_THAN, 4))) {
return false;
}
cryptname = value;
return true;
}
bool get_crypt_password(std::string& password) noexcept {
std::string value{};
static constexpr auto luks_pass_body = "\nEnter a password to un/encrypt the partition.\n \nThis should not be the same as\nthe Root account or user account passwords.\n";
if (!detail::inputbox_widget(value, luks_pass_body, size(HEIGHT, GREATER_THAN, 4))) {
return false;
}
password = value;
return true;
}
bool luks_open() noexcept {
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
config_data["LUKS_ROOT_NAME"] = "";
config_data["INCLUDE_PART"] = "part\\|crypt\\|lvm";
utils::umount_partitions();
utils::find_partitions();
// Filter out partitions that don't contain crypt device
const auto& ignore_part = utils::list_non_crypt();
/* const auto& parts = utils::make_multiline(ignore_part);
for (const auto& part : parts) {
utils::delete_partition_in_list(part);
}*/
// stop if no encrypted partition found
const auto& partitions = std::get<std::vector<std::string>>(config_data["PARTITIONS"]);
if (partitions.empty()) {
detail::msgbox_widget("\nNo LUKS-encrypted partition found.\n");
return false;
}
// Select encrypted partition to open
/* clang-format off */
if (!tui::select_crypt_partition(luks_menu_body)) { return false; }
/* clang-format on */
// Enter name of the Luks partition and get password to open it
const auto& partition = std::get<std::string>(config_data["PARTITION"]);
auto& luks_root_name = std::get<std::string>(config_data["LUKS_ROOT_NAME"]);
auto& luks_password = std::get<std::string>(config_data["PASSWD"]);
/* clang-format off */
if (!tui::get_cryptname(luks_root_name)) { return false; }
if (!tui::get_crypt_password(luks_password)) { return false; }
/* clang-format on */
spdlog::info("partition: {}, luks_root_name: {}, luks_password: {}", partition, luks_root_name, luks_password);
// Try to open the luks partition with the credentials given. If successful show this, otherwise
// show the error
detail::infobox_widget("\nPlease wait...\n");
#ifdef NDEVENV
detail::follow_process_log_widget({"/bin/sh", "-c", fmt::format("echo \"{}\" | cryptsetup open --type luks {} {}", luks_password, partition, luks_root_name)});
#endif
const auto& devlist = utils::exec(fmt::format("lsblk -o NAME,TYPE,FSTYPE,SIZE,MOUNTPOINT {} | grep \"crypt\\|NAME\\|MODEL\\|TYPE\\|FSTYPE\\|SIZE\"", partition));
detail::msgbox_widget(devlist);
return true;
}
bool luks_setup() noexcept {
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
#ifdef NDEVENV
utils::exec("modprobe -a dm-mod dm_crypt");
#endif
config_data["INCLUDE_PART"] = "part\\|lvm";
utils::umount_partitions();
utils::find_partitions();
// Select partition to encrypt
/* clang-format off */
static constexpr auto luks_encrypt_body = "Select a partition to encrypt.";
if (!tui::select_crypt_partition(luks_encrypt_body)) { return false; }
/* clang-format on */
// Enter name of the Luks partition and get password to create it
auto& luks_root_name = std::get<std::string>(config_data["LUKS_ROOT_NAME"]);
auto& luks_password = std::get<std::string>(config_data["PASSWD"]);
/* clang-format off */
if (!tui::get_cryptname(luks_root_name)) { return false; }
if (!tui::get_crypt_password(luks_password)) { return false; }
/* clang-format on */
return true;
}
void luks_encrypt([[maybe_unused]] const std::string_view& command) noexcept {
// Encrypt selected partition or LV with credentials given
detail::infobox_widget("\nPlease wait...\n");
std::this_thread::sleep_for(std::chrono::seconds(2));
#ifdef NDEVENV
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& partition = std::get<std::string>(config_data["PARTITION"]);
const auto& luks_root_name = std::get<std::string>(config_data["LUKS_ROOT_NAME"]);
const auto& luks_password = std::get<std::string>(config_data["PASSWD"]);
detail::follow_process_log_widget({"/bin/sh", "-c", fmt::format("echo \"{}\" | cryptsetup -q {} {}", luks_password, command, partition)});
// Now open the encrypted partition or LV
detail::follow_process_log_widget({"/bin/sh", "-c", fmt::format("echo \"{}\" | cryptsetup open {} {}", luks_password, partition, luks_root_name)});
#endif
}
void luks_default() noexcept {
tui::luks_encrypt("--type luks1 luksFormat");
}
bool luks_key_define() noexcept {
std::string value{"-s 512 -c aes-xts-plain64"};
static constexpr auto luks_cipher_key = "\nOnce the specified flags have been amended,\nthey will automatically be used with the 'cryptsetup -q luksFormat /dev/...' command.\n \nNOTE: Key files are not supported;\nthey can be added manually post-installation.\nDo not specify any additional flags such as -v (--verbose) or -y (--verify-passphrase).";
if (!detail::inputbox_widget(value, luks_cipher_key, size(HEIGHT, GREATER_THAN, 4))) {
return false;
}
tui::luks_encrypt(value);
return true;
}
void luks_express() noexcept {
tui::luks_encrypt("--pbkdf-force-iterations 200000 --type luks1 luksFormat");
}
void luks_show() noexcept {
static constexpr auto luks_success = "Done! Opened and ready for LVM (recommended) or direct mounting.";
const auto& lsblk = utils::exec("lsblk -o NAME,TYPE,FSTYPE,SIZE | grep \"part\\|crypt\\|NAME\\|TYPE\\|FSTYPE\\|SIZE\"");
const auto& content = fmt::format("\n{}\n \n{}", luks_success, lsblk);
detail::msgbox_widget(content, size(HEIGHT, GREATER_THAN, 5));
}
void luks_menu_advanced() noexcept {
const std::vector<std::string> menu_entries = {
"Open Encrypted Partition",
"Automatic LUKS Encryption",
"Define Key-Size and Cypher",
"Express LUKS",
"Back",
};
auto screen = ScreenInteractive::Fullscreen();
bool success{};
std::int32_t selected{};
auto ok_callback = [&] {
success = true;
screen.ExitLoopClosure()();
};
const auto& content = fmt::format("\n{}\n \n{}\n \n{}\n", luks_menu_body, luks_menu_body2, luks_menu_body3);
detail::menu_widget(menu_entries, ok_callback, &selected, &screen, content);
/* clang-format off */
if (!success) { return; }
switch (selected) {
case 0:
tui::luks_open();
break;
case 1: {
if (!tui::luks_setup()) { return; }
tui::luks_default();
tui::luks_show();
break;
}
case 2: {
if (!tui::luks_setup() && !tui::luks_key_define()) { return; }
tui::luks_show();
break;
}
case 3: {
if (!tui::luks_setup()) { return; }
tui::luks_express();
tui::luks_show();
break;
}
}
/* clang-format on */
}
} // namespace tui

8
src/crypto.hpp Normal file
View File

@ -0,0 +1,8 @@
#ifndef CRYPTO_HPP
#define CRYPTO_HPP
namespace tui {
void luks_menu_advanced() noexcept;
} // namespace tui
#endif // CRYPTO_HPP

View File

@ -1,5 +1,6 @@
#include "tui.hpp"
#include "config.hpp"
#include "crypto.hpp"
#include "definitions.hpp"
#include "utils.hpp"
#include "widgets.hpp"
@ -726,7 +727,7 @@ void install_base() noexcept {
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
const std::vector<std::string> available_kernels{"linux-cachyos", "linux", "linux-zen", "linux-lts", "linux-cachyos-cacule", "linux-cachyos-cacule-rdb", "linux-cachyos-bmq", "linux-cachyos-pds", "linux-cachyos-baby", "linux-cachyos-cacule-lts"};
const std::vector<std::string> available_kernels{"linux-cachyos", "linux", "linux-zen", "linux-lts", "linux-cachyos-cacule", "linux-cachyos-bmq", "linux-cachyos-pds", "linux-cachyos-tt", "linux-cachyos-bore"};
// Create the base list of packages
std::vector<std::string> install_packages{};
@ -771,7 +772,7 @@ void install_base() noexcept {
const auto& pkg = pkg_list[i];
pkg_list.emplace_back(fmt::format("{}-headers", pkg));
}
pkg_list.insert(pkg_list.cend(), {"base", "base-devel", "cachyos-keyring", "cachyos-mirrorlist", "cachyos-v3-mirrorlist"});
pkg_list.insert(pkg_list.cend(), {"base", "base-devel", "cachyos-keyring", "cachyos-mirrorlist", "cachyos-v3-mirrorlist", "cachyos-hello", "cachyos-hooks", "cachyos-settings", "cachyos-rate-mirrors", "cachy-browser"});
packages = utils::make_multiline(pkg_list, false, " ");
spdlog::info(fmt::format("Preparing for pkgs to install: \"{}\"", packages));
@ -848,7 +849,7 @@ void install_desktop() noexcept {
/* clang-format off */
static constexpr std::array to_be_inserted{"plasma-desktop", "plasma-framework", "plasma-nm", "plasma-pa", "plasma-workspace",
"konsole", "kate", "dolphin", "sddm", "sddm-kcm", "plasma", "plasma-wayland-protocols", "plasma-wayland-session",
"gamemode", "lib32-gamemode", "ksysguard", "pamac-aur", "openssh", "htop"};
"gamemode", "lib32-gamemode", "ksysguard", "pamac-aur", "openssh", "btop"};
/* clang-format on */
pkg_list.insert(pkg_list.end(), std::move_iterator(to_be_inserted.begin()),
std::move_iterator(to_be_inserted.end()));
@ -1997,7 +1998,6 @@ void prep_menu() noexcept {
case 1:
tui::show_devices();
break;
case 2: {
utils::umount_partitions();
if (tui::select_device()) {
@ -2005,12 +2005,14 @@ void prep_menu() noexcept {
}
break;
}
case 5:
tui::luks_menu_advanced();
break;
case 7:
tui::mount_partitions();
break;
case 3:
case 4:
case 5:
case 6:
case 8:
case 9:

View File

@ -189,7 +189,7 @@ void infobox_widget(const std::string_view& content, Decorator boxsize) noexcept
Dimension::Full() // Height
);
auto element = centered_widget_nocontrols("New CLI Installer", multiline_text(utils::make_multiline(content.data())) | vcenter | boxsize);
auto element = centered_widget_nocontrols("New CLI Installer", multiline_text(utils::make_multiline(content)) | vcenter | boxsize);
Render(screen, element);
screen.Print();
}
@ -214,7 +214,7 @@ bool yesno_widget(const std::string_view& content, Decorator boxsize) noexcept {
});
auto renderer = Renderer(container, [&] {
return centered_widget(container, "New CLI Installer", multiline_text(utils::make_multiline(content.data())) | hcenter | boxsize);
return centered_widget(container, "New CLI Installer", multiline_text(utils::make_multiline(content)) | hcenter | boxsize);
});
screen.Loop(renderer);