cleanup of connection management, new major version number 3, use static connection methods; refs #26, refs #28, refs #29
This commit is contained in:
@@ -22,7 +22,7 @@ TST_DIR=
|
||||
DOC_DIR=doc
|
||||
|
||||
m4_define(x_packagename, libpcscxx)
|
||||
m4_define(x_major, 2)
|
||||
m4_define(x_major, 3)
|
||||
m4_define(x_minor, 0)
|
||||
PACKAGENAME=x_packagename
|
||||
MAJOR=x_major
|
||||
@@ -94,7 +94,12 @@ AC_CHECK_PROG(have_dot, dot, yes, no)
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
# libraries
|
||||
PKG_CHECK_MODULES([QT], [QtNetwork])
|
||||
PKG_CHECK_MODULES([QT_GUI], [QtCore QtGui QtWidgets],
|
||||
[AC_DEFINE([HAVE_QTGUI], [1], [Use QtGui])],
|
||||
[PKG_CHECK_MODULES([QT_GUI], [Qt5Core Qt5Gui Qt5Widgets])])
|
||||
PKG_CHECK_MODULES([QT_NETWORK], [QtNetwork],
|
||||
[AC_DEFINE([HAVE_QTNETWORK], [1], [Use QtNetwork])],
|
||||
[PKG_CHECK_MODULES([QT_NETWORK], [Qt5Network])])
|
||||
|
||||
AC_ARG_ENABLE(pedantic,
|
||||
[AS_HELP_STRING([--enable-pedantic],
|
||||
|
@@ -93,7 +93,7 @@ class Commands: public cardos::Commands {
|
||||
}
|
||||
|
||||
void listReader() {
|
||||
_readers = _c.scan();
|
||||
_readers = pcsc::Connection::scan();
|
||||
std::cout<<"Found "<<_readers.size()<<" readers"
|
||||
<<(_readers.size()?":":".")<<std::endl;
|
||||
int i(0);
|
||||
@@ -107,7 +107,7 @@ class Commands: public cardos::Commands {
|
||||
if (_readers.size()<0) return;
|
||||
int num(-1);
|
||||
if (std::cin>>num && num>=0 && num<_readers.size()) {
|
||||
_reader = _c.reader(_readers[num]);
|
||||
_reader = pcsc::Connection::reader(_readers[num]);
|
||||
std::cout<<"Active Reader: "<<_readers[num]<<std::endl;
|
||||
} else throw std::runtime_error("no valid reader selected");
|
||||
}
|
||||
@@ -153,7 +153,6 @@ class Commands: public cardos::Commands {
|
||||
|
||||
private:
|
||||
|
||||
pcsc::Connection _c;
|
||||
pcsc::Connection::Strings _readers;
|
||||
|
||||
cardos::BerValues _ber;
|
||||
|
@@ -21,13 +21,10 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
pcsc::Connection c;
|
||||
pcsc::Connection::Strings readers;
|
||||
|
||||
|
||||
void list() {
|
||||
pcsc::Connection c;
|
||||
pcsc::Connection::Strings readers(c.scan());
|
||||
pcsc::Connection::Strings readers(pcsc::Connection::scan());
|
||||
std::cout<<"Found "<<readers.size()<<" readers"
|
||||
<<(readers.size()?":":".")<<std::endl;
|
||||
int i(0);
|
||||
@@ -39,7 +36,7 @@ void list() {
|
||||
int main(int argc, char** argv) try {
|
||||
int reader(0);
|
||||
std::string pin;
|
||||
std::string path("3f005015");
|
||||
std::string path("3f00");
|
||||
std::string id("8888");
|
||||
std::string data("Hallo Welt");
|
||||
mrw::args::parse(argc, argv, "Write data to card.",
|
||||
@@ -64,27 +61,29 @@ int main(int argc, char** argv) try {
|
||||
mrw::args::decl::param_list()
|
||||
<<mrw::args::param(data, "text"))
|
||||
);
|
||||
pcsc::Connection c;
|
||||
pcsc::Connection::Strings readers(c.scan());
|
||||
pcsc::Connection::Strings readers(pcsc::Connection::scan());
|
||||
if (reader<0 || readers.size()<reader) {
|
||||
std::cerr<<"reader not found: "<<reader<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
cardos::Commands cmd(c.reader(readers[reader]));
|
||||
//cardos::BerValues d(cmd.directory(path));
|
||||
cardos::Commands cmd(pcsc::Connection::reader(readers[reader]));
|
||||
cardos::Dir d(cmd, path);
|
||||
//cardos::BerValues d(cmd.readBerFile(path));
|
||||
//std::cout<<d.print()<<std::endl;
|
||||
//cardos::BerValues d(cmd.directory(path));
|
||||
std::cout<<"-----------------------------------------------------"<<std::endl
|
||||
<<d.print()<<std::endl
|
||||
<<"-----------------------------------------------------"<<std::endl;
|
||||
//std::string res(cmd.readBinary(path));
|
||||
//std::cout<<"HEX:"<<std::endl<<crypto::readable(res)<<std::endl;
|
||||
//std::cout<<"BER:"<<std::endl<<cardos::BerValues(res).print()<<std::endl;
|
||||
if (!pin.size()) {
|
||||
std::cout<<"PIN: ";
|
||||
std::cin>>pin;
|
||||
}
|
||||
if (pin.size()) cmd.logonTransport(pin);
|
||||
cmd.phaseControl();
|
||||
cmd.createBinary(path, id, data);
|
||||
cmd.phaseControl();
|
||||
// if (!pin.size()) {
|
||||
// std::cout<<"PIN: ";
|
||||
// std::cin>>pin;
|
||||
// }
|
||||
// if (pin.size()) cmd.logonTransport(pin);
|
||||
// cmd.phaseControl();
|
||||
// cmd.createBinary(path, id, data);
|
||||
// cmd.phaseControl();
|
||||
return 0;
|
||||
} catch (std::exception& x) {
|
||||
std::cerr<<"ERROR: "<<x.what()<<std::endl;
|
||||
|
@@ -36,13 +36,16 @@ openssl_ssl_demo_SOURCES = openssl-ssl-demo.cxx
|
||||
openssl_engine_demo_SOURCES = openssl-engine-demo.cxx
|
||||
cardos_demo_SOURCES = cardos-demo.cxx
|
||||
suisse_id_demo_SOURCES = suisse-id-demo.cxx
|
||||
create_files_demo_SOURCES = create-files-demo.cxx
|
||||
# moc_suisse-id-demo.cxx
|
||||
suisse_id_demo_CXXFLAGS = ${QT_CFLAGS}
|
||||
suisse_id_demo_LDADD = ${QT_LIBS}
|
||||
suisse_id_demo_CXXFLAGS = ${QT_NETWORK_CFLAGS} -fPIC
|
||||
suisse_id_demo_LDADD = ${QT_NETWORK_LIBS}
|
||||
create_files_demo_SOURCES = create-files-demo.cxx
|
||||
|
||||
%_ui.hxx: %.ui
|
||||
uic -o $@ $<
|
||||
|
||||
moc_%.cxx: %.hxx
|
||||
moc -o $@ $<
|
||||
|
||||
CLEANFILES = moc_suisse-id-demo.cxx
|
||||
CLEANFILES = ${BUILT_SOURCES}
|
||||
MAINTAINERCLEANFILES = makefile.in
|
||||
|
88
doc/examples/moc_cardgui-model.cxx
Normal file
88
doc/examples/moc_cardgui-model.cxx
Normal file
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'cardgui-model.hxx'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.0.2)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "cardgui-model.hxx"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'cardgui-model.hxx' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.0.2. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
struct qt_meta_stringdata_CardGuiModel_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata[14];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
offsetof(qt_meta_stringdata_CardGuiModel_t, stringdata) + ofs \
|
||||
- idx * sizeof(QByteArrayData) \
|
||||
)
|
||||
static const qt_meta_stringdata_CardGuiModel_t qt_meta_stringdata_CardGuiModel = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 12)
|
||||
},
|
||||
"CardGuiModel\0"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_CardGuiModel[] = {
|
||||
|
||||
// content:
|
||||
7, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void CardGuiModel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
const QMetaObject CardGuiModel::staticMetaObject = {
|
||||
{ &QAbstractItemModel::staticMetaObject, qt_meta_stringdata_CardGuiModel.data,
|
||||
qt_meta_data_CardGuiModel, qt_static_metacall, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
const QMetaObject *CardGuiModel::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *CardGuiModel::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return 0;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_CardGuiModel.stringdata))
|
||||
return static_cast<void*>(const_cast< CardGuiModel*>(this));
|
||||
return QAbstractItemModel::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int CardGuiModel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QAbstractItemModel::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
return _id;
|
||||
}
|
||||
QT_END_MOC_NAMESPACE
|
@@ -3,15 +3,14 @@
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char const*const*const argv) try {
|
||||
pcsc::Connection c;
|
||||
pcsc::Connection::Strings reader(c.scan());
|
||||
pcsc::Connection::Strings reader(pcsc::Connection::scan());
|
||||
std::cout<<"Library-Version: "<<pcsc::version()<<std::endl;
|
||||
std::cout<<"Suche PCSC-Reader ..."<<std::endl;
|
||||
if (!reader.size()) std::cout<<"Keine gefunden."<<std::endl;
|
||||
for (pcsc::Connection::Strings::const_iterator it(reader.begin());
|
||||
it!=reader.end(); ++it) {
|
||||
std::cout<<"Reader: "<<*it<<std::endl;
|
||||
pcsc::Connection::Reader::Status s(c.reader(*it)->status());
|
||||
pcsc::Connection::Reader::Status s(pcsc::Connection::reader(*it)->status());
|
||||
std::cout<<"Status = "<<s.state<<std::endl;
|
||||
std::cout<<"ATR = "<<crypto::hex(s.atr)<<std::endl;
|
||||
}
|
||||
|
122
src/cardgui-model.hxx
Normal file
122
src/cardgui-model.hxx
Normal file
@@ -0,0 +1,122 @@
|
||||
/*! @file
|
||||
|
||||
@id $Id$
|
||||
*/
|
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#ifndef CARDGUI_MODEL_HXX
|
||||
#define CARDGUI_MODEL_HXX
|
||||
|
||||
#include <cardos.hxx>
|
||||
|
||||
#include <QtCore/QAbstractItemModel>
|
||||
#include <QtGui/QFont>
|
||||
|
||||
class CardGuiModel: public QAbstractItemModel {
|
||||
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
|
||||
CardGuiModel(cardos::Commands& cmd, const std::string& path):
|
||||
_rootItem(cmd, path) {
|
||||
}
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid()) return QVariant();
|
||||
cardos::Object* o(static_cast<cardos::Object*>(index.internalPointer()));
|
||||
switch (role) {
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignTop;
|
||||
case Qt::FontRole:
|
||||
if (index.column() == 2) {
|
||||
QFont f("Monospaced");
|
||||
f.setStyleHint(QFont::TypeWriter);
|
||||
return f;
|
||||
} else return QVariant();
|
||||
case Qt::DisplayRole:
|
||||
switch (index.column()) {
|
||||
case 0: return QString::fromStdString(o->logicalName());
|
||||
case 1: return QString::fromStdString(o->name());
|
||||
case 3: return QString::fromStdString(o->contentInfo());
|
||||
case 2: if (o->content().size())
|
||||
return QString::fromStdString(crypto::readable(o->content()));
|
||||
default: return QVariant();
|
||||
}
|
||||
default: return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const {
|
||||
if (!index.isValid()) return 0;
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const {
|
||||
if (orientation!=Qt::Horizontal || role!=Qt::DisplayRole)
|
||||
return QVariant();
|
||||
switch (section) {
|
||||
case 0: return "Object";
|
||||
case 1: return "ID";
|
||||
case 3: return "Logical Content";
|
||||
case 2: return "Binary Content";
|
||||
default: return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const {
|
||||
if (!hasIndex(row, column, parent)) return QModelIndex();
|
||||
const cardos::Object* parentItem(0);
|
||||
if (!parent.isValid())
|
||||
parentItem = &_rootItem;
|
||||
else
|
||||
parentItem = static_cast<cardos::Object*>(parent.internalPointer());
|
||||
if (row<parentItem->size())
|
||||
return
|
||||
createIndex(row, column, &(*parentItem->children().at(row)));
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
std::pair<const cardos::Object*, int> scan(const cardos::Object& o,
|
||||
const cardos::Object* c) const {
|
||||
int i(0);
|
||||
for (cardos::Object::Children::const_iterator it(o.children().begin());
|
||||
it!=o.children().end(); ++it, ++i) {
|
||||
if (it->get()==c) return std::make_pair(&o, i);
|
||||
std::pair<const cardos::Object*, int> res(scan(**it, c));
|
||||
if (res.first) return res;
|
||||
}
|
||||
return std::make_pair((const cardos::Object*)0, 0);
|
||||
}
|
||||
|
||||
QModelIndex parent(const QModelIndex &index) const {
|
||||
if (!index.isValid()) return QModelIndex();
|
||||
cardos::Object* childItem
|
||||
(static_cast<cardos::Object*>(index.internalPointer()));
|
||||
if (childItem==&_rootItem) return QModelIndex();
|
||||
std::pair<const cardos::Object*, int>
|
||||
parentItem(scan(_rootItem, childItem));
|
||||
if (!parentItem.first) return QModelIndex();
|
||||
return createIndex(parentItem.second, 0,
|
||||
const_cast<cardos::Object*>(parentItem.first));
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const {
|
||||
if (parent.isValid() && parent.internalPointer())
|
||||
return static_cast<cardos::Object*>(parent.internalPointer())->size();
|
||||
else
|
||||
return _rootItem.size();
|
||||
}
|
||||
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const {
|
||||
return 4;
|
||||
}
|
||||
|
||||
protected:
|
||||
cardos::Dir _rootItem;
|
||||
};
|
||||
|
||||
#endif
|
20
src/cardgui.cxx
Normal file
20
src/cardgui.cxx
Normal file
@@ -0,0 +1,20 @@
|
||||
/*! @file
|
||||
|
||||
@id $Id$
|
||||
*/
|
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#include <cardgui.hxx>
|
||||
|
||||
#include <mrw/vector.hxx>
|
||||
#include <mrw/args.hxx>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
QApplication app(argc, argv);
|
||||
CardGui win;
|
||||
win.show();
|
||||
return app.exec();
|
||||
}
|
108
src/cardgui.hxx
Normal file
108
src/cardgui.hxx
Normal file
@@ -0,0 +1,108 @@
|
||||
/*! @file
|
||||
|
||||
@id $Id$
|
||||
*/
|
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#ifndef CARDGUI_HXX
|
||||
#define CARDGUI_HXX
|
||||
|
||||
#include <cardgui-model.hxx>
|
||||
#include <cardgui_ui.hxx>
|
||||
#include <password.hxx>
|
||||
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
class CardGui: public QMainWindow, protected Ui_CardGui {
|
||||
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
|
||||
CardGui(QWidget* p=0):
|
||||
QMainWindow(p), _pwd(this) {
|
||||
setupUi(this);
|
||||
on__rescan_clicked();
|
||||
}
|
||||
|
||||
void resizeEvent(QResizeEvent* event) {
|
||||
QMainWindow::resizeEvent(event);
|
||||
if (_tree->model())
|
||||
for (int i = 0; i < _tree->model()->columnCount(); ++i)
|
||||
_tree->resizeColumnToContents(i);
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
void on__rescan_clicked(bool=true) {
|
||||
static bool inRescan(false);
|
||||
if (inRescan) return;
|
||||
inRescan = true;
|
||||
try {
|
||||
delete _tree->model();
|
||||
_tree->setModel(0);
|
||||
_card->clear();
|
||||
pcsc::Connection::Strings readers(pcsc::Connection::scan());
|
||||
for (pcsc::Connection::Strings::iterator r(readers.begin());
|
||||
r!=readers.end(); ++r)
|
||||
_card->addItem(QString::fromStdString(*r));
|
||||
} catch (...) {
|
||||
}
|
||||
inRescan = false;
|
||||
}
|
||||
|
||||
void on__card_currentIndexChanged(int) {
|
||||
on__reload_clicked();
|
||||
}
|
||||
|
||||
void on__reload_clicked(bool=true) {
|
||||
try {
|
||||
delete _tree->model();
|
||||
_tree->setModel(0);
|
||||
cardos::Commands cmd(pcsc::Connection::reader
|
||||
(_card->currentText().toStdString()));
|
||||
_tree->setModel(new CardGuiModel(cmd, "3f00"));
|
||||
} catch (...) {
|
||||
on__rescan_clicked();
|
||||
}
|
||||
}
|
||||
|
||||
void on__actionRestartPCSCD_triggered() {
|
||||
delete _tree->model();
|
||||
_tree->setModel(0);
|
||||
if (_pwd.exec()) {
|
||||
_p.start("sudo -S service pcscd restart");
|
||||
_p.write((_pwd.password()+"\n").toUtf8());
|
||||
_p.closeWriteChannel();
|
||||
if (!_p.waitForFinished())
|
||||
QMessageBox::warning(this, tr("Restarting PCSC Daemon failed"),
|
||||
tr("<html><p>Restarting PCSC daemon"
|
||||
" failed with message:</p>"
|
||||
"\n<pre>%1</pre></html>")
|
||||
.arg(QString::fromUtf8
|
||||
(_p.readAll()+"\n"+
|
||||
_p.readAllStandardOutput()+"\n"+
|
||||
_p.readAllStandardError())));
|
||||
else
|
||||
QMessageBox::information(this, tr("Restarted PCSC Daemon"),
|
||||
tr("<html><p>Restarted PCSC daemon"
|
||||
" with message:</p>"
|
||||
"\n<pre>%1</pre></html>")
|
||||
.arg(QString::fromUtf8
|
||||
(_p.readAll()+"\n"+
|
||||
_p.readAllStandardOutput()+"\n"+
|
||||
_p.readAllStandardError())));
|
||||
}
|
||||
on__reload_clicked();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Password _pwd;
|
||||
QProcess _p;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
103
src/cardgui.ui
Normal file
103
src/cardgui.ui
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CardGui</class>
|
||||
<widget class="QMainWindow" name="CardGui">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1349</width>
|
||||
<height>878</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>CardOS V4.4</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTreeView" name="_tree">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="_rescan">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>rescan for cards</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="_card"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="_reload">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>reload card info</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1349</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="_actionRestartPCSCD"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="_actionRestartPCSCD">
|
||||
<property name="text">
|
||||
<string>Restart PCSCD</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
229
src/cardos.hxx
229
src/cardos.hxx
@@ -124,6 +124,8 @@ namespace cardos {
|
||||
//@}
|
||||
|
||||
//============================================================================
|
||||
/// @addtogroup cardoslib
|
||||
//@{
|
||||
|
||||
class BerValue {
|
||||
public:
|
||||
@@ -262,6 +264,10 @@ namespace cardos {
|
||||
return _value;
|
||||
}
|
||||
|
||||
std::string hex() {
|
||||
return crypto::hex(_value);
|
||||
}
|
||||
|
||||
unsigned long ulong() {
|
||||
return crypto::ulongFromBinary(_value);
|
||||
}
|
||||
@@ -346,6 +352,7 @@ namespace cardos {
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
/// Store a sequence of BerValue
|
||||
class BerValues: public std::vector<BerValue> {
|
||||
public:
|
||||
@@ -401,12 +408,7 @@ namespace cardos {
|
||||
}
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
//============================================================================
|
||||
/// @addtogroup cardoslib
|
||||
//@{
|
||||
|
||||
/// Implements CardOS V4.4 commands.
|
||||
/** Directly sends CardOS V4.4 commands to a smart card using APDUs. */
|
||||
class Commands {
|
||||
@@ -422,12 +424,12 @@ namespace cardos {
|
||||
Commands() {}
|
||||
|
||||
/// Initialize with given smart card reader.
|
||||
Commands(mrw::Shared<pcsc::Connection::Reader> reader):
|
||||
Commands(pcsc::shared_ptr<pcsc::Connection::Reader>::t reader):
|
||||
_reader(reader) {
|
||||
}
|
||||
|
||||
/// Set smart card reader.
|
||||
void reader(mrw::Shared<pcsc::Connection::Reader> reader) {
|
||||
void reader(pcsc::shared_ptr<pcsc::Connection::Reader>::t reader) {
|
||||
_reader = reader;
|
||||
}
|
||||
|
||||
@@ -941,10 +943,13 @@ namespace cardos {
|
||||
};
|
||||
|
||||
//! Read a record oriented file
|
||||
std::string readRecord(unsigned char record = 0,
|
||||
std::string readRecord(const std::string& path = std::string(),
|
||||
unsigned char record = 0,
|
||||
unsigned char sfi = 0,
|
||||
ReadRecordMode mode = ABSOLUTE_RECORD) {
|
||||
CRYPTOLOG("log");
|
||||
pcsc::Connection::Reader::Transaction lock(_reader);
|
||||
if (path.size()) select(path);
|
||||
return check(send(0x00, 0xB2, record, (sfi&0xF8)|mode));
|
||||
}
|
||||
|
||||
@@ -1529,9 +1534,215 @@ namespace cardos {
|
||||
|
||||
protected:
|
||||
|
||||
mrw::Shared<pcsc::Connection::Reader> _reader;
|
||||
pcsc::shared_ptr<pcsc::Connection::Reader>::t _reader;
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
/// Represents a CardOS Filesystem Object
|
||||
class Object {
|
||||
public:
|
||||
typedef pcsc::shared_ptr<Object>::t Child;
|
||||
typedef std::vector<Child> Children;
|
||||
public:
|
||||
Object(const std::string& path): _path(path) {}
|
||||
virtual ~Object() {}
|
||||
virtual const std::string& path() const {
|
||||
return _path;
|
||||
}
|
||||
virtual std::string name() const {
|
||||
return _path;
|
||||
}
|
||||
virtual std::string logicalName() const {
|
||||
switch (crypto::ulongFromBinary(crypto::hexToBin(name()))) {
|
||||
case 0x3f00: return "Masterfile";
|
||||
case 0x5649: return "Version Info";
|
||||
case 0x2F02: return "Global Definition Object";
|
||||
case 0x5015: return "PKCS#15";
|
||||
case 0x5032: return "Token Info";
|
||||
case 0x5600: return "File System Version";
|
||||
case 0x4404: return "Certificate Definition";
|
||||
case 0x4304: return "Certificates";
|
||||
case 0x4401: return "Public Key Definition";
|
||||
case 0x5075: return "Public Keys";
|
||||
case 0x4408: return "Authentication Object Definition";
|
||||
case 0x5031: return "Object Definition";
|
||||
case 0x4407: return "Data Object Definition";
|
||||
case 0x4444: return "Data Objects";
|
||||
case 0x4400: return "Private Key Definition";
|
||||
case 0x5072: return "Private Keys";
|
||||
case 0x1fff: return "SigG";
|
||||
case 0xfe15: return "Transport Protection State";
|
||||
case 0xc100: return "Public Key";
|
||||
default:
|
||||
switch (crypto::ulongFromBinary(crypto::hexToBin(name()))&0xff00) {
|
||||
case 0x4b00: return "Private Key "+name().substr(2);
|
||||
case 0x5500: return "Public Key "+name().substr(2);
|
||||
default: return type();
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual const std::string& content() const {
|
||||
const static std::string c;
|
||||
return c;
|
||||
}
|
||||
virtual const std::string& contentInfo() const {
|
||||
const static std::string c;
|
||||
return c;
|
||||
}
|
||||
virtual std::string print(int indent=0, int=4) const {
|
||||
return std::string(indent, ' ')+type()+": "+name();
|
||||
}
|
||||
virtual bool isFile() const {
|
||||
return false;
|
||||
}
|
||||
virtual bool isDir() const {
|
||||
return false;
|
||||
}
|
||||
virtual bool hasChildren() const {
|
||||
return _children.size();
|
||||
}
|
||||
virtual Children::size_type size() const {
|
||||
return _children.size();
|
||||
}
|
||||
virtual const Children& children() const {
|
||||
return _children;
|
||||
}
|
||||
virtual std::string type() const = 0;
|
||||
protected:
|
||||
std::string _path;
|
||||
Children _children;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
/// Represents a File on a Smart Card
|
||||
class File: public Object {
|
||||
public:
|
||||
File(Commands& cmd, const std::string& path, const std::string& file):
|
||||
Object(path), _file(file) {
|
||||
CRYPTOLOG("new file "<<file<<" at "<<path);
|
||||
try {
|
||||
_content = cmd.readBinary(path+file);
|
||||
try {
|
||||
_contentInfo = cardos::BerValues(_content).print();
|
||||
} catch (...) {
|
||||
}
|
||||
} catch (std::exception& x) {
|
||||
_contentInfo = x.what();
|
||||
}
|
||||
}
|
||||
File(const std::string& path, const std::string& file):
|
||||
Object(path), _file(file) {
|
||||
CRYPTOLOG("new file "<<file<<" at "<<path);
|
||||
}
|
||||
std::string name() const {
|
||||
return _file;
|
||||
}
|
||||
const std::string& content() const {
|
||||
return _content;
|
||||
}
|
||||
const std::string& contentInfo() const {
|
||||
return _contentInfo;
|
||||
}
|
||||
bool isFile() const {
|
||||
return true;
|
||||
}
|
||||
std::string type() const {
|
||||
return "File";
|
||||
}
|
||||
protected:
|
||||
std::string _file;
|
||||
std::string _content;
|
||||
std::string _contentInfo;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
/// Represents a Link on a Smart Card
|
||||
class Link: public File {
|
||||
public:
|
||||
Link(Commands& cmd, const std::string& path, const std::string& file):
|
||||
File(cmd, path, file) {
|
||||
CRYPTOLOG("new link "<<file<<" at "<<path);
|
||||
}
|
||||
std::string type() const {
|
||||
return "Link";
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
/// Represents a Counter on a Smart Card
|
||||
class Counter: public File {
|
||||
public:
|
||||
Counter(Commands& cmd, const std::string& path, const std::string& file):
|
||||
File(path, file) {
|
||||
CRYPTOLOG("new counter "<<file<<" at "<<path);
|
||||
try {
|
||||
_content = cmd.readRecord(path+file);
|
||||
std::stringstream s;
|
||||
s<<crypto::ulongFromBinary(_content);
|
||||
_contentInfo = s.str();
|
||||
} catch (std::exception& x) {
|
||||
_contentInfo = x.what();
|
||||
}
|
||||
}
|
||||
std::string type() const {
|
||||
return "Counter";
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
/// Represents a Directory on a Smart Card
|
||||
class Dir: public Object {
|
||||
public:
|
||||
Dir(Commands& cmd, const std::string& path): Object(path) {
|
||||
CRYPTOLOG("new directory path="<<path);
|
||||
setup(cmd);
|
||||
}
|
||||
std::string name() const {
|
||||
return _path.substr(_path.size()-4);
|
||||
}
|
||||
bool isDir() const {
|
||||
return true;
|
||||
}
|
||||
std::string print(int indent=0, int step=4) const {
|
||||
std::string res(std::string(indent, ' ')+type()+": "+name());
|
||||
for (Children::const_iterator it(_children.begin());
|
||||
it!=_children.end(); ++it)
|
||||
res+='\n'+(*it)->print(indent+step, step);
|
||||
return res;
|
||||
}
|
||||
std::string type() const {
|
||||
return "Directory";
|
||||
}
|
||||
protected:
|
||||
void setup(Commands& cmd) {
|
||||
_children.clear();
|
||||
BerValues i(cmd.directory(_path));
|
||||
CRYPTOLOG("Found Structure: "<<i.print());
|
||||
for (BerValues::iterator it(i.begin()); it!=i.end(); ++it) {
|
||||
CRYPTOLOG(" -> Value: "<<it->print());
|
||||
if (it->size()<2) continue; // empty dir
|
||||
switch ((*it)[0].ulong()) {
|
||||
case 0x38:
|
||||
_children.push_back(Child(new Dir(cmd, _path+(*it)[1].hex())));
|
||||
break;
|
||||
case 0x01:
|
||||
_children.push_back(Child(new File(cmd, _path, (*it)[1].hex())));
|
||||
break;
|
||||
case 0x05:
|
||||
_children.push_back(Child(new Link(cmd, _path, (*it)[1].hex())));
|
||||
break;
|
||||
case 0x06:
|
||||
_children.push_back(Child(new Counter(cmd, _path, (*it)[1].hex())));
|
||||
break;
|
||||
default: // unknown
|
||||
throw runtime_error("unknown object: "+it->print());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
}
|
||||
|
@@ -36,15 +36,19 @@
|
||||
# else
|
||||
# include <iostream>
|
||||
# define CRYPTOLOG(X) { \
|
||||
std::string file(__FILE__); \
|
||||
std::string line(CRYPTOLOG_QUOTE(__LINE__)); \
|
||||
std::string::size_type pos(file.rfind('/')); \
|
||||
if (pos!=std::string::npos) file=file.substr(pos+1); \
|
||||
std::string spc1(18>file.size()?std::string(18-file.size(), ' ') \
|
||||
std::string __C_FILE__(__FILE__); \
|
||||
std::string __C_LINE__(CRYPTOLOG_QUOTE(__LINE__)); \
|
||||
std::string::size_type __LOC_POS__(__C_FILE__.rfind('/')); \
|
||||
if (__LOC_POS__!=std::string::npos) \
|
||||
__C_FILE__=__C_FILE__.substr(__LOC_POS__+1); \
|
||||
std::string __LOC_SPC1__(18>__C_FILE__.size() \
|
||||
?std::string(18-__C_FILE__.size(), ' ') \
|
||||
:std::string()); \
|
||||
std::string spc2(4>line.size()?std::string(4-line.size(), ' ') \
|
||||
std::string __LOC_SPC2__(4>__C_LINE__.size() \
|
||||
?std::string(4-__C_LINE__.size(), ' ') \
|
||||
:std::string()); \
|
||||
std::clog<<"CRYPTO: "<<spc1<<file<<':'<<spc2<<line<<" -- "<<X \
|
||||
std::clog<<"CRYPTO: "<<__LOC_SPC1__<<__C_FILE__ \
|
||||
<<':'<<__LOC_SPC2__<<__C_LINE__<<" -- "<<X \
|
||||
<<CRYPTOLOG_END; \
|
||||
}
|
||||
# endif
|
||||
@@ -58,15 +62,19 @@
|
||||
# else
|
||||
# include <iostream>
|
||||
# define CRYPTOLOG_VERBOSE(X) { \
|
||||
std::string file(__FILE__); \
|
||||
std::string line(CRYPTOLOG_QUOTE(__LINE__)); \
|
||||
std::string::size_type pos(file.rfind('/')); \
|
||||
if (pos!=std::string::npos) file=file.substr(pos+1); \
|
||||
std::string spc1(18>file.size()?std::string(18-file.size(), ' ') \
|
||||
std::string __C_FILE__(__FILE__); \
|
||||
std::string __C_LINE__(CRYPTOLOG_QUOTE(__LINE__)); \
|
||||
std::string::size_type __LOC_POS__(__C_FILE__.rfind('/')); \
|
||||
if (__LOC_POS__!=std::string::npos) \
|
||||
__C_FILE__=__C_FILE__.substr(__LOC_POS__+1); \
|
||||
std::string __LOC_SPC1__(18>__C_FILE__.size() \
|
||||
?std::string(18-__C_FILE__.size(), ' ') \
|
||||
:std::string()); \
|
||||
std::string spc2(4>line.size()?std::string(4-line.size(), ' ') \
|
||||
std::string __LOC_SPC2__(4>__C_LINE__.size() \
|
||||
?std::string(4-__C_LINE__.size(), ' ') \
|
||||
:std::string()); \
|
||||
std::clog<<"CRYPTO: "<<spc1<<file<<':'<<spc2<<line<<" -- "<<X \
|
||||
std::clog<<"CRYPTO: "<<__LOC_SPC1__<<__C_FILE__<<':' \
|
||||
<<__LOC_SPC2__<<__C_LINE__<<" -- "<<X \
|
||||
<<CRYPTOLOG_END; \
|
||||
}
|
||||
# endif
|
||||
@@ -168,7 +176,7 @@ namespace crypto {
|
||||
inline std::string toBinary(unsigned long data, int bytes=2) {
|
||||
std::string res(0, bytes);
|
||||
for (int i(0); i<bytes; ++i) {
|
||||
res[bytes-i-1] = data&0xff;
|
||||
res[i] = data&0xff;
|
||||
data>>=8;
|
||||
}
|
||||
return res;
|
||||
@@ -177,9 +185,8 @@ namespace crypto {
|
||||
/// convert integer from binary of given size
|
||||
inline unsigned long ulongFromBinary(const std::string& data) {
|
||||
unsigned long res(0);
|
||||
for (std::string::const_reverse_iterator it(data.rbegin());
|
||||
it!=data.rend(); ++it)
|
||||
(res<<=8)+=(unsigned)*it;
|
||||
for (std::string::const_iterator it(data.begin()); it!=data.end(); ++it)
|
||||
(res<<=8)+=(unsigned long)(unsigned char)*it;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,8 @@ include_HEADERS = pcsc.hxx cryptoki.hxx openssl.hxx cryptaux.hxx \
|
||||
openssl-engine.hxx suisseid.hxx cardos.hxx
|
||||
#certimport.hxx
|
||||
|
||||
noinst_HEADERS = cardgui.hxx cardgui-model.hxx
|
||||
|
||||
if !MINGW32
|
||||
if MAC
|
||||
AM_CPPFLAGS += -I/opt/local/include -I/Library/OpenSC/include
|
||||
@@ -29,15 +31,15 @@ pkgconfig2_DATA = $(pkgconfig_DATA)
|
||||
|
||||
EXTRA_DIST = $(pkgconfig_DATA).in ${top_srcdir}/src/*.doc
|
||||
|
||||
bin_PROGRAMS = cardgui
|
||||
|
||||
lib_LTLIBRARIES = libpcscxx.la
|
||||
|
||||
libpcscxx_la_SOURCES = cryptoki.cxx cryptoki.hxx pcsc.cxx version.cxx \
|
||||
openssl-engine.cxx
|
||||
#moc_certimport.cxx
|
||||
libpcscxx_la_LDFLAGS = -version-info ${LIB_VERSION}
|
||||
#libpcscxx_la_CXXFLAGS = ${QT_CFLAGS}
|
||||
libpcscxx_la_LIBADD = -lssl -lcrypto
|
||||
# ${QT_LIBS}
|
||||
if MINGW32
|
||||
libpcscxx_la_LIBADD += -lgdi32 -lws2_32
|
||||
else
|
||||
@@ -47,15 +49,25 @@ libpcscxx_la_LIBADD += -lpcsclite
|
||||
endif
|
||||
endif
|
||||
|
||||
cardgui_SOURCES = cardgui.cxx
|
||||
nodist_cardgui_SOURCES = cardgui_ui.hxx password_ui.hxx \
|
||||
moc_cardgui.cxx moc_password.cxx moc_cardgui-model.cxx
|
||||
BUILT_SOURCES = ${nodist_cardgui_SOURCES}
|
||||
cardgui_CXXFLAGS = ${QT_GUI_CFLAGS} -fPIC
|
||||
cardgui_LDADD = ${QT_GUI_LIBS} libpcscxx.la ${libpcscxx_la_LIBADD}
|
||||
|
||||
noinst_PROGRAMS = versiontest
|
||||
versiontest_SOURCES = versiontest.cxx
|
||||
|
||||
%_ui.hxx: %.ui
|
||||
uic -o $@ $<
|
||||
|
||||
moc_%.cxx: %.hxx
|
||||
moc -o $@ $<
|
||||
|
||||
clean-local:
|
||||
-rm -r ${QMAKE_TARGET}.app
|
||||
|
||||
CLEANFILES = ${MOC_FILES}
|
||||
CLEANFILES = ${MOC_FILES} ${BUILT_SOURCES}
|
||||
DISTCLEANFILES = $(pkgconfig_DATA)
|
||||
MAINTAINERCLEANFILES = makefile.in
|
||||
|
@@ -5,6 +5,8 @@
|
||||
This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit (http://www.openssl.org/)
|
||||
|
||||
This product includes cryptographic software written by
|
||||
Eric Young (eay@cryptsoft.com)
|
||||
*/
|
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
@@ -5,6 +5,8 @@
|
||||
This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit (http://www.openssl.org/)
|
||||
|
||||
This product includes cryptographic software written by
|
||||
Eric Young (eay@cryptsoft.com)
|
||||
*/
|
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
@@ -5,6 +5,8 @@
|
||||
This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit (http://www.openssl.org/)
|
||||
|
||||
This product includes cryptographic software written by
|
||||
Eric Young (eay@cryptsoft.com)
|
||||
*/
|
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
30
src/password.hxx
Normal file
30
src/password.hxx
Normal file
@@ -0,0 +1,30 @@
|
||||
/*! @file
|
||||
|
||||
@id $Id$
|
||||
*/
|
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#ifndef PASSWORD_HXX
|
||||
#define PASSWORD_HXX
|
||||
|
||||
#include <password_ui.hxx>
|
||||
|
||||
class Password: public QDialog, protected Ui_Password {
|
||||
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
|
||||
Password(QWidget* p=0):
|
||||
QDialog(p) {
|
||||
setupUi(this);
|
||||
}
|
||||
|
||||
QString password() {
|
||||
return _pwd->text();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
101
src/password.ui
Normal file
101
src/password.ui
Normal file
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Password</class>
|
||||
<widget class="QDialog" name="Password">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>360</width>
|
||||
<height>152</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Your password is required to restart PCSC daemon. Please anter your user password and make sure, you are allowed to sudo on this host.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Password:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="_pwd">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Password</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Password</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
285
src/pcsc.hxx
285
src/pcsc.hxx
@@ -12,7 +12,6 @@
|
||||
|
||||
#include <cryptaux.hxx>
|
||||
|
||||
#include <mrw/shared.hxx>
|
||||
#include <string>
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -205,7 +204,8 @@ namespace pcsc {
|
||||
/*! @note Please note that the Reader is required in the
|
||||
destructor und must therefore live longer than the
|
||||
Transaction instance. */
|
||||
Transaction(mrw::Shared<Reader> r): _reader(r), _running(true) {
|
||||
Transaction(shared_ptr<Reader>::t r):
|
||||
_reader(r), _running(true) {
|
||||
CRYPTOLOG("log");
|
||||
_reader->beginTransaction();
|
||||
}
|
||||
@@ -222,7 +222,7 @@ namespace pcsc {
|
||||
_running = false;
|
||||
}
|
||||
private:
|
||||
mrw::Shared<Reader> _reader;
|
||||
shared_ptr<Reader>::t _reader;
|
||||
bool _running;
|
||||
};
|
||||
|
||||
@@ -424,7 +424,7 @@ namespace pcsc {
|
||||
friend class Connection;
|
||||
|
||||
//! Establishes a connection to the given named cardreader
|
||||
Reader(const std::string& nm, const Connection& c,
|
||||
Reader(const std::string& nm, shared_ptr<Connection>::t c,
|
||||
DWORD mode=SCARD_SHARE_SHARED,
|
||||
DWORD protocol=SCARD_PROTOCOL_T1):
|
||||
name(nm), _connection(c) {
|
||||
@@ -441,7 +441,7 @@ namespace pcsc {
|
||||
//...........................................................variables
|
||||
private:
|
||||
|
||||
mrw::Shared<Connection> _connection;
|
||||
shared_ptr<Connection>::t _connection;
|
||||
SCARDHANDLE _id;
|
||||
DWORD _state;
|
||||
DWORD _protocol;
|
||||
@@ -461,6 +461,71 @@ namespace pcsc {
|
||||
//................................................................methods
|
||||
public:
|
||||
|
||||
//! Closes the connection (releases the smartcard context)
|
||||
~Connection() {
|
||||
CRYPTOLOG("Close Connection id="<<_id);
|
||||
_state = SCardReleaseContext(_id);
|
||||
if (!std::uncaught_exception()) check("smartcard release context");
|
||||
}
|
||||
|
||||
//! Scans for available readers from a specified list of groups.
|
||||
/*! Defaults to all groups. */
|
||||
static Strings scan(const Strings& groups = Strings(),
|
||||
Scope s=USER, bool exceptions=true) {
|
||||
Connection c(s, exceptions);
|
||||
Strings res;
|
||||
std::string grp(c.join(groups));
|
||||
DWORD num(0);
|
||||
if (!c.check(SCardListReaders(c._id,
|
||||
groups.size()?strconv(grp).data():0, 0,
|
||||
&num),
|
||||
"smartcard get size of readers of groups "+grp))
|
||||
return res;
|
||||
CRYPTOLOG("size of readers: "<<num);
|
||||
if (!num) return res;
|
||||
std::auto_ptr<char_t> nm(new char_t[num]);
|
||||
if (!c.check(SCardListReaders(c._id,
|
||||
groups.size()?strconv(grp).data():0,
|
||||
nm.get(), &num),
|
||||
"smartcard list reader names of groups "+grp))
|
||||
return res;
|
||||
CRYPTOLOG("got all readers, size is "<<num);
|
||||
if (!num) return res;
|
||||
CRYPTOLOG("list of readers: "
|
||||
<<crypto::readable(std::string(nm.get(), num-1)));
|
||||
return res = c.split(strconv(string(nm.get(), num-1)));
|
||||
}
|
||||
|
||||
//! Find all readers with a given ATR.
|
||||
/*! @param atr full or partial ATR to match to the reader's ATR
|
||||
@returns list of readers that contain @c atr in their ATR */
|
||||
static Strings getReadersWithAtr(const std::string& atr,
|
||||
Scope s=USER, bool exceptions=true) {
|
||||
Connection c(s, exceptions);
|
||||
Strings res;
|
||||
pcsc::Connection::Strings readers(c.scan());
|
||||
for (pcsc::Connection::Strings::const_iterator it(readers.begin());
|
||||
it!=readers.end(); ++it)
|
||||
if (crypto::hex(c.reader(*it)->status().atr).find(atr)!=string::npos)
|
||||
res.push_back(*it);
|
||||
return res;
|
||||
}
|
||||
|
||||
//! Get a reader, open a connection if not already open.
|
||||
/*! First use scan() to get a list of readers, then open a
|
||||
connection to the reader, then access it. */
|
||||
static shared_ptr<Reader>::t reader(const std::string& name,
|
||||
Scope s=USER, bool exceptions=true) {
|
||||
CRYPTOLOG("get reader: "<<name);
|
||||
return shared_ptr<Reader>::t
|
||||
(new Reader(name,
|
||||
shared_ptr<Connection>::t
|
||||
(new Connection(s, exceptions))));
|
||||
}
|
||||
|
||||
//................................................................methods
|
||||
private:
|
||||
|
||||
//! Opens a connection (establishes a smartcard context)
|
||||
/*! The errorhandling is defined with the @c exceptions flag:
|
||||
|
||||
@@ -490,131 +555,14 @@ namespace pcsc {
|
||||
- @c false: no exceptions, check your instance after each
|
||||
operation */
|
||||
Connection(Scope s=USER, bool exceptions=true):
|
||||
_connectionlifetime(connectionlifetime(s, exceptions)) {
|
||||
++connectionlifetimecounter();
|
||||
CRYPTOLOG("Connection Counter is now: "<<connectionlifetimecounter());
|
||||
_exc(exceptions), _id(0), _s(s),
|
||||
_state(SCardEstablishContext(s, 0, 0, &_id)) {
|
||||
CRYPTOLOG("Open Connection id="<<_id);
|
||||
check("establish smartcard context");
|
||||
}
|
||||
|
||||
Connection(const Connection& o) {
|
||||
++connectionlifetimecounter();
|
||||
*this = o;
|
||||
}
|
||||
|
||||
//! Closes the connection (releases the smartcard context)
|
||||
~Connection() {
|
||||
// connection is closed, when _connectionlifetime is destructed
|
||||
if (--connectionlifetimecounter()==0) {
|
||||
CRYPTOLOG("Delete Connection");
|
||||
delete connectionlifetime();
|
||||
connectionlifetime()=0;
|
||||
}
|
||||
CRYPTOLOG("Connection Counter is now: "<<connectionlifetimecounter());
|
||||
}
|
||||
|
||||
//! Scans for available readers from a specified list of groups.
|
||||
/*! Defaults to all groups. */
|
||||
Strings scan(const Strings& groups = Strings()) {
|
||||
Strings res;
|
||||
std::string grp(join(groups));
|
||||
DWORD num(0);
|
||||
if (!check(SCardListReaders(_connectionlifetime->id(),
|
||||
groups.size()?strconv(grp).data():0, 0,
|
||||
&num),
|
||||
"smartcard get size of readers of groups "+grp))
|
||||
return res;
|
||||
CRYPTOLOG("size of readers: "<<num);
|
||||
if (!num) return res;
|
||||
std::auto_ptr<char_t> nm(new char_t[num]);
|
||||
if (!check(SCardListReaders(_connectionlifetime->id(),
|
||||
groups.size()?strconv(grp).data():0,
|
||||
nm.get(), &num),
|
||||
"smartcard list reader names of groups "+grp))
|
||||
return res;
|
||||
CRYPTOLOG("got all readers, size is "<<num);
|
||||
if (!num) return res;
|
||||
CRYPTOLOG("list of readers: "
|
||||
<<crypto::readable(std::string(nm.get(), num-1)));
|
||||
return res = split(strconv(string(nm.get(), num-1)));
|
||||
}
|
||||
|
||||
//! Get a reader, open a connection if not already open.
|
||||
/*! First use scan() to get a list of readers, then open a
|
||||
connection to the reader, then access it. */
|
||||
mrw::Shared<Reader> reader(const std::string& name) {
|
||||
return _connectionlifetime->reader(name, this);
|
||||
}
|
||||
|
||||
// //! Close connection of a named reader.
|
||||
// /*! If you access the same reader through raeder() later, the
|
||||
// connection will be reestablished. */
|
||||
// void close(const std::string& s) {
|
||||
|
||||
// }
|
||||
|
||||
/// Reset and reestablish the connection.
|
||||
/** @note You must remove all readers that have been returned by
|
||||
@ref reader(), if you have assigned them to a variable
|
||||
and stored them. Otherwise the connections will remain
|
||||
open and next access should probably fail.
|
||||
@begincode
|
||||
{
|
||||
mrw::Shared<Reader> r(c.reader(name));
|
||||
// use r
|
||||
c.reset(); // now r is invalid
|
||||
// either reassign r:
|
||||
r = c.reader(name);
|
||||
// or simply reset it
|
||||
r.reset();
|
||||
}
|
||||
// or clenaup by leaving the context of r
|
||||
@endcode */
|
||||
void reset() {
|
||||
_connectionlifetime->reset();
|
||||
}
|
||||
|
||||
//! Find all readers with a given ATR.
|
||||
/*! @param atr full or partial ATR to match to the reader's ATR
|
||||
@returns list of readers that contain @c atr in their ATR */
|
||||
Strings getReadersWithAtr(const std::string& atr) {
|
||||
Strings res;
|
||||
pcsc::Connection::Strings readers(scan());
|
||||
for (pcsc::Connection::Strings::const_iterator it(readers.begin());
|
||||
it!=readers.end(); ++it)
|
||||
if (crypto::hex(reader(*it)->status().atr).find(atr)!=string::npos)
|
||||
res.push_back(*it);
|
||||
return res;
|
||||
}
|
||||
|
||||
//! @c false if last operation was not successful
|
||||
operator bool() const {
|
||||
return *_connectionlifetime;
|
||||
}
|
||||
|
||||
//................................................................methods
|
||||
private:
|
||||
|
||||
mrw::Shared<Reader> newreader(const std::string& name) {
|
||||
return new Reader(name, *this);
|
||||
}
|
||||
|
||||
//! Sets state and throws an exception if neccessary.
|
||||
/*! @throw access_error if it is instanciated for exceptions and
|
||||
an error occured in the last command. */
|
||||
bool check(long state, const std::string& context="") {
|
||||
_connectionlifetime->state(state);
|
||||
return check(context);
|
||||
}
|
||||
|
||||
//! Throws an exception if neccessary.
|
||||
/*! @throw access_error if it is instanciated for exceptions and
|
||||
an error occured in the last command. */
|
||||
bool check(const std::string& context="") {
|
||||
return _connectionlifetime->check(context);
|
||||
}
|
||||
|
||||
//! Splits a buffer with 0 separators into a vector of strings.
|
||||
Strings split(const std::string& in) {
|
||||
static Strings split(const std::string& in) {
|
||||
Strings res;
|
||||
for (std::string::size_type pos(0); pos<in.size() && in[pos]!=0;
|
||||
pos+=res.rbegin()->size()+1)
|
||||
@@ -623,7 +571,7 @@ namespace pcsc {
|
||||
}
|
||||
|
||||
//! Joins a vector of strings into a buffer with 0 separators.
|
||||
std::string join(const Strings& in) {
|
||||
static std::string join(const Strings& in) {
|
||||
std::string res;
|
||||
if (in.size()) {
|
||||
for (Strings::const_iterator it(in.begin());
|
||||
@@ -634,35 +582,6 @@ namespace pcsc {
|
||||
return res;
|
||||
}
|
||||
|
||||
//! Connection id
|
||||
SCARDCONTEXT id() {
|
||||
return _connectionlifetime->id();
|
||||
}
|
||||
|
||||
//! @c true if exceptions are thrown
|
||||
bool exc() {
|
||||
return _connectionlifetime->exc();
|
||||
}
|
||||
|
||||
//..............................................................variables
|
||||
private:
|
||||
|
||||
class ConnectionLifetime {
|
||||
public:
|
||||
//! opens connection that is closed on destruction
|
||||
ConnectionLifetime(Scope s, bool exc):
|
||||
_exc(exc), _id(0), _s(s),
|
||||
_state(SCardEstablishContext(s, 0, 0, &_id)) {
|
||||
CRYPTOLOG("Open Connection");
|
||||
check("establish smartcard context");
|
||||
}
|
||||
//! Closes the connection (releases the smartcard context)
|
||||
~ConnectionLifetime() {
|
||||
CRYPTOLOG("Close Connection");
|
||||
_state = SCardReleaseContext(_id);
|
||||
if (!std::uncaught_exception()) check("smartcard release context");
|
||||
}
|
||||
//! @c false if last operation was not successful
|
||||
operator bool() const {
|
||||
#ifdef WIN32
|
||||
return (_state>>30&3)==0;
|
||||
@@ -670,6 +589,15 @@ namespace pcsc {
|
||||
return _state==SCARD_S_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Throws an exception if neccessary.
|
||||
/*! @throw access_error if it is instanciated for exceptions and
|
||||
an error occured in the last command. */
|
||||
bool check(long state, const std::string& context="") {
|
||||
_state = state;
|
||||
check(context);
|
||||
}
|
||||
|
||||
//! Throws an exception if neccessary.
|
||||
/*! @throw access_error if it is instanciated for exceptions and
|
||||
an error occured in the last command. */
|
||||
@@ -1075,25 +1003,6 @@ namespace pcsc {
|
||||
return _exc;
|
||||
}
|
||||
|
||||
//! Get a reader, open a connection if not already open.
|
||||
/*! First use scan() to get a list of readers, then open a
|
||||
connection to the reader, then access it. */
|
||||
mrw::Shared<Reader> reader(const std::string& name, Connection* c) {
|
||||
CRYPTOLOG("get reader: "<<name<<" from "<<(void*)&_readers);
|
||||
if (_readers.find(name)==_readers.end())
|
||||
_readers.insert(std::make_pair(name, c->newreader(name)));
|
||||
return _readers.find(name)->second;
|
||||
}
|
||||
|
||||
/// Cleans up the readers, resets the context.
|
||||
void reset() {
|
||||
_readers.clear();
|
||||
_state = SCardReleaseContext(_id);
|
||||
check("smartcard release context");
|
||||
_state = SCardEstablishContext(_s, 0, 0, &_id);
|
||||
check("establish smartcard context");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool _exc;
|
||||
@@ -1101,32 +1010,6 @@ namespace pcsc {
|
||||
Scope _s;
|
||||
long _state;
|
||||
|
||||
//! Readers are closed when the last shared object is destructed
|
||||
std::map<std::string, mrw::Shared<Reader> > _readers;
|
||||
};
|
||||
|
||||
//! Connection is closed when the last shared object is destructed
|
||||
/*! Handling the connection lifetime in a separate shared object
|
||||
allows to copy connections and still make sure, that the
|
||||
lifetime of the connection is as long as all copied opbjects
|
||||
live. */
|
||||
static ConnectionLifetime*&
|
||||
connectionlifetime(Scope s=USER, bool exc=true) {
|
||||
static ConnectionLifetime* instance(0);
|
||||
if (instance==0) {
|
||||
CRYPTOLOG("New Connection");
|
||||
instance = new ConnectionLifetime(s, exc);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
static int& connectionlifetimecounter() {
|
||||
static int instance(0);
|
||||
return instance;
|
||||
}
|
||||
|
||||
ConnectionLifetime* _connectionlifetime;
|
||||
|
||||
};
|
||||
|
||||
//@}
|
||||
|
@@ -395,22 +395,10 @@ namespace suisseid {
|
||||
_cryptoki(lib) {
|
||||
}
|
||||
|
||||
Scanner(const pcsc::Connection& pcsc,
|
||||
const std::string& lib="libcvP11.so"):
|
||||
_pcsc(pcsc),
|
||||
_cryptoki(lib) {
|
||||
}
|
||||
|
||||
Scanner(const cryptoki::Library& cryptoki):
|
||||
_cryptoki(cryptoki) {
|
||||
}
|
||||
|
||||
Scanner(const pcsc::Connection& pcsc,
|
||||
const cryptoki::Library& cryptoki):
|
||||
_pcsc(pcsc),
|
||||
_cryptoki(cryptoki) {
|
||||
}
|
||||
|
||||
/// Scan for available known SuisseID cards on the system.
|
||||
/** @return List of detected SuisseID smart cards. */
|
||||
Cards scan() {
|
||||
@@ -418,20 +406,20 @@ namespace suisseid {
|
||||
Cards res;
|
||||
// By now, scan only for PostSuisseID; in future use factory pattern
|
||||
pcsc::Connection::Strings readers
|
||||
(_pcsc.getReadersWithAtr("4b53776973735369676e"));
|
||||
(pcsc::Connection::getReadersWithAtr("4b53776973735369676e"));
|
||||
for (pcsc::Connection::Strings::iterator reader(readers.begin());
|
||||
reader!=readers.end(); ++reader) {
|
||||
cryptoki::SlotList slots(_cryptoki.slotList(true, *reader));
|
||||
if (slots.size()==1)
|
||||
res.push_back(dynamic_cast<Card*>
|
||||
(new Post(_pcsc.reader(*reader), _cryptoki)));
|
||||
(new Post(pcsc::Connection::reader(*reader),
|
||||
_cryptoki)));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
pcsc::Connection _pcsc;
|
||||
cryptoki::Library _cryptoki;
|
||||
|
||||
};
|
||||
|
Reference in New Issue
Block a user