windows: add token manipulation functions and constants

These are extremely useful functions and core to the Windows security
API. They are so useful, in fact, that most of these were taken right
out of the Go repo's internal/syscall/windows package.

Change-Id: I13e34b830dd60f59fcae8085ae2be189d9cc9282
Reviewed-on: https://go-review.googlesource.com/c/sys/+/176625
Reviewed-by: Matt Layher <mdlayher@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Matt Layher <mdlayher@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Jason A. Donenfeld
2019-05-13 11:46:50 +02:00
committed by Ian Lance Taylor
parent a5b02f93d8
commit 3a4b5fb9f7
3 changed files with 222 additions and 7 deletions

View File

@@ -502,6 +502,53 @@ const (
MaxTokenInfoClass
)
// Group attributes inside of Tokengroups.Groups[i].Attributes
const (
SE_GROUP_MANDATORY = 0x00000001
SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002
SE_GROUP_ENABLED = 0x00000004
SE_GROUP_OWNER = 0x00000008
SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010
SE_GROUP_INTEGRITY = 0x00000020
SE_GROUP_INTEGRITY_ENABLED = 0x00000040
SE_GROUP_LOGON_ID = 0xC0000000
SE_GROUP_RESOURCE = 0x20000000
SE_GROUP_VALID_ATTRIBUTES = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED | SE_GROUP_OWNER | SE_GROUP_USE_FOR_DENY_ONLY | SE_GROUP_LOGON_ID | SE_GROUP_RESOURCE | SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED
)
// Privilege attributes
const (
SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
SE_PRIVILEGE_ENABLED = 0x00000002
SE_PRIVILEGE_REMOVED = 0x00000004
SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000
SE_PRIVILEGE_VALID_ATTRIBUTES = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED | SE_PRIVILEGE_USED_FOR_ACCESS
)
// Token types
const (
TokenPrimary = 1
TokenImpersonation = 2
)
// Impersonation levels
const (
SecurityAnonymous = 0
SecurityIdentification = 1
SecurityImpersonation = 2
SecurityDelegation = 3
)
type LUID struct {
LowPart uint32
HighPart int32
}
type LUIDAndAttributes struct {
Luid LUID
Attributes uint32
}
type SIDAndAttributes struct {
Sid *SID
Attributes uint32
@@ -520,10 +567,33 @@ type Tokengroups struct {
Groups [1]SIDAndAttributes
}
type Tokenprivileges struct {
PrivilegeCount uint32
Privileges [1]LUIDAndAttributes
}
type Tokenmandatorylabel struct {
Label SIDAndAttributes
}
func (tml *Tokenmandatorylabel) Size() uint32 {
return uint32(unsafe.Sizeof(Tokenmandatorylabel{})) + GetLengthSid(tml.Label.Sid)
}
// Authorization Functions
//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
//sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
//sys GetCurrentThreadToken() (token Token) = advapi32.GetCurrentThreadToken
//sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
//sys GetCurrentProcessToken() (token Token) = advapi32.GetCurrentProcessToken
//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
//sys RevertToSelf() (err error) = advapi32.RevertToSelf
//sys SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken
//sys LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW
//sys AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) = advapi32.AdjustTokenPrivileges
//sys GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
//sys SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) = advapi32.SetTokenInformation
//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW

View File

@@ -171,6 +171,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error)
//sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW
//sys GetCurrentProcess() (pseudoHandle Handle, err error)
//sys GetCurrentThread() (pseudoHandle Handle, err error)
//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error)
//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error)
//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff]

View File

@@ -111,6 +111,7 @@ var (
procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess")
procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW")
procGetCurrentProcess = modkernel32.NewProc("GetCurrentProcess")
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
procGetProcessTimes = modkernel32.NewProc("GetProcessTimes")
procDuplicateHandle = modkernel32.NewProc("DuplicateHandle")
procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject")
@@ -253,7 +254,17 @@ var (
procEqualSid = modadvapi32.NewProc("EqualSid")
procCheckTokenMembership = modadvapi32.NewProc("CheckTokenMembership")
procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken")
procGetCurrentThreadToken = modadvapi32.NewProc("GetCurrentThreadToken")
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
procGetCurrentProcessToken = modadvapi32.NewProc("GetCurrentProcessToken")
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
procSetThreadToken = modadvapi32.NewProc("SetThreadToken")
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation")
procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation")
procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx")
procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW")
procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW")
)
@@ -1076,6 +1087,19 @@ func GetCurrentProcess() (pseudoHandle Handle, err error) {
return
}
func GetCurrentThread() (pseudoHandle Handle, err error) {
r0, _, e1 := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
pseudoHandle = Handle(r0)
if pseudoHandle == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) {
r1, _, e1 := syscall.Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0)
if r1 == 0 {
@@ -2729,8 +2753,8 @@ func checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (
return
}
func OpenProcessToken(h Handle, access uint32, token *Token) (err error) {
r1, _, e1 := syscall.Syscall(procOpenProcessToken.Addr(), 3, uintptr(h), uintptr(access), uintptr(unsafe.Pointer(token)))
func OpenProcessToken(process Handle, access uint32, token *Token) (err error) {
r1, _, e1 := syscall.Syscall(procOpenProcessToken.Addr(), 3, uintptr(process), uintptr(access), uintptr(unsafe.Pointer(token)))
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
@@ -2741,8 +2765,128 @@ func OpenProcessToken(h Handle, access uint32, token *Token) (err error) {
return
}
func GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procGetTokenInformation.Addr(), 5, uintptr(t), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0)
func GetCurrentThreadToken() (token Token) {
r0, _, _ := syscall.Syscall(procGetCurrentThreadToken.Addr(), 0, 0, 0, 0)
token = Token(r0)
return
}
func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) {
var _p0 uint32
if openAsSelf {
_p0 = 1
} else {
_p0 = 0
}
r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func GetCurrentProcessToken() (token Token) {
r0, _, _ := syscall.Syscall(procGetCurrentProcessToken.Addr(), 0, 0, 0, 0)
token = Token(r0)
return
}
func ImpersonateSelf(impersonationlevel uint32) (err error) {
r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0)
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func RevertToSelf() (err error) {
r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func SetThreadToken(thread *Handle, token Token) (err error) {
r1, _, e1 := syscall.Syscall(procSetThreadToken.Addr(), 2, uintptr(unsafe.Pointer(thread)), uintptr(token), 0)
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) {
r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, 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 GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procGetTokenInformation.Addr(), 5, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0)
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), 0, 0)
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) {
r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(existingToken), uintptr(desiredAccess), uintptr(unsafe.Pointer(tokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(newToken)))
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)