# kio Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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

This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:24:04 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003