71 #pragma comment(lib, "IPHLPAPI.lib")
75 #include <sys/types.h>
76 #include <sys/sysctl.h>
80 #include <OpenFlipper/LicenseManager/LicenseManagerActive.hh>
84 #include <QCryptographicHash>
85 #include <QNetworkInterface>
98 QByteArray decodeString(
const QString& _string ,
bool _utf8){
101 return _string.toUtf8();
103 return _string.toLatin1();
107 LicenseManager::~LicenseManager()
112 LicenseManager::LicenseManager()
118 QObject::blockSignals(
true );
126 QObject::blockSignals(
true );
128 QObject::blockSignals(_state);
134 bool LicenseManager::timestampOk() {
136 bool notExpired =
false;
137 bool gotTimestampEntry =
false;
139 quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
140 quint64 lastTimestamp = timestamp;
141 quint64 timestampEntry = 0;
142 quint64 lastTimestampEntryNum = 0;
153 if( lastTimestampEntry==QString(
"empty") ){
156 lastTimestampEntryNum = lastTimestampEntry.toULongLong(&gotTimestampEntry,16);
163 const unsigned int factor = 30000;
165 const unsigned int moduloFactor = 72;
167 const int nameEncr = ( name[0] ) + ( name[nameSize-1] ) + (name[(nameSize-1) / 2] );
169 bool moduloOK = (lastTimestampEntryNum -( 100 * (lastTimestampEntryNum / 100) ) == (lastTimestampEntryNum/100) % moduloFactor );
171 lastTimestampEntryNum = lastTimestampEntryNum / 100;
172 lastTimestampEntryNum = lastTimestampEntryNum - nameEncr;
173 lastTimestampEntryNum = lastTimestampEntryNum * factor;
175 lastTimestamp = lastTimestampEntryNum;
181 if (notExpired||(timestamp>(lastTimestamp-360000) && moduloOK)) {
184 timestamp = std::numeric_limits<quint64>::max();
192 timestampEntry = timestamp;
194 timestampEntry = timestampEntry / factor;
195 timestampEntry = timestampEntry + nameEncr;
196 timestampEntry = (timestampEntry * 100) + (timestampEntry % moduloFactor);
221 ADD_SALT_PRE(saltPre);
224 ADD_SALT_POST(saltPost);
226 QString licenseFileName = OpenFlipper::Options::licenseDirStr() + QDir::separator() +
pluginFileName() +
".lic";
227 QFile file( licenseFileName );
228 QStringList elements;
229 bool signatureOk =
false;
231 bool utf8Encoded =
true;
233 if (file.open(QIODevice::ReadOnly|QIODevice::Text))
235 QString licenseContents = file.readAll();
236 elements = licenseContents.split(
'\n',QString::SkipEmptyParts);
237 bool fileOk = !elements.empty() && elements[0] !=
"ERROR";
242 for (
int i = 0 ; i < elements.size(); ++i )
243 elements[i] = elements[i].simplified();
246 QString license = saltPre;
247 for (
int i = 1 ; i < elements.size(); ++i )
248 license += elements[i];
250 QString licenseHash = QCryptographicHash::hash ( license.toUtf8() , QCryptographicHash::Sha1 ).toHex();
251 signatureOk = licenseHash == elements[0];
257 licenseHash = QCryptographicHash::hash ( license.toLatin1() , QCryptographicHash::Sha1 ).toHex();
258 signatureOk = licenseHash == elements[0];
265 elements = QStringList();
273 QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() +
"OpenFlipper.exe");
274 #elif defined ARCH_DARWIN
275 QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() +
".." +
276 QDir::separator() +
"MacOS"+
277 QDir::separator() +
"OpenFlipper");
279 QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() +
"bin" + QDir::separator() +
TOSTRING(PRODUCT_STRING));
282 if ( ! coreApp.exists() ) {
283 std::cerr <<
"Error finding core application for security check! : " << coreApp.fileName().toStdString() << std::endl;
287 coreApp.open(QIODevice::ReadOnly);
288 QCryptographicHash sha1sumCore( QCryptographicHash::Sha1 );
289 sha1sumCore.addData(coreApp.readAll() );
292 QString coreHash = QString(sha1sumCore.result().toHex());
300 QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() +
pluginFileName() +
".dll");
301 #elif defined ARCH_DARWIN
302 QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() +
"lib" +
pluginFileName() +
".so");
304 QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() +
"lib" +
pluginFileName() +
".so");
307 if ( ! pluginFile.exists() ) {
308 std::cerr <<
"Error finding plugin file for security check!" << std::endl;
309 std::cerr <<
"Path: " << pluginFile.fileName().toStdString() << std::endl;
313 pluginFile.open(QIODevice::ReadOnly);
314 QCryptographicHash sha1sumPlugin( QCryptographicHash::Sha1 );
315 sha1sumPlugin.addData(pluginFile.readAll());
318 QString pluginHash = QString(sha1sumPlugin.result().toHex());
324 QStringList macHashes;
328 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
329 #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
332 PIP_ADAPTER_ADDRESSES pAddresses = NULL;
338 outBufLen =
sizeof (IP_ADAPTER_ADDRESSES);
339 pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
342 ULONG family = AF_UNSPEC;
345 ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
349 if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) {
351 pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
355 if (pAddresses != NULL) {
358 DWORD dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
360 if (dwRetVal == NO_ERROR) {
363 PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses;
365 while (pCurrAddresses) {
368 if (pCurrAddresses->PhysicalAddressLength != 0) {
369 QString currentMac =
"";
371 for (uint i = 0; i < pCurrAddresses->PhysicalAddressLength; i++) {
373 currentMac += QString(
"%1").arg( (
int) pCurrAddresses->PhysicalAddress[i] , 2 ,16,QChar(
'0'));
375 if (i != (pCurrAddresses->PhysicalAddressLength - 1))
381 if ( (currentMac.count(
":") == 5) &&
382 ( pCurrAddresses->IfType == IF_TYPE_IEEE80211 || pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD ) ) {
385 currentMac = (decodeString(currentMac,utf8Encoded)).toUpper();
386 currentMac = currentMac.remove(
":");
387 macHashes.push_back(currentMac);
393 pCurrAddresses = pCurrAddresses->Next;
405 QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
406 foreach ( QNetworkInterface netInterface, interfaces ) {
409 if ( ( netInterface.flags() & QNetworkInterface::IsLoopBack ) ) {
414 if ( netInterface.hardwareAddress().count(
":") != 5 ) {
419 QString currentMac = (decodeString(netInterface.hardwareAddress(),utf8Encoded)).toUpper();
420 currentMac = currentMac.remove(
":");
422 macHashes.push_back(currentMac);
429 macHashes.removeDuplicates();
432 for (
int i = 0 ; i < macHashes.size(); ++i )
434 macHashes[i] = QCryptographicHash::hash ( decodeString(macHashes[i],utf8Encoded) , QCryptographicHash::Sha1 ).toHex();
440 QString processor(
"Unknown");
443 QSettings registryCPU(
"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor", QSettings::NativeFormat);
445 QStringList cpus = registryCPU.childGroups();
446 if ( cpus.size() != 0 ) {
447 processor = registryCPU.value( cpus[0]+
"/ProcessorNameString",
"Unknown" ).toString();
450 #elif defined ARCH_DARWIN
456 sysctlbyname(
"machdep.cpu.brand_string", NULL, &lenCPU, NULL, 0);
459 pCPU = (
char * )malloc(lenCPU);
462 sysctlbyname(
"machdep.cpu.brand_string", pCPU, &lenCPU, NULL, 0);
465 processor = QString(pCPU);
471 QFile cpuinfo(
"/proc/cpuinfo");
472 if ( cpuinfo.exists() ) {
473 cpuinfo.open(QFile::ReadOnly);
474 QTextStream stream(&cpuinfo);
475 QStringList splitted = stream.readAll().split(
"\n",QString::SkipEmptyParts);
477 int position = splitted.indexOf ( QRegExp(
"^model name.*") );
478 if ( position != -1 ){
479 QString cpuModel = splitted[position].section(
':', -1).simplified();
480 processor = cpuModel;
485 QString cpuHash = QCryptographicHash::hash ( decodeString(processor,utf8Encoded) , QCryptographicHash::Sha1 ).toHex();
494 QSettings registryProduct(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", QSettings::NativeFormat);
495 QString productId = registryProduct.value(
"ProductId",
"Unknown" ).toString();
497 QString productId =
"-";
500 QString productHash = QCryptographicHash::hash ( decodeString(productId,utf8Encoded) , QCryptographicHash::Sha1 ).toHex();
506 if (!elements.empty())
510 QDate currentDate = QDate::currentDate();
511 QDate expiryDate = QDate::fromString(elements[1],Qt::ISODate);
512 bool expired = (currentDate > expiryDate);
514 QStringList licensedMacs;
515 for (
int i = 7 ; i < elements.size(); ++i ) {
516 licensedMacs.push_back(elements[i]);
519 bool macFound =
false;
520 for (
int i = 0; i < macHashes.size(); ++i ) {
521 if ( licensedMacs.contains(macHashes[i]) )
525 if ( !signatureOk ) {
526 authstring_ += tr(
"License Error: The license file signature for Plugin \"") +
name() + tr(
"\" is invalid!\n\n");
527 }
else if ( expired ) {
528 authstring_ += tr(
"License Error: The license for plugin \"") +
name() + tr(
"\" has expired on ") + elements[1] +
"!\n\n";
529 }
else if ( !timestampOk() ) {
530 authstring_ += tr(
"License Error: System time has been reset. The license for plugin \"") +
name() + tr(
"\" has been expired!\n\n");
532 authstring_ += tr(
"License Error: The license file contains plugin name\"") + elements[2] + tr(
"\" but this is plugin \"") +
name() +
"\"!\n\n";
533 }
else if ( elements[3] != coreHash ) {
534 authstring_ += tr(
"License Error: The license file for plugin \"") +
name() + tr(
"\" is invalid for the currently running OpenFlipper Core!\n\n");
535 }
else if ( elements[4] != pluginHash ) {
536 authstring_ += tr(
"License Error: The plugin \"") +
name() + tr(
"\" is a different version than specified in license file!\n\n");
537 }
else if ( elements[5] != cpuHash ) {
538 authstring_ +=
"License Error: The plugin \"" +
name() +
"\" is not allowed to run on the current system (Changed CPU?)!\n\n";
539 }
else if ( elements[6] != productHash ) {
540 authstring_ +=
"License Error: The plugin \"" +
name() +
"\" is not allowed to run on the current system (Changed OS?)!\n\n";
541 }
else if ( !macFound ) {
542 authstring_ +=
"License Error: The plugin \"" +
name() +
"\" is not allowed to run on the current system (Changed Network?)!\n\n";
556 authstring_ += tr(
"Message: License check for plugin failed.\n");
557 authstring_ += tr(
"Message: Please get a valid License!\n");
558 authstring_ += tr(
"Message: Send the following Information to \n");
559 authstring_ += tr(
"Contact mail: ") + CONTACTMAIL +
"\n\n";
566 for (
int i = 0 ; i < macHashes.size(); ++i )
569 QString keyRequest = saltPre +
pluginFileName() + coreHash + pluginHash + cpuHash + productHash + macHashes.join(
"") + saltPost;
570 QString requestSig = QCryptographicHash::hash ( keyRequest.toUtf8() , QCryptographicHash::Sha1 ).toHex();
602 ADD_PLUGIN_FILENAME(pluginFileName);
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
virtual QString pluginFileName()
bool authenticated_
This flag is true if authentication was successful.
#define TOSTRING(x)
QSettings object containing all program settings of OpenFlipper.
QString authstring_
License information string.
void connectNotify(const char *signal)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
void blockSignals(bool _state)