diff --git a/firewall/interception/windowskext/handler.go b/firewall/interception/windowskext/handler.go index ddfa21ef..f9f541f6 100644 --- a/firewall/interception/windowskext/handler.go +++ b/firewall/interception/windowskext/handler.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "net" + "unsafe" "github.com/tevino/abool" @@ -68,6 +69,10 @@ type VersionInfo struct { build uint8 } +func (v *VersionInfo) String() string { + return fmt.Sprintf("%d.%d.%d.%d", v.major, v.minor, v.revision, v.build) +} + // Handler transforms received packets to the Packet interface. func Handler(packets chan packet.Packet) { defer close(packets) @@ -167,6 +172,27 @@ 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) +func ipAddressToArray(ip net.IP, isIPv6 bool) [4]uint32 { + array := [4]uint32{0} + if isIPv6 { + for i := 0; i < 4; i++ { + binary.BigEndian.PutUint32(asByteArrayWithLength(&array[i], 4), getUInt32Value(&ip[i])) + } + } else { + binary.BigEndian.PutUint32(asByteArrayWithLength(&array[0], 4), getUInt32Value(&ip[0])) + } + + return array +} + +func asByteArray[T any](obj *T) []byte { + return unsafe.Slice((*byte)(unsafe.Pointer(obj)), unsafe.Sizeof(*obj)) +} + +func asByteArrayWithLength[T any](obj *T, size uint32) []byte { + return unsafe.Slice((*byte)(unsafe.Pointer(obj)), size) +} + +func getUInt32Value[T any](obj *T) uint32 { + return *(*uint32)(unsafe.Pointer(obj)) } diff --git a/firewall/interception/windowskext/kext.go b/firewall/interception/windowskext/kext.go index 1f85083e..33a387e7 100644 --- a/firewall/interception/windowskext/kext.go +++ b/firewall/interception/windowskext/kext.go @@ -13,6 +13,7 @@ import ( "github.com/safing/portbase/log" "github.com/safing/portmaster/network" + "github.com/safing/portmaster/network/packet" "golang.org/x/sys/windows" ) @@ -217,24 +218,27 @@ func UpdateVerdict(conn *network.Connection) error { defer kextLock.RUnlock() // Check if driver is initialized - if !ready.IsSet() { + if kextHandle == winInvalidHandleValue { log.Error("kext: failed to clear the cache: kext not ready") return ErrKextNotReady } + var isIpv6 uint8 = 0 + if conn.IPVersion == packet.IPv6 { + isIpv6 = 1 + } + // initialize variables - info := &VerdictUpdateInfo{ - ipV6: uint8(conn.IPVersion), + info := VerdictUpdateInfo{ + ipV6: isIpv6, protocol: uint8(conn.IPProtocol), + localIP: ipAddressToArray(conn.LocalIP, isIpv6 == 1), localPort: conn.LocalPort, + remoteIP: ipAddressToArray(conn.Entity.IP, isIpv6 == 1), 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) @@ -246,7 +250,7 @@ func GetVersion() (*VersionInfo, error) { defer kextLock.RUnlock() // Check if driver is initialized - if !ready.IsSet() { + if kextHandle == winInvalidHandleValue { log.Error("kext: failed to clear the cache: kext not ready") return nil, ErrKextNotReady } @@ -267,10 +271,6 @@ func GetVersion() (*VersionInfo, error) { return version, nil } -func asByteArray[T any](obj *T) []byte { - return unsafe.Slice((*byte)(unsafe.Pointer(obj)), unsafe.Sizeof(*obj)) -} - func openDriver(filename string) (windows.Handle, error) { u16filename, err := syscall.UTF16FromString(filename) if err != nil { diff --git a/firewall/interception/windowskext/syscall.go b/firewall/interception/windowskext/syscall.go index 69c0b6ef..2b85adf5 100644 --- a/firewall/interception/windowskext/syscall.go +++ b/firewall/interception/windowskext/syscall.go @@ -15,13 +15,13 @@ const ( ) var ( - IOCTL_VERSION = ctlCode(SIOCTL_TYPE, 0x800, METHOD_NEITHER, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA) + IOCTL_VERSION = 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) // 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) + IOCTL_UPDATE_VERDICT = ctlCode(SIOCTL_TYPE, 0x806, METHOD_BUFFERED, windows.FILE_READ_DATA|windows.FILE_WRITE_DATA) ) func ctlCode(device_type, function, method, access uint32) uint32 {