LicenseManager.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 83 $                                                         *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-02-27 17:31:45 +0100 (Fr, 27. Feb 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 #include <OpenFlipper/LicenseManager/LicenseManager.hh>
00044 #include <OpenFlipper/common/GlobalOptions.hh>
00045 #include <QFile>
00046 #include <QCryptographicHash>
00047 #include <QNetworkInterface>
00048 
00049 /*
00050 //
00051 // CpuIDSupported will return 0 if CPUID instruction is unavailable. Otherwise, it will return 
00052 // the maximum supported standard function.
00053 //
00054 
00055 unsigned int CpuIDSupported(void)
00056 {
00057   unsigned int MaxInputValue;
00058   // If CPUID instruction is supported
00059   #ifndef WIN32
00060       try
00061       {
00062           MaxInputValue = 0;
00063           // call cpuid with eax = 0
00064           asm
00065           (
00066               "xorl %%eax,%%eax\n\t"
00067               "cpuid\n\t"
00068                       : "=a" (MaxInputValue)
00069                       :
00070                       : "%ebx", "%ecx", "%edx"
00071                   );
00072       }
00073       catch (...)
00074       {
00075           return(0);                   // cpuid instruction is unavailable
00076       }
00077   #else //Win32
00078       try
00079       {
00080           MaxInputValue = 0;
00081           // call cpuid with eax = 0
00082           __asm
00083           {
00084               xor eax, eax
00085               cpuid
00086               mov MaxInputValue, eax
00087           }
00088       }
00089       catch (...)
00090       {
00091           return(0);                   // cpuid instruction is unavailable
00092       }
00093   #endif
00094   return MaxInputValue;
00095 }
00096 
00097 //
00098 // GenuineIntel will return 0 if the processor is not a Genuine Intel Processor
00099 //
00100 unsigned int GenuineIntel(void)
00101 {
00102   #ifndef WIN32
00103     unsigned int VendorIDb = 0,VendorIDd = 0, VendorIDc = 0;
00104     try
00105     // If CPUID instruction is supported
00106     {
00107       // Get vendor id string
00108       asm
00109       (
00110         //get the vendor string
00111         // call cpuid with eax = 0
00112               "xorl %%eax, %%eax\n\t"
00113               "cpuid\n\t"
00114           :   "=b" (VendorIDb),
00115               "=d" (VendorIDd),
00116               "=c" (VendorIDc)
00117           :
00118           : "%eax"
00119       );
00120     }
00121     catch (...)
00122     {
00123       return(0);                   // cpuid instruction is unavailable
00124     }
00125     return (
00126                 (VendorIDb  == 'uneG') &&
00127                 (VendorIDd  == 'Ieni') &&
00128                 (VendorIDc  == 'letn')
00129             );
00130   #else
00131     unsigned int VendorID[3] = {0, 0, 0};
00132     try    // If CPUID instruction is supported
00133     {
00134       __asm
00135       {
00136           xor eax, eax            // call cpuid with eax = 0
00137           cpuid                    // Get vendor id string
00138           mov VendorID, ebx
00139           mov VendorID + 4, edx
00140           mov VendorID + 8, ecx
00141       }
00142     }
00143     catch (...)
00144     {
00145       return(0);
00146       unsigned int MaxInputValue =0;
00147       // cpuid instruction is unavailable
00148     }
00149     return (
00150                (VendorID[0] == 'uneG') &&
00151                (VendorID[1] == 'Ieni') &&
00152                (VendorID[2] == 'letn')
00153            );
00154   #endif
00155 }
00156 */
00157 
00158 
00159 LicenseManager::~LicenseManager() 
00160 { 
00161   exit(0); 
00162 }
00163 
00164 LicenseManager::LicenseManager()
00165 {
00166   authenticated_ = false;
00167   std::cerr << "Constructor Security Interface" << std::endl;
00168   QObject::blockSignals( true );
00169 }
00170 
00171 void LicenseManager::blockSignals( bool _state) {
00172   std::cerr << "Block Signals called" << std::endl;
00173   if ( !authenticated() ) {
00174     QObject::blockSignals( true );
00175     std::cerr << "Request to unblock plugin denied" << std::endl;
00176   } else {
00177     QObject::blockSignals(_state);
00178     std::cerr << "Unblocked Signal" << std::endl;
00179   }
00180 
00181 }
00182 
00183 bool LicenseManager::authenticate() {
00184   std::cerr << "Auth slot" << std::endl;
00185 
00186   std::cerr << "Application Directory: " << OpenFlipper::Options::applicationDirStr().toStdString() << std::endl;
00187   std::cerr << "Plugin Directory: " << OpenFlipper::Options::pluginDirStr().toStdString() << std::endl;
00188   
00189 
00190   std::cerr << "Name: " << name().toStdString() << std::endl;
00191 
00192   // ===============================================================================================
00193   // Compute hash of Core application
00194   // ===============================================================================================
00195 
00196   #ifdef WIN32
00197     QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() + "bin" + QDir::separator() + "OpenFlipper.exe");
00198   #else
00199     QFile coreApp(OpenFlipper::Options::applicationDirStr() + QDir::separator() + "bin" + QDir::separator() + "OpenFlipper");
00200   #endif
00201 
00202   if ( ! coreApp.exists() ) {
00203     std::cerr << "Error finding core application for security check! : " << coreApp.fileName().toStdString() << std::endl;
00204     return false;
00205   }
00206 
00207   coreApp.open(QIODevice::ReadOnly);
00208   QCryptographicHash sha1sumCore( QCryptographicHash::Sha1 );
00209   sha1sumCore.addData(coreApp.readAll() );
00210   coreApp.close();
00211 
00212   QString coreHash = QString(sha1sumCore.result().toHex());
00213   
00214 
00215   // ===============================================================================================
00216   // Compute hash of Plugin application
00217   // ===============================================================================================
00218 
00219   #ifdef WIN32
00220     QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() + pluginFileName() + ".dll");
00221   #else
00222     QFile pluginFile(OpenFlipper::Options::pluginDirStr() + QDir::separator() + pluginFileName() + ".so");
00223   #endif
00224 
00225   if ( ! pluginFile.exists() ) {
00226     std::cerr << "Error finding plugin file for security check!" << std::endl;
00227     return false;
00228   }
00229 
00230   pluginFile.open(QIODevice::ReadOnly);
00231   QCryptographicHash sha1sumPlugin( QCryptographicHash::Sha1 );
00232   sha1sumPlugin.addData(pluginFile.readAll());
00233   pluginFile.close();
00234 
00235   QString pluginHash = QString(sha1sumPlugin.result().toHex());
00236 
00237 
00238   QString mac;
00239 
00240   // Get all Network Interfaces
00241   QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
00242   foreach ( QNetworkInterface interface, interfaces ) {
00243     mac = mac + interface.hardwareAddress().remove(":");
00244   }
00245 
00246   QString macHash = QCryptographicHash::hash ( mac.toAscii()  , QCryptographicHash::Sha1 ).toHex();
00247 
00248 //   std::cerr << "CPUID Supported : " << CpuIDSupported() << std::endl;
00249 //   std::cerr << "GenuineIntel    : " << GenuineIntel() << std::endl;
00250 
00251   QString saltPre;
00252   ADD_SALT_PRE(saltPre);
00253 
00254   QString saltPost;
00255   ADD_SALT_POST(saltPost);
00256 
00257     QString licenseFileName = OpenFlipper::Options::licenseDirStr() + QDir::separator() + pluginFileName() + ".lic";
00258   QFile file( licenseFileName );
00259 
00260   if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
00261     std::cerr << "Unable to find license File " <<  licenseFileName.toStdString() << std::endl;
00262   } else {
00263     QString licenseContents = file.readAll();
00264     QStringList elements = licenseContents.split('\n');
00265 
00266     for ( int i = 0 ; i < elements.size(); ++i )
00267       elements[i] = elements[i].simplified();
00268 
00269     if ( elements.size() != 6 ) {
00270       QString sizeMismatchMessage = "The license file for plugin \"" + name() + "\" is invalid!";
00271       QMessageBox::critical(0,tr("License file size invalid"),sizeMismatchMessage );
00272     } else {
00273 
00274       // Check signature of license file
00275       QString license = saltPre + elements[0] + elements[1] + elements[2] + elements[3] + elements[4] + saltPost;
00276       QString licenseHash = QCryptographicHash::hash ( license.toAscii()  , QCryptographicHash::Sha1 ).toHex();
00277       
00278       QDate currentDate = QDate::currentDate();
00279       QDate expiryDate  = QDate::fromString(elements[4],Qt::ISODate);
00280 
00281       if ( licenseHash !=  elements[5] ) {
00282         QString signatureMismatchMessage = tr("The license file signature for plugin \"") + name() + tr("\" is invalid!");
00283         QMessageBox::critical(0,tr("License file signature invalid"),signatureMismatchMessage );   
00284       } else  if ( elements[0] != pluginFileName() ) {
00285         QString nameMismatchMessage = tr("The license file contains plugin name\"") + elements[0] + tr("\" but this is plugin \"") + name() + "\"!";
00286         QMessageBox::critical(0,tr("License invalid for this plugin"),nameMismatchMessage );
00287       } else if ( elements[1] != coreHash ) {
00288         QString coreMismatchMessage = tr("The license file for plugin \"") + name() + tr("\" is invalid for the currently running OpenFlipper Core!");
00289         QMessageBox::critical(0,tr("License invalid for current core"),coreMismatchMessage );
00290       } else if ( elements[2] != pluginHash ) {
00291         QString pluginMismatchMessage = tr("The plugin \"") + name() + tr("\" is a different version than specified in license file!");
00292         QMessageBox::critical(0,tr("License invalid for this plugin"),pluginMismatchMessage );
00293       } else if ( elements[3] != macHash ) {
00294         QString hardwareMismatchMessage = "The plugin \"" + name() + "\" is not allowed to run on the current system (Changed Hardware?)!";
00295         QMessageBox::critical(0,tr("License invalid for current System"),hardwareMismatchMessage );    
00296       } else if ( currentDate > expiryDate ) {
00297         QString expiredMessage = tr("The license for plugin \"") + name() + tr("\" has expired on ") + elements[1] + "!";
00298         QMessageBox::critical(0,tr("License expired"),expiredMessage );
00299       } else {
00300         authenticated_ = true;
00301       }
00302     }
00303   }
00304 
00305   if ( authenticated_ ) 
00306     std::cerr << "Authentication succcessfull for Plugin " << name().toStdString() << std::endl;
00307   else {
00308     QString text = tr("License check for plugin has failed.\n");
00309     text += tr("Please get a valid License!\n");
00310     text += tr("Send the following Information to ") + CONTACTMAIL + "\n\n";
00311     text += pluginFileName() +"\n";
00312     text += coreHash +"\n";
00313     text += pluginHash +"\n";
00314     text += macHash +"\n";
00315 
00316     QString keyRequest = saltPre + pluginFileName() + coreHash+pluginHash+macHash +saltPost;
00317     QString requestSig = QCryptographicHash::hash ( keyRequest.toAscii()  , QCryptographicHash::Sha1 ).toHex();
00318     text += requestSig + "\n";
00319 
00320     QMessageBox::warning ( 0, tr("Plugin License check failed"),  text );
00321     std::cerr << "Authentication failed" << std::endl;
00322     authenticated_ = false;
00323   }
00324 
00325 //   authenticated_ = true;
00326   return authenticated_;
00327 }
00328 
00329 bool LicenseManager::authenticated() {
00330   return authenticated_;
00331 }
00332 
00333 void LicenseManager::connectNotify ( const char * /*signal*/ ) {
00334   std::cerr << "connectNotify Security Interface" << std::endl;
00335   if ( !authenticated() ) {
00336     blockSignals(true);
00337     std::cerr << "Connects failed due to blocked Plugin" << std::endl;
00338   }
00339 
00340   disconnect();
00341 }
00342 
00343 QString LicenseManager::pluginFileName() {
00344   return QString("unset");
00345 }
00346 

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .