diff --git a/swisssurfer/src/browser.hxx b/swisssurfer/src/browser.hxx index b4a8a00..5fc18d2 100644 --- a/swisssurfer/src/browser.hxx +++ b/swisssurfer/src/browser.hxx @@ -54,11 +54,11 @@ class Browser: public QMainWindow, protected Ui::Browser { Browser(const QString& actlib, const QStringList& urls = QStringList(), QSettings* settings=0, Settings::MimeTypes mimeTypes = Settings::MimeTypes(), - bool kiosk = false): + bool kiosk = false, bool login = true): _url(0), _clearUrl(0), _addBookmark(0), _find(0), _kiosk(kiosk), _settings(mimeTypes, this, settings, !kiosk), - _scAuth(actlib) { + _scAuth(actlib, this, login) { LOG< settings @@ -252,6 +253,7 @@ int main(int argv, char** argc) try { " -k, --kiosk no url bar\n" " if you sepcify -k and -s, -k must be first\n" " -n, --no-settings don't load or store any settings\n" + " --no-login don't ask for smartcard password\n" " -l, --lib path to file libengine_act.so\n" " -s, --settings \n" " load settings from \n" @@ -277,6 +279,8 @@ int main(int argv, char** argc) try { settings.reset(); } else if ((*it=="-n" || *it=="--no-settings")) { settings.reset(); + } else if (*it=="--no-settings") { + login = false; } else if ((*it=="-l" || *it=="--lib") && ++it!=args.end()) { actlib = *it; } else if ((*it=="-s" || *it=="--settings") && ++it!=args.end()) { @@ -323,7 +327,7 @@ int main(int argv, char** argc) try { sslConfig.setPeerVerifyMode(QSslSocket::VerifyPeer); QSslConfiguration::setDefaultConfiguration(sslConfig); //............................................................................ - Browser browser(actlib, urls, settings.get(), mimetypes, silent); + Browser browser(actlib, urls, settings.get(), mimetypes, silent, login); browser.show(); return app.exec(); } catch (std::exception& x) { diff --git a/swisssurfer/src/smartcardauth.hxx b/swisssurfer/src/smartcardauth.hxx index e672cc2..4e474dd 100644 --- a/swisssurfer/src/smartcardauth.hxx +++ b/swisssurfer/src/smartcardauth.hxx @@ -15,98 +15,42 @@ #include -class CryptokiEngine: public openssl::Engine { +class CryptokiEngine: public QObject, public openssl::Engine { + + Q_OBJECT; + + Q_SIGNALS: + + void certRequired(); + public: - CryptokiEngine(std::string lib): - _cryptoki(lib) { + + CryptokiEngine(std::string lib, QWidget* p): + _cryptoki(lib), _parent(p) { OPENSSL_LOG("log"); - QSslConfiguration sslConfig(QSslConfiguration::defaultConfiguration()); - QList cacerts(sslConfig.caCertificates()); - QList authcerts; - QList allcerts; - QSslCertificate cert; - _slots = _cryptoki.slotList(); - for (cryptoki::SlotList::iterator slot(_slots.begin()); - slot!=_slots.end() && _pin.isEmpty(); ++slot) { - _session = - std::auto_ptr(new cryptoki::Session(*slot)); - cryptoki::ObjectList certs(_session->find - (cryptoki::Attribute(CKA_CLASS) - .from(CKO_CERTIFICATE))); - for (cryptoki::ObjectList::iterator cert(certs.begin()); - cert!=certs.end() && _pin.isEmpty(); ++cert) { - cryptoki::Attribute label(cert->attribute(CKA_LABEL)); - cryptoki::Attribute id(cert->attribute(CKA_ID)); - OPENSSL_LOG("**** FOUND CERTIFICATE: "<find(cryptoki::Attribute(CKA_CLASS) - .from(CKO_PUBLIC_KEY), - id)); - OPENSSL_LOG("**** with keys: "<attribute(CKA_VALUE).value); - cacerts.push_back(QSslCertificate - (QByteArray(data.data(), data.size()), - QSsl::Der)); - } else { - OPENSSL_LOG("**** user cert, check for authentictaion"); - if (label.value.find("auth")==0 || - label.value.find("Authentication")!=std::string::npos) { - OPENSSL_LOG("**** it's our authentication cert"); - std::string data(cert->attribute(CKA_VALUE).value); - QSslCertificate c(QByteArray(data.data(), data.size()), - QSsl::Der); - PinEntry pinEntry(c); /*! @todo set widget */ - while (pinEntry.exec()==PinEntry::Accepted) - try { - cryptoki::Attribute value(cert->attribute(CKA_VALUE)); - _cert = std::auto_ptr - (new openssl::X509(value.value)); - _session->login(pinEntry.pin().toStdString()); - cryptoki::ObjectList keys - (_session->find(cryptoki::Attribute(CKA_CLASS) - .from(CKO_PRIVATE_KEY), - id)); - if (keys.size()==1) { - OPENSSL_LOG("**** found one private key"); - _privateKeys = keys; - _modulus = keys[0].attribute(CKA_MODULUS).value; - _exponent = keys[0].attribute(CKA_PUBLIC_EXPONENT).value; - } - _pin = pinEntry.pin(); - break; - } catch (std::exception& x) { - _pin.clear(); - OPENSSL_LOG("**** ERROR"<attribute(CKA_VALUE).value); - // allcerts.push_back(QSslCertificate - // (QByteArray(data.data(), data.size()), - // QSsl::Der)); - // if (label.value.find("auth")==0) { - // authcerts.push_back(*allcerts.rbegin()); - // } - } - } - } - sslConfig.setCaCertificates(cacerts); } - //! Was initialization successful? + operator bool() { - return !_pin.isEmpty() && _cert.get() && _session.get(); + return _privateKey.get() && _cert.get(); + } + + cryptoki::Init& cryptoki() { + return _cryptoki; } + + void cert(cryptoki::Object privateKey, std::auto_ptr c) { + _cert = c; + _privateKey = std::auto_ptr + (new cryptoki::Object(privateKey)); + _modulus = privateKey.attribute(CKA_MODULUS).value; + _exponent = privateKey.attribute(CKA_PUBLIC_EXPONENT).value; + } + const openssl::X509& cert() { return *_cert; } - virtual EVP_PKEY* privkey(const char* id, UI_METHOD*, void*) { + + virtual EVP_PKEY* privkey() { OPENSSL_LOG("log"); EVP_PKEY* k(EVP_PKEY_new()); RSA* r(RSA_new_method(_e)); @@ -123,14 +67,17 @@ class CryptokiEngine: public openssl::Engine { } protected: + virtual const char* id() { OPENSSL_LOG("log"); return "CryptokiEngine_ID"; } + virtual const char* name() { OPENSSL_LOG("log"); return "CryptokiEngine_NAME"; } + virtual std::string rsaSign(const std::string& in, unsigned int type) { std::string inModded(in); @@ -142,72 +89,174 @@ class CryptokiEngine: public openssl::Engine { // default: throw("unknown key mechanism"); // } - //------------------------------------------------------------ PKCS11_sign - int sigsize(openssl::BigNum(_modulus).size()); - { - int ssl = ((type == NID_md5_sha1) ? 1 : 0); - unsigned char *encoded = NULL; - - if (ssl) { - OPENSSL_LOG("It's SSL"); - if((inModded.size() != 36) /* SHA1 + MD5 */ || - ((inModded.size() + RSA_PKCS1_PADDING_SIZE) > sigsize)) { - throw std::runtime_error("the size is wrong"); - } - } else { - OPENSSL_LOG("It's not SSL"); - ASN1_TYPE parameter; - parameter.type = V_ASN1_NULL; - parameter.value.ptr = 0; - X509_ALGOR algor; - algor.algorithm = OBJ_nid2obj(type); - algor.parameter = ¶meter; - ASN1_STRING digest; - digest.data = (unsigned char *)inModded.data(); - digest.length = inModded.size(); - X509_SIG sig; - sig.algor = &algor; - sig.digest = &digest; - int size (i2d_X509_SIG(&sig, 0)); - if (!algor.algorithm) throw std::runtime_error("algor wrong nid"); - if (!algor.algorithm->length) - throw std::runtime_error("algor length"); - if (size) throw std::runtime_error("digest size"); - if (size + RSA_PKCS1_PADDING_SIZE < sigsize) - throw std::runtime_error("incompatible size"); - unsigned char* buf(new unsigned char[size]); - i2d_X509_SIG(&sig, &buf); - inModded.assign((char*)buf, size); - delete[] buf; - } - } + // //------------------------------------------------------------ PKCS11_sign + // int sigsize(openssl::BigNum(_modulus).size()); + // { + // int ssl = ((type == NID_md5_sha1) ? 1 : 0); + // unsigned char *encoded = NULL; + + // if (ssl) { + // OPENSSL_LOG("It's SSL"); + // if((inModded.size() != 36) /* SHA1 + MD5 */ || + // ((inModded.size() + RSA_PKCS1_PADDING_SIZE) > sigsize)) { + // throw std::runtime_error("the size is wrong"); + // } + // } else { + // OPENSSL_LOG("It's not SSL"); + // ASN1_TYPE parameter; + // parameter.type = V_ASN1_NULL; + // parameter.value.ptr = 0; + // X509_ALGOR algor; + // algor.algorithm = OBJ_nid2obj(type); + // algor.parameter = ¶meter; + // ASN1_STRING digest; + // digest.data = (unsigned char *)inModded.data(); + // digest.length = inModded.size(); + // X509_SIG sig; + // sig.algor = &algor; + // sig.digest = &digest; + // int size (i2d_X509_SIG(&sig, 0)); + // if (!algor.algorithm) throw std::runtime_error("algor wrong nid"); + // if (!algor.algorithm->length) + // throw std::runtime_error("algor length"); + // if (size) throw std::runtime_error("digest size"); + // if (size + RSA_PKCS1_PADDING_SIZE < sigsize) + // throw std::runtime_error("incompatible size"); + // unsigned char* buf(new unsigned char[size]); + // i2d_X509_SIG(&sig, &buf); + // inModded.assign((char*)buf, size); + // delete[] buf; + // } + // } - //------------------------------------------------- PKCS11_private_encrypt - { - char padding(RSA_PKCS1_PADDING); + // //------------------------------------------------- PKCS11_private_encrypt + // { + // char padding(RSA_PKCS1_PADDING); - if ((inModded.size() + RSA_PKCS1_PADDING_SIZE) > sigsize) - throw std::runtime_error("the size is wrong"); - } + // if ((inModded.size() + RSA_PKCS1_PADDING_SIZE) > sigsize) + // throw std::runtime_error("the size is wrong"); + // } - //----------------------------------------------------------------------- - if (in!=inModded) - OPENSSL_LOG("changed input"<sign(inModded, CKM_RSA_PKCS); } + private: + cryptoki::Init _cryptoki; - cryptoki::SlotList _slots; - std::auto_ptr _session; - QString _pin; - std::auto_ptr _cert; std::string _modulus; std::string _exponent; - cryptoki::ObjectList _privateKeys; + std::auto_ptr _privateKey; + std::auto_ptr _cert; + + public: + + void login() { + QMutexLocker lock(&_mutex); + try { + QList authcerts; + QList allcerts; + QSslConfiguration sslConfig(QSslConfiguration::defaultConfiguration()); + QList cacerts(sslConfig.caCertificates()); + _slots = _cryptoki.slotList(); + for (cryptoki::SlotList::iterator slot(_slots.begin()); + slot!=_slots.end(); ++slot) { + _session = + std::auto_ptr(new cryptoki::Session(*slot)); + cryptoki::ObjectList certs(_session->find + (cryptoki::Attribute(CKA_CLASS) + .from(CKO_CERTIFICATE))); + for (cryptoki::ObjectList::iterator cert(certs.begin()); + cert!=certs.end(); ++cert) { + cryptoki::Attribute label(cert->attribute(CKA_LABEL)); + cryptoki::Attribute id(cert->attribute(CKA_ID)); + OPENSSL_LOG("**** FOUND CERTIFICATE: "<find(cryptoki::Attribute(CKA_CLASS) + .from(CKO_PUBLIC_KEY), + id)); + OPENSSL_LOG("**** with keys: "<attribute(CKA_VALUE).value); + if (!keys.size()) { // add CA-certificate + OPENSSL_LOG("**** add to CA-certificates"); + cacerts.push_back(QSslCertificate + (QByteArray(data.data(), data.size()), + QSsl::Der)); + } else { + OPENSSL_LOG("**** user cert, check for authentictaion"); + if (label.value.find("auth")==0 || + label.value.find("Authentication")!=std::string::npos) { + OPENSSL_LOG("**** it's our authentication cert"); + authcerts.push_back(CertInfo(data, slot, id)); + } else { + OPENSSL_LOG("**** it's an unknown cert"); + allcerts.push_back(CertInfo(data, slot, id)); + } + } + } + } + if (!authcerts.isEmpty() || !allcerts.isEmpty()) { + CertInfo c(authcerts.size()?authcerts[0]:allcerts[0]); + PinEntry pinEntry(QSslCertificate(QByteArray(c.data.data(), + c.data.size()), + QSsl::Der), _parent); + while (pinEntry.exec()==PinEntry::Accepted) + try { + _session = + std::auto_ptr + (new cryptoki::Session(*c.slot)); + _session->login(pinEntry.pin().toStdString()); + cryptoki::ObjectList keys + (_session->find(cryptoki::Attribute(CKA_CLASS) + .from(CKO_PRIVATE_KEY), + c.id)); + if (keys.size()==1) { + OPENSSL_LOG("**** found one private key"); + cert(keys[0], + std::auto_ptr + (new openssl::X509(c.data))); + sslConfig.setCaCertificates(cacerts); + break; + } + } catch (std::exception& x) { + pinEntry.pin().clear(); + OPENSSL_LOG("**** ERROR"< _session; + QMutex _mutex; + std::auto_ptr _pinEntry; + }; class SmartCardAuth: public QObject { @@ -215,30 +264,35 @@ class SmartCardAuth: public QObject { public: - SmartCardAuth(const QString& lib): - _reg(e(lib)) { + SmartCardAuth(const QString& lib, QWidget* p=0, bool login=true): + _reg(e(lib, p)) { qDebug()<<__PRETTY_FUNCTION__; + if (login) e()->login(); + //assert(connect(e(), SIGNAL(certRequired()), SLOT(login()))); } private Q_SLOTS: void extendedContextInitialization(ssl_ctx_st* ctx, QSslSocket* socket) { qDebug()<<__PRETTY_FUNCTION__; - if (!*e()) return; // no certificate found SSL_CTX_set_client_cert_cb(ctx, clientCert); } + private: + static int clientCert(SSL* ssl, X509 **x509, EVP_PKEY **pkey) { + qDebug()<<__PRETTY_FUNCTION__; + if (!*e()) return 0; // no certificate found qDebug()<<"*** A "<<__PRETTY_FUNCTION__; *x509 = e()->cert().lowLevelCopy(); qDebug()<<"*** B "<<__PRETTY_FUNCTION__; - *pkey = e()->privkey(0, 0, 0); + *pkey = e()->privkey(); qDebug()<<"*** C "<<__PRETTY_FUNCTION__; return 1; } - static CryptokiEngine* e(const QString& lib = QString()) { - static CryptokiEngine* _e(new CryptokiEngine(lib.toStdString())); + static CryptokiEngine* e(const QString& lib = QString(), QWidget* p = 0) { + static CryptokiEngine* _e(new CryptokiEngine(lib.toStdString(), p)); return _e; } diff --git a/swisssurfer/src/swisssurfer_de.ts b/swisssurfer/src/swisssurfer_de.ts index 2950ba8..fd97bac 100644 --- a/swisssurfer/src/swisssurfer_de.ts +++ b/swisssurfer/src/swisssurfer_de.ts @@ -541,12 +541,12 @@ p, li { white-space: pre-wrap; } QMessageBox - + Wrong PIN - + Authentication failed, please try again. @@ -554,13 +554,14 @@ p, li { white-space: pre-wrap; } QObject - + Usage: %1 [OPTIONS...] [<url> ...] Options: -h, --help show this help text -k, --kiosk no url bar if you sepcify -k and -s, -k must be first -n, --no-settings don't load or store any settings + --no-login don't ask for smartcard password -l, --lib <file> path to file libengine_act.so -s, --settings <file> load settings from <file> @@ -579,27 +580,27 @@ 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 diff --git a/swisssurfer/src/swisssurfer_en.ts b/swisssurfer/src/swisssurfer_en.ts index 2950ba8..fd97bac 100644 --- a/swisssurfer/src/swisssurfer_en.ts +++ b/swisssurfer/src/swisssurfer_en.ts @@ -541,12 +541,12 @@ p, li { white-space: pre-wrap; } QMessageBox - + Wrong PIN - + Authentication failed, please try again. @@ -554,13 +554,14 @@ p, li { white-space: pre-wrap; } QObject - + Usage: %1 [OPTIONS...] [<url> ...] Options: -h, --help show this help text -k, --kiosk no url bar if you sepcify -k and -s, -k must be first -n, --no-settings don't load or store any settings + --no-login don't ask for smartcard password -l, --lib <file> path to file libengine_act.so -s, --settings <file> load settings from <file> @@ -579,27 +580,27 @@ 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 diff --git a/swisssurfer/src/swisssurfer_fr.ts b/swisssurfer/src/swisssurfer_fr.ts index 2950ba8..fd97bac 100644 --- a/swisssurfer/src/swisssurfer_fr.ts +++ b/swisssurfer/src/swisssurfer_fr.ts @@ -541,12 +541,12 @@ p, li { white-space: pre-wrap; } QMessageBox - + Wrong PIN - + Authentication failed, please try again. @@ -554,13 +554,14 @@ p, li { white-space: pre-wrap; } QObject - + Usage: %1 [OPTIONS...] [<url> ...] Options: -h, --help show this help text -k, --kiosk no url bar if you sepcify -k and -s, -k must be first -n, --no-settings don't load or store any settings + --no-login don't ask for smartcard password -l, --lib <file> path to file libengine_act.so -s, --settings <file> load settings from <file> @@ -579,27 +580,27 @@ 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 diff --git a/swisssurfer/src/swisssurfer_it.ts b/swisssurfer/src/swisssurfer_it.ts index 2950ba8..fd97bac 100644 --- a/swisssurfer/src/swisssurfer_it.ts +++ b/swisssurfer/src/swisssurfer_it.ts @@ -541,12 +541,12 @@ p, li { white-space: pre-wrap; } QMessageBox - + Wrong PIN - + Authentication failed, please try again. @@ -554,13 +554,14 @@ p, li { white-space: pre-wrap; } QObject - + Usage: %1 [OPTIONS...] [<url> ...] Options: -h, --help show this help text -k, --kiosk no url bar if you sepcify -k and -s, -k must be first -n, --no-settings don't load or store any settings + --no-login don't ask for smartcard password -l, --lib <file> path to file libengine_act.so -s, --settings <file> load settings from <file> @@ -579,27 +580,27 @@ 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