diff --git a/CMakeLists.txt b/CMakeLists.txt index 452bd865..de9e9ab9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -478,6 +478,10 @@ target_include_directories(${LICENSE_GENERATOR_PROJECT_NAME} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS} ) +if(UNIX AND NOT APPLE) + target_link_libraries(${LICENSE_GENERATOR_PROJECT_NAME} pthread dl) +endif() + target_link_libraries(${LICENSE_GENERATOR_PROJECT_NAME} ${LIB_LICENSE_PROJECT_NAME} ${Boost_LIBRARIES} ) # CxxTest ---------------------------------------------------------------------- diff --git a/src/app/LicenseChecker.h b/src/app/LicenseChecker.h index 7a1b8c49..0b215500 100644 --- a/src/app/LicenseChecker.h +++ b/src/app/LicenseChecker.h @@ -84,7 +84,7 @@ private: } License license; - bool isLoaded = license.loadFromString(licenseString); + bool isLoaded = license.loadFromEncodedString(licenseString,AppPath::getAppPath()); if (!isLoaded) { break; diff --git a/src/app/main.cpp b/src/app/main.cpp index 87e7aa3f..c049d636 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -65,6 +65,11 @@ int main(int argc, char *argv[]) QtMainWindow::setWindowSettingsPath(windowSettingsPath); Application::setAppSettingsPath(appSettingsPath); + + if(AppPath::getAppPath().empty()) + { + AppPath::setAppPath(QCoreApplication::applicationDirPath().toStdString()); + } LicenseChecker checker; diff --git a/src/lib/utility/AppPath.cpp b/src/lib/utility/AppPath.cpp index 4780c3ec..1720df2c 100644 --- a/src/lib/utility/AppPath.cpp +++ b/src/lib/utility/AppPath.cpp @@ -51,4 +51,14 @@ void AppPath::setupAppPath() m_appPath = m_appPath.substr(0, pos + 1); } #endif // WINDOWS -} \ No newline at end of file +} + +bool AppPath::setAppPath(std::string path) +{ + if(!path.empty()) + { + m_appPath = path; + return true; + } + return false; +} diff --git a/src/lib/utility/AppPath.h b/src/lib/utility/AppPath.h index 9fb301b4..8ae66954 100644 --- a/src/lib/utility/AppPath.h +++ b/src/lib/utility/AppPath.h @@ -20,6 +20,7 @@ class AppPath { public: static std::string getAppPath(); + static bool setAppPath(std::string path); private: static void setupAppPath(); diff --git a/src/lib_gui/qt/window/QtLicense.cpp b/src/lib_gui/qt/window/QtLicense.cpp index 9457f11c..8452778f 100644 --- a/src/lib_gui/qt/window/QtLicense.cpp +++ b/src/lib_gui/qt/window/QtLicense.cpp @@ -45,9 +45,17 @@ void QtLicense::load() { clear(); + License license; + bool isLoaded = license.loadFromEncodedString( + ApplicationSettings::getInstance()->getLicenseString(), AppPath::getAppPath()); + if (!isLoaded) + { + return; + } + if (m_licenseText) { - m_licenseText->setText(ApplicationSettings::getInstance()->getLicenseString().c_str()); + m_licenseText->setText(license.getLicenseString().c_str()); } } @@ -148,8 +156,8 @@ void QtLicense::handleUpdateButtonPress() if (license.isValid()) { ApplicationSettings* appSettings = ApplicationSettings::getInstance().get(); - appSettings->setLicenseString(license.getLicenseString()); - std::string appLocation = AppPath::getAppPath(); // for easier debugging + std::string appLocation = AppPath::getAppPath(); + appSettings->setLicenseString(license.getLicenseEncodedString(appLocation)); FilePath p(appLocation); appSettings->setLicenseCheck(license.hashLocation(p.absolute().str())); appSettings->save(); diff --git a/src/lib_license/Generator.cpp b/src/lib_license/Generator.cpp index 19e69984..af0881a3 100644 --- a/src/lib_license/Generator.cpp +++ b/src/lib_license/Generator.cpp @@ -49,7 +49,7 @@ void Generator::setVersion(std::string version) } } -std::string Generator::encodeLicense(std::string user) +std::string Generator::encodeLicense(std::string user, std::string licenseType) { License license; @@ -62,7 +62,7 @@ std::string Generator::encodeLicense(std::string user) std::cout << "The key is not a RSA key" << std::endl; } - license.create(user, m_version, rsaKey); + license.create(user, m_version, rsaKey, licenseType); license.writeToFile("license.txt"); license.print(); diff --git a/src/lib_license/Generator.h b/src/lib_license/Generator.h index 6e3fe8af..b09c2963 100644 --- a/src/lib_license/Generator.h +++ b/src/lib_license/Generator.h @@ -11,7 +11,7 @@ public: Generator(std::string version = "x"); ~Generator(); - std::string encodeLicense(std::string message); + std::string encodeLicense(std::string message, std::string licenseType); bool verifyLicense(std::string filename = "license.txt"); void generateKeys(); void writeKeysToFiles(); diff --git a/src/lib_license/License.cpp b/src/lib_license/License.cpp index bca326b3..05ad2a21 100644 --- a/src/lib_license/License.cpp +++ b/src/lib_license/License.cpp @@ -69,7 +69,7 @@ std::string License::getLicenseTypeLine() const return lines[2]; } -void License::create(std::string user, std::string version, Botan::RSA_PrivateKey* privateKey, unsigned int type) +void License::create(std::string user, std::string version, Botan::RSA_PrivateKey* privateKey, std::string type) { m_version = version; createMessage(user, version, type); @@ -85,20 +85,12 @@ void License::create(std::string user, std::string version, Botan::RSA_PrivateKe addSignature(signature); } -void License::createMessage(std::string user, std::string version, unsigned int type) +void License::createMessage(std::string user, std::string version, std::string type) { lines.clear(); lines.push_back(BEGIN_LICENSE); lines.push_back(user); - std::string typestring; - switch(type) - { - case 0: - default: - typestring = "Single User License"; - - }; - lines.push_back(typestring); + lines.push_back(type); std::string versionstring = "Coati " + getVersion(); lines.push_back(versionstring); std::string pass9 = Botan::generate_passhash9(versionstring, *(m_rng.get())); @@ -155,7 +147,6 @@ bool License::load(std::istream& stream) return true; } - bool License::loadFromFile(std::string filename) { lines.clear(); @@ -201,7 +192,7 @@ bool License::isValid() const } if(Botan::check_passhash9("Coati "+ getVersion(), getHashLine())) { - std::cout << "Hash from Coati "+ getVersion() + " confirmed" << std::endl; +// std::cout << "Hash from Coati "+ getVersion() + " confirmed" << std::endl; } Botan::secure_vector sig = Botan::base64_decode(getSignature()); @@ -267,7 +258,6 @@ bool License::loadPublicKeyFromString(std::string publicKey) return true; } - void License::setVersion(const std::string& version) { if(!version.empty()) @@ -295,3 +285,55 @@ bool License::checkLocation(const std::string& location, const std::string& hash { return Botan::check_passhash9(location, hash); } + +std::string License::getLicenseEncodedString(std::string applicationLocation) const +{ + Botan::AutoSeeded_RNG rng; + std::vector file_contents; + std::stringstream input(getLicenseString()); + + //prepare the license string to work with the botan cryptobox + while(input.good()) + { + Botan::byte filebuf[4096] = { 0 }; + input.read((char*)filebuf, sizeof(filebuf)); + size_t got = input.gcount(); + + file_contents.insert(file_contents.end(), filebuf, filebuf+got); + } + + std::string ret = Botan::CryptoBox::encrypt(&file_contents[0], file_contents.size(),getEncodeKey(applicationLocation),rng); + + //remove Botan Cryptobox begin and end + //should not be in the application settings + ret = ret.substr(40,ret.length()-78); + + return ret; +} + +bool License::loadFromEncodedString(std::string encodedLicense, std::string applicationLocation) +{ + try { + //add cryptobox begin and end to loaded string + std::string crypbobxInput = "-----BEGIN BOTAN CRYPTOBOX MESSAGE-----\n"; + crypbobxInput += encodedLicense; + crypbobxInput += "-----END BOTAN CRYPTOBOX MESSAGE-----"; + + //decrypt license + loadFromString(Botan::CryptoBox::decrypt(crypbobxInput,getEncodeKey(applicationLocation))); + } + catch(...) + { + //loaded string from application settings is invalid + return false; + } + return true; +} + +std::string License::getEncodeKey(const std::string applicationLocation) const +{ + Botan::PBKDF *pbkdf = Botan::get_pbkdf("PBKDF2(SHA-256)"); + Botan::secure_vector salt = Botan::base64_decode("34zA54n60v4CxjY5n20k3J40c976n690", 32); + Botan::AutoSeeded_RNG rng; + return pbkdf->derive_key(32, applicationLocation, &salt[0], salt.size(), 10000).as_string(); +} diff --git a/src/lib_license/License.h b/src/lib_license/License.h index 1e200ed9..3920da11 100644 --- a/src/lib_license/License.h +++ b/src/lib_license/License.h @@ -15,11 +15,6 @@ namespace Botan class License { public: - enum LicenseType - { - LICENSETYPE_SINGLEUSER = 0, - }; - License(); ~License(); @@ -33,19 +28,22 @@ public: std::string getPublicKeyFilename() const; std::string getVersion() const; - void create(std::string user, std::string version, Botan::RSA_PrivateKey* privateKey, unsigned int type = 0); + void create(std::string user, std::string version, Botan::RSA_PrivateKey* privateKey, std::string type="Private License"); std::string getLicenseString() const; + std::string getLicenseEncodedString(std::string applicationLocation) const; void writeToFile(std::string filename); bool load(std::istream& stream); bool loadFromString(std::string licenseText); bool loadFromFile(std::string filename); + bool loadFromEncodedString(std::string encodedLicense, std::string applicationLocation); + + bool loadPublicKeyFromFile(std::string); - bool loadPublicKeyFromFile(std::string); bool loadPublicKeyFromString(std::string); + void setVersion(const std::string&); - void setVersion(const std::string&); bool isValid() const; void print(); @@ -54,14 +52,15 @@ public: static bool checkLocation(const std::string&, const std::string&); private: - void createMessage(std::string user, std::string version, unsigned int type = 0); - void addSignature(std::string); + void createMessage(std::string user, std::string version, std::string type = 0); + void addSignature(std::string); + std::string getEncodeKey(const std::string applicationLocation) const; - std::string m_version; - std::string m_publicKeyFilename; - std::shared_ptr m_publicKey; - std::vector lines; - std::shared_ptr m_rng; + std::string m_version; + std::string m_publicKeyFilename; + std::shared_ptr m_publicKey; + std::vector lines; + std::shared_ptr m_rng; const std::string KEY_FILEENDING = ".pem"; const std::string BEGIN_LICENSE = "-----BEGIN LICENSE-----"; diff --git a/src/license_generator/main.cpp b/src/license_generator/main.cpp index 7e462e6f..dc649376 100644 --- a/src/license_generator/main.cpp +++ b/src/license_generator/main.cpp @@ -17,7 +17,8 @@ bool process_command_line(int argc, char** argv) std::string version; std::string privateKey; std::string publicKey; - std::string license; + std::string license = ""; + std::string type = ""; po::options_description desc("Coati Generator"); desc.add_options() @@ -26,6 +27,7 @@ bool process_command_line(int argc, char** argv) ("generate,g", po::value(&user), "Generate a License, USERNAME as value") ("check,c", "Validate a License") ("version,v", po::value(&version), "Versionnumber of Coati") + ("licenseType,t", po::value(&type), "License Type of ") ("public-file", po::value(&publicKey), "Custom public key file") ("private-file", po::value(&privateKey), "Custom private key file") ("license-file", po::value(&license), "Custom license") @@ -61,9 +63,14 @@ bool process_command_line(int argc, char** argv) if(vm.count("generate")) { -// std::cout << "generate License" << std::endl; - keygen.encodeLicense(user); + bool fail = false; + if(!vm.count("version")) + { + std::cout << "Version of Coati is needed to generate a License" << std::endl; + return false; + } + keygen.encodeLicense(user,type); } if(vm.count("check")) diff --git a/src/test/GeneratorTestSuite.h b/src/test/GeneratorTestSuite.h index c246d7ef..8d85194e 100644 --- a/src/test/GeneratorTestSuite.h +++ b/src/test/GeneratorTestSuite.h @@ -51,7 +51,7 @@ public: license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); TS_ASSERT_EQUALS(license.getOwnerLine(), "TestUser"); - TS_ASSERT_EQUALS(license.getLicenseTypeLine(), "Single User License"); + TS_ASSERT_EQUALS(license.getLicenseTypeLine(), "Private License"); TS_ASSERT_EQUALS(license.getVersion(), "v2"); TS_ASSERT(license.isValid()); }