mirror of
https://github.com/golang/sys.git
synced 2026-02-08 19:56:04 +03:00
The svc package exposes svc.SessionChange, but it's impossible to do anything with them without these structures, and without being able to enumerate them prior to events, the events themselves aren't useful, so we add the enumeration functions as well. Change-Id: I14c932dfe97c6712fd4868c1b3a0e3a61a6a562c Reviewed-on: https://go-review.googlesource.com/c/sys/+/176623 Run-TryBot: Jason Donenfeld <Jason@zx2c4.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
762 lines
26 KiB
Go
762 lines
26 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package windows
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
const (
|
|
STANDARD_RIGHTS_REQUIRED = 0xf0000
|
|
STANDARD_RIGHTS_READ = 0x20000
|
|
STANDARD_RIGHTS_WRITE = 0x20000
|
|
STANDARD_RIGHTS_EXECUTE = 0x20000
|
|
STANDARD_RIGHTS_ALL = 0x1F0000
|
|
)
|
|
|
|
const (
|
|
NameUnknown = 0
|
|
NameFullyQualifiedDN = 1
|
|
NameSamCompatible = 2
|
|
NameDisplay = 3
|
|
NameUniqueId = 6
|
|
NameCanonical = 7
|
|
NameUserPrincipal = 8
|
|
NameCanonicalEx = 9
|
|
NameServicePrincipal = 10
|
|
NameDnsDomain = 12
|
|
)
|
|
|
|
// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
|
|
// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
|
|
//sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
|
|
//sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
|
|
|
|
// TranslateAccountName converts a directory service
|
|
// object name from one format to another.
|
|
func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
|
|
u, e := UTF16PtrFromString(username)
|
|
if e != nil {
|
|
return "", e
|
|
}
|
|
n := uint32(50)
|
|
for {
|
|
b := make([]uint16, n)
|
|
e = TranslateName(u, from, to, &b[0], &n)
|
|
if e == nil {
|
|
return UTF16ToString(b[:n]), nil
|
|
}
|
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
|
return "", e
|
|
}
|
|
if n <= uint32(len(b)) {
|
|
return "", e
|
|
}
|
|
}
|
|
}
|
|
|
|
const (
|
|
// do not reorder
|
|
NetSetupUnknownStatus = iota
|
|
NetSetupUnjoined
|
|
NetSetupWorkgroupName
|
|
NetSetupDomainName
|
|
)
|
|
|
|
type UserInfo10 struct {
|
|
Name *uint16
|
|
Comment *uint16
|
|
UsrComment *uint16
|
|
FullName *uint16
|
|
}
|
|
|
|
//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
|
|
//sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
|
|
//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
|
|
|
|
const (
|
|
// do not reorder
|
|
SidTypeUser = 1 + iota
|
|
SidTypeGroup
|
|
SidTypeDomain
|
|
SidTypeAlias
|
|
SidTypeWellKnownGroup
|
|
SidTypeDeletedAccount
|
|
SidTypeInvalid
|
|
SidTypeUnknown
|
|
SidTypeComputer
|
|
SidTypeLabel
|
|
)
|
|
|
|
type SidIdentifierAuthority struct {
|
|
Value [6]byte
|
|
}
|
|
|
|
var (
|
|
SECURITY_NULL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
|
|
SECURITY_WORLD_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
|
|
SECURITY_LOCAL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
|
|
SECURITY_CREATOR_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
|
|
SECURITY_NON_UNIQUE_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
|
|
SECURITY_NT_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
|
|
SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
|
|
)
|
|
|
|
const (
|
|
SECURITY_NULL_RID = 0
|
|
SECURITY_WORLD_RID = 0
|
|
SECURITY_LOCAL_RID = 0
|
|
SECURITY_CREATOR_OWNER_RID = 0
|
|
SECURITY_CREATOR_GROUP_RID = 1
|
|
SECURITY_DIALUP_RID = 1
|
|
SECURITY_NETWORK_RID = 2
|
|
SECURITY_BATCH_RID = 3
|
|
SECURITY_INTERACTIVE_RID = 4
|
|
SECURITY_LOGON_IDS_RID = 5
|
|
SECURITY_SERVICE_RID = 6
|
|
SECURITY_LOCAL_SYSTEM_RID = 18
|
|
SECURITY_BUILTIN_DOMAIN_RID = 32
|
|
SECURITY_PRINCIPAL_SELF_RID = 10
|
|
SECURITY_CREATOR_OWNER_SERVER_RID = 0x2
|
|
SECURITY_CREATOR_GROUP_SERVER_RID = 0x3
|
|
SECURITY_LOGON_IDS_RID_COUNT = 0x3
|
|
SECURITY_ANONYMOUS_LOGON_RID = 0x7
|
|
SECURITY_PROXY_RID = 0x8
|
|
SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
|
|
SECURITY_SERVER_LOGON_RID = SECURITY_ENTERPRISE_CONTROLLERS_RID
|
|
SECURITY_AUTHENTICATED_USER_RID = 0xb
|
|
SECURITY_RESTRICTED_CODE_RID = 0xc
|
|
SECURITY_NT_NON_UNIQUE_RID = 0x15
|
|
)
|
|
|
|
// Predefined domain-relative RIDs for local groups.
|
|
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
|
|
const (
|
|
DOMAIN_ALIAS_RID_ADMINS = 0x220
|
|
DOMAIN_ALIAS_RID_USERS = 0x221
|
|
DOMAIN_ALIAS_RID_GUESTS = 0x222
|
|
DOMAIN_ALIAS_RID_POWER_USERS = 0x223
|
|
DOMAIN_ALIAS_RID_ACCOUNT_OPS = 0x224
|
|
DOMAIN_ALIAS_RID_SYSTEM_OPS = 0x225
|
|
DOMAIN_ALIAS_RID_PRINT_OPS = 0x226
|
|
DOMAIN_ALIAS_RID_BACKUP_OPS = 0x227
|
|
DOMAIN_ALIAS_RID_REPLICATOR = 0x228
|
|
DOMAIN_ALIAS_RID_RAS_SERVERS = 0x229
|
|
DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 0x22a
|
|
DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS = 0x22b
|
|
DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS = 0x22c
|
|
DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
|
|
DOMAIN_ALIAS_RID_MONITORING_USERS = 0x22e
|
|
DOMAIN_ALIAS_RID_LOGGING_USERS = 0x22f
|
|
DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS = 0x230
|
|
DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS = 0x231
|
|
DOMAIN_ALIAS_RID_DCOM_USERS = 0x232
|
|
DOMAIN_ALIAS_RID_IUSERS = 0x238
|
|
DOMAIN_ALIAS_RID_CRYPTO_OPERATORS = 0x239
|
|
DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP = 0x23b
|
|
DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c
|
|
DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP = 0x23d
|
|
DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP = 0x23e
|
|
)
|
|
|
|
//sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
|
|
//sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
|
|
//sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
|
|
//sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
|
|
//sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
|
|
//sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
|
|
//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
|
|
//sys createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) = advapi32.CreateWellKnownSid
|
|
//sys FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
|
|
//sys EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
|
|
|
|
// The security identifier (SID) structure is a variable-length
|
|
// structure used to uniquely identify users or groups.
|
|
type SID struct{}
|
|
|
|
// StringToSid converts a string-format security identifier
|
|
// sid into a valid, functional sid.
|
|
func StringToSid(s string) (*SID, error) {
|
|
var sid *SID
|
|
p, e := UTF16PtrFromString(s)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
e = ConvertStringSidToSid(p, &sid)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
defer LocalFree((Handle)(unsafe.Pointer(sid)))
|
|
return sid.Copy()
|
|
}
|
|
|
|
// LookupSID retrieves a security identifier sid for the account
|
|
// and the name of the domain on which the account was found.
|
|
// System specify target computer to search.
|
|
func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
|
|
if len(account) == 0 {
|
|
return nil, "", 0, syscall.EINVAL
|
|
}
|
|
acc, e := UTF16PtrFromString(account)
|
|
if e != nil {
|
|
return nil, "", 0, e
|
|
}
|
|
var sys *uint16
|
|
if len(system) > 0 {
|
|
sys, e = UTF16PtrFromString(system)
|
|
if e != nil {
|
|
return nil, "", 0, e
|
|
}
|
|
}
|
|
n := uint32(50)
|
|
dn := uint32(50)
|
|
for {
|
|
b := make([]byte, n)
|
|
db := make([]uint16, dn)
|
|
sid = (*SID)(unsafe.Pointer(&b[0]))
|
|
e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
|
|
if e == nil {
|
|
return sid, UTF16ToString(db), accType, nil
|
|
}
|
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
|
return nil, "", 0, e
|
|
}
|
|
if n <= uint32(len(b)) {
|
|
return nil, "", 0, e
|
|
}
|
|
}
|
|
}
|
|
|
|
// String converts sid to a string format
|
|
// suitable for display, storage, or transmission.
|
|
func (sid *SID) String() (string, error) {
|
|
var s *uint16
|
|
e := ConvertSidToStringSid(sid, &s)
|
|
if e != nil {
|
|
return "", e
|
|
}
|
|
defer LocalFree((Handle)(unsafe.Pointer(s)))
|
|
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
|
|
}
|
|
|
|
// Len returns the length, in bytes, of a valid security identifier sid.
|
|
func (sid *SID) Len() int {
|
|
return int(GetLengthSid(sid))
|
|
}
|
|
|
|
// Copy creates a duplicate of security identifier sid.
|
|
func (sid *SID) Copy() (*SID, error) {
|
|
b := make([]byte, sid.Len())
|
|
sid2 := (*SID)(unsafe.Pointer(&b[0]))
|
|
e := CopySid(uint32(len(b)), sid2, sid)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
return sid2, nil
|
|
}
|
|
|
|
// LookupAccount retrieves the name of the account for this sid
|
|
// and the name of the first domain on which this sid is found.
|
|
// System specify target computer to search for.
|
|
func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
|
|
var sys *uint16
|
|
if len(system) > 0 {
|
|
sys, err = UTF16PtrFromString(system)
|
|
if err != nil {
|
|
return "", "", 0, err
|
|
}
|
|
}
|
|
n := uint32(50)
|
|
dn := uint32(50)
|
|
for {
|
|
b := make([]uint16, n)
|
|
db := make([]uint16, dn)
|
|
e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
|
|
if e == nil {
|
|
return UTF16ToString(b), UTF16ToString(db), accType, nil
|
|
}
|
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
|
return "", "", 0, e
|
|
}
|
|
if n <= uint32(len(b)) {
|
|
return "", "", 0, e
|
|
}
|
|
}
|
|
}
|
|
|
|
// Various types of pre-specified sids that can be synthesized at runtime.
|
|
type WELL_KNOWN_SID_TYPE uint32
|
|
|
|
const (
|
|
WinNullSid = 0
|
|
WinWorldSid = 1
|
|
WinLocalSid = 2
|
|
WinCreatorOwnerSid = 3
|
|
WinCreatorGroupSid = 4
|
|
WinCreatorOwnerServerSid = 5
|
|
WinCreatorGroupServerSid = 6
|
|
WinNtAuthoritySid = 7
|
|
WinDialupSid = 8
|
|
WinNetworkSid = 9
|
|
WinBatchSid = 10
|
|
WinInteractiveSid = 11
|
|
WinServiceSid = 12
|
|
WinAnonymousSid = 13
|
|
WinProxySid = 14
|
|
WinEnterpriseControllersSid = 15
|
|
WinSelfSid = 16
|
|
WinAuthenticatedUserSid = 17
|
|
WinRestrictedCodeSid = 18
|
|
WinTerminalServerSid = 19
|
|
WinRemoteLogonIdSid = 20
|
|
WinLogonIdsSid = 21
|
|
WinLocalSystemSid = 22
|
|
WinLocalServiceSid = 23
|
|
WinNetworkServiceSid = 24
|
|
WinBuiltinDomainSid = 25
|
|
WinBuiltinAdministratorsSid = 26
|
|
WinBuiltinUsersSid = 27
|
|
WinBuiltinGuestsSid = 28
|
|
WinBuiltinPowerUsersSid = 29
|
|
WinBuiltinAccountOperatorsSid = 30
|
|
WinBuiltinSystemOperatorsSid = 31
|
|
WinBuiltinPrintOperatorsSid = 32
|
|
WinBuiltinBackupOperatorsSid = 33
|
|
WinBuiltinReplicatorSid = 34
|
|
WinBuiltinPreWindows2000CompatibleAccessSid = 35
|
|
WinBuiltinRemoteDesktopUsersSid = 36
|
|
WinBuiltinNetworkConfigurationOperatorsSid = 37
|
|
WinAccountAdministratorSid = 38
|
|
WinAccountGuestSid = 39
|
|
WinAccountKrbtgtSid = 40
|
|
WinAccountDomainAdminsSid = 41
|
|
WinAccountDomainUsersSid = 42
|
|
WinAccountDomainGuestsSid = 43
|
|
WinAccountComputersSid = 44
|
|
WinAccountControllersSid = 45
|
|
WinAccountCertAdminsSid = 46
|
|
WinAccountSchemaAdminsSid = 47
|
|
WinAccountEnterpriseAdminsSid = 48
|
|
WinAccountPolicyAdminsSid = 49
|
|
WinAccountRasAndIasServersSid = 50
|
|
WinNTLMAuthenticationSid = 51
|
|
WinDigestAuthenticationSid = 52
|
|
WinSChannelAuthenticationSid = 53
|
|
WinThisOrganizationSid = 54
|
|
WinOtherOrganizationSid = 55
|
|
WinBuiltinIncomingForestTrustBuildersSid = 56
|
|
WinBuiltinPerfMonitoringUsersSid = 57
|
|
WinBuiltinPerfLoggingUsersSid = 58
|
|
WinBuiltinAuthorizationAccessSid = 59
|
|
WinBuiltinTerminalServerLicenseServersSid = 60
|
|
WinBuiltinDCOMUsersSid = 61
|
|
WinBuiltinIUsersSid = 62
|
|
WinIUserSid = 63
|
|
WinBuiltinCryptoOperatorsSid = 64
|
|
WinUntrustedLabelSid = 65
|
|
WinLowLabelSid = 66
|
|
WinMediumLabelSid = 67
|
|
WinHighLabelSid = 68
|
|
WinSystemLabelSid = 69
|
|
WinWriteRestrictedCodeSid = 70
|
|
WinCreatorOwnerRightsSid = 71
|
|
WinCacheablePrincipalsGroupSid = 72
|
|
WinNonCacheablePrincipalsGroupSid = 73
|
|
WinEnterpriseReadonlyControllersSid = 74
|
|
WinAccountReadonlyControllersSid = 75
|
|
WinBuiltinEventLogReadersGroup = 76
|
|
WinNewEnterpriseReadonlyControllersSid = 77
|
|
WinBuiltinCertSvcDComAccessGroup = 78
|
|
WinMediumPlusLabelSid = 79
|
|
WinLocalLogonSid = 80
|
|
WinConsoleLogonSid = 81
|
|
WinThisOrganizationCertificateSid = 82
|
|
WinApplicationPackageAuthoritySid = 83
|
|
WinBuiltinAnyPackageSid = 84
|
|
WinCapabilityInternetClientSid = 85
|
|
WinCapabilityInternetClientServerSid = 86
|
|
WinCapabilityPrivateNetworkClientServerSid = 87
|
|
WinCapabilityPicturesLibrarySid = 88
|
|
WinCapabilityVideosLibrarySid = 89
|
|
WinCapabilityMusicLibrarySid = 90
|
|
WinCapabilityDocumentsLibrarySid = 91
|
|
WinCapabilitySharedUserCertificatesSid = 92
|
|
WinCapabilityEnterpriseAuthenticationSid = 93
|
|
WinCapabilityRemovableStorageSid = 94
|
|
WinBuiltinRDSRemoteAccessServersSid = 95
|
|
WinBuiltinRDSEndpointServersSid = 96
|
|
WinBuiltinRDSManagementServersSid = 97
|
|
WinUserModeDriversSid = 98
|
|
WinBuiltinHyperVAdminsSid = 99
|
|
WinAccountCloneableControllersSid = 100
|
|
WinBuiltinAccessControlAssistanceOperatorsSid = 101
|
|
WinBuiltinRemoteManagementUsersSid = 102
|
|
WinAuthenticationAuthorityAssertedSid = 103
|
|
WinAuthenticationServiceAssertedSid = 104
|
|
WinLocalAccountSid = 105
|
|
WinLocalAccountAndAdministratorSid = 106
|
|
WinAccountProtectedUsersSid = 107
|
|
WinCapabilityAppointmentsSid = 108
|
|
WinCapabilityContactsSid = 109
|
|
WinAccountDefaultSystemManagedSid = 110
|
|
WinBuiltinDefaultSystemManagedGroupSid = 111
|
|
WinBuiltinStorageReplicaAdminsSid = 112
|
|
WinAccountKeyAdminsSid = 113
|
|
WinAccountEnterpriseKeyAdminsSid = 114
|
|
WinAuthenticationKeyTrustSid = 115
|
|
WinAuthenticationKeyPropertyMFASid = 116
|
|
WinAuthenticationKeyPropertyAttestationSid = 117
|
|
WinAuthenticationFreshKeyAuthSid = 118
|
|
WinBuiltinDeviceOwnersSid = 119
|
|
)
|
|
|
|
// Creates a sid for a well-known predefined alias, generally using the constants of the form
|
|
// Win*Sid, for the local machine.
|
|
func CreateWellKnownSid(sidType WELL_KNOWN_SID_TYPE) (*SID, error) {
|
|
return CreateWellKnownDomainSid(sidType, nil)
|
|
}
|
|
|
|
// Creates a sid for a well-known predefined alias, generally using the constants of the form
|
|
// Win*Sid, for the domain specified by the domainSid parameter.
|
|
func CreateWellKnownDomainSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID) (*SID, error) {
|
|
n := uint32(50)
|
|
for {
|
|
b := make([]byte, n)
|
|
sid := (*SID)(unsafe.Pointer(&b[0]))
|
|
err := createWellKnownSid(sidType, domainSid, sid, &n)
|
|
if err == nil {
|
|
return sid, nil
|
|
}
|
|
if err != ERROR_INSUFFICIENT_BUFFER {
|
|
return nil, err
|
|
}
|
|
if n <= uint32(len(b)) {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
|
|
const (
|
|
// do not reorder
|
|
TOKEN_ASSIGN_PRIMARY = 1 << iota
|
|
TOKEN_DUPLICATE
|
|
TOKEN_IMPERSONATE
|
|
TOKEN_QUERY
|
|
TOKEN_QUERY_SOURCE
|
|
TOKEN_ADJUST_PRIVILEGES
|
|
TOKEN_ADJUST_GROUPS
|
|
TOKEN_ADJUST_DEFAULT
|
|
TOKEN_ADJUST_SESSIONID
|
|
|
|
TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
|
|
TOKEN_ASSIGN_PRIMARY |
|
|
TOKEN_DUPLICATE |
|
|
TOKEN_IMPERSONATE |
|
|
TOKEN_QUERY |
|
|
TOKEN_QUERY_SOURCE |
|
|
TOKEN_ADJUST_PRIVILEGES |
|
|
TOKEN_ADJUST_GROUPS |
|
|
TOKEN_ADJUST_DEFAULT |
|
|
TOKEN_ADJUST_SESSIONID
|
|
TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
|
|
TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
|
|
TOKEN_ADJUST_PRIVILEGES |
|
|
TOKEN_ADJUST_GROUPS |
|
|
TOKEN_ADJUST_DEFAULT
|
|
TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
|
|
)
|
|
|
|
const (
|
|
// do not reorder
|
|
TokenUser = 1 + iota
|
|
TokenGroups
|
|
TokenPrivileges
|
|
TokenOwner
|
|
TokenPrimaryGroup
|
|
TokenDefaultDacl
|
|
TokenSource
|
|
TokenType
|
|
TokenImpersonationLevel
|
|
TokenStatistics
|
|
TokenRestrictedSids
|
|
TokenSessionId
|
|
TokenGroupsAndPrivileges
|
|
TokenSessionReference
|
|
TokenSandBoxInert
|
|
TokenAuditPolicy
|
|
TokenOrigin
|
|
TokenElevationType
|
|
TokenLinkedToken
|
|
TokenElevation
|
|
TokenHasRestrictions
|
|
TokenAccessInformation
|
|
TokenVirtualizationAllowed
|
|
TokenVirtualizationEnabled
|
|
TokenIntegrityLevel
|
|
TokenUIAccess
|
|
TokenMandatoryPolicy
|
|
TokenLogonSid
|
|
MaxTokenInfoClass
|
|
)
|
|
|
|
// Group attributes inside of Tokengroups.Groups[i].Attributes
|
|
const (
|
|
SE_GROUP_MANDATORY = 0x00000001
|
|
SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002
|
|
SE_GROUP_ENABLED = 0x00000004
|
|
SE_GROUP_OWNER = 0x00000008
|
|
SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010
|
|
SE_GROUP_INTEGRITY = 0x00000020
|
|
SE_GROUP_INTEGRITY_ENABLED = 0x00000040
|
|
SE_GROUP_LOGON_ID = 0xC0000000
|
|
SE_GROUP_RESOURCE = 0x20000000
|
|
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
|
|
)
|
|
|
|
// Privilege attributes
|
|
const (
|
|
SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
|
|
SE_PRIVILEGE_ENABLED = 0x00000002
|
|
SE_PRIVILEGE_REMOVED = 0x00000004
|
|
SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000
|
|
SE_PRIVILEGE_VALID_ATTRIBUTES = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED | SE_PRIVILEGE_USED_FOR_ACCESS
|
|
)
|
|
|
|
// Token types
|
|
const (
|
|
TokenPrimary = 1
|
|
TokenImpersonation = 2
|
|
)
|
|
|
|
// Impersonation levels
|
|
const (
|
|
SecurityAnonymous = 0
|
|
SecurityIdentification = 1
|
|
SecurityImpersonation = 2
|
|
SecurityDelegation = 3
|
|
)
|
|
|
|
type LUID struct {
|
|
LowPart uint32
|
|
HighPart int32
|
|
}
|
|
|
|
type LUIDAndAttributes struct {
|
|
Luid LUID
|
|
Attributes uint32
|
|
}
|
|
|
|
type SIDAndAttributes struct {
|
|
Sid *SID
|
|
Attributes uint32
|
|
}
|
|
|
|
type Tokenuser struct {
|
|
User SIDAndAttributes
|
|
}
|
|
|
|
type Tokenprimarygroup struct {
|
|
PrimaryGroup *SID
|
|
}
|
|
|
|
type Tokengroups struct {
|
|
GroupCount uint32
|
|
Groups [1]SIDAndAttributes
|
|
}
|
|
|
|
type Tokenprivileges struct {
|
|
PrivilegeCount uint32
|
|
Privileges [1]LUIDAndAttributes
|
|
}
|
|
|
|
type Tokenmandatorylabel struct {
|
|
Label SIDAndAttributes
|
|
}
|
|
|
|
func (tml *Tokenmandatorylabel) Size() uint32 {
|
|
return uint32(unsafe.Sizeof(Tokenmandatorylabel{})) + GetLengthSid(tml.Label.Sid)
|
|
}
|
|
|
|
// Authorization Functions
|
|
//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
|
|
//sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
|
|
//sys GetCurrentThreadToken() (token Token) = advapi32.GetCurrentThreadToken
|
|
//sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
|
|
//sys GetCurrentProcessToken() (token Token) = advapi32.GetCurrentProcessToken
|
|
//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
|
|
//sys RevertToSelf() (err error) = advapi32.RevertToSelf
|
|
//sys SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken
|
|
//sys LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW
|
|
//sys AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) = advapi32.AdjustTokenPrivileges
|
|
//sys GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
|
|
//sys SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) = advapi32.SetTokenInformation
|
|
//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
|
|
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
|
//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
|
|
|
|
// An access token contains the security information for a logon session.
|
|
// The system creates an access token when a user logs on, and every
|
|
// process executed on behalf of the user has a copy of the token.
|
|
// The token identifies the user, the user's groups, and the user's
|
|
// privileges. The system uses the token to control access to securable
|
|
// objects and to control the ability of the user to perform various
|
|
// system-related operations on the local computer.
|
|
type Token Handle
|
|
|
|
// OpenCurrentProcessToken opens the access token
|
|
// associated with current process.
|
|
func OpenCurrentProcessToken() (Token, error) {
|
|
p, e := GetCurrentProcess()
|
|
if e != nil {
|
|
return 0, e
|
|
}
|
|
var t Token
|
|
e = OpenProcessToken(p, TOKEN_QUERY, &t)
|
|
if e != nil {
|
|
return 0, e
|
|
}
|
|
return t, nil
|
|
}
|
|
|
|
// Close releases access to access token.
|
|
func (t Token) Close() error {
|
|
return CloseHandle(Handle(t))
|
|
}
|
|
|
|
// getInfo retrieves a specified type of information about an access token.
|
|
func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
|
|
n := uint32(initSize)
|
|
for {
|
|
b := make([]byte, n)
|
|
e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
|
|
if e == nil {
|
|
return unsafe.Pointer(&b[0]), nil
|
|
}
|
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
|
return nil, e
|
|
}
|
|
if n <= uint32(len(b)) {
|
|
return nil, e
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetTokenUser retrieves access token t user account information.
|
|
func (t Token) GetTokenUser() (*Tokenuser, error) {
|
|
i, e := t.getInfo(TokenUser, 50)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
return (*Tokenuser)(i), nil
|
|
}
|
|
|
|
// GetTokenGroups retrieves group accounts associated with access token t.
|
|
func (t Token) GetTokenGroups() (*Tokengroups, error) {
|
|
i, e := t.getInfo(TokenGroups, 50)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
return (*Tokengroups)(i), nil
|
|
}
|
|
|
|
// GetTokenPrimaryGroup retrieves access token t primary group information.
|
|
// A pointer to a SID structure representing a group that will become
|
|
// the primary group of any objects created by a process using this access token.
|
|
func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
|
|
i, e := t.getInfo(TokenPrimaryGroup, 50)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
return (*Tokenprimarygroup)(i), nil
|
|
}
|
|
|
|
// GetUserProfileDirectory retrieves path to the
|
|
// root directory of the access token t user's profile.
|
|
func (t Token) GetUserProfileDirectory() (string, error) {
|
|
n := uint32(100)
|
|
for {
|
|
b := make([]uint16, n)
|
|
e := GetUserProfileDirectory(t, &b[0], &n)
|
|
if e == nil {
|
|
return UTF16ToString(b), nil
|
|
}
|
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
|
return "", e
|
|
}
|
|
if n <= uint32(len(b)) {
|
|
return "", e
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetSystemDirectory retrieves path to current location of the system
|
|
// directory, which is typically, though not always, C:\Windows\System32.
|
|
func GetSystemDirectory() (string, error) {
|
|
n := uint32(MAX_PATH)
|
|
for {
|
|
b := make([]uint16, n)
|
|
l, e := getSystemDirectory(&b[0], n)
|
|
if e != nil {
|
|
return "", e
|
|
}
|
|
if l <= n {
|
|
return UTF16ToString(b[:l]), nil
|
|
}
|
|
n = l
|
|
}
|
|
}
|
|
|
|
// IsMember reports whether the access token t is a member of the provided SID.
|
|
func (t Token) IsMember(sid *SID) (bool, error) {
|
|
var b int32
|
|
if e := checkTokenMembership(t, sid, &b); e != nil {
|
|
return false, e
|
|
}
|
|
return b != 0, nil
|
|
}
|
|
|
|
const (
|
|
WTS_CONSOLE_CONNECT = 0x1
|
|
WTS_CONSOLE_DISCONNECT = 0x2
|
|
WTS_REMOTE_CONNECT = 0x3
|
|
WTS_REMOTE_DISCONNECT = 0x4
|
|
WTS_SESSION_LOGON = 0x5
|
|
WTS_SESSION_LOGOFF = 0x6
|
|
WTS_SESSION_LOCK = 0x7
|
|
WTS_SESSION_UNLOCK = 0x8
|
|
WTS_SESSION_REMOTE_CONTROL = 0x9
|
|
WTS_SESSION_CREATE = 0xa
|
|
WTS_SESSION_TERMINATE = 0xb
|
|
)
|
|
|
|
const (
|
|
WTSActive = 0
|
|
WTSConnected = 1
|
|
WTSConnectQuery = 2
|
|
WTSShadow = 3
|
|
WTSDisconnected = 4
|
|
WTSIdle = 5
|
|
WTSListen = 6
|
|
WTSReset = 7
|
|
WTSDown = 8
|
|
WTSInit = 9
|
|
)
|
|
|
|
type WTSSESSION_NOTIFICATION struct {
|
|
Size uint32
|
|
SessionID uint32
|
|
}
|
|
|
|
type WTS_SESSION_INFO struct {
|
|
SessionID uint32
|
|
WindowStationName *uint16
|
|
State uint32
|
|
}
|
|
|
|
//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
|
|
//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
|
|
//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
|