kssl.cc
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023
00024
00025
00026 #ifdef KSSL_HAVE_SSL
00027 #include <unistd.h>
00028 #include <netinet/in.h>
00029 #include <sys/socket.h>
00030 #define crypt _openssl_crypt
00031 #include <openssl/ssl.h>
00032 #include <openssl/x509.h>
00033 #include <openssl/x509v3.h>
00034 #include <openssl/pem.h>
00035 #include <openssl/rand.h>
00036 #undef crypt
00037 #endif
00038
00039 #include "kssl.h"
00040
00041 #include <kdebug.h>
00042 #include <kstandarddirs.h>
00043 #include <ksock.h>
00044 #include <ksockaddr.h>
00045
00046 #include <kopenssl.h>
00047 #include <ksslx509v3.h>
00048 #include <ksslpkcs12.h>
00049 #include <klocale.h>
00050 #include <ksocks.h>
00051
00052 #define sk_dup d->kossl->sk_dup
00053
00054 class KSSLPrivate {
00055 public:
00056 KSSLPrivate() {
00057 lastInitTLS = false;
00058 kossl = KOpenSSLProxy::self();
00059 }
00060
00061 ~KSSLPrivate() {
00062
00063 }
00064
00065 bool lastInitTLS;
00066 KSSLCertificate::KSSLValidation m_cert_vfy_res;
00067 QString proxyPeer;
00068
00069 #ifdef KSSL_HAVE_SSL
00070 SSL *m_ssl;
00071 SSL_CTX *m_ctx;
00072 SSL_METHOD *m_meth;
00073 #endif
00074 KOSSL *kossl;
00075 };
00076
00077
00078 KSSL::KSSL(bool init) {
00079 d = new KSSLPrivate;
00080 m_bInit = false;
00081 m_bAutoReconfig = true;
00082 m_cfg = new KSSLSettings();
00083 #ifdef KSSL_HAVE_SSL
00084 d->m_ssl = NULL;
00085 #endif
00086
00087 if (init) initialize();
00088 }
00089
00090
00091 KSSL::~KSSL() {
00092 close();
00093 delete m_cfg;
00094 delete d;
00095 }
00096
00097
00098 int KSSL::seedWithEGD() {
00099 int rc = 0;
00100 #ifdef KSSL_HAVE_SSL
00101 if (m_cfg->useEGD() && !m_cfg->getEGDPath().isEmpty()) {
00102 rc = d->kossl->RAND_egd(m_cfg->getEGDPath().latin1());
00103 if (rc < 0)
00104 kdDebug(7029) << "KSSL: Error seeding PRNG with the EGD." << endl;
00105 else
00106 kdDebug(7029) << "KSSL: PRNG was seeded with " << rc
00107 << " bytes from the EGD." << endl;
00108 } else if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) {
00109 rc = d->kossl->RAND_load_file(m_cfg->getEGDPath().latin1(), -1);
00110 if (rc < 0)
00111 kdDebug(7029) << "KSSL: Error seeding PRNG with the entropy file." << endl;
00112 else
00113 kdDebug(7029) << "KSSL: PRNG was seeded with " << rc
00114 << " bytes from the entropy file." << endl;
00115 }
00116 #endif
00117 return rc;
00118 }
00119
00120
00121 bool KSSL::TLSInit() {
00122 #ifdef KSSL_HAVE_SSL
00123
00124 if (m_bInit) return false;
00125
00126 if (m_bAutoReconfig)
00127 m_cfg->load();
00128
00129 if (!m_cfg->tlsv1()) return false;
00130
00131 seedWithEGD();
00132 d->m_meth = d->kossl->TLSv1_client_method();
00133 d->lastInitTLS = true;
00134
00135 d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth);
00136 if (d->m_ctx == NULL) {
00137 return false;
00138 }
00139
00140
00141 QString clist = m_cfg->getCipherList();
00142
00143 if (!clist.isEmpty())
00144 d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast<char *>(clist.ascii()));
00145
00146 m_bInit = true;
00147 return true;
00148 #else
00149 return false;
00150 #endif
00151 }
00152
00153
00154 bool KSSL::initialize() {
00155 #ifdef KSSL_HAVE_SSL
00156 kdDebug(7029) << "KSSL initialize" << endl;
00157 if (m_bInit) return false;
00158
00159 if (m_bAutoReconfig)
00160 m_cfg->load();
00161
00162 seedWithEGD();
00163
00164
00165
00166
00167 d->lastInitTLS = false;
00168
00169 m_pi.reset();
00170
00171 if (m_cfg->sslv2() && m_cfg->sslv3())
00172 d->m_meth = d->kossl->SSLv23_client_method();
00173 else if (m_cfg->sslv3())
00174 d->m_meth = d->kossl->SSLv3_client_method();
00175 else
00176 d->m_meth = d->kossl->SSLv2_client_method();
00177
00178
00179
00180
00181
00182
00183
00184 d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth);
00185 if (d->m_ctx == NULL) {
00186 return false;
00187 }
00188
00189
00190 QString clist = m_cfg->getCipherList();
00191 kdDebug(7029) << "Cipher list: " << clist << endl;
00192 if (!clist.isEmpty())
00193 d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast<char *>(clist.ascii()));
00194
00195 m_bInit = true;
00196 return true;
00197 #else
00198 return false;
00199 #endif
00200 }
00201
00202
00203
00204
00205 void KSSL::close() {
00206 #ifdef KSSL_HAVE_SSL
00207
00208 if (!m_bInit) return;
00209 if (d->m_ssl) {
00210 d->kossl->SSL_shutdown(d->m_ssl);
00211 d->kossl->SSL_free(d->m_ssl);
00212 d->m_ssl = NULL;
00213 }
00214 d->kossl->SSL_CTX_free(d->m_ctx);
00215 if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) {
00216 d->kossl->RAND_write_file(m_cfg->getEGDPath().latin1());
00217 }
00218 m_bInit = false;
00219 #endif
00220 }
00221
00222
00223 bool KSSL::reInitialize() {
00224 close();
00225 return initialize();
00226 }
00227
00228
00229 #include "ksslcallback.c"
00230
00231
00232 bool KSSL::setVerificationLogic() {
00233 #if 0
00234 #ifdef KSSL_HAVE_SSL
00235
00236
00237 #endif
00238 #endif
00239 return true;
00240 }
00241
00242
00243 int KSSL::accept(int sock) {
00244 #ifdef KSSL_HAVE_SSL
00245
00246 int rc;
00247 if (!m_bInit) return -1;
00248 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
00249 if (!d->m_ssl) return -1;
00250
00251
00252
00253
00254
00255
00256 if (!d->lastInitTLS)
00257 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_NO_TLSv1);
00258 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_ALL);
00259
00260 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
00261 if (rc == 0) return rc;
00262
00263 rc = d->kossl->SSL_accept(d->m_ssl);
00264 if (rc == 1) {
00265 setConnectionInfo();
00266 setPeerInfo();
00267 kdDebug(7029) << "KSSL connected OK" << endl;
00268 } else {
00269 kdDebug(7029) << "KSSL accept failed - rc = " << rc << endl;
00270 kdDebug(7029) << " ERROR = " << d->kossl->SSL_get_error(d->m_ssl, rc) << endl;
00271 return -1;
00272 }
00273 return rc;
00274 #else
00275 return -1;
00276 #endif
00277 }
00278
00279
00280 int KSSL::connect(int sock) {
00281 #ifdef KSSL_HAVE_SSL
00282
00283 int rc;
00284 if (!m_bInit) return -1;
00285 d->m_ssl = d->kossl->SSL_new(d->m_ctx);
00286 if (!d->m_ssl) return -1;
00287
00288
00289
00290
00291
00292
00293 if (!d->lastInitTLS)
00294 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_NO_TLSv1);
00295 d->kossl->SSL_set_options(d->m_ssl, SSL_OP_ALL);
00296
00297 rc = d->kossl->SSL_set_fd(d->m_ssl, sock);
00298 if (rc == 0) return rc;
00299
00300 rc = d->kossl->SSL_connect(d->m_ssl);
00301 if (rc == 1) {
00302 setConnectionInfo();
00303 setPeerInfo();
00304 kdDebug(7029) << "KSSL connected OK" << endl;
00305 } else {
00306 kdDebug(7029) << "KSSL connect failed - rc = " << rc << endl;
00307 kdDebug(7029) << " ERROR = " << d->kossl->SSL_get_error(d->m_ssl, rc) << endl;
00308 d->kossl->ERR_print_errors_fp(stderr);
00309 return -1;
00310 }
00311 return rc;
00312 #else
00313 return -1;
00314 #endif
00315 }
00316
00317
00318 int KSSL::pending() {
00319 #ifdef KSSL_HAVE_SSL
00320 if (!m_bInit) return -1;
00321 return d->kossl->SSL_pending(d->m_ssl);
00322 #else
00323 return -1;
00324 #endif
00325 }
00326
00327
00328 int KSSL::peek(void *buf, int len) {
00329 #ifdef KSSL_HAVE_SSL
00330 if (!m_bInit) return -1;
00331 return d->kossl->SSL_peek(d->m_ssl, buf, len);
00332 #else
00333 return -1;
00334 #endif
00335 }
00336
00337
00338 int KSSL::read(void *buf, int len) {
00339 #ifdef KSSL_HAVE_SSL
00340 if (!m_bInit) return -1;
00341
00342 int rc = d->kossl->SSL_read(d->m_ssl, (char *)buf, len);
00343 if (rc <= 0) {
00344 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
00345 kdDebug(7029) << "SSL READ ERROR: " << err << endl;
00346 if (err != SSL_ERROR_NONE && err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL)
00347 rc = -1;
00348
00349
00350 }
00351 return rc;
00352 #else
00353 return -1;
00354 #endif
00355 }
00356
00357
00358 int KSSL::write(const void *buf, int len) {
00359 #ifdef KSSL_HAVE_SSL
00360 if (!m_bInit) return -1;
00361
00362 int rc = d->kossl->SSL_write(d->m_ssl, (const char *)buf, len);
00363 if (rc <= 0) {
00364 int err = d->kossl->SSL_get_error(d->m_ssl, rc);
00365 kdDebug(7029) << "SSL WRITE ERROR: " << err << endl;
00366 if (err != SSL_ERROR_NONE && err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL)
00367 rc = -1;
00368 }
00369
00370 return rc;
00371 #else
00372 return -1;
00373 #endif
00374 }
00375
00376
00377 bool KSSL::reconfig() {
00378 return reInitialize();
00379 }
00380
00381
00382 void KSSL::setAutoReconfig(bool ar) {
00383 m_bAutoReconfig = ar;
00384 }
00385
00386
00387 bool KSSL::setSettings(KSSLSettings *settings) {
00388 delete m_cfg;
00389 m_cfg = settings;
00390 return reconfig();
00391 }
00392
00393
00394 #ifdef KSSL_HAVE_SSL
00395 bool KSSL::m_bSSLWorks = true;
00396 #else
00397 bool KSSL::m_bSSLWorks = false;
00398 #endif
00399
00400 bool KSSL::doesSSLWork() {
00401 return m_bSSLWorks;
00402 }
00403
00404
00405 void KSSL::setConnectionInfo() {
00406 #ifdef KSSL_HAVE_SSL
00407 SSL_CIPHER *sc;
00408 char buf[1024];
00409
00410 buf[0] = 0;
00411 sc = d->kossl->SSL_get_current_cipher(d->m_ssl);
00412 if (!sc) {
00413 kdDebug(7029) << "KSSL get current cipher failed - we're probably gonna crash!" << endl;
00414 return;
00415 }
00416
00417 m_ci.m_iCipherUsedBits = d->kossl->SSL_CIPHER_get_bits(sc, &(m_ci.m_iCipherBits));
00418
00419 m_ci.m_cipherVersion = d->kossl->SSL_CIPHER_get_version(sc);
00420
00421 m_ci.m_cipherName = d->kossl->SSL_CIPHER_get_name(sc);
00422
00423 m_ci.m_cipherDescription = d->kossl->SSL_CIPHER_description(sc, buf, 1023);
00424
00425 #endif
00426 }
00427
00428
00429 void KSSL::setPeerInfo() {
00430 #ifdef KSSL_HAVE_SSL
00431 m_pi.setPeerHost(d->proxyPeer);
00432 m_pi.m_cert.setCert(d->kossl->SSL_get_peer_certificate(d->m_ssl));
00433 STACK_OF(X509) *xs = d->kossl->SSL_get_peer_cert_chain(d->m_ssl);
00434 if (xs) xs = sk_X509_dup(xs);
00435 m_pi.m_cert.setChain((void *)xs);
00436 #endif
00437 }
00438
00439
00440 KSSLConnectionInfo& KSSL::connectionInfo() {
00441 return m_ci;
00442 }
00443
00444
00445 void KSSL::setPeerHost(QString realHost) {
00446 d->proxyPeer = realHost;
00447 }
00448
00449
00450 void KSSL::setProxyUse(bool, QString, int, QString) {
00451 }
00452
00453
00454 KSSLPeerInfo& KSSL::peerInfo() {
00455 return m_pi;
00456 }
00457
00458
00459 bool KSSL::setClientCertificate(KSSLPKCS12 *pkcs) {
00460 #ifdef KSSL_HAVE_SSL
00461 if (!pkcs || !pkcs->getCertificate()) return false;
00462
00463 int rc;
00464 X509 *x = pkcs->getCertificate()->getCert();
00465 EVP_PKEY *k = pkcs->getPrivateKey();
00466
00467 if (!x || !k) return false;
00468
00469 if (!pkcs->getCertificate()->x509V3Extensions().certTypeSSLClient())
00470 return false;
00471
00472 rc = d->kossl->SSL_CTX_use_certificate(d->m_ctx, x);
00473 if (rc <= 0) {
00474 kdDebug(7029) << "KSSL - SSL_CTX_use_certificate failed. rc = " << rc << endl;
00475 return false;
00476 }
00477
00478 rc = d->kossl->SSL_CTX_use_PrivateKey(d->m_ctx, k);
00479 if (rc <= 0) {
00480 kdDebug(7029) << "KSSL - SSL_CTX_use_PrivateKey failed. rc = " << rc << endl;
00481 return false;
00482 }
00483
00484 return true;
00485 #else
00486 return false;
00487 #endif
00488 }
00489
00490 #undef sk_dup
00491
This file is part of the documentation for kdelibs Version 3.1.5.