-- acf model for squid -- Copyright(c) 2007 A. Brodmann - Licensed under terms of GPL2 module (..., package.seeall) require "format" squidconf = "/etc/squid/squid.conf" squidtempl = "/etc/squid/squid.conf.template" --- the tokenizer functions - must be dislocated into a library later tokenizer = {} tokenizer.new = function( str, delim ) local token = {} token.value = str; token.delim = delim; token.pos = 1 return token end tokenizer.pos = function( value, substr, pos ) local retval = pos local done = false while not done and retval <= #value do if string.sub( value, retval, retval ) == substr then done = true else retval = retval + 1 end end return retval end tokenizer.next = function( token ) if token.pos > #token.value then return token, nil end local strpos = tokenizer.pos( token.value, token.delim, token.pos ) retval = string.sub(token.value, token.pos, strpos-1) if retval == token.delim then retval = "" token.pos = token.pos + 1 else token.pos = strpos + 1 end return token, retval end --- get_status = function() local retval = "stopped" local ptr = io.popen( "/bin/pidof squid" ) local pid = ptr:read( "*a" ) ptr:close() if pid ~= nil then if #pid > 1 then retval = "running" end end return retval end get_squid_version = function() local retval = "" local ptr = io.popen( "/usr/sbin/squid -v" ) if ptr ~= nil then retval = ptr:read( "*l" ) ptr:close() else retval = "Error - can't retrieve squid version" end return retval end get_winbind_version = function() local retval = "" local ptr = io.popen( "/usr/sbin/winbindd -V" ) if ptr ~= nil then retval = ptr:read( "*l" ) ptr:close() else retval = "Error - can't retrieve winbindd version" end return retval end get_status_winbindd = function() local retval = "stopped" local ptr = io.popen( "/bin/pidof winbindd" ) local pid = ptr:read( "*a" ) ptr:close() if pid ~= nil then if #pid > 1 then retval = "running" end end return retval end service_control = function( control ) local retval = "" local ptr = io.popen( "/etc/init.d/squid " .. control, "r" ) if ptr ~= nil then local retmsg = ptr:read( "*a" ) ptr:close() if retmsg ~= nil then retval = retmsg else retval = "service_control(): Failed to read output from initscript!\n" end else retval = "service_control(): Failed to start/stop/restart service!\n" end return retval end service_control_winbindd = function( control ) local retval = "" local ptr = io.popen( "/etc/init.d/winbindd " .. control, "r" ) if ptr ~= nil then local retmsg = ptr:read( "*a" ) ptr:close() if retmsg ~= nil then retval = retmsg else retval = "service_control(): Failed to read output from initscript!\n" end else retval = "service_control(): Failed to start/stop/restart service!\n" end return retval end get_winbindd_config = function() local error = "" local config = { domain = { value="", type="text", label="domain" }, dcname = { value="", type="text", label="DC NetBIOS name" }, dcipaddr = { value="", type="text", label="DC IP Address" }, interfaces = { value="", type="text", label="interfaces" }, loglevel = { value="", type="text", label="0" }, account = { value="", type="text", label="account" }, password = { value="", type="text", label="password" } } local ptr = io.open( "/etc/samba/smb.conf" ) if ptr ~= nil then else end end get_adv_config = function() local retval = "" local ptr = io.open( squidconf, "r" ) if ptr ~= nil then local retcfg = ptr:read( "*a" ) ptr:close() if retcfg == nil then retval = "\n\n Error: Failed to read " .. squidconf .. "!\n\n" else retval = retcfg end end return retval end get_digest_userlist = function() local retval = "" local ptr = io.open( "/etc/squid/users.list" ) if ptr ~= nil then local retcfg = ptr:read( "*a" ) ptr:close() if retcfg == nil then retval = "\n\n Error: Failed to read user/password list!\n\n" else retval = retcfg end end return retval end get_saccess = function() local config = {} config.s_ip = get_file_contents( "/etc/squid/anoniplist" ) config.s_browser = get_file_contents( "/etc/squid/anonbrowserlist" ) config.s_domain = get_file_contents( "/etc/squid/anondomainlist" ) return config end update_saccess = function( config ) write_file_contents( "/etc/squid/anoniplist", config.s_ip ) write_file_contents( "/etc/squid/anonbrowserlist", config.s_browser ) write_file_contents( "/etc/squid/anondomainlist", config.s_domain ) return end write_file_contents = function( name, contents ) local ptr = io.open( name, "wb+" ) if ptr ~= nil then ptr:write( format.dostounix( contents ) ) ptr:close() end return end get_file_contents = function( name ) local retval = "" local ptr = io.open( name ) if ptr ~= nil then retval = ptr:read( "*a" ) ptr:close() if retval == nil then retval = "" end end return retval end update_adv_config = function( config ) local retval = "Successfully updated " .. squidconf .. "!" local ptr = io.open( squidconf, "wb+" ) if ptr ~= nil then ptr:write( format.dostounix( config ) ) ptr:close() else retval = "update_config(): Error, failed to open " .. squidconf .. "!\n" end return retval end update_digest_userlist = function( config ) local retval = "Successfully updated user list!" local ptr = io.open( "/etc/squid/users.list", "wb+" ) if ptr ~= nil then ptr:write( format.dostounix( config ) ) ptr:close() else retval = "Update Digest User List: Error, failed to open /etc/squid/users.list!\n" end end get_conf_tag = function( tag, gat ) local retval = "" local error = "" local found = false local done = false local fptr = io.open( squidconf, "r" ) if fptr == nil then return "", "Failed to open squid config file!" end while not found and not done do local line = fptr:read( "*l" ) if line == nil then done = true else if string.sub( line, 1, 22 ) == tag then found = true end end end if done then fptr:close() return "", "TAG not found in squid config!" end found = false done = false while not found and not done do local line = fptr:read( "*l" ) if line == nil then done = true elseif string.sub( line, 1, 22 ) == gat then found = true else retval = retval .. "\n" .. line end end if done then fptr:close() return "", "End TAG (GAT) not found in squid config! '" .. gat .. "'" end fptr:close() return retval, error end get_basic_config = function() local error = "" local config = { proxyip = { value="empty", type="text", label="Proxy IP" }, proxyport = { value="", type="text", label="Proxy Port" }, filterip = { value="", type="text", label="Filter IP" }, filterport = { value="", type="text", label="Filter Port" }, filterregex = { value="", type="text", label="FilterRegex" }, safeports = { value="", type="text", label="Safe_ports" }, sslports = { value="", type="text", label="SSL_ports" }, accesslog = { value="", type="select", label="Access Logs", option={ "yes", "no" } }, diskcache = { value="", type="select", label="Disk Cache Parameters", option={ "yes", "no" } }, authmethod = { value="", type="text", label="Authentication Method" } } local cfg1, error = get_conf_tag( "### ACF-SQUID-TAG-0001", "### ACF-SQUID-GAT-0001" ) if #error > 0 then return config, error end local cfg1tok = "" local cfg2tok = "" local cfg3tok = "" --- get proxyip, proxyport cfg1tok = tokenizer.new( cfg1, "\n" ) local done = false while not done do local str1 = "" cfg1tok, str1 = tokenizer.next( cfg1tok ) if str1 == nil then return nil, "Corrupt squid.conf! Missing 'http_port' statement!" else if string.sub( str1, 1, 10 ) == "http_port " then local str2 = "" local ipport = "" local ip = "" local port = "" cfg2tok = tokenizer.new( str1, " " ) cfg2tok, ipport = tokenizer.next( cfg2tok ) cfg2tok, ipport = tokenizer.next( cfg2tok ) if ipport == nil then return config, "Corrupt squid.conf! Missing parameter #1 for 'http_port' statement!" end cfg3tok = tokenizer.new( ipport, ":" ) cfg3tok, ip = tokenizer.next( cfg3tok ) cfg3tok, port = tokenizer.next( cfg3tok ) if port == nil then port = ip ip = "" end config.proxyip.value = ip config.proxyport.value = port done = true end end end cfg1tok = nil cfg2tok = nil cfg3tok = nil --- get filterip, filterport local cfg1, error = get_conf_tag( "### ACF-SQUID-TAG-0007", "### ACF-SQUID-GAT-0007" ) if #error > 0 then return config, error end cfg1tok = tokenizer.new( cfg1, "\n" ) done = false while not done do local str1 = "" cfg1tok, str1 = tokenizer.next( cfg1tok ) if str1 == nil then return nil, "Corrupt squid.conf! Missing 'cache_peer' statement!" else if string.sub( str1, 1, 11 ) == "cache_peer " then local str2 = "" local tmp = "" local ip = "" local port = "" cfg2tok = tokenizer.new( str1, " " ) cfg2tok, tmp = tokenizer.next( cfg2tok ) cfg2tok, ip = tokenizer.next( cfg2tok ) cfg2tok, tmp = tokenizer.next( cfg2tok ) cfg2tok, port = tokenizer.next( cfg2tok ) if ip == nil or port == nil then return config, "Corrupt squid.conf! Missing parameters #2 and/or #4 for 'cache_peer' statement!" end config.filterip.value = ip config.filterport.value = port done = true end end end cfg1tok = nil cfg2tok = nil cfg3tok = nil --- get diskcache local cfg1, error = get_conf_tag( "### ACF-SQUID-TAG-0002", "### ACF-SQUID-GAT-0002" ) if #error > 0 then return config, error end cfg1tok = tokenizer.new( cfg1, "\n" ) done = false while not done do local str1 = "" cfg1tok, str1 = tokenizer.next( cfg1tok ) if str1 == nil then return nil, "Corrupt squid.conf! Missing 'cache_dir' statement!" else if string.sub( str1, 1, 15 ) == "cache_dir diskd" then config.diskcache.value = "yes" done = true elseif string.sub( str1, 1, 14 ) == "cache_dir null" then config.diskcache.value = "no" done = true end end end cfg1tok = nil --- get cache_access log local cfg1, error = get_conf_tag( "### ACF-SQUID-TAG-0003", "### ACF-SQUID-GAT-0003" ) if #error > 0 then return config, error end cfg1tok = tokenizer.new( cfg1, "\n" ) done = false local str1 = "" while str1 ~= nil do cfg1tok, str1 = tokenizer.next( cfg1tok ) if str1 ~= nil then if string.sub( str1, 1, 16 ) == "cache_access_log" then config.accesslog.value = "yes" elseif string.sub( str1, 1, 17 ) == "#cache_access_log" or string.sub( str1, 1, 18 ) == "# cache_access_log" then config.accesslog.value = "no" end end end if config.accesslog.value == "" then return nil, "Corrupt squid.conf! Missing 'cache_access_log' statement!" end cfg1tok = nil --- authentication method local cfg1, error = get_conf_tag( "### ACF-SQUID-TAG-0004", "### ACF-SQUID-GAT-0004" ) if #error > 0 then return config, error end cfg1tok = tokenizer.new( cfg1, "\n" ) local done = false local auth = "" while not done do local str1 = "" cfg1tok, str1 = tokenizer.next( cfg1tok ) if str1 == nil then done = true else if string.sub( str1, 1, 18 ) == "auth_param digest " then if string.match( auth, "D" ) == nil then auth = auth .. "D" end elseif string.sub( str1, 1, 16 ) == "auth_param ntlm " then if string.match( auth, "N" ) == nil then auth = auth .. "N" end elseif string.sub( str1, 1, 17 ) == "auth_param basic " then if string.match( auth, "B" ) == nil then auth = auth .. "B" end end end end config.authmethod.value = auth cfg1tok = nil --- get filterregex local cfg1, error = get_conf_tag( "### ACF-SQUID-TAG-0005", "### ACF-SQUID-GAT-0005" ) if #error > 0 then return config, error end cfg1tok = tokenizer.new( cfg1, "\n" ) done = false while not done do local str1 = "" cfg1tok, str1 = tokenizer.next( cfg1tok ) if str1 == nil then return nil, "Corrupt squid.conf! Missing 'acl ContentFilter urlpath_regex -i' statement!" else if string.sub( str1, 1, 35 ) == "acl ContentFilter urlpath_regex -i " then config.filterregex.value = string.sub( str1, 36 ) done = true end end end cfg1tok = nil cfg2tok = nil cfg3tok = nil --- get SSL_ports, Safe_ports local done1 = false local done2 = false cfg1tok = tokenizer.new( cfg1, "\n" ) while not done1 or not done2 do local str1 = "" cfg1tok, str1 = tokenizer.next( cfg1tok ) if str1 == nil then return nil, "Corrupt squid.conf! Missing 'acl SSL_ports/Safe_ports' statement!" else if string.sub( str1, 1, 19 ) == "acl SSL_ports port " then config.sslports.value = string.sub( str1, 20 ) done1 = true elseif string.sub( str1, 1, 20 ) == "acl Safe_ports port " then config.safeports.value = string.sub( str1, 21 ) done2 = true end end end cfg1tok = nil return config, error end config_preblock_copy = function( fromfile, tofile, tag ) local done = false local line = "" while not done do line = fromfile:read( "*l" ) tofile:write( line .. "\n" ) if string.sub( line, 1, #tag ) == tag then done = true end end end config_postblock_copy = function( fromfile, tofile ) local done = false local line = "" while not done do line = fromfile:read( "*l" ) if line ~= nil then tofile:write( line .. "\n" ) else done = true end end end update_basic_config = function( config ) local error = "" --- put proxyip, proxyport local tmpfilename = os.tmpname() local tmpfile = io.open( tmpfilename, "w+" ) local cfgfile = io.open( squidconf, "r" ) local done = false config_preblock_copy( cfgfile, tmpfile, "### ACF-SQUID-TAG-0001" ) local don2 = false while not done do line = cfgfile:read( "*l" ) if string.sub( line, 1, 22 ) == "### ACF-SQUID-GAT-0001" then done = true end if don2 then tmpfile:write( line .. "\n" ) else if string.sub( line, 1, 10 ) == "http_port " then don2 = true tmpfile:write( "http_port " .. config.proxyip.value .. ":" .. config.proxyport.value .. "\n" ) else tmpfile:write( line .. "\n" ) end end end config_postblock_copy( cfgfile, tmpfile ) tmpfile:close() cfgfile:close() os.rename( tmpfilename, squidconf ) --- put filterip, filterport tmpfilename = os.tmpname() tmpfile = io.open( tmpfilename, "w+" ) cfgfile = io.open( squidconf, "r" ) done = false config_preblock_copy( cfgfile, tmpfile, "### ACF-SQUID-TAG-0007" ) local don2 = false while not done do line = cfgfile:read( "*l" ) if string.sub( line, 1, 22 ) == "### ACF-SQUID-GAT-0007" then done = true end if don2 then tmpfile:write( line .. "\n" ) else if string.sub( line, 1, 11 ) == "cache_peer " then don2 = true local lap = 1 local cfg2tok = tokenizer.new( line, " " ) local tmpval = "" local newstr = "" local tmparr = {} cfg2tok, tmpval = tokenizer.next( cfg2tok ) while tmpval ~= nil do tmparr[lap] = tmpval if lap == 2 then newstr = newstr .. config.filterip.value .. " " elseif lap == 4 then newstr = newstr .. config.filterport.value .. " " else newstr = newstr .. tmpval .. " " end lap = lap + 1 cfg2tok, tmpval = tokenizer.next( cfg2tok ) end tmpfile:write( newstr .. "\n" ) else tmpfile:write( line .. "\n" ) end end end config_postblock_copy( cfgfile, tmpfile ) tmpfile:close() cfgfile:close() os.rename( tmpfilename, squidconf ) --- disk cache parameters tmpfilename = os.tmpname() tmpfile = io.open( tmpfilename, "w+" ) cfgfile = io.open( squidconf, "r" ) done = false config_preblock_copy( cfgfile, tmpfile, "### ACF-SQUID-TAG-0002" ) while not done do line = cfgfile:read( "*l" ) if string.sub( line, 1, 7 ) == "### ACF" then done = true tmpfile:write( line .. "\n" ) else if config.diskcache.value == "yes" then if string.sub( line, 1, 16 ) == "#cache_dir diskd" then tmpfile:write( string.sub( line, 2 ) .. "\n" ) elseif string.sub( line, 1, 14 ) == "cache_dir null" then tmpfile:write( "#" .. line .. "\n" ) else tmpfile:write( line .. "\n" ) end else if string.sub( line, 1, 15 ) == "cache_dir diskd" then tmpfile:write( "#" .. line .. "\n" ) elseif string.sub( line, 1, 15 ) == "#cache_dir null" then tmpfile:write( string.sub( line, 2 ) .. "\n" ) else tmpfile:write( line .. "\n" ) end end end end config_postblock_copy( cfgfile, tmpfile ) tmpfile:close() cfgfile:close() os.rename( tmpfilename, squidconf ) --- cache access log parameters tmpfilename = os.tmpname() tmpfile = io.open( tmpfilename, "w+" ) cfgfile = io.open( squidconf, "r" ) done = false config_preblock_copy( cfgfile, tmpfile, "### ACF-SQUID-TAG-0003" ) while not done do line = cfgfile:read( "*l" ) if string.sub( line, 1, 7 ) == "### ACF" then done = true tmpfile:write( line .. "\n" ) else if config.accesslog.value == "yes" then if string.sub( line, 1, 17 ) == "#cache_access_log" then tmpfile:write( string.sub( line, 2 ) .. "\n" ) elseif string.sub( line, 1, 18 ) == "# cache_access_log" then tmpfile:write( string.sub( line, 3 ) .. "\n" ) else tmpfile:write( line .. "\n" ) end else if string.sub( line, 1, 16 ) == "cache_access_log" then tmpfile:write( "#" .. line .. "\n" ) else tmpfile:write( line .. "\n" ) end end end end config_postblock_copy( cfgfile, tmpfile ) tmpfile:close() cfgfile:close() os.rename( tmpfilename, squidconf ) --- cache access log parameters tmpfilename = os.tmpname() tmpfile = io.open( tmpfilename, "w+" ) cfgfile = io.open( squidconf, "r" ) done = false config_preblock_copy( cfgfile, tmpfile, "### ACF-SQUID-TAG-0005" ) while not done do line = cfgfile:read( "*l" ) if string.sub( line, 1, 7 ) == "### ACF" then done = true tmpfile:write( line .. "\n" ) else if string.sub( line, 1, 18 ) == "acl SSL_ports port" then tmpfile:write( "acl SSL_ports port " .. config.sslports.value .. "\n" ) elseif string.sub( line, 1, 19 ) == "acl Safe_ports port" then tmpfile:write( "acl Safe_ports port " .. config.safeports.value .. "\n" ) elseif string.sub( line, 1, 34 ) == "acl ContentFilter urlpath_regex -i" then tmpfile:write( "acl ContentFilter urlpath_regex -i " .. config.filterregex.value .. "\n" ) else tmpfile:write( line .. "\n" ) end end end config_postblock_copy( cfgfile, tmpfile ) tmpfile:close() cfgfile:close() os.rename( tmpfilename, squidconf ) return error end upd_authmethod = function( method ) local tmpfilename = os.tmpname() local tmpfile = io.open( tmpfilename, "w+" ) local cfgfile = io.open( squidconf, "r" ) local error = "" local line = "" local done = false config_preblock_copy( cfgfile, tmpfile, "### ACF-SQUID-TAG-0004" ) while not done do line = cfgfile:read( "*l" ) if string.sub( line, 1, 7 ) == "### ACF" then done = true tmpfile:write( line .. "\n" ) else if string.sub( line, 1, 17 ) == "auth_param digest" then if string.find( method, "D" ) ~= nil then tmpfile:write( line .. "\n" ) else tmpfile:write( "#" .. line .. "\n" ) end elseif string.sub( line, 1, 18 ) == "#auth_param digest" then if string.find( method, "D" ) ~= nil then tmpfile:write( string.sub( line, 2 ) .. "\n" ) else tmpfile:write( line .. "\n" ) end elseif string.sub( line, 1, 15 ) == "auth_param ntlm" then if string.find( method, "N" ) ~= nil then tmpfile:write( line .. "\n" ) else tmpfile:write( "#" .. line .. "\n" ) end elseif string.sub( line, 1, 16 ) == "#auth_param ntlm" then if string.find( method, "N" ) ~= nil then tmpfile:write( string.sub( line, 2 ) .. "\n" ) else tmpfile:write( line .. "\n" ) end else tmpfile:write( line .. "\n" ) end end end config_postblock_copy( cfgfile, tmpfile ) tmpfile:close() cfgfile:close() os.rename( tmpfilename, squidconf ) return error end dependancy_ok = function() local retval = false local cfgfile = io.open( squidconf ) local line = "" if cfgfile ~= nil then line = cfgfile:read( "*l" ) if string.sub( line, 1, 19 ) == "### ACF-SQUID-MAGIC" then retval = true end end return retval end create_cfg_from_template = function() local from = io.open( squidtempl ) local to = io.open( squidconf, "wb+" ) local line = "" while line ~= nil do line = from:read( "*l" ) if line ~= nil then to:write( line .. "\n" ) end end from:close() to:close() return end