Source file src/internal/syscall/windows/security_windows.go

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package windows
     6  
     7  import (
     8  	"syscall"
     9  	"unsafe"
    10  )
    11  
    12  const (
    13  	SecurityAnonymous      = 0
    14  	SecurityIdentification = 1
    15  	SecurityImpersonation  = 2
    16  	SecurityDelegation     = 3
    17  )
    18  
    19  //sys	ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
    20  //sys	RevertToSelf() (err error) = advapi32.RevertToSelf
    21  //sys	ImpersonateLoggedOnUser(token syscall.Token) (err error) = advapi32.ImpersonateLoggedOnUser
    22  //sys	LogonUser(username *uint16, domain *uint16, password *uint16, logonType uint32, logonProvider uint32, token *syscall.Token) (err error) = advapi32.LogonUserW
    23  
    24  const (
    25  	TOKEN_ADJUST_PRIVILEGES = 0x0020
    26  	SE_PRIVILEGE_ENABLED    = 0x00000002
    27  )
    28  
    29  type LUID struct {
    30  	LowPart  uint32
    31  	HighPart int32
    32  }
    33  
    34  type LUID_AND_ATTRIBUTES struct {
    35  	Luid       LUID
    36  	Attributes uint32
    37  }
    38  
    39  type TOKEN_PRIVILEGES struct {
    40  	PrivilegeCount uint32
    41  	Privileges     [1]LUID_AND_ATTRIBUTES
    42  }
    43  
    44  //sys	OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *syscall.Token) (err error) = advapi32.OpenThreadToken
    45  //sys	LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW
    46  //sys	adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (ret uint32, err error) [true] = advapi32.AdjustTokenPrivileges
    47  
    48  func AdjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) error {
    49  	ret, err := adjustTokenPrivileges(token, disableAllPrivileges, newstate, buflen, prevstate, returnlen)
    50  	if ret == 0 {
    51  		// AdjustTokenPrivileges call failed
    52  		return err
    53  	}
    54  	// AdjustTokenPrivileges call succeeded
    55  	if err == syscall.EINVAL {
    56  		// GetLastError returned ERROR_SUCCESS
    57  		return nil
    58  	}
    59  	return err
    60  }
    61  
    62  //sys DuplicateTokenEx(hExistingToken syscall.Token, dwDesiredAccess uint32, lpTokenAttributes *syscall.SecurityAttributes, impersonationLevel uint32, tokenType TokenType, phNewToken *syscall.Token) (err error) = advapi32.DuplicateTokenEx
    63  //sys SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32, tokenInformation uintptr, tokenInformationLength uint32) (err error) = advapi32.SetTokenInformation
    64  
    65  type SID_AND_ATTRIBUTES struct {
    66  	Sid        *syscall.SID
    67  	Attributes uint32
    68  }
    69  
    70  type TOKEN_MANDATORY_LABEL struct {
    71  	Label SID_AND_ATTRIBUTES
    72  }
    73  
    74  func (tml *TOKEN_MANDATORY_LABEL) Size() uint32 {
    75  	return uint32(unsafe.Sizeof(TOKEN_MANDATORY_LABEL{})) + syscall.GetLengthSid(tml.Label.Sid)
    76  }
    77  
    78  const SE_GROUP_INTEGRITY = 0x00000020
    79  
    80  type TokenType uint32
    81  
    82  const (
    83  	TokenPrimary       TokenType = 1
    84  	TokenImpersonation TokenType = 2
    85  )
    86  
    87  //sys	GetProfilesDirectory(dir *uint16, dirLen *uint32) (err error) = userenv.GetProfilesDirectoryW
    88  
    89  const (
    90  	LG_INCLUDE_INDIRECT  = 0x1
    91  	MAX_PREFERRED_LENGTH = 0xFFFFFFFF
    92  )
    93  
    94  type LocalGroupUserInfo0 struct {
    95  	Name *uint16
    96  }
    97  
    98  const (
    99  	NERR_UserNotFound syscall.Errno = 2221
   100  	NERR_UserExists   syscall.Errno = 2224
   101  )
   102  
   103  const (
   104  	USER_PRIV_USER = 1
   105  )
   106  
   107  type UserInfo1 struct {
   108  	Name        *uint16
   109  	Password    *uint16
   110  	PasswordAge uint32
   111  	Priv        uint32
   112  	HomeDir     *uint16
   113  	Comment     *uint16
   114  	Flags       uint32
   115  	ScriptPath  *uint16
   116  }
   117  
   118  type UserInfo4 struct {
   119  	Name            *uint16
   120  	Password        *uint16
   121  	PasswordAge     uint32
   122  	Priv            uint32
   123  	HomeDir         *uint16
   124  	Comment         *uint16
   125  	Flags           uint32
   126  	ScriptPath      *uint16
   127  	AuthFlags       uint32
   128  	FullName        *uint16
   129  	UsrComment      *uint16
   130  	Parms           *uint16
   131  	Workstations    *uint16
   132  	LastLogon       uint32
   133  	LastLogoff      uint32
   134  	AcctExpires     uint32
   135  	MaxStorage      uint32
   136  	UnitsPerWeek    uint32
   137  	LogonHours      *byte
   138  	BadPwCount      uint32
   139  	NumLogons       uint32
   140  	LogonServer     *uint16
   141  	CountryCode     uint32
   142  	CodePage        uint32
   143  	UserSid         *syscall.SID
   144  	PrimaryGroupID  uint32
   145  	Profile         *uint16
   146  	HomeDirDrive    *uint16
   147  	PasswordExpired uint32
   148  }
   149  
   150  //sys	NetUserAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint32) (neterr error) = netapi32.NetUserAdd
   151  //sys	NetUserDel(serverName *uint16, userName *uint16) (neterr error) = netapi32.NetUserDel
   152  //sys	NetUserGetLocalGroups(serverName *uint16, userName *uint16, level uint32, flags uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32) (neterr error) = netapi32.NetUserGetLocalGroups
   153  
   154  // GetSystemDirectory retrieves the path to current location of the system
   155  // directory, which is typically, though not always, `C:\Windows\System32`.
   156  //
   157  //go:linkname GetSystemDirectory
   158  func GetSystemDirectory() string // Implemented in runtime package.
   159  
   160  // GetUserName retrieves the user name of the current thread
   161  // in the specified format.
   162  func GetUserName(format uint32) (string, error) {
   163  	n := uint32(50)
   164  	for {
   165  		b := make([]uint16, n)
   166  		e := syscall.GetUserNameEx(format, &b[0], &n)
   167  		if e == nil {
   168  			return syscall.UTF16ToString(b[:n]), nil
   169  		}
   170  		if e != syscall.ERROR_MORE_DATA {
   171  			return "", e
   172  		}
   173  		if n <= uint32(len(b)) {
   174  			return "", e
   175  		}
   176  	}
   177  }
   178  
   179  // getTokenInfo retrieves a specified type of information about an access token.
   180  func getTokenInfo(t syscall.Token, class uint32, initSize int) (unsafe.Pointer, error) {
   181  	n := uint32(initSize)
   182  	for {
   183  		b := make([]byte, n)
   184  		e := syscall.GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
   185  		if e == nil {
   186  			return unsafe.Pointer(&b[0]), nil
   187  		}
   188  		if e != syscall.ERROR_INSUFFICIENT_BUFFER {
   189  			return nil, e
   190  		}
   191  		if n <= uint32(len(b)) {
   192  			return nil, e
   193  		}
   194  	}
   195  }
   196  
   197  type TOKEN_GROUPS struct {
   198  	GroupCount uint32
   199  	Groups     [1]SID_AND_ATTRIBUTES
   200  }
   201  
   202  func (g *TOKEN_GROUPS) AllGroups() []SID_AND_ATTRIBUTES {
   203  	return (*[(1 << 28) - 1]SID_AND_ATTRIBUTES)(unsafe.Pointer(&g.Groups[0]))[:g.GroupCount:g.GroupCount]
   204  }
   205  
   206  func GetTokenGroups(t syscall.Token) (*TOKEN_GROUPS, error) {
   207  	i, e := getTokenInfo(t, syscall.TokenGroups, 50)
   208  	if e != nil {
   209  		return nil, e
   210  	}
   211  	return (*TOKEN_GROUPS)(i), nil
   212  }
   213  

View as plain text