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;
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));
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.
KSSLX509V3 & x509V3Extensions()
Access the X.509v3 parameters.
KSSLValidation
A CA certificate can be validated as Irrelevant when it was not used to sign any other relevant certi...
bool setCert(TQString &cert)
Re-set the certificate from a base64 string.
KDE SSL Connection Information.
EVP_PKEY * getPrivateKey()
Get the private key.
KSSLCertificate * getCertificate()
Get the X.509 certificate.
void reset()
Clear out the host name.
void setPeerHost(TQString host=TQString::null)
Set the host that we are connected to.
KDE SSL Session Information.
TQString getCipherList()
Get the OpenSSL cipher list for selecting the list of ciphers to use in a connection.
bool sslv2() const
Does the user allow SSLv2.
bool sslv3() const
Does the user allow SSLv3.
bool tlsv1() const
Does the user allow TLSv1.
void load()
Load the user's settings.
bool useEFile() const
Does the user want to use an entropy file?
TQString & getEGDPath()
Get the configured path to the entropy gathering daemon or entropy file.
bool useEGD() const
Does the user want to use the Entropy Gathering Daemon?
bool certTypeSSLClient()
Determine if this certificate can be used by an SSL client.
void setProxyUse(bool active, TQString realIP=TQString::null, int realPort=0, TQString proxy=TQString::null) TDE_DEPRECATED
Set the status of the connection with respect to proxies.
void setAutoReconfig(bool ar)
Enable or disable automatic reconfiguration on initialize().
bool reconfig()
Trigger a reread of KSSL configuration and reInitialize() KSSL.
bool setSettings(KSSLSettings *settings)
Set a new KSSLSettings instance as the settings.
static bool doesSSLWork()
Determine if SSL is available and works.
void close()
Close the SSL session.
bool reInitialize()
Reinitialize OpenSSL.
bool takeSession(KSSLSession *session)
Set an SSL session to use.
KSSL(bool init=true)
Construct a KSSL object.
bool reusingSession() const
Determine if we are currently reusing an SSL session ID.
int accept(int sock)
Connect the SSL session to the remote host using the provided socket descriptor.
int write(const void *buf, int len)
Write data to the remote host via SSL.
int pending()
Determine if data is waiting to be read.
KSSLPeerInfo & peerInfo()
Obtain a reference to the information about the peer.
KSSLConnectionInfo & connectionInfo()
Obtain a reference to the connection information.
int seedWithEGD()
This will reseed the pseudo-random number generator with the EGD (entropy gathering daemon) if the EG...
KSSLSettings * settings()
One is built by the constructor, so this will only return a NULL pointer if you set one with setSetti...
int connect(int sock)
Connect the SSL session to the remote host using the provided socket descriptor.
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.
~KSSL()
Destroy this KSSL object.
bool TLSInit()
This is used for applicationss which do STARTTLS or something similar.
void setPeerHost(TQString realHost=TQString::null)
Set the peer hostname to be used for certificate verification.
const KSSLSession * session() const
Obtain a pointer to the session information.
int read(void *buf, int len)
Read data from the remote host via SSL.
bool initialize()
Initialize OpenSSL.