| | |
| | | #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; |
| | |
| | | |
| | | 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")) { |
| | |
| | | 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); |
| | | } |
| | | } |
| | |
| | | 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) { |
| | |
| | | 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; |
| | | } |
| | |
| | | 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(); |
| | | } |
| | | } |