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

View File

@@ -210,12 +210,14 @@ input_t input {
};
sunshine_t sunshine {
2, // min_log_level
0, // flags
{}, //User file
{}, //Username
{}, //Password
{} //Password Salt
2, // min_log_level
0, // flags
{}, // User file
{}, // Username
{}, // Password
{}, // Password Salt
SUNSHINE_ASSETS_DIR "/sunshine.conf", // config file
{} // cmd args
};
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 ret = 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[]) {
const char *config_file = SUNSHINE_ASSETS_DIR "/sunshine.conf";
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];
if(line == "--help"sv) {
@@ -663,6 +650,13 @@ int parse(int argc, char *argv[]) {
return 1;
}
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)) {
print_help(*argv);
return -1;
@@ -673,7 +667,7 @@ int parse(int argc, char *argv[]) {
auto pos = std::find(line, line_end, '=');
if(pos == line_end) {
config_file = line;
sunshine.config_file = line;
}
else {
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(config_file));
auto vars = parse_config(read_file(sunshine.config_file.c_str()));
for(auto &[name, value] : cmd_vars) {
vars.insert_or_assign(std::move(name), std::move(value));

View File

@@ -96,6 +96,12 @@ struct sunshine_t {
std::string salt;
std::string config_file;
struct cmd_t {
std::string name;
int argc;
char **argv;
} cmd;
};
extern video_t video;

View File

@@ -405,7 +405,7 @@ void savePassword(resp_https_t response, req_https_t request) {
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);
outputTree.put("status", true);
}

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(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);
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;
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("password", util::hex(crypto::hash(password + salt)).to_string());
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) << "Username: "sv << username;
BOOST_LOG(info) << "Password: "sv << password;
if(run_our_mouth) {
BOOST_LOG(info) << "Username: "sv << username;
BOOST_LOG(info) << "Password: "sv << password;
}
return 0;
}

View File

@@ -5,7 +5,12 @@ namespace http {
void init(std::shared_ptr<safe::signal_t> shutdown_event);
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);
extern std::string unique_id;
extern net::net_e origin_pin_allowed;

View File

@@ -6,9 +6,9 @@
#include <csignal>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <thread>
#include <fstream>
#include <boost/log/attributes/clock.hpp>
#include <boost/log/common.hpp>
@@ -52,6 +52,27 @@ struct NoDelete {
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() {
sink->flush();
}
@@ -68,6 +89,24 @@ void on_signal(int sig, FN &&fn) {
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[]) {
if(config::parse(argc, argv)) {
return 0;
@@ -123,6 +162,22 @@ int main(int argc, char *argv[]) {
bl::core::get()->add_sink(sink);
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
auto shutdown_event = std::make_shared<safe::event_t<bool>>();
on_signal(SIGINT, [shutdown_event]() {

View File

@@ -20,6 +20,8 @@ extern boost::log::sources::severity_logger<int> fatal;
void log_flush();
void print_help(const char *name);
std::string read_file(const char *path);
int write_file(const char *path, const std::string_view &contents);
#endif //SUNSHINE_MAIN_H