Overhaul of GetPendingRequests DBus method to call AddRuleAsync multiple times instead of returning a string array.

TLSGuard now handles multiple expected client and server message types.
shw_dev
Stephen Watt 7 years ago
parent bdca5d330d
commit b9c2e03afd

@ -3,10 +3,6 @@ fw-daemon:
remove all stale references to SANDBOX: rules/policyForPathAndSandbox() remove all stale references to SANDBOX: rules/policyForPathAndSandbox()
TLSGuard needs to handle unexpected SSL3_MT_HELLO_REQUEST properly - make expectations a slice
GetPendingRequests Dbus method should send a bunch of DBus requests
fw-prompt: fw-prompt:
apply once rules still do not work because they the DBus invocation requires the guid to be passed apply once rules still do not work because they the DBus invocation requires the guid to be passed

@ -82,7 +82,6 @@ var radioOnce, radioProcess, radioParent, radioSession, radioPermanent *gtk.Radi
var btnApprove, btnDeny, btnIgnore *gtk.Button var btnApprove, btnDeny, btnIgnore *gtk.Button
var chkTLS, chkUser, chkGroup *gtk.CheckButton var chkTLS, chkUser, chkGroup *gtk.CheckButton
func promptInfo(msg string) { func promptInfo(msg string) {
dialog := gtk.MessageDialogNew(mainWin, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Displaying full log info:") dialog := gtk.MessageDialogNew(mainWin, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Displaying full log info:")
// dialog.SetDefaultGeometry(500, 200) // dialog.SetDefaultGeometry(500, 200)
@ -941,71 +940,6 @@ func getSelectedRule() (ruleColumns, int, error) {
return rule, lIndex, nil return rule, lIndex, nil
} }
func addPendingPrompts(rules []string) {
for _, rule := range rules {
fields := strings.Split(rule, "|")
if len(fields) != 19 {
log.Printf("Got saved prompt message with strange data: \"%s\"", rule)
continue
}
guid := fields[0]
icon := fields[2]
path := fields[3]
address := fields[4]
port, err := strconv.Atoi(fields[5])
if err != nil {
log.Println("Error converting port in pending prompt message to integer:", err)
continue
}
ip := fields[6]
origin := fields[7]
proto := fields[8]
uid, err := strconv.Atoi(fields[9])
if err != nil {
log.Println("Error converting UID in pending prompt message to integer:", err)
continue
}
gid, err := strconv.Atoi(fields[10])
if err != nil {
log.Println("Error converting GID in pending prompt message to integer:", err)
continue
}
pid, err := strconv.Atoi(fields[13])
if err != nil {
log.Println("Error converting pid in pending prompt message to integer:", err)
continue
}
sandbox := fields[14]
is_socks, err := strconv.ParseBool(fields[15])
if err != nil {
log.Println("Error converting SOCKS flag in pending prompt message to boolean:", err)
continue
}
timestamp := fields[16]
optstring := fields[17]
action, err := strconv.Atoi(fields[18])
if err != nil {
log.Println("Error converting action in pending prompt message to integer:", err)
continue
}
addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, timestamp, is_socks, optstring, sandbox, action)
}
}
func buttonAction(action string) { func buttonAction(action string) {
globalPromptLock.Lock() globalPromptLock.Lock()
rule, idx, err := getSelectedRule() rule, idx, err := getSelectedRule()
@ -1336,14 +1270,14 @@ func main() {
mainWin.ShowAll() mainWin.ShowAll()
// mainWin.SetKeepAbove(true) // mainWin.SetKeepAbove(true)
var dres = []string{} var dres bool
call := dbuso.Call("GetPendingRequests", 0, "*") call := dbuso.Call("GetPendingRequests", 0, "*")
err = call.Store(&dres) err = call.Store(&dres)
if err != nil { if err != nil {
errmsg := "Could not query running SGFW instance (maybe it's not running?): " + err.Error() errmsg := "Could not query running SGFW instance (maybe it's not running?): " + err.Error()
promptError(errmsg) promptError(errmsg)
} else { } else if !dres {
addPendingPrompts(dres) promptError("Call to sgfw did not succeed; fw-prompt may have loaded without retrieving all pending connections")
} }
gtk.Main() gtk.Main()

@ -199,18 +199,19 @@ func (ds *dbusServer) DeleteRule(id uint32) *dbus.Error {
return nil return nil
} }
func (ds *dbusServer) GetPendingRequests(policy string) ([]string, *dbus.Error) { func (ds *dbusServer) GetPendingRequests(policy string) (bool, *dbus.Error) {
succeeded := true
log.Debug("+++ GetPendingRequests()") log.Debug("+++ GetPendingRequests()")
ds.fw.lock.Lock() ds.fw.lock.Lock()
defer ds.fw.lock.Unlock() defer ds.fw.lock.Unlock()
pending_data := make([]string, 0)
for pname := range ds.fw.policyMap { for pname := range ds.fw.policyMap {
policy := ds.fw.policyMap[pname] policy := ds.fw.policyMap[pname]
pqueue := policy.pendingQueue pqueue := policy.pendingQueue
for _, pc := range pqueue { for _, pc := range pqueue {
var dres bool
addr := pc.hostname() addr := pc.hostname()
if addr == "" { if addr == "" {
addr = pc.dst().String() addr = pc.dst().String()
@ -224,32 +225,40 @@ func (ds *dbusServer) GetPendingRequests(policy string) ([]string, *dbus.Error)
dststr = addr + " (via proxy resolver)" dststr = addr + " (via proxy resolver)"
} }
pstr := "" call := ds.prompter.dbusObj.Call("com.subgraph.FirewallPrompt.RequestPromptAsync", 0,
pstr += pc.getGUID() + "|" pc.getGUID(),
pstr += policy.application + "|" policy.application,
pstr += policy.icon + "|" policy.icon,
pstr += policy.path + "|" policy.path,
pstr += addr + "|" addr,
pstr += strconv.FormatUint(uint64(pc.dstPort()), 10) + "|" int32(pc.dstPort()),
pstr += dststr + "|" dststr,
pstr += pc.src().String() + "|" pc.src().String(),
pstr += pc.proto() + "|" pc.proto(),
pstr += strconv.FormatInt(int64(pc.procInfo().UID), 10) + "|" int32(pc.procInfo().UID),
pstr += strconv.FormatInt(int64(pc.procInfo().GID), 10) + "|" int32(pc.procInfo().GID),
pstr += uidToUser(pc.procInfo().UID) + "|" uidToUser(pc.procInfo().UID),
pstr += gidToGroup(pc.procInfo().GID) + "|" gidToGroup(pc.procInfo().GID),
pstr += strconv.FormatInt(int64(pc.procInfo().Pid), 10) + "|" int32(pc.procInfo().Pid),
pstr += pc.sandbox() + "|" pc.sandbox(),
pstr += strconv.FormatBool(pc.socks()) + "|" pc.socks(),
pstr += pc.getTimestamp() + "|" pc.getTimestamp(),
pstr += pc.getOptString() + "|" pc.getOptString(),
pstr += strconv.FormatUint(uint64(FirewallConfig.DefaultActionID), 10) FirewallConfig.PromptExpanded,
pending_data = append(pending_data, pstr) FirewallConfig.PromptExpert,
int32(FirewallConfig.DefaultActionID))
err := call.Store(&dres)
if err != nil {
log.Warningf("Error sending DBus async pending RequestPrompt message: %v", err)
succeeded = false
}
} }
} }
return pending_data, nil return succeeded, nil
} }
func (ds *dbusServer) AddRuleAsync(scope uint32, rule string, policy string) (bool, *dbus.Error) { func (ds *dbusServer) AddRuleAsync(scope uint32, rule string, policy string) (bool, *dbus.Error) {

@ -350,6 +350,16 @@ func connectionReader(conn net.Conn, is_client bool, c chan connReader, done cha
} }
func isExpected(val uint, possibilities []uint) bool {
for _, pval := range possibilities {
if val == pval {
return true
}
}
return false
}
func TLSGuard(conn, conn2 net.Conn, fqdn string) error { func TLSGuard(conn, conn2 net.Conn, fqdn string) error {
x509Valid := false x509Valid := false
ndone := 0 ndone := 0
@ -366,8 +376,8 @@ func TLSGuard(conn, conn2 net.Conn, fqdn string) error {
go connectionReader(conn, true, crChan, dChan) go connectionReader(conn, true, crChan, dChan)
go connectionReader(conn2, false, crChan, dChan2) go connectionReader(conn2, false, crChan, dChan2)
client_expected := SSL3_MT_CLIENT_HELLO client_expected := []uint{SSL3_MT_CLIENT_HELLO}
server_expected := SSL3_MT_SERVER_HELLO server_expected := []uint{SSL3_MT_SERVER_HELLO}
client_sess := false client_sess := false
server_sess := false server_sess := false
@ -462,9 +472,9 @@ select_loop:
} }
if cr.client && s != uint(client_expected) { if cr.client && !isExpected(s, client_expected) {
return errors.New(fmt.Sprintf("Client sent handshake type %#x but expected %#x", s, client_expected)) return errors.New(fmt.Sprintf("Client sent handshake type %#x but expected %#x", s, client_expected))
} else if !cr.client && s != uint(server_expected) { } else if !cr.client && !isExpected(s, server_expected) {
return errors.New(fmt.Sprintf("Server sent handshake type %#x but expected %#x", s, server_expected)) return errors.New(fmt.Sprintf("Server sent handshake type %#x but expected %#x", s, server_expected))
} }
@ -476,7 +486,7 @@ select_loop:
if s == SSL3_MT_CLIENT_HELLO { if s == SSL3_MT_CLIENT_HELLO {
SRC = "CLIENT" SRC = "CLIENT"
} else { } else {
server_expected = SSL3_MT_CERTIFICATE server_expected = []uint{SSL3_MT_CERTIFICATE, SSL3_MT_HELLO_REQUEST}
SRC = "SERVER" SRC = "SERVER"
} }
@ -501,157 +511,73 @@ select_loop:
server_sess = true server_sess = true
} }
/* if sess_len != 0 {
fmt.Printf("ALERT: %v attempting to resume session; intercepting request\n", SRC)
rewrite = true
dcopy := make([]byte, len(cr.data))
copy(dcopy, cr.data)
// Copy the bytes before the session ID start
rewrite_buf = dcopy[0 : TLS_RECORD_HDR_LEN+hello_offset+1]
// Set the session ID to 0
rewrite_buf[len(rewrite_buf)-1] = 0
// Write the new TLS record length
binary.BigEndian.PutUint16(rewrite_buf[3:5], uint16(len(dcopy)-(int(sess_len)+TLS_RECORD_HDR_LEN)))
// Write the new ClientHello length
// Starts after the first 6 bytes (record header + type byte)
orig_len := binary.BigEndian.Uint32(handshakeMsg[0:4])
// But it's only 3 bytes so mask out the first one
b1 := orig_len & 0xff000000
orig_len &= 0x00ffffff
orig_len -= uint32(sess_len)
orig_len |= b1
binary.BigEndian.PutUint32(rewrite_buf[TLS_RECORD_HDR_LEN:], orig_len)
rewrite_buf = append(rewrite_buf, dcopy[TLS_RECORD_HDR_LEN+hello_offset+int(sess_len)+1:]...)
}
hello_offset += int(sess_len) + 1
// 2 byte cipher suite array
cs := binary.BigEndian.Uint16(handshakeMsg[hello_offset : hello_offset+2])
noCS := cs
fmt.Printf("cs = %v / %#x\n", noCS, noCS)
var ciphersuite_excisions = []int{}
saved_ciphersuite_size_off := hello_offset
if !cr.client {
fmt.Printf("SERVER selected ciphersuite: %#x (%s)\n", cs, getCipherSuiteName(uint(cs)))
hello_offset += 2
} else {
for csind := 0; csind < int(noCS/2); csind++ {
off := hello_offset + 2 + (csind * 2)
cs = binary.BigEndian.Uint16(handshakeMsg[off : off+2])
cname := getCipherSuiteName(uint(cs))
fmt.Printf("%s HELLO CIPHERSUITE: %d/%d: %#x (%s)\n", SRC, csind+1, noCS/2, cs, cname)
if isBadCipher(cname) {
fmt.Println("BAD CIPHER: ", cname)
ciphersuite_excisions = append(ciphersuite_excisions, off)
}
}
hello_offset += 2 + int(noCS)
}
clen := uint(handshakeMsg[hello_offset])
hello_offset++
if !cr.client {
fmt.Println("SERVER selected compression method: ", clen)
} else {
fmt.Println(SRC, "HELLO COMPRESSION METHODS LEN = ", clen)
fmt.Println(SRC, "HELLO COMPRESSION METHODS: ", handshakeMsg[hello_offset:hello_offset+int(clen)])
hello_offset += int(clen)
}
var extlen uint16 = 0
if hello_offset == len(handshakeMsg) {
fmt.Println("Message didn't have any extensions present")
} else {
extlen = binary.BigEndian.Uint16(handshakeMsg[hello_offset : hello_offset+2])
fmt.Println(SRC, "HELLO EXTENSIONS LENGTH: ", extlen)
hello_offset += 2
}
if cr.client {
ext_ctr := 0
for ext_ctr < int(extlen)-2 {
exttype := binary.BigEndian.Uint16(handshakeMsg[hello_offset : hello_offset+2])
hello_offset += 2
ext_ctr += 2
// fmt.Printf("PROGRESS: %v of %v, %v of %v\n", ext_ctr, extlen, hello_offset, len(handshakeMsg))
fmt.Printf("EXTTYPE = %#x (%s)\n", exttype, gettlsExtensionName(uint(exttype)))
inner_len := binary.BigEndian.Uint16(handshakeMsg[hello_offset : hello_offset+2])
hello_offset += int(inner_len) + 2
ext_ctr += int(inner_len) + 2
}
}
/* /*
if extlen > 0 { hello_offset += int(sess_len) + 1
fmt.Printf("ALERT: %v attempting to send extensions; intercepting request\n", SRC) // 2 byte cipher suite array
rewrite = true cs := binary.BigEndian.Uint16(handshakeMsg[hello_offset : hello_offset+2])
tocopy := cr.data noCS := cs
fmt.Printf("cs = %v / %#x\n", noCS, noCS)
if len(rewrite_buf) > 0 {
tocopy = rewrite_buf saved_ciphersuite_size_off := hello_offset
}
if !cr.client {
dcopy := make([]byte, len(tocopy)-int(extlen)) fmt.Printf("SERVER selected ciphersuite: %#x (%s)\n", cs, getCipherSuiteName(uint(cs)))
copy(dcopy, tocopy[0:len(tocopy)-int(extlen)]) hello_offset += 2
rewrite_buf = dcopy } else {
// Write the new TLS record length
binary.BigEndian.PutUint16(rewrite_buf[3:5], uint16(len(dcopy)-(int(sess_len)+TLS_RECORD_HDR_LEN))) for csind := 0; csind < int(noCS/2); csind++ {
// Write the new ClientHello length off := hello_offset + 2 + (csind * 2)
// Starts after the first 6 bytes (record header + type byte) cs = binary.BigEndian.Uint16(handshakeMsg[off : off+2])
orig_len := binary.BigEndian.Uint32(rewrite_buf[TLS_RECORD_HDR_LEN:]) cname := getCipherSuiteName(uint(cs))
// But it's only 3 bytes so mask out the first one fmt.Printf("%s HELLO CIPHERSUITE: %d/%d: %#x (%s)\n", SRC, csind+1, noCS/2, cs, cname)
b1 := orig_len & 0xff000000
orig_len &= 0x00ffffff if isBadCipher(cname) {
orig_len -= uint32(extlen) fmt.Println("BAD CIPHER: ", cname)
orig_len |= b1 }
binary.BigEndian.PutUint32(rewrite_buf[TLS_RECORD_HDR_LEN:], orig_len)
// Write session length 0 at the end }
rewrite_buf[len(rewrite_buf)-1] = 0
rewrite_buf[len(rewrite_buf)-2] = 0 hello_offset += 2 + int(noCS)
} */ }
sendbuf := cr.data clen := uint(handshakeMsg[hello_offset])
hello_offset++
/* if rewrite {
sendbuf = rewrite_buf if !cr.client {
} fmt.Println("SERVER selected compression method: ", clen)
} else {
if len(ciphersuite_excisions) > 0 { fmt.Println(SRC, "HELLO COMPRESSION METHODS LEN = ", clen)
fmt.Printf("Rewriting client handshake with %d ciphersuite options removed\n", len(ciphersuite_excisions)) fmt.Println(SRC, "HELLO COMPRESSION METHODS: ", handshakeMsg[hello_offset:hello_offset+int(clen)])
fmt.Println("PREVIOUS: ", hex.Dump(sendbuf)) hello_offset += int(clen)
rewrite = true }
mod := sendbuf
var extlen uint16 = 0
for _, exind := range ciphersuite_excisions {
mod = stripTLSData(mod, exind+TLS_RECORD_HDR_LEN, exind+TLS_RECORD_HDR_LEN+2, saved_ciphersuite_size_off+TLS_RECORD_HDR_LEN, 2) if hello_offset == len(handshakeMsg) {
fmt.Println("Message didn't have any extensions present")
if mod == nil { } else {
return errors.New("Unknown error occurred stripping ciphersuite from client TLS handshake") extlen = binary.BigEndian.Uint16(handshakeMsg[hello_offset : hello_offset+2])
} fmt.Println(SRC, "HELLO EXTENSIONS LENGTH: ", extlen)
hello_offset += 2
} }
rewrite_buf = mod if cr.client {
sendbuf = rewrite_buf ext_ctr := 0
}
for ext_ctr < int(extlen)-2 {
if rewrite { exttype := binary.BigEndian.Uint16(handshakeMsg[hello_offset : hello_offset+2])
fmt.Println("TLSGuard writing back modified handshake data to server") hello_offset += 2
fmt.Printf("ORIGINAL[%d]: %v\n", len(cr.data), hex.Dump(cr.data)) ext_ctr += 2
fmt.Printf("NEW[%d]: %v\n", len(rewrite_buf), hex.Dump(rewrite_buf)) // fmt.Printf("PROGRESS: %v of %v, %v of %v\n", ext_ctr, extlen, hello_offset, len(handshakeMsg))
} */ fmt.Printf("EXTTYPE = %#x (%s)\n", exttype, gettlsExtensionName(uint(exttype)))
inner_len := binary.BigEndian.Uint16(handshakeMsg[hello_offset : hello_offset+2])
other.Write(sendbuf) hello_offset += int(inner_len) + 2
ext_ctr += int(inner_len) + 2
}
}*/
other.Write(cr.data)
continue continue
} }
@ -660,8 +586,8 @@ select_loop:
continue continue
} }
if !cr.client && server_expected == SSL3_MT_SERVER_HELLO { if !cr.client && isExpected(SSL3_MT_SERVER_HELLO, server_expected) {
server_expected = SSL3_MT_CERTIFICATE server_expected = []uint{SSL3_MT_CERTIFICATE}
} }
if !cr.client && s == SSL3_MT_HELLO_REQUEST { if !cr.client && s == SSL3_MT_HELLO_REQUEST {
@ -674,7 +600,6 @@ select_loop:
} }
if s == SSL3_MT_CERTIFICATE { if s == SSL3_MT_CERTIFICATE {
fmt.Println("HMM")
// fmt.Printf("chunk len = %v, handshakeMsgLen = %v, slint = %v\n", len(chunk), len(handshakeMsg), handshakeMessageLenInt) // fmt.Printf("chunk len = %v, handshakeMsgLen = %v, slint = %v\n", len(chunk), len(handshakeMsg), handshakeMessageLenInt)
if len(handshakeMsg) < handshakeMessageLenInt { if len(handshakeMsg) < handshakeMessageLenInt {
return errors.New(fmt.Sprintf("len(handshakeMsg) %v < handshakeMessageLenInt %v!\n", len(handshakeMsg), handshakeMessageLenInt)) return errors.New(fmt.Sprintf("len(handshakeMsg) %v < handshakeMessageLenInt %v!\n", len(handshakeMsg), handshakeMessageLenInt))

Loading…
Cancel
Save