diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-05-14 17:00:10 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-05-14 17:10:50 +0200 |
commit | bfdb3aa855de75d91c5d191ef116c651feb0fcfc (patch) | |
tree | a3050b6130f1eef70baccfe7305a7a7884c4e153 /service | |
parent | service: drop all privileges for tunnel service (diff) | |
download | wireguard-windows-bfdb3aa855de75d91c5d191ef116c651feb0fcfc.tar.xz wireguard-windows-bfdb3aa855de75d91c5d191ef116c651feb0fcfc.zip |
service: clean up token mangling
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'service')
-rw-r--r-- | service/securityapi.go | 62 | ||||
-rw-r--r-- | service/service_manager.go | 2 | ||||
-rw-r--r-- | service/service_tunnel.go | 14 | ||||
-rw-r--r-- | service/zsyscall_windows.go | 32 |
4 files changed, 21 insertions, 89 deletions
diff --git a/service/securityapi.go b/service/securityapi.go index 989b4ac3..a7e6072c 100644 --- a/service/securityapi.go +++ b/service/securityapi.go @@ -55,40 +55,6 @@ 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 -) - func tokenIsElevated(token windows.Token) bool { var isElevated uint32 var outLen uint32 @@ -116,7 +82,7 @@ func getElevatedToken(token windows.Token) (windows.Token, error) { return windows.Token(0), errors.New("the linked token is not elevated") } -func tokenIsMemberOfBuiltInAdministrator(token windows.Token) bool { +func TokenIsMemberOfBuiltInAdministrator(token windows.Token) bool { adminSid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid) if err != nil { return false @@ -128,7 +94,7 @@ func tokenIsMemberOfBuiltInAdministrator(token windows.Token) bool { groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(unsafe.Pointer(&gs.Groups[0]))[:gs.GroupCount] isAdmin := false for _, g := range groups { - if (g.Attributes&SE_GROUP_USE_FOR_DENY_ONLY != 0 || g.Attributes&SE_GROUP_ENABLED != 0) && windows.EqualSid(g.Sid, adminSid) { + if (g.Attributes&windows.SE_GROUP_USE_FOR_DENY_ONLY != 0 || g.Attributes&windows.SE_GROUP_ENABLED != 0) && windows.EqualSid(g.Sid, adminSid) { isAdmin = true break } @@ -143,33 +109,31 @@ func dropAllPrivileges() error { return err } var processToken windows.Token - err = openProcessToken(processHandle, TOKEN_READ | TOKEN_WRITE, (*windows.Token)(unsafe.Pointer(&processToken))) + err = windows.OpenProcessToken(processHandle, windows.TOKEN_READ|windows.TOKEN_WRITE, &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 { + windows.GetTokenInformation(processToken, windows.TokenPrivileges, nil, 0, &bufferSizeRequired) + if bufferSizeRequired == 0 || bufferSizeRequired < uint32(unsafe.Sizeof(windows.Tokenprivileges{}.PrivilegeCount)) { return errors.New("GetTokenInformation failed to provide a buffer size") } - buffer := make([]uint8, bufferSizeRequired) + buffer := make([]byte, bufferSizeRequired) var bytesWritten uint32 - err = windows.GetTokenInformation(processToken, TokenPrivileges, (*uint8)(unsafe.Pointer(&buffer[0])), (uint32)(len(buffer)), (*uint32)(unsafe.Pointer(&bytesWritten))) + err = windows.GetTokenInformation(processToken, windows.TokenPrivileges, &buffer[0], uint32(len(buffer)), &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)])) + tokenPrivileges := (*windows.Tokenprivileges)(unsafe.Pointer(&buffer[0])) 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 + (*windows.LUIDAndAttributes)(unsafe.Pointer(uintptr(unsafe.Pointer(&tokenPrivileges.Privileges[0])) + unsafe.Sizeof(tokenPrivileges.Privileges[0])*uintptr(i))).Attributes = windows.SE_PRIVILEGE_REMOVED } - return nil + err = windows.AdjustTokenPrivileges(processToken, false, tokenPrivileges, 0, nil, nil) + runtime.KeepAlive(buffer) + return err } diff --git a/service/service_manager.go b/service/service_manager.go index fae8800a..b2d93385 100644 --- a/service/service_manager.go +++ b/service/service_manager.go @@ -91,7 +91,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest if err != nil { return } - if !tokenIsMemberOfBuiltInAdministrator(userToken) { + if !TokenIsMemberOfBuiltInAdministrator(userToken) { userToken.Close() return } diff --git a/service/service_tunnel.go b/service/service_tunnel.go index 0af7c733..3c09ed77 100644 --- a/service/service_tunnel.go +++ b/service/service_tunnel.go @@ -150,6 +150,13 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest, return } + logger.Info.Println("Dropping all privileges") + err = dropAllPrivileges() + if err != nil { + serviceError = ErrorDropPrivileges + return + } + logger.Info.Println("Creating interface instance") dev = device.NewDevice(wintun, logger) @@ -194,13 +201,6 @@ 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 a269d3a8..cc40ddea 100644 --- a/service/zsyscall_windows.go +++ b/service/zsyscall_windows.go @@ -44,8 +44,6 @@ 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") ) @@ -79,36 +77,6 @@ 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 { |