/*! @file @id $Id$ */ // 1 2 3 4 5 6 7 8 // 45678901234567890123456789012345678901234567890123456789012345678901234567890 #ifndef __Tokentool_HXX__ #define __Tokentool_HXX__ #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 namespace QSsl { typedef AlternativeNameEntryType AlternateNameEntryType; } #endif inline QString qs(const std::string& s) { return QString::fromStdString(s); } template QString qs(const cryptoki::FixString& s) { return QString::fromStdString(s); } class Progress: public QProgressBar { public: Progress() { reset(); } Progress& steps(int incr) { setMaximum(maximum()+incr); setVisible(value()=maximum()) { setMaximum(0); setValue(0); } return *this; } Progress& reset() { setMinimum(0); setMaximum(0); setValue(0); setVisible(false); return *this; } }; class tokentool: public QMainWindow, protected Ui::tokentool { Q_OBJECT; public: tokentool(std::string lib="libcvP11.so", QWidget* p=0): QMainWindow(p), _slot(0), _progress(new Progress) { try { setupUi(this); statusBar()->addPermanentWidget(_progress, 2); show(); _progress->steps(3); _cryptoki = std::auto_ptr(new cryptoki::Library(lib)); ++*_progress; _certificates->addAction(actionDeleteSelectedCertificate); libraryInfo(lib); ++*_progress; on_actionRescan_triggered(); ++*_progress; } catch (...) { QMessageBox::critical(this, tr("Initialization Failed"), tr("SmardCard Initialization Failed")); } } private Q_SLOTS: void on_actionRescan_triggered() { qDebug()<<__PRETTY_FUNCTION__; static bool lock(false); if (lock) return; lock = true; try { _slot = 0; _slots->clear(); _slotList = _cryptoki->slotList(false); _progress->steps(_slotList.size()); for (cryptoki::SlotList::iterator it(_slotList.begin()); it!=_slotList.end(); ++it) { qDebug()<<"Add Slot"; QAction* a(_slots->addAction(qs(it->slotinfo().slotDescription))); a->setCheckable(true); a->setData((qulonglong)&*it); assert(connect(a, SIGNAL(triggered(bool)), SLOT(chosen(bool)))); if (!_slot) a->trigger(); ++*_progress; } qDebug()<<"DONE"; } catch (...) {} // ignore lock = false; on__certificates_itemSelectionChanged(); } void on_actionDeleteSelectedCertificate_triggered() { QList items(_certificates->selectedItems()); if (items.size()>0) deleteCert(items[0]); } void on__certificates_itemSelectionChanged() { actionDeleteSelectedCertificate ->setEnabled(_certificates->selectedItems().size() &&!_pin->text().isEmpty()); } void on__pin_textChanged(const QString&) { on__certificates_itemSelectionChanged(); } void chosen(bool) { _pin->clear(); QAction* a(qobject_cast(sender())); a->setChecked(true); QMenu* m(qobject_cast(a->parent())); QObjectList actions(m->children()); for (QObjectList::iterator it(actions.begin());it!=actions.end(); ++it) if (qobject_cast(*it)!=a) qobject_cast(*it)->setChecked(false); _slot = (cryptoki::Slot*)a->data().toLongLong(); setup(); } void setup() { try { _progress->steps(3); slotInfo(); ++*_progress; tokenInfo(); ++*_progress; certificates(); ++*_progress; objects(); } catch (...) { _progress->reset(); on_actionRescan_triggered(); } } void libraryInfo(std::string lib) { _soname->setText(qs(lib)); cryptoki::Info inf(_cryptoki->info()); _libraryCryptokiVersion->setText(QString("%1.%2") .arg(inf.cryptokiVersion.major) .arg(inf.cryptokiVersion.minor)); _libraryManufacturerID->setText(qs(inf.manufacturerID)); _libraryDescription->setText(qs(inf.libraryDescription)); _libraryVersion->setText(QString("%1.%2") .arg(inf.libraryVersion.major) .arg(inf.libraryVersion.minor)); } void slotInfo() { try { if (!_slot) return; _hardware->setTabEnabled(1, true); cryptoki::SlotInfo slotInfo(_slot->slotinfo()); _slotDescription->setText(qs(slotInfo.slotDescription)); _slotManufacturerID->setText(qs(slotInfo.manufacturerID)); _slotHardwareVersion->setText(QString("%1.%2") .arg(slotInfo.hardwareVersion.major) .arg(slotInfo.hardwareVersion.minor)); _slotFirmwareVersion->setText(QString("%1.%2") .arg(slotInfo.firmwareVersion.major) .arg(slotInfo.firmwareVersion.minor)); _tokenPresent->setEnabled(slotInfo.flags&CKF_TOKEN_PRESENT); _removableDevice->setEnabled(slotInfo.flags&CKF_REMOVABLE_DEVICE); _hwSlot->setEnabled(slotInfo.flags&CKF_HW_SLOT); } catch (...) { _hardware->setTabEnabled(1, false); } } void tokenInfo() { try { if (!_slot) return; _hardware->setTabEnabled(2, true); _hardware->setTabEnabled(3, true); cryptoki::TokenInfo tokenInfo(_slot->tokeninfo()); _tokenLabel->setText(qs(tokenInfo.label)); _tokenManufacturerID->setText(qs(tokenInfo.manufacturerID)); _tokenModel->setText(qs(tokenInfo.model)); _tokenSerialNumber->setText(qs(tokenInfo.serialNumber)); _tokenSessionCount->setText(QString("%2/%1") .arg(qs(cryptoki::string (tokenInfo.maxSessionCount))) .arg(qs(cryptoki::string (tokenInfo.sessionCount)))); _tokenRWSessionCount->setText(QString("%2/%1") .arg(qs(cryptoki::string (tokenInfo.maxRwSessionCount))) .arg(qs(cryptoki::string (tokenInfo.rwSessionCount)))); _tokenPinLen->setText(QString("%2-%1") .arg(tokenInfo.maxPinLen) .arg(tokenInfo.minPinLen)); _tokenPublicMemory->setText(QString("%2/%1") .arg(qs(cryptoki::string (tokenInfo.totalPublicMemory))) .arg(qs(cryptoki::string (tokenInfo.freePublicMemory)))); _tokenPrivateMemory->setText(QString("%2/%1") .arg(qs(cryptoki::string (tokenInfo.totalPrivateMemory))) .arg(qs(cryptoki::string (tokenInfo.freePrivateMemory)))); _tokenHardwareVersion->setText(QString("%1.%2") .arg(tokenInfo.hardwareVersion.major) .arg(tokenInfo.hardwareVersion.minor)); _tokenFirmwareVersion->setText(QString("%1.%2") .arg(tokenInfo.firmwareVersion.major) .arg(tokenInfo.firmwareVersion.minor)); _tokenUTCTime->setText(qs(tokenInfo.utcTime)); _tokenUTCTime->setVisible(tokenInfo.flags&CKF_CLOCK_ON_TOKEN); _rng->setEnabled(tokenInfo.flags&CKF_RNG); _writeProtected->setEnabled(tokenInfo.flags&CKF_WRITE_PROTECTED); _loginRequired->setEnabled(tokenInfo.flags&CKF_LOGIN_REQUIRED); _userPinInitialized->setEnabled (tokenInfo.flags&CKF_USER_PIN_INITIALIZED); _restoreKeyNotNeeded->setEnabled (tokenInfo.flags&CKF_RESTORE_KEY_NOT_NEEDED); _clockOnToken->setEnabled(tokenInfo.flags&CKF_CLOCK_ON_TOKEN); _protectedAuthenticationPath->setEnabled (tokenInfo.flags&CKF_PROTECTED_AUTHENTICATION_PATH); _dualCryptoOperations->setEnabled (tokenInfo.flags&CKF_DUAL_CRYPTO_OPERATIONS); _tokenInitialized->setEnabled(tokenInfo.flags&CKF_TOKEN_INITIALIZED); _secondaryAuthentication->setEnabled (tokenInfo.flags&CKF_SECONDARY_AUTHENTICATION); _userPinCountLow->setEnabled(tokenInfo.flags&CKF_USER_PIN_COUNT_LOW); _userPinFinalTry->setEnabled(tokenInfo.flags&CKF_USER_PIN_FINAL_TRY); _userPinLocked->setEnabled(tokenInfo.flags&CKF_USER_PIN_LOCKED); _userPinToBeChanged->setEnabled (tokenInfo.flags&CKF_USER_PIN_TO_BE_CHANGED); _soPinCountLow->setEnabled(tokenInfo.flags&CKF_SO_PIN_COUNT_LOW); _soPinFinalTry->setEnabled(tokenInfo.flags&CKF_SO_PIN_FINAL_TRY); _soPinLocked->setEnabled(tokenInfo.flags&CKF_SO_PIN_LOCKED); _soPinToBeChanged->setEnabled(tokenInfo.flags&CKF_SO_PIN_TO_BE_CHANGED); } catch (...) { _hardware->setTabEnabled(2, false); _hardware->setTabEnabled(3, false); } } void certificates() { try { _certificates->clear(); if (!_slot) return; _certificates->setEnabled(true); cryptoki::Session session(*_slot); cryptoki::ObjectList certs (session.find(cryptoki::Attribute(CKA_CLASS) .from(CKO_CERTIFICATE))); _progress->steps(certs.size()); for (cryptoki::ObjectList::iterator cert(certs.begin()); cert!=certs.end(); ++cert) { std::string data(cert->attribute(CKA_VALUE).value); QByteArray der(QByteArray(data.data(), data.size())); QSslCertificate c(der, QSsl::Der); addCertificate(cert->attribute(CKA_LABEL).value, crypto::hex(cert->attribute(CKA_ID).value), c); ++*_progress; } } catch (...) { _certificates->setEnabled(false); } } void objects() { try { _objects->clear(); if (!_slot) return; _objects->setEnabled(true); cryptoki::Session session(*_slot); cryptoki::ObjectList objs(session.find()); _progress->steps(objs.size()); for (cryptoki::ObjectList::iterator obj(objs.begin()); obj!=objs.end(); ++obj) { _objects->addTopLevelItem (new QTreeWidgetItem (QStringList() <attribute(CKA_LABEL).value) <attribute(CKA_ID).value)))); ++*_progress; } _objects->resizeColumnToContents(0); _objects->resizeColumnToContents(1); } catch (...) { _objects->setEnabled(false); } } void addCertificate(const std::string& label, const std::string& id, const QSslCertificate& cert) { if (cert.isNull()) return; QTreeWidgetItem* c(new QTreeWidgetItem(QStringList()<setData(0, Qt::UserRole, qs(id)); _certificates->addTopLevelItem(c); c->addChild ((new QTreeWidgetItem (QStringList()<addChild ((new QTreeWidgetItem (QStringList()<addChild ((new QTreeWidgetItem (QStringList()<addChild ((it = new QTreeWidgetItem(QStringList()<=QSslCertificate::Organization; si=(QSslCertificate::SubjectInfo)((int)si-1)) if (!cert.subjectInfo(si).isEmpty()) { it->addChild ((new QTreeWidgetItem(subjectInfo(si) <setExpanded(true); QMultiMap #if QT_VERSION <0x050000 asns(cert.alternateSubjectNames()) #else asns(cert.subjectAlternativeNames()) #endif ; for (QMultiMap::iterator asn(asns.begin()); asn!=asns.end(); ++asn) it->addChild ((new QTreeWidgetItem (QStringList()<addChild ((it = new QTreeWidgetItem(QStringList()<=QSslCertificate::Organization; si=(QSslCertificate::SubjectInfo)((int)si-1)) if (!cert.issuerInfo(si).isEmpty()) it->addChild ((new QTreeWidgetItem(subjectInfo(si) <setExpanded(true); _certificates->resizeColumnToContents(0); _certificates->resizeColumnToContents(1); } private: void deleteCert(QTreeWidgetItem* item) { if (!_slot) return; if (_pin->text().isEmpty()) { QMessageBox::critical(this, tr("PIN required"), tr("Please enter PIN")); return; } if (item->parent()) return deleteCert(item->parent()); QByteArray qid(QByteArray::fromHex(item->data(0, Qt::UserRole) .toByteArray())); std::string id(qid.data(), qid.size()); cryptoki::Session session(*_slot, true); try { session.login(_pin->text().toStdString()); } catch (...) { QMessageBox::critical(this, tr("Login Failed"), tr("Wrong PIN")); return; } cryptoki::ObjectList objs (session.find(cryptoki::AttributeList() <(CKO_CERTIFICATE) <destroy(); } catch (const std::exception& e) { QMessageBox::critical(this, tr("Delete Failed"), tr("Certificate Deletion Failes")); } setup(); } QString alternateName(QSsl::AlternateNameEntryType an) { switch (an) { case QSsl::EmailEntry: return tr("E-Mail"); case QSsl::DnsEntry: return tr("URL"); } return tr("error", "unknown certificate subject alternate name"); } QStringList subjectInfo(QSslCertificate::SubjectInfo si) { QStringList res; switch (si) { case QSslCertificate::Organization: res< _cryptoki; cryptoki::SlotList _slotList; cryptoki::Slot* _slot; Progress* _progress; }; #endif