Przeglądaj źródła

windows: do not query library for inline functions

The GetCurrent*Token variety of functions are actually implemented as
inline functions in the header files of the SDK. Attempting to call out
to these as library functions is an error. This commit also adds a test
to ensure that these work as expected.

Change-Id: I105f1ca1a8936114fe61bc22188200c31f240a23
Reviewed-on: https://go-review.googlesource.com/c/sys/+/177840
Run-TryBot: Jason Donenfeld <Jason@zx2c4.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Jason A. Donenfeld 6 lat temu
rodzic
commit
8097e1b27f

+ 24 - 3
windows/security_windows.go

@@ -583,9 +583,7 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
 // Authorization Functions
 // Authorization Functions
 //sys	checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
 //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	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	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	ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
 //sys	RevertToSelf() (err error) = advapi32.RevertToSelf
 //sys	RevertToSelf() (err error) = advapi32.RevertToSelf
 //sys	SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken
 //sys	SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken
@@ -608,7 +606,9 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
 type Token Handle
 type Token Handle
 
 
 // OpenCurrentProcessToken opens the access token
 // 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) {
 func OpenCurrentProcessToken() (Token, error) {
 	p, e := GetCurrentProcess()
 	p, e := GetCurrentProcess()
 	if e != nil {
 	if e != nil {
@@ -622,6 +622,27 @@ func OpenCurrentProcessToken() (Token, error) {
 	return t, nil
 	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.
 // Close releases access to access token.
 func (t Token) Close() error {
 func (t Token) Close() error {
 	return CloseHandle(Handle(t))
 	return CloseHandle(Handle(t))

+ 65 - 0
windows/syscall_windows_test.go

@@ -8,6 +8,7 @@ import (
 	"io/ioutil"
 	"io/ioutil"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
+	"runtime"
 	"syscall"
 	"syscall"
 	"testing"
 	"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)
 		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")
+	}
+}

+ 0 - 14
windows/zsyscall_windows.go

@@ -259,9 +259,7 @@ var (
 	procEqualSid                           = modadvapi32.NewProc("EqualSid")
 	procEqualSid                           = modadvapi32.NewProc("EqualSid")
 	procCheckTokenMembership               = modadvapi32.NewProc("CheckTokenMembership")
 	procCheckTokenMembership               = modadvapi32.NewProc("CheckTokenMembership")
 	procOpenProcessToken                   = modadvapi32.NewProc("OpenProcessToken")
 	procOpenProcessToken                   = modadvapi32.NewProc("OpenProcessToken")
-	procGetCurrentThreadToken              = modadvapi32.NewProc("GetCurrentThreadToken")
 	procOpenThreadToken                    = modadvapi32.NewProc("OpenThreadToken")
 	procOpenThreadToken                    = modadvapi32.NewProc("OpenThreadToken")
-	procGetCurrentProcessToken             = modadvapi32.NewProc("GetCurrentProcessToken")
 	procImpersonateSelf                    = modadvapi32.NewProc("ImpersonateSelf")
 	procImpersonateSelf                    = modadvapi32.NewProc("ImpersonateSelf")
 	procRevertToSelf                       = modadvapi32.NewProc("RevertToSelf")
 	procRevertToSelf                       = modadvapi32.NewProc("RevertToSelf")
 	procSetThreadToken                     = modadvapi32.NewProc("SetThreadToken")
 	procSetThreadToken                     = modadvapi32.NewProc("SetThreadToken")
@@ -2824,12 +2822,6 @@ func OpenProcessToken(process Handle, access uint32, token *Token) (err error) {
 	return
 	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) {
 func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) {
 	var _p0 uint32
 	var _p0 uint32
 	if openAsSelf {
 	if openAsSelf {
@@ -2848,12 +2840,6 @@ func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token
 	return
 	return
 }
 }
 
 
-func GetCurrentProcessToken() (token Token) {
-	r0, _, _ := syscall.Syscall(procGetCurrentProcessToken.Addr(), 0, 0, 0, 0)
-	token = Token(r0)
-	return
-}
-
 func ImpersonateSelf(impersonationlevel uint32) (err error) {
 func ImpersonateSelf(impersonationlevel uint32) (err error) {
 	r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0)
 	r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0)
 	if r1 == 0 {
 	if r1 == 0 {