- 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', '100M'); # ------------------------------------------------------------------------------ # ToDo ! Must use all settings via $squidguard_config ! # Sdelat rewrite dlya smeny skachivaniya # ------------------------------------------------------------------------------ # files header # ------------------------------------------------------------------------------ define('FILES_DB_HEADER', ' # ------------------------------------------------------------------------------ # File created by squidGuard package GUI # (C)2006-2010 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 # ============================================================ "); # ------------------------------------------------------------------------------ # 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'); define('REDIRECTOR_PROCESS_COUNT', '3'); # redirector processes count will started # ------------------------------------------------------------------------------ # 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 constants # ------------------------------------------------------------------------------ define('SQUID_CONFIGFILE', '/usr/local/etc/squid/squid.conf'); define('TMP_DIR', '/var/tmp'); # define('SQUIDGUARD_CONFIGFILE', '/squidGuard.conf'); define('SQUIDGUARD_CONFLOGFILE', '/sg_configurator.log'); define('SQUIDGUARD_LOGFILE', 'block.log'); define('SQUIDGUARD_CONFBASE', '/usr/local/etc/squid'); define('SQUIDGUARD_WORKDIR', '/usr/local/etc/squidGuard'); define('SQUIDGUARD_BINPATH', '/usr/local/bin'); define('SQUIDGUARD_TMP', '/tmp/squidGuard'); # SG temp define('SQUIDGUARD_VAR', '/var/squidGuard'); # SG variables define('SQUIDGUARD_STATE', '/squidGuard.state'); define('SQUIDGUARD_REBUILD', '/squidGuard.rebuild'); define('SQUIDGUARD_CONFXML', '/squidguard_conf.xml'); define('SQUIDGUARD_DBHOME', '/var/db/squidGuard'); define('SQUIDGUARD_DBHOME_BLK', SQUIDGUARD_DBHOME); define('SQUIDGUARD_DBSAMPLE', '/var/db/squidGuard.sample'); define('SQUIDGUARD_LOGDIR', '/var/squidGuard/log'); define('SQUIDGUARD_WEBGUI_LOG', '/squidguard_gui.log'); define('SQUIDGUARD_WEBGUI_HISTORY_LOG', '/squidguard_gui_history.log'); # define('SQUIDGUARD_SCR_LOGROTATE', '/usr/local/etc/rc.d/squidGuard_logrotate'); # Logrotate script # # DB home catalog contains 'Blacklist' and 'User' sub-catalogs 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('SQUIDGUARD_BLK_FILELIST', '/blacklist.files'); define('SQUIDGUARD_BLK_FILELISTPATH', SQUIDGUARD_WORKDIR . SQUIDGUARD_BLK_FILELIST); define('BLACKLIST_ARCHIVE', '/blacklists.tar'); define('SCR_NAME_BLKUPDATE', '/tmp/squidGuard_blacklist_update.sh'); 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'); define('SG_UPDATE_TARFILE', '/tmp/squidguard_blacklist.tar'); define('SG_UPDATE_TMPFILE', '/tmp/squidguard_download.tmp'); define('SG_UPDATE_LOGFILE', '/tmp/squidguard_download.log'); define('SG_UPDATE_STATFILE', '/tmp/squidguard_download.stat'); # ============================================================================== # CONSTANTS # ============================================================================== # 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'); # Log level: 0-error, 1-warning; 2-info define('SQUIDGUARD_INFO', 2); define('SQUIDGUARD_WARNING', 1); define('SQUIDGUARD_ERROR', 0); # define('ACL_WARNING_ABSENSE_PASS', "!WARNING! Absence PASS 'all' or 'none' added as 'none'"); # ============================================================================== # OPTIONS # ============================================================================== # Log define('SQUIDGUARD_GUILOG_LEVEL', SQUIDGUARD_INFO); # log level define('SQUIDGUARD_GUILOG_MAXCOUNT', 500); # log max lines define('SQUIDGUARD_GUILOG_ENABLE', true); # on/off gui log - option override GUI settings define('SQUIDGUARD_LOG_ENABLE', true); # on/off SG log - option override GUI settings # 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 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_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 ; rmod_301; rmod_302; define('F_NOTALLOWINGIP', 'notallowingip'); # not allowing ip in URL define('F_USERNAME', 'username'); define('F_ORDER', 'order'); # log define('F_ENABLELOG', 'enablelog'); define('F_ENABLEGUILOG', 'enableguilog'); define('F_LOGROTATION', 'logrotation'); # 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'); # blacklist define('F_BLACKLISTENABLED', 'blacklist_enabled'); define('F_BLACKLISTURL', 'blacklist_url'); # ============================================================================== # Globals # ============================================================================== $squidguard_config = array(); # squidGuard config array # call default init sg_init(); # ------------------------------------------------------------------------------ # 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; $squidguard_config[F_DBHOME] = SQUIDGUARD_DBHOME; $squidguard_config[F_WORKDIR] = SQUIDGUARD_WORKDIR; $squidguard_config[F_BINPATH] = SQUIDGUARD_BINPATH; $squidguard_config[F_SQUIDCONFIGFILE] = SQUID_CONFIGFILE; $squidguard_config[F_PROCCESSCOUNT] = REDIRECTOR_PROCESS_COUNT; } else { # copy config from $init foreach($init as $key => $in) $squidguard_config[$key] = $in; } 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'.", SQUIDGUARD_INFO); } else sg_addlog("sg_load_configxml", "File '$filename' is empty.", SQUIDGUARD_ERROR); } else sg_addlog("sg_load_configxml", "File '$filename' does not exists.", SQUIDGUARD_ERROR); } # ------------------------------------------------------------------------------ # sg_saveconfig_xml # ------------------------------------------------------------------------------ function sg_save_configxml($filename) { global $squidguard_config; conf_mount_rw(); file_put_contents($filename, dump_xml_config($squidguard_config, F_SQUIDGUARD)); conf_mount_ro(); } # ------------------------------------------------------------------------------ # sg_reconfigure - squidguard reconfiguration # ------------------------------------------------------------------------------ function sg_reconfigure() { global $squidguard_config; $conf_file = SQUIDGUARD_LOGDIR . 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) { conf_mount_rw(); 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); conf_mount_ro(); sg_addlog("sg_reconfigure", "Save squidGuard config to '$conf_file'.", SQUIDGUARD_INFO); } else sg_addlog("sg_reconfigure", "Can't create squidGuard config.", SQUIDGUARD_ERROR); # 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.", SQUIDGUARD_INFO); } # 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.", SQUIDGUARD_INFO); } # 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; conf_mount_rw(); # 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'.", SQUIDGUARD_WARNING); } } # 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'.", SQUIDGUARD_WARNING); } # 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); } # 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'.", SQUIDGUARD_WARNING); } # set access right set_file_access($db_dir, OWNER_NAME, 0755); } conf_mount_ro(); # logrotate if (file_exists(SQUIDGUARD_SCR_LOGROTATE)) unlink(SQUIDGUARD_SCR_LOGROTATE); if ($squidguard_config[F_LOGROTATION] == 'on') { file_put_contents(SQUIDGUARD_SCR_LOGROTATE, sg_script_logrotate()); set_file_access (SQUIDGUARD_SCR_LOGROTATE, OWNER_NAME, 0755); } } # ============================================================================== # squidGuard DB # ============================================================================== # sg_reconfigure_user_db - reconfigure(update) db user entries # ------------------------------------------------------------------------------ function sg_reconfigure_user_db() { global $squidguard_config; conf_mount_rw(); $dbhome = $squidguard_config[F_DBHOME]; sg_addlog("sg_reconfigure_user_db", "Begin with '$dbhome'", SQUIDGUARD_INFO); # create user DB catalog, if not extsts if (!file_exists($dbhome)) { if (!mkdir($dbhome, 0755)) { sg_addlog("sg_reconfigure_user_db", "Can't create user DB directory '$dbhome'.", SQUIDGUARD_ERROR); return; } set_file_access($dbhome, OWNER_NAME, 0755); sg_addlog("sg_reconfigure_user_db", "Create user DB directory '$dbhome'.", SQUIDGUARD_INFO); } # 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", SQUIDGUARD_INFO); 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", "Can't create dir '$path'.", SQUIDGUARD_ERROR); return; } sg_addlog("sg_reconfigure_user_db", "Create dir '$path'.", SQUIDGUARD_INFO); } # 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';", SQUIDGUARD_INFO); } 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';", SQUIDGUARD_INFO); } 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';", SQUIDGUARD_INFO); } unset($expr); } # 5. recursive set files access set_file_access($dbhome, OWNER_NAME, 0755); # 6. rebuild user db ('/var/db/squidGuard') squidguard_rebuild_db("_usrdb", $dbhome, $dst_list); } else sg_addlog("sg_reconfigure_user_db", "User destinations list empty.", SQUIDGUARD_WARNING); # 7. remove unused db entries sg_remove_unused_db_entries(); conf_mount_ro(); } # ------------------------------------------------------------------------------ # sg_remove_unused_db_entries # ------------------------------------------------------------------------------ function sg_remove_unused_db_entries() { global $squidguard_config; conf_mount_rw(); $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 (SQUIDGUARD_BLK_FILELISTPATH) { $file_for_del = array(); # load blk entries $db_entries = explode("\n", file_get_contents(SQUIDGUARD_BLK_FILELISTPATH)); # $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'.", SQUIDGUARD_INFO); } else sg_addlog("sg_remove_unused_db_entries", "File'$file_fd' not found.", SQUIDGUARD_ERROR); } } } } conf_mount_ro(); } # ------------------------------------------------------------------------------ # 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_mount_rw(); $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'.", SQUIDGUARD_INFO); # 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'.", SQUIDGUARD_INFO); # *** 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'.", SQUIDGUARD_INFO); conf_mount_ro(); } */ # ------------------------------------------------------------------------------ # squidguard_rebuild_db Rebuild squidGuard DB from list items # ------------------------------------------------------------------------------ # $tag - rebuild task 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 squidguard_rebuild_db($tag, $rdb_dbhome, $rdb_itemslist) { global $squidguard_config; $dbhome = $rdb_dbhome; $logdir = $squidguard_config[F_LOGDIR]; $workdir = $squidguard_config[F_WORKDIR]; $conf_path = "{$workdir}/squidGuard_{$tag}rebuild.conf"; sg_addlog("squidguard_rebuild_db", "Begin with path '$dbhome'.", SQUIDGUARD_INFO); # make rebuild config; include all found dest items $dbitems = array(); if ($rdb_itemslist) { # items list as ['dest_key']='dest_DB_path' foreach ($rdb_itemslist as $it) { $dbitems[str_replace('/', '_', $it)] = $it; # replace path to name } } file_put_contents($conf_path, sg_create_simple_config($dbhome, $dbitems)); set_file_access($conf_path, OWNER_NAME, 0750); sg_addlog("squidguard_rebuild_db", "Create rebuild config '$conf_path'.", SQUIDGUARD_INFO); # rebuild blacklist db mwexec_bg("/usr/bin/nice -n20 " . SQUIDGUARD_BINPATH . "/squidGuard -c $conf_path -C all"); # wait while (exec("ps -auxwwww | grep 'squidGuard -c .* -C all' | grep -v grep | awk '{print $2}' | wc -l | awk '{ print $1 }'") > 0) { sleep (10); } set_file_access($dbhome, OWNER_NAME, 0755); sg_addlog("squidguard_rebuild_db", "Start rebuild DB.", SQUIDGUARD_INFO); } # ============================================================================== # Log # ------------------------------------------------------------------------------ # sg_addlog # ------------------------------------------------------------------------------ function sg_addlog($module, $log, $level = 0) { global $squidguard_config; # log disabled if ( SQUIDGUARD_GUILOG_ENABLE === false || $squidguard_config[F_ENABLEGUILOG] != 'on' ) return; # log level if ($level > SQUIDGUARD_GUILOG_LEVEL) return; if ($module) $module = "[$module]"; $leveltext = ""; switch($level) { case SQUIDGUARD_INFO: $leveltext = ""; break; case SQUIDGUARD_WARNING: $leveltext = "Warning"; break; default: $leveltext = "Error"; break; } $logfile = ''; $logfile = SQUIDGUARD_LOGDIR . SQUIDGUARD_CONFLOGFILE; $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] . SQUIDGUARD_CONFLOGFILE; } 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 : $module $leveltext $log"; if (count($log_content) > SQUIDGUARD_GUILOG_MAXCOUNT) array_splice($log_content, 0, SQUIDGUARD_GUILOG_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 . SQUIDGUARD_CONFLOGFILE; # define logfile if (!empty($squidguard_config) && file_exists($squidguard_config[F_LOGDIR])) $logfile = $squidguard_config[F_LOGDIR] . SQUIDGUARD_CONFLOGFILE; # 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", "Bad squidGuard config data.", SQUIDGUARD_ERROR); return sg_create_simple_config('', '', "Error! Check squidGuard configuration data." . " (sg_create_config: [1])."); } # check configuration data if (!sg_check_config_data(&$error_res)) { sg_addlog("sg_create_config", "Bad config data. It's all error_res: $error_res", SQUIDGUARD_ERROR); sg_addlog("sg_create_config", "Terminated.", SQUIDGUARD_ERROR); return sg_create_simple_config('', '', "Error! Check squidGuard configuration data." . " (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: $temp_str", SQUIDGUARD_INFO); } # --- 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 ($squidguard_config[F_ENABLELOG] == 'on' ) { if ($src[F_LOG]) $sg_tag->items[] = "log " . SQUIDGUARD_LOGFILE; } $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: $temp_str", SQUIDGUARD_INFO); } # --- 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", SQUIDGUARD_INFO); 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"; if ($squidguard_config[F_ENABLELOG] == 'on' ) { $sg_tag->items[] = "log ". SQUIDGUARD_LOGFILE; } $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: $log_entr_added .", SQUIDGUARD_INFO); if (!empty($log_entr_ignored)) sg_addlog("sg_create_config", "Ignored: $log_entr_ignored .", SQUIDGUARD_WARNING); } # --- 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 ($squidguard_config[F_ENABLELOG] == 'on' ) { if ($dst[F_LOG]) $sg_tag->items[] = "log " . SQUIDGUARD_LOGFILE; } $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: $temp_str", SQUIDGUARD_INFO); } # --- 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 ($squidguard_config[F_ENABLELOG] == 'on' ) { if ($rew[F_LOG]) $sg_tag->items[] = "log " . SQUIDGUARD_LOGFILE; } $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 if (!empty($log_entr_added)) sg_addlog("sg_create_config", "Add rewrites: $log_entr_added", SQUIDGUARD_INFO); if (!empty($log_entr_err)) sg_addlog("sg_create_config", "Add rewrites error $log_entr_err", SQUIDGUARD_ERROR); } # ---------------------------------------- $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 () $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 ($squidguard_config[F_ENABLELOG] == 'on' ) { if ($acl[F_LOG]) $sg_acltag->items[] = "log " . SQUIDGUARD_LOGFILE; } # 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 ($squidguard_config[F_ENABLELOG] == 'on' ) { if ($acl[F_LOG]) $sg_acltag->items[] = "log " . SQUIDGUARD_LOGFILE; } } $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: $log_entr_added", SQUIDGUARD_INFO); } # --- Default --- $sg_tag_def = new TSgTag; $sg_tag_def->set("default", "", "", ""); $def = $squidguard_config[F_DEFAULT]; sg_addlog("sg_create_config", "Add Default", SQUIDGUARD_INFO); 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 () $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 ($squidguard_config[F_ENABLELOG] == 'on' ) { if ($def[F_LOG]) $sg_tag_def->items[] = "log " . SQUIDGUARD_LOGFILE; } } # <- if def else { $msg = "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.", SQUIDGUARD_ERROR); } # --- 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 = $blk_dbhome ? $blk_dbhome : $squidguard_config[F_DBHOME]; sg_addlog("sg_create_simple_config", "Begin with dbhome='$dbhome'.", SQUIDGUARD_INFO); # 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'.", SQUIDGUARD_INFO); } else sg_addlog("sg_create_simple_config", "Ignored empty item '$dst' = '$dbhome/$dpath'.", SQUIDGUARD_WARNING); } } # 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'; $rdr_path = "http://$guiip:$guiport" . REDIRECT_BASE_URL; # check redirect $errmsg = ''; if (!sg_check_redirect($redirect_mode, $rdr_info, &$errmsg)) { $redirect_mode = RMOD_INT_ERRORPAGE; $rdr_info = "Bad redirect settings. $errmsg Check you configuration."; sg_addlog("sg_redirector_base_url", "$errmsg", SQUIDGUARD_ERROR); } 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)", SQUIDGUARD_INFO); return $rdr_path; } # ------------------------------------------------------------------------------------------------- # sg_aclpass_reorder # ------------------------------------------------------------------------------------------------- function sg_aclpass_reorder($pass) { $ar_pass = explode(" ", $pass); # 'pass' order: 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 --- if ($squidguard_config[F_BLACKLISTENABLED]) { $blk_entries_file = SQUIDGUARD_BLK_FILELISTPATH; 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); } # ========================== UTILS ============================================= # ------------------------------------------------------------------------------ # ============================================================================== # 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; } # ****************************************************************************** # 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 # ------------------------------------------------------------------------------ if(!function_exists("is_url")) { 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_sg($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_sg($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 or ip foreach ($dm as $d_it) { if ($d_it && !is_domain_valid($d_it) && !is_ipaddr($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(); if (!is_array($db_entries)) return; $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; } # ----------------------------------------------------------------------------- # sg_script_logrotate # ----------------------------------------------------------------------------- function sg_script_logrotate() { global $squidguard_config; $sglogname = $squidguard_config[F_LOGDIR] . "/" . SQUIDGUARD_LOGFILE; $res = << $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 'squidGuard' package"); configure_cron(); } } else { # ! error $name ! return; } } # ***************************************************************************** # RAMDisk # Temp ramdisk for quickly DB update # ***************************************************************************** function squidguard_ramdisk($enable) { $ramsize = 200; # delete old squidguard ramdisk if (file_exists("/dev/md15")) { mwexec("umount -f " . SQUIDGUARD_TMP); mwexec("sleep 1"); mwexec("mdconfig -d -u 15"); } if ($enable === true) { # create temp ramdisk # size 300Mb very nice for work with Archive < 30Mb # this is size use physical RAM + Swap file mwexec("/sbin/mdmfs -s {$ramsize}M md15 " . SQUIDGUARD_TMP); mwexec("chmod 1777 " . SQUIDGUARD_TMP); } } # ****************************************************************************** # Blacklist # ****************************************************************************** # ------------------------------------------------------------------------------ # squidguard_update_stat # ------------------------------------------------------------------------------ function squidguard_update_log($msg, $new="") { $to = $new ? ">" : ">>"; # create new or save to exists file mwexec("echo $msg $to " . SG_UPDATE_STATFILE); } # ----------------------------------------------------------------------------- # squidguard_blacklist_update_start() # ----------------------------------------------------------------------------- function squidguard_blacklist_update_start($url_filename) { # 1. if started - calncel if (squidguard_blacklist_update_IsStarted()) squidguard_blacklist_update_cancel(); # 2. delete old script if (file_exists(SCR_NAME_BLKUPDATE)) unlink(SCR_NAME_BLKUPDATE); # 3. create new php script & set permissions file_put_contents(SCR_NAME_BLKUPDATE, squidguard_script_blacklistupdate($url_filename, "")); set_file_access (SCR_NAME_BLKUPDATE, OWNER_NAME, 0755); # 4. start script background mwexec_bg(SCR_NAME_BLKUPDATE); } # ----------------------------------------------------------------------------- # squidguard_blacklist_update_cancel() # ----------------------------------------------------------------------------- function squidguard_blacklist_update_cancel() { # kill script and SG update process mwexec("kill `ps auxwwww | grep '" . SCR_NAME_BLKUPDATE . "' | grep -v 'grep' | awk '{print $2}'`"); mwexec("kill `ps auxwwww | grep 'squidGuard -c .* -C all' | grep -v 'grep' | awk '{print $2}'`"); squidguard_ramdisk(false); squidguard_update_log("Blacklist update terminated by user.", ""); } # ----------------------------------------------------------------------------- # squidguard_blacklist_update_IsStarted() # ----------------------------------------------------------------------------- function squidguard_blacklist_update_IsStarted() { return exec("ps auxwwww | grep '" . SCR_NAME_BLKUPDATE . "' | grep -v 'grep' | awk '{print $2}' | wc -l | awk '{ print $1 }'"); } # ----------------------------------------------------------------------------- # 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 blacklist update.", SQUIDGUARD_INFO); squidguard_update_log("Begin blacklist update", "New"); # 1. check system sg_check_system(); # 2. download if ($sf[0] === "/") { # local file - example '/tmp/blacklists.tar' sg_addlog("sg_reconfigure_blacklist", "Update from file '$sf'.", SQUIDGUARD_INFO); squidguard_update_log("Copy archive from file '$sf'"); if (file_exists($sf)) { $sf_contents = file_get_contents($sf); } else { sg_addlog("sg_reconfigure_blacklist", "File '$sf' not found.", SQUIDGUARD_ERROR); squidguard_update_log("File '$sf' not found."); return; } } # from url else { sg_addlog("sg_reconfigure_blacklist", "Download from url '$sf'.", SQUIDGUARD_INFO); squidguard_update_log("Start download."); $sf_contents = sg_uploadfile_from_url($sf, $opt); } # 3. update if (empty($sf_contents)) { sg_addlog("sg_reconfigure_blacklist", "Bad content from '$sf'. Terminate.", SQUIDGUARD_ERROR); squidguard_update_log("Bad content from '$sf'. Terminate."); return; } # save black list archive content to local file file_put_contents(SG_UPDATE_TARFILE, $sf_contents); # update blacklist sg_update_blacklist(SG_UPDATE_TARFILE); } # ------------------------------------------------------------------------------ # sg_update_blacklist - update blacklist from file # How it's work: # - unpack tar archive to temp dir # - copy subdir's tree to one-level TempDB # - rebuild TempDB # - create Blacklist files listing and copy to values dir and TempDB 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; $workdir = SQUIDGUARD_WORKDIR; $tmp_unpack_dir = SQUIDGUARD_TMP . SQUIDGUARD_BL_UNPACK; $arc_db_dir = SQUIDGUARD_TMP . SG_BLK_ARC; $conf_path = SQUIDGUARD_VAR . DB_REBUILD_BLK_CONF; $blklist_file = SQUIDGUARD_BLK_FILELISTPATH; sg_addlog("sg_update_blacklist", "Begin with '$from_file'.", SQUIDGUARD_INFO); 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"); squidguard_ramdisk(false); # create new tmp/arc dir's, use ramdisk for quick operations squidguard_ramdisk(true); mwexec("mkdir -p -m 0755 $tmp_unpack_dir"); mwexec("mkdir -p -m 0755 $arc_db_dir"); # 1. unpack archive squidguard_update_log("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'.", SQUIDGUARD_INFO); # 2. copy blacklist to TempDB base & create entries list squidguard_update_log("Scan blacklist categories."); 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.", SQUIDGUARD_INFO); } } set_file_access($arc_db_dir, OWNER_NAME, 0755); # create entries list if (count($blk_items)) { # save to temp DB $cont = implode("\n", array_keys($blk_items)); # temp blacklist files $blklist_file = $arc_db_dir . SQUIDGUARD_BLK_FILELIST; file_put_contents($blklist_file, $cont); set_file_access ($blklist_file, OWNER_NAME, 0755); # system blacklist files $blklist_file = SQUIDGUARD_BLK_FILELISTPATH; file_put_contents($blklist_file, $cont); set_file_access ($blklist_file, OWNER_NAME, 0755); sg_addlog("sg_update_blacklist", "Create DB entries list '$blklist_file'.", SQUIDGUARD_INFO); squidguard_update_log("Found " . count($blk_items) . " items."); } # rebuild db & save to work dir squidguard_update_log("Start rebuild DB."); squidguard_rebuild_db("blk_", $arc_db_dir, $blk_list); squidguard_update_log("Copy DB to workdir."); mwexec("cp -R -p $arc_db_dir/ $dbhome"); mwexec("cp -f -p $blklist_file " . SQUIDGUARD_WORKDIR); set_file_access($dbhome, OWNER_NAME, 0755); squidguard_update_log("Reconfigure Squid proxy."); mwexec("/usr/local/sbin/squid -k reconfigure"); squidguard_update_log("Blacklist update complete."); } # free ramdisk squidguard_ramdisk(false); } else sg_addlog("sg_update_blacklist", "File $from_file not found.", SQUIDGUARD_ERROR); } # ----------------------------------------------------------------------------- # sg_entries_blacklist # ----------------------------------------------------------------------------- function sg_entries_blacklist() { $contents = ''; $fl = SQUIDGUARD_BLK_FILELISTPATH; 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'.", SQUIDGUARD_INFO); # make dest list $blklist_file = SQUIDGUARD_BLK_FILELISTPATH; 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') squidguard_rebuild_db("_blkdb", $dbhome, $dst_list); } */ # ----------------------------------------------------------------------------- # sg_uploadfile_from_url # ----------------------------------------------------------------------------- function sg_uploadfile_from_url($url_file, $proxy = '') { $err = 0; $download_tmpfile = SG_UPDATE_TMPFILE; #"/tmp/squidguard_download.tmp"; $download_logfile = SG_UPDATE_LOGFILE; #"/tmp/squidguard_download.log"; conf_mount_rw(); # open destination file $s = "Download archive '$url_file'" . ( $proxy ? " via proxy'$proxy'" : "" ); sg_addlog("sg_uploadfile_from_url", $s, SQUIDGUARD_INFO); squidguard_update_log( $s ); # open temp and log files for curl $ftmp = fopen($download_tmpfile, "w"); # download result file $flog = fopen($download_logfile, "w"); # download log file $result = ''; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url_file); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_NOPROGRESS, 0); curl_setopt($ch, CURLOPT_FILE, $ftmp); curl_setopt($ch, CURLOPT_STDERR, $flog); 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_exec ($ch); $err = curl_errno($ch); if ($err) squidguard_update_log( "Download error: " . curl_error($ch) ); else squidguard_update_log( "Download complete" ); curl_close ($ch); # close temp and log files fclose($ftmp); fclose($flog); conf_mount_ro(); if (!$err && file_exists( $download_tmpfile )) $result = file_get_contents( $download_tmpfile ); return $result; } # ------------------------------------------------------------------------------ # squidguard_blacklist_restore_arcdb - copy arc blacklist to db # ------------------------------------------------------------------------------ function squidguard_blacklist_restore_arcdb() { global $squidguard_config; $dbhome = $squidguard_config[F_DBHOME] ? $squidguard_config[F_DBHOME] : SQUIDGUARD_DBHOME; $blklist_file = SQUIDGUARD_BLK_FILELISTPATH; $arc_db_dir = SQUIDGUARD_DBSAMPLE; squidguard_update_log("Restore default blacklist DB.", "new"); if (file_exists($arc_db_dir)) { conf_mount_rw(); # 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("squidguard_blacklist_restore_arcdb", "Restore blacklist archive from '$arc_db_dir'.", SQUIDGUARD_INFO); # generate blacklist files list $blklist = ""; $files = scan_dir("$arc_db_dir/"); if ($files) $blklist = implode("\n", $files); file_put_contents($blklist_file, $blklist); set_file_access($blklist_file, OWNER_NAME, 0755); squidguard_rebuild_db("arc_", $dbhome, $files); squidguard_update_log("Reconfigure Squid proxy."); mwexec("/usr/local/sbin/squid -k reconfigure"); conf_mount_ro(); squidguard_update_log("Restore success."); } else { sg_addlog("squidguard_blacklist_restore_arcdb", "File '$arc_db_dir' or '$blklist_file' not found.", SQUIDGUARD_ERROR); squidguard_update_log("Restore error: File '$arc_db_dir' or '$blklist_file' not found."); } } # ------------------------------------------------------------------------------ # 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; } } # ============================================================================= # Blacklist Scripts # ============================================================================= # squidGuard blacklist update php script function squidguard_script_blacklistupdate($fname, $opt) { $sh[] = "#!/usr/local/bin/php -f"; $sh[] = ""; return implode ("\n", $sh); } # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ # 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); } } ?>