logic: Application moving protection, licensegenerator for other licensetypes
* Licensegenerator can now generate any type of license via commandline argument * When moving the appliction, the user needs to enter the License again
This commit is contained in:
@@ -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 ----------------------------------------------------------------------
|
||||
|
||||
@@ -84,7 +84,7 @@ private:
|
||||
}
|
||||
|
||||
License license;
|
||||
bool isLoaded = license.loadFromString(licenseString);
|
||||
bool isLoaded = license.loadFromEncodedString(licenseString,AppPath::getAppPath());
|
||||
if (!isLoaded)
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -51,4 +51,14 @@ void AppPath::setupAppPath()
|
||||
m_appPath = m_appPath.substr(0, pos + 1);
|
||||
}
|
||||
#endif // WINDOWS
|
||||
}
|
||||
}
|
||||
|
||||
bool AppPath::setAppPath(std::string path)
|
||||
{
|
||||
if(!path.empty())
|
||||
{
|
||||
m_appPath = path;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ class AppPath
|
||||
{
|
||||
public:
|
||||
static std::string getAppPath();
|
||||
static bool setAppPath(std::string path);
|
||||
|
||||
private:
|
||||
static void setupAppPath();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
+56
-14
@@ -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<Botan::byte> 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<Botan::byte> 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<Botan::byte> salt = Botan::base64_decode("34zA54n60v4CxjY5n20k3J40c976n690", 32);
|
||||
Botan::AutoSeeded_RNG rng;
|
||||
return pbkdf->derive_key(32, applicationLocation, &salt[0], salt.size(), 10000).as_string();
|
||||
}
|
||||
|
||||
+14
-15
@@ -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<Botan::RSA_PublicKey> m_publicKey;
|
||||
std::vector<std::string> lines;
|
||||
std::shared_ptr<Botan::AutoSeeded_RNG> m_rng;
|
||||
std::string m_version;
|
||||
std::string m_publicKeyFilename;
|
||||
std::shared_ptr<Botan::RSA_PublicKey> m_publicKey;
|
||||
std::vector<std::string> lines;
|
||||
std::shared_ptr<Botan::AutoSeeded_RNG> m_rng;
|
||||
|
||||
const std::string KEY_FILEENDING = ".pem";
|
||||
const std::string BEGIN_LICENSE = "-----BEGIN LICENSE-----";
|
||||
|
||||
@@ -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<std::string>(&user), "Generate a License, USERNAME as value")
|
||||
("check,c", "Validate a License")
|
||||
("version,v", po::value<std::string>(&version), "Versionnumber of Coati")
|
||||
("licenseType,t", po::value<std::string>(&type), "License Type of ")
|
||||
("public-file", po::value<std::string>(&publicKey), "Custom public key file")
|
||||
("private-file", po::value<std::string>(&privateKey), "Custom private key file")
|
||||
("license-file", po::value<std::string>(&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"))
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user