From 13cea54d190d949f881c089eb8d3ffd04ced5981 Mon Sep 17 00:00:00 2001 From: Sami Littow Date: Tue, 22 Nov 2022 14:00:11 +0200 Subject: Updated linux installer Added support for mocwrapper leeway time - Occurs when server connection is broken - Requires server update --- include/commonsetup.h | 1 + include/licenser.h | 3 +- include/utils.h | 8 ++++- include/version.h | 3 +- jsonhandler.cpp | 2 +- licenser.cpp | 71 ++++++++++++++++++++------------------ linux_service_scripts/installer.sh | 4 +-- utils.cpp | 32 +++++++++++++---- 8 files changed, 75 insertions(+), 49 deletions(-) diff --git a/include/commonsetup.h b/include/commonsetup.h index 08f08e6..1622503 100644 --- a/include/commonsetup.h +++ b/include/commonsetup.h @@ -38,3 +38,4 @@ #define DAEMON_SETTINGS_FILE WORKING_DIR "/licd.ini" #define LICENSE_FILE_BASE WORKING_DIR "/lic_" #define SHA256_HASH_SIZE 32 +#define SECS_IN_HOUR 3600 diff --git a/include/licenser.h b/include/licenser.h index fd413fe..ad7296c 100644 --- a/include/licenser.h +++ b/include/licenser.h @@ -76,7 +76,7 @@ private: int parseIncoming(const std::string &incoming, RequestInfo &request); int buildRequestJson(RequestInfo &request); int parseAndSaveJsonReply(std::string &reply, const RequestInfo &request); - bool checkLicenseExpiryDate(const std::string &licenseFile); + bool checkLicenseExpiryDate(std::string &reply, const RequestInfo &request); bool isMocRenewalDue(const std::string &licenseFile); void doHmacHashSha256(const std::string &payload, const std::string &secret, std::string &authKey); int initDaemonSettings(); @@ -92,7 +92,6 @@ private: {e_license_rejected, "No valid license acquired"}, {e_bad_connection, "No connection to server. Try again later."} }; - }; #ifndef __TIME_IMP diff --git a/include/utils.h b/include/utils.h index c541741..982e305 100644 --- a/include/utils.h +++ b/include/utils.h @@ -31,7 +31,7 @@ #define SYSTEM_ROOT "/" #endif #if __APPLE__ || __MACH__ - #define USER_SETTINGS_DIR "/something/else" // not supported yet + #define USER_SETTINGS_DIR ".local/share/Qt/" // not supported yet #elif __linux__ #define USER_SETTINGS_DIR ".local/share/Qt/" #endif @@ -62,7 +62,13 @@ std::vector getDirListing(const std::string &directory, const std:: * Other */ +// Time conversions +std::string epochToString(time_t epochTime, const char* format = "%Y-%m-%d %H:%M:%S"); +time_t stringToEpoch(const char* theTime, const char* format = "%Y-%m-%d %H:%M:%S"); + +// Find out host OS std::string getOsName(); + // Swap endian of any data template T swapEndian(T val) { diff --git a/include/version.h b/include/version.h index 954b2ad..e5e7b67 100644 --- a/include/version.h +++ b/include/version.h @@ -6,7 +6,7 @@ #pragma once #define DAEMON_VERSION_MAJOR "2" -#define DAEMON_VERSION_MINOR "0.1" +#define DAEMON_VERSION_MINOR "0.2" #define DAEMON_VERSION DAEMON_VERSION_MAJOR "." DAEMON_VERSION_MINOR #define LICD_SERVICE_DESCRIPTION "Qt Licensing service" #define COPYRIGHT_TEXT "Copyright (C) 2022 The Qt Company Ltd" @@ -19,4 +19,3 @@ #define MOCWRAPPER_VERSION_MAJOR DAEMON_VERSION_MAJOR #define MOCWRAPPER_VERSION_MINOR DAEMON_VERSION_MINOR #define MOCWRAPPER_VERSION MOCWRAPPER_VERSION_MAJOR "." MOCWRAPPER_VERSION_MINOR - diff --git a/jsonhandler.cpp b/jsonhandler.cpp index 52185de..f46fd72 100644 --- a/jsonhandler.cpp +++ b/jsonhandler.cpp @@ -28,7 +28,7 @@ int JsonHandler::getInt(const std::string &item) return std::stoi(m_items[item]); } catch (...) { - return -1; + return INT16_MIN; } } diff --git a/licenser.cpp b/licenser.cpp index 202effb..142164d 100644 --- a/licenser.cpp +++ b/licenser.cpp @@ -52,7 +52,7 @@ int Licenser::listen() std::cout << "Standard license renewal request\n"; // See if it's MOC who's calling us (special case) if (request.appName == MOCWRAPPER_APP_NAME) { - // More than 24hrs from last successful request? + // More than MOC_RENEWAL_INTERVAL from last successful request? if (!isMocRenewalDue(request.licenseFile)) { // No - Just send ok message and no further actions needed reply = replyString[e_license_granted]; @@ -63,14 +63,7 @@ int Licenser::listen() if (buildRequestJson(request) == 0) { if (sendLicensingRequest(reply, request) != 0) { // Bad server connection: Check the existing license file for expiry date - if (!checkLicenseExpiryDate(request.licenseFile)) { - // If expiry date is up or no license file found, - // Send "Bad connection" - reply = replyString[e_bad_connection]; - reply += m_http->error(); - } else { - reply = replyString[e_license_granted]; - } + checkLicenseExpiryDate(reply, request); } else { parseAndSaveJsonReply(reply, request); } @@ -203,12 +196,11 @@ int Licenser::parseIncoming(const std::string &incoming, RequestInfo &request) } // Add user info to the license filename - std::string file = settings->get("license_file_base"); - file += request.userId; - file += "_"; - file += request.licenseId; - file += settings->get("license_file_extension"); - request.licenseFile = file; + std::stringstream ss; + ss << WORKING_DIR << DIR_SEPARATOR + << settings->get("license_file_base") << request.userId + << "_" << request.licenseId << settings->get("license_file_extension"); + request.licenseFile = ss.str(); return 0; } @@ -267,45 +259,56 @@ int Licenser::parseAndSaveJsonReply(std::string &reply, const RequestInfo &reque json.add("last_timestamp", timeNow); int result = utils::writeToFile(request.licenseFile, json.dump(4)); if (result != 0) { - std::cout << "ERROR saving license file: " << strerror(result) << std::endl; + std::cout << "ERROR saving license file: '" << request.licenseFile << "': " << strerror(result) << std::endl; } return 0; } -bool Licenser::checkLicenseExpiryDate(const std::string &licenseFile) +bool Licenser::checkLicenseExpiryDate(std::string &reply, const RequestInfo &request) { - std::cout << "Offline - checking validity from license file " << licenseFile << std::endl; + std::cout << "Offline - checking validity from license file " << request.licenseFile << std::endl; // Open the license file std::string data; - if (utils::readFile(data, licenseFile) != 0) { - std::cout << "No license file - rejecting license " <tm_year + 1900) << '-' - << std::setfill('0') << std::setw(2) << (now->tm_mon + 1) << '-' - << std::setfill('0') << std::setw(2) << now->tm_mday; - - // See if the time has expired - if (current.str() > expiryDate) { + std::time_t current = std::time(0); + // See if the time has expire + if (current > expEpoch) { // License expired - std::cout << "License already expired at " << expiryDate << ", rejecting\n"; + if (request.appName == MOCWRAPPER_APP_NAME) { + // For MOC, allow some leeway time + int leewayTimeLeft = expEpoch + (license.getInt("leeway_time") * SECS_IN_HOUR) - current; + std::cout << "Leeway time left: " << leewayTimeLeft << std::endl; + if (leewayTimeLeft > 0) { + std::stringstream ss; + ss << "Warning: No connection to server. " + << "Leeway time left: " + << std::fixed << std::setprecision(1) + << (float)leewayTimeLeft / (24 * SECS_IN_HOUR) << " days"; + reply = ss.str(); + return true; + } + } + std::cout << "License already expired at " << expDate << ", rejecting\n"; + reply = replyString[e_license_rejected]; return false; } - std::cout << "License granted, expires at " << expiryDate << std::endl; + std::cout << "License granted, expires at " << expDate << std::endl; + reply = replyString[e_license_granted]; return true; } diff --git a/linux_service_scripts/installer.sh b/linux_service_scripts/installer.sh index f0ba87f..404fb90 100755 --- a/linux_service_scripts/installer.sh +++ b/linux_service_scripts/installer.sh @@ -21,7 +21,7 @@ function create_install_dir { function copy_files { # Copy executables and .ini - cp ${name} ${name}.ini qtlongterm mocwrapper licheck ${installdir}/ + cp ${name} ${name}.ini qtlicensetool mocwrapper licheck ${installdir}/ if [ $? != 0 ]; then exit_fail "Failed to copy files to $installdir" fi @@ -33,7 +33,7 @@ function copy_files { fi # Create a symlink for qtlongterm binary - ln -s ${installdir}/qtlongterm /usr/bin/qtlongterm + ln -s ${installdir}/qtlicensetool /usr/bin/qtlicensetool sync } diff --git a/utils.cpp b/utils.cpp index 7bfd481..b60295b 100644 --- a/utils.cpp +++ b/utils.cpp @@ -80,23 +80,26 @@ int strToInt(const std::string &str) std::string getUserHomeDir() { // Try to find current user's home - std::string homedir; + const char* homedir; #if __linux__ || __APPLE__ || __MACH__ // Linux and Mac - if (getenv("HOME") != nullptr) - homedir = getenv("HOME"); - if (homedir.length() == 0) { + homedir = std::getenv("PATH"); + if (homedir == nullptr) { homedir = getpwuid(getuid())->pw_dir; } #else + // Windows homedir = getenv("HOMEPATH"); - homedir = SYSTEM_ROOT + homedir; + if (homedir != nullptr) { + homedir = SYSTEM_ROOT + homedir; + } + #endif - if (&homedir == nullptr) { + if (homedir == nullptr) { printf("ERROR Not able to determine user's home directory\n"); homedir = ""; } - return homedir; + return std::string(homedir); } // Write data to the file @@ -250,6 +253,21 @@ std::string getOsName() #endif } +std::string epochToString(time_t epochTime, const char* format) +{ + char timestamp[64] = {0}; + strftime(timestamp, sizeof(timestamp), format, localtime(&epochTime)); + return timestamp; +} + +time_t stringToEpoch(const char* theTime, const char* format) +{ + std::tm tmTime; + memset(&tmTime, 0, sizeof(tmTime)); + strptime(theTime, format, &tmTime); + return mktime(&tmTime); +} + /* * App-specific utils here (not generic) */ -- cgit v1.2.3