# knewstuff Library API Documentation

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

# security.cpp

    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"

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