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
   5package windows
   6
   7import (
   8	"syscall"
   9	"unsafe"
  10)
  11
  12const (
  13	NameUnknown          = 0
  14	NameFullyQualifiedDN = 1
  15	NameSamCompatible    = 2
  16	NameDisplay          = 3
  17	NameUniqueId         = 6
  18	NameCanonical        = 7
  19	NameUserPrincipal    = 8
  20	NameCanonicalEx      = 9
  21	NameServicePrincipal = 10
  22	NameDnsDomain        = 12
  23)
  24
  25// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
  26// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
  27//sys	TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
  28//sys	GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
  29
  30// TranslateAccountName converts a directory service
  31// object name from one format to another.
  32func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
  33	u, e := UTF16PtrFromString(username)
  34	if e != nil {
  35		return "", e
  36	}
  37	n := uint32(50)
  38	for {
  39		b := make([]uint16, n)
  40		e = TranslateName(u, from, to, &b[0], &n)
  41		if e == nil {
  42			return UTF16ToString(b[:n]), nil
  43		}
  44		if e != ERROR_INSUFFICIENT_BUFFER {
  45			return "", e
  46		}
  47		if n <= uint32(len(b)) {
  48			return "", e
  49		}
  50	}
  51}
  52
  53const (
  54	// do not reorder
  55	NetSetupUnknownStatus = iota
  56	NetSetupUnjoined
  57	NetSetupWorkgroupName
  58	NetSetupDomainName
  59)
  60
  61type UserInfo10 struct {
  62	Name       *uint16
  63	Comment    *uint16
  64	UsrComment *uint16
  65	FullName   *uint16
  66}
  67
  68//sys	NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
  69//sys	NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
  70//sys	NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
  71//sys   NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) = netapi32.NetUserEnum
  72
  73const (
  74	// do not reorder
  75	SidTypeUser = 1 + iota
  76	SidTypeGroup
  77	SidTypeDomain
  78	SidTypeAlias
  79	SidTypeWellKnownGroup
  80	SidTypeDeletedAccount
  81	SidTypeInvalid
  82	SidTypeUnknown
  83	SidTypeComputer
  84	SidTypeLabel
  85)
  86
  87type SidIdentifierAuthority struct {
  88	Value [6]byte
  89}
  90
  91var (
  92	SECURITY_NULL_SID_AUTHORITY        = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
  93	SECURITY_WORLD_SID_AUTHORITY       = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
  94	SECURITY_LOCAL_SID_AUTHORITY       = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
  95	SECURITY_CREATOR_SID_AUTHORITY     = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
  96	SECURITY_NON_UNIQUE_AUTHORITY      = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
  97	SECURITY_NT_AUTHORITY              = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
  98	SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
  99)
 100
 101const (
 102	SECURITY_NULL_RID                   = 0
 103	SECURITY_WORLD_RID                  = 0
 104	SECURITY_LOCAL_RID                  = 0
 105	SECURITY_CREATOR_OWNER_RID          = 0
 106	SECURITY_CREATOR_GROUP_RID          = 1
 107	SECURITY_DIALUP_RID                 = 1
 108	SECURITY_NETWORK_RID                = 2
 109	SECURITY_BATCH_RID                  = 3
 110	SECURITY_INTERACTIVE_RID            = 4
 111	SECURITY_LOGON_IDS_RID              = 5
 112	SECURITY_SERVICE_RID                = 6
 113	SECURITY_LOCAL_SYSTEM_RID           = 18
 114	SECURITY_BUILTIN_DOMAIN_RID         = 32
 115	SECURITY_PRINCIPAL_SELF_RID         = 10
 116	SECURITY_CREATOR_OWNER_SERVER_RID   = 0x2
 117	SECURITY_CREATOR_GROUP_SERVER_RID   = 0x3
 118	SECURITY_LOGON_IDS_RID_COUNT        = 0x3
 119	SECURITY_ANONYMOUS_LOGON_RID        = 0x7
 120	SECURITY_PROXY_RID                  = 0x8
 121	SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
 122	SECURITY_SERVER_LOGON_RID           = SECURITY_ENTERPRISE_CONTROLLERS_RID
 123	SECURITY_AUTHENTICATED_USER_RID     = 0xb
 124	SECURITY_RESTRICTED_CODE_RID        = 0xc
 125	SECURITY_NT_NON_UNIQUE_RID          = 0x15
 126)
 127
 128// Predefined domain-relative RIDs for local groups.
 129// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
 130const (
 131	DOMAIN_ALIAS_RID_ADMINS                         = 0x220
 132	DOMAIN_ALIAS_RID_USERS                          = 0x221
 133	DOMAIN_ALIAS_RID_GUESTS                         = 0x222
 134	DOMAIN_ALIAS_RID_POWER_USERS                    = 0x223
 135	DOMAIN_ALIAS_RID_ACCOUNT_OPS                    = 0x224
 136	DOMAIN_ALIAS_RID_SYSTEM_OPS                     = 0x225
 137	DOMAIN_ALIAS_RID_PRINT_OPS                      = 0x226
 138	DOMAIN_ALIAS_RID_BACKUP_OPS                     = 0x227
 139	DOMAIN_ALIAS_RID_REPLICATOR                     = 0x228
 140	DOMAIN_ALIAS_RID_RAS_SERVERS                    = 0x229
 141	DOMAIN_ALIAS_RID_PREW2KCOMPACCESS               = 0x22a
 142	DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS           = 0x22b
 143	DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS      = 0x22c
 144	DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
 145	DOMAIN_ALIAS_RID_MONITORING_USERS               = 0x22e
 146	DOMAIN_ALIAS_RID_LOGGING_USERS                  = 0x22f
 147	DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS            = 0x230
 148	DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS             = 0x231
 149	DOMAIN_ALIAS_RID_DCOM_USERS                     = 0x232
 150	DOMAIN_ALIAS_RID_IUSERS                         = 0x238
 151	DOMAIN_ALIAS_RID_CRYPTO_OPERATORS               = 0x239
 152	DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP     = 0x23b
 153	DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c
 154	DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP        = 0x23d
 155	DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP      = 0x23e
 156)
 157
 158//sys	LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
 159//sys	LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
 160//sys	ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
 161//sys	ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
 162//sys	GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
 163//sys	CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
 164//sys	AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) = advapi32.AllocateAndInitializeSid
 165//sys	createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) = advapi32.CreateWellKnownSid
 166//sys	isWellKnownSid(sid *SID, sidType WELL_KNOWN_SID_TYPE) (isWellKnown bool) = advapi32.IsWellKnownSid
 167//sys	FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
 168//sys	EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
 169//sys	getSidIdentifierAuthority(sid *SID) (authority *SidIdentifierAuthority) = advapi32.GetSidIdentifierAuthority
 170//sys	getSidSubAuthorityCount(sid *SID) (count *uint8) = advapi32.GetSidSubAuthorityCount
 171//sys	getSidSubAuthority(sid *SID, index uint32) (subAuthority *uint32) = advapi32.GetSidSubAuthority
 172//sys	isValidSid(sid *SID) (isValid bool) = advapi32.IsValidSid
 173
 174// The security identifier (SID) structure is a variable-length
 175// structure used to uniquely identify users or groups.
 176type SID struct{}
 177
 178// StringToSid converts a string-format security identifier
 179// SID into a valid, functional SID.
 180func StringToSid(s string) (*SID, error) {
 181	var sid *SID
 182	p, e := UTF16PtrFromString(s)
 183	if e != nil {
 184		return nil, e
 185	}
 186	e = ConvertStringSidToSid(p, &sid)
 187	if e != nil {
 188		return nil, e
 189	}
 190	defer LocalFree((Handle)(unsafe.Pointer(sid)))
 191	return sid.Copy()
 192}
 193
 194// LookupSID retrieves a security identifier SID for the account
 195// and the name of the domain on which the account was found.
 196// System specify target computer to search.
 197func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
 198	if len(account) == 0 {
 199		return nil, "", 0, syscall.EINVAL
 200	}
 201	acc, e := UTF16PtrFromString(account)
 202	if e != nil {
 203		return nil, "", 0, e
 204	}
 205	var sys *uint16
 206	if len(system) > 0 {
 207		sys, e = UTF16PtrFromString(system)
 208		if e != nil {
 209			return nil, "", 0, e
 210		}
 211	}
 212	n := uint32(50)
 213	dn := uint32(50)
 214	for {
 215		b := make([]byte, n)
 216		db := make([]uint16, dn)
 217		sid = (*SID)(unsafe.Pointer(&b[0]))
 218		e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
 219		if e == nil {
 220			return sid, UTF16ToString(db), accType, nil
 221		}
 222		if e != ERROR_INSUFFICIENT_BUFFER {
 223			return nil, "", 0, e
 224		}
 225		if n <= uint32(len(b)) {
 226			return nil, "", 0, e
 227		}
 228	}
 229}
 230
 231// String converts SID to a string format suitable for display, storage, or transmission.
 232func (sid *SID) String() string {
 233	var s *uint16
 234	e := ConvertSidToStringSid(sid, &s)
 235	if e != nil {
 236		return ""
 237	}
 238	defer LocalFree((Handle)(unsafe.Pointer(s)))
 239	return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:])
 240}
 241
 242// Len returns the length, in bytes, of a valid security identifier SID.
 243func (sid *SID) Len() int {
 244	return int(GetLengthSid(sid))
 245}
 246
 247// Copy creates a duplicate of security identifier SID.
 248func (sid *SID) Copy() (*SID, error) {
 249	b := make([]byte, sid.Len())
 250	sid2 := (*SID)(unsafe.Pointer(&b[0]))
 251	e := CopySid(uint32(len(b)), sid2, sid)
 252	if e != nil {
 253		return nil, e
 254	}
 255	return sid2, nil
 256}
 257
 258// IdentifierAuthority returns the identifier authority of the SID.
 259func (sid *SID) IdentifierAuthority() SidIdentifierAuthority {
 260	return *getSidIdentifierAuthority(sid)
 261}
 262
 263// SubAuthorityCount returns the number of sub-authorities in the SID.
 264func (sid *SID) SubAuthorityCount() uint8 {
 265	return *getSidSubAuthorityCount(sid)
 266}
 267
 268// SubAuthority returns the sub-authority of the SID as specified by
 269// the index, which must be less than sid.SubAuthorityCount().
 270func (sid *SID) SubAuthority(idx uint32) uint32 {
 271	if idx >= uint32(sid.SubAuthorityCount()) {
 272		panic("sub-authority index out of range")
 273	}
 274	return *getSidSubAuthority(sid, idx)
 275}
 276
 277// IsValid returns whether the SID has a valid revision and length.
 278func (sid *SID) IsValid() bool {
 279	return isValidSid(sid)
 280}
 281
 282// Equals compares two SIDs for equality.
 283func (sid *SID) Equals(sid2 *SID) bool {
 284	return EqualSid(sid, sid2)
 285}
 286
 287// IsWellKnown determines whether the SID matches the well-known sidType.
 288func (sid *SID) IsWellKnown(sidType WELL_KNOWN_SID_TYPE) bool {
 289	return isWellKnownSid(sid, sidType)
 290}
 291
 292// LookupAccount retrieves the name of the account for this SID
 293// and the name of the first domain on which this SID is found.
 294// System specify target computer to search for.
 295func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
 296	var sys *uint16
 297	if len(system) > 0 {
 298		sys, err = UTF16PtrFromString(system)
 299		if err != nil {
 300			return "", "", 0, err
 301		}
 302	}
 303	n := uint32(50)
 304	dn := uint32(50)
 305	for {
 306		b := make([]uint16, n)
 307		db := make([]uint16, dn)
 308		e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
 309		if e == nil {
 310			return UTF16ToString(b), UTF16ToString(db), accType, nil
 311		}
 312		if e != ERROR_INSUFFICIENT_BUFFER {
 313			return "", "", 0, e
 314		}
 315		if n <= uint32(len(b)) {
 316			return "", "", 0, e
 317		}
 318	}
 319}
 320
 321// Various types of pre-specified SIDs that can be synthesized and compared at runtime.
 322type WELL_KNOWN_SID_TYPE uint32
 323
 324const (
 325	WinNullSid                                    = 0
 326	WinWorldSid                                   = 1
 327	WinLocalSid                                   = 2
 328	WinCreatorOwnerSid                            = 3
 329	WinCreatorGroupSid                            = 4
 330	WinCreatorOwnerServerSid                      = 5
 331	WinCreatorGroupServerSid                      = 6
 332	WinNtAuthoritySid                             = 7
 333	WinDialupSid                                  = 8
 334	WinNetworkSid                                 = 9
 335	WinBatchSid                                   = 10
 336	WinInteractiveSid                             = 11
 337	WinServiceSid                                 = 12
 338	WinAnonymousSid                               = 13
 339	WinProxySid                                   = 14
 340	WinEnterpriseControllersSid                   = 15
 341	WinSelfSid                                    = 16
 342	WinAuthenticatedUserSid                       = 17
 343	WinRestrictedCodeSid                          = 18
 344	WinTerminalServerSid                          = 19
 345	WinRemoteLogonIdSid                           = 20
 346	WinLogonIdsSid                                = 21
 347	WinLocalSystemSid                             = 22
 348	WinLocalServiceSid                            = 23
 349	WinNetworkServiceSid                          = 24
 350	WinBuiltinDomainSid                           = 25
 351	WinBuiltinAdministratorsSid                   = 26
 352	WinBuiltinUsersSid                            = 27
 353	WinBuiltinGuestsSid                           = 28
 354	WinBuiltinPowerUsersSid                       = 29
 355	WinBuiltinAccountOperatorsSid                 = 30
 356	WinBuiltinSystemOperatorsSid                  = 31
 357	WinBuiltinPrintOperatorsSid                   = 32
 358	WinBuiltinBackupOperatorsSid                  = 33
 359	WinBuiltinReplicatorSid                       = 34
 360	WinBuiltinPreWindows2000CompatibleAccessSid   = 35
 361	WinBuiltinRemoteDesktopUsersSid               = 36
 362	WinBuiltinNetworkConfigurationOperatorsSid    = 37
 363	WinAccountAdministratorSid                    = 38
 364	WinAccountGuestSid                            = 39
 365	WinAccountKrbtgtSid                           = 40
 366	WinAccountDomainAdminsSid                     = 41
 367	WinAccountDomainUsersSid                      = 42
 368	WinAccountDomainGuestsSid                     = 43
 369	WinAccountComputersSid                        = 44
 370	WinAccountControllersSid                      = 45
 371	WinAccountCertAdminsSid                       = 46
 372	WinAccountSchemaAdminsSid                     = 47
 373	WinAccountEnterpriseAdminsSid                 = 48
 374	WinAccountPolicyAdminsSid                     = 49
 375	WinAccountRasAndIasServersSid                 = 50
 376	WinNTLMAuthenticationSid                      = 51
 377	WinDigestAuthenticationSid                    = 52
 378	WinSChannelAuthenticationSid                  = 53
 379	WinThisOrganizationSid                        = 54
 380	WinOtherOrganizationSid                       = 55
 381	WinBuiltinIncomingForestTrustBuildersSid      = 56
 382	WinBuiltinPerfMonitoringUsersSid              = 57
 383	WinBuiltinPerfLoggingUsersSid                 = 58
 384	WinBuiltinAuthorizationAccessSid              = 59
 385	WinBuiltinTerminalServerLicenseServersSid     = 60
 386	WinBuiltinDCOMUsersSid                        = 61
 387	WinBuiltinIUsersSid                           = 62
 388	WinIUserSid                                   = 63
 389	WinBuiltinCryptoOperatorsSid                  = 64
 390	WinUntrustedLabelSid                          = 65
 391	WinLowLabelSid                                = 66
 392	WinMediumLabelSid                             = 67
 393	WinHighLabelSid                               = 68
 394	WinSystemLabelSid                             = 69
 395	WinWriteRestrictedCodeSid                     = 70
 396	WinCreatorOwnerRightsSid                      = 71
 397	WinCacheablePrincipalsGroupSid                = 72
 398	WinNonCacheablePrincipalsGroupSid             = 73
 399	WinEnterpriseReadonlyControllersSid           = 74
 400	WinAccountReadonlyControllersSid              = 75
 401	WinBuiltinEventLogReadersGroup                = 76
 402	WinNewEnterpriseReadonlyControllersSid        = 77
 403	WinBuiltinCertSvcDComAccessGroup              = 78
 404	WinMediumPlusLabelSid                         = 79
 405	WinLocalLogonSid                              = 80
 406	WinConsoleLogonSid                            = 81
 407	WinThisOrganizationCertificateSid             = 82
 408	WinApplicationPackageAuthoritySid             = 83
 409	WinBuiltinAnyPackageSid                       = 84
 410	WinCapabilityInternetClientSid                = 85
 411	WinCapabilityInternetClientServerSid          = 86
 412	WinCapabilityPrivateNetworkClientServerSid    = 87
 413	WinCapabilityPicturesLibrarySid               = 88
 414	WinCapabilityVideosLibrarySid                 = 89
 415	WinCapabilityMusicLibrarySid                  = 90
 416	WinCapabilityDocumentsLibrarySid              = 91
 417	WinCapabilitySharedUserCertificatesSid        = 92
 418	WinCapabilityEnterpriseAuthenticationSid      = 93
 419	WinCapabilityRemovableStorageSid              = 94
 420	WinBuiltinRDSRemoteAccessServersSid           = 95
 421	WinBuiltinRDSEndpointServersSid               = 96
 422	WinBuiltinRDSManagementServersSid             = 97
 423	WinUserModeDriversSid                         = 98
 424	WinBuiltinHyperVAdminsSid                     = 99
 425	WinAccountCloneableControllersSid             = 100
 426	WinBuiltinAccessControlAssistanceOperatorsSid = 101
 427	WinBuiltinRemoteManagementUsersSid            = 102
 428	WinAuthenticationAuthorityAssertedSid         = 103
 429	WinAuthenticationServiceAssertedSid           = 104
 430	WinLocalAccountSid                            = 105
 431	WinLocalAccountAndAdministratorSid            = 106
 432	WinAccountProtectedUsersSid                   = 107
 433	WinCapabilityAppointmentsSid                  = 108
 434	WinCapabilityContactsSid                      = 109
 435	WinAccountDefaultSystemManagedSid             = 110
 436	WinBuiltinDefaultSystemManagedGroupSid        = 111
 437	WinBuiltinStorageReplicaAdminsSid             = 112
 438	WinAccountKeyAdminsSid                        = 113
 439	WinAccountEnterpriseKeyAdminsSid              = 114
 440	WinAuthenticationKeyTrustSid                  = 115
 441	WinAuthenticationKeyPropertyMFASid            = 116
 442	WinAuthenticationKeyPropertyAttestationSid    = 117
 443	WinAuthenticationFreshKeyAuthSid              = 118
 444	WinBuiltinDeviceOwnersSid                     = 119
 445)
 446
 447// Creates a SID for a well-known predefined alias, generally using the constants of the form
 448// Win*Sid, for the local machine.
 449func CreateWellKnownSid(sidType WELL_KNOWN_SID_TYPE) (*SID, error) {
 450	return CreateWellKnownDomainSid(sidType, nil)
 451}
 452
 453// Creates a SID for a well-known predefined alias, generally using the constants of the form
 454// Win*Sid, for the domain specified by the domainSid parameter.
 455func CreateWellKnownDomainSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID) (*SID, error) {
 456	n := uint32(50)
 457	for {
 458		b := make([]byte, n)
 459		sid := (*SID)(unsafe.Pointer(&b[0]))
 460		err := createWellKnownSid(sidType, domainSid, sid, &n)
 461		if err == nil {
 462			return sid, nil
 463		}
 464		if err != ERROR_INSUFFICIENT_BUFFER {
 465			return nil, err
 466		}
 467		if n <= uint32(len(b)) {
 468			return nil, err
 469		}
 470	}
 471}
 472
 473const (
 474	// do not reorder
 475	TOKEN_ASSIGN_PRIMARY = 1 << iota
 476	TOKEN_DUPLICATE
 477	TOKEN_IMPERSONATE
 478	TOKEN_QUERY
 479	TOKEN_QUERY_SOURCE
 480	TOKEN_ADJUST_PRIVILEGES
 481	TOKEN_ADJUST_GROUPS
 482	TOKEN_ADJUST_DEFAULT
 483	TOKEN_ADJUST_SESSIONID
 484
 485	TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
 486		TOKEN_ASSIGN_PRIMARY |
 487		TOKEN_DUPLICATE |
 488		TOKEN_IMPERSONATE |
 489		TOKEN_QUERY |
 490		TOKEN_QUERY_SOURCE |
 491		TOKEN_ADJUST_PRIVILEGES |
 492		TOKEN_ADJUST_GROUPS |
 493		TOKEN_ADJUST_DEFAULT |
 494		TOKEN_ADJUST_SESSIONID
 495	TOKEN_READ  = STANDARD_RIGHTS_READ | TOKEN_QUERY
 496	TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
 497		TOKEN_ADJUST_PRIVILEGES |
 498		TOKEN_ADJUST_GROUPS |
 499		TOKEN_ADJUST_DEFAULT
 500	TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
 501)
 502
 503const (
 504	// do not reorder
 505	TokenUser = 1 + iota
 506	TokenGroups
 507	TokenPrivileges
 508	TokenOwner
 509	TokenPrimaryGroup
 510	TokenDefaultDacl
 511	TokenSource
 512	TokenType
 513	TokenImpersonationLevel
 514	TokenStatistics
 515	TokenRestrictedSids
 516	TokenSessionId
 517	TokenGroupsAndPrivileges
 518	TokenSessionReference
 519	TokenSandBoxInert
 520	TokenAuditPolicy
 521	TokenOrigin
 522	TokenElevationType
 523	TokenLinkedToken
 524	TokenElevation
 525	TokenHasRestrictions
 526	TokenAccessInformation
 527	TokenVirtualizationAllowed
 528	TokenVirtualizationEnabled
 529	TokenIntegrityLevel
 530	TokenUIAccess
 531	TokenMandatoryPolicy
 532	TokenLogonSid
 533	MaxTokenInfoClass
 534)
 535
 536// Group attributes inside of Tokengroups.Groups[i].Attributes
 537const (
 538	SE_GROUP_MANDATORY          = 0x00000001
 539	SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002
 540	SE_GROUP_ENABLED            = 0x00000004
 541	SE_GROUP_OWNER              = 0x00000008
 542	SE_GROUP_USE_FOR_DENY_ONLY  = 0x00000010
 543	SE_GROUP_INTEGRITY          = 0x00000020
 544	SE_GROUP_INTEGRITY_ENABLED  = 0x00000040
 545	SE_GROUP_LOGON_ID           = 0xC0000000
 546	SE_GROUP_RESOURCE           = 0x20000000
 547	SE_GROUP_VALID_ATTRIBUTES   = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED | SE_GROUP_OWNER | SE_GROUP_USE_FOR_DENY_ONLY | SE_GROUP_LOGON_ID | SE_GROUP_RESOURCE | SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED
 548)
 549
 550// Privilege attributes
 551const (
 552	SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
 553	SE_PRIVILEGE_ENABLED            = 0x00000002
 554	SE_PRIVILEGE_REMOVED            = 0x00000004
 555	SE_PRIVILEGE_USED_FOR_ACCESS    = 0x80000000
 556	SE_PRIVILEGE_VALID_ATTRIBUTES   = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED | SE_PRIVILEGE_USED_FOR_ACCESS
 557)
 558
 559// Token types
 560const (
 561	TokenPrimary       = 1
 562	TokenImpersonation = 2
 563)
 564
 565// Impersonation levels
 566const (
 567	SecurityAnonymous      = 0
 568	SecurityIdentification = 1
 569	SecurityImpersonation  = 2
 570	SecurityDelegation     = 3
 571)
 572
 573type LUID struct {
 574	LowPart  uint32
 575	HighPart int32
 576}
 577
 578type LUIDAndAttributes struct {
 579	Luid       LUID
 580	Attributes uint32
 581}
 582
 583type SIDAndAttributes struct {
 584	Sid        *SID
 585	Attributes uint32
 586}
 587
 588type Tokenuser struct {
 589	User SIDAndAttributes
 590}
 591
 592type Tokenprimarygroup struct {
 593	PrimaryGroup *SID
 594}
 595
 596type Tokengroups struct {
 597	GroupCount uint32
 598	Groups     [1]SIDAndAttributes // Use AllGroups() for iterating.
 599}
 600
 601// AllGroups returns a slice that can be used to iterate over the groups in g.
 602func (g *Tokengroups) AllGroups() []SIDAndAttributes {
 603	return (*[(1 << 28) - 1]SIDAndAttributes)(unsafe.Pointer(&g.Groups[0]))[:g.GroupCount:g.GroupCount]
 604}
 605
 606type Tokenprivileges struct {
 607	PrivilegeCount uint32
 608	Privileges     [1]LUIDAndAttributes // Use AllPrivileges() for iterating.
 609}
 610
 611// AllPrivileges returns a slice that can be used to iterate over the privileges in p.
 612func (p *Tokenprivileges) AllPrivileges() []LUIDAndAttributes {
 613	return (*[(1 << 27) - 1]LUIDAndAttributes)(unsafe.Pointer(&p.Privileges[0]))[:p.PrivilegeCount:p.PrivilegeCount]
 614}
 615
 616type Tokenmandatorylabel struct {
 617	Label SIDAndAttributes
 618}
 619
 620func (tml *Tokenmandatorylabel) Size() uint32 {
 621	return uint32(unsafe.Sizeof(Tokenmandatorylabel{})) + GetLengthSid(tml.Label.Sid)
 622}
 623
 624// Authorization Functions
 625//sys	checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
 626//sys	isTokenRestricted(tokenHandle Token) (ret bool, err error) [!failretval] = advapi32.IsTokenRestricted
 627//sys	OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
 628//sys	OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
 629//sys	ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
 630//sys	RevertToSelf() (err error) = advapi32.RevertToSelf
 631//sys	SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken
 632//sys	LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW
 633//sys	AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) = advapi32.AdjustTokenPrivileges
 634//sys	AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) = advapi32.AdjustTokenGroups
 635//sys	GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
 636//sys	SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) = advapi32.SetTokenInformation
 637//sys	DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
 638//sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
 639//sys	getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
 640//sys	getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetWindowsDirectoryW
 641//sys	getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemWindowsDirectoryW
 642
 643// An access token contains the security information for a logon session.
 644// The system creates an access token when a user logs on, and every
 645// process executed on behalf of the user has a copy of the token.
 646// The token identifies the user, the user's groups, and the user's
 647// privileges. The system uses the token to control access to securable
 648// objects and to control the ability of the user to perform various
 649// system-related operations on the local computer.
 650type Token Handle
 651
 652// OpenCurrentProcessToken opens an access token associated with current
 653// process with TOKEN_QUERY access. It is a real token that needs to be closed.
 654//
 655// Deprecated: Explicitly call OpenProcessToken(CurrentProcess(), ...)
 656// with the desired access instead, or use GetCurrentProcessToken for a
 657// TOKEN_QUERY token.
 658func OpenCurrentProcessToken() (Token, error) {
 659	var token Token
 660	err := OpenProcessToken(CurrentProcess(), TOKEN_QUERY, &token)
 661	return token, err
 662}
 663
 664// GetCurrentProcessToken returns the access token associated with
 665// the current process. It is a pseudo token that does not need
 666// to be closed.
 667func GetCurrentProcessToken() Token {
 668	return Token(^uintptr(4 - 1))
 669}
 670
 671// GetCurrentThreadToken return the access token associated with
 672// the current thread. It is a pseudo token that does not need
 673// to be closed.
 674func GetCurrentThreadToken() Token {
 675	return Token(^uintptr(5 - 1))
 676}
 677
 678// GetCurrentThreadEffectiveToken returns the effective access token
 679// associated with the current thread. It is a pseudo token that does
 680// not need to be closed.
 681func GetCurrentThreadEffectiveToken() Token {
 682	return Token(^uintptr(6 - 1))
 683}
 684
 685// Close releases access to access token.
 686func (t Token) Close() error {
 687	return CloseHandle(Handle(t))
 688}
 689
 690// getInfo retrieves a specified type of information about an access token.
 691func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
 692	n := uint32(initSize)
 693	for {
 694		b := make([]byte, n)
 695		e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
 696		if e == nil {
 697			return unsafe.Pointer(&b[0]), nil
 698		}
 699		if e != ERROR_INSUFFICIENT_BUFFER {
 700			return nil, e
 701		}
 702		if n <= uint32(len(b)) {
 703			return nil, e
 704		}
 705	}
 706}
 707
 708// GetTokenUser retrieves access token t user account information.
 709func (t Token) GetTokenUser() (*Tokenuser, error) {
 710	i, e := t.getInfo(TokenUser, 50)
 711	if e != nil {
 712		return nil, e
 713	}
 714	return (*Tokenuser)(i), nil
 715}
 716
 717// GetTokenGroups retrieves group accounts associated with access token t.
 718func (t Token) GetTokenGroups() (*Tokengroups, error) {
 719	i, e := t.getInfo(TokenGroups, 50)
 720	if e != nil {
 721		return nil, e
 722	}
 723	return (*Tokengroups)(i), nil
 724}
 725
 726// GetTokenPrimaryGroup retrieves access token t primary group information.
 727// A pointer to a SID structure representing a group that will become
 728// the primary group of any objects created by a process using this access token.
 729func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
 730	i, e := t.getInfo(TokenPrimaryGroup, 50)
 731	if e != nil {
 732		return nil, e
 733	}
 734	return (*Tokenprimarygroup)(i), nil
 735}
 736
 737// GetUserProfileDirectory retrieves path to the
 738// root directory of the access token t user's profile.
 739func (t Token) GetUserProfileDirectory() (string, error) {
 740	n := uint32(100)
 741	for {
 742		b := make([]uint16, n)
 743		e := GetUserProfileDirectory(t, &b[0], &n)
 744		if e == nil {
 745			return UTF16ToString(b), nil
 746		}
 747		if e != ERROR_INSUFFICIENT_BUFFER {
 748			return "", e
 749		}
 750		if n <= uint32(len(b)) {
 751			return "", e
 752		}
 753	}
 754}
 755
 756// IsElevated returns whether the current token is elevated from a UAC perspective.
 757func (token Token) IsElevated() bool {
 758	var isElevated uint32
 759	var outLen uint32
 760	err := GetTokenInformation(token, TokenElevation, (*byte)(unsafe.Pointer(&isElevated)), uint32(unsafe.Sizeof(isElevated)), &outLen)
 761	if err != nil {
 762		return false
 763	}
 764	return outLen == uint32(unsafe.Sizeof(isElevated)) && isElevated != 0
 765}
 766
 767// GetLinkedToken returns the linked token, which may be an elevated UAC token.
 768func (token Token) GetLinkedToken() (Token, error) {
 769	var linkedToken Token
 770	var outLen uint32
 771	err := GetTokenInformation(token, TokenLinkedToken, (*byte)(unsafe.Pointer(&linkedToken)), uint32(unsafe.Sizeof(linkedToken)), &outLen)
 772	if err != nil {
 773		return Token(0), err
 774	}
 775	return linkedToken, nil
 776}
 777
 778// GetSystemDirectory retrieves the path to current location of the system
 779// directory, which is typically, though not always, `C:\Windows\System32`.
 780func GetSystemDirectory() (string, error) {
 781	n := uint32(MAX_PATH)
 782	for {
 783		b := make([]uint16, n)
 784		l, e := getSystemDirectory(&b[0], n)
 785		if e != nil {
 786			return "", e
 787		}
 788		if l <= n {
 789			return UTF16ToString(b[:l]), nil
 790		}
 791		n = l
 792	}
 793}
 794
 795// GetWindowsDirectory retrieves the path to current location of the Windows
 796// directory, which is typically, though not always, `C:\Windows`. This may
 797// be a private user directory in the case that the application is running
 798// under a terminal server.
 799func GetWindowsDirectory() (string, error) {
 800	n := uint32(MAX_PATH)
 801	for {
 802		b := make([]uint16, n)
 803		l, e := getWindowsDirectory(&b[0], n)
 804		if e != nil {
 805			return "", e
 806		}
 807		if l <= n {
 808			return UTF16ToString(b[:l]), nil
 809		}
 810		n = l
 811	}
 812}
 813
 814// GetSystemWindowsDirectory retrieves the path to current location of the
 815// Windows directory, which is typically, though not always, `C:\Windows`.
 816func GetSystemWindowsDirectory() (string, error) {
 817	n := uint32(MAX_PATH)
 818	for {
 819		b := make([]uint16, n)
 820		l, e := getSystemWindowsDirectory(&b[0], n)
 821		if e != nil {
 822			return "", e
 823		}
 824		if l <= n {
 825			return UTF16ToString(b[:l]), nil
 826		}
 827		n = l
 828	}
 829}
 830
 831// IsMember reports whether the access token t is a member of the provided SID.
 832func (t Token) IsMember(sid *SID) (bool, error) {
 833	var b int32
 834	if e := checkTokenMembership(t, sid, &b); e != nil {
 835		return false, e
 836	}
 837	return b != 0, nil
 838}
 839
 840// IsRestricted reports whether the access token t is a restricted token.
 841func (t Token) IsRestricted() (isRestricted bool, err error) {
 842	isRestricted, err = isTokenRestricted(t)
 843	if !isRestricted && err == syscall.EINVAL {
 844		// If err is EINVAL, this returned ERROR_SUCCESS indicating a non-restricted token.
 845		err = nil
 846	}
 847	return
 848}
 849
 850const (
 851	WTS_CONSOLE_CONNECT        = 0x1
 852	WTS_CONSOLE_DISCONNECT     = 0x2
 853	WTS_REMOTE_CONNECT         = 0x3
 854	WTS_REMOTE_DISCONNECT      = 0x4
 855	WTS_SESSION_LOGON          = 0x5
 856	WTS_SESSION_LOGOFF         = 0x6
 857	WTS_SESSION_LOCK           = 0x7
 858	WTS_SESSION_UNLOCK         = 0x8
 859	WTS_SESSION_REMOTE_CONTROL = 0x9
 860	WTS_SESSION_CREATE         = 0xa
 861	WTS_SESSION_TERMINATE      = 0xb
 862)
 863
 864const (
 865	WTSActive       = 0
 866	WTSConnected    = 1
 867	WTSConnectQuery = 2
 868	WTSShadow       = 3
 869	WTSDisconnected = 4
 870	WTSIdle         = 5
 871	WTSListen       = 6
 872	WTSReset        = 7
 873	WTSDown         = 8
 874	WTSInit         = 9
 875)
 876
 877type WTSSESSION_NOTIFICATION struct {
 878	Size      uint32
 879	SessionID uint32
 880}
 881
 882type WTS_SESSION_INFO struct {
 883	SessionID         uint32
 884	WindowStationName *uint16
 885	State             uint32
 886}
 887
 888//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
 889//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
 890//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
 891//sys WTSGetActiveConsoleSessionId() (sessionID uint32)
 892
 893type ACL struct {
 894	aclRevision byte
 895	sbz1        byte
 896	aclSize     uint16
 897	AceCount    uint16
 898	sbz2        uint16
 899}
 900
 901type SECURITY_DESCRIPTOR struct {
 902	revision byte
 903	sbz1     byte
 904	control  SECURITY_DESCRIPTOR_CONTROL
 905	owner    *SID
 906	group    *SID
 907	sacl     *ACL
 908	dacl     *ACL
 909}
 910
 911type SECURITY_QUALITY_OF_SERVICE struct {
 912	Length              uint32
 913	ImpersonationLevel  uint32
 914	ContextTrackingMode byte
 915	EffectiveOnly       byte
 916}
 917
 918// Constants for the ContextTrackingMode field of SECURITY_QUALITY_OF_SERVICE.
 919const (
 920	SECURITY_STATIC_TRACKING  = 0
 921	SECURITY_DYNAMIC_TRACKING = 1
 922)
 923
 924type SecurityAttributes struct {
 925	Length             uint32
 926	SecurityDescriptor *SECURITY_DESCRIPTOR
 927	InheritHandle      uint32
 928}
 929
 930type SE_OBJECT_TYPE uint32
 931
 932// Constants for type SE_OBJECT_TYPE
 933const (
 934	SE_UNKNOWN_OBJECT_TYPE     = 0
 935	SE_FILE_OBJECT             = 1
 936	SE_SERVICE                 = 2
 937	SE_PRINTER                 = 3
 938	SE_REGISTRY_KEY            = 4
 939	SE_LMSHARE                 = 5
 940	SE_KERNEL_OBJECT           = 6
 941	SE_WINDOW_OBJECT           = 7
 942	SE_DS_OBJECT               = 8
 943	SE_DS_OBJECT_ALL           = 9
 944	SE_PROVIDER_DEFINED_OBJECT = 10
 945	SE_WMIGUID_OBJECT          = 11
 946	SE_REGISTRY_WOW64_32KEY    = 12
 947	SE_REGISTRY_WOW64_64KEY    = 13
 948)
 949
 950type SECURITY_INFORMATION uint32
 951
 952// Constants for type SECURITY_INFORMATION
 953const (
 954	OWNER_SECURITY_INFORMATION            = 0x00000001
 955	GROUP_SECURITY_INFORMATION            = 0x00000002
 956	DACL_SECURITY_INFORMATION             = 0x00000004
 957	SACL_SECURITY_INFORMATION             = 0x00000008
 958	LABEL_SECURITY_INFORMATION            = 0x00000010
 959	ATTRIBUTE_SECURITY_INFORMATION        = 0x00000020
 960	SCOPE_SECURITY_INFORMATION            = 0x00000040
 961	BACKUP_SECURITY_INFORMATION           = 0x00010000
 962	PROTECTED_DACL_SECURITY_INFORMATION   = 0x80000000
 963	PROTECTED_SACL_SECURITY_INFORMATION   = 0x40000000
 964	UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000
 965	UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000
 966)
 967
 968type SECURITY_DESCRIPTOR_CONTROL uint16
 969
 970// Constants for type SECURITY_DESCRIPTOR_CONTROL
 971const (
 972	SE_OWNER_DEFAULTED       = 0x0001
 973	SE_GROUP_DEFAULTED       = 0x0002
 974	SE_DACL_PRESENT          = 0x0004
 975	SE_DACL_DEFAULTED        = 0x0008
 976	SE_SACL_PRESENT          = 0x0010
 977	SE_SACL_DEFAULTED        = 0x0020
 978	SE_DACL_AUTO_INHERIT_REQ = 0x0100
 979	SE_SACL_AUTO_INHERIT_REQ = 0x0200
 980	SE_DACL_AUTO_INHERITED   = 0x0400
 981	SE_SACL_AUTO_INHERITED   = 0x0800
 982	SE_DACL_PROTECTED        = 0x1000
 983	SE_SACL_PROTECTED        = 0x2000
 984	SE_RM_CONTROL_VALID      = 0x4000
 985	SE_SELF_RELATIVE         = 0x8000
 986)
 987
 988type ACCESS_MASK uint32
 989
 990// Constants for type ACCESS_MASK
 991const (
 992	DELETE                   = 0x00010000
 993	READ_CONTROL             = 0x00020000
 994	WRITE_DAC                = 0x00040000
 995	WRITE_OWNER              = 0x00080000
 996	SYNCHRONIZE              = 0x00100000
 997	STANDARD_RIGHTS_REQUIRED = 0x000F0000
 998	STANDARD_RIGHTS_READ     = READ_CONTROL
 999	STANDARD_RIGHTS_WRITE    = READ_CONTROL
1000	STANDARD_RIGHTS_EXECUTE  = READ_CONTROL
1001	STANDARD_RIGHTS_ALL      = 0x001F0000
1002	SPECIFIC_RIGHTS_ALL      = 0x0000FFFF
1003	ACCESS_SYSTEM_SECURITY   = 0x01000000
1004	MAXIMUM_ALLOWED          = 0x02000000
1005	GENERIC_READ             = 0x80000000
1006	GENERIC_WRITE            = 0x40000000
1007	GENERIC_EXECUTE          = 0x20000000
1008	GENERIC_ALL              = 0x10000000
1009)
1010
1011type ACCESS_MODE uint32
1012
1013// Constants for type ACCESS_MODE
1014const (
1015	NOT_USED_ACCESS   = 0
1016	GRANT_ACCESS      = 1
1017	SET_ACCESS        = 2
1018	DENY_ACCESS       = 3
1019	REVOKE_ACCESS     = 4
1020	SET_AUDIT_SUCCESS = 5
1021	SET_AUDIT_FAILURE = 6
1022)
1023
1024// Constants for AceFlags and Inheritance fields
1025const (
1026	NO_INHERITANCE                     = 0x0
1027	SUB_OBJECTS_ONLY_INHERIT           = 0x1
1028	SUB_CONTAINERS_ONLY_INHERIT        = 0x2
1029	SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x3
1030	INHERIT_NO_PROPAGATE               = 0x4
1031	INHERIT_ONLY                       = 0x8
1032	INHERITED_ACCESS_ENTRY             = 0x10
1033	INHERITED_PARENT                   = 0x10000000
1034	INHERITED_GRANDPARENT              = 0x20000000
1035	OBJECT_INHERIT_ACE                 = 0x1
1036	CONTAINER_INHERIT_ACE              = 0x2
1037	NO_PROPAGATE_INHERIT_ACE           = 0x4
1038	INHERIT_ONLY_ACE                   = 0x8
1039	INHERITED_ACE                      = 0x10
1040	VALID_INHERIT_FLAGS                = 0x1F
1041)
1042
1043type MULTIPLE_TRUSTEE_OPERATION uint32
1044
1045// Constants for MULTIPLE_TRUSTEE_OPERATION
1046const (
1047	NO_MULTIPLE_TRUSTEE    = 0
1048	TRUSTEE_IS_IMPERSONATE = 1
1049)
1050
1051type TRUSTEE_FORM uint32
1052
1053// Constants for TRUSTEE_FORM
1054const (
1055	TRUSTEE_IS_SID              = 0
1056	TRUSTEE_IS_NAME             = 1
1057	TRUSTEE_BAD_FORM            = 2
1058	TRUSTEE_IS_OBJECTS_AND_SID  = 3
1059	TRUSTEE_IS_OBJECTS_AND_NAME = 4
1060)
1061
1062type TRUSTEE_TYPE uint32
1063
1064// Constants for TRUSTEE_TYPE
1065const (
1066	TRUSTEE_IS_UNKNOWN          = 0
1067	TRUSTEE_IS_USER             = 1
1068	TRUSTEE_IS_GROUP            = 2
1069	TRUSTEE_IS_DOMAIN           = 3
1070	TRUSTEE_IS_ALIAS            = 4
1071	TRUSTEE_IS_WELL_KNOWN_GROUP = 5
1072	TRUSTEE_IS_DELETED          = 6
1073	TRUSTEE_IS_INVALID          = 7
1074	TRUSTEE_IS_COMPUTER         = 8
1075)
1076
1077// Constants for ObjectsPresent field
1078const (
1079	ACE_OBJECT_TYPE_PRESENT           = 0x1
1080	ACE_INHERITED_OBJECT_TYPE_PRESENT = 0x2
1081)
1082
1083type EXPLICIT_ACCESS struct {
1084	AccessPermissions ACCESS_MASK
1085	AccessMode        ACCESS_MODE
1086	Inheritance       uint32
1087	Trustee           TRUSTEE
1088}
1089
1090// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header
1091type ACE_HEADER struct {
1092	AceType  uint8
1093	AceFlags uint8
1094	AceSize  uint16
1095}
1096
1097// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-access_allowed_ace
1098type ACCESS_ALLOWED_ACE struct {
1099	Header   ACE_HEADER
1100	Mask     ACCESS_MASK
1101	SidStart uint32
1102}
1103
1104const (
1105	// Constants for AceType
1106	// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header
1107	ACCESS_ALLOWED_ACE_TYPE = 0
1108	ACCESS_DENIED_ACE_TYPE  = 1
1109)
1110
1111// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions.
1112type TrusteeValue uintptr
1113
1114func TrusteeValueFromString(str string) TrusteeValue {
1115	return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str)))
1116}
1117func TrusteeValueFromSID(sid *SID) TrusteeValue {
1118	return TrusteeValue(unsafe.Pointer(sid))
1119}
1120func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue {
1121	return TrusteeValue(unsafe.Pointer(objectsAndSid))
1122}
1123func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue {
1124	return TrusteeValue(unsafe.Pointer(objectsAndName))
1125}
1126
1127type TRUSTEE struct {
1128	MultipleTrustee          *TRUSTEE
1129	MultipleTrusteeOperation MULTIPLE_TRUSTEE_OPERATION
1130	TrusteeForm              TRUSTEE_FORM
1131	TrusteeType              TRUSTEE_TYPE
1132	TrusteeValue             TrusteeValue
1133}
1134
1135type OBJECTS_AND_SID struct {
1136	ObjectsPresent          uint32
1137	ObjectTypeGuid          GUID
1138	InheritedObjectTypeGuid GUID
1139	Sid                     *SID
1140}
1141
1142type OBJECTS_AND_NAME struct {
1143	ObjectsPresent          uint32
1144	ObjectType              SE_OBJECT_TYPE
1145	ObjectTypeName          *uint16
1146	InheritedObjectTypeName *uint16
1147	Name                    *uint16
1148}
1149
1150//sys	getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetSecurityInfo
1151//sys	SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetSecurityInfo
1152//sys	getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetNamedSecurityInfoW
1153//sys	SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW
1154//sys	SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) = advapi32.SetKernelObjectSecurity
1155
1156//sys	buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) = advapi32.BuildSecurityDescriptorW
1157//sys	initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor
1158
1159//sys	getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) = advapi32.GetSecurityDescriptorControl
1160//sys	getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorDacl
1161//sys	getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorSacl
1162//sys	getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner
1163//sys	getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorGroup
1164//sys	getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) = advapi32.GetSecurityDescriptorLength
1165//sys	getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) [failretval!=0] = advapi32.GetSecurityDescriptorRMControl
1166//sys	isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) = advapi32.IsValidSecurityDescriptor
1167
1168//sys	setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) = advapi32.SetSecurityDescriptorControl
1169//sys	setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl
1170//sys	setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl
1171//sys	setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) = advapi32.SetSecurityDescriptorOwner
1172//sys	setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) = advapi32.SetSecurityDescriptorGroup
1173//sys	setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) = advapi32.SetSecurityDescriptorRMControl
1174
1175//sys	convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
1176//sys	convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
1177
1178//sys	makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) = advapi32.MakeAbsoluteSD
1179//sys	makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD
1180
1181//sys	setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW
1182//sys	GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (err error) = advapi32.GetAce
1183
1184// Control returns the security descriptor control bits.
1185func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) {
1186	err = getSecurityDescriptorControl(sd, &control, &revision)
1187	return
1188}
1189
1190// SetControl sets the security descriptor control bits.
1191func (sd *SECURITY_DESCRIPTOR) SetControl(controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) error {
1192	return setSecurityDescriptorControl(sd, controlBitsOfInterest, controlBitsToSet)
1193}
1194
1195// RMControl returns the security descriptor resource manager control bits.
1196func (sd *SECURITY_DESCRIPTOR) RMControl() (control uint8, err error) {
1197	err = getSecurityDescriptorRMControl(sd, &control)
1198	return
1199}
1200
1201// SetRMControl sets the security descriptor resource manager control bits.
1202func (sd *SECURITY_DESCRIPTOR) SetRMControl(rmControl uint8) {
1203	setSecurityDescriptorRMControl(sd, &rmControl)
1204}
1205
1206// DACL returns the security descriptor DACL and whether it was defaulted. The dacl return value may be nil
1207// if a DACL exists but is an "empty DACL", meaning fully permissive. If the DACL does not exist, err returns
1208// ERROR_OBJECT_NOT_FOUND.
1209func (sd *SECURITY_DESCRIPTOR) DACL() (dacl *ACL, defaulted bool, err error) {
1210	var present bool
1211	err = getSecurityDescriptorDacl(sd, &present, &dacl, &defaulted)
1212	if !present {
1213		err = ERROR_OBJECT_NOT_FOUND
1214	}
1215	return
1216}
1217
1218// SetDACL sets the absolute security descriptor DACL.
1219func (absoluteSD *SECURITY_DESCRIPTOR) SetDACL(dacl *ACL, present, defaulted bool) error {
1220	return setSecurityDescriptorDacl(absoluteSD, present, dacl, defaulted)
1221}
1222
1223// SACL returns the security descriptor SACL and whether it was defaulted. The sacl return value may be nil
1224// if a SACL exists but is an "empty SACL", meaning fully permissive. If the SACL does not exist, err returns
1225// ERROR_OBJECT_NOT_FOUND.
1226func (sd *SECURITY_DESCRIPTOR) SACL() (sacl *ACL, defaulted bool, err error) {
1227	var present bool
1228	err = getSecurityDescriptorSacl(sd, &present, &sacl, &defaulted)
1229	if !present {
1230		err = ERROR_OBJECT_NOT_FOUND
1231	}
1232	return
1233}
1234
1235// SetSACL sets the absolute security descriptor SACL.
1236func (absoluteSD *SECURITY_DESCRIPTOR) SetSACL(sacl *ACL, present, defaulted bool) error {
1237	return setSecurityDescriptorSacl(absoluteSD, present, sacl, defaulted)
1238}
1239
1240// Owner returns the security descriptor owner and whether it was defaulted.
1241func (sd *SECURITY_DESCRIPTOR) Owner() (owner *SID, defaulted bool, err error) {
1242	err = getSecurityDescriptorOwner(sd, &owner, &defaulted)
1243	return
1244}
1245
1246// SetOwner sets the absolute security descriptor owner.
1247func (absoluteSD *SECURITY_DESCRIPTOR) SetOwner(owner *SID, defaulted bool) error {
1248	return setSecurityDescriptorOwner(absoluteSD, owner, defaulted)
1249}
1250
1251// Group returns the security descriptor group and whether it was defaulted.
1252func (sd *SECURITY_DESCRIPTOR) Group() (group *SID, defaulted bool, err error) {
1253	err = getSecurityDescriptorGroup(sd, &group, &defaulted)
1254	return
1255}
1256
1257// SetGroup sets the absolute security descriptor owner.
1258func (absoluteSD *SECURITY_DESCRIPTOR) SetGroup(group *SID, defaulted bool) error {
1259	return setSecurityDescriptorGroup(absoluteSD, group, defaulted)
1260}
1261
1262// Length returns the length of the security descriptor.
1263func (sd *SECURITY_DESCRIPTOR) Length() uint32 {
1264	return getSecurityDescriptorLength(sd)
1265}
1266
1267// IsValid returns whether the security descriptor is valid.
1268func (sd *SECURITY_DESCRIPTOR) IsValid() bool {
1269	return isValidSecurityDescriptor(sd)
1270}
1271
1272// String returns the SDDL form of the security descriptor, with a function signature that can be
1273// used with %v formatting directives.
1274func (sd *SECURITY_DESCRIPTOR) String() string {
1275	var sddl *uint16
1276	err := convertSecurityDescriptorToStringSecurityDescriptor(sd, 1, 0xff, &sddl, nil)
1277	if err != nil {
1278		return ""
1279	}
1280	defer LocalFree(Handle(unsafe.Pointer(sddl)))
1281	return UTF16PtrToString(sddl)
1282}
1283
1284// ToAbsolute converts a self-relative security descriptor into an absolute one.
1285func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
1286	control, _, err := selfRelativeSD.Control()
1287	if err != nil {
1288		return
1289	}
1290	if control&SE_SELF_RELATIVE == 0 {
1291		err = ERROR_INVALID_PARAMETER
1292		return
1293	}
1294	var absoluteSDSize, daclSize, saclSize, ownerSize, groupSize uint32
1295	err = makeAbsoluteSD(selfRelativeSD, nil, &absoluteSDSize,
1296		nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &groupSize)
1297	switch err {
1298	case ERROR_INSUFFICIENT_BUFFER:
1299	case nil:
1300		// makeAbsoluteSD is expected to fail, but it succeeds.
1301		return nil, ERROR_INTERNAL_ERROR
1302	default:
1303		return nil, err
1304	}
1305	if absoluteSDSize > 0 {
1306		absoluteSD = new(SECURITY_DESCRIPTOR)
1307		if unsafe.Sizeof(*absoluteSD) < uintptr(absoluteSDSize) {
1308			panic("sizeof(SECURITY_DESCRIPTOR) too small")
1309		}
1310	}
1311	var (
1312		dacl  *ACL
1313		sacl  *ACL
1314		owner *SID
1315		group *SID
1316	)
1317	if daclSize > 0 {
1318		dacl = (*ACL)(unsafe.Pointer(unsafe.SliceData(make([]byte, daclSize))))
1319	}
1320	if saclSize > 0 {
1321		sacl = (*ACL)(unsafe.Pointer(unsafe.SliceData(make([]byte, saclSize))))
1322	}
1323	if ownerSize > 0 {
1324		owner = (*SID)(unsafe.Pointer(unsafe.SliceData(make([]byte, ownerSize))))
1325	}
1326	if groupSize > 0 {
1327		group = (*SID)(unsafe.Pointer(unsafe.SliceData(make([]byte, groupSize))))
1328	}
1329	// We call into Windows via makeAbsoluteSD, which sets up
1330	// pointers within absoluteSD that point to other chunks of memory
1331	// we pass into makeAbsoluteSD, and that happens outside the view of the GC.
1332	// We therefore take some care here to then verify the pointers are as we expect
1333	// and set them explicitly in view of the GC. See https://go.dev/issue/73199.
1334	// TODO: consider weak pointers once Go 1.24 is appropriate. See suggestion in https://go.dev/cl/663575.
1335	err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize,
1336		dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize)
1337	if err != nil {
1338		// Don't return absoluteSD, which might be partially initialized.
1339		return nil, err
1340	}
1341	// Before using any fields, verify absoluteSD is in the format we expect according to Windows.
1342	// See https://learn.microsoft.com/en-us/windows/win32/secauthz/absolute-and-self-relative-security-descriptors
1343	absControl, _, err := absoluteSD.Control()
1344	if err != nil {
1345		panic("absoluteSD: " + err.Error())
1346	}
1347	if absControl&SE_SELF_RELATIVE != 0 {
1348		panic("absoluteSD not in absolute format")
1349	}
1350	if absoluteSD.dacl != dacl {
1351		panic("dacl pointer mismatch")
1352	}
1353	if absoluteSD.sacl != sacl {
1354		panic("sacl pointer mismatch")
1355	}
1356	if absoluteSD.owner != owner {
1357		panic("owner pointer mismatch")
1358	}
1359	if absoluteSD.group != group {
1360		panic("group pointer mismatch")
1361	}
1362	absoluteSD.dacl = dacl
1363	absoluteSD.sacl = sacl
1364	absoluteSD.owner = owner
1365	absoluteSD.group = group
1366
1367	return
1368}
1369
1370// ToSelfRelative converts an absolute security descriptor into a self-relative one.
1371func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURITY_DESCRIPTOR, err error) {
1372	control, _, err := absoluteSD.Control()
1373	if err != nil {
1374		return
1375	}
1376	if control&SE_SELF_RELATIVE != 0 {
1377		err = ERROR_INVALID_PARAMETER
1378		return
1379	}
1380	var selfRelativeSDSize uint32
1381	err = makeSelfRelativeSD(absoluteSD, nil, &selfRelativeSDSize)
1382	switch err {
1383	case ERROR_INSUFFICIENT_BUFFER:
1384	case nil:
1385		// makeSelfRelativeSD is expected to fail, but it succeeds.
1386		return nil, ERROR_INTERNAL_ERROR
1387	default:
1388		return nil, err
1389	}
1390	if selfRelativeSDSize > 0 {
1391		selfRelativeSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, selfRelativeSDSize)[0]))
1392	}
1393	err = makeSelfRelativeSD(absoluteSD, selfRelativeSD, &selfRelativeSDSize)
1394	return
1395}
1396
1397func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR {
1398	sdLen := int(selfRelativeSD.Length())
1399	const min = int(unsafe.Sizeof(SECURITY_DESCRIPTOR{}))
1400	if sdLen < min {
1401		sdLen = min
1402	}
1403
1404	src := unsafe.Slice((*byte)(unsafe.Pointer(selfRelativeSD)), sdLen)
1405	// SECURITY_DESCRIPTOR has pointers in it, which means checkptr expects for it to
1406	// be aligned properly. When we're copying a Windows-allocated struct to a
1407	// Go-allocated one, make sure that the Go allocation is aligned to the
1408	// pointer size.
1409	const psize = int(unsafe.Sizeof(uintptr(0)))
1410	alloc := make([]uintptr, (sdLen+psize-1)/psize)
1411	dst := unsafe.Slice((*byte)(unsafe.Pointer(&alloc[0])), sdLen)
1412	copy(dst, src)
1413	return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&dst[0]))
1414}
1415
1416// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a
1417// self-relative security descriptor object allocated on the Go heap.
1418func SecurityDescriptorFromString(sddl string) (sd *SECURITY_DESCRIPTOR, err error) {
1419	var winHeapSD *SECURITY_DESCRIPTOR
1420	err = convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &winHeapSD, nil)
1421	if err != nil {
1422		return
1423	}
1424	defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1425	return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1426}
1427
1428// GetSecurityInfo queries the security information for a given handle and returns the self-relative security
1429// descriptor result on the Go heap.
1430func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
1431	var winHeapSD *SECURITY_DESCRIPTOR
1432	err = getSecurityInfo(handle, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
1433	if err != nil {
1434		return
1435	}
1436	defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1437	return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1438}
1439
1440// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security
1441// descriptor result on the Go heap.
1442func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
1443	var winHeapSD *SECURITY_DESCRIPTOR
1444	err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
1445	if err != nil {
1446		return
1447	}
1448	defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1449	return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1450}
1451
1452// BuildSecurityDescriptor makes a new security descriptor using the input trustees, explicit access lists, and
1453// prior security descriptor to be merged, any of which can be nil, returning the self-relative security descriptor
1454// result on the Go heap.
1455func BuildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, accessEntries []EXPLICIT_ACCESS, auditEntries []EXPLICIT_ACCESS, mergedSecurityDescriptor *SECURITY_DESCRIPTOR) (sd *SECURITY_DESCRIPTOR, err error) {
1456	var winHeapSD *SECURITY_DESCRIPTOR
1457	var winHeapSDSize uint32
1458	var firstAccessEntry *EXPLICIT_ACCESS
1459	if len(accessEntries) > 0 {
1460		firstAccessEntry = &accessEntries[0]
1461	}
1462	var firstAuditEntry *EXPLICIT_ACCESS
1463	if len(auditEntries) > 0 {
1464		firstAuditEntry = &auditEntries[0]
1465	}
1466	err = buildSecurityDescriptor(owner, group, uint32(len(accessEntries)), firstAccessEntry, uint32(len(auditEntries)), firstAuditEntry, mergedSecurityDescriptor, &winHeapSDSize, &winHeapSD)
1467	if err != nil {
1468		return
1469	}
1470	defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1471	return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1472}
1473
1474// NewSecurityDescriptor creates and initializes a new absolute security descriptor.
1475func NewSecurityDescriptor() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
1476	absoluteSD = &SECURITY_DESCRIPTOR{}
1477	err = initializeSecurityDescriptor(absoluteSD, 1)
1478	return
1479}
1480
1481// ACLFromEntries returns a new ACL on the Go heap containing a list of explicit entries as well as those of another ACL.
1482// Both explicitEntries and mergedACL are optional and can be nil.
1483func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL, err error) {
1484	var firstExplicitEntry *EXPLICIT_ACCESS
1485	if len(explicitEntries) > 0 {
1486		firstExplicitEntry = &explicitEntries[0]
1487	}
1488	var winHeapACL *ACL
1489	err = setEntriesInAcl(uint32(len(explicitEntries)), firstExplicitEntry, mergedACL, &winHeapACL)
1490	if err != nil {
1491		return
1492	}
1493	defer LocalFree(Handle(unsafe.Pointer(winHeapACL)))
1494	aclBytes := make([]byte, winHeapACL.aclSize)
1495	copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes):len(aclBytes)])
1496	return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil
1497}