-
-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
auth: add hyprlock-setpwhash target for setting the password hash
- Loading branch information
1 parent
3f20cc2
commit 15a04ee
Showing
4 changed files
with
173 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
#include "../src/helpers/Log.hpp" | ||
|
||
#include <filesystem> | ||
#include <hyprutils/path/Path.hpp> | ||
#include <iostream> | ||
#include <fstream> | ||
#include <istream> | ||
#include <sodium.h> | ||
#include <string> | ||
#include <termios.h> | ||
#include <unistd.h> | ||
#include <print> | ||
|
||
using std::filesystem::perms; | ||
|
||
void setStdinEcho(bool enable = true) { | ||
struct termios tty; | ||
tcgetattr(STDIN_FILENO, &tty); | ||
if (!enable) | ||
tty.c_lflag &= ~ECHO; | ||
else | ||
tty.c_lflag |= ECHO; | ||
RASSERT(tcsetattr(STDIN_FILENO, TCSANOW, &tty) == 0, "Failed to set terminal attributes"); | ||
} | ||
|
||
// returns the first none-whitespace char | ||
int getChoice() { | ||
std::string input; | ||
std::getline(std::cin, input); | ||
const auto p = input.find_first_not_of(" \n"); | ||
return (p == std::string::npos) ? 0 : input[p]; | ||
} | ||
|
||
constexpr auto CHOOSELIMITSPROMPT = R"#( | ||
Choose how hard it will be to brute force your password. | ||
This also defines how long it will take to check the password. | ||
1 - interactive (low, pretty fast, but still above current owasp recomendations (12/2024)) | ||
2 - moderate (medium, takes below a second on most machines) | ||
3 - sensitive (high, takes around 2-4 seconds on most machines) | ||
Type 1, 2 or 3, or Enter for default (2): )#"; | ||
|
||
unsigned int getOpsLimit(int choice) { | ||
switch (choice) { | ||
case '1': return crypto_pwhash_OPSLIMIT_INTERACTIVE; | ||
case '2': return crypto_pwhash_OPSLIMIT_MODERATE; | ||
case '3': return crypto_pwhash_OPSLIMIT_SENSITIVE; | ||
default: return crypto_pwhash_OPSLIMIT_MODERATE; | ||
} | ||
std::unreachable(); | ||
} | ||
|
||
unsigned int getMemLimit(int choice) { | ||
switch (choice) { | ||
case '1': return crypto_pwhash_MEMLIMIT_INTERACTIVE; | ||
case '2': return crypto_pwhash_MEMLIMIT_MODERATE; | ||
case '3': return crypto_pwhash_MEMLIMIT_SENSITIVE; | ||
default: return crypto_pwhash_MEMLIMIT_MODERATE; | ||
} | ||
std::unreachable(); | ||
} | ||
|
||
void help() { | ||
std::println(R"#( | ||
Usage: hyprlock-setpwhash | ||
Interactive utility to set the password hash for hyprlock | ||
)#"); | ||
} | ||
|
||
int main(int argc, char** argv, char** envp) { | ||
std::vector<std::string> args(argv, argv + argc); | ||
|
||
RASSERT(sodium_init() >= 0, "Failed to initialize libsodium"); | ||
|
||
for (std::size_t i = 1; i < args.size(); ++i) { | ||
const std::string arg = argv[i]; | ||
|
||
if (arg == "--help" || arg == "-h") { | ||
help(); | ||
return 0; | ||
} else { | ||
std::cerr << "Unknown argument: " << arg << std::endl; | ||
help(); | ||
return 1; | ||
} | ||
} | ||
|
||
const auto [SECRETSCONF, DOTDIR] = Hyprutils::Path::findConfig("hyprlock_pwhash"); | ||
if (SECRETSCONF.has_value()) { | ||
// check permissions | ||
std::println("{} already exists.", SECRETSCONF.value()); | ||
std::print("Do you want to overwrite it? [y/N] "); | ||
const auto CHOICE = getChoice(); | ||
|
||
if (CHOICE != 'y' && CHOICE != 'Y') { | ||
std::println("Keeping existing secrets!"); | ||
|
||
const auto PERMS = std::filesystem::status(SECRETSCONF.value()).permissions(); | ||
if ((PERMS & perms::group_read) != perms::none || (PERMS & perms::group_write) != perms::none || (PERMS & perms::others_read) != perms::none || | ||
(PERMS & perms::others_write) != perms::none) { | ||
std::println("Setting permissions of {} to -rw-------", SECRETSCONF.value()); | ||
|
||
// set perms to -rw------- | ||
std::filesystem::permissions(SECRETSCONF.value(), perms::owner_read | perms::owner_write); | ||
} | ||
return 0; | ||
} | ||
} | ||
|
||
RASSERT(DOTDIR.has_value(), "Failed to find config directory!"); | ||
const auto DEST = DOTDIR.value() + "/hypr/hyprlock_pwhash.conf"; | ||
|
||
std::println(R"#(Note: We are going to write a password hash to {} | ||
If you choose a weak password and this hash gets leaked, | ||
someone might be able to guess your password using a password list or brute force. | ||
So best to keep it safe and (or) choose a good password.)#", | ||
DEST); | ||
|
||
std::print(CHOOSELIMITSPROMPT); | ||
const auto CHOICE = getChoice(); | ||
|
||
setStdinEcho(false); | ||
std::string pw = ""; | ||
while (true) { | ||
std::print("New password: "); | ||
std::getline(std::cin, pw); | ||
std::print("\r"); | ||
|
||
if (pw.empty()) { | ||
std::println("Empty password"); | ||
continue; | ||
} | ||
|
||
if (pw.size() < 4) { | ||
std::println("Less than 4 characters? Nope."); | ||
continue; | ||
} | ||
|
||
std::string pw2 = ""; | ||
std::print("Repeat password: "); | ||
std::getline(std::cin, pw2); | ||
std::print("\r"); | ||
|
||
if (pw != pw2) { | ||
std::println("Ups, passwords do not match"); | ||
continue; | ||
} | ||
|
||
break; | ||
} | ||
setStdinEcho(true); | ||
|
||
char hash[crypto_pwhash_STRBYTES]; | ||
if (crypto_pwhash_str(hash, pw.c_str(), pw.size(), getOpsLimit(CHOICE), getMemLimit(CHOICE)) != 0) { | ||
std::println("[Sodium] Failed to hash password"); | ||
return 1; | ||
} | ||
|
||
std::println("Writing password hash to {}", DEST); | ||
{ | ||
std::ofstream out(DEST); | ||
out << "pw_hash = " << hash << std::endl; | ||
} | ||
|
||
// set perms to -rw------- | ||
std::filesystem::permissions(DEST, perms::owner_read | perms::owner_write); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters