From 22b6427979a71c23d795cb351a84210342b5d352 Mon Sep 17 00:00:00 2001
From: Gabriele Contini <contini.mailing@gmail.com>
Date: 摹曛, 09 1月 2020 10:19:22 +0800
Subject: [PATCH] pc identifiers intermediate work

---
 src/library/locate/ExternalDefinition.cpp             |   54 +--
 src/library/os/linux/execution_environment.cpp        |   78 ++++++
 src/library/pc_identifier/default_strategy.hpp        |   27 ++
 src/library/limits/license_verifier.cpp               |    9 
 test/functional/generate-license.cpp                  |    2 
 src/library/locate/ExternalDefinition.hpp             |    5 
 src/library/os/os.h                                   |    5 
 test/library/pc_identifier_facade_test.cpp            |   10 
 test/IdentificationStrategy_test.cpp                  |   10 
 src/library/pc_identifier/identification_strategy.hpp |   28 ++
 test/default_strategy_test.cpp                        |   10 
 src/library/os/cpu_info.hpp                           |   31 ++
 src/library/os/execution_environment.hpp              |   39 +++
 extern/license-generator                              |    2 
 test/library/pc_identifier_test.cpp                   |   10 
 src/library/pc_identifier/pc_identifier.cpp           |   58 ++++
 test/library/cpu_info_test.cpp                        |   10 
 src/library/pc_identifier/pc-identifiers.h            |    2 
 src/library/pc_identifier/pc_identifier.hpp           |   64 ++++
 src/library/pc_identifier/pc_identifier_facade.cpp    |   30 ++
 src/library/pc_identifier/pc-identifiers.c            |   11 
 src/library/os/linux/network_id.c                     |    2 
 src/library/pc_identifier/pc_identifier_facade.hpp    |   25 +
 src/library/os/linux/os-linux.c                       |   80 -----
 /dev/null                                             |   33 --
 src/library/LicenseReader.hpp                         |    1 
 src/library/licensecc.cpp                             |   11 
 src/library/LicenseReader.cpp                         |    4 
 src/library/os/windows/os-win.c                       |    3 
 src/library/pc_identifier/default_strategy.cpp        |   35 ++
 test/library/Os_Linux_test.cpp                        |   15 
 src/library/os/linux/cpu_info.cpp                     |   64 ++++
 src/library/pc_identifier/CMakeLists.txt              |   10 
 33 files changed, 597 insertions(+), 181 deletions(-)

diff --git a/extern/license-generator b/extern/license-generator
index c40c095..61acc7d 160000
--- a/extern/license-generator
+++ b/extern/license-generator
@@ -1 +1 @@
-Subproject commit c40c0951e77c012a1c4043182c88ae5fe185efea
+Subproject commit 61acc7dee39b9947e08d0753d2f69d2a41d5fe31
diff --git a/src/library/LicenseReader.cpp b/src/library/LicenseReader.cpp
index 7390f3c..0448243 100644
--- a/src/library/LicenseReader.cpp
+++ b/src/library/LicenseReader.cpp
@@ -27,7 +27,6 @@
 #include <licensecc/licensecc.h>
 
 #include "base/base.h"
-#include "pc-identifiers.h"
 #include "LicenseReader.hpp"
 #include "base/StringUtils.h"
 #include "base/logger.h"
@@ -39,7 +38,8 @@
 FullLicenseInfo::FullLicenseInfo(const string &source, const string &product, const string &license_signature)
 	: source(source),
 	  m_project(product),  //
-	  license_signature(license_signature) {}
+	  license_signature(license_signature),
+	  m_magic(0) {}
 
 LicenseReader::LicenseReader(const LicenseLocation *licenseLocation) : licenseLocation(licenseLocation) {}
 
diff --git a/src/library/LicenseReader.hpp b/src/library/LicenseReader.hpp
index bad939e..854a0d6 100644
--- a/src/library/LicenseReader.hpp
+++ b/src/library/LicenseReader.hpp
@@ -24,6 +24,7 @@
 	const std::string license_signature;
 	const std::string source;
 	const std::string m_project;
+	unsigned int m_magic;
 	std::map<std::string, std::string> m_limits;
 
 	FullLicenseInfo(const std::string& source, const std::string& product, const std::string& license_signature);
diff --git a/src/library/licensecc.cpp b/src/library/licensecc.cpp
index 27f3ac7..964f362 100644
--- a/src/library/licensecc.cpp
+++ b/src/library/licensecc.cpp
@@ -17,22 +17,21 @@
 #include <licensecc/licensecc.h>
 #include <licensecc_properties.h>
 
+#include "pc_identifier/pc_identifier_facade.hpp"
 #include "limits/license_verifier.hpp"
 #include "base/StringUtils.h"
 #include "LicenseReader.hpp"
-#include "pc-identifiers.h"
 
 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) {
 	FUNCTION_RETURN result = FUNC_RET_BUFFER_TOO_SMALL;
-	if (*bufSize >= sizeof(PcSignature)) {
-		PcSignature identifier_out;
-		result = generate_user_pc_signature(identifier_out, pc_id_method);
-		strncpy(chbuffer, identifier_out, *bufSize);
+	string pc_id = license::PcIdentifierFacade::generate_user_pc_signature(pc_id_method);
+	if (*bufSize >= pc_id.size() + 1) {
+		strncpy(chbuffer, pc_id.c_str(), *bufSize);
 	} else {
-		*bufSize = sizeof(PcSignature);
+		*bufSize = pc_id.size() + 1;
 	}
 	return result == FUNC_RET_OK;
 }
diff --git a/src/library/limits/license_verifier.cpp b/src/library/limits/license_verifier.cpp
index 6c62492..0edbbb3 100644
--- a/src/library/limits/license_verifier.cpp
+++ b/src/library/limits/license_verifier.cpp
@@ -9,7 +9,7 @@
 #include <licensecc_properties.h>
 
 #include "license_verifier.hpp"
-#include "../pc_identifier_facade.hpp"
+#include "../pc_identifier/pc_identifier_facade.hpp"
 #include "../os/signature_verifier.h"
 #include "../base/StringUtils.h"
 
@@ -39,13 +39,10 @@
 	if (!is_valid) {
 		m_event_registry.addEvent(LICENSE_CORRUPTED, licInfo.source.c_str());
 	}
-	const const time_t now = time(nullptr);
+	const time_t now = time(nullptr);
 	auto expiry = licInfo.m_limits.find(PARAM_EXPIRY_DATE);
 	if (is_valid && expiry != licInfo.m_limits.end()) {
 		if (seconds_from_epoch(expiry->second) < now) {
-			/*
-						eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),
-								string("Expired on: " + this->to_date).c_str());*/
 			m_event_registry.addEvent(PRODUCT_EXPIRED, licInfo.source.c_str(), ("Expired " + expiry->second).c_str());
 			is_valid = false;
 		}
@@ -53,8 +50,6 @@
 	const auto start_date = licInfo.m_limits.find(PARAM_BEGIN_DATE);
 	if (is_valid && start_date != licInfo.m_limits.end()) {
 		if (seconds_from_epoch(start_date->second) > now) {
-			/*eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),
-					string("Valid from " + this->from_date).c_str());*/
 			m_event_registry.addEvent(PRODUCT_EXPIRED, licInfo.source.c_str(),
 									  ("Valid from " + start_date->second).c_str());
 			is_valid = false;
diff --git a/src/library/locate/ExternalDefinition.cpp b/src/library/locate/ExternalDefinition.cpp
index 78b9825..13ca80a 100644
--- a/src/library/locate/ExternalDefinition.cpp
+++ b/src/library/locate/ExternalDefinition.cpp
@@ -23,50 +23,44 @@
 namespace locate {
 using namespace std;
 
-ExternalDefinition::ExternalDefinition(const LicenseLocation *location) :
-		LocatorStrategy("ExternalDefinition"), m_location(location) {
-}
+ExternalDefinition::ExternalDefinition(const LicenseLocation *location)
+	: LocatorStrategy("ExternalDefinition"), m_location(location) {}
 
-ExternalDefinition::~ExternalDefinition() {
-}
+ExternalDefinition::~ExternalDefinition() {}
 
-const std::vector<std::string> ExternalDefinition::license_locations(
-		EventRegistry &eventRegistry) {
+const std::vector<std::string> ExternalDefinition::license_locations(EventRegistry &eventRegistry) {
 	vector<string> existing_pos;
-	if (m_location->licenseData != nullptr
-			&& m_location->licenseData[0] != '\0') {
+	if (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);
+		switch (m_location->license_data_type) {
+			case LICENSE_PATH: {
+				string licData(m_location->licenseData, mstrnlen_s(m_location->licenseData, API_LICENSE_DATA_LENGTH));
+				const vector<string> declared_positions = license::split_string(licData, ';');
+				existing_pos =
+					license::filter_existing_files(declared_positions, eventRegistry, get_strategy_name().c_str());
+			} break;
+			case LICENSE_ENCODED:
+			case LICENSE_PLAIN_DATA:
+				existing_pos.push_back(get_strategy_name());
+				break;
+			default:
+				throw logic_error("license type not supported ");
 		}
-	}
-	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 {
+const std::string ExternalDefinition::retrieve_license_content(const std::string &licenseLocation) const {
 	if (licenseLocation == get_strategy_name()) {
-		if (licenseDataIsBase64) {
+		string licData(m_location->licenseData, mstrnlen_s(m_location->licenseData, API_LICENSE_DATA_LENGTH));
+		if (m_location->license_data_type == LICENSE_ENCODED) {
 			int flen = 0;
-			unsigned char *raw = unbase64(m_location->licenseData,
-					strlen(m_location->licenseData), &flen);
-			string str = string(reinterpret_cast<char*>(raw));
+			unsigned char *raw = unbase64(licData.c_str(), licData.length(), &flen);
+			string str = string(reinterpret_cast<char *>(raw));
 			free(raw);
 			return str;
 		} else {
-			return m_location->licenseData;
+			return licData;
 		}
 	} else {
 		return LocatorStrategy::retrieve_license_content(licenseLocation);
diff --git a/src/library/locate/ExternalDefinition.hpp b/src/library/locate/ExternalDefinition.hpp
index c70775a..7ffa9ae 100644
--- a/src/library/locate/ExternalDefinition.hpp
+++ b/src/library/locate/ExternalDefinition.hpp
@@ -16,11 +16,10 @@
 class ExternalDefinition: public LocatorStrategy {
 private:
 	const LicenseLocation* m_location;
-	bool licenseDataIsBase64 = false;
 public:
 	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;
+	const virtual std::vector<std::string> license_locations(EventRegistry& eventRegistry);
+	const virtual std::string retrieve_license_content(const std::string& licenseLocation) const;
 	virtual ~ExternalDefinition();
 };
 
diff --git a/src/library/os/cpu_info.hpp b/src/library/os/cpu_info.hpp
new file mode 100644
index 0000000..716ca40
--- /dev/null
+++ b/src/library/os/cpu_info.hpp
@@ -0,0 +1,31 @@
+/*
+ * cpu_info.h
+ *
+ *  Created on: Dec 14, 2019
+ *      Author: devel
+ */
+
+#ifndef SRC_LIBRARY_OS_CPU_INFO_H_
+#define SRC_LIBRARY_OS_CPU_INFO_H_
+#include <string>
+namespace license {
+
+/**
+ * Cpu informations
+ */
+class CpuInfo {
+public:
+	CpuInfo();
+	virtual ~CpuInfo();
+	/**
+	 * Detect Virtual machine using hypervisor bit or the cpu vendor name.
+	 * @return true if the cpu is detected to be a virtual cpu
+	 */
+	bool cpu_virtual() const;
+	uint32_t model();
+	std::string vendor() const;
+};
+
+} /* namespace license */
+
+#endif /* SRC_LIBRARY_OS_CPU_INFO_H_ */
diff --git a/src/library/os/execution_environment.hpp b/src/library/os/execution_environment.hpp
new file mode 100644
index 0000000..6fbd6c6
--- /dev/null
+++ b/src/library/os/execution_environment.hpp
@@ -0,0 +1,39 @@
+/*
+ * virtualization.hpp
+ *
+ *  Created on: Dec 15, 2019
+ *      Author: GC
+ */
+
+#ifndef SRC_LIBRARY_OS_VIRTUALIZATION_HPP_
+#define SRC_LIBRARY_OS_VIRTUALIZATION_HPP_
+
+namespace license {
+
+typedef enum { NONE, CONTAINER, VM } VIRTUALIZATION;
+typedef enum {
+	ON_PREMISE,
+	GOOGLE_CLOUD,
+	AZURE_CLOUD,
+	AWS,
+	/**
+	 * "/sys/class/dmi/id/bios_vendor" SeaBIOS
+	 * "/sys/class/dmi/id/sys_vendor" Alibaba Cloud
+	 * modalias
+	 * "dmi:bvnSeaBIOS:bvrrel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org:bd04/01/2014:svnAlibabaCloud:pnAlibabaCloudECS:pvrpc-i440fx-2.1:cvnAlibabaCloud:ct1:cvrpc-i440fx-2.1:"
+	 */
+	ALI_CLOUD
+} CLOUD_PROVIDER;
+
+typedef enum { BARE_TO_METAL, VMWARE, VIRTUALBOX, XEN, KVM } VIRTUALIZATION_DETAIL;
+
+class ExecutionEnvironment {
+public:
+	ExecutionEnvironment(){};
+	virtual ~ExecutionEnvironment(){};
+	VIRTUALIZATION getVirtualization();
+};
+
+}  // namespace license
+
+#endif /* SRC_LIBRARY_OS_VIRTUALIZATION_HPP_ */
diff --git a/src/library/os/linux/cpu_info.cpp b/src/library/os/linux/cpu_info.cpp
new file mode 100644
index 0000000..4db4ba0
--- /dev/null
+++ b/src/library/os/linux/cpu_info.cpp
@@ -0,0 +1,64 @@
+/*
+ * cpu_info.cpp
+ *
+ *  Created on: Dec 14, 2019
+ *      Author: devel
+ */
+
+#include <cpuid.h>
+#include <string>
+#include <unordered_set>
+#include "../cpu_info.hpp"
+
+namespace license {
+using namespace std;
+
+const unordered_set<string> virtual_cpu_names = {"bhyve bhyve ", "KVMKVMKVM",	"Microsoft Hv",
+												 " lrpepyh vr",  "prl hyperv  ", "VMwareVMware",
+												 "XenVMMXenVMM", "ACRNACRNACRN", "VBoxVBoxVBox"};
+struct CPUVendorID {
+	unsigned int ebx;
+	unsigned int edx;
+	unsigned int ecx;
+
+	string toString() const { return string(reinterpret_cast<const char *>(this), 12); }
+};
+
+CpuInfo::CpuInfo() {}
+
+CpuInfo::~CpuInfo() {}
+/**
+ * Detect Virtual machine using hypervisor bit.
+ * @return true if the cpu hypervisor bit is set to 1
+ */
+bool CpuInfo::cpu_virtual() const {
+	unsigned int level = 1, eax = 0, ebx = 0, ecx = 0, edx = 0;
+	__get_cpuid(level, &eax, &ebx, &ecx, &edx);
+
+	bool is_virtual = (((ecx >> 31) & 1) == 1);  // hypervisor flag
+	if (!is_virtual) {
+		string cpu_vendor = vendor();
+		auto it = virtual_cpu_names.find(cpu_vendor);
+		is_virtual = (it != virtual_cpu_names.end());
+	}
+	return is_virtual;
+}
+
+uint32_t CpuInfo::model() {
+	unsigned int level = 1, eax = 0, ebx = 0, ecx = 0, edx = 0;
+	__get_cpuid(level, &eax, &ebx, &ecx, &edx);
+	// ax bits 0-3 stepping,4-7 model,8-11 family id,12-13 processor type
+	//        14-15 reserved, 16-19 extended model, 20-27 extended family, 27-31 reserved
+	// bx bits 0-7 brand index
+	return (eax & 0x3FFF) | (eax & 0x3FF8000) >> 2 | (ebx & 0xff) << 24;
+}
+
+string CpuInfo::vendor() const {
+	unsigned int level = 0, eax = 0, ebx = 0, ecx = 0, edx = 0;
+	// hypervisor flag false, try to get the vendor name, see if it's a virtual cpu
+	__get_cpuid(level, &eax, &ebx, &ecx, &edx);
+	CPUVendorID vendorID{.ebx = ebx, .edx = edx, .ecx = ecx};
+	return vendorID.toString();
+}
+
+} /* namespace license */
diff --git a/src/library/os/linux/execution_environment.cpp b/src/library/os/linux/execution_environment.cpp
new file mode 100644
index 0000000..81c5b16
--- /dev/null
+++ b/src/library/os/linux/execution_environment.cpp
@@ -0,0 +1,78 @@
+/*
+ * virtualization.cpp
+ *
+ *  Created on: Dec 15, 2019
+ *      Author: GC
+ */
+#include <paths.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/utsname.h>
+
+#include "../../base/base.h"
+#include "../cpu_info.hpp"
+#include "../execution_environment.hpp"
+
+namespace license {
+
+// 0=NO 1=Docker/2=Lxc
+static int checkContainerProc() {
+	// in docer /proc/self/cgroups contains the "docker" or "lxc" string
+	// https://stackoverflow.com/questions/23513045/how-to-check-if-a-process-is-running-inside-docker-container
+	char path[MAX_PATH] = {0};
+	char proc_path[MAX_PATH], pidStr[64];
+	pid_t pid = getpid();
+	sprintf(pidStr, "%d", pid);
+	strcpy(proc_path, "/proc/");
+	strcat(proc_path, pidStr);
+	strcat(proc_path, "/cgroup");
+
+	FILE *fp;
+	char *line = NULL;
+	size_t len = 0;
+	ssize_t read;
+	int result = 0;
+
+	fp = fopen(proc_path, "r");
+	if (fp == NULL) {
+		return 0;
+	}
+
+	while ((read = getline(&line, &len, fp)) != -1 && result == 0) {
+		// line[len]=0;
+		// printf("Retrieved line of length %zu:\n", read);
+		// printf("%s", line);
+		if (strstr(line, "docker") != NULL) {
+			result = 1;
+		}
+		if (strstr(line, "lxc") != NULL) {
+			result = 2;
+		}
+	}
+
+	fclose(fp);
+	if (line) free(line);
+	return result;
+}
+
+// 0=NO 1=Docker/Lxc
+static int checkLXC() { return (access("/var/run/systemd/container", F_OK) == 0) ? 1 : 0; }
+
+VIRTUALIZATION ExecutionEnvironment::getVirtualization() {
+	VIRTUALIZATION result = NONE;
+	CpuInfo cpuInfo;
+	int isContainer = checkContainerProc();
+	if (isContainer == 1) {
+		result = CONTAINER;
+	} else if (isContainer == 2 || checkLXC()) {
+		result = CONTAINER;
+	} else if (cpuInfo.cpu_virtual()) {
+		result = VM;
+	} else {
+	}
+	return result;
+}
+}  // namespace license
diff --git a/src/library/os/network_id.c b/src/library/os/linux/network_id.c
similarity index 99%
rename from src/library/os/network_id.c
rename to src/library/os/linux/network_id.c
index 556ef49..7f48a3f 100644
--- a/src/library/os/network_id.c
+++ b/src/library/os/linux/network_id.c
@@ -25,7 +25,7 @@
 #include <string.h>
 #include <stdio.h>
 
-#include "os.h"
+#include "../os.h"
 
 /**
  *
diff --git a/src/library/os/os-linux.c b/src/library/os/linux/os-linux.c
similarity index 77%
rename from src/library/os/os-linux.c
rename to src/library/os/linux/os-linux.c
index 00409cc..1dc23cb 100644
--- a/src/library/os/os-linux.c
+++ b/src/library/os/linux/os-linux.c
@@ -1,9 +1,8 @@
 #include <paths.h>
 #include <sys/stat.h>
-#include "os.h"
-#include "../base/logger.h"
-#include <openssl/pem.h>
-#include <openssl/err.h>
+#include <stdio.h>
+#include "../os.h"
+#include "../../base/logger.h"
 
 #include <mntent.h>
 #include <dirent.h>
@@ -190,8 +189,6 @@
 	return result;
 }
 
-void os_initialize() {}
-
 static void _getCpuid(unsigned int *p, unsigned int ax) {
 	__asm __volatile(
 		"movl %%ebx, %%esi\n\t"
@@ -212,78 +209,7 @@
 	return FUNC_RET_OK;
 }
 
-// 0=NO 1=Docker/Lxc
-static int checkContainerProc() {
-	// in docer /proc/self/cgroups contains the "docker" or "lxc" string
-	// https://stackoverflow.com/questions/23513045/how-to-check-if-a-process-is-running-inside-docker-container
-	char path[MAX_PATH] = {0};
-	char proc_path[MAX_PATH], pidStr[64];
-	pid_t pid = getpid();
-	sprintf(pidStr, "%d", pid);
-	strcpy(proc_path, "/proc/");
-	strcat(proc_path, pidStr);
-	strcat(proc_path, "/cgroup");
 
-	FILE *fp;
-	char *line = NULL;
-	size_t len = 0;
-	ssize_t read;
-	int result = 0;
-
-	fp = fopen(proc_path, "r");
-	if (fp == NULL) {
-		return 0;
-	}
-
-	while ((read = getline(&line, &len, fp)) != -1 && result == 0) {
-		// line[len]=0;
-		// printf("Retrieved line of length %zu:\n", read);
-		// printf("%s", line);
-		if (strstr(line, "docker") != NULL || strstr(line, "lxc") != NULL) {
-			result = 1;
-		}
-	}
-
-	fclose(fp);
-	if (line) free(line);
-	return result;
-}
-
-// 0=NO 1=Docker/Lxc
-static int checkLXC() { return (access("/var/run/systemd/container", F_OK) == 0) ? 1 : 0; }
-
-VIRTUALIZATION getVirtualization() {
-	VIRTUALIZATION result = NONE;
-	int isContainer = checkContainerProc();
-	if (isContainer == 1) {
-		result = CONTAINER;
-	} else if (checkLXC()) {
-		result = CONTAINER;
-	}
-	return result;
-
-	// http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
-	//
-	// bool rc = true;
-	/*__asm__ (
-	 "push   %edx\n"
-	 "push   %ecx\n"
-	 "push   %ebx\n"
-	 "mov    %eax, 'VMXh'\n"
-	 "mov    %ebx, 0\n" // any value but not the MAGIC VALUE
-	 "mov    %ecx, 10\n"// get VMWare version
-	 "mov    %edx, 'VX'\n"// port number
-	 "in     %eax, dx\n"// read port on return EAX returns the VERSION
-	 "cmp    %ebx, 'VMXh'\n"// is it a reply from VMWare?
-	 "setz   [rc] \n"// set return value
-	 "pop    %ebx \n"
-	 "pop    %ecx \n"
-	 "pop    %edx \n"
-	 );*/
-
-	// systemd-detect-virt
-	return NONE;
-}
 
 FUNCTION_RETURN getMachineName(unsigned char identifier[6]) {
 	static struct utsname u;
diff --git a/src/library/os/os.h b/src/library/os/os.h
index f32ca92..d59e33c 100644
--- a/src/library/os/os.h
+++ b/src/library/os/os.h
@@ -24,9 +24,6 @@
 #include <stdbool.h>
 #endif
 
-typedef enum {
-	NONE, CONTAINER, VM
-} VIRTUALIZATION;
 
 typedef enum {
 	IFACE_TYPE_ETHERNET, IFACE_TYPE_WIRELESS
@@ -74,8 +71,6 @@
  * @return
  */
 FUNCTION_RETURN getOsSpecificIdentifier(unsigned char identifier[6]);
-VIRTUALIZATION getVirtualization();
-void os_initialize();
 
 // FUNCTION_RETURN verifySignature(const char* stringToVerify, const char* signatureB64);
 
diff --git a/src/library/os/os-win.c b/src/library/os/windows/os-win.c
similarity index 99%
rename from src/library/os/os-win.c
rename to src/library/os/windows/os-win.c
index eab2f28..aa6c5f3 100644
--- a/src/library/os/os-win.c
+++ b/src/library/os/windows/os-win.c
@@ -29,9 +29,6 @@
 	return FUNC_RET_NOT_AVAIL;
 }
 
-void os_initialize() {
-}
-
 //http://www.ok-soft-gmbh.com/ForStackOverflow/EnumMassStorage.c
 //http://stackoverflow.com/questions/3098696/same-code-returns-diffrent-result-on-windows7-32-bit-system
 #define MAX_UNITS 30
diff --git a/src/library/pc_identifier/CMakeLists.txt b/src/library/pc_identifier/CMakeLists.txt
new file mode 100644
index 0000000..a330b6f
--- /dev/null
+++ b/src/library/pc_identifier/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_library(pc_identifier OBJECT
+	pc_identifier_facade.cpp
+	pc_identifier.cpp
+	default_strategy.cpp
+	#pc-identifiers.c
+)
+
+if(CODE_COVERAGE AND UNIX)
+	  target_compile_options(pc_identifier PUBLIC -O0 -g --coverage)
+endif(CODE_COVERAGE AND UNIX)
\ No newline at end of file
diff --git a/src/library/pc_identifier/default_strategy.cpp b/src/library/pc_identifier/default_strategy.cpp
new file mode 100644
index 0000000..afa961f
--- /dev/null
+++ b/src/library/pc_identifier/default_strategy.cpp
@@ -0,0 +1,35 @@
+/*
+ * default_strategy.cpp
+ *
+ *  Created on: Jan 2, 2020
+ *      Author: devel
+ */
+
+#include "default_strategy.hpp"
+
+namespace license {
+
+DefaultStrategy::DefaultStrategy() {
+	// TODO Auto-generated constructor stub
+}
+
+DefaultStrategy::~DefaultStrategy() {
+	// TODO Auto-generated destructor stub
+}
+
+DefaultStrategy::DefaultStrategy(const DefaultStrategy& other) {
+	// TODO Auto-generated constructor stub
+}
+
+IDENTIFICATION_STRATEGY DefaultStrategy::identification_strategy() const { return STRATEGY_DEFAULT; }
+
+void DefaultStrategy::identify_pc(PcIdentifier& identifier) const {}
+
+std::vector<PcIdentifier> DefaultStrategy::alternative_ids() const {}
+
+EVENT_TYPE DefaultStrategy::validate_identifier(const PcIdentifier& identifier) const {
+	// default strategy should always realize itself as a concrete strategy
+	return IDENTIFIERS_MISMATCH;
+}
+
+} /* namespace license */
diff --git a/src/library/pc_identifier/default_strategy.hpp b/src/library/pc_identifier/default_strategy.hpp
new file mode 100644
index 0000000..667140d
--- /dev/null
+++ b/src/library/pc_identifier/default_strategy.hpp
@@ -0,0 +1,27 @@
+/*
+ * default_strategy.hpp
+ *
+ *  Created on: Jan 2, 2020
+ *      Author: devel
+ */
+
+#ifndef SRC_LIBRARY_PC_IDENTIFIER_DEFAULT_STRATEGY_HPP_
+#define SRC_LIBRARY_PC_IDENTIFIER_DEFAULT_STRATEGY_HPP_
+#include "identification_strategy.hpp"
+
+namespace license {
+
+class DefaultStrategy : public IdentificationStrategy {
+public:
+	DefaultStrategy();
+	DefaultStrategy(const DefaultStrategy &other);
+	virtual ~DefaultStrategy();
+	virtual IDENTIFICATION_STRATEGY identification_strategy() const;
+	virtual void identify_pc(PcIdentifier &identifier) const;
+	virtual std::vector<PcIdentifier> alternative_ids() const;
+	virtual EVENT_TYPE validate_identifier(const PcIdentifier &identifier) const;
+};
+
+} /* namespace license */
+
+#endif /* SRC_LIBRARY_PC_IDENTIFIER_DEFAULT_STRATEGY_HPP_ */
diff --git a/src/library/pc_identifier/identification_strategy.hpp b/src/library/pc_identifier/identification_strategy.hpp
new file mode 100644
index 0000000..852de7b
--- /dev/null
+++ b/src/library/pc_identifier/identification_strategy.hpp
@@ -0,0 +1,28 @@
+/*
+ * identification_strategy.hpp
+ *
+ *  Created on: Jan 1, 2020
+ *      Author: devel
+ */
+
+#ifndef SRC_LIBRARY_PC_IDENTIFIER_IDENTIFICATION_STRATEGY_HPP_
+#define SRC_LIBRARY_PC_IDENTIFIER_IDENTIFICATION_STRATEGY_HPP_
+
+#include <licensecc/datatypes.h>
+#include <vector>
+#include "pc_identifier.hpp"
+namespace license {
+
+class IdentificationStrategy {
+public:
+	IdentificationStrategy(){};
+	virtual ~IdentificationStrategy(){};
+	virtual IDENTIFICATION_STRATEGY identification_strategy() const = 0;
+	virtual void identify_pc(PcIdentifier &identifier) const = 0;
+	virtual std::vector<PcIdentifier> alternative_ids() const = 0;
+	virtual EVENT_TYPE validate_identifier(const PcIdentifier &identifier) const = 0;
+};
+
+} /* namespace license */
+
+#endif /* SRC_LIBRARY_PC_IDENTIFIER_IDENTIFICATION_STRATEGY_HPP_ */
diff --git a/src/library/pc_identifier/pc-identifiers.c b/src/library/pc_identifier/pc-identifiers.c
index f1ec089..eda22b6 100644
--- a/src/library/pc_identifier/pc-identifiers.c
+++ b/src/library/pc_identifier/pc-identifiers.c
@@ -4,14 +4,14 @@
  *  Created on: Apr 16, 2014
  *
  */
-
-#include "os/os.h"
-#include "pc-identifiers.h"
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include "base/base64.h"
-#include "base/base.h"
+
+#include "../os/os.h"
+#include "pc-identifiers.h"
+#include "../base/base64.h"
+#include "../base/base.h"
 #ifdef __linux__
 #include <stdbool.h>
 #include <valgrind/memcheck.h>
@@ -69,7 +69,6 @@
 				array_index = i * adapter_num + j;
 				if (array_index >= caller_identifiers) {
 					function_return = FUNC_RET_BUFFER_TOO_SMALL;
-					// sweet memories...
 					goto end;
 				}
 				for (k = 0; k < 6; k++)
diff --git a/src/library/pc_identifier/pc-identifiers.h b/src/library/pc_identifier/pc-identifiers.h
index 2eb0d56..f245096 100644
--- a/src/library/pc_identifier/pc-identifiers.h
+++ b/src/library/pc_identifier/pc-identifiers.h
@@ -9,11 +9,11 @@
 #define PC_IDENTIFIERS_H_
 
 #include <licensecc/datatypes.h>
-#include "base/base.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
+#include "../base/base.h"
 
 typedef unsigned char PcIdentifier[6];
 typedef char PcSignature[PC_IDENTIFIER_SIZE + 1];
diff --git a/src/library/pc_identifier/pc_identifier.cpp b/src/library/pc_identifier/pc_identifier.cpp
new file mode 100644
index 0000000..e9dc59c
--- /dev/null
+++ b/src/library/pc_identifier/pc_identifier.cpp
@@ -0,0 +1,58 @@
+/*
+ * pc_identifier.cpp
+ *
+ *  Created on: Dec 22, 2019
+ *      Author: GC
+ */
+
+#include <algorithm>
+#include "pc_identifier.hpp"
+#include "../base/base64.h"
+
+namespace license {
+using namespace std;
+
+PcIdentifier::PcIdentifier() {}
+
+PcIdentifier::PcIdentifier(const std::string& param) {
+	// TODO Auto-generated constructor stub
+}
+
+PcIdentifier::~PcIdentifier() {}
+
+PcIdentifier::PcIdentifier(const PcIdentifier& other) : m_data(other.m_data) {}
+
+void PcIdentifier::set_identification_strategy(IDENTIFICATION_STRATEGY strategy) {
+	if (strategy == STRATEGY_UNKNOWN || strategy == STRATEGY_DEFAULT) {
+		throw logic_error("Only known strategies are permitted");
+	}
+	uint8_t stratMov = (strategy << 5);
+	m_data[1] = (m_data[1] & 0x1F) | stratMov;
+}
+
+void PcIdentifier::set_use_environment_var(bool use_env_var) {
+	if (use_env_var) {
+		m_data[0] = m_data[0] | 0x40;
+	} else {
+		m_data[0] = m_data[0] & ~0x40;
+	}
+}
+
+void PcIdentifier::set_virtual_environment(VIRTUALIZATION virt) {
+	// 110000 0x30
+	m_data[0] = (m_data[0] && ~0x30) | virt << 4;
+}
+
+void PcIdentifier::set_virtualization(VIRTUALIZATION_DETAIL virtualization_detail) {}
+
+void PcIdentifier::set_cloud_provider(CLOUD_PROVIDER cloud_provider) {}
+
+void PcIdentifier::set_data(const std::array<uint8_t, 6>& data) {}
+
+std::string PcIdentifier::print() const {
+	string result = base64(m_data.data(), m_data.size(), 4);
+	std::replace(result.begin(), result.end(), '\n', '-');
+	return result;
+}
+
+} /* namespace license */
diff --git a/src/library/pc_identifier/pc_identifier.hpp b/src/library/pc_identifier/pc_identifier.hpp
new file mode 100644
index 0000000..f3587bb
--- /dev/null
+++ b/src/library/pc_identifier/pc_identifier.hpp
@@ -0,0 +1,64 @@
+/*
+ * pc_identifier.h
+ *
+ *  Created on: Dec 22, 2019
+ *      Author: GC
+ */
+
+#ifndef SRC_LIBRARY_PC_IDENTIFIER_PC_IDENTIFIER_HPP_
+#define SRC_LIBRARY_PC_IDENTIFIER_PC_IDENTIFIER_HPP_
+
+#include <bits/stdint-uintn.h>
+#include <array>
+#include <iostream>
+#include <string>
+
+#include "../../../include/licensecc/datatypes.h"
+#include "../os/execution_environment.hpp"
+
+namespace license {
+
+/**
+ * data[0]
+ * bit 7 = 0 if pc id is being generated 1 if it is included in a license.
+ *
+ * if bit 7 = 0
+ * bit 6 = environment variable was used to generate pc_id
+ * bit 5-4 = execution environment information (0=BARE_TO_METAL,1=VM,2=CONTAINER)
+ * bit 3 = 0 on premise vm 1 = cloud
+ * if on premise vm bits 2-1-0 are virtualization technology
+ * if cloud vm bits 2-1-0 identify cloud provider
+ *
+ * if bit 7 = 1 pc identifier is used to enable some flag that we don't want to show openly in the license
+ * bit 6 = 1 enable magic file/registry key
+ * ----
+ * data[1] bit 7-6-5 define identification strategy.
+ * data[1] bits 4-0 and data[1-5] are pc identifier proprietary strategy data.
+ */
+
+class PcIdentifier {
+private:
+	std::array<uint8_t, 6> m_data = {};
+
+public:
+	PcIdentifier();
+	PcIdentifier(const std::string &param);
+	virtual ~PcIdentifier();
+	PcIdentifier(const PcIdentifier &other);
+	void set_identification_strategy(IDENTIFICATION_STRATEGY strategy);
+	IDENTIFICATION_STRATEGY get_identification_strategy() const;
+	void set_use_environment_var(bool use_env_var);
+	void set_virtual_environment(VIRTUALIZATION virtualization);
+	void set_virtualization(VIRTUALIZATION_DETAIL virtualization_detail);
+	void set_cloud_provider(CLOUD_PROVIDER cloud_provider);
+	void set_data(const std::array<uint8_t, 6> &data);
+	std::string print() const;
+	friend std::ostream &operator<<(std::ostream &output, const PcIdentifier &d) {
+		output << d.print();
+		return output;
+	};
+};
+
+} /* namespace license */
+
+#endif /* SRC_LIBRARY_PC_IDENTIFIER_PC_IDENTIFIER_HPP_ */
diff --git a/src/library/pc_identifier/pc_identifier_facade.cpp b/src/library/pc_identifier/pc_identifier_facade.cpp
new file mode 100644
index 0000000..46263f6
--- /dev/null
+++ b/src/library/pc_identifier/pc_identifier_facade.cpp
@@ -0,0 +1,30 @@
+/*
+ * pc_identifier_facade.cpp
+ *
+ *  Created on: Dec 26, 2019
+ *      Author: devel
+ */
+#include <unordered_map>
+#include <bits/unique_ptr.h>
+
+#include "pc_identifier_facade.hpp"
+#include "identification_strategy.hpp"
+#include "pc_identifier.hpp"
+#include "../os/execution_environment.hpp"
+namespace license {
+
+std::unordered_map<IDENTIFICATION_STRATEGY, std::unique_ptr<IdentificationStrategy>> STRATEGY_MAP;
+
+EVENT_TYPE PcIdentifierFacade::validate_pc_signature(const std::string& str_code) {
+	PcIdentifier pc_id(str_code);
+	IDENTIFICATION_STRATEGY id_strategy = pc_id.get_identification_strategy();
+	auto it = STRATEGY_MAP.find(id_strategy);
+	EVENT_TYPE result = IDENTIFIERS_MISMATCH;
+	if (it != STRATEGY_MAP.end()) {
+		result = it->second->validate_identifier(pc_id);
+	}
+	return result;
+}
+
+std::string PcIdentifierFacade::generate_user_pc_signature(IDENTIFICATION_STRATEGY strategy) { PcIdentifier pc_id; }
+} /* namespace license */
diff --git a/src/library/pc_identifier/pc_identifier_facade.hpp b/src/library/pc_identifier/pc_identifier_facade.hpp
new file mode 100644
index 0000000..0d54332
--- /dev/null
+++ b/src/library/pc_identifier/pc_identifier_facade.hpp
@@ -0,0 +1,25 @@
+/*
+ * pc_identifier_facade.hpp
+ *
+ *  Created on: Dec 26, 2019
+ *      Author: devel
+ */
+
+#ifndef SRC_LIBRARY_PC_IDENTIFIER_PC_IDENTIFIER_FACADE_HPP_
+#define SRC_LIBRARY_PC_IDENTIFIER_PC_IDENTIFIER_FACADE_HPP_
+#include <string>
+#include <licensecc/datatypes.h>
+
+namespace license {
+class PcIdentifierFacade {
+private:
+	PcIdentifierFacade(){};
+	virtual ~PcIdentifierFacade(){};
+public:
+	static EVENT_TYPE validate_pc_signature(const std::string& str_code);
+	static std::string generate_user_pc_signature(IDENTIFICATION_STRATEGY strategy);
+};
+
+} /* namespace license */
+
+#endif /* SRC_LIBRARY_PC_IDENTIFIER_PC_IDENTIFIER_FACADE_HPP_ */
diff --git a/test/IdentificationStrategy_test.cpp b/test/IdentificationStrategy_test.cpp
new file mode 100644
index 0000000..f81a169
--- /dev/null
+++ b/test/IdentificationStrategy_test.cpp
@@ -0,0 +1,10 @@
+/*
+ * IdentificationStrategy_test.cpp
+ *
+ *  Created on: Jan 1, 2020
+ *      Author: devel
+ */
+
+#include "identification_strategy.hpp"
+
+namespace license {} /* namespace license */
diff --git a/test/default_strategy_test.cpp b/test/default_strategy_test.cpp
new file mode 100644
index 0000000..8cba3cf
--- /dev/null
+++ b/test/default_strategy_test.cpp
@@ -0,0 +1,10 @@
+/*
+ * default_strategy_test.cpp
+ *
+ *  Created on: Jan 2, 2020
+ *      Author: devel
+ */
+
+#include "default_strategy.hpp"
+
+namespace license {} /* namespace license */
diff --git a/test/functional/generate-license.cpp b/test/functional/generate-license.cpp
index 8ef9477..98cd979 100644
--- a/test/functional/generate-license.cpp
+++ b/test/functional/generate-license.cpp
@@ -20,8 +20,10 @@
 
 namespace fs = boost::filesystem;
 using namespace std;
+
 namespace license {
 namespace test {
+
 string generate_license(const string& license_name, const vector<string>& other_args) {
 	fs::path lcc_exe(LCC_EXE);
 	BOOST_REQUIRE_MESSAGE(fs::is_regular_file(lcc_exe), "License generator not found: " LCC_EXE);
diff --git a/test/functional/hijiaking_test.cpp b/test/functional/hijiaking_test.cpp
deleted file mode 100644
index d18b84d..0000000
--- a/test/functional/hijiaking_test.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#define BOOST_TEST_MODULE standard_license_test
-
-#include <build_properties.h>
-#include <boost/filesystem.hpp>
-#include <boost/test/unit_test.hpp>
-
-#include "../../src/tools/license-generator/license-generator.h"
-#include <licensecc/licensecc.h>
-#include "../../src/library/ini/SimpleIni.h"
-#include "generate-license.h"
-
-namespace fs = boost::filesystem;
-using namespace license;
-using namespace std;
-
-
-BOOST_AUTO_TEST_CASE( standard_lic_file ) {
-	const string licLocation(PROJECT_TEST_TEMP_DIR "/standard_license.lic");
-	vector<string> extraArgs;
-	generate_license(licLocation, extraArgs);
-	/* */
-	LicenseInfo license;
-	LicenseLocation licenseLocation;
-	licenseLocation.openFileNearModule=false;
-	licenseLocation.licenseFileLocation = licLocation.c_str();
-	licenseLocation.licenseData = "";
-	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);
-}
-
diff --git a/test/library/Os_Linux_test.cpp b/test/library/Os_Linux_test.cpp
index b7b8c21..6d272bf 100644
--- a/test/library/Os_Linux_test.cpp
+++ b/test/library/Os_Linux_test.cpp
@@ -7,11 +7,15 @@
 #include <licensecc_properties_test.h>
 #include "../../src/library/base/StringUtils.h"
 #include "../../src/library/os/os.h"
+#include "../../src/library/os/execution_environment.hpp"
+
 namespace license {
 using namespace std;
 namespace test {
+
 BOOST_AUTO_TEST_CASE(read_disk_id) {
-	VIRTUALIZATION virt = getVirtualization();
+	ExecutionEnvironment exec_env;
+	VIRTUALIZATION virt = exec_env.getVirtualization();
 	if (virt == NONE || virt == VM) {
 		DiskInfo *diskInfos = NULL;
 		size_t disk_info_size = 0;
@@ -61,20 +65,19 @@
 	free(adapter_info);
 }
 
-BOOST_AUTO_TEST_CASE(get_cpuid) { BOOST_CHECK_EQUAL(1, 1); }
-
 // To test if virtualization is detected correctly define an env variable VIRT_ENV
 // otherwise the test is skipped
 BOOST_AUTO_TEST_CASE(test_virtualization) {
 	const char *env = getenv("VIRT_ENV");
+	ExecutionEnvironment exec_env;
 	if (env != NULL) {
 		if (strcmp(env, "CONTAINER") == 0) {
-			VIRTUALIZATION virt = getVirtualization();
-			BOOST_CHECK_EQUAL(virt, CONTAINER);
+			VIRTUALIZATION virt = exec_env.getVirtualization();
+			BOOST_CHECK_MESSAGE(virt == CONTAINER, "container detected");
 		} else if (strcmp(env, "VM") == 0) {
 			BOOST_FAIL("check for vm not implemented");
 		} else if (strcmp(env, "NONE") == 0) {
-			VIRTUALIZATION virt = getVirtualization();
+			VIRTUALIZATION virt = exec_env.getVirtualization();
 			BOOST_CHECK_EQUAL(virt, NONE);
 		} else {
 			BOOST_FAIL(string("value ") + env + " not supported: VM,CONTAINER,NONE");
diff --git a/test/library/cpu_info_test.cpp b/test/library/cpu_info_test.cpp
new file mode 100644
index 0000000..e04f2fe
--- /dev/null
+++ b/test/library/cpu_info_test.cpp
@@ -0,0 +1,10 @@
+/*
+ * cpu_info_test.cpp
+ *
+ *  Created on: Dec 19, 2019
+ *      Author: devel
+ */
+
+#include "cpu_info.hpp"
+
+namespace license {} /* namespace license */
diff --git a/test/library/pc_identifier_facade_test.cpp b/test/library/pc_identifier_facade_test.cpp
new file mode 100644
index 0000000..2571bc0
--- /dev/null
+++ b/test/library/pc_identifier_facade_test.cpp
@@ -0,0 +1,10 @@
+/*
+ * pc_identifier_facade_test.cpp
+ *
+ *  Created on: Dec 26, 2019
+ *      Author: devel
+ */
+
+#include "pc_identifier_facade.hpp"
+
+namespace license {} /* namespace license */
diff --git a/test/library/pc_identifier_test.cpp b/test/library/pc_identifier_test.cpp
new file mode 100644
index 0000000..108961a
--- /dev/null
+++ b/test/library/pc_identifier_test.cpp
@@ -0,0 +1,10 @@
+/*
+ * pc_identifier_test.cpp
+ *
+ *  Created on: Dec 26, 2019
+ *      Author: devel
+ */
+
+#include "../../src/library/pc_identifier/pc_identifier.hpp"
+
+namespace license {} /* namespace license */

--
Gitblit v1.9.1