kssl.cc
00001
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 if (d->session) {
00234 delete d->session;
00235 d->session = 0L;
00236 }
00237
00238 if (d->m_ssl) {
00239 d->kossl->SSL_shutdown(d->m_ssl);
00240 d->kossl->SSL_free(d->m_ssl);
00241 d->m_ssl = 0L;
00242 }
00243
00244 d->kossl->SSL_CTX_free(d->m_ctx);
00245 if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) {
00246 d->kossl->RAND_write_file(m_cfg->getEGDPath().latin1());
00247 }
00248
00249 m_bInit = false;
00250 #endif
00251 }
00252
00253
00254 bool KSSL::reInitialize() {
00255 close();
00256 return initialize();
00257 }
00258
00259
00260
00261
00262
00263 bool KSSL::setVerificationLogic() {
00264 #if 0
00265 #ifdef KSSL_HAVE_SSL
00266
00267
00268 #endif
00269 #endif
00270 return true;
00271 }
00272
00273
00274 int KSSL::accept(int sock) {
00275 #ifdef KSSL_HAVE_SSL
00276
00277 int rc;
00278 if (!m_bInit)
00279 return -1;
00280 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
00281 if (!d->m_ssl)
00282 return -1;
00283
00284 if (d->session) {
00285 if (static_cast<SSL_SESSION*>(d->session->_session)->sess_cert == 0)
00286 {
00287 kdDebug(7029) << "Can't reuse session, no certificate." << endl;
00288 delete d->session;
00289 d->session = 0;
00290 } else if (1 == d->kossl->SSL_set_session(d->m_ssl,
00291 static_cast<SSL_SESSION*>(d->session->_session))) {
00292 kdDebug(7029) << "Session ID is being reused." << endl;
00293 } else {
00294 kdDebug(7029) << "Error attempting to reuse session." << endl;
00295 delete d->session;
00296 d->session = 0;
00297 }
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 if (!d->lastInitTLS)
00310 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_NO_TLSv1);
00311
00312 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_ALL);
00313
00314 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
00315 if (rc == 0) {
00316 d->kossl->SSL_shutdown(d->m_ssl);
00317 d->kossl->SSL_free(d->m_ssl);
00318 d->m_ssl = 0;
00319 return rc;
00320 }
00321
00322 rc = d->kossl->SSL_accept(d->m_ssl);
00323 if (rc == 1) {
00324 setConnectionInfo();
00325 setPeerInfo();
00326 kdDebug(7029) << "KSSL connected OK" << endl;
00327 } else {
00328 kdDebug(7029) << "KSSL accept failed - rc = " << rc << endl;
00329 kdDebug(7029) << " ERROR = "
00330 << d->kossl->SSL_get_error(d->m_ssl, rc) << endl;
00331 d->kossl->SSL_shutdown(d->m_ssl);
00332 d->kossl->SSL_free(d->m_ssl);
00333 d->m_ssl = 0;
00334 return -1;
00335 }
00336
00337 if (!d->kossl->SSL_session_reused(d->m_ssl)) {
00338 if (d->session) {
00339 kdDebug(7029) << "Session reuse failed. New session used instead." << endl;
00340 delete d->session;
00341 d->session = 0L;
00342 }
00343 }
00344
00345 if (!d->session) {
00346 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
00347 if (sess) {
00348 d->session = new KSSLSession;
00349 d->session->_session = sess;
00350 }
00351 }
00352
00353 return rc;
00354 #else
00355 return -1;
00356 #endif
00357 }
00358
00359
00360 int KSSL::connect(int sock) {
00361 #ifdef KSSL_HAVE_SSL
00362
00363 int rc;
00364 if (!m_bInit)
00365 return -1;
00366 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
00367 if (!d->m_ssl)
00368 return -1;
00369
00370 if (d->session) {
00371 if (static_cast<SSL_SESSION*>(d->session->_session)->sess_cert == 0)
00372 {
00373 kdDebug(7029) << "Can't reuse session, no certificate." << endl;
00374 delete d->session;
00375 d->session = 0;
00376 } else if (1 == d->kossl->SSL_set_session(d->m_ssl,
00377 static_cast<SSL_SESSION*>(d->session->_session))) {
00378 kdDebug(7029) << "Session ID is being reused." << endl;
00379 } else {
00380 kdDebug(7029) << "Error attempting to reuse session." << endl;
00381 delete d->session;
00382 d->session = 0;
00383 }
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 if (!d->lastInitTLS)
00396 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_NO_TLSv1);
00397
00398 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_ALL);
00399
00400 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
00401 if (rc == 0) {
00402 d->kossl->SSL_shutdown(d->m_ssl);
00403 d->kossl->SSL_free(d->m_ssl);
00404 d->m_ssl = 0;
00405 return rc;
00406 }
00407
00408 connect_again:
00409 rc = d->kossl->SSL_connect(d->m_ssl);
00410 if (rc == 1) {
00411 setConnectionInfo();
00412 setPeerInfo();
00413 kdDebug(7029) << "KSSL connected OK" << endl;
00414 } else {
00415 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
00416 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
00417
00418 goto connect_again;
00419 } else {
00420 kdDebug(7029) << "KSSL connect failed - rc = "
00421 << rc << endl;
00422 kdDebug(7029) << " ERROR = "
00423 << err << endl;
00424 d->kossl->ERR_print_errors_fp(stderr);
00425 d->kossl->SSL_shutdown(d->m_ssl);
00426 d->kossl->SSL_free(d->m_ssl);
00427 d->m_ssl = 0;
00428 return -1;
00429 }
00430 }
00431
00432 if (!d->kossl->SSL_session_reused(d->m_ssl)) {
00433 if (d->session) {
00434 kdDebug(7029) << "Session reuse failed. New session used instead." << endl;
00435 delete d->session;
00436 d->session = 0L;
00437 }
00438 }
00439
00440 if (!d->session) {
00441 SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl);
00442 if (sess) {
00443 d->session = new KSSLSession;
00444 d->session->_session = sess;
00445 }
00446 }
00447
00448 return rc;
00449 #else
00450 return -1;
00451 #endif
00452 }
00453
00454
00455 int KSSL::pending() {
00456 #ifdef KSSL_HAVE_SSL
00457 if (!m_bInit)
00458 return -1;
00459 return d->kossl->SSL_pending(d->m_ssl);
00460 #else
00461 return -1;
00462 #endif
00463 }
00464
00465
00466 int KSSL::peek(void *buf, int len) {
00467 #ifdef KSSL_HAVE_SSL
00468 if (!m_bInit)
00469 return -1;
00470 return d->kossl->SSL_peek(d->m_ssl, buf, len);
00471 #else
00472 return -1;
00473 #endif
00474 }
00475
00476
00477 int KSSL::read(void *buf, int len) {
00478 #ifdef KSSL_HAVE_SSL
00479 int rc = 0;
00480
00481 if (!m_bInit)
00482 return -1;
00483
00484 rc = d->kossl->SSL_read(d->m_ssl, (char *)buf, len);
00485 if (rc <= 0) {
00486 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
00487
00488 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
00489 return 0;
00490 }
00491
00492 kdDebug(7029) << "SSL READ ERROR: " << err << endl;
00493 if (err != SSL_ERROR_NONE &&
00494 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL) {
00495 rc = -1;
00496 }
00497
00498
00499
00500 }
00501 return rc;
00502 #else
00503 return -1;
00504 #endif
00505 }
00506
00507
00508 int KSSL::write(const void *buf, int len) {
00509 #ifdef KSSL_HAVE_SSL
00510 if (!m_bInit)
00511 return -1;
00512
00513 int rc = d->kossl->SSL_write(d->m_ssl, (const char *)buf, len);
00514 if (rc <= 0) {
00515 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
00516
00517 if (err == SSL_ERROR_WANT_WRITE) {
00518 return 0;
00519 }
00520
00521 kdDebug(7029) << "SSL WRITE ERROR: " << err << endl;
00522 if (err != SSL_ERROR_NONE &&
00523 err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL)
00524 rc = -1;
00525 }
00526
00527 return rc;
00528 #else
00529 return -1;
00530 #endif
00531 }
00532
00533
00534 bool KSSL::reconfig() {
00535 return reInitialize();
00536 }
00537
00538
00539 void KSSL::setAutoReconfig(bool ar) {
00540 m_bAutoReconfig = ar;
00541 }
00542
00543
00544 bool KSSL::setSettings(KSSLSettings *settings) {
00545 delete m_cfg;
00546 m_cfg = settings;
00547 return reconfig();
00548 }
00549
00550
00551 #ifdef KSSL_HAVE_SSL
00552 bool KSSL::m_bSSLWorks = true;
00553 #else
00554 bool KSSL::m_bSSLWorks = false;
00555 #endif
00556
00557 bool KSSL::doesSSLWork() {
00558 return m_bSSLWorks;
00559 }
00560
00561
00562 void KSSL::setConnectionInfo() {
00563 #ifdef KSSL_HAVE_SSL
00564 SSL_CIPHER *sc;
00565 char buf[1024];
00566
00567 buf[0] = 0;
00568 sc = d->kossl->SSL_get_current_cipher(d->m_ssl);
00569 if (!sc) {
00570 kdDebug(7029) << "KSSL get current cipher failed - we're probably gonna crash!" << endl;
00571 return;
00572 }
00573
00574
00575 m_ci.m_iCipherUsedBits = d->kossl->SSL_CIPHER_get_bits(sc, &(m_ci.m_iCipherBits));
00576
00577 m_ci.m_cipherVersion = d->kossl->SSL_CIPHER_get_version(sc);
00578
00579 m_ci.m_cipherName = d->kossl->SSL_CIPHER_get_name(sc);
00580
00581 m_ci.m_cipherDescription = d->kossl->SSL_CIPHER_description(sc, buf, 1023);
00582
00583 #endif
00584 }
00585
00586
00587 void KSSL::setPeerInfo() {
00588 #ifdef KSSL_HAVE_SSL
00589 m_pi.setPeerHost(d->proxyPeer);
00590 m_pi.m_cert.setCert(d->kossl->SSL_get_peer_certificate(d->m_ssl));
00591 STACK_OF(X509) *xs = d->kossl->SSL_get_peer_cert_chain(d->m_ssl);
00592 if (xs)
00593 xs = sk_X509_dup(xs);
00594 m_pi.m_cert.setChain((void *)xs);
00595 #endif
00596 }
00597
00598
00599 KSSLConnectionInfo& KSSL::connectionInfo() {
00600 return m_ci;
00601 }
00602
00603
00604
00605 void KSSL::setPeerHost(QString realHost) {
00606 d->proxyPeer = realHost;
00607 }
00608
00609
00610 void KSSL::setProxyUse(bool, QString, int, QString) {
00611 }
00612
00613
00614 KSSLPeerInfo& KSSL::peerInfo() {
00615 return m_pi;
00616 }
00617
00618
00619 bool KSSL::setClientCertificate(KSSLPKCS12 *pkcs) {
00620 #ifdef KSSL_HAVE_SSL
00621 if (!pkcs || !pkcs->getCertificate())
00622 return false;
00623
00624 int rc;
00625 X509 *x = pkcs->getCertificate()->getCert();
00626 EVP_PKEY *k = pkcs->getPrivateKey();
00627
00628 if (!x || !k) return false;
00629
00630 if (!pkcs->getCertificate()->x509V3Extensions().certTypeSSLClient())
00631 return false;
00632
00633 rc = d->kossl->SSL_CTX_use_certificate(d->m_ctx, x);
00634 if (rc <= 0) {
00635 kdDebug(7029) << "KSSL - SSL_CTX_use_certificate failed. rc = " << rc << endl;
00636 return false;
00637 }
00638
00639 rc = d->kossl->SSL_CTX_use_PrivateKey(d->m_ctx, k);
00640 if (rc <= 0) {
00641 kdDebug(7029) << "KSSL - SSL_CTX_use_PrivateKey failed. rc = " << rc << endl;
00642 return false;
00643 }
00644
00645 return true;
00646 #else
00647 return false;
00648 #endif
00649 }
00650
00651 #undef sk_dup
00652
00653 const KSSLSession* KSSL::session() const {
00654 return d->session;
00655 }
00656
00657 bool KSSL::reusingSession() const {
00658 #ifdef KSSL_HAVE_SSL
00659 return (d->m_ssl && d->kossl->SSL_session_reused(d->m_ssl));
00660 #else
00661 return false;
00662 #endif
00663 }
00664
00665
This file is part of the documentation for kio Library Version 3.2.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Mar 4 22:44:26 2004 by
doxygen 1.3.6-20040222 written by
Dimitri van Heesch, © 1997-2003