diff --git a/windows/security_windows.go b/windows/security_windows.go index f119a4ad..e9d26bee 100644 --- a/windows/security_windows.go +++ b/windows/security_windows.go @@ -583,9 +583,7 @@ func (tml *Tokenmandatorylabel) Size() uint32 { // Authorization Functions //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 @@ -608,7 +606,9 @@ func (tml *Tokenmandatorylabel) Size() uint32 { type Token Handle // OpenCurrentProcessToken opens the access token -// associated with current process. +// associated with current process. It is a real +// token that needs to be closed, unlike +// GetCurrentProcessToken. func OpenCurrentProcessToken() (Token, error) { p, e := GetCurrentProcess() if e != nil { @@ -622,6 +622,27 @@ func OpenCurrentProcessToken() (Token, error) { return t, nil } +// GetCurrentProcessToken returns the access token associated with +// the current process. It is a pseudo token that does not need +// to be closed. +func GetCurrentProcessToken() Token { + return Token(^uintptr(4 - 1)) +} + +// GetCurrentThreadToken return the access token associated with +// the current thread. It is a pseudo token that does not need +// to be closed. +func GetCurrentThreadToken() Token { + return Token(^uintptr(5 - 1)) +} + +// GetCurrentThreadEffectiveToken returns the effective access token +// associated with the current thread. It is a pseudo token that does +// not need to be closed. +func GetCurrentThreadEffectiveToken() Token { + return Token(^uintptr(6 - 1)) +} + // Close releases access to access token. func (t Token) Close() error { return CloseHandle(Handle(t)) diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go index f2f449cd..423fa9ec 100644 --- a/windows/syscall_windows_test.go +++ b/windows/syscall_windows_test.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "syscall" "testing" @@ -104,3 +105,67 @@ func TestCreateWellKnownSid(t *testing.T) { t.Fatalf("Expecting administrators to be S-1-5-32-544, but found %s instead", sidStr) } } + +func TestPseudoTokens(t *testing.T) { + version, err := windows.GetVersion() + if err != nil { + t.Fatal(err) + } + if ((version&0xffff)>>8)|((version&0xff)<<8) < 0x0602 { + return + } + + realProcessToken, err := windows.OpenCurrentProcessToken() + if err != nil { + t.Fatal(err) + } + defer realProcessToken.Close() + realProcessUser, err := realProcessToken.GetTokenUser() + if err != nil { + t.Fatal(err) + } + + pseudoProcessToken := windows.GetCurrentProcessToken() + pseudoProcessUser, err := pseudoProcessToken.GetTokenUser() + if err != nil { + t.Fatal(err) + } + if !windows.EqualSid(realProcessUser.User.Sid, pseudoProcessUser.User.Sid) { + t.Fatal("The real process token does not have the same as the pseudo process token") + } + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err = windows.RevertToSelf() + if err != nil { + t.Fatal(err) + } + + pseudoThreadToken := windows.GetCurrentThreadToken() + _, err = pseudoThreadToken.GetTokenUser() + if err != windows.ERROR_NO_TOKEN { + t.Fatal("Expected an empty thread token") + } + pseudoThreadEffectiveToken := windows.GetCurrentThreadEffectiveToken() + pseudoThreadEffectiveUser, err := pseudoThreadEffectiveToken.GetTokenUser() + if err != nil { + t.Fatal(nil) + } + if !windows.EqualSid(realProcessUser.User.Sid, pseudoThreadEffectiveUser.User.Sid) { + t.Fatal("The real process token does not have the same as the pseudo thread effective token, even though we aren't impersonating") + } + + err = windows.ImpersonateSelf(windows.SecurityImpersonation) + if err != nil { + t.Fatal(err) + } + defer windows.RevertToSelf() + pseudoThreadUser, err := pseudoThreadToken.GetTokenUser() + if err != nil { + t.Fatal(err) + } + if !windows.EqualSid(realProcessUser.User.Sid, pseudoThreadUser.User.Sid) { + t.Fatal("The real process token does not have the same as the pseudo thread token after impersonating self") + } +} diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go index 624d02fa..2a0f3969 100644 --- a/windows/zsyscall_windows.go +++ b/windows/zsyscall_windows.go @@ -259,9 +259,7 @@ 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") @@ -2824,12 +2822,6 @@ func OpenProcessToken(process Handle, access uint32, token *Token) (err error) { return } -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 { @@ -2848,12 +2840,6 @@ func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token 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 {