From 90c13efab1fd1b67625ec23815ccc195803e230e Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 28 Sep 2020 00:21:23 +0200 Subject: Matrix: fix login with pantalaimon proxy, fix logout crash, show real login error --- src/plugins/Matrix.cpp | 82 ++++++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 52 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 8b819a2..d709f73 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -54,7 +54,7 @@ namespace QuickMedia { char url[512]; if(next_batch.empty()) - snprintf(url, sizeof(url), "%s/_matrix/client/r0/sync?timeout=0", homeserver.c_str()); + snprintf(url, sizeof(url), "%s/_matrix/client/r0/sync?timeout=0&full_state=true", homeserver.c_str()); else snprintf(url, sizeof(url), "%s/_matrix/client/r0/sync?timeout=30000&since=%s", homeserver.c_str(), next_batch.c_str()); @@ -831,38 +831,6 @@ namespace QuickMedia { return post_message(room_id, filename, content_uri_json.asString(), MessageType::IMAGE, &message_info); } - static std::string parse_login_error_response(std::string json_str) { - if(json_str.empty()) - return "Unknown error"; - - Json::Value json_root; - Json::CharReaderBuilder json_builder; - std::unique_ptr json_reader(json_builder.newCharReader()); - std::string json_errors; - if(!json_reader->parse(&json_str[0], &json_str[json_str.size()], &json_root, &json_errors)) { - fprintf(stderr, "Matrix login response parse error: %s\n", json_errors.c_str()); - return json_str; - } - - if(!json_root.isObject()) - return json_str; - - const Json::Value &errcode_json = json_root["errcode"]; - // Yes, matrix is retarded and returns M_NOT_JSON error code when username/password is incorrect - if(errcode_json.isString() && strcmp(errcode_json.asCString(), "M_NOT_JSON") == 0) - return "Incorrect username or password"; - - return json_str; - } - - // Returns empty string on error - static std::string extract_homeserver_from_user_id(const std::string &user_id) { - size_t index = user_id.find(':'); - if(index == std::string::npos) - return ""; - return user_id.substr(index + 1); - } - PluginResult Matrix::login(const std::string &username, const std::string &password, const std::string &homeserver, std::string &err_msg) { // TODO: this is deprecated but not all homeservers have the new version. // When this is removed from future version then switch to the new login method (identifier object with the username). @@ -882,8 +850,8 @@ namespace QuickMedia { }; std::string server_response; - if(download_to_string(homeserver + "/_matrix/client/r0/login", server_response, std::move(additional_args), use_tor, true) != DownloadResult::OK) { - err_msg = parse_login_error_response(std::move(server_response)); + if(download_to_string(homeserver + "/_matrix/client/r0/login", server_response, std::move(additional_args), use_tor, true, false) != DownloadResult::OK) { + err_msg = std::move(server_response); return PluginResult::NET_ERR; } @@ -904,6 +872,12 @@ namespace QuickMedia { return PluginResult::ERR; } + const Json::Value &error = json_root["error"]; + if(error.isString()) { + err_msg = error.asString(); + return PluginResult::ERR; + } + const Json::Value &user_id_json = json_root["user_id"]; if(!user_id_json.isString()) { err_msg = "Failed to parse matrix login response"; @@ -916,17 +890,13 @@ namespace QuickMedia { return PluginResult::ERR; } - std::string user_id = user_id_json.asString(); + // Use the user-provided homeserver instead of the one the server tells us about, otherwise this wont work with a proxy + // such as pantalaimon + json_root["homeserver"] = homeserver; - std::string homeserver_response = extract_homeserver_from_user_id(user_id); - if(homeserver_response.empty()) { - err_msg = "Missing homeserver in user id, user id: " + user_id; - return PluginResult::ERR; - } - - this->user_id = std::move(user_id); + this->user_id = user_id_json.asString(); this->access_token = access_token_json.asString(); - this->homeserver = "https://" + std::move(homeserver_response); + this->homeserver = homeserver; // TODO: Handle well_known field. The spec says clients SHOULD handle it if its provided @@ -956,6 +926,13 @@ namespace QuickMedia { if(download_to_string(homeserver + "/_matrix/client/r0/logout", server_response, std::move(additional_args), use_tor, true) != DownloadResult::OK) return PluginResult::NET_ERR; + // Make sure all fields are reset here! + room_data_by_id.clear(); + user_id.clear(); + access_token.clear(); + homeserver.clear(); + next_batch.clear(); + return PluginResult::OK; } @@ -991,29 +968,30 @@ namespace QuickMedia { return PluginResult::ERR; } - std::string user_id = user_id_json.asString(); - std::string access_token = access_token_json.asString(); - - std::string homeserver = extract_homeserver_from_user_id(user_id); - if(homeserver.empty()) { - fprintf(stderr, "Missing homeserver in user id, user id: %s\n", user_id.c_str()); + const Json::Value &homeserver_json = json_root["homeserver"]; + if(!homeserver_json.isString()) { + fprintf(stderr, "Failed to parse matrix cached session response\n"); return PluginResult::ERR; } + std::string user_id = user_id_json.asString(); + std::string access_token = access_token_json.asString(); + std::string homeserver = homeserver_json.asString(); + std::vector additional_args = { { "-H", "Authorization: Bearer " + access_token } }; std::string server_response; // We want to make any request to the server that can verify that our token is still valid, doesn't matter which call - if(download_to_string("https://" + homeserver + "/_matrix/client/r0/account/whoami", server_response, std::move(additional_args), use_tor, true) != DownloadResult::OK) { + if(download_to_string(homeserver + "/_matrix/client/r0/account/whoami", server_response, std::move(additional_args), use_tor, true) != DownloadResult::OK) { fprintf(stderr, "Matrix whoami response: %s\n", server_response.c_str()); return PluginResult::NET_ERR; } this->user_id = std::move(user_id); this->access_token = std::move(access_token); - this->homeserver = "https://" + homeserver; + this->homeserver = std::move(homeserver); return PluginResult::OK; } -- cgit v1.2.3