keygenWidget.cc 12.3 KB
Newer Older
1
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
2 3
*                                                                            *
*                              OpenFlipper                                   *
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 31 32 33 34 35 36 37 38
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openflipper.org                            *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenFlipper.                                         *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39
*                                                                            *
40 41 42
\*===========================================================================*/

/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
43 44 45 46 47
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
48 49
\*===========================================================================*/

50

51
#include <QtWidgets>
52

Hans-Christian Ebke's avatar
Hans-Christian Ebke committed
53 54
#include <QMessageBox>

55
#include "keygenWidget.hh"
Jan Möbius's avatar
Jan Möbius committed
56
#include <iostream>
57

Jan Möbius's avatar
Jan Möbius committed
58 59
#include "salt.hh"

60 61 62 63 64 65 66 67 68 69 70
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;
}

71
QString KeyGen::computeSignature(const bool _utf8 ) const {
72 73 74 75 76 77 78 79
    // 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;
80 81 82 83 84 85 86 87 88 89 90

    QString requestSigCheck;

    if ( _utf8 )
      requestSigCheck =
          QCryptographicHash::hash(keyRequest.toUtf8(),
              QCryptographicHash::Sha1).toHex();
    else
      requestSigCheck =
        QCryptographicHash::hash(keyRequest.toLatin1(),
            QCryptographicHash::Sha1).toHex();
91 92 93 94

    return requestSigCheck;
}

95
KeyGen::ValidationResult KeyGen::isValid() const
96
{
97
  if (requestSig == computeSignature(true))
98 99 100
  {
    return UTF8;
  }
101
  else if(requestSig == computeSignature(false))
102 103 104 105
  {
    return LATIN1;
  }
  return INVALID;
106 107 108 109 110 111 112 113 114 115
}

QString KeyGen::Generate(QString expiryDate) const
{
	// Get the salts
	QString saltPre;
	ADD_SALT_PRE(saltPre);
	QString saltPost;
	ADD_SALT_POST(saltPost);

116
	KeyGen::ValidationResult valid = isValid();
117

118
	if ( !valid ){
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
		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;
134 135 136 137 138
		QString licenseHash;
		if (valid == UTF8)
		  licenseHash = QCryptographicHash::hash ( licenseTmp.toUtf8()  , QCryptographicHash::Sha1 ).toHex();
		else
		  licenseHash = QCryptographicHash::hash ( licenseTmp.toLatin1()  , QCryptographicHash::Sha1 ).toHex();
139 140 141 142 143 144 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
		// 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;
}

Jan Möbius's avatar
Jan Möbius committed
189
KeyGenWidget::KeyGenWidget(QMainWindow *parent)
190
    : QMainWindow(parent)
191
{
Jan Möbius's avatar
Jan Möbius committed
192
  setupUi(this);
193 194 195
  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)));
196 197
  
  connect(splitButton,SIGNAL(clicked()),this,SLOT(slotSplit()));
Jan Möbius's avatar
Jan Möbius committed
198 199 200 201 202 203 204
  
  connect(requestData,SIGNAL(textChanged()),this,SLOT(slotAnalyze()));
  
  // connect spinboxes forexpiry date
  connect(days  ,SIGNAL(valueChanged(int)),this,SLOT(slotDate()));
  connect(months,SIGNAL(valueChanged(int)),this,SLOT(slotDate()));
  connect(years ,SIGNAL(valueChanged(int)),this,SLOT(slotDate()));
205
  
206 207 208 209 210
  /*
   * Mangle Tab
   */
  connect(mangle_pb, SIGNAL(clicked()), this, SLOT(slotMangle()));

211 212 213 214
  // Automatically set expire date to current date
  // For security reasons no default span is set here!
  expires->setDate( QDate::currentDate());
  
215 216
  generateLocalButton->setVisible(false);
  generateAllButton->setVisible(false);
217 218
}

219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
void KeyGenWidget::slotMangle() {
    const QString hardwareHash_raw = hardwareHashDump_te->toPlainText();
    const QString pluginHashes_raw = pluginHashDump_te->toPlainText();

    const std::vector<KeyGen> hardwareKeygens = KeyGen::CreateFromMessyString(hardwareHash_raw);
    if (hardwareKeygens.empty()) {
        QMessageBox::critical(this, tr("Unable to Mangle"), tr("No valid request found in hardware textbox."));
        return;
    }
    KeyGen hardwareKeygen = hardwareKeygens.front();

    std::vector<KeyGen> pluginKeygens = KeyGen::CreateFromMessyString(pluginHashes_raw);
    if (pluginKeygens.empty()) {
        QMessageBox::critical(this, tr("Unable to Mangle"), tr("No valid request found in plugins textbox."));
        return;
    }

    QString generatedRequest;
    for (std::vector<KeyGen>::iterator it = pluginKeygens.begin(), it_end = pluginKeygens.end();
            it != it_end; ++it) {

        it->copyHardwareHashesFrom(hardwareKeygen);

        generatedRequest += it->generateRequest();
    }

    requestData->setPlainText(generatedRequest);
}

Jan Möbius's avatar
Jan Möbius committed
248
void KeyGenWidget::slotDate() {
249
  QDate today = QDate::currentDate();
250 251 252 253 254 255 256
  today = today.addDays(days->value());
  today = today.addMonths(months->value());
  today = today.addYears(years->value());
  
  expires->setDate(today);
}

Jan Möbius's avatar
Jan Möbius committed
257
void KeyGenWidget::slotAnalyze() {
258 259
	QString inputData = requestData->toPlainText();
	keygens_ = KeyGen::CreateFromMessyString(inputData);
Jan Möbius's avatar
Jan Möbius committed
260

261 262 263 264 265 266
	keyList->clear();
	for (std::vector<KeyGen>::const_iterator it = keygens_.begin(), it_end = keygens_.end();
	        it != it_end; ++it) {
        QListWidgetItem *newItem = new QListWidgetItem( keyList);
        newItem->setText(it->name);
        newItem->setHidden(false);
267 268 269 270 271
        KeyGen::ValidationResult r = it->isValid();
        if (!r)
          newItem->setTextColor(QColor(255, 0, 0));
        else if (r == KeyGen::LATIN1)
          newItem->setTextColor(QColor(128, 128, 0));
272
	}
Jan Möbius's avatar
Jan Möbius committed
273

274 275
	generateLocalButton->setVisible(false);
	generateAllButton->setVisible(keygens_.size());
Jan Möbius's avatar
Jan Möbius committed
276 277
}

278 279 280 281 282 283 284 285 286 287
void KeyGenWidget::slotSplit() {
  // Get request data
  QString inputData = requestData->toPlainText();
  
  // Split with ;
  QStringList data = inputData.split(";",QString::SkipEmptyParts);
  
  QString newText = data.join("\n");
  
  requestData->setText(newText);
288
  
Jan Möbius's avatar
Jan Möbius committed
289
}
290

291 292 293 294 295 296 297 298
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);
299 300 301 302 303 304 305 306

		KeyGen::ValidationResult valid = keygens_[i].isValid();
		if (valid == KeyGen::INVALID)
		  lbWarning->setText("ERROR: Signature does not match.\nCannot generate key");
		else if (valid == KeyGen::LATIN1)
		  lbWarning->setText("WARNING: Request uses old Ascii format.\nKey will be generated with Ascii encoding.");
		else
		  lbWarning->setText("");
307
	}
308 309
}

310
KeyGenWidget::~KeyGenWidget() {
311

312
}
Jan Möbius's avatar
Jan Möbius committed
313

314 315 316
void KeyGenWidget::toFile(const KeyGen* gen)
{
	QString licenseFileName_ = gen->name;
Jan Möbius's avatar
Jan Möbius committed
317 318
  std::cerr << "Writing License file to output : " << licenseFileName_.toStdString() << std::endl;
  QFile outFile(licenseFileName_ + ".lic");
319

Jan Möbius's avatar
Jan Möbius committed
320
  if (!outFile.open(QIODevice::WriteOnly|QIODevice::Text)) {
321 322
	  QMessageBox::critical(this,tr("Unable to open file"),tr("Unable to Open output File"));
	  return;
Jan Möbius's avatar
Jan Möbius committed
323
  }
324

Jan Möbius's avatar
Jan Möbius committed
325
  QTextStream output(&outFile);
326
  output << gen->Generate(expires->date().toString(Qt::ISODate));
Jan Möbius's avatar
Jan Möbius committed
327
  outFile.close();
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
}

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]);
352
}