diff options
Diffstat (limited to 'services/tokens.go')
-rw-r--r-- | services/tokens.go | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/services/tokens.go b/services/tokens.go new file mode 100644 index 00000000..aa6f2c4a --- /dev/null +++ b/services/tokens.go @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. + */ + +package services + +import ( + "errors" + "runtime" + "unsafe" + + "golang.org/x/sys/windows" +) + +func TokenIsMemberOfBuiltInAdministrator(token windows.Token) bool { + adminSid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid) + if err != nil { + return false + } + gs, err := token.GetTokenGroups() + if err != nil { + return false + } + groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(unsafe.Pointer(&gs.Groups[0]))[:gs.GroupCount] + isAdmin := false + for _, g := range groups { + 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 + } + } + runtime.KeepAlive(gs) + return isAdmin +} + +func DropAllPrivileges() error { + processHandle, err := windows.GetCurrentProcess() + if err != nil { + return err + } + var processToken windows.Token + 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, 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([]byte, bufferSizeRequired) + var bytesWritten uint32 + 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 := (*windows.Tokenprivileges)(unsafe.Pointer(&buffer[0])) + for i := uint32(0); i < tokenPrivileges.PrivilegeCount; i++ { + (*windows.LUIDAndAttributes)(unsafe.Pointer(uintptr(unsafe.Pointer(&tokenPrivileges.Privileges[0])) + unsafe.Sizeof(tokenPrivileges.Privileges[0])*uintptr(i))).Attributes = windows.SE_PRIVILEGE_REMOVED + } + err = windows.AdjustTokenPrivileges(processToken, false, tokenPrivileges, 0, nil, nil) + runtime.KeepAlive(buffer) + return err +} |