security_windows.mx raw

   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