welcome now puts credentials instead of generating

This commit is contained in:
Elia Zammuto
2021-07-30 16:06:59 +02:00
parent 28fecbc50c
commit 7f643345ce
6 changed files with 83 additions and 84 deletions

View File

@ -87,8 +87,8 @@ sunshine needs access to uinput to create mouse and gamepad events:
- When Moonlight request you insert the correct pin on sunshine: - When Moonlight request you insert the correct pin on sunshine:
- Type in the URL bar of your browser: `https://xxx.xxx.xxx.xxx:47990` where `xxx.xxx.xxx.xxx` is the IP address of your computer - Type in the URL bar of your browser: `https://xxx.xxx.xxx.xxx:47990` where `xxx.xxx.xxx.xxx` is the IP address of your computer
- Ignore any warning given by your browser about "insecure website" - Ignore any warning given by your browser about "insecure website"
- You should see a page containing both a new username and a password, needed to login into the next step - You should compile the next page with a new username and a password, needed to login into the next step
- Press "login" and log in using the credentials given above - Press "Save" and log in using the credentials given above
- Go to "PIN" in the Header - Go to "PIN" in the Header
- Type in your PIN and press Enter, you should get a Success Message - Type in your PIN and press Enter, you should get a Success Message
- Click on one of the Applications listed - Click on one of the Applications listed

View File

@ -6,25 +6,64 @@
</div> </div>
</div> </div>
<div class="alert alert-warning">These Credentials down below are needed to access the rest of the application.<br> Keep them safe, since <b>you will never see them again!</b></div> <div class="alert alert-warning">These Credentials down below are needed to access the rest of the application.<br> Keep them safe, since <b>you will never see them again!</b></div>
<div class="card p-4" style="width: 100%;"> <form @submit.prevent="save" class="card p-4" style="width: 100%;">
<div class="mb-2"> <div class="mb-2">
<label for="" class="form-label">Username: </label> <label for="" class="form-label">Username: </label>
<input type="text" class="form-control" disabled id="username"> <input type="text" class="form-control" v-model="passwordData.newUsername">
</div> </div>
<div class="mb-2"> <div class="mb-2">
<label for="" class="form-label">Password: </label> <label for="" class="form-label">Password: </label>
<input type="text" class="form-control" disabled id="password"> <input type="password" class="form-control" v-model="passwordData.newPassword">
</div> </div>
<a href="/" class="mb-2 btn btn-primary" style="margin: 1em auto;">Login</a> <div class="mb-2">
<label for="" class="form-label">Password: </label>
<input type="password" class="form-control" v-model="passwordData.confirmNewPassword">
</div> </div>
<button class="mb-2 btn btn-primary" style="margin: 1em auto;">Login</button>
<div class="alert alert-danger" v-if="error"><b>Error: </b>{{error}}</div>
<div class="alert alert-success" v-if="success"><b>Success! </b>This page will reload soon, your browser will ask you for the new credentials</div>
</form>
</div> </div>
</main> </main>
<script> <script>
fetch("/api/setup/password").then(r => r.json()).then(r => { new Vue({
if(r.status === "true"){ el: '#app',
document.querySelector("#username").value = r.username; data() {
document.querySelector("#password").value = r.password; return {
error: null,
success: false,
passwordData: {
newUsername: 'sunshine',
newPassword: '',
confirmNewPassword: ''
}
}
},
methods: {
save() {
this.error = null;
fetch("/api/password", {
method: "POST",
body: JSON.stringify(this.passwordData)
}).then((r) => {
if (r.status == 200){
r.json().then((rj) => {
if(rj.status.toString() === "true"){
this.success = true;
setTimeout(()=>{
document.location.reload();
},5000);
} else {
this.error = rj.error;
}
})
}
else {
this.error = "Internal Server Error"
}
});
}
} }
}) })
</script> </script>

View File

@ -230,8 +230,6 @@ sunshine_t sunshine {
SUNSHINE_CONFIG_DIR "/sunshine.conf", // config file SUNSHINE_CONFIG_DIR "/sunshine.conf", // config file
{}, // cmd args {}, // cmd args
47989, 47989,
false, // show credentials,
""
}; };
bool endline(char ch) { bool endline(char ch) {

View File

@ -109,9 +109,6 @@ struct sunshine_t {
} cmd; } cmd;
std::uint16_t port; std::uint16_t port;
bool showCredentials;
std::string plainPassword;
}; };
extern video_t video; extern video_t video;

View File

@ -92,17 +92,16 @@ bool authenticate(resp_https_t response, req_https_t request) {
return false; return false;
} }
//If credentials are shown, redirect the user to a /welcome page
if(config::sunshine.username.empty()){
send_redirect(response,request,"/welcome");
return false;
}
auto fg = util::fail_guard([&]() { auto fg = util::fail_guard([&]() {
send_unauthorized(response, request); send_unauthorized(response, request);
}); });
//If credentials are shown, redirect the user to a /welcome page
if(config::sunshine.showCredentials){
send_redirect(response,request,"/welcome");
fg.disable();
return false;
}
auto auth = request->header.find("authorization"); auto auth = request->header.find("authorization");
if(auth == request->header.end()) { if(auth == request->header.end()) {
return false; return false;
@ -203,7 +202,7 @@ void getPasswordPage(resp_https_t response, req_https_t request) {
void getWelcomePage(resp_https_t response, req_https_t request) { void getWelcomePage(resp_https_t response, req_https_t request) {
print_req(request); print_req(request);
if(!config::sunshine.showCredentials){ if(!config::sunshine.username.empty()){
send_redirect(response,request,"/"); send_redirect(response,request,"/");
return; return;
} }
@ -362,29 +361,6 @@ void getConfig(resp_https_t response, req_https_t request) {
} }
} }
void getPlainPassword(resp_https_t response, req_https_t request) {
print_req(request);
pt::ptree outputTree;
auto g = util::fail_guard([&]() {
std::ostringstream data;
pt::write_json(data, outputTree);
response->write(data.str());
});
if(config::sunshine.showCredentials){
outputTree.put("status", "true");
outputTree.put("username", config::sunshine.username);
outputTree.put("password", config::sunshine.plainPassword);
config::sunshine.showCredentials = false;
config::sunshine.plainPassword = "";
} else {
outputTree.put("status", "false");
}
}
void saveConfig(resp_https_t response, req_https_t request) { void saveConfig(resp_https_t response, req_https_t request) {
if(!authenticate(response, request)) return; if(!authenticate(response, request)) return;
@ -421,7 +397,7 @@ void saveConfig(resp_https_t response, req_https_t request) {
} }
void savePassword(resp_https_t response, req_https_t request) { void savePassword(resp_https_t response, req_https_t request) {
if(!authenticate(response, request)) return; if(!config::sunshine.username.empty() && !authenticate(response, request)) return;
print_req(request); print_req(request);
@ -440,29 +416,33 @@ void savePassword(resp_https_t response, req_https_t request) {
try { try {
//TODO: Input Validation //TODO: Input Validation
pt::read_json(ss, inputTree); pt::read_json(ss, inputTree);
auto username = inputTree.get<std::string>("currentUsername"); auto username = inputTree.count("currentUsername") > 0 ? inputTree.get<std::string>("currentUsername") : "";
auto newUsername = inputTree.get<std::string>("newUsername"); auto newUsername = inputTree.get<std::string>("newUsername");
auto password = inputTree.get<std::string>("currentPassword"); auto password = inputTree.count("currentPassword") > 0 ? inputTree.get<std::string>("currentPassword") : "";
auto newPassword = inputTree.get<std::string>("newPassword"); auto newPassword = inputTree.get<std::string>("newPassword");
auto confirmPassword = inputTree.get<std::string>("confirmNewPassword"); auto confirmPassword = inputTree.get<std::string>("confirmNewPassword");
if(newUsername.length() == 0) newUsername = username; if(newUsername.length() == 0) newUsername = username;
if(newUsername.length() == 0){
outputTree.put("status", false);
outputTree.put("error", "Invalid Username");
} else {
auto hash = util::hex(crypto::hash(password + config::sunshine.salt)).to_string(); auto hash = util::hex(crypto::hash(password + config::sunshine.salt)).to_string();
if(username == config::sunshine.username && hash == config::sunshine.password) { if(config::sunshine.username.empty() || (username == config::sunshine.username && hash == config::sunshine.password)) {
if(newPassword != confirmPassword) { if(newPassword != confirmPassword) {
outputTree.put("status", false); outputTree.put("status", false);
outputTree.put("error", "Password Mismatch"); outputTree.put("error", "Password Mismatch");
} } else {
http::save_user_creds(config::sunshine.credentials_file, newUsername, newPassword); 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);
} }
}
else { else {
outputTree.put("status", false); outputTree.put("status", false);
outputTree.put("error", "Invalid Current Credentials"); outputTree.put("error", "Invalid Current Credentials");
} }
} }
}
catch(std::exception &e) { catch(std::exception &e) {
BOOST_LOG(warning) << "SavePassword: "sv << e.what(); BOOST_LOG(warning) << "SavePassword: "sv << e.what();
outputTree.put("status", false); outputTree.put("status", false);
@ -525,7 +505,6 @@ void start() {
server.resource["^/api/config$"]["POST"] = saveConfig; server.resource["^/api/config$"]["POST"] = saveConfig;
server.resource["^/api/password$"]["POST"] = savePassword; server.resource["^/api/password$"]["POST"] = savePassword;
server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp;
server.resource["^/api/setup/password$"]["GET"] = getPlainPassword;
server.config.reuse_address = true; server.config.reuse_address = true;
server.config.address = "0.0.0.0"s; server.config.address = "0.0.0.0"s;
server.config.port = port_https; server.config.port = port_https;

View File

@ -54,15 +54,11 @@ int init() {
return -1; return -1;
} }
} }
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), true)) { if(reload_user_creds(config::sunshine.credentials_file)) return -1;
return -1; } else {
BOOST_LOG(info) << "Open the Web UI to set your new username and password and getting started";
} }
}
if(reload_user_creds(config::sunshine.credentials_file)) {
return -1;
}
return 0; return 0;
} }
@ -92,16 +88,6 @@ 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) << "Password: "sv << password;
BOOST_LOG(info) << "Open the Web UI to see your new username and password";
//Save these two in memory to show user and password the first time Sunshine is started
config::sunshine.showCredentials = true;
config::sunshine.plainPassword = password;
}
return 0; return 0;
} }