From cd84f2f7fe1849d615d60ccaf0cf53059716e3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=A4ckerlin?= Date: Thu, 13 Jan 2011 07:08:40 +0000 Subject: [PATCH] it works; closes #8 --- Test_Qt_Frontend/QtSslTest.pro | 6 +- Test_Qt_Frontend/qtssltest.cpp | 45 ++++++- Test_Qt_Frontend/smartcardauth.cpp | 25 ++-- Test_Qt_Frontend/smartcardauth.h | 1 + openssl-act-engine/README | 27 ++++ openssl-act-engine/configure.in | 2 +- openssl-act-engine/makefile.am | 5 +- openssl-act-engine/src/engine_sct.cpp | 11 +- openssl-act-engine/src/test_engine.cpp | 6 +- swisssurfer/README | 6 + swisssurfer/configure.in | 1 + swisssurfer/src/browser.hxx | 44 +++---- swisssurfer/src/main.cxx | 5 + swisssurfer/src/pindialog.cxx | 37 ++++++ swisssurfer/src/pindialog.hxx | 22 ++++ swisssurfer/src/qmake.pro.in | 9 +- swisssurfer/src/smartcardauth.cxx | 163 +++++++++++++++++++++++++ swisssurfer/src/smartcardauth.hxx | 30 +++++ swisssurfer/src/swisssurfer_de.ts | 100 ++++++++------- swisssurfer/src/swisssurfer_en.ts | 100 ++++++++------- swisssurfer/src/swisssurfer_fr.ts | 100 ++++++++------- swisssurfer/src/swisssurfer_it.ts | 100 ++++++++------- 22 files changed, 638 insertions(+), 207 deletions(-) create mode 100644 swisssurfer/src/pindialog.cxx create mode 100644 swisssurfer/src/pindialog.hxx create mode 100644 swisssurfer/src/smartcardauth.cxx create mode 100644 swisssurfer/src/smartcardauth.hxx diff --git a/Test_Qt_Frontend/QtSslTest.pro b/Test_Qt_Frontend/QtSslTest.pro index abfacea..b3bd3c7 100644 --- a/Test_Qt_Frontend/QtSslTest.pro +++ b/Test_Qt_Frontend/QtSslTest.pro @@ -6,7 +6,11 @@ TARGET = DEPENDPATH += . INCLUDEPATH += ../openssl-act-engine ../openssl-act-engine/src . ../qt/qt-everywhere-opensource-src-4.6.3/include ../qt/qt-everywhere-opensource-src-4.6.3/include/Qt -CONFIG += debug +QMAKE_CXXFLAGS+=-pthread +QMAKE_LFLAGS+=-pthread + +CONFIG += debug thread +LIBS += -lssl # Input SOURCES += qtssltest.cpp \ diff --git a/Test_Qt_Frontend/qtssltest.cpp b/Test_Qt_Frontend/qtssltest.cpp index b18db1e..52d35cb 100644 --- a/Test_Qt_Frontend/qtssltest.cpp +++ b/Test_Qt_Frontend/qtssltest.cpp @@ -6,11 +6,54 @@ #include #include "smartcardauth.h" +#include + +#define CHECK(X) \ + if (((!(((res=X)))))) { \ + printf("ERROR: %s\n", #X); \ + for (unsigned int err(0); err=ERR_get_error();) { \ + fprintf(stderr,"%s\n", ERR_error_string(err, NULL)); \ + } \ + return -1; \ + } + SmartCardAuth g_scard_auth; int main(int argc, char *argv[]) { + /* + ENGINE* e = NULL; + enum_certs_s* certs_found = NULL; + + ENGINE_load_dynamic(); + e = ENGINE_by_id("dynamic"); + + if (!e) { + printf("ERROR: No Engine"); + return -1; + } + + int res(-1); + + // Parameters to set for the dynamic loader + CHECK(ENGINE_ctrl_cmd_string(e, "SO_PATH", "./.libs/libengine_act.so", 0)); + CHECK(ENGINE_ctrl_cmd_string(e, "ID", "act", 0)); + CHECK(ENGINE_ctrl_cmd_string(e, "LIST_ADD", "1", 0)); + + // Now actually load the SecureToken engine. + CHECK(ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0) + || ENGINE_ctrl_cmd_string(e, "SO_PATH", "./src/.libs/libengine_act.so", 0) + && ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0) + || ENGINE_ctrl_cmd_string(e, "SO_PATH", "../openssl-act-engine/src/.libs/libengine_act.so", 0) + && ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)); + + // Following control commands go to the SecureToken engine rather than the dynamic loader + + CHECK(ENGINE_init(e)); + + return 0; + */ SmartCardAuth::initialize(); QApplication app(argc, argv); @@ -20,7 +63,7 @@ int main(int argc, char *argv[]) // Works even without specifying the root certificate, we just need to add the intermediates, // and that's done in SmartCardAuth.cpp #if 0 - QFile caCertsFile("D:\\QtSmartCardAuth_TMI\\QtSslTest\\swsign_root.pem"); + QFile caCertsFile("swsign_root.pem"); caCertsFile.open(QIODevice::ReadOnly); QList chain( QSslCertificate::fromDevice(&caCertsFile) ); diff --git a/Test_Qt_Frontend/smartcardauth.cpp b/Test_Qt_Frontend/smartcardauth.cpp index ea4d444..fe5eadb 100644 --- a/Test_Qt_Frontend/smartcardauth.cpp +++ b/Test_Qt_Frontend/smartcardauth.cpp @@ -6,6 +6,8 @@ #include +#include + ENGINE* SmartCardAuth::e=NULL; enum_certs_s* SmartCardAuth::certs_found=NULL; QWidget* SmartCardAuth::parent=0; @@ -13,16 +15,20 @@ bool SmartCardAuth::pin_configured=false; bool SmartCardAuth::pin_rejected=false; void SmartCardAuth::initialize() { - QSslSocketPrivate::ensureInitialized(); + //QSslSocketPrivate::ensureInitialized(); - q_ENGINE_load_dynamic(); - e = q_ENGINE_by_id("dynamic"); + ENGINE_load_dynamic(); + e = ENGINE_by_id("dynamic"); + Q_ASSERT(e); - //! @todo add library-name - int r=q_ENGINE_ctrl_cmd_string(e, "SO_PATH", "...library-name...", 0); - r=q_ENGINE_ctrl_cmd_string(e, "ID", "act", 0); - r=q_ENGINE_ctrl_cmd_string(e, "LIST_ADD", "1", 0); - r=q_ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0); + int r=ENGINE_ctrl_cmd_string(e, "SO_PATH", "../openssl-act-engine/src/.libs/libengine_act.so", 0); + Q_ASSERT(r); + r=ENGINE_ctrl_cmd_string(e, "ID", "act", 0); + Q_ASSERT(r); + r=ENGINE_ctrl_cmd_string(e, "LIST_ADD", "1", 0); + Q_ASSERT(r); + r=ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0); + Q_ASSERT(r); if(!r) { @@ -34,7 +40,7 @@ void SmartCardAuth::initialize() { } } - r=q_ENGINE_init(e); + r=ENGINE_init(e); } @@ -59,6 +65,7 @@ int SmartCardAuth::client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) // Name has the format "slot-x-name-SwissSign_digSig" for the certificate/key we're looking for std::string name(certs_found->certificate[i].name); + qDebug()<<"Certificate:"< + class QWidget; struct enum_certs_s; diff --git a/openssl-act-engine/README b/openssl-act-engine/README index e615bf1..f733ae4 100644 --- a/openssl-act-engine/README +++ b/openssl-act-engine/README @@ -2,3 +2,30 @@ OpenSSL-Engine auf Basis der actlibrary zur Benutzung von Smartcard-basierten Schlüsseln von OpenSSL aus. Erstellt libengine_act.so + +Beim Kompilieren braucht es den Pfad zu einer passenden libact.a, z.B.: + ./bootstrap.sh && \ + LDFLAGS="-L/home/marc/svn/swisssurfer/actlibrary/OpenSUSE-11-x86_64/Release" \ + ./configure && \ + make + src/test_engine + +Bei Erfolg kommt keien Fehlermeldung: +------------------------------------------------------------------------------ +> src/test_engine +Found 4 certificates. +Certificate 0: + Name: /C=CH/O=SwissSign AG/CN=SwissSign Platinum CA - G2 + No key. +Certificate 1: + Name: /CN=Marc Waeckerlin/emailAddress=marc@waeckerlin.org + Key access ID: slot-0-id-7e807c700d5880aa3d7e6db92ae9fcc4bf9afd2d +Certificate 2: + Name: /CN=Marc Waeckerlin/emailAddress=marc@waeckerlin.org + Key access ID: slot-0-id-46afda4155d8c4b7a038340a479584ab5385549e +Certificate 3: + Name: /C=CH/O=SwissSign AG/CN=Swiss Post Platinum CA 2008 - G2 + No key. +Token PIN: +Signature-Len: 256 +------------------------------------------------------------------------------ diff --git a/openssl-act-engine/configure.in b/openssl-act-engine/configure.in index 96620d1..dda7e75 100644 --- a/openssl-act-engine/configure.in +++ b/openssl-act-engine/configure.in @@ -44,7 +44,7 @@ LIB_VERSION="${LIB_MAJOR}:${LIB_MINOR}:${LIB_LEAST}" AC_SUBST(LIB_VERSION) # Get rid of that stupid -O2 -g options! -CXXFLAGS="${CXXFLAGS:-}" +CXXFLAGS="${CXXFLAGS:-} -pthread" # languages AC_LANG(C++) diff --git a/openssl-act-engine/makefile.am b/openssl-act-engine/makefile.am index 1bfdcf4..737003e 100644 --- a/openssl-act-engine/makefile.am +++ b/openssl-act-engine/makefile.am @@ -1 +1,4 @@ -SUBDIRS=src +SUBDIRS=src doc + +MAINTAINERCLEANFILES = configure depcomp config.guess ltmain.sh \ + config.sub makefile.in missing aclocal.m4 install-sh diff --git a/openssl-act-engine/src/engine_sct.cpp b/openssl-act-engine/src/engine_sct.cpp index 8ac867f..cac9abd 100644 --- a/openssl-act-engine/src/engine_sct.cpp +++ b/openssl-act-engine/src/engine_sct.cpp @@ -351,13 +351,15 @@ int SecureTokenEngine::rsa_sign(int type, const unsigned char *msg, unsigned int int SecureTokenEngine::rsa_verify(int type, const unsigned char *msg, unsigned int msglen, unsigned char *signature, unsigned int siglen, const CardKey* ck) { + bool ssl = (type == NID_md5_sha1); if(ck == NULL) { ACT_TRACE("SecureTokenEngine::rsa_verify: No CardKey given\n"); return 0; } - - act::IToken* token = ck->getKey()->GetToken(); + + act::ITokenKey* key = ck->getKey(); + act::IToken* token = key->GetToken(); SecOpGuard guard(token); act::Synchronize lock(*token); @@ -365,9 +367,12 @@ int SecureTokenEngine::rsa_verify(int type, const unsigned char *msg, unsigned i act::Blob _signature(signature, signature+siglen); bool sig_ok = false; + if(ssl) + key->SetParam(act::HASH, "DummyHash"); + try { - act::Algorithm alg(ck->getKey(), act::VERIFY, _signature); + act::Algorithm alg(key, act::VERIFY, _signature); alg << _plaintext << act::final; sig_ok = alg.GetStatus() == act::SIGNATURE_OK; } diff --git a/openssl-act-engine/src/test_engine.cpp b/openssl-act-engine/src/test_engine.cpp index e7b86a3..9522355 100644 --- a/openssl-act-engine/src/test_engine.cpp +++ b/openssl-act-engine/src/test_engine.cpp @@ -31,12 +31,14 @@ int main(int argc, char* argv[]) int res(-1); // Parameters to set for the dynamic loader - CHECK(ENGINE_ctrl_cmd_string(e, "SO_PATH", "./libengine_act.so", 0)); + CHECK(ENGINE_ctrl_cmd_string(e, "SO_PATH", "./.libs/libengine_act.so", 0)); CHECK(ENGINE_ctrl_cmd_string(e, "ID", "act", 0)); CHECK(ENGINE_ctrl_cmd_string(e, "LIST_ADD", "1", 0)); // Now actually load the SecureToken engine. - CHECK(ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)); + CHECK(ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0) + || ENGINE_ctrl_cmd_string(e, "SO_PATH", "./src/.libs/libengine_act.so", 0) + && ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)); // Following control commands go to the SecureToken engine rather than the dynamic loader diff --git a/swisssurfer/README b/swisssurfer/README index e69de29..8b28388 100644 --- a/swisssurfer/README +++ b/swisssurfer/README @@ -0,0 +1,6 @@ +Zum Konfigurieren muss der Pfad zur Installation des gepatchten Qts angegeben werden, z.B.: + + ./bootstrap.sh && \ + QMAKE=/usr/local/Trolltech/Qt-4.6.3/bin/qmake ./configure && \ + make + \ No newline at end of file diff --git a/swisssurfer/configure.in b/swisssurfer/configure.in index c63caea..fb72846 100644 --- a/swisssurfer/configure.in +++ b/swisssurfer/configure.in @@ -73,6 +73,7 @@ AM_PATH_CPPUNIT([1.0.0], [have_cppunit="yes"], [have_cppunit="no"]) # Special Options AC_CHECK_PROGS([QMAKE], [qmake-qt4 qmake-mac qmake]) test -n "$QMAKE" || AC_MSG_ERROR([qmake for Qt 4 not found!]) +AC_MSG_NOTICE([QMAKE IS: $QMAKE]) AC_SUBST(QMAKE) AC_CHECK_PROGS([LRELEASE], [lrelease-qt4 lrelease-mac lrelease]) test -n "$LRELEASE" || AC_MSG_ERROR([lrelease for Qt 4 not found!]) diff --git a/swisssurfer/src/browser.hxx b/swisssurfer/src/browser.hxx index 691a0a6..8105163 100644 --- a/swisssurfer/src/browser.hxx +++ b/swisssurfer/src/browser.hxx @@ -26,7 +26,7 @@ #include #include -#define LOG qDebug()<<__PRETTY_FUNCTION__; +#define LOG qDebug()<<__PRETTY_FUNCTION__ class SslClientAuthNetworkAccessManager: public QNetworkAccessManager { Q_OBJECT; @@ -42,7 +42,7 @@ class SslClientAuthNetworkAccessManager: public QNetworkAccessManager { virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest& req, QIODevice* outgoingData = 0 ) { - LOG; + LOG<showMessage(tr("Checking: %1").arg(page.toString())); try { if (!check(page)) { @@ -457,7 +457,7 @@ class Browser: public QMainWindow, protected Ui::Browser { } void startDownload(QUrl url) { - LOG; + LOG<showMessage(tr("Reading: %1").arg(url.toString())); if (!url.isValid()) { statusBar()->showMessage(tr("Illegal URL: %1").arg(url.errorString())); @@ -469,7 +469,7 @@ class Browser: public QMainWindow, protected Ui::Browser { } void reply_error(QNetworkReply::NetworkError err) { - LOG; + LOG<showMessage(tr("network error")); _error += tr("

%1

%2

") .arg(tr("Reply Error")) @@ -479,7 +479,7 @@ class Browser: public QMainWindow, protected Ui::Browser { //! intermediate proxy error void proxy_error(QNetworkReply::NetworkError err, QString errStr, QString proxy) { - LOG; + LOG<showMessage(tr("proxy error")); _error += tr("

%1

Proxy: %3

%2

%4

") .arg(tr("Possible Proxy Failed")) @@ -490,7 +490,7 @@ class Browser: public QMainWindow, protected Ui::Browser { //! final proxy error void proxy_error(QNetworkReply::NetworkError err) { - LOG; + LOG<showMessage(tr("proxy error")); _error = tr("

%1

%2

") .arg(tr("Connection Cannot Be Established")) @@ -499,7 +499,7 @@ class Browser: public QMainWindow, protected Ui::Browser { } void zoom(int i) { - LOG; + LOG<<100.0*i/10.0; statusBar()->showMessage(tr("Zoom: %1%").arg(100.0*i/10.0)); _browser->setZoomFactor(i/10.0); } @@ -510,12 +510,12 @@ class Browser: public QMainWindow, protected Ui::Browser { } void on__browser_urlChanged(const QUrl& url) { - LOG; + LOG<setText(url.toString()); } void on__browser_linkClicked(const QUrl& url) { - LOG; + LOG<showMessage(tr("Info: %1").arg(text)); } void on__browser_loadProgress(int i) { - LOG; + LOG<setValue(i); } @@ -553,7 +553,7 @@ class Browser: public QMainWindow, protected Ui::Browser { } void on__browser_loadFinished(bool ok) { - LOG; + LOG<<(ok?"success":"error"); if (!ok) { _browser->setHtml(tr("Page Load Error" "

Page Load Error

%1" @@ -814,7 +814,7 @@ class Browser: public QMainWindow, protected Ui::Browser { } void databaseQuotaExceeded(QWebFrame* frame, QString databaseName) { - LOG; + LOG<showMessage(tr("%1", "statusbar for hovered link %1=url") .arg(link)); } void loadFinished(bool ok) { - LOG; + LOG<<(ok?"succeess":"error"); } void loadProgress(int progress) { - LOG; + LOG<error()==QNetworkReply::NoError?"success":"error"); if (reply->error()!=QNetworkReply::NoError) { _error += tr("

%1

URL: %3

%2

") .arg(tr("Network Error")) diff --git a/swisssurfer/src/main.cxx b/swisssurfer/src/main.cxx index 2e1ae3b..e84ace0 100644 --- a/swisssurfer/src/main.cxx +++ b/swisssurfer/src/main.cxx @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include + const QByteArray SWISSSIGN_GOLD_CA_G2 ("-----BEGIN CERTIFICATE-----\n" "MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJ\n" @@ -138,6 +140,7 @@ void notrace(QtMsgType, const char*) { } int main(int argv, char** argc) try { + SmartCardAuth scardauth; // qInstallMsgHandler(notrace); // std::cout.rdbuf((new std::stringstream)->rdbuf()); // std::cerr.rdbuf((new std::stringstream)->rdbuf()); @@ -253,6 +256,8 @@ int main(int argv, char** argc) try { .arg(QFileInfo(argc[0]).fileName()).toStdString()< +#include "pindialog.hxx" + + +PinDialog::PinDialog(QWidget *parent) + : QDialog(parent) +{ + label=new QLabel(tr("Enter &PIN:")); + lineEdit=new QLineEdit; + lineEdit->setEchoMode(QLineEdit::Password); + label->setBuddy(lineEdit); + + okButton=new QPushButton(tr("&OK")); + okButton->setDefault(true); + + cancelButton=new QPushButton(tr("&Cancel")); + + connect(okButton, SIGNAL(clicked()), this, SLOT(accept())); + connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); + + QHBoxLayout* tl= new QHBoxLayout; + tl->addWidget(label); + tl->addWidget(lineEdit); + QHBoxLayout* bl= new QHBoxLayout; + bl->addStretch(); + bl->addWidget(okButton); + bl->addWidget(cancelButton); + QVBoxLayout* ml= new QVBoxLayout; + ml->addLayout(tl); + ml->addLayout(bl); + setLayout(ml); +} + +QString PinDialog::pin() const { + // TODO: Cleanup of internal strings as soon as the PIN is retrieved + return lineEdit ? lineEdit->text() : ""; +} diff --git a/swisssurfer/src/pindialog.hxx b/swisssurfer/src/pindialog.hxx new file mode 100644 index 0000000..712c203 --- /dev/null +++ b/swisssurfer/src/pindialog.hxx @@ -0,0 +1,22 @@ +#ifndef PINDIALOG_H +#define PINDIALOG_H + +#include +class QLabel; +class QLineEdit; +class QPushButton; + +class PinDialog : public QDialog +{ + Q_OBJECT +public: + PinDialog(QWidget *parent = 0); + QString pin() const; +private: + QLabel* label; + QLineEdit* lineEdit; + QPushButton* okButton; + QPushButton* cancelButton; +}; + +#endif // PINDIALOG_H diff --git a/swisssurfer/src/qmake.pro.in b/swisssurfer/src/qmake.pro.in index 535618f..5880df1 100644 --- a/swisssurfer/src/qmake.pro.in +++ b/swisssurfer/src/qmake.pro.in @@ -1,6 +1,9 @@ QT += webkit network gui CONFIG += release -QMAKE_LIBS += -lproxyface -lcryptoki++ +QMAKE_LIBS += -lproxyface -lcryptoki++ -lssl +QMAKE_INCDIR += ../../qt/qt-everywhere-opensource-src-4.6.3/include/Qt \ + ../../openssl-act-engine/src/ + unix { QMAKE_LIBS += -lproxy } @@ -18,8 +21,8 @@ TRANSLATIONS = @PACKAGENAME@_en.ts \ @PACKAGENAME@_de.ts \ @PACKAGENAME@_fr.ts \ @PACKAGENAME@_it.ts -SOURCES = main.cxx -HEADERS = browser.hxx +SOURCES = main.cxx smartcardauth.cxx pindialog.cxx +HEADERS = browser.hxx smartcardauth.hxx pindialog.hxx FORMS = browser.ui RESOURCES = languages.qrc resources.qrc TARGET = @PACKAGENAME@ diff --git a/swisssurfer/src/smartcardauth.cxx b/swisssurfer/src/smartcardauth.cxx new file mode 100644 index 0000000..846edb3 --- /dev/null +++ b/swisssurfer/src/smartcardauth.cxx @@ -0,0 +1,163 @@ +#include "smartcardauth.hxx" +#include "pindialog.hxx" +#include + +#include "engine_sct.h" + +#include + +#include +#include + +ENGINE* SmartCardAuth::e=NULL; +enum_certs_s* SmartCardAuth::certs_found=NULL; +QWidget* SmartCardAuth::parent=0; +bool SmartCardAuth::pin_configured=false; +bool SmartCardAuth::pin_rejected=false; +QMutex SmartCardAuth::_mutex; + +SmartCardAuth::SmartCardAuth(QWidget*) { + //QSslSocketPrivate::ensureInitialized(); + + ENGINE_load_dynamic(); + e = ENGINE_by_id("dynamic"); + Q_ASSERT(e); + + int r=ENGINE_ctrl_cmd_string(e, "SO_PATH", "../openssl-act-engine/src/.libs/libengine_act.so", 0); + Q_ASSERT(r); + r=ENGINE_ctrl_cmd_string(e, "ID", "act", 0); + Q_ASSERT(r); + r=ENGINE_ctrl_cmd_string(e, "LIST_ADD", "1", 0); + Q_ASSERT(r); + r=ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0); + Q_ASSERT(r); + + if(!r) + { + unsigned int err = 0; + while((err = q_ERR_get_error())) + { + char *str = q_ERR_error_string(err, NULL); + fprintf(stderr,"%s\n", str); + } + } + + r=ENGINE_init(e); + +} + +SmartCardAuth::~SmartCardAuth() { + q_ENGINE_finish(e); + q_ENGINE_cleanup(); +} + +void SmartCardAuth::setPinDlgParent(QWidget* p) { + parent=p; +} + +int SmartCardAuth::client_cert_cb(SSL*, X509 **x509, EVP_PKEY **pkey) +{ + while (!_mutex.tryLock()) QCoreApplication::processEvents(); + // NB: Keep in mind that this function is called for EVERY SSL connection to be opened. + + for(size_t i=certs_found->num_certs;i--;) + { + const char *id_p = certs_found->certificate[i].id; + + if(id_p == NULL) continue; + + // Name has the format "slot-x-name-SwissSign_digSig" for the certificate/key we're looking for + std::string name(certs_found->certificate[i].name); + qDebug()<<"Certificate:"<certificate[i].cert); + *pkey = NULL; + + // If we don't have a PIN yet, pop up a dialog, ask for a PIN and pass it along to the engine + // for usage. + if(!pin_configured) + { + PinDialog dlg(parent); + int ok=dlg.exec(); + if(ok!=1) {_mutex.unlock(); return 0;} // User cancelled + QByteArray pinByteArray=dlg.pin().toAscii(); + char *pin_str = pinByteArray.data(); + + // The engine control command takes a copy and overwrites the source array + if(q_ENGINE_ctrl_cmd_string(e, "PIN", pin_str, 0)) + pin_configured = true; + else + {_mutex.unlock(); return 0;} // Engine refuses to take the PIN + + *pkey = q_ENGINE_load_private_key(e, id_p, NULL, NULL); + + // We do a test authorization on loading of the private key. If the operation fails at all, + // DON'T try again (see below) or we would instantly lock the card in a single session because + // of the retries! + if(!*pkey) + pin_rejected = true; + } + + // Second to nth iteration: We skipped the PIN dialog here, now load the key if we don't have the + // explicit information not to do it (because the PIN is wrong) + if(!*pkey && !pin_rejected) + *pkey = q_ENGINE_load_private_key(e, id_p, NULL, NULL); + + break; + } + + if(!*x509) { + qWarning("Unable to load certificate"); + _mutex.unlock(); + return 0; + } + + if(!*pkey) { + qWarning("Unable to load key"); + _mutex.unlock(); + return 0; + } + + _mutex.unlock(); + return 1; +} + +bool SmartCardAuth::hookInitSslContext(SSL_CTX *ctx) +{ + bool result = false; + + if(!certs_found) + result = (q_ENGINE_ctrl_cmd(e, "ENUM_CERTS", 0, &certs_found, NULL, 0) != 0); + else + result = true; + +#ifdef USE_CERTIFICATE_FILE + // Load a specific intermediate certificate from a file + //! @todo PEM-File + BIO* cert_file= q_BIO_new_file("swsign_interm.pem", "r"); + X509* interm=q_PEM_read_bio_X509(cert_file,NULL,NULL, NULL); + q_BIO_free(cert_file); + + q_SSL_CTX_add_extra_chain_cert(ctx,interm); +#else + // Add all of the card's certificates without a private key as intermediate certs + for(size_t i=certs_found->num_certs;i--;) + { + if(certs_found->certificate[i].id == NULL) + q_SSL_CTX_add_extra_chain_cert(ctx, q_X509_dup(certs_found->certificate[i].cert)); + } +#endif + + q_SSL_CTX_set_client_cert_cb(ctx, client_cert_cb); + return true; +} diff --git a/swisssurfer/src/smartcardauth.hxx b/swisssurfer/src/smartcardauth.hxx new file mode 100644 index 0000000..33a7cf9 --- /dev/null +++ b/swisssurfer/src/smartcardauth.hxx @@ -0,0 +1,30 @@ +#ifndef SMARTCARDAUTH_H +#define SMARTCARDAUTH_H + +#include +#include + +class QWidget; + +struct enum_certs_s; + +class SmartCardAuth : public QOpenSslHook { + +public: + SmartCardAuth(QWidget* parent=0); + ~SmartCardAuth(); + static void setPinDlgParent(QWidget* parent); + + virtual bool hookInitSslContext(SSL_CTX* ctx); + +private: + static int client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey); + static ENGINE* e; + static enum_certs_s* certs_found; + static QWidget* parent; + static bool pin_configured; + static bool pin_rejected; + static QMutex _mutex; +}; + +#endif // SMARTCARDAUTH_H diff --git a/swisssurfer/src/swisssurfer_de.ts b/swisssurfer/src/swisssurfer_de.ts index e9b0c53..54d8d72 100644 --- a/swisssurfer/src/swisssurfer_de.ts +++ b/swisssurfer/src/swisssurfer_de.ts @@ -113,63 +113,63 @@ - + Checking: %1 Opening: %1 - + Reading: %1 Reading: %1% - - + + <h2>%1</h2><p>%2</p> - + Reply Error - + Network Error - + Zoom: %1% - + %1 - SwissSurfer - + <html><title>Page Load Error</title><body><h1>Page Load Error</h1>%1</body></html> - - - + + + <h2>%1</h2><p>URL: %3</p><p>%2</p> - + <h2>%1</h2><p>URL: %4</p><p>%2</p><h3>SSL Errors</h3><p><ul>%3</ul></p> <h2>%1</h2><p>URL: %3</p><p>%2</p><h3>SSL Errors</h3><p><ul>%3</ul></p> - + Unsuported Content @@ -284,109 +284,127 @@ - + Illegal URL: %1 - + network error - - + + proxy error - + <h2>%1</h2><p>Proxy: %3</p><p>%2</p><p>%4</p> - + Possible Proxy Failed - + Connection Cannot Be Established - + Info: %1 - + download error donload error - + done. - + %1 statusbar for hovered link %1=url - + unsupported content - + Forbidden: %1 - + Access Denied - + <p>Access denied due to security considerations.</p><p>You are not allowed to connect to %1. - + authentication required - + Authentication Required - + ssl error - + <li>%1</li> single ssl error - + SSL Error + + PinDialog + + + Enter &PIN: + + + + + &OK + + + + + &Cancel + + + QObject - + Usage: %1 [OPTIONS...] [<url> ...] Options: -h, --help show this help text @@ -417,33 +435,33 @@ Environment: - + Cannot read PEM certificate from file: %1 - + Read PEM certificates from file: %1 - + Cannot read PEM RSA key from file: %1 - + Read private key from file: %1 - + Too few arguments. Try: %1 --help - + http://swisssign.com diff --git a/swisssurfer/src/swisssurfer_en.ts b/swisssurfer/src/swisssurfer_en.ts index e9b0c53..54d8d72 100644 --- a/swisssurfer/src/swisssurfer_en.ts +++ b/swisssurfer/src/swisssurfer_en.ts @@ -113,63 +113,63 @@ - + Checking: %1 Opening: %1 - + Reading: %1 Reading: %1% - - + + <h2>%1</h2><p>%2</p> - + Reply Error - + Network Error - + Zoom: %1% - + %1 - SwissSurfer - + <html><title>Page Load Error</title><body><h1>Page Load Error</h1>%1</body></html> - - - + + + <h2>%1</h2><p>URL: %3</p><p>%2</p> - + <h2>%1</h2><p>URL: %4</p><p>%2</p><h3>SSL Errors</h3><p><ul>%3</ul></p> <h2>%1</h2><p>URL: %3</p><p>%2</p><h3>SSL Errors</h3><p><ul>%3</ul></p> - + Unsuported Content @@ -284,109 +284,127 @@ - + Illegal URL: %1 - + network error - - + + proxy error - + <h2>%1</h2><p>Proxy: %3</p><p>%2</p><p>%4</p> - + Possible Proxy Failed - + Connection Cannot Be Established - + Info: %1 - + download error donload error - + done. - + %1 statusbar for hovered link %1=url - + unsupported content - + Forbidden: %1 - + Access Denied - + <p>Access denied due to security considerations.</p><p>You are not allowed to connect to %1. - + authentication required - + Authentication Required - + ssl error - + <li>%1</li> single ssl error - + SSL Error + + PinDialog + + + Enter &PIN: + + + + + &OK + + + + + &Cancel + + + QObject - + Usage: %1 [OPTIONS...] [<url> ...] Options: -h, --help show this help text @@ -417,33 +435,33 @@ Environment: - + Cannot read PEM certificate from file: %1 - + Read PEM certificates from file: %1 - + Cannot read PEM RSA key from file: %1 - + Read private key from file: %1 - + Too few arguments. Try: %1 --help - + http://swisssign.com diff --git a/swisssurfer/src/swisssurfer_fr.ts b/swisssurfer/src/swisssurfer_fr.ts index e9b0c53..54d8d72 100644 --- a/swisssurfer/src/swisssurfer_fr.ts +++ b/swisssurfer/src/swisssurfer_fr.ts @@ -113,63 +113,63 @@ - + Checking: %1 Opening: %1 - + Reading: %1 Reading: %1% - - + + <h2>%1</h2><p>%2</p> - + Reply Error - + Network Error - + Zoom: %1% - + %1 - SwissSurfer - + <html><title>Page Load Error</title><body><h1>Page Load Error</h1>%1</body></html> - - - + + + <h2>%1</h2><p>URL: %3</p><p>%2</p> - + <h2>%1</h2><p>URL: %4</p><p>%2</p><h3>SSL Errors</h3><p><ul>%3</ul></p> <h2>%1</h2><p>URL: %3</p><p>%2</p><h3>SSL Errors</h3><p><ul>%3</ul></p> - + Unsuported Content @@ -284,109 +284,127 @@ - + Illegal URL: %1 - + network error - - + + proxy error - + <h2>%1</h2><p>Proxy: %3</p><p>%2</p><p>%4</p> - + Possible Proxy Failed - + Connection Cannot Be Established - + Info: %1 - + download error donload error - + done. - + %1 statusbar for hovered link %1=url - + unsupported content - + Forbidden: %1 - + Access Denied - + <p>Access denied due to security considerations.</p><p>You are not allowed to connect to %1. - + authentication required - + Authentication Required - + ssl error - + <li>%1</li> single ssl error - + SSL Error + + PinDialog + + + Enter &PIN: + + + + + &OK + + + + + &Cancel + + + QObject - + Usage: %1 [OPTIONS...] [<url> ...] Options: -h, --help show this help text @@ -417,33 +435,33 @@ Environment: - + Cannot read PEM certificate from file: %1 - + Read PEM certificates from file: %1 - + Cannot read PEM RSA key from file: %1 - + Read private key from file: %1 - + Too few arguments. Try: %1 --help - + http://swisssign.com diff --git a/swisssurfer/src/swisssurfer_it.ts b/swisssurfer/src/swisssurfer_it.ts index e9b0c53..54d8d72 100644 --- a/swisssurfer/src/swisssurfer_it.ts +++ b/swisssurfer/src/swisssurfer_it.ts @@ -113,63 +113,63 @@ - + Checking: %1 Opening: %1 - + Reading: %1 Reading: %1% - - + + <h2>%1</h2><p>%2</p> - + Reply Error - + Network Error - + Zoom: %1% - + %1 - SwissSurfer - + <html><title>Page Load Error</title><body><h1>Page Load Error</h1>%1</body></html> - - - + + + <h2>%1</h2><p>URL: %3</p><p>%2</p> - + <h2>%1</h2><p>URL: %4</p><p>%2</p><h3>SSL Errors</h3><p><ul>%3</ul></p> <h2>%1</h2><p>URL: %3</p><p>%2</p><h3>SSL Errors</h3><p><ul>%3</ul></p> - + Unsuported Content @@ -284,109 +284,127 @@ - + Illegal URL: %1 - + network error - - + + proxy error - + <h2>%1</h2><p>Proxy: %3</p><p>%2</p><p>%4</p> - + Possible Proxy Failed - + Connection Cannot Be Established - + Info: %1 - + download error donload error - + done. - + %1 statusbar for hovered link %1=url - + unsupported content - + Forbidden: %1 - + Access Denied - + <p>Access denied due to security considerations.</p><p>You are not allowed to connect to %1. - + authentication required - + Authentication Required - + ssl error - + <li>%1</li> single ssl error - + SSL Error + + PinDialog + + + Enter &PIN: + + + + + &OK + + + + + &Cancel + + + QObject - + Usage: %1 [OPTIONS...] [<url> ...] Options: -h, --help show this help text @@ -417,33 +435,33 @@ Environment: - + Cannot read PEM certificate from file: %1 - + Read PEM certificates from file: %1 - + Cannot read PEM RSA key from file: %1 - + Read private key from file: %1 - + Too few arguments. Try: %1 --help - + http://swisssign.com