diff options
Diffstat (limited to 'kcontrol/crypto/crypto.cpp')
-rw-r--r-- | kcontrol/crypto/crypto.cpp | 2458 |
1 files changed, 2458 insertions, 0 deletions
diff --git a/kcontrol/crypto/crypto.cpp b/kcontrol/crypto/crypto.cpp new file mode 100644 index 000000000..f5c4b0099 --- /dev/null +++ b/kcontrol/crypto/crypto.cpp @@ -0,0 +1,2458 @@ +/** + * crypto.cpp + * + * Copyright (c) 2000-2005 George Staikos <staikos@kde.org> + * 2000 Carsten Pfeiffer <pfeiffer@kde.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// +// Attention. The suck factor on this code is increasing. It's a bit of a +// hack. </understatement> It might be time to rewrite it soon. +// + +#include <sys/types.h> +#include <sys/stat.h> + +#include <stdlib.h> +#include <pwd.h> +#include <unistd.h> + +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qframe.h> +#include <qhbuttongroup.h> +#include <qhgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qregexp.h> +#include <qvbox.h> +#include <qvbuttongroup.h> +#include <qvgroupbox.h> +#include <qwhatsthis.h> + +#include <kaboutdata.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <kdatepicker.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kfiledialog.h> +#include <kgenericfactory.h> +#include <kglobal.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmdcodec.h> +#include <kmessagebox.h> +#include <kpassdlg.h> +#include <kprocess.h> +#include <kpushbutton.h> +#include <kresolver.h> +#include <kseparator.h> +#include <kstandarddirs.h> +#include <kurllabel.h> +#include <kurlrequester.h> + +#include <config.h> +#ifdef HAVE_SSL +#define crypt _openssl_crypt +#include <openssl/ssl.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/pem.h> +#include <openssl/rand.h> +#include <openssl/err.h> +#include <openssl/stack.h> +#include <openssl/safestack.h> +#undef crypt +#endif + +#include <ksslall.h> +#include <kopenssl.h> + +#include "crypto.h" +#include "certexport.h" +#include "kdatetimedlg.h" + +using namespace KNetwork; + +typedef KGenericFactory<KCryptoConfig, QWidget> KryptoFactory; +K_EXPORT_COMPONENT_FACTORY( kcm_crypto, KryptoFactory("kcmcrypto") ) + +CipherItem::CipherItem( QListView *view, const QString& cipher, int bits, + int maxBits, KCryptoConfig *module ) + : QCheckListItem( view, QString::null, CheckBox ) +{ + m_cipher = cipher; + m_bits = bits; + m_module = module; + + QString tmp( i18n("%1 (%2 of %3 bits)") ); + setText( 0, tmp.arg( cipher ).arg( bits ).arg( maxBits )); +} + +void CipherItem::stateChange( bool ) +{ + m_module->configChanged(); +} + +QString CipherItem::configName() const +{ + QString cipherName("cipher_%1"); + return cipherName.arg( m_cipher ); +} + + + +OtherCertItem::OtherCertItem( QListView *view, const QString& sub, const QString& md5, bool perm, int policy, QDateTime exp, KCryptoConfig *module ) + : QListViewItem( view, QString::null ), _sub(sub), _md5(md5), _exp(exp), _perm(perm), _policy(policy) + +{ + m_module = module; +KSSLX509Map cert(sub); + setText(0, cert.getValue("O")); + setText(1, cert.getValue("CN").replace("\n", ", ")); + + if (_exp.date().year() > 3000 || _exp.date().year() < 1900) + _exp.setDate(QDate(3000,1,1)); +} + +void OtherCertItem::stateChange( bool ) +{ + m_module->configChanged(); +} + +QString OtherCertItem::configName() const +{ + return _sub; +} + + +YourCertItem::YourCertItem( QListView *view, QString pkcs, QString pass, QString name, KCryptoConfig *module ) + : QListViewItem( view, QString::null ) + +{ + m_module = module; +KSSLX509Map cert(name); + QString tmp = cert.getValue("CN").replace("\n", ", "); + setText(0, tmp); + setText(1, cert.getValue("Email")); + _pkcs = pkcs; + _name = name; + _pass = pass; +} + +void YourCertItem::stateChange( bool ) +{ + m_module->configChanged(); +} + +QString YourCertItem::configName() const +{ + return _name; +} + + + +CAItem::CAItem( QListView *view, QString name, QString cert, bool site, bool email, bool code, KCryptoConfig *module ) + : QListViewItem( view, QString::null ) + +{ + m_module = module; +KSSLX509Map mcert(name); +QString tmp; + setText(0, mcert.getValue("O")); + tmp = mcert.getValue("OU"); + tmp.replace("\n", ", "); + setText(1, tmp); + tmp = mcert.getValue("CN"); + tmp.replace("\n", ", "); + setText(2, tmp); + _name = name; + _cert = cert; + _site = site; + _email = email; + _code = code; + isNew = false; + modified = false; +} + +void CAItem::stateChange( bool ) +{ + m_module->configChanged(); +} + +QString CAItem::configName() const +{ + return _name; +} + + + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + + + + +KCryptoConfig::KCryptoConfig(QWidget *parent, const char *name, const QStringList &) + : KCModule(KryptoFactory::instance(), parent, name) +{ +QGridLayout *grid; +QBoxLayout *top = new QVBoxLayout(this); +QString whatstr; + + setQuickHelp( i18n("<h1>Crypto</h1> This module allows you to configure SSL for" + " use with most KDE applications, as well as manage your personal" + " certificates and the known certificate authorities.")); + + ___lehack = false; + otherCertDelList.setAutoDelete(true); + yourCertDelList.setAutoDelete(true); + authDelList.setAutoDelete(true); + caDelList.setAutoDelete(true); + + _signers = new KSSLSigners; + + KAboutData *about = + new KAboutData(I18N_NOOP("kcmcrypto"), I18N_NOOP("KDE Crypto Control Module"), + 0, 0, KAboutData::License_GPL, + I18N_NOOP("(c) 2000 - 2001 George Staikos")); + about->addAuthor("George Staikos", 0, "staikos@kde.org"); + about->addAuthor("Carsten Pfeiffer", 0, "pfeiffer@kde.org"); + setAboutData( about ); + + /////////////////////////////////////////////////////////////////////////// + // Create the GUI here - there are currently a total of 6 tabs. + // The first is SSL and cipher related + // The second is OpenSSL settings + // The third is user's SSL certificate related + // The fourth is certificate authentication related + // The fifth is other SSL certificate related + // The sixth is CA related + // The seventh is misc. settings related (unimplemented) + // The eighth is peer [email] certificate related (unimplemented) + /////////////////////////////////////////////////////////////////////////// + + tabs = new QTabWidget(this); + top->addWidget(tabs); + + /////////////////////////////////////////////////////////////////////////// + // FIRST TAB + /////////////////////////////////////////////////////////////////////////// + tabSSL = new QFrame(this); + grid = new QGridLayout(tabSSL, 7, 2, KDialog::marginHint(), + KDialog::spacingHint() ); + mUseTLS = new QCheckBox(i18n("Enable &TLS support if supported by the server"), tabSSL); + connect(mUseTLS, SIGNAL(clicked()), SLOT(configChanged())); + grid->addWidget(mUseTLS, 0, 0); + whatstr = i18n("TLS is the newest revision of the SSL protocol." + " It integrates better with other protocols and has" + " replaced SSL in protocols such as POP3 and SMTP."); + QWhatsThis::add(mUseTLS, whatstr); + + mUseSSLv2 = new QCheckBox(i18n("Enable SSLv&2"), tabSSL); + connect(mUseSSLv2, SIGNAL(clicked()), SLOT(configChanged())); + grid->addWidget(mUseSSLv2, 1, 0); + whatstr = i18n("SSL v2 is the second revision of the SSL protocol." + " It is most common to enable v2 and v3."); + QWhatsThis::add(mUseSSLv2, whatstr); + + mUseSSLv3 = new QCheckBox(i18n("Enable SSLv&3"), tabSSL); + connect(mUseSSLv3, SIGNAL(clicked()), SLOT(configChanged())); + grid->addWidget(mUseSSLv3, 1, 1); + whatstr = i18n("SSL v3 is the third revision of the SSL protocol." + " It is most common to enable v2 and v3."); + QWhatsThis::add(mUseSSLv3, whatstr); + +#ifdef HAVE_SSL + SSLv2Box = new QListView(tabSSL, "v2ciphers"); + (void) SSLv2Box->addColumn(i18n("SSLv2 Ciphers to Use")); + whatstr = i18n("Select the ciphers you wish to enable when using the" + " SSL v2 protocol. The actual protocol used will be" + " negotiated with the server at connection time."); + QWhatsThis::add(SSLv2Box, whatstr); + SSLv2Box->setSelectionMode(QListView::NoSelection); + + grid->addWidget( SSLv2Box, 2, 0 ); + connect( mUseSSLv2, SIGNAL( toggled( bool ) ), + SSLv2Box, SLOT( setEnabled( bool ))); +#else + QLabel *nossllabel = new QLabel(i18n("SSL ciphers cannot be configured" + " because this module was not linked" + " with OpenSSL."), tabSSL); + grid->addMultiCellWidget(nossllabel, 2, 2, 0, 1); + grid->addRowSpacing( 3, 100 ); // give minimum height to look better +#endif + + // no need to parse kdeglobals. + config = new KConfig("cryptodefaults", false, false); + policies = new KSimpleConfig("ksslpolicies", false); + pcerts = new KSimpleConfig("ksslcertificates", false); + authcfg = new KSimpleConfig("ksslauthmap", false); + +#ifdef HAVE_SSL + SSLv3Box = new QListView(tabSSL, "v3ciphers"); + (void) SSLv3Box->addColumn(i18n("SSLv3 Ciphers to Use")); + whatstr = i18n("Select the ciphers you wish to enable when using the" + " SSL v3 protocol. The actual protocol used will be" + " negotiated with the server at connection time."); + QWhatsThis::add(SSLv3Box, whatstr); + SSLv3Box->setSelectionMode(QListView::NoSelection); + grid->addWidget(SSLv3Box, 2, 1); + connect( mUseSSLv3, SIGNAL( toggled( bool ) ), + SSLv3Box, SLOT( setEnabled( bool ))); + + loadCiphers(); + + // + // CipherWizards + // + QHGroupBox *cwbg = new QHGroupBox(i18n("Cipher Wizard"), tabSSL); + QComboBox *cwcb = new QComboBox(cwbg); + grid->addMultiCellWidget(cwbg, 3, 3, 0, 1); + QString whatStr = i18n("<qt>Use these preconfigurations to more easily configure the SSL encryption settings. You can choose among the following modes: <ul>"); + + cwcb->insertItem(QString::null); + cwcb->insertItem(i18n("Most Compatible")); + whatStr += i18n("<li><b>Most Compatible:</b> Select the settings found to be most compatible.</li>"); + cwcb->insertItem(i18n("US Ciphers Only")); + whatStr += i18n("<li><b>US Ciphers Only:</b> Select only the US strong (>= 128 bit) encryption ciphers.</li>"); + cwcb->insertItem(i18n("Export Ciphers Only")); + whatStr += i18n("<li><b>Export Ciphers Only:</b> Select only the weak ciphers (<= 56 bit).</li>"); + cwcb->insertItem(i18n("Enable All")); + whatStr += i18n("<li><b>Enable All:</b> Select all SSL ciphers and methods.</li></ul>"); + + QWhatsThis::add(cwcb, whatStr); + + connect(cwcb, SIGNAL(activated(int)), SLOT(slotSelectCipher(int))); + + + + +#endif + + mWarnOnEnter = new QCheckBox(i18n("Warn on &entering SSL mode"), tabSSL); + connect(mWarnOnEnter, SIGNAL(clicked()), SLOT(configChanged())); + grid->addWidget(mWarnOnEnter, 5, 0); + whatstr = i18n("If selected, you will be notified when entering an SSL" + " enabled site"); + QWhatsThis::add(mWarnOnEnter, whatstr); + + mWarnOnLeave = new QCheckBox(i18n("Warn on &leaving SSL mode"), tabSSL); + connect(mWarnOnLeave, SIGNAL(clicked()), SLOT(configChanged())); + grid->addWidget(mWarnOnLeave, 5, 1); + whatstr = i18n("If selected, you will be notified when leaving an SSL" + " based site."); + QWhatsThis::add(mWarnOnLeave, whatstr); + + mWarnOnUnencrypted = new QCheckBox(i18n("Warn on sending &unencrypted data"), tabSSL); + connect(mWarnOnUnencrypted, SIGNAL(clicked()), SLOT(configChanged())); + grid->addWidget(mWarnOnUnencrypted, 6, 0); + whatstr = i18n("If selected, you will be notified before sending" + " unencrypted data via a web browser."); + QWhatsThis::add(mWarnOnUnencrypted, whatstr); + +#if 0 // NOT IMPLEMENTED IN KDE 3.0 + mWarnOnMixed = new QCheckBox(i18n("Warn on &mixed SSL/non-SSL pages"), tabSSL); + connect(mWarnOnMixed, SIGNAL(clicked()), SLOT(configChanged())); + grid->addWidget(mWarnOnMixed, 6, 1); + whatstr = i18n("If selected, you will be notified if you view a page" + " that has both encrypted and non-encrypted parts."); + QWhatsThis::add(mWarnOnMixed, whatstr); +#endif + + /////////////////////////////////////////////////////////////////////////// + // SECOND TAB + /////////////////////////////////////////////////////////////////////////// + +#ifdef HAVE_SSL + tabOSSL = new QFrame(this); + QBoxLayout *vbox = new QVBoxLayout(tabOSSL, KDialog::marginHint(), KDialog::spacingHint()); + + oInfo = new QVGroupBox(i18n("Path to OpenSSL Shared Libraries"), tabOSSL); + vbox->addWidget(oInfo); + oPath = new KURLRequester(oInfo); + oPath->setMode(KFile::Directory); + oTest = new QPushButton(i18n("&Test"), oInfo); + connect(oTest, SIGNAL(clicked()), SLOT(slotTestOSSL())); + + connect(oPath, SIGNAL(textChanged(const QString&)), SLOT(configChanged())); + + // + // Settings for the EGD + // + QFrame *eFrame = new QFrame(tabOSSL); + QVBoxLayout *egrid = new QVBoxLayout(eFrame); + mUseEGD = new QCheckBox(i18n("Use EGD"), eFrame); + connect(mUseEGD, SIGNAL(clicked()), SLOT(slotUseEGD())); + mUseEFile = new QCheckBox(i18n("Use entropy file"), eFrame); + connect(mUseEFile, SIGNAL(clicked()), SLOT(slotUseEFile())); + vbox->addWidget(eFrame); + egrid->addWidget(mUseEGD); + egrid->addWidget(mUseEFile); + QFrame *egdframe = new QFrame(tabOSSL); + QGridLayout *grid2 = new QGridLayout(egdframe, 2, 2, KDialog::marginHint(), + KDialog::spacingHint()); + mEGDLabel = new QLabel(i18n("Path to EGD:"), egdframe); + grid2->addWidget(mEGDLabel, 0, 0); + mEGDPath = new KURLRequester(egdframe); + grid2->addWidget(mEGDPath, 0, 1); + connect(mEGDPath, SIGNAL(textChanged(const QString&)), SLOT(configChanged())); + vbox->addWidget(egdframe); + whatstr = i18n("If selected, OpenSSL will be asked to use the entropy gathering" + " daemon (EGD) for initializing the pseudo-random number generator."); + QWhatsThis::add(mUseEGD, whatstr); + whatstr = i18n("If selected, OpenSSL will be asked to use the given file" + " as entropy for initializing the pseudo-random number generator."); + QWhatsThis::add(mUseEFile, whatstr); + whatstr = i18n("Enter the path to the socket created by the entropy gathering" + " daemon (or the entropy file) here."); + QWhatsThis::add(mEGDPath, whatstr); + whatstr = i18n("Click here to browse for the EGD socket file."); + QWhatsThis::add(mEGDPath, whatstr); + + vbox->addStretch(); +#endif + + + + /////////////////////////////////////////////////////////////////////////// + // THIRD TAB + /////////////////////////////////////////////////////////////////////////// + tabYourSSLCert = new QFrame(this); + +#ifdef HAVE_SSL + grid = new QGridLayout(tabYourSSLCert, 16, 6, KDialog::marginHint(), KDialog::spacingHint() ); + + yourSSLBox = new QListView(tabYourSSLCert); + yourSSLBox->setAllColumnsShowFocus(true); + whatstr = i18n("This list box shows which certificates of yours KDE" + " knows about. You can easily manage them from here."); + QWhatsThis::add(yourSSLBox, whatstr); + grid->addMultiCellWidget(yourSSLBox, 0, 5, 0, 4); + yourSSLBox->addColumn(i18n("Common Name")); + yourSSLBox->addColumn(i18n("Email Address")); + connect(yourSSLBox, SIGNAL(selectionChanged()), SLOT(slotYourCertSelect())); + + yourSSLImport = new QPushButton(i18n("I&mport..."), tabYourSSLCert); + connect(yourSSLImport, SIGNAL(clicked()), SLOT(slotYourImport())); + grid->addWidget(yourSSLImport, 0, 5); + + yourSSLExport = new QPushButton(i18n("&Export..."), tabYourSSLCert); + yourSSLExport->setEnabled(false); + connect(yourSSLExport, SIGNAL(clicked()), SLOT(slotYourExport())); + grid->addWidget(yourSSLExport, 1, 5); + + yourSSLRemove = new QPushButton(i18n("Remo&ve"), tabYourSSLCert); + yourSSLRemove->setEnabled(false); + connect(yourSSLRemove, SIGNAL(clicked()), SLOT(slotYourRemove())); + grid->addWidget(yourSSLRemove, 2, 5); + + yourSSLUnlock = new QPushButton(i18n("&Unlock"), tabYourSSLCert); + yourSSLUnlock->setEnabled(false); + connect(yourSSLUnlock, SIGNAL(clicked()), SLOT(slotYourUnlock())); + grid->addWidget(yourSSLUnlock, 3, 5); + + yourSSLVerify = new QPushButton(i18n("Verif&y"), tabYourSSLCert); + yourSSLVerify->setEnabled(false); + connect(yourSSLVerify, SIGNAL(clicked()), SLOT(slotYourVerify())); + grid->addWidget(yourSSLVerify, 4, 5); + + yourSSLPass = new QPushButton(i18n("Chan&ge Password..."), tabYourSSLCert); + yourSSLPass->setEnabled(false); + connect(yourSSLPass, SIGNAL(clicked()), SLOT(slotYourPass())); + grid->addWidget(yourSSLPass, 5, 5); + + grid->addMultiCellWidget(new KSeparator(KSeparator::HLine, tabYourSSLCert), 6, 6, 0, 5); + ySubject = KSSLInfoDlg::certInfoWidget(tabYourSSLCert, QString(QString::null)); + yIssuer = KSSLInfoDlg::certInfoWidget(tabYourSSLCert, QString(QString::null)); + grid->addMultiCellWidget(ySubject, 7, 11, 0, 2); + grid->addMultiCellWidget(yIssuer, 7, 11, 3, 5); + whatstr = i18n("This is the information known about the owner of the certificate."); + QWhatsThis::add(ySubject, whatstr); + whatstr = i18n("This is the information known about the issuer of the certificate."); + QWhatsThis::add(yIssuer, whatstr); + + grid->addWidget(new QLabel(i18n("Valid from:"), tabYourSSLCert), 12, 0); + grid->addWidget(new QLabel(i18n("Valid until:"), tabYourSSLCert), 13, 0); + yValidFrom = new QLabel(tabYourSSLCert); + grid->addWidget(yValidFrom, 12, 1); + yValidUntil = new QLabel(tabYourSSLCert); + grid->addWidget(yValidUntil, 13, 1); + whatstr = i18n("The certificate is valid starting at this date."); + QWhatsThis::add(yValidFrom, whatstr); + whatstr = i18n("The certificate is valid until this date."); + QWhatsThis::add(yValidUntil, whatstr); + grid->addWidget(new QLabel(i18n("MD5 digest:"), tabYourSSLCert), 14, 0); + yHash = new QLabel(tabYourSSLCert); + grid->addWidget(yHash, 14, 1); + whatstr = i18n("A hash of the certificate used to identify it quickly."); + QWhatsThis::add(yHash, whatstr); + +#if 0 + QHButtonGroup *ocbg = new QHButtonGroup(i18n("On SSL Connection..."), tabYourSSLCert); + yourSSLUseDefault = new QRadioButton(i18n("&Use default certificate"), ocbg); + yourSSLList = new QRadioButton(i18n("&List upon connection"), ocbg); + yourSSLDont = new QRadioButton(i18n("&Do not use certificates"), ocbg); + grid->addMultiCellWidget(ocbg, 14, 14, 0, 5); +#endif +#else + nossllabel = new QLabel(i18n("SSL certificates cannot be managed" + " because this module was not linked" + " with OpenSSL."), tabYourSSLCert); + grid->addMultiCellWidget(nossllabel, 3, 3, 0, 5); +#endif + + + /////////////////////////////////////////////////////////////////////////// + // FOURTH TAB + /////////////////////////////////////////////////////////////////////////// + tabAuth = new QFrame(this); + +#ifdef HAVE_SSL + grid = new QGridLayout(tabAuth, 20, 6, KDialog::marginHint(), KDialog::spacingHint()); + + grid->addMultiCellWidget(new QLabel(i18n("Default Authentication Certificate"), tabAuth), 0, 0, 0, 2); + defCertBG = new QVButtonGroup(i18n("Default Action"), tabAuth); + defSend = new QRadioButton(i18n("&Send"), defCertBG); + defPrompt = new QRadioButton(i18n("&Prompt"), defCertBG); + defDont = new QRadioButton(i18n("Do ¬ send"), defCertBG); + grid->addMultiCellWidget(defCertBG, 1, 3, 0, 2); + grid->addMultiCellWidget(new QLabel(i18n("Default certificate:"), tabAuth), 1, 1, 3, 5); + defCertBox = new KComboBox(false, tabAuth); + grid->addMultiCellWidget(defCertBox, 2, 2, 3, 5); + + grid->addMultiCellWidget(new KSeparator(KSeparator::HLine, tabAuth), 4, 4, 0, 5); + + + grid->addMultiCellWidget(new QLabel(i18n("Host authentication:"), tabAuth), 5, 5, 0, 1); + hostAuthList = new QListView(tabAuth); + hostAuthList->setAllColumnsShowFocus(true); + grid->addMultiCellWidget(hostAuthList, 6, 13, 0, 5); + hostAuthList->addColumn(i18n("Host")); + hostAuthList->addColumn(i18n("Certificate")); + hostAuthList->addColumn(i18n("Policy")); + + grid->addWidget(new QLabel(i18n("Host:"), tabAuth), 14, 0); + grid->addWidget(new QLabel(i18n("Certificate:"), tabAuth), 15, 0); + + authHost = new QLineEdit(tabAuth); + grid->addMultiCellWidget(authHost, 14, 14, 1, 4); + hostCertBox = new KComboBox(false, tabAuth); + grid->addMultiCellWidget(hostCertBox, 15, 15, 1, 4); + + hostCertBG = new QHButtonGroup(i18n("Action"), tabAuth); + hostSend = new QRadioButton(i18n("Send"), hostCertBG); + hostPrompt = new QRadioButton(i18n("Prompt"), hostCertBG); + hostDont = new QRadioButton(i18n("Do not send"), hostCertBG); + grid->addMultiCellWidget(hostCertBG, 16, 16, 0, 5); + + authAdd = new QPushButton(i18n("Ne&w"), tabAuth); + authRemove = new QPushButton(i18n("Remo&ve"), tabAuth); + grid->addWidget(authAdd, 17, 4); + grid->addWidget(authRemove, 17, 5); + + authHost->setEnabled(false); + hostCertBox->setEnabled(false); + hostCertBG->setEnabled(false); + authRemove->setEnabled(false); + + connect(defCertBox, SIGNAL(activated(int)), this, SLOT(configChanged())); + connect(defCertBG, SIGNAL(clicked(int)), this, SLOT(configChanged())); + connect(hostAuthList, SIGNAL(selectionChanged()), this, SLOT(slotAuthItemChanged())); + connect(authAdd, SIGNAL(clicked()), this, SLOT(slotNewHostAuth())); + connect(authRemove, SIGNAL(clicked()), this, SLOT(slotRemoveHostAuth())); + connect(authHost, SIGNAL(textChanged(const QString &)), this, SLOT(slotAuthText(const QString &))); + connect(hostCertBG, SIGNAL(clicked(int)), this, SLOT(slotAuthButtons())); + connect(hostCertBox, SIGNAL(activated(int)), this, SLOT(slotAuthCombo())); + +#else + nossllabel = new QLabel(i18n("SSL certificates cannot be managed" + " because this module was not linked" + " with OpenSSL."), tabAuth); + grid->addMultiCellWidget(nossllabel, 3, 3, 0, 5); +#endif + + + + /////////////////////////////////////////////////////////////////////////// + // FIFTH TAB + /////////////////////////////////////////////////////////////////////////// + tabOtherSSLCert = new QFrame(this); + +#ifdef HAVE_SSL + oGrid = grid = new QGridLayout(tabOtherSSLCert, 21, 6, KDialog::marginHint(), KDialog::spacingHint()); + + otherSSLBox = new QListView(tabOtherSSLCert); + otherSSLBox->setAllColumnsShowFocus(true); + connect(otherSSLBox, SIGNAL(selectionChanged()), SLOT(slotOtherCertSelect())); + whatstr = i18n("This list box shows which site and person certificates KDE" + " knows about. You can easily manage them from here."); + QWhatsThis::add(otherSSLBox, whatstr); + otherSSLBox->addColumn(i18n("Organization")); + otherSSLBox->addColumn(i18n("Common Name")); + grid->addMultiCellWidget(otherSSLBox, 0, 7, 0, 4); + + otherSSLExport = new QPushButton(i18n("&Export..."), tabOtherSSLCert); + connect(otherSSLExport, SIGNAL(clicked()), SLOT(slotExportCert())); + grid->addWidget(otherSSLExport, 0, 5); + whatstr = i18n("This button allows you to export the selected certificate" + " to a file of various formats."); + QWhatsThis::add(otherSSLExport, whatstr); + + otherSSLRemove = new QPushButton(i18n("&Remove"), tabOtherSSLCert); + connect(otherSSLRemove, SIGNAL(clicked()), SLOT(slotRemoveCert())); + grid->addWidget(otherSSLRemove, 1, 5); + whatstr = i18n("This button removes the selected certificate" + " from the certificate cache."); + QWhatsThis::add(otherSSLRemove, whatstr); + + otherSSLVerify = new QPushButton(i18n("&Verify"), tabOtherSSLCert); + connect(otherSSLVerify, SIGNAL(clicked()), SLOT(slotVerifyCert())); + grid->addWidget(otherSSLVerify, 2, 5); + whatstr = i18n("This button tests the selected certificate" + " for validity."); + QWhatsThis::add(otherSSLVerify, whatstr); + + otherSSLExport->setEnabled(false); + otherSSLVerify->setEnabled(false); + otherSSLRemove->setEnabled(false); + + grid->addMultiCellWidget(new KSeparator(KSeparator::HLine, tabOtherSSLCert), 8, 8, 0, 5); + oSubject = KSSLInfoDlg::certInfoWidget(tabOtherSSLCert, QString(QString::null)); + oIssuer = KSSLInfoDlg::certInfoWidget(tabOtherSSLCert, QString(QString::null)); + grid->addMultiCellWidget(oSubject, 9, 13, 0, 2); + grid->addMultiCellWidget(oIssuer, 9, 13, 3, 5); + whatstr = i18n("This is the information known about the owner of the certificate."); + QWhatsThis::add(oSubject, whatstr); + whatstr = i18n("This is the information known about the issuer of the certificate."); + QWhatsThis::add(oIssuer, whatstr); + + fromLabel = new QLabel(i18n("Valid from:"), tabOtherSSLCert); + untilLabel = new QLabel(i18n("Valid until:"), tabOtherSSLCert); + grid->addWidget(fromLabel, 14, 0); + grid->addWidget(untilLabel, 15, 0); + fromLabel->setEnabled(false); + untilLabel->setEnabled(false); + validFrom = new QLabel(tabOtherSSLCert); + grid->addWidget(validFrom, 14, 1); + validUntil = new QLabel(tabOtherSSLCert); + grid->addWidget(validUntil, 15, 1); + whatstr = i18n("The certificate is valid starting at this date."); + QWhatsThis::add(validFrom, whatstr); + whatstr = i18n("The certificate is valid until this date."); + QWhatsThis::add(validUntil, whatstr); + + cacheGroup = new QVButtonGroup(i18n("Cache"), tabOtherSSLCert); + cachePerm = new QRadioButton(i18n("Permanentl&y"), cacheGroup); + cacheUntil = new QRadioButton(i18n("&Until"), cacheGroup); + untilDate = new KURLLabel(QString::null, QString::null, cacheGroup); + cacheGroup->setEnabled(false); + grid->addMultiCellWidget(cacheGroup, 16, 19, 0, 2); + + cachePerm->setEnabled(false); + cacheUntil->setEnabled(false); + untilDate->setEnabled(false); + connect(cachePerm, SIGNAL(clicked()), SLOT(slotPermanent())); + connect(cacheUntil, SIGNAL(clicked()), SLOT(slotUntil())); + connect(untilDate, SIGNAL(leftClickedURL()), SLOT(slotDatePick())); + whatstr = i18n("Select here to make the cache entry permanent."); + QWhatsThis::add(cachePerm, whatstr); + whatstr = i18n("Select here to make the cache entry temporary."); + QWhatsThis::add(cacheUntil, whatstr); + whatstr = i18n("The date and time until the certificate cache entry should expire."); + QWhatsThis::add(untilDate, whatstr); + + policyGroup = new QVButtonGroup(i18n("Policy"), tabOtherSSLCert); + policyAccept = new QRadioButton(i18n("Accep&t"), policyGroup); + policyReject = new QRadioButton(i18n("Re&ject"), policyGroup); + policyPrompt = new QRadioButton(i18n("&Prompt"), policyGroup); + policyGroup->setEnabled(false); + grid->addMultiCellWidget(policyGroup, 16, 19, 3, 5); + connect(policyGroup, SIGNAL(clicked(int)), SLOT(slotPolicyChanged(int))); + whatstr = i18n("Select this to always accept this certificate."); + QWhatsThis::add(policyAccept, whatstr); + whatstr = i18n("Select this to always reject this certificate."); + QWhatsThis::add(policyReject, whatstr); + whatstr = i18n("Select this if you wish to be prompted for action when receiving this certificate."); + QWhatsThis::add(policyPrompt, whatstr); + grid->addWidget(new QLabel(i18n("MD5 digest:"), tabOtherSSLCert), 20, 0); + pHash = new QLabel(tabOtherSSLCert); + grid->addWidget(pHash, 20, 1); + whatstr = i18n("A hash of the certificate used to identify it quickly."); + QWhatsThis::add(pHash, whatstr); + +#else + nossllabel = new QLabel(i18n("SSL certificates cannot be managed" + " because this module was not linked" + " with OpenSSL."), tabOtherSSLCert); + grid->addMultiCellWidget(nossllabel, 1, 1, 0, 1); +#endif + + + /////////////////////////////////////////////////////////////////////////// + // SIXTH TAB + /////////////////////////////////////////////////////////////////////////// + tabSSLCA = new QFrame(this); + +#ifdef HAVE_SSL + grid = new QGridLayout(tabSSLCA, 11, 8, KDialog::marginHint(), KDialog::spacingHint()); + + caList = new QListView(tabSSLCA); + caList->setAllColumnsShowFocus(true); + whatstr = i18n("This list box shows which certificate authorities KDE" + " knows about. You can easily manage them from here."); + QWhatsThis::add(caList, whatstr); + grid->addMultiCellWidget(caList, 0, 3, 0, 6); + caList->addColumn(i18n("Organization")); + caList->addColumn(i18n("Organizational Unit")); + caList->addColumn(i18n("Common Name")); + connect(caList, SIGNAL(selectionChanged()), SLOT(slotCAItemChanged())); + + caSSLImport = new QPushButton(i18n("I&mport..."), tabSSLCA); + connect(caSSLImport, SIGNAL(clicked()), SLOT(slotCAImport())); + grid->addWidget(caSSLImport, 0, 7); + + caSSLRemove = new QPushButton(i18n("&Remove"), tabSSLCA); + connect(caSSLRemove, SIGNAL(clicked()), SLOT(slotCARemove())); + grid->addWidget(caSSLRemove, 1, 7); + caSSLRemove->setEnabled(false); + + caSSLRestore = new QPushButton(i18n("Res&tore"), tabSSLCA); + connect(caSSLRestore, SIGNAL(clicked()), SLOT(slotCARestore())); + grid->addWidget(caSSLRestore, 2, 7); + + caSubject = KSSLInfoDlg::certInfoWidget(tabSSLCA, QString(QString::null)); + caIssuer = KSSLInfoDlg::certInfoWidget(tabSSLCA, QString(QString::null)); + grid->addMultiCellWidget(caSubject, 4, 6, 0, 3); + grid->addMultiCellWidget(caIssuer, 4, 6, 4, 7); + + // Accept for Web Site Signing, Email Signing, Code Signing + caSite = new QCheckBox(i18n("Accept for site signing"), tabSSLCA); + caEmail = new QCheckBox(i18n("Accept for email signing"), tabSSLCA); + caCode = new QCheckBox(i18n("Accept for code signing"), tabSSLCA); + grid->addMultiCellWidget(caSite, 7, 7, 0, 3); + connect(caSite, SIGNAL(clicked()), SLOT(slotCAChecked())); + grid->addMultiCellWidget(caEmail, 8, 8, 0, 3); + connect(caEmail, SIGNAL(clicked()), SLOT(slotCAChecked())); + grid->addMultiCellWidget(caCode, 9, 9, 0, 3); + connect(caCode, SIGNAL(clicked()), SLOT(slotCAChecked())); + caSite->setEnabled(false); + caEmail->setEnabled(false); + caCode->setEnabled(false); + grid->addWidget(new QLabel(i18n("MD5 digest:"), tabSSLCA), 10, 0); + cHash = new QLabel(tabSSLCA); + grid->addWidget(cHash, 10, 1); + whatstr = i18n("A hash of the certificate used to identify it quickly."); + QWhatsThis::add(cHash, whatstr); + +#else + nossllabel = new QLabel(i18n("SSL certificates cannot be managed" + " because this module was not linked" + " with OpenSSL."), tabSSLCA); + grid->addMultiCellWidget(nossllabel, 1, 1, 0, 1); +#endif + + +#if 0 + /////////////////////////////////////////////////////////////////////////// + // SEVENTH TAB + /////////////////////////////////////////////////////////////////////////// + tabSSLCOpts = new QFrame(this); + +#ifdef HAVE_SSL + grid = new QGridLayout(tabSSLCOpts, 9, 4, KDialog::marginHint(), KDialog::spacingHint()); + mWarnSelfSigned = new QCheckBox(i18n("Warn on &self-signed certificates or unknown CA's"), tabSSLCOpts); + connect(mWarnSelfSigned, SIGNAL(clicked()), SLOT(configChanged())); + mWarnExpired = new QCheckBox(i18n("Warn on &expired certificates"), tabSSLCOpts); + connect(mWarnExpired, SIGNAL(clicked()), SLOT(configChanged())); + mWarnRevoked = new QCheckBox(i18n("Warn on re&voked certificates"), tabSSLCOpts); + connect(mWarnRevoked, SIGNAL(clicked()), SLOT(configChanged())); + grid->addMultiCellWidget(mWarnSelfSigned, 0, 0, 0, 3); + grid->addMultiCellWidget(mWarnExpired, 1, 1, 0, 3); + grid->addMultiCellWidget(mWarnRevoked, 2, 2, 0, 3); + + macCert = new QLineEdit(tabSSLCOpts); + grid->addMultiCellWidget(macCert, 4, 4, 0, 2); + + macBox = new QListBox(tabSSLCOpts); + whatstr = i18n("This list box shows which sites you have decided to accept" + " a certificate from even though the certificate might fail" + " the validation procedure."); + QWhatsThis::add(macBox, whatstr); + caSSLBox->setSelectionMode(QListBox::Single); + caSSLBox->setColumnMode(QListBox::FixedNumber); + grid->addMultiCellWidget(macBox, 5, 8, 0, 2); + + macAdd = new QPushButton(i18n("&Add"), tabSSLCOpts); + //connect(macAdd, SIGNAL(), SLOT()); + grid->addWidget(macAdd, 4, 3); + + macRemove = new QPushButton(i18n("&Remove"), tabSSLCOpts); + //connect(macRemove, SIGNAL(), SLOT()); + grid->addWidget(macRemove, 5, 3); + + macClear = new KPushButton(KGuiItem::clear(), tabSSLCOpts); + //connect(macAdd, SIGNAL(), SLOT()); + grid->addWidget(macClear, 6, 3); + +#else + nossllabel = new QLabel(i18n("These options are not configurable" + " because this module was not linked" + " with OpenSSL."), tabSSLCOpts); + grid->addMultiCellWidget(nossllabel, 1, 1, 0, 1); +#endif +#endif + + /////////////////////////////////////////////////////////////////////////// + // Add the tabs and startup + /////////////////////////////////////////////////////////////////////////// + tabs->addTab(tabSSL, i18n("SSL")); +#ifdef HAVE_SSL + tabs->addTab(tabOSSL, i18n("OpenSSL")); +#endif + tabs->addTab(tabYourSSLCert, i18n("Your Certificates")); + tabs->addTab(tabAuth, i18n("Authentication")); + tabs->addTab(tabOtherSSLCert, i18n("Peer SSL Certificates")); + tabs->addTab(tabSSLCA, i18n("SSL Signers")); + +#if 0 + tabs->addTab(tabSSLCOpts, i18n("Validation Options")); +#endif + + tabs->resize(tabs->sizeHint()); + load(); +} + +KCryptoConfig::~KCryptoConfig() +{ + delete config; + delete policies; + delete pcerts; + delete authcfg; + delete _signers; +} + +void KCryptoConfig::configChanged() +{ + emit changed(true); +} + +void KCryptoConfig::load() +{ + load( false ); +} + +void KCryptoConfig::load( bool useDefaults ) +{ + config->setReadDefaults( useDefaults ); +#ifdef HAVE_SSL + otherCertDelList.clear(); + yourCertDelList.clear(); + authDelList.clear(); + caDelList.clear(); + config->setGroup("TLS"); + mUseTLS->setChecked(config->readBoolEntry("Enabled", true)); + + config->setGroup("SSLv2"); + mUseSSLv2->setChecked(config->readBoolEntry("Enabled", true)); + + config->setGroup("SSLv3"); + mUseSSLv3->setChecked(config->readBoolEntry("Enabled", true)); + + config->setGroup("Warnings"); + mWarnOnEnter->setChecked(config->readBoolEntry("OnEnter", false)); + mWarnOnLeave->setChecked(config->readBoolEntry("OnLeave", true)); + mWarnOnUnencrypted->setChecked(config->readBoolEntry("OnUnencrypted", true)); + +#if 0 // NOT IMPLEMENTED IN KDE 2.0 + mWarnOnMixed->setChecked(config->readBoolEntry("OnMixed", true)); + + config->setGroup("Validation"); + mWarnSelfSigned->setChecked(config->readBoolEntry("WarnSelfSigned", true)); + mWarnExpired->setChecked(config->readBoolEntry("WarnExpired", true)); + mWarnRevoked->setChecked(config->readBoolEntry("WarnRevoked", true)); +#endif + + config->setGroup("EGD"); + slotUseEGD(); // set the defaults + if (config->readBoolEntry("UseEGD", false)) { + mUseEGD->setChecked(true); + slotUseEGD(); + } else if (config->readBoolEntry("UseEFile", false)) { + mUseEFile->setChecked(true); + slotUseEFile(); + } + mEGDPath->setURL(config->readPathEntry("EGDPath")); + + +#ifdef HAVE_SSL + config->setGroup("OpenSSL"); + oPath->setURL(config->readPathEntry("Path")); +#endif + + config->setGroup("SSLv2"); + CipherItem *item = static_cast<CipherItem *>(SSLv2Box->firstChild()); + while ( item ) { + item->setOn(config->readBoolEntry(item->configName(), + item->bits() >= 56)); + item = static_cast<CipherItem *>(item->nextSibling()); + } + + config->setGroup("SSLv3"); + item = static_cast<CipherItem *>(SSLv3Box->firstChild()); + while ( item ) { + item->setOn(config->readBoolEntry(item->configName(), + item->bits() >= 56)); + item = static_cast<CipherItem *>(item->nextSibling()); + } + + SSLv2Box->setEnabled( mUseSSLv2->isChecked() ); + SSLv3Box->setEnabled( mUseSSLv3->isChecked() ); + + QStringList groups = policies->groupList(); + + otherSSLBox->clear(); + for (QStringList::Iterator i = groups.begin(); i != groups.end(); ++i) { + if ((*i).isEmpty() || *i == "<default>" || *i == "General") continue; + policies->setGroup(*i); + KSSLCertificate *cert = KSSLCertificate::fromString(policies->readEntry("Certificate", QString::null).local8Bit()); + if (cert) { + new OtherCertItem(otherSSLBox, cert->getSubject(), *i, + policies->readBoolEntry("Permanent", true), + policies->readNumEntry("Policy", 3), + policies->readDateTimeEntry("Expires"), this ); + delete cert; + } + } + + groups = pcerts->groupList(); + + yourSSLBox->clear(); + for (QStringList::Iterator i = groups.begin(); i != groups.end(); ++i) { + if ((*i).isEmpty() || *i == "<default>") continue; + pcerts->setGroup(*i); + YourCertItem *j = new YourCertItem(yourSSLBox, + pcerts->readEntry("PKCS12Base64"), + pcerts->readEntry("Password"), + *i, this ); + j->setPassCache(QString::null); + } + + setAuthCertLists(); + + config->setGroup("Auth"); + QString whichAuth = config->readEntry("AuthMethod", "none"); + if (whichAuth == "send") + defCertBG->setButton(defCertBG->id(defSend)); + else if (whichAuth == "prompt") + defCertBG->setButton(defCertBG->id(defPrompt)); + else + defCertBG->setButton(defCertBG->id(defDont)); + + QString whichCert = config->readEntry("DefaultCert"); + defCertBox->setCurrentItem(0); + for (int i = 0; i < defCertBox->count(); i++) { + if (defCertBox->text(i) == whichCert) { + defCertBox->setCurrentItem(i); + break; + } + } + hostAuthList->clear(); + groups = authcfg->groupList(); + for (QStringList::Iterator i = groups.begin(); + i != groups.end(); + ++i) { + if ((*i).isEmpty() || *i == "<default>") continue; + authcfg->setGroup(*i); + KSSLCertificateHome::KSSLAuthAction aa = KSSLCertificateHome::AuthDont; + if (authcfg->readBoolEntry("send", false) == true) + aa = KSSLCertificateHome::AuthSend; + else if (authcfg->readBoolEntry("prompt", false) == true) + aa = KSSLCertificateHome::AuthPrompt; + HostAuthItem *j = new HostAuthItem(hostAuthList, + KResolver::domainToAscii(*i), + authcfg->readEntry("certificate"), + this ); + j->setAction(aa); + j->setOriginalName(*i); + } + + groups = _signers->list(); + KConfig sigcfg("ksslcalist", true, false); + caList->clear(); + for (QStringList::Iterator i = groups.begin(); + i != groups.end(); + ++i) { + if ((*i).isEmpty() || *i == "<default>") continue; + if (!sigcfg.hasGroup(*i)) continue; + sigcfg.setGroup(*i); + if (!sigcfg.hasKey("x509")) continue; + new CAItem(caList, + (*i), + sigcfg.readEntry("x509"), + sigcfg.readBoolEntry("site", false), + sigcfg.readBoolEntry("email", false), + sigcfg.readBoolEntry("code", false), + this ); + } + + slotCAItemChanged(); + slotOtherCertSelect(); + slotYourCertSelect(); +#endif + + emit changed( useDefaults ); +} + +void KCryptoConfig::save() +{ +#ifdef HAVE_SSL + if (!mUseSSLv2->isChecked() && + !mUseSSLv3->isChecked()) + KMessageBox::information(this, i18n("If you do not select at least one" + " SSL algorithm, either SSL will not" + " work or the application may be" + " forced to choose a suitable default."), + i18n("SSL")); + + config->setGroup("TLS"); + config->writeEntry("Enabled", mUseTLS->isChecked()); + + config->setGroup("SSLv2"); + config->writeEntry("Enabled", mUseSSLv2->isChecked()); + + config->setGroup("SSLv3"); + config->writeEntry("Enabled", mUseSSLv3->isChecked()); + + config->setGroup("Warnings"); + config->writeEntry("OnEnter", mWarnOnEnter->isChecked()); + config->writeEntry("OnLeave", mWarnOnLeave->isChecked()); + config->writeEntry("OnUnencrypted", mWarnOnUnencrypted->isChecked()); + + config->setGroup("EGD"); + config->writeEntry("UseEGD", mUseEGD->isChecked()); + config->writeEntry("UseEFile", mUseEFile->isChecked()); + config->writePathEntry("EGDPath", mEGDPath->url()); + +#if 0 // NOT IMPLEMENTED IN KDE 2.0 + config->writeEntry("OnMixed", mWarnOnMixed->isChecked()); + + config->setGroup("Validation"); + config->writeEntry("WarnSelfSigned", mWarnSelfSigned->isChecked()); + config->writeEntry("WarnExpired", mWarnExpired->isChecked()); + config->writeEntry("WarnRevoked", mWarnRevoked->isChecked()); +#endif + +#ifdef HAVE_SSL + config->setGroup("OpenSSL"); + config->writePathEntry("Path", oPath->url()); +#endif + + int ciphercount = 0; + config->setGroup("SSLv2"); + CipherItem *item = static_cast<CipherItem *>(SSLv2Box->firstChild()); + while ( item ) { + if (item->isOn()) { + config->writeEntry(item->configName(), true); + ciphercount++; + } else config->writeEntry(item->configName(), false); + + item = static_cast<CipherItem *>(item->nextSibling()); + } + + if (mUseSSLv2->isChecked() && ciphercount == 0) + KMessageBox::information(this, i18n("If you do not select at least one" + " cipher, SSLv2 will not work."), + i18n("SSLv2 Ciphers")); + + ciphercount = 0; + config->setGroup("SSLv3"); + item = static_cast<CipherItem *>(SSLv3Box->firstChild()); + while ( item ) { + if (item->isOn()) { + config->writeEntry(item->configName(), true); + ciphercount++; + } else config->writeEntry(item->configName(), false); + + item = static_cast<CipherItem *>(item->nextSibling()); + } + + KSSLCertificateCache _cc; + + if (mUseSSLv3->isChecked() && ciphercount == 0) + KMessageBox::information(this, i18n("If you do not select at least one" + " cipher, SSLv3 will not work."), + i18n("SSLv3 Ciphers")); + // SSL Policies code + for (OtherCertItem *x = otherCertDelList.first(); x != 0; x = otherCertDelList.next()) { + KSSLX509Map cert(x->configName()); + QString thisCN = cert.getValue("CN"); + _cc.removeByCN(thisCN); + otherCertDelList.remove(x); + } + // Go through the non-deleted ones and save them + for (OtherCertItem *x = + static_cast<OtherCertItem *>(otherSSLBox->firstChild()); + x; + x = static_cast<OtherCertItem *>(x->nextSibling())) { + KSSLX509Map cert(x->configName()); + QString thisCN = cert.getValue("CN"); + QDateTime expires = x->getExpires(); + _cc.modifyByCN(thisCN, (KSSLCertificateCache::KSSLCertificatePolicy)x->getPolicy(), x->isPermanent(), expires); + } + + // SSL Personal certificates code + for (YourCertItem *x = yourCertDelList.first(); x != 0; x = yourCertDelList.next()) { + pcerts->deleteGroup(x->configName()); + yourCertDelList.remove(x); + } + // Go through the non-deleted ones and save them + for (YourCertItem *x = + static_cast<YourCertItem *>(yourSSLBox->firstChild()); + x; + x = static_cast<YourCertItem *>(x->nextSibling())) { + pcerts->setGroup(x->configName()); + pcerts->writeEntry("PKCS12Base64", x->getPKCS()); + pcerts->writeEntry("Password", x->getPass()); + } + + bool doGen = false; + + // CA certificates code + for (CAItem *x = caDelList.first(); x != 0; x = caDelList.next()) { + _signers->remove(x->configName()); + caDelList.remove(x); + doGen = true; + } + + // Go through the non-deleted ones and save them + for (CAItem *x = static_cast<CAItem *>(caList->firstChild()); x; + x = static_cast<CAItem *>(x->nextSibling())) { + if (!x->modified && !x->isNew) continue; + if (x->isNew) { + x->isNew = false; + _signers->addCA(x->getCert(), + x->getSite(), + x->getEmail(), + x->getCode()); + } else { + _signers->setUse(x->configName(), + x->getSite(), + x->getEmail(), + x->getCode()); + } + x->modified = false; + doGen = true; + } + + if (doGen) genCAList(); + + + config->setGroup("Auth"); + QString whichAuth = config->readEntry("AuthMethod", "none"); + if (defCertBG->selected() == defSend) + config->writeEntry("AuthMethod", "send"); + else if (defCertBG->selected() == defPrompt) + config->writeEntry("AuthMethod", "prompt"); + else + config->writeEntry("AuthMethod", "none"); + + if (defCertBox->currentItem() == 0) + config->writeEntry("DefaultCert", QString::null); + else config->writeEntry("DefaultCert", defCertBox->currentText()); + + for (HostAuthItem *x = authDelList.first(); x != 0; x = authDelList.next()) { + authcfg->deleteGroup(x->configName()); + authDelList.remove(x); + } + + for (HostAuthItem *x = + static_cast<HostAuthItem *>(hostAuthList->firstChild()); + x; + x = static_cast<HostAuthItem *>(x->nextSibling())) { + if (!x->originalName().isNull()) + authcfg->deleteGroup(x->originalName()); + } + + for (HostAuthItem *x = + static_cast<HostAuthItem *>(hostAuthList->firstChild()); + x; + x = static_cast<HostAuthItem *>(x->nextSibling())) { + authcfg->setGroup(KResolver::domainToAscii(x->configName())); + authcfg->writeEntry("certificate", x->getCertName()); + authcfg->writeEntry("prompt", (x->getAction() == KSSLCertificateHome::AuthPrompt)); + authcfg->writeEntry("send", (x->getAction() == KSSLCertificateHome::AuthSend)); + } + +#endif + + config->sync(); + policies->sync(); + pcerts->sync(); + authcfg->sync(); + + // insure proper permissions -- contains sensitive data + QString cfgName(KGlobal::dirs()->findResource("config", "cryptodefaults")); + if (!cfgName.isEmpty()) + ::chmod(QFile::encodeName(cfgName), 0600); + + emit changed(false); +} + +void KCryptoConfig::defaults() +{ + load( true ); +} + +void KCryptoConfig::genCAList() { + _signers->regenerate(); + +} + +void KCryptoConfig::slotSelectCipher(int id) { + switch(id) { + case 1: + cwCompatible(); + break; + case 2: + cwUS(); + break; + case 3: + cwExp(); + break; + case 4: + cwAll(); + } +} + +void KCryptoConfig::cwCompatible() { + #ifdef HAVE_SSL + CipherItem *item; + for ( item = static_cast<CipherItem *>(SSLv2Box->firstChild()); item; + item = static_cast<CipherItem *>(item->nextSibling()) ) { + item->setOn( item->bits() >= 56 && item->bits() <= 128 ); + } + + for ( item = static_cast<CipherItem *>(SSLv3Box->firstChild()); item; + item = static_cast<CipherItem *>(item->nextSibling()) ) { + item->setOn( item->bits() >= 56 && item->bits() <= 128 ); + } + + mUseTLS->setChecked(true); + mUseSSLv2->setChecked(true); + mUseSSLv3->setChecked(true); + configChanged(); + #endif +} + + +void KCryptoConfig::cwUS() { + #ifdef HAVE_SSL + CipherItem *item; + for ( item = static_cast<CipherItem *>(SSLv2Box->firstChild()); item; + item = static_cast<CipherItem *>(item->nextSibling()) ) { + item->setOn( item->bits() >= 128 ); + } + + for ( item = static_cast<CipherItem *>(SSLv3Box->firstChild()); item; + item = static_cast<CipherItem *>(item->nextSibling()) ) { + item->setOn( item->bits() >= 128 ); + } + + configChanged(); + #endif +} + + +void KCryptoConfig::cwExp() { + #ifdef HAVE_SSL + CipherItem *item; + for ( item = static_cast<CipherItem *>(SSLv2Box->firstChild()); item; + item = static_cast<CipherItem *>(item->nextSibling()) ) { + item->setOn( item->bits() <= 56 && item->bits() > 0); + } + + for ( item = static_cast<CipherItem *>(SSLv3Box->firstChild()); item; + item = static_cast<CipherItem *>(item->nextSibling()) ) { + item->setOn( item->bits() <= 56 && item->bits() > 0); + } + + configChanged(); + #endif +} + + +void KCryptoConfig::cwAll() { + #ifdef HAVE_SSL + CipherItem *item; + for ( item = static_cast<CipherItem *>(SSLv2Box->firstChild()); item; + item = static_cast<CipherItem *>(item->nextSibling()) ) { + item->setOn( true ); + } + + for ( item = static_cast<CipherItem *>(SSLv3Box->firstChild()); item; + item = static_cast<CipherItem *>(item->nextSibling()) ) { + item->setOn( true ); + } + + mUseTLS->setChecked(true); + mUseSSLv2->setChecked(true); + mUseSSLv3->setChecked(true); + configChanged(); + #endif +} + + + +void KCryptoConfig::slotExportCert() { +OtherCertItem *x = static_cast<OtherCertItem *>(otherSSLBox->selectedItem()); + if (x) { + policies->setGroup(x->getMD5()); + KSSLCertificate *cert = KSSLCertificate::fromString(policies->readEntry("Certificate", QString::null).local8Bit()); + if (cert) { + KCertExport kce; + kce.setCertificate(cert); + kce.exec(); + delete cert; + } else KMessageBox::sorry(this, i18n("Could not open the certificate."), + i18n("SSL")); + } +} + + + +void KCryptoConfig::slotRemoveCert() { +QListViewItem *act = otherSSLBox->selectedItem(); +OtherCertItem *x = static_cast<OtherCertItem *>(act); + if (x) { + QListViewItem *next = act->itemBelow(); + if (!next) next = act->itemAbove(); + otherSSLBox->takeItem(x); + otherCertDelList.append(x); + configChanged(); + if (next) otherSSLBox->setSelected(next, true); + } +} + + + +void KCryptoConfig::slotVerifyCert() { +OtherCertItem *x = static_cast<OtherCertItem *>(otherSSLBox->selectedItem()); + if (!x) return; + + policies->setGroup(x->getMD5()); + KSSLCertificate *cert = KSSLCertificate::fromString(policies->readEntry("Certificate", QString::null).local8Bit()); + + if (!cert) { + KMessageBox::error(this, i18n("Error obtaining the certificate."), i18n("SSL")); + return; + } + + cert->chain().setCertChain(policies->readListEntry("Chain")); + + KSSLCertificate::KSSLValidation v = cert->revalidate(KSSLCertificate::SSLServer); + + /* + * Don't enable this until we keep this info in the cache + if (v != KSSLCerticiate::Ok) + v = cert->revalidate(KSSLCertificate::SMIMESign); + if (v != KSSLCerticiate::Ok) + v = cert->revalidate(KSSLCertificate::SMIMEEncrypt); + */ + + if (v == KSSLCertificate::Ok) { + KMessageBox::information(this, i18n("This certificate passed the verification tests successfully."), i18n("SSL")); + } else { + KMessageBox::detailedError(this, i18n("This certificate has failed the tests and should be considered invalid."), KSSLCertificate::verifyText(v), i18n("SSL")); + } + + delete cert; +} + + + +void KCryptoConfig::slotUntil() { +OtherCertItem *x = static_cast<OtherCertItem *>(otherSSLBox->selectedItem()); + + cachePerm->setChecked(false); + untilDate->setEnabled(true); + + if (!x) return; + x->setPermanent(false); + + configChanged(); +} + + + +void KCryptoConfig::slotPermanent() { +OtherCertItem *x = static_cast<OtherCertItem *>(otherSSLBox->selectedItem()); + + cacheUntil->setChecked(false); + untilDate->setEnabled(false); + + if (!x) return; + x->setPermanent(true); + + configChanged(); +} + + + +void KCryptoConfig::slotPolicyChanged(int id) { +OtherCertItem *x = static_cast<OtherCertItem *>(otherSSLBox->selectedItem()); +if (!x) return; + + if (id == policyGroup->id(policyAccept)) { + x->setPolicy(KSSLCertificateCache::Accept); + } else if (id == policyGroup->id(policyReject)) { + x->setPolicy(KSSLCertificateCache::Reject); + } else if (id == policyGroup->id(policyPrompt)) { + x->setPolicy(KSSLCertificateCache::Prompt); + } + + configChanged(); +} + + + +void KCryptoConfig::slotDatePick() { +KDateTimeDlg kdtd; +OtherCertItem *x = static_cast<OtherCertItem *>(otherSSLBox->selectedItem()); + + if (!x || !untilDate->isEnabled()) return; + +QDateTime qdt = x->getExpires(); + + kdtd.setDateTime(qdt); + int rc = kdtd.exec(); + if (rc == KDialog::Accepted) { + x->setExpires(kdtd.getDateTime()); + untilDate->setText(KGlobal::locale()->formatDateTime(x->getExpires())); + configChanged(); + } +} + + + +void KCryptoConfig::slotOtherCertSelect() { +OtherCertItem *x = static_cast<OtherCertItem *>(otherSSLBox->selectedItem()); +QString iss = QString::null; + if (x) { + otherSSLExport->setEnabled(true); + otherSSLVerify->setEnabled(true); + otherSSLRemove->setEnabled(true); + + fromLabel->setEnabled(true); + untilLabel->setEnabled(true); + policyGroup->setEnabled(true); + cacheGroup->setEnabled(true); + cachePerm->setEnabled(true); + cacheUntil->setEnabled(true); + policies->setGroup(x->getMD5()); + + KSSLCertificate *cert = KSSLCertificate::fromString(policies->readEntry("Certificate", QString::null).local8Bit()); + + if (cert) { + QPalette cspl; + iss = cert->getIssuer(); + cspl = validFrom->palette(); + if (QDateTime::currentDateTime(Qt::UTC) < cert->getQDTNotBefore()) { + cspl.setColor(QColorGroup::Foreground, QColor(196,33,21)); + } else { + cspl.setColor(QColorGroup::Foreground, QColor(42,153,59)); + } + validFrom->setPalette(cspl); + + cspl = validUntil->palette(); + if (QDateTime::currentDateTime(Qt::UTC) > cert->getQDTNotAfter()) { + cspl.setColor(QColorGroup::Foreground, QColor(196,33,21)); + } else { + cspl.setColor(QColorGroup::Foreground, QColor(42,153,59)); + } + validUntil->setPalette(cspl); + + validFrom->setText(cert->getNotBefore()); + validUntil->setText(cert->getNotAfter()); + untilDate->setText(x ? KGlobal::locale()->formatDateTime(x->getExpires()) + : KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(Qt::UTC))); + untilDate->setEnabled(x && !x->isPermanent()); + pHash->setText(cert->getMD5DigestText()); + delete cert; + } else { + validFrom->setText(QString::null); + validUntil->setText(QString::null); + pHash->clear(); + } + + switch(x->getPolicy()) { + case KSSLCertificateCache::Accept: + policyGroup->setButton(policyGroup->id(policyAccept)); + break; + case KSSLCertificateCache::Reject: + policyGroup->setButton(policyGroup->id(policyReject)); + break; + case KSSLCertificateCache::Prompt: + policyGroup->setButton(policyGroup->id(policyPrompt)); + break; + } + + cachePerm->setChecked(x->isPermanent()); + cacheUntil->setChecked(!x->isPermanent()); + + } else { + otherSSLExport->setEnabled(false); + otherSSLVerify->setEnabled(false); + otherSSLRemove->setEnabled(false); + fromLabel->setEnabled(false); + untilLabel->setEnabled(false); + policyGroup->setEnabled(false); + cacheGroup->setEnabled(false); + cachePerm->setChecked(false); + cacheUntil->setChecked(false); + policyAccept->setChecked(false); + policyReject->setChecked(false); + policyPrompt->setChecked(false); + cachePerm->setEnabled(false); + cacheUntil->setEnabled(false); + validFrom->setText(QString::null); + validUntil->setText(QString::null); + untilDate->setText(QString::null); + untilDate->setEnabled(false); + pHash->clear(); + } + + + oSubject->setValues(x ? x->getSub() : QString(QString::null)); + oIssuer->setValues(iss); + +} + + +void KCryptoConfig::slotYourImport() { + + QString certFile = KFileDialog::getOpenFileName(QString::null, "application/x-pkcs12"); + if (certFile.isEmpty()) + return; + +#ifdef HAVE_SSL +KSSLPKCS12 *cert = NULL; +QCString pass; + +TryImportPassAgain: + int rc = KPasswordDialog::getPassword(pass, i18n("Certificate password")); + if (rc != KPasswordDialog::Accepted) return; + + cert = KSSLPKCS12::loadCertFile(certFile, QString(pass)); + + if (!cert) { + rc = KMessageBox::warningYesNo(this, i18n("The certificate file could not be loaded. Try a different password?"), i18n("SSL"),i18n("Try"),i18n("Do Not Try")); + if (rc == KMessageBox::Yes) goto TryImportPassAgain; + return; + } + + // At this point, we know that we can read the certificate in. + // The procedure will be to convert it to Base64 in it's raw form + // and add it to the ListView - eventually going into the SimpleConfig. + + // FIXME: prompt if the user wants the password stored along with the + // certificate + + QString name = cert->getCertificate()->getSubject(); + for (YourCertItem *i = + static_cast<YourCertItem *>(yourSSLBox->firstChild()); + i; + i = static_cast<YourCertItem *>(i->nextSibling())) { + if (i->configName() == name) { + rc = KMessageBox::warningContinueCancel(this, i18n("A certificate with that name already exists. Are you sure that you wish to replace it?"), i18n("SSL"), i18n("Replace")); + if (rc == KMessageBox::Cancel) { + delete cert; + return; + } + yourSSLBox->takeItem(i); + yourCertDelList.append(i); + } + } + + new YourCertItem(yourSSLBox, + cert->toString(), + QString::null, // the password - don't store it yet! + name, + this ); + + setAuthCertLists(); + configChanged(); + delete cert; +#endif + + offerImportToKMail( certFile ); +} + + +void KCryptoConfig::slotYourExport() { +YourCertItem *x = static_cast<YourCertItem *>(yourSSLBox->selectedItem()); + if (!x) return; + + KSSLPKCS12 *pkcs = KSSLPKCS12::fromString(x->getPKCS(), x->getPass()); + if (!pkcs) + pkcs = KSSLPKCS12::fromString(x->getPKCS(), x->getPassCache()); + if (!pkcs) { + QString pprompt = i18n("Enter the certificate password:"); + QCString oldpass; + do { + int i = KPasswordDialog::getPassword(oldpass, pprompt); + if (i != KPasswordDialog::Accepted) return; + pkcs = KSSLPKCS12::fromString(x->getPKCS(), oldpass); + pprompt = i18n("Decoding failed. Please try again:"); + } while (!pkcs); + x->setPassCache(oldpass); + slotYourUnlock(); + } + + // For now, we will only export to PKCS#12 + QString certFile = KFileDialog::getSaveFileName(QString::null, + "application/x-pkcs12"); + if (certFile.isEmpty()) + return; + + if (!pkcs->toFile(certFile)) + KMessageBox::sorry(this, i18n("Export failed."), i18n("SSL")); +} + + +void KCryptoConfig::slotYourVerify() { +YourCertItem *x = static_cast<YourCertItem *>(yourSSLBox->selectedItem()); +QString iss; + if (!x) return; + + KSSLPKCS12 *pkcs = KSSLPKCS12::fromString(x->getPKCS(), x->getPass()); + if (!pkcs) + pkcs = KSSLPKCS12::fromString(x->getPKCS(), x->getPassCache()); + if (!pkcs) { + QString pprompt = i18n("Enter the certificate password:"); + QCString oldpass; + do { + int i = KPasswordDialog::getPassword(oldpass, pprompt); + if (i != KPasswordDialog::Accepted) return; + pkcs = KSSLPKCS12::fromString(x->getPKCS(), oldpass); + pprompt = i18n("Decoding failed. Please try again:"); + } while (!pkcs); + x->setPassCache(oldpass); + slotYourUnlock(); + } + + KSSLCertificate::KSSLValidation v = pkcs->revalidate(KSSLCertificate::SSLClient); + if (v != KSSLCertificate::Ok) + v = pkcs->revalidate(KSSLCertificate::SMIMEEncrypt); + if (v != KSSLCertificate::Ok) + v = pkcs->revalidate(KSSLCertificate::SMIMESign); + + if (v == KSSLCertificate::Ok) { + KMessageBox::information(this, i18n("This certificate passed the verification tests successfully."), i18n("SSL")); + } else { + KMessageBox::detailedError(this, i18n("This certificate has failed the tests and should be considered invalid."), KSSLCertificate::verifyText(v), i18n("SSL")); + } + + delete pkcs; +} + + +void KCryptoConfig::slotYourRemove() { +YourCertItem *x = static_cast<YourCertItem *>(yourSSLBox->selectedItem()); + if (x) { + yourSSLBox->takeItem(x); + yourCertDelList.append(x); + setAuthCertLists(); + configChanged(); + } +} + + +void KCryptoConfig::slotYourUnlock() { +YourCertItem *x = static_cast<YourCertItem *>(yourSSLBox->selectedItem()); +QString iss; + if (!x || !yourSSLUnlock->isEnabled()) return; + + KSSLPKCS12 *pkcs = KSSLPKCS12::fromString(x->getPKCS(), x->getPass()); + if (!pkcs) + pkcs = KSSLPKCS12::fromString(x->getPKCS(), x->getPassCache()); + if (!pkcs) { + QString pprompt = i18n("Enter the certificate password:"); + QCString oldpass; + do { + int i = KPasswordDialog::getPassword(oldpass, pprompt); + if (i != KPasswordDialog::Accepted) return; + pkcs = KSSLPKCS12::fromString(x->getPKCS(), oldpass); + pprompt = i18n("Decoding failed. Please try again:"); + } while (!pkcs); + x->setPassCache(oldpass); + } + + // update the info + iss = pkcs->getCertificate()->getIssuer(); + ySubject->setValues(x ? x->getName() : QString(QString::null)); + yIssuer->setValues(iss); + QPalette cspl; + KSSLCertificate *cert = pkcs->getCertificate(); + cspl = yValidFrom->palette(); + if (QDateTime::currentDateTime(Qt::UTC) < cert->getQDTNotBefore()) { + cspl.setColor(QColorGroup::Foreground, QColor(196,33,21)); + } else { + cspl.setColor(QColorGroup::Foreground, QColor(42,153,59)); + } + yValidFrom->setPalette(cspl); + + cspl = yValidUntil->palette(); + if (QDateTime::currentDateTime(Qt::UTC) > cert->getQDTNotAfter()) { + cspl.setColor(QColorGroup::Foreground, QColor(196,33,21)); + } else { + cspl.setColor(QColorGroup::Foreground, QColor(42,153,59)); + } + yValidUntil->setPalette(cspl); + + yValidFrom->setText(cert->getNotBefore()); + yValidUntil->setText(cert->getNotAfter()); + yHash->setText(cert->getMD5DigestText()); + yourSSLUnlock->setEnabled(false); + delete pkcs; +} + + +void KCryptoConfig::slotYourCertSelect() { +YourCertItem *x = static_cast<YourCertItem *>(yourSSLBox->selectedItem()); +QString iss; + + yourSSLExport->setEnabled(x != NULL); + yourSSLPass->setEnabled(x != NULL); + yourSSLUnlock->setEnabled(false); + yourSSLVerify->setEnabled(x != NULL); + yourSSLRemove->setEnabled(x != NULL); + + if (x) { + KSSLPKCS12 *pkcs = KSSLPKCS12::fromString(x->getPKCS(), x->getPass()); + if (pkcs) { + QPalette cspl; + KSSLCertificate *cert = pkcs->getCertificate(); + iss = cert->getIssuer(); + cspl = yValidFrom->palette(); + if (QDateTime::currentDateTime(Qt::UTC) < cert->getQDTNotBefore()) { + cspl.setColor(QColorGroup::Foreground, QColor(196,33,21)); + } else { + cspl.setColor(QColorGroup::Foreground, QColor(42,153,59)); + } + yValidFrom->setPalette(cspl); + + cspl = yValidUntil->palette(); + if (QDateTime::currentDateTime(Qt::UTC) > cert->getQDTNotAfter()) { + cspl.setColor(QColorGroup::Foreground, QColor(196,33,21)); + } else { + cspl.setColor(QColorGroup::Foreground, QColor(42,153,59)); + } + yValidUntil->setPalette(cspl); + + yValidFrom->setText(cert->getNotBefore()); + yValidUntil->setText(cert->getNotAfter()); + yHash->setText(cert->getMD5DigestText()); + delete pkcs; + } else { + yourSSLUnlock->setEnabled(x != NULL); + yHash->clear(); + } + } else { + yHash->clear(); + } + + ySubject->setValues(x ? x->getName() : QString(QString::null)); + yIssuer->setValues(iss); +} + + +void KCryptoConfig::slotYourPass() { +YourCertItem *x = static_cast<YourCertItem *>(yourSSLBox->selectedItem()); +QCString oldpass = ""; + if (!x) return; + + KSSLPKCS12 *pkcs = KSSLPKCS12::fromString(x->getPKCS(), x->getPass()); + if (!pkcs) + pkcs = KSSLPKCS12::fromString(x->getPKCS(), x->getPassCache()); + if (!pkcs) { + QString pprompt = i18n("Enter the OLD password for the certificate:"); + do { + int i = KPasswordDialog::getPassword(oldpass, pprompt); + if (i != KPasswordDialog::Accepted) break; + pkcs = KSSLPKCS12::fromString(x->getPKCS(), oldpass); + pprompt = i18n("Decoding failed. Please try again:"); + } while (!pkcs); + } + + if (pkcs) { + x->setPassCache(oldpass); + slotYourUnlock(); + KPasswordDialog *kpd = new KPasswordDialog(KPasswordDialog::NewPassword, false, 0, this); + kpd->setPrompt(i18n("Enter the new certificate password")); + kpd->setAllowEmptyPasswords(true); + + int i = kpd->exec(); + if (i == KPasswordDialog::Accepted) { + QCString pass = kpd->password(); + pkcs->changePassword(QString(oldpass), QString(pass)); + x->setPKCS(pkcs->toString()); + x->setPassCache(pass); + configChanged(); + } + delete kpd; + delete pkcs; + } +} + + +void KCryptoConfig::slotCAImport() { + QString certFile = KFileDialog::getOpenFileName(QString::null, "application/x-x509-ca-cert"); + + if (certFile.isEmpty()) + return; + +#ifdef HAVE_SSL +#define sk_free KOSSL::self()->sk_free +#define sk_num KOSSL::self()->sk_num +#define sk_value KOSSL::self()->sk_value + + // First try to load using the OpenSSL method + X509_STORE *certStore = KOSSL::self()->X509_STORE_new(); + X509_LOOKUP *certLookup = KOSSL::self()->X509_STORE_add_lookup(certStore, KOSSL::self()->X509_LOOKUP_file()); + + if (certLookup && + KOSSL::self()->X509_LOOKUP_load_file(certLookup, + certFile.local8Bit(), + X509_FILETYPE_PEM)) { + for (int i = 0; i < sk_X509_OBJECT_num(certStore->objs); i++) { + X509_OBJECT* x5o = sk_X509_OBJECT_value(certStore->objs, i); + if (!x5o) continue; + + if (x5o->type != X509_LU_X509) continue; + + X509 *x5 = x5o->data.x509; + if (!x5) continue; + + // Easier to use in this form + KSSLCertificate *x = KSSLCertificate::fromX509(x5); + + // Only import CA's + if (!x || !x->x509V3Extensions().certTypeCA()) { + if (x) { + QString emsg = x->getSubject() + ":\n" + + i18n("This is not a signer certificate."); + KMessageBox::error(this, + emsg, + i18n("SSL")); + delete x; + } + continue; + } + + QString name = x->getSubject(); + + // search for dups + for (CAItem *m = static_cast<CAItem *>(caList->firstChild()); + m; + m = static_cast<CAItem *>(m->nextSibling())) { + if (m->configName() == name) { + KSSLCertificate *y = KSSLCertificate::fromString(m->getCert().local8Bit()); + if (!y) continue; + if (*x == *y) { + QString emsg = name + ":\n" + + i18n("You already have this signer certificate installed."); + KMessageBox::error(this, + emsg, + i18n("SSL")); + delete x; + delete y; + x = NULL; + break; + } + delete y; + } + } + + if (!x) continue; + + // Ok, add it to the list + (new CAItem(caList, + name, + x->toString(), + true, true, true, this) + )->isNew = true; + delete x; + } + + // Can the PEM code be wiped out now? + } else { // try to load it manually as a single X.509 DER encoded + // ASSUMPTION: we only read one certificate in this code + QFile qf(certFile); + QString name; + QString certtext; + KSSLCertificate *x; + qf.open(IO_ReadOnly); + qf.readLine(certtext, qf.size()); + + if (certStore) { KOSSL::self()->X509_STORE_free(certStore); + certStore = NULL; } + + if (certtext.contains("-----BEGIN CERTIFICATE-----")) { + qf.reset(); + certtext = QString::null; + while (!qf.atEnd()) { + QString xx; + qf.readLine(xx, qf.size()); + certtext += xx; + } + certtext = certtext.replace("-----BEGIN CERTIFICATE-----", QString::null); + certtext = certtext.replace("-----END CERTIFICATE-----", QString::null); + certtext = certtext.stripWhiteSpace(); + certtext = certtext.replace("\n", QString::null); + } else { + // Must [could?] be DER + qf.close(); + qf.open(IO_ReadOnly); + char *cr; + cr = new char[qf.size()+1]; + qf.readBlock(cr, qf.size()); + QByteArray qba; + qba.duplicate(cr, qf.size()); + certtext = KCodecs::base64Encode(qba); + delete [] cr; + } + + qf.close(); + + x = KSSLCertificate::fromString(certtext.latin1()); + + if (!x) { + KMessageBox::sorry(this, + i18n("The certificate file could not be loaded."), + i18n("SSL")); + return; + } + + if (!x->x509V3Extensions().certTypeCA()) { + KMessageBox::sorry(this, + i18n("This is not a signer certificate."), + i18n("SSL")); + return; + } + + name = x->getSubject(); + + for (CAItem *i = static_cast<CAItem *>(caList->firstChild()); + i; + i = static_cast<CAItem *>(i->nextSibling())) { + if (i->configName() == name) { + KSSLCertificate *y = KSSLCertificate::fromString(i->getCert().local8Bit()); + if (!y) continue; + if (*x == *y) { + KMessageBox::error(this, + i18n("You already have this signer certificate installed."), + i18n("SSL")); + delete x; + delete y; + return; + } + delete y; + } + } + + (new CAItem(caList, name, x->toString(), true, true, true, this))->isNew = true; + + delete x; + } + + + if (certStore) KOSSL::self()->X509_STORE_free(certStore); + + configChanged(); +#undef sk_free +#undef sk_num +#undef sk_value +#endif + + offerImportToKMail( certFile ); +} + +void KCryptoConfig::offerImportToKMail( const QString& certFile ) +{ + if ( KMessageBox::questionYesNo( this, i18n( "Do you want to make this certificate available to KMail as well?" ), QString::null, i18n("Make Available"), i18n("Do Not Make Available") ) == KMessageBox::Yes ) { + KProcess proc; + proc << "kleopatra"; + proc << "--import-certificate"; + proc << certFile; + if ( !proc.start( KProcess::DontCare ) ) + KMessageBox::error( this, i18n( "Could not execute Kleopatra. You might have to install or update the kdepim package." ) ); + } +} + + +void KCryptoConfig::slotCARemove() { +CAItem *x = static_cast<CAItem *>(caList->selectedItem()); + if (x) { + caList->takeItem(x); + caDelList.append(x); + configChanged(); + slotCAItemChanged(); + } +} + + +void KCryptoConfig::slotCARestore() { + + int rc = KMessageBox::warningContinueCancel(this, i18n("This will revert your certificate signers database to the KDE default.\nThis operation cannot be undone.\nAre you sure you wish to continue?"), i18n("SSL"),i18n("Revert")); + if (rc == KMessageBox::Cancel) { + return; + } + +// For now, we just rm the existing file and rebuild + + QString path = KGlobal::dirs()->saveLocation("config"); + + path += "/ksslcalist"; + + QFile::remove(path); + + // Remove all our old work and rebuild the GUI/List + caDelList.clear(); + caList->clear(); + + + QStringList groups = _signers->list(); + KConfig sigcfg("ksslcalist", true, false); + + for (QStringList::Iterator i = groups.begin(); + i != groups.end(); + ++i) { + if ((*i).isEmpty() || *i == "<default>") continue; + if (!sigcfg.hasGroup(*i)) continue; + sigcfg.setGroup(*i); + if (!sigcfg.hasKey("x509")) continue; + new CAItem(caList, + (*i), + sigcfg.readEntry("x509", QString::null), + sigcfg.readBoolEntry("site", false), + sigcfg.readBoolEntry("email", false), + sigcfg.readBoolEntry("code", false), + this ); + } + + genCAList(); + slotCAItemChanged(); +} + + +void KCryptoConfig::slotCAItemChanged() { +CAItem *x = static_cast<CAItem *>(caList->selectedItem()); + if (x) { + caSSLRemove->setEnabled(true); + caSubject->setValues(x ? x->getName() : QString(QString::null)); + KSSLCertificate *cert = KSSLCertificate::fromString(x->getCert().local8Bit()); + if (!cert) { + caIssuer->setValues(QString(QString::null)); + caSite->setEnabled(false); + caEmail->setEnabled(false); + caCode->setEnabled(false); + caSite->setChecked(false); + caEmail->setChecked(false); + caCode->setChecked(false); + cHash->clear(); + } else { + caSite->setEnabled(cert->x509V3Extensions().certTypeSSLCA()); + caEmail->setEnabled(cert->x509V3Extensions().certTypeEmailCA()); + caCode->setEnabled(cert->x509V3Extensions().certTypeCodeCA()); + caSite->setChecked(x->getSite()); + caEmail->setChecked(x->getEmail()); + caCode->setChecked(x->getCode()); + caIssuer->setValues(cert->getIssuer()); + cHash->setText(cert->getMD5DigestText()); + delete cert; + } + } else { + caSSLRemove->setEnabled(false); + caSite->setEnabled(false); + caEmail->setEnabled(false); + caCode->setEnabled(false); + caSubject->setValues(QString(QString::null)); + caIssuer->setValues(QString(QString::null)); + cHash->clear(); + } +} + + +void KCryptoConfig::slotCAChecked() { +CAItem *x = static_cast<CAItem *>(caList->selectedItem()); + if (x) { + x->setSite(caSite->isChecked()); + x->setEmail(caEmail->isChecked()); + x->setCode(caCode->isChecked()); + x->modified = true; + configChanged(); + } +} + + + +void KCryptoConfig::slotNewHostAuth() { + HostAuthItem *j = new HostAuthItem(hostAuthList, + QString::null, + QString::null, + this ); + j->setAction(KSSLCertificateHome::AuthSend); + hostAuthList->setSelected(j, true); + authHost->setEnabled(true); + hostCertBox->setEnabled(true); + hostCertBG->setEnabled(true); + authRemove->setEnabled(true); + + hostCertBG->setButton(0); + + authHost->setFocus(); +} + + + +void KCryptoConfig::slotRemoveHostAuth() { +QListViewItem *act = hostAuthList->selectedItem(); +HostAuthItem *x = static_cast<HostAuthItem *>(act); + + if (x) { + QListViewItem *next = act->itemBelow(); + if (!next) next = act->itemAbove(); + hostAuthList->takeItem(x); + authDelList.append(x); + configChanged(); + if (next) hostAuthList->setSelected(next, true); + } +} + + +void KCryptoConfig::slotAuthItemChanged() { +HostAuthItem *x = static_cast<HostAuthItem *>(hostAuthList->selectedItem()); + +if (x) { + // Make sure the fields are enabled + authHost->setEnabled(true); + hostCertBox->setEnabled(true); + hostCertBG->setEnabled(true); + authRemove->setEnabled(true); + + // Populate the fields + switch(x->getAction()) { + case KSSLCertificateHome::AuthSend: + hostCertBG->setButton(hostCertBG->id(hostSend)); + break; + case KSSLCertificateHome::AuthPrompt: + hostCertBG->setButton(hostCertBG->id(hostPrompt)); + break; + case KSSLCertificateHome::AuthDont: + hostCertBG->setButton(hostCertBG->id(hostDont)); + break; + default: + hostSend->setChecked(false); + hostPrompt->setChecked(false); + hostDont->setChecked(false); + break; + } + + ___lehack = true; + authHost->setText(x->configName()); + ___lehack = false; + hostCertBox->setCurrentItem(0); + + QString theCert = x->getCertName(); + for (int i = 0; i < hostCertBox->count(); i++) { + if (hostCertBox->text(i) == theCert) { + hostCertBox->setCurrentItem(i); + break; + } + } +} else { + authHost->clear(); + authHost->setEnabled(false); + hostCertBox->setEnabled(false); + hostCertBG->setEnabled(false); + authRemove->setEnabled(false); +} +} + + +void KCryptoConfig::slotAuthText(const QString &t) { +if (___lehack) return; +HostAuthItem *x = static_cast<HostAuthItem *>(hostAuthList->selectedItem()); + +if (x) { + x->setHost(t); +configChanged(); +} +} + + + +void KCryptoConfig::slotAuthButtons() { +HostAuthItem *x = static_cast<HostAuthItem *>(hostAuthList->selectedItem()); + +if (x) { + KSSLCertificateHome::KSSLAuthAction aa = KSSLCertificateHome::AuthDont; + int sel = hostCertBG->id(hostCertBG->selected()); + + if (sel == hostCertBG->id(hostSend)) + aa = KSSLCertificateHome::AuthSend; + else if (sel == hostCertBG->id(hostPrompt)) + aa = KSSLCertificateHome::AuthPrompt; + else + aa = KSSLCertificateHome::AuthDont; + + x->setAction(aa); +configChanged(); +} +} + + +void KCryptoConfig::slotAuthCombo() { +HostAuthItem *x = static_cast<HostAuthItem *>(hostAuthList->selectedItem()); + + if (x) { + if (hostCertBox->currentItem() == 0) + x->setCertName(QString::null); + else x->setCertName(hostCertBox->currentText()); + configChanged(); + } +} + + +void KCryptoConfig::slotTestOSSL() { +KOSSL::self()->destroy(); + +if (!KOSSL::self()->hasLibSSL()) { + KMessageBox::detailedSorry(this, + i18n("Failed to load OpenSSL."), + i18n("libssl was not found or successfully loaded."), + i18n("OpenSSL")); + return; +} + +if (!KOSSL::self()->hasLibCrypto()) { + KMessageBox::detailedSorry(this, + i18n("Failed to load OpenSSL."), + i18n("libcrypto was not found or successfully loaded."), + i18n("OpenSSL")); + return; +} + + KMessageBox::information(this, i18n("OpenSSL was successfully loaded."), i18n("OpenSSL")); +} + + +void KCryptoConfig::slotUseEGD() { + if (mUseEGD->isChecked()) { + mUseEFile->setChecked(false); + } + mEGDLabel->setText(i18n("Path to EGD:")); + mEGDPath->setEnabled(mUseEGD->isChecked()); + mEGDLabel->setEnabled(mUseEGD->isChecked()); + configChanged(); +} + + +void KCryptoConfig::slotUseEFile() { + if (mUseEFile->isChecked()) { + mUseEGD->setChecked(false); + } + mEGDLabel->setText(i18n("Path to entropy file:")); + mEGDPath->setEnabled(mUseEFile->isChecked()); + mEGDLabel->setEnabled(mUseEFile->isChecked()); + configChanged(); +} + + +// Lets make this a separate module. it's a whole lot of work and can really be +// encompassed in a separate module quite nicely. +void KCryptoConfig::slotGeneratePersonal() { +#if 0 + QStringList qslCertTypes; + + qslCertTypes << i18n("Personal SSL") + << i18n("Server SSL") + << i18n("S/MIME") + << i18n("PGP") + << i18n("GPG") + << i18n("SSL Personal Request") + << i18n("SSL Server Request") + << i18n("Netscape SSL") + << i18n("Server certificate authority", "Server CA") + << i18n("Personal certificate authority", "Personal CA") + << i18n("Secure MIME certificate authority", "S/MIME CA"); +#endif + +} + + +#ifdef HAVE_SSL +// This gets all the available ciphers from OpenSSL +bool KCryptoConfig::loadCiphers() { +unsigned int i; +SSL_CTX *ctx; +SSL *ssl; +SSL_METHOD *meth; + + SSLv2Box->clear(); + SSLv3Box->clear(); + + meth = SSLv2_client_method(); + SSLeay_add_ssl_algorithms(); + ctx = SSL_CTX_new(meth); + if (ctx == NULL) return false; + + ssl = SSL_new(ctx); + if (!ssl) return false; + + CipherItem *item; + for (i=0; ; i++) { + int j, k; + SSL_CIPHER *sc; + sc = (meth->get_cipher)(i); + if (!sc) + break; + // Leak of sc*? + QString scn(sc->name); + if (scn.contains("ADH-") || scn.contains("NULL-") || scn.contains("DES-CBC3-SHA") || scn.contains("FZA-")) { + continue; + } + k = SSL_CIPHER_get_bits(sc, &j); + + item = new CipherItem( SSLv2Box, sc->name, k, j, this ); + } + + if (ctx) SSL_CTX_free(ctx); + if (ssl) SSL_free(ssl); + + // We repeat for SSLv3 + meth = SSLv3_client_method(); + SSLeay_add_ssl_algorithms(); + ctx = SSL_CTX_new(meth); + if (ctx == NULL) return false; + + ssl = SSL_new(ctx); + if (!ssl) return false; + + for (i=0; ; i++) { + int j, k; + SSL_CIPHER *sc; + sc = (meth->get_cipher)(i); + if (!sc) + break; + // Leak of sc*? + QString scn(sc->name); + if (scn.contains("ADH-") || scn.contains("NULL-") || scn.contains("DES-CBC3-SHA") || scn.contains("FZA-")) { + continue; + } + k = SSL_CIPHER_get_bits(sc, &j); + + item = new CipherItem( SSLv3Box, sc->name, k, j, this ); + } + + if (ctx) SSL_CTX_free(ctx); + if (ssl) SSL_free(ssl); + +return true; +} +#endif + + +void KCryptoConfig::setAuthCertLists() { +QString oldDef, oldHost; +bool noneDef, noneHost; + +// get the old setting + oldDef = defCertBox->currentText(); + oldHost = hostCertBox->currentText(); + noneDef = (0 == defCertBox->currentItem()); + noneHost = (0 == hostCertBox->currentItem()); + +// repopulate + defCertBox->clear(); + hostCertBox->clear(); + QStringList defCertStrList; // = KSSLCertificateHome::getCertificateList(); + defCertStrList.append(i18n("None")); + for (YourCertItem *x = static_cast<YourCertItem *>(yourSSLBox->firstChild()); + x; + x = static_cast<YourCertItem *>(x->nextSibling())) { + defCertStrList.append(x->configName()); + } + defCertBox->insertStringList(defCertStrList); + hostCertBox->insertStringList(defCertStrList); + +// try to restore it + + defCertBox->setCurrentItem(0); + if (!noneDef) { + for (int i = 0; i < defCertBox->count(); i++) { + if (defCertBox->text(i) == oldDef) { + defCertBox->setCurrentItem(i); + break; + } + } + } + + if (!noneDef && defCertBox->currentItem() == 0) configChanged(); + + hostCertBox->setCurrentItem(0); + if (!noneHost) { + for (int i = 0; i < hostCertBox->count(); i++) { + if (hostCertBox->text(i) == oldHost) { + hostCertBox->setCurrentItem(i); + break; + } + } + } + + if (!noneHost && hostCertBox->currentItem() == 0) configChanged(); + + // Update the host entries too + for (HostAuthItem *x = + static_cast<HostAuthItem *>(hostAuthList->firstChild()); + x; + x = static_cast<HostAuthItem *>(x->nextSibling())) { + QString newValue = QString::null; + for (int i = 1; i < hostCertBox->count(); i++) { + if (hostCertBox->text(i) == x->getCertName()) { + newValue = x->getCertName(); + break; + } + } + if (newValue != x->getCertName()) configChanged(); + x->setCertName(newValue); + } + + +} + +#include "crypto.moc" |