diff options
Diffstat (limited to 'config/squidGuard/squidguard_configurator.inc')
-rw-r--r-- | config/squidGuard/squidguard_configurator.inc | 2106 |
1 files changed, 2106 insertions, 0 deletions
diff --git a/config/squidGuard/squidguard_configurator.inc b/config/squidGuard/squidguard_configurator.inc new file mode 100644 index 00000000..f683a19c --- /dev/null +++ b/config/squidGuard/squidguard_configurator.inc @@ -0,0 +1,2106 @@ +<?php +# ------------------------------------------------------------------------------ +/* squidguard_configurator.inc + (C)2006-2008 Serg Dvoriancev + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +# ------------------------------------------------------------------------------ +# SquidGuard Configurator +# email: dv_serg@mail.ru +# ------------------------------------------------------------------------------ +# squidGuard inline options: +# squidGuard -C all - update database +# squidGuard -c <configfile> - create squidGuard with specified config file +# ------------------------------------------------------------------------------ +# Notes: +# for work squidGuard need present ALL destinations; +# if dest not present in config - then this item will ignored in operations +# (in rebuild DB for example) +# ------------------------------------------------------------------------------ +# Directories: +# work path - $workdir +# log path - $workdir + $logdir +# ------------------------------------------------------------------------------ + +require_once('globals.inc'); +require_once('config.inc'); +require_once('util.inc'); +require_once('pfsense-utils.inc'); +require_once('pkg-utils.inc'); +require_once('filter.inc'); +require_once('service-utils.inc'); +require_once('squid.inc'); + +/* Allow additional execution time 0 = no limit. */ +ini_set('max_execution_time', '3600'); +ini_set('max_input_time', '3600'); +ini_set('memory_limit', '32M'); + +# ------------------------------------------------------------------------------ +# files header +# ------------------------------------------------------------------------------ +define('FILES_DB_HEADER', ' +# ------------------------------------------------------------------------------ +# File created by squidGuard package GUI +# (C)2006-2008 Serg Dvoriancev +# ------------------------------------------------------------------------------ +'); + +define('CONFIG_SG_HEADER', " +# ============================================================ +# SquidGuard configuration file +# This file generated automaticly with SquidGuard configurator +# (C)2006 Serg Dvoriancev +# email: dv_serg@mail.ru +# ============================================================ +"); + +define('ACL_WARNING_ABSENSE_PASS', "!WARNING! Absence PASS 'all' or 'none' added as 'none'"); + +# ------------------------------------------------------------------------------ +# squid config options +# ------------------------------------------------------------------------------ +define('REDIRECTOR_OPTIONS_REM', '# squidGuard options'); +define('REDIRECTOR_PROGRAM_OPT', 'redirect_program'); +define('REDIRECT_BYPASS_OPT', 'redirector_bypass'); +define('REDIRECT_CHILDREN_OPT', 'redirect_children'); + +# ------------------------------------------------------------------------------ +# setup count redirector processes will started +# * for big count users service increase this option, but you need use this on powerful system +# ------------------------------------------------------------------------------ +define('REDIRECTOR_PROCESS_COUNT', '3'); + +# ------------------------------------------------------------------------------ +# squidguard config options +# ------------------------------------------------------------------------------ +# define default redirection url (redirector get this url for all blocked url's) +# * !ATTENTION! this url must be exists; IF url not exist, redirector will't block +# (returned to squid some url, what blocked) +# ------------------------------------------------------------------------------ +define('REDIRECT_BASE_URL', '/sgerror.php'); +define('REDIRECT_URL_ARGS', '&a=%a&n=%n&i=%i&s=%s&t=%t&u=%u'); + +# ------------------------------------------------------------------------------ +# squidguard system defines +# ------------------------------------------------------------------------------ +define('SQUID_CONFIGFILE', '/usr/local/etc/squid/squid.conf'); +define('TMP_DIR', '/var/tmp'); + +define('SQUIDGUARD_CONFIGFILE', '/squidGuard.conf'); +define('SQUIDGUARDCONF_LOGFILE', '/sg_configurator.log'); +define('SQUIDGUARD_ACCESSBLOCK_FILE', 'block.log'); +define('SQUIDGUARD_CONFBASE_DEF', '/usr/local/etc/squid'); +define('SQUIDGUARD_LOGDIR_DEF', '/tmp'); +define('SQUIDGUARD_WORKDIR_DEF', '/usr/local/etc/squidGuard'); +define('SQUIDGUARD_BINPATH_DEF', '/usr/local/bin'); +define('SQUIDGUARD_TMP', '/var/tmp/squidGuard'); # SG temp +define('SQUIDGUARD_VAR', '/var/squidGuard'); # SG variables +define('SQUIDGUARD_STATE', '/squidGuard.state'); +define('SQUIDGUARD_REBUILD', '/squidGuard.rebuild'); + +# DB home catalog contains 'Blacklist' and 'User' sub-catalogs +define('SQUIDGUARD_DBHOME_DEF', '/var/db/squidGuard'); +define('SQUIDGUARD_DB_BLACKLIST', '/bl'); +define('SQUIDGUARD_DB_USER', '/usr'); +define('SQUIDGUARD_BL_UNPACK', '/unpack'); +define('SQUIDGUARD_BL_DB', '/db'); + +# DB/Blacklist defines +define('SQUIDGUARD_BLK_ENTRIES', '/blacklist.files'); +define('BLACKLIST_ARCHIVE', '/blacklists.tar'); +define('BLK_LOCALFILE', '/tmp/sg_blacklists.tar'); +define('DB_REBUILD_SH', '/tmp/squidGuard_db_rebuild.sh'); +define('DB_REBUILD_CONF', '/tmp/squidGuard_db_rebuild.conf'); +define('DB_REBUILD_BLK_CONF', '/squidGuard_blk_rebuild.conf'); +define('BLK_TEMP', '/tmp/sg_blk'); +define('SG_BLK_ARC', '/arcdb'); # blk db archive +define('SG_INFO_FILE', '/var/squidGuard/sg_db_upd.inf'); + +# error_res +define('SG_ERR0', "Error! Check squidGuard configuration data."); + +# redirect mode +define('RMOD_NONE', 'rmod_none'); +define('RMOD_INT_ERRORPAGE', 'rmod_int'); +define('RMOD_INT_BLANKPAGE', 'rmod_int_bpg'); +define('RMOD_INT_BLANKIMG', 'rmod_int_bim'); +define('RMOD_INT_SIZELIMIT', 'rmod_int_szl'); +define('RMOD_EXT_ERR', 'rmod_ext_err'); +define('RMOD_EXT_RDR', 'rmod_ext_rdr'); +define('RMOD_EXT_MOVED', 'rmod_ext_mov'); +define('RMOD_EXT_FOUND', 'rmod_ext_fnd'); + +# GUI options +define('SQUIDGUARD_LOG_MAXCOUNT', 500); # max log lines + +# 0-all, 1-medium; 2-low +define('SQUIDGUARD_LOG_LEVEL', 0); + +# +define('FLT_DEFAULT_ALL', 'all'); +define('FLT_NOTALLOWIP', '!in-addr'); + +# owner user name (squid system user - need for define rights access) +define('OWNER_NAME', 'proxy'); + +# Debug +define('DEBUG_ON', 'true'); + +# ============================================================================== +# black list +# ============================================================================== +# known black list standard names +# ------------------------------------------------------------------------------ +define('FLT_AD', 'ads'); +define('FLT_AGGRESSIVE', 'aggressive'); +define('FLT_AUDIOVIDEO', 'audio-video'); +define('FLT_DRUGGS', 'druggs'); +define('FLT_GAMBLING', 'gambling'); +define('FLT_HACKING', 'hacking'); +define('FLT_MAIL', 'mail'); +define('FLT_PORN', 'porn'); +define('FLT_PROXY', 'proxy'); +define('FLT_VIOLENCE', 'viol'); +define('FLT_WAREZ', 'warez'); + +# ============================================================================== +# SquidGuard Configurator +# ============================================================================== +$squidguard_config = array(); # squidGuard config array + +# call default init +sg_init(); + +# ------------------------------------------------------------------------------ +# squidguard system fields +# ------------------------------------------------------------------------------ +define('F_SQUIDGUARD', 'squidGuard'); +define('F_LOGDIR', 'logdir'); +define('F_DBHOME', 'dbhome'); +define('F_WORKDIR', 'workdir'); +define('F_BINPATH', 'binpath'); +define('F_PROCCESSCOUNT', 'process_count'); +define('F_SQUIDCONFIGFILE', 'squid_configfile'); +define('F_ENABLED', 'enabled'); +define('F_BLACKLISTENABLED', 'blacklist_enabled'); +define('F_SGCONF_XML', 'sgxml_file'); + +# other fields +define('F_ITEM', 'item'); +define('F_TIMES', 'times'); +define('F_SOURCES', 'sources'); +define('F_DESTINATIONS', 'destinations'); +define('F_REWRITES', 'rewrites'); +define('F_ACLS', 'acls'); +define('F_DEFAULT', 'default'); +define('F_NAME', 'name'); +define('F_DESCRIPTION', 'description'); +define('F_IP', 'ip'); +define('F_URLS', 'urls'); +define('F_DOMAINS', 'domains'); +define('F_EXPRESSIONS', 'expressions'); +define('F_REDIRECT', 'redirect'); +define('F_TARGETURL', 'targeturl'); +define('F_REPLACETO', 'replaceto'); +define('F_LOG', 'log'); +define('F_ITEM', 'item'); +define('F_DISABLED', 'disabled'); +define('F_TIMENAME', 'timename'); +define('F_DESTINATIONNAME', 'destname'); +define('F_REDIRECT', 'redirect'); +define('F_REWRITE', 'rewrite'); +define('F_MODE', 'mode'); +define('F_REWRITENAME', 'rewritename'); +define('F_OVERDESTINATIONNAME', 'overdestname'); +define('F_OVERREDIRECT', 'overredirect'); +define('F_OVERREWRITE', 'overrewrite'); +define('F_OVERREWRITENAME', 'overrewritename'); +define('F_TIMETYPE', 'timetype'); +define('F_TIMEDAYS', 'timedays'); +define('F_DATRANGE', 'daterange'); +define('F_TIMERANGE', 'sg_timerange'); +define('F_RMOD', 'redirect_mode'); # [redirect_mode] = rmod_int <base- use sgerror.php>; rmod_301; rmod_302; +define('F_NOTALLOWINGIP', 'notallowingip'); # not allowing ip in URL +define('F_USERNAME', 'username'); +define('F_ORDER', 'order'); + +# transparent mode +define('F_SQUID_TRANSPARENT_MODE', 'squid_transparent_mode'); +define('F_CURRENT_LAN_IP', 'current_lan_ip'); +define('F_CURRENT_GUI_PORT', 'current_gui_port'); +define('F_CURRENT_GUI_PROTO', 'current_gui_protocol'); + +# ------------------------------------------------------------------------------ +# sg_init - initialize config array +# ------------------------------------------------------------------------------ +function sg_init($init = '') +{ + global $squidguard_config; + + $squidguard_config = array(); + if(empty($init) or !is_array($init) ) { + # default init (for generate minimal config) + $squidguard_config[F_LOGDIR] = SQUIDGUARD_LOGDIR_DEF; + $squidguard_config[F_DBHOME] = SQUIDGUARD_DBHOME_DEF; + $squidguard_config[F_WORKDIR] = SQUIDGUARD_WORKDIR_DEF; + $squidguard_config[F_BINPATH] = SQUIDGUARD_BINPATH_DEF; + $squidguard_config[F_SQUIDCONFIGFILE] = SQUID_CONFIGFILE; + $squidguard_config[F_PROCCESSCOUNT] = REDIRECTOR_PROCESS_COUNT; + } else { + $squidguard_config = $init; + } + + return $squidguard_config; +} + +# ------------------------------------------------------------------------------ +# sg_loadconfig_xml +# ------------------------------------------------------------------------------ +function sg_load_configxml($filename) +{ + global $squidguard_config; + + sg_init(); + if (file_exists($filename)) { + $xmlconf = file_get_contents($filename); + + if (!empty($xmlconf)) { + $squidguard_config = $xmlconf[F_SQUIDGUARD]; + sg_addlog("sg_load_configxml: Success update from '$filename'.", 1); + } else + sg_addlog("sg_load_configxml: Error, file '$filename' is empty.", 2); + } else + sg_addlog("sg_load_configxml: Error, file '$filename' does not exists.", 2); +} + +# ------------------------------------------------------------------------------ +# sg_saveconfig_xml +# ------------------------------------------------------------------------------ +function sg_save_configxml($filename) +{ + global $squidguard_config; + + file_put_contents($filename, dump_xml_config($squidguard_config, F_SQUIDGUARD)); +} + +# ------------------------------------------------------------------------------ +# sg_reconfigure - squidguard reconfiguration +# ------------------------------------------------------------------------------ +function sg_reconfigure() +{ + global $squidguard_config; + $conf_file = SQUIDGUARD_LOGDIR_DEF . SQUIDGUARD_CONFIGFILE; + + # 1. check system + sg_check_system(); + + # 2. reconfigure user db + sg_reconfigure_user_db(); + + # 3. generate squidGuard config + $conf = sg_create_config(); + if ($conf) { + if ($squidguard_config[F_WORKDIR]) + $conf_file = $squidguard_config[F_WORKDIR] . SQUIDGUARD_CONFIGFILE; + file_put_contents($conf_file, $conf); + file_put_contents('/usr/local/etc/squid' . SQUIDGUARD_CONFIGFILE, $conf); # << squidGuard want config '/usr/local/etc/squid' by default + set_file_access($squidguard_config[F_WORKDIR], OWNER_NAME, 0755); + sg_addlog("sg_reconfigure: save squidGuard config to '$conf_file'.", 1); + } else + sg_addlog("sg_reconfigure: error make squidGuard config.", 2); + + # 4. reconfigure squid + squid_reconfigure(); +} + +# ------------------------------------------------------------------------------ +# squid_reconfigure +# Insert in '/usr/local/squid/etc/squid.conf' options: +# redirector_bypass on +# redirect_program /usr/local/squidGuard/bin/squidGuard -c /path_to_config_file +# redirect_children 1 +# ------------------------------------------------------------------------------ + +function squid_reconfigure($remove_only = '') +{ + global $config; + global $squidguard_config; + $conf = ''; + $cust_opt = $config['installedpackages']['squid']['config'][0]['custom_options']; + + # remove old options + if (!empty($cust_opt)) { + $conf = explode(";", $cust_opt); + foreach ($conf as $key => $c_opt) { + $t_opt = ltrim($c_opt); + if ((strpos($t_opt, REDIRECTOR_PROGRAM_OPT) === 0) or + (strpos($t_opt, REDIRECT_BYPASS_OPT) === 0) or + (strpos($t_opt, REDIRECT_CHILDREN_OPT) === 0)) + unset($conf[$key]); + } + sg_addlog("squid_reconfigure: Remove old redirector options from Squid config.", 1); + } + + # add new options - if squidGuard enabled + if (empty($remove_only) && ($squidguard_config[F_ENABLED] === 'on')) { + $redirector_path = $squidguard_config[F_BINPATH] . '/squidGuard'; + $redirector_conf = $squidguard_config[F_WORKDIR] . SQUIDGUARD_CONFIGFILE; + + $conf[] = REDIRECTOR_PROGRAM_OPT . " $redirector_path -c $redirector_conf"; + $conf[] = REDIRECT_BYPASS_OPT . " on"; + $conf[] = REDIRECT_CHILDREN_OPT . " " . REDIRECTOR_PROCESS_COUNT; + + sg_addlog("squid_reconfigure: Add new redirector options to Squid config.", 1); + } + + # update config + if (is_array($conf)) $conf = implode(";", $conf); + + $config['installedpackages']['squid']['config'][0]['custom_options'] = $conf; + write_config('Update redirector options to squid config.'); + + squid_resync(); +} + +# ------------------------------------------------------------------------------ +# sg_check_system - check squidguard catalog's and access right's +# ------------------------------------------------------------------------------ +function sg_check_system() +{ + global $squidguard_config; + + # check work_dir & create if not exists + $work_dir = $squidguard_config[F_WORKDIR]; + if (!empty($work_dir)) { + # check dir's + if (!file_exists($work_dir)) { + mwexec("mkdir -p $work_dir"); + set_file_access($work_dir, OWNER_NAME, 0755); + sg_addlog("sg_check_system: Create work dir '$work_dir'.", 1); + } + } + unset($work_dir); + + # check log_dir & create if not exists + $log_dir = $squidguard_config[F_LOGDIR]; + if (!empty($log_dir)) { + if (!file_exists($log_dir)) { + mwexec("mkdir -p $log_dir"); + sg_addlog("sg_check_system: Create log dir '$log_dir'.", 1); + } + # set access right - need start any time; + # (SG possible start from console and log file will have only root access) + set_file_access($log_dir, OWNER_NAME, 0755); + } + unset($log_dir); + + # check db dir + $db_dir = $squidguard_config[F_DBHOME]; + if (!empty($db_dir)) { + if (!file_exists($db_dir)) { + mwexec("mkdir -p $db_dir"); + sg_addlog("sg_check_system: Create db dir '$db_dir'.", 1); + } + # set access right + set_file_access($db_dir, OWNER_NAME, 0755); + } + unset($db_dir); +} +# ============================================================================== +# squidGuard DB +# ============================================================================== +# sg_reconfigure_user_db - reconfigure(update) db user entries +# ------------------------------------------------------------------------------ +function sg_reconfigure_user_db() +{ + global $squidguard_config; + $dbhome = $squidguard_config[F_DBHOME]; + + sg_addlog("sg_reconfigure_user_db: Begin with '$dbhome'", 1); + + # create user DB catalog, if not extsts + if (!file_exists($dbhome)) { + if (!mkdir($dbhome, 0755)) { + sg_addlog("sg_reconfigure_user_db: Error create user DB directory '$dbhome'.", 2); + return; + } + set_file_access($dbhome, OWNER_NAME, 0755); + sg_addlog("sg_reconfigure_user_db: Create user DB directory '$dbhome'.", 1); + } + + # update destinations to db + $dests = $squidguard_config[F_DESTINATIONS]; + if(!empty($dests)){ + $dst_names = Array(); + $dst_list = Array(); + + sg_addlog("sg_reconfigure_user_db: Add user entries", 1); + foreach($dests[F_ITEM] as $dst) { + $path = "$dbhome/" . $dst[F_NAME]; + $dst_names[] = $path; + $dst_list["usr_{$dst[F_NAME]}"] = $dst[F_NAME]; + + # 1. check destination catalog and create them, if need + if (!file_exists($path)) { + if (!mkdir ($path, 0755)) { + sg_addlog("sg_reconfigure_user_db: Error create dir '$path'.", 2); + return; + } + sg_addlog("sg_reconfigure_user_db: Create dir '$path'.", 1); + } + + # 2. build domains file + $domains = $dst[F_DOMAINS]; + if (!empty($domains)) { + $content = trim(str_replace(" ", "\n", $domains)); + file_put_contents($path . '/domains', $content); + sg_addlog("sg_reconfigure_user_db: -- add {$dst[F_NAME]} domains '$domains';", 1); + } + unset($domains); + + # 3. build urls file + $urls = $dst[F_URLS]; + if (!empty($urls)) { + $content = trim(str_replace(" ", "\n", $urls)); + file_put_contents($path . '/urls', $content); + sg_addlog("sg_reconfigure_user_db: -- add {$dst[F_NAME]} urls '$content';", 1); + } + unset($urls); + + # 4. build expression file + $expr = $dst[F_EXPRESSIONS]; + if (!empty($expr)) { + $content = trim(str_replace("|", " ", $expr)); # delete first and last unnecessary '|' symbol + $content = str_replace(" ", "|", $content); + file_put_contents($path . '/expressions', $content); + sg_addlog("sg_reconfigure_user_db: -- add {$dst[F_NAME]} expressions '$content';", 1); + } + unset($expr); + } + + # 5. recursive set files access + set_file_access($dbhome, OWNER_NAME, 0755); + + # 6. rebuild user db ('/var/db/squidGuard') + sg_rebuild_db("_usrdb", $dbhome, $dst_list); + } else + sg_addlog("sg_reconfigure_user_db: Nothing. User destinations list empty.", 2); + + # 7. remove unused db entries + sg_remove_unused_db_entries(); +} + +# ------------------------------------------------------------------------------ +# sg_remove_unused_db_entries +# ------------------------------------------------------------------------------ +function sg_remove_unused_db_entries() +{ + global $squidguard_config; + $db_entries = array(); + $file_list = ''; + $dbhome = $squidguard_config[F_DBHOME]; + $workdir = $squidguard_config[F_WORKDIR]; + + # black list entries + # * worked only with 'blacklist entries list file - else may be deleted black list entry + if (file_exists($workdir . SQUIDGUARD_BLK_ENTRIES)) { + $file_for_del = array(); + + # load blk entries + $db_entries = explode("\n", file_get_contents($workdir . SQUIDGUARD_BLK_ENTRIES)); + + # $db_entries + add user entries + $dests = $squidguard_config[F_DESTINATIONS]; + if (!empty($dests)) { + foreach($dests[F_ITEM] as $dst) + $db_entries[] = $dst[F_NAME]; + } + + # diff between file list and entries list + $file_list = scan_dir($dbhome); + if (is_array($file_list) and is_array($db_entries)) { + $file_for_del = array_diff($file_list, $db_entries); + } + + # delete + if (is_array($file_for_del) and !empty($file_for_del)) { + foreach($file_for_del as $fd) { + $file_fd = "$dbhome/$fd"; + if (!empty($fd) && ($fd != ".") && ($fd != "..")) { + if (file_exists($file_fd)) { + mwexec("rm -R $file_fd"); + sg_addlog("sg_remove_unused_db_entries: Removed file '$file_fd'.", 1); + } else + sg_addlog("sg_remove_unused_db_entries: File'$file_fd' not found.", 2); + } + } + } + } +} +# ------------------------------------------------------------------------------ +# sg_rebuild_db Rebuild squidGuard DB from list items +# ------------------------------------------------------------------------------ +# $shtag - rebuild SH script TAG +# $rdb_dbhome - DB directory (default: '/var/db/squidGuard') +# $rdb_itemslist - items list as ['dest_key']='dest_DB_path' +# dest_DB_path - path without '$rdb_dbhome' +# example: ['ads_ban']='ads/banners' -> '/var/db/squidGuard/ads/banners' +# ------------------------------------------------------------------------------ +function sg_rebuild_db($shtag, $rdb_dbhome, $rdb_itemslist) +{ + global $squidguard_config; + $conf = ''; + $conf_path = ''; + $logdir = $squidguard_config[F_LOGDIR]; + $dbhome = $squidguard_config[F_DBHOME]; + + # current dbhome dir + if (!empty($rdb_dbhome)) $dbhome = $rdb_dbhome; + sg_addlog("sg_rebuild_db: Begin with path '$dbhome'.", 1); + + # define - where config will placed + $conf_path = "/tmp/squidGuard_rebuild.conf" . $shtag; + + # make rebuild config; include all found dest items + $conf = sg_create_simple_config($dbhome, $rdb_itemslist); + file_put_contents($conf_path, $conf); + set_file_access($conf_path, OWNER_NAME, 0750); + sg_addlog("sg_rebuild_db: Create temporary config '$conf_path'.", 1); + + # *** SH script *** + $sh_scr = Array(); + $sh_scr[] = "#!/bin/sh"; + $sh_scr[] = "cd $dbhome"; + $sh_scr[] = $squidguard_config[F_BINPATH] . "/squidGuard -c $conf_path -C all"; + $sh_scr[] = "wait"; # wait while SG rebuild DB + + # set DB owner and right access + $sh_scr[] = "chown -R -v " . OWNER_NAME . " $dbhome"; + + # restart squid for changes to take effects + $sh_scr[] = "/usr/local/sbin/squid -k reconfigure"; + + # store & exec sh + $sh_scr = implode("\n", $sh_scr); + $shfile = DB_REBUILD_SH . $shtag; + file_put_contents($shfile, $sh_scr); + set_file_access($shfile, OWNER_NAME, 0750); + # ! not background exec ! + mwexec($shfile); + sg_addlog("sg_rebuild_db: Started SH script '$shfile'.", 1); +} + +# ============================================================================== +# Log +# ------------------------------------------------------------------------------ +# sg_addlog +# ------------------------------------------------------------------------------ +function sg_addlog($log, $level = 0) +{ + global $squidguard_config; + + # log level + if ($level < SQUIDGUARD_LOG_LEVEL) return; + + $logfile = ''; + $logfile = SQUIDGUARD_LOGDIR_DEF . SQUIDGUARDCONF_LOGFILE; + $log_content = array(); + + setlocale(LC_TIME, ''); + $dt = date("d.m.Y H:i:s"); + + # define logfile + if (!empty($squidguard_config)) { + if (file_exists($squidguard_config[F_LOGDIR])) + $logfile = $squidguard_config[F_LOGDIR] . SQUIDGUARDCONF_LOGFILE; + } else + $log_content[] = "$dt : " . "sg_addlog: Error: squidguard_config is empty"; + + $tmplog = ''; + if (file_exists($logfile)) + $tmplog = file_get_contents($logfile); + $log_content = explode("\n", $tmplog); + unset($tmplog); + + # shrink to MAXCOUNT log entries + $log_content[] = "$dt : $log"; + if (count($log_content) > SQUIDGUARD_LOG_MAXCOUNT) + array_splice($log_content, 0, SQUIDGUARD_LOG_MAXCOUNT - count($log_content)); + + file_put_contents($logfile, implode("\n", $log_content)); +} +# ------------------------------------------------------------------------------ +# sg_getlog +# ------------------------------------------------------------------------------ +function sg_getlog($last_entries_count) +{ + global $squidguard_config; + $log_content = ''; + $logfile = SQUIDGUARD_LOGDIR_DEF . SQUIDGUARDCONF_LOGFILE; + + # define logfile + if (!empty($squidguard_config) && file_exists($squidguard_config[F_LOGDIR])) + $logfile = $squidguard_config[F_LOGDIR] . SQUIDGUARDCONF_LOGFILE; + + # get log last 100 entries + if (file_exists($logfile)) { + $log_content = explode("\n", file_get_contents($logfile)); + if (count($log_content) > $last_entries_count) + array_splice($log_content, 0, $last_entries_count - count($log_content)); + + # insert log file name on top + $log_content[0] = $logfile; + $log_content = implode("\n", $log_content); + } + + return $log_content; +} + +# ============================================================================== +# make config +# ============================================================================== +# sg_create_config +# ------------------------------------------------------------------------------ + +function sg_create_config() +{ + global $squidguard_config; + $sgconf = array(); + $sg_tag = new TSgTag; + $error_res = ''; + $temp_str = ''; + + if(!is_array($squidguard_config) || empty($squidguard_config)) { + sg_addlog("sg_create_config: Error squidguard config data.", 2); + return sg_create_simple_config('', '', SG_ERR0 . " (sg_create_config: [1])."); + } + + # check configuration data + if (!sg_check_config_data(&$error_res)) { + sg_addlog("sg_create_config: Error config data. It's all error_res: \n$error_res", 2); + sg_addlog("sg_create_config: Terminated.", 2); + return sg_create_simple_config('', '', SG_ERR0 . " (sg_create_config: [2])."); + } + + # --- Header --- + $sgconf[] = CONFIG_SG_HEADER; + $sgconf[] = "logdir {$squidguard_config[F_LOGDIR]}"; + $sgconf[] = "dbhome {$squidguard_config[F_DBHOME]}"; + + # --- Times --- + if ($squidguard_config[F_TIMES]) { + $temp_str = ''; + foreach($squidguard_config[F_TIMES][F_ITEM] as $tm) { + $sg_tag->clear(); + $sg_tag->set("time", $tm[F_NAME], "", $tm[F_DESCRIPTION]); + + foreach($tm[F_ITEM] as $itm) { + $dts = ($itm[F_TIMETYPE] === "weekly") ? $itm[F_TIMEDAYS] : $itm[F_DATERANGE]; + $sg_tag->items[] = "{$itm[F_TIMETYPE]} $dts {$itm[F_TIMERANGE]}"; + } + $sgconf[] = ""; + $sgconf[] = $sg_tag->tag_text(); + + # log + $temp_str .= " {$tm[F_NAME]}"; + } + # log + $temp_str = !empty($temp_str) ? $temp_str : "Nothing."; + sg_addlog("sg_create_config: add times: \n $temp_str", 1); + } + + # --- Sources --- + if ($squidguard_config[F_SOURCES]) { + $temp_str = ''; + foreach($squidguard_config[F_SOURCES][F_ITEM] as $src) { + $sg_tag->clear(); + $sg_tag->set("src", $src[F_NAME], "", $src[F_DESCRIPTION]); + + # separate IP, domains, usernames + $tsrc = explode(" ", trim($src[F_SOURCE])); + foreach($tsrc as $sr) { + $sr = trim($sr); + if (empty($sr)) continue; + if (is_ipaddr_valid($sr)) $sg_tag->items[] = "ip $sr"; + elseif (is_domain_valid($sr)) $sg_tag->items[] = "domain $sr"; + elseif (is_username($sr)) $sg_tag->items[] = "user " . str_replace("'", "", $sr); + } + if ($src[F_LOG]) $sg_tag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE; + + $sgconf[] = ""; + $sgconf[] = $sg_tag->tag_text(); + + # log + $temp_str .= " " . $src[F_NAME]; + } + # log + $temp_str = !empty($temp_str) ? $temp_str : "Nothing."; + sg_addlog("sg_create_config: add sources: \n $temp_str", 1); + } + + # --- Blacklist --- + # Note! Blacklist must be added to config permanently. It's need for rebuild DB now + + $db_entries = sg_entries_blacklist(); + if (($squidguard_config[F_BLACKLISTENABLED] === 'on') and $db_entries) { + $log_entr_added = ''; + $log_entr_ignored = ''; + sg_addlog("sg_create_config: add blacklist entries", 1); + foreach($db_entries as $key => $ent) { + $ent_state = array(); + $file_dms = "{$squidguard_config[F_DBHOME]}/$ent/domains"; + $file_urls = "{$squidguard_config[F_DBHOME]}/$ent/urls"; + $file_expr = "{$squidguard_config[F_DBHOME]}/$ent/expressions"; + + # check blacklist acl state + if (file_exists($file_dms)) { + $ent_state['exists'] = 'on'; + $ent_state[F_DOMAINS] = 'on'; + } + if (file_exists($file_urls)) { + $ent_state['exists'] = 'on'; + $ent_state[F_URLS] = 'on'; + } + if (file_exists($file_expr)) { + $ent_state['exists'] = 'on'; + $ent_state[F_EXPRESSIONS] = 'on'; + } + + # create config if blacklist item exists + if ($ent_state['exists']) { + $sg_tag->clear(); + $sg_tag->set("dest", $ent, "", ""); + + if ($ent_state[F_DOMAINS]) $sg_tag->items[] = "domainlist $ent/domains"; + if ($ent_state[F_EXPRESSIONS]) $sg_tag->items[] = "expressionlist $ent/expressions"; + if ($ent_state[F_URLS]) $sg_tag->items[] = "urllist $ent/urls"; + $sg_tag->items[] = "log ". SQUIDGUARD_ACCESSBLOCK_FILE; + + $sgconf[] = ""; + $sgconf[] = $sg_tag->tag_text(); + + # log + $log_entr_added .= " $ent;"; + } else { + $sgconf[] = "\t# Config ERROR: Destination '$ent' not found in DB"; + $log_entr_ignored .= " $ent;"; + } + } + + # log 'added' and 'ignored' + if (!empty($log_entr_added)) sg_addlog("sg_create_config: added: \n $log_entr_added \n", 1); + if (!empty($log_entr_ignored)) sg_addlog("sg_create_config: ignored: \n $log_entr_ignored \n", 2); + } + + # --- Destinations --- + if ($squidguard_config[F_DESTINATIONS]) { + $temp_str = ''; + foreach($squidguard_config[F_DESTINATIONS][F_ITEM] as $dst) { + $dstname = $dst[F_NAME]; + $sg_tag->clear(); + $sg_tag->set("dest", $dst[F_NAME], "", $dst[F_DESCRIPTION]); + + if ($dst[F_DOMAINS]) + $sg_tag->items[] = "domainlist $dstname/domains"; + if ($dst[F_EXPRESSIONS]) + $sg_tag->items[] = "expressionlist $dstname/expressions"; + if ($dst[F_URLS]) + $sg_tag->items[] = "urllist $dstname/urls"; + if ($dst[F_RMOD] != RMOD_NONE) + $sg_tag->items[] = "redirect " . sg_redirector_base_url($dst[F_REDIRECT], $dst[F_RMOD]); + if ($dst[F_LOG]) + $sg_tag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE; + + $sgconf[] = ""; + $sgconf[] = $sg_tag->tag_text(); + + # log + $temp_str .= " $dstname;"; + } + # log + $temp_str = !empty($temp_str) ? $temp_str : "Nothing."; + sg_addlog("sg_create_config: add destinations: \n $temp_str", 1); + } + + # --- Rewrites --- + if ($squidguard_config[F_REWRITES]) { + $temp_str = ''; + $log_entr_added = ''; + $log_entr_err = ''; + foreach($squidguard_config[F_REWRITES][F_ITEM] as $rew) { + $sg_tag->clear(); + $sg_tag->set("rew", $rew[F_NAME], "", ""); + + if (is_array($rew[F_ITEM])) { + foreach ($rew[F_ITEM] as $rw) + $sg_tag->items[] = "s@{$rw[F_TARGETURL]}@{$rw[F_REPLACETO]}@{$rw[F_MODE]}"; + + if ($rew[F_LOG]) + $sg_tag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE; + + $sgconf[] = ""; + $sgconf[] = $sg_tag->tag_text(); + # log + $log_entr_added .= " {$rew[F_NAME]};"; + } + else { + $sgconf[] = ""; + $sgconf[] = "# Rewrite {$rew[F_NAME]} error."; + # log + $log_entr_err .= " {$rew[F_NAME]};"; + } + } + + # log + sg_addlog("sg_create_config: add rewrites: \n success $log_entr_added \n error $log_entr_err", 1); + } + + # ---------------------------------------- + $entry_blacklist = sg_entries_blacklist(); + + # --- ACL --- + $sg_tag->clear(); + $sg_tag->set("acl", "", "", ""); + if ($squidguard_config[F_ACLS]) { + $temp_str = ''; + $log_entr_added = ''; + foreach($squidguard_config[F_ACLS][F_ITEM] as $acl) { + if (!$acl[F_DISABLED]) { + $sg_acltag = new TSgTag; + $sg_acltag->set($acl[F_NAME], "", $acl[F_TIMENAME], $acl[F_DESCRIPTION]); + + # delete blacklist entries from 'pass' if blacklist disabled + if ($squidguard_config[F_BLACKLISTENABLED] !== 'on') { + acl_remove_blacklist_items(&$acl[F_DESTINATIONNAME]); + acl_remove_blacklist_items(&$acl[F_OVERDESTINATIONNAME]); + } + + # not allowing IP in URL + if ($acl[F_NOTALLOWINGIP]) { + $acl[F_DESTINATIONNAME] = "!in-addr {$acl[F_DESTINATIONNAME]}"; + $acl[F_OVERDESTINATIONNAME] = "!in-addr {$acl[F_OVERDESTINATIONNAME]}"; + } + + # re-order acl pass (<allow><deny<all|none>) + $acl[F_DESTINATIONNAME] = sg_aclpass_reorder($acl[F_DESTINATIONNAME]); + $acl[F_OVERDESTINATIONNAME] = sg_aclpass_reorder($acl[F_OVERDESTINATIONNAME]); + + # ontime + $sg_acltag->items[] = "pass {$acl[F_DESTINATIONNAME]}"; + if ($acl[F_RMOD] != RMOD_NONE) + $sg_acltag->items[] = "redirect " . sg_redirector_base_url($acl[F_REDIRECT], $acl[F_RMOD]); + if ($acl[F_REWRITENAME]) + $sg_acltag->items[] = "rewrite {$acl[F_REWRITENAME]}"; + if ($acl[F_LOG]) + $sg_acltag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE; + + # overtime + if ($acl[F_TIMENAME]) { + $sg_acltag->items[] = "} else {"; + $sg_acltag->items[] = "pass {$acl[F_OVERDESTINATIONNAME]}"; + if ($acl[F_REDIRECMODE] !== RMOD_NONE) + $sg_acltag->items[] = "redirect " . sg_redirector_base_url($acl[F_OVERREDIRECT], $acl[F_RMOD]); + if ($acl[F_OVERREWRITENAME]) + $sg_acltag->items[] = "rewrite {$acl[F_OVERREWRITENAME]}"; + if ($acl[F_LOG]) + $sg_acltag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE; + } + $sg_tag->items[] = $sg_acltag; + } + $log_entr_added .= " {$acl[F_NAME]};"; + } + # log + $log_entr_added = !empty($log_entr_added) ? $log_entr_added : "Nothing."; + sg_addlog("sg_create_config: add ACL's: \n $log_entr_added", 1); + } + + # --- Default --- + $sg_tag_def = new TSgTag; + $sg_tag_def->set("default", "", "", ""); + $def = $squidguard_config[F_DEFAULT]; + sg_addlog("sg_create_config: add Default", 1); + if ($def) { + $temp_str = ''; + + # delete blacklist entries from 'pass' if blacklist disabled + if ($squidguard_config[F_BLACKLISTENABLED] !== 'on') + acl_remove_blacklist_items(&$def[F_DESTINATIONNAME]); + + # not allowing IP in URL + if ($def[F_NOTALLOWINGIP]) + $def[F_DESTINATIONNAME] = "!in-addr " . $def[F_DESTINATIONNAME]; + + # re-order acl pass (<allow><deny<all|none>) + $def[F_DESTINATIONNAME] = sg_aclpass_reorder($def[F_DESTINATIONNAME]); + + # ! 'Default' must use without times ! + $sg_tag_def->items[] = "pass {$def[F_DESTINATIONNAME]}"; + if ($def[F_RMOD] !== RMOD_NONE) + $sg_tag_def->items[] = "redirect " . sg_redirector_base_url($def[F_REDIRECT], $def[F_RMOD]); + if ($def[F_REWRITENAME]) + $sg_tag_def->items[] = "rewrite {$def[F_REWRITENAME]}"; + if ($def[F_LOG]) + $sg_tag_def->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE; + + } # <- if def + else { + $msg = "Error: ACL 'default' is empty, will use default 'block all'"; + $sg_tag_def->items[] = "# $msg"; + $sg_tag_def->items[] = "pass none"; + $sg_tag_def->items[] = "redirect " . sg_redirector_base_url('', RMOD_INT_ERRORPAGE); + sg_addlog("sg_create_config: $msg.", 2); + } + + # --- ACL end --- + $sg_tag->items[] = $sg_tag_def; # add 'default' ACL object + $sgconf[] = ""; + $sgconf[] = $sg_tag->tag_text(); + + # delete "\n" chars before each string - SG bug (first string of config must be not empty) + foreach ($sgconf as $key => $val) $sgconf[$key] = ltrim($sgconf[$key], "\n"); + return implode("\n", $sgconf); +} + +# ------------------------------------------------------------------------------ +# sg_create_simple_config +# Create config for DB rebuilding +# Default rule - block all +# Variables: +# $blk_dbhome - temporary DB home dir, may be different with DBHOME +# $blk_destlist - is array as [dst_name] = 'path', +# where path - catalog without dbhome path +# For example: dbhome is '/var/db/squidGuard/', +# path can be 'usr/ads' or 'bl/poxy' +# $redirect_to - redirector string +# ------------------------------------------------------------------------------ +function sg_create_simple_config($blk_dbhome, $blk_destlist, $redirect_to = "404") +{ + global $squidguard_config; + $sgconf = array(); + $logdir = $squidguard_config[F_LOGDIR]; + $dbhome = $squidguard_config[F_DBHOME]; + + # current dbhome dir + if (!empty($blk_dbhome)) $dbhome = $blk_dbhome; + sg_addlog("sg_create_simple_config: Begin with dbhome='$dbhome'.", 1); + + # header + $sgconf[] = CONFIG_SG_HEADER; + + # init section + $sgconf[] = "logdir $logdir"; + $sgconf[] = "dbhome $dbhome"; + $sgconf[] = ""; + + # destination section + if (is_array($blk_destlist)) { + foreach($blk_destlist as $dst => $dpath) { + $tmp_s = array(); + + # check item elements + if (file_exists("$dbhome/$dpath/domains")) $tmp_s[] = "\t domainlist $dpath/domains"; + if (file_exists("$dbhome/$dpath/urls")) $tmp_s[] = "\t urllist $dpath/urls"; + if (file_exists("$dbhome/$dpath/expressions")) $tmp_s[] = "\t expressionlist $dpath/expressions"; + + # create only valid items + if (!empty($tmp_s)) { + $tmp_s = implode("\n", $tmp_s); + $sgconf[] = "dest $dst {\n $tmp_s \n}\n"; + sg_addlog("sg_create_simple_config: -- added item '$dst' = '$dbhome/$dpath'."); + } else + sg_addlog("sg_create_simple_config: -- ignored empty item '$dst' = '$dbhome/$dpath'."); + } + } + + # acl section + $sgconf[] = "acl {\n\t default {\n\t\t pass all "; + $sgconf[] = "\t\t redirect " . sg_redirector_base_url($redirect_to, RMOD_INT_ERRORPAGE); # use sgerror only! + $sgconf[] = "\t } \n}"; + + # delete "\n" chars before each string - SG bug (first string of config must be not empty) + foreach ($sgconf as $key => $val) $sgconf[$key] = ltrim($sgconf[$key], "\n"); + + return implode("\n", $sgconf); +} + +# ------------------------------------------------------------------------------------------------- +# sg_redirector_base_url +# $url - url where redirect to +# $use_internal - ignore 'Redirect mode' option, use internal (for rebuild config, for example) +# +# ------------------------------------------------------------------------------------------------- +function sg_redirector_base_url($rdr_info, $redirect_mode) +{ + global $squidguard_config; + $rdr_path = ''; + + # gui port, ip & proto + $guiip = (!empty($squidguard_config[F_CURRENT_LAN_IP])) ? $squidguard_config[F_CURRENT_LAN_IP] : '127.0.0.1'; + $guiport = (!empty($squidguard_config[F_CURRENT_GUI_PORT])) ? $squidguard_config[F_CURRENT_GUI_PORT] : '80'; + $guiproto = ($squidguard_config[F_CURRENT_GUI_PROTO] === "https") ? "https" : "http"; + $rdr_path = "$guiproto://$guiip:$guiport" . REDIRECT_BASE_URL; + + # check redirect + $errmsg = ''; + if (!sg_check_redirect($redirect_mode, $rdr_info, &$errmsg)) { + $redirect_mode = RMOD_INT_ERRORPAGE; + $rdr_info = "Redirect settings error. $errmsg Check you configuration."; + sg_addlog("sg_redirector_base_url: ERROR: $errmsg"); + } + + switch($redirect_mode) { + case RMOD_EXT_ERR: $rdr_path = "$rdr_info" . REDIRECT_URL_ARGS; break; + case RMOD_EXT_RDR: $rdr_path = "$rdr_info"; break; + case RMOD_EXT_MOVED: $rdr_path = "301:$rdr_info"; break; + case RMOD_EXT_FOUND: $rdr_path = "302:$rdr_info"; break; + case RMOD_INT_BLANKPAGE: $rdr_path .= "?url=blank&msg=" . rawurlencode($rdr_info) . REDIRECT_URL_ARGS; break; + case RMOD_INT_BLANKIMG: $rdr_path .= "?url=blank_img&msg=" . rawurlencode($rdr_info) . REDIRECT_URL_ARGS; break; + case RMOD_INT_SIZELIMIT: $rdr_path .= "?url=maxlen_$rdr_info" . REDIRECT_URL_ARGS; break; + case RMOD_INT_ERRORPAGE: + default: $rdr_path .= "?url=" . rawurlencode("403 $rdr_info") . REDIRECT_URL_ARGS; break; + } + + sg_addlog("sg_redirector_base_url: Select redirector base url ($rdr_path)"); + return $rdr_path; +} + +# ------------------------------------------------------------------------------------------------- +# sg_aclpass_reorder +# ------------------------------------------------------------------------------------------------- +function sg_aclpass_reorder($pass) +{ + $ar_pass = explode(" ", $pass); + + # 'pass' order: <allow> <deny> <all|none> + if (is_array($ar_pass)) { + $pass_end = ''; + $pass_fst = array(); # whitelist - '^' prefix (will deleted) + $pass_sec = array(); # blacklist - '!' prefix + $pass_lst = array(); # allow + foreach ($ar_pass as $val) { + $tk = trim($val); + if ($tk === 'all' or $tk === 'none') + $pass_end = $val; + elseif (strpos($tk, "^") !== false) + # delete '^' prefix + $pass_fst[] = str_replace('^', '', $val); + elseif (strpos($tk, "!") !== false) + $pass_sec[] = $val; + else + $pass_lst[] = $val; + } + $ar_pass = array_merge($pass_fst, $pass_sec, $pass_lst); + $ar_pass[] = $pass_end; + } + return implode(" ", $ar_pass); +} + +# ------------------------------------------------------------ +# sg_check_config_data +# ------------------------------------------------------------ +function sg_check_config_data ($input_errors) +{ + global $squidguard_config; + $elog = array(); + $times = sg_list_itemsfield($squidguard_config[F_TIMES], F_NAME); + $sources = sg_list_itemsfield($squidguard_config[F_SOURCES], F_NAME); + $destinations = sg_list_itemsfield($squidguard_config[F_DESTINATIONS], F_NAME); + $rewrites = sg_list_itemsfield($squidguard_config[F_REWRITES], F_NAME); + $acls = array(); + + # --- Times --- + if ($squidguard_config[F_TIMES]) { + $key_tm = array_count_values($times); + foreach($squidguard_config[F_TIMES][F_ITEM] as $tm) { + # check name as unique and name format + $tm_name = $tm[F_NAME]; + $err_s = ''; + if (!check_name_format($tm_name, &$err_s)) + $elog[] = "(T1) TIME '$tm_name' error: >>> $err_s"; + + if ($key_tm[$tm_name] > 1) + $elog[] = "(T2) TIME '$tm_name' error: duplicate time name '$tm_name'"; + + # check time items format + sg_check_time($tm, &$elog); + } + } + + # --- Sources --- + if ($squidguard_config[F_SOURCES]) { + $key_src = array_count_values($sources); + foreach($squidguard_config[F_SOURCES][F_ITEM] as $src) { + # check name as unique and name format + $src_name = $src[F_NAME]; + $err_s = ''; + if (!check_name_format($src_name, &$err_s)) + $elog[] = "(A1) ACL '$src_name'error: $err_s"; + + if ($key_src[$src_name] > 1) + $elog[] = "(A2) ACL '$src_name' error: duplicate source name '$src_name'"; + + sg_check_src($src, $elog); + } + } + + # --- Destinations --- + if ($squidguard_config[F_DESTINATIONS]) { + $key_dst = array_count_values($destinations); + foreach($squidguard_config[F_DESTINATIONS][F_ITEM] as $dst) { + # check name as unique and name format + $dst_name = $dst[F_NAME]; + $err_s = ''; + if (!check_name_format($dst_name, &$err_s)) + $elog[] = "(D1) DEST '$dst_name' error: $err_s"; + + if ($key_dst[$dst_name] > 1) + $elog[] = "(D2) DEST '$dst_name' error: duplicate destination name '$dst_name'"; + # + sg_check_dest($dst, &$elog); + } + } + + # --- Blacklist --- + $blk_entries_file = $squidguard_config[F_WORKDIR] . SQUIDGUARD_BLK_ENTRIES; + if (file_exists($blk_entries_file)) { + $blk_entr = explode("\n", file_get_contents($blk_entries_file)); + foreach($blk_entr as $entr) { + if ($entr) { + $destinations[] = $entr; + # check entry for exists + $dbfile = $squidguard_config[F_DBHOME] . "/$entr"; + if (!file_exists($dbfile)) + $elog[] = "(B1) BLACKLIST '$entr' error: file '$dbfile' not found"; + } + } + } + + # --- Rewrites --- + if ($squidguard_config[F_REWRITES]) { + $key_rw = array_count_values($rewrites); + foreach($squidguard_config[F_REWRITES][F_ITEM] as $rw) { + # check check name as unique and name format + $rw_name = $rw[F_NAME]; + $err_s = ''; + if (!check_name_format($rw_name, &$err_s)) + $elog[] = "(R1) REWRITE '$rw_name' error: $err_s"; + + if ($key_rw[$rw_name] > 1) + $elog[] = "(R2) REWRITE '$rw_name' error: duplicate rewrite name '$rw_name'"; + } + } + + $key_times = array_count_values($times); + $key_sources = array_count_values($sources); + $key_destinations = array_count_values($destinations); + $key_rewrites = array_count_values($rewrites); + + # --- ACLs --- + if ($squidguard_config[F_ACLS]) { + $acls = array(); + foreach($squidguard_config[F_ACLS][F_ITEM] as $acl) { + # skip disabled acl + if ($acls[F_DISABLED]) continue; + + $acl_name = $acl[F_NAME]; + + # check acl name for unique and exists (as source items) + if ($acl_name and !$key_sources[$acl_name]) + $elog[] = "(A1) ACL '$acl_name' error: acl name '$acl_name' not found"; + + $acls[] = $acl_name; + $key_acls = array_count_values($acls); + if ($key_acls[$acl_name] > 1) + $elog[] = "(A2) ACL '$acl_name' error: duplicate acl name '$acl_name'"; + + # check time + $time = $acl[F_TIMENAME]; + if ($time and !$key_times[$time]) # time name must exists + $elog[] = "(A3) ACL '$acl_name' error: time name '$time' not found"; + + # check destinations + if ($acl[F_DESTINATIONNAME]) { + $acldest = $acl[F_DESTINATIONNAME]; + $acldest = str_replace("!", "", $acldest); + $acldest = str_replace("^", "", $acldest); + $acldest = explode(" ", $acldest); + $key_acldest = array_count_values($acldest); + foreach($acldest as $adest) { + # check duplicates destinations in acl + if ($key_acldest[$adest] > 1) + $elog[] = "(A4) ACL '$acl_name' error: duplicate destination name '$adest'. Any destination must included once."; + # check destinations for exists + if ($adest and ($adest != 'all') and ($adest != 'none') and !$key_destinations[$adest]) + $elog[] = "(A5) ACL '$acl_name' error: destination name '$adest' not found"; + } + } else { + $elog[] = "(A6) ACL '$acl_name' error: ontime pass list is empty. Added 'none'."; + $acl[F_DESTINATIONNAME] = "none"; + } + + # check overtime destinations + if ($time) { + if ($acl[F_OVERDESTINATIONNAME]) { + $acloverdest = $acl[F_OVERDESTINATIONNAME]; + $acloverdest = str_replace("!", "", $acloverdest); + $acloverdest = str_replace("^", "", $acloverdest); + $acloverdest = explode(" ", $acloverdest); + $key_acloverdest = array_count_values($acloverdest); + foreach($acloverdest as $adest) { + # check duplicates destinations in acl + if ($key_acloverdest[$adest] > 1) + $elog[] = "(A7) ACL '$acl_name' error: duplicate overtime destination name '$adest'. Any destination must included once."; + # check destinations for exists + if ($adest and ($adest != 'all') and ($adest != 'none') and !$key_destinations[$adest]) + $elog[] = "(A8) ACL '$acl_name' error: overtime destination name '$adest' not found"; + } + } else { + $elog[] = "(A9) ACL '$acl_name' error: overtime pass list is empty. Added 'none'."; + $acl[F_OVERDESTINATIONNAME] = "none"; + } + } + + # check rewrite + $rew = $acl[F_REWRITENAME]; + if ($rew and !$key_rewrites[$rew]) + $elog[] = "(AA) ACL '$acl_name' error: rewrite name '$rew' not found"; + + # check overtime rewrite + $overrew = $acl[F_OVERREWRITENAME]; + if ($time and $overrew and !$key_rewrites[$overrew]) + $elog[] = "(AB) ACL '$acl_name' error: overtime rewrite name '$overrew' not found"; + + # check redirect + $redir = $acl[F_REDIRECT]; + $overredir = $acl[F_OVERREDIRECT]; + } + } + + # --- Default --- + if ($squidguard_config[F_ACLS]) { + $def = $squidguard_config[F_DEFAULT]; + + # check time + $time = $def[F_TIMENAME]; + if ($time and !$key_times[$time]) # time name must exists + $elog[] = "(DF1) ACL 'default' error: time name '$time' not found"; + + # check destinations + if ($def[F_DESTINATIONNAME]) { + $defdest = $def[F_DESTINATIONNAME]; + $defdest = str_replace("!", "", $defdest); + $defdest = str_replace("^", "", $defdest); + $defdest = explode(" ", $defdest); + $key_defdest = array_count_values($defdest); + foreach($defdest as $adest) { + # check duplicates destinations in acl + if ($key_defdest[$adest] > 1) + $elog[] = "(DF2) ACL 'default' error: duplicate destination name '$adest'. Any destination must included once."; + # check destinations for exists + if ($adest and ($adest != 'all') and ($adest != 'none') and !$key_destinations[$adest]) + $elog[] = "(DF3) ACL 'default' error: destination name '$adest' not found"; + } + } else { + $elog[] = "(DF4) ACL 'default' error: ontime pass list is empty. Added 'none'."; + $def[F_DESTINATIONNAME] = "none"; + } + + # check rewrite + $rew = $def[F_REWRITENAME]; + if ($rew and !$key_rewrites[$rew]) + $elog[] = "(DF5) ACL 'default' error: rewrite name '$rew' not found"; + + # check overtime rewrite + $overrew = $def[F_OVERREWRITENAME]; + if ($time and $overrew and !$key_rewrites[$overrew]) + $elog[] = "(DF6) ACL 'default' error: overtime rewrite name '$overrew' not found"; + + # check redirect + $redir = $def[F_REDIRECT]; + $overredir = $def[F_OVERREDIRECT]; + } + + # update log + if (!empty($elog)) { + $input_errors = (is_array($input_errors)) ? array_merge($input_errors, $elog) : implode("\n", $elog); + } + + return empty($elog); +} + +# ============================================================================= +# Blacklist +# ============================================================================= +# sg_reconfigure_blacklist($source_filename, $opt) +# $source_filename - file name or url +# $opt - option: +# '' or 'local' - update from local file +# 'url' - update from url +# ----------------------------------------------------------------------------- +function sg_reconfigure_blacklist($source_filename, $opt = '') +{ + global $squidguard_config; + $sf = trim($source_filename); + $sf_contents = ''; + + sg_addlog("sg_reconfigure_blacklist: Begin with '$sf'.", 1); + + # 1. check system + sg_check_system(); + + # 2. upload + if ($sf[0] === "/") { # local file - example '/tmp/blacklists.tar' + sg_addlog("sg_reconfigure_blacklist: Update from file '$sf'.", 1); + if (file_exists($sf)) { + $sf_contents = file_get_contents($sf); + } else { + sg_addlog("sg_reconfigure_blacklist: Error, file '$sf' not found.", 2); + return; + } + } + # from url + else { + sg_addlog("sg_reconfigure_blacklist: Upload from url '$sf'.", 1); + $sf_contents = sg_uploadfile_from_url($sf, BLK_LOCALFILE, $opt); + } + + # 3. update + if (empty($sf_contents)) { + sg_addlog("sg_reconfigure_blacklist: Error content from '$sf'.", 2); + return; + } + # save black list archive content to local file + file_put_contents(BLK_LOCALFILE, $sf_contents); + + # 4. update blacklist + sg_update_blacklist(BLK_LOCALFILE); +} + +# ------------------------------------------------------------------------------ +# sg_update_blacklist - update blacklist from file +# How it's work: +# - unpack tar archive to temp dir +# - copy subdir's tree to one-level temp DB +# - copy unrebuilded temp db to work db (for user's can configure with new Blacklist) +# - create Blacklist files listing and copy to values dir and temp DB dir +# - background rebuild temp DB via sh script (longer proccess) and copy to work DB +# ------------------------------------------------------------------------------ + +function sg_update_blacklist($from_file) +{ + global $squidguard_config; + $dbhome = SQUIDGUARD_DBHOME_DEF; + $workdir = SQUIDGUARD_WORKDIR_DEF; + $tmp_unpack_dir = SQUIDGUARD_TMP . SQUIDGUARD_BL_UNPACK; + $arc_db_dir = SQUIDGUARD_VAR . SG_BLK_ARC; + + sg_addlog("sg_update_blacklist: Begin with '$from_file'.", 1); + + if (file_exists($from_file)) { + # check work and DB dir's + if (file_exists($squidguard_config[F_DBHOME])) $dbhome = $squidguard_config[F_DBHOME]; + if (file_exists($squidguard_config[F_WORKDIR])) $workdir = $squidguard_config[F_WORKDIR]; + # delete old tmp dir's + if (file_exists($tmp_unpack_dir)) mwexec("rm -R . $tmp_unpack_dir"); + if (file_exists($arc_db_dir)) mwexec("rm -R . $arc_db_dir"); + # create new tmp/arc dir's + mwexec("mkdir -p -m 0755 $tmp_unpack_dir"); + mwexec("mkdir -p -m 0755 $arc_db_dir"); + + # 1. unpack archive + mwexec("tar zxvf $from_file -C $tmp_unpack_dir"); + set_file_access($tmp_unpack_dir, OWNER_NAME, 0755); + sg_addlog("sg_update_blacklist: Unpack uploaded file '$from_file' -> '$tmp_unpack_dir'.", 1); + + # 2. copy blacklist to squidGuard base & create entries list + if (file_exists($tmp_unpack_dir)) { + $blk_items = array(); + $blk_list = array(); + + # scan blacklist items + scan_blacklist_cat($tmp_unpack_dir, "blk", & $blk_items); + + # move blacklist catalog structure to 'one level' (from tmp_DB to arch_DB) + foreach ($blk_items as $key => $val) { + $current_dbpath = "$arc_db_dir/$key"; + if (count($val)) { + # make blk_list for config file + $blk_list[$key] = $key; + + # delete '$current_dbpath' for correct moving + # need moving $val['path'] to $current_dbpath + # if $current_dbpath exists, + # then $val['path'] will created as subdir - !it's worng! + if (file_exists($current_dbpath)) + mwexec("rm -R $current_dbpath"); + mwexec("mv -f {$val['path']}/ $current_dbpath"); + sg_addlog("sg_update_blacklist: Move {$val['path']}/ -> $current_dbpath.", 1); + } + } + set_file_access($arc_db_dir, OWNER_NAME, 0755); + + # -- DISABLED -- copy unrebuilded blacklist from arch_DB_to work DB & set access rights +# mwexec("cp -R $arc_db_dir/ $dbhome"); +# set_file_access($dbhome, OWNER_NAME, 0755); + + # create entries list + if (count($blk_items)) { + # save to temp DB + $blklist_file = SQUIDGUARD_VAR . SQUIDGUARD_BLK_ENTRIES; + file_put_contents($blklist_file, implode("\n", array_keys($blk_items))); + set_file_access ($blklist_file, OWNER_NAME, 0755); + + # -- DISABLED -- save copy to squidGuard config dir +# $blklist_file = "{$squidguard_config[F_WORKDIR]}/" . SQUIDGUARD_BLK_ENTRIES; +# file_put_contents($blklist_file, implode("\n", array_keys($blk_items))); +# set_file_access ($blklist_file, OWNER_NAME, 0755); + sg_addlog("sg_update_blacklist: Create DB entries list '$blklist_file'.", 1); + } + + # make rebuild config (included all found dest items) & save to work dir + $conf_path = SQUIDGUARD_VAR . DB_REBUILD_BLK_CONF; # "/tmp/squidGuard_rebuild_blk.conf"; + file_put_contents($conf_path, sg_create_simple_config($arc_db_dir, $blk_list)); + set_file_access($conf_path, OWNER_NAME, 0755); + sg_addlog("sg_update_blacklist: Create rebuild config '$conf_path'.", 1); + + # *** SH script *********************************************** + $sh_scr = Array(); + $sh_scr[] = "#!/bin/sh"; + $sh_scr[] = "cd $arc_db_dir"; + $sh_scr[] = $squidguard_config[F_BINPATH] . "/squidGuard -c $conf_path -C all"; + $sh_scr[] = "wait"; # wait while SG rebuild DB + $sh_scr[] = "chown -R -v " . OWNER_NAME . " $arc_db_dir"; + $sh_scr[] = "chmod -R -v 0755 $arc_db_dir"; + + # copy temp db to '/var/db/squidGuard (-R - recursive; -p - copy access rights) + # '$bl_temp_dbhome/' - slash in end of path - copy only dir content (not self dir) + $sh_scr[] = "cp -R -p $arc_db_dir/ $dbhome"; + $sh_scr[] = "cp -f -p $blklist_file " . SQUIDGUARD_WORKDIR_DEF; + # set DB owner and right access + $sh_scr[] = "chown -R -v " . OWNER_NAME . " $dbhome"; + $sh_scr[] = "chmod -R -v 0755 $dbhome"; + + # if new blacklist some as already installed, then restart squid for changes to take effects + $blk_items_old = ''; + $blk_file_old = $squidguard_config[F_WORKDIR] . SQUIDGUARD_BLK_ENTRIES; + if (file_exists($blk_items_old)) + $blk_items_old = file_get_contents($blk_file_old); + if (!empty($blk_items_old) && ($blk_items_old === implode("\n", array_keys($blk_items)))) { + $sh_scr[] = "/usr/local/sbin/squid -k reconfigure"; + $sh_scr[] = "wait"; # wait while process + } + unset($blk_file_old); + unset($blk_items_old); + + # store & exec sh + $sh_scr = implode("\n", $sh_scr); + $shfile = DB_REBUILD_SH . "_blk"; + file_put_contents($shfile, $sh_scr); + set_file_access($shfile, OWNER_NAME, 0755); # 0755 - script will execute + # kill exists rebuild processes +# mwexec("kill `ps auxw | grep \"$shfile\" | grep -v \"grep\" | awk '{print $2}'`"); # sh script + mwexec("kill `ps auxw | grep \"squidGuard_blk_rebuild\" | grep -v \"grep\" | awk '{print $2}'`"); # squidGuard process + mwexec_bg("nice -n 5 $shfile"); + sg_addlog("sg_update_blacklist: Started sh script '$shfile'.", 1); + + # clearing temp +# mwexec("rm -R $bl_temp"); + } + } +} + + +# ----------------------------------------------------------------------------- +# sg_blacklist_rebuild_DB - update blacklist from file +# ----------------------------------------------------------------------------- +function sg_entries_blacklist() +{ + global $squidguard_config; + $contents = ''; + + $fl = SQUIDGUARD_WORKDIR_DEF . SQUIDGUARD_BLK_ENTRIES; + if (file_exists($squidguard_config[F_WORKDIR])) + $fl = $squidguard_config[F_WORKDIR] . SQUIDGUARD_BLK_ENTRIES; + if (file_exists($fl)) + $contents = explode("\n", file_get_contents($fl)); + + return $contents; +} +# ----------------------------------------------------------------------------- +# sg_blacklist_rebuild_db - rebuild current Blacklist DB (default: '/var/db/squidGuard') +# ----------------------------------------------------------------------------- +function sg_blacklist_rebuild_db() +{ + global $squidguard_config; + $dst_list = array(); + $dbhome = $squidguard_config[F_DBHOME]; + $workdir = $squidguard_config[F_WORKDIR]; + + # current dbhome and work dir's + sg_addlog("sg_blacklist_rebuild_db: Start with path '$dbhome'.", 1); + + # make dest list + $blklist_file = "$workdir/" . SQUIDGUARD_BLK_ENTRIES; + if (file_exists($blklist_file)) { + $blklist = explode("\n", file_get_contents($blklist_file)); + if (is_array($blklist)) + foreach($blklist as $bl) { $dst_list[$bl] = $bl; } + } + + # rebuild user db ('/var/db/squidGuard') + sg_rebuild_db("_blkdb", $dbhome, $dst_list); +} + +# ========================== UTILS ============================================= +# sg_uploadfile_from_url +# upload file and put them to $destination_file +# return = upload content +# ------------------------------------------------------------------------------ +function sg_uploadfile_from_url($url_file, $destination_file, $proxy = '') +{ + # open destination file + sg_addlog("sg_uploadfile_from_url: begin url'$url_file' proxy'$proxy'", 1); + + $result = ''; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url_file); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + if (!empty($proxy)) { + $ip = ''; + $login = ''; + $s = trim($proxy); + if (strpos($s, ' ')) { + $ip = substr($s, 0, strpos($s, ' ')); + $login = substr($s, strpos($s, ' ') + 1); + } else $ip = $s; + + if($ip != '') { + curl_setopt($ch, CURLOPT_PROXY, $ip); + if($login != '') + curl_setopt($ch, CURLOPT_PROXYUSERPWD, $login); + } + } + $result=curl_exec ($ch); + curl_close ($ch); + if (!empty($destination_file)) + file_put_contents($destination_file, $result); + else sg_addlog("sg_uploadfile_from_url: Error upload file", 2); + + # for test + file_put_contents(BLK_LOCALFILE, $result); + + return $result; +} + +# ============================================================================== +# self utils +# ============================================================================== +# Set file access +# ------------------------------------------------------------------------------ +function set_file_access($dir, $owner, $mod) +{ + $mod = sprintf("%o", $mod); + if (!file_exists($dir)) return; + # recursive change access + mwexec("chown -R -v $owner $dir"); + mwexec("chgrp -R -v $owner $dir"); + mwexec("chmod -R -v $mod $dir"); +} +# ------------------------------------------------------------------------------ +# scan_dir - build files listing for $dir +# ------------------------------------------------------------------------------ +function scan_dir($dir) +{ + $files = array(); + if (file_exists($dir)) { + $dh = opendir($dir); + while (false !== ($filename = readdir($dh))) { + # skip '.' and '..' names + if (($filename !== '.') and ($filename !== '..')) $files[] = $filename; + } + sort($files); + } + return $files; +} +# ------------------------------------------------------------------------------ +# restore_arc_blacklist - copy arc blacklist to db +# ------------------------------------------------------------------------------ +function restore_arc_blacklist() +{ + global $squidguard_config; + $dbhome = SQUIDGUARD_DBHOME_DEF; + $blklist_file = SQUIDGUARD_WORKDIR_DEF . SQUIDGUARD_BLK_ENTRIES; + $arc_db_dir = SQUIDGUARD_VAR . SG_BLK_ARC; + $arc_blklist_file = SQUIDGUARD_VAR . SQUIDGUARD_BLK_ENTRIES; + + if (file_exists($arc_db_dir) and file_exists($arc_blklist_file)) { + + # copy arc blacklist to work DB with permissions + mwexec("cp -R -p $arc_db_dir/ $dbhome"); + set_file_access($dbhome, OWNER_NAME, 0755); + sg_addlog("restore_arc_blacklist: Restore blacklist archive from '$arc_db_dir'.", 1); + + # copy black list file + copy($arc_blklist_file, $blklist_file); + set_file_access($blklist_file, OWNER_NAME, 0755); + sg_addlog("restore_arc_blacklist: Restore black list file from '$arc_blklist_file' to '$blklist_file'.", 1); + } else { + sg_addlog("restore_arc_blacklist: Error, file '$arc_db_dir' or '$blklist_file' not found.", 2); + } +} + +# ------------------------------------------------------------------------------ +# scan_blacklist_cat - scan all dirs and subdirs tree and make blk enrties list +# $cur_dir - start directory +# $key_name - current key name +# ------------------------------------------------------------------------------ +# blk entry[key]: +# ["domains"] domains file path +# ["urls"] urls file path +# ["expressions"] expressions file path +# ------------------------------------------------------------------------------ +function scan_blacklist_cat($curdir, $key_name, $cat_array) +{ + + if (file_exists($curdir) and is_dir($curdir)) { + $blk_entry = array(); + $files = scan_dir($curdir); + + foreach($files as $fls) { + $fls_file = "$curdir/$fls"; + + if (($fls != ".") and ($fls != "..")) { + if (is_file($fls_file)) { + + # add files path + switch(strtolower($fls)) { + case "domains": + $blk_entry["domains"] = $fls_file; + $blk_entry["path"] = $curdir; + break; + case "urls": + $blk_entry["urls"] = $fls_file; + $blk_entry["path"] = $curdir; + break; + case "expressions": + $blk_entry["expressions"] = $fls_file; + $blk_entry["path"] = $curdir; + break; + } + } + elseif (is_dir($fls_file)) { + $fls_key = $key_name . "_" . $fls; + + # recursive call + scan_blacklist_cat($fls_file, $fls_key, & $cat_array); + } + } + } + + if (count($blk_entry)) + $cat_array[$key_name] = $blk_entry; + } +} + +# ****************************************************************************** +# squidguard utils +# ****************************************************************************** +# sg_list_itemsfield - get items field list +# ------------------------------------------------------------------------------ +function sg_list_itemsfield($xml_items, $fld_name) +{ + $ls = array(); + if (is_array($xml_items[F_ITEM])) + foreach($xml_items[F_ITEM] as $it) { + $ls[] = $it[$fld_name]; + } + return $ls; +} + +# ------------------------------------------------------------------------------ +# is_url - check url an err_codes +# ------------------------------------------------------------------------------ +function is_url($url) +{ + if (empty($url)) return false; + if (eregi("^http://", $url)) return true; + if (eregi("^https://", $url)) return true; + if (strstr("blank", $url)) return true; + if (strstr("blank_img", $url)) return true; + if (eregi("^((30[1235]{1})|(40[0-9]{1})|(41[0-7]{1})|(50[0-5]{1}))", $url)) return true; # http error code 30x, 4xx, 50x. + return false; +} + +# url as 'domain/path': 'mydomain.com/index.php' +function is_dest_url($url) +{ + $fmt = "[a-zA-Z0-9_-]"; + + if (empty($url)) return false; + if (eregi("^(($fmt){1,}\.){1,}($fmt){2,}(/(.[^\*][^ ])*)", $url)) return true; + return false; +} +# ------------------------------------------------------------------------------ +# is_masksubnet - check ip/mask +# ------------------------------------------------------------------------------ +function is_masksubnet($subnet) +{ + if (!is_string($subnet)) + return false; + + list($ip,$msk) = explode('/', $subnet); + if (!is_ipaddr($ip) || !is_ipaddr($msk)) + return false; + + return true; +} +# ------------------------------------------------------------------------------ +# is_iprange - check ip1-ip2 +# ------------------------------------------------------------------------------ +function is_iprange($ip_range) { + if (!is_string($ip_range)) return false; + + list($ip1,$ip2) = explode('-', $ip_range); + if (!is_ipaddr($ip1) || !is_ipaddr($ip2)) return false; + + # ip2 < ip1 - wrong + if (ipcmp(ip2, ip1) === -1) return false; + + return true; +} +# ------------------------------------------------------------------------------ +# is_ipaddr_valid - validate IP, subnet, IP range +# ------------------------------------------------------------------------------ +function is_ipaddr_valid($val) +{ + return is_string($val) && (is_ipaddr($val) || is_masksubnet($val) || is_subnet($val) || is_iprange($val)); +} + +# ------------------------------------------------------------------------------ +# is_domain_valid - check domain format +# ------------------------------------------------------------------------------ +function is_domain_valid($domain) +{ + $dm_fmt = "([a-z0-9\-]{1,})"; + $dm_fmt = "^(($dm_fmt{1,}\.){1,}$dm_fmt{2,})+$"; # example: (my.)(super.)(domain.)com + return is_string($domain) && eregi($dm_fmt, trim($domain)); +} + +# ------------------------------------------------------------------------------ +# is_username - check username +# ------------------------------------------------------------------------------ +function is_username($username) +{ + $unm_fmt = "^\'[a-zA-Z_0-9\-]{1,}\'$"; + return is_string($username) && eregi($unm_fmt, trim($username)); +} +# ------------------------------------------------------------------------------ +# check name +# ------------------------------------------------------------------------------ +function check_name_format ($name, $input_errors) +{ + $elog = array(); + $val = trim($name); + + if ((strlen($val) < 2) || (strlen($val) > 16)) + $elog[] = " Size of name '$val' must be between [2..16]."; + + # All symbols must be [a-zA-Z_0-9\-] First symbol = letter. + if (!eregi("^([a-zA-Z]{1})([a-zA-Z_0-9\-]+)$", $val)) + $elog[] = " Invalid name $name. Valid name symbols: ['a-Z', '_', '0-9', '-']. First symbol must be a letter."; + + # update log + if (!empty($elog)) { + $input_errors = (is_array($input_errors)) ? array_merge($input_errors, $elog) : implode("\n", $elog); + } + + return empty($elog); +} +# ****************************************************************************** +# squidguard check +# ****************************************************************************** +# check redirect +# ------------------------------------------------------------------------------ +function sg_check_redirect($rdr_mode, $rdr_info, $err_msg) +{ + $res = true; + switch($rdr_mode) { + case RMOD_EXT_ERR: case RMOD_EXT_RDR: case RMOD_EXT_MOVED: case RMOD_EXT_FOUND: + $res = is_url($rdr_info); + if (!$res) $err_msg = "Valid URL expected, but '$rdr_info' found."; + break; + case RMOD_INT_SIZELIMIT: + $res = is_numeric($rdr_path); + if (!$res) $err_msg = "Valid number value expected, but '$rdr_info' found."; + break; + case RMOD_INT_BLANKPAGE: case RMOD_INT_BLANKIMG: case RMOD_INT_ERRORPAGE: + default: + $res = true; break; + } + return $res; +} + +# ------------------------------------------------------------------------------ +# sg_check_time +# ------------------------------------------------------------------------------ +function sg_check_time($sgtime, $input_errors) +{ + $err = ''; + $days = array("*", "mon", "tue", "wed", "thu", "fri", "sat", "sun"); + $timetypes = array("weekly", "date"); + + if (is_array($sgtime[F_ITEM])) { + # check date and time + foreach ($sgtime[F_ITEM] as $item) { + if (!in_array(trim($item[F_TIMETYPE]), $timetypes)) + $err .= " Invalid type '{$item[F_TIMETYPE]}'."; + if (!in_array(trim($item[F_TIMEDAYS]), $days)) + $err .= " Invalid week day '{$item[F_TIMEDAYS]}'."; + if (trim($item[F_DATERANGE])) $err .= check_date(trim($item[F_DATERANGE])); + if (trim($item[F_TIMERANGE])) $err .= check_time(trim($item[F_TIMERANGE])); + } + } + + # errors update + if (!empty($err)) $input_errors[] = "TIME '{$sgtime[F_NAME]}': $err"; + return empty($err); +} + +# ------------------------------------------------------------------------------ +# sg_check_dest +# ------------------------------------------------------------------------------ +function sg_check_dest($sgx, $input_errors) +{ + $elog = array(); + $dm = explode(" ", $sgx[F_DOMAINS]); +# $ex = explode(" ", $sgx[F_EXPRESSIONS]); + $ur = explode(" ", $sgx[F_URLS]); + array_packitems(&$dm); + array_packitems(&$ur); + + # domain + foreach ($dm as $d_it) + if ($d_it && !is_domain_valid($d_it)) $elog[] = "Item '$d_it' is not a domain."; + + # url + foreach ($ur as $u_it) + if ($u_it && !is_dest_url($u_it)) $elog[] = "Item '$u_it' is not a url."; + + # check redirect + sg_check_redirect($sgx[F_RMOD], $sgx[F_REDIRECT], &$elog); + + # update log + if (!empty($elog)) { + $elog = "DEST '{$sgx[F_NAME]}': " . implode(" ", $elog); + if (is_array($input_errors)) + $input_errors[] = $elog; + else $input_errors = $elog; + } + return empty($elog); +} + +# ------------------------------------------------------------------------------ +# sg_check_src +# ------------------------------------------------------------------------------ +function sg_check_src($sgx, $input_errors) +{ + $elog = array(); + + # source may be as one ('source') field or as two ('ip' and 'domain') fields + $src = (isset($sgx[F_SOURCE])) ? $sgx[F_SOURCE] : $sgx[F_IP] . " " . $sgx[F_DOMAINS]; + $src = explode(" ", $src); + foreach ($src as $s_item) { + if ($s_item) { + if (!is_ipaddr_valid($s_item) and !is_domain_valid($s_item) and !is_username($s_item)) + $elog[] = "SRC '{$sgx[F_NAME]}': Item '$s_item' is not a ip address or a domain or a 'username'."; + } + } + + # update log + if (!empty($elog)) { + $input_errors = (is_array($input_errors)) ? array_merge($input_errors, $elog) : implode("\n", $elog); + } + + return empty($elog); +} +# ------------------------------------------------------------------------------ +# check rebuild blacklist +# ------------------------------------------------------------------------------ +function is_blacklist_update_started() +{ + return exec("ps auxw | grep \"[s]quidGuard_blk_rebuild\" | awk '{print $2}' | wc -l | awk '{ print $1 }'"); +} + +# ------------------------------------------------------------------------------ +# Strings +# ------------------------------------------------------------------------------ +# str_pack_spaces - replace two and more space to single +# ------------------------------------------------------------------------------ +function str_packspaces($str) +{ + while(strpos($str, ' ')) $str = str_replace(' ', ' ', $str); +} + +function array_packitems($arval) +{ + if (is_array($arval)) { + $arval = array_map("trim", $arval); # trim all items + $arval = array_diff($arval, array(' ', '')); # exclude ' ' abd '' elements + $arval = array_unique($arval); # unique items + $arval = array_values($arval); # pack array + } + return $arval; +} + +# ----------------------------------------------------------------------------- +# check date +# date or date range format: 'yyyy-mm-dd', 'yyyy-m-d', 'yyyy.mm.dd' 'yyyy.mm.dd-yyyy.mm.dd' +# date mask format: '*-mm-dd', 'yyyy-*-dd', 'yyyy.mm.*' (but not for range) +# ----------------------------------------------------------------------------- +function check_date($date) +{ + $err = ''; + $val = trim($date); + $dtfmt = "([0-9]{4})\.([0-9]{2})\.([0-9]{2})"; + + # check date range + if (eregi("^{$dtfmt}-{$dtfmt}$", $val)) { + $val = explode("-", str_replace(".", '', $val)); + if (intval($val[0]) >= intval($val[1])) + $err .= "Invalid date range, begin range must be less than the end. {$val[0]} - {$val[1]}"; + } + elseif (!eregi("^(([0-9]{4})|[*])\.(([0-9]{2})|[*])\.(([0-9]{2})|[*])$", $val)) { + $err .= "Bad date format."; + } + + if ($err) + $err = " Invalid date '$date'. + $err + You mast use date or date range format: 'yyyy.mm.dd' and 'yyyy.mm.dd-yyyy.mm.dd'. + Also possible use mask * (mean any). Example: '*-10-01', '1990-*-*'."; + return $err; +} + +# ----------------------------------------------------------------------------- +# check time +# ----------------------------------------------------------------------------- +function check_time($time) +{ + $err = ''; + $time = trim($time); + + if (empty($time)) return ''; + + # time range format: 'HH:MM-HH:MM' + if (!eregi("^([0-2][0-9])\:([0-5][0-9])-([0-2][0-9])\:([0-5][0-9])$", $time)) + $err = "Invalid time range '$time'. You must use 'HH:MM-HH:MM' time range format. "; + else { + $tms = str_replace("-", "\n", $time); + $tmsview = explode("\n", $tms); + $tms = str_replace(":", "", $tms); + $tms = explode("\n", $tms); + if ($tms[0] >= 2400) + $err .= "Invalid time range var1='{$tmsview[0]}' must be < '24:00'. "; + if ($tms[1] > 2400) + $err .= "Invalid time range var2='{$tmsview[1]}' must be <= '24:00'. "; + if ($tms[0] >= $tms[1]) + $err .= "Invalid time range var1='{$tmsview[0]}' must be < var2='{$tmsview[1]}'. "; + } + + return $err; +} + +# ----------------------------------------------------------------------------- +# acl_remove_blacklist_items +# ----------------------------------------------------------------------------- +function acl_remove_blacklist_items($items) +{ + # add !items and ^items + $db_entries = sg_entries_blacklist(); + $tdb_entries = array(); + foreach ($db_entries as $ent) { + $tdb_entries[] = $ent; + $tdb_entries[] = "!$ent"; + $tdb_entries[] = "^$ent"; + } + $db_entries = $tdb_entries; + unset($tdb_entries); + + # delete blacklist entries from 'pass' if blacklist disabled + $items = explode(" ", $items); + $items = implode(" ", array_diff($items, $db_entries)); + return $items; +} + +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# classes +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +class TSgTag +{ + var $tag; + var $name; + var $time; + var $items; + var $desc; + + function __construct() { + $this->clear(); + } + + function clear() { + $this->tag = ''; + $this->name = ''; + $this->time = ''; + $this->items = array(); + $this->desc = ''; + } + + function set($tag, $name, $time, $desc) { + $this->tag = $tag; + $this->name = $name; + $this->time = $time; + $this->desc = $desc; + } + + function tag_text($offset = 0) { + $str = array(); + $off = str_repeat("\t", $offset); + + $str[] = $off . "# {$this->desc}"; + if (empty($this->time)) + $str[] = $off . "{$this->tag} {$this->name} {"; + else $str[] = $off . "{$this->tag} {$this->name} within {$this->time} {"; + + # get items + foreach($this->items as $it) { + if (is_a($it, "TSgTag")) + $str[] = $off . $it->tag_text($offset + 1); # sub tag + else $str[] = $off . "\t{$it}"; # item + } + + $str[] = $off . "}"; + return implode("\n", $str); + } +} + +?> |