Commit f05f04ea authored by Hans-Christian Ebke's avatar Hans-Christian Ebke
Browse files

License manager now parses any number of license requests out of garbled junk.

Patch by Hannes Hergeth with some modifications by me.


git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@17344 383ad7c9-94d9-4d36-a494-682f7c89f535
parent a2bb1908
...@@ -2,14 +2,6 @@ ...@@ -2,14 +2,6 @@
<ui version="4.0"> <ui version="4.0">
<class>keyWindow</class> <class>keyWindow</class>
<widget class="QMainWindow" name="keyWindow"> <widget class="QMainWindow" name="keyWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>989</width>
<height>727</height>
</rect>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>MainWindow</string> <string>MainWindow</string>
</property> </property>
...@@ -22,6 +14,9 @@ ...@@ -22,6 +14,9 @@
<property name="text"> <property name="text">
<string>Request data:</string> <string>Request data:</string>
</property> </property>
<property name="buddy">
<cstring>requestData</cstring>
</property>
</widget> </widget>
</item> </item>
<item> <item>
...@@ -52,17 +47,37 @@ ...@@ -52,17 +47,37 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_7"> <layout class="QHBoxLayout" name="horizontalLayout_9" stretch="1,1,2">
<item>
<widget class="QListWidget" name="keyList"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Mac Hashes</string>
</property>
<property name="buddy">
<cstring>macHashBox</cstring>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="macHashBox"/>
</item>
</layout>
</item>
<item> <item>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="label_6">
<property name="text"> <property name="text">
<string>Filename</string> <string>Filename</string>
</property> </property>
<property name="buddy">
<cstring>fileNameBox</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
...@@ -73,6 +88,9 @@ ...@@ -73,6 +88,9 @@
<property name="text"> <property name="text">
<string>Core Hash</string> <string>Core Hash</string>
</property> </property>
<property name="buddy">
<cstring>coreHashBox</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
...@@ -83,6 +101,9 @@ ...@@ -83,6 +101,9 @@
<property name="text"> <property name="text">
<string>Plugin Hash</string> <string>Plugin Hash</string>
</property> </property>
<property name="buddy">
<cstring>pluginHashBox</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
...@@ -93,6 +114,9 @@ ...@@ -93,6 +114,9 @@
<property name="text"> <property name="text">
<string>Cpu Hash</string> <string>Cpu Hash</string>
</property> </property>
<property name="buddy">
<cstring>cpuHashBox</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="1">
...@@ -103,6 +127,9 @@ ...@@ -103,6 +127,9 @@
<property name="text"> <property name="text">
<string>ProductID</string> <string>ProductID</string>
</property> </property>
<property name="buddy">
<cstring>productIDBox</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="4" column="1">
...@@ -113,6 +140,9 @@ ...@@ -113,6 +140,9 @@
<property name="text"> <property name="text">
<string>Signature</string> <string>Signature</string>
</property> </property>
<property name="buddy">
<cstring>signatureBox</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="5" column="1">
...@@ -125,20 +155,13 @@ ...@@ -125,20 +155,13 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout> <item row="7" column="1">
</item> <widget class="QPushButton" name="generateLocalButton">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_10">
<property name="text"> <property name="text">
<string>Mac Hashes</string> <string>Generate</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QTextEdit" name="macHashBox"/>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>
...@@ -258,9 +281,9 @@ ...@@ -258,9 +281,9 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="generateButton"> <widget class="QPushButton" name="generateAllButton">
<property name="text"> <property name="text">
<string>Generate</string> <string>Generate All</string>
</property> </property>
</widget> </widget>
</item> </item>
......
...@@ -53,13 +53,117 @@ ...@@ -53,13 +53,117 @@
#include "salt.hh" #include "salt.hh"
KeyGen::KeyGen(QString n, QString cHash, QString pHash, QString cpHash, QString prHash, QStringList mHashes, QString request)
{
name = n;
coreHash = cHash;
pluginHash = pHash;
cpuHash = cpHash;
productHash = prHash;
macHashes = mHashes;
requestSig = request;
}
bool KeyGen::isValid() const
{
// Get the salts
QString saltPre;
ADD_SALT_PRE(saltPre);
QString saltPost;
ADD_SALT_POST(saltPost);
QString keyRequest = saltPre + name + coreHash + pluginHash + cpuHash + productHash + macHashes.join("") + saltPost;
QString requestSigCheck = QCryptographicHash::hash ( keyRequest.toAscii() , QCryptographicHash::Sha1 ).toHex();
return requestSig == requestSigCheck;
}
QString KeyGen::Generate(QString expiryDate) const
{
// Get the salts
QString saltPre;
ADD_SALT_PRE(saltPre);
QString saltPost;
ADD_SALT_POST(saltPost);
QString keyRequest = saltPre + name + coreHash + pluginHash + cpuHash + productHash + macHashes.join("") + saltPost;
QString requestSigCheck = QCryptographicHash::hash ( keyRequest.toAscii() , QCryptographicHash::Sha1 ).toHex();
if ( requestSig != requestSigCheck ){
return "ERROR";
}
else{
QString license_ = "";
// Add basic hashes
license_ += expiryDate + "\n";
license_ += name + "\n";
license_ += coreHash + "\n";
license_ += pluginHash + "\n";
license_ += cpuHash + "\n";
license_ += productHash + "\n";
license_ += macHashes.join("\n") + "\n";
QString licenseTmp = saltPre + expiryDate + name + coreHash + pluginHash + cpuHash + productHash + macHashes.join("") + saltPost;
QString licenseHash = QCryptographicHash::hash ( licenseTmp.toAscii() , QCryptographicHash::Sha1 ).toHex();
// Prepend signature
license_ = licenseHash + "\n" + license_;
return license_;
}
}
QString KeyGen::filterString(QString in) {
const QRegExp validChar("[a-f0-9]");
QString out; out.reserve(in.size());
for (QString::iterator it = in.begin(), it_end = in.end(); it != it_end; ++it) {
if (validChar.exactMatch(*it))
out.append(*it);
}
return out;
}
std::vector<KeyGen> KeyGen::CreateFromMessyString(QString info)
{
const QString dirt = "[\\s;>]*";
const QRegExp rx("\\b([\\w-]+)" + dirt + "((?:(?:[a-f0-9]" + dirt + "){40}){6,})\\b");
const QRegExp partRe("((?:[a-f0-9]" + dirt + "){40})");
std::vector<KeyGen> R;
int pos = 0;
while ((pos = rx.indexIn(info, pos)) != -1) {
QString hashesStr = rx.cap(2);
QStringList hashes;
int hashPos = 0;
while ((hashPos = partRe.indexIn(hashesStr, hashPos)) != -1) {
hashes.append(filterString(partRe.cap(1)));
hashPos += partRe.matchedLength();
}
QStringList macList;
std::copy(hashes.begin() + 4, hashes.end() - 1, std::back_inserter(macList));
KeyGen K(rx.cap(1),
hashes[0],
hashes[1],
hashes[2],
hashes[3],
macList,
hashes[hashes.count()-1]);
R.push_back(K);
pos += rx.matchedLength();
}
return R;
}
KeyGenWidget::KeyGenWidget(QMainWindow *parent) KeyGenWidget::KeyGenWidget(QMainWindow *parent)
: QMainWindow(parent), : QMainWindow(parent)
valid_(false)
{ {
setupUi(this); setupUi(this);
connect(generateButton,SIGNAL(clicked()),this,SLOT(slotGenerateButton())); connect(generateAllButton,SIGNAL(clicked()),this,SLOT(slotGenerateAllButton()));
connect(generateLocalButton,SIGNAL(clicked()),this,SLOT(slotGenerateButton()));
connect(keyList->selectionModel(),SIGNAL(selectionChanged(QItemSelection,QItemSelection)),this, SLOT(handleSelectionChanged(QItemSelection)));
connect(splitButton,SIGNAL(clicked()),this,SLOT(slotSplit())); connect(splitButton,SIGNAL(clicked()),this,SLOT(slotSplit()));
...@@ -74,6 +178,8 @@ KeyGenWidget::KeyGenWidget(QMainWindow *parent) ...@@ -74,6 +178,8 @@ KeyGenWidget::KeyGenWidget(QMainWindow *parent)
// For security reasons no default span is set here! // For security reasons no default span is set here!
expires->setDate( QDate::currentDate()); expires->setDate( QDate::currentDate());
generateLocalButton->setVisible(false);
generateAllButton->setVisible(false);
} }
void KeyGenWidget::slotDate() { void KeyGenWidget::slotDate() {
...@@ -86,106 +192,23 @@ void KeyGenWidget::slotDate() { ...@@ -86,106 +192,23 @@ void KeyGenWidget::slotDate() {
} }
void KeyGenWidget::slotAnalyze() { void KeyGenWidget::slotAnalyze() {
QString inputData = requestData->toPlainText();
// Convert to text and split to elements keygens_ = KeyGen::CreateFromMessyString(inputData);
QString inputData = requestData->toPlainText();
QStringList data = inputData.split('\n',QString::SkipEmptyParts);
// This is never a valid request!
if ( data.size() < 6 ) {
QPalette p = requestData->palette();
p.setColor( QPalette::Base, QColor(255,0,0) );
requestData->setPalette(p);
valid_ = false;
return;
} else {
QPalette p = requestData->palette();
p.setColor( QPalette::Base, QColor(255,255,255) );
requestData->setPalette(p);
}
// Get strings
QString name = data[0].simplified();
QString coreHash = data[1].simplified();
QString pluginHash = data[2].simplified();
QString cpuHash = data[3].simplified();
QString productHash = data[4].simplified();
QStringList macHashes;
for ( int i = 5 ; i < data.size() - 1; ++i)
macHashes.push_back(data[i].simplified());
QString requestSig = data[data.size() - 1].simplified();
fileNameBox->setText(name); keyList->clear();
coreHashBox->setText(coreHash); for (std::vector<KeyGen>::const_iterator it = keygens_.begin(), it_end = keygens_.end();
pluginHashBox->setText(pluginHash); it != it_end; ++it) {
cpuHashBox->setText(cpuHash); QListWidgetItem *newItem = new QListWidgetItem( keyList);
productIDBox->setText(productHash); newItem->setText(it->name);
newItem->setHidden(false);
macHashBox->setText(macHashes.join("\n")); if (!it->isValid())
newItem->setTextColor(QColor(255, 0, 0));
signatureBox->setText(requestSig); }
// Get the salts
QString saltPre;
ADD_SALT_PRE(saltPre);
QString saltPost;
ADD_SALT_POST(saltPost);
QString keyRequest = saltPre + name + coreHash + pluginHash + cpuHash + productHash + macHashes.join("") + saltPost; generateLocalButton->setVisible(false);
QString requestSigCheck = QCryptographicHash::hash ( keyRequest.toAscii() , QCryptographicHash::Sha1 ).toHex(); generateAllButton->setVisible(keygens_.size());
if ( requestSig != requestSigCheck ) {
QPalette p = signatureBox->palette();
p.setColor( QPalette::Base, QColor(255,0,0) );
signatureBox->setPalette(p);
valid_ = false;
if (! ignoreSigBox->isChecked() )
return;
} else {
QPalette p = signatureBox->palette();
p.setColor( QPalette::Base, QColor(0,255,0) );
signatureBox->setPalette(p);
}
QString expiryDate = expires->date().toString(Qt::ISODate);
license_ = "";
// Add basic hashes
license_ += expiryDate + "\n";
license_ += name + "\n";
license_ += coreHash + "\n";
license_ += pluginHash + "\n";
license_ += cpuHash + "\n";
license_ += productHash + "\n";
license_ += macHashes.join("\n") + "\n";
QString licenseTmp = saltPre + expiryDate + name + coreHash + pluginHash + cpuHash + productHash + macHashes.join("") + saltPost;
QString licenseHash = QCryptographicHash::hash ( licenseTmp.toAscii() , QCryptographicHash::Sha1 ).toHex();
// Prepend signature
license_ = licenseHash + "\n" + license_;
std::cerr << "Full license : \n" << license_.toStdString() << std::endl;
// Only set valid, if the the request and the signature boxes match
if ( requestSig == requestSigCheck )
valid_ = true;
licenseFileName_ = name;
} }
void KeyGenWidget::slotSplit() { void KeyGenWidget::slotSplit() {
// Get request data // Get request data
QString inputData = requestData->toPlainText(); QString inputData = requestData->toPlainText();
...@@ -199,34 +222,57 @@ void KeyGenWidget::slotSplit() { ...@@ -199,34 +222,57 @@ void KeyGenWidget::slotSplit() {
} }
KeyGenWidget::~KeyGenWidget() { void KeyGenWidget::handleSelectionChanged(const QItemSelection& selection){
generateLocalButton->setVisible(false);
if(keyList->selectionModel()->selectedIndexes().count())
{
int i = keyList->selectionModel()->selectedIndexes()[0].row();
setKeyGen(&keygens_[i]);
generateLocalButton->setVisible(true);
generateAllButton->setVisible(true);
}
} }
KeyGenWidget::~KeyGenWidget() {
void KeyGenWidget::slotGenerateButton() { }
if ( ! valid_ ) { void KeyGenWidget::toFile(const KeyGen* gen)
if ( ! ignoreSigBox->isChecked( ) ) { {
std::cerr << "Invalid Request " << std::endl; QString licenseFileName_ = gen->name;
return;
} else {
std::cerr << "Invalid Request but overriding!!" << std::endl;
}
}
std::cerr << "Writing License file to output : " << licenseFileName_.toStdString() << std::endl; std::cerr << "Writing License file to output : " << licenseFileName_.toStdString() << std::endl;
QFile outFile(licenseFileName_ + ".lic"); QFile outFile(licenseFileName_ + ".lic");
if (!outFile.open(QIODevice::WriteOnly|QIODevice::Text)) { if (!outFile.open(QIODevice::WriteOnly|QIODevice::Text)) {
QMessageBox::critical(this,tr("Unable to open file"),tr("Unable to Open output File")); QMessageBox::critical(this,tr("Unable to open file"),tr("Unable to Open output File"));
return; return;
} }
QTextStream output(&outFile); QTextStream output(&outFile);
output << gen->Generate(expires->date().toString(Qt::ISODate));
output << license_;
outFile.close(); outFile.close();
}
void KeyGenWidget::setKeyGen(const KeyGen* gen) {
fileNameBox->setText(gen->name);
coreHashBox->setText(gen->coreHash);
pluginHashBox->setText(gen->pluginHash);
cpuHashBox->setText(gen->cpuHash);
productIDBox->setText(gen->productHash);
macHashBox->setText(gen->macHashes.join("\n"));
signatureBox->setText(gen->requestSig);
generateLocalButton->setEnabled(gen->isValid());
}
void KeyGenWidget::slotGenerateButton() {
if(keyList->selectionModel()->selectedIndexes().count())
{
int i = keyList->selectionModel()->selectedIndexes()[0].row();
toFile(&keygens_[i]);
}
}
void KeyGenWidget::slotGenerateAllButton() {
for(unsigned int i = 0; i < keygens_.size(); i++)
toFile(&keygens_[i]);
} }
...@@ -46,6 +46,28 @@ ...@@ -46,6 +46,28 @@
#include <ui_keygen.hh> #include <ui_keygen.hh>
class KeyGen
{
public:
QString name;
QString coreHash;
QString pluginHash;
QString cpuHash;
QString productHash;
QStringList macHashes;
QString requestSig;
public:
KeyGen(QString n, QString cHash, QString pHash, QString cpHash, QString prHash, QStringList mHashes, QString request);
//returns string containing the key
QString Generate(QString expiryDate) const;
//finds all occurrences of info in messy string
bool isValid() const;
static std::vector<KeyGen> CreateFromMessyString(QString info);
static QString filterString(QString in);
};
class KeyGenWidget : public QMainWindow, public Ui::keyWindow class KeyGenWidget : public QMainWindow, public Ui::keyWindow
{ {
...@@ -56,6 +78,7 @@ public: ...@@ -56,6 +78,7 @@ public:
virtual ~KeyGenWidget(); virtual ~KeyGenWidget();
public slots: public slots:
void slotGenerateAllButton();
void slotGenerateButton(); void slotGenerateButton();
// slot taking license duration and convert to expiration date // slot taking license duration and convert to expiration date
...@@ -67,13 +90,15 @@ public slots: ...@@ -67,13 +90,15 @@ public slots:
// Split Code based on ;; for broken windows requests // Split Code based on ;; for broken windows requests
void slotSplit(); void slotSplit();
void handleSelectionChanged(const QItemSelection& selection);
private: private:
bool valid_;