mirror of
https://github.com/kunkundi/crossdesk-server.git
synced 2026-10-25 17:21:59 +08:00
[fix] synchronize authenticated password changes
This commit is contained in:
1 parent
174745a98b
commit
8bda471bbd
4 files changed
+134
-1
No files matched your search
@@ -70,11 +70,16 @@ bool SignalNegotiation::login_user(websocketpp::connection_hdl hdl,
|
||||
|
||||
// Check if AddDevice failed
|
||||
if (ret_host_id.empty()) {
|
||||
std::string reason = "Failed to register device";
|
||||
if (!host_id.empty() &&
|
||||
device_db_manager_->VerifyDevice(host_id, password) == -1) {
|
||||
reason = "Incorrect password";
|
||||
}
|
||||
LOG_ERROR("Failed to add device for host_id [{}]", host_id);
|
||||
json message = {{"type", "login"},
|
||||
{"user_id", ""},
|
||||
{"status", "fail"},
|
||||
{"reason", "Failed to register device"}};
|
||||
{"reason", reason}};
|
||||
send_msg_(hdl, message);
|
||||
return true;
|
||||
}
|
||||
@@ -426,6 +431,49 @@ bool SignalNegotiation::new_candidate_mid(websocketpp::connection_hdl hdl,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SignalNegotiation::change_password(websocketpp::connection_hdl hdl,
|
||||
const json& j) {
|
||||
json message = {{"type", "change_password"}};
|
||||
std::string request_id;
|
||||
if (!GetStringField(j, "request_id", request_id) || request_id.empty()) {
|
||||
message["status"] = "fail";
|
||||
message["reason"] = "Missing or invalid request ID";
|
||||
send_msg_(hdl, message);
|
||||
return true;
|
||||
}
|
||||
message["request_id"] = request_id;
|
||||
|
||||
const std::string user_id = transmission_manager_->GetUserId(hdl);
|
||||
message["user_id"] = user_id;
|
||||
|
||||
if (user_id.empty()) {
|
||||
message["status"] = "fail";
|
||||
message["reason"] = "Not authenticated";
|
||||
} else if (user_id.rfind("C-", 0) == 0 ||
|
||||
user_id.rfind("web-", 0) == 0) {
|
||||
// Controller and browser identities are temporary and are not authenticated
|
||||
// against a persisted device password.
|
||||
message["status"] = "fail";
|
||||
message["reason"] = "Password changes are not allowed for this identity";
|
||||
} else {
|
||||
std::string new_password;
|
||||
if (!GetStringField(j, "new_password", new_password) ||
|
||||
new_password.size() != 6) {
|
||||
message["status"] = "fail";
|
||||
message["reason"] = "Password must contain exactly 6 characters";
|
||||
} else if (!device_db_manager_->UpdatePassword(user_id, new_password)) {
|
||||
message["status"] = "fail";
|
||||
message["reason"] = "Failed to update password";
|
||||
} else {
|
||||
message["status"] = "success";
|
||||
LOG_INFO("Authenticated client [{}] changed its device password", user_id);
|
||||
}
|
||||
}
|
||||
|
||||
send_msg_(hdl, message);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SignalNegotiation::turn_credentials(websocketpp::connection_hdl hdl,
|
||||
const json& j) {
|
||||
(void)j;
|
||||
|
||||
@@ -36,6 +36,7 @@ class SignalNegotiation {
|
||||
bool answer(websocketpp::connection_hdl hdl, const json& j);
|
||||
bool new_candidate(websocketpp::connection_hdl hdl, const json& j);
|
||||
bool new_candidate_mid(websocketpp::connection_hdl hdl, const json& j);
|
||||
bool change_password(websocketpp::connection_hdl hdl, const json& j);
|
||||
bool turn_credentials(websocketpp::connection_hdl hdl, const json& j);
|
||||
void OnWebClientDisconnect(const std::string& user_id);
|
||||
|
||||
|
||||
@@ -828,6 +828,9 @@ void SignalServer::OnMessage(websocketpp::connection_hdl hdl,
|
||||
case "new_candidate_mid"_H:
|
||||
signal_negotiation_->new_candidate_mid(hdl, j);
|
||||
break;
|
||||
case "change_password"_H:
|
||||
signal_negotiation_->change_password(hdl, j);
|
||||
break;
|
||||
case "turn_credentials"_H:
|
||||
signal_negotiation_->turn_credentials(hdl, j);
|
||||
break;
|
||||
|
||||
@@ -84,12 +84,52 @@ int main() {
|
||||
"wrong device password login response has login type");
|
||||
expect(sent_messages[0].value("status", "") == "fail",
|
||||
"wrong device password login fails");
|
||||
expect(sent_messages[0].value("reason", "") == "Incorrect password",
|
||||
"wrong device password login reports a specific reason");
|
||||
}
|
||||
expect(db.VerifyDevice(offline_host.device_id, offline_host.password) == 0,
|
||||
"wrong device password login does not replace original password");
|
||||
expect(db.VerifyDevice(offline_host.device_id, "attacker-password") != 0,
|
||||
"wrong device password is not accepted after failed login");
|
||||
|
||||
sent_messages.clear();
|
||||
negotiation.change_password(
|
||||
attacker_hdl,
|
||||
{{"type", "change_password"}, {"new_password", "654321"}});
|
||||
expect(sent_messages.size() == 1 &&
|
||||
sent_messages[0].value("status", "") == "fail" &&
|
||||
sent_messages[0].value("reason", "") ==
|
||||
"Missing or invalid request ID",
|
||||
"password change requires a request id");
|
||||
|
||||
sent_messages.clear();
|
||||
negotiation.change_password(
|
||||
attacker_hdl,
|
||||
{{"type", "change_password"},
|
||||
{"request_id", "unauthenticated"},
|
||||
{"new_password", "654321"}});
|
||||
expect(sent_messages.size() == 1 &&
|
||||
sent_messages[0].value("status", "") == "fail" &&
|
||||
sent_messages[0].value("reason", "") == "Not authenticated",
|
||||
"unauthenticated connection cannot change a device password");
|
||||
expect(db.VerifyDevice(offline_host.device_id, offline_host.password) == 0,
|
||||
"unauthenticated password change leaves the password unchanged");
|
||||
|
||||
sent_messages.clear();
|
||||
auto controller_connection = std::make_shared<int>(5);
|
||||
websocketpp::connection_hdl controller_hdl(controller_connection);
|
||||
transmission->BindUserToWsHandle("C-controller", controller_hdl);
|
||||
negotiation.change_password(
|
||||
controller_hdl,
|
||||
{{"type", "change_password"},
|
||||
{"request_id", "controller"},
|
||||
{"new_password", "654321"}});
|
||||
expect(sent_messages.size() == 1 &&
|
||||
sent_messages[0].value("status", "") == "fail",
|
||||
"temporary controller identity cannot change a device password");
|
||||
expect(db.VerifyDevice(offline_host.device_id, offline_host.password) == 0,
|
||||
"controller password change leaves the device password unchanged");
|
||||
|
||||
sent_messages.clear();
|
||||
auto authenticated_connection = std::make_shared<int>(3);
|
||||
websocketpp::connection_hdl authenticated_hdl(authenticated_connection);
|
||||
@@ -132,6 +172,47 @@ int main() {
|
||||
sent_messages[0].contains("turn"),
|
||||
"authenticated client can explicitly refresh TURN credentials");
|
||||
|
||||
sent_messages.clear();
|
||||
negotiation.change_password(
|
||||
authenticated_hdl,
|
||||
{{"type", "change_password"},
|
||||
{"request_id", "malformed"},
|
||||
{"new_password", "short"}});
|
||||
expect(sent_messages.size() == 1 &&
|
||||
sent_messages[0].value("status", "") == "fail",
|
||||
"authenticated client cannot set a malformed password");
|
||||
expect(db.VerifyDevice(offline_host.device_id, offline_host.password) == 0,
|
||||
"malformed password change leaves the password unchanged");
|
||||
|
||||
sent_messages.clear();
|
||||
const std::string new_password = "654321";
|
||||
negotiation.change_password(
|
||||
authenticated_hdl,
|
||||
{{"type", "change_password"},
|
||||
{"request_id", "successful"},
|
||||
{"new_password", new_password}});
|
||||
expect(sent_messages.size() == 1 &&
|
||||
sent_messages[0].value("type", "") == "change_password" &&
|
||||
sent_messages[0].value("status", "") == "success" &&
|
||||
sent_messages[0].value("request_id", "") == "successful" &&
|
||||
sent_messages[0].value("user_id", "") == offline_host.device_id,
|
||||
"authenticated device can change its own password");
|
||||
expect(db.VerifyDevice(offline_host.device_id, offline_host.password) != 0,
|
||||
"old password is rejected after a successful password change");
|
||||
expect(db.VerifyDevice(offline_host.device_id, new_password) == 0,
|
||||
"new password is accepted after a successful password change");
|
||||
|
||||
sent_messages.clear();
|
||||
auto relogin_connection = std::make_shared<int>(4);
|
||||
websocketpp::connection_hdl relogin_hdl(relogin_connection);
|
||||
negotiation.login_user(
|
||||
relogin_hdl,
|
||||
{{"type", "login"},
|
||||
{"user_id", offline_host.device_id + "@" + new_password}});
|
||||
expect(sent_messages.size() == 1 &&
|
||||
sent_messages[0].value("status", "") == "success",
|
||||
"device can log in again with its changed password");
|
||||
|
||||
}
|
||||
|
||||
std::filesystem::remove(db_path);
|
||||
|
||||
Reference in new issue
Block a user