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> 89 QByteArray decodeString(
const QString& _string ,
bool _utf8){
92 return _string.toUtf8();
94 return _string.toLatin1();
98 LicenseManager::~LicenseManager()
103 LicenseManager::LicenseManager()
109 QObject::blockSignals(
true );
117 QObject::blockSignals(
true );
119 QObject::blockSignals(_state);
125 bool LicenseManager::timestampOk() {
127 bool notExpired =
false;
128 bool gotTimestampEntry =
false;
130 quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
131 quint64 lastTimestamp = timestamp;
132 quint64 timestampEntry = 0;
133 quint64 lastTimestampEntryNum = 0;
144 if( lastTimestampEntry==QString(
"empty") ){
147 lastTimestampEntryNum = lastTimestampEntry.toULongLong(&gotTimestampEntry,16);
154 const unsigned int factor = 30000;
156 const unsigned int moduloFactor = 72;
158 const int nameEncr = ( name[0] ) + ( name[nameSize-1] ) + (name[(nameSize-1) / 2] );
160 bool moduloOK = (lastTimestampEntryNum -( 100 * (lastTimestampEntryNum / 100) ) == (lastTimestampEntryNum/100) % moduloFactor );
162 lastTimestampEntryNum = lastTimestampEntryNum / 100;
163 lastTimestampEntryNum = lastTimestampEntryNum - nameEncr;
164 lastTimestampEntryNum = lastTimestampEntryNum * factor;
166 lastTimestamp = lastTimestampEntryNum;
172 if (notExpired||(timestamp>(lastTimestamp-360000) && moduloOK)) {
175 timestamp = std::numeric_limits<quint64>::max();
183 timestampEntry = timestamp;
185 timestampEntry = timestampEntry / factor;
186 timestampEntry = timestampEntry + nameEncr;
187 timestampEntry = (timestampEntry * 100) + (timestampEntry % moduloFactor);
212 ADD_SALT_PRE(saltPre);
215 ADD_SALT_POST(saltPost);
217 QString licenseFileName = OpenFlipper::Options::licenseDirStr() + QDir::separator() +
pluginFileName() +
".lic";
218 QFile file( licenseFileName );
219 QStringList elements;
220 bool signatureOk =
false;
222 bool utf8Encoded =
true;
224 if (file.open(QIODevice::ReadOnly|QIODevice::Text))
226 QString licenseContents = file.readAll();
227 elements = licenseContents.split(
'\n',QString::SkipEmptyParts);
228 bool fileOk = !elements.empty() && elements[0] !=
"ERROR";
233 for (
int i = 0 ; i < elements.size(); ++i )
234 elements[i] = elements[i].simplified();
237 QString license = saltPre;
238 for (
int i = 1 ; i < elements.size(); ++i )
239 license += elements[i];
241 QString licenseHash = QCryptographicHash::hash ( license.toUtf8() , QCryptographicHash::Sha1 ).toHex();
242 signatureOk = licenseHash == elements[0];
248 licenseHash = QCryptographicHash::hash ( license.toLatin1() , QCryptographicHash::Sha1 ).toHex();
249 signatureOk = licenseHash == elements[0];
256 elements = QStringList();
264 QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() +
"OpenFlipper.exe");
265 #elif defined ARCH_DARWIN 266 QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() +
".." +
267 QDir::separator() +
"MacOS"+
268 QDir::separator() +
"OpenFlipper");
270 QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() +
"bin" + QDir::separator() +
TOSTRING(PRODUCT_STRING));
273 if ( ! coreApp.exists() ) {
274 std::cerr <<
"Error finding core application for security check! : " << coreApp.fileName().toStdString() << std::endl;
278 coreApp.open(QIODevice::ReadOnly);
279 QCryptographicHash sha1sumCore( QCryptographicHash::Sha1 );
280 sha1sumCore.addData(coreApp.readAll() );
283 QString coreHash = QString(sha1sumCore.result().toHex());
291 QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() +
pluginFileName() +
".dll");
292 #elif defined ARCH_DARWIN 293 QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() +
"lib" +
pluginFileName() +
".so");
295 QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() +
"lib" +
pluginFileName() +
".so");
298 if ( ! pluginFile.exists() ) {
299 std::cerr <<
"Error finding plugin file for security check!" << std::endl;
300 std::cerr <<
"Path: " << pluginFile.fileName().toStdString() << std::endl;
304 pluginFile.open(QIODevice::ReadOnly);
305 QCryptographicHash sha1sumPlugin( QCryptographicHash::Sha1 );
306 sha1sumPlugin.addData(pluginFile.readAll());
309 QString pluginHash = QString(sha1sumPlugin.result().toHex());
315 QStringList macHashes;
319 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) 320 #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) 323 PIP_ADAPTER_ADDRESSES pAddresses = NULL;
329 outBufLen =
sizeof (IP_ADAPTER_ADDRESSES);
330 pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
333 ULONG family = AF_UNSPEC;
336 ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
340 if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) {
342 pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
346 if (pAddresses != NULL) {
349 DWORD dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
351 if (dwRetVal == NO_ERROR) {
354 PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses;
356 while (pCurrAddresses) {
359 if (pCurrAddresses->PhysicalAddressLength != 0) {
360 QString currentMac =
"";
362 for (uint i = 0; i < pCurrAddresses->PhysicalAddressLength; i++) {
364 currentMac += QString(
"%1").arg( (
int) pCurrAddresses->PhysicalAddress[i] , 2 ,16,QChar(
'0'));
366 if (i != (pCurrAddresses->PhysicalAddressLength - 1))
372 if ( (currentMac.count(
":") == 5) &&
373 ( pCurrAddresses->IfType == IF_TYPE_IEEE80211 || pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD ) ) {
376 currentMac = (decodeString(currentMac,utf8Encoded)).toUpper();
377 currentMac = currentMac.remove(
":");
378 macHashes.push_back(currentMac);
384 pCurrAddresses = pCurrAddresses->Next;
396 QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
397 foreach ( QNetworkInterface netInterface, interfaces ) {
400 if ( ( netInterface.flags() & QNetworkInterface::IsLoopBack ) ) {
405 if ( netInterface.hardwareAddress().count(
":") != 5 ) {
410 QString currentMac = (decodeString(netInterface.hardwareAddress(),utf8Encoded)).toUpper();
411 currentMac = currentMac.remove(
":");
413 macHashes.push_back(currentMac);
420 macHashes.removeDuplicates();
423 for (
int i = 0 ; i < macHashes.size(); ++i )
425 macHashes[i] = QCryptographicHash::hash ( decodeString(macHashes[i],utf8Encoded) , QCryptographicHash::Sha1 ).toHex();
431 QString processor(
"Unknown");
434 QSettings registryCPU(
"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor", QSettings::NativeFormat);
436 QStringList cpus = registryCPU.childGroups();
437 if ( cpus.size() != 0 ) {
438 processor = registryCPU.value( cpus[0]+
"/ProcessorNameString",
"Unknown" ).toString();
441 #elif defined ARCH_DARWIN 447 sysctlbyname(
"machdep.cpu.brand_string", NULL, &lenCPU, NULL, 0);
450 pCPU = (
char * )malloc(lenCPU);
453 sysctlbyname(
"machdep.cpu.brand_string", pCPU, &lenCPU, NULL, 0);
456 processor = QString(pCPU);
462 QFile cpuinfo(
"/proc/cpuinfo");
463 if ( cpuinfo.exists() ) {
464 cpuinfo.open(QFile::ReadOnly);
465 QTextStream stream(&cpuinfo);
466 QStringList splitted = stream.readAll().split(
"\n",QString::SkipEmptyParts);
468 int position = splitted.indexOf ( QRegExp(
"^model name.*") );
469 if ( position != -1 ){
470 QString cpuModel = splitted[position].section(
':', -1).simplified();
471 processor = cpuModel;
476 QString cpuHash = QCryptographicHash::hash ( decodeString(processor,utf8Encoded) , QCryptographicHash::Sha1 ).toHex();
485 QSettings registryProduct(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", QSettings::NativeFormat);
486 QString productId = registryProduct.value(
"ProductId",
"Unknown" ).toString();
488 QString productId =
"-";
491 QString productHash = QCryptographicHash::hash ( decodeString(productId,utf8Encoded) , QCryptographicHash::Sha1 ).toHex();
497 if (!elements.empty())
501 QDate currentDate = QDate::currentDate();
502 QDate expiryDate = QDate::fromString(elements[1],Qt::ISODate);
503 bool expired = (currentDate > expiryDate);
505 QStringList licensedMacs;
506 for (
int i = 7 ; i < elements.size(); ++i ) {
507 licensedMacs.push_back(elements[i]);
510 bool macFound =
false;
511 for (
int i = 0; i < macHashes.size(); ++i ) {
512 if ( licensedMacs.contains(macHashes[i]) )
516 if ( !signatureOk ) {
517 authstring_ += tr(
"License Error: The license file signature for Plugin \"") +
name() + tr(
"\" is invalid!\n\n");
518 }
else if ( expired ) {
519 authstring_ += tr(
"License Error: The license for plugin \"") +
name() + tr(
"\" has expired on ") + elements[1] +
"!\n\n";
520 }
else if ( !timestampOk() ) {
521 authstring_ += tr(
"License Error: System time has been reset. The license for plugin \"") +
name() + tr(
"\" has been expired!\n\n");
523 authstring_ += tr(
"License Error: The license file contains plugin name\"") + elements[2] + tr(
"\" but this is plugin \"") +
name() +
"\"!\n\n";
524 }
else if ( elements[3] != coreHash ) {
525 authstring_ += tr(
"License Error: The license file for plugin \"") +
name() + tr(
"\" is invalid for the currently running OpenFlipper Core!\n\n");
526 }
else if ( elements[4] != pluginHash ) {
527 authstring_ += tr(
"License Error: The plugin \"") +
name() + tr(
"\" is a different version than specified in license file!\n\n");
528 }
else if ( elements[5] != cpuHash ) {
529 authstring_ +=
"License Error: The plugin \"" +
name() +
"\" is not allowed to run on the current system (Changed CPU?)!\n\n";
530 }
else if ( elements[6] != productHash ) {
531 authstring_ +=
"License Error: The plugin \"" +
name() +
"\" is not allowed to run on the current system (Changed OS?)!\n\n";
532 }
else if ( !macFound ) {
533 authstring_ +=
"License Error: The plugin \"" +
name() +
"\" is not allowed to run on the current system (Changed Network?)!\n\n";
547 authstring_ += tr(
"Message: License check for plugin failed.\n");
548 authstring_ += tr(
"Message: Please get a valid License!\n");
549 authstring_ += tr(
"Message: Send the following Information to \n");
550 authstring_ += tr(
"Contact mail: ") + CONTACTMAIL +
"\n\n";
557 for (
int i = 0 ; i < macHashes.size(); ++i )
560 QString keyRequest = saltPre +
pluginFileName() + coreHash + pluginHash + cpuHash + productHash + macHashes.join(
"") + saltPost;
561 QString requestSig = QCryptographicHash::hash ( keyRequest.toUtf8() , QCryptographicHash::Sha1 ).toHex();
593 ADD_PLUGIN_FILENAME(pluginFileName);
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void connectNotify(const char *signal)
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
virtual QString pluginFileName()
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
#define TOSTRING(x)
QSettings object containing all program settings of OpenFlipper.
bool authenticated_
This flag is true if authentication was successful.
void blockSignals(bool _state)
QString authstring_
License information string.