kio Library API Documentation

ksslsettings.cc

00001 /* This file is part of the KDE project 00002 * 00003 * Copyright (C) 2000 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 #include <sys/types.h> 00026 #include <sys/stat.h> 00027 00028 #include <stdlib.h> 00029 #include <pwd.h> 00030 #include <unistd.h> 00031 00032 #include <qfile.h> 00033 #include <qsortedlist.h> 00034 00035 #include "ksslsettings.h" 00036 #include <kglobal.h> 00037 #include <kstandarddirs.h> 00038 #include <kdebug.h> 00039 00040 // this hack provided by Malte Starostik to avoid glibc/openssl bug 00041 // on some systems 00042 #ifdef KSSL_HAVE_SSL 00043 #define crypt _openssl_crypt 00044 #include <openssl/ssl.h> 00045 #undef crypt 00046 #endif 00047 00048 #include <kopenssl.h> 00049 00050 class CipherNode { 00051 public: 00052 CipherNode(const char *_name, int _keylen) : 00053 name(_name), keylen(_keylen) {} 00054 QString name; 00055 int keylen; 00056 inline int operator==(CipherNode &x) 00057 { return ((x.keylen == keylen) && (x.name == name)); } 00058 inline int operator< (CipherNode &x) { return keylen < x.keylen; } 00059 inline int operator<=(CipherNode &x) { return keylen <= x.keylen; } 00060 inline int operator> (CipherNode &x) { return keylen > x.keylen; } 00061 inline int operator>=(CipherNode &x) { return keylen >= x.keylen; } 00062 }; 00063 00064 00065 class KSSLSettingsPrivate { 00066 public: 00067 KSSLSettingsPrivate() { 00068 kossl = NULL; // try to delay this as long as possible 00069 } 00070 ~KSSLSettingsPrivate() { 00071 00072 } 00073 00074 KOSSL *kossl; 00075 bool m_bUseEGD; 00076 bool m_bUseEFile; 00077 QString m_EGDPath; 00078 bool m_bSendX509; 00079 bool m_bPromptX509; 00080 }; 00081 00082 // 00083 // FIXME 00084 // Implementation note: for now, we only read cipher settings from disk, 00085 // and do not store them in memory. This should change. 00086 // 00087 00088 KSSLSettings::KSSLSettings(bool readConfig) { 00089 d = new KSSLSettingsPrivate; 00090 m_cfg = new KConfig("cryptodefaults", false, false); 00091 00092 if (!KGlobal::dirs()->addResourceType("kssl", KStandardDirs::kde_default("data") + "kssl")) { 00093 //kdDebug(7029) << "Error adding (kssl, share/apps/kssl)" << endl; 00094 } 00095 00096 if (readConfig) load(); 00097 } 00098 00099 00100 // we don't save settings incase it was a temporary object 00101 KSSLSettings::~KSSLSettings() { 00102 delete m_cfg; 00103 delete d; 00104 } 00105 00106 00107 bool KSSLSettings::sslv2() const { 00108 return m_bUseSSLv2; 00109 } 00110 00111 00112 bool KSSLSettings::sslv3() const { 00113 return m_bUseSSLv3; 00114 } 00115 00116 00117 bool KSSLSettings::tlsv1() const { 00118 return m_bUseTLSv1; 00119 } 00120 00121 00122 // FIXME: we should make a default list available if this fails 00123 // since OpenSSL seems to just choose any old thing if it's given an 00124 // empty list. This behavior is not confirmed though. 00125 QString KSSLSettings::getCipherList() { 00126 QString clist = ""; 00127 #ifdef KSSL_HAVE_SSL 00128 QString tcipher; 00129 bool firstcipher = true; 00130 SSL_METHOD *meth; 00131 QSortedList<CipherNode> cipherSort; 00132 cipherSort.setAutoDelete(true); 00133 00134 00135 if (!d->kossl) 00136 d->kossl = KOSSL::self(); 00137 00138 // The user might have v2 and v3 enabled so we start with an 00139 // empty buffer and add v2 if needed, then v3 if needed. 00140 // we assume that the config file will have consecutive entries. 00141 for (int k = 0; k < 2; k++) { 00142 00143 if (k == 0) { // do v2, then v3 00144 if (!m_bUseSSLv2) 00145 continue; 00146 m_cfg->setGroup("SSLv2"); 00147 meth = d->kossl->SSLv2_client_method(); 00148 } else { 00149 if (!m_bUseSSLv3) 00150 continue; 00151 m_cfg->setGroup("SSLv3"); 00152 meth = d->kossl->SSLv3_client_method(); 00153 } 00154 00155 // I always thought that OpenSSL negotiated the best possible 00156 // cipher for the connection based on the list provided. Boy 00157 // was I ever wrong. There have been many complaints over the 00158 // fact that we do not care about the order of ciphers we submit 00159 // to OpenSSL for use, and thus 40 bit is sometimes used. Ok, 00160 // that's fine, but choosing more bits does not mean it's more 00161 // secure. Infact, it could be quite the opposite sometimes!! 00162 // DO NOT TRUST THIS TO MAKE IT MORE SECURE. It is here only 00163 // for peace of mind of the users. Eventually it would be best 00164 // to set an internal preference order based on accepted strength 00165 // analyzes of the various algorithms INCLUDING the key length. 00166 00167 for(int i = 0;; i++) { 00168 SSL_CIPHER *sc = (meth->get_cipher)(i); 00169 if (!sc) 00170 break; 00171 tcipher.sprintf("cipher_%s", sc->name); 00172 int bits = d->kossl->SSL_CIPHER_get_bits(sc, NULL); 00173 00174 if (m_cfg->readBoolEntry(tcipher, bits >= 56)) { 00175 CipherNode *xx = new CipherNode(sc->name,bits); 00176 if (!cipherSort.contains(xx)) { 00177 cipherSort.inSort(xx); 00178 } else { 00179 delete xx; 00180 } 00181 } // if 00182 } // for i 00183 } // for k 00184 00185 // Hack time 00186 // --------- 00187 // A lot of these webservers suck. So in order to get around their 00188 // sucking, we take the most common ciphers and make them the first ones 00189 // we offer. This seems to make it work better. 00190 // 00191 00192 // Put least preferred first, most preferred last. 00193 CipherNode tnode("", 0); 00194 00195 #define AdjustCipher(X, Y) tnode.name = X; tnode.keylen = Y; \ 00196 if (cipherSort.find(&tnode) != -1) { \ 00197 cipherSort.remove(); \ 00198 cipherSort.append(new CipherNode(tnode.name.latin1(), tnode.keylen)); \ 00199 } 00200 00201 AdjustCipher("IDEA-CBC-MD5", 128); 00202 AdjustCipher("DES-CBC3-MD5", 168); 00203 AdjustCipher("RC2-CBC-MD5", 128); 00204 AdjustCipher("DES-CBC3-SHA", 168); 00205 AdjustCipher("IDEA-CBC-SHA", 128); 00206 AdjustCipher("RC4-SHA", 128); 00207 AdjustCipher("RC4-MD5", 128); 00208 #undef AdjustCipher 00209 00210 // Remove any ADH ciphers as per RFC2246 00211 for (unsigned int i = 0; i < cipherSort.count(); i++) { 00212 CipherNode *j = 0L; 00213 while ((j = cipherSort.at(i)) != 0L) { 00214 if (j->name.contains("ADH-")) { 00215 cipherSort.remove(j); 00216 } else { 00217 break; 00218 } 00219 } 00220 } 00221 00222 // now assemble the list cipher1:cipher2:cipher3:...:ciphern 00223 while (!cipherSort.isEmpty()) { 00224 if (firstcipher) 00225 firstcipher = false; 00226 else clist.append(":"); 00227 clist.append(cipherSort.getLast()->name); 00228 cipherSort.removeLast(); 00229 } // while 00230 00231 // kdDebug(7029) << "Cipher list is: " << clist << endl; 00232 00233 #endif 00234 return clist; 00235 } 00236 00237 // FIXME - sync these up so that we can use them with the control module!! 00238 void KSSLSettings::load() { 00239 m_cfg->reparseConfiguration(); 00240 00241 m_cfg->setGroup("TLS"); 00242 m_bUseTLSv1 = m_cfg->readBoolEntry("Enabled", true); 00243 00244 m_cfg->setGroup("SSLv2"); 00245 m_bUseSSLv2 = m_cfg->readBoolEntry("Enabled", true); 00246 00247 m_cfg->setGroup("SSLv3"); 00248 m_bUseSSLv3 = m_cfg->readBoolEntry("Enabled", true); 00249 00250 m_cfg->setGroup("Warnings"); 00251 m_bWarnOnEnter = m_cfg->readBoolEntry("OnEnter", false); 00252 m_bWarnOnLeave = m_cfg->readBoolEntry("OnLeave", true); 00253 m_bWarnOnUnencrypted = m_cfg->readBoolEntry("OnUnencrypted", true); 00254 m_bWarnOnMixed = m_cfg->readBoolEntry("OnMixed", true); 00255 00256 m_cfg->setGroup("Validation"); 00257 m_bWarnSelfSigned = m_cfg->readBoolEntry("WarnSelfSigned", true); 00258 m_bWarnExpired = m_cfg->readBoolEntry("WarnExpired", true); 00259 m_bWarnRevoked = m_cfg->readBoolEntry("WarnRevoked", true); 00260 00261 m_cfg->setGroup("EGD"); 00262 d->m_bUseEGD = m_cfg->readBoolEntry("UseEGD", false); 00263 d->m_bUseEFile = m_cfg->readBoolEntry("UseEFile", false); 00264 d->m_EGDPath = m_cfg->readPathEntry("EGDPath"); 00265 00266 m_cfg->setGroup("Auth"); 00267 d->m_bSendX509 = ("send" == m_cfg->readEntry("AuthMethod", "")); 00268 d->m_bPromptX509 = ("prompt" == m_cfg->readEntry("AuthMethod", "")); 00269 00270 #ifdef KSSL_HAVE_SSL 00271 00272 00273 00274 #endif 00275 } 00276 00277 00278 void KSSLSettings::defaults() { 00279 m_bUseTLSv1 = true; 00280 m_bUseSSLv2 = true; 00281 m_bUseSSLv3 = true; 00282 m_bWarnOnEnter = false; 00283 m_bWarnOnLeave = true; 00284 m_bWarnOnUnencrypted = true; 00285 m_bWarnOnMixed = true; 00286 m_bWarnSelfSigned = true; 00287 m_bWarnExpired = true; 00288 m_bWarnRevoked = true; 00289 d->m_bUseEGD = false; 00290 d->m_bUseEFile = false; 00291 d->m_EGDPath = ""; 00292 } 00293 00294 00295 void KSSLSettings::save() { 00296 m_cfg->setGroup("TLS"); 00297 m_cfg->writeEntry("Enabled", m_bUseTLSv1); 00298 00299 m_cfg->setGroup("SSLv2"); 00300 m_cfg->writeEntry("Enabled", m_bUseSSLv2); 00301 00302 m_cfg->setGroup("SSLv3"); 00303 m_cfg->writeEntry("Enabled", m_bUseSSLv3); 00304 00305 m_cfg->setGroup("Warnings"); 00306 m_cfg->writeEntry("OnEnter", m_bWarnOnEnter); 00307 m_cfg->writeEntry("OnLeave", m_bWarnOnLeave); 00308 m_cfg->writeEntry("OnUnencrypted", m_bWarnOnUnencrypted); 00309 m_cfg->writeEntry("OnMixed", m_bWarnOnMixed); 00310 00311 m_cfg->setGroup("Validation"); 00312 m_cfg->writeEntry("WarnSelfSigned", m_bWarnSelfSigned); 00313 m_cfg->writeEntry("WarnExpired", m_bWarnExpired); 00314 m_cfg->writeEntry("WarnRevoked", m_bWarnRevoked); 00315 00316 m_cfg->setGroup("EGD"); 00317 m_cfg->writeEntry("UseEGD", d->m_bUseEGD); 00318 m_cfg->writeEntry("UseEFile", d->m_bUseEFile); 00319 m_cfg->writePathEntry("EGDPath", d->m_EGDPath); 00320 00321 m_cfg->sync(); 00322 // FIXME - ciphers 00323 #if 0 00324 #ifdef KSSL_HAVE_SSL 00325 m_cfg->setGroup("SSLv2"); 00326 for (unsigned int i = 0; i < v2ciphers.count(); i++) { 00327 QString ciphername; 00328 ciphername.sprintf("cipher_%s", v2ciphers[i].ascii()); 00329 if (v2selectedciphers.contains(v2ciphers[i])) { 00330 m_cfg->writeEntry(ciphername, true); 00331 } else m_cfg->writeEntry(ciphername, false); 00332 } 00333 00334 m_cfg->setGroup("SSLv3"); 00335 for (unsigned int i = 0; i < v3ciphers.count(); i++) { 00336 QString ciphername; 00337 ciphername.sprintf("cipher_%s", v3ciphers[i].ascii()); 00338 if (v3selectedciphers.contains(v3ciphers[i])) { 00339 m_cfg->writeEntry(ciphername, true); 00340 } else m_cfg->writeEntry(ciphername, false); 00341 } 00342 #endif 00343 00344 m_cfg->sync(); 00345 00346 // insure proper permissions -- contains sensitive data 00347 QString cfgName(KGlobal::dirs()->findResource("config", "cryptodefaults")); 00348 if (!cfgName.isEmpty()) 00349 ::chmod(QFile::encodeName(cfgName), 0600); 00350 #endif 00351 } 00352 00353 00354 bool KSSLSettings::warnOnEnter() const { return m_bWarnOnEnter; } 00355 void KSSLSettings::setWarnOnEnter(bool x) { m_bWarnOnEnter = x; } 00356 bool KSSLSettings::warnOnUnencrypted() const { return m_bWarnOnUnencrypted; } 00357 void KSSLSettings::setWarnOnUnencrypted(bool x) { m_bWarnOnUnencrypted = x; } 00358 bool KSSLSettings::warnOnLeave() const { return m_bWarnOnLeave; } 00359 void KSSLSettings::setWarnOnLeave(bool x) { m_bWarnOnLeave = x; } 00360 bool KSSLSettings::warnOnMixed() const { return m_bWarnOnMixed; } 00361 bool KSSLSettings::warnOnSelfSigned() const { return m_bWarnSelfSigned; } 00362 bool KSSLSettings::warnOnRevoked() const { return m_bWarnRevoked; } 00363 bool KSSLSettings::warnOnExpired() const { return m_bWarnExpired; } 00364 bool KSSLSettings::useEGD() const { return d->m_bUseEGD; } 00365 bool KSSLSettings::useEFile() const { return d->m_bUseEFile; } 00366 bool KSSLSettings::autoSendX509() const { return d->m_bSendX509; } 00367 bool KSSLSettings::promptSendX509() const { return d->m_bPromptX509; } 00368 00369 void KSSLSettings::setTLSv1(bool enabled) { m_bUseTLSv1 = enabled; } 00370 void KSSLSettings::setSSLv2(bool enabled) { m_bUseSSLv2 = enabled; } 00371 void KSSLSettings::setSSLv3(bool enabled) { m_bUseSSLv3 = enabled; } 00372 00373 QString& KSSLSettings::getEGDPath() { return d->m_EGDPath; } 00374
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:41:07 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003