File indexing completed on 2023-09-24 04:05:18
0001 /* This file is part of the KDE project 0002 * 0003 * Copyright (C) 2000-2003 George Staikos <staikos@kde.org> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "kssl.h" 0022 0023 #include <ksslconfig.h> 0024 0025 // this hack provided by Malte Starostik to avoid glibc/openssl bug 0026 // on some systems 0027 #if KSSL_HAVE_SSL 0028 #define crypt _openssl_crypt 0029 #include <openssl/ssl.h> 0030 #include <openssl/x509.h> 0031 #include <openssl/x509v3.h> 0032 #include <openssl/pem.h> 0033 #include <openssl/rand.h> 0034 #undef crypt 0035 #endif 0036 0037 #include <kopenssl.h> 0038 #include <ksslx509v3.h> 0039 #include <klocalizedstring.h> 0040 0041 #include <QAbstractSocket> 0042 #include <QFile> 0043 0044 #ifdef __GNUC__ 0045 #warning "kssl.cpp contains temporary functions! Clean up" 0046 #warning "kssl.cpp needs to be ported to QSslSocket" 0047 #endif 0048 0049 class KSSLPrivate 0050 { 0051 public: 0052 KSSLPrivate() 0053 { 0054 kossl = KOpenSSLProxy::self(); 0055 } 0056 0057 ~KSSLPrivate() {} 0058 0059 #if KSSL_HAVE_SSL 0060 SSL *m_ssl; 0061 SSL_CTX *m_ctx; 0062 SSL_METHOD *m_meth; 0063 #endif 0064 KOSSL *kossl; 0065 }; 0066 0067 KSSL::KSSL(bool init) 0068 { 0069 d = new KSSLPrivate; 0070 m_bInit = false; 0071 m_bAutoReconfig = true; 0072 m_cfg = new KSSLSettings(); 0073 #if KSSL_HAVE_SSL 0074 d->m_ssl = nullptr; 0075 #endif 0076 0077 if (init) { 0078 initialize(); 0079 } 0080 } 0081 0082 KSSL::~KSSL() 0083 { 0084 close(); 0085 delete m_cfg; 0086 delete d; 0087 } 0088 0089 int KSSL::seedWithEGD() 0090 { 0091 int rc = 0; 0092 #if KSSL_HAVE_SSL 0093 if (m_cfg->useEGD() && !m_cfg->getEGDPath().isEmpty()) { 0094 rc = d->kossl->RAND_egd(QFile::encodeName(m_cfg->getEGDPath()).constData()); 0095 if (rc < 0) { 0096 qWarning() << "KSSL: Error seeding PRNG with the EGD."; 0097 } else { 0098 //qDebug() << "KSSL: PRNG was seeded with" << rc << "bytes from the EGD."; 0099 } 0100 } else if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) { 0101 rc = d->kossl->RAND_load_file(QFile::encodeName(m_cfg->getEGDPath()).constData(), -1); 0102 if (rc < 0) { 0103 qWarning() << "KSSL: Error seeding PRNG with the entropy file."; 0104 } else { 0105 //qDebug() << "KSSL: PRNG was seeded with" << rc << "bytes from the entropy file."; 0106 } 0107 } 0108 #endif 0109 return rc; 0110 } 0111 0112 bool KSSL::initialize() 0113 { 0114 #if KSSL_HAVE_SSL 0115 //qDebug() << "KSSL initialize"; 0116 if (m_bInit) { 0117 return false; 0118 } 0119 0120 if (m_bAutoReconfig) { 0121 m_cfg->load(); 0122 } 0123 0124 seedWithEGD(); 0125 0126 d->m_meth = d->kossl->SSLv23_client_method(); 0127 d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth); 0128 if (d->m_ctx == nullptr) { 0129 return false; 0130 } 0131 0132 // set cipher list 0133 QString clist = m_cfg->getCipherList(); 0134 //qDebug() << "Cipher list: " << clist; 0135 if (!clist.isEmpty()) { 0136 d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast<char *>(clist.toLatin1().constData())); 0137 } 0138 0139 m_bInit = true; 0140 return true; 0141 #else 0142 return false; 0143 #endif 0144 } 0145 0146 void KSSL::close() 0147 { 0148 #if KSSL_HAVE_SSL 0149 //qDebug() << "KSSL close"; 0150 if (!m_bInit) { 0151 return; 0152 } 0153 0154 if (d->m_ssl) { 0155 d->kossl->SSL_shutdown(d->m_ssl); 0156 d->kossl->SSL_free(d->m_ssl); 0157 d->m_ssl = nullptr; 0158 } 0159 0160 d->kossl->SSL_CTX_free(d->m_ctx); 0161 if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) { 0162 d->kossl->RAND_write_file(m_cfg->getEGDPath().toLatin1().constData()); 0163 } 0164 0165 m_bInit = false; 0166 #endif 0167 } 0168 0169 bool KSSL::reInitialize() 0170 { 0171 close(); 0172 return initialize(); 0173 } 0174 0175 // get the callback file - it's hidden away in here 0176 //#include "ksslcallback.c" 0177 0178 bool KSSL::reconfig() 0179 { 0180 return reInitialize(); 0181 } 0182 0183 void KSSL::setAutoReconfig(bool ar) 0184 { 0185 m_bAutoReconfig = ar; 0186 } 0187 0188 bool KSSL::setSettings(KSSLSettings *settings) 0189 { 0190 delete m_cfg; 0191 m_cfg = settings; 0192 return reconfig(); 0193 } 0194 0195 KSSLSettings *KSSL::settings() 0196 { 0197 return m_cfg; 0198 } 0199 0200 #if KSSL_HAVE_SSL 0201 bool KSSL::m_bSSLWorks = true; 0202 #else 0203 bool KSSL::m_bSSLWorks = false; 0204 #endif 0205 0206 bool KSSL::doesSSLWork() 0207 { 0208 return m_bSSLWorks; 0209 } 0210