init.lua 3.43 KB
Newer Older
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
1 2 3 4 5 6 7 8
--[[
Alpine Wall main module
Copyright (C) 2012 Kaarle Ritvanen
Licensed under the terms of GPL2
]]--

module(..., package.seeall)

9
require 'lfs'
10
require 'stringy'
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
11

12
require 'awall.ipset'
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
13
require 'awall.iptables'
14
require 'awall.model'
15
require 'awall.object'
16
require 'awall.policy'
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
17 18 19
require 'awall.util'


20 21
local procorder
local defrules
22 23

function loadmodules(path)
24 25 26 27 28 29 30 31 32 33
   classmap = {}
   procorder = {}
   defrules = {}

   local function readmetadata(mod)
      for i, clsdef in ipairs(mod.classes) do
	 local path, cls = unpack(clsdef)
	 classmap[path] = cls
	 table.insert(procorder, path)
      end
34 35 36 37
      for phase, rules in pairs(mod.defrules) do
	 if not defrules[phase] then defrules[phase] = {} end
	 util.extend(defrules[phase], rules)
      end
38 39 40 41
   end

   readmetadata(model)

42 43 44
   local cdir = lfs.currentdir()
   if path then lfs.chdir(path) end

45 46 47 48
   for modfile in lfs.dir((path or '/usr/share/lua/5.1')..'/awall/modules') do
      if stringy.endswith(modfile, '.lua') then
	 local name = 'awall.modules.'..string.sub(modfile, 1, -5)
	 require(name)
49
	 readmetadata(package.loaded[name])
50
      end
51
   end
52 53

   lfs.chdir(cdir)
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
54 55 56
end


57 58 59
PolicySet = policy.PolicySet


60
Config = object.class(object.Object)
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
61

62
function Config:init(policyset)
63

64
   self.input = policyset:load()
65
   self.iptables = iptables.IPTables.new()
66

67
   local function expandvars(obj)
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
68 69 70 71 72 73 74 75
      for k, v in pairs(obj) do
	 if type(v) == 'table' then
	    expandvars(v)

	 else
	    local visited = {}
	    local val = v

76 77 78 79
	    local pattern = '%$(%a[%w_]*)'

	    while type(val) == 'string' and string.find(val, pattern) do
	       local si, ei, name = string.find(val, pattern)
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
80 81 82 83 84
		  
	       if util.contains(visited, name) then
		  error('Circular variable definition: '..name)
	       end
	       table.insert(visited, name)
85 86 87 88 89 90 91 92 93 94

	       local var = self.input.variable[name]
	       if not var then error('Invalid variable reference: '..name) end

	       if si == 1 and ei == string.len(val) then val = var
	       elseif util.contains({'number', 'string'}, type(var)) then
		  val = string.sub(val, 1, si - 1)..var..string.sub(val, ei + 1, -1)
	       else
		  error('Attempted to concatenate complex variable: '..name)
	       end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
95 96
	    end

97
	    obj[k] = val ~= '' and val or nil
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
98 99 100 101
	 end
      end
   end

102 103 104
   for k, v in pairs(self.input) do
      if k ~= 'variable' then expandvars(v) end
   end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
105 106


107 108 109 110 111 112 113 114
   local function insertrules(trules)
      for i, trule in ipairs(trules) do
	 local t = self.iptables.config[trule.family][trule.table][trule.chain]
	 if trule.position == 'prepend' then
	    table.insert(t, 1, trule.opts)
	 else
	    table.insert(t, trule.opts)
	 end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
115 116 117
      end
   end

118 119 120
   local function insertdefrules(phase)
      if defrules[phase] then insertrules(defrules[phase]) end
   end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
121

122 123 124 125
   for i, path in ipairs(procorder) do
      if self.input[path] then
	 util.map(self.input[path],
		  function(obj) return classmap[path].morph(obj, self) end)
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
126 127 128
      end
   end

129
   insertdefrules('pre')
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
130

131 132 133 134 135
   for i, path in ipairs(procorder) do
      if self.input[path] then
	 for i, rule in ipairs(self.input[path]) do
	    insertrules(rule:trules())
	 end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
136
      end
137
      insertdefrules('post-'..path)
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
138
   end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
139

140
   self.ipset = ipset.IPSet.new(self.input.ipset)
141
end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
142

143 144 145
function Config:dump(iptdir, ipsfile)
   self.ipset:dump(ipsfile or '/etc/ipset.d/awall')
   self.iptables:dump(iptdir or '/etc/iptables')
146
end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
147

148 149 150
function Config:test()
   self.ipset:create()
   self.iptables:test()
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
151
end
152 153 154 155 156

function Config:activate()
   self:test()
   self.iptables:activate()
end