diff options
author | Sami Littow <sami.littow@qt.io> | 2023-04-14 08:54:38 +0300 |
---|---|---|
committer | Sami Littow <sami.littow@qt.io> | 2023-04-19 14:36:08 +0300 |
commit | 481ae1cb9e52dfe198030e9a4a6e562005f04ca7 (patch) | |
tree | 4365c32ac61766da8d539c4eb60a31a4edcd900d /src | |
parent | b8e7c76ea05ab2ab1dbec0efe547ee2ff259e374 (diff) |
(clitoolhandler.h)
- Server response validity was only checked when requesting longterm reservation
- Could have exploited with telnet
- Server response JSON status field check moved to the beginning of method
(HttpClient, Licenser classes)
- Pass the REST endpoint to the HTTP client per request, rather than
trying to guess it in HTTP client
Change-Id: I13d05b33f1032a91d393e7315552f1b9d391142d
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Arttu Tarkiainen <arttu.tarkiainen@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/libs/qlicenseservice/clienthandler.cpp | 5 | ||||
-rw-r--r-- | src/libs/qlicenseservice/daemon_clients/clitoolhandler.h | 48 | ||||
-rw-r--r-- | src/libs/qlicenseservice/httpclient.cpp | 47 | ||||
-rw-r--r-- | src/libs/qlicenseservice/httpclient.h | 16 | ||||
-rw-r--r-- | src/libs/qlicenseservice/licenser.cpp | 11 | ||||
-rw-r--r-- | src/libs/qlicenseservice/request.h | 1 |
6 files changed, 52 insertions, 76 deletions
diff --git a/src/libs/qlicenseservice/clienthandler.cpp b/src/libs/qlicenseservice/clienthandler.cpp index fbeab7b..863384e 100644 --- a/src/libs/qlicenseservice/clienthandler.cpp +++ b/src/libs/qlicenseservice/clienthandler.cpp @@ -62,8 +62,10 @@ int ClientHandler::parseRequest() m_request.reqType = RequestType::no_request; if (cmd == LICENSE_REQUEST_CMD) { m_request.reqType = RequestType::license_request; + m_request.accessPoint = m_settings.get("reservation_access_point"); } else if (cmd ==PERMANENT_REQUEST_CMD) { m_request.reqType = RequestType::long_term_request; + m_request.accessPoint = m_settings.get("permanent_access_point"); // find either 'add' or 'remove' if (params.size() > 0) { if (params[0] != OP_ADD_RESERVATION && params[0] != OP_REMOVE_RESERVATION) { @@ -80,8 +82,7 @@ int ClientHandler::parseRequest() params.erase(params.begin()); } else if (cmd == SERVER_VERSION_CMD) { m_request.reqType = RequestType::server_version; - buildRequestJson(); - return 0; + m_request.accessPoint = m_settings.get("version_query_access_point"); } else if (cmd == DAEMON_VERSION_CMD) { m_request.reqType = RequestType::daemon_version; } else if (cmd == RESERVATION_QUERY_CMD) { diff --git a/src/libs/qlicenseservice/daemon_clients/clitoolhandler.h b/src/libs/qlicenseservice/daemon_clients/clitoolhandler.h index ceeefc0..021d958 100644 --- a/src/libs/qlicenseservice/daemon_clients/clitoolhandler.h +++ b/src/libs/qlicenseservice/daemon_clients/clitoolhandler.h @@ -45,37 +45,33 @@ class CliToolHandler : public virtual ClientHandler { JsonHandler json(response); std::stringstream ss; - if (m_request.reqType == RequestType::long_term_request) { - // long-term request: Have "message" field from response JSON directly as a reply to the user - response = json.get("message"); - if (json.get("status") != "true" ) { - if (response == "License fully reserved") { - response = replyString[e_license_pool_full]; - } else if (response.find("cannot be early released") != std::string::npos) { - response = replyString[e_no_permanent_to_release]; - } else { - response = replyString[e_license_rejected]; - } - // Do not touch the license file, just return - return 1; - } - } else if (m_request.reqType == RequestType::server_version) { + if (m_request.reqType == RequestType::server_version) { response = "Qt License Server v"; response += json.get("version"); - return 0; // Do not touch cached license files pls. + return 0; } - ss << replyString[e_license_granted]; - ss << " expiry_date=" << json.get("expiry_date"); - ss << " license_id=" << json.get("license_number"); - ss << " reservation_id=" << json.get("reservation_id"); - response = ss.str(); - // Add timestamp into license JSON - json.add("last_timestamp", utils::getTimestampNow()); + if (json.get("status") != "true" ) { + if (response == "License fully reserved") { + response = replyString[e_license_pool_full]; + } else if (response.find("cannot be early released") != std::string::npos) { + response = replyString[e_no_permanent_to_release]; + } else { + response = replyString[e_license_rejected]; + } + // Do not touch the license file, just return + return 1; + } else if (m_request.reqType == RequestType::long_term_request) { + // long-term request: Have "message" field from response JSON directly as a reply to the user + response = json.get("message"); - int result = utils::writeToFile(m_request.licenseFile, json.dump(4)); - if (result != 0) { - std::cout << "ERROR saving license file: '" << m_request.licenseFile << "': " << strerror(result) << std::endl; + // Add timestamp into license JSON + json.add("last_timestamp", utils::getTimestampNow()); + + int result = utils::writeToFile(m_request.licenseFile, json.dump(4)); + if (result != 0) { + std::cout << "ERROR saving license file: '" << m_request.licenseFile << "': " << strerror(result) << std::endl; + } } return 0; } diff --git a/src/libs/qlicenseservice/httpclient.cpp b/src/libs/qlicenseservice/httpclient.cpp index 7f5d1fc..8d07674 100644 --- a/src/libs/qlicenseservice/httpclient.cpp +++ b/src/libs/qlicenseservice/httpclient.cpp @@ -16,45 +16,34 @@ size_t WriteCallback(char *contents, size_t size, size_t nmemb, void *userp) return size * nmemb; } -HttpClient::HttpClient( const std::string &serverUrl, - const std::string &requestAccessPoint, - const std::string &permanentAccessPoint, - const std::string &versionAccessPoint) : - m_serverUrl(serverUrl), - m_requestAccessPoint(requestAccessPoint), - m_permanentAccessPoint(permanentAccessPoint), - m_versionAccessPoint(versionAccessPoint) +HttpClient::HttpClient(const std::string &serverUrl) + : m_serverUrl(serverUrl) { m_userAgent += DAEMON_VERSION; } -int HttpClient::sendRequest(std::string &reply, const std::string &payload, - const std::string &server, const std::string &authKey) +int HttpClient::sendAndReceive(std::string &reply, const std::string &payload, + const std::string &accessPoint, const std::string &server, + const std::string &authKey) { + if (accessPoint.empty()) { + std::cout << "[HttpClient] error: No server endpoint given\n"; + return 1; + } HttpRequest request; - m_lastError = "No errors"; - - /* specify URL to POST */ - request.url = server; - request.payload = payload; + // specify URL if (server.empty()) { // If server URL is not given as param, we use the default request.url = m_serverUrl; } + request.url += accessPoint; + request.payload = payload; + if (!authKey.empty()) { - // normal request - request.url += m_requestAccessPoint; + // Add auth key in headers std::string auth = "Authorization: " + authKey; request.headers = curl_slist_append(request.headers, auth.c_str()); - } else { - if (payload.empty()) { - // version query - request.url += m_versionAccessPoint; - } else { - // permanentrequest - request.url += m_permanentAccessPoint; - } } std::string agent = "User-Agent: " + m_userAgent; @@ -73,13 +62,11 @@ int HttpClient::sendRequest(std::string &reply, const std::string &payload, retVal = 1; } } catch(...) { - m_lastError = "Connection failed"; + std::cout << "Connection failed\n"; retVal = 1; } if (retVal == 0) { std::cout << request.reply.length() << " bytes retrieved from license server\n"; - } else { - std::cout << m_lastError << std::endl; } /* cleanup curl stuff */ @@ -108,7 +95,7 @@ int HttpClient::doRequest(CURL *curl, HttpRequest &request) curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.payload.c_str()); } else { - curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); // for server ping } if (curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL) != CURLE_OK) { std::cout << "Warning! No SSL support available\n"; @@ -122,7 +109,7 @@ int HttpClient::doRequest(CURL *curl, HttpRequest &request) // check for errors if (res != CURLE_OK) { std::cout << "HTTP transfer failed, URL: " << request.url << std::endl; - m_lastError = curl_easy_strerror(res); + std::cout << curl_easy_strerror(res) << std::endl; return 1; } request.reply = readBuffer; diff --git a/src/libs/qlicenseservice/httpclient.h b/src/libs/qlicenseservice/httpclient.h index 13d2478..9df41c6 100644 --- a/src/libs/qlicenseservice/httpclient.h +++ b/src/libs/qlicenseservice/httpclient.h @@ -38,22 +38,16 @@ struct HttpRequest { class HttpClient { public: - explicit HttpClient(const std::string &serverUrl, - const std::string &requestAccessPoint, - const std::string &permanentccessPoint, - const std::string &versionAccessPoint); + explicit HttpClient(const std::string &serverUrl); + ~HttpClient() {} - int sendRequest(std::string &reply, const std::string &payload, - const std::string &server, const std::string &authKey=""); - std::string error() { return m_lastError; } + int sendAndReceive(std::string &reply, const std::string &payload, + const std::string &accessPoint, const std::string &server, + const std::string &authKey=""); private: std::string m_serverUrl; - std::string m_requestAccessPoint; - std::string m_permanentAccessPoint; - std::string m_versionAccessPoint; std::string m_userAgent = "License daemon / "; - std::string m_lastError; int doRequest(CURL *curl, HttpRequest &request); }; diff --git a/src/libs/qlicenseservice/licenser.cpp b/src/libs/qlicenseservice/licenser.cpp index 9094bd7..df85f4e 100644 --- a/src/libs/qlicenseservice/licenser.cpp +++ b/src/libs/qlicenseservice/licenser.cpp @@ -31,10 +31,7 @@ Licenser::Licenser(uint16_t tcpPort, const std::string &settingsPath) } m_mocInterval = utils::strToInt(m_settings->get("moc_renewal_interval")) * SECS_IN_HOUR; // Start the HTTP client - m_http = new HttpClient(m_settings->get("server_addr"), - m_settings->get("reservation_access_point"), - m_settings->get("permanent_access_point"), - m_settings->get("version_query_access_point")); + m_http = new HttpClient(m_settings->get("server_addr")); // Start the TCP/IP server m_tcpServer = new TcpServer(tcpPort); if (!m_tcpServer->init()) { @@ -149,7 +146,6 @@ int Licenser::listen() if (m_floatingClients.size() > 0) { checkTasksDue(); } - std::cout << "Current clients in cache: " << m_floatingClients.size() << std::endl; return 0; } @@ -214,7 +210,6 @@ ClientHandler *Licenser::parseInputAndCreateCLient(uint16_t socketId, const std: int Licenser::sendServerRequest(const RequestInfo &request, std::string &reply) { std::string auth; - std::cout << "Payload: " << request.payload << std::endl; // Generate auth hash for HTTP headers std::string hash; @@ -223,7 +218,9 @@ int Licenser::sendServerRequest(const RequestInfo &request, std::string &reply) auth = "apikey " + hash; // Send the request - if (m_http->sendRequest(reply, request.payload, request.serverAddr, auth) != 0) { + if (m_http->sendAndReceive(reply, request.payload, + request.accessPoint, + request.serverAddr, auth) != 0) { return e_bad_connection; } return e_got_response; diff --git a/src/libs/qlicenseservice/request.h b/src/libs/qlicenseservice/request.h index 7533e4e..1668c92 100644 --- a/src/libs/qlicenseservice/request.h +++ b/src/libs/qlicenseservice/request.h @@ -46,6 +46,7 @@ struct RequestInfo { std::string email; std::string payload; std::string serverAddr; + std::string accessPoint; uint64_t startTimestamp = 0; // used by QA-Tools only uint64_t stopTimestamp = 0; // used by QA-Tools only std::string runnerType; // "qa_tester" || "qa_exe", used by QA-Tools only |