From 8bbef2865455754425a84b86680a89bff8aa7691 Mon Sep 17 00:00:00 2001 From: gcontini <1121667+gcontini@users.noreply.github.com> Date: 周六, 19 10月 2019 08:50:45 +0800 Subject: [PATCH] issue #64 , issue #56 (part) --- src/library/locate/EnvironmentVarData.hpp | 5 src/library/locate/ExternalDefinition.cpp | 62 + .gitignore | 3 src/library/base/base64.h | 140 --- src/library/api/datatypes.h | 38 src/library/api/license++.h | 19 src/tools/license-generator/license-generator.cpp | 141 ++- src/library/locate/EnvironmentVarData.cpp | 44 src/library/locate/ExternalDefinition.hpp | 8 src/library/os/os.h | 10 src/library/base/base64.c | 133 +++ src/library/locate/LocatorStrategy.hpp | 20 src/library/base/CMakeLists.txt | 1 src/library/locate/EnvironmentVarLocation.hpp | 2 src/library/locate/LocatorStrategy.cpp | 2 test/library/CMakeLists.txt | 18 src/library/base/EventRegistry.h | 48 test/functional/CMakeLists.txt | 8 src/library/locate/ApplicationFolder.hpp | 2 src/library/locate/LocatorFactory.cpp | 22 test/functional/standard-license_test.cpp | 39 test/functional/hijiaking_test.cpp | 2 src/library/locate/LocatorFactory.hpp | 5 src/tools/license-generator/license-generator.h | 12 src/library/locate/ApplicationFolder.cpp | 13 test/library/EventRegistry_test.cpp | 41 + src/library/base/StringUtils.cpp | 39 src/library/CMakeLists.txt | 1 src/library/base/FileUtils.cpp | 11 test/library/LicenseLocator_test.cpp | 60 CONTRIBUTING.md | 9 test/functional/date_test.cpp | 11 src/library/base/EventRegistry.cpp | 188 ++- test/library/LicenseReader_test.cpp | 68 + example/example.cpp | 77 - src/library/license++.cpp | 25 test/functional/volid_test.cpp | 5 README.md | 2 src/tools/license-generator/CMakeLists.txt | 1 src/library/locate/EnvironmentVarLocation.cpp | 20 src/library/LicenseReader.hpp | 56 src/library/base/StringUtils.h | 13 src/library/LicenseReader.cpp | 75 - src/tools/base_lib/win/CryptoHelperWindows.h | 92 +- src/library/base/FileUtils.hpp | 5 src/tools/base_lib/win/CryptoHelperWindows.cpp | 788 +++++++++--------- 46 files changed, 1,349 insertions(+), 1,035 deletions(-) diff --git a/.gitignore b/.gitignore index 0018bea..7165b6c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ *.so *.dylib +#Visual studio files +.vs + # Compiled Static libraries *.lai *.la diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9cd24af..32db051 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,8 @@ * **Use a clear and descriptive title** for the issue to identify the problem. * **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how are you using Open License Manager. -* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or licenses, which can cause the bug. If you're providing code snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). The best way to report a bug is to **design a test** to demonstrate it. +* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or licenses, which can cause the bug. If you're providing code snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). +* **Provide a boost unit test to demonstrate the bug**. The best way to report a bug, and to have it fixed **forever** is to design a test to demonstrate it. * **If you're reporting that Open License Manager crashed**, include a crash dump and the associated message. * **Label the issue as bug.** @@ -79,8 +80,8 @@ ##### Don't * Don't reformat the code following your personal likes, it introduce a lot of "noise" and makes very hard to merge. - * Very large pull requests with few comments, no corresponding issue will probably be rejected. - * We understand that the project is still in a very alpha stage and a rearrangement is needed, however we would like to discuss it with you before we take project changing decision. - * We can't break current functionality, user established habits without documenting the change. + * Very large pull requests with few comments, no corresponding issue explaining what's it about will probably be rejected. + * We understand that the project is still in a very alpha stage and a rearrangement is needed, however we would like to discuss it with you before we take project changing decision. Please contact the project maintainer at `contini.mailing[AT]gmail.com` if you have time and plan to do a large contribution. + * Even it it's in alpha stage it's used ( _by some really courageous people!_ ) in production. We can't break current functionality, user established habits without documenting the change. \ No newline at end of file diff --git a/README.md b/README.md index 3b096d7..72838b4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [](https://travis-ci.org/open-license-manager/open-license-manager) [](http://github.com/badges/stability-badges)[](https://opensource.org/licenses/BSD-3-Clause) -A copy protection, licensing software written in C/C++ for Windows and Linux. +A copy protection, licensing software written in C++ for Windows and Linux (with a simple C api for use in C projects). It allows to protect the software you develop from unauthorized copies, limit the usage in time, to a specific set of machines, or prevent the usage in diff --git a/example/example.cpp b/example/example.cpp index 45370dd..2379d6a 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -2,55 +2,46 @@ #include <map> #include "api/license++.h" #include "pc-identifiers.h" -#include "ini/SimpleIni.h" using namespace std; -int main(int argc, char *argv[]) -{ - map<EVENT_TYPE, string> stringByEventType; - stringByEventType[LICENSE_OK ] = "OK "; - stringByEventType[LICENSE_FILE_NOT_FOUND ] = "license file not found "; - stringByEventType[LICENSE_SERVER_NOT_FOUND ] = "license server can't be contacted "; - stringByEventType[ENVIRONMENT_VARIABLE_NOT_DEFINED] = "environment variable not defined "; - stringByEventType[FILE_FORMAT_NOT_RECOGNIZED ] = "license file has invalid format (not .ini file) "; - stringByEventType[LICENSE_MALFORMED ] = "some mandatory field are missing, or data can't be fully read. "; - stringByEventType[PRODUCT_NOT_LICENSED ] = "this product was not licensed "; - stringByEventType[PRODUCT_EXPIRED ] = "license expired "; - stringByEventType[LICENSE_CORRUPTED ] = "license signature didn't match with current license "; - stringByEventType[IDENTIFIERS_MISMATCH ] = "Calculated identifier and the one provided in license didn't match"; - stringByEventType[LICENSE_FILE_FOUND ] = "license file not found "; - stringByEventType[LICENSE_VERIFIED ] = "license verified "; - - const string licLocation("example.lic"); - - LicenseInfo licenseInfo; - LicenseLocation licenseLocation; - licenseLocation.openFileNearModule = false; - licenseLocation.licenseFileLocation = licLocation.c_str(); - licenseLocation.environmentVariableName = ""; - EVENT_TYPE result = acquire_license("example", licenseLocation, &licenseInfo); - PcSignature signature; - FUNCTION_RETURN generate_ok = generate_user_pc_signature(signature, DEFAULT); +int main(int argc, char *argv[]) { + map<EVENT_TYPE, string> stringByEventType; + stringByEventType[LICENSE_OK] = "OK "; + stringByEventType[LICENSE_FILE_NOT_FOUND] = "license file not found "; + stringByEventType[LICENSE_SERVER_NOT_FOUND] = "license server can't be contacted "; + stringByEventType[ENVIRONMENT_VARIABLE_NOT_DEFINED] = "environment variable not defined "; + stringByEventType[FILE_FORMAT_NOT_RECOGNIZED] = "license file has invalid format (not .ini file) "; + stringByEventType[LICENSE_MALFORMED] = "some mandatory field are missing, or data can't be fully read. "; + stringByEventType[PRODUCT_NOT_LICENSED] = "this product was not licensed "; + stringByEventType[PRODUCT_EXPIRED] = "license expired "; + stringByEventType[LICENSE_CORRUPTED] = "license signature didn't match with current license "; + stringByEventType[IDENTIFIERS_MISMATCH] = "Calculated identifier and the one provided in license didn't match"; - if (result == LICENSE_OK && licenseInfo.linked_to_pc) { - CSimpleIniA ini; - SI_Error rc = ini.LoadFile(licLocation.c_str()); - string IDinLicense = ini.GetValue("example", "client_signature", ""); - if (IDinLicense == "") { - cout << "No client signature in license file, generate license with -s <id>"; + LicenseInfo licenseInfo; + EVENT_TYPE result = acquire_license("example", nullptr, &licenseInfo); + + if (result == LICENSE_OK) { + //for this example we want to link the license to the execution hardware. + if (licenseInfo.linked_to_pc) { + cout + << "No client signature in license file, generate license with -s <id>"; result = IDENTIFIERS_MISMATCH; - } else if (IDinLicense != signature) { - result = IDENTIFIERS_MISMATCH; + } else { + cout << "license OK" << endl; + } + } + if (result != LICENSE_OK) { + cout << "license ERROR :" << endl; + cout << " " << stringByEventType[result].c_str() << endl; + if (result == IDENTIFIERS_MISMATCH) { + PcSignature signature; + FUNCTION_RETURN generate_ok = generate_user_pc_signature(signature, + DEFAULT); + cout << "the pc signature is :" << endl; + cout << " " << signature << endl; } } - if (result != LICENSE_OK) { - cout << "license ERROR :" << endl; - cout << " " << stringByEventType[result].c_str() << endl; - cout << "the pc signature is :" << endl; - cout << " " << signature << endl; - } - else - cout << "license OK" << endl; + return result; } diff --git a/src/library/CMakeLists.txt b/src/library/CMakeLists.txt index 2fe7c85..0589736 100644 --- a/src/library/CMakeLists.txt +++ b/src/library/CMakeLists.txt @@ -15,6 +15,7 @@ ini locators os + base ) install(TARGETS licensecc_static ARCHIVE DESTINATION lib) diff --git a/src/library/LicenseReader.cpp b/src/library/LicenseReader.cpp index 7c020b1..84de09d 100644 --- a/src/library/LicenseReader.cpp +++ b/src/library/LicenseReader.cpp @@ -52,35 +52,42 @@ extra_data(extra_data) { } -EventRegistry FullLicenseInfo::validate(int sw_version) { - EventRegistry er; +bool FullLicenseInfo::validate(int sw_version, + EventRegistry &eventRegistryOut) { os_initialize(); const FUNCTION_RETURN sigVer = verifySignature(printForSign().c_str(), license_signature.c_str()); - const bool sigVerified = sigVer == FUNC_RET_OK; - if (sigVerified) { - er.addEvent(LICENSE_VERIFIED, SVRT_INFO); + bool is_valid = (sigVer == FUNC_RET_OK); + if (is_valid) { + eventRegistryOut.addEvent(SIGNATURE_VERIFIED, source); } else { - er.addEvent(LICENSE_CORRUPTED, SVRT_ERROR); + eventRegistryOut.addEvent(LICENSE_CORRUPTED, source); } if (has_expiry) { + cout<<source<<endl; const time_t now = time(nullptr); if (expires_on() < now) { - er.addEvent(PRODUCT_EXPIRED, SVRT_ERROR, ""); +/* + eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(), + string("Expired on: " + this->to_date).c_str());*/ + eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),nullptr); + is_valid = false; } if (valid_from() > now) { - er.addEvent(PRODUCT_EXPIRED, SVRT_ERROR); + /*eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(), + string("Valid from " + this->from_date).c_str());*/ + eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),nullptr); + is_valid = false; } } if (has_client_sig) { PcSignature str_code; strncpy(str_code, client_signature.c_str(), sizeof(str_code) - 1); const EVENT_TYPE event = validate_pc_signature(str_code); - if (event != LICENSE_OK) { - er.addEvent(event, SVRT_ERROR); - } + eventRegistryOut.addEvent(event, source); + is_valid = is_valid && (event == LICENSE_OK); } - return er; + return is_valid; } void FullLicenseInfo::toLicenseInfo(LicenseInfo *license) const { @@ -102,7 +109,7 @@ } } -LicenseReader::LicenseReader(const LicenseLocation &licenseLocation) : +LicenseReader::LicenseReader(const LicenseLocation* licenseLocation) : licenseLocation(licenseLocation) { } @@ -110,48 +117,39 @@ vector<FullLicenseInfo> &licenseInfoOut) { vector<string> diskFiles; vector<unique_ptr<locate::LocatorStrategy>> locator_strategies; - FUNCTION_RETURN ret = locate::LocatorFactory::getActiveStrategies( - locator_strategies, licenseLocation.licenseFileLocation); + FUNCTION_RETURN ret = locate::LocatorFactory::get_active_strategies( + locator_strategies, licenseLocation); EventRegistry eventRegistry; if (ret != FUNC_RET_OK) { - eventRegistry.addError(LICENSE_FILE_NOT_FOUND); + eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND); + eventRegistry.turnWarningsIntoErrors(); return eventRegistry; } - if (!eventRegistry.isGood()) { - return eventRegistry; - } - bool atLeastOneFileFound = false; - bool atLeastOneFileRecognized = false; - bool atLeastOneProductLicensed = false; bool atLeastOneLicenseComplete = false; - for (unique_ptr<locate::LocatorStrategy>& locator : locator_strategies) { - vector<string> licenseLocations = locator->licenseLocations( + for (unique_ptr<locate::LocatorStrategy> &locator : locator_strategies) { + vector<string> licenseLocations = locator->license_locations( eventRegistry); if (licenseLocations.size() == 0) { continue; } - atLeastOneFileFound = true; CSimpleIniA ini; for (auto it = licenseLocations.begin(); it != licenseLocations.end(); it++) { ini.Reset(); - string license = locator->retrieveLicense((*it).c_str()); + string license = locator->retrieve_license_content((*it).c_str()); const SI_Error rc = ini.LoadData(license.c_str(), license.size()); if (rc < 0) { - eventRegistry.addEvent(FILE_FORMAT_NOT_RECOGNIZED, SVRT_WARN, - *it); + eventRegistry.addEvent(FILE_FORMAT_NOT_RECOGNIZED, *it); continue; - } else { - atLeastOneFileRecognized = true; } const char *productNamePtr = product.c_str(); const int sectionSize = ini.GetSectionSize(productNamePtr); if (sectionSize <= 0) { - eventRegistry.addEvent(PRODUCT_NOT_LICENSED, SVRT_WARN, *it); + eventRegistry.addEvent(PRODUCT_NOT_LICENSED, *it); continue; } else { - atLeastOneProductLicensed = true; + eventRegistry.addEvent(PRODUCT_FOUND, *it); } /* * sw_version_from = (optional int) @@ -193,19 +191,12 @@ licenseInfoOut.push_back(licInfo); atLeastOneLicenseComplete = true; } else { - eventRegistry.addEvent(LICENSE_MALFORMED, SVRT_WARN, *it); + eventRegistry.addEvent(LICENSE_MALFORMED, *it); } } } - if (!atLeastOneFileFound) { - eventRegistry.turnEventIntoError(ENVIRONMENT_VARIABLE_NOT_DEFINED); - eventRegistry.turnEventIntoError(LICENSE_FILE_NOT_FOUND); - } else if (!atLeastOneFileRecognized) { - eventRegistry.turnEventIntoError(FILE_FORMAT_NOT_RECOGNIZED); - } else if (!atLeastOneProductLicensed) { - eventRegistry.turnEventIntoError(PRODUCT_NOT_LICENSED); - } else if (!atLeastOneLicenseComplete) { - eventRegistry.turnEventIntoError(LICENSE_MALFORMED); + if (!atLeastOneLicenseComplete) { + eventRegistry.turnWarningsIntoErrors(); } return eventRegistry; } diff --git a/src/library/LicenseReader.hpp b/src/library/LicenseReader.hpp index c42be92..661bd05 100644 --- a/src/library/LicenseReader.hpp +++ b/src/library/LicenseReader.hpp @@ -2,55 +2,53 @@ * LicenseReader.h * * Created on: Mar 30, 2014 - * + * */ #ifndef LICENSEREADER_H_ #define LICENSEREADER_H_ +#include <string> +#include <ctime> +#define SI_SUPPORT_IOSTREAMS #include "api/datatypes.h" #include "base/EventRegistry.h" #include "os/os.h" -#include "locate/LocatorStrategy.hpp" -#define SI_SUPPORT_IOSTREAMS #include "ini/SimpleIni.h" -#include <string> -#include <ctime> -namespace license { -using namespace std; +namespace license { class FullLicenseInfo { public: - string source; - string product; - string license_signature; + std::string source; + std::string product; + std::string license_signature; int license_version; - string from_date; - string to_date; + std::string from_date; + std::string to_date; bool has_expiry; unsigned int from_sw_version; unsigned int to_sw_version; bool has_versions; - string client_signature; + std::string client_signature; bool has_client_sig; - string extra_data; + std::string extra_data; static const char* UNUSED_TIME; static const unsigned int UNUSED_SOFTWARE_VERSION = 0; - FullLicenseInfo(const string& source, const string& product, - const string& license_signature, int licenseVersion, - string from_date = UNUSED_TIME, - string to_date = UNUSED_TIME, // - const string& client_signature = "", // + FullLicenseInfo(const std::string& source, const std::string& product, + const std::string& license_signature, int licenseVersion, + std::string from_date = UNUSED_TIME, + std::string to_date = UNUSED_TIME, // + const std::string& client_signature = "", // unsigned int from_sw_version = UNUSED_SOFTWARE_VERSION, unsigned int to_sw_version = UNUSED_SOFTWARE_VERSION, - const string& extra_data = ""); - string printForSign() const; - void printAsIni(ostream & a_ostream) const; + const std::string& extra_data = ""); + std::string printForSign() const; + void printAsIni(std::ostream & a_ostream) const; void toLicenseInfo(LicenseInfo* license) const; - EventRegistry validate(int sw_version); + bool validate(int sw_version, EventRegistry& eventRegistryOut); time_t expires_on() const; time_t valid_from() const; }; @@ -67,19 +65,19 @@ * sw_version_to = (optional int) * from_date = YYYY-MM-DD (optional) * to_date = YYYY-MM-DD (optional) - * client_signature = XXXXXXXX (optional string 16) + * client_signature = XXXXXXXX (optional std::string 16) * license_signature = XXXXXXXXXX (mandatory, 1024) - * application_data = xxxxxxxxx (optional string 16) + * application_data = xxxxxxxxx (optional std::string 16) * license_version = 100 (mandatory int) * </pre> */ class LicenseReader { private: - const LicenseLocation licenseLocation; + const LicenseLocation* licenseLocation; public: - LicenseReader(const LicenseLocation& licenseLocation); - EventRegistry readLicenses(const string &product, - vector<FullLicenseInfo>& licenseInfoOut); + LicenseReader(const LicenseLocation* licenseLocation); + EventRegistry readLicenses(const std::string &product, + std::vector<FullLicenseInfo>& licenseInfoOut); virtual ~LicenseReader(); }; } diff --git a/src/library/api/datatypes.h b/src/library/api/datatypes.h index 1eadf88..439f477 100644 --- a/src/library/api/datatypes.h +++ b/src/library/api/datatypes.h @@ -13,13 +13,18 @@ #ifdef __unix__ #define DllExport +#ifndef MAX_PATH + #define MAX_PATH 1024 +#endif #else #include <windows.h> #define DllExport __declspec( dllexport ) #endif + #define PC_IDENTIFIER_SIZE 18 #define PROPRIETARY_DATA_SIZE 16 +#define AUDIT_EVENT_NUM 5 #define LICENESE_INT_VERSION 110 #define LICENSEPP_VERSION "1.1.0" @@ -36,8 +41,10 @@ LICENSE_CORRUPTED = 8, //License signature didn't match with current license IDENTIFIERS_MISMATCH = 9, //Calculated identifier and the one provided in license didn't match - LICENSE_FILE_FOUND = 100, - LICENSE_VERIFIED = 101 + LICENSE_SPECIFIED = 100, //license location was specified + LICENSE_FOUND = 101, //License file has been found or license data has been located + PRODUCT_FOUND = 102, //License has been loaded and the declared product has been found + SIGNATURE_VERIFIED = 103 } EVENT_TYPE; @@ -52,23 +59,40 @@ typedef struct { SEVERITY severity; EVENT_TYPE event_type; - char param1[256]; + /** + * License file name or location where the license is stored. + */ + char license_reference[MAX_PATH]; char param2[256]; } AuditEvent; +/** + * This structure contains informations on the raw license data. Software authors + * can specify the location of the license file or its full content. + * + * Can be NULL, in this case OpenLicenseManager will try to figure out the + * license file location on its own. + */ typedef struct { + /** + * A list of absolute path separated by ';' containing the eventual location + * of the license files. Can be NULL. + */ const char *licenseFileLocation; - const char *environmentVariableName; - bool openFileNearModule; + /** + * The application can provide the full license content through this string. + * It can be both in encoded form (base64) or in plain. It's optional. + */ + const char *licenseData; } LicenseLocation; typedef struct { /** * Detailed reason of success/failure. Reasons for a failure can be * multiple (for instance, license expired and signature not verified). - * Only the last 5 are reported. + * Only the last AUDIT_EVENT_NUM are reported. */ - AuditEvent status[5]; + AuditEvent status[AUDIT_EVENT_NUM]; /** * Eventual expiration date of the software, * can be '\0' if the software don't expire diff --git a/src/library/api/license++.h b/src/library/api/license++.h index 185a3f3..ef1fbb6 100644 --- a/src/library/api/license++.h +++ b/src/library/api/license++.h @@ -3,22 +3,9 @@ /* * This include file is the public api di License++ - * You should include this file if your software don't plan to use - * the part of the library dealing with features. - * Otherwise licensepp-features.h should be included. - */ +*/ #ifdef __cplusplus extern "C" { -#endif - -#ifdef __unix__ -#define DllExport -#ifndef MAX_PATH - #define MAX_PATH 1024 -#endif -#else -#include <windows.h> -#define DllExport __declspec( dllexport ) #endif #include "datatypes.h" @@ -53,7 +40,7 @@ */ EVENT_TYPE acquire_license(const char * productName, - LicenseLocation licenseLocation, LicenseInfo* license); + const LicenseLocation* licenseLocation, LicenseInfo* license); /** * Do nothing for now, useful for network licenses. @@ -61,7 +48,7 @@ * license. */ EVENT_TYPE confirm_license(char * featureName, - LicenseLocation licenseLocation); + LicenseLocation* licenseLocation); /** * Do nothing for now, useful for network licenses. */ diff --git a/src/library/base/CMakeLists.txt b/src/library/base/CMakeLists.txt index ab0a196..0a61fdf 100644 --- a/src/library/base/CMakeLists.txt +++ b/src/library/base/CMakeLists.txt @@ -3,6 +3,7 @@ StringUtils.cpp FileUtils.cpp logger.c + base64.c ) add_dependencies( base public_key ) diff --git a/src/library/base/EventRegistry.cpp b/src/library/base/EventRegistry.cpp index 389ee42..ec9d4c1 100644 --- a/src/library/base/EventRegistry.cpp +++ b/src/library/base/EventRegistry.cpp @@ -2,106 +2,151 @@ * EventRegistry.cpp * * Created on: Mar 30, 2014 - * + * */ -#include "EventRegistry.h" #include <cstddef> #include <string.h> #include <algorithm> +#include <map> +#include <iostream> + +#include "EventRegistry.h" +#define LIC_ID_NOT_DEFINED "UNDEF" namespace license { using namespace std; +const map<EVENT_TYPE, int> PROGRESS_BY_EVENT_TYPE = { { LICENSE_SPECIFIED, 0 }, + { LICENSE_FOUND, 1 }, { PRODUCT_FOUND, 2 }, { SIGNATURE_VERIFIED, 3 }, { + LICENSE_OK, 4 } }; + EventRegistry::EventRegistry() { + current_validation_step = -1; } -EventRegistry& operator<<(EventRegistry& eventRegistry, - AuditEvent& securityEvent) { +EventRegistry& operator<<(EventRegistry &eventRegistry, + AuditEvent &securityEvent) { eventRegistry.logs.push_back(securityEvent); return eventRegistry; } -EventRegistry& operator<<(EventRegistry& eventRegistry1, - EventRegistry& otherRegistry) { +EventRegistry& operator<<(EventRegistry &eventRegistry1, + EventRegistry &otherRegistry) { eventRegistry1.append(otherRegistry); return eventRegistry1; } -void EventRegistry::append(const EventRegistry& eventRegistry) { +ostream& operator<<(std::ostream &out, const EventRegistry &er) { + out << string("EventReg[step:") << er.current_validation_step + << ",events:{"; + for (auto &it : er.logs) { + out << "[ev:" << it.event_type << ",sev:" << it.severity << "ref:" + << it.license_reference << "]"; + } + out << "]"; + return out; +} + +void EventRegistry::append(const EventRegistry &eventRegistry) { logs.insert(logs.end(), eventRegistry.logs.begin(), eventRegistry.logs.end()); } -void EventRegistry::turnLastEventIntoError() { - if (logs.size() > 0) { - logs.back().severity = SVRT_ERROR; +AuditEvent const* EventRegistry::getLastFailure() const { + const AuditEvent *result = nullptr; + if (logs.size() == 0) { + return result; + } + //try to find a failure between the licenses who progressed the most + if (mostAdvancedLogIdx_by_LicenseId.size() > 0) { + for (auto const &mostAdvLogIter : mostAdvancedLogIdx_by_LicenseId) { + const AuditEvent ¤tLog = logs[mostAdvLogIter.second]; + if (currentLog.severity == SVRT_ERROR) { + result = &(currentLog); + break; + } + } + } + if (result == nullptr) { + auto it = logs.end(); + do { + --it; + if (it->severity == SVRT_ERROR) { + result = &(*it); + break; + } + } while (it != logs.begin()); + } + return result; +} + +void EventRegistry::addEvent(EVENT_TYPE event, + const std::string &licenseLocationId) { + addEvent(event, licenseLocationId.c_str(), nullptr); +} + +void EventRegistry::addEvent(EVENT_TYPE event, const char *licenseLocationId, + const char *info) { + AuditEvent audit; + auto eventIterator = PROGRESS_BY_EVENT_TYPE.find(event); + bool successEvent = (eventIterator != PROGRESS_BY_EVENT_TYPE.end()); + audit.severity = successEvent ? SVRT_INFO : SVRT_WARN; + audit.event_type = event; + if (licenseLocationId == nullptr) { + strcpy(audit.license_reference, LIC_ID_NOT_DEFINED); + } else { + strncpy(audit.license_reference, licenseLocationId, MAX_PATH); + } + if (info == nullptr) { + audit.param2[0] = '\0'; + } else { + strncpy(audit.param2, info, 255); + } + logs.push_back(audit); +//udpate the status of the log + if (successEvent) { + int step = eventIterator->second; + if (step > current_validation_step) { + mostAdvancedLogIdx_by_LicenseId.clear(); + current_validation_step = step; + } + + if (step == current_validation_step) { + mostAdvancedLogIdx_by_LicenseId[audit.license_reference] = + logs.size() - 1; + } + } else if (mostAdvancedLogIdx_by_LicenseId.find(audit.license_reference) + != mostAdvancedLogIdx_by_LicenseId.end()) { + mostAdvancedLogIdx_by_LicenseId[audit.license_reference] = logs.size() + - 1; } } -bool EventRegistry::turnEventIntoError(EVENT_TYPE event) { +bool EventRegistry::turnWarningsIntoErrors() { bool eventFound = false; - for (auto it = logs.begin(); it != logs.end(); ++it) { - if (it->event_type == event) { - it->severity = SVRT_ERROR; - eventFound = true; + if (mostAdvancedLogIdx_by_LicenseId.size() > 0) { + for (auto const &mostAdvLogIter : mostAdvancedLogIdx_by_LicenseId) { + AuditEvent ¤tLog = logs[mostAdvLogIter.second]; + if (currentLog.severity == SVRT_WARN + || currentLog.severity == SVRT_ERROR) { + currentLog.severity = SVRT_ERROR; + eventFound = true; + } + } + } + if (!eventFound) { + for (auto it = logs.begin(); it != logs.end(); ++it) { + if (it->severity == SVRT_WARN) { + it->severity = SVRT_ERROR; + eventFound = true; + } } } return eventFound; } -AuditEvent const * EventRegistry::getLastFailure() const { - const AuditEvent* result = nullptr; - if (logs.size() == 0) { - return result; - } - auto it = logs.end(); - do { - --it; - if (it->severity == SVRT_ERROR) { - result = &(*it); - break; - } - } while (it != logs.begin()); - return result; - -} - -bool EventRegistry::isGood() const { - bool isGood = true; - for (auto it = logs.begin(); it != logs.end(); ++it) { - if (it->severity == SVRT_ERROR) { - isGood = false; - break; - } - } - return isGood; -} - -void EventRegistry::addError(EVENT_TYPE event) { - this->addEvent(event, SVRT_ERROR); -} - -void EventRegistry::addEvent(EVENT_TYPE event, SEVERITY severity) { - AuditEvent audit; - audit.severity = severity; - audit.event_type = event; - audit.param1[0] = '\0'; - audit.param2[0] = '\0'; - logs.push_back(audit); -} - -void EventRegistry::addEvent(EVENT_TYPE event, SEVERITY severity, - const string& eventParameter) { - AuditEvent audit; - audit.severity = severity; - audit.event_type = event; - strncpy(audit.param1, eventParameter.c_str(), 255); - audit.param2[0] = '\0'; - logs.push_back(audit); -} - -bool EventRegistry::turnErrosIntoWarnings() { +bool EventRegistry::turnErrorsIntoWarnings() { bool eventFound = false; for (auto it = logs.begin(); it != logs.end(); ++it) { if (it->severity == SVRT_ERROR) { @@ -112,9 +157,14 @@ return eventFound; } -void EventRegistry::exportLastEvents(AuditEvent* auditEvents, int nlogs) { +void EventRegistry::exportLastEvents(AuditEvent *auditEvents, int nlogs) { const int sizeToCopy = min(nlogs, (int) logs.size()); - std::copy(logs.begin(), logs.begin() + sizeToCopy, auditEvents); + std::copy(logs.end() - sizeToCopy, logs.end(), auditEvents); } + +bool EventRegistry::isGood() const { + return getLastFailure() == nullptr; +} + } diff --git a/src/library/base/EventRegistry.h b/src/library/base/EventRegistry.h index c8bc3b9..f5fec62 100644 --- a/src/library/base/EventRegistry.h +++ b/src/library/base/EventRegistry.h @@ -2,7 +2,7 @@ * EventRegistry.h * * Created on: Mar 30, 2014 - * + * */ #ifndef EVENTREGISTRY_H_ @@ -10,43 +10,51 @@ #include "../api/datatypes.h" #include <vector> +#include <map> +#include <set> #include <string> namespace license { -/* - AuditEvent error_event_builder(EVENT_TYPE event); - AuditEvent audit_event_builder(EVENT_TYPE event, SEVERITY severity); - AuditEvent audit_event_builder(EVENT_TYPE event, SEVERITY severity, - const string& eventParameter);*/ - +/** + * Tracks the events relative to a license and provide explanation regarding + * failures to verify licenses. + */ class EventRegistry { private: friend EventRegistry& operator<<(EventRegistry&, AuditEvent&); friend EventRegistry& operator<<(EventRegistry&, EventRegistry&); - //TODO change into map + friend std::ostream & operator << (std::ostream &out, const EventRegistry &er); + std::vector<AuditEvent> logs; - //Forbid copy - //EventRegistry(const EventRegistry& that) = delete; + /** + * For every license keep track of the events who progressed most + * in the validation process + */ + std::map<std::string,int> mostAdvancedLogIdx_by_LicenseId; + int current_validation_step; + public: EventRegistry(); //operator << void append(const EventRegistry &eventRegistry); - void turnLastEventIntoError(); - bool turnEventIntoError(EVENT_TYPE event); - bool turnErrosIntoWarnings(); /** + * Turn the event warning for the license with the most advanced status + * into an error. + */ + bool turnWarningsIntoErrors(); + bool turnErrorsIntoWarnings(); + bool isGood() const; + /** + * Return the last failure (event with warn or error status) + * for the license with the most advanced status. * @return NULL if no failures are found. */ AuditEvent const* getLastFailure() const; - bool isGood() const; - - void addError(EVENT_TYPE event); - void addEvent(EVENT_TYPE event, SEVERITY severity); - void addEvent(EVENT_TYPE event, SEVERITY severity, - const std::string &eventParameter); + void addEvent(EVENT_TYPE event, const std::string &licenseLocationId); + void addEvent(EVENT_TYPE event, const char *licenseLocationId = nullptr, + const char *info = nullptr); void exportLastEvents(AuditEvent *auditEvents, int nlogs); - }; } #endif /* EVENTREGISTRY_H_ */ diff --git a/src/library/base/FileUtils.cpp b/src/library/base/FileUtils.cpp index ff79406..f8fcc20 100644 --- a/src/library/base/FileUtils.cpp +++ b/src/library/base/FileUtils.cpp @@ -9,19 +9,24 @@ #include <string> #include <cerrno> #include <iostream> -#include <algorithm> +#include <algorithm> #include "FileUtils.hpp" namespace license { using namespace std; -vector<string> filter_existing_files(const vector<string> &fileList) { +vector<string> filter_existing_files(const vector<string> &fileList, + EventRegistry& registry,const char* extraData) { vector<string> existingFiles; for (auto it = fileList.begin(); it != fileList.end(); it++) { + registry.addEvent(LICENSE_SPECIFIED,it->c_str(), extraData); ifstream f(it->c_str()); if (f.good()) { existingFiles.push_back(*it); + registry.addEvent(LICENSE_FOUND,it->c_str(),extraData); + } else { + registry.addEvent(LICENSE_FILE_NOT_FOUND,it->c_str(), extraData); } f.close(); } @@ -57,7 +62,7 @@ return (dotpos == 0 ? path : path.substr(0, dotpos)); } else if(pathsep_pos >= dotpos +1) { return path; - } + } return path.substr(0, dotpos); } diff --git a/src/library/base/FileUtils.hpp b/src/library/base/FileUtils.hpp index ac73a3a..e6f9e9e 100644 --- a/src/library/base/FileUtils.hpp +++ b/src/library/base/FileUtils.hpp @@ -2,17 +2,18 @@ * FileUtils.h * * Created on: Apr 8, 2019 - * + * */ #ifndef FILEUTILS_H_ #define FILEUTILS_H_ #include <string> #include <vector> +#include "EventRegistry.h" namespace license { -std::vector<std::string> filter_existing_files(const std::vector<std::string>& fileList); +std::vector<std::string> filter_existing_files(const std::vector<std::string>& fileList,EventRegistry& registry, const char* extraData); std::string get_file_contents(const char *filename,size_t max_size); std::string remove_extension(const std::string& path); diff --git a/src/library/base/StringUtils.cpp b/src/library/base/StringUtils.cpp index 3e34432..cf9da96 100644 --- a/src/library/base/StringUtils.cpp +++ b/src/library/base/StringUtils.cpp @@ -2,17 +2,18 @@ * StringUtils.cpp * * Created on: Apr 8, 2014 - * + * */ #include <cctype> //toupper -#include "StringUtils.h" #include <iostream> #include <string> #include <sstream> #include <cstring> #include <algorithm> #include <stdexcept> +#include <regex> +#include "StringUtils.h" #ifdef _WIN32 #include <time.h> //mktime under windows @@ -21,7 +22,7 @@ namespace license { using namespace std; -string trim_copy(const string& string_to_trim) { +string trim_copy(const string &string_to_trim) { std::string::const_iterator it = string_to_trim.begin(); while (it != string_to_trim.end() && isspace(*it)) it++; @@ -33,13 +34,13 @@ return std::string(it, rit.base()); } -string toupper_copy(const string& lowercase) { +string toupper_copy(const string &lowercase) { string cp(lowercase); - std::transform(cp.begin(), cp.end(), cp.begin(), (int (*)(int))toupper); + std::transform(cp.begin(), cp.end(), cp.begin(), (int (*)(int)) toupper); return cp; } -time_t seconds_from_epoch(const char* timeString) { +time_t seconds_from_epoch(const char *timeString) { int year, month, day; tm tm; if (strlen(timeString) == 8) { @@ -48,14 +49,16 @@ throw invalid_argument("Date not recognized"); } } else if (strlen(timeString) == 10) { - const int nfield = sscanf(timeString, "%4d-%2d-%2d", &year, &month, &day); + const int nfield = sscanf(timeString, "%4d-%2d-%2d", &year, &month, + &day); if (nfield != 3) { - const int nfield = sscanf(timeString, "%4d/%2d/%2d", &year, &month, &day); + const int nfield = sscanf(timeString, "%4d/%2d/%2d", &year, &month, + &day); if (nfield != 3) { throw invalid_argument("Date not recognized"); } } - } else{ + } else { throw invalid_argument("Date not recognized"); } tm.tm_isdst = -1; @@ -70,8 +73,8 @@ return mktime(&tm); } - -const vector<string> split_string(const string& licensePositions,char splitchar) { +const vector<string> split_string(const string &licensePositions, + char splitchar) { std::stringstream streamToSplit(licensePositions); std::string segment; std::vector<string> seglist; @@ -82,4 +85,18 @@ return seglist; } +const static regex iniSection("\\[.*?\\]"); +const static regex b64( + "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"); + +FILE_FORMAT identify_format(const string &license) { + FILE_FORMAT result = UNKNOWN; + if (regex_match(license, b64)) { + result = BASE64; + } else if (regex_search(license, iniSection)) { + result = INI; + } + return result; +} + } /* namespace license */ diff --git a/src/library/base/StringUtils.h b/src/library/base/StringUtils.h index a52376d..dee0526 100644 --- a/src/library/base/StringUtils.h +++ b/src/library/base/StringUtils.h @@ -2,11 +2,13 @@ * StringUtils.h * * Created on: Apr 8, 2014 - * + * */ #ifndef STRINGUTILS_H_ #define STRINGUTILS_H_ + +#include <bits/types/time_t.h> #include <string> #include <vector> @@ -28,7 +30,14 @@ /** * Split a string on a given character */ -const vector<string> split_string(const string& licensePositions, const char splitchar); +const vector<string> split_string(const string& stringToBeSplit, const char splitchar); + +typedef enum { + INI, BASE64, UNKNOWN +} FILE_FORMAT; + +FILE_FORMAT identify_format(const string& license); + } /* namespace license */ diff --git a/src/library/base/base64.c b/src/library/base/base64.c new file mode 100644 index 0000000..4d17d33 --- /dev/null +++ b/src/library/base/base64.c @@ -0,0 +1,133 @@ +#include <stdio.h> +#include <stdlib.h> + +const static char* b64 = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +// maps A=>0,B=>1.. +const static unsigned char unb64[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40 + 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, //50 + 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, //60 + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, //70 + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //80 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //90 + 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, //100 + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, //110 + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //120 + 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, //130 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //250 + 0, 0, 0, 0, 0, 0, }; // This array has 255 elements + +//review api +char* base64(const void* binaryData, int len, int *flen) { + const unsigned char* bin = (const unsigned char*) binaryData; + char* res; + + int rc = 0; // result counter + int byteNo; // I need this after the loop + + int modulusLen = len % 3; + int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0. + + *flen = 4 * (len + pad) / 3; + res = (char*) malloc(*flen + 1); // and one for the null + if (!res) { + puts("ERROR: base64 could not allocate enough memory."); + puts("I must stop because I could not get enough"); + return 0; + } + + for (byteNo = 0; byteNo <= len - 3; byteNo += 3) { + unsigned char BYTE0 = bin[byteNo]; + unsigned char BYTE1 = bin[byteNo + 1]; + unsigned char BYTE2 = bin[byteNo + 2]; + res[rc++] = b64[BYTE0 >> 2]; + res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)]; + res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)]; + res[rc++] = b64[0x3f & BYTE2]; + } + + if (pad == 2) { + res[rc++] = b64[bin[byteNo] >> 2]; + res[rc++] = b64[(0x3 & bin[byteNo]) << 4]; + res[rc++] = '='; + res[rc++] = '='; + } else if (pad == 1) { + res[rc++] = b64[bin[byteNo] >> 2]; + res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)]; + res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2]; + res[rc++] = '='; + } + + res[rc] = 0; // NULL TERMINATOR! ;) + return res; +} + +unsigned char* unbase64(const char* ascii, int len, int *flen) { + const unsigned char *safeAsciiPtr = (const unsigned char*) ascii; + unsigned char *bin; + int cb = 0; + int charNo; + int pad = 0; + + if (len < 2) { // 2 accesses below would be OOB. + // catch empty string, return NULL as result. + puts( + "ERROR: You passed an invalid base64 string (too short). You get NULL back."); + *flen = 0; + return 0; + } + if (safeAsciiPtr[len - 1] == '=') + ++pad; + if (safeAsciiPtr[len - 2] == '=') + ++pad; + + *flen = 3 * len / 4 - pad; + bin = (unsigned char*) malloc(*flen); + if (!bin) { + puts("ERROR: unbase64 could not allocate enough memory."); + puts("I must stop because I could not get enough"); + return 0; + } + + for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) { + int A = unb64[safeAsciiPtr[charNo]]; + int B = unb64[safeAsciiPtr[charNo + 1]]; + int C = unb64[safeAsciiPtr[charNo + 2]]; + int D = unb64[safeAsciiPtr[charNo + 3]]; + + bin[cb++] = (A << 2) | (B >> 4); + bin[cb++] = (B << 4) | (C >> 2); + bin[cb++] = (C << 6) | (D); + } + + if (pad == 1) { + int A = unb64[safeAsciiPtr[charNo]]; + int B = unb64[safeAsciiPtr[charNo + 1]]; + int C = unb64[safeAsciiPtr[charNo + 2]]; + + bin[cb++] = (A << 2) | (B >> 4); + bin[cb++] = (B << 4) | (C >> 2); + } else if (pad == 2) { + int A = unb64[safeAsciiPtr[charNo]]; + int B = unb64[safeAsciiPtr[charNo + 1]]; + + bin[cb++] = (A << 2) | (B >> 4); + } + + return bin; +} diff --git a/src/library/base/base64.h b/src/library/base/base64.h index 27f49cd..9a353df 100644 --- a/src/library/base/base64.h +++ b/src/library/base/base64.h @@ -31,140 +31,14 @@ #ifndef BASE64_H #define BASE64_H -#include <stdio.h> -#include <stdlib.h> +#ifdef __cplusplus +extern "C" { +#endif -const static char* b64 = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +unsigned char* unbase64(const char* ascii, int len, int *flen); +char* base64(const void* binaryData, int len, int *flen); -// maps A=>0,B=>1.. -const static unsigned char unb64[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40 - 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, //50 - 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, //60 - 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, //70 - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //80 - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //90 - 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, //100 - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, //110 - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //120 - 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, //130 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //250 - 0, 0, 0, 0, 0, 0, }; // This array has 255 elements - -// Converts binary data of length=len to base64 characters. -// Length of the resultant string is stored in flen -// (you must pass pointer flen). -char* base64(const void* binaryData, int len, int *flen) { - const unsigned char* bin = (const unsigned char*) binaryData; - char* res; - - int rc = 0; // result counter - int byteNo; // I need this after the loop - - int modulusLen = len % 3; - int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0. - - *flen = 4 * (len + pad) / 3; - res = (char*) malloc(*flen + 1); // and one for the null - if (!res) { - puts("ERROR: base64 could not allocate enough memory."); - puts("I must stop because I could not get enough"); - return 0; - } - - for (byteNo = 0; byteNo <= len - 3; byteNo += 3) { - unsigned char BYTE0 = bin[byteNo]; - unsigned char BYTE1 = bin[byteNo + 1]; - unsigned char BYTE2 = bin[byteNo + 2]; - res[rc++] = b64[BYTE0 >> 2]; - res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)]; - res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)]; - res[rc++] = b64[0x3f & BYTE2]; - } - - if (pad == 2) { - res[rc++] = b64[bin[byteNo] >> 2]; - res[rc++] = b64[(0x3 & bin[byteNo]) << 4]; - res[rc++] = '='; - res[rc++] = '='; - } else if (pad == 1) { - res[rc++] = b64[bin[byteNo] >> 2]; - res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)]; - res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2]; - res[rc++] = '='; - } - - res[rc] = 0; // NULL TERMINATOR! ;) - return res; +#ifdef __cplusplus } - -unsigned char* unbase64(const char* ascii, int len, int *flen) { - const unsigned char *safeAsciiPtr = (const unsigned char*) ascii; - unsigned char *bin; - int cb = 0; - int charNo; - int pad = 0; - - if (len < 2) { // 2 accesses below would be OOB. - // catch empty string, return NULL as result. - puts( - "ERROR: You passed an invalid base64 string (too short). You get NULL back."); - *flen = 0; - return 0; - } - if (safeAsciiPtr[len - 1] == '=') - ++pad; - if (safeAsciiPtr[len - 2] == '=') - ++pad; - - *flen = 3 * len / 4 - pad; - bin = (unsigned char*) malloc(*flen); - if (!bin) { - puts("ERROR: unbase64 could not allocate enough memory."); - puts("I must stop because I could not get enough"); - return 0; - } - - for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) { - int A = unb64[safeAsciiPtr[charNo]]; - int B = unb64[safeAsciiPtr[charNo + 1]]; - int C = unb64[safeAsciiPtr[charNo + 2]]; - int D = unb64[safeAsciiPtr[charNo + 3]]; - - bin[cb++] = (A << 2) | (B >> 4); - bin[cb++] = (B << 4) | (C >> 2); - bin[cb++] = (C << 6) | (D); - } - - if (pad == 1) { - int A = unb64[safeAsciiPtr[charNo]]; - int B = unb64[safeAsciiPtr[charNo + 1]]; - int C = unb64[safeAsciiPtr[charNo + 2]]; - - bin[cb++] = (A << 2) | (B >> 4); - bin[cb++] = (B << 4) | (C >> 2); - } else if (pad == 2) { - int A = unb64[safeAsciiPtr[charNo]]; - int B = unb64[safeAsciiPtr[charNo + 1]]; - - bin[cb++] = (A << 2) | (B >> 4); - } - - return bin; -} - +#endif #endif diff --git a/src/library/license++.cpp b/src/library/license++.cpp index 3e4ae40..b702d51 100644 --- a/src/library/license++.cpp +++ b/src/library/license++.cpp @@ -1,6 +1,6 @@ //============================================================================ // Name : license-manager-cpp.cpp -// Author : +// Author : // Version : // Copyright : BSD //============================================================================ @@ -9,6 +9,7 @@ #include <stdio.h> #include <stdlib.h> #include <cstring> +#include <iostream> #include "api/license++.h" @@ -41,7 +42,7 @@ } EVENT_TYPE acquire_license(const char * product, - LicenseLocation licenseLocation, LicenseInfo* license) { + const LicenseLocation* licenseLocation, LicenseInfo* licenseInfoOut) { license::LicenseReader lr = license::LicenseReader(licenseLocation); vector<license::FullLicenseInfo> licenses; license::EventRegistry er = lr.readLicenses(string(product), licenses); @@ -50,28 +51,32 @@ vector<license::FullLicenseInfo> licenses_with_errors; vector<license::FullLicenseInfo> licenses_ok; for (auto it = licenses.begin(); it != licenses.end(); it++) { - license::EventRegistry validation_er = it->validate(0); - if (validation_er.isGood()) { + bool valid = it->validate(0,er); + if (valid) { licenses_ok.push_back(*it); } else { licenses_with_errors.push_back(*it); } - er.append(validation_er); } if (licenses_ok.size() > 0) { - er.turnErrosIntoWarnings(); + er.turnErrorsIntoWarnings(); result = LICENSE_OK; - mergeLicenses(licenses_ok, license); + mergeLicenses(licenses_ok, licenseInfoOut); } else { + er.turnWarningsIntoErrors(); result = er.getLastFailure()->event_type; - mergeLicenses(licenses_with_errors, license); + mergeLicenses(licenses_with_errors, licenseInfoOut); } } else { + er.turnWarningsIntoErrors(); result = er.getLastFailure()->event_type; } - if (license != nullptr) { - er.exportLastEvents(license->status, 5); +#ifdef _DEBUG + cout << er <<endl; +#endif + if (licenseInfoOut != nullptr) { + er.exportLastEvents(licenseInfoOut->status, AUDIT_EVENT_NUM); } return result; } diff --git a/src/library/locate/ApplicationFolder.cpp b/src/library/locate/ApplicationFolder.cpp index 9ba99ee..b1fb0e3 100644 --- a/src/library/locate/ApplicationFolder.cpp +++ b/src/library/locate/ApplicationFolder.cpp @@ -23,18 +23,15 @@ namespace locate { using namespace std; - - ApplicationFolder::ApplicationFolder() : LocatorStrategy("ApplicationFolder") { - } ApplicationFolder::~ApplicationFolder() { } -const vector<string> ApplicationFolder::licenseLocations( - EventRegistry &eventRegistry) const { +const vector<string> ApplicationFolder::license_locations( + EventRegistry &eventRegistry) { vector<string> diskFiles; char fname[MAX_PATH] = { 0 }; const FUNCTION_RETURN fret = getModuleName(fname); @@ -44,11 +41,9 @@ ifstream f(temptativeLicense.c_str()); if (f.good()) { diskFiles.push_back(temptativeLicense); - eventRegistry.addEvent((EVENT_TYPE) LICENSE_FILE_FOUND, - (SEVERITY) SVRT_INFO, temptativeLicense); + eventRegistry.addEvent(LICENSE_FOUND, temptativeLicense.c_str()); } else { - eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, SVRT_WARN, - temptativeLicense); + eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, temptativeLicense.c_str()); } f.close(); } else { diff --git a/src/library/locate/ApplicationFolder.hpp b/src/library/locate/ApplicationFolder.hpp index b98182e..649d8da 100644 --- a/src/library/locate/ApplicationFolder.hpp +++ b/src/library/locate/ApplicationFolder.hpp @@ -18,7 +18,7 @@ class ApplicationFolder: public LocatorStrategy { public: ApplicationFolder(); - virtual const std::vector<std::string> licenseLocations(EventRegistry& eventRegistry) const; + virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistry); virtual ~ApplicationFolder(); }; diff --git a/src/library/locate/EnvironmentVarData.cpp b/src/library/locate/EnvironmentVarData.cpp index 844470e..616b948 100644 --- a/src/library/locate/EnvironmentVarData.cpp +++ b/src/library/locate/EnvironmentVarData.cpp @@ -6,6 +6,18 @@ */ #include "EnvironmentVarData.hpp" + +#include <build_properties.h> +#include <cstdlib> +#include <regex> +#include <string> +#include <vector> + +#include "../api/datatypes.h" +#include "../base/base64.h" +#include "../base/EventRegistry.h" +#include "../base/StringUtils.h" + namespace license { namespace locate { @@ -18,15 +30,37 @@ EnvironmentVarData::~EnvironmentVarData() { } -const vector<string> EnvironmentVarData::licenseLocations( - EventRegistry &eventRegistry) const { +const vector<string> EnvironmentVarData::license_locations( + EventRegistry &eventRegistry) { vector<string> diskFiles; - + char *env_var_value = getenv(LICENSE_DATA_ENV_VAR); + if (env_var_value != nullptr && env_var_value[0] != '\0') { + eventRegistry.addEvent(LICENSE_SPECIFIED, LICENSE_LOCATION_ENV_VAR); + FILE_FORMAT licenseFormat = identify_format(env_var_value); + if (licenseFormat == UNKNOWN) { + eventRegistry.addEvent(LICENSE_MALFORMED, LICENSE_LOCATION_ENV_VAR); + } else { + diskFiles.push_back(LICENSE_LOCATION_ENV_VAR); + isBase64 = (licenseFormat == BASE64); + } + } else { + eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED, + LICENSE_LOCATION_ENV_VAR); + } return diskFiles; } -const std::string EnvironmentVarData::retrieveLicense(const std::string &licenseLocation) const{ - return ""; +const std::string EnvironmentVarData::retrieve_license_content( + const std::string &licenseLocation) const { + string tmpVal = getenv(LICENSE_LOCATION_ENV_VAR); + if (isBase64) { + int flen = 0; + unsigned char *raw = unbase64(tmpVal.c_str(), tmpVal.length(), &flen); + string str = string(reinterpret_cast<char*>(raw)); + free(raw); + return str; + } + return tmpVal; } } diff --git a/src/library/locate/EnvironmentVarData.hpp b/src/library/locate/EnvironmentVarData.hpp index 1a1dd36..5698975 100644 --- a/src/library/locate/EnvironmentVarData.hpp +++ b/src/library/locate/EnvironmentVarData.hpp @@ -14,11 +14,12 @@ namespace locate { class EnvironmentVarData: public LocatorStrategy { private: + bool isBase64 = false; public: EnvironmentVarData(); - virtual const std::vector<std::string> licenseLocations(EventRegistry& eventRegistr) const; - virtual const std::string retrieveLicense(const std::string &licenseLocation) const; + virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistr); + virtual const std::string retrieve_license_content(const std::string &licenseLocation) const; virtual ~EnvironmentVarData(); }; diff --git a/src/library/locate/EnvironmentVarLocation.cpp b/src/library/locate/EnvironmentVarLocation.cpp index c8b23dc..a904b9a 100644 --- a/src/library/locate/EnvironmentVarLocation.cpp +++ b/src/library/locate/EnvironmentVarLocation.cpp @@ -22,8 +22,8 @@ EnvironmentVarLocation::~EnvironmentVarLocation() { } -const vector<string> EnvironmentVarLocation::licenseLocations( - EventRegistry &eventRegistry) const { +const vector<string> EnvironmentVarLocation::license_locations( + EventRegistry &eventRegistry) { vector<string> licenseFileFoundWithEnvVariable; const string varName(LICENSE_LOCATION_ENV_VAR); @@ -33,20 +33,10 @@ if (env_var_value != nullptr && env_var_value[0] != '\0') { const vector<string> declared_positions = license::split_string( string(env_var_value), ';'); - vector<string> existing_pos = license::filter_existing_files( - declared_positions); - if (existing_pos.size() > 0) { - for (auto it = existing_pos.begin(); it != existing_pos.end(); - ++it) { - licenseFileFoundWithEnvVariable.push_back(*it); - eventRegistry.addEvent(LICENSE_FILE_FOUND, SVRT_INFO, *it); - } - } else { - eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, SVRT_WARN, - env_var_value); - } + licenseFileFoundWithEnvVariable = license::filter_existing_files( + declared_positions, eventRegistry, LICENSE_LOCATION_ENV_VAR); } else { - eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED, SVRT_WARN); + eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED); } } return licenseFileFoundWithEnvVariable; diff --git a/src/library/locate/EnvironmentVarLocation.hpp b/src/library/locate/EnvironmentVarLocation.hpp index 7e5ef60..b2f9b6a 100644 --- a/src/library/locate/EnvironmentVarLocation.hpp +++ b/src/library/locate/EnvironmentVarLocation.hpp @@ -17,7 +17,7 @@ public: EnvironmentVarLocation(); - virtual const std::vector<std::string> licenseLocations(EventRegistry& eventRegistry) const; + virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistry); virtual ~EnvironmentVarLocation(); }; diff --git a/src/library/locate/ExternalDefinition.cpp b/src/library/locate/ExternalDefinition.cpp index af9af5e..ec0428f 100644 --- a/src/library/locate/ExternalDefinition.cpp +++ b/src/library/locate/ExternalDefinition.cpp @@ -5,36 +5,72 @@ * Author: Gabriele Contini */ -#include "../base/StringUtils.h" +#include <stdlib.h> +#include <cstring> +#include <string> +#include <vector> + +#include "../api/datatypes.h" +#include "../base/base64.h" +#include "../base/EventRegistry.h" #include "../base/FileUtils.hpp" +#include "../base/StringUtils.h" + #include "ExternalDefinition.hpp" namespace license { namespace locate { using namespace std; -ExternalDefinition::ExternalDefinition(const char *location) : +ExternalDefinition::ExternalDefinition(const LicenseLocation *location) : LocatorStrategy("ExternalDefinition"), m_location(location) { } ExternalDefinition::~ExternalDefinition() { } -const std::vector<std::string> ExternalDefinition::licenseLocations( - EventRegistry &eventRegistry) const { - const vector<string> declared_positions = license::split_string(m_location, - ';'); - const vector<string> existing_pos = license::filter_existing_files( - declared_positions); - if (existing_pos.size() > 0) { - for (auto it = existing_pos.begin(); it != existing_pos.end(); ++it) { - eventRegistry.addEvent(LICENSE_FILE_FOUND, SVRT_INFO, *it); +const std::vector<std::string> ExternalDefinition::license_locations( + EventRegistry &eventRegistry) { + vector<string> existing_pos; + if (m_location->licenseData != nullptr + && m_location->licenseData[0] != '\0') { + eventRegistry.addEvent(LICENSE_SPECIFIED, get_strategy_name()); + FILE_FORMAT licenseFormat = identify_format(m_location->licenseData); + + if (licenseFormat == UNKNOWN) { + eventRegistry.addEvent(LICENSE_MALFORMED, get_strategy_name()); + } else { + existing_pos.push_back(get_strategy_name()); + licenseDataIsBase64 = (licenseFormat == BASE64); } - } else { - eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, SVRT_WARN, m_location); + } + if (m_location->licenseFileLocation != nullptr + && strlen(m_location->licenseFileLocation) > 0) { + const vector<string> declared_positions = license::split_string( + m_location->licenseFileLocation, ';'); + existing_pos = license::filter_existing_files(declared_positions, + eventRegistry, get_strategy_name().c_str()); } return existing_pos; } +const std::string ExternalDefinition::retrieve_license_content( + const std::string &licenseLocation) const { + if (licenseLocation == get_strategy_name()) { + if (licenseDataIsBase64) { + int flen = 0; + unsigned char *raw = unbase64(m_location->licenseData, + strlen(m_location->licenseData), &flen); + string str = string(reinterpret_cast<char*>(raw)); + free(raw); + return str; + } else { + return m_location->licenseData; + } + } else { + return LocatorStrategy::retrieve_license_content(licenseLocation); + } +} + } /* namespace locate */ } /* namespace license */ diff --git a/src/library/locate/ExternalDefinition.hpp b/src/library/locate/ExternalDefinition.hpp index 3f50ee9..c70775a 100644 --- a/src/library/locate/ExternalDefinition.hpp +++ b/src/library/locate/ExternalDefinition.hpp @@ -15,10 +15,12 @@ class ExternalDefinition: public LocatorStrategy { private: - const std::string m_location; + const LicenseLocation* m_location; + bool licenseDataIsBase64 = false; public: - ExternalDefinition(const char* location); - virtual const std::vector<std::string> licenseLocations(EventRegistry& eventRegistry) const; + ExternalDefinition(const LicenseLocation* location); + virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistry); + virtual const std::string retrieve_license_content(const std::string &licenseLocation) const; virtual ~ExternalDefinition(); }; diff --git a/src/library/locate/LocatorFactory.cpp b/src/library/locate/LocatorFactory.cpp index be9cd67..1b45752 100644 --- a/src/library/locate/LocatorFactory.cpp +++ b/src/library/locate/LocatorFactory.cpp @@ -10,34 +10,32 @@ #include "LocatorStrategy.hpp" #include "LocatorFactory.hpp" #include "ApplicationFolder.hpp" -//#include "EnvironmentVarData.hpp" +#include "EnvironmentVarData.hpp" #include "EnvironmentVarLocation.hpp" #include "ExternalDefinition.hpp" namespace license { namespace locate { -using namespace std; - -FUNCTION_RETURN LocatorFactory::getActiveStrategies( - vector<unique_ptr<LocatorStrategy>> &strategies, - const char *locationHint) { +FUNCTION_RETURN LocatorFactory::get_active_strategies( + std::vector<std::unique_ptr<LocatorStrategy>> &strategies, + const LicenseLocation *locationHint) { #if(FIND_LICENSE_NEAR_MODULE) strategies.push_back( - unique_ptr<LocatorStrategy>( + std::unique_ptr<LocatorStrategy>( (LocatorStrategy*) new ApplicationFolder())); #endif #if(FIND_LICENSE_WITH_ENV_VAR) strategies.push_back( - unique_ptr<LocatorStrategy>( + std::unique_ptr<LocatorStrategy>( (LocatorStrategy*) new EnvironmentVarLocation())); -// strategies.push_back( -// unique_ptr<LocatorStrategy>( -// (LocatorStrategy*) new EnvironmentVarData())); + strategies.push_back( + std::unique_ptr<LocatorStrategy>( + (LocatorStrategy*) new EnvironmentVarData())); #endif if (locationHint != nullptr) { strategies.push_back( - unique_ptr<LocatorStrategy>( + std::unique_ptr<LocatorStrategy>( (LocatorStrategy*) new ExternalDefinition(locationHint))); } return strategies.size() > 0 ? FUNC_RET_OK : FUNC_RET_NOT_AVAIL; diff --git a/src/library/locate/LocatorFactory.hpp b/src/library/locate/LocatorFactory.hpp index 5231107..6f1cd30 100644 --- a/src/library/locate/LocatorFactory.hpp +++ b/src/library/locate/LocatorFactory.hpp @@ -6,6 +6,7 @@ #include <vector> #include "../base/base.h" +#include "../api/datatypes.h" #include "LocatorStrategy.hpp" namespace license { @@ -19,9 +20,9 @@ } public: - static FUNCTION_RETURN getActiveStrategies( + static FUNCTION_RETURN get_active_strategies( std::vector<std::unique_ptr<LocatorStrategy>> &strategiesOut, - const char *locationHint); + const LicenseLocation *locationHint); }; diff --git a/src/library/locate/LocatorStrategy.cpp b/src/library/locate/LocatorStrategy.cpp index fc7f3ab..e1319b2 100644 --- a/src/library/locate/LocatorStrategy.cpp +++ b/src/library/locate/LocatorStrategy.cpp @@ -14,7 +14,7 @@ namespace locate { using namespace std; -const string LocatorStrategy::retrieveLicense( +const string LocatorStrategy::retrieve_license_content( const string &licenseLocation) const { return get_file_contents(licenseLocation.c_str(), MAX_LICENSE_LENGTH); } diff --git a/src/library/locate/LocatorStrategy.hpp b/src/library/locate/LocatorStrategy.hpp index 4aabd6d..278c6a3 100644 --- a/src/library/locate/LocatorStrategy.hpp +++ b/src/library/locate/LocatorStrategy.hpp @@ -31,18 +31,26 @@ virtual const std::string get_strategy_name() const { return m_strategy_name; } - - virtual const std::vector<std::string> licenseLocations( - EventRegistry &eventRegistry) const = 0; + /** + * Try to find licenses + * @param eventRegistry + * @return + * A list of identifiers for call retrieve_license_content. + */ + virtual const std::vector<std::string> license_locations( + EventRegistry &eventRegistry) = 0; /** * Default implementation is to retrieve the license from file. * Subclasses may override it. - * @param licenseLocation + * @param licenseLocationId + * String that identifies the license. It is usually the file name + * but can be whatever is understood by the class * @return + * a string containing the license data in INI format. */ - virtual const std::string retrieveLicense( - const std::string &licenseLocation) const; + virtual const std::string retrieve_license_content( + const std::string &licenseLocationId) const; inline virtual ~LocatorStrategy() { } }; diff --git a/src/library/os/os.h b/src/library/os/os.h index 7eea3eb..1371786 100644 --- a/src/library/os/os.h +++ b/src/library/os/os.h @@ -2,7 +2,7 @@ * os-dependent.hpp * * Created on: Mar 29, 2014 - * + * */ #ifndef OS_DEPENDENT_HPP_ @@ -79,6 +79,14 @@ FUNCTION_RETURN verifySignature(const char* stringToVerify, const char* signatureB64); +#ifdef _WIN32 +#define SETENV(VAR,VAL) _putenv_s(VAR, VAL); +#define UNSETENV(P) _putenv_s(P, ""); +#else +#define SETENV(VAR,VAL) setenv(VAR, VAL, 1); +#define UNSETENV(P) unsetenv(P); +#endif + #ifdef __cplusplus } #endif diff --git a/src/tools/base_lib/win/CryptoHelperWindows.cpp b/src/tools/base_lib/win/CryptoHelperWindows.cpp index 99e0b12..ff40457 100644 --- a/src/tools/base_lib/win/CryptoHelperWindows.cpp +++ b/src/tools/base_lib/win/CryptoHelperWindows.cpp @@ -1,394 +1,394 @@ -/* - * CryptoHelperWindows.cpp - * - * Created on: Sep 14, 2014 - * - */ - -#include <sstream> -#include <vector> -#include <string> -#include "CryptoHelperWindows.h" -// The RSA public-key key exchange algorithm -#define ENCRYPT_ALGORITHM CALG_RSA_SIGN -// The high order WORD 0x0200 (decimal 512) -// determines the key length in bits. -#define KEYLENGTH 0x02000000 -#pragma comment(lib, "crypt32.lib") - -namespace license { - -CryptoHelperWindows::CryptoHelperWindows() { - m_hCryptProv = NULL; - m_hCryptKey = NULL; - if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL , PROV_RSA_FULL, 0)) { - // If the key container cannot be opened, try creating a new - // container by specifying a container name and setting the - // CRYPT_NEWKEYSET flag. - DWORD lastError = GetLastError(); - printf("Error in CryptAcquireContext (1) 0x%08x \n", lastError); - if (NTE_BAD_KEYSET == lastError) { - if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL , PROV_RSA_FULL, CRYPT_NEWKEYSET)) { - printf("Warn in CryptAcquireContext: acquiring new user keyset failed 0x%08x, trying less secure mackine keyset \n", GetLastError()); - //maybe access to protected storage disabled. Try with machine keys (less secure) - if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)) { - printf("Error in CryptAcquireContext (2) 0x%08x \n", GetLastError()); - if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET)) { - printf("Error in CryptAcquireContext (3): acquiring new keyset(machine) failed 0x%08x \n", GetLastError()); - throw logic_error(""); - } - } - } - } else { - printf(" Error in CryptAcquireContext (4) 0x%08x \n", lastError); - throw logic_error(""); - } - } - -} - -/** - This method calls the CryptGenKey function to get a handle to an - - exportable key-pair. The key-pair is generated with the RSA public-key - key exchange algorithm using Microsoft Enhanced Cryptographic Provider. - */ -void CryptoHelperWindows::generateKeyPair() { - HRESULT hr = S_OK; - DWORD dwErrCode; - // If the handle to key container is NULL, fail. - if (m_hCryptProv == NULL) - throw logic_error("Cryptocontext not correctly initialized"); - // Release a previously acquired handle to key-pair. - if (m_hCryptKey) - m_hCryptKey = NULL; - // Call the CryptGenKey method to get a handle - // to a new exportable key-pair. - if (!CryptGenKey(m_hCryptProv, ENCRYPT_ALGORITHM, - KEYLENGTH | CRYPT_EXPORTABLE, &m_hCryptKey)) { - dwErrCode = GetLastError(); - throw logic_error( - string("Error generating keys ") - + to_string(static_cast<long long>(dwErrCode))); - } - //double check the key is really generated - if(m_hCryptKey == NULL) { - dwErrCode = GetLastError(); - throw logic_error( - string("Error generating keys (2)") - + to_string(static_cast<long long>(dwErrCode))); - } -} - -/* This method calls the CryptExportKey function to get the Public key - in a string suitable for C source inclusion. - */ -const string CryptoHelperWindows::exportPublicKey() const { - HRESULT hr = S_OK; - DWORD dwErrCode; - DWORD dwBlobLen; - BYTE *pbKeyBlob = nullptr; - stringstream ss; - // If the handle to key container is NULL, fail. - if (m_hCryptKey == NULL) - throw logic_error("call GenerateKey first."); - // This call here determines the length of the key - // blob. - if (!CryptExportKey(m_hCryptKey, - NULL, PUBLICKEYBLOB, 0, nullptr, &dwBlobLen)) { - dwErrCode = GetLastError(); - throw logic_error( - string("Error calculating size of public key ") - + to_string(static_cast<long long>(dwErrCode))); - } - // Allocate memory for the pbKeyBlob. - if ((pbKeyBlob = new BYTE[dwBlobLen]) == nullptr) { - throw logic_error(string("Out of memory exporting public key ")); - } - // Do the actual exporting into the key BLOB. - if (!CryptExportKey(m_hCryptKey, - NULL, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) { - delete pbKeyBlob; - dwErrCode = GetLastError(); - throw logic_error( - string("Error exporting public key ") - + to_string(static_cast<long long>(dwErrCode))); - } else { - ss << "\t"; - for (unsigned int i = 0; i < dwBlobLen; i++) { - if (i != 0) { - ss << ", "; - if (i % 10 == 0) { - ss << "\\" << endl << "\t"; - } - } - ss << to_string(static_cast<long long>(pbKeyBlob[i])); - } - delete pbKeyBlob; - } - return ss.str(); -} - -CryptoHelperWindows::~CryptoHelperWindows() { - if (m_hCryptProv) { - CryptReleaseContext(m_hCryptProv, 0); - m_hCryptProv = NULL; - } - if (m_hCryptKey) - m_hCryptKey = NULL; -} - -//-------------------------------------------------------------------- -// This method calls the CryptExportKey function to get the Private key -// in a byte array. The byte array is allocated on the heap and the size -// of this is returned to the caller. The caller is responsible for releasing // this memory using a delete call. -//-------------------------------------------------------------------- -const string CryptoHelperWindows::exportPrivateKey() const { - HRESULT hr = S_OK; - DWORD dwErrCode; - DWORD dwBlobLen; - BYTE *pbKeyBlob; - stringstream ss; - // If the handle to key container is NULL, fail. - if (m_hCryptKey == NULL) - throw logic_error(string("call GenerateKey first.")); - // This call here determines the length of the key - // blob. - if (!CryptExportKey(m_hCryptKey, - NULL, PRIVATEKEYBLOB, 0, nullptr, &dwBlobLen)) { - dwErrCode = GetLastError(); - throw logic_error( - string("Error calculating size of private key ") - + to_string(static_cast<long long>(dwErrCode))); - } - // Allocate memory for the pbKeyBlob. - if ((pbKeyBlob = new BYTE[dwBlobLen]) == nullptr) { - throw logic_error(string("Out of memory exporting private key ")); - } - - // Do the actual exporting into the key BLOB. - if (!CryptExportKey(m_hCryptKey, - NULL, PRIVATEKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) { - delete pbKeyBlob; - dwErrCode = GetLastError(); - throw logic_error( - string("Error exporting private key ") - + to_string(static_cast<long long>(dwErrCode))); - } else { - ss << "\t"; - for (unsigned int i = 0; i < dwBlobLen; i++) { - if (i != 0) { - ss << ", "; - if (i % 15 == 0) { - ss << "\\" << endl << "\t"; - } - } - ss << to_string(static_cast<long long>(pbKeyBlob[i])); - } - delete pbKeyBlob; - } - return ss.str(); -} - -void CryptoHelperWindows::printHash(HCRYPTHASH *hHash) const { - BYTE *pbHash; - DWORD dwHashLen; - DWORD dwHashLenSize = sizeof(DWORD); - char *hashStr; - unsigned int i; - - if (CryptGetHashParam(*hHash, HP_HASHSIZE, (BYTE*) &dwHashLen, - &dwHashLenSize, 0)) { - pbHash = (BYTE*) malloc(dwHashLen); - hashStr = (char*) malloc(dwHashLen * 2 + 1); - if (CryptGetHashParam(*hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)) { - for (i = 0; i < dwHashLen; i++) { - sprintf(&hashStr[i * 2], "%02x", pbHash[i]); - } - printf("hash To be signed: %s \n", hashStr); - } - free(pbHash); - free(hashStr); - } -} - -const string CryptoHelperWindows::signString(const void *privateKey, - size_t pklen, const string &license) const { - BYTE *pbBuffer = (BYTE*) license.c_str(); - const DWORD dwBufferLen = (DWORD) strlen((char*) pbBuffer); - HCRYPTHASH hHash; - - HCRYPTKEY hKey; - BYTE *pbSignature; - DWORD dwSigLen; - DWORD strLen; - - //------------------------------------------------------------------- - // Acquire a cryptographic provider context handle. - - if (!CryptImportKey(m_hCryptProv, (const BYTE*) privateKey, (DWORD) pklen, - 0, 0, &hKey)) { - throw logic_error( - string("Error in importing the PrivateKey ") - + to_string(static_cast<long long>(GetLastError()))); - } - - //------------------------------------------------------------------- - // Create the hash object. - - if (CryptCreateHash(m_hCryptProv, CALG_SHA1, 0, 0, &hHash)) { - printf("Hash object created. \n"); - } else { - CryptDestroyKey(hKey); - throw logic_error(string("Error during CryptCreateHash.")); - } - //------------------------------------------------------------------- - // Compute the cryptographic hash of the buffer. - - if (CryptHashData(hHash, pbBuffer, dwBufferLen, 0)) { -#ifdef _DEBUG - printf("Length of data to be hashed: %d \n", dwBufferLen); - printHash(&hHash); -#endif - } else { - throw logic_error(string("Error during CryptHashData.")); - } - //------------------------------------------------------------------- - // Determine the size of the signature and allocate memory. - - dwSigLen = 0; - if (CryptSignHash(hHash, AT_SIGNATURE, nullptr, 0, nullptr, &dwSigLen)) { - printf("Signature length %d found.\n", dwSigLen); - } else { - throw logic_error(string("Error during CryptSignHash.")); - } - //------------------------------------------------------------------- - // Allocate memory for the signature buffer. - - if (pbSignature = (BYTE*) malloc(dwSigLen)) { - printf("Memory allocated for the signature.\n"); - } else { - throw logic_error(string("Out of memory.")); - } - //------------------------------------------------------------------- - // Sign the hash object. - - if (CryptSignHash(hHash, AT_SIGNATURE, nullptr, 0, pbSignature, - &dwSigLen)) { - printf("pbSignature is the signature length. %d\n", dwSigLen); - } else { - throw logic_error(string("Error during CryptSignHash.")); - } - //------------------------------------------------------------------- - // Destroy the hash object. - - CryptDestroyHash(hHash); - CryptDestroyKey(hKey); - - CryptBinaryToString(pbSignature, dwSigLen, - CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &strLen); - vector<char> buffer(strLen); - CryptBinaryToString(pbSignature, dwSigLen, - CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, &buffer[0], &strLen); - - //------------------------------------------------------------------- - // In the second phase, the hash signature is verified. - // This would most often be done by a different user in a - // separate program. The hash, signature, and the PUBLICKEYBLOB - // would be read from a file, an email message, - // or some other source. - - // Here, the original pbBuffer, pbSignature, szDescription. - // pbKeyBlob, and their lengths are used. - - // The contents of the pbBuffer must be the same data - // that was originally signed. - - //------------------------------------------------------------------- - // Get the public key of the user who created the digital signature - // and import it into the CSP by using CryptImportKey. This returns - // a handle to the public key in hPubKey. - - /*if (CryptImportKey( - hProv, - pbKeyBlob, - dwBlobLen, - 0, - 0, - &hPubKey)) - { - printf("The key has been imported.\n"); - } - else - { - MyHandleError("Public key import failed."); - } - //------------------------------------------------------------------- - // Create a new hash object. - - if (CryptCreateHash( - hProv, - CALG_MD5, - 0, - 0, - &hHash)) - { - printf("The hash object has been recreated. \n"); - } - else - { - MyHandleError("Error during CryptCreateHash."); - } - //------------------------------------------------------------------- - // Compute the cryptographic hash of the buffer. - - if (CryptHashData( - hHash, - pbBuffer, - dwBufferLen, - 0)) - { - printf("The new hash has been created.\n"); - } - else - { - MyHandleError("Error during CryptHashData."); - } - //------------------------------------------------------------------- - // Validate the digital signature. - - if (CryptVerifySignature( - hHash, - pbSignature, - dwSigLen, - hPubKey, - NULL, - 0)) - { - printf("The signature has been verified.\n"); - } - else - { - printf("Signature not validated!\n"); - } - //------------------------------------------------------------------- - // Free memory to be used to store signature. - - - - //------------------------------------------------------------------- - // Destroy the hash object. - - - - //------------------------------------------------------------------- - // Release the provider handle. - - /*if (hProv) - CryptReleaseContext(hProv, 0);*/ - if (pbSignature) { - free(pbSignature); - } - return string(&buffer[0]); -} -} /* namespace license */ +/* + * CryptoHelperWindows.cpp + * + * Created on: Sep 14, 2014 + * + */ + +#include <sstream> +#include <vector> +#include <string> +#include "CryptoHelperWindows.h" +// The RSA public-key key exchange algorithm +#define ENCRYPT_ALGORITHM CALG_RSA_SIGN +// The high order WORD 0x0200 (decimal 512) +// determines the key length in bits. +#define KEYLENGTH 0x02000000 +#pragma comment(lib, "crypt32.lib") + +namespace license { + +CryptoHelperWindows::CryptoHelperWindows() { + m_hCryptProv = NULL; + m_hCryptKey = NULL; + if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL , PROV_RSA_FULL, 0)) { + // If the key container cannot be opened, try creating a new + // container by specifying a container name and setting the + // CRYPT_NEWKEYSET flag. + DWORD lastError = GetLastError(); + printf("Error in CryptAcquireContext (1) 0x%08x \n", lastError); + if (NTE_BAD_KEYSET == lastError) { + if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL , PROV_RSA_FULL, CRYPT_NEWKEYSET)) { + printf("Warn in CryptAcquireContext: acquiring new user keyset failed 0x%08x, trying less secure mackine keyset \n", GetLastError()); + //maybe access to protected storage disabled. Try with machine keys (less secure) + if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)) { + printf("Error in CryptAcquireContext (2) 0x%08x \n", GetLastError()); + if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET)) { + printf("Error in CryptAcquireContext (3): acquiring new keyset(machine) failed 0x%08x \n", GetLastError()); + throw logic_error(""); + } + } + } + } else { + printf(" Error in CryptAcquireContext (4) 0x%08x \n", lastError); + throw logic_error(""); + } + } + +} + +/** + This method calls the CryptGenKey function to get a handle to an + + exportable key-pair. The key-pair is generated with the RSA public-key + key exchange algorithm using Microsoft Enhanced Cryptographic Provider. + */ +void CryptoHelperWindows::generateKeyPair() { + HRESULT hr = S_OK; + DWORD dwErrCode; + // If the handle to key container is NULL, fail. + if (m_hCryptProv == NULL) + throw logic_error("Cryptocontext not correctly initialized"); + // Release a previously acquired handle to key-pair. + if (m_hCryptKey) + m_hCryptKey = NULL; + // Call the CryptGenKey method to get a handle + // to a new exportable key-pair. + if (!CryptGenKey(m_hCryptProv, ENCRYPT_ALGORITHM, + KEYLENGTH | CRYPT_EXPORTABLE, &m_hCryptKey)) { + dwErrCode = GetLastError(); + throw logic_error( + string("Error generating keys ") + + to_string(static_cast<long long>(dwErrCode))); + } + //double check the key is really generated + if(m_hCryptKey == NULL) { + dwErrCode = GetLastError(); + throw logic_error( + string("Error generating keys (2)") + + to_string(static_cast<long long>(dwErrCode))); + } +} + +/* This method calls the CryptExportKey function to get the Public key + in a string suitable for C source inclusion. + */ +const string CryptoHelperWindows::exportPublicKey() const { + HRESULT hr = S_OK; + DWORD dwErrCode; + DWORD dwBlobLen; + BYTE *pbKeyBlob = nullptr; + stringstream ss; + // If the handle to key container is NULL, fail. + if (m_hCryptKey == NULL) + throw logic_error("call GenerateKey first."); + // This call here determines the length of the key + // blob. + if (!CryptExportKey(m_hCryptKey, + NULL, PUBLICKEYBLOB, 0, nullptr, &dwBlobLen)) { + dwErrCode = GetLastError(); + throw logic_error( + string("Error calculating size of public key ") + + to_string(static_cast<long long>(dwErrCode))); + } + // Allocate memory for the pbKeyBlob. + if ((pbKeyBlob = new BYTE[dwBlobLen]) == nullptr) { + throw logic_error(string("Out of memory exporting public key ")); + } + // Do the actual exporting into the key BLOB. + if (!CryptExportKey(m_hCryptKey, + NULL, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) { + delete pbKeyBlob; + dwErrCode = GetLastError(); + throw logic_error( + string("Error exporting public key ") + + to_string(static_cast<long long>(dwErrCode))); + } else { + ss << "\t"; + for (unsigned int i = 0; i < dwBlobLen; i++) { + if (i != 0) { + ss << ", "; + if (i % 10 == 0) { + ss << "\\" << endl << "\t"; + } + } + ss << to_string(static_cast<long long>(pbKeyBlob[i])); + } + delete pbKeyBlob; + } + return ss.str(); +} + +CryptoHelperWindows::~CryptoHelperWindows() { + if (m_hCryptProv) { + CryptReleaseContext(m_hCryptProv, 0); + m_hCryptProv = NULL; + } + if (m_hCryptKey) + m_hCryptKey = NULL; +} + +//-------------------------------------------------------------------- +// This method calls the CryptExportKey function to get the Private key +// in a byte array. The byte array is allocated on the heap and the size +// of this is returned to the caller. The caller is responsible for releasing // this memory using a delete call. +//-------------------------------------------------------------------- +const string CryptoHelperWindows::exportPrivateKey() const { + HRESULT hr = S_OK; + DWORD dwErrCode; + DWORD dwBlobLen; + BYTE *pbKeyBlob; + stringstream ss; + // If the handle to key container is NULL, fail. + if (m_hCryptKey == NULL) + throw logic_error(string("call GenerateKey first.")); + // This call here determines the length of the key + // blob. + if (!CryptExportKey(m_hCryptKey, + NULL, PRIVATEKEYBLOB, 0, nullptr, &dwBlobLen)) { + dwErrCode = GetLastError(); + throw logic_error( + string("Error calculating size of private key ") + + to_string(static_cast<long long>(dwErrCode))); + } + // Allocate memory for the pbKeyBlob. + if ((pbKeyBlob = new BYTE[dwBlobLen]) == nullptr) { + throw logic_error(string("Out of memory exporting private key ")); + } + + // Do the actual exporting into the key BLOB. + if (!CryptExportKey(m_hCryptKey, + NULL, PRIVATEKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) { + delete pbKeyBlob; + dwErrCode = GetLastError(); + throw logic_error( + string("Error exporting private key ") + + to_string(static_cast<long long>(dwErrCode))); + } else { + ss << "\t"; + for (unsigned int i = 0; i < dwBlobLen; i++) { + if (i != 0) { + ss << ", "; + if (i % 15 == 0) { + ss << "\\" << endl << "\t"; + } + } + ss << to_string(static_cast<long long>(pbKeyBlob[i])); + } + delete pbKeyBlob; + } + return ss.str(); +} + +void CryptoHelperWindows::printHash(HCRYPTHASH *hHash) const { + BYTE *pbHash; + DWORD dwHashLen; + DWORD dwHashLenSize = sizeof(DWORD); + char *hashStr; + unsigned int i; + + if (CryptGetHashParam(*hHash, HP_HASHSIZE, (BYTE*) &dwHashLen, + &dwHashLenSize, 0)) { + pbHash = (BYTE*) malloc(dwHashLen); + hashStr = (char*) malloc(dwHashLen * 2 + 1); + if (CryptGetHashParam(*hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)) { + for (i = 0; i < dwHashLen; i++) { + sprintf(&hashStr[i * 2], "%02x", pbHash[i]); + } + printf("hash To be signed: %s \n", hashStr); + } + free(pbHash); + free(hashStr); + } +} + +const string CryptoHelperWindows::signString(const void *privateKey, + size_t pklen, const string &license) const { + BYTE *pbBuffer = (BYTE*) license.c_str(); + const DWORD dwBufferLen = (DWORD) strlen((char*) pbBuffer); + HCRYPTHASH hHash; + + HCRYPTKEY hKey; + BYTE *pbSignature; + DWORD dwSigLen; + DWORD strLen; + + //------------------------------------------------------------------- + // Acquire a cryptographic provider context handle. + + if (!CryptImportKey(m_hCryptProv, (const BYTE*) privateKey, (DWORD) pklen, + 0, 0, &hKey)) { + throw logic_error( + string("Error in importing the PrivateKey ") + + to_string(static_cast<long long>(GetLastError()))); + } + + //------------------------------------------------------------------- + // Create the hash object. + + if (CryptCreateHash(m_hCryptProv, CALG_SHA1, 0, 0, &hHash)) { + printf("Hash object created. \n"); + } else { + CryptDestroyKey(hKey); + throw logic_error(string("Error during CryptCreateHash.")); + } + //------------------------------------------------------------------- + // Compute the cryptographic hash of the buffer. + + if (CryptHashData(hHash, pbBuffer, dwBufferLen, 0)) { +#ifdef _DEBUG + printf("Length of data to be hashed: %d \n", dwBufferLen); + printHash(&hHash); +#endif + } else { + throw logic_error(string("Error during CryptHashData.")); + } + //------------------------------------------------------------------- + // Determine the size of the signature and allocate memory. + + dwSigLen = 0; + if (CryptSignHash(hHash, AT_SIGNATURE, nullptr, 0, nullptr, &dwSigLen)) { + printf("Signature length %d found.\n", dwSigLen); + } else { + throw logic_error(string("Error during CryptSignHash.")); + } + //------------------------------------------------------------------- + // Allocate memory for the signature buffer. + + if (pbSignature = (BYTE*) malloc(dwSigLen)) { + printf("Memory allocated for the signature.\n"); + } else { + throw logic_error(string("Out of memory.")); + } + //------------------------------------------------------------------- + // Sign the hash object. + + if (CryptSignHash(hHash, AT_SIGNATURE, nullptr, 0, pbSignature, + &dwSigLen)) { + printf("pbSignature is the signature length. %d\n", dwSigLen); + } else { + throw logic_error(string("Error during CryptSignHash.")); + } + //------------------------------------------------------------------- + // Destroy the hash object. + + CryptDestroyHash(hHash); + CryptDestroyKey(hKey); + + CryptBinaryToString(pbSignature, dwSigLen, + CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &strLen); + vector<char> buffer(strLen); + CryptBinaryToString(pbSignature, dwSigLen, + CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, &buffer[0], &strLen); + + //------------------------------------------------------------------- + // In the second phase, the hash signature is verified. + // This would most often be done by a different user in a + // separate program. The hash, signature, and the PUBLICKEYBLOB + // would be read from a file, an email message, + // or some other source. + + // Here, the original pbBuffer, pbSignature, szDescription. + // pbKeyBlob, and their lengths are used. + + // The contents of the pbBuffer must be the same data + // that was originally signed. + + //------------------------------------------------------------------- + // Get the public key of the user who created the digital signature + // and import it into the CSP by using CryptImportKey. This returns + // a handle to the public key in hPubKey. + + /*if (CryptImportKey( + hProv, + pbKeyBlob, + dwBlobLen, + 0, + 0, + &hPubKey)) + { + printf("The key has been imported.\n"); + } + else + { + MyHandleError("Public key import failed."); + } + //------------------------------------------------------------------- + // Create a new hash object. + + if (CryptCreateHash( + hProv, + CALG_MD5, + 0, + 0, + &hHash)) + { + printf("The hash object has been recreated. \n"); + } + else + { + MyHandleError("Error during CryptCreateHash."); + } + //------------------------------------------------------------------- + // Compute the cryptographic hash of the buffer. + + if (CryptHashData( + hHash, + pbBuffer, + dwBufferLen, + 0)) + { + printf("The new hash has been created.\n"); + } + else + { + MyHandleError("Error during CryptHashData."); + } + //------------------------------------------------------------------- + // Validate the digital signature. + + if (CryptVerifySignature( + hHash, + pbSignature, + dwSigLen, + hPubKey, + NULL, + 0)) + { + printf("The signature has been verified.\n"); + } + else + { + printf("Signature not validated!\n"); + } + //------------------------------------------------------------------- + // Free memory to be used to store signature. + + + + //------------------------------------------------------------------- + // Destroy the hash object. + + + + //------------------------------------------------------------------- + // Release the provider handle. + + /*if (hProv) + CryptReleaseContext(hProv, 0);*/ + if (pbSignature) { + free(pbSignature); + } + return string(&buffer[0]); +} +} /* namespace license */ diff --git a/src/tools/base_lib/win/CryptoHelperWindows.h b/src/tools/base_lib/win/CryptoHelperWindows.h index a432e27..b4e7594 100644 --- a/src/tools/base_lib/win/CryptoHelperWindows.h +++ b/src/tools/base_lib/win/CryptoHelperWindows.h @@ -1,46 +1,46 @@ -/* - * CryptoHelperWindows.h - * - * Created on: Sep 14, 2014 - * - */ - -#ifndef CRYPTOHELPERWINDOWS_H_ -#define CRYPTOHELPERWINDOWS_H_ - -//#define _WIN32_WINNT 0x0400 -#include <windows.h> -#include <wincrypt.h> -#include <tchar.h> -#include <string> -#include "../CryptoHelper.h" - - - -namespace license { -using namespace std; - -class CryptoHelperWindows: public CryptoHelper { -private : - void acquireContext(); - // Handle to the cryptography provider. - HCRYPTPROV m_hCryptProv; - // Handle to the cryptography key. - HCRYPTKEY m_hCryptKey; - void printHash(HCRYPTHASH* hHash) const; -public: - CryptoHelperWindows(); - - virtual void generateKeyPair(); - virtual const string exportPrivateKey() const; - virtual const string exportPublicKey() const; - - virtual const string signString(const void* privateKey, size_t pklen, - const string& license) const; - - virtual ~CryptoHelperWindows(); -}; - -} /* namespace license */ - -#endif /* CRYPTOHELPERWINDOWS_H_ */ +/* + * CryptoHelperWindows.h + * + * Created on: Sep 14, 2014 + * + */ + +#ifndef CRYPTOHELPERWINDOWS_H_ +#define CRYPTOHELPERWINDOWS_H_ + +//#define _WIN32_WINNT 0x0400 +#include <windows.h> +#include <wincrypt.h> +#include <tchar.h> +#include <string> +#include "../CryptoHelper.h" + + + +namespace license { +using namespace std; + +class CryptoHelperWindows: public CryptoHelper { +private : + void acquireContext(); + // Handle to the cryptography provider. + HCRYPTPROV m_hCryptProv; + // Handle to the cryptography key. + HCRYPTKEY m_hCryptKey; + void printHash(HCRYPTHASH* hHash) const; +public: + CryptoHelperWindows(); + + virtual void generateKeyPair(); + virtual const string exportPrivateKey() const; + virtual const string exportPublicKey() const; + + virtual const string signString(const void* privateKey, size_t pklen, + const string& license) const; + + virtual ~CryptoHelperWindows(); +}; + +} /* namespace license */ + +#endif /* CRYPTOHELPERWINDOWS_H_ */ diff --git a/src/tools/license-generator/CMakeLists.txt b/src/tools/license-generator/CMakeLists.txt index f86817b..334b178 100644 --- a/src/tools/license-generator/CMakeLists.txt +++ b/src/tools/license-generator/CMakeLists.txt @@ -10,6 +10,7 @@ target_link_libraries( license_generator_lib tools_base + base licensecc_static $<$<CONFIG:Debug>:${Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG}> $<$<NOT:$<CONFIG:Debug>>:${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE}> diff --git a/src/tools/license-generator/license-generator.cpp b/src/tools/license-generator/license-generator.cpp index dcffd7e..d7335cf 100644 --- a/src/tools/license-generator/license-generator.cpp +++ b/src/tools/license-generator/license-generator.cpp @@ -1,32 +1,40 @@ -#include <build_properties.h> -#include <private-key.h> #include "license-generator.h" -#include "../base_lib/CryptoHelper.h" + +#include <stddef.h> #include <stdlib.h> -#include <stdio.h> +#include <cerrno> +#include <cstdio> +#include <cstring> +#include <ctime> +#include <fstream> +#include <iomanip> #include <iostream> -#include <string.h> -#include <iostream> -#include <string.h> -#include <boost/date_time.hpp> +#include <iterator> +#include <map> +#include <memory> +#include <regex> +#include <sstream> +#include <stdexcept> +#include <string> +#include <vector> #include <boost/program_options.hpp> #include <boost/algorithm/string.hpp> -#include <boost/unordered_map.hpp> -#include <boost/assign.hpp> -#include <fstream> -#include <regex> -#include <boost/filesystem.hpp> -namespace fs = boost::filesystem; -namespace bt = boost::posix_time; +#include <private-key.h> +#include <build_properties.h> +#include "../../library/base/base64.h" +#include "../base_lib/CryptoHelper.h" + +//namespace fs = boost::filesystem; +//namespace bt = boost::posix_time; namespace po = boost::program_options; using namespace std; namespace license { -void LicenseGenerator::printHelp(const char* prog_name, - const po::options_description& options) { +void LicenseGenerator::printHelp(const char *prog_name, + const po::options_description &options) { cout << endl; cout << prog_name << " Version " << PROJECT_VERSION << endl << ". Usage:" << endl; @@ -40,43 +48,41 @@ po::options_description LicenseGenerator::configureProgramOptions() { po::options_description common("General options"); - common.add_options() - ("help,h", "print help message and exit.") - ("verbose,v", "print more information.") - ("output,o", po::value<string>(), "Output file name. If not specified the " - "license will be printed in standard output") - ; + common.add_options()("help,h", "print help message and exit.") // + ("verbose,v", "print more information.")// + + ("output,o", po::value<string>(), "Output file name. If not specified the " + "license will be printed to standard output"); po::options_description licenseGeneration("License Generation"); - licenseGeneration.add_options() - ("private_key,p", po::value<string>(), + licenseGeneration.add_options()("private_key,p", po::value<string>(), "Specify an alternate file for the primary key to be used. " - "If not specified the internal primary key will be used.") - ("begin_date,b", po::value<string>(), + "If not specified the internal primary key will be used.")( + "begin_date,b", po::value<string>(), "Specify the start of the validity for this license. " - " Format YYYYMMDD. If not specified defaults to today") - ("expire_date,e", po::value<string>(), + " Format YYYYMMDD. If not specified defaults to today")( + "expire_date,e", po::value<string>(), "Specify the expire date for this license. " - " Format YYYYMMDD. If not specified the license won't expire") - ("client_signature,s", po::value<string>(), + " Format YYYYMMDD. If not specified the license won't expire")( + "client_signature,s", po::value<string>(), "The signature of the pc that requires the license. " "It should be in the format XXXX-XXXX-XXXX-XXXX." " If not specified the license " - "won't be linked to a specific pc.") - ("start_version,t", po::value<unsigned int>()->default_value(0 + "won't be linked to a specific pc.")("start_version,t", + po::value<unsigned int>()->default_value(0 /*FullLicenseInfo.UNUSED_SOFTWARE_VERSION*/, "All Versions"), - "Specify the first version of the software this license apply to.") - ("end_version,n", po::value<unsigned int>()->default_value(0 + "Specify the first version of the software this license apply to.")( + "end_version,n", po::value<unsigned int>()->default_value(0 /*FullLicenseInfo.UNUSED_SOFTWARE_VERSION*/, "All Versions"), - "Specify the last version of the software this license apply to.") - ("extra_data,x", po::value<string>(), "Specify extra data to be included into the license") - ; + "Specify the last version of the software this license apply to.")( + "extra_data,x", po::value<string>(), + "Specify extra data to be included into the license"); po::options_description visibleOptions; visibleOptions.add(common).add(licenseGeneration); return visibleOptions; } vector<FullLicenseInfo> LicenseGenerator::parseLicenseInfo( - const po::variables_map& vm) { + const po::variables_map &vm) { string begin_date = FullLicenseInfo::UNUSED_TIME; string end_date = FullLicenseInfo::UNUSED_TIME; if (vm.count("expire_date")) { @@ -108,13 +114,14 @@ if (vm.count("client_signature")) { client_signature = vm["client_signature"].as<string>(); cout << "cli sig:" << client_signature; - regex e("[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}"); + regex e( + "[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}"); cout << "\nregex:"; if (!regex_match(client_signature, e)) { cerr << endl << "Client signature not recognized: " - << client_signature - << " Please enter a valid signature in format XXXX-XXXX-XXXX-XXXX" - << endl; + << client_signature + << " Please enter a valid signature in format XXXX-XXXX-XXXX-XXXX" + << endl; exit(2); } } @@ -142,18 +149,32 @@ return licInfo; } -void LicenseGenerator::generateAndOutputLicenses(const po::variables_map& vm, - ostream& outputFile) { +void LicenseGenerator::generateAndOutputLicenses(const po::variables_map &vm, + ostream &outputFile) { vector<FullLicenseInfo> licenseInfo = parseLicenseInfo(vm); const unique_ptr<CryptoHelper> helper = CryptoHelper::getInstance(); const unsigned char pkey[] = PRIVATE_KEY; const size_t len = sizeof(pkey); for (auto it = licenseInfo.begin(); it != licenseInfo.end(); ++it) { const string license = it->printForSign(); - const string signature = helper->signString((const void *)pkey,len,license); + const string signature = helper->signString((const void*) pkey, len, + license); it->license_signature = signature; it->printAsIni(outputFile); } +} + +void LicenseGenerator::generateB64Licenses(const po::variables_map &vm, + ostream &outputFile) { + std::ostringstream tempStream; + generateAndOutputLicenses(vm, tempStream); + + std::string str = tempStream.str(); + const char *chr = str.c_str(); + int finalLenght; + char *encoded = base64(chr, str.length(), &finalLenght); + outputFile.write(encoded, finalLenght); + free(encoded); } int LicenseGenerator::generateLicense(int argc, const char **argv) { @@ -183,13 +204,21 @@ fstream ofstream(fname, std::ios::out | std::ios::app); if (!ofstream.is_open()) { cerr << "can't open file [" << fname << "] for output." << endl - << " error: " << strerror( errno); + << " error: " << strerror(errno) << endl; exit(3); } - generateAndOutputLicenses(vm, ofstream); + if (vm.count("base64")) { + generateB64Licenses(vm, ofstream); + } else { + generateAndOutputLicenses(vm, ofstream); + } ofstream.close(); } else { - generateAndOutputLicenses(vm, cout); + if (vm.count("base64")) { + generateB64Licenses(vm, cout); + } else { + generateAndOutputLicenses(vm, cout); + } } return 0; } @@ -197,22 +226,24 @@ const std::string formats[] = { "%4u-%2u-%2u", "%4u/%2u/%2u", "%4u%2u%2u" }; const size_t formats_n = 3; -string LicenseGenerator::normalize_date(const std::string& sDate) { - if(sDate.size()<8) +string LicenseGenerator::normalize_date(const std::string &sDate) { + if (sDate.size() < 8) throw invalid_argument("Date string too small for known formats"); unsigned int year, month, day; bool found = false; for (size_t i = 0; i < formats_n && !found; ++i) { - const int chread = sscanf(sDate.c_str(),formats[i].c_str(),&year,&month,&day); - if(chread==3) { + const int chread = sscanf(sDate.c_str(), formats[i].c_str(), &year, + &month, &day); + if (chread == 3) { found = true; break; } } - if(!found) + if (!found) throw invalid_argument("Date string did not match a known format"); ostringstream oss; - oss << year << "-" << setfill('0') << std::setw(2) << month << "-" << setfill('0') << std::setw(2) << day; + oss << year << "-" << setfill('0') << std::setw(2) << month << "-" + << setfill('0') << std::setw(2) << day; return oss.str(); } } diff --git a/src/tools/license-generator/license-generator.h b/src/tools/license-generator/license-generator.h index 531e01b..04eaee6 100644 --- a/src/tools/license-generator/license-generator.h +++ b/src/tools/license-generator/license-generator.h @@ -2,14 +2,13 @@ * LicenseSigner.h * * Created on: Apr 6, 2014 - * + * */ #ifndef LICENSE_GENERATOR_H_ #define LICENSE_GENERATOR_H_ #include <boost/program_options.hpp> - #include "../../library/LicenseReader.hpp" namespace license { @@ -22,12 +21,15 @@ class LicenseGenerator { private: LicenseGenerator(); + static void printHelp(const char* prog_name, const po::options_description& options); static po::options_description configureProgramOptions(); - static vector<FullLicenseInfo> parseLicenseInfo(const po::variables_map& vm); + static std::vector<FullLicenseInfo> parseLicenseInfo(const po::variables_map& vm); static void generateAndOutputLicenses(const po::variables_map& vm, - ostream& outputFile); - static string normalize_date(const std::string& s); + std::ostream& outputFile); + static void generateB64Licenses(const po::variables_map& vm, + std::ostream& outputFile); + static std::string normalize_date(const std::string& s); public: /** * Available options: diff --git a/test/functional/CMakeLists.txt b/test/functional/CMakeLists.txt index 3d122ea..44b4a8d 100644 --- a/test/functional/CMakeLists.txt +++ b/test/functional/CMakeLists.txt @@ -8,12 +8,12 @@ ) add_executable( - standard_license_test + test_standard_license standard-license_test.cpp ) target_link_libraries( - standard_license_test + test_standard_license licensecc_static license_generator_snippet ${Boost_LIBRARIES} @@ -46,11 +46,11 @@ IF( ( CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") AND CMAKE_CROSSCOMPILING) #binfmt_misc doesn't work in my system :( - ADD_TEST(NAME standard_license_test COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/standard_license_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + ADD_TEST(NAME test_standard_license COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_standard_license WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) ADD_TEST(NAME test_date COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_date WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) ADD_TEST(NAME test_volid COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_volid WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) ELSE() - ADD_TEST(NAME standard_license_test COMMAND standard_license_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + ADD_TEST(NAME test_standard_license COMMAND test_standard_license WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) ADD_TEST(NAME test_date COMMAND test_date WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) ADD_TEST(NAME test_volid COMMAND test_volid WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) ENDIF() diff --git a/test/functional/date_test.cpp b/test/functional/date_test.cpp index b07216b..44a9911 100644 --- a/test/functional/date_test.cpp +++ b/test/functional/date_test.cpp @@ -24,10 +24,9 @@ /* */ LicenseInfo license; LicenseLocation licenseLocation; - licenseLocation.openFileNearModule = false; licenseLocation.licenseFileLocation = licLocation.c_str(); - licenseLocation.environmentVariableName = ""; - const EVENT_TYPE result = acquire_license("TEST", licenseLocation, + licenseLocation.licenseData = ""; + const EVENT_TYPE result = acquire_license("TEST", &licenseLocation, &license); BOOST_CHECK_EQUAL(result, LICENSE_OK); BOOST_CHECK_EQUAL(license.has_expiry, true); @@ -44,10 +43,10 @@ /* */ LicenseInfo license; LicenseLocation licenseLocation; - licenseLocation.openFileNearModule = false; licenseLocation.licenseFileLocation = licLocation.c_str(); - licenseLocation.environmentVariableName = ""; - const EVENT_TYPE result = acquire_license("TEST", licenseLocation, + licenseLocation.licenseData = nullptr; + BOOST_TEST_MESSAGE("before acquire license"); + const EVENT_TYPE result = acquire_license("TEST", &licenseLocation, &license); BOOST_CHECK_EQUAL(result, PRODUCT_EXPIRED); BOOST_CHECK_EQUAL(license.has_expiry, true); diff --git a/test/functional/hijiaking_test.cpp b/test/functional/hijiaking_test.cpp index 6ada4fa..009e47b 100644 --- a/test/functional/hijiaking_test.cpp +++ b/test/functional/hijiaking_test.cpp @@ -23,7 +23,7 @@ LicenseLocation licenseLocation; licenseLocation.openFileNearModule=false; licenseLocation.licenseFileLocation = licLocation.c_str(); - licenseLocation.environmentVariableName = ""; + licenseLocation.licenseData = ""; EVENT_TYPE result = acquire_license("TEST", licenseLocation, & license); BOOST_CHECK_EQUAL(result, LICENSE_OK); diff --git a/test/functional/standard-license_test.cpp b/test/functional/standard-license_test.cpp index 67e8d67..19b6000 100644 --- a/test/functional/standard-license_test.cpp +++ b/test/functional/standard-license_test.cpp @@ -1,6 +1,5 @@ -#define BOOST_TEST_MODULE standard_license_test -//#define BOOST_TEST_MAIN -//#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE test_standard_license + #include <boost/test/unit_test.hpp> #include "../../src/tools/license-generator/license-generator.h" #include "../../src/library/api/license++.h" @@ -8,12 +7,12 @@ #include <boost/filesystem.hpp> #include "../../src/library/ini/SimpleIni.h" #include "generate-license.h" +#include "../../src/library/base/FileUtils.hpp" +namespace test { namespace fs = boost::filesystem; using namespace license; using namespace std; - -namespace test { BOOST_AUTO_TEST_CASE( standard_lic_file ) { const string licLocation(PROJECT_TEST_TEMP_DIR "/standard_license.lic"); @@ -22,10 +21,29 @@ /* */ LicenseInfo license; LicenseLocation licenseLocation; - licenseLocation.openFileNearModule = false; licenseLocation.licenseFileLocation = licLocation.c_str(); - licenseLocation.environmentVariableName = ""; - const EVENT_TYPE result = acquire_license("TEST", licenseLocation, + licenseLocation.licenseData = nullptr; + const EVENT_TYPE result = acquire_license("TEST", &licenseLocation, + &license); + BOOST_CHECK_EQUAL(result, LICENSE_OK); + BOOST_CHECK_EQUAL(license.has_expiry, false); + BOOST_CHECK_EQUAL(license.linked_to_pc, false); +} + +/** + * Pass the license data to the application. + */ +BOOST_AUTO_TEST_CASE( b64_environment_variable ) { + const string licLocation(PROJECT_TEST_TEMP_DIR "/standard_env_license.lic"); + const vector<string> extraArgs; + generate_license(licLocation, extraArgs); + const string licensestr(license::get_file_contents(licLocation.c_str(), MAX_LICENSE_LENGTH)); + /* */ + LicenseInfo license; + LicenseLocation licenseLocation; + licenseLocation.licenseFileLocation = nullptr; + licenseLocation.licenseData = licensestr.c_str(); + const EVENT_TYPE result = acquire_license("TEST", &licenseLocation, &license); BOOST_CHECK_EQUAL(result, LICENSE_OK); BOOST_CHECK_EQUAL(license.has_expiry, false); @@ -39,10 +57,9 @@ LicenseInfo license; LicenseLocation licenseLocation; - licenseLocation.openFileNearModule = false; licenseLocation.licenseFileLocation = licLocation.c_str(); - licenseLocation.environmentVariableName = ""; - const EVENT_TYPE result = acquire_license("TEST", licenseLocation, + licenseLocation.licenseData = ""; + const EVENT_TYPE result = acquire_license("TEST", &licenseLocation, &license); BOOST_CHECK_EQUAL(result, IDENTIFIERS_MISMATCH); BOOST_CHECK_EQUAL(license.has_expiry, false); diff --git a/test/functional/volid_test.cpp b/test/functional/volid_test.cpp index d02b36d..3ab5348 100644 --- a/test/functional/volid_test.cpp +++ b/test/functional/volid_test.cpp @@ -35,10 +35,9 @@ LicenseInfo license; LicenseLocation licenseLocation; - licenseLocation.openFileNearModule = false; licenseLocation.licenseFileLocation = licLocation.c_str(); - licenseLocation.environmentVariableName = ""; - const EVENT_TYPE result = acquire_license("TEST", licenseLocation, &license); + licenseLocation.licenseData = ""; + const EVENT_TYPE result = acquire_license("TEST", &licenseLocation, &license); BOOST_CHECK_EQUAL(result, LICENSE_OK); BOOST_CHECK_EQUAL(license.has_expiry, false); BOOST_CHECK_EQUAL(license.linked_to_pc, true); diff --git a/test/library/CMakeLists.txt b/test/library/CMakeLists.txt index 78ad9ad..b7f4d90 100644 --- a/test/library/CMakeLists.txt +++ b/test/library/CMakeLists.txt @@ -51,4 +51,22 @@ ADD_TEST(NAME test_license_locator COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_license_locator) ELSE() ADD_TEST(NAME test_license_locator COMMAND test_license_locator) +ENDIF() + +### LicenseLocator tests +add_executable( + test_event_registry + EventRegistry_test.cpp +) + +target_link_libraries( + test_event_registry + base + ${Boost_LIBRARIES} +) + +IF( ( CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") AND CMAKE_CROSSCOMPILING) + ADD_TEST(NAME test_event_registry COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_event_registry) +ELSE() + ADD_TEST(NAME test_event_registry COMMAND test_event_registry) ENDIF() \ No newline at end of file diff --git a/test/library/EventRegistry_test.cpp b/test/library/EventRegistry_test.cpp new file mode 100644 index 0000000..70abe9b --- /dev/null +++ b/test/library/EventRegistry_test.cpp @@ -0,0 +1,41 @@ +#define BOOST_TEST_MODULE "test_event_registry" + +#include <iostream> +#include <iterator> + +#include <fstream> +#include <string> +#include <vector> + +#include <boost/filesystem.hpp> +#include <boost/optional.hpp> +#include <boost/test/unit_test.hpp> +#include <stdlib.h> +#include <cstdio> + +#include <build_properties.h> + +#include "../../src/library/base/EventRegistry.h" + +namespace test { + +using namespace std; +using namespace license; + +/** + * The error reported is for the license that advanced most in the validation process + * + */ +BOOST_AUTO_TEST_CASE( test_most_advanced_license_error ) { + EventRegistry er; + er.addEvent(LICENSE_SPECIFIED, "lic2"); + er.addEvent(LICENSE_FOUND, "lic1"); + er.addEvent(LICENSE_CORRUPTED, "lic1"); + er.turnWarningsIntoErrors(); + const AuditEvent *event = er.getLastFailure(); + BOOST_CHECK_MESSAGE(event != nullptr, "An error is detected"); + BOOST_CHECK_MESSAGE(string("lic1") == event->license_reference, "Error is for lic1"); + BOOST_CHECK_MESSAGE(LICENSE_CORRUPTED == event->event_type, "Error is for LICENSE_CORRUPTED"); +} + +} //namespace test diff --git a/test/library/LicenseLocator_test.cpp b/test/library/LicenseLocator_test.cpp index eb4bda0..cf532b2 100644 --- a/test/library/LicenseLocator_test.cpp +++ b/test/library/LicenseLocator_test.cpp @@ -14,6 +14,8 @@ #include <cstdio> #include <build_properties.h> + +#include "../../src/library/os/os.h" #include "../../src/library/base/EventRegistry.h" #include "../../src/library/locate/ApplicationFolder.hpp" #include "../../src/library/locate/EnvironmentVarLocation.hpp" @@ -69,13 +71,13 @@ license::EventRegistry registry; ApplicationFolder applicationFolder; - vector<string> licenseInfos = applicationFolder.licenseLocations(registry); + vector<string> licenseInfos = applicationFolder.license_locations(registry); BOOST_CHECK(registry.isGood()); BOOST_REQUIRE_EQUAL(1, licenseInfos.size()); string currentLocation = licenseInfos[0]; BOOST_CHECK_MESSAGE(equivalent(path(referenceLicenseFileName),path(currentLocation)), "file " +currentLocation + "found at expected location"); - string licenseRealContent = applicationFolder.retrieveLicense( + string licenseRealContent = applicationFolder.retrieve_license_content( currentLocation); src.seekg(0, ios::beg); std::string referenceContent((std::istreambuf_iterator<char>(src)), @@ -100,31 +102,33 @@ std::string referenceContent((std::istreambuf_iterator<char>(src)), std::istreambuf_iterator<char>()); license::EventRegistry registry; - ExternalDefinition externalDefinition(applicationDefinedString); - vector<string> licenseInfos = externalDefinition.licenseLocations(registry); + const LicenseLocation licLocation({applicationDefinedString,nullptr}); + ExternalDefinition externalDefinition(&licLocation); + vector<string> licenseInfos = externalDefinition.license_locations(registry); BOOST_CHECK(registry.isGood()); BOOST_CHECK_EQUAL(1, licenseInfos.size()); string currentLocation = licenseInfos[0]; BOOST_CHECK_MESSAGE(string(MOCK_LICENSE).compare(currentLocation) == 0, "file found at expected location"); - string licenseRealContent = externalDefinition.retrieveLicense( + string licenseRealContent = externalDefinition.retrieve_license_content( currentLocation); BOOST_CHECK_MESSAGE(referenceContent.compare(licenseRealContent) == 0, "File content is same"); } /** - * The license file doesn't exist. Chech that the locator reports the right error + * The license file doesn't exist. Check that the locator reports the right error */ BOOST_AUTO_TEST_CASE( external_definition_not_found ) { const char *applicationDefinedString = PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist"; license::EventRegistry registry; - ExternalDefinition externalDefinition(applicationDefinedString); - vector<string> licenseInfos = externalDefinition.licenseLocations(registry); + const LicenseLocation licLocation({applicationDefinedString,nullptr}); + ExternalDefinition externalDefinition(&licLocation); + vector<string> licenseInfos = externalDefinition.license_locations(registry); BOOST_CHECK_MESSAGE(registry.isGood(), "No fatal error for now, only warnings"); - registry.turnEventIntoError(LICENSE_FILE_NOT_FOUND); + registry.turnWarningsIntoErrors(); BOOST_REQUIRE_MESSAGE(!registry.isGood(), "Error detected"); BOOST_CHECK_EQUAL(0, licenseInfos.size()); BOOST_CHECK_MESSAGE( @@ -152,23 +156,18 @@ license::EventRegistry registry; EnvironmentVarLocation envVarLocationStrategy; - vector<string> licenseInfos = envVarLocationStrategy.licenseLocations( + vector<string> licenseInfos = envVarLocationStrategy.license_locations( registry); BOOST_CHECK(registry.isGood()); BOOST_CHECK_EQUAL(1, licenseInfos.size()); string currentLocation = licenseInfos[0]; BOOST_CHECK_MESSAGE(string(MOCK_LICENSE).compare(currentLocation) == 0, "file found at expected location"); - string licenseRealContent = envVarLocationStrategy.retrieveLicense( + string licenseRealContent = envVarLocationStrategy.retrieve_license_content( currentLocation); BOOST_CHECK_MESSAGE(referenceContent.compare(licenseRealContent) == 0, "File content is same"); -#ifdef _WIN32 - _putenv_s(LICENSE_LOCATION_ENV_VAR, ""); -#else - unsetenv(LICENSE_LOCATION_ENV_VAR); -#endif - + UNSETENV(LICENSE_LOCATION_ENV_VAR); } /** @@ -177,47 +176,36 @@ BOOST_AUTO_TEST_CASE( environment_var_location_not_found ) { const char *environment_variable_value = PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist"; -#ifdef _WIN32 - _putenv_s(LICENSE_LOCATION_ENV_VAR, environment_variable_value); -#else - setenv(LICENSE_LOCATION_ENV_VAR, environment_variable_value, 1); -#endif + SETENV(LICENSE_LOCATION_ENV_VAR, environment_variable_value); + license::EventRegistry registry; EnvironmentVarLocation envVarLocationStrategy; - vector<string> licenseInfos = envVarLocationStrategy.licenseLocations( + vector<string> licenseInfos = envVarLocationStrategy.license_locations( registry); BOOST_CHECK_MESSAGE(registry.isGood(), "No fatal error for now, only warnings"); - registry.turnEventIntoError(LICENSE_FILE_NOT_FOUND); + registry.turnWarningsIntoErrors(); BOOST_REQUIRE_MESSAGE(!registry.isGood(), "Error detected"); BOOST_CHECK_EQUAL(0, licenseInfos.size()); BOOST_CHECK_MESSAGE( registry.getLastFailure()->event_type == LICENSE_FILE_NOT_FOUND, "Error detected"); -#ifdef _WIN32 - _putenv_s(LICENSE_LOCATION_ENV_VAR, ""); -#else - unsetenv(LICENSE_LOCATION_ENV_VAR); -#endif + UNSETENV(LICENSE_LOCATION_ENV_VAR); } /** * The license file doesn't exist. Check that the locator reports the right error */ BOOST_AUTO_TEST_CASE( environment_var_location_not_defined ) { -#ifdef _WIN32 - _putenv_s(LICENSE_LOCATION_ENV_VAR, ""); -#else - unsetenv(LICENSE_LOCATION_ENV_VAR); -#endif + UNSETENV(LICENSE_LOCATION_ENV_VAR); license::EventRegistry registry; EnvironmentVarLocation environmentVarLocation; - vector<string> licenseInfos = environmentVarLocation.licenseLocations( + vector<string> licenseInfos = environmentVarLocation.license_locations( registry); BOOST_CHECK_MESSAGE(registry.isGood(), "No fatal error for now, only warnings"); - registry.turnEventIntoError(ENVIRONMENT_VARIABLE_NOT_DEFINED); + registry.turnWarningsIntoErrors(); BOOST_REQUIRE_MESSAGE(!registry.isGood(), "Error detected"); BOOST_CHECK_EQUAL(0, licenseInfos.size()); BOOST_CHECK_MESSAGE( diff --git a/test/library/LicenseReader_test.cpp b/test/library/LicenseReader_test.cpp index df86061..2198ab3 100644 --- a/test/library/LicenseReader_test.cpp +++ b/test/library/LicenseReader_test.cpp @@ -1,4 +1,14 @@ #define BOOST_TEST_MODULE "test_license_reader" +#include <boost/assert.hpp> +#include <boost/test/tools/old/interface.hpp> +#include <boost/test/unit_test_suite.hpp> +#include <iostream> +#include <vector> + +#include "../../src/library/api/datatypes.h" +#include "../../src/library/base/EventRegistry.h" +#include "../../src/library/os/os.h" + #include <boost/test/unit_test.hpp> #include <stdlib.h> @@ -6,13 +16,17 @@ #include <build_properties.h> #include "../../src/library/LicenseReader.hpp" +namespace test { using namespace license; - +using namespace std; +/** + * Read license at fixed location + */ BOOST_AUTO_TEST_CASE( read_single_file ) { - const char *licLocation = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; + const char *licLocation = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; - const LicenseLocation location = { licLocation, nullptr, false }; - LicenseReader licenseReader(location); + const LicenseLocation location = { licLocation, nullptr }; + LicenseReader licenseReader(&location); vector<FullLicenseInfo> licenseInfos; const EventRegistry registry = licenseReader.readLicenses("PrODUCT", licenseInfos); @@ -20,11 +34,14 @@ BOOST_CHECK_EQUAL(1, licenseInfos.size()); } +/** + * Test the error return if the product code is not found in the license + */ BOOST_AUTO_TEST_CASE( product_not_licensed ) { const char *licLocation = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; - const LicenseLocation location = { licLocation, nullptr, false }; - LicenseReader licenseReader(location); + const LicenseLocation location = { licLocation, nullptr }; + LicenseReader licenseReader(&location); vector<FullLicenseInfo> licenseInfos; const EventRegistry registry = licenseReader.readLicenses("PRODUCT-NOT", licenseInfos); @@ -35,11 +52,14 @@ registry.getLastFailure()->event_type); } +/** + * Test the error code if the license file is specified but doesn't exists + */ BOOST_AUTO_TEST_CASE( file_not_found ) { const char *licLocation = PROJECT_TEST_SRC_DIR "/library/not_found.ini"; //const char * envName = "MYVAR"; - const LicenseLocation location = { licLocation, nullptr, false }; - LicenseReader licenseReader(location); + const LicenseLocation location = { licLocation, nullptr }; + LicenseReader licenseReader(&location); vector<FullLicenseInfo> licenseInfos; const EventRegistry registry = licenseReader.readLicenses("PRODUCT", licenseInfos); @@ -50,10 +70,13 @@ registry.getLastFailure()->event_type); } +/** + * Test the error code if the license default environment variable isn't specified + */ BOOST_AUTO_TEST_CASE( env_var_not_defined ) { - const char *envName = "MYVAR"; - const LicenseLocation location = { nullptr, envName, false }; - LicenseReader licenseReader(location); + UNSETENV(LICENSE_LOCATION_ENV_VAR); + const LicenseLocation location = { nullptr, nullptr }; + LicenseReader licenseReader(&location); vector<FullLicenseInfo> licenseInfos; const EventRegistry registry = licenseReader.readLicenses("PRODUCT", licenseInfos); @@ -64,3 +87,26 @@ registry.getLastFailure()->event_type); } +/** + * Test the error code if the license default environment variable is + * specified but points to a non existent file. + */ +BOOST_AUTO_TEST_CASE( env_var_point_to_wrong_file ) { + const char *environment_variable_value = + PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist"; + SETENV(LICENSE_LOCATION_ENV_VAR, environment_variable_value) + + const LicenseLocation location = { nullptr, nullptr }; + LicenseReader licenseReader(&location); + vector<FullLicenseInfo> licenseInfos; + const EventRegistry registry = licenseReader.readLicenses("PRODUCT", + licenseInfos); + cout << registry << endl; + BOOST_CHECK(!registry.isGood()); + BOOST_CHECK_EQUAL(0, licenseInfos.size()); + BOOST_ASSERT(registry.getLastFailure()!=NULL); + BOOST_CHECK_EQUAL(LICENSE_FILE_NOT_FOUND, + registry.getLastFailure()->event_type); + UNSETENV(LICENSE_LOCATION_ENV_VAR); +} +} /* namespace test*/ -- Gitblit v1.9.1