diff options
author | Mavridis Philippe <[email protected]> | 2021-02-26 19:34:09 +0200 |
---|---|---|
committer | Mavridis Philippe <[email protected]> | 2021-03-03 17:44:31 +0200 |
commit | 13cb4a5e7dc1c22d25c51da52156a558be0b7d05 (patch) | |
tree | e013fb1be4c88430b4be1ef21acb656c7f91eb5d /src | |
parent | 8300c80d583320087d844b9f0ad0025d4a60aa10 (diff) | |
download | klamav-13cb4a5e7dc1c22d25c51da52156a558be0b7d05.tar.gz klamav-13cb4a5e7dc1c22d25c51da52156a558be0b7d05.zip |
Added On-Access Scanner.
There are still a few TODOs, but it seems to work quite well already.
This relates to issue #10.
Signed-off-by: Mavridis Philippe <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/configdialog.cpp | 46 | ||||
-rw-r--r-- | src/configdialog.h | 7 | ||||
-rw-r--r-- | src/klamav.h | 14 | ||||
-rw-r--r-- | src/klamavconfig.kcfg | 47 | ||||
-rw-r--r-- | src/klamonacc.cpp | 387 | ||||
-rw-r--r-- | src/klamonacc.h | 73 | ||||
-rw-r--r-- | src/klamonacc_alert.ui | 212 | ||||
-rw-r--r-- | src/klamonacc_config.ui | 253 | ||||
-rw-r--r-- | src/klamonacc_config.ui.h | 54 |
10 files changed, 1064 insertions, 32 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2275778..046fe3e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,7 @@ tde_add_executable( ${PROJECT_NAME} AUTOMOC klamscan.cpp kuarantine.cpp welcome.cpp dbviewer.cpp frame.cpp tabwidget.cpp viewer.cpp pageviewer.cpp klamav_run.cpp dcopklamscan.skel directorylist.cpp + klamonacc.cpp klamonacc_alert.ui scanviewer.cpp schedule.cpp datepicker.cpp cthost.cpp ctcron.cpp ctmonth.cpp ctdom.cpp ctdow.cpp cttask.cpp ctvariable.cpp @@ -39,7 +40,7 @@ tde_add_executable( ${PROJECT_NAME} AUTOMOC ktview.cpp ktlistcron.cpp kticon.cpp activityviewer.cpp collectiondb.cpp configdialog.cpp klamavconfig.kcfgc - archives.ui specialfiletypes.ui + archives.ui specialfiletypes.ui klamonacc_config.ui firstrunwizard.ui logoptions.ui backend.ui k3bjobprogressosd_mod.cpp diff --git a/src/configdialog.cpp b/src/configdialog.cpp index 5cd76ac..43a0fe8 100644 --- a/src/configdialog.cpp +++ b/src/configdialog.cpp @@ -13,11 +13,13 @@ email : [email protected] * * ***************************************************************************/ +#include "klamav.h" #include "configdialog.h" #include "backend.h" #include "archives.h" #include "specialfiletypes.h" -/* #include "autoscanoptions.h" */ +#include "klamonacc.h" +#include "klamonacc_config.h" #include "logoptions.h" #include "sigtool.h" @@ -42,6 +44,7 @@ email : [email protected] #include <klineedit.h> #include <tdelocale.h> #include <kstandarddirs.h> +#include <tdemessagebox.h> ////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC @@ -57,7 +60,7 @@ KlamavConfigDialog::KlamavConfigDialog( TQWidget *parent, const char* name, TDEC m_archives = new ArchiveOptions( 0, "Archives" ); m_emailprotection = new Sigtool ( 0, "E-mail protection" ); m_specialfiletypes = new SpecialFileTypes( 0, "File Types" ); - /* m_autoscanoptions = new AutoScanOptions( 0, "Auto-Scan" ); */ + m_klamonacc = new KlamOnAccConfig( 0, "On-Access Scanner" ); m_logoptions = new LogOptions( 0, "Event Logging" ); // add pages @@ -68,7 +71,13 @@ KlamavConfigDialog::KlamavConfigDialog( TQWidget *parent, const char* name, TDEC addPage( m_archives, i18n( "Archives" ), "ark", i18n( "Configure Archive Scanning" ) ); addPage( m_emailprotection, i18n( "E-mail protection" ), "email", i18n( "Set up your e-mail client to use Klammail" ) ); addPage( m_specialfiletypes, i18n( "File Types" ), "folder", i18n( "Configure File Types" ) ); - /* addPage( m_autoscanoptions, i18n( "Auto-Scan" ), "filefind", i18n( "Configure Auto-Scan" ) ); */ + + addPage( m_klamonacc, i18n( "On-Access Scanner" ), "filefind", i18n( "Configure On-Access Scanning" ) ); + connect( m_klamonacc, SIGNAL(directoriesModified()), tdemain->klamonacc, SLOT(restart()) ); + connect( tdemain->klamonacc, SIGNAL(stateUpdated()), this, SLOT(slotToggleKlamOnAccCheckbox()) ); + connect( m_klamonacc->kcfg_EnableOnAccess, SIGNAL(toggled(bool)), this, SLOT(slotToggleKlamOnAcc(bool)) ); + slotToggleKlamOnAcc( m_klamonacc->kcfg_EnableOnAccess->isOn() ); // initial state + addPage( m_logoptions, i18n( "Event Logging" ), "kate", i18n( "Configure Events to Log" ) ); TQObjectList *list = queryList( "TQLabel", "infoPixmap" ); @@ -82,7 +91,7 @@ KlamavConfigDialog::KlamavConfigDialog( TQWidget *parent, const char* name, TDEC static_cast<TQLabel*>(label)->setMaximumWidth( 250 ); delete list; - + connect( this, SIGNAL(settingsChanged()), SLOT(applySettings()) ); } KlamavConfigDialog::~KlamavConfigDialog() @@ -96,6 +105,19 @@ void KlamavConfigDialog::slotToggleClamdscan(bool on) m_specialfiletypes->setEnabled(!on); } +void KlamavConfigDialog::slotToggleKlamOnAcc(bool on) +{ + m_klamonacc->kcfg_ExtraScanning->setEnabled(on); + m_klamonacc->kcfg_OnAccessMaxFile->setEnabled(on); +// m_klamonacc->kcfg_ExcludeConfDir->setEnabled(on); + m_klamonacc->GroupWatchDirs->setEnabled(on); +} + +void KlamavConfigDialog::slotToggleKlamOnAccCheckbox() +{ + m_klamonacc->kcfg_EnableOnAccess->setChecked( tdemain->klamonacc->isEnabled() ); +} + /** Show page by object name */ void KlamavConfigDialog::showPage( const TQCString& page ) { @@ -116,6 +138,22 @@ void KlamavConfigDialog::addPage( TQWidget *page, const TQString &itemName, cons TDEConfigDialog::addPage( page, itemName, pixmapName, header, manage ); } +void KlamavConfigDialog::applySettings() { + // Some precautions + // if(! m_klamonacc->kcfg_ExcludeConfDir->isOn() ) + // KMessageBox::information(this, i18n("You have chosen not to exclude the TDE configuration directory from the on-access scanner's watchlist. Be warned that watching this directory can severely impact your computer's performance and cause instability."), i18n("Warning!") ); + + // Toggle/restart Klamonacc + bool oldState = tdemain->klamonacc->isEnabled(); + bool newState = m_klamonacc->kcfg_EnableOnAccess->isOn(); + + if( oldState != newState ) // If Klamonacc's state changed + tdemain->klamonacc->toggle( newState ); + else if( newState && m_klamonacc->needsRestart() ) { // If KlamOnAcc's settings were changed + tdemain->klamonacc->restart(); + m_klamonacc->slotSettingsApplied(); + } +} diff --git a/src/configdialog.h b/src/configdialog.h index ad906c9..a943492 100644 --- a/src/configdialog.h +++ b/src/configdialog.h @@ -42,6 +42,8 @@ class KlamavConfigDialog : public TDEConfigDialog public slots: void slotToggleClamdscan( bool on ); + void slotToggleKlamOnAcc( bool on ); + void slotToggleKlamOnAccCheckbox(); private: bool clamdscan; @@ -50,12 +52,15 @@ class KlamavConfigDialog : public TDEConfigDialog class ArchiveOptions *m_archives; class SpecialFileTypes *m_specialfiletypes; class Sigtool *m_emailprotection; - class AutoScanOptions *m_autoscanoptions; + class KlamOnAccConfig *m_klamonacc; class LogOptions *m_logoptions; TQValueList<TQWidget*> m_pageList; TQMap<TQString, TQString> m_pluginName; TQMap<TQString, TQString> m_pluginKlamavName; + + private slots: + void applySettings(); }; diff --git a/src/klamav.h b/src/klamav.h index f3d2960..210934b 100644 --- a/src/klamav.h +++ b/src/klamav.h @@ -37,6 +37,7 @@ class Activityviewer; class Aboutklamav; class KlamDB; class KSystemTray; +class KlamOnAcc; /** * This class serves as the main window for Klamav. It handles the @@ -69,6 +70,8 @@ public: KSystemTray *_tray; TDEAction *EnableFreshklam; TDEAction *DisableFreshklam; + TDEAction *EnableKlamOnAcc; + TDEAction *DisableKlamOnAcc; Freshklam *freshklam; bool firstDownload; bool downloadDBForWizard; @@ -78,6 +81,7 @@ public: Activityviewer *activityviewer; void showVirusBrowser(); TQTabWidget *tab; + KlamOnAcc *klamonacc; protected: @@ -104,7 +108,6 @@ protected: //void readProperties(TDEConfig *); public slots: - void clamdStopped(); void slotConfigKlamav( const TQCString& page ); private slots: void slotScanFile(); @@ -115,9 +118,12 @@ private slots: void slotToggleQuarantine(); void slotToggleDBViewer(); void slotToggleEvents(); + void slotKOAStateUpdate(); void contextEnableFK(); - void contextUpdateFK(); - void contextDisableFK(); + void contextUpdateFK(); + void contextDisableFK(); + void contextEnableKOA(); + void contextDisableKOA(); void tabClosed(TQString name); private: @@ -158,7 +164,7 @@ private: TQStringList lastSearchPaths; Sigtool *sigtool; Aboutklamav *aboutklamav; - + TDEPopupMenu *tabs_menu; int showWelcomeTab; int showQuarantineTab; diff --git a/src/klamavconfig.kcfg b/src/klamavconfig.kcfg index 8a2c55c..4646d32 100644 --- a/src/klamavconfig.kcfg +++ b/src/klamavconfig.kcfg @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.dtd"> -<kcfg> -<kcfgfile name="klamavrc"/> +<kcfg> +<kcfgfile name="klamavrc"/> <group name="KlamavBackend"> <entry name="ScannerClamscan" type="Bool"> @@ -30,17 +30,17 @@ <label>Maximum Recursion Level</label> <whatsthis>The maximum number of subdirectories in a zip file to open before .</whatsthis> <default>0</default> - </entry> + </entry> <entry name="MaxFileSize" type="Int"> <label>Maximum MBs to Extract</label> <whatsthis>The maximum number of megabytes to extract from a zip file before marking it as suspicious.</whatsthis> <default>0</default> - </entry> + </entry> <entry name="MaxScanSize" type="Int"> <label>Maximum MBs to Extract</label> <whatsthis>The maximum number of megabytes to extract from a zip file before marking it as suspicious.</whatsthis> <default>0</default> - </entry> + </entry> <entry name="NoFilesToExtract" type="Int"> <label>Maximum Number of Files to Extract</label> <whatsthis>The maximum number of file to extract from a zip file before marking it as suspicious.</whatsthis> @@ -48,7 +48,7 @@ </entry> </group> -<group name="FileTypes"> +<group name="FileTypes"> <entry name="VirusEncrypted" type="Bool"> <label>Mark Encrypted Files as Suspicious</label> <default>true</default> @@ -101,27 +101,30 @@ </group> -<group name="Autoscan"> - <entry name="Executed" type="Bool"> - <label>Scan Files When They Are Executed</label> - <default>true</default> +<group name="OnAccess"> + <entry name="EnableOnAccess" type="Bool"> + <label>Enable On-Access Scanner</label> + <default>false</default> </entry> - <entry name="Opened" type="Bool"> - <label>Scan Files When They Are Opened</label> - <default>true</default> + <entry name="ExtraScanning" type="Bool"> + <label>Scan Files/Directories When They Are Created or Moved</label> + <default>false</default> </entry> - <entry name="Closed" type="Bool"> - <label>Scan Files When They Are Closed</label> - <default>true</default> + <entry name="ExcludeConfDir" type="Bool"> + <label>Exclude TDE Configuration Directory</label> + <default>true</default> </entry> - <entry name="Created" type="Bool"> - <label>Scan Files When They Are Created or Modified</label> - <default>false</default> + <entry name="OnAccessMaxFile" type="Int"> + <label>Maximum File Size</label> + <default>5</default> + </entry> + <entry name="Watchlist" type="StringList"> + <label>Directories to Watch</label> + <default></default> </entry> - </group> -<group name="EventLogging"> +<group name="EventLogging"> <entry name="ExpireDays" type="Int"> <label>Expire Events After the Specified Number of Days</label> <default>30</default> @@ -158,7 +161,7 @@ </group> -<group name="Misc"> +<group name="Misc"> <entry name="ClamAVVersion" type="String"> <label>Expire Events After the Specified Number of Days</label> </entry> diff --git a/src/klamonacc.cpp b/src/klamonacc.cpp new file mode 100644 index 0000000..76a41d8 --- /dev/null +++ b/src/klamonacc.cpp @@ -0,0 +1,387 @@ +/* + * KlamOnAcc class -- the non-graphical class which manages clamonacc. + * + * Copyright (C) 2021 Mavridis Philippe <[email protected]> + * + * Portions taken from freshklam.cpp and scanviewer.cpp + */ + +/* TODO: + - Implement a separate start/stop daemon process so that we don't need to + ask for root privgileges every time we start or kill clamonacc + - processOutput: [Initializing] and [Scanner ready] notifications + */ + +#include "klamonacc.h" +#include "klamonacc_alert.h" +#include "klamav.h" +#include "klamavconfig.h" +#include "collectiondb.h" +#include "directorylist.h" + +#include <tdeglobal.h> +#include <tdelocale.h> +#include <tdeconfig.h> +#include <tdetempfile.h> +#include <kprocess.h> +#include <tdemessagebox.h> +#include <ksystemtray.h> +#include <knotifyclient.h> + +/* Required by quarantine() function */ +#include <kiconloader.h> +#include <tdeio/netaccess.h> + +KlamOnAcc::KlamOnAcc( TQWidget *parent, const char *name ) + : TQObject( parent, name ) +{ + config = TDEGlobal::config(); + config->setGroup("OnAccess"); + + // Initial state + toggle( config->readBoolEntry("EnableOnAccess", false) ); +} + +KlamOnAcc::~KlamOnAcc() +{ +} + +TQString KlamOnAcc::tdesu(TQString command, TQString caption, bool terminal) +{ + TQString sucommand; + + if(terminal) + sucommand = TQString("tdesu --caption \"%1\" --ignorebutton -t ").arg( caption ); + else + sucommand = TQString("tdesu --caption \"%1\" --ignorebutton ").arg( caption ); + + sucommand += "\"" + command + "\""; + + return sucommand; +} + +TQString KlamOnAcc::startPrepare() +{ + // Determine and write configuration + TQString daemonOpts; + TQStringList daemonConfig; + + // Create a config file based on the default one + TQFile defaultConfigFile( "/etc/clamav/clamd.conf" ); + + if( defaultConfigFile.open(IO_ReadOnly) ) + { + TQTextStream in_stream( &defaultConfigFile ); + TQString in_line; + int in_line_n = 0; + + while(! in_stream.atEnd() ) + { + daemonConfig += in_stream.readLine(); + ++in_line_n; + } + + defaultConfigFile.close(); + } + + // Set up ClamOnAcc's config + daemonConfig += "OnAccessPrevention yes"; + + config->setGroup("OnAccess"); + + if ( config->readBoolEntry("ExtraScanning", false) ) + daemonConfig += "OnAccessExtraScanning yes"; + + daemonConfig += TQString("OnAccessMaxFileSize %1M").arg( + config->readNumEntry("OnAccessMaxFile", 5) + ); + + daemonConfig += "OnAccessExcludeUname clamav"; + + // Specify directories to watch + TQStringList dirs = CollectionSetup::pruneSelectedDirs( config->readListEntry("Watchlist") ); + + if (! dirs.count() ) { + fatalError( i18n("Please select the directories you want to watch from the Options dialog.") ); + return TQString::null; + } + + for ( TQStringList::Iterator it = dirs.begin(); it != dirs.end(); it++ ) + daemonConfig += TQString("OnAccessIncludePath %1").arg(*it); + + /* BUG: DOES NOT WORK (why do they have this option then?) + "ERROR: ClamInotif: can't exclude '/home/user/.trinity'" */ + // if ( config->readBoolEntry("ExcludeConfDir", true) ) + // daemonConfig += TQString("OnAccessExcludePath %1/.trinity").arg(getenv("HOME")); + + // Write the config + KTempFile tf; + + if ( tf.status() != 0 ) { + tf.close(); + + fatalError( i18n("Could not create temporary configuration file for ClamOnAcc!") ); + return TQString::null; + } + + TQString tempFileName = tf.name(); + + TQTextStream &ts = *(tf.textStream()); + + for ( TQStringList::Iterator it = daemonConfig.begin(); it != daemonConfig.end(); it++ ) + ts << (*it) << endl; + + tf.close(); + + // Set up ClamOnAcc's command-line options + daemonOpts += " --fdpass -v --stdout --foreground"; + daemonOpts += TQString(" --config-file=%1").arg(tempFileName); + + // Make the start command + TQString command = "clamonacc"; + command += daemonOpts; + + return command; +} + +void KlamOnAcc::startProcess( TQString command ) +{ + childproc = new KShellProcess(); + *childproc << command; + childproc->start(TDEProcess::NotifyOnExit, TDEProcess::Stdout); + + connect( childproc, SIGNAL(receivedStdout(TDEProcess*, char*, int)), SLOT(processOutput(TDEProcess*, char*, int)) ); + connect( childproc, SIGNAL(processExited(TDEProcess*)), SLOT(childExited()) ); + + emit stateUpdated(); +} + +void KlamOnAcc::start() +{ + if( active || !enabled ) return; + active = true; + crashed = false; + + // Log this event + CollectionDB::instance()->insertEvent("On-Access Scanner","Starting On-Access Scanner",0); + + startProcess( tdesu(startPrepare(), i18n("Start On-Access Scanner"), true) ); +} + +TQString KlamOnAcc::stopPrepare() +{ + disconnect( childproc, 0, 0, 0 ); + + // It's like this until a proper start/stop daemon is implemented + return TQString("killall -9 clamonacc"); +} + +void KlamOnAcc::stopProcess( TQString command ) +{ + if( childproc->isRunning() ) { + TDEProcess *terminator = new KShellProcess(); + *terminator << command; + terminator->start(); + } + + emit stateUpdated(); +} + +void KlamOnAcc::stop() +{ + if( !active || !enabled ) return; + active = false; + + // Log this event + CollectionDB::instance()->insertEvent("On-Access Scanner","Stopping On-Access Scanner",0); + + stopProcess( tdesu(stopPrepare(), i18n("Stop On-Access Scanner")) ); +} + + +void KlamOnAcc::restart() +{ + kdDebug() << "restart()" << endl; + if( isActive() ) + { + active = false; + + // We combine two commands here + TQString command = stopPrepare() + TQString("; ") + startPrepare(); + kdDebug() << "restart(): " << command << endl; + startProcess( tdesu(command, i18n("Restart On-Access Scanner"), true) ); + + active = true; + } +} + +void KlamOnAcc::toggle( bool on ) { + kdDebug() << "toggle()" << endl; + + if ( !on && isEnabled() ) + disable(); + else if ( on && !isEnabled() ) + enable(); +} + +void KlamOnAcc::childExited() { + if(active) // died too early + fatalError( i18n("ClamOnAcc has died unexpectedly. If you did not kill it yourself, please check your ClamAV installation.") ); +} + +void KlamOnAcc::fatalError(TQString descr) +{ + if( crashed ) return; // do not display further errors + + active = false; + crashed = true; + + CollectionDB::instance()->insertEvent("On-Access Scanner","On-Access Scanner has died!",0); + + disable(); + + KMessageBox::sorry( + 0, + descr, + i18n("Fatal Error") + ); +} + +void KlamOnAcc::processOutput(TDEProcess*, char* buffer, int buffSize) +{ + + TQString buff( buffer ); + buff = buff.mid( 0, buff.find("\n") ).stripWhiteSpace(); + + kdDebug() << "KLAMONACC " << buff << endl; + + int pos; + + if( buff.find("Could not connect to clamd") != -1 ) + { + fatalError( i18n("The ClamAV daemon is unavailable! Please ensure that it is running and try again.") ); + return; + } + else if( buff.find("ClamInotif: watching") != -1 ) + { + // TODO: "initialization complete" notification + } + else if( (pos = buff.find("FOUND")) != -1 ) + { + fname = buff.mid( 0, buff.find(":") ); + vname = buff.mid( buff.find(":")+2, pos ); + + if( shownAlerts.find(fname) != shownAlerts.end() ) + return; // alert already shown for this file + + TQListViewItem *virusItem; + alert = new KlamOnAccAlert(); + alert->setModal(false); + alert->setActiveWindow(); + + TQListViewItem *virus = new TQListViewItem( alert->VirusList, fname, vname, i18n("Loose") ); + virus->setPixmap( 0, SmallIcon("klamav_virus") ); + + shownAlerts << fname; + alert->exec(); + + if( alert->result() == TQDialog::Accepted ) + quarantine(); + } +} + +void KlamOnAcc::enable() +{ + kdDebug() << "% ENABLE()" << endl; + + config->setGroup("OnAccess"); + config->writeEntry("EnableOnAccess", true); + config->sync(); + + enabled = true; + + if(! isActive() ) start(); + + emit stateUpdated(); +} + +void KlamOnAcc::disable() +{ + kdDebug() << "% DISABLE()" << endl; + if( isActive() ) stop(); + + config->setGroup("OnAccess"); + config->writeEntry("EnableOnAccess", false); + config->sync(); + + enabled = false; + + emit stateUpdated(); +} + +void KlamOnAcc::quarantine() +{ + TQDate today = TQDate::currentDate(); + TQTime now = TQTime::currentTime(); + TQString suffix = TQString(":%1 %2") + .arg(today.toString("ddd MMMM d yyyy")) + .arg(now.toString("hh-mm-ss-zzz ap")); + + TQStringList QuarantineList; + QuarantineList.append(fname+":"+vname+suffix); + + /* The following has been taken nearly verbatim from scanviewer.cpp */ + bool allQuarantined=TRUE; + config->setGroup("Kuarantine"); + TQStringList lastQuarLocations = config->readListEntry("KuarantineLocations"); + + tdemain->_tray->setPixmap(KSystemTray::loadIcon("klamav_quarantining")); + + TQString quarloc; + for (TQStringList::Iterator it = lastQuarLocations.begin(); it == lastQuarLocations.begin() ; it++){ + quarloc = *it; + } + TQStringList lastQuarItems = config->readListEntry(TQString("Items %1").arg(quarloc)); + + for (TQStringList::Iterator it = QuarantineList.begin(); it != QuarantineList.end(); it++ ){ + if (lastQuarItems.contains(*it) != 0) { + lastQuarItems.remove(*it); + } + TQString item2 = (*it).stripWhiteSpace(); + int fnameStartPoint = 0; + int dtStartPoint = item2.findRev(":"); + int fnameEndPoint = item2.findRev(":", (signed int)-((item2.length() - dtStartPoint)+1)); + TQString fname = item2.mid(fnameStartPoint,(fnameEndPoint - fnameStartPoint)); + TQString itemName = item2.mid((fnameEndPoint+1),((dtStartPoint+1) - (fnameEndPoint+2))); + TQString when = item2.mid((dtStartPoint+1),(item2.length() - (dtStartPoint+1))); + if (!(fname.isEmpty())){ + TQStringList tokens = TQStringList::split ( "/", fname, FALSE ); + TQString qname = tokens.last(); + qname.prepend("/"); + qname.prepend(quarloc); + qname.append(":"+when); + if (TDEIO::NetAccess::file_move(fname,qname)){ + if (lastQuarItems.contains(item2)) + lastQuarItems.remove(item2); + lastQuarItems.prepend(item2); + (alert->VirusList->findItem(fname,0))->setText(2,"Quarantined"); + (alert->VirusList->findItem(fname,0))->setPixmap( 0, SmallIcon("klamav") ); + chmod(qname.ascii(),0400); + CollectionDB::instance()->insertEvent("Quarantine",TQString("Quarantined"),fname); + + }else{ + KMessageBox::information (tdemain, i18n("<p>There was a problem quarantining <b>%1</b>. Check your diskspace, the permissions on your quarantine location and whether a file with the same name already exists in the quarantine. </p>").arg(fname)); + } + + + } + } + + emit stateUpdated(); + + config->writeEntry(TQString("Items %1").arg(quarloc), lastQuarItems); + config->sync(); + +} + +#include "klamonacc.moc"
\ No newline at end of file diff --git a/src/klamonacc.h b/src/klamonacc.h new file mode 100644 index 0000000..3938bc1 --- /dev/null +++ b/src/klamonacc.h @@ -0,0 +1,73 @@ +/* + * KlamOnAcc class -- the non-graphical class which manages clamonacc. + * + * Copyright (C) 2021 Mavridis Philippe <[email protected]> + */ + +#ifndef _KLAMONACC_H_ +#define _KLAMONACC_H_ + +#include <tdeapplication.h> + +class TDEProcess; +class KlamOnAccAlert; + +class KlamOnAcc : public TQObject { + Q_OBJECT + + public: + KlamOnAcc( TQWidget *parent, const char *name = 0 ); + virtual ~KlamOnAcc(); + + const TQObject* object() { return static_cast<TQObject*>(this); }; + const bool isActive() { return active; }; + const bool isEnabled() { return enabled; }; + + public slots: + void start(); + void stop(); + void enable(); + void disable(); + void restart(); + void toggle( bool on ); + + private: + TDEConfig *config; + TDEProcess *childproc; + KlamOnAccAlert *alert; + bool enabled = false; + bool active = false; + bool crashed = false; + + /* These contain information about the file which triggered the alert */ + TQString vname; + TQString fname; + + void quarantine(); + + /* We use this to avoid showing two alerts for the same file, as clamonacc + often scans the same file multiple times, triggering the alert */ + TQStringList shownAlerts; + + /* This is a wrapper for tdesu */ + TQString tdesu( TQString command, TQString caption, bool terminal = false ); + + private slots: + /* These functions are responsible for interfacing with clamonacc */ + void childExited(); + void fatalError( TQString descr ); + void processOutput( TDEProcess*, char*, int ); + + /* These functions are responsible for preparing and executing the start/stop/restart commands + They are reused by restart() to avoid calling tdesu twice */ + TQString startPrepare(); + TQString stopPrepare(); + void startProcess( TQString command ); + void stopProcess( TQString command ); + + signals: + /* This signal causes some GUI elements to update */ + void stateUpdated(); +}; + +#endif /* _KLAMONACC_H_ */
\ No newline at end of file diff --git a/src/klamonacc_alert.ui b/src/klamonacc_alert.ui new file mode 100644 index 0000000..e4c7fcb --- /dev/null +++ b/src/klamonacc_alert.ui @@ -0,0 +1,212 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KlamOnAccAlert</class> +<widget class="TQDialog"> + <property name="name"> + <cstring>KlamOnAccAlert</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>450</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>600</width> + <height>450</height> + </size> + </property> + <property name="caption"> + <string>Suspicious File Found! - KlamOnAcc</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>5</number> + </property> + <widget class="TQFrame"> + <property name="name"> + <cstring>AttentionFrame</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLabel"> + <property name="name"> + <cstring>AttentionIcon</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + </widget> + <widget class="TQLabel"> + <property name="name"> + <cstring>AttentionLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><b>Your attention, please!</b><br> +The file you tried to access appears to be infected.</string> + </property> + </widget> + </hbox> + </widget> + <widget class="TQListView"> + <column> + <property name="text"> + <string>Name of File</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Name of Problem Found</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Status</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>VirusList</cstring> + </property> + <property name="selectionMode"> + <enum>NoSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="resizeMode"> + <enum>LastColumn</enum> + </property> + </widget> + <widget class="KTextBrowser"> + <property name="name"> + <cstring>KlamTip</cstring> + </property> + <property name="text"> + <string><p>KlamAV has prevented access to this file because <b>this file might potentially harm your system</b>.</p> +<p>You are advised to <i>quarantine this file</i> and inspect it in the Virus Browser.</p></string> + </property> + </widget> + <widget class="TQButtonGroup"> + <property name="name"> + <cstring>ActionGroup</cstring> + </property> + <property name="title"> + <string>Action</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQPushButton"> + <property name="name"> + <cstring>ActionQuarantine</cstring> + </property> + <property name="focusPolicy"> + <enum>StrongFocus</enum> + </property> + <property name="text"> + <string>&Quarantine</string> + </property> + <property name="accel"> + <string>Alt+Q</string> + </property> + </widget> + <widget class="TQPushButton"> + <property name="name"> + <cstring>ActionDismiss</cstring> + </property> + <property name="text"> + <string>&Dismiss</string> + </property> + <property name="accel"> + <string>Alt+D</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="2309">89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000000473424954080808087c086488000008bc494441545885bd975b8c5d5519c77fdfdab773e69c33b7339d4b874e5ba62d6db95f1a042aa8107da80f3ee00d1fc01862d4f84004313e68d404a2263e98a8408d91e88b574c006f118422985268c1964e67da613af7393367e69c33e7b2cfbeade5c399d2d24e018df14b7676b2b3d6faffbfebfe2fe17f6c33b7dd8164232417df22a9e44fe2e81c02460b269437a2ba757ba544e1aa675f0440decba1079ede2f8003786b8fb3b6370122a0090499e39349ff0b07b64a67f47d9589f76199d4f96799484a41c5da3fbb601ebee5b983e575091c787a3fc6184f27e1e628a85d9b44f56b74ec0f63c27ea3e31c26f1c088412522962fca2989959a6d6bcad8b6975e7abfe5f91f1165d479d02dca023a96a0b2a4be77aa107ee30202cf3df9a81734caef8bfca5bb494a1f705463a3e744aee320b6054ab5b618035a6be25893c4863881ece9d85c32bd8252fa42c79446ac160903840d299c9a892fb3cff53a0afdbedaf29b0fe860e69e8e4c339febb2715c1b11afb56b1d33c690241add4ce85ca98b840a50e7af6a254e34ace5ce71e84dbbf2e3b70844a1dfeb57a67ee0e8c98fe77b95a32c1730186d504a9d415b5b7dd6410194650160970dd4ed0bb9da09e22690a873f7896be94fdbadb03fe2d5564e3fe8574e7ea2e037ec978fd6a8d60330906d73d8349063fb962eba3a52c89ad7c680284110e244535cf471ab06ab6aadd15acbb99720690d5a61f4db79692d6203542b2b7b47468edd3d363e6197ab2189d62002c6a0b5e1c8f1221bba17f8d04d9bd8bea58b175f2d305308b8e99a6e06fb323cfff23423c78adca33a19ce7a2d4fc5208e0157230844721e38acd493451be0efff78e533232323f944c764db3d366eeea1b3a703cb7258592c313b59647caa42a1d860f7b61e5e38d220d42ea7262b6cd9e87074b488089ceace326c7b88738eabb15ab77cc2484713e5e021d973fdb5227169c2b682cddb2eeb65cfde9d0c0e6d219dce8181c5a5091666e7397a68868953458220a1dc7010e5a24c9dae9c904a395c7dc3107b862f65cf2b2b64571beb409e3563e078b9f6ea5f168a7b6dadf577033fdcb4754b965b3e7805976edb85eb7a8880ef5770ac90dede1cd7dd3844b9e4333b5bc1b39a244913d78128b6b86a573f37de7c2df99e01169c4506fe36465b2d5a77ca6963cc84df98f8c3ece2433f9e9a6cda49a21fd04673d9ae01b66e19a62d954630945796989b1e2568fa28cba63d9b6278db06a6a72b88806db5f2984e3b5c71e5a57464f384f5267e5f9ad9abd3f4bdd660b06693d68218888c66298a1869d45f7ba1b8f4f5df2ccc3d0360c7498252167d7d79b26d391486f9a929e6a64e902421c640d3af61b0684b5988b4c65926e3525ef5696bf348bb596aa53a4a691af54556dc65662e0f391941679422ac861c1e2bf0f2a24fd5765f9aaeadfeb59a24bad5a189062d448146744ce097a8ae9ca6a7274347f700464369a54661b644d4f449b421dfd5c61d7b87f9c513afb58650ac71ec8454ba49366bd1d5b591e2e20ab6e3d0966f27ae864c2ecc515c005ba970e3e04653ae545a23426b6db456327a6292cb777793cbd80c6deec5b22d3010c7867cb78dc2e3d8e8184110d39bcfb07b7b2f29cfa15c69b25c5ca0bfd76089e03a366d29875c364d1c2744b1a65af229147c0c4e92683da6947aab319481fb0c7672fcc432c78fce103422c42848c0c4606243d088191f2f327a7291c4c0f5570eb27d6b0f5b2ee9a4520b38f2fa3485850a3a34985820169456a015955293c347e6289662105930c6bc343232f256515af97cfe20c2c7eaf56060b552030d9628746468d4230a8b358ebe31c73f0f4d323d576178a89bcf7ef2067aba32d8b6e2d0eb332c971a34fd0841504a11479a6a3560726a85570ecf70f0c83c7ee4c696b27f8af0ebe5e595e40c0101d8b163c7877512fd24092b97f6f6a419ecefa03de7014279b5c97c619595b24f5f4f96afdcbb973d575d02024110f3f8ef0ef3db3f1ec31843ff861cbd1bb2b4a51dc230a658aa333b57a1e65bb193ca3d29a2be343636367f6e5b0ac0ce9d9729adf56d24fe77c4346f4610cb528021490c8eadb87c471f77df791d57ef1e40c9d90e6ff8114f3e738227fe7c8cc252ad15564ba1b526d11a11a7ae49ff5cd9dec302b3274647b98000c0ae9d3bb9f3a3b75ce1a9eaafcae599dd353fc218e8db90e39addfd5cb5ab9f9463234a61dbad1f8e3186288c50965028d638f4af1946c78bac567d5229876ccad39df96d8f8d4e2cdf7ff0f058fdf839b9bf8000c081a7f7ab242c7fca93e91f6d1a743b3dcf4529858810853127474e03425f7f1ec775a856eb2c2d2cb3a1bf9bc14dbd6b934e932409a5528dc272f620eed05dca72dfbc75dfbdebccc5f394c3adfbeed5cae9f87da0fb7fb8b8143695806d2b94126cc7a2bd2b8beffb8c9f9c6474649cd9a9792c5b916bcfa09442590ac7510441c87229358133f03565b9131703bf200267ecf9a71e6937e1d2b73ad2c52f6cda94f11cc7c198960ea8d77caaab759238c14bb9b47766f13c973365b15aa9313567a62306bfac9cf6276fdd77af5e0fe38cd9eb7d14b15671367cbbe20b7a6ae9f3434399b4e7b960845c47865c47665d2f4aa51a33f33211b1f17eb1734fbd1bf845237036128f664db4fc6057a6f0d52d5b3b5da5d4fada50a0516f32fe663415cae0e7949d7df6bd80c345220067a4b906f10a512c31e0aefd87d658afc92ec0c89a4236ce2aca5e35c6bca7fbc699532eb0e79f7a4c99a47183242bf765bcd57d839778b9f6f3c2de423e7b82d69ac27cc52c16add3a1eefe99d89dfb453985772a40b84804e2b0768d63667f39b8516febce67c576ce2e7b5b06e4ec4b94a277a05dda3bc2adf3f30bdf5c5e0d7658dee01781da7f4c001ddcd8960986bb7bf2224ad01ab45c28c9cf9a016330086eda6343afb6cbabd5dbc0f4fd5704949d7eb5da681b1d7fb3b42393b12dd7b3b02d69c970a55a2ab7a5cf5b125db7d473146b023fa65a4dfc84fc010b597a27f08b12b09ccccb5a0dedaed46b779557fdc721b05b7d9e0009724e224ceb6a0228b4b111e9185556dbed96db362bf2eeb528c65ce4cef57fb27f037bd249327d42e1690000000049454e44ae426082</data> + </image> +</images> +<connections> + <connection> + <sender>ActionDismiss</sender> + <signal>clicked()</signal> + <receiver>KlamOnAccAlert</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>ActionQuarantine</sender> + <signal>clicked()</signal> + <receiver>KlamOnAccAlert</receiver> + <slot>accept()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>ktextbrowser.h</includehint> +</includehints> +</UI> diff --git a/src/klamonacc_config.ui b/src/klamonacc_config.ui new file mode 100644 index 0000000..97e9fe5 --- /dev/null +++ b/src/klamonacc_config.ui @@ -0,0 +1,253 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KlamOnAccConfig</class> +<widget class="TQWidget"> + <property name="name"> + <cstring>KlamOnAccConfig</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>712</width> + <height>647</height> + </rect> + </property> + <property name="caption"> + <string>Form1</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQGroupBox"> + <property name="name"> + <cstring>GroupScannerOpts</cstring> + </property> + <property name="title"> + <string>Scanner Settings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>kcfg_EnableOnAccess</cstring> + </property> + <property name="text"> + <string>Enable &On-Access Scanner</string> + </property> + <property name="accel"> + <string>Alt+O</string> + </property> + </widget> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>kcfg_ExtraScanning</cstring> + </property> + <property name="text"> + <string>Scan Files/Directories When They Are &Created or Moved</string> + </property> + <property name="accel"> + <string>Alt+C</string> + </property> + </widget> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>kcfg_ExcludeConfDir</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>E&xclude TDE Configuration Directory</string> + </property> + <property name="accel"> + <string>Alt+X</string> + </property> + </widget> + </vbox> + </widget> + <widget class="TQGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Limits</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLayoutWidget"> + <property name="name"> + <cstring>MaxFileHBox</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLabel"> + <property name="name"> + <cstring>MaxFileLabel</cstring> + </property> + <property name="text"> + <string>Max File Size:</string> + </property> + </widget> + <widget class="TQSpinBox"> + <property name="name"> + <cstring>kcfg_OnAccessMaxFile</cstring> + </property> + <property name="suffix"> + <string> M</string> + </property> + <property name="value"> + <number>5</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>MaxFileSpacer</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> + </widget> + <widget class="TQFrame"> + <property name="name"> + <cstring>GroupWatchDirs</cstring> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>WatchDirsSpacerLeft</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="TQPushButton"> + <property name="name"> + <cstring>SetUpWatchDirs</cstring> + </property> + <property name="text"> + <string>Set up &Directories to Watch</string> + </property> + <property name="accel"> + <string>Alt+D</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>WatchDirsSpacerRight</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="TQTextEdit"> + <property name="name"> + <cstring>textEdit1</cstring> + </property> + <property name="text"> + <string><html><head><meta name="qrichtext" content="1" /></head><body style="font-size:12pt;font-family:Arial"> +<p align="center"><span style="font-weight:600;text-decoration:underline;color:#ff0000">Warning!</span> This function is experimental. Use with caution.</p> +<p>The <span style="font-weight:600">On-Access Scanner</span> can scan files and directories as you open them, or even as you create them.</p> +<p>This function requires the <span style="font-style:italic">ClamAV Daemon</span> to be already running in the background and requires root permissions to start.</p> +</body></html> +</string> + </property> + <property name="wordWrap"> + <enum>WidgetWidth</enum> + </property> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>SetUpWatchDirs</sender> + <signal>clicked()</signal> + <receiver>KlamOnAccConfig</receiver> + <slot>reconfigurePaths()</slot> + </connection> + <connection> + <sender>kcfg_ExtraScanning</sender> + <signal>clicked()</signal> + <receiver>KlamOnAccConfig</receiver> + <slot>slotSettingsChanged()</slot> + </connection> + <connection> + <sender>kcfg_ExcludeConfDir</sender> + <signal>clicked()</signal> + <receiver>KlamOnAccConfig</receiver> + <slot>slotSettingsChanged()</slot> + </connection> + <connection> + <sender>kcfg_OnAccessMaxFile</sender> + <signal>valueChanged(const TQString&)</signal> + <receiver>KlamOnAccConfig</receiver> + <slot>slotSettingsChanged()</slot> + </connection> +</connections> +<includes> + <include location="local" impldecl="in implementation">klamonacc_config.ui.h</include> +</includes> +<variables> + <variable>bool restart;</variable> +</variables> +<signals> + <signal>directoriesModified()</signal> +</signals> +<slots> + <slot>reconfigurePaths()</slot> + <slot access="private">slotSettingsChanged()</slot> + <slot>slotSettingsApplied()</slot> +</slots> +<functions> + <function returnType="bool">needsRestart()</function> +</functions> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/klamonacc_config.ui.h b/src/klamonacc_config.ui.h new file mode 100644 index 0000000..7201e8d --- /dev/null +++ b/src/klamonacc_config.ui.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you want to add, delete, or rename functions or slots, use +** TQt Designer to update this file, preserving your code. +** +** You should not define a constructor or destructor in this file. +** Instead, write your code in functions called init() and destroy(). +** These will automatically be called by the form's constructor and +** destructor. +*****************************************************************************/ + +#include "directorylist.h" + +#include <kdialogbase.h> +#include <tdeconfig.h> +#include <tdeglobal.h> + +void KlamOnAccConfig::reconfigurePaths() { + // Borrowed from amaroK (collectionbrowser.cpp) + KDialogBase dialog( this, 0, false ); + // kapp->setTopWidget( &dialog ); + dialog.setCaption( "Configure Directories Watchlist" ); + + TDEConfig *config = TDEGlobal::config(); + config->setGroup("OnAccess"); + TQStringList dirs = config->readListEntry("Watchlist"); + + CollectionSetup *setup = new CollectionSetup( &dialog, true, false, dirs ); + dialog.setMainWidget( setup ); + dialog.showButtonApply( false ); + dialog.adjustSize(); + + // Make the dialog a bit bigger, default is too small to be useful + dialog.resize( dialog.width() + 50, dialog.height() + 150 ); + + if ( dialog.exec() != TQDialog::Rejected ) { + setup->writeConfig("OnAccess","Watchlist"); + } + + restart = true; +} + +void KlamOnAccConfig::slotSettingsChanged() { + restart = true; +} + +void KlamOnAccConfig::slotSettingsApplied() { + restart = false; +} + +bool KlamOnAccConfig::needsRestart() { + return restart; +} |