Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
keygenWidget.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50
51
52 #if QT_VERSION >= 0x050000
53 #include <QtWidgets>
54 #else
55 #include <QtGui>
56 #endif
57
58 #include <QMessageBox>
59
60 #include "keygenWidget.hh"
61 #include <iostream>
62
63 #include "salt.hh"
64
65 KeyGen::KeyGen(QString n, QString cHash, QString pHash, QString cpHash, QString prHash, QStringList mHashes, QString request)
66 {
67 name = n;
68 coreHash = cHash;
69 pluginHash = pHash;
70 cpuHash = cpHash;
71 productHash = prHash;
72 macHashes = mHashes;
73 requestSig = request;
74 }
75
76 QString KeyGen::computeSignature(const bool _utf8 ) const {
77 // Get the salts
78 QString saltPre;
79 ADD_SALT_PRE(saltPre);
80 QString saltPost;
81 ADD_SALT_POST(saltPost);
82
83 QString keyRequest = saltPre + name + coreHash + pluginHash + cpuHash
84 + productHash + macHashes.join("") + saltPost;
85
86 QString requestSigCheck;
87
88 if ( _utf8 )
89 requestSigCheck =
90 QCryptographicHash::hash(keyRequest.toUtf8(),
91 QCryptographicHash::Sha1).toHex();
92 else
93 requestSigCheck =
94 QCryptographicHash::hash(keyRequest.toLatin1(),
95 QCryptographicHash::Sha1).toHex();
96
97 return requestSigCheck;
98 }
99
100 KeyGen::ValidationResult KeyGen::isValid() const
101 {
102 if (requestSig == computeSignature(true))
103 {
104 return UTF8;
105 }
106 else if(requestSig == computeSignature(false))
107 {
108 return LATIN1;
109 }
110 return INVALID;
111 }
112
113 QString KeyGen::Generate(QString expiryDate) const
114 {
115 // Get the salts
116 QString saltPre;
117 ADD_SALT_PRE(saltPre);
118 QString saltPost;
119 ADD_SALT_POST(saltPost);
120
121 KeyGen::ValidationResult valid = isValid();
122
123 if ( !valid ){
124 return "ERROR";
125 }
126 else{
127 QString license_ = "";
128
129 // Add basic hashes
130 license_ += expiryDate + "\n";
131 license_ += name + "\n";
132 license_ += coreHash + "\n";
133 license_ += pluginHash + "\n";
134 license_ += cpuHash + "\n";
135 license_ += productHash + "\n";
136 license_ += macHashes.join("\n") + "\n";
137
138 QString licenseTmp = saltPre + expiryDate + name + coreHash + pluginHash + cpuHash + productHash + macHashes.join("") + saltPost;
139 QString licenseHash;
140 if (valid == UTF8)
141 licenseHash = QCryptographicHash::hash ( licenseTmp.toUtf8() , QCryptographicHash::Sha1 ).toHex();
142 else
143 licenseHash = QCryptographicHash::hash ( licenseTmp.toLatin1() , QCryptographicHash::Sha1 ).toHex();
144 // Prepend signature
145 license_ = licenseHash + "\n" + license_;
146 return license_;
147 }
148 }
149
150 QString KeyGen::filterString(QString in) {
151 const QRegExp validChar("[a-f0-9]");
152 QString out; out.reserve(in.size());
153 for (QString::iterator it = in.begin(), it_end = in.end(); it != it_end; ++it) {
154 if (validChar.exactMatch(*it))
155 out.append(*it);
156 }
157 return out;
158 }
159
160 std::vector<KeyGen> KeyGen::CreateFromMessyString(QString info)
161 {
162 const QString dirt = "[\\s;>]*";
163 const QRegExp rx("\\b([\\w-]+)" + dirt + "((?:(?:[a-f0-9]" + dirt + "){40}){6,})\\b");
164 const QRegExp partRe("((?:[a-f0-9]" + dirt + "){40})");
165
166 std::vector<KeyGen> R;
167 int pos = 0;
168 while ((pos = rx.indexIn(info, pos)) != -1) {
169 QString hashesStr = rx.cap(2);
170 QStringList hashes;
171 int hashPos = 0;
172 while ((hashPos = partRe.indexIn(hashesStr, hashPos)) != -1) {
173 hashes.append(filterString(partRe.cap(1)));
174 hashPos += partRe.matchedLength();
175 }
176
177 QStringList macList;
178 std::copy(hashes.begin() + 4, hashes.end() - 1, std::back_inserter(macList));
179
180 KeyGen K(rx.cap(1),
181 hashes[0],
182 hashes[1],
183 hashes[2],
184 hashes[3],
185 macList,
186 hashes[hashes.count()-1]);
187 R.push_back(K);
188 pos += rx.matchedLength();
189 }
190
191 return R;
192 }
193
194 KeyGenWidget::KeyGenWidget(QMainWindow *parent)
195 : QMainWindow(parent)
196 {
197 setupUi(this);
198 connect(generateAllButton,SIGNAL(clicked()),this,SLOT(slotGenerateAllButton()));
199 connect(generateLocalButton,SIGNAL(clicked()),this,SLOT(slotGenerateButton()));
200 connect(keyList->selectionModel(),SIGNAL(selectionChanged(QItemSelection,QItemSelection)),this, SLOT(handleSelectionChanged(QItemSelection)));
201
202 connect(splitButton,SIGNAL(clicked()),this,SLOT(slotSplit()));
203
204 connect(requestData,SIGNAL(textChanged()),this,SLOT(slotAnalyze()));
205
206 // connect spinboxes forexpiry date
207 connect(days ,SIGNAL(valueChanged(int)),this,SLOT(slotDate()));
208 connect(months,SIGNAL(valueChanged(int)),this,SLOT(slotDate()));
209 connect(years ,SIGNAL(valueChanged(int)),this,SLOT(slotDate()));
210
211 /*
212 * Mangle Tab
213 */
214 connect(mangle_pb, SIGNAL(clicked()), this, SLOT(slotMangle()));
215
216 // Automatically set expire date to current date
217 // For security reasons no default span is set here!
218 expires->setDate( QDate::currentDate());
219
220 generateLocalButton->setVisible(false);
221 generateAllButton->setVisible(false);
222 }
223
224 void KeyGenWidget::slotMangle() {
225 const QString hardwareHash_raw = hardwareHashDump_te->toPlainText();
226 const QString pluginHashes_raw = pluginHashDump_te->toPlainText();
227
228 const std::vector<KeyGen> hardwareKeygens = KeyGen::CreateFromMessyString(hardwareHash_raw);
229 if (hardwareKeygens.empty()) {
230 QMessageBox::critical(this, tr("Unable to Mangle"), tr("No valid request found in hardware textbox."));
231 return;
232 }
233 KeyGen hardwareKeygen = hardwareKeygens.front();
234
235 std::vector<KeyGen> pluginKeygens = KeyGen::CreateFromMessyString(pluginHashes_raw);
236 if (pluginKeygens.empty()) {
237 QMessageBox::critical(this, tr("Unable to Mangle"), tr("No valid request found in plugins textbox."));
238 return;
239 }
240
241 QString generatedRequest;
242 for (std::vector<KeyGen>::iterator it = pluginKeygens.begin(), it_end = pluginKeygens.end();
243 it != it_end; ++it) {
244
245 it->copyHardwareHashesFrom(hardwareKeygen);
246
247 generatedRequest += it->generateRequest();
248 }
249
250 requestData->setPlainText(generatedRequest);
251 }
252
253 void KeyGenWidget::slotDate() {
254 QDate today = QDate::currentDate();
255 today = today.addDays(days->value());
256 today = today.addMonths(months->value());
257 today = today.addYears(years->value());
258
259 expires->setDate(today);
260 }
261
262 void KeyGenWidget::slotAnalyze() {
263 QString inputData = requestData->toPlainText();
264 keygens_ = KeyGen::CreateFromMessyString(inputData);
265
266 keyList->clear();
267 for (std::vector<KeyGen>::const_iterator it = keygens_.begin(), it_end = keygens_.end();
268 it != it_end; ++it) {
269 QListWidgetItem *newItem = new QListWidgetItem( keyList);
270 newItem->setText(it->name);
271 newItem->setHidden(false);
272 KeyGen::ValidationResult r = it->isValid();
273 if (!r)
274 newItem->setTextColor(QColor(255, 0, 0));
275 else if (r == KeyGen::LATIN1)
276 newItem->setTextColor(QColor(128, 128, 0));
277 }
278
279 generateLocalButton->setVisible(false);
280 generateAllButton->setVisible(keygens_.size());
281 }
282
283 void KeyGenWidget::slotSplit() {
284 // Get request data
285 QString inputData = requestData->toPlainText();
286
287 // Split with ;
288 QStringList data = inputData.split(";",QString::SkipEmptyParts);
289
290 QString newText = data.join("\n");
291
292 requestData->setText(newText);
293
294 }
295
296 void KeyGenWidget::handleSelectionChanged(const QItemSelection& selection){
297 generateLocalButton->setVisible(false);
298 if(keyList->selectionModel()->selectedIndexes().count())
299 {
300 int i = keyList->selectionModel()->selectedIndexes()[0].row();
301 setKeyGen(&keygens_[i]);
302 generateLocalButton->setVisible(true);
303 generateAllButton->setVisible(true);
304
305 KeyGen::ValidationResult valid = keygens_[i].isValid();
306 if (valid == KeyGen::INVALID)
307 lbWarning->setText("ERROR: Signature does not match.\nCannot generate key");
308 else if (valid == KeyGen::LATIN1)
309 lbWarning->setText("WARNING: Request uses old Ascii format.\nKey will be generated with Ascii encoding.");
310 else
311 lbWarning->setText("");
312 }
313 }
314
315 KeyGenWidget::~KeyGenWidget() {
316
317 }
318
319 void KeyGenWidget::toFile(const KeyGen* gen)
320 {
321 QString licenseFileName_ = gen->name;
322 std::cerr << "Writing License file to output : " << licenseFileName_.toStdString() << std::endl;
323 QFile outFile(licenseFileName_ + ".lic");
324
325 if (!outFile.open(QIODevice::WriteOnly|QIODevice::Text)) {
326 QMessageBox::critical(this,tr("Unable to open file"),tr("Unable to Open output File"));
327 return;
328 }
329
330 QTextStream output(&outFile);
331 output << gen->Generate(expires->date().toString(Qt::ISODate));
332 outFile.close();
333 }
334
335 void KeyGenWidget::setKeyGen(const KeyGen* gen) {
336 fileNameBox->setText(gen->name);
337 coreHashBox->setText(gen->coreHash);
338 pluginHashBox->setText(gen->pluginHash);
339 cpuHashBox->setText(gen->cpuHash);
340 productIDBox->setText(gen->productHash);
341 macHashBox->setText(gen->macHashes.join("\n"));
342 signatureBox->setText(gen->requestSig);
343 generateLocalButton->setEnabled(gen->isValid());
344 }
345
346 void KeyGenWidget::slotGenerateButton() {
347 if(keyList->selectionModel()->selectedIndexes().count())
348 {
349 int i = keyList->selectionModel()->selectedIndexes()[0].row();
350 toFile(&keygens_[i]);
351 }
352 }
353
354 void KeyGenWidget::slotGenerateAllButton() {
355 for(unsigned int i = 0; i < keygens_.size(); i++)
356 toFile(&keygens_[i]);
357 }
INIFile::connect
bool connect(const QString &name, const bool create)
Connect INIFile object with given filename.
Definition: INIFile.cc:76
KeyGen
Definition: keygenWidget.hh:56