Source file src/syscall/security_windows.go

     1  // Copyright 2012 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 syscall
     6  
     7  import (
     8  	"unsafe"
     9  )
    10  
    11  const (
    12  	STANDARD_RIGHTS_REQUIRED = 0xf0000
    13  	STANDARD_RIGHTS_READ     = 0x20000
    14  	STANDARD_RIGHTS_WRITE    = 0x20000
    15  	STANDARD_RIGHTS_EXECUTE  = 0x20000
    16  	STANDARD_RIGHTS_ALL      = 0x1F0000
    17  )
    18  
    19  const (
    20  	NameUnknown          = 0
    21  	NameFullyQualifiedDN = 1
    22  	NameSamCompatible    = 2
    23  	NameDisplay          = 3
    24  	NameUniqueId         = 6
    25  	NameCanonical        = 7
    26  	NameUserPrincipal    = 8
    27  	NameCanonicalEx      = 9
    28  	NameServicePrincipal = 10
    29  	NameDnsDomain        = 12
    30  )
    31  
    32  // This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
    33  // https://learn.microsoft.com/en-gb/archive/blogs/drnick/windows-and-upn-format-credentials
    34  //sys	TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
    35  //sys	GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
    36  
    37  // TranslateAccountName converts a directory service
    38  // object name from one format to another.
    39  func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
    40  	u, e := UTF16PtrFromString(username)
    41  	if e != nil {
    42  		return "", e
    43  	}
    44  	n := uint32(50)
    45  	for {
    46  		b := make([]uint16, n)
    47  		e = TranslateName(u, from, to, &b[0], &n)
    48  		if e == nil {
    49  			return UTF16ToString(b[:n]), nil
    50  		}
    51  		if e != ERROR_INSUFFICIENT_BUFFER {
    52  			return "", e
    53  		}
    54  		if n <= uint32(len(b)) {
    55  			return "", e
    56  		}
    57  	}
    58  }
    59  
    60  const (
    61  	// do not reorder
    62  	NetSetupUnknownStatus = iota
    63  	NetSetupUnjoined
    64  	NetSetupWorkgroupName
    65  	NetSetupDomainName
    66  )
    67  
    68  type UserInfo10 struct {
    69  	Name       *uint16
    70  	Comment    *uint16
    71  	UsrComment *uint16
    72  	FullName   *uint16
    73  }
    74  
    75  //sys	NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
    76  //sys	NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
    77  //sys	NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
    78  
    79  const (
    80  	// do not reorder
    81  	SidTypeUser = 1 + iota
    82  	SidTypeGroup
    83  	SidTypeDomain
    84  	SidTypeAlias
    85  	SidTypeWellKnownGroup
    86  	SidTypeDeletedAccount
    87  	SidTypeInvalid
    88  	SidTypeUnknown
    89  	SidTypeComputer
    90  	SidTypeLabel
    91  )
    92  
    93  //sys	LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
    94  //sys	LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
    95  //sys	ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
    96  //sys	ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
    97  //sys	GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
    98  //sys	CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
    99  
   100  // The security identifier (SID) structure is a variable-length
   101  // structure used to uniquely identify users or groups.
   102  type SID struct{}
   103  
   104  // StringToSid converts a string-format security identifier
   105  // sid into a valid, functional sid.
   106  func StringToSid(s string) (*SID, error) {
   107  	var sid *SID
   108  	p, e := UTF16PtrFromString(s)
   109  	if e != nil {
   110  		return nil, e
   111  	}
   112  	e = ConvertStringSidToSid(p, &sid)
   113  	if e != nil {
   114  		return nil, e
   115  	}
   116  	defer LocalFree((Handle)(unsafe.Pointer(sid)))
   117  	return sid.Copy()
   118  }
   119  
   120  // LookupSID retrieves a security identifier sid for the account
   121  // and the name of the domain on which the account was found.
   122  // System specify target computer to search.
   123  func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
   124  	if len(account) == 0 {
   125  		return nil, "", 0, EINVAL
   126  	}
   127  	acc, e := UTF16PtrFromString(account)
   128  	if e != nil {
   129  		return nil, "", 0, e
   130  	}
   131  	var sys *uint16
   132  	if len(system) > 0 {
   133  		sys, e = UTF16PtrFromString(system)
   134  		if e != nil {
   135  			return nil, "", 0, e
   136  		}
   137  	}
   138  	n := uint32(50)
   139  	dn := uint32(50)
   140  	for {
   141  		b := make([]byte, n)
   142  		db := make([]uint16, dn)
   143  		sid = (*SID)(unsafe.Pointer(&b[0]))
   144  		e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
   145  		if e == nil {
   146  			return sid, UTF16ToString(db), accType, nil
   147  		}
   148  		if e != ERROR_INSUFFICIENT_BUFFER {
   149  			return nil, "", 0, e
   150  		}
   151  		if n <= uint32(len(b)) {
   152  			return nil, "", 0, e
   153  		}
   154  	}
   155  }
   156  
   157  // String converts sid to a string format
   158  // suitable for display, storage, or transmission.
   159  func (sid *SID) String() (string, error) {
   160  	var s *uint16
   161  	e := ConvertSidToStringSid(sid, &s)
   162  	if e != nil {
   163  		return "", e
   164  	}
   165  	defer LocalFree((Handle)(unsafe.Pointer(s)))
   166  	return utf16PtrToString(s), nil
   167  }
   168  
   169  // Len returns the length, in bytes, of a valid security identifier sid.
   170  func (sid *SID) Len() int {
   171  	return int(GetLengthSid(sid))
   172  }
   173  
   174  // Copy creates a duplicate of security identifier sid.
   175  func (sid *SID) Copy() (*SID, error) {
   176  	b := make([]byte, sid.Len())
   177  	sid2 := (*SID)(unsafe.Pointer(&b[0]))
   178  	e := CopySid(uint32(len(b)), sid2, sid)
   179  	if e != nil {
   180  		return nil, e
   181  	}
   182  	return sid2, nil
   183  }
   184  
   185  // LookupAccount retrieves the name of the account for this sid
   186  // and the name of the first domain on which this sid is found.
   187  // System specify target computer to search for.
   188  func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
   189  	var sys *uint16
   190  	if len(system) > 0 {
   191  		sys, err = UTF16PtrFromString(system)
   192  		if err != nil {
   193  			return "", "", 0, err
   194  		}
   195  	}
   196  	n := uint32(50)
   197  	dn := uint32(50)
   198  	for {
   199  		b := make([]uint16, n)
   200  		db := make([]uint16, dn)
   201  		e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
   202  		if e == nil {
   203  			return UTF16ToString(b), UTF16ToString(db), accType, nil
   204  		}
   205  		if e != ERROR_INSUFFICIENT_BUFFER {
   206  			return "", "", 0, e
   207  		}
   208  		if n <= uint32(len(b)) {
   209  			return "", "", 0, e
   210  		}
   211  	}
   212  }
   213  
   214  const (
   215  	// do not reorder
   216  	TOKEN_ASSIGN_PRIMARY = 1 << iota
   217  	TOKEN_DUPLICATE
   218  	TOKEN_IMPERSONATE
   219  	TOKEN_QUERY
   220  	TOKEN_QUERY_SOURCE
   221  	TOKEN_ADJUST_PRIVILEGES
   222  	TOKEN_ADJUST_GROUPS
   223  	TOKEN_ADJUST_DEFAULT
   224  	TOKEN_ADJUST_SESSIONID
   225  
   226  	TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
   227  		TOKEN_ASSIGN_PRIMARY |
   228  		TOKEN_DUPLICATE |
   229  		TOKEN_IMPERSONATE |
   230  		TOKEN_QUERY |
   231  		TOKEN_QUERY_SOURCE |
   232  		TOKEN_ADJUST_PRIVILEGES |
   233  		TOKEN_ADJUST_GROUPS |
   234  		TOKEN_ADJUST_DEFAULT |
   235  		TOKEN_ADJUST_SESSIONID
   236  	TOKEN_READ  = STANDARD_RIGHTS_READ | TOKEN_QUERY
   237  	TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
   238  		TOKEN_ADJUST_PRIVILEGES |
   239  		TOKEN_ADJUST_GROUPS |
   240  		TOKEN_ADJUST_DEFAULT
   241  	TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
   242  )
   243  
   244  const (
   245  	// do not reorder
   246  	TokenUser = 1 + iota
   247  	TokenGroups
   248  	TokenPrivileges
   249  	TokenOwner
   250  	TokenPrimaryGroup
   251  	TokenDefaultDacl
   252  	TokenSource
   253  	TokenType
   254  	TokenImpersonationLevel
   255  	TokenStatistics
   256  	TokenRestrictedSids
   257  	TokenSessionId
   258  	TokenGroupsAndPrivileges
   259  	TokenSessionReference
   260  	TokenSandBoxInert
   261  	TokenAuditPolicy
   262  	TokenOrigin
   263  	TokenElevationType
   264  	TokenLinkedToken
   265  	TokenElevation
   266  	TokenHasRestrictions
   267  	TokenAccessInformation
   268  	TokenVirtualizationAllowed
   269  	TokenVirtualizationEnabled
   270  	TokenIntegrityLevel
   271  	TokenUIAccess
   272  	TokenMandatoryPolicy
   273  	TokenLogonSid
   274  	MaxTokenInfoClass
   275  )
   276  
   277  type SIDAndAttributes struct {
   278  	Sid        *SID
   279  	Attributes uint32
   280  }
   281  
   282  type Tokenuser struct {
   283  	User SIDAndAttributes
   284  }
   285  
   286  type Tokenprimarygroup struct {
   287  	PrimaryGroup *SID
   288  }
   289  
   290  //sys	OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
   291  //sys	GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
   292  //sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
   293  
   294  // An access token contains the security information for a logon session.
   295  // The system creates an access token when a user logs on, and every
   296  // process executed on behalf of the user has a copy of the token.
   297  // The token identifies the user, the user's groups, and the user's
   298  // privileges. The system uses the token to control access to securable
   299  // objects and to control the ability of the user to perform various
   300  // system-related operations on the local computer.
   301  type Token Handle
   302  
   303  // OpenCurrentProcessToken opens the access token
   304  // associated with current process.
   305  func OpenCurrentProcessToken() (Token, error) {
   306  	p, e := GetCurrentProcess()
   307  	if e != nil {
   308  		return 0, e
   309  	}
   310  	var t Token
   311  	e = OpenProcessToken(p, TOKEN_QUERY, &t)
   312  	if e != nil {
   313  		return 0, e
   314  	}
   315  	return t, nil
   316  }
   317  
   318  // Close releases access to access token.
   319  func (t Token) Close() error {
   320  	return CloseHandle(Handle(t))
   321  }
   322  
   323  // getInfo retrieves a specified type of information about an access token.
   324  func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
   325  	n := uint32(initSize)
   326  	for {
   327  		b := make([]byte, n)
   328  		e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
   329  		if e == nil {
   330  			return unsafe.Pointer(&b[0]), nil
   331  		}
   332  		if e != ERROR_INSUFFICIENT_BUFFER {
   333  			return nil, e
   334  		}
   335  		if n <= uint32(len(b)) {
   336  			return nil, e
   337  		}
   338  	}
   339  }
   340  
   341  // GetTokenUser retrieves access token t user account information.
   342  func (t Token) GetTokenUser() (*Tokenuser, error) {
   343  	i, e := t.getInfo(TokenUser, 50)
   344  	if e != nil {
   345  		return nil, e
   346  	}
   347  	return (*Tokenuser)(i), nil
   348  }
   349  
   350  // GetTokenPrimaryGroup retrieves access token t primary group information.
   351  // A pointer to a SID structure representing a group that will become
   352  // the primary group of any objects created by a process using this access token.
   353  func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
   354  	i, e := t.getInfo(TokenPrimaryGroup, 50)
   355  	if e != nil {
   356  		return nil, e
   357  	}
   358  	return (*Tokenprimarygroup)(i), nil
   359  }
   360  
   361  // GetUserProfileDirectory retrieves path to the
   362  // root directory of the access token t user's profile.
   363  func (t Token) GetUserProfileDirectory() (string, error) {
   364  	n := uint32(100)
   365  	for {
   366  		b := make([]uint16, n)
   367  		e := GetUserProfileDirectory(t, &b[0], &n)
   368  		if e == nil {
   369  			return UTF16ToString(b), nil
   370  		}
   371  		if e != ERROR_INSUFFICIENT_BUFFER {
   372  			return "", e
   373  		}
   374  		if n <= uint32(len(b)) {
   375  			return "", e
   376  		}
   377  	}
   378  }
   379  

View as plain text