generate user credentials based on command line iuput

This commit is contained in:
loki
2021-06-09 21:55:13 +02:00
parent 33fbd5f431
commit 1afd1b7c94
7 changed files with 98 additions and 34 deletions
+13 -21
View File
@@ -215,7 +215,9 @@ sunshine_t sunshine {
{}, // User file {}, // User file
{}, // Username {}, // Username
{}, // Password {}, // Password
{} //Password Salt {}, // Password Salt
SUNSHINE_ASSETS_DIR "/sunshine.conf", // config file
{} // cmd args
}; };
bool endline(char ch) { bool endline(char ch) {
@@ -500,19 +502,6 @@ void list_int_f(std::unordered_map<std::string, std::string> &vars, const std::s
} }
} }
void print_help(const char *name) {
std::cout
<< "Usage: "sv << name << " [options] [/path/to/configuration_file]"sv << std::endl
<< " Any configurable option can be overwritten with: \"name=value\""sv << std::endl
<< std::endl
<< " --help | print help"sv << std::endl
<< std::endl
<< " flags"sv << std::endl
<< " -0 | Read PIN from stdin"sv << std::endl
<< " -1 | Do not load previously saved state and do retain any state after shutdown"sv << std::endl
<< " | Effectively starting as if for the first time without overwriting any pairings with your devices"sv;
}
int apply_flags(const char *line) { int apply_flags(const char *line) {
int ret = 0; int ret = 0;
while(*line != '\0') { while(*line != '\0') {
@@ -651,11 +640,9 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
} }
int parse(int argc, char *argv[]) { int parse(int argc, char *argv[]) {
const char *config_file = SUNSHINE_ASSETS_DIR "/sunshine.conf";
std::unordered_map<std::string, std::string> cmd_vars; std::unordered_map<std::string, std::string> cmd_vars;
for(auto x = argc - 1; x > 0; --x) { for(auto x = 1; x < argc; ++x) {
auto line = argv[x]; auto line = argv[x];
if(line == "--help"sv) { if(line == "--help"sv) {
@@ -663,6 +650,13 @@ int parse(int argc, char *argv[]) {
return 1; return 1;
} }
else if(*line == '-') { else if(*line == '-') {
if(*(line + 1) == '-') {
sunshine.cmd.name = line + 2;
sunshine.cmd.argc = argc - x - 1;
sunshine.cmd.argv = argv + x + 1;
break;
}
if(apply_flags(line + 1)) { if(apply_flags(line + 1)) {
print_help(*argv); print_help(*argv);
return -1; return -1;
@@ -673,7 +667,7 @@ int parse(int argc, char *argv[]) {
auto pos = std::find(line, line_end, '='); auto pos = std::find(line, line_end, '=');
if(pos == line_end) { if(pos == line_end) {
config_file = line; sunshine.config_file = line;
} }
else { else {
TUPLE_EL(var, 1, parse_option(line, line_end)); TUPLE_EL(var, 1, parse_option(line, line_end));
@@ -687,9 +681,7 @@ int parse(int argc, char *argv[]) {
} }
} }
sunshine.config_file = config_file; auto vars = parse_config(read_file(sunshine.config_file.c_str()));
auto vars = parse_config(read_file(config_file));
for(auto &[name, value] : cmd_vars) { for(auto &[name, value] : cmd_vars) {
vars.insert_or_assign(std::move(name), std::move(value)); vars.insert_or_assign(std::move(name), std::move(value));
+6
View File
@@ -96,6 +96,12 @@ struct sunshine_t {
std::string salt; std::string salt;
std::string config_file; std::string config_file;
struct cmd_t {
std::string name;
int argc;
char **argv;
} cmd;
}; };
extern video_t video; extern video_t video;
+1 -1
View File
@@ -405,7 +405,7 @@ void savePassword(resp_https_t response, req_https_t request) {
outputTree.put("error", "Password Mismatch"); outputTree.put("error", "Password Mismatch");
} }
http::save_user_creds(config::sunshine.credentials_file, newUsername, newPassword, crypto::rand_alphabet(16)); http::save_user_creds(config::sunshine.credentials_file, newUsername, newPassword);
http::reload_user_creds(config::sunshine.credentials_file); http::reload_user_creds(config::sunshine.credentials_file);
outputTree.put("status", true); outputTree.put("status", true);
} }
+7 -3
View File
@@ -53,7 +53,7 @@ void init(std::shared_ptr<safe::signal_t> shutdown_event) {
} }
} }
if(!user_creds_exist(config::sunshine.credentials_file)) { if(!user_creds_exist(config::sunshine.credentials_file)) {
if(save_user_creds(config::sunshine.credentials_file, "sunshine"s, crypto::rand_alphabet(16), crypto::rand_alphabet(16))) { if(save_user_creds(config::sunshine.credentials_file, "sunshine"s, crypto::rand_alphabet(16), true)) {
shutdown_event->raise(true); shutdown_event->raise(true);
return; return;
} }
@@ -64,7 +64,7 @@ void init(std::shared_ptr<safe::signal_t> shutdown_event) {
} }
} }
int save_user_creds(const std::string &file, const std::string &username, const std::string &password, const std::string &salt) { int save_user_creds(const std::string &file, const std::string &username, const std::string &password, bool run_our_mouth) {
pt::ptree outputTree; pt::ptree outputTree;
if(fs::exists(file)) { if(fs::exists(file)) {
@@ -77,7 +77,8 @@ int save_user_creds(const std::string &file, const std::string &username, const
} }
} }
outputTree.put("username", "sunshine"); auto salt = crypto::rand_alphabet(16);
outputTree.put("username", username);
outputTree.put("salt", salt); outputTree.put("salt", salt);
outputTree.put("password", util::hex(crypto::hash(password + salt)).to_string()); outputTree.put("password", util::hex(crypto::hash(password + salt)).to_string());
try { try {
@@ -89,8 +90,11 @@ int save_user_creds(const std::string &file, const std::string &username, const
} }
BOOST_LOG(info) << "New credentials have been created"sv; BOOST_LOG(info) << "New credentials have been created"sv;
if(run_our_mouth) {
BOOST_LOG(info) << "Username: "sv << username; BOOST_LOG(info) << "Username: "sv << username;
BOOST_LOG(info) << "Password: "sv << password; BOOST_LOG(info) << "Password: "sv << password;
}
return 0; return 0;
} }
+6 -1
View File
@@ -5,7 +5,12 @@ namespace http {
void init(std::shared_ptr<safe::signal_t> shutdown_event); void init(std::shared_ptr<safe::signal_t> shutdown_event);
int create_creds(const std::string &pkey, const std::string &cert); int create_creds(const std::string &pkey, const std::string &cert);
int save_user_creds(const std::string &file, const std::string &username, const std::string &password, const std::string &salt); int save_user_creds(
const std::string &file,
const std::string &username,
const std::string &password,
bool run_our_mouth = false);
int reload_user_creds(const std::string &file); int reload_user_creds(const std::string &file);
extern std::string unique_id; extern std::string unique_id;
extern net::net_e origin_pin_allowed; extern net::net_e origin_pin_allowed;
+56 -1
View File
@@ -6,9 +6,9 @@
#include <csignal> #include <csignal>
#include <filesystem> #include <filesystem>
#include <fstream>
#include <iostream> #include <iostream>
#include <thread> #include <thread>
#include <fstream>
#include <boost/log/attributes/clock.hpp> #include <boost/log/attributes/clock.hpp>
#include <boost/log/common.hpp> #include <boost/log/common.hpp>
@@ -52,6 +52,27 @@ struct NoDelete {
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int) BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int)
void print_help(const char *name) {
std::cout
<< "Usage: "sv << name << " [options] [/path/to/configuration_file] [--cmd]"sv << std::endl
<< " Any configurable option can be overwritten with: \"name=value\""sv << std::endl
<< std::endl
<< " --help | print help"sv << std::endl
<< " --creds username password | set user credentials for the Web manager" << std::endl
<< std::endl
<< " flags"sv << std::endl
<< " -0 | Read PIN from stdin"sv << std::endl
<< " -1 | Do not load previously saved state and do retain any state after shutdown"sv << std::endl
<< " | Effectively starting as if for the first time without overwriting any pairings with your devices"sv << std::endl;
}
namespace help {
int entry(const char *name, int argc, char *argv[]) {
print_help(name);
return 0;
}
} // namespace help
void log_flush() { void log_flush() {
sink->flush(); sink->flush();
} }
@@ -68,6 +89,24 @@ void on_signal(int sig, FN &&fn) {
std::signal(sig, on_signal_forwarder); std::signal(sig, on_signal_forwarder);
} }
namespace gen_creds {
int entry(const char *name, int argc, char *argv[]) {
if(argc < 2 || argv[0] == "help"sv || argv[1] == "help"sv) {
print_help(name);
return 0;
}
http::save_user_creds(config::sunshine.credentials_file, argv[0], argv[1]);
return 0;
}
} // namespace gen_creds
std::map<std::string_view, std::function<int(const char *name, int argc, char **argv)>> cmd_to_func {
{ "creds"sv, gen_creds::entry },
{ "help"sv, help::entry }
};
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if(config::parse(argc, argv)) { if(config::parse(argc, argv)) {
return 0; return 0;
@@ -123,6 +162,22 @@ int main(int argc, char *argv[]) {
bl::core::get()->add_sink(sink); bl::core::get()->add_sink(sink);
auto fg = util::fail_guard(log_flush); auto fg = util::fail_guard(log_flush);
if(!config::sunshine.cmd.name.empty()) {
auto fn = cmd_to_func.find(config::sunshine.cmd.name);
if(fn == std::end(cmd_to_func)) {
BOOST_LOG(fatal) << "Unknown command: "sv << config::sunshine.cmd.name;
BOOST_LOG(info) << "Possible commands:"sv;
for(auto &[key, _] : cmd_to_func) {
BOOST_LOG(info) << '\t' << key;
}
return 7;
}
return fn->second(argv[0], config::sunshine.cmd.argc, config::sunshine.cmd.argv);
}
// Create signal handler after logging has been initialized // Create signal handler after logging has been initialized
auto shutdown_event = std::make_shared<safe::event_t<bool>>(); auto shutdown_event = std::make_shared<safe::event_t<bool>>();
on_signal(SIGINT, [shutdown_event]() { on_signal(SIGINT, [shutdown_event]() {
+2
View File
@@ -20,6 +20,8 @@ extern boost::log::sources::severity_logger<int> fatal;
void log_flush(); void log_flush();
void print_help(const char *name);
std::string read_file(const char *path); std::string read_file(const char *path);
int write_file(const char *path, const std::string_view &contents); int write_file(const char *path, const std::string_view &contents);
#endif //SUNSHINE_MAIN_H #endif //SUNSHINE_MAIN_H