gcontini
2019-10-19 8bbef2865455754425a84b86680a89bff8aa7691
src/tools/license-generator/license-generator.cpp
@@ -1,32 +1,40 @@
#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;
@@ -40,43 +48,41 @@
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")) {
@@ -108,13 +114,14 @@
   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);
      }
   }
@@ -142,18 +149,32 @@
   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) {
@@ -183,13 +204,21 @@
      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;
}
@@ -197,22 +226,24 @@
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();
}
}