KIO
sslui.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 * 00003 * Copyright (C) 2009 Andreas Hartmetz <ahartmetz@gmail.com> 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., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "sslui.h" 00022 00023 #include <kdebug.h> 00024 #include <klocalizedstring.h> 00025 #include <kmessagebox.h> 00026 #include <ksslcertificatemanager.h> 00027 #include <ksslinfodialog.h> 00028 #include <ktcpsocket_p.h> 00029 00030 00031 bool KIO::SslUi::askIgnoreSslErrors(const KTcpSocket *socket, RulesStorage storedRules) 00032 { 00033 KSslErrorUiData uiData(socket); 00034 return askIgnoreSslErrors(uiData, storedRules); 00035 } 00036 00037 00038 bool KIO::SslUi::askIgnoreSslErrors(const KSslErrorUiData &uiData, RulesStorage storedRules) 00039 { 00040 const KSslErrorUiData::Private *ud = KSslErrorUiData::Private::get(&uiData); 00041 if (ud->sslErrors.isEmpty()) { 00042 return true; 00043 } 00044 00045 QList<KSslError> fatalErrors = KSslCertificateManager::nonIgnorableErrors(ud->sslErrors); 00046 if (!fatalErrors.isEmpty()) { 00047 //TODO message "sorry, fatal error, you can't override it" 00048 return false; 00049 } 00050 if (ud->certificateChain.isEmpty()) { 00051 // SSL without certificates is quite useless and should never happen 00052 KMessageBox::sorry(0, i18n("The remote host did not send any SSL certificates.\n" 00053 "Aborting because the identity of the host cannot be established.")); 00054 return false; 00055 } 00056 00057 KSslCertificateManager *const cm = KSslCertificateManager::self(); 00058 KSslCertificateRule rule(ud->certificateChain.first(), ud->host); 00059 if (storedRules & RecallRules) { 00060 rule = cm->rule(ud->certificateChain.first(), ud->host); 00061 // remove previously seen and acknowledged errors 00062 QList<KSslError> remainingErrors = rule.filterErrors(ud->sslErrors); 00063 if (remainingErrors.isEmpty()) { 00064 kDebug(7029) << "Error list empty after removing errors to be ignored. Continuing."; 00065 return true; 00066 } 00067 } 00068 00069 //### We don't ask to permanently reject the certificate 00070 00071 QString message = i18n("The server failed the authenticity check (%1).\n\n", ud->host); 00072 foreach (const KSslError &err, ud->sslErrors) { 00073 message.append(err.errorString()); 00074 message.append('\n'); 00075 } 00076 message = message.trimmed(); 00077 00078 int msgResult; 00079 do { 00080 msgResult = KMessageBox::warningYesNoCancel(0, message, i18n("Server Authentication"), 00081 KGuiItem(i18n("&Details"), "help-about"), 00082 KGuiItem(i18n("Co&ntinue"), "arrow-right")); 00083 if (msgResult == KMessageBox::Yes) { 00084 //Details was chosen - show the certificate and error details 00085 00086 00087 QList<QList<KSslError::Error> > meh; // parallel list to cert list :/ 00088 00089 foreach (const QSslCertificate &cert, ud->certificateChain) { 00090 QList<KSslError::Error> errors; 00091 foreach(const KSslError &error, ud->sslErrors) { 00092 if (error.certificate() == cert) { 00093 // we keep only the error code enum here 00094 errors.append(error.error()); 00095 } 00096 } 00097 meh.append(errors); 00098 } 00099 00100 00101 KSslInfoDialog *dialog = new KSslInfoDialog(); 00102 dialog->setSslInfo(ud->certificateChain, ud->ip, ud->host, ud->sslProtocol, 00103 ud->cipher, ud->usedBits, ud->bits, meh); 00104 dialog->exec(); 00105 } else if (msgResult == KMessageBox::Cancel) { 00106 return false; 00107 } 00108 //fall through on KMessageBox::No 00109 } while (msgResult == KMessageBox::Yes); 00110 00111 00112 if (storedRules & StoreRules) { 00113 //Save the user's choice to ignore the SSL errors. 00114 00115 msgResult = KMessageBox::warningYesNo(0, 00116 i18n("Would you like to accept this " 00117 "certificate forever without " 00118 "being prompted?"), 00119 i18n("Server Authentication"), 00120 KGuiItem(i18n("&Forever"), "flag-green"), 00121 KGuiItem(i18n("&Current Session only"), "chronometer")); 00122 QDateTime ruleExpiry = QDateTime::currentDateTime(); 00123 if (msgResult == KMessageBox::Yes) { 00124 //accept forever ("for a very long time") 00125 ruleExpiry = ruleExpiry.addYears(1000); 00126 } else { 00127 //accept "for a short time", half an hour. 00128 ruleExpiry = ruleExpiry.addSecs(30*60); 00129 } 00130 00131 //TODO special cases for wildcard domain name in the certificate! 00132 //rule = KSslCertificateRule(d->socket.peerCertificateChain().first(), whatever); 00133 00134 rule.setExpiryDateTime(ruleExpiry); 00135 rule.setIgnoredErrors(ud->sslErrors); 00136 cm->setRule(rule); 00137 } 00138 00139 return true; 00140 } 00141
KDE 4.6 API Reference