123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- // LicenseManagerTest.cpp : 이 파일에는 'main' 함수가 포함됩니다. 거기서 프로그램 실행이 시작되고 종료됩니다.
- //
- #include "../pch.h"
- #include "../SHA256.h"
- #include <stdio.h>
- #include <winbase.h>
- #include <iostream>
- #include <string>
- #include <fstream>
- #include <sstream>
- #include <vector>
- #include <map>
- #include <algorithm>
- #include <functional>
- #include <cctype>
- #include <locale>
- #include <ctime>
- using namespace std;
- struct LicenseInfo
- {
- int error;
- std::string errorMessage;
- std::string product;
- std::string serialId;
- std::string issueDay;
- std::string edition;
- std::string type;
- std::string accountsStr;
- int accounts;
- std::string identifiedHost;
- std::string signature;
- std::string demoDurationStr;
- int demoDuration;
- };
- #define MAX_COMPUTERNAME_LENGTH 15
- std::string GetLocalComputerName() {
- char computerName[MAX_COMPUTERNAME_LENGTH + 1];
- DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
- if (GetComputerNameA(computerName, &size))
- {
- std::string computerNameStr(computerName);
- return computerNameStr;
- }
- return "";
- }
- inline std::string& ltrim(std::string& s) {
- s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
- return s;
- }
- // 문자열의 오른쪽 공백 제거 (in-place)
- inline std::string& rtrim(std::string& s) {
- s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
- return s;
- }
- // 문자열의 양쪽 공백 제거 (in-place)
- inline std::string& trim(std::string& s) {
- rtrim(s);
- ltrim(s);
- return s;
- }
- bool equalsIgnoreCase(std::string& str1, std::string& str2)
- {
- if (str1.length() != str2.length())
- return false;
- for (int i = 0; i < str1.length(); ++i) {
- if (tolower(str1[i]) != tolower(str2[i]))
- return false;
- }
- return true;
- }
- bool is_number(const std::string& s) {
- return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
- }
- std::string toLower(std::string& str) {
- for (int i = 0; i < str.length(); ++i) {
- str[i] = tolower(str[i]);
- }
- return str;
- }
- std::string toUpper(std::string& str) {
- for (int i = 0; i < str.length(); ++i) {
- str[i] = toupper(str[i]);
- }
- return str;
- }
- // 주어진 문자열이 유효한 날짜 형식인지 확인하는 함수
- bool isValidDate(const std::string& dateStr)
- {
- struct tm tm;
- if (sscanf(dateStr.c_str(), "%d-%d-%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday) != 3)
- {
- return false;
- }
- tm.tm_mon -= 1; // 월은 0부터 시작
- tm.tm_year -= 1900; // 연도는 1900을 뺀 값
- tm.tm_hour = 0;
- tm.tm_min = 0;
- tm.tm_sec = 0;
- time_t t = mktime(&tm);
- if (t == -1)
- {
- return false;
- }
- return true;
- }
- // 만료일이 현재일자보다 큰지 여부를 확인하는 함수
- bool IsExpirationDateValid(const std::string& expirationDate, int daysToAdd)
- {
- struct tm expirationTm;
- if (sscanf(expirationDate.c_str(), "%d-%d-%d", &expirationTm.tm_year, &expirationTm.tm_mon, &expirationTm.tm_mday) != 3)
- {
- return false;
- }
- expirationTm.tm_mon -= 1; // 월은 0부터 시작
- expirationTm.tm_year -= 1900; // 연도는 1900을 뺀 값
- expirationTm.tm_hour = 23;
- expirationTm.tm_min = 59;
- expirationTm.tm_sec = 59;
- expirationTm.tm_mday += daysToAdd;
- time_t expiredTime = mktime(&expirationTm);
- if (expiredTime == -1)
- {
- return false;
- }
- time_t now = time(nullptr);
- return expiredTime > now;
- }
- int __stdcall ValidateLicense(char* licenseFilePath, int* licenseAccount)
- {
- LicenseInfo licenseInfo;
- licenseInfo.error = 0;
- licenseInfo.errorMessage = "";
- licenseInfo.product = "";
- licenseInfo.serialId = "";
- licenseInfo.issueDay = "";
- licenseInfo.edition = "";
- licenseInfo.type = "";
- licenseInfo.accountsStr = "";
- licenseInfo.accounts = 0;
- licenseInfo.identifiedHost = "";
- licenseInfo.signature = "";
- licenseInfo.demoDurationStr = "";
- licenseInfo.demoDuration = 0;
- if (licenseFilePath == NULL || licenseAccount == NULL) {
- licenseInfo.error = 1;
- licenseInfo.errorMessage = "라이센스 요청 정보가 올바르지 않습니다.";
- return -1;
- }
- *licenseAccount = -1;
- try
- {
- std::ifstream file(licenseFilePath);
- if (!file.is_open())
- {
- licenseInfo.error = 1;
- licenseInfo.errorMessage = "라이센스 파일을 열수가 없습니다.";
- return -2;
- }
- std::string line;
- while (std::getline(file, line))
- {
- if (line.find("<product") != std::string::npos)
- licenseInfo.product = line.substr(line.find(">") + 1, line.find("</product>") - line.find(">") - 1);
- else if (line.find("<serialId>") != std::string::npos)
- licenseInfo.serialId = line.substr(line.find(">") + 1, line.find("</serialId>") - line.find(">") - 1);
- else if (line.find("<issueDay>") != std::string::npos)
- licenseInfo.issueDay = line.substr(line.find(">") + 1, line.find("</issueDay>") - line.find(">") - 1);
- else if (line.find("<edition>") != std::string::npos)
- licenseInfo.edition = line.substr(line.find(">") + 1, line.find("</edition>") - line.find(">") - 1);
- else if (line.find("<type>") != std::string::npos)
- licenseInfo.type = line.substr(line.find(">") + 1, line.find("</type>") - line.find(">") - 1);
- else if (line.find("<accounts>") != std::string::npos)
- licenseInfo.accountsStr = line.substr(line.find(">") + 1, line.find("</accounts>") - line.find(">") - 1);
- else if (line.find("<identifiedHost>") != std::string::npos)
- licenseInfo.identifiedHost = line.substr(line.find(">") + 1, line.find("</identifiedHost>") - line.find(">") - 1);
- else if (line.find("<signature>") != std::string::npos)
- licenseInfo.signature = line.substr(line.find(">") + 1, line.find("</signature>") - line.find(">") - 1);
- else if (line.find("<demoDuration>") != std::string::npos)
- licenseInfo.demoDurationStr = line.substr(line.find(">") + 1, line.find("</demoDuration>") - line.find(">") - 1);
- }
- licenseInfo.product = trim(licenseInfo.product);
- licenseInfo.serialId = trim(licenseInfo.serialId);
- licenseInfo.issueDay = trim(licenseInfo.issueDay);
- licenseInfo.edition = trim(licenseInfo.edition);
- licenseInfo.type = trim(licenseInfo.type);
- licenseInfo.accountsStr = trim(licenseInfo.accountsStr);
- licenseInfo.accounts = 0;
- licenseInfo.identifiedHost = trim(licenseInfo.identifiedHost);
- licenseInfo.signature = trim(licenseInfo.signature);
- licenseInfo.demoDurationStr = trim(licenseInfo.demoDurationStr);
- file.close();
- bool isDemo = false;
- if (licenseInfo.product.empty() || licenseInfo.product == "") {
- return 1;
- }
- if (licenseInfo.serialId.empty() || licenseInfo.serialId == "") {
- return 2;
- }
- if (licenseInfo.issueDay.empty() || licenseInfo.issueDay == "") {
- return 3;
- }
- if (!isValidDate(licenseInfo.issueDay)) {
- return 33;
- }
- if (licenseInfo.edition.empty() || licenseInfo.edition == "") {
- return 4;
- }
- std::string standard = "standard";
- std::string enterprise = "enterprise";
- if (!equalsIgnoreCase(licenseInfo.edition, standard) && !equalsIgnoreCase(licenseInfo.edition, enterprise)) {
- return 34;
- }
- if (licenseInfo.type.empty() || licenseInfo.type == "") {
- return 5;
- }
- std::string demo = "demo";
- std::string product = "product";
- if (!equalsIgnoreCase(licenseInfo.type, demo) && !equalsIgnoreCase(licenseInfo.type, product)) {
- return 35;
- }
- if (equalsIgnoreCase(licenseInfo.type, demo)) {
- isDemo = true;
- }
- if (licenseInfo.accountsStr.empty() || licenseInfo.accountsStr == "") {
- return 6;
- }
- if (!is_number(licenseInfo.accountsStr)) {
- return 36;
- }
- licenseInfo.accounts = stoi(licenseInfo.accountsStr);
- *licenseAccount = licenseInfo.accounts;
- if (licenseInfo.identifiedHost.empty() || licenseInfo.identifiedHost == "") {
- return 7;
- }
- if (licenseInfo.signature.empty() || licenseInfo.signature == "") {
- return 8;
- }
- if (isDemo) {
- if (licenseInfo.demoDurationStr.empty() || licenseInfo.demoDurationStr == "") {
- return 9;
- }
- if (!is_number(licenseInfo.demoDurationStr)) {
- return 39;
- }
- licenseInfo.demoDuration = stoi(licenseInfo.demoDurationStr);
- if (!IsExpirationDateValid(licenseInfo.issueDay, licenseInfo.demoDuration)) {
- return 88; // 데모 유효기간 초과
- }
- }
- std::string localComputerName = GetLocalComputerName();
- if (!equalsIgnoreCase(localComputerName, licenseInfo.identifiedHost)) {
- return 81; // 컴퓨터 이름이 다름
- }
- std::string encKey = "hanteinfo12#$!";
- std::string encProduct = toUpper(licenseInfo.product) + encKey;
- std::string encSerialId = toLower(licenseInfo.serialId);
- std::string encIssueDay = licenseInfo.issueDay;
- std::string encEdition = toUpper(licenseInfo.edition);
- std::string encType = toLower(licenseInfo.type);
- std::string encAccounts = std::to_string(licenseInfo.accounts + 10000);
- std::string encHost = toLower(licenseInfo.identifiedHost);
- std::string encData = encProduct + encSerialId + encIssueDay + encEdition + encType + encAccounts + encHost;
- SHA256 sha;
- sha.update(encData);
- std::array<uint8_t, 32> digest = sha.digest();
- std::string encResult = "";
- for (auto& data : digest) {
- char temp[20];
- memset(temp, 0x00, sizeof(temp));
- snprintf(temp, sizeof(temp), "%02x", data);
- encResult += std::string(temp);
- }
- if (!equalsIgnoreCase(licenseInfo.signature, encResult)) {
- return 92; //시그니처 오류
- }
- return 0;
- }
- catch (const std::exception& ex)
- {
- std::string errorMessage = ex.what();
- licenseInfo.error = 99;
- licenseInfo.errorMessage = "라이센스 정보를 확인하는 중에 오류가 발생했습니다. " + errorMessage;
- return -2;
- }
- }
- int main()
- {
- int accounts;
- const char* fileName = "C:\\DEV\\SOLUTION\\IIS\\AipGateway\\License\\license.xml";
- ValidateLicense((char*)fileName, &accounts);
- std::cout << "Hello World!\n";
- }
|