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
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