From 5a3124f321759c9816612c17a1dee8122a78277e Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 11 May 2019 22:13:31 +0200 Subject: service: run UI with elevated token There are too many attacks possible when starting this with a non-elevated token. --- attacksurface.md | 10 +-- service/securityapi.go | 184 -------------------------------------------- service/service_manager.go | 33 +++----- service/zsyscall_windows.go | 169 +--------------------------------------- 4 files changed, 15 insertions(+), 381 deletions(-) diff --git a/attacksurface.md b/attacksurface.md index 7eefb677..8010d7b0 100644 --- a/attacksurface.md +++ b/attacksurface.md @@ -29,17 +29,15 @@ The manager service is a userspace service running as Local System, responsible - A writable `CreateFileMapping` handle to a binary ringlog shared by all services, inherited by the unprivileged UI process. It's unclear if this brings with it surprising hidden attack surface in the mm system. - It listens for service changes in tunnel services according to the string prefix "WireGuardTunnel$". - It manages DPAPI-encrypted configuration files in Local System's local appdata directory, and makes some effort to enforce good configuration filenames. - - It uses `wtsEnumerateSessions` and `WTSSESSION_NOTIFICATION` to walk through each available session. It then uses `wtfQueryUserToken`, and then calls `GetTokenInformation(TokenGroups)` on it. If one of the returned group's SIDs matches `CreateWellKnownSid(WinBuiltinAdministratorsSid)`, and has attributes of either `SE_GROUP_ENABLED` or `SE_GROUP_USE_FOR_DENY_ONLY` and calling `GetTokenInformation(TokenElevation)` on it or its `TokenLinkedToken` indicates that either is elevated, then it spawns the unprivileged UI process as that (unelevated) user token, passing it three unnamed pipe handles for IPC and the log mapping handle, as descried above. + - It uses `wtsEnumerateSessions` and `WTSSESSION_NOTIFICATION` to walk through each available session. It then uses `wtfQueryUserToken`, and then calls `GetTokenInformation(TokenGroups)` on it. If one of the returned group's SIDs matches `CreateWellKnownSid(WinBuiltinAdministratorsSid)`, and has attributes of either `SE_GROUP_ENABLED` or `SE_GROUP_USE_FOR_DENY_ONLY` and calling `GetTokenInformation(TokenElevation)` on it or its `TokenLinkedToken` indicates that either is elevated, then it spawns the UI process as that the elevated user token, passing it three unnamed pipe handles for IPC and the log mapping handle, as descried above. ### UI -The UI is an unprivileged process running as the ordinary user for each user who is in the Administrators group (per the above). It exposes: +The UI is a process running for each user who is in the Administrators group (per the above). It exposes: - - The manager service (above) calls `GetSecurityInfo(ATTRIBUTE_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION|SCOPE_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION)` on itself. Then it examines all of the groups associated with the users token, and finds the first one that is of type `SE_GROUP_LOGON_ID`. It adds to the prior DACL one for this SID for only `PROCESS_QUERY_LIMITED_INFORMATION` permission. Then it passes the returned security attributes as the UI's process and thread attributes in the call to `CreateProcessAsUser`. This means that debugging the UI process (in order for another process to steal its handles and exfiltrate private keys) is only possible by processes that can debug the manager service. - - Right now, we're removing the SACL/integrity level from the above, which means the UI process only requires medium integrity to access it. Requiring greater integrity level access prevents the process from running properly, unfortunately (`ERROR_PRIVILEGE_NOT_HELD`). It would be nice to require high integrity to open the process, without having to increase the privileges that the process has in its own token. - - Actually, for the time being, we're giving the UI a high integrity token. This is a bummer but seems unavoidable. - - Perhaps due to the above and other reasons, it appears that it is possible for other processes to write into the UI process's message loop, which is bad, and might defeat the purpose of the above. On the other hand, the permissions of the above are fairly strict (`O:BAG:SYD:(A;;0x1fffff;;;SY)(A;;0x121411;;;BA)(A;;0x1000;;;S-logonsid)`). + - Since the UI process is executed with an elevated token, it runs at high integrity and should be immune to various shatter attacks, modulo the great variety of clever bypasses in the latest Windows release. - It renders highlighted config files to a msftedit.dll control, which typically is capable of all sorts of OLE and RTF nastiness that we make some attempt to avoid. + - The syntax editor invokes `IID_ITextDocument` with `QueryInterface`, which might undermine the high integrity token. ### Updates diff --git a/service/securityapi.go b/service/securityapi.go index cf2e597a..37713b32 100644 --- a/service/securityapi.go +++ b/service/securityapi.go @@ -7,10 +7,8 @@ package service import ( "errors" - "fmt" "golang.org/x/sys/windows" "runtime" - "syscall" "unicode/utf16" "unsafe" ) @@ -51,68 +49,10 @@ type wtsSessionInfo struct { //sys wtsFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory const ( - SE_KERNEL_OBJECT = 6 - - SE_GROUP_LOGON_ID = 0xC0000000 SE_GROUP_ENABLED = 0x00000004 SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010 - - ACL_REVISION = 2 - - PROCESS_TERMINATE = 0x0001 - PROCESS_CREATE_THREAD = 0x0002 - PROCESS_SET_SESSIONID = 0x0004 - PROCESS_VM_OPERATION = 0x0008 - PROCESS_VM_READ = 0x0010 - PROCESS_VM_WRITE = 0x0020 - PROCESS_DUP_HANDLE = 0x0040 - PROCESS_CREATE_PROCESS = 0x0080 - PROCESS_SET_QUOTA = 0x0100 - PROCESS_SET_INFORMATION = 0x0200 - PROCESS_QUERY_INFORMATION = 0x0400 - PROCESS_SUSPEND_RESUME = 0x0800 - PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 - - OWNER_SECURITY_INFORMATION = 0x00000001 - GROUP_SECURITY_INFORMATION = 0x00000002 - DACL_SECURITY_INFORMATION = 0x00000004 - SACL_SECURITY_INFORMATION = 0x00000008 - LABEL_SECURITY_INFORMATION = 0x00000010 - ATTRIBUTE_SECURITY_INFORMATION = 0x00000020 - SCOPE_SECURITY_INFORMATION = 0x00000040 - BACKUP_SECURITY_INFORMATION = 0x00010000 - PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000 - PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000 - UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000 - UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000 - - AclRevisionInformation = 1 - AclSizeInformation = 2 ) -type ACL_SIZE_INFORMATION struct { - aceCount uint32 - aclBytesInUse uint32 - aclBytesFree uint32 -} -type ACE_HEADER struct { - aceType byte - aceFlags byte - aceSize uint16 -} - -//sys getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, owner *uintptr, group *uintptr, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo -//sys addAccessAllowedAce(acl *byte, aceRevision uint32, accessmask uint32, sid *windows.SID) (err error) = advapi32.AddAccessAllowedAce -//sys setSecurityDescriptorDacl(securityDescriptor *byte, daclPresent bool, dacl *byte, defaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl -//sys setSecurityDescriptorSacl(securityDescriptor *byte, saclPresent bool, sacl *byte, defaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl -//sys getAclInformation(acl *byte, info *ACL_SIZE_INFORMATION, len uint32, infoclass uint32) (err error) = advapi32.GetAclInformation -//sys getAce(acl *byte, index uint32, ace **ACE_HEADER) (err error) = advapi32.GetAce -//sys addAce(acl *byte, revision uint32, index uint32, ace *ACE_HEADER, lenAce uint32) (err error) = advapi32.AddAce -//sys initializeAcl(acl *byte, len uint32, revision uint32) (err error) = advapi32.InitializeAcl -//sys makeAbsoluteSd(selfRelativeSecurityDescriptor uintptr, absoluteSecurityDescriptor *byte, absoluteSecurityDescriptorSize *uint32, dacl *byte, daclSize *uint32, sacl *byte, saclSize *uint32, owner *byte, ownerSize *uint32, primaryGroup *byte, primaryGroupSize *uint32) (err error) = advapi32.MakeAbsoluteSD -//sys makeSelfRelativeSd(absoluteSecurityDescriptor *byte, relativeSecurityDescriptor *byte, relativeSecurityDescriptorSize *uint32) (err error) = advapi32.MakeSelfRelativeSD -//sys setTokenInformation(token windows.Token, infoClass uint32, info *byte, infoSize uint32) (err error) = advapi32.SetTokenInformation - //sys createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock //sys destroyEnvironmentBlock(block uintptr) (err error) = userenv.DestroyEnvironmentBlock @@ -149,7 +89,6 @@ func tokenIsElevated(token windows.Token) bool { return false } return outLen == uint32(unsafe.Sizeof(isElevated)) && isElevated != 0 - } func getElevatedToken(token windows.Token) (windows.Token, error) { @@ -189,126 +128,3 @@ func tokenIsMemberOfBuiltInAdministrator(token windows.Token) bool { runtime.KeepAlive(gs) return isAdmin } - -func sliceToSecurityAttributes(sa []byte) *syscall.SecurityAttributes { - return &syscall.SecurityAttributes{ - Length: uint32(len(sa)), - SecurityDescriptor: uintptr(unsafe.Pointer(&sa[0])), - } -} - -func getSecurityAttributes(mainToken windows.Token, tokenThatHasLogonSession windows.Token) ([]byte, error) { - gs, err := tokenThatHasLogonSession.GetTokenGroups() - if err != nil { - return nil, err - } - var logonSid *windows.SID - groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(unsafe.Pointer(&gs.Groups[0]))[:gs.GroupCount] - for _, g := range groups { - if g.Attributes&SE_GROUP_LOGON_ID != 0 && g.Attributes&SE_GROUP_ENABLED != 0 { - logonSid = g.Sid - break - } - } - if logonSid == nil { - return nil, errors.New("Unable to find logon SID") - } - - var originalSecurityDescriptor uintptr - err = getSecurityInfo(windows.Handle(mainToken), SE_KERNEL_OBJECT, ATTRIBUTE_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION|SCOPE_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, nil, nil, nil, nil, &originalSecurityDescriptor) - if err != nil { - return nil, err - } - var ( - absoluteSecurityDescriptorSize uint32 - daclSize uint32 - saclSize uint32 - ownerSize uint32 - primaryGroupSize uint32 - ) - err = makeAbsoluteSd(originalSecurityDescriptor, nil, &absoluteSecurityDescriptorSize, nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &primaryGroupSize) - if err != windows.ERROR_INSUFFICIENT_BUFFER { - windows.LocalFree(windows.Handle(originalSecurityDescriptor)) - return nil, fmt.Errorf("Expected insufficient buffer from MakeAbsoluteSd, but got: %v", err) - } - absoluteSecurityDescriptor := make([]byte, absoluteSecurityDescriptorSize) - dacl := make([]byte, daclSize) - sacl := make([]byte, saclSize) - owner := make([]byte, ownerSize) - primaryGroup := make([]byte, primaryGroupSize) - err = makeAbsoluteSd(originalSecurityDescriptor, &absoluteSecurityDescriptor[0], &absoluteSecurityDescriptorSize, &dacl[0], &daclSize, &sacl[0], &saclSize, &owner[0], &ownerSize, &primaryGroup[0], &primaryGroupSize) - if err != nil { - windows.LocalFree(windows.Handle(originalSecurityDescriptor)) - return nil, err - } - windows.LocalFree(windows.Handle(originalSecurityDescriptor)) - - var daclInfo ACL_SIZE_INFORMATION - err = getAclInformation(&dacl[0], &daclInfo, uint32(unsafe.Sizeof(daclInfo)), AclSizeInformation) - if err != nil { - return nil, err - } - newDacl := make([]byte, daclInfo.aclBytesInUse*2+0x1000) - err = initializeAcl(&newDacl[0], uint32(len(newDacl)), ACL_REVISION) - if err != nil { - return nil, err - } - var ace *ACE_HEADER - for i := uint32(0); i < daclInfo.aceCount; i++ { - err = getAce(&dacl[0], i, &ace) - if err != nil { - return nil, err - } - err = addAce(&newDacl[0], ACL_REVISION, ^uint32(0), ace, uint32(ace.aceSize)) - if err != nil { - return nil, err - } - } - runtime.KeepAlive(dacl) - err = addAccessAllowedAce(&newDacl[0], ACL_REVISION, PROCESS_QUERY_LIMITED_INFORMATION, logonSid) - if err != nil { - return nil, err - } - runtime.KeepAlive(gs) - err = setSecurityDescriptorDacl(&absoluteSecurityDescriptor[0], true, &newDacl[0], false) - if err != nil { - return nil, err - } - //TODO: This should not be required!! But right now we can't give the process the high integrity SACL, which is unfortunate. So we unset it. - err = setSecurityDescriptorSacl(&absoluteSecurityDescriptor[0], false, nil, true) - if err != nil { - return nil, err - } - var selfRelativeSecurityDescriptorSize uint32 - err = makeSelfRelativeSd(&absoluteSecurityDescriptor[0], nil, &selfRelativeSecurityDescriptorSize) - if err != windows.ERROR_INSUFFICIENT_BUFFER { - return nil, fmt.Errorf("Expected insufficient buffer from MakeSelfRelativeSd, but got: %v", err) - } - relativeSecurityDescriptor := make([]byte, selfRelativeSecurityDescriptorSize) - err = makeSelfRelativeSd(&absoluteSecurityDescriptor[0], &relativeSecurityDescriptor[0], &selfRelativeSecurityDescriptorSize) - if err != nil { - return nil, err - } - runtime.KeepAlive(absoluteSecurityDescriptor) - runtime.KeepAlive(newDacl) - runtime.KeepAlive(sacl) - runtime.KeepAlive(owner) - runtime.KeepAlive(primaryGroup) - - return relativeSecurityDescriptor, nil -} - -func addElevatedIntegrityToUserToken(elevatedToken, userToken windows.Token) error { - //TODO: We really don't want to be doing this. See the note above. We'd rather the UI process have very few permissions in its token, and do everything with its SACL. But we can't. - var integrityLevel [0x2000]byte - len := uint32(len(integrityLevel)) - err := windows.GetTokenInformation(elevatedToken, windows.TokenIntegrityLevel, &integrityLevel[0], len, &len) - if err != nil { - return err - } - err = setTokenInformation(userToken, windows.TokenIntegrityLevel, &integrityLevel[0], len) - if err != nil { - return err - } - return nil -} diff --git a/service/service_manager.go b/service/service_manager.go index c1416c49..c61bd517 100644 --- a/service/service_manager.go +++ b/service/service_manager.go @@ -90,26 +90,24 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest if err != nil { return } - defer userToken.Close() if !tokenIsMemberOfBuiltInAdministrator(userToken) { + userToken.Close() return } user, err := userToken.GetTokenUser() if err != nil { log.Printf("Unable to lookup user from token: %v", err) + userToken.Close() return } username, domain, accType, err := user.User.Sid.LookupAccount("") if err != nil { log.Printf("Unable to lookup username from sid: %v", err) + userToken.Close() return } if accType != windows.SidTypeUser { - return - } - env, err := userEnviron(userToken) - if err != nil { - log.Printf("Unable to determine user environment: %v", err) + userToken.Close() return } userTokenInfo := &UserTokenInfo{} @@ -119,24 +117,15 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest return } if userTokenInfo.elevatedToken != userToken { - defer userTokenInfo.elevatedToken.Close() + userToken.Close() } - userTokenInfo.elevatedEnvironment, err = userEnviron(userTokenInfo.elevatedToken) + defer userTokenInfo.elevatedToken.Close() + userToken = 0 + userTokenInfo.elevatedEnvironment, err = userEnviron(userTokenInfo.elevatedToken) //TODO: This seems to have the same PATH as the userToken. Aren't there attacks? if err != nil { log.Printf("Unable to determine elevated environment: %v", err) return } - currentProcess, _ := windows.GetCurrentProcess() - securityAttributes, err := getSecurityAttributes(windows.Token(currentProcess), userToken) - if err != nil { - log.Printf("Unable to extract security attributes from manager token and combine them with SID from user token: %v", err) - return - } - err = addElevatedIntegrityToUserToken(userTokenInfo.elevatedToken, userToken) - if err != nil { - log.Printf("Unable to copy integrity level from elevated token to user token") - return - } first := true for { if stoppingManager { @@ -180,12 +169,10 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest log.Printf("Starting UI process for user '%s@%s' for session %d", username, domain, session) attr := &os.ProcAttr{ Sys: &syscall.SysProcAttr{ - Token: syscall.Token(userToken), - ProcessAttributes: sliceToSecurityAttributes(securityAttributes), - ThreadAttributes: sliceToSecurityAttributes(securityAttributes), + Token: syscall.Token(userTokenInfo.elevatedToken), }, Files: []*os.File{devNull, devNull, devNull}, - Env: env, + Env: userTokenInfo.elevatedEnvironment, } procsLock.Lock() var proc *os.Process diff --git a/service/zsyscall_windows.go b/service/zsyscall_windows.go index 9819b1f2..20f9753b 100644 --- a/service/zsyscall_windows.go +++ b/service/zsyscall_windows.go @@ -38,24 +38,13 @@ func errnoErr(e syscall.Errno) error { var ( modwtsapi32 = windows.NewLazySystemDLL("wtsapi32.dll") - modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") moduserenv = windows.NewLazySystemDLL("userenv.dll") + modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") modkernel32 = windows.NewLazySystemDLL("kernel32.dll") procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken") procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW") procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory") - procGetSecurityInfo = modadvapi32.NewProc("GetSecurityInfo") - procAddAccessAllowedAce = modadvapi32.NewProc("AddAccessAllowedAce") - procSetSecurityDescriptorDacl = modadvapi32.NewProc("SetSecurityDescriptorDacl") - procSetSecurityDescriptorSacl = modadvapi32.NewProc("SetSecurityDescriptorSacl") - procGetAclInformation = modadvapi32.NewProc("GetAclInformation") - procGetAce = modadvapi32.NewProc("GetAce") - procAddAce = modadvapi32.NewProc("AddAce") - procInitializeAcl = modadvapi32.NewProc("InitializeAcl") - procMakeAbsoluteSD = modadvapi32.NewProc("MakeAbsoluteSD") - procMakeSelfRelativeSD = modadvapi32.NewProc("MakeSelfRelativeSD") - procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW") @@ -91,162 +80,6 @@ func wtsFreeMemory(ptr uintptr) { return } -func getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, owner *uintptr, group *uintptr, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) { - r1, _, e1 := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(securityDescriptor)), 0) - if r1 != 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func addAccessAllowedAce(acl *byte, aceRevision uint32, accessmask uint32, sid *windows.SID) (err error) { - r1, _, e1 := syscall.Syscall6(procAddAccessAllowedAce.Addr(), 4, uintptr(unsafe.Pointer(acl)), uintptr(aceRevision), uintptr(accessmask), uintptr(unsafe.Pointer(sid)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setSecurityDescriptorDacl(securityDescriptor *byte, daclPresent bool, dacl *byte, defaulted bool) (err error) { - var _p0 uint32 - if daclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if defaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(securityDescriptor)), uintptr(_p0), uintptr(unsafe.Pointer(dacl)), uintptr(_p1), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setSecurityDescriptorSacl(securityDescriptor *byte, saclPresent bool, sacl *byte, defaulted bool) (err error) { - var _p0 uint32 - if saclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if defaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(securityDescriptor)), uintptr(_p0), uintptr(unsafe.Pointer(sacl)), uintptr(_p1), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getAclInformation(acl *byte, info *ACL_SIZE_INFORMATION, len uint32, infoclass uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetAclInformation.Addr(), 4, uintptr(unsafe.Pointer(acl)), uintptr(unsafe.Pointer(info)), uintptr(len), uintptr(infoclass), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getAce(acl *byte, index uint32, ace **ACE_HEADER) (err error) { - r1, _, e1 := syscall.Syscall(procGetAce.Addr(), 3, uintptr(unsafe.Pointer(acl)), uintptr(index), uintptr(unsafe.Pointer(ace))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func addAce(acl *byte, revision uint32, index uint32, ace *ACE_HEADER, lenAce uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procAddAce.Addr(), 5, uintptr(unsafe.Pointer(acl)), uintptr(revision), uintptr(index), uintptr(unsafe.Pointer(ace)), uintptr(lenAce), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func initializeAcl(acl *byte, len uint32, revision uint32) (err error) { - r1, _, e1 := syscall.Syscall(procInitializeAcl.Addr(), 3, uintptr(unsafe.Pointer(acl)), uintptr(len), uintptr(revision)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func makeAbsoluteSd(selfRelativeSecurityDescriptor uintptr, absoluteSecurityDescriptor *byte, absoluteSecurityDescriptorSize *uint32, dacl *byte, daclSize *uint32, sacl *byte, saclSize *uint32, owner *byte, ownerSize *uint32, primaryGroup *byte, primaryGroupSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall12(procMakeAbsoluteSD.Addr(), 11, uintptr(selfRelativeSecurityDescriptor), uintptr(unsafe.Pointer(absoluteSecurityDescriptor)), uintptr(unsafe.Pointer(absoluteSecurityDescriptorSize)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclSize)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(saclSize)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(ownerSize)), uintptr(unsafe.Pointer(primaryGroup)), uintptr(unsafe.Pointer(primaryGroupSize)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func makeSelfRelativeSd(absoluteSecurityDescriptor *byte, relativeSecurityDescriptor *byte, relativeSecurityDescriptorSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procMakeSelfRelativeSD.Addr(), 3, uintptr(unsafe.Pointer(absoluteSecurityDescriptor)), uintptr(unsafe.Pointer(relativeSecurityDescriptor)), uintptr(unsafe.Pointer(relativeSecurityDescriptorSize))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setTokenInformation(token windows.Token, infoClass uint32, info *byte, infoSize uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoSize), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - func createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) { var _p0 uint32 if inheritExisting { -- cgit v1.2.3-59-g8ed1b