dd931d9b48
Reviewed-on: https://go-review.googlesource.com/136435 gotools/: * Makefile.am (mostlyclean-local): Run chmod on check-go-dir to make sure it is writable. (check-go-tools): Likewise. (check-vet): Copy internal/objabi to check-vet-dir. * Makefile.in: Rebuild. From-SVN: r264546
140 lines
2.8 KiB
Go
140 lines
2.8 KiB
Go
// Copyright 2017 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build windows
|
|
|
|
package windows_test
|
|
|
|
import (
|
|
"fmt"
|
|
"internal/syscall/windows"
|
|
"os"
|
|
"os/exec"
|
|
"syscall"
|
|
"testing"
|
|
"unsafe"
|
|
)
|
|
|
|
func TestRunAtLowIntegrity(t *testing.T) {
|
|
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
|
|
wil, err := getProcessIntegrityLevel()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
|
|
os.Exit(9)
|
|
return
|
|
}
|
|
fmt.Printf("%s", wil)
|
|
os.Exit(0)
|
|
return
|
|
}
|
|
|
|
cmd := exec.Command(os.Args[0], "-test.run=TestRunAtLowIntegrity", "--")
|
|
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
|
|
|
|
token, err := getIntegrityLevelToken(sidWilLow)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer token.Close()
|
|
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
Token: token,
|
|
}
|
|
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if string(out) != sidWilLow {
|
|
t.Fatalf("Child process did not run as low integrity level: %s", string(out))
|
|
}
|
|
}
|
|
|
|
const (
|
|
sidWilLow = `S-1-16-4096`
|
|
)
|
|
|
|
func getProcessIntegrityLevel() (string, error) {
|
|
procToken, err := syscall.OpenCurrentProcessToken()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer procToken.Close()
|
|
|
|
p, err := tokenGetInfo(procToken, syscall.TokenIntegrityLevel, 64)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
tml := (*windows.TOKEN_MANDATORY_LABEL)(p)
|
|
|
|
sid := (*syscall.SID)(unsafe.Pointer(tml.Label.Sid))
|
|
|
|
return sid.String()
|
|
}
|
|
|
|
func tokenGetInfo(t syscall.Token, class uint32, initSize int) (unsafe.Pointer, error) {
|
|
n := uint32(initSize)
|
|
for {
|
|
b := make([]byte, n)
|
|
e := syscall.GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
|
|
if e == nil {
|
|
return unsafe.Pointer(&b[0]), nil
|
|
}
|
|
if e != syscall.ERROR_INSUFFICIENT_BUFFER {
|
|
return nil, e
|
|
}
|
|
if n <= uint32(len(b)) {
|
|
return nil, e
|
|
}
|
|
}
|
|
}
|
|
|
|
func getIntegrityLevelToken(wns string) (syscall.Token, error) {
|
|
var procToken, token syscall.Token
|
|
|
|
proc, err := syscall.GetCurrentProcess()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer syscall.CloseHandle(proc)
|
|
|
|
err = syscall.OpenProcessToken(proc,
|
|
syscall.TOKEN_DUPLICATE|
|
|
syscall.TOKEN_ADJUST_DEFAULT|
|
|
syscall.TOKEN_QUERY|
|
|
syscall.TOKEN_ASSIGN_PRIMARY,
|
|
&procToken)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer procToken.Close()
|
|
|
|
sid, err := syscall.StringToSid(wns)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
tml := &windows.TOKEN_MANDATORY_LABEL{}
|
|
tml.Label.Attributes = windows.SE_GROUP_INTEGRITY
|
|
tml.Label.Sid = sid
|
|
|
|
err = windows.DuplicateTokenEx(procToken, 0, nil, windows.SecurityImpersonation,
|
|
windows.TokenPrimary, &token)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
err = windows.SetTokenInformation(token,
|
|
syscall.TokenIntegrityLevel,
|
|
uintptr(unsafe.Pointer(tml)),
|
|
tml.Size())
|
|
if err != nil {
|
|
token.Close()
|
|
return 0, err
|
|
}
|
|
return token, nil
|
|
}
|