kssl.cc00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024
00025
00026
00027 #ifdef KSSL_HAVE_SSL
00028 #include <unistd.h>
00029 #include <netinet/in.h>
00030 #include <sys/socket.h>
00031 #define crypt _openssl_crypt
00032 #include <openssl/ssl.h>
00033 #include <openssl/x509.h>
00034 #include <openssl/x509v3.h>
00035 #include <openssl/pem.h>
00036 #include <openssl/rand.h>
00037 #undef crypt
00038 #endif
00039
00040 #include "kssl.h"
00041
00042 #include <kdebug.h>
00043 #include <kstandarddirs.h>
00044 #include <ksock.h>
00045 #include <ksockaddr.h>
00046
00047 #include <kopenssl.h>
00048 #include <ksslx509v3.h>
00049 #include <ksslpkcs12.h>
00050 #include <ksslsession.h>
00051 #include <klocale.h>
00052 #include <ksocks.h>
00053
00054 #define sk_dup d->kossl->sk_dup
00055
00056 class KSSLPrivate {
00057 public:
00058 KSSLPrivate() {
00059 lastInitTLS = false;
00060 kossl = KOpenSSLProxy::self();
00061 session = 0L;
00062 }
00063
00064 ~KSSLPrivate() {
00065 delete session;
00066 session = 0L;
00067 }
00068
00069 bool lastInitTLS;
00070 KSSLCertificate::KSSLValidation m_cert_vfy_res;
00071 QString proxyPeer;
00072
00073 #ifdef KSSL_HAVE_SSL
00074 SSL *m_ssl;
00075 SSL_CTX *m_ctx;
00076 SSL_METHOD *m_meth;
00077 #endif
00078 KSSLSession *session;
00079 KOSSL *kossl;
00080 };
00081
00082
00083 KSSL::KSSL(bool init) {
00084 d = new KSSLPrivate;
00085 m_bInit = false;
00086 m_bAutoReconfig = true;
00087 m_cfg = new KSSLSettings();
00088 #ifdef KSSL_HAVE_SSL
00089 d->m_ssl = 0L;
00090 #endif
00091
00092 if (init)
00093 initialize();
00094 }
00095
00096
00097 KSSL::~KSSL() {
00098 close();
00099 delete m_cfg;
00100 delete d;
00101 }
00102
00103
00104 int KSSL::seedWithEGD() {
00105 int rc = 0;
00106 #ifdef KSSL_HAVE_SSL
00107 if (m_cfg->useEGD() && !m_cfg->getEGDPath().isEmpty()) {
00108 rc = d->kossl->RAND_egd(m_cfg->getEGDPath().latin1());
00109 if (rc < 0)
00110 kdDebug(7029) << "KSSL: Error seeding PRNG with the EGD." << endl;
00111 else kdDebug(7029) << "KSSL: PRNG was seeded with " << rc
00112 << " bytes from the EGD." << endl;
00113 } else if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) {
00114 rc = d->kossl->RAND_load_file(m_cfg->getEGDPath().latin1(), -1);
00115 if (rc < 0)
00116 kdDebug(7029) << "KSSL: Error seeding PRNG with the entropy file." << endl;
00117 else kdDebug(7029) << "KSSL: PRNG was seeded with " << rc
00118 << " bytes from the entropy file." << endl;
00119 }
00120 #endif
00121 return rc;
00122 }
00123
00124
00125 bool KSSL::TLSInit() {
00126 #ifdef KSSL_HAVE_SSL
00127
00128 if (m_bInit)
00129 return false;
00130
00131 if (m_bAutoReconfig)
00132 m_cfg->load();
00133
00134 if (!m_cfg->tlsv1())
00135 return false;
00136
00137 seedWithEGD();
00138 d->m_meth = d->kossl->TLSv1_client_method();
00139 d->lastInitTLS = true;
00140
00141 d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth);
00142 if (d->m_ctx == 0L) {
00143 return false;
00144 }
00145
00146
00147 QString clist = m_cfg->getCipherList();
00148
00149 if (!clist.isEmpty())
00150 d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast<char *>(clist.ascii()));
00151
00152 m_bInit = true;
00153 return true;
00154 #else
00155 return false;
00156 #endif
00157 }
00158
00159
00160 bool KSSL::initialize() {
00161 #ifdef KSSL_HAVE_SSL
00162 kdDebug(7029) << "KSSL initialize" << endl;
00163 if (m_bInit)
00164 return false;
00165
00166 if (m_bAutoReconfig)
00167 m_cfg->load();
00168
00169 seedWithEGD();
00170
00171 d->lastInitTLS = false;
00172
00173 m_pi.reset();
00174
00175 if (m_cfg->sslv2() && !m_cfg->sslv3())
00176 d->m_meth = d->kossl->SSLv2_client_method();
00177 else if (m_cfg->sslv3() && !m_cfg->sslv2())
00178 d->m_meth = d->kossl->SSLv3_client_method();
00179 else d->m_meth = d->kossl->SSLv23_client_method();
00180
00181
00182
00183
00184
00185
00186
00187 d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth);
00188 if (d->m_ctx == 0L) {
00189 return false;
00190 }
00191
00192
00193 QString clist = m_cfg->getCipherList();
00194 kdDebug(7029) << "Cipher list: " << clist << endl;
00195 if (!clist.isEmpty())
00196 d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast<char *>(clist.ascii()));
00197
00198 m_bInit = true;
00199 return true;
00200 #else
00201 return false;
00202 #endif
00203 }
00204
00205
00206 bool KSSL::setSession(const KSSLSession *session) {
00207 #ifdef KSSL_HAVE_SSL
00208 if (!session) {
00209 delete d->session;
00210 d->session = 0L;
00211 return true;
00212 }
00213
00214
00215 static_cast<SSL_SESSION*>(session->_session)->references++;
00216
00217 d->session = new KSSLSession;
00218 d->session->_session = session->_session;
00219
00220 return true;
00221 #else
00222 return false;
00223 #endif
00224 }
00225
00226
00227 void KSSL::close() {
00228 #ifdef KSSL_HAVE_SSL
00229
00230 if (!m_bInit)
00231 return;
00232
00233 delete d->session;
00234 d->session = 0L;
00235
00236 if (d->m_ssl) {
00237 d->kossl->SSL_shutdown(d->m_ssl);
00238 d->kossl->SSL_free(d->m_ssl);
00239 d->m_ssl = 0L;
00240 }
00241
00242 d->kossl->SSL_CTX_free(d->m_ctx);
00243 if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) {
00244 d->kossl->RAND_write_file(m_cfg->getEGDPath().latin1());
00245 }
00246
00247 m_bInit = false;
00248 #endif
00249 }
00250
00251
00252 bool KSSL::reInitialize() {
00253 close();
00254 return initialize();
00255 }
00256
00257
00258
00259
00260
00261 bool KSSL::setVerificationLogic() {
00262 #if 0
00263 #ifdef KSSL_HAVE_SSL
00264
00265
00266 #endif
00267 #endif
00268 return true;
00269 }
00270
00271
00272 int KSSL::accept(int sock) {
00273 #ifdef KSSL_HAVE_SSL
00274
00275 int rc;
00276 if (!m_bInit)
00277 return -1;
00278 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
00279 if (!d->m_ssl)
00280 return -1;
00281
00282 if (d->session) {
00283 if (static_cast<SSL_SESSION*>(d->session->_session)->sess_cert == 0)
00284 {
00285 kdDebug(7029) << "Can't reuse session, no certificate." << endl;
00286 delete d->session;
00287 d->session = 0;
00288 } else if (1 == d->kossl->SSL_set_session(d->m_ssl,
00289 static_cast<SSL_SESSION*>(d->session->_session))) {
00290 kdDebug(7029) << "Session ID is being reused." << endl;
00291 } else {
00292 kdDebug(7029) << "Error attempting to reuse session." << endl;
00293 delete d->session;
00294 d->session = 0;
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 if (!d->lastInitTLS)
00308 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_NO_TLSv1);
00309
00310 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_ALL);
00311
00312 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
00313 if (rc == 0) {
00314 d->kossl->SSL_shutdown(d->m_ssl);
00315 d->kossl->SSL_free(d->m_ssl);
00316 d->m_ssl = 0;
00317 return rc;
00318 }
00319
00320 rc = d->kossl->SSL_accept(d->m_ssl);
00321 if (rc == 1) {
00322 setConnectionInfo();
00323 setPeerInfo();
00324 kdDebug(7029) << "KSSL connected OK" << endl;
00325 } else {
00326 kdDebug(7029) << "KSSL accept failed - rc = " << rc << endl;
00327 kdDebug(7029) << " ERROR = "
00328 << d->kossl->SSL_get_error(d->m_ssl, rc) << endl;
00329 d->kossl->SSL_shutdown(d->m_ssl);
00330 d->kossl->SSL_free(d->m_ssl);
00331 d->m_ssl = 0;
00332 return -1;
00333 }
00334
00335 if (!d->kossl->SSL_session_reused(d->m_ssl)) {
00336 if (d->session) {
00337 kdDebug(7029) << "Session reuse failed. New session used instead." << endl;
00338 delete d->session;
00339 d->session = 0L;
00340 }
00341 }
00342
00343 if (!d->session) {
00344 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
00345 if (sess) {
00346 d->session = new KSSLSession;
00347 d->session->_session = sess;
00348 }
00349 }
00350
00351 return rc;
00352 #else
00353 return -1;
00354 #endif
00355 }
00356
00357
00358 int KSSL::connect(int sock) {
00359 #ifdef KSSL_HAVE_SSL
00360
00361 int rc;
00362 if (!m_bInit)
00363 return -1;
00364 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
00365 if (!d->m_ssl)
00366 return -1;
00367
00368 if (d->session) {
00369 if (static_cast<SSL_SESSION*>(d->session->_session)->sess_cert == 0)
00370 {
00371 kdDebug(7029) << "Can't reuse session, no certificate." << endl;
00372 delete d->session;
00373 d->session = 0;
00374 } else if (1 == d->kossl->SSL_set_session(d->m_ssl,
00375 static_cast<SSL_SESSION*>(d->session->_session))) {
00376 kdDebug(7029) << "Session ID is being reused." << endl;
00377 } else {
00378 kdDebug(7029) << "Error attempting to reuse session." << endl;
00379 delete d->session;
00380 d->session = 0;
00381 }
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 if (!d->lastInitTLS)
00394 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_NO_TLSv1);
00395
00396 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_ALL);
00397
00398 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
00399 if (rc == 0) {
00400 d->kossl->SSL_shutdown(d->m_ssl);
00401 d->kossl->SSL_free(d->m_ssl);
00402 d->m_ssl = 0;
00403 return rc;
00404 }
00405
00406 connect_again:
00407 rc = d->kossl->SSL_connect(d->m_ssl);
00408 if (rc == 1) {
00409 setConnectionInfo();
00410 setPeerInfo();
00411 kdDebug(7029) << "KSSL connected OK" << endl;
00412 } else {
00413 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
00414 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
00415
00416 goto connect_again;
00417 } else {
00418 kdDebug(7029) << "KSSL connect failed - rc = "
00419 << rc << endl;
00420 kdDebug(7029) << " ERROR = "
00421 << err << endl;
00422 d->kossl->ERR_print_errors_fp(stderr);
00423 d->kossl->SSL_shutdown(d->m_ssl);
00424 d->kossl->SSL_free(d->m_ssl);
00425 d->m_ssl = 0;
00426 return -1;
00427 }
00428 }
00429
00430 if (!d->kossl->SSL_session_reused(d->m_ssl)) {
00431 if (d->session) {
00432 kdDebug(7029) << "Session reuse failed. New session used instead." << endl;
00433 delete d->session;
00434 d->session = 0L;
00435 }
00436 }
00437
00438 if (!d->session) {
00439 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
00440 if (sess) {
00441 d->session = new KSSLSession;
00442 d->session->_session = sess;
00443 }
00444 }
00445
00446 return rc;
00447 #else
00448 return -1;
00449 #endif
00450 }
00451
00452
00453 int KSSL::pending() {
00454 #ifdef KSSL_HAVE_SSL
00455 if (!m_bInit)
00456 return -1;
00457 return d->kossl->SSL_pending(d->m_ssl);
00458 #else
00459 return -1;
00460 #endif
00461 }
00462
00463
00464 int KSSL::peek(void *buf, int len) {
00465 #ifdef KSSL_HAVE_SSL
00466 if (!m_bInit)
00467 return -1;
00468
00469 return d->kossl->SSL_peek(d->m_ssl, buf, len);
00470 #else
00471 return -1;
00472 #endif
00473 }
00474
00475
00476 int KSSL::read(void *buf, int len) {
00477 #ifdef KSSL_HAVE_SSL
00478 int rc = 0;
00479 int maxIters = 10;
00480
00481 if (!m_bInit)
00482 return -1;
00483
00484 read_again:
00485 rc = d->kossl->SSL_read(d->m_ssl, (char *)buf, len);
00486 if (rc <= 0) {
00487 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
00488
00489 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
00490 kdDebug(7029) << "SSL read() returning 0: " << err << endl;
00491 if (maxIters-- > 0) {
00492 ::usleep(20000);
00493 goto read_again;
00494 }
00495 return 0;
00496 }
00497
00498 kdDebug(7029) << "SSL READ ERROR: " << err << endl;
00499 if (err != SSL_ERROR_NONE &&
00500 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL) {
00501 rc = -1;
00502 }
00503
00504
00505
00506 }
00507 return rc;
00508 #else
00509 return -1;
00510 #endif
00511 }
00512
00513
00514 int KSSL::write(const void *buf, int len) {
00515 #ifdef KSSL_HAVE_SSL
00516 if (!m_bInit)
00517 return -1;
00518
00519 write_again:
00520 int rc = d->kossl->SSL_write(d->m_ssl, (const char *)buf, len);
00521 if (rc <= 0) {
00522 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
00523
00524 if (err == SSL_ERROR_WANT_WRITE) {
00525 ::usleep(20000);
00526 goto write_again;
00527 }
00528
00529 kdDebug(7029) << "SSL WRITE ERROR: " << err << endl;
00530 if (err != SSL_ERROR_NONE &&
00531 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL)
00532 rc = -1;
00533 }
00534
00535 return rc;
00536 #else
00537 return -1;
00538 #endif
00539 }
00540
00541
00542 bool KSSL::reconfig() {
00543 return reInitialize();
00544 }
00545
00546
00547 void KSSL::setAutoReconfig(bool ar) {
00548 m_bAutoReconfig = ar;
00549 }
00550
00551
00552 bool KSSL::setSettings(KSSLSettings *settings) {
00553 delete m_cfg;
00554 m_cfg = settings;
00555 return reconfig();
00556 }
00557
00558
00559 #ifdef KSSL_HAVE_SSL
00560 bool KSSL::m_bSSLWorks = true;
00561 #else
00562 bool KSSL::m_bSSLWorks = false;
00563 #endif
00564
00565 bool KSSL::doesSSLWork() {
00566 return m_bSSLWorks;
00567 }
00568
00569
00570 void KSSL::setConnectionInfo() {
00571 #ifdef KSSL_HAVE_SSL
00572 SSL_CIPHER *sc;
00573 char buf[1024];
00574
00575 buf[0] = 0;
00576 sc = d->kossl->SSL_get_current_cipher(d->m_ssl);
00577 if (!sc) {
00578 kdDebug(7029) << "KSSL get current cipher failed - we're probably gonna crash!" << endl;
00579 return;
00580 }
00581
00582
00583 m_ci.m_iCipherUsedBits = d->kossl->SSL_CIPHER_get_bits(sc, &(m_ci.m_iCipherBits));
00584
00585 m_ci.m_cipherVersion = d->kossl->SSL_CIPHER_get_version(sc);
00586
00587 m_ci.m_cipherName = d->kossl->SSL_CIPHER_get_name(sc);
00588
00589 m_ci.m_cipherDescription = d->kossl->SSL_CIPHER_description(sc, buf, 1023);
00590
00591 #endif
00592 }
00593
00594
00595 void KSSL::setPeerInfo() {
00596 #ifdef KSSL_HAVE_SSL
00597 m_pi.setPeerHost(d->proxyPeer);
00598 m_pi.m_cert.setCert(d->kossl->SSL_get_peer_certificate(d->m_ssl));
00599 STACK_OF(X509) *xs = d->kossl->SSL_get_peer_cert_chain(d->m_ssl);
00600 if (xs)
00601 xs = sk_X509_dup(xs);
00602 m_pi.m_cert.setChain((void *)xs);
00603 #endif
00604 }
00605
00606
00607 KSSLConnectionInfo& KSSL::connectionInfo() {
00608 return m_ci;
00609 }
00610
00611
00612
00613 void KSSL::setPeerHost(QString realHost) {
00614 d->proxyPeer = realHost;
00615 }
00616
00617
00618 void KSSL::setProxyUse(bool, QString, int, QString) {
00619 }
00620
00621
00622 KSSLPeerInfo& KSSL::peerInfo() {
00623 return m_pi;
00624 }
00625
00626
00627 bool KSSL::setClientCertificate(KSSLPKCS12 *pkcs) {
00628 #ifdef KSSL_HAVE_SSL
00629 if (!pkcs || !pkcs->getCertificate())
00630 return false;
00631
00632 int rc;
00633 X509 *x = pkcs->getCertificate()->getCert();
00634 EVP_PKEY *k = pkcs->getPrivateKey();
00635
00636 if (!x || !k) return false;
00637
00638 if (!pkcs->getCertificate()->x509V3Extensions().certTypeSSLClient())
00639 return false;
00640
00641 rc = d->kossl->SSL_CTX_use_certificate(d->m_ctx, x);
00642 if (rc <= 0) {
00643 kdDebug(7029) << "KSSL - SSL_CTX_use_certificate failed. rc = " << rc << endl;
00644 return false;
00645 }
00646
00647 rc = d->kossl->SSL_CTX_use_PrivateKey(d->m_ctx, k);
00648 if (rc <= 0) {
00649 kdDebug(7029) << "KSSL - SSL_CTX_use_PrivateKey failed. rc = " << rc << endl;
00650 return false;
00651 }
00652
00653 return true;
00654 #else
00655 return false;
00656 #endif
00657 }
00658
00659 #undef sk_dup
00660
00661 const KSSLSession* KSSL::session() const {
00662 return d->session;
00663 }
00664
00665 bool KSSL::reusingSession() const {
00666 #ifdef KSSL_HAVE_SSL
00667 return (d->m_ssl && d->kossl->SSL_session_reused(d->m_ssl));
00668 #else
00669 return false;
00670 #endif
00671 }
00672
00673
|