aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/service/securityapi.go
diff options
context:
space:
mode:
Diffstat (limited to 'service/securityapi.go')
-rw-r--r--service/securityapi.go157
1 files changed, 157 insertions, 0 deletions
diff --git a/service/securityapi.go b/service/securityapi.go
new file mode 100644
index 00000000..6c5f7844
--- /dev/null
+++ b/service/securityapi.go
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package service
+
+import (
+ "errors"
+ "golang.org/x/sys/windows"
+ "syscall"
+ "unicode/utf16"
+ "unsafe"
+)
+
+const (
+ wtsSessionLogon uint32 = 5
+ wtsSessionLogoff uint32 = 6
+)
+
+type wtsState int
+
+const (
+ wtsActive wtsState = iota
+ wtsConnected
+ wtsConnectQuery
+ wtsShadow
+ wtsDisconnected
+ wtsIdle
+ wtsListen
+ wtsReset
+ wtsDown
+ wtsInit
+)
+
+type wtsSessionNotification struct {
+ size uint32
+ sessionID uint32
+}
+
+type wtsSessionInfo struct {
+ sessionID uint32
+ windowStationName *uint16
+ state wtsState
+}
+
+//sys wtsQueryUserToken(session uint32, token *windows.Token) (err error) = wtsapi32.WTSQueryUserToken
+//sys wtsEnumerateSessions(handle windows.Handle, reserved uint32, version uint32, sessions **wtsSessionInfo, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
+//sys wtsFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
+
+const (
+ SE_KERNEL_OBJECT = 6
+
+ DACL_SECURITY_INFORMATION = 4
+ ATTRIBUTE_SECURITY_INFORMATION = 16
+)
+
+//sys getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo
+//sys getSecurityDescriptorLength(securityDescriptor uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
+
+//sys createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
+//sys destroyEnvironmentBlock(block uintptr) (err error) = userenv.DestroyEnvironmentBlock
+
+func userEnviron(token windows.Token) (env []string, err error) {
+ var block uintptr
+ err = createEnvironmentBlock(&block, token, false)
+ if err != nil {
+ return
+ }
+ offset := uintptr(0)
+ for {
+ entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(block + offset))[:]
+ for i, v := range entry {
+ if v == 0 {
+ entry = entry[:i]
+ break
+ }
+ }
+ if len(entry) == 0 {
+ break
+ }
+ env = append(env, string(utf16.Decode(entry)))
+ offset += 2 * (uintptr(len(entry)) + 1)
+ }
+ destroyEnvironmentBlock(block)
+ return
+}
+
+func tokenIsElevated(token windows.Token) bool {
+ var isElevated uint32
+ var outLen uint32
+ err := windows.GetTokenInformation(token, windows.TokenElevation, (*byte)(unsafe.Pointer(&isElevated)), uint32(unsafe.Sizeof(isElevated)), &outLen)
+ if err != nil {
+ return false
+ }
+ return outLen == uint32(unsafe.Sizeof(isElevated)) && isElevated != 0
+
+}
+
+func getElevatedToken(token windows.Token) (windows.Token, error) {
+ if tokenIsElevated(token) {
+ return token, nil
+ }
+ var linkedToken windows.Token
+ var outLen uint32
+ err := windows.GetTokenInformation(token, windows.TokenLinkedToken, (*byte)(unsafe.Pointer(&linkedToken)), uint32(unsafe.Sizeof(linkedToken)), &outLen)
+ if err != nil {
+ return windows.Token(0), err
+ }
+ if tokenIsElevated(linkedToken) {
+ return linkedToken, nil
+ }
+ linkedToken.Close()
+ return windows.Token(0), errors.New("the linked token is not elevated")
+}
+
+func tokenIsMemberOfBuiltInAdministrator(token windows.Token) bool {
+ //TODO: SECURITY CRITICIAL!
+ //TODO: Isn't it better to use an impersonation token or userToken.IsMember instead?
+ adminSid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid)
+ if err != nil {
+ return false
+ }
+ gs, err := token.GetTokenGroups()
+ if err != nil {
+ return false
+ }
+ p := unsafe.Pointer(&gs.Groups[0])
+ groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(p)[:gs.GroupCount]
+ isAdmin := false
+ for _, g := range groups {
+ if windows.EqualSid(g.Sid, adminSid) {
+ isAdmin = true
+ break
+ }
+ }
+ return isAdmin
+}
+
+func getCurrentSecurityAttributes() (*syscall.SecurityAttributes, error) {
+ currentProcess, err := windows.GetCurrentProcess()
+ if err != nil {
+ return nil, err
+ }
+ securityAttributes := &syscall.SecurityAttributes{}
+ err = getSecurityInfo(currentProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, nil, nil, &securityAttributes.SecurityDescriptor)
+ if err != nil {
+ return nil, err
+ }
+ windows.LocalFree(windows.Handle(securityAttributes.SecurityDescriptor))
+ securityAttributes.Length = getSecurityDescriptorLength(securityAttributes.SecurityDescriptor)
+ if securityAttributes.Length == 0 {
+ windows.LocalFree(windows.Handle(securityAttributes.SecurityDescriptor))
+ return nil, err
+ }
+ return securityAttributes, nil
+} \ No newline at end of file