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