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