• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KNewStuff

security.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           security.cpp  -  description
00003                              -------------------
00004     begin                : Thu Jun 24 11:22:12 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 
00016  //qt includes
00017 #include <qfile.h>
00018 #include <qfileinfo.h>
00019 #include <qstringlist.h>
00020 #include <qtimer.h>
00021 
00022  //kde includes
00023 #include <kdebug.h>
00024 #include <kinputdialog.h>
00025 #include <klocale.h>
00026 #include <kmdcodec.h>
00027 #include <kmessagebox.h>
00028 #include <kpassdlg.h>
00029 #include <kprocio.h>
00030 
00031  //app includes
00032 #include "security.h"
00033 
00034 using namespace KNS;
00035 
00036 Security::Security()
00037 {
00038    m_keysRead = false;
00039    m_gpgRunning = false;
00040    readKeys();
00041    readSecretKeys();
00042 }
00043 
00044 
00045 Security::~Security()
00046 {
00047 }
00048 
00049 void Security::readKeys()
00050 {
00051   if (m_gpgRunning)
00052   {
00053     QTimer::singleShot(5, this, SLOT(readKeys()));
00054     return;
00055   }
00056   m_runMode = List;
00057   m_keys.clear();
00058   KProcIO *readProcess=new KProcIO();
00059   *readProcess << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-keys";
00060   connect(readProcess, SIGNAL(processExited(KProcess *)), this, SLOT(slotProcessExited(KProcess *)));
00061   connect(readProcess, SIGNAL(readReady(KProcIO *)) ,this, SLOT(slotDataArrived(KProcIO *)));
00062   if (!readProcess->start(KProcess::NotifyOnExit, true))
00063     KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and retrieve the available keys. Make sure that <i>gpg</i> is installed, otherwise verification of downloaded resources will not be possible.</qt>"));
00064   else
00065     m_gpgRunning = true;
00066 }
00067 
00068 void Security::readSecretKeys()
00069 {
00070   if (m_gpgRunning)
00071   {
00072     QTimer::singleShot(5, this, SLOT(readSecretKeys()));
00073     return;
00074   }
00075   m_runMode = ListSecret;
00076   KProcIO *readProcess=new KProcIO();
00077   *readProcess << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-secret-keys";
00078   connect(readProcess, SIGNAL(processExited(KProcess *)), this, SLOT(slotProcessExited(KProcess *)));
00079   connect(readProcess, SIGNAL(readReady(KProcIO *)) ,this, SLOT(slotDataArrived(KProcIO *)));
00080   if (readProcess->start(KProcess::NotifyOnExit, true))
00081     m_gpgRunning = true;  
00082 }
00083 
00084 void Security::slotProcessExited(KProcess *process)
00085 {
00086   switch (m_runMode)
00087    {
00088      case ListSecret:
00089                   m_keysRead = true;
00090                   break;
00091      case Verify: emit validityResult(m_result);
00092                   break;
00093      case Sign:   emit fileSigned(m_result);
00094                   break;
00095 
00096    }
00097    m_gpgRunning = false;
00098    delete process;
00099 }
00100 
00101 void Security::slotDataArrived(KProcIO *procIO)
00102 {
00103   QString data;
00104   while (procIO->readln(data, true) != -1)
00105   {
00106      switch (m_runMode)
00107      {
00108         case List:
00109         case ListSecret:  
00110           if (data.startsWith("pub") || data.startsWith("sec"))
00111           {
00112               KeyStruct key;
00113               if (data.startsWith("pub"))
00114                 key.secret = false;
00115               else
00116                 key.secret = true;
00117               QStringList line = QStringList::split(":", data, true);
00118               key.id = line[4];
00119               QString shortId = key.id.right(8);
00120               QString trustStr = line[1];
00121               key.trusted = false;
00122               if (trustStr == "u" || trustStr == "f")
00123                   key.trusted = true;
00124               data = line[9];
00125               key.mail=data.section('<', -1, -1);
00126               key.mail.truncate(key.mail.length() - 1);
00127               key.name=data.section('<',0,0);
00128               if (key.name.find("(")!=-1)
00129                   key.name=key.name.section('(',0,0);
00130               m_keys[shortId] = key;
00131           }
00132           break;
00133        case Verify:
00134           data = data.section("]",1,-1).stripWhiteSpace();
00135           if (data.startsWith("GOODSIG"))
00136           {
00137               m_result &= SIGNED_BAD_CLEAR;
00138               m_result |= SIGNED_OK;
00139               QString id = data.section(" ", 1 , 1).right(8);
00140               if (!m_keys.contains(id))
00141               {
00142                   m_result |= UNKNOWN;
00143               } else
00144               {
00145                  m_signatureKey = m_keys[id];
00146               }
00147           } else
00148           if (data.startsWith("NO_PUBKEY"))
00149           {
00150               m_result &= SIGNED_BAD_CLEAR;
00151               m_result |= UNKNOWN;
00152           } else
00153           if (data.startsWith("BADSIG"))
00154           {
00155               m_result |= SIGNED_BAD;
00156               QString id = data.section(" ", 1 , 1).right(8);
00157               if (!m_keys.contains(id))
00158               {
00159                   m_result |= UNKNOWN;
00160               } else
00161               {
00162                  m_signatureKey = m_keys[id];
00163               }
00164           } else
00165           if (data.startsWith("TRUST_ULTIMATE"))
00166           {
00167             m_result &= SIGNED_BAD_CLEAR;
00168             m_result |= TRUSTED;
00169           }
00170           break;
00171 
00172        case Sign:
00173          if (data.find("passphrase.enter") != -1)
00174          {
00175            QCString password;
00176            KeyStruct key = m_keys[m_secretKey];
00177            int result = KPasswordDialog::getPassword(password, i18n("<qt>Enter passphrase for key <b>0x%1</b>, belonging to<br><i>%2&lt;%3&gt;</i>:</qt>").arg(m_secretKey).arg(key.name).arg(key.mail));
00178            if (result == KPasswordDialog::Accepted)
00179            {
00180              procIO->writeStdin(password, true);
00181              password.fill(' ');
00182            }
00183            else
00184            {
00185              m_result |= BAD_PASSPHRASE;
00186              slotProcessExited(procIO);
00187              return;
00188            }
00189          } else
00190          if (data.find("BAD_PASSPHRASE") != -1)
00191          {
00192            m_result |= BAD_PASSPHRASE;
00193          }
00194          break;
00195      }
00196   }
00197 }
00198 
00199 void Security::checkValidity(const QString& filename)
00200 {
00201   m_fileName = filename;
00202   slotCheckValidity();
00203 }  
00204 
00205 void Security::slotCheckValidity()
00206 {  
00207   if (!m_keysRead || m_gpgRunning)
00208   {
00209     QTimer::singleShot(5, this, SLOT(slotCheckValidity()));
00210     return;
00211   }
00212   if (m_keys.count() == 0)
00213   {    
00214     emit validityResult(-1);
00215     return;
00216   }  
00217 
00218   m_result = 0;
00219   m_runMode = Verify;
00220   QFileInfo f(m_fileName);
00221   //check the MD5 sum
00222   QString md5sum;
00223   const char* c = "";
00224   KMD5 context(c);
00225   QFile file(m_fileName);
00226   if (file.open(IO_ReadOnly))
00227   {
00228      context.reset();
00229      context.update(file);
00230      md5sum = context.hexDigest();
00231      file.close();
00232   }
00233   file.setName(f.dirPath() + "/md5sum");
00234   if (file.open(IO_ReadOnly))
00235   {
00236      QString md5sum_file;
00237      file.readLine(md5sum_file, 50);
00238      if (!md5sum.isEmpty() && !md5sum_file.isEmpty() && md5sum_file.startsWith(md5sum))
00239        m_result |= MD5_OK;
00240      file.close();
00241   }
00242   m_result |= SIGNED_BAD;
00243   m_signatureKey.id = "";
00244   m_signatureKey.name = "";
00245   m_signatureKey.mail = "";
00246   m_signatureKey.trusted = false;
00247 
00248   //verify the signature
00249   KProcIO *verifyProcess=new KProcIO();
00250   *verifyProcess<<"gpg"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--verify" << f.dirPath() + "/signature"<< m_fileName;
00251   connect(verifyProcess, SIGNAL(processExited(KProcess *)),this, SLOT(slotProcessExited(KProcess *)));
00252   connect(verifyProcess, SIGNAL(readReady(KProcIO *)),this, SLOT(slotDataArrived(KProcIO *)));
00253   if (verifyProcess->start(KProcess::NotifyOnExit,true))
00254       m_gpgRunning = true;
00255   else
00256   {
00257       KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and check the validity of the file. Make sure that <i>gpg</i> is installed, otherwise verification of downloaded resources will not be possible.</qt>"));
00258       emit validityResult(0);
00259       delete verifyProcess;
00260   }
00261 }
00262 
00263 void Security::signFile(const QString &fileName)
00264 {
00265   m_fileName = fileName;
00266   slotSignFile();
00267 }
00268 
00269 void Security::slotSignFile()
00270 {
00271   if (!m_keysRead || m_gpgRunning)
00272   {
00273     QTimer::singleShot(5, this, SLOT(slotSignFile()));
00274     return;
00275   }
00276   
00277   QStringList secretKeys;
00278   for (QMap<QString, KeyStruct>::Iterator it = m_keys.begin(); it != m_keys.end(); ++it)
00279   {
00280     if (it.data().secret)
00281       secretKeys.append(it.key());
00282   }
00283   
00284   if (secretKeys.count() == 0)
00285   {    
00286     emit fileSigned(-1);
00287     return;
00288   }  
00289   
00290   m_result = 0;
00291   QFileInfo f(m_fileName);
00292 
00293   //create the MD5 sum
00294   QString md5sum;
00295   const char* c = "";
00296   KMD5 context(c);
00297   QFile file(m_fileName);
00298   if (file.open(IO_ReadOnly))
00299   {
00300     context.reset();
00301     context.update(file);
00302     md5sum = context.hexDigest();
00303     file.close();
00304   }
00305   file.setName(f.dirPath() + "/md5sum");
00306   if (file.open(IO_WriteOnly))
00307   {
00308     QTextStream stream(&file);
00309     stream << md5sum;
00310     m_result |= MD5_OK;
00311     file.close();
00312   }
00313   
00314   if (secretKeys.count() > 1)
00315   {
00316     bool ok;
00317     secretKeys = KInputDialog::getItemList(i18n("Select Signing Key"), i18n("Key used for signing:"), secretKeys, secretKeys[0], false, &ok);    
00318     if (ok)
00319       m_secretKey = secretKeys[0];
00320     else
00321     {
00322       emit fileSigned(0);
00323       return;
00324     }
00325   } else
00326     m_secretKey = secretKeys[0];
00327 
00328   //verify the signature
00329   KProcIO *signProcess=new KProcIO();
00330   *signProcess<<"gpg"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--no-tty"<<"--detach-sign" << "-u" << m_secretKey << "-o" << f.dirPath() + "/signature" << m_fileName;
00331   connect(signProcess, SIGNAL(processExited(KProcess *)),this, SLOT(slotProcessExited(KProcess *)));
00332   connect(signProcess, SIGNAL(readReady(KProcIO *)),this, SLOT(slotDataArrived(KProcIO *)));
00333   m_runMode = Sign;
00334   if (signProcess->start(KProcess::NotifyOnExit,true))
00335     m_gpgRunning = true;
00336   else
00337   {
00338     KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and sign the file. Make sure that <i>gpg</i> is installed, otherwise signing of the resources will not be possible.</qt>"));
00339     emit fileSigned(0);
00340     delete signProcess;
00341   }
00342 }
00343 
00344 #include "security.moc"

KNewStuff

Skip menu "KNewStuff"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal