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:
Andreas Stallinger
2016-02-10 12:52:00 +01:00
parent 082b94ac8d
commit 50a94bf108
12 changed files with 117 additions and 41 deletions
+4
View File
@@ -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 ----------------------------------------------------------------------
+1 -1
View File
@@ -84,7 +84,7 @@ private:
}
License license;
bool isLoaded = license.loadFromString(licenseString);
bool isLoaded = license.loadFromEncodedString(licenseString,AppPath::getAppPath());
if (!isLoaded)
{
break;
+5
View File
@@ -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;
+11 -1
View File
@@ -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;
}
+1
View File
@@ -20,6 +20,7 @@ class AppPath
{
public:
static std::string getAppPath();
static bool setAppPath(std::string path);
private:
static void setupAppPath();
+11 -3
View File
@@ -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();
+2 -2
View File
@@ -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();
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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-----";
+10 -3
View File
@@ -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"))
+1 -1
View File
@@ -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());
}