Version and update verdict kernel functions

This commit is contained in:
Vladimir
2022-11-04 11:21:53 +01:00
parent 9bc2da90a8
commit ad8bb2059d
5 changed files with 115 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"github.com/safing/portmaster/firewall/interception/windowskext"
"github.com/safing/portmaster/network"
"github.com/safing/portmaster/network/packet"
"github.com/safing/portmaster/updates"
)
@@ -39,3 +40,16 @@ func stop() error {
func ResetVerdictOfAllConnections() error {
return windowskext.ClearCache()
}
func UpdateVerdictOfConnection(conn *network.Connection) error {
return windowskext.UpdateVerdict(conn)
}
func GetVersion() (string, error) {
version, err := windowskext.GetVersion()
if err != nil {
return "", err
}
return version.String(), nil
}

View File

@@ -6,6 +6,7 @@ package windowskext
import (
"encoding/binary"
"errors"
"fmt"
"net"
"github.com/tevino/abool"
@@ -50,6 +51,23 @@ type VerdictInfo struct {
verdict network.Verdict // verdict for the connection
}
type VerdictUpdateInfo struct {
ipV6 uint8 //True: IPv6, False: IPv4
protocol uint8 //Protocol (UDP, TCP, ...)
localIP [4]uint32 //Source Address, only srcIP[0] if IPv4
remoteIP [4]uint32 //Destination Address
localPort uint16 //Source Port
remotePort uint16 //Destination port
verdict uint8 //New verdict
}
type VersionInfo struct {
major uint8
minor uint8
revision uint8
build uint8
}
// Handler transforms received packets to the Packet interface.
func Handler(packets chan packet.Packet) {
if !ready.IsSet() {
@@ -152,3 +170,7 @@ func convertIPv6(input [4]uint32) net.IP {
}
return net.IP(addressBuf)
}
func (v *VersionInfo) String() string {
return fmt.Sprintf("%d.%d.%d.%d", v.major, v.minor, v.revision, v.build)
}

View File

@@ -226,6 +226,61 @@ func ClearCache() error {
return err
}
func UpdateVerdict(conn *network.Connection) error {
kextLock.RLock()
defer kextLock.RUnlock()
// Check if driver is initialized
if !ready.IsSet() {
log.Error("kext: failed to clear the cache: kext not ready")
return ErrKextNotReady
}
// initialize variables
info := &VerdictUpdateInfo{
ipV6: uint8(conn.IPVersion),
protocol: uint8(conn.IPProtocol),
localPort: conn.LocalPort,
remotePort: conn.Entity.Port,
verdict: uint8(conn.Verdict.Active),
}
// copy ip addresses
copy(asByteArray(&info.localIP[0]), conn.LocalIP)
copy(asByteArray(&info.remoteIP[0]), conn.Entity.IP)
// Make driver request
data := asByteArray(&info)
err := deviceIoControlDirect(kextHandle, IOCTL_UPDATE_VERDICT, data)
return err
}
func GetVersion() (*VersionInfo, error) {
kextLock.RLock()
defer kextLock.RUnlock()
// Check if driver is initialized
if !ready.IsSet() {
log.Error("kext: failed to clear the cache: kext not ready")
return nil, ErrKextNotReady
}
data := make([]uint8, 4)
err := deviceIoControlDirect(kextHandle, IOCTL_VERSION, data)
if err != nil {
return nil, err
}
version := &VersionInfo{
major: data[0],
minor: data[1],
revision: data[2],
build: data[3],
}
return version, nil
}
func asByteArray[T any](obj *T) []byte {
return unsafe.Slice((*byte)(unsafe.Pointer(obj)), unsafe.Sizeof(*obj))
}

View File

@@ -15,12 +15,13 @@ const (
)
var (
IOCTL_HELLO = ctlCode(SIOCTL_TYPE, 0x800, METHOD_BUFFERED, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA)
IOCTL_RECV_VERDICT_REQ_POLL = ctlCode(SIOCTL_TYPE, 0x801, METHOD_BUFFERED, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA)
IOCTL_VERSION = ctlCode(SIOCTL_TYPE, 0x800, METHOD_NEITHER, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA)
IOCTL_RECV_VERDICT_REQ_POLL = ctlCode(SIOCTL_TYPE, 0x801, METHOD_BUFFERED, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA) // Not used
IOCTL_RECV_VERDICT_REQ = ctlCode(SIOCTL_TYPE, 0x802, METHOD_BUFFERED, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA)
IOCTL_SET_VERDICT = ctlCode(SIOCTL_TYPE, 0x803, METHOD_BUFFERED, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA)
IOCTL_GET_PAYLOAD = ctlCode(SIOCTL_TYPE, 0x804, METHOD_BUFFERED, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA)
IOCTL_CLEAR_CACHE = ctlCode(SIOCTL_TYPE, 0x805, METHOD_BUFFERED, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA)
IOCTL_UPDATE_VERDICT = ctlCode(SIOCTL_TYPE, 0x806, METHOD_NEITHER, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA)
)
func ctlCode(device_type, function, method, access uint32) uint32 {
@@ -89,3 +90,21 @@ func deviceIoControlReadWrite(handle windows.Handle, code uint32, inData []byte,
return bytesReturned, err
}
// Use for METHOD_NEITHER IOCTL, the data buffer is passed directly to the kernel
func deviceIoControlDirect(handle windows.Handle, code uint32, data []byte) error {
var dataPtr *byte = nil
var dataSize uint32 = 0
if data != nil {
dataPtr = &data[0]
dataSize = uint32(len(data))
}
err := windows.DeviceIoControl(handle,
code,
dataPtr, dataSize,
nil, 0,
nil, nil)
return err
}