aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorOdd Stranne <odd@mullvad.net>2019-05-14 10:01:07 +0200
committerOdd Stranne <odd@mullvad.net>2019-05-14 15:29:22 +0200
commitb45e9763a5a9b4bf2dc10121afa5e2a643ec815b (patch)
tree10bd24c20ce5da83f5225d09b017f5338ff6f0e5
parentservice: replace GetIfEntry2Ex with GetIfEntry2 (diff)
downloadwireguard-windows-b45e9763a5a9b4bf2dc10121afa5e2a643ec815b.tar.xz
wireguard-windows-b45e9763a5a9b4bf2dc10121afa5e2a643ec815b.zip
service: drop all privileges for tunnel service
Signed-off-by: Odd Stranne <odd@mullvad.net> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--service/errors.go3
-rw-r--r--service/securityapi.go66
-rw-r--r--service/service_tunnel.go7
-rw-r--r--service/zsyscall_windows.go32
4 files changed, 108 insertions, 0 deletions
diff --git a/service/errors.go b/service/errors.go
index 339b61b3..b76ef656 100644
--- a/service/errors.go
+++ b/service/errors.go
@@ -30,6 +30,7 @@ const (
ErrorOpenNULFile
ErrorTrackTunnels
ErrorEnumerateSessions
+ ErrorDropPrivileges
ErrorWin32
)
@@ -65,6 +66,8 @@ func (e Error) Error() string {
return "Unable to track existing tunnels"
case ErrorEnumerateSessions:
return "Unable to enumerate current sessions"
+ case ErrorDropPrivileges:
+ return "Unable to drop privileges"
case ErrorWin32:
return "An internal Windows error has occurred"
default:
diff --git a/service/securityapi.go b/service/securityapi.go
index 497f43ce..989b4ac3 100644
--- a/service/securityapi.go
+++ b/service/securityapi.go
@@ -55,6 +55,35 @@ type WTS_SESSION_INFO struct {
//sys wtsEnumerateSessions(handle windows.Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
//sys wtsFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
+// TEMP //
+
+type LUID struct {
+ LowPart uint32
+ HighPart int32
+}
+
+type LUID_AND_ATTRIBUTES struct {
+ Luid LUID
+ Attributes uint32
+}
+
+type TOKEN_PRIVILEGES struct {
+ PrivilegeCount uint32
+ Privileges [1]LUID_AND_ATTRIBUTES
+}
+
+const (
+ SE_PRIVILEGE_REMOVED uint32 = 0X00000004
+ TOKEN_READ uint32 = 0x00020008
+ TOKEN_WRITE uint32 = 0x000200e0
+ TokenPrivileges uint32 = 3
+)
+
+//sys adjustTokenPrivileges(token windows.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (err error) = advapi32.AdjustTokenPrivileges
+//sys openProcessToken(processHandle windows.Handle, accessFlags uint32, token *windows.Token) (err error) = advapi32.OpenProcessToken
+
+// END TEMP //
+
const (
SE_GROUP_ENABLED = 0x00000004
SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010
@@ -107,3 +136,40 @@ func tokenIsMemberOfBuiltInAdministrator(token windows.Token) bool {
runtime.KeepAlive(gs)
return isAdmin
}
+
+func dropAllPrivileges() error {
+ processHandle, err := windows.GetCurrentProcess()
+ if err != nil {
+ return err
+ }
+ var processToken windows.Token
+ err = openProcessToken(processHandle, TOKEN_READ | TOKEN_WRITE, (*windows.Token)(unsafe.Pointer(&processToken)))
+ if err != nil {
+ return err
+ }
+ defer processToken.Close()
+ var bufferSizeRequired uint32
+ _ = windows.GetTokenInformation(processToken, TokenPrivileges, nil, 0, (*uint32)(unsafe.Pointer(&bufferSizeRequired)))
+ if bufferSizeRequired == 0 {
+ return errors.New("GetTokenInformation failed to provide a buffer size")
+ }
+ buffer := make([]uint8, bufferSizeRequired)
+ var bytesWritten uint32
+ err = windows.GetTokenInformation(processToken, TokenPrivileges, (*uint8)(unsafe.Pointer(&buffer[0])), (uint32)(len(buffer)), (*uint32)(unsafe.Pointer(&bytesWritten)))
+ if err != nil {
+ return err
+ }
+ if bytesWritten != bufferSizeRequired {
+ return errors.New("GetTokenInformation returned incomplete data")
+ }
+ tokenPrivileges := (*TOKEN_PRIVILEGES)(unsafe.Pointer(&buffer[0]))
+ privs := (*[1024]LUID_AND_ATTRIBUTES)(unsafe.Pointer(&buffer[unsafe.Sizeof(tokenPrivileges.PrivilegeCount)]))
+ for i := uint32(0); i < tokenPrivileges.PrivilegeCount; i++ {
+ privs[i].Attributes = SE_PRIVILEGE_REMOVED
+ }
+ err = adjustTokenPrivileges(processToken, false, tokenPrivileges, 0, nil, nil)
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/service/service_tunnel.go b/service/service_tunnel.go
index c7b469fb..0af7c733 100644
--- a/service/service_tunnel.go
+++ b/service/service_tunnel.go
@@ -194,6 +194,13 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
}
}()
+ logger.Info.Println("Dropping all privileges")
+ err = dropAllPrivileges()
+ if err != nil {
+ serviceError = ErrorDropPrivileges
+ return
+ }
+
changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop}
logger.Info.Println("Startup complete")
diff --git a/service/zsyscall_windows.go b/service/zsyscall_windows.go
index cc40ddea..a269d3a8 100644
--- a/service/zsyscall_windows.go
+++ b/service/zsyscall_windows.go
@@ -44,6 +44,8 @@ var (
procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken")
procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW")
procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory")
+ procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
+ procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken")
procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW")
procSleepEx = modkernel32.NewProc("SleepEx")
)
@@ -77,6 +79,36 @@ func wtsFreeMemory(ptr uintptr) {
return
}
+func adjustTokenPrivileges(token windows.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (err error) {
+ var _p0 uint32
+ if disableAllPrivileges {
+ _p0 = 1
+ } else {
+ _p0 = 0
+ }
+ r1, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func openProcessToken(processHandle windows.Handle, accessFlags uint32, token *windows.Token) (err error) {
+ r1, _, e1 := syscall.Syscall(procOpenProcessToken.Addr(), 3, uintptr(processHandle), uintptr(accessFlags), uintptr(unsafe.Pointer(token)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
func notifyServiceStatusChange(service windows.Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) {
r0, _, _ := syscall.Syscall(procNotifyServiceStatusChangeW.Addr(), 3, uintptr(service), uintptr(notifyMask), uintptr(unsafe.Pointer(notifier)))
if r0 != 0 {