| | |
| | | #define PC_IDENTIFIER_SIZE 19 |
| | | #define PROPRIETARY_DATA_SIZE 16 |
| | | #define AUDIT_EVENT_NUM 5 |
| | | #define API_LICENSE_DATA_LENGTH 1024 * 4 |
| | | #define API_VERSION_LENGTH 16 |
| | | |
| | | typedef enum { |
| | | LICENSE_OK = 0, // OK |
| | |
| | | char param2[256]; |
| | | } AuditEvent; |
| | | |
| | | typedef enum { |
| | | /** |
| | | * A list of absolute path separated by ';' containing the eventual location |
| | | * of the license files. Can be NULL. |
| | | */ |
| | | LICENSE_PATH, |
| | | /** |
| | | * The license is provided as plain data |
| | | */ |
| | | LICENSE_PLAIN_DATA, |
| | | /** |
| | | * The license is encoded |
| | | */ |
| | | LICENSE_ENCODED |
| | | } LICENSE_DATA_TYPE; |
| | | |
| | | /** |
| | | * This structure contains informations on the raw license data. Software authors |
| | | * can specify the location of the license file or its full content. |
| | |
| | | * 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; |
| | | /** |
| | | * 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; |
| | | LICENSE_DATA_TYPE license_data_type; |
| | | char licenseData[API_LICENSE_DATA_LENGTH]; |
| | | } LicenseLocation; |
| | | |
| | | /** |
| | | * Informations on the software requiring the license |
| | | */ |
| | | typedef struct { |
| | | char version[16]; // software version in format xxxx.xxxx.xxxx |
| | | char version[API_VERSION_LENGTH]; // software version in format xxxx[.xxxx.xxxx] //TODO |
| | | char project_name[16]; // name of the project (must correspond to the name in the license) |
| | | uint32_t magic; // reserved |
| | | /** |
| | | * this number passed in by the application must correspond to the magic number used when compiling the library. |
| | | * See cmake parameter -DLCC_PROJECT_MAGIC_NUM and licensecc_properties.h macro VERIFY_MAGIC |
| | | */ |
| | | unsigned int magic; |
| | | } CallerInformations; |
| | | |
| | | typedef struct { |
| | | /** |
| | | * Detailed reason of success/failure. Reasons for a failure can be |
| | |
| | | * in most cases. |
| | | */ |
| | | typedef enum { |
| | | STRATEGY_DEFAULT, |
| | | STRATEGY_ETHERNET, |
| | | STRATEGY_IP_ADDRESS, |
| | | STRATEGY_DISK_NUM, |
| | | STRATEGY_DISK_LABEL, |
| | | STRATEGY_PLATFORM_SPECIFIC, |
| | | STRATEGY_UNKNOWN |
| | | STRATEGY_DEFAULT = -1, |
| | | STRATEGY_ETHERNET = 0, |
| | | STRATEGY_IP_ADDRESS = 1, |
| | | STRATEGY_DISK_NUM = 1, |
| | | STRATEGY_DISK_LABEL = 2, |
| | | STRATEGY_PLATFORM_SPECIFIC = 3, |
| | | STRATEGY_UNKNOWN = -2 |
| | | } IDENTIFICATION_STRATEGY; |
| | | |
| | | #ifdef __cplusplus |
| | |
| | | #define LICENSEPP_H_ |
| | | |
| | | /* |
| | | * This include file is the public api di License++ |
| | | * This include file is the public api di Licensecc |
| | | */ |
| | | #ifdef __cplusplus |
| | | extern "C" { |
| | |
| | | * This method calculate the pc identifier. The string has to be shown |
| | | * to the user in order to calculate the license. |
| | | */ |
| | | bool identify_pc(IDENTIFICATION_STRATEGY pc_id_method, char* identifier_out, size_t bufSize); |
| | | bool identify_pc(IDENTIFICATION_STRATEGY pc_id_method, char* identifier_out, size_t* bufSize); |
| | | |
| | | /** |
| | | * This method is used to request the use of one license for a product. |
| | |
| | | using namespace std; |
| | | void print_error(char out_buffer[256], LicenseInfo* licenseInfo) {} |
| | | |
| | | bool identify_pc(IDENTIFICATION_STRATEGY pc_id_method, char* chbuffer, size_t bufSize) { |
| | | bool identify_pc(IDENTIFICATION_STRATEGY pc_id_method, char* chbuffer, size_t* bufSize) { |
| | | FUNCTION_RETURN result = FUNC_RET_BUFFER_TOO_SMALL; |
| | | if (bufSize >= sizeof(PcSignature)) { |
| | | if (*bufSize >= sizeof(PcSignature)) { |
| | | PcSignature identifier_out; |
| | | result = generate_user_pc_signature(identifier_out, pc_id_method); |
| | | strncpy(chbuffer, identifier_out, bufSize); |
| | | strncpy(chbuffer, identifier_out, *bufSize); |
| | | } else { |
| | | *bufSize = sizeof(PcSignature); |
| | | } |
| | | return result == FUNC_RET_OK; |
| | | } |
| | |
| | | vector<LicenseInfo> licenses_with_errors; |
| | | vector<LicenseInfo> licenses_ok; |
| | | license::LicenseVerifier verifier(er); |
| | | for (auto it = licenses.begin(); it != licenses.end(); it++) { |
| | | FUNCTION_RETURN signatureValid = verifier.verify_signature(*it); |
| | | for (auto full_lic_info_it = licenses.begin(); full_lic_info_it != licenses.end(); full_lic_info_it++) { |
| | | if (callerInformation != nullptr) { |
| | | full_lic_info_it->m_magic = callerInformation->magic; |
| | | } |
| | | const FUNCTION_RETURN signatureValid = verifier.verify_signature(*full_lic_info_it); |
| | | LicenseInfo licInfo = verifier.toLicenseInfo(*full_lic_info_it); |
| | | if (signatureValid == FUNC_RET_OK) { |
| | | if (verifier.verify_limits(*it) == FUNC_RET_OK) { |
| | | licenses_ok.push_back(verifier.toLicenseInfo(*it)); |
| | | if (verifier.verify_limits(*full_lic_info_it) == FUNC_RET_OK) { |
| | | licenses_ok.push_back(licInfo); |
| | | } else { |
| | | licenses_with_errors.push_back(verifier.toLicenseInfo(*it)); |
| | | licenses_with_errors.push_back(licInfo); |
| | | } |
| | | } else { |
| | | licenses_with_errors.push_back(verifier.toLicenseInfo(*it)); |
| | | licenses_with_errors.push_back(licInfo); |
| | | } |
| | | } |
| | | if (licenses_ok.size() > 0) { |
| | |
| | | const string licLocation = generate_license("not_expired.lic", extraArgs); |
| | | /* */ |
| | | LicenseInfo license; |
| | | LicenseLocation licenseLocation; |
| | | licenseLocation.licenseFileLocation = licLocation.c_str(); |
| | | licenseLocation.licenseData = ""; |
| | | const EVENT_TYPE result = acquire_license(nullptr, &licenseLocation, &license); |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | |
| | | const EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, LICENSE_OK); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, true); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, false); |
| | |
| | | const string licLocation = generate_license("expired", extraArgs); |
| | | /* */ |
| | | LicenseInfo license; |
| | | LicenseLocation licenseLocation; |
| | | licenseLocation.licenseFileLocation = licLocation.c_str(); |
| | | licenseLocation.licenseData = nullptr; |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | BOOST_TEST_MESSAGE("before acquire license"); |
| | | const EVENT_TYPE result = acquire_license(nullptr, &licenseLocation, &license); |
| | | const EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, PRODUCT_EXPIRED); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, true); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, false); |
| | |
| | | using namespace std; |
| | | |
| | | /** |
| | | * Test a generic license with no expiry neither client id. |
| | | * Test a generic license with no expiry neither client id. The license is read from file |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(test_generic_license) { |
| | | BOOST_AUTO_TEST_CASE(test_generic_license_read_file) { |
| | | const vector<string> extraArgs; |
| | | const string licLocation = generate_license("standard_license", extraArgs); |
| | | /* */ |
| | | LicenseInfo license; |
| | | LicenseLocation licenseLocation; |
| | | licenseLocation.licenseFileLocation = licLocation.c_str(); |
| | | licenseLocation.licenseData = nullptr; |
| | | const EVENT_TYPE result = acquire_license(nullptr, &licenseLocation, &license); |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | const EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, LICENSE_OK); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, false); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, false); |
| | | } |
| | | |
| | | /** |
| | | * Test a generic license with no expiry neither client id. The license is passed in trhough the licenseData structure. |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(test_read_license_data) { |
| | | const vector<string> extraArgs; |
| | | const fs::path licLocation = fs::path(generate_license("standard_license1", extraArgs)); |
| | | string license_data; |
| | | // load the license string |
| | | fs::load_string_file(licLocation, license_data); |
| | | LicenseInfo license; |
| | | LicenseLocation location = {LICENSE_PLAIN_DATA}; |
| | | std::copy(license_data.begin(), license_data.end(), location.licenseData); |
| | | const EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, LICENSE_OK); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, false); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, false); |
| | |
| | | |
| | | const IDENTIFICATION_STRATEGY strategy = IDENTIFICATION_STRATEGY::STRATEGY_ETHERNET; |
| | | BOOST_TEST_CHECKPOINT("Before generate"); |
| | | const FUNCTION_RETURN generate_ok = generate_user_pc_signature(identifier_out, |
| | | strategy); |
| | | const FUNCTION_RETURN generate_ok = generate_user_pc_signature(identifier_out, strategy); |
| | | BOOST_TEST_CHECKPOINT("After generate signature"); |
| | | BOOST_ASSERT(generate_ok == FUNCTION_RETURN::FUNC_RET_OK); |
| | | cout << "Identifier:" << identifier_out << endl; |
| | |
| | | const string licLocation = generate_license("volid_license", extraArgs); |
| | | |
| | | LicenseInfo license; |
| | | LicenseLocation licenseLocation; |
| | | licenseLocation.licenseFileLocation = licLocation.c_str(); |
| | | licenseLocation.licenseData = ""; |
| | | const EVENT_TYPE result = acquire_license(nullptr, &licenseLocation, &license); |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | const EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, LICENSE_OK); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, false); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, true); |
| | | } |
| | | |
| | | static void generate_reference_file(const string &idfileLocation, |
| | | IDENTIFICATION_STRATEGY strategies[], int num_strategies) { |
| | | static void generate_reference_file(const string &idfileLocation, IDENTIFICATION_STRATEGY strategies[], |
| | | int num_strategies) { |
| | | ofstream idfile(idfileLocation); |
| | | PcSignature identifier_out; |
| | | for (int i = 0; i < num_strategies; i++) { |
| | | FUNCTION_RETURN generate_ok = generate_user_pc_signature(identifier_out, |
| | | strategies[i]); |
| | | FUNCTION_RETURN generate_ok = generate_user_pc_signature(identifier_out, strategies[i]); |
| | | if (generate_ok != FUNC_RET_OK) { |
| | | BOOST_ERROR( |
| | | "Generating identifier for strategy " << strategies[i] << " failed with: " << generate_ok); |
| | | BOOST_ERROR("Generating identifier for strategy " << strategies[i] << " failed with: " << generate_ok); |
| | | idfile << "0000-0000-0000-0000" << endl; |
| | | BOOST_ASSERT(generate_ok == FUNC_RET_OK); |
| | | } else |
| | |
| | | } |
| | | std::ifstream test_idfile_exist(idfileLocation); |
| | | if (!test_idfile_exist.good()) { |
| | | generate_reference_file(idfileLocation, strategies.data(), |
| | | strategies.size()); |
| | | generate_reference_file(idfileLocation, strategies.data(), strategies.size()); |
| | | } else { |
| | | std::istream_iterator<string> start(test_idfile_exist), end; |
| | | std::vector<string> reference_signatures(start, end); |
| | | test_idfile_exist.close(); |
| | | if (reference_signatures.size() != num_strategies |
| | | || std::find(reference_signatures.begin(), |
| | | reference_signatures.end(), "0000-0000-0000-0000") |
| | | != reference_signatures.end()) |
| | | if (reference_signatures.size() != num_strategies || |
| | | std::find(reference_signatures.begin(), reference_signatures.end(), "0000-0000-0000-0000") != |
| | | reference_signatures.end()) |
| | | generate_reference_file(idfileLocation, strategies.data(), num_strategies); |
| | | } |
| | | std::ifstream is(idfileLocation); |
| | | std::istream_iterator<string> start(is), end; |
| | | std::vector<string> reference_signatures(start, end); |
| | | BOOST_TEST_CHECKPOINT( |
| | | "Generating current signatures and comparing with past"); |
| | | BOOST_TEST_CHECKPOINT("Generating current signatures and comparing with past"); |
| | | for (int i = 0; i < num_strategies; i++) { |
| | | PcSignature generated_identifier; |
| | | FUNCTION_RETURN generate_ok = generate_user_pc_signature( |
| | | generated_identifier, strategies[i]); |
| | | FUNCTION_RETURN generate_ok = generate_user_pc_signature(generated_identifier, strategies[i]); |
| | | BOOST_ASSERT(generate_ok == FUNCTION_RETURN::FUNC_RET_OK); |
| | | if (generate_ok != FUNC_RET_OK) { |
| | | BOOST_ERROR( |
| | | "Generating identifier for strategy " << strategies[i] << " failed with: " << generate_ok); |
| | | BOOST_ERROR("Generating identifier for strategy " << strategies[i] << " failed with: " << generate_ok); |
| | | continue; |
| | | } |
| | | if (reference_signatures[i] != generated_identifier) { |
| | | string message = string("pc signature compare fail: strategy: ") |
| | | + to_string(static_cast<long long>(strategies[i])) |
| | | + " generated: [" + generated_identifier + "] reference: [" |
| | | + reference_signatures[i] + "]"; |
| | | string message = string("pc signature compare fail: strategy: ") + |
| | | to_string(static_cast<long long>(strategies[i])) + " generated: [" + generated_identifier + |
| | | "] reference: [" + reference_signatures[i] + "]"; |
| | | BOOST_ERROR(message); |
| | | } |
| | | } |
| | | BOOST_TEST_CHECKPOINT("Verifying signatures"); |
| | | for (int j = 0; j < 100; j++) { |
| | | for (unsigned int i = 0; i < reference_signatures.size(); i++) { |
| | | if (reference_signatures[i] == "0000-0000-0000-0000") |
| | | continue; |
| | | if (reference_signatures[i] == "0000-0000-0000-0000") continue; |
| | | PcSignature pcsig; |
| | | strncpy(pcsig, reference_signatures[i].c_str(), |
| | | sizeof(PcSignature) - 1); |
| | | strncpy(pcsig, reference_signatures[i].c_str(), sizeof(PcSignature) - 1); |
| | | EVENT_TYPE val_result = validate_pc_signature(pcsig); |
| | | BOOST_TEST_CHECKPOINT("Verifying signature: "); |
| | | BOOST_CHECK_EQUAL(val_result, LICENSE_OK); |
| | |
| | | #define BOOST_TEST_MODULE "test_license_locator" |
| | | #define __STDC_WANT_LIB_EXT1__ 1 |
| | | #include <string.h> |
| | | |
| | | #include <iostream> |
| | | #include <iterator> |
| | | #include <cstdio> |
| | | #include <fstream> |
| | | #include <string> |
| | | #include <vector> |
| | | #include <boost/filesystem.hpp> |
| | | #include <boost/optional.hpp> |
| | |
| | | |
| | | BOOST_AUTO_TEST_CASE(external_definition) { |
| | | // an application can define multiple license locations separated by ';' |
| | | const char *applicationDefinedString = MOCK_LICENSE ";/this/one/doesnt/exist"; |
| | | string applicationDefinedString = MOCK_LICENSE ";/this/one/doesnt/exist"; |
| | | |
| | | // read test license |
| | | std::ifstream src(MOCK_LICENSE, std::ios::binary); |
| | | std::string referenceContent((std::istreambuf_iterator<char>(src)), std::istreambuf_iterator<char>()); |
| | | license::EventRegistry registry; |
| | | const LicenseLocation licLocation = {applicationDefinedString, nullptr}; |
| | | LicenseLocation licLocation = {LICENSE_PATH}; |
| | | std::copy(applicationDefinedString.begin(), applicationDefinedString.end(), licLocation.licenseData); |
| | | ExternalDefinition externalDefinition(&licLocation); |
| | | vector<string> licenseInfos = externalDefinition.license_locations(registry); |
| | | BOOST_CHECK(registry.isGood()); |
| | |
| | | * 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"; |
| | | string applicationDefinedString = PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist"; |
| | | license::EventRegistry registry; |
| | | const LicenseLocation licLocation = {applicationDefinedString, nullptr}; |
| | | LicenseLocation licLocation = {LICENSE_PATH}; |
| | | std::copy(applicationDefinedString.begin(), applicationDefinedString.end(), licLocation.licenseData); |
| | | ExternalDefinition externalDefinition(&licLocation); |
| | | vector<string> licenseInfos = externalDefinition.license_locations(registry); |
| | | |
| | |
| | | #define BOOST_TEST_MODULE "test_license_reader" |
| | | #define __STDC_WANT_LIB_EXT1__ 1 |
| | | |
| | | #include <string> |
| | | |
| | | #include <boost/test/unit_test.hpp> |
| | | #include <iostream> |
| | |
| | | * Read license at application provided location |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(read_single_file) { |
| | | const char *licLocation = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; |
| | | string location = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; |
| | | |
| | | const LicenseLocation location = {licLocation, nullptr}; |
| | | LicenseReader licenseReader(&location); |
| | | LicenseLocation licLocation = {LICENSE_PATH}; |
| | | std::copy(location.begin(), location.end(), licLocation.licenseData); |
| | | LicenseReader licenseReader(&licLocation); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PrODUCT", licenseInfos); |
| | | BOOST_CHECK(registry.isGood()); |
| | |
| | | * 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}; |
| | | LicenseReader licenseReader(&location); |
| | | string location = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; |
| | | LicenseLocation licLocation = {LICENSE_PATH}; |
| | | std::copy(location.begin(), location.end(), licLocation.licenseData); |
| | | LicenseReader licenseReader(&licLocation); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PRODUCT-NOT", licenseInfos); |
| | | BOOST_CHECK(!registry.isGood()); |
| | |
| | | * 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"; |
| | | string licLocation = PROJECT_TEST_SRC_DIR "/library/not_found.ini"; |
| | | |
| | | locate::LocatorFactory::find_license_near_module(false); |
| | | locate::LocatorFactory::find_license_with_env_var(false); |
| | | const LicenseLocation location = {licLocation, nullptr}; |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | LicenseReader licenseReader(&location); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PRODUCT", licenseInfos); |
| | |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(env_var_not_defined) { |
| | | UNSETENV(LICENSE_LOCATION_ENV_VAR); |
| | | const LicenseLocation location = {nullptr, nullptr}; |
| | | locate::LocatorFactory::find_license_near_module(false); |
| | | locate::LocatorFactory::find_license_with_env_var(true); |
| | | LicenseReader licenseReader(&location); |
| | | LicenseReader licenseReader(nullptr); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PRODUCT", licenseInfos); |
| | | BOOST_CHECK(!registry.isGood()); |
| | |
| | | locate::LocatorFactory::find_license_near_module(false); |
| | | locate::LocatorFactory::find_license_with_env_var(true); |
| | | |
| | | const LicenseLocation location = {nullptr, nullptr}; |
| | | LicenseReader licenseReader(&location); |
| | | LicenseReader licenseReader(nullptr); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PRODUCT", licenseInfos); |
| | | cout << registry << endl; |