--- /dev/null
+-- module to access linux ARP cache
+
+config = require "config"
+
+_arpcache = {}
+_ARPCACHE4 = '/sbin/ip -4 n'
+_ARPCACHE6 = '/sbin/ip -6 n'
+
+function _match_v4(ip)
+ return string.match(ip,"%d*%.%d*%.%d*%.%d*")
+end
+
+function _arpcache.get_mac(ip)
+
+ local cmd
+ if _match_v4(ip) then
+ cmd = _ARPCACHE4
+ else
+ cmd = _ARPCACHE6
+ end
+
+ local f = io.popen(cmd)
+ local res = nil
+ local line, w
+
+ while true do
+
+ line = f:read()
+ if not line then
+ break
+ end
+
+ w = {}
+
+ for k in string.gmatch(line, "(%S+)") do
+ table.insert(w, k)
+ end
+
+ if w[1]==ip then
+ res = w[5]
+ break
+ end
+
+ end
+
+ f:close()
+ return res
+
+end
+
+return _arpcache
--- /dev/null
+{
+
+"ident": {
+ "timeout": 2,
+ "default": ""
+},
+
+"portmap" : {
+
+ "3128" : "80",
+ "3130" : "80",
+ "3131" : "443",
+ "3132" : "443"
+
+},
+
+"hosts" : {
+ "ip": {
+
+ "192.168.1.100": "*ident",
+ "2001:470:6f:9d5::100": "*ident",
+
+ "192.168.1.4": "net"
+
+ },
+
+ "mac": {
+
+ "00:1f:c6:86:f7:9c": "*ident",
+
+ "90:a2:da:f8:0b:73": "media",
+
+ "ea:cf:b0:f9:24:43": "camera"
+
+ }
+
+ }
+
+}
--- /dev/null
+json = require "json"
+
+_config = {}
+
+function _config.read(file)
+
+ local file = file or "/opt/squid-auth-helper/config.json"
+ local f = assert(io.open(file))
+ local cfg = json.decode(f:read("*all"))
+
+ _config.pmap = cfg["portmap"] or {}
+
+ _config.ident_timeout = 2
+ _config.ident_default = nil
+
+ if cfg["ident"] then
+ _config.ident_timeout = cfg["ident"]["timeout"] or _config.ident_timeout
+ _config.ident_default = cfg["ident"]["default"] or _config.ident_default
+ end
+
+ _config.ipmap = {}
+ _config.macmap = {}
+
+ if cfg["hosts"] then
+ if cfg["hosts"]["ip"] then
+ for k, v in pairs(cfg["hosts"]["ip"]) do
+ local k, n = string.gsub(k, "%.", "%%.")
+ local k, n = string.gsub(k,"%*",".*")
+ _config.ipmap["^"..k.."$"] = v
+ end
+ end
+ if cfg["hosts"]["mac"] then
+ for k, v in pairs(cfg["hosts"]["mac"]) do
+ local k, n = string.gsub(k,"%*",".*")
+ _config.macmap["^"..k.."$"] = v
+ end
+ end
+ end
+
+end
+
+function _config.map_port(port)
+ return _config.pmap[tostring(port)] or port
+end
+
+function _config.map_ip(ip)
+ for k,v in pairs(_config.ipmap) do
+ if string.match(ip,k) then
+ return v
+ end
+ end
+ return nil
+end
+
+function _config.map_mac(mac)
+ for k,v in pairs(_config.macmap) do
+ if string.match(mac,k) then
+ return v
+ end
+ end
+ return nil
+end
+
+return _config
--- /dev/null
+_connection = {}
+
+config = require "config"
+ident = require "ident"
+arpcache = require "arpcache"
+
+function _connection.auth(serv, localport, remoteport)
+
+ local user = config.map_ip(serv)
+
+ if not user then
+ local mac = arpcache.get_mac(serv)
+ if mac then
+ user = config.map_mac(mac)
+ end
+ end
+
+ if user == "*ident" then
+ user = ident.resolve(serv,localport,config.map_port(remoteport))
+ end
+
+ return user
+
+end
+
+return _connection
--- /dev/null
+#!/usr/bin/lua
+
+config = require "config"
+connection = require "connection"
+
+io.stdout:setvbuf 'no'
+io.stdin:setvbuf 'no'
+
+if arg then
+ cf = arg[1]
+else
+ cf = nil
+end
+
+config.read(cf)
+
+function string:split(sep)
+ local sep, fields = sep or ":", {}
+ local pattern = string.format("([^%s]+)", sep)
+ self:gsub(pattern, function(c) fields[#fields+1] = c end)
+ return fields
+end
+
+function main()
+ while true do
+ str=io.read()
+ vals = str:split(" ")
+ status, res = pcall(connection.auth,vals[1],vals[2],vals[3])
+ if status then
+ if res and res ~= "" then
+ io.write("OK user="..res.."\n")
+ else
+ io.write("OK\n")
+ end
+ else
+ io.write("BH\n")
+ end
+ end
+end
+
+main()
+
--- /dev/null
+config = require("config")
+
+local socket = require("socket")
+
+_ident = {}
+
+_IDENTD_PORT = 113
+
+function _ident.resolve(serv, port, remote)
+
+ local tcp = assert(socket.tcp())
+ tcp:settimeout(config.ident_timeout, 't')
+ tcp:connect(serv,_IDENTD_PORT)
+ tcp:send(tostring(port) .. ", "..tostring(remote).."\n")
+
+ res = ""
+ while true do
+ local s, status, partial = tcp:receive()
+ res = res..(s or partial)
+ if status == "closed" then break end
+ end
+
+ tcp:close()
+
+ local uname = config.ident_default
+
+ for user in string.gmatch(res,"%d*,%d*:USERID:UNIX:(.*)") do
+ uname = user
+ end
+
+ return uname
+
+end
+
+return _ident