knewstuffsecure.cpp
00001 /*************************************************************************** 00002 knewstuffsecure.cpp - description 00003 ------------------- 00004 begin : Tue Jun 22 12:19:55 2004 00005 copyright : (C) 2004, 2005 by Andras Mantia <amantia@kde.org> 00006 ***************************************************************************/ 00007 00008 /*************************************************************************** 00009 * * 00010 * This program is free software; you can redistribute it and/or modify * 00011 * it under the terms of the GNU Library General Public License as * 00012 * published by the Free Software Foundation; version 2 of the License. * 00013 * * 00014 ***************************************************************************/ 00015 //qt includes 00016 #include <qfileinfo.h> 00017 00018 //kde includes 00019 #include <kconfig.h> 00020 #include <kdebug.h> 00021 #include <kglobal.h> 00022 #include <kio/netaccess.h> 00023 #include <klocale.h> 00024 #include <kmessagebox.h> 00025 #include <kstandarddirs.h> 00026 #include <ktar.h> 00027 #include <ktempdir.h> 00028 00029 //app includes 00030 #include "engine.h" 00031 #include "knewstuffsecure.h" 00032 #include "security.h" 00033 00034 using namespace KNS; 00035 00036 KNewStuffSecure::KNewStuffSecure(const QString &type, QWidget *parentWidget) 00037 : KNewStuff(type, parentWidget) 00038 { 00039 m_tempDir = 0L; 00040 connect(engine(), SIGNAL(uploadFinished(bool)), SLOT(slotUploadFinished(bool))); 00041 } 00042 00043 00044 KNewStuffSecure::~KNewStuffSecure() 00045 { 00046 removeTempDirectory(); 00047 } 00048 00049 bool KNewStuffSecure::install(const QString &fileName) 00050 { 00051 bool ok = true; 00052 00053 removeTempDirectory(); 00054 m_tempDir = new KTempDir(); 00055 m_tempDir->setAutoDelete(true); 00056 KTar tar(fileName, "application/x-gzip"); 00057 if (tar.open(IO_ReadOnly)) 00058 { 00059 const KArchiveDirectory *directory = tar.directory(); 00060 directory->copyTo(m_tempDir->name(), true); 00061 m_tarName = ""; 00062 QStringList entries = directory->entries(); 00063 for (QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) 00064 { 00065 if (*it != "signature" && *it != "md5sum") 00066 { 00067 m_tarName = *it; 00068 break; 00069 } 00070 } 00071 tar.close(); 00072 if (m_tarName.isEmpty()) 00073 ok = false; 00074 else 00075 { 00076 m_tarName.prepend(m_tempDir->name()); 00077 connect(Security::ref(), SIGNAL(validityResult(int)), this, SLOT(slotValidated(int))); 00078 Security::ref()->checkValidity(m_tarName); 00079 } 00080 } else 00081 ok = false; 00082 if (!ok) 00083 KMessageBox::error(parentWidget(), i18n("There was an error with the downloaded resource tarball file. Possible causes are damaged archive or invalid directory structure in the archive."), i18n("Resource Installation Error")); 00084 return ok; 00085 } 00086 00087 void KNewStuffSecure::slotValidated(int result) 00088 { 00089 QString errorString; 00090 QString signatureStr; 00091 bool valid = true; 00092 if (result == -1) 00093 { 00094 errorString ="<br>- " + i18n("No keys were found."); 00095 valid = false; 00096 } else 00097 if (result == 0) 00098 { 00099 errorString ="<br>- " + i18n("The validation failed for unknown reason."); 00100 valid = false; 00101 } else 00102 { 00103 KeyStruct key = Security::ref()->signatureKey(); 00104 if (!(result & Security::MD5_OK )) 00105 { 00106 errorString = "<br>- " + i18n("The MD5SUM check failed, the archive might be broken."); 00107 valid = false; 00108 } 00109 if (result & Security::SIGNED_BAD) 00110 { 00111 errorString += "<br>- " + i18n("The signature is bad, the archive might be broken or altered."); 00112 valid = false; 00113 } 00114 if (result & Security::SIGNED_OK) 00115 { 00116 if (result & Security::TRUSTED) 00117 { 00118 kdDebug() << "Signed and trusted " << endl; 00119 } else 00120 { 00121 errorString += "<br>- " + i18n("The signature is valid, but untrusted."); 00122 valid = false; 00123 } 00124 } 00125 if (result & Security::UNKNOWN) 00126 { 00127 errorString += "<br>- " + i18n("The signature is unknown."); 00128 valid = false; 00129 } else 00130 { 00131 signatureStr = i18n("The resource was signed with key <i>0x%1</i>, belonging to <i>%2 <%3></i>.").arg(key.id.right(8)).arg(key.name).arg(key.mail); 00132 } 00133 } 00134 if (!valid) 00135 { 00136 signatureStr.prepend( "<br>"); 00137 if (KMessageBox::warningContinueCancel(parentWidget(), i18n("<qt>There is a problem with the resource file you have downloaded. The errors are :<b>%1</b><br>%2<br><br>Installation of the resource is <b>not recommended</b>.<br><br>Do you want to proceed with the installation?</qt>").arg(errorString).arg(signatureStr), i18n("Problematic Resource File")) == KMessageBox::Continue) 00138 valid = true; 00139 } else 00140 KMessageBox::information(parentWidget(), i18n("<qt>%1<br><br>Press OK to install it.</qt>").arg(signatureStr), i18n("Valid Resource"), "Show Valid Signature Information"); 00141 if (valid) 00142 { 00143 installResource(); 00144 emit installFinished(); 00145 } else 00146 { 00147 KConfig *cfg = KGlobal::config(); 00148 cfg->deleteGroup("KNewStuffStatus"); 00149 cfg->setGroup("KNewStuffStatus"); 00150 for (QMap<QString, QString>::ConstIterator it = m_installedResources.constBegin(); it != m_installedResources.constEnd(); ++it) 00151 { 00152 cfg->writeEntry(it.key(), it.data()); 00153 } 00154 cfg->sync(); 00155 } 00156 removeTempDirectory(); 00157 disconnect(Security::ref(), SIGNAL(validityResult(int)), this, SLOT(slotValidated(int))); 00158 } 00159 00160 void KNewStuffSecure::downloadResource() 00161 { 00162 KConfig *cfg = KGlobal::config(); 00163 m_installedResources = cfg->entryMap("KNewStuffStatus"); 00164 engine()->ignoreInstallResult(true); 00165 KNewStuff::download(); 00166 } 00167 00168 bool KNewStuffSecure::createUploadFile(const QString &fileName) 00169 { 00170 Q_UNUSED(fileName); 00171 return true; 00172 } 00173 00174 void KNewStuffSecure::uploadResource(const QString& fileName) 00175 { 00176 connect(Security::ref(), SIGNAL(fileSigned(int)), this, SLOT(slotFileSigned(int))); 00177 removeTempDirectory(); 00178 m_tempDir = new KTempDir(); 00179 m_tempDir->setAutoDelete(true); 00180 QFileInfo f(fileName); 00181 m_signedFileName = m_tempDir->name() + "/" + f.fileName(); 00182 KIO::NetAccess::file_copy(KURL::fromPathOrURL(fileName), KURL::fromPathOrURL(m_signedFileName), -1, true); 00183 Security::ref()->signFile(m_signedFileName); 00184 } 00185 00186 void KNewStuffSecure::slotFileSigned(int result) 00187 { 00188 if (result == 0) 00189 { 00190 KMessageBox::error(parentWidget(), i18n("The signing failed for unknown reason.")); 00191 } else 00192 { 00193 if (result & Security::BAD_PASSPHRASE) 00194 { 00195 if (KMessageBox::warningContinueCancel(parentWidget(), i18n("There are no keys usable for signing or you did not entered the correct passphrase.\nProceed without signing the resource?")) == KMessageBox::Cancel) 00196 { 00197 disconnect(Security::ref(), SIGNAL(fileSigned(int)), this, SLOT(slotFileSigned(int))); 00198 removeTempDirectory(); 00199 return; 00200 } 00201 } 00202 KTar tar(m_signedFileName + ".signed", "application/x-gzip"); 00203 tar.open(IO_WriteOnly); 00204 QStringList files; 00205 files << m_signedFileName; 00206 files << m_tempDir->name() + "/md5sum"; 00207 files << m_tempDir->name() + "/signature"; 00208 00209 for (QStringList::Iterator it_f = files.begin(); it_f != files.end(); ++it_f) 00210 { 00211 QFile file(*it_f); 00212 file.open(IO_ReadOnly); 00213 QByteArray bArray = file.readAll(); 00214 tar.writeFile(QFileInfo(file).fileName(), "user", "group", bArray.size(), bArray.data()); 00215 file.close(); 00216 } 00217 tar.close(); 00218 KIO::NetAccess::file_move(KURL::fromPathOrURL(m_signedFileName + ".signed"), KURL::fromPathOrURL(m_signedFileName), -1, true); 00219 KNewStuff::upload(m_signedFileName, QString::null); 00220 disconnect(Security::ref(), SIGNAL(fileSigned(int)), this, SLOT(slotFileSigned(int))); 00221 } 00222 } 00223 00224 void KNewStuffSecure::slotUploadFinished(bool result) 00225 { 00226 Q_UNUSED(result); 00227 removeTempDirectory(); 00228 } 00229 00230 void KNewStuffSecure::removeTempDirectory() 00231 { 00232 if (m_tempDir) 00233 { 00234 KIO::NetAccess::del(KURL().fromPathOrURL(m_tempDir->name()), parentWidget()); 00235 delete m_tempDir; 00236 m_tempDir = 0L; 00237 } 00238 } 00239 00240 #include "knewstuffsecure.moc"