blob: b84840feb32c6b2319efc2f8c5117f8b7f63849d [file] [log] [blame]
Zack Williamse940c7a2019-08-21 14:25:39 -07001// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package windows
6
7import (
8 "syscall"
9 "unsafe"
10)
11
12const (
13 STANDARD_RIGHTS_REQUIRED = 0xf0000
14 STANDARD_RIGHTS_READ = 0x20000
15 STANDARD_RIGHTS_WRITE = 0x20000
16 STANDARD_RIGHTS_EXECUTE = 0x20000
17 STANDARD_RIGHTS_ALL = 0x1F0000
18)
19
20const (
21 NameUnknown = 0
22 NameFullyQualifiedDN = 1
23 NameSamCompatible = 2
24 NameDisplay = 3
25 NameUniqueId = 6
26 NameCanonical = 7
27 NameUserPrincipal = 8
28 NameCanonicalEx = 9
29 NameServicePrincipal = 10
30 NameDnsDomain = 12
31)
32
33// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
34// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
35//sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
36//sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
37
38// TranslateAccountName converts a directory service
39// object name from one format to another.
40func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
41 u, e := UTF16PtrFromString(username)
42 if e != nil {
43 return "", e
44 }
45 n := uint32(50)
46 for {
47 b := make([]uint16, n)
48 e = TranslateName(u, from, to, &b[0], &n)
49 if e == nil {
50 return UTF16ToString(b[:n]), nil
51 }
52 if e != ERROR_INSUFFICIENT_BUFFER {
53 return "", e
54 }
55 if n <= uint32(len(b)) {
56 return "", e
57 }
58 }
59}
60
61const (
62 // do not reorder
63 NetSetupUnknownStatus = iota
64 NetSetupUnjoined
65 NetSetupWorkgroupName
66 NetSetupDomainName
67)
68
69type UserInfo10 struct {
70 Name *uint16
71 Comment *uint16
72 UsrComment *uint16
73 FullName *uint16
74}
75
76//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
77//sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
78//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
79
80const (
81 // do not reorder
82 SidTypeUser = 1 + iota
83 SidTypeGroup
84 SidTypeDomain
85 SidTypeAlias
86 SidTypeWellKnownGroup
87 SidTypeDeletedAccount
88 SidTypeInvalid
89 SidTypeUnknown
90 SidTypeComputer
91 SidTypeLabel
92)
93
94type SidIdentifierAuthority struct {
95 Value [6]byte
96}
97
98var (
99 SECURITY_NULL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
100 SECURITY_WORLD_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
101 SECURITY_LOCAL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
102 SECURITY_CREATOR_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
103 SECURITY_NON_UNIQUE_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
104 SECURITY_NT_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
105 SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
106)
107
108const (
109 SECURITY_NULL_RID = 0
110 SECURITY_WORLD_RID = 0
111 SECURITY_LOCAL_RID = 0
112 SECURITY_CREATOR_OWNER_RID = 0
113 SECURITY_CREATOR_GROUP_RID = 1
114 SECURITY_DIALUP_RID = 1
115 SECURITY_NETWORK_RID = 2
116 SECURITY_BATCH_RID = 3
117 SECURITY_INTERACTIVE_RID = 4
118 SECURITY_LOGON_IDS_RID = 5
119 SECURITY_SERVICE_RID = 6
120 SECURITY_LOCAL_SYSTEM_RID = 18
121 SECURITY_BUILTIN_DOMAIN_RID = 32
122 SECURITY_PRINCIPAL_SELF_RID = 10
123 SECURITY_CREATOR_OWNER_SERVER_RID = 0x2
124 SECURITY_CREATOR_GROUP_SERVER_RID = 0x3
125 SECURITY_LOGON_IDS_RID_COUNT = 0x3
126 SECURITY_ANONYMOUS_LOGON_RID = 0x7
127 SECURITY_PROXY_RID = 0x8
128 SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
129 SECURITY_SERVER_LOGON_RID = SECURITY_ENTERPRISE_CONTROLLERS_RID
130 SECURITY_AUTHENTICATED_USER_RID = 0xb
131 SECURITY_RESTRICTED_CODE_RID = 0xc
132 SECURITY_NT_NON_UNIQUE_RID = 0x15
133)
134
135// Predefined domain-relative RIDs for local groups.
136// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
137const (
138 DOMAIN_ALIAS_RID_ADMINS = 0x220
139 DOMAIN_ALIAS_RID_USERS = 0x221
140 DOMAIN_ALIAS_RID_GUESTS = 0x222
141 DOMAIN_ALIAS_RID_POWER_USERS = 0x223
142 DOMAIN_ALIAS_RID_ACCOUNT_OPS = 0x224
143 DOMAIN_ALIAS_RID_SYSTEM_OPS = 0x225
144 DOMAIN_ALIAS_RID_PRINT_OPS = 0x226
145 DOMAIN_ALIAS_RID_BACKUP_OPS = 0x227
146 DOMAIN_ALIAS_RID_REPLICATOR = 0x228
147 DOMAIN_ALIAS_RID_RAS_SERVERS = 0x229
148 DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 0x22a
149 DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS = 0x22b
150 DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS = 0x22c
151 DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
152 DOMAIN_ALIAS_RID_MONITORING_USERS = 0x22e
153 DOMAIN_ALIAS_RID_LOGGING_USERS = 0x22f
154 DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS = 0x230
155 DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS = 0x231
156 DOMAIN_ALIAS_RID_DCOM_USERS = 0x232
157 DOMAIN_ALIAS_RID_IUSERS = 0x238
158 DOMAIN_ALIAS_RID_CRYPTO_OPERATORS = 0x239
159 DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP = 0x23b
160 DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c
161 DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP = 0x23d
162 DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP = 0x23e
163)
164
165//sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
166//sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
167//sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
168//sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
169//sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
170//sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
171//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
172//sys createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) = advapi32.CreateWellKnownSid
173//sys isWellKnownSid(sid *SID, sidType WELL_KNOWN_SID_TYPE) (isWellKnown bool) = advapi32.IsWellKnownSid
174//sys FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
175//sys EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
176//sys getSidIdentifierAuthority(sid *SID) (authority *SidIdentifierAuthority) = advapi32.GetSidIdentifierAuthority
177//sys getSidSubAuthorityCount(sid *SID) (count *uint8) = advapi32.GetSidSubAuthorityCount
178//sys getSidSubAuthority(sid *SID, index uint32) (subAuthority *uint32) = advapi32.GetSidSubAuthority
179//sys isValidSid(sid *SID) (isValid bool) = advapi32.IsValidSid
180
181// The security identifier (SID) structure is a variable-length
182// structure used to uniquely identify users or groups.
183type SID struct{}
184
185// StringToSid converts a string-format security identifier
186// SID into a valid, functional SID.
187func StringToSid(s string) (*SID, error) {
188 var sid *SID
189 p, e := UTF16PtrFromString(s)
190 if e != nil {
191 return nil, e
192 }
193 e = ConvertStringSidToSid(p, &sid)
194 if e != nil {
195 return nil, e
196 }
197 defer LocalFree((Handle)(unsafe.Pointer(sid)))
198 return sid.Copy()
199}
200
201// LookupSID retrieves a security identifier SID for the account
202// and the name of the domain on which the account was found.
203// System specify target computer to search.
204func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
205 if len(account) == 0 {
206 return nil, "", 0, syscall.EINVAL
207 }
208 acc, e := UTF16PtrFromString(account)
209 if e != nil {
210 return nil, "", 0, e
211 }
212 var sys *uint16
213 if len(system) > 0 {
214 sys, e = UTF16PtrFromString(system)
215 if e != nil {
216 return nil, "", 0, e
217 }
218 }
219 n := uint32(50)
220 dn := uint32(50)
221 for {
222 b := make([]byte, n)
223 db := make([]uint16, dn)
224 sid = (*SID)(unsafe.Pointer(&b[0]))
225 e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
226 if e == nil {
227 return sid, UTF16ToString(db), accType, nil
228 }
229 if e != ERROR_INSUFFICIENT_BUFFER {
230 return nil, "", 0, e
231 }
232 if n <= uint32(len(b)) {
233 return nil, "", 0, e
234 }
235 }
236}
237
238// String converts SID to a string format
239// suitable for display, storage, or transmission.
240func (sid *SID) String() (string, error) {
241 var s *uint16
242 e := ConvertSidToStringSid(sid, &s)
243 if e != nil {
244 return "", e
245 }
246 defer LocalFree((Handle)(unsafe.Pointer(s)))
247 return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
248}
249
250// Len returns the length, in bytes, of a valid security identifier SID.
251func (sid *SID) Len() int {
252 return int(GetLengthSid(sid))
253}
254
255// Copy creates a duplicate of security identifier SID.
256func (sid *SID) Copy() (*SID, error) {
257 b := make([]byte, sid.Len())
258 sid2 := (*SID)(unsafe.Pointer(&b[0]))
259 e := CopySid(uint32(len(b)), sid2, sid)
260 if e != nil {
261 return nil, e
262 }
263 return sid2, nil
264}
265
266// IdentifierAuthority returns the identifier authority of the SID.
267func (sid *SID) IdentifierAuthority() SidIdentifierAuthority {
268 return *getSidIdentifierAuthority(sid)
269}
270
271// SubAuthorityCount returns the number of sub-authorities in the SID.
272func (sid *SID) SubAuthorityCount() uint8 {
273 return *getSidSubAuthorityCount(sid)
274}
275
276// SubAuthority returns the sub-authority of the SID as specified by
277// the index, which must be less than sid.SubAuthorityCount().
278func (sid *SID) SubAuthority(idx uint32) uint32 {
279 if idx >= uint32(sid.SubAuthorityCount()) {
280 panic("sub-authority index out of range")
281 }
282 return *getSidSubAuthority(sid, idx)
283}
284
285// IsValid returns whether the SID has a valid revision and length.
286func (sid *SID) IsValid() bool {
287 return isValidSid(sid)
288}
289
290// Equals compares two SIDs for equality.
291func (sid *SID) Equals(sid2 *SID) bool {
292 return EqualSid(sid, sid2)
293}
294
295// IsWellKnown determines whether the SID matches the well-known sidType.
296func (sid *SID) IsWellKnown(sidType WELL_KNOWN_SID_TYPE) bool {
297 return isWellKnownSid(sid, sidType)
298}
299
300// LookupAccount retrieves the name of the account for this SID
301// and the name of the first domain on which this SID is found.
302// System specify target computer to search for.
303func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
304 var sys *uint16
305 if len(system) > 0 {
306 sys, err = UTF16PtrFromString(system)
307 if err != nil {
308 return "", "", 0, err
309 }
310 }
311 n := uint32(50)
312 dn := uint32(50)
313 for {
314 b := make([]uint16, n)
315 db := make([]uint16, dn)
316 e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
317 if e == nil {
318 return UTF16ToString(b), UTF16ToString(db), accType, nil
319 }
320 if e != ERROR_INSUFFICIENT_BUFFER {
321 return "", "", 0, e
322 }
323 if n <= uint32(len(b)) {
324 return "", "", 0, e
325 }
326 }
327}
328
329// Various types of pre-specified SIDs that can be synthesized and compared at runtime.
330type WELL_KNOWN_SID_TYPE uint32
331
332const (
333 WinNullSid = 0
334 WinWorldSid = 1
335 WinLocalSid = 2
336 WinCreatorOwnerSid = 3
337 WinCreatorGroupSid = 4
338 WinCreatorOwnerServerSid = 5
339 WinCreatorGroupServerSid = 6
340 WinNtAuthoritySid = 7
341 WinDialupSid = 8
342 WinNetworkSid = 9
343 WinBatchSid = 10
344 WinInteractiveSid = 11
345 WinServiceSid = 12
346 WinAnonymousSid = 13
347 WinProxySid = 14
348 WinEnterpriseControllersSid = 15
349 WinSelfSid = 16
350 WinAuthenticatedUserSid = 17
351 WinRestrictedCodeSid = 18
352 WinTerminalServerSid = 19
353 WinRemoteLogonIdSid = 20
354 WinLogonIdsSid = 21
355 WinLocalSystemSid = 22
356 WinLocalServiceSid = 23
357 WinNetworkServiceSid = 24
358 WinBuiltinDomainSid = 25
359 WinBuiltinAdministratorsSid = 26
360 WinBuiltinUsersSid = 27
361 WinBuiltinGuestsSid = 28
362 WinBuiltinPowerUsersSid = 29
363 WinBuiltinAccountOperatorsSid = 30
364 WinBuiltinSystemOperatorsSid = 31
365 WinBuiltinPrintOperatorsSid = 32
366 WinBuiltinBackupOperatorsSid = 33
367 WinBuiltinReplicatorSid = 34
368 WinBuiltinPreWindows2000CompatibleAccessSid = 35
369 WinBuiltinRemoteDesktopUsersSid = 36
370 WinBuiltinNetworkConfigurationOperatorsSid = 37
371 WinAccountAdministratorSid = 38
372 WinAccountGuestSid = 39
373 WinAccountKrbtgtSid = 40
374 WinAccountDomainAdminsSid = 41
375 WinAccountDomainUsersSid = 42
376 WinAccountDomainGuestsSid = 43
377 WinAccountComputersSid = 44
378 WinAccountControllersSid = 45
379 WinAccountCertAdminsSid = 46
380 WinAccountSchemaAdminsSid = 47
381 WinAccountEnterpriseAdminsSid = 48
382 WinAccountPolicyAdminsSid = 49
383 WinAccountRasAndIasServersSid = 50
384 WinNTLMAuthenticationSid = 51
385 WinDigestAuthenticationSid = 52
386 WinSChannelAuthenticationSid = 53
387 WinThisOrganizationSid = 54
388 WinOtherOrganizationSid = 55
389 WinBuiltinIncomingForestTrustBuildersSid = 56
390 WinBuiltinPerfMonitoringUsersSid = 57
391 WinBuiltinPerfLoggingUsersSid = 58
392 WinBuiltinAuthorizationAccessSid = 59
393 WinBuiltinTerminalServerLicenseServersSid = 60
394 WinBuiltinDCOMUsersSid = 61
395 WinBuiltinIUsersSid = 62
396 WinIUserSid = 63
397 WinBuiltinCryptoOperatorsSid = 64
398 WinUntrustedLabelSid = 65
399 WinLowLabelSid = 66
400 WinMediumLabelSid = 67
401 WinHighLabelSid = 68
402 WinSystemLabelSid = 69
403 WinWriteRestrictedCodeSid = 70
404 WinCreatorOwnerRightsSid = 71
405 WinCacheablePrincipalsGroupSid = 72
406 WinNonCacheablePrincipalsGroupSid = 73
407 WinEnterpriseReadonlyControllersSid = 74
408 WinAccountReadonlyControllersSid = 75
409 WinBuiltinEventLogReadersGroup = 76
410 WinNewEnterpriseReadonlyControllersSid = 77
411 WinBuiltinCertSvcDComAccessGroup = 78
412 WinMediumPlusLabelSid = 79
413 WinLocalLogonSid = 80
414 WinConsoleLogonSid = 81
415 WinThisOrganizationCertificateSid = 82
416 WinApplicationPackageAuthoritySid = 83
417 WinBuiltinAnyPackageSid = 84
418 WinCapabilityInternetClientSid = 85
419 WinCapabilityInternetClientServerSid = 86
420 WinCapabilityPrivateNetworkClientServerSid = 87
421 WinCapabilityPicturesLibrarySid = 88
422 WinCapabilityVideosLibrarySid = 89
423 WinCapabilityMusicLibrarySid = 90
424 WinCapabilityDocumentsLibrarySid = 91
425 WinCapabilitySharedUserCertificatesSid = 92
426 WinCapabilityEnterpriseAuthenticationSid = 93
427 WinCapabilityRemovableStorageSid = 94
428 WinBuiltinRDSRemoteAccessServersSid = 95
429 WinBuiltinRDSEndpointServersSid = 96
430 WinBuiltinRDSManagementServersSid = 97
431 WinUserModeDriversSid = 98
432 WinBuiltinHyperVAdminsSid = 99
433 WinAccountCloneableControllersSid = 100
434 WinBuiltinAccessControlAssistanceOperatorsSid = 101
435 WinBuiltinRemoteManagementUsersSid = 102
436 WinAuthenticationAuthorityAssertedSid = 103
437 WinAuthenticationServiceAssertedSid = 104
438 WinLocalAccountSid = 105
439 WinLocalAccountAndAdministratorSid = 106
440 WinAccountProtectedUsersSid = 107
441 WinCapabilityAppointmentsSid = 108
442 WinCapabilityContactsSid = 109
443 WinAccountDefaultSystemManagedSid = 110
444 WinBuiltinDefaultSystemManagedGroupSid = 111
445 WinBuiltinStorageReplicaAdminsSid = 112
446 WinAccountKeyAdminsSid = 113
447 WinAccountEnterpriseKeyAdminsSid = 114
448 WinAuthenticationKeyTrustSid = 115
449 WinAuthenticationKeyPropertyMFASid = 116
450 WinAuthenticationKeyPropertyAttestationSid = 117
451 WinAuthenticationFreshKeyAuthSid = 118
452 WinBuiltinDeviceOwnersSid = 119
453)
454
455// Creates a SID for a well-known predefined alias, generally using the constants of the form
456// Win*Sid, for the local machine.
457func CreateWellKnownSid(sidType WELL_KNOWN_SID_TYPE) (*SID, error) {
458 return CreateWellKnownDomainSid(sidType, nil)
459}
460
461// Creates a SID for a well-known predefined alias, generally using the constants of the form
462// Win*Sid, for the domain specified by the domainSid parameter.
463func CreateWellKnownDomainSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID) (*SID, error) {
464 n := uint32(50)
465 for {
466 b := make([]byte, n)
467 sid := (*SID)(unsafe.Pointer(&b[0]))
468 err := createWellKnownSid(sidType, domainSid, sid, &n)
469 if err == nil {
470 return sid, nil
471 }
472 if err != ERROR_INSUFFICIENT_BUFFER {
473 return nil, err
474 }
475 if n <= uint32(len(b)) {
476 return nil, err
477 }
478 }
479}
480
481const (
482 // do not reorder
483 TOKEN_ASSIGN_PRIMARY = 1 << iota
484 TOKEN_DUPLICATE
485 TOKEN_IMPERSONATE
486 TOKEN_QUERY
487 TOKEN_QUERY_SOURCE
488 TOKEN_ADJUST_PRIVILEGES
489 TOKEN_ADJUST_GROUPS
490 TOKEN_ADJUST_DEFAULT
491 TOKEN_ADJUST_SESSIONID
492
493 TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
494 TOKEN_ASSIGN_PRIMARY |
495 TOKEN_DUPLICATE |
496 TOKEN_IMPERSONATE |
497 TOKEN_QUERY |
498 TOKEN_QUERY_SOURCE |
499 TOKEN_ADJUST_PRIVILEGES |
500 TOKEN_ADJUST_GROUPS |
501 TOKEN_ADJUST_DEFAULT |
502 TOKEN_ADJUST_SESSIONID
503 TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
504 TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
505 TOKEN_ADJUST_PRIVILEGES |
506 TOKEN_ADJUST_GROUPS |
507 TOKEN_ADJUST_DEFAULT
508 TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
509)
510
511const (
512 // do not reorder
513 TokenUser = 1 + iota
514 TokenGroups
515 TokenPrivileges
516 TokenOwner
517 TokenPrimaryGroup
518 TokenDefaultDacl
519 TokenSource
520 TokenType
521 TokenImpersonationLevel
522 TokenStatistics
523 TokenRestrictedSids
524 TokenSessionId
525 TokenGroupsAndPrivileges
526 TokenSessionReference
527 TokenSandBoxInert
528 TokenAuditPolicy
529 TokenOrigin
530 TokenElevationType
531 TokenLinkedToken
532 TokenElevation
533 TokenHasRestrictions
534 TokenAccessInformation
535 TokenVirtualizationAllowed
536 TokenVirtualizationEnabled
537 TokenIntegrityLevel
538 TokenUIAccess
539 TokenMandatoryPolicy
540 TokenLogonSid
541 MaxTokenInfoClass
542)
543
544// Group attributes inside of Tokengroups.Groups[i].Attributes
545const (
546 SE_GROUP_MANDATORY = 0x00000001
547 SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002
548 SE_GROUP_ENABLED = 0x00000004
549 SE_GROUP_OWNER = 0x00000008
550 SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010
551 SE_GROUP_INTEGRITY = 0x00000020
552 SE_GROUP_INTEGRITY_ENABLED = 0x00000040
553 SE_GROUP_LOGON_ID = 0xC0000000
554 SE_GROUP_RESOURCE = 0x20000000
555 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
556)
557
558// Privilege attributes
559const (
560 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
561 SE_PRIVILEGE_ENABLED = 0x00000002
562 SE_PRIVILEGE_REMOVED = 0x00000004
563 SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000
564 SE_PRIVILEGE_VALID_ATTRIBUTES = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED | SE_PRIVILEGE_USED_FOR_ACCESS
565)
566
567// Token types
568const (
569 TokenPrimary = 1
570 TokenImpersonation = 2
571)
572
573// Impersonation levels
574const (
575 SecurityAnonymous = 0
576 SecurityIdentification = 1
577 SecurityImpersonation = 2
578 SecurityDelegation = 3
579)
580
581type LUID struct {
582 LowPart uint32
583 HighPart int32
584}
585
586type LUIDAndAttributes struct {
587 Luid LUID
588 Attributes uint32
589}
590
591type SIDAndAttributes struct {
592 Sid *SID
593 Attributes uint32
594}
595
596type Tokenuser struct {
597 User SIDAndAttributes
598}
599
600type Tokenprimarygroup struct {
601 PrimaryGroup *SID
602}
603
604type Tokengroups struct {
605 GroupCount uint32
606 Groups [1]SIDAndAttributes
607}
608
609type Tokenprivileges struct {
610 PrivilegeCount uint32
611 Privileges [1]LUIDAndAttributes
612}
613
614type Tokenmandatorylabel struct {
615 Label SIDAndAttributes
616}
617
618func (tml *Tokenmandatorylabel) Size() uint32 {
619 return uint32(unsafe.Sizeof(Tokenmandatorylabel{})) + GetLengthSid(tml.Label.Sid)
620}
621
622// Authorization Functions
623//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
624//sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
625//sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
626//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
627//sys RevertToSelf() (err error) = advapi32.RevertToSelf
628//sys SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken
629//sys LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW
630//sys AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) = advapi32.AdjustTokenPrivileges
631//sys AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) = advapi32.AdjustTokenGroups
632//sys GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
633//sys SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) = advapi32.SetTokenInformation
634//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
635//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
636//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
637
638// An access token contains the security information for a logon session.
639// The system creates an access token when a user logs on, and every
640// process executed on behalf of the user has a copy of the token.
641// The token identifies the user, the user's groups, and the user's
642// privileges. The system uses the token to control access to securable
643// objects and to control the ability of the user to perform various
644// system-related operations on the local computer.
645type Token Handle
646
647// OpenCurrentProcessToken opens the access token
648// associated with current process. It is a real
649// token that needs to be closed, unlike
650// GetCurrentProcessToken.
651func OpenCurrentProcessToken() (Token, error) {
652 p, e := GetCurrentProcess()
653 if e != nil {
654 return 0, e
655 }
656 var t Token
657 e = OpenProcessToken(p, TOKEN_QUERY, &t)
658 if e != nil {
659 return 0, e
660 }
661 return t, nil
662}
663
664// GetCurrentProcessToken returns the access token associated with
665// the current process. It is a pseudo token that does not need
666// to be closed.
667func GetCurrentProcessToken() Token {
668 return Token(^uintptr(4 - 1))
669}
670
671// GetCurrentThreadToken return the access token associated with
672// the current thread. It is a pseudo token that does not need
673// to be closed.
674func GetCurrentThreadToken() Token {
675 return Token(^uintptr(5 - 1))
676}
677
678// GetCurrentThreadEffectiveToken returns the effective access token
679// associated with the current thread. It is a pseudo token that does
680// not need to be closed.
681func GetCurrentThreadEffectiveToken() Token {
682 return Token(^uintptr(6 - 1))
683}
684
685// Close releases access to access token.
686func (t Token) Close() error {
687 return CloseHandle(Handle(t))
688}
689
690// getInfo retrieves a specified type of information about an access token.
691func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
692 n := uint32(initSize)
693 for {
694 b := make([]byte, n)
695 e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
696 if e == nil {
697 return unsafe.Pointer(&b[0]), nil
698 }
699 if e != ERROR_INSUFFICIENT_BUFFER {
700 return nil, e
701 }
702 if n <= uint32(len(b)) {
703 return nil, e
704 }
705 }
706}
707
708// GetTokenUser retrieves access token t user account information.
709func (t Token) GetTokenUser() (*Tokenuser, error) {
710 i, e := t.getInfo(TokenUser, 50)
711 if e != nil {
712 return nil, e
713 }
714 return (*Tokenuser)(i), nil
715}
716
717// GetTokenGroups retrieves group accounts associated with access token t.
718func (t Token) GetTokenGroups() (*Tokengroups, error) {
719 i, e := t.getInfo(TokenGroups, 50)
720 if e != nil {
721 return nil, e
722 }
723 return (*Tokengroups)(i), nil
724}
725
726// GetTokenPrimaryGroup retrieves access token t primary group information.
727// A pointer to a SID structure representing a group that will become
728// the primary group of any objects created by a process using this access token.
729func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
730 i, e := t.getInfo(TokenPrimaryGroup, 50)
731 if e != nil {
732 return nil, e
733 }
734 return (*Tokenprimarygroup)(i), nil
735}
736
737// GetUserProfileDirectory retrieves path to the
738// root directory of the access token t user's profile.
739func (t Token) GetUserProfileDirectory() (string, error) {
740 n := uint32(100)
741 for {
742 b := make([]uint16, n)
743 e := GetUserProfileDirectory(t, &b[0], &n)
744 if e == nil {
745 return UTF16ToString(b), nil
746 }
747 if e != ERROR_INSUFFICIENT_BUFFER {
748 return "", e
749 }
750 if n <= uint32(len(b)) {
751 return "", e
752 }
753 }
754}
755
756// IsElevated returns whether the current token is elevated from a UAC perspective.
757func (token Token) IsElevated() bool {
758 var isElevated uint32
759 var outLen uint32
760 err := GetTokenInformation(token, TokenElevation, (*byte)(unsafe.Pointer(&isElevated)), uint32(unsafe.Sizeof(isElevated)), &outLen)
761 if err != nil {
762 return false
763 }
764 return outLen == uint32(unsafe.Sizeof(isElevated)) && isElevated != 0
765}
766
767// GetLinkedToken returns the linked token, which may be an elevated UAC token.
768func (token Token) GetLinkedToken() (Token, error) {
769 var linkedToken Token
770 var outLen uint32
771 err := GetTokenInformation(token, TokenLinkedToken, (*byte)(unsafe.Pointer(&linkedToken)), uint32(unsafe.Sizeof(linkedToken)), &outLen)
772 if err != nil {
773 return Token(0), err
774 }
775 return linkedToken, nil
776}
777
778// GetSystemDirectory retrieves path to current location of the system
779// directory, which is typically, though not always, C:\Windows\System32.
780func GetSystemDirectory() (string, error) {
781 n := uint32(MAX_PATH)
782 for {
783 b := make([]uint16, n)
784 l, e := getSystemDirectory(&b[0], n)
785 if e != nil {
786 return "", e
787 }
788 if l <= n {
789 return UTF16ToString(b[:l]), nil
790 }
791 n = l
792 }
793}
794
795// IsMember reports whether the access token t is a member of the provided SID.
796func (t Token) IsMember(sid *SID) (bool, error) {
797 var b int32
798 if e := checkTokenMembership(t, sid, &b); e != nil {
799 return false, e
800 }
801 return b != 0, nil
802}
803
804const (
805 WTS_CONSOLE_CONNECT = 0x1
806 WTS_CONSOLE_DISCONNECT = 0x2
807 WTS_REMOTE_CONNECT = 0x3
808 WTS_REMOTE_DISCONNECT = 0x4
809 WTS_SESSION_LOGON = 0x5
810 WTS_SESSION_LOGOFF = 0x6
811 WTS_SESSION_LOCK = 0x7
812 WTS_SESSION_UNLOCK = 0x8
813 WTS_SESSION_REMOTE_CONTROL = 0x9
814 WTS_SESSION_CREATE = 0xa
815 WTS_SESSION_TERMINATE = 0xb
816)
817
818const (
819 WTSActive = 0
820 WTSConnected = 1
821 WTSConnectQuery = 2
822 WTSShadow = 3
823 WTSDisconnected = 4
824 WTSIdle = 5
825 WTSListen = 6
826 WTSReset = 7
827 WTSDown = 8
828 WTSInit = 9
829)
830
831type WTSSESSION_NOTIFICATION struct {
832 Size uint32
833 SessionID uint32
834}
835
836type WTS_SESSION_INFO struct {
837 SessionID uint32
838 WindowStationName *uint16
839 State uint32
840}
841
842//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
843//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
844//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory