option is noe --login to enable immediate login, otherwise logs in at first https-access; also works without cryptoki-library; closes #34

This commit is contained in:
Marc Wäckerlin
2011-05-03 10:21:12 +00:00
parent 108f66b43e
commit 0870f9e4e4
9 changed files with 245 additions and 210 deletions

View File

@@ -25,12 +25,16 @@ class CryptokiEngine: public QObject, public openssl::Engine {
public:
CryptokiEngine(std::string lib, QWidget* p):
_cryptoki(lib), _parent(p) {
CryptokiEngine(std::string lib):
_cryptoki(lib) {
OPENSSL_LOG("log");
}
operator bool() {
OPENSSL_LOG("Status of CryptokiEngine: "
<<(_privateKey.get()
?"privateKey defined, ":"privateKey undefined")
<<(_cert.get()?"cert defined":"cert undefined"));
return _privateKey.get() && _cert.get();
}
@@ -39,6 +43,7 @@ class CryptokiEngine: public QObject, public openssl::Engine {
}
void cert(cryptoki::Object privateKey, std::auto_ptr<openssl::X509> c) {
OPENSSL_LOG("log");
_cert = c;
_privateKey = std::auto_ptr<cryptoki::Object>
(new cryptoki::Object(privateKey));
@@ -79,72 +84,11 @@ class CryptokiEngine: public QObject, public openssl::Engine {
}
virtual std::string rsaSign(const std::string& in, unsigned int type) {
std::string inModded(in);
OPENSSL_LOG("log");
OPENSSL_LOG("type="<<type);
// CK_MECHANISM_TYPE mech(0);
// switch (type) {
// case NID_idea_ecb: mech=CKM_IDEA_ECB; break;
// 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 = &parameter;
// 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);
// if ((inModded.size() + RSA_PKCS1_PADDING_SIZE) > sigsize)
// throw std::runtime_error("the size is wrong");
// }
// //-----------------------------------------------------------------------
// if (in!=inModded)
// OPENSSL_LOG("changed input"<<std::endl
// <<"from:"<<std::endl
// <<crypto::readable(in)<<std::endl
// <<"to:"<<std::endl
// <<crypto::readable(inModded));
return _privateKey->sign(inModded, CKM_RSA_PKCS);
OPENSSL_LOG("type="<<type<<"; size="<<in.size());
if (type != NID_md5_sha1) throw std::runtime_error("wrong sign type");
if (in.size() != 36) throw std::runtime_error("wrong msg size to sign");
return _privateKey->sign(in, CKM_RSA_PKCS);
}
private:
@@ -154,17 +98,64 @@ class CryptokiEngine: public QObject, public openssl::Engine {
std::string _exponent;
std::auto_ptr<cryptoki::Object> _privateKey;
std::auto_ptr<openssl::X509> _cert;
};
class SmartCardAuth: public QObject {
Q_OBJECT;
public:
SmartCardAuth(const QString& lib, QWidget* p=0, bool loginAtStart=true):
_reg(e(lib)), _parent(p) {
qDebug()<<__PRETTY_FUNCTION__;
if (loginAtStart) login();
//assert(connect(e(), SIGNAL(certRequired()), SLOT(login())));
}
private Q_SLOTS:
void extendedContextInitialization(ssl_ctx_st* ctx, QSslSocket* socket) {
qDebug()<<__PRETTY_FUNCTION__;
SSL_CTX_set_client_cert_cb(ctx, SmartCardAuth::clientCert);
}
private:
static int clientCert(SSL* ssl, X509 **x509, EVP_PKEY **pkey) {
qDebug()<<__PRETTY_FUNCTION__;
if (!e() || !*e()) return 0; // no certificate found
qDebug()<<"*** A "<<__PRETTY_FUNCTION__;
*x509 = e()->cert().lowLevelCopy();
qDebug()<<"*** B "<<__PRETTY_FUNCTION__;
*pkey = e()->privkey();
qDebug()<<"*** C "<<__PRETTY_FUNCTION__;
return 1;
}
static CryptokiEngine* e(const QString& lib = QString()) try {
static CryptokiEngine* _e(new CryptokiEngine(lib.toStdString()));
return _e;
} catch (...) {
return 0;
}
private:
openssl::RegisterEngine _reg;
//std::map<ssl_ctx_st*, QSslSocket*> sockets;
public:
void login() {
void login(bool force=false) {
QMutexLocker lock(&_mutex);
if (!e() || (!force && *e())) return; // already logged in
try {
QList<CertInfo> authcerts;
QList<CertInfo> allcerts;
QSslConfiguration sslConfig(QSslConfiguration::defaultConfiguration());
QList<QSslCertificate> cacerts(sslConfig.caCertificates());
_slots = _cryptoki.slotList();
_slots = e()->cryptoki().slotList();
for (cryptoki::SlotList::iterator slot(_slots.begin());
slot!=_slots.end(); ++slot) {
_session =
@@ -218,9 +209,9 @@ class CryptokiEngine: public QObject, public openssl::Engine {
c.id));
if (keys.size()==1) {
OPENSSL_LOG("**** found one private key");
cert(keys[0],
std::auto_ptr<openssl::X509>
(new openssl::X509(c.data)));
e()->cert(keys[0],
std::auto_ptr<openssl::X509>
(new openssl::X509(c.data)));
sslConfig.setCaCertificates(cacerts);
break;
}
@@ -255,51 +246,6 @@ class CryptokiEngine: public QObject, public openssl::Engine {
cryptoki::SlotList _slots;
std::auto_ptr<cryptoki::Session> _session;
QMutex _mutex;
std::auto_ptr<PinEntry> _pinEntry;
};
class SmartCardAuth: public QObject {
Q_OBJECT;
public:
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__;
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();
qDebug()<<"*** C "<<__PRETTY_FUNCTION__;
return 1;
}
static CryptokiEngine* e(const QString& lib = QString(), QWidget* p = 0) {
static CryptokiEngine* _e(new CryptokiEngine(lib.toStdString(), p));
return _e;
}
private:
openssl::RegisterEngine _reg;
//std::map<ssl_ctx_st*, QSslSocket*> sockets;
};