LicenseManager.cc 11.1 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//=============================================================================
//
//                               OpenFlipper
//        Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
//                           www.openflipper.org
//
//-----------------------------------------------------------------------------
//
//                                License
//
//  OpenFlipper is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  OpenFlipper is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with OpenFlipper.  If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
//
//   $Revision: 6574 $
//   $Author: moebius $
//   $Date: 2009-07-08 14:06:06 +0200 (Mi, 08. Jul 2009) $
//
//=============================================================================
31
32
33
34
35
36
37

#include <OpenFlipper/LicenseManager/LicenseManager.hh>
#include <OpenFlipper/common/GlobalOptions.hh>
#include <QFile>
#include <QCryptographicHash>
#include <QNetworkInterface>

Jan Möbius's avatar
Jan Möbius committed
38
/*
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// CpuIDSupported will return 0 if CPUID instruction is unavailable. Otherwise, it will return 
// the maximum supported standard function.
//

unsigned int CpuIDSupported(void)
{
  unsigned int MaxInputValue;
  // If CPUID instruction is supported
  #ifndef WIN32
      try
      {
          MaxInputValue = 0;
	  // call cpuid with eax = 0
	  asm
	  (
	      "xorl %%eax,%%eax\n\t"
	      "cpuid\n\t"
		      : "=a" (MaxInputValue)
		      :
		      : "%ebx", "%ecx", "%edx"
		  );
      }
      catch (...)
      {
	  return(0);                   // cpuid instruction is unavailable
      }
  #else //Win32
      try
      {
	  MaxInputValue = 0;
	  // call cpuid with eax = 0
	  __asm
	  {
	      xor eax, eax
	      cpuid
	      mov MaxInputValue, eax
	  }
      }
      catch (...)
      {
	  return(0);                   // cpuid instruction is unavailable
      }
  #endif
  return MaxInputValue;
}

//
// GenuineIntel will return 0 if the processor is not a Genuine Intel Processor
//
unsigned int GenuineIntel(void)
{
  #ifndef WIN32
    unsigned int VendorIDb = 0,VendorIDd = 0, VendorIDc = 0;
    try
    // If CPUID instruction is supported
    {
      // Get vendor id string
      asm
      (
        //get the vendor string
        // call cpuid with eax = 0
              "xorl %%eax, %%eax\n\t"
              "cpuid\n\t"
          :   "=b" (VendorIDb),
              "=d" (VendorIDd),
              "=c" (VendorIDc)
          :
          : "%eax"
      );
    }
    catch (...)
    {
      return(0);                   // cpuid instruction is unavailable
    }
    return (
                (VendorIDb  == 'uneG') &&
                (VendorIDd  == 'Ieni') &&
                (VendorIDc  == 'letn')
            );
  #else
    unsigned int VendorID[3] = {0, 0, 0};
    try    // If CPUID instruction is supported
    {
      __asm
      {
          xor eax, eax            // call cpuid with eax = 0
          cpuid                    // Get vendor id string
          mov VendorID, ebx
          mov VendorID + 4, edx
          mov VendorID + 8, ecx
      }
    }
    catch (...)
    {
      return(0);
      unsigned int MaxInputValue =0;
      // cpuid instruction is unavailable
    }
    return (
               (VendorID[0] == 'uneG') &&
               (VendorID[1] == 'Ieni') &&
               (VendorID[2] == 'letn')
           );
  #endif
}
Jan Möbius's avatar
Jan Möbius committed
145
*/
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226


LicenseManager::~LicenseManager() 
{ 
  exit(0); 
}

LicenseManager::LicenseManager()
{
  authenticated_ = false;
  std::cerr << "Constructor Security Interface" << std::endl;
  QObject::blockSignals( true );
}

void LicenseManager::blockSignals( bool _state) {
  std::cerr << "Block Signals called" << std::endl;
  if ( !authenticated() ) {
    QObject::blockSignals( true );
    std::cerr << "Request to unblock plugin denied" << std::endl;
  } else {
    QObject::blockSignals(_state);
    std::cerr << "Unblocked Signal" << std::endl;
  }

}

bool LicenseManager::authenticate() {
  std::cerr << "Auth slot" << std::endl;

  std::cerr << "Application Directory: " << OpenFlipper::Options::applicationDirStr().toStdString() << std::endl;
  std::cerr << "Plugin Directory: " << OpenFlipper::Options::pluginDirStr().toStdString() << std::endl;
  

  std::cerr << "Name: " << name().toStdString() << std::endl;

  // ===============================================================================================
  // Compute hash of Core application
  // ===============================================================================================

  #ifdef WIN32
    QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() + "bin" + QDir::separator() + "OpenFlipper.exe");
  #else
    QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() + "bin" + QDir::separator() + "OpenFlipper");
  #endif

  if ( ! coreApp.exists() ) {
    std::cerr << "Error finding core application for security check! : " << coreApp.fileName().toStdString() << std::endl;
    return false;
  }

  coreApp.open(QIODevice::ReadOnly);
  QCryptographicHash sha1sumCore( QCryptographicHash::Sha1 );
  sha1sumCore.addData(coreApp.readAll() );
  coreApp.close();

  QString coreHash = QString(sha1sumCore.result().toHex());
  

  // ===============================================================================================
  // Compute hash of Plugin application
  // ===============================================================================================

  #ifdef WIN32
    QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() + pluginFileName() + ".dll");
  #else
    QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() + pluginFileName() + ".so");
  #endif

  if ( ! pluginFile.exists() ) {
    std::cerr << "Error finding plugin file for security check!" << std::endl;
    return false;
  }

  pluginFile.open(QIODevice::ReadOnly);
  QCryptographicHash sha1sumPlugin( QCryptographicHash::Sha1 );
  sha1sumPlugin.addData(pluginFile.readAll());
  pluginFile.close();

  QString pluginHash = QString(sha1sumPlugin.result().toHex());


Jan Möbius's avatar
Jan Möbius committed
227
  QString mac;
228
229
230
231

  // Get all Network Interfaces
  QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
  foreach ( QNetworkInterface interface, interfaces ) {
Jan Möbius's avatar
Jan Möbius committed
232
    mac = mac + interface.hardwareAddress().remove(":");
233
234
  }

Jan Möbius's avatar
Jan Möbius committed
235
  QString macHash = QCryptographicHash::hash ( mac.toAscii()  , QCryptographicHash::Sha1 ).toHex();
236

Jan Möbius's avatar
Jan Möbius committed
237
238
//   std::cerr << "CPUID Supported : " << CpuIDSupported() << std::endl;
//   std::cerr << "GenuineIntel    : " << GenuineIntel() << std::endl;
239

Jan Möbius's avatar
Jan Möbius committed
240
241
242
243
244
245
  QString saltPre;
  ADD_SALT_PRE(saltPre);

  QString saltPost;
  ADD_SALT_POST(saltPost);

Jan Möbius's avatar
Jan Möbius committed
246
    QString licenseFileName = OpenFlipper::Options::licenseDirStr() + QDir::separator() + pluginFileName() + ".lic";
Jan Möbius's avatar
Jan Möbius committed
247
248
249
250
251
252
  QFile file( licenseFileName );

  if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
    std::cerr << "Unable to find license File " <<  licenseFileName.toStdString() << std::endl;
  } else {
    QString licenseContents = file.readAll();
Jan Möbius's avatar
Jan Möbius committed
253
254
    QStringList elements = licenseContents.split('\n');

Jan Möbius's avatar
Jan Möbius committed
255
256
257
    for ( int i = 0 ; i < elements.size(); ++i )
      elements[i] = elements[i].simplified();

Jan Möbius's avatar
Jan Möbius committed
258
259
260
    if ( elements.size() != 6 ) {
      QString sizeMismatchMessage = "The license file for plugin \"" + name() + "\" is invalid!";
      QMessageBox::critical(0,"License file size invalid",sizeMismatchMessage );
Jan Möbius's avatar
Jan Möbius committed
261
262
    } else {

Jan Möbius's avatar
Jan Möbius committed
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
      // Check signature of license file
      QString license = saltPre + elements[0] + elements[1] + elements[2] + elements[3] + elements[4] + saltPost;
      license = saltPre + license + saltPost;
      QString licenseHash = QCryptographicHash::hash ( license.toAscii()  , QCryptographicHash::Sha1 ).toHex();
      
      QDate currentDate = QDate::currentDate();
      QDate expiryDate  = QDate::fromString(elements[4],Qt::ISODate);

      if ( licenseHash !=  elements[5] ) {
        QString signatureMismatchMessage = "The license file signature for plugin \"" + name() + "\" is invalid!";
        QMessageBox::critical(0,"License file signature invalid",signatureMismatchMessage );   
      } else  if ( elements[0] != pluginFileName() ) {
        QString nameMismatchMessage = "The license file contains plugin name\"" + elements[0] + "\" but this is plugin \"" + name() + "\"!";
        QMessageBox::critical(0,"License invalid for this plugin",nameMismatchMessage );
      } else if ( elements[1] != coreHash ) {
        QString coreMismatchMessage = "The license file for plugin \"" + name() + "\" is invalid for the currently running OpenFlipper Core!";
        QMessageBox::critical(0,"License invalid for current core",coreMismatchMessage );
      } else if ( elements[2] != pluginHash ) {
        QString pluginMismatchMessage = "The plugin \"" + name() + "\" is a different version than specified in license file!";
        QMessageBox::critical(0,"License invalid for this plugin",pluginMismatchMessage );
      } else if ( elements[3] != macHash ) {
        QString hardwareMismatchMessage = "The plugin \"" + name() + "\" is not allowed to run on the current system (Changed Hardware?)!";
        QMessageBox::critical(0,"License invalid for current System",hardwareMismatchMessage );    
      } else if ( currentDate > expiryDate ) {
        QString expiredMessage = "The license for plugin \"" + name() + "\" has expired on " + elements[1] + "!";
        QMessageBox::critical(0,"License expired",expiredMessage );
Jan Möbius's avatar
Jan Möbius committed
289
      } else {
Jan Möbius's avatar
Jan Möbius committed
290
        authenticated_ = true;
Jan Möbius's avatar
Jan Möbius committed
291
292
293
294
      }
    }
  }

295
  if ( authenticated_ ) 
Jan Möbius's avatar
Jan Möbius committed
296
    std::cerr << "Authentication succcessfull for Plugin " << name().toStdString() << std::endl;
297
  else {
Jan Möbius's avatar
Jan Möbius committed
298
299
    QString text = "License check for plugin has failed.\n";
    text += "Please get a valid License!\n";
Jan Möbius's avatar
Jan Möbius committed
300
    text += "Send the following Information to " + CONTACTMAIL + "\n\n";
Jan Möbius's avatar
Jan Möbius committed
301
302
303
304
    text += pluginFileName() +"\n";
    text += coreHash +"\n";
    text += pluginHash +"\n";
    text += macHash +"\n";
Jan Möbius's avatar
Jan Möbius committed
305
306
307
308
309

    QString keyRequest = saltPre + pluginFileName() + coreHash+pluginHash+macHash +saltPost;
    QString requestSig = QCryptographicHash::hash ( keyRequest.toAscii()  , QCryptographicHash::Sha1 ).toHex();
    text += requestSig + "\n";

Jan Möbius's avatar
Jan Möbius committed
310
    QMessageBox::warning ( 0, "Plugin License check failed",  text );
311
    std::cerr << "Authentication failed" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
312
    authenticated_ = false;
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  }

//   authenticated_ = true;
  return authenticated_;
}

bool LicenseManager::authenticated() {
  return authenticated_;
}

void LicenseManager::connectNotify ( const char * /*signal*/ ) {
  std::cerr << "connectNotify Security Interface" << std::endl;
  if ( !authenticated() ) {
    blockSignals(true);
    std::cerr << "Connects failed due to blocked Plugin" << std::endl;
  }

  disconnect();
}

QString LicenseManager::pluginFileName() {
  return QString("unset");
}