Various changes to support settings dialog

pull/16/head
Bruce Leidl 9 years ago
parent a155427a84
commit d8f63bc60a

@ -7,6 +7,8 @@ import (
"github.com/subgraph/fw-daemon/Godeps/_workspace/src/github.com/godbus/dbus"
"github.com/subgraph/fw-daemon/Godeps/_workspace/src/github.com/godbus/dbus/introspect"
"github.com/subgraph/fw-daemon/Godeps/_workspace/src/github.com/op/go-logging"
"path"
)
const introspectXml = `
@ -15,9 +17,31 @@ const introspectXml = `
<method name="SetEnabled">
<arg name="enabled" direction="in" type="b" />
</method>
<method name="IsEnabled">
<arg name="enabled" direction="out" type="b" />
</method>
<method name="ListRules">
<arg name="rules" direction="out" type="a(ussus)" />
</method>
<method name="DeleteRule">
<arg name="id" direction="in" type="u" />
</method>
<method name="UpdateRule">
<arg name="rule" direction="in" type="(ussus)" />
</method>
<method name="GetConfig">
<arg name="config" direction="out" type="a{sv}" />
</method>
<method name="SetConfig">
<arg name="key" direction="in" type="s" />
<arg name="val" direction="in" type="v" />
</method>
</interface>` +
introspect.IntrospectDataString +
`</node>`
@ -27,10 +51,19 @@ const objectPath = "/com/subgraph/Firewall"
const interfaceName = "com.subgraph.Firewall"
type dbusServer struct {
fw *Firewall
conn *dbus.Conn
prompter *prompter
}
type DbusRule struct {
Id uint32
App string
Path string
Verb uint32
Target string
}
func newDbusServer() (*dbusServer, error) {
conn, err := dbus.SystemBus()
if err != nil {
@ -88,13 +121,96 @@ func (ds *dbusServer) Introspect(msg dbus.Message) (string, *dbus.Error) {
}
func (ds *dbusServer) SetEnabled(flag bool) *dbus.Error {
log.Info("SetEnabled(%v) called", flag)
log.Debug("SetEnabled(%v) called", flag)
ds.fw.setEnabled(flag)
return nil
}
func (ds *dbusServer) IsEnabled() (bool, *dbus.Error) {
log.Info("IsEnabled() called")
return true, nil
log.Debug("IsEnabled() called")
return ds.fw.isEnabled(), nil
}
func createDbusRule(r *Rule) DbusRule {
return DbusRule{
Id: uint32(r.id),
App: path.Base(r.policy.path),
Path: r.policy.path,
Verb: uint32(r.rtype),
Target: r.AddrString(),
}
}
func (ds *dbusServer) ListRules() ([]DbusRule, *dbus.Error) {
ds.fw.lock.Lock()
defer ds.fw.lock.Unlock()
var result []DbusRule
for _, p := range ds.fw.policies {
for _, r := range p.rules {
result = append(result, createDbusRule(r))
}
}
return result, nil
}
func (ds *dbusServer) DeleteRule(id uint32) *dbus.Error {
ds.fw.lock.Lock()
r := ds.fw.rulesById[uint(id)]
ds.fw.lock.Unlock()
if r != nil {
r.policy.removeRule(r)
}
if !r.sessionOnly {
ds.fw.saveRules()
}
return nil
}
func (ds *dbusServer) UpdateRule(rule DbusRule) *dbus.Error {
log.Debug("UpdateRule %v", rule)
ds.fw.lock.Lock()
r := ds.fw.rulesById[uint(rule.Id)]
ds.fw.lock.Unlock()
if r != nil {
tmp := new(Rule)
tmp.addr = noAddress
if !tmp.parseTarget(rule.Target) {
log.Warning("Unable to parse target: %s", rule.Target)
return nil
}
r.policy.lock.Lock()
if rule.Verb == RULE_ALLOW || rule.Verb == RULE_DENY {
r.rtype = int(rule.Verb)
}
r.hostname = tmp.hostname
r.addr = tmp.addr
r.port = tmp.port
r.policy.lock.Unlock()
if !r.sessionOnly {
ds.fw.saveRules()
}
}
return nil
}
func (ds *dbusServer) GetConfig() (map[string]dbus.Variant, *dbus.Error) {
conf := make(map[string]dbus.Variant)
conf["loglevel"] = dbus.MakeVariant(int32(ds.fw.logBackend.GetLevel("sgfw")))
conf["logredact"] = dbus.MakeVariant(ds.fw.logRedact)
return conf, nil
}
func (ds *dbusServer) SetConfig(key string, val dbus.Variant) *dbus.Error {
switch key {
case "loglevel":
l := val.Value().(int32)
lvl := logging.Level(l)
ds.fw.logBackend.SetLevel(lvl, "sgfw")
case "logredact":
flag := val.Value().(bool)
ds.fw.logRedact = flag
}
return nil
}
func (ds *dbusServer) prompt(p *Policy) {

@ -17,7 +17,7 @@ func setupIPTables() {
func addIPTRules(rules ...string) {
for _, r := range rules {
if(iptables('C', r)) {
if iptables('C', r) {
log.Info("IPTables rule already present: %s", r)
} else {
log.Info("Installing IPTables rule: %s", r)

@ -8,10 +8,10 @@ import (
"github.com/subgraph/fw-daemon/Godeps/_workspace/src/github.com/op/go-logging"
"github.com/subgraph/fw-daemon/nfqueue"
"github.com/subgraph/fw-daemon/proc"
"sync"
"syscall"
"unsafe"
"github.com/subgraph/fw-daemon/proc"
)
var log = logging.MustGetLogger("sgfw")
@ -22,6 +22,7 @@ var logFormat = logging.MustStringFormatter(
var ttyFormat = logging.MustStringFormatter(
"%{color}%{time:15:04:05} â–¶ %{level:.4s} %{id:03x}%{color:reset} %{message}",
)
const ioctlReadTermios = 0x5401
func isTerminal(fd int) bool {
@ -30,7 +31,7 @@ func isTerminal(fd int) bool {
return err == 0
}
func init() {
func setupLoggerBackend() logging.LeveledBackend {
format := logFormat
if isTerminal(int(os.Stderr.Fd())) {
format = ttyFormat
@ -38,16 +39,66 @@ func init() {
backend := logging.NewLogBackend(os.Stderr, "", 0)
formatter := logging.NewBackendFormatter(backend, format)
leveler := logging.AddModuleLevel(formatter)
log.SetBackend(leveler)
return leveler
}
type Firewall struct {
dbus *dbusServer
dns *dnsCache
enabled bool
logRedact bool
logBackend logging.LeveledBackend
lock sync.Mutex
policyMap map[string]*Policy
policies []*Policy
ruleLock sync.Mutex
rulesById map[uint]*Rule
nextRuleId uint
}
func (fw *Firewall) setEnabled(flag bool) {
fw.lock.Lock()
defer fw.lock.Unlock()
fw.enabled = flag
}
func (fw *Firewall) isEnabled() bool {
fw.lock.Lock()
defer fw.lock.Unlock()
return fw.enabled
}
func (fw *Firewall) clearRules() {
fw.ruleLock.Lock()
defer fw.ruleLock.Unlock()
fw.rulesById = nil
fw.nextRuleId = 0
}
func (fw *Firewall) addRule(r *Rule) {
fw.ruleLock.Lock()
defer fw.ruleLock.Unlock()
r.id = fw.nextRuleId
fw.nextRuleId += 1
if fw.rulesById == nil {
fw.rulesById = make(map[uint]*Rule)
}
fw.rulesById[r.id] = r
}
func (fw *Firewall) getRuleById(id uint) *Rule {
fw.ruleLock.Lock()
defer fw.ruleLock.Unlock()
if fw.rulesById == nil {
return nil
}
return fw.rulesById[id]
}
func (fw *Firewall) runFilter() {
@ -64,7 +115,11 @@ func (fw *Firewall) runFilter() {
for {
select {
case pkt := <-packets:
if fw.isEnabled() {
fw.filterPacket(pkt)
} else {
pkt.Accept()
}
case <-sigs:
return
}
@ -72,6 +127,8 @@ func (fw *Firewall) runFilter() {
}
func main() {
logBackend := setupLoggerBackend()
log.SetBackend(logBackend)
proc.SetLogger(log)
if os.Geteuid() != 0 {
@ -90,8 +147,12 @@ func main() {
fw := &Firewall{
dbus: ds,
dns: NewDnsCache(),
enabled: true,
logRedact: false,
logBackend: logBackend,
policyMap: make(map[string]*Policy),
}
ds.fw = fw
fw.loadRules()

@ -110,6 +110,34 @@ func (p *Policy) processNewRule(r *Rule, scope int32) bool {
return p.promptInProgress
}
func (p *Policy) parseRule(s string, add bool) (*Rule, error) {
r := new(Rule)
r.policy = p
if !r.parse(s) {
return nil, parseError(s)
}
if add {
p.lock.Lock()
defer p.lock.Unlock()
p.rules = append(p.rules, r)
}
p.fw.addRule(r)
return r, nil
}
func (p *Policy) removeRule(r *Rule) {
p.lock.Lock()
defer p.lock.Unlock()
var newRules RuleList
for _, rr := range p.rules {
if rr.id != r.id {
newRules = append(newRules, rr)
}
}
p.rules = newRules
}
func (p *Policy) filterPending(rule *Rule) {
remaining := []*pendingPkt{}
for _, pp := range p.pendingQueue {

@ -100,18 +100,16 @@ func (p *prompter) processPacket(pp *pendingPkt) {
pp.policy.removePending(pp)
pp.pkt.Mark = 1
pp.pkt.Accept()
//pp.pkt.Drop()
return
}
log.Debug("Received prompt response: %s [%s]", printScope(scope), rule)
r, err := parseRule(rule)
r, err := pp.policy.parseRule(rule, false)
if err != nil {
log.Warning("Error parsing rule string returned from dbus RequestPrompt: %v", err)
pp.policy.removePending(pp)
pp.pkt.Mark = 1
pp.pkt.Accept()
//pp.pkt.Drop()
return
}
if scope == APPLY_SESSION {

@ -8,11 +8,11 @@ import (
"unicode"
"github.com/subgraph/fw-daemon/nfqueue"
"github.com/subgraph/fw-daemon/proc"
"io/ioutil"
"os"
"strconv"
"path"
"github.com/subgraph/fw-daemon/proc"
"strconv"
)
const (
@ -24,6 +24,8 @@ const matchAny = 0
const noAddress = uint32(0xffffffff)
type Rule struct {
id uint
policy *Policy
sessionOnly bool
rtype int
hostname string
@ -32,10 +34,17 @@ type Rule struct {
}
func (r *Rule) String() string {
addr := "*"
port := "*"
rtype := "DENY"
if r.rtype == RULE_ALLOW {
rtype = "ALLOW"
}
return fmt.Sprintf("%s|%s", rtype, r.AddrString())
}
func (r *Rule) AddrString() string {
addr := "*"
port := "*"
if r.hostname != "" {
addr = r.hostname
} else if r.addr != matchAny && r.addr != noAddress {
@ -48,11 +57,7 @@ func (r *Rule) String() string {
port = fmt.Sprintf("%d", r.port)
}
if r.rtype == RULE_ALLOW {
rtype = "ALLOW"
}
return fmt.Sprintf("%s|%s:%s", rtype, addr, port)
return fmt.Sprintf("%s:%s", addr, port)
}
type RuleList []*Rule
@ -154,25 +159,17 @@ func (r *Rule) parsePort(p string) bool {
}
var err error
port, err := strconv.ParseUint(p, 10, 16)
if err != nil {
if err != nil || port == 0 || port > 0xFFFF {
return false
}
r.port = uint16(port)
return true
}
func parseRule(s string) (*Rule, error) {
r := new(Rule)
if !r.parse(s) {
return nil, parseError(s)
}
return r, nil
}
const ruleFile = "/var/lib/sgfw/sgfw_rules"
func maybeCreateDir(dir string) error {
_,err := os.Stat(dir)
_, err := os.Stat(dir)
if os.IsNotExist(err) {
return os.MkdirAll(dir, 0755)
}
@ -190,7 +187,7 @@ func (fw *Firewall) saveRules() {
fw.lock.Lock()
defer fw.lock.Unlock()
p,err := rulesPath()
p, err := rulesPath()
if err != nil {
log.Warning("Failed to open %s for writing: %v", p, err)
return
@ -239,7 +236,9 @@ func (fw *Firewall) loadRules() {
fw.lock.Lock()
defer fw.lock.Unlock()
p,err := rulesPath()
fw.clearRules()
p, err := rulesPath()
if err != nil {
log.Warning("Failed to open %s for reading: %v", p, err)
return
@ -275,12 +274,9 @@ func processRuleLine(policy *Policy, line string) {
log.Warning("Cannot process rule line without first seeing path line: %s", line)
return
}
rule, err := parseRule(line)
_, err := policy.parseRule(line, true)
if err != nil {
log.Warning("Error parsing rule (%s): %v", line, err)
return
}
policy.lock.Lock()
defer policy.lock.Unlock()
policy.rules = append(policy.rules, rule)
}

Loading…
Cancel
Save