29 #include <netinet/in.h>
30 #include <sys/socket.h>
31 #define crypt _openssl_crypt
32 #include <openssl/ssl.h>
33 #include <openssl/x509.h>
34 #include <openssl/x509v3.h>
35 #include <openssl/pem.h>
36 #include <openssl/rand.h>
43 #include <kstandarddirs.h>
45 #include <ksockaddr.h>
48 #include <ksslx509v3.h>
49 #include <ksslpkcs12.h>
50 #include <ksslsession.h>
51 #include <tdelocale.h>
85 m_bAutoReconfig =
true;
107 rc = d->kossl->RAND_egd(m_cfg->
getEGDPath().latin1());
109 kdDebug(7029) <<
"KSSL: Error seeding PRNG with the EGD." << endl;
110 else kdDebug(7029) <<
"KSSL: PRNG was seeded with " << rc
111 <<
" bytes from the EGD." << endl;
113 rc = d->kossl->RAND_load_file(m_cfg->
getEGDPath().latin1(), -1);
115 kdDebug(7029) <<
"KSSL: Error seeding PRNG with the entropy file." << endl;
116 else kdDebug(7029) <<
"KSSL: PRNG was seeded with " << rc
117 <<
" bytes from the entropy file." << endl;
137 d->m_meth = d->kossl->TLS_client_method();
138 d->lastInitTLS =
true;
142 d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth);
143 if (d->m_ctx == 0L) {
150 if (!clist.isEmpty())
151 d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast<char *>(clist.ascii()));
163 kdDebug(7029) <<
"KSSL initialize" << endl;
172 d->lastInitTLS =
false;
177 d->m_meth = d->kossl->TLS_client_method();
179 else if (m_cfg->
sslv3()) {
180 d->m_meth = d->kossl->SSLv3_client_method();
182 else if (m_cfg->
sslv2()) {
183 d->m_meth = d->kossl->SSLv2_client_method();
192 d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth);
193 if (d->m_ctx == 0L) {
199 kdDebug(7029) <<
"Cipher list: " << clist << endl;
200 if (!clist.isEmpty())
201 d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast<char *>(clist.ascii()));
221 d->session->_session = session->_session;
222 session->_session = 0L;
241 d->kossl->SSL_shutdown(d->m_ssl);
242 d->kossl->SSL_free(d->m_ssl);
246 d->kossl->SSL_CTX_free(d->m_ctx);
248 d->kossl->RAND_write_file(m_cfg->
getEGDPath().latin1());
265 bool KSSL::setVerificationLogic() {
282 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
287 #if OPENSSL_VERSION_NUMBER < 0x10100000L
288 if (static_cast<SSL_SESSION*>(d->session->_session)->sess_cert == 0)
290 kdDebug(7029) <<
"Can't reuse session, no certificate." << endl;
296 if (1 == d->kossl->SSL_set_session(d->m_ssl,
297 static_cast<SSL_SESSION*>(d->session->_session))) {
298 kdDebug(7029) <<
"Session ID is being reused." << endl;
300 kdDebug(7029) <<
"Error attempting to reuse session." << endl;
315 int off = SSL_OP_ALL;
316 if (!d->lastInitTLS && !m_cfg->
tlsv1())
317 off |= SSL_OP_NO_TLSv1;
319 off |= SSL_OP_NO_SSLv3;
321 off |= SSL_OP_NO_SSLv2;
323 d->kossl->_SSL_set_options(d->m_ssl, off);
325 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
327 d->kossl->SSL_shutdown(d->m_ssl);
328 d->kossl->SSL_free(d->m_ssl);
332 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
333 d->kossl->SSL_set_tlsext_host_name(d->m_ssl, d->proxyPeer.ascii());
336 rc = d->kossl->SSL_accept(d->m_ssl);
340 kdDebug(7029) <<
"KSSL connected OK" << endl;
342 kdDebug(7029) <<
"KSSL accept failed - rc = " << rc << endl;
343 kdDebug(7029) <<
" ERROR = "
344 << d->kossl->SSL_get_error(d->m_ssl, rc) << endl;
345 d->kossl->SSL_shutdown(d->m_ssl);
346 d->kossl->SSL_free(d->m_ssl);
351 if (!d->kossl->_SSL_session_reused(d->m_ssl)) {
353 kdDebug(7029) <<
"Session reuse failed. New session used instead." << endl;
360 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
363 d->session->_session = sess;
380 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
385 #if OPENSSL_VERSION_NUMBER < 0x10100000L
386 if (static_cast<SSL_SESSION*>(d->session->_session)->sess_cert == 0)
388 kdDebug(7029) <<
"Can't reuse session, no certificate." << endl;
394 if (1 == d->kossl->SSL_set_session(d->m_ssl,
395 static_cast<SSL_SESSION*>(d->session->_session))) {
396 kdDebug(7029) <<
"Session ID is being reused." << endl;
398 kdDebug(7029) <<
"Error attempting to reuse session." << endl;
413 int off = SSL_OP_ALL;
414 if (!d->lastInitTLS && !m_cfg->
tlsv1())
415 off |= SSL_OP_NO_TLSv1;
417 off |= SSL_OP_NO_SSLv3;
419 off |= SSL_OP_NO_SSLv2;
421 d->kossl->_SSL_set_options(d->m_ssl, off);
423 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
425 d->kossl->SSL_shutdown(d->m_ssl);
426 d->kossl->SSL_free(d->m_ssl);
430 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
431 d->kossl->SSL_set_tlsext_host_name(d->m_ssl, d->proxyPeer.ascii());
435 rc = d->kossl->SSL_connect(d->m_ssl);
439 kdDebug(7029) <<
"KSSL connected OK" << endl;
441 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
442 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
446 kdDebug(7029) <<
"KSSL connect failed - rc = "
448 kdDebug(7029) <<
" ERROR = "
450 d->kossl->ERR_print_errors_fp(stderr);
451 d->kossl->SSL_shutdown(d->m_ssl);
452 d->kossl->SSL_free(d->m_ssl);
458 if (!d->kossl->_SSL_session_reused(d->m_ssl)) {
460 kdDebug(7029) <<
"Session reuse failed. New session used instead." << endl;
467 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
470 d->session->_session = sess;
485 return d->kossl->SSL_pending(d->m_ssl);
497 return d->kossl->SSL_peek(d->m_ssl, buf, len);
513 rc = d->kossl->SSL_read(d->m_ssl, (
char *)buf, len);
515 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
517 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
518 kdDebug(7029) <<
"SSL read() returning 0: " << err << endl;
519 if (maxIters-- > 0) {
526 kdDebug(7029) <<
"SSL READ ERROR: " << err << endl;
527 if (err != SSL_ERROR_NONE &&
528 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL) {
530 d->kossl->ERR_print_errors_fp(stderr);
549 int rc = d->kossl->SSL_write(d->m_ssl, (
const char *)buf, len);
551 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
553 if (err == SSL_ERROR_WANT_WRITE) {
558 kdDebug(7029) <<
"SSL WRITE ERROR: " << err << endl;
559 if (err != SSL_ERROR_NONE &&
560 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL)
577 m_bAutoReconfig = ar;
589 bool KSSL::m_bSSLWorks =
true;
591 bool KSSL::m_bSSLWorks =
false;
599 void KSSL::setConnectionInfo() {
605 sc = d->kossl->SSL_get_current_cipher(d->m_ssl);
607 kdDebug(7029) <<
"KSSL get current cipher failed - we're probably gonna crash!" << endl;
612 m_ci.m_iCipherUsedBits = d->kossl->SSL_CIPHER_get_bits(sc, &(m_ci.m_iCipherBits));
614 m_ci.m_cipherVersion = d->kossl->SSL_CIPHER_get_version(sc);
616 m_ci.m_cipherName = d->kossl->SSL_CIPHER_get_name(sc);
618 m_ci.m_cipherDescription = d->kossl->SSL_CIPHER_description(sc, buf, 1023);
624 void KSSL::setPeerInfo() {
627 m_pi.m_cert.
setCert(d->kossl->SSL_get_peer_certificate(d->m_ssl));
628 STACK_OF(X509) *xs = d->kossl->SSL_get_peer_cert_chain(d->m_ssl);
630 xs =
reinterpret_cast<STACK_OF(X509)*
>(d->kossl->OPENSSL_sk_dup(xs));
631 m_pi.m_cert.setChain((
void *)xs);
643 d->proxyPeer = realHost;
665 if (!x || !k)
return false;
670 rc = d->kossl->SSL_CTX_use_certificate(d->m_ctx, x);
672 kdDebug(7029) <<
"KSSL - SSL_CTX_use_certificate failed. rc = " << rc << endl;
676 rc = d->kossl->SSL_CTX_use_PrivateKey(d->m_ctx, k);
678 kdDebug(7029) <<
"KSSL - SSL_CTX_use_PrivateKey failed. rc = " << rc << endl;
694 return (d->m_ssl && d->kossl->_SSL_session_reused(d->m_ssl));
bool reconfig()
Trigger a reread of KSSL configuration and reInitialize() KSSL.
int seedWithEGD()
This will reseed the pseudo-random number generator with the EGD (entropy gathering daemon) if the EG...
const KSSLSession * session() const
Obtain a pointer to the session information.
bool useEFile() const
Does the user want to use an entropy file?
bool initialize()
Initialize OpenSSL.
int read(void *buf, int len)
Read data from the remote host via SSL.
KSSLX509V3 & x509V3Extensions()
Access the X.509v3 parameters.
void reset()
Clear out the host name.
bool setCert(TQString &cert)
Re-set the certificate from a base64 string.
bool TLSInit()
This is used for applicationss which do STARTTLS or something similar.
KSSL(bool init=true)
Construct a KSSL object.
bool sslv3() const
Does the user allow SSLv3.
~KSSL()
Destroy this KSSL object.
void setPeerHost(TQString host=TQString::null)
Set the host that we are connected to.
bool useEGD() const
Does the user want to use the Entropy Gathering Daemon?
bool takeSession(KSSLSession *session)
Set an SSL session to use.
void setProxyUse(bool active, TQString realIP=TQString::null, int realPort=0, TQString proxy=TQString::null) KDE_DEPRECATED
Set the status of the connection with respect to proxies.
int write(const void *buf, int len)
Write data to the remote host via SSL.
KSSLValidation
A CA certificate can be validated as Irrelevant when it was not used to sign any other relevant certi...
bool setClientCertificate(KSSLPKCS12 *pkcs)
Use this to set the certificate to send to the server.
int peek(void *buf, int len)
Peek at available data from the remote host via SSL.
void load()
Load the user's settings.
TQString & getEGDPath()
Get the configured path to the entropy gathering daemon or entropy file.
bool certTypeSSLClient()
Determine if this certificate can be used by an SSL client.
void setPeerHost(TQString realHost=TQString::null)
Set the peer hostname to be used for certificate verification.
int pending()
Determine if data is waiting to be read.
bool tlsv1() const
Does the user allow TLSv1.
TQString getCipherList()
Get the OpenSSL cipher list for selecting the list of ciphers to use in a connection.
KSSLSettings * settings()
One is built by the constructor, so this will only return a NULL pointer if you set one with setSetti...
int accept(int sock)
Connect the SSL session to the remote host using the provided socket descriptor.
EVP_PKEY * getPrivateKey()
Get the private key.
int connect(int sock)
Connect the SSL session to the remote host using the provided socket descriptor.
KSSLPeerInfo & peerInfo()
Obtain a reference to the information about the peer.
KDE SSL Session Information.
static bool doesSSLWork()
Determine if SSL is available and works.
bool reusingSession() const
Determine if we are currently reusing an SSL session ID.
void setAutoReconfig(bool ar)
Enable or disable automatic reconfiguration on initialize().
KSSLConnectionInfo & connectionInfo()
Obtain a reference to the connection information.
bool setSettings(KSSLSettings *settings)
Set a new KSSLSettings instance as the settings.
KSSLCertificate * getCertificate()
Get the X.509 certificate.
bool sslv2() const
Does the user allow SSLv2.
void close()
Close the SSL session.
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.
bool reInitialize()
Reinitialize OpenSSL.
KDE SSL Connection Information.