1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package windows
6
7import (
8	"syscall"
9	"unsafe"
10)
11
12const (
13	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 // Use AllGroups() for iterating.
607}
608
609// AllGroups returns a slice that can be used to iterate over the groups in g.
610func (g *Tokengroups) AllGroups() []SIDAndAttributes {
611	return (*[(1 << 28) - 1]SIDAndAttributes)(unsafe.Pointer(&g.Groups[0]))[:g.GroupCount:g.GroupCount]
612}
613
614type Tokenprivileges struct {
615	PrivilegeCount uint32
616	Privileges     [1]LUIDAndAttributes // Use AllPrivileges() for iterating.
617}
618
619// AllPrivileges returns a slice that can be used to iterate over the privileges in p.
620func (p *Tokenprivileges) AllPrivileges() []LUIDAndAttributes {
621	return (*[(1 << 27) - 1]LUIDAndAttributes)(unsafe.Pointer(&p.Privileges[0]))[:p.PrivilegeCount:p.PrivilegeCount]
622}
623
624type Tokenmandatorylabel struct {
625	Label SIDAndAttributes
626}
627
628func (tml *Tokenmandatorylabel) Size() uint32 {
629	return uint32(unsafe.Sizeof(Tokenmandatorylabel{})) + GetLengthSid(tml.Label.Sid)
630}
631
632// Authorization Functions
633//sys	checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
634//sys	OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
635//sys	OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
636//sys	ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
637//sys	RevertToSelf() (err error) = advapi32.RevertToSelf
638//sys	SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken
639//sys	LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW
640//sys	AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) = advapi32.AdjustTokenPrivileges
641//sys	AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) = advapi32.AdjustTokenGroups
642//sys	GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
643//sys	SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) = advapi32.SetTokenInformation
644//sys	DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
645//sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
646//sys	getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
647//sys	getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetWindowsDirectoryW
648//sys	getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemWindowsDirectoryW
649
650// An access token contains the security information for a logon session.
651// The system creates an access token when a user logs on, and every
652// process executed on behalf of the user has a copy of the token.
653// The token identifies the user, the user's groups, and the user's
654// privileges. The system uses the token to control access to securable
655// objects and to control the ability of the user to perform various
656// system-related operations on the local computer.
657type Token Handle
658
659// OpenCurrentProcessToken opens the access token
660// associated with current process. It is a real
661// token that needs to be closed, unlike
662// GetCurrentProcessToken.
663func OpenCurrentProcessToken() (Token, error) {
664	p, e := GetCurrentProcess()
665	if e != nil {
666		return 0, e
667	}
668	var t Token
669	e = OpenProcessToken(p, TOKEN_QUERY, &t)
670	if e != nil {
671		return 0, e
672	}
673	return t, nil
674}
675
676// GetCurrentProcessToken returns the access token associated with
677// the current process. It is a pseudo token that does not need
678// to be closed.
679func GetCurrentProcessToken() Token {
680	return Token(^uintptr(4 - 1))
681}
682
683// GetCurrentThreadToken return the access token associated with
684// the current thread. It is a pseudo token that does not need
685// to be closed.
686func GetCurrentThreadToken() Token {
687	return Token(^uintptr(5 - 1))
688}
689
690// GetCurrentThreadEffectiveToken returns the effective access token
691// associated with the current thread. It is a pseudo token that does
692// not need to be closed.
693func GetCurrentThreadEffectiveToken() Token {
694	return Token(^uintptr(6 - 1))
695}
696
697// Close releases access to access token.
698func (t Token) Close() error {
699	return CloseHandle(Handle(t))
700}
701
702// getInfo retrieves a specified type of information about an access token.
703func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
704	n := uint32(initSize)
705	for {
706		b := make([]byte, n)
707		e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
708		if e == nil {
709			return unsafe.Pointer(&b[0]), nil
710		}
711		if e != ERROR_INSUFFICIENT_BUFFER {
712			return nil, e
713		}
714		if n <= uint32(len(b)) {
715			return nil, e
716		}
717	}
718}
719
720// GetTokenUser retrieves access token t user account information.
721func (t Token) GetTokenUser() (*Tokenuser, error) {
722	i, e := t.getInfo(TokenUser, 50)
723	if e != nil {
724		return nil, e
725	}
726	return (*Tokenuser)(i), nil
727}
728
729// GetTokenGroups retrieves group accounts associated with access token t.
730func (t Token) GetTokenGroups() (*Tokengroups, error) {
731	i, e := t.getInfo(TokenGroups, 50)
732	if e != nil {
733		return nil, e
734	}
735	return (*Tokengroups)(i), nil
736}
737
738// GetTokenPrimaryGroup retrieves access token t primary group information.
739// A pointer to a SID structure representing a group that will become
740// the primary group of any objects created by a process using this access token.
741func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
742	i, e := t.getInfo(TokenPrimaryGroup, 50)
743	if e != nil {
744		return nil, e
745	}
746	return (*Tokenprimarygroup)(i), nil
747}
748
749// GetUserProfileDirectory retrieves path to the
750// root directory of the access token t user's profile.
751func (t Token) GetUserProfileDirectory() (string, error) {
752	n := uint32(100)
753	for {
754		b := make([]uint16, n)
755		e := GetUserProfileDirectory(t, &b[0], &n)
756		if e == nil {
757			return UTF16ToString(b), nil
758		}
759		if e != ERROR_INSUFFICIENT_BUFFER {
760			return "", e
761		}
762		if n <= uint32(len(b)) {
763			return "", e
764		}
765	}
766}
767
768// IsElevated returns whether the current token is elevated from a UAC perspective.
769func (token Token) IsElevated() bool {
770	var isElevated uint32
771	var outLen uint32
772	err := GetTokenInformation(token, TokenElevation, (*byte)(unsafe.Pointer(&isElevated)), uint32(unsafe.Sizeof(isElevated)), &outLen)
773	if err != nil {
774		return false
775	}
776	return outLen == uint32(unsafe.Sizeof(isElevated)) && isElevated != 0
777}
778
779// GetLinkedToken returns the linked token, which may be an elevated UAC token.
780func (token Token) GetLinkedToken() (Token, error) {
781	var linkedToken Token
782	var outLen uint32
783	err := GetTokenInformation(token, TokenLinkedToken, (*byte)(unsafe.Pointer(&linkedToken)), uint32(unsafe.Sizeof(linkedToken)), &outLen)
784	if err != nil {
785		return Token(0), err
786	}
787	return linkedToken, nil
788}
789
790// GetSystemDirectory retrieves the path to current location of the system
791// directory, which is typically, though not always, `C:\Windows\System32`.
792func GetSystemDirectory() (string, error) {
793	n := uint32(MAX_PATH)
794	for {
795		b := make([]uint16, n)
796		l, e := getSystemDirectory(&b[0], n)
797		if e != nil {
798			return "", e
799		}
800		if l <= n {
801			return UTF16ToString(b[:l]), nil
802		}
803		n = l
804	}
805}
806
807// GetWindowsDirectory retrieves the path to current location of the Windows
808// directory, which is typically, though not always, `C:\Windows`. This may
809// be a private user directory in the case that the application is running
810// under a terminal server.
811func GetWindowsDirectory() (string, error) {
812	n := uint32(MAX_PATH)
813	for {
814		b := make([]uint16, n)
815		l, e := getWindowsDirectory(&b[0], n)
816		if e != nil {
817			return "", e
818		}
819		if l <= n {
820			return UTF16ToString(b[:l]), nil
821		}
822		n = l
823	}
824}
825
826// GetSystemWindowsDirectory retrieves the path to current location of the
827// Windows directory, which is typically, though not always, `C:\Windows`.
828func GetSystemWindowsDirectory() (string, error) {
829	n := uint32(MAX_PATH)
830	for {
831		b := make([]uint16, n)
832		l, e := getSystemWindowsDirectory(&b[0], n)
833		if e != nil {
834			return "", e
835		}
836		if l <= n {
837			return UTF16ToString(b[:l]), nil
838		}
839		n = l
840	}
841}
842
843// IsMember reports whether the access token t is a member of the provided SID.
844func (t Token) IsMember(sid *SID) (bool, error) {
845	var b int32
846	if e := checkTokenMembership(t, sid, &b); e != nil {
847		return false, e
848	}
849	return b != 0, nil
850}
851
852const (
853	WTS_CONSOLE_CONNECT        = 0x1
854	WTS_CONSOLE_DISCONNECT     = 0x2
855	WTS_REMOTE_CONNECT         = 0x3
856	WTS_REMOTE_DISCONNECT      = 0x4
857	WTS_SESSION_LOGON          = 0x5
858	WTS_SESSION_LOGOFF         = 0x6
859	WTS_SESSION_LOCK           = 0x7
860	WTS_SESSION_UNLOCK         = 0x8
861	WTS_SESSION_REMOTE_CONTROL = 0x9
862	WTS_SESSION_CREATE         = 0xa
863	WTS_SESSION_TERMINATE      = 0xb
864)
865
866const (
867	WTSActive       = 0
868	WTSConnected    = 1
869	WTSConnectQuery = 2
870	WTSShadow       = 3
871	WTSDisconnected = 4
872	WTSIdle         = 5
873	WTSListen       = 6
874	WTSReset        = 7
875	WTSDown         = 8
876	WTSInit         = 9
877)
878
879type WTSSESSION_NOTIFICATION struct {
880	Size      uint32
881	SessionID uint32
882}
883
884type WTS_SESSION_INFO struct {
885	SessionID         uint32
886	WindowStationName *uint16
887	State             uint32
888}
889
890//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
891//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
892//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
893