62 #pragma comment(lib, "IPHLPAPI.lib") 66 #include <sys/types.h> 67 #include <sys/sysctl.h> 71 #include <OpenFlipper/LicenseManager/LicenseManagerActive.hh> 75 #include <QCryptographicHash> 76 #include <QNetworkInterface> 90 QByteArray decodeString(
const QString& _string ,
bool _utf8){
93 return _string.toUtf8();
95 return _string.toLatin1();
99 LicenseManager::~LicenseManager()
104 LicenseManager::LicenseManager()
110 QObject::blockSignals(
true );
118 QObject::blockSignals(
true );
120 QObject::blockSignals(_state);
126 bool LicenseManager::timestampOk() {
128 bool notExpired =
false;
129 bool gotTimestampEntry =
false;
131 quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
132 quint64 lastTimestamp = timestamp;
133 quint64 timestampEntry = 0;
134 quint64 lastTimestampEntryNum = 0;
145 if( lastTimestampEntry==QString(
"empty") ){
148 lastTimestampEntryNum = lastTimestampEntry.toULongLong(&gotTimestampEntry,16);
155 const unsigned int factor = 30000;
157 const unsigned int moduloFactor = 72;
159 const int nameEncr = ( name[0] ) + ( name[nameSize-1] ) + (name[(nameSize-1) / 2] );
161 bool moduloOK = (lastTimestampEntryNum -( 100 * (lastTimestampEntryNum / 100) ) == (lastTimestampEntryNum/100) % moduloFactor );
163 lastTimestampEntryNum = lastTimestampEntryNum / 100;
164 lastTimestampEntryNum = lastTimestampEntryNum - nameEncr;
165 lastTimestampEntryNum = lastTimestampEntryNum * factor;
167 lastTimestamp = lastTimestampEntryNum;
173 if (notExpired||(timestamp>(lastTimestamp-360000) && moduloOK)) {
176 timestamp = std::numeric_limits<quint64>::max();
184 timestampEntry = timestamp;
186 timestampEntry = timestampEntry / factor;
187 timestampEntry = timestampEntry + nameEncr;
188 timestampEntry = (timestampEntry * 100) + (timestampEntry % moduloFactor);
213 ADD_SALT_PRE(saltPre);
216 ADD_SALT_POST(saltPost);
218 QString licenseFileName = OpenFlipper::Options::licenseDirStr() + QDir::separator() +
pluginFileName() +
".lic";
219 QFile file( licenseFileName );
220 QStringList elements;
221 bool signatureOk =
false;
223 bool utf8Encoded =
true;
225 if (file.open(QIODevice::ReadOnly|QIODevice::Text))
227 QString licenseContents = file.readAll();
228 elements = licenseContents.split(
'\n',QString::SkipEmptyParts);
229 bool fileOk = !elements.empty() && elements[0] !=
"ERROR";
234 for (
int i = 0 ; i < elements.size(); ++i )
235 elements[i] = elements[i].simplified();
238 QString license = saltPre;
239 for (
int i = 1 ; i < elements.size(); ++i )
240 license += elements[i];
242 QString licenseHash = QCryptographicHash::hash ( license.toUtf8() , QCryptographicHash::Sha1 ).toHex();
243 signatureOk = licenseHash == elements[0];
249 licenseHash = QCryptographicHash::hash ( license.toLatin1() , QCryptographicHash::Sha1 ).toHex();
250 signatureOk = licenseHash == elements[0];
257 elements = QStringList();
265 QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() +
"OpenFlipper.exe");
266 #elif defined ARCH_DARWIN 267 QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() +
".." +
268 QDir::separator() +
"MacOS"+
269 QDir::separator() +
"OpenFlipper");
271 QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() +
"bin" + QDir::separator() +
TOSTRING(PRODUCT_STRING));
274 if ( ! coreApp.exists() ) {
275 std::cerr <<
"Error finding core application for security check! : " << coreApp.fileName().toStdString() << std::endl;
279 coreApp.open(QIODevice::ReadOnly);
280 QCryptographicHash sha1sumCore( QCryptographicHash::Sha1 );
281 sha1sumCore.addData(coreApp.readAll() );
284 QString coreHash = QString(sha1sumCore.result().toHex());
292 QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() +
pluginFileName() +
".dll");
293 #elif defined ARCH_DARWIN 294 QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() +
"lib" +
pluginFileName() +
".so");
296 QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() +
"lib" +
pluginFileName() +
".so");
299 if ( ! pluginFile.exists() ) {
300 std::cerr <<
"Error finding plugin file for security check!" << std::endl;
301 std::cerr <<
"Path: " << pluginFile.fileName().toStdString() << std::endl;
305 pluginFile.open(QIODevice::ReadOnly);
306 QCryptographicHash sha1sumPlugin( QCryptographicHash::Sha1 );
307 sha1sumPlugin.addData(pluginFile.readAll());
310 QString pluginHash = QString(sha1sumPlugin.result().toHex());
316 QStringList macHashes;
320 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) 321 #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) 324 PIP_ADAPTER_ADDRESSES pAddresses = NULL;
330 outBufLen =
sizeof (IP_ADAPTER_ADDRESSES);
331 pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
334 ULONG family = AF_UNSPEC;
337 ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
341 if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) {
343 pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
347 if (pAddresses != NULL) {
350 DWORD dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
352 if (dwRetVal == NO_ERROR) {
355 PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses;
357 while (pCurrAddresses) {
360 if (pCurrAddresses->PhysicalAddressLength != 0) {
361 QString currentMac =
"";
363 for (uint i = 0; i < pCurrAddresses->PhysicalAddressLength; i++) {
365 currentMac += QString(
"%1").arg( (
int) pCurrAddresses->PhysicalAddress[i] , 2 ,16,QChar(
'0'));
367 if (i != (pCurrAddresses->PhysicalAddressLength - 1))
373 if ( (currentMac.count(
":") == 5) &&
374 ( pCurrAddresses->IfType == IF_TYPE_IEEE80211 || pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD ) ) {
377 currentMac = (decodeString(currentMac,utf8Encoded)).toUpper();
378 currentMac = currentMac.remove(
":");
379 macHashes.push_back(currentMac);
385 pCurrAddresses = pCurrAddresses->Next;
397 QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
398 foreach ( QNetworkInterface netInterface, interfaces ) {
401 if ( ( netInterface.flags() & QNetworkInterface::IsLoopBack ) ) {
406 if ( netInterface.hardwareAddress().count(
":") != 5 ) {
411 QString currentMac = (decodeString(netInterface.hardwareAddress(),utf8Encoded)).toUpper();
412 currentMac = currentMac.remove(
":");
414 macHashes.push_back(currentMac);
421 macHashes.removeDuplicates();
424 for (
int i = 0 ; i < macHashes.size(); ++i )
426 macHashes[i] = QCryptographicHash::hash ( decodeString(macHashes[i],utf8Encoded) , QCryptographicHash::Sha1 ).toHex();
432 QString processor(
"Unknown");
435 QSettings registryCPU(
"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor", QSettings::NativeFormat);
437 QStringList cpus = registryCPU.childGroups();
438 if ( cpus.size() != 0 ) {
439 processor = registryCPU.value( cpus[0]+
"/ProcessorNameString",
"Unknown" ).toString();
442 #elif defined ARCH_DARWIN 448 sysctlbyname(
"machdep.cpu.brand_string", NULL, &lenCPU, NULL, 0);
451 pCPU = (
char * )malloc(lenCPU);
454 sysctlbyname(
"machdep.cpu.brand_string", pCPU, &lenCPU, NULL, 0);
457 processor = QString(pCPU);
463 QFile cpuinfo(
"/proc/cpuinfo");
464 if ( cpuinfo.exists() ) {
465 cpuinfo.open(QFile::ReadOnly);
466 QTextStream stream(&cpuinfo);
467 QStringList splitted = stream.readAll().split(
"\n",QString::SkipEmptyParts);
469 int position = splitted.indexOf ( QRegExp(
"^model name.*") );
470 if ( position != -1 ){
471 QString cpuModel = splitted[position].section(
':', -1).simplified();
472 processor = cpuModel;
477 QString cpuHash = QCryptographicHash::hash ( decodeString(processor,utf8Encoded) , QCryptographicHash::Sha1 ).toHex();
486 QSettings registryProduct(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", QSettings::NativeFormat);
487 QString productId = registryProduct.value(
"ProductId",
"Unknown" ).toString();
489 QString productId =
"-";
492 QString productHash = QCryptographicHash::hash ( decodeString(productId,utf8Encoded) , QCryptographicHash::Sha1 ).toHex();
498 if (!elements.empty())
502 QDate currentDate = QDate::currentDate();
503 QDate expiryDate = QDate::fromString(elements[1],Qt::ISODate);
504 bool expired = (currentDate > expiryDate);
506 QStringList licensedMacs;
507 for (
int i = 7 ; i < elements.size(); ++i ) {
508 licensedMacs.push_back(elements[i]);
511 bool macFound =
false;
512 for (
int i = 0; i < macHashes.size(); ++i ) {
513 if ( licensedMacs.contains(macHashes[i]) )
517 if ( !signatureOk ) {
518 authstring_ += tr(
"License Error: The license file signature for Plugin \"") +
name() + tr(
"\" is invalid!\n\n");
519 }
else if ( expired ) {
520 authstring_ += tr(
"License Error: The license for plugin \"") +
name() + tr(
"\" has expired on ") + elements[1] +
"!\n\n";
521 }
else if ( !timestampOk() ) {
522 authstring_ += tr(
"License Error: System time has been reset. The license for plugin \"") +
name() + tr(
"\" has been expired!\n\n");
524 authstring_ += tr(
"License Error: The license file contains plugin name\"") + elements[2] + tr(
"\" but this is plugin \"") +
name() +
"\"!\n\n";
525 }
else if ( elements[3] != coreHash ) {
526 authstring_ += tr(
"License Error: The license file for plugin \"") +
name() + tr(
"\" is invalid for the currently running OpenFlipper Core!\n\n");
527 }
else if ( elements[4] != pluginHash ) {
528 authstring_ += tr(
"License Error: The plugin \"") +
name() + tr(
"\" is a different version than specified in license file!\n\n");
529 }
else if ( elements[5] != cpuHash ) {
530 authstring_ +=
"License Error: The plugin \"" +
name() +
"\" is not allowed to run on the current system (Changed CPU?)!\n\n";
531 }
else if ( elements[6] != productHash ) {
532 authstring_ +=
"License Error: The plugin \"" +
name() +
"\" is not allowed to run on the current system (Changed OS?)!\n\n";
533 }
else if ( !macFound ) {
534 authstring_ +=
"License Error: The plugin \"" +
name() +
"\" is not allowed to run on the current system (Changed Network?)!\n\n";
548 authstring_ += tr(
"Message: License check for plugin failed.\n");
549 authstring_ += tr(
"Message: Please get a valid License!\n");
550 authstring_ += tr(
"Message: Send the following Information to \n");
551 authstring_ += tr(
"Contact mail: ") + CONTACTMAIL +
"\n\n";
558 for (
int i = 0 ; i < macHashes.size(); ++i )
561 QString keyRequest = saltPre +
pluginFileName() + coreHash + pluginHash + cpuHash + productHash + macHashes.join(
"") + saltPost;
562 QString requestSig = QCryptographicHash::hash ( keyRequest.toUtf8() , QCryptographicHash::Sha1 ).toHex();
594 ADD_PLUGIN_FILENAME(pluginFileName);
bool authenticated_
This flag is true if authentication was successful.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
QString authstring_
License information string.
virtual QString pluginFileName()
#define TOSTRING(x)
QSettings object containing all program settings of OpenFlipper.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void blockSignals(bool _state)
void connectNotify(const char *signal)