# kio Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kssl.cc

    00001 /* This file is part of the KDE project
    00002  *
    00003  * Copyright (C) 2000-2003 George Staikos <staikos@kde.org>
    00004  *
    00005  * This library is free software; you can redistribute it and/or
    00006  * modify it under the terms of the GNU Library General Public
    00007  * License as published by the Free Software Foundation; either
    00008  * version 2 of the License, or (at your option) any later version.
    00009  *
    00010  * This library is distributed in the hope that it will be useful,
    00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013  * Library General Public License for more details.
    00014  *
    00015  * You should have received a copy of the GNU Library General Public License
    00016  * along with this library; see the file COPYING.LIB.  If not, write to
    00017  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018  * Boston, MA 02111-1307, USA.
    00019  */
    00020
    00021 #ifdef HAVE_CONFIG_H
    00022 #include <config.h>
    00023 #endif
    00024
    00025 // this hack provided by Malte Starostik to avoid glibc/openssl bug
    00026 // on some systems
    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 // kdDebug(7029) << "KSSL TLS initialize" << endl;
    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     // set cipher list
    00147     QString clist = m_cfg->getCipherList();
    00148     //kdDebug(7029) << "Cipher list: " << clist << endl;
    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     // FIXME: we should be able to force SSL off entirely.
    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 if (m_cfg->sslv2() && m_cfg->sslv3()) kdDebug(7029) << "Double method" << endl;
    00183 else if (m_cfg->sslv2()) kdDebug(7029) << "SSL2 method" << endl;
    00184 else if (m_cfg->sslv3()) kdDebug(7029) << "SSL3 method" << endl;
    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     // set cipher list
    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     // Obtain a reference by incrementing the reference count.  Yuck.
    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 //kdDebug(7029) << "KSSL close" << endl;
    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 // get the callback file - it's hidden away in here
    00258 //#include "ksslcallback.c"
    00259
    00260
    00261 bool KSSL::setVerificationLogic() {
    00262 #if 0
    00263 #ifdef KSSL_HAVE_SSL
    00264   //  SSL_set_verify_result(d->m_ssl, X509_V_OK);
    00265   //  SSL_CTX_set_verify(d->m_ctx, SSL_VERIFY_PEER, X509Callback);
    00266 #endif
    00267 #endif
    00268 return true;
    00269 }
    00270
    00271
    00272 int KSSL::accept(int sock) {
    00273 #ifdef KSSL_HAVE_SSL
    00274 // kdDebug(7029) << "KSSL accept" << endl;
    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     if (!setVerificationLogic()) {
    00300         d->kossl->SSL_shutdown(d->m_ssl);
    00301         d->kossl->SSL_free(d->m_ssl);
    00302         d->m_ssl = 0;
    00303         return -1;
    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 // kdDebug(7029) << "KSSL connect" << endl;
    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     if (!setVerificationLogic()) {
    00386         d->kossl->SSL_shutdown(d->m_ssl);
    00387         d->kossl->SSL_free(d->m_ssl);
    00388         d->m_ssl = 0;
    00389         return -1;
    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             // nonblocking - but we block anyways in connect() :)
    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     // FIXME: enhance to work the way read() does below, handling errors
    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); // 20ms sleep
    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;      // OpenSSL returns 0 on error too
    00502         }
    00503
    00504 //      else if (err == SSL_ERROR_ZERO_RETURN)
    00505 //          rc = 0;
    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) {      // OpenSSL returns 0 on error too
    00522         int err = d->kossl->SSL_get_error(d->m_ssl, rc);
    00523
    00524         if (err == SSL_ERROR_WANT_WRITE) {
    00525             ::usleep(20000); // 20ms sleep
    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;  // for safety.
    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     // set the number of bits, bits used
    00583     m_ci.m_iCipherUsedBits = d->kossl->SSL_CIPHER_get_bits(sc, &(m_ci.m_iCipherBits));
    00584     // set the cipher version
    00585     m_ci.m_cipherVersion = d->kossl->SSL_CIPHER_get_version(sc);
    00586     // set the cipher name
    00587     m_ci.m_cipherName = d->kossl->SSL_CIPHER_get_name(sc);
    00588     // set the cipher description
    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);   // Leak?
    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 // KDE 4: Make it const QString &
    00613 void KSSL::setPeerHost(QString realHost) {
    00614     d->proxyPeer = realHost;
    00615 }
    00616
    00617 // deprecated
    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

This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:24:04 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003