mirror of
https://github.com/CachyOS/New-Cli-Installer.git
synced 2025-01-23 14:32:22 +08:00
🔥 add luks ui
This commit is contained in:
parent
03453a9c6f
commit
c03df0c549
@ -89,6 +89,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
src/utils.cpp src/utils.hpp
|
src/utils.cpp src/utils.hpp
|
||||||
src/widgets.cpp src/widgets.hpp
|
src/widgets.cpp src/widgets.hpp
|
||||||
src/follow_process_log.hpp src/follow_process_log.cpp
|
src/follow_process_log.hpp src/follow_process_log.cpp
|
||||||
|
src/crypto.cpp src/crypto.hpp
|
||||||
src/tui.cpp src/tui.hpp
|
src/tui.cpp src/tui.hpp
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
)
|
)
|
||||||
|
@ -49,6 +49,7 @@ src_files = files(
|
|||||||
'src/utils.cpp', 'src/utils.hpp',
|
'src/utils.cpp', 'src/utils.hpp',
|
||||||
'src/widgets.cpp', 'src/widgets.hpp',
|
'src/widgets.cpp', 'src/widgets.hpp',
|
||||||
'src/follow_process_log.cpp', 'src/follow_process_log.hpp',
|
'src/follow_process_log.cpp', 'src/follow_process_log.hpp',
|
||||||
|
'src/crypto.cpp', 'src/crypto.hpp',
|
||||||
'src/tui.cpp', 'src/tui.hpp',
|
'src/tui.cpp', 'src/tui.hpp',
|
||||||
'src/main.cpp',
|
'src/main.cpp',
|
||||||
)
|
)
|
||||||
|
240
src/crypto.cpp
Normal file
240
src/crypto.cpp
Normal 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
8
src/crypto.hpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef CRYPTO_HPP
|
||||||
|
#define CRYPTO_HPP
|
||||||
|
|
||||||
|
namespace tui {
|
||||||
|
void luks_menu_advanced() noexcept;
|
||||||
|
} // namespace tui
|
||||||
|
|
||||||
|
#endif // CRYPTO_HPP
|
12
src/tui.cpp
12
src/tui.cpp
@ -1,5 +1,6 @@
|
|||||||
#include "tui.hpp"
|
#include "tui.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
#include "crypto.hpp"
|
||||||
#include "definitions.hpp"
|
#include "definitions.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
#include "widgets.hpp"
|
#include "widgets.hpp"
|
||||||
@ -726,7 +727,7 @@ void install_base() noexcept {
|
|||||||
auto* config_instance = Config::instance();
|
auto* config_instance = Config::instance();
|
||||||
auto& config_data = config_instance->data();
|
auto& config_data = config_instance->data();
|
||||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
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
|
// Create the base list of packages
|
||||||
std::vector<std::string> install_packages{};
|
std::vector<std::string> install_packages{};
|
||||||
@ -771,7 +772,7 @@ void install_base() noexcept {
|
|||||||
const auto& pkg = pkg_list[i];
|
const auto& pkg = pkg_list[i];
|
||||||
pkg_list.emplace_back(fmt::format("{}-headers", pkg));
|
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, " ");
|
packages = utils::make_multiline(pkg_list, false, " ");
|
||||||
|
|
||||||
spdlog::info(fmt::format("Preparing for pkgs to install: \"{}\"", packages));
|
spdlog::info(fmt::format("Preparing for pkgs to install: \"{}\"", packages));
|
||||||
@ -848,7 +849,7 @@ void install_desktop() noexcept {
|
|||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
static constexpr std::array to_be_inserted{"plasma-desktop", "plasma-framework", "plasma-nm", "plasma-pa", "plasma-workspace",
|
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",
|
"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 */
|
/* clang-format on */
|
||||||
pkg_list.insert(pkg_list.end(), std::move_iterator(to_be_inserted.begin()),
|
pkg_list.insert(pkg_list.end(), std::move_iterator(to_be_inserted.begin()),
|
||||||
std::move_iterator(to_be_inserted.end()));
|
std::move_iterator(to_be_inserted.end()));
|
||||||
@ -1997,7 +1998,6 @@ void prep_menu() noexcept {
|
|||||||
case 1:
|
case 1:
|
||||||
tui::show_devices();
|
tui::show_devices();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: {
|
case 2: {
|
||||||
utils::umount_partitions();
|
utils::umount_partitions();
|
||||||
if (tui::select_device()) {
|
if (tui::select_device()) {
|
||||||
@ -2005,12 +2005,14 @@ void prep_menu() noexcept {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 5:
|
||||||
|
tui::luks_menu_advanced();
|
||||||
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
tui::mount_partitions();
|
tui::mount_partitions();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
case 5:
|
|
||||||
case 6:
|
case 6:
|
||||||
case 8:
|
case 8:
|
||||||
case 9:
|
case 9:
|
||||||
|
@ -189,7 +189,7 @@ void infobox_widget(const std::string_view& content, Decorator boxsize) noexcept
|
|||||||
Dimension::Full() // Height
|
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);
|
Render(screen, element);
|
||||||
screen.Print();
|
screen.Print();
|
||||||
}
|
}
|
||||||
@ -214,7 +214,7 @@ bool yesno_widget(const std::string_view& content, Decorator boxsize) noexcept {
|
|||||||
});
|
});
|
||||||
|
|
||||||
auto renderer = Renderer(container, [&] {
|
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);
|
screen.Loop(renderer);
|
||||||
|
Loading…
Reference in New Issue
Block a user