$field) { if ($field['fieldname'] === F_SCANFILEPATH) { $pkg['fields']['field'][$key]['description'] .= havp_fscan_html(); break; } } } } # ------------------------------------------------------------------------------ # validation # ------------------------------------------------------------------------------ function havp_validate_settings($post, &$input_errors) { $submit = isset($_GET['submit']) ? $_GET['submit'] : $_POST['submit']; # manual update AV database if ($submit === 'Update_AV') { havp_update_AV(); } # Scan file or dir elseif($submit === 'Start_scan') { if (file_exists($post[F_SCANFILEPATH])) start_antivirus_scanner($post[F_SCANFILEPATH]); else $input_errors[] = "File or path not exists '{$post[F_SCANFILEPATH]}'."; } else { # ifaces if (!isset($post[F_PROXYINTERFACE]) || empty($post[F_PROXYINTERFACE])) { $post[F_PROXYINTERFACE] = "lan"; } # port validate $prxport = trim($post[F_PROXYPORT]); if (!empty($prxport) && !is_port($prxport)) $input_errors[] = 'You must enter a valid port number in the \'Proxy port\' field'; # parent proxy validate $parent = trim($post[F_PARENT]); # max download size validate $maxval = trim($post[F_MAXDOWNLOADSIZE]); if (!empty($maxval) && !is_numericint($maxval)) # is_port - validate value $input_errors[] = 'You must enter a valid numeric value in \'Max download size\' field.'; # scan max file size validate $maxval = trim($post[F_SCANMAXSIZE]); if (!empty($maxval) && !is_numericint($maxval)) # is_port - validate value $input_errors[] = 'You must enter a valid numeric value in \'Scan max file size\' field.'; # whitelist validate $lst = str_replace(array(" ", ";"), "\n", $post[F_WHITELIST]); $lst = explode("\n", $lst); foreach ($lst as $dm) { $dm = trim($dm); if ($dm && check_bw_domain($dm) === false) $input_errors[] = "Invalid whitelist element '$dm'. Example: '*domain.com, domain.com/*path*'."; } # blacklist validate $lst = str_replace(array(" ", ";"), "\n", $post[F_BLACKLIST]); $lst = explode("\n", $lst); foreach ($lst as $dm) { $dm = trim($dm); if ($dm && check_bw_domain($dm) === false) $input_errors[] = "Invalid blacklist element '$dm'. Example: '*domain.com, domain.com/*path*'."; } } } # ------------------------------------------------------------------------------ # resync # ------------------------------------------------------------------------------ function havp_resync() { global $havp_config; havp_convert_pfxml_xml(); havp_check_system(); # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # whitelist and blacklist # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # also white-listed by default: $whitelist = havp_whitelist_def() . "\n" . str_replace(";", "\n", $havp_config[F_WHITELIST]); $blacklist = str_replace(";", "\n", $havp_config[F_BLACKLIST]); # fix: stupid havp parser - error on 0x0D: $whitelist = str_replace("\r", "", $whitelist); $blacklist = str_replace("\r", "", $blacklist); file_put_contents(HVDEF_HAVP_WHITELIST, $whitelist); file_put_contents(HVDEF_HAVP_BLACKLIST, $blacklist); # reconfigure clamd havp_reconfigure_clamd(); # config havp file_put_contents (HVDEF_HAVP_CONFIG, havp_config_havp()); havp_set_file_access(HVDEF_WORK_DIR, HVDEF_USER, '0755'); if ($havp_config[F_ENABLE] === 'true') { mwexec_bg(HVDEF_HAVP_STARTUP_SCRIPT . " restart"); log_error("Starting HAVP"); } else { mwexec_bg(HVDEF_HAVP_STARTUP_SCRIPT . " stop"); log_error("Stopping HAVP"); } # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # reconfigure squid havp_configure_squid(); # reconfigure AV parts havp_reconfigure_freshclam(); havp_reconfigure_cron(); # configure system filter for 2.xx if (pfsense_version_() !== '1') filter_configure(); } # ------------------------------------------------------------------------------ function havp_avset_resync() { havp_convert_pfxml_xml(); havp_check_system(); # reconfigure havp_reconfigure_clamd(); havp_reconfigure_freshclam(); havp_reconfigure_cron(); } # ============================================================================== # check system # ============================================================================== function havp_check_system() { global $havp_config; # check user group $grp = exec('pw group show ' . HVDEF_GROUP); if (strpos($grp, HVDEF_GROUP) !== 0) { exec('pw group add ' . HVDEF_GROUP); log_error("Antivirus: Group '" . HVDEF_GROUP . "' was added."); } $usr = exec('pw usershow -n ' . HVDEF_USER); if (strpos($usr, HVDEF_USER) !== 0) { exec('pw useradd ' . HVDEF_USER . ' -g ' . HVDEF_GROUP . ' -h - -s "/sbin/nologin" -d "/nonexistent" -c "havp daemon"'); log_error("Antivirus: User '" . HVDEF_USER . "' was added."); } # workdir permissions havp_set_file_access(HVDEF_WORK_DIR, HVDEF_USER, ''); # havp tempdir if (!file_exists(HVDEF_HAVPTEMP_DIR)) mwexec("mkdir -p " . HVDEF_HAVPTEMP_DIR); havp_set_file_access(HVDEF_HAVPTEMP_DIR, HVDEF_USER, ''); # clamav dbdir if (!file_exists(HVDEF_CLAM_DBDIR)) mwexec("mkdir -p " . HVDEF_CLAM_DBDIR); havp_set_file_access(HVDEF_CLAM_DBDIR, HVDEF_AVUSER, ''); # RAM tempdir if (!file_exists(HVDEF_RAMTEMP_DIR)) mwexec("mkdir -p " . HVDEF_RAMTEMP_DIR); havp_set_file_access(HVDEF_RAMTEMP_DIR, HVDEF_USER, ''); # template permissions if (!file_exists(HVDEF_TEMPLATES_EX)) mwexec("mkdir -p " . HVDEF_TEMPLATES_EX); havp_set_file_access(HVDEF_TEMPLATES, HVDEF_USER, ''); havp_set_file_access(HVDEF_TEMPLATES_EX, HVDEF_USER, ''); # havp log dir if (!file_exists(HVDEF_LOG_DIR)) mwexec("mkdir -p " . HVDEF_LOG_DIR); havp_set_file_access(HVDEF_LOG_DIR, HVDEF_USER, ''); # log files exists ? if (!file_exists(HVDEF_HAVP_ACCESSLOG)) file_put_contents(HVDEF_HAVP_ACCESSLOG, ''); if (!file_exists(HVDEF_HAVP_ERRORLOG)) file_put_contents(HVDEF_HAVP_ERRORLOG, ''); # log dir permissions havp_set_file_access(HVDEF_LOG_DIR, HVDEF_USER, '0764'); # pid file if (!file_exists(HVDEF_PID_FILE)) file_put_contents(HVDEF_PID_FILE, ''); havp_set_file_access(HVDEF_PID_FILE, HVDEF_USER, '0664'); # freshclam config permissions if (!file_exists(HVDEF_FRESHCLAM_CONF)) file_put_contents(HVDEF_FRESHCLAM_CONF, ''); havp_set_file_access(HVDEF_FRESHCLAM_CONF, HVDEF_AVUSER, '0664'); # clam log dir if (!file_exists(HVDEF_AVLOG_DIR)) mwexec("mkdir -p " . HVDEF_AVLOG_DIR); havp_set_file_access(HVDEF_AVLOG_DIR, HVDEF_USER, ''); # log files exists ? if (!file_exists(HVDEF_CLAM_LOG)) file_put_contents(HVDEF_CLAM_LOG, ''); if (!file_exists(HVDEF_FRESHCLAM_LOG)) file_put_contents(HVDEF_FRESHCLAM_LOG, ''); # log dir permissions # if (!file_exists(HVDEF_AVLOG_DIR)) # mwexec("mkdir -p " . HVDEF_AVLOG_DIR); havp_set_file_access(HVDEF_AVLOG_DIR, HVDEF_USER, '0777'); # =-= ClamAV =-= # catalog for Pid and Socket files # if (!file_exists(HVDEF_CLAM_RUNDIR)) # mwexec("mkdir -p " . HVDEF_CLAM_RUNDIR); # havp_set_file_access(HVDEF_CLAM_RUNDIR, HVDEF_USER, '0774'); # AV update script file_put_contents(HVDEF_AVUPD_SCRIPT, havp_AVupdate_script()); havp_set_file_access(HVDEF_AVUPD_SCRIPT, HVDEF_AVUSER, '0755'); # AV update notification script # file_put_contents(HVDEF_ON_AVUPD_SCRIPT, havp_on_avupd_script()); # havp_set_file_access(HVDEF_ON_AVUPD_SCRIPT, HVDEF_AVUSER, '0755'); # startup script's (havp and clamd) havp_startup_script(); hv_clamd_startup_script(); # havp filter script if (pfsense_version_() == '1') { # script exists only for 1.2.x file_put_contents(HVDEF_FILTER_RESYNC_SCRIPT, havp_filter_resync_script()); havp_set_file_access(HVDEF_FILTER_RESYNC_SCRIPT, HVDEF_AVUSER, '0755'); } else { # delete script if exists if (file_exists(HVDEF_FILTER_RESYNC_SCRIPT)) mwexec("rm -f " . HVDEF_FILTER_RESYNC_SCRIPT); } # mount RAMDisk mountRAMdisk(true); } # ============================================================================== # Reconfigure package parts # ============================================================================== function havp_reconfigure_clamd() { file_put_contents (HVDEF_CLAM_CONFIG, havp_config_clam()); havp_set_file_access(HVDEF_CLAM_CONFIG, HVDEF_USER, '0664'); } # ------------------------------------------------------------------------------ function havp_reconfigure_freshclam() { # config freshclam file_put_contents (HVDEF_FRESHCLAM_CONF, havp_config_freshclam()); havp_set_file_access(HVDEF_FRESHCLAM_CONF, HVDEF_USER, '0664'); } # ------------------------------------------------------------------------------ function havp_reconfigure_cron() { global $havp_config; # cron task $on = false; $optval = array("", "*/1", "*/2", "*/3", "*/4", "*/6", "*/8", "*/12", "0"); $opt = array("0", "*", "*", "*", "*", "root", "/usr/bin/nice -n20 " . HVDEF_AVUPD_SCRIPT); $opt[1] = $optval[$havp_config[F_HAVPUPDATE]]; $on = ($opt[1] !== ""); havp_setup_cron(HVDEF_AVUPD_SCRIPT, $opt, $on); } # ------------------------------------------------------------------------------ # Convert conf to XML # ------------------------------------------------------------------------------ function havp_convert_pfxml_xml() { global $config, $havp_config; $pfconf = $config['installedpackages'][HVFORM_HAVP]['config'][0]; # === GUI Fields === $havp_config[F_ENABLE] = ( $pfconf[F_ENABLE] === 'on' ? 'true' : 'false' ); # proxy $havp_config[F_PROXYMODE] = ( !empty($pfconf[F_PROXYMODE]) ? $pfconf[F_PROXYMODE] : 'standard' ); # ToDo: add check squid transparent $havp_config[F_PROXYINTERFACE] = $pfconf[F_PROXYINTERFACE]; $havp_config[F_PROXYPORT] = ( !empty($pfconf[F_PROXYPORT]) ? $pfconf[F_PROXYPORT] : HVDEF_PROXYPORT ); # ToDo: add check squid proxy port # parent proxy # [F_PARENTPROXY] = "proxy_ip:port" $pfconf[F_PARENTPROXY] = trim($pfconf[F_PARENTPROXY]); if (!empty($pfconf[F_PARENTPROXY])) { $parent = explode(":", trim($pfconf[F_PARENTPROXY])); $havp_config[F_PARENTPROXY] = array( 'ip' => $parent[0], 'port' => $parent[1] ); } else $havp_config[F_PARENTPROXY] = ''; # language $havp_config[F_LANGUAGE] = trim($pfconf[F_LANGUAGE]); # proxy settings $havp_config[F_ENABLEFORWARDEDIP] = ( $pfconf[F_ENABLEFORWARDEDIP] === 'on' ? 'true' : 'false' ); $havp_config[F_ENABLEXFORWARDEDFOR] = ( $pfconf[F_ENABLEXFORWARDEDFOR] === 'on' ? 'true' : 'false' ); $havp_config[F_MAXDOWNLOADSIZE] = ( is_numeric($pfconf[F_MAXDOWNLOADSIZE]) ? $pfconf[F_MAXDOWNLOADSIZE] : 0 ); $havp_config[F_RANGE] = ( $pfconf[F_RANGE] === 'on' ? 'true' : 'false' ); $havp_config[F_ENABLERAMDISK] = ( $pfconf[F_ENABLERAMDISK] === 'on' ? 'true' : 'false' ); # whitelist $havp_config[F_WHITELIST] = base64_decode($pfconf[F_WHITELIST]); $havp_config[F_WHITELIST] = str_replace(";", "\n", $havp_config[F_WHITELIST]); $havp_config[F_WHITELIST] = str_replace(";", " ", $havp_config[F_WHITELIST]); # blacklist $havp_config[F_BLACKLIST] = base64_decode($pfconf[F_BLACKLIST]); $havp_config[F_BLACKLIST] = str_replace(";", "\n", $havp_config[F_BLACKLIST]); $havp_config[F_BLACKLIST] = str_replace(";", " ", $havp_config[F_BLACKLIST]); # =-= Temp RAMDisk =-= # use RAMDisk if only capacity > calculated [MAXSCANSIZE * 50 connections] # =-= # before config manage Temp Dir = RAMDisk|Hard Disk $havp_config[HV_SCANTEMPFILE] = HVDEF_HAVPTEMP_DIR . HVDEF_SCANTEMPFILE; if ($havp_config[F_ENABLERAMDISK] === 'true') { $sys_capacity = get_memory(); $mem_capacity = intval($sys_capacity[0]) / 4; # [Mb] $calculated = 50 * $havp_config[F_SCANMAXSIZE] / (1024 * 1024); # [Mb] # this is restriction need for balancing between pfSense and HAVP work speed # we can not allocate memory at the expense of other services of the pfSense if ($mem_capacity > $calculated) { # re-define temp file to RAM Disk $havp_config[HV_SCANTEMPFILE] = HVDEF_RAMTEMP_DIR . HVDEF_SCANTEMPFILE; } else log_error("havp: RAMDisk not used. Diagnostic: system {$sys_capacity[0]}Mb, avialable {$mem_capacity}Mb, calculated {$calculated}Mb. Try reducing 'MAXSCANSIZE' value."); } # scanner $havp_config[F_FAILSCANERROR] = ( $pfconf[F_FAILSCANERROR] === 'on' ? 'true' : 'false' ); $havp_config[F_SCANMAXSIZE] = ( is_numeric($pfconf[F_SCANMAXSIZE]) ? $pfconf[F_SCANMAXSIZE] : HVDEF_MAXSCANSIZE ) * 1024; # KB -> Byte $havp_config[F_SCANIMG] = ( $pfconf[F_SCANIMG] === 'on' ? 'true' : 'false' ); $havp_config[F_SCANARC] = ( $pfconf[F_SCANARC] === 'on' ? 'true' : 'false' ); $havp_config[F_SCANSTREAM] = ( $pfconf[F_SCANSTREAM] === 'on' ? 'true' : 'false' ); $havp_config[F_SCANBROKENEXE] = ( $pfconf[F_SCANBROKENEXE] === 'on' ? 'true' : 'false' ); $havp_config[F_SCANARCMAXSIZE] = ( is_numeric($pfconf[F_SCANARCMAXSIZE]) ? $pfconf[F_SCANARCMAXSIZE] : HVDEF_MAXARCSCANSIZE ); # log $havp_config[F_SYSLOG] = ( $pfconf[F_SYSLOG] === 'on' ? 'true' : 'false' ); $havp_config[F_LOG] = ( $pfconf[F_LOG] === 'on' ? 'true' : 'false' ); # # =-= Internal variables =-= # proxy $havp_config[F_PROXYBINDIFACE] = 'localhost'; # language template files path $lng = $havp_config[F_LANGUAGE] ? $havp_config[F_LANGUAGE] : "en"; $havp_config[F_TEMPLATEPATH] = ( file_exists(HVDEF_TEMPLATES_EX . "/$lng") ? HVDEF_TEMPLATES_EX : HVDEF_TEMPLATES ); $havp_config[F_TEMPLATEPATH] .= "/$lng"; # # =-= HVFORM_AVSET =-= # av settings $pf_avset_conf = $config['installedpackages'][HVFORM_AVSET]['config'][0]; $havp_config[F_HAVPUPDATE] = $pf_avset_conf[F_HAVPUPDATE]; $havp_config[F_DBREGION] = $pf_avset_conf[F_DBREGION]; $havp_config[F_AVUPDATESERVER] = $pf_avset_conf[F_AVUPDATESERVER]; # avlog $havp_config[F_AVSETSYSLOG] = $pf_avset_conf[F_AVSETSYSLOG] === 'on' ? 'true' : 'false'; $havp_config[F_AVSETLOG] = $pf_avset_conf[F_AVSETLOG] === 'on' ? 'true' : 'false'; # # store havp config cache $cfg_xml = dump_xml_config($havp_config, 'havp'); file_put_contents(HVDEF_HAVP_XMLCONF, $cfg_xml); return $havp_config; } # ------------------------------------------------------------------------------ # config # ------------------------------------------------------------------------------ # HAVP config function havp_config_havp() { global $havp_config; $conf = array(); $conf[] = "# ============================================================ # HAVP config file # This file generated automaticly with HAVP configurator (part of pfSense) # (C)2008 Serg Dvoriancev # email: dv_serg@mail.ru # ============================================================ "; $conf[] = "USER " . HVDEF_USER; $conf[] = "GROUP " . HVDEF_GROUP; $conf[] = "DAEMON true"; $conf[] = "PIDFILE " . HVDEF_PID_FILE; $conf[] = "\n# For small home use, 8 should be minimum."; $conf[] = "# For 500 users corporate use, start at 40."; $conf[] = "SERVERNUMBER " . HVDEF_HAVP_MINSRV; $conf[] = "MAXSERVERS " . HVDEF_HAVP_MAXSRV; # log $conf[] = "\n# log "; $conf[] = "ACCESSLOG " . HVDEF_HAVP_ACCESSLOG; $conf[] = "ERRORLOG " . HVDEF_HAVP_ERRORLOG; # syslog $conf[] = "\n# syslog"; $conf[] = "USESYSLOG {$havp_config[F_SYSLOG]}"; $conf[] = "SYSLOGNAME havp"; $conf[] = "SYSLOGFACILITY daemon"; $conf[] = "SYSLOGLEVEL " . (HV_DEBUG === 'true' ? "debug" : "info"); # err | warning | info | debug # $conf[] = "\n# Level of HAVP logging\n# 0 = Only serious errors and information\n# 1 = Less interesting information is included"; $conf[] = "LOG_OKS false"; # false - access_log requests viruses only, true - access_log all requests $conf[] = "LOGLEVEL " . ( HV_DEBUG === 'true' ? "1" : "0" ); # 0 - work level, 1 - debug level # temp $conf[] = "\n# temp "; $conf[] = "SCANTEMPFILE " . $havp_config[HV_SCANTEMPFILE]; $conf[] = "TEMPDIR " . HVDEF_TEMP_DIR; # $conf[] = "\n#"; $conf[] = "DBRELOAD 180"; $conf[] = "TRANSPARENT " . ( $havp_config[F_PROXYMODE] === 'transparent' ? "true" : "false" ); # X-FORWARD, X-FORWARDED-FOR options $conf[] = "\n# if HAVP is used as parent proxy by some other proxy, this allows to write the real users IP to log, instead of proxy IP."; $conf[] = "FORWARDED_IP " . $havp_config[F_ENABLEFORWARDEDIP]; $conf[] = "X_FORWARDED_FOR " . $havp_config[F_ENABLEXFORWARDEDFOR]; # parent proxy = [proxy:port] if (!empty($havp_config[F_PARENTPROXY])) { $conf[] = "\n# parent proxy "; $conf[] = "PARENTPROXY {$havp_config[F_PARENTPROXY]['ip']}"; $conf[] = "PARENTPORT {$havp_config[F_PARENTPROXY]['port']}"; } # proxy listening on $conf[] = "\n# havp is listening on "; $conf[] = "PORT {$havp_config[F_PROXYPORT]}"; # bind to ip address $bind_iface = get_real_interface_address($havp_config[F_PROXYBINDIFACE]); $conf[] = "BIND_ADDRESS {$bind_iface[0]}"; # template files language $conf[] = "\n# Path to template files "; $conf[] = "TEMPLATEPATH {$havp_config[F_TEMPLATEPATH]}"; # $conf[] = "\n# whitelist and blacklist"; $conf[] = "WHITELISTFIRST true"; $conf[] = "WHITELIST " . HVDEF_HAVP_WHITELIST; $conf[] = "BLACKLIST " . HVDEF_HAVP_BLACKLIST; # failscanerror - pass/block files if scanner error $conf[] = "\n# block file if error scanning"; $conf[] = "FAILSCANERROR {$havp_config[F_FAILSCANERROR]}"; # $conf[] = "\n# scanner "; $conf[] = "SCANNERTIMEOUT 10"; # if ($havp_config[F_SCANSTREAM] === 'true') { # $conf[] = "\n# always allow range, if stream scan enabled"; $conf[] = "RANGE true"; $conf[] = "\n# stream scan enabled"; $conf[] = "STREAMUSERAGENT Player Winamp iTunes QuickTime Audio RMA/ MAD/ Foobar2000 XMMS"; $conf[] = "STREAMSCANSIZE 2000"; } else { # renew downloads ? $conf[] = "RANGE {$havp_config[F_RANGE]}"; $conf[] = "\n# stream scan disabled"; $conf[] = "STREAMSCANSIZE 0"; } # scan options $conf[] = "SCANIMAGES {$havp_config[F_SCANIMG]}"; $conf[] = "MAXSCANSIZE {$havp_config[F_SCANMAXSIZE]}"; # $conf[] = "KEEPBACKBUFFER 200000"; $conf[] = "KEEPBACKTIME 5"; # $conf[] = "# After Trickling Time (seconds), some bytes are sent to browser to keep the connection alive"; $conf[] = "TRICKLING 10"; $conf[] = "TRICKLINGBYTES 1"; # $conf[] = "# Downloads larger than MAXDOWNLOADSIZE will be blocked."; $conf[] = "MAXDOWNLOADSIZE {$havp_config[F_MAXDOWNLOADSIZE]}"; # $conf[] = "\n# ClamAV Library Scanner (libclamav) "; $conf[] = "ENABLECLAMLIB " . (HV_USE_CLAMD !== 'true' ? "true" : "false"); # use clamd, if configured if (HV_USE_CLAMD === 'true') { $conf[] = "\n# Clamd scanner (Clam daemon)"; $conf[] = "ENABLECLAMD true"; # clamd socket if (HV_CLAMD_TCPSOCKET === 'true') { $conf[] = "CLAMDSERVER 127.0.0.1"; $conf[] = "CLAMDPORT " . HVDEF_CLAM_TCPSOCKET; } else $conf[] = "CLAMDSOCKET " . HVDEF_CLAM_SOCKET; } $conf[] = ""; return implode("\n", $conf); } # ------------------------------------------------------------------------------ # Clamd config # ------------------------------------------------------------------------------ function havp_config_clam() { global $havp_config; $conf = array(); $conf[] = "# ============================================================================== # CLAMD config file # This file generated automaticly with HAVP configurator (part of pfSense) # (C)2008 Serg Dvoriancev # email: dv_serg@mail.ru # ============================================================================== "; $conf[] = "# log"; $conf[] = "LogFileUnlock yes"; $conf[] = "LogFileMaxSize 2M"; $conf[] = "LogTime yes"; $conf[] = "LogClean no"; $conf[] = "LogFacility LOG_LOCAL6"; $conf[] = "LogVerbose " . ( HV_DEBUG === "true" ? "yes" : "no" ); # Syslog $islog = $havp_config[F_AVSETLOG] === 'true'; $issyslog = $havp_config[F_AVSETSYSLOG] === 'true'; $conf[] = "LogSyslog " . ($islog && $issyslog ? 'yes' : 'no'); if ($islog && !$issyslog) $conf[] = "LogFile " . HVDEF_CLAM_LOG; # $conf[] = "\n# sysdirs"; $conf[] = "PidFile " . HVDEF_CLAM_PID; $conf[] = "TemporaryDirectory " . HVDEF_TEMP_DIR; $conf[] = "DatabaseDirectory /var/db/clamav"; # $conf[] = "\n# socket"; $conf[] = "LocalSocket " . HVDEF_CLAM_SOCKET; $conf[] = "FixStaleSocket yes"; # if (HV_CLAMD_TCPSOCKET === 'true') { $conf[] = "TCPAddr 127.0.0.1"; $conf[] = "TCPSocket " . HVDEF_CLAM_TCPSOCKET; } $conf[] = "MaxConnectionQueueLength 30"; # $conf[] = "\n# daemon"; $conf[] = "MaxThreads 100"; # $conf[] = "\n# scanner"; $conf[] = "MaxDirectoryRecursion 255"; $conf[] = "FollowDirectorySymlinks no"; # not need scan symbol links dirs $conf[] = "FollowFileSymlinks yes"; $conf[] = "# perform a database check.(sec) [3600 sec = 60 min]"; $conf[] = "SelfCheck 3600"; $conf[] = "# detect possibly unwanted applications."; $conf[] = "DetectPUA no"; # possible unwanted applications $conf[] = "AlgorithmicDetection yes"; $conf[] = "# executable"; if ($havp_config[F_SCANBROKENEXE] === 'true') {$conf[] = "DetectBrokenExecutables yes";} else {$conf[] = "DetectBrokenExecutables no";} # $conf[] = "ScanPE yes"; $conf[] = "ScanELF yes"; $conf[] = "# documents"; $conf[] = "ScanOLE2 yes"; $conf[] = "ScanPDF yes"; $conf[] = "# email"; $conf[] = "ScanMail yes"; $conf[] = "MailFollowURLs no"; $conf[] = "PhishingSignatures yes"; $conf[] = "PhishingScanURLs yes"; $conf[] = "PhishingAlwaysBlockSSLMismatch no"; $conf[] = "PhishingAlwaysBlockCloak no"; $conf[] = "# html"; $conf[] = "ScanHTML yes"; $conf[] = "# archives"; $conf[] = "ScanArchive yes"; # $conf[] = "ArchiveLimitMemoryUsage no"; # deprecated on 0.95 $conf[] = "ArchiveBlockEncrypted no"; $conf[] = "# limits"; $conf[] = "MaxScanSize 50M"; $conf[] = "MaxFileSize 30M"; $conf[] = "MaxRecursion 255"; $conf[] = "MaxFiles 10000"; # $conf[] = "\n# system"; $conf[] = "User root"; # . HVDEF_USER; # mast have full access to files for scan $conf[] = "AllowSupplementaryGroups yes"; $conf[] = "Debug " . (HV_DEBUG === 'true' ? "yes" : "no"); # $conf[] = ""; return implode("\n", $conf); } # ------------------------------------------------------------------------------ # FreshClamAV config # ------------------------------------------------------------------------------ function havp_config_freshclam() { global $havp_config; $pfconf = $havp_config; $conf = array(); $conf[] = "# ============================================================================== # freshclam(HAVP) config file # This file generated automaticly with HAVP configurator (part of pfSense) # (C)2008 Serg Dvoriancev # email: dv_serg@mail.ru # ============================================================================== "; $conf[] = "DatabaseDirectory /var/db/clamav"; # log $conf[] = "LogFileMaxSize 2M"; $conf[] = "LogTime yes"; $conf[] = "LogVerbose " . ( HV_DEBUG === "true" ? "yes" : "no" ); $conf[] = "LogFacility LOG_LOCAL6"; # LOG_LOCAL6 | LOG_MAIL $conf[] = "\n# syslog"; # Syslog $is_syslog = ($pfconf[F_AVSETLOG] === 'true') && ($pfconf[F_AVSETSYSLOG] === 'true'); $conf[] = "LogSyslog " . ( $is_syslog ? 'yes' : 'no'); unset ($is_syslog); # log # freshclam for 1.2.x have a bug with logfile permissions; now disable logfile for 1.2.x - only syslog $is_log = (pfsense_version_() != "1") && ($pfconf[F_AVSETLOG] === 'true'); if ($is_log) { $conf[] = "UpdateLogFile " . HVDEF_FRESHCLAM_LOG; } else { $conf[] = "# for pfsense 1.2.x Log disabled - permission bug exists!"; } unset ($is_log); $conf[] = "\n# pid"; $conf[] = "PidFile /var/run/clamav/freshclam.pid"; $conf[] = "\n# db"; $conf[] = "DatabaseOwner havp"; $conf[] = "AllowSupplementaryGroups yes"; $conf[] = "DNSDatabaseInfo current.cvd.clamav.net"; $avsrv = $pfconf[F_AVUPDATESERVER]; $avsrv = explode(" ", trim($avsrv)); foreach ($avsrv as $asr) if (!empty($asr)) $conf[] = "DatabaseMirror $asr"; # regional mirror if (!empty($pfconf[F_DBREGION])) { $conf[] = '# regional db'; switch($pfconf[F_DBREGION]) { case 'au': $conf[] = "DatabaseMirror clamav.mirror.ayudahosting.com.au"; break; # australia case 'ca': $conf[] = "DatabaseMirror clamav.mirror.rafal.ca"; break; # canada case 'cn': $conf[] = "DatabaseMirror 4most2.clamav.ialfa.net"; break; # china case 'eu': $conf[] = "DatabaseMirror clamav.edpnet.net"; break; # europe case 'id': $conf[] = "DatabaseMirror db.clamav.or.id"; break; # indonesia case 'jp': $conf[] = "DatabaseMirror clamavdb2.ml-club.jp"; break; # japan case 'kr': $conf[] = "DatabaseMirror clamav.hostway.co.kr"; break; # korea case 'ml': $conf[] = "DatabaseMirror clamav.doubleukay.com"; break; # malaysia case 'ru': $conf[] = "DatabaseMirror clamav.citrin.ru"; break; # russia case 'sa': $conf[] = "DatabaseMirror clamav.dial-up.net"; break; # south africa case 'tw': $conf[] = "DatabaseMirror clamav.cs.pu.edu.tw"; break; # taiwan case 'uk': $conf[] = "DatabaseMirror clamav.oucs.ox.ac.uk"; break; # united kingdom case 'us': $conf[] = "DatabaseMirror db.us.clamav.net "; break; # united states default: break; } } $conf[] = "DatabaseMirror db.at.clamav.net"; $conf[] = "DatabaseMirror db.au.clamav.net"; $conf[] = "DatabaseMirror db.ba.clamav.net"; $conf[] = "DatabaseMirror db.be.clamav.net"; $conf[] = "DatabaseMirror db.ca.clamav.net"; $conf[] = "DatabaseMirror db.ch.clamav.net"; $conf[] = "DatabaseMirror db.cn.clamav.net"; $conf[] = "DatabaseMirror db.cr.clamav.net"; $conf[] = "DatabaseMirror db.cy.clamav.net"; $conf[] = "DatabaseMirror db.cz.clamav.net"; $conf[] = "DatabaseMirror db.de.clamav.net"; $conf[] = "DatabaseMirror db.dk.clamav.net"; $conf[] = "DatabaseMirror db.ec.clamav.net"; $conf[] = "DatabaseMirror db.ee.clamav.net"; $conf[] = "DatabaseMirror db.es.clamav.net"; $conf[] = "DatabaseMirror db.fi.clamav.net"; $conf[] = "DatabaseMirror db.fr.clamav.net"; $conf[] = "DatabaseMirror db.gr.clamav.net"; $conf[] = "DatabaseMirror db.hk.clamav.net"; $conf[] = "DatabaseMirror db.hu.clamav.net"; $conf[] = "DatabaseMirror db.id.clamav.net"; $conf[] = "DatabaseMirror db.ie.clamav.net"; $conf[] = "DatabaseMirror db.it.clamav.net"; $conf[] = "DatabaseMirror db.jp.clamav.net"; $conf[] = "DatabaseMirror db.kr.clamav.net"; $conf[] = "DatabaseMirror db.li.clamav.net"; $conf[] = "DatabaseMirror db.lt.clamav.net"; $conf[] = "DatabaseMirror db.lv.clamav.net"; $conf[] = "DatabaseMirror db.mt.clamav.net"; $conf[] = "DatabaseMirror db.my.clamav.net"; $conf[] = "DatabaseMirror db.ml.clamav.net"; $conf[] = "DatabaseMirror db.no.clamav.net"; $conf[] = "DatabaseMirror db.pl.clamav.net"; $conf[] = "DatabaseMirror db.pt.clamav.net"; $conf[] = "DatabaseMirror db.ro.clamav.net"; $conf[] = "DatabaseMirror db.ru.clamav.net"; $conf[] = "DatabaseMirror db.se.clamav.net"; $conf[] = "DatabaseMirror db.sk.clamav.net"; $conf[] = "DatabaseMirror db.th.clamav.net"; $conf[] = "DatabaseMirror db.tr.clamav.net"; $conf[] = "DatabaseMirror db.tw.clamav.net"; $conf[] = "DatabaseMirror db.ua.clamav.net"; $conf[] = "DatabaseMirror db.uk.clamav.net"; $conf[] = "DatabaseMirror db.za.clamav.net"; $conf[] = "\n# DO NOT TOUCH the following line "; $conf[] = "DatabaseMirror database.clamav.net"; $conf[] = "\n# Number of database checks per day. Default: 12 (every two hours)"; $chks = 0; $conf[] = "Checks $chks"; $conf[] = "# notification"; $conf[] = "OnUpdateExecute date \"+%Y.%m.%d %H:%M:%S Antivirus update success\" > " . HVDEF_FRESHCLAM_STATUS_FILE; $conf[] = "OnErrorExecute date \"+%Y.%m.%d %H:%M:%S Antivirus update error\" > " . HVDEF_FRESHCLAM_STATUS_FILE; $conf[] = "Debug " . (HV_DEBUG === 'true' ? "yes" : "no"); # $conf[] = "# Proxy settings"; # future #HTTPProxyServer myproxy.com #HTTPProxyPort 1234 #HTTPProxyUsername myusername #HTTPProxyPassword mypass # MAKE GUI Errors display # Run command when database update process fails. # Default: disabled #OnErrorExecute command # Run command when freshclam reports outdated version. # In the command string %v will be replaced by the new version number. # Default: disabled #OnOutdatedExecute command # Enable debug messages in libclamav. # Default: disabled #Debug yes # use google safesearch AV database $conf[] = "SafeBrowsing yes"; $conf[] = ""; return implode("\n", $conf); } # ------------------------------------------------------------------------------ # configure squid function havp_configure_squid() { global $config, $havp_config; $new_opt = array(); $on_configure = ($havp_config[F_PROXYMODE] === 'squid' ? true : false); if (!isset($config['installedpackages']['squid']['config'][0]['custom_options'])) return; if ($on_configure === true) { $new_opt[] = "never_direct allow all"; $new_opt[] = "cache_peer 127.0.0.1 parent {$havp_config[F_PROXYPORT]} 0 name=havp no-query no-digest no-netdb-exchange default"; } # copy options, but not 'cache_peer' option $cust_opt = explode(";", $config['installedpackages']['squid']['config'][0]['custom_options']); foreach($cust_opt as $key => $val) { if (strpos($val, "never_direct") !== false) continue; if (strpos($val, "cache_peer 127.0.0.1 parent") !== false) continue; $new_opt[] = $val; } $new_opt = implode(";", $new_opt); if (/*is_package_installed('squid') && */file_exists('/usr/local/pkg/squid.inc')) { # squid config update $config['installedpackages']['squid']['config'][0]['custom_options'] = $new_opt; # disable upstream proxy if ($on_configure === true) $config['installedpackages']['squidupstream']['config'][0]['proxy_forwarding'] = ''; write_config('Update redirector options to squid config.'); require_once('squid.inc'); squid_resync(); } } # ------------------------------------------------------------------------------ function havp_whitelist_def() { $whitelist = array(); $whitelist[] = "*sourceforge.net/*clamav-*"; $whitelist[] = "*pfsense.com/*"; $whitelist[] = "*.microsoft.com/*"; $whitelist[] = "*.windowsupdate.com/*"; # M$ & M$ update # media and image extensions $whitelist[] = "*/*.gif\n*/*.swf\n*/*.png\n*/*.jpg\n*/*.jpeg\n*/*.mov\n*/*.avi\n*/*.flv\n*/*.bmp\n*/*.ico\n*/*.pdf\n*/*.mp3\n*/*.wma\n*/*.wmv\n*/*.ogg"; return implode("\n", $whitelist); } # ============================================================================== # Utils # ============================================================================== function havp_set_file_access($dir, $owner, $mod) { if ( file_exists($dir) ) { mwexec("chgrp -R -v $owner $dir"); mwexec("chown -R -v $owner $dir"); if (!empty($mod)) { mwexec( "chmod -R -v $mod $dir"); } } } # ------------------------------------------------------------------------------ # Src from squid.inc Copyright (C) 2006 Scott Ullrich, Fernando Lemos function get_real_interface_address($iface) { global $config; if ($iface === 'localhost') return array('127.0.0.1', ''); $iface = convert_friendly_interface_to_real_interface_name($iface); $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6")); list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line); return array($ip, long2ip(hexdec($netmask))); } #------------------------------------------------------------------------------- # *** check black/white list domain *** # Lines can hold URLs with wildcards with following rules: # Line must cointain Domain/Path # Domains can have a wildcard at begin. # Pages can hav a wildcard at begin and end. # URLs without wildcards are exact # Examples: # (1) www.server-side.de (Only this URL is whitelisted) # (2) www.server-side.de/* (Domain is completely whitelisted) # (3) *server-side.de/index.html # (4) */*.gif (All .gif are whitelisted) # (5) www.server-side.de/novirus* # (6) www.server-side.de/*novirus* #------------------------------------------------------------------------------- function check_bw_domain($_dm) { $domain = ""; $path = ""; if (!is_string($_dm)) return false; $pos = strpos($_dm, "/"); if ($pos === false) { $domain = $_dm; $path = ""; } else { $domain = substr($_dm, 0, $pos); $path = substr($_dm, $pos+1); } # Domains can have a wildcard at begin '*domain.xx' - *my.domain.com # Path can have a wildcard(*) at begin and end '*xxx*' # Regex: * - {0,}; + - {1,}; ? = {0,1} $df = "[a-zA-Z0-9\-]"; $dm_fmt = "^((\*)|(\*\.))?($df+\.)+$df{2,}$"; # d.com *d.com *.d.com $ph_fmt = "^((\*)|((\*)?([^\*]+)(\*)?))$"; # *path* if (empty($path)) { # d.com *d.com *.d.com return eregi($dm_fmt, $domain); } else { if (!empty($domain)) { return (($domain === '*') || eregi($dm_fmt, $domain)) && eregi($ph_fmt, $path); } } return false; } # ------------------------------------------------------------------------------ # cron # ------------------------------------------------------------------------------ # $options: [0]='minute', [1]='hour', [2]='mday', [3]='month', [4]='wday', [5]='who', [6]='command' # function havp_setup_cron($task_key, $options, $on_off) { global $config; $cron_item = array(); # $on_off = TRUE/FALSE - install/deinstall cron task: # prepare new cron item if (is_array($options)) { $cron_item['minute'] = $options[0]; $cron_item['hour'] = $options[1]; $cron_item['mday'] = $options[2]; $cron_item['month'] = $options[3]; $cron_item['wday'] = $options[4]; $cron_item['who'] = ($options[5]) ? $options[5] : 'nobody'; $cron_item['command'] = $options[6]; } # unset old cron task with $task_key if (!empty($task_key)) { $flag_cron_upd = false; # delete old cron task if exists if (is_array($config['cron']['item'])) { foreach($config['cron']['item'] as $key => $val) { if (strpos($config['cron']['item'][$key]['command'], $task_key) !== false) { unset($config['cron']['item'][$key]); $flag_cron_upd = true; break; } } } # set new cron task if (($on_off === true) and !empty($cron_item)) { $config['cron']['item'][] = $cron_item; $flag_cron_upd = true; } # write config and configure cron only if cron task modified if ($flag_cron_upd === true) { write_config("Installed cron task '$task_key' for 'havp' package"); configure_cron(); } } else { # ! error $name ! return; } } # ------------------------------------------------------------------------------ # filter rules # ------------------------------------------------------------------------------ function havp_generate_rules($type = 'filter') { # pfSense v.2.x - welcome ! # 'nat' 'filter' global $config, $havp_config; $rules = array(); # no rules if havp disabled if ($havp_config[F_ENABLE] !== 'true') { return ''; } $proxymode = $havp_config[F_PROXYMODE]; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # =-= HAVP always listen 127.0.0.1:port =-= # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Proxy mode: # Standard - Filter: Rdr ifaces:port => 127.0.0.1:port # Parent for Squid - Filter: No # Transparent - Filter: Rdr ifaces:port => 127.0.0.1:port; # Rdr Any Http => 127.0.0.1:port + Allow Http traffic via iface # If Squid transparent, then as Standard. # Internal - Filter: No # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $proxybindiface = 'lo0'; # 127.0.0.1 $ifaces = array_map('convert_friendly_interface_to_real_interface_name', explode(',', $havp_config[F_PROXYINTERFACE])); $proxyport = ( $havp_config[F_PROXYPORT] ? $havp_config[F_PROXYPORT] : HVDEF_PROXYPORT ); # squid already transparent $squid_transparent_proxy = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on'); if (($proxymode === 'transparent') && $squid_transparent_proxy) { $proxymode = 'standard'; log_error("Havp: Squid is already configured as transparent proxy. Use 'Standard' proxy mode."); } # nat if ($type == 'nat') { $rules[] = ""; $rules[] = "# havp proxy ifaces redirect"; foreach($ifaces as $iface) { switch($proxymode) { case 'transparent': # rdr any http => localhost:port $rules[] = "rdr on $iface proto tcp from any to !($iface) port 80 -> $proxybindiface port $proxyport"; case 'standard': case 'squid': # rdr iface:port => localhost:port $rules[] = "rdr on $iface proto tcp from any to ($iface) port $proxyport -> $proxybindiface port $proxyport"; break; # no more rdr case 'internal': default: break; } } $rules[] = ""; } # filter if ($type == 'filter' || $type == 'rule') { $rules[] = ""; $rules[] = "# havp proxy ifaces rules"; foreach($ifaces as $iface) { switch($proxymode) { case 'transparent': # pass http on iface $rules[] = "pass in quick on $iface proto tcp from any to !($iface) port 80 flags S/SA keep state"; break; # no more rules case 'standard': case 'squid': case 'internal': default: break; } } $rules[] = ""; } if ($type == 'pfearly') { } if ($type == 'pflate') { } # test # file_put_contents("/tmp/havp_".$type, "state: $proxymode\n" . implode("\n", $rules)); return implode("\n", $rules); } # ------------------------------------------------------------------------------ function havp_filter_update_3() { # for 1.x only if (pfsense_version_() != '1') return; $rules_file = '/tmp/rules.debug'; if (file_exists($rules_file)) { $newrules = array(); $rules = file_get_contents($rules_file); $rules = explode("\n", $rules); foreach($rules as $val) { $newrules[] = $val; # rdr if (trim($val) === "rdr-anchor \"miniupnpd\"") { $newrules[] = "# havp rdr"; $newrules[] = havp_generate_rules('nat'); $newrules[] = ""; } # rules elseif(trim($val) === "anchor \"miniupnpd\"") { $newrules[] = "# havp rules"; $newrules[] = havp_generate_rules('filter'); $newrules[] = ""; } $rules = implode("\n", $newrules); } file_put_contents($rules_file, $rules); mwexec("pfctl -f $rules_file"); } } # ------------------------------------------------------------------------------ function havp_update_AV() { # AV update script file_put_contents(HVDEF_AVUPD_SCRIPT, havp_AVupdate_script()); havp_set_file_access(HVDEF_AVUPD_SCRIPT, HVDEF_AVUSER, '0755'); mwexec_bg(HVDEF_AVUPD_SCRIPT); # run update background } # ============================================================================== # Scripts # ============================================================================== # AV update script function havp_AVupdate_script() { $f = HVDEF_UPD_STATUS_FILE; $u = HVDEF_FRESHCLAM_STATUS_FILE; return << $f date +"%Y.%m.%d %H:%M:%S Antivirus database already is updated." > $u /usr/local/bin/freshclam wait cat $u >> $f /usr/local/bin/sigtool --unpack-current daily.cvd /usr/local/bin/sigtool --unpack-current main.cvd wait date +"%Y.%m.%d %H:%M:%S Antivirus update end." >> $f EOD; } # ------------------------------------------------------------------------------ # HAVP service startup script function havp_startup_script() { global $havp_config; $pid = HVDEF_PID_FILE; $havpchk = "ps auxw | grep \"[h]avp -c\"|awk '{print $2}'"; $clamdchk = "ps auxw | grep \"[c]lamd -c\"|awk '{print $2}'"; # rc script $rc = array(); $rc['file'] = basename(HVDEF_HAVP_STARTUP_SCRIPT); $s[] = "\t# init"; $s[] = "\techo 'Starting ..' > " . HVDEF_HAVP_STATUS_FILE; $s[] = "\t# start"; $s[] = "\tif [ -z \"`{$havpchk}`\" ];then"; if (HV_USE_CLAMD === 'true') { $clampid_dir = HVDEF_CLAM_RUNDIR; $s[] = "\t\t# start clamd before (to be sure)"; $s[] = "\t\t" . HVDEF_CLAM_STARTUP_SCRIPT . " start"; $s[] = "\t\tsleep 2"; $s[] = ""; $s[] = "\t\t# if clamd started"; $s[] = "\t\tif [ -n \"`{$clamdchk}`\" ];then"; $s[] = "\t\t\t# Waiting CLAMD"; $s[] = "\t\t\techo -n \"Waiting CLAMD \""; $s[] = "\t\t\techo 'Waiting CLAMD' > " . HVDEF_HAVP_STATUS_FILE; $s[] = "\t\t\twhile [ \"`{$clamdchk}`\" != \"`/bin/cat {$clampid_dir}/clamd.pid`\" ];do"; $s[] = "\t\t\t\techo -n '.'"; $s[] = "\t\t\t\tsleep 1"; $s[] = "\t\t\tdone"; $s[] = "\t\t\techo"; $s[] = "\t\tfi"; $s[] = ""; } $s[] = "\t\t/usr/local/sbin/havp -c " . HVDEF_HAVP_CONFIG . " 2>/dev/null"; $s[] = "\t\twait"; $s[] = "\tfi"; $s[] = "\t# Status"; $s[] = "\tif [ -z \"`{$havpchk}`\" ];then"; $s[] = "\t\techo 'Stopped' > " . HVDEF_HAVP_STATUS_FILE; $s[] = "\telse"; $s[] = "\t\techo 'Started' > " . HVDEF_HAVP_STATUS_FILE; $s[] = "\tfi"; $s[] = ""; $rc['start'] = implode("\n", $s); unset($s); $s[] = "# stop"; $s[] = "\t killall havp 2>/dev/null"; $s[] = "\t sleep 2"; $s[] = "\t killall -9 havp 2>/dev/null"; $s[] = "\t wait"; $s[] = "\t echo 'Stopped' > " . HVDEF_HAVP_STATUS_FILE; $s[] = ""; $rc['stop'] = implode("\n", $s); unset($s); # we don't use start if package disabled if ($havp_config[F_ENABLE] !== 'true') { $rc['start'] = "\t echo 'Disabled' > " . HVDEF_HAVP_STATUS_FILE; } write_rcfile($rc); } # ------------------------------------------------------------------------------ # clamd service startup script function hv_clamd_startup_script() { global $havp_config; $pid = HVDEF_CLAM_PID; $clamdchk = "ps auxw | grep \"[c]lamd -c\"|awk '{print $2}'"; # rc script $rc = array(); $rc['file'] = basename(HVDEF_CLAM_STARTUP_SCRIPT); $s[] = "\t\techo 'Starting..' > " . HVDEF_CLAM_STATUS_FILE; $s[] = "# start"; $s[] = "\tif [ -z \"`{$clamdchk}`\" ];then"; $s[] = "\t\t/usr/local/sbin/clamd -c " . HVDEF_CLAM_CONFIG . " 2>/dev/null"; $s[] = "\t\twait"; $s[] = "\tfi"; $s[] = "\techo 'Started' > " . HVDEF_CLAM_STATUS_FILE; $s[] = ""; $rc['start'] = implode("\n", $s); unset($s); $s[] = "#stop"; $s[] = "\t killall clamd 2>/dev/null"; $s[] = "\t sleep 2"; $s[] = "\t killall -9 clamd 2>/dev/null"; $s[] = "\t wait"; $s[] = "\t\techo 'Stopped' > " . HVDEF_CLAM_STATUS_FILE; $s[] = ""; $rc['stop'] = implode("\n", $s); unset($s); write_rcfile($rc); } # ------------------------------------------------------------------------------ # HAVP filter resync script function havp_filter_resync_script() { return << EOD; } # ============================================================================== # RAM Disk # ============================================================================== function mountRAMdisk($free_and_mount = true) { global $havp_config; $mnt_point = HVDEF_RAMTEMP_DIR; $mnt_flag_file = "$mnt_point/.mnt"; # RAM Disk disabled if (HV_USE_TMPRAMDISK !== 'true') { umountRAMDisk(); return; } # RAM Disk on VM disabled if ((HV_VM_TMPRAMDISK !== 'true') && VMWare_detect()) { umountRAMDisk(); log_error("havp: RAMDisk on VM disabled."); return; } # free RAMDisk only if ($free_and_mount !== true) { umountRAMDisk(); return; } # =-= Temp RAMDisk =-= # note: use 1/4 of system memory capacity $ramdisk_capacity = get_memory(); $ramdisk_capacity = intval(intval($ramdisk_capacity[0]) / 4); # [Mb] # RAMDisk already exists? if (file_exists("/dev/md10")) return; # umount old RAMDisk # umountRAMDisk(); # create and mount a swap backed file system on /var/tmp/havp by /dev/md10: # SWAP # mwexec("mdconfig -a -t swap -s {$ramdisk_capacity}M -u 10"); # mwexec("newfs -U /dev/md10"); # mwexec("mount /dev/md10 $mnt_point"); # RAM - more quickly, used physical RAM mwexec("/sbin/mdmfs -s {$ramdisk_capacity}M md10 {$mnt_point}"); mwexec("chmod 1777 {$mnt_point}"); # create flag file file_put_contents($mnt_flag_file, "{$ramdisk_capacity}"); # syslog if (HV_DEBUG === 'true') log_error("havp: Create RAMDisk {$ramdisk_capacity}Mb."); } # ------------------------------------------------------------------------------ function umountRAMDisk() { global $havp_config; # detach and free all resources used by /dev/md10: mwexec("umount -f " . HVDEF_RAMTEMP_DIR); mwexec("mdconfig -d -u 10"); } # ============================================================================== # Utilites # ============================================================================== function VMWare_detect() { global $g; $fc = ''; if (file_exists("{$g['varlog_path']}/dmesg.boot") !== false) $fc = file_get_contents("{$g['varlog_path']}/dmesg.boot"); return (strpos($fc, " '2.0.Beta' $s = explode(".", $s); $ver = $s ? $s[0] : '1'; } return intval($ver); } # ------------------------------------------------------------------------------ function start_antivirus_scanner($filename) { $param = array(); # $param[] = "-v"; # verbose if (HV_DEBUG === 'true') $param[] = "--debug"; # debug option else $param[] = "--quiet"; # output only errors $param[] = "--stdout"; # Write to stdout instead of stderr # $param[] = "--no-summary"; # Disable summary at end of scanning $param[] = "-i"; # Only print infected files $param[] = "--tempdir=" . HVDEF_TEMP_DIR; # Create temporary files in DIRECTORY # $param[] = "-d FILE/DIR"; # Load virus database from FILE or load all .cvd and .db[2] files from DIR $param[] = "-l " . HVDEF_CLAMSCAN_LOG; # Save scan report to FILE $param[] = "-r"; # Scan subdirectories recursively $param[] = "--remove"; # Remove infected files. Be careful! $param[] = "--detect-broken"; # Try to detect broken executable files $param[] = "--max-filesize=10000000"; # Files larger than this will be skipped and assumed clean $param[] = "--max-scansize=5000000"; # The maximum amount of data to scan for each container file (*) $param[] = "--max-files=10000"; # The maximum number of files to scan for each container file (*) $param[] = "--max-recursion=255"; # Maximum archive recursion level for container file (*) $param[] = "--max-dir-recursion=255"; # Maximum directory recursion level $param = implode(" ", $param); if (HV_USE_CLAMD === 'true') $param = "clamdscan $param $filename"; # use clamd daemon (more quickly) else $param = "clamscan $param $filename"; # debug clamscan cmd if (HV_DEBUG === 'true') file_put_contents("/tmp/clamscan.cmd", $param); if (file_exists($filename)) { log_error("Antivirus: Starting file '$filename' scanner. Log file is '" . HVDEF_CLAMSCAN_LOG . "'. Wait 5-10 minutes."); # put to log scanning file $cont="Starting scan file {$filename}\n"; file_put_contents(HVDEF_CLAMSCAN_LOG, $cont); mwexec_bg("$param"); exec("date +\"%Y.%m.%d %H:%M:%S Starting scan file '$filename'.\" > " . HVDEF_CLAMSCAN_LOG); } else log_error("Antivirus: Can't starting file scanner. File '$filename' not exists."); } # ------------------------------------------------------------------------------ # HTML # ------------------------------------------------------------------------------ function havp_fscan_html() { global $g; $clamscan_log = HVDEF_CLAMSCAN_LOG; return <<  Squid cache path (scan your squid cache now).
 Common DB path.
 Temp path.

Press button for start antivirus scanner now. After 5-10 minutes look log file '{$clamscan_log}'.
(Diagnostics: Execute Shell command: 'cat {$clamscan_log}') EOD; } /* Future - in next time */ # blacklist, dns, down, error, invalid, maxsize, request, scanner, virus function havp_html_notification_page($type, $title, $notify, $message) { $class = ''; switch($type) { case 'blacklist': $class = 'notify-warn'; break; case 'dns': $class = 'notify-standart'; break; case 'down': $class = 'notify-standart'; break; case 'error': $class = 'notify-standart'; break; case 'invalid': $class = 'notify-standart'; break; case 'maxsize': $class = 'notify-warn'; break; case 'request': $class = 'notify-standart'; break; case 'scanner': $class = 'notify-warn'; break; case 'virus': $class = 'notify-danger'; break; } return << HTTP AntiVirus Proxy: $type
$title
HTTP AntiVirus Proxy: $type
$notify
$message
EOD; } # ============================================================================== # Status, widgets # ============================================================================== function havp_get_scan_log() { $s = ''; $clamscanlog = "/var/log/clamscan.log"; if (file_exists($clamscanlog)) { $s = file_get_contents("/var/log/clamscan.log"); } if (empty($s)) $s = "Not found."; return $s; } function havp_get_filescanlist() { $slist = array(); $slist[0]['descr'] = 'Squid cache path (scan you squid cache now).'; $slist[0]['path'] = '/var/squid'; $slist[1]['descr'] = 'Common DB path.'; $slist[1]['path'] = '/var/db'; $slist[2]['descr'] = 'Temp path.'; $slist[2]['path'] = '/tmp'; return $slist; } function havp_get_av_viruslog() { $s = array(); if (file_exists(HVDEF_HAVP_ACCESSLOG)) { $log = file_get_contents(HVDEF_HAVP_ACCESSLOG); $log = explode("\n", $log); $count = 0; foreach($log as $ln) { if (substr_count(strtolower($ln), "virus clam")) $s[] = $ln; } } return $s; } function havp_get_av_statistic() { $s = "Unknown."; if (file_exists(HVDEF_HAVP_ACCESSLOG)) { $log = file_get_contents(HVDEF_HAVP_ACCESSLOG); $count = substr_count(strtolower($log), "virus clam"); $s = "Found $count viruses (total)."; } return $s; } # ------------------------------------------------------------------------------ # Fix # ------------------------------------------------------------------------------ function havp_fix() { # remove old named scripts # now must exists 'havp.sh'/'clamd' mwexec(HVDEF_SCRIPT_DIR . "/havp"); mwexec(HVDEF_SCRIPT_DIR . "/clamd.sh"); } ?>