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> 54 #define sk_dup d->kossl->sk_dup 86 m_bAutoReconfig =
true;
107 if (m_cfg->useEGD() && !m_cfg->getEGDPath().isEmpty()) {
108 rc = d->kossl->RAND_egd(m_cfg->getEGDPath().latin1());
110 kdDebug(7029) <<
"KSSL: Error seeding PRNG with the EGD." << endl;
111 else kdDebug(7029) <<
"KSSL: PRNG was seeded with " << rc
112 <<
" bytes from the EGD." << endl;
113 }
else if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) {
114 rc = d->kossl->RAND_load_file(m_cfg->getEGDPath().latin1(), -1);
116 kdDebug(7029) <<
"KSSL: Error seeding PRNG with the entropy file." << endl;
117 else kdDebug(7029) <<
"KSSL: PRNG was seeded with " << rc
118 <<
" bytes from the entropy file." << endl;
138 d->m_meth = d->kossl->TLSv1_client_method();
139 d->lastInitTLS =
true;
143 d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth);
144 if (d->m_ctx == 0L) {
149 TQString clist = m_cfg->getCipherList();
151 if (!clist.isEmpty())
152 d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast<char *>(clist.ascii()));
164 kdDebug(7029) <<
"KSSL initialize" << endl;
173 d->lastInitTLS =
false;
177 if (!m_cfg->tlsv1() && !m_cfg->sslv3() && m_cfg->sslv2())
178 d->m_meth = d->kossl->SSLv2_client_method();
179 else if (m_cfg->tlsv1() && !m_cfg->sslv3() && !m_cfg->sslv2())
180 d->m_meth = d->kossl->TLSv1_client_method();
181 else if (!m_cfg->tlsv1() && m_cfg->sslv3() && !m_cfg->sslv2())
182 d->m_meth = d->kossl->SSLv3_client_method();
183 else d->m_meth = d->kossl->SSLv23_client_method();
191 d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth);
192 if (d->m_ctx == 0L) {
197 TQString clist = m_cfg->getCipherList();
198 kdDebug(7029) <<
"Cipher list: " << clist << endl;
199 if (!clist.isEmpty())
200 d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast<char *>(clist.ascii()));
219 static_cast<SSL_SESSION*
>(session->_session)->references++;
222 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);
247 if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) {
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 (static_cast<SSL_SESSION*>(d->session->_session)->sess_cert == 0)
289 kdDebug(7029) <<
"Can't reuse session, no certificate." << endl;
292 }
else if (1 == d->kossl->SSL_set_session(d->m_ssl,
293 static_cast<SSL_SESSION*>(d->session->_session))) {
294 kdDebug(7029) <<
"Session ID is being reused." << endl;
296 kdDebug(7029) <<
"Error attempting to reuse session." << endl;
311 int off = SSL_OP_ALL;
312 if (!d->lastInitTLS && !m_cfg->tlsv1())
313 off |= SSL_OP_NO_TLSv1;
315 off |= SSL_OP_NO_SSLv3;
317 off |= SSL_OP_NO_SSLv2;
319 d->kossl->SSL_set_options(d->m_ssl, off);
321 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
323 d->kossl->SSL_shutdown(d->m_ssl);
324 d->kossl->SSL_free(d->m_ssl);
329 rc = d->kossl->SSL_accept(d->m_ssl);
333 kdDebug(7029) <<
"KSSL connected OK" << endl;
335 kdDebug(7029) <<
"KSSL accept failed - rc = " << rc << endl;
336 kdDebug(7029) <<
" ERROR = " 337 << d->kossl->SSL_get_error(d->m_ssl, rc) << endl;
338 d->kossl->SSL_shutdown(d->m_ssl);
339 d->kossl->SSL_free(d->m_ssl);
344 if (!d->kossl->SSL_session_reused(d->m_ssl)) {
346 kdDebug(7029) <<
"Session reuse failed. New session used instead." << endl;
353 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
356 d->session->_session = sess;
373 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
378 if (static_cast<SSL_SESSION*>(d->session->_session)->sess_cert == 0)
380 kdDebug(7029) <<
"Can't reuse session, no certificate." << endl;
383 }
else if (1 == d->kossl->SSL_set_session(d->m_ssl,
384 static_cast<SSL_SESSION*>(d->session->_session))) {
385 kdDebug(7029) <<
"Session ID is being reused." << endl;
387 kdDebug(7029) <<
"Error attempting to reuse session." << endl;
402 int off = SSL_OP_ALL;
403 if (!d->lastInitTLS && !m_cfg->tlsv1())
404 off |= SSL_OP_NO_TLSv1;
406 off |= SSL_OP_NO_SSLv3;
408 off |= SSL_OP_NO_SSLv2;
410 d->kossl->SSL_set_options(d->m_ssl, off);
412 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
414 d->kossl->SSL_shutdown(d->m_ssl);
415 d->kossl->SSL_free(d->m_ssl);
421 rc = d->kossl->SSL_connect(d->m_ssl);
425 kdDebug(7029) <<
"KSSL connected OK" << endl;
427 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
428 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
432 kdDebug(7029) <<
"KSSL connect failed - rc = " 434 kdDebug(7029) <<
" ERROR = " 436 d->kossl->ERR_print_errors_fp(stderr);
437 d->kossl->SSL_shutdown(d->m_ssl);
438 d->kossl->SSL_free(d->m_ssl);
444 if (!d->kossl->SSL_session_reused(d->m_ssl)) {
446 kdDebug(7029) <<
"Session reuse failed. New session used instead." << endl;
453 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
456 d->session->_session = sess;
471 return d->kossl->SSL_pending(d->m_ssl);
483 return d->kossl->SSL_peek(d->m_ssl, buf, len);
499 rc = d->kossl->SSL_read(d->m_ssl, (
char *)buf, len);
501 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
503 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
504 kdDebug(7029) <<
"SSL read() returning 0: " << err << endl;
505 if (maxIters-- > 0) {
512 kdDebug(7029) <<
"SSL READ ERROR: " << err << endl;
513 if (err != SSL_ERROR_NONE &&
514 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL) {
516 d->kossl->ERR_print_errors_fp(stderr);
535 int rc = d->kossl->SSL_write(d->m_ssl, (
const char *)buf, len);
537 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
539 if (err == SSL_ERROR_WANT_WRITE) {
544 kdDebug(7029) <<
"SSL WRITE ERROR: " << err << endl;
545 if (err != SSL_ERROR_NONE &&
546 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL)
558 return reInitialize();
563 m_bAutoReconfig = ar;
575 bool KSSL::m_bSSLWorks =
true;
577 bool KSSL::m_bSSLWorks =
false;
585 void KSSL::setConnectionInfo() {
591 sc = d->kossl->SSL_get_current_cipher(d->m_ssl);
593 kdDebug(7029) <<
"KSSL get current cipher failed - we're probably gonna crash!" << endl;
598 m_ci.m_iCipherUsedBits = d->kossl->SSL_CIPHER_get_bits(sc, &(m_ci.m_iCipherBits));
600 m_ci.m_cipherVersion = d->kossl->SSL_CIPHER_get_version(sc);
602 m_ci.m_cipherName = d->kossl->SSL_CIPHER_get_name(sc);
604 m_ci.m_cipherDescription = d->kossl->SSL_CIPHER_description(sc, buf, 1023);
610 void KSSL::setPeerInfo() {
612 m_pi.setPeerHost(d->proxyPeer);
613 m_pi.m_cert.setCert(d->kossl->SSL_get_peer_certificate(d->m_ssl));
614 STACK_OF(X509) *xs = d->kossl->SSL_get_peer_cert_chain(d->m_ssl);
616 xs = sk_X509_dup(xs);
617 m_pi.m_cert.setChain((
void *)xs);
629 d->proxyPeer = realHost;
651 if (!x || !k)
return false;
656 rc = d->kossl->SSL_CTX_use_certificate(d->m_ctx, x);
658 kdDebug(7029) <<
"KSSL - SSL_CTX_use_certificate failed. rc = " << rc << endl;
662 rc = d->kossl->SSL_CTX_use_PrivateKey(d->m_ctx, k);
664 kdDebug(7029) <<
"KSSL - SSL_CTX_use_PrivateKey failed. rc = " << rc << endl;
682 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 initialize()
Initialize OpenSSL.
int read(void *buf, int len)
Read data from the remote host via SSL.
KSSLX509V3 & x509V3Extensions()
Access the X.509v3 parameters.
bool TLSInit()
This is used for applicationss which do STARTTLS or something similar.
KSSL(bool init=true)
Construct a KSSL object.
~KSSL()
Destroy this KSSL object.
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.
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.
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.
void close()
Close the SSL session.
bool setSession(const KSSLSession *session)
Set an SSL session to use.
static KOpenSSLProxy * self()
Return an instance of class KOpenSSLProxy * You cannot delete this object.
bool reInitialize()
Reinitialize OpenSSL.
KDE SSL Connection Information.