1 /*
2 Copyright (C) 2011-2014 Yubico AB. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 2. Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "toolpage.h"
30 #include "yubikeyfinder.h"
31 #include "yubikeywriter.h"
32 #include "yubikeyutil.h"
33 #include "ui_toolpage.h"
34 #include "ui/helpbox.h"
35 #include "ui/confirmbox.h"
36 #include "mainwindow.h"
37 #include "otppage.h"
38 #include "chalresppage.h"
39 #include "oathpage.h"
40 #include "staticpage.h"
41
42 #include <QFileDialog>
43 #include <QDebug>
44 #include <QSettings>
45 #include <QSignalMapper>
46 #include <QClipboard>
47 #include <QApplication>
48
49 #include <ykpers.h>
50 #include <ykdef.h>
51
52 #include "common.h"
53
54 #define IMPORT_FILENAME_DEF "import.ycfg"
55
56 QString ToolPage::m_filename = defaultImportFilename();
57
ToolPage(QWidget * parent)58 ToolPage::ToolPage(QWidget *parent) :
59 QStackedWidget(parent),
60 ui(new Ui::ToolPage)
61 {
62 ui->setupUi(this);
63
64 //Connect pages
65 connectPages();
66
67 //Connect help buttons
68 connectHelpButtons();
69
70 //Connect other signals and slots
71 connect(ui->converterResetBtn, SIGNAL(clicked()),
72 this, SLOT(resetConverterPage()));
73 connect(ui->chalRespResetBtn, SIGNAL(clicked()),
74 this, SLOT(resetChalRespPage()));
75 connect(ui->chalRespPerformBtn, SIGNAL(clicked()),
76 this, SLOT(performChallengeResponse()));
77 connect(ui->chalRespChallenge, SIGNAL(editingFinished()),
78 this, SLOT(on_chalRespChallenge_editingFinished()));
79 connect(ui->ndefResetBtn, SIGNAL(clicked()),
80 this, SLOT(resetNdefPage()));
81 connect(ui->ndefProgramBtn, SIGNAL(clicked()),
82 this, SLOT(programNdef()));
83
84 connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)),
85 this, SLOT(keyFound(bool, bool*)));
86
87 ui->zapAccCodeEdit->setEnabled(false);
88 ui->ndefAccCodeEdit->setEnabled(false);
89
90 ui->importBox->setVisible(false);
91
92 loadSettings();
93 }
94
~ToolPage()95 ToolPage::~ToolPage() {
96 delete ui;
97 }
98
99 /*
100 Common
101 */
102
connectPages()103 void ToolPage::connectPages() {
104 //Map the values of the navigation buttons with the indexes of
105 //the stacked widget
106
107 //Create a QMapper
108 QSignalMapper *mapper = new QSignalMapper(this);
109
110 //Connect the clicked signal with the QSignalMapper
111 connect(ui->converterBtn, SIGNAL(clicked()), mapper, SLOT(map()));
112 connect(ui->converterBackBtn, SIGNAL(clicked()), mapper, SLOT(map()));
113
114 connect(ui->chalRespBtn, SIGNAL(clicked()), mapper, SLOT(map()));
115 connect(ui->chalRespBackBtn, SIGNAL(clicked()), mapper, SLOT(map()));
116
117 connect(ui->ndefBtn, SIGNAL(clicked()), mapper, SLOT(map()));
118 connect(ui->ndefBackBtn, SIGNAL(clicked()), mapper, SLOT(map()));
119
120 connect(ui->zapBtn, SIGNAL(clicked()), mapper, SLOT(map()));
121 connect(ui->zapBackBtn, SIGNAL(clicked()), mapper, SLOT(map()));
122
123 connect(ui->importBtn, SIGNAL(clicked()), mapper, SLOT(map()));
124 connect(ui->importBackBtn, SIGNAL(clicked()), mapper, SLOT(map()));
125
126 //Set a value for each button
127 mapper->setMapping(ui->converterBtn, Page_Converter);
128 mapper->setMapping(ui->converterBackBtn, Page_Base);
129
130 mapper->setMapping(ui->chalRespBtn, Page_ChalResp);
131 mapper->setMapping(ui->chalRespBackBtn, Page_Base);
132
133 mapper->setMapping(ui->ndefBtn, Page_Ndef);
134 mapper->setMapping(ui->ndefBackBtn, Page_Base);
135
136 mapper->setMapping(ui->zapBtn, Page_Zap);
137 mapper->setMapping(ui->zapBackBtn, Page_Base);
138
139 mapper->setMapping(ui->importBtn, Page_Import);
140 mapper->setMapping(ui->importBackBtn, Page_Base);
141
142 //Connect the mapper to the widget
143 //The mapper will set a value to each button and
144 //set that value to the widget
145 //connect(pageMapper, SIGNAL(mapped(int)), this, SLOT(setCurrentIndex(int)));
146 connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCurrentPage(int)));
147
148 //Set the current page
149 m_currentPage = 0;
150 setCurrentIndex(Page_Base);
151 }
152
loadSettings()153 void ToolPage::loadSettings() {
154 QSettings settings;
155 ui->importBox->setVisible(settings.value(SG_EXPORT_PREFERENCE).toBool());
156 }
157
setCurrentPage(int pageIndex)158 void ToolPage::setCurrentPage(int pageIndex) {
159 //Page changed...
160
161 m_currentPage = pageIndex;
162
163 switch(pageIndex){
164 case Page_Converter:
165 resetConverterPage();
166 break;
167 }
168
169 setCurrentIndex(pageIndex);
170 }
171
connectHelpButtons()172 void ToolPage::connectHelpButtons() {
173 }
174
resetChalRespPage()175 void ToolPage::resetChalRespPage() {
176 ui->chalRespChallenge->clear();
177 ui->chalRespResponse->clear();
178 }
179
on_chalRespChallenge_editingFinished()180 void ToolPage::on_chalRespChallenge_editingFinished() {
181 QString challenge = ui->chalRespChallenge->text().trimmed();
182 ui->chalRespChallenge->setText(challenge);
183 }
184
performChallengeResponse()185 void ToolPage::performChallengeResponse() {
186 QString challenge = ui->chalRespChallenge->text();
187 QString response = "";
188 bool hmac;
189 int slot;
190 if(ui->chalRespHmacRadio->isChecked()) {
191 hmac = true;
192 } else if(ui->chalRespYubicoRadio->isChecked()) {
193 hmac = false;
194 } else {
195 emit showStatusMessage(tr(ERR_CHAL_TYPE_NOT_SELECTED), 1);
196 return;
197 }
198 if(ui->chalRespSlot1Radio->isChecked()) {
199 slot = 1;
200 } else if(ui->chalRespSlot2Radio->isChecked()) {
201 slot = 2;
202 } else {
203 emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1);
204 return;
205 }
206 YubiKeyWriter::getInstance()->doChallengeResponse(challenge, response, slot, hmac);
207 qDebug() << "response was: " << response;
208 ui->chalRespResponse->setText(response);
209 }
210 /*
211 Quick Page handling
212 */
resetConverterPage()213 void ToolPage::resetConverterPage() {
214 convert(0, "");
215 ui->converterHexTxt->setCursorPosition(0);
216 ui->converterHexTxt->setFocus();
217 }
218
convert(int updatedIndex,QString txt)219 void ToolPage::convert(int updatedIndex, QString txt) {
220 unsigned char buf[32];
221 memset(buf, 0, sizeof(buf));
222 size_t bufLen;
223
224 switch(updatedIndex) {
225 case 0: //Hex
226 YubiKeyUtil::qstrHexDecode(buf, &bufLen, txt);
227 break;
228
229 case 1: //Modhex
230 YubiKeyUtil::qstrModhexDecode(buf, &bufLen, txt);
231 break;
232
233 case 2: //Decimal
234 QString tmp = QString::number(txt.toULongLong(), 16);
235 size_t len = tmp.length();
236 if(len % 2 != 0) {
237 len++;
238 }
239 YubiKeyUtil::qstrClean(&tmp, (size_t)len, true);
240 YubiKeyUtil::qstrHexDecode(buf, &bufLen, tmp);
241 break;
242 }
243
244 QString hex = YubiKeyUtil::qstrHexEncode(buf, bufLen);
245 QString modhex = YubiKeyUtil::qstrModhexEncode(buf, bufLen);
246 bool ok = false;
247 qulonglong dec = hex.toULongLong(&ok, 16);
248
249 int hexLen = hex.length();
250 int modhexLen = modhex.length();
251
252 ui->converterHexTxt->setText(hex);
253 ui->converterModhexTxt->setText(modhex);
254 ui->converterDecTxt->setText(QString::number(dec));
255
256 ui->converterHexCopyBtn->setEnabled(hexLen > 0);
257 ui->converterModhexCopyBtn->setEnabled(modhexLen > 0);
258 ui->converterDecCopyBtn->setEnabled(
259 ui->converterDecTxt->text().length() > 0);
260
261 ui->converterHexLenLbl->setText(tr("(%1 chars)").arg(hexLen));
262 ui->converterModhexLenLbl->setText(tr("(%1 chars)").arg(modhexLen));
263
264 if(hexLen != 0 && !ok) {
265 ui->converterDecErrLbl->setText(tr(TOVERFLOW));
266 } else {
267 ui->converterDecErrLbl->setText(tr(""));
268 }
269 }
270
on_converterHexTxt_editingFinished()271 void ToolPage::on_converterHexTxt_editingFinished() {
272 QString txt = ui->converterHexTxt->text();
273 YubiKeyUtil::qstrClean(&txt, 0, true);
274
275 size_t len = txt.length();
276 if(len > 0) {
277 if(len % 2 != 0) {
278 len++;
279 }
280 YubiKeyUtil::qstrClean(&txt, (size_t)len, true);
281 convert(0, txt);
282 }
283 ui->converterHexTxt->setCursorPosition(len + len/2);
284 }
285
on_converterModhexTxt_editingFinished()286 void ToolPage::on_converterModhexTxt_editingFinished() {
287 QString txt = ui->converterModhexTxt->text();
288 YubiKeyUtil::qstrModhexClean(&txt, 0, true);
289
290 size_t len = txt.length();
291 if(len > 0) {
292 if(len % 2 != 0) {
293 len++;
294 }
295 YubiKeyUtil::qstrModhexClean(&txt, (size_t)len, true);
296 convert(1, txt);
297 }
298 ui->converterModhexTxt->setCursorPosition(len + len/2);
299 }
300
on_converterDecTxt_editingFinished()301 void ToolPage::on_converterDecTxt_editingFinished() {
302 QString txt = ui->converterDecTxt->text();
303 bool ok = false;
304 qulonglong dec = txt.toULongLong(&ok);
305 if(ok) {
306 if(dec > 0) {
307 size_t len = txt.length();
308 YubiKeyUtil::qstrClean(&txt, (size_t)len, true);
309 convert(2, txt);
310 ui->converterDecTxt->setCursorPosition(len);
311 }
312 } else {
313 ui->converterDecErrLbl->setText(tr(TOVERFLOW));
314 }
315
316 }
317
copyToClipboard(const QString & str)318 void ToolPage::copyToClipboard(const QString &str) {
319 QClipboard *clipboard = QApplication::clipboard();
320 clipboard->setText(str);
321
322 showStatusMessage(tr(VALUE_COPIED), 0);
323 }
324
on_converterHexCopyBtn_clicked()325 void ToolPage::on_converterHexCopyBtn_clicked() {
326 QString txt = ui->converterHexTxt->text();
327 YubiKeyUtil::qstrClean(&txt, 0, true);
328
329 copyToClipboard(txt);
330 }
331
on_converterModhexCopyBtn_clicked()332 void ToolPage::on_converterModhexCopyBtn_clicked() {
333 QString txt = ui->converterModhexTxt->text();
334 YubiKeyUtil::qstrModhexClean(&txt, 0, true);
335
336 copyToClipboard(txt);
337 }
338
on_converterDecCopyBtn_clicked()339 void ToolPage::on_converterDecCopyBtn_clicked() {
340 copyToClipboard(ui->converterDecTxt->text());
341 }
342
resetNdefPage()343 void ToolPage::resetNdefPage() {
344 ui->ndefEdit->setText("https://my.yubico.com/neo/");
345 ui->ndefTextLangEdit->setText("en-US");
346 ui->ndefUriRadio->setChecked(true);
347 ui->ndefAccCodeCheckbox->setChecked(false);
348 ui->ndefSlot1Radio->setChecked(false);
349 ui->ndefSlot2Radio->setChecked(false);
350 }
351
programNdef()352 void ToolPage::programNdef() {
353 QSettings settings;
354 YubiKeyWriter *writer = YubiKeyWriter::getInstance();
355 bool uri = true;
356 QString language;
357 QString payload;
358 int slot;
359 if(ui->ndefTextRadio->isChecked()) {
360 uri = false;
361 language = ui->ndefTextLangEdit->text().trimmed();
362 if(language.isEmpty()) {
363 return;
364 }
365 }
366 payload = ui->ndefEdit->text().trimmed();
367 if(payload.isEmpty()) {
368 return;
369 }
370
371 if(uri && !settings.value(SG_NDEF_WITHOUT_HTTP).toBool()) {
372 if(!payload.startsWith("http")) {
373 ConfirmBox confirm(this);
374 confirm.setConfirmIndex(ConfirmBox::Confirm_NdefWithoutHttp);
375 int ret = confirm.exec();
376 if(ret != 1) // 1 is yes
377 return;
378 }
379 }
380
381 if(ui->ndefSlot1Radio->isChecked()) {
382 slot = 1;
383 } else if(ui->ndefSlot2Radio->isChecked()) {
384 slot = 2;
385 } else {
386 emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1);
387 return;
388 }
389
390 connect(writer, SIGNAL(configWritten(bool, const QString &)),
391 this, SLOT(ndefWritten(bool, const QString &)));
392 writer->writeNdef(uri, language, payload, ui->ndefAccCodeEdit->text().remove(" "), slot);
393 }
394
ndefWritten(bool written,const QString & msg)395 void ToolPage::ndefWritten(bool written, __attribute__((unused)) const QString &msg) {
396 disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)),
397 this, SLOT(ndefWritten(bool, const QString &)));
398 if(written) {
399 showStatusMessage(tr("NDEF successfully written"));
400 }
401 }
402
on_ndefTextRadio_toggled(bool checked)403 void ToolPage::on_ndefTextRadio_toggled(bool checked) {
404 if(checked) {
405 ui->ndefTextLangEdit->setEnabled(true);
406 ui->ndefEdit->setText("");
407 } else {
408 ui->ndefTextLangEdit->setText("en-US");
409 ui->ndefTextLangEdit->setEnabled(false);
410 ui->ndefEdit->setText("https://my.yubico.com/neo/");
411 }
412 }
413
on_ndefAccCodeCheckbox_toggled(bool checked)414 void ToolPage::on_ndefAccCodeCheckbox_toggled(bool checked) {
415 ui->ndefAccCodeEdit->setText("00 00 00 00 00 00");
416 ui->ndefAccCodeEdit->setEnabled(checked);
417 ui->ndefUseSerial->setChecked(false);
418 ui->ndefUseSerial->setEnabled(checked);
419 }
420
on_ndefUseSerial_toggled(bool checked)421 void ToolPage::on_ndefUseSerial_toggled(bool checked) {
422 if(checked) {
423 setSerial(ui->ndefAccCodeEdit);
424 }
425 }
426
on_zapPerformBtn_clicked()427 void ToolPage::on_zapPerformBtn_clicked() {
428 int slot;
429 if(ui->zapSlot1Radio->isChecked()) {
430 slot = 1;
431 } else if(ui->zapSlot2Radio->isChecked()) {
432 slot = 2;
433 } else {
434 emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1);
435 return;
436 }
437
438 YubiKeyWriter *writer = YubiKeyWriter::getInstance();
439 connect(writer, SIGNAL(configWritten(bool, const QString &)),
440 this, SLOT(zapDone(bool, const QString &)));
441 writer->deleteConfig(slot, ui->zapAccCodeEdit->text().remove(" "));
442 }
443
zapDone(bool written,const QString & msg)444 void ToolPage::zapDone(bool written, __attribute__((unused)) const QString &msg) {
445 disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)),
446 this, SLOT(zapDone(bool, const QString &)));
447 if(written) {
448 showStatusMessage(tr("Configuration successfully deleted."));
449 }
450 }
451
on_zapAccCodeCheckbox_toggled(bool checked)452 void ToolPage::on_zapAccCodeCheckbox_toggled(bool checked) {
453 ui->zapAccCodeEdit->setText("00 00 00 00 00 00");
454 ui->zapAccCodeEdit->setEnabled(checked);
455 ui->zapUseSerial->setChecked(false);
456 ui->zapUseSerial->setEnabled(checked);
457 }
458
on_zapUseSerial_toggled(bool checked)459 void ToolPage::on_zapUseSerial_toggled(bool checked) {
460 if(checked) {
461 setSerial(ui->zapAccCodeEdit);
462 }
463 }
464
on_importPerformBtn_clicked()465 void ToolPage::on_importPerformBtn_clicked() {
466 QString filename = QFileDialog::getOpenFileName(this, tr("Open file for import"), m_filename, tr("Yubico cfg format (*.ycfg);;All Files (*.*)"));
467 if(filename.isEmpty()) {
468 return;
469 }
470 QFile file(filename);
471
472 if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
473 showStatusMessage(tr("Failed to open selected file."), 1);
474 }
475
476 char data[1024];
477 int len = file.read(data, 1024);
478 if(!len) {
479 showStatusMessage(tr("Failed to read from selected file."), 1);
480 }
481 file.close();
482
483 YKP_CONFIG *cfg = ykp_alloc();
484 YK_STATUS *ykds = YubiKeyFinder::getInstance()->status();
485 ykp_configure_version(cfg, ykds);
486 int ret = ykp_import_config(cfg, data, len, YKP_FORMAT_YCFG);
487 if(ret) {
488 QSettings settings;
489 m_filename = filename;
490 settings.setValue(SG_IMPORT_FILENAME, filename);
491
492 MainWindow::Page page = MainWindow::Page_Otp;
493 int tab = OtpPage::Page_Advanced;
494 if(ykp_get_tktflag_OATH_HOTP(cfg)) {
495 if(ykp_get_cfgflag_CHAL_HMAC(cfg)) {
496 qDebug() << "importing mode chal-resp hmac";
497 page = MainWindow::Page_ChalResp;
498 tab = ChalRespPage::Page_Advanced;
499 settings.setValue(SG_REQUIRE_INPUT, ykp_get_cfgflag_CHAL_BTN_TRIG(cfg));
500 settings.setValue(SG_HMAC_LT64, ykp_get_cfgflag_HMAC_LT64(cfg));
501 } else if(ykp_get_cfgflag_CHAL_YUBICO(cfg)) {
502 qDebug() << "importing mode chal-resp yubico";
503 page = MainWindow::Page_ChalResp;
504 tab = ChalRespPage::Page_Quick;
505 settings.setValue(SG_REQUIRE_INPUT, ykp_get_cfgflag_CHAL_BTN_TRIG(cfg));
506 } else {
507 qDebug() << "importing mode oath hotp";
508 page = MainWindow::Page_Oath;
509 tab = OathPage::Page_Advanced;
510 settings.setValue(SG_OATH_HOTP8, ykp_get_cfgflag_OATH_HOTP8(cfg));
511 // XXX: handle seed and fixed_modhex
512 }
513 } else if(ykp_get_cfgflag_STATIC_TICKET(cfg)) {
514 qDebug() << "importing mode static";
515 page = MainWindow::Page_Static;
516 tab = StaticPage::Page_Advanced;
517 settings.setValue(SG_STRONG_PW1, ykp_get_cfgflag_STRONG_PW1(cfg));
518 if(ykp_get_cfgflag_STRONG_PW2(cfg)) {
519 settings.setValue(SG_STRONG_PW2, true);
520 settings.setValue(SG_STRONG_PW3, ykp_get_cfgflag_SEND_REF(cfg));
521 } else {
522 settings.setValue(SG_STRONG_PW2, false);
523 }
524 } else {
525 qDebug() << "importing yubico otp";
526 }
527
528 settings.setValue(SG_MAN_UPDATE, ykp_get_cfgflag_MAN_UPDATE(cfg));
529 settings.setValue(SG_PACING_10MS, ykp_get_cfgflag_PACING_10MS(cfg));
530 settings.setValue(SG_PACING_20MS, ykp_get_cfgflag_PACING_20MS(cfg));
531 settings.setValue(SG_APPEND_CR, ykp_get_tktflag_APPEND_CR(cfg));
532 settings.setValue(SG_APPEND_DELAY1, ykp_get_tktflag_APPEND_DELAY1(cfg));
533 settings.setValue(SG_APPEND_DELAY2, ykp_get_tktflag_APPEND_DELAY2(cfg));
534 settings.setValue(SG_APPEND_TAB1, ykp_get_tktflag_APPEND_TAB1(cfg));
535 settings.setValue(SG_APPEND_TAB2, ykp_get_tktflag_APPEND_TAB2(cfg));
536 settings.setValue(SG_TAB_FIRST, ykp_get_tktflag_TAB_FIRST(cfg));
537 settings.setValue(SG_SR_BTN_VISIBLE, ykp_get_extflag_SERIAL_BTN_VISIBLE(cfg));
538 settings.setValue(SG_SR_USB_VISIBLE, ykp_get_extflag_SERIAL_USB_VISIBLE(cfg));
539 settings.setValue(SG_SR_API_VISIBLE, ykp_get_extflag_SERIAL_API_VISIBLE(cfg));
540 settings.setValue(SG_USE_NUMERIC_KEYPAD, ykp_get_extflag_USE_NUMERIC_KEYPAD(cfg));
541 settings.setValue(SG_FAST_TRIG, ykp_get_extflag_FAST_TRIG(cfg));
542 settings.setValue(SG_ALLOW_UPDATE, ykp_get_extflag_ALLOW_UPDATE(cfg));
543 settings.setValue(SG_LED_INVERT, ykp_get_extflag_LED_INV(cfg));
544
545 int config = ykp_config_num(cfg);
546
547 emit switchPage(page, tab, config);
548 emit reloadSettings();
549 } else {
550 showStatusMessage(tr("Failed to parse the configuration."), 1);
551 }
552 ykp_free_config(cfg);
553 }
554
keyFound(bool found,bool * featuresMatrix)555 void ToolPage::keyFound(bool found, bool* featuresMatrix) {
556 if(found && featuresMatrix[YubiKeyFinder::Feature_ChallengeResponse]) {
557 ui->chalRespPerformBtn->setEnabled(true);
558 } else {
559 ui->chalRespPerformBtn->setEnabled(false);
560 }
561 if(found && featuresMatrix[YubiKeyFinder::Feature_Ndef]) {
562 ui->ndefProgramBtn->setEnabled(true);
563 } else {
564 ui->ndefProgramBtn->setEnabled(false);
565 }
566 if(found && featuresMatrix[YubiKeyFinder::Feature_MultipleConfigurations]) {
567 ui->chalRespSlot2Radio->setEnabled(true);
568 ui->zapSlot2Radio->setEnabled(true);
569 ui->ndefSlot2Radio->setEnabled(true);
570 } else {
571 ui->chalRespSlot2Radio->setEnabled(false);
572 ui->zapSlot2Radio->setEnabled(false);
573 ui->ndefSlot2Radio->setEnabled(false);
574 }
575 ui->zapPerformBtn->setEnabled(found);
576 ui->importPerformBtn->setEnabled(found);
577
578 if(found) {
579 m_serial = QString::number(YubiKeyFinder::getInstance()->serial());
580 int num = 12 - m_serial.length();
581 for(int i = 0; i < num; i++) {
582 m_serial.prepend("0");
583 }
584 if(!m_serial.isEmpty()) {
585 if(ui->ndefUseSerial->isChecked()) {
586 setSerial(ui->ndefAccCodeEdit);
587 }
588 if(ui->zapUseSerial->isChecked()) {
589 setSerial(ui->zapAccCodeEdit);
590 }
591 }
592 } else {
593 m_serial.clear();
594 }
595 }
596
setImportFilename(QString filename)597 void ToolPage::setImportFilename(QString filename) {
598 m_filename = filename;
599 }
600
defaultImportFilename()601 QString ToolPage::defaultImportFilename() {
602 return QDir::homePath() + "/" + IMPORT_FILENAME_DEF;
603 }
604
setSerial(QLineEdit * line)605 void ToolPage::setSerial(QLineEdit *line) {
606 if(!m_serial.isEmpty()) {
607 line->setText(m_serial);
608 }
609 }
610