// LicenseManagerTest.cpp : 이 파일에는 'main' 함수가 포함됩니다. 거기서 프로그램 실행이 시작되고 종료됩니다. // #include "../pch.h" #include "../SHA256.h" #include #include #include #include #include #include #include #include #include #include #include #include #include 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(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(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("") + 1, line.find("") - line.find(">") - 1); else if (line.find("") != std::string::npos) licenseInfo.serialId = line.substr(line.find(">") + 1, line.find("") - line.find(">") - 1); else if (line.find("") != std::string::npos) licenseInfo.issueDay = line.substr(line.find(">") + 1, line.find("") - line.find(">") - 1); else if (line.find("") != std::string::npos) licenseInfo.edition = line.substr(line.find(">") + 1, line.find("") - line.find(">") - 1); else if (line.find("") != std::string::npos) licenseInfo.type = line.substr(line.find(">") + 1, line.find("") - line.find(">") - 1); else if (line.find("") != std::string::npos) licenseInfo.accountsStr = line.substr(line.find(">") + 1, line.find("") - line.find(">") - 1); else if (line.find("") != std::string::npos) licenseInfo.identifiedHost = line.substr(line.find(">") + 1, line.find("") - line.find(">") - 1); else if (line.find("") != std::string::npos) licenseInfo.signature = line.substr(line.find(">") + 1, line.find("") - line.find(">") - 1); else if (line.find("") != std::string::npos) licenseInfo.demoDurationStr = line.substr(line.find(">") + 1, line.find("") - 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 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"; }