blob: 111c10d3a7f6033bd5b8cbe94f085c33a4b31917 [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001// 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"
Andrea Campanella3614a922021-02-25 12:40:42 +010010
11 "golang.org/x/sys/internal/unsafeheader"
khenaidooab1f7bd2019-11-14 14:00:27 -050012)
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)))
Andrea Campanella3614a922021-02-25 12:40:42 +0100240 return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:])
khenaidooab1f7bd2019-11-14 14:00:27 -0500241}
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
khenaidood948f772021-08-11 17:49:24 -0400627//sys isTokenRestricted(tokenHandle Token) (ret bool, err error) [!failretval] = advapi32.IsTokenRestricted
khenaidooab1f7bd2019-11-14 14:00:27 -0500628//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
khenaidood948f772021-08-11 17:49:24 -0400841// 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
khenaidooab1f7bd2019-11-14 14:00:27 -0500851const (
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
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
khenaidood948f772021-08-11 17:49:24 -0400911type 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
khenaidooab1f7bd2019-11-14 14:00:27 -0500924type 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// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions.
1091type TrusteeValue uintptr
1092
1093func TrusteeValueFromString(str string) TrusteeValue {
1094 return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str)))
1095}
1096func TrusteeValueFromSID(sid *SID) TrusteeValue {
1097 return TrusteeValue(unsafe.Pointer(sid))
1098}
1099func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue {
1100 return TrusteeValue(unsafe.Pointer(objectsAndSid))
1101}
1102func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue {
1103 return TrusteeValue(unsafe.Pointer(objectsAndName))
1104}
1105
1106type TRUSTEE struct {
1107 MultipleTrustee *TRUSTEE
1108 MultipleTrusteeOperation MULTIPLE_TRUSTEE_OPERATION
1109 TrusteeForm TRUSTEE_FORM
1110 TrusteeType TRUSTEE_TYPE
1111 TrusteeValue TrusteeValue
1112}
1113
1114type OBJECTS_AND_SID struct {
1115 ObjectsPresent uint32
1116 ObjectTypeGuid GUID
1117 InheritedObjectTypeGuid GUID
1118 Sid *SID
1119}
1120
1121type OBJECTS_AND_NAME struct {
1122 ObjectsPresent uint32
1123 ObjectType SE_OBJECT_TYPE
1124 ObjectTypeName *uint16
1125 InheritedObjectTypeName *uint16
1126 Name *uint16
1127}
1128
1129//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
khenaidood948f772021-08-11 17:49:24 -04001130//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetSecurityInfo
khenaidooab1f7bd2019-11-14 14:00:27 -05001131//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
1132//sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW
khenaidood948f772021-08-11 17:49:24 -04001133//sys SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) = advapi32.SetKernelObjectSecurity
khenaidooab1f7bd2019-11-14 14:00:27 -05001134
1135//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
1136//sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor
1137
1138//sys getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) = advapi32.GetSecurityDescriptorControl
1139//sys getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorDacl
1140//sys getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorSacl
1141//sys getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner
1142//sys getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorGroup
1143//sys getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) = advapi32.GetSecurityDescriptorLength
1144//sys getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) [failretval!=0] = advapi32.GetSecurityDescriptorRMControl
1145//sys isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) = advapi32.IsValidSecurityDescriptor
1146
1147//sys setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) = advapi32.SetSecurityDescriptorControl
1148//sys setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl
1149//sys setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl
1150//sys setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) = advapi32.SetSecurityDescriptorOwner
1151//sys setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) = advapi32.SetSecurityDescriptorGroup
1152//sys setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) = advapi32.SetSecurityDescriptorRMControl
1153
1154//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
1155//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
1156
1157//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
1158//sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD
1159
1160//sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW
1161
1162// Control returns the security descriptor control bits.
1163func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) {
1164 err = getSecurityDescriptorControl(sd, &control, &revision)
1165 return
1166}
1167
1168// SetControl sets the security descriptor control bits.
1169func (sd *SECURITY_DESCRIPTOR) SetControl(controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) error {
1170 return setSecurityDescriptorControl(sd, controlBitsOfInterest, controlBitsToSet)
1171}
1172
1173// RMControl returns the security descriptor resource manager control bits.
1174func (sd *SECURITY_DESCRIPTOR) RMControl() (control uint8, err error) {
1175 err = getSecurityDescriptorRMControl(sd, &control)
1176 return
1177}
1178
1179// SetRMControl sets the security descriptor resource manager control bits.
1180func (sd *SECURITY_DESCRIPTOR) SetRMControl(rmControl uint8) {
1181 setSecurityDescriptorRMControl(sd, &rmControl)
1182}
1183
1184// DACL returns the security descriptor DACL and whether it was defaulted. The dacl return value may be nil
1185// if a DACL exists but is an "empty DACL", meaning fully permissive. If the DACL does not exist, err returns
1186// ERROR_OBJECT_NOT_FOUND.
1187func (sd *SECURITY_DESCRIPTOR) DACL() (dacl *ACL, defaulted bool, err error) {
1188 var present bool
1189 err = getSecurityDescriptorDacl(sd, &present, &dacl, &defaulted)
1190 if !present {
1191 err = ERROR_OBJECT_NOT_FOUND
1192 }
1193 return
1194}
1195
1196// SetDACL sets the absolute security descriptor DACL.
1197func (absoluteSD *SECURITY_DESCRIPTOR) SetDACL(dacl *ACL, present, defaulted bool) error {
1198 return setSecurityDescriptorDacl(absoluteSD, present, dacl, defaulted)
1199}
1200
1201// SACL returns the security descriptor SACL and whether it was defaulted. The sacl return value may be nil
1202// if a SACL exists but is an "empty SACL", meaning fully permissive. If the SACL does not exist, err returns
1203// ERROR_OBJECT_NOT_FOUND.
1204func (sd *SECURITY_DESCRIPTOR) SACL() (sacl *ACL, defaulted bool, err error) {
1205 var present bool
1206 err = getSecurityDescriptorSacl(sd, &present, &sacl, &defaulted)
1207 if !present {
1208 err = ERROR_OBJECT_NOT_FOUND
1209 }
1210 return
1211}
1212
1213// SetSACL sets the absolute security descriptor SACL.
1214func (absoluteSD *SECURITY_DESCRIPTOR) SetSACL(sacl *ACL, present, defaulted bool) error {
1215 return setSecurityDescriptorSacl(absoluteSD, present, sacl, defaulted)
1216}
1217
1218// Owner returns the security descriptor owner and whether it was defaulted.
1219func (sd *SECURITY_DESCRIPTOR) Owner() (owner *SID, defaulted bool, err error) {
1220 err = getSecurityDescriptorOwner(sd, &owner, &defaulted)
1221 return
1222}
1223
1224// SetOwner sets the absolute security descriptor owner.
1225func (absoluteSD *SECURITY_DESCRIPTOR) SetOwner(owner *SID, defaulted bool) error {
1226 return setSecurityDescriptorOwner(absoluteSD, owner, defaulted)
1227}
1228
1229// Group returns the security descriptor group and whether it was defaulted.
1230func (sd *SECURITY_DESCRIPTOR) Group() (group *SID, defaulted bool, err error) {
1231 err = getSecurityDescriptorGroup(sd, &group, &defaulted)
1232 return
1233}
1234
1235// SetGroup sets the absolute security descriptor owner.
1236func (absoluteSD *SECURITY_DESCRIPTOR) SetGroup(group *SID, defaulted bool) error {
1237 return setSecurityDescriptorGroup(absoluteSD, group, defaulted)
1238}
1239
1240// Length returns the length of the security descriptor.
1241func (sd *SECURITY_DESCRIPTOR) Length() uint32 {
1242 return getSecurityDescriptorLength(sd)
1243}
1244
1245// IsValid returns whether the security descriptor is valid.
1246func (sd *SECURITY_DESCRIPTOR) IsValid() bool {
1247 return isValidSecurityDescriptor(sd)
1248}
1249
1250// String returns the SDDL form of the security descriptor, with a function signature that can be
1251// used with %v formatting directives.
1252func (sd *SECURITY_DESCRIPTOR) String() string {
1253 var sddl *uint16
1254 err := convertSecurityDescriptorToStringSecurityDescriptor(sd, 1, 0xff, &sddl, nil)
1255 if err != nil {
1256 return ""
1257 }
1258 defer LocalFree(Handle(unsafe.Pointer(sddl)))
Andrea Campanella3614a922021-02-25 12:40:42 +01001259 return UTF16PtrToString(sddl)
khenaidooab1f7bd2019-11-14 14:00:27 -05001260}
1261
1262// ToAbsolute converts a self-relative security descriptor into an absolute one.
1263func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
1264 control, _, err := selfRelativeSD.Control()
1265 if err != nil {
1266 return
1267 }
1268 if control&SE_SELF_RELATIVE == 0 {
1269 err = ERROR_INVALID_PARAMETER
1270 return
1271 }
1272 var absoluteSDSize, daclSize, saclSize, ownerSize, groupSize uint32
1273 err = makeAbsoluteSD(selfRelativeSD, nil, &absoluteSDSize,
1274 nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &groupSize)
1275 switch err {
1276 case ERROR_INSUFFICIENT_BUFFER:
1277 case nil:
1278 // makeAbsoluteSD is expected to fail, but it succeeds.
1279 return nil, ERROR_INTERNAL_ERROR
1280 default:
1281 return nil, err
1282 }
1283 if absoluteSDSize > 0 {
1284 absoluteSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, absoluteSDSize)[0]))
1285 }
1286 var (
1287 dacl *ACL
1288 sacl *ACL
1289 owner *SID
1290 group *SID
1291 )
1292 if daclSize > 0 {
1293 dacl = (*ACL)(unsafe.Pointer(&make([]byte, daclSize)[0]))
1294 }
1295 if saclSize > 0 {
1296 sacl = (*ACL)(unsafe.Pointer(&make([]byte, saclSize)[0]))
1297 }
1298 if ownerSize > 0 {
1299 owner = (*SID)(unsafe.Pointer(&make([]byte, ownerSize)[0]))
1300 }
1301 if groupSize > 0 {
1302 group = (*SID)(unsafe.Pointer(&make([]byte, groupSize)[0]))
1303 }
1304 err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize,
1305 dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize)
1306 return
1307}
1308
1309// ToSelfRelative converts an absolute security descriptor into a self-relative one.
1310func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURITY_DESCRIPTOR, err error) {
1311 control, _, err := absoluteSD.Control()
1312 if err != nil {
1313 return
1314 }
1315 if control&SE_SELF_RELATIVE != 0 {
1316 err = ERROR_INVALID_PARAMETER
1317 return
1318 }
1319 var selfRelativeSDSize uint32
1320 err = makeSelfRelativeSD(absoluteSD, nil, &selfRelativeSDSize)
1321 switch err {
1322 case ERROR_INSUFFICIENT_BUFFER:
1323 case nil:
1324 // makeSelfRelativeSD is expected to fail, but it succeeds.
1325 return nil, ERROR_INTERNAL_ERROR
1326 default:
1327 return nil, err
1328 }
1329 if selfRelativeSDSize > 0 {
1330 selfRelativeSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, selfRelativeSDSize)[0]))
1331 }
1332 err = makeSelfRelativeSD(absoluteSD, selfRelativeSD, &selfRelativeSDSize)
1333 return
1334}
1335
1336func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR {
khenaidood948f772021-08-11 17:49:24 -04001337 sdLen := int(selfRelativeSD.Length())
1338 const min = int(unsafe.Sizeof(SECURITY_DESCRIPTOR{}))
1339 if sdLen < min {
1340 sdLen = min
1341 }
Andrea Campanella3614a922021-02-25 12:40:42 +01001342
1343 var src []byte
1344 h := (*unsafeheader.Slice)(unsafe.Pointer(&src))
1345 h.Data = unsafe.Pointer(selfRelativeSD)
1346 h.Len = sdLen
1347 h.Cap = sdLen
1348
khenaidood948f772021-08-11 17:49:24 -04001349 const psize = int(unsafe.Sizeof(uintptr(0)))
1350
1351 var dst []byte
1352 h = (*unsafeheader.Slice)(unsafe.Pointer(&dst))
1353 alloc := make([]uintptr, (sdLen+psize-1)/psize)
1354 h.Data = (*unsafeheader.Slice)(unsafe.Pointer(&alloc)).Data
1355 h.Len = sdLen
1356 h.Cap = sdLen
1357
Andrea Campanella3614a922021-02-25 12:40:42 +01001358 copy(dst, src)
1359 return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&dst[0]))
khenaidooab1f7bd2019-11-14 14:00:27 -05001360}
1361
1362// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a
1363// self-relative security descriptor object allocated on the Go heap.
1364func SecurityDescriptorFromString(sddl string) (sd *SECURITY_DESCRIPTOR, err error) {
1365 var winHeapSD *SECURITY_DESCRIPTOR
1366 err = convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &winHeapSD, nil)
1367 if err != nil {
1368 return
1369 }
1370 defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1371 return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1372}
1373
1374// GetSecurityInfo queries the security information for a given handle and returns the self-relative security
1375// descriptor result on the Go heap.
1376func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
1377 var winHeapSD *SECURITY_DESCRIPTOR
1378 err = getSecurityInfo(handle, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
1379 if err != nil {
1380 return
1381 }
1382 defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1383 return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1384}
1385
1386// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security
1387// descriptor result on the Go heap.
1388func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
1389 var winHeapSD *SECURITY_DESCRIPTOR
1390 err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
1391 if err != nil {
1392 return
1393 }
1394 defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1395 return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1396}
1397
1398// BuildSecurityDescriptor makes a new security descriptor using the input trustees, explicit access lists, and
1399// prior security descriptor to be merged, any of which can be nil, returning the self-relative security descriptor
1400// result on the Go heap.
1401func BuildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, accessEntries []EXPLICIT_ACCESS, auditEntries []EXPLICIT_ACCESS, mergedSecurityDescriptor *SECURITY_DESCRIPTOR) (sd *SECURITY_DESCRIPTOR, err error) {
1402 var winHeapSD *SECURITY_DESCRIPTOR
1403 var winHeapSDSize uint32
1404 var firstAccessEntry *EXPLICIT_ACCESS
1405 if len(accessEntries) > 0 {
1406 firstAccessEntry = &accessEntries[0]
1407 }
1408 var firstAuditEntry *EXPLICIT_ACCESS
1409 if len(auditEntries) > 0 {
1410 firstAuditEntry = &auditEntries[0]
1411 }
1412 err = buildSecurityDescriptor(owner, group, uint32(len(accessEntries)), firstAccessEntry, uint32(len(auditEntries)), firstAuditEntry, mergedSecurityDescriptor, &winHeapSDSize, &winHeapSD)
1413 if err != nil {
1414 return
1415 }
1416 defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1417 return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1418}
1419
1420// NewSecurityDescriptor creates and initializes a new absolute security descriptor.
1421func NewSecurityDescriptor() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
1422 absoluteSD = &SECURITY_DESCRIPTOR{}
1423 err = initializeSecurityDescriptor(absoluteSD, 1)
1424 return
1425}
1426
1427// ACLFromEntries returns a new ACL on the Go heap containing a list of explicit entries as well as those of another ACL.
1428// Both explicitEntries and mergedACL are optional and can be nil.
1429func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL, err error) {
1430 var firstExplicitEntry *EXPLICIT_ACCESS
1431 if len(explicitEntries) > 0 {
1432 firstExplicitEntry = &explicitEntries[0]
1433 }
1434 var winHeapACL *ACL
1435 err = setEntriesInAcl(uint32(len(explicitEntries)), firstExplicitEntry, mergedACL, &winHeapACL)
1436 if err != nil {
1437 return
1438 }
1439 defer LocalFree(Handle(unsafe.Pointer(winHeapACL)))
1440 aclBytes := make([]byte, winHeapACL.aclSize)
Andrea Campanella3614a922021-02-25 12:40:42 +01001441 copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes):len(aclBytes)])
khenaidooab1f7bd2019-11-14 14:00:27 -05001442 return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil
1443}