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>
48#include <ksslx509v3.h>
49#include <ksslpkcs12.h>
50#include <ksslsession.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());
265bool KSSL::setVerificationLogic() {
282 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
287 if (1 == d->kossl->SSL_set_session(d->m_ssl,
288 static_cast<SSL_SESSION*
>(d->session->_session))) {
289 kdDebug(7029) <<
"Session ID is being reused." << endl;
291 kdDebug(7029) <<
"Error attempting to reuse session." << endl;
306 int off = SSL_OP_ALL;
307 if (!d->lastInitTLS && !m_cfg->
tlsv1())
308 off |= SSL_OP_NO_TLSv1;
310 off |= SSL_OP_NO_SSLv3;
312 off |= SSL_OP_NO_SSLv2;
314 d->kossl->_SSL_set_options(d->m_ssl, off);
316 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
318 d->kossl->SSL_shutdown(d->m_ssl);
319 d->kossl->SSL_free(d->m_ssl);
323#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
324 d->kossl->SSL_set_tlsext_host_name(d->m_ssl, d->proxyPeer.ascii());
327 rc = d->kossl->SSL_accept(d->m_ssl);
331 kdDebug(7029) <<
"KSSL connected OK" << endl;
333 kdDebug(7029) <<
"KSSL accept failed - rc = " << rc << endl;
334 kdDebug(7029) <<
" ERROR = "
335 << d->kossl->SSL_get_error(d->m_ssl, rc) << endl;
336 d->kossl->SSL_shutdown(d->m_ssl);
337 d->kossl->SSL_free(d->m_ssl);
342 if (!d->kossl->_SSL_session_reused(d->m_ssl)) {
344 kdDebug(7029) <<
"Session reuse failed. New session used instead." << endl;
351 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
354 d->session->_session = sess;
371 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
376 if (1 == d->kossl->SSL_set_session(d->m_ssl,
377 static_cast<SSL_SESSION*
>(d->session->_session))) {
378 kdDebug(7029) <<
"Session ID is being reused." << endl;
380 kdDebug(7029) <<
"Error attempting to reuse session." << endl;
395 int off = SSL_OP_ALL;
396 if (!d->lastInitTLS && !m_cfg->
tlsv1())
397 off |= SSL_OP_NO_TLSv1;
399 off |= SSL_OP_NO_SSLv3;
401 off |= SSL_OP_NO_SSLv2;
403 d->kossl->_SSL_set_options(d->m_ssl, off);
405 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
407 d->kossl->SSL_shutdown(d->m_ssl);
408 d->kossl->SSL_free(d->m_ssl);
412#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
413 d->kossl->SSL_set_tlsext_host_name(d->m_ssl, d->proxyPeer.ascii());
417 rc = d->kossl->SSL_connect(d->m_ssl);
421 kdDebug(7029) <<
"KSSL connected OK" << endl;
423 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
424 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
428 kdDebug(7029) <<
"KSSL connect failed - rc = "
430 kdDebug(7029) <<
" ERROR = "
432 d->kossl->ERR_print_errors_fp(stderr);
433 d->kossl->SSL_shutdown(d->m_ssl);
434 d->kossl->SSL_free(d->m_ssl);
440 if (!d->kossl->_SSL_session_reused(d->m_ssl)) {
442 kdDebug(7029) <<
"Session reuse failed. New session used instead." << endl;
449 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
452 d->session->_session = sess;
467return d->kossl->SSL_pending(d->m_ssl);
479return d->kossl->SSL_peek(d->m_ssl, buf, len);
495 rc = d->kossl->SSL_read(d->m_ssl, (
char *)buf, len);
497 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
499 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
500 kdDebug(7029) <<
"SSL read() returning 0: " << err << endl;
501 if (maxIters-- > 0) {
508 kdDebug(7029) <<
"SSL READ ERROR: " << err << endl;
509 if (err != SSL_ERROR_NONE &&
510 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL) {
512 d->kossl->ERR_print_errors_fp(stderr);
531 int rc = d->kossl->SSL_write(d->m_ssl, (
const char *)buf, len);
533 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
535 if (err == SSL_ERROR_WANT_WRITE) {
540 kdDebug(7029) <<
"SSL WRITE ERROR: " << err << endl;
541 if (err != SSL_ERROR_NONE &&
542 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL)
559 m_bAutoReconfig = ar;
571bool KSSL::m_bSSLWorks =
true;
573bool KSSL::m_bSSLWorks =
false;
581void KSSL::setConnectionInfo() {
587 sc = d->kossl->SSL_get_current_cipher(d->m_ssl);
589 kdDebug(7029) <<
"KSSL get current cipher failed - we're probably gonna crash!" << endl;
594 m_ci.m_iCipherUsedBits = d->kossl->SSL_CIPHER_get_bits(sc, &(m_ci.m_iCipherBits));
596 m_ci.m_cipherVersion = d->kossl->SSL_CIPHER_get_version(sc);
598 m_ci.m_cipherName = d->kossl->SSL_CIPHER_get_name(sc);
600 m_ci.m_cipherDescription = d->kossl->SSL_CIPHER_description(sc, buf, 1023);
606void KSSL::setPeerInfo() {
609 m_pi.m_cert.
setCert(d->kossl->SSL_get_peer_certificate(d->m_ssl));
610 STACK_OF(X509) *xs = d->kossl->SSL_get_peer_cert_chain(d->m_ssl);
612 xs =
reinterpret_cast<STACK_OF(X509)*
>(d->kossl->OPENSSL_sk_dup(xs));
613 m_pi.m_cert.setChain((
void *)xs);
625 d->proxyPeer = realHost;
647 if (!x || !k)
return false;
652 rc = d->kossl->SSL_CTX_use_certificate(d->m_ctx, x);
654 kdDebug(7029) <<
"KSSL - SSL_CTX_use_certificate failed. rc = " << rc << endl;
658 rc = d->kossl->SSL_CTX_use_PrivateKey(d->m_ctx, k);
660 kdDebug(7029) <<
"KSSL - SSL_CTX_use_PrivateKey failed. rc = " << rc << endl;
676 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.
KSSLSettings * settings()
One is built by the constructor, so this will only return a NULL pointer if you set one with setSetti...
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...
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.