Path: blob/main/vendor/golang.org/x/sys/windows/security_windows.go
2880 views
// Copyright 2012 The Go Authors. All rights reserved.1// Use of this source code is governed by a BSD-style2// license that can be found in the LICENSE file.34package windows56import (7"syscall"8"unsafe"9)1011const (12NameUnknown = 013NameFullyQualifiedDN = 114NameSamCompatible = 215NameDisplay = 316NameUniqueId = 617NameCanonical = 718NameUserPrincipal = 819NameCanonicalEx = 920NameServicePrincipal = 1021NameDnsDomain = 1222)2324// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.25// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx26//sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW27//sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW2829// TranslateAccountName converts a directory service30// object name from one format to another.31func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {32u, e := UTF16PtrFromString(username)33if e != nil {34return "", e35}36n := uint32(50)37for {38b := make([]uint16, n)39e = TranslateName(u, from, to, &b[0], &n)40if e == nil {41return UTF16ToString(b[:n]), nil42}43if e != ERROR_INSUFFICIENT_BUFFER {44return "", e45}46if n <= uint32(len(b)) {47return "", e48}49}50}5152const (53// do not reorder54NetSetupUnknownStatus = iota55NetSetupUnjoined56NetSetupWorkgroupName57NetSetupDomainName58)5960type UserInfo10 struct {61Name *uint1662Comment *uint1663UsrComment *uint1664FullName *uint1665}6667//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo68//sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation69//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree70//sys NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) = netapi32.NetUserEnum7172const (73// do not reorder74SidTypeUser = 1 + iota75SidTypeGroup76SidTypeDomain77SidTypeAlias78SidTypeWellKnownGroup79SidTypeDeletedAccount80SidTypeInvalid81SidTypeUnknown82SidTypeComputer83SidTypeLabel84)8586type SidIdentifierAuthority struct {87Value [6]byte88}8990var (91SECURITY_NULL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}92SECURITY_WORLD_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}93SECURITY_LOCAL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}94SECURITY_CREATOR_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}95SECURITY_NON_UNIQUE_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}96SECURITY_NT_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}97SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}98)99100const (101SECURITY_NULL_RID = 0102SECURITY_WORLD_RID = 0103SECURITY_LOCAL_RID = 0104SECURITY_CREATOR_OWNER_RID = 0105SECURITY_CREATOR_GROUP_RID = 1106SECURITY_DIALUP_RID = 1107SECURITY_NETWORK_RID = 2108SECURITY_BATCH_RID = 3109SECURITY_INTERACTIVE_RID = 4110SECURITY_LOGON_IDS_RID = 5111SECURITY_SERVICE_RID = 6112SECURITY_LOCAL_SYSTEM_RID = 18113SECURITY_BUILTIN_DOMAIN_RID = 32114SECURITY_PRINCIPAL_SELF_RID = 10115SECURITY_CREATOR_OWNER_SERVER_RID = 0x2116SECURITY_CREATOR_GROUP_SERVER_RID = 0x3117SECURITY_LOGON_IDS_RID_COUNT = 0x3118SECURITY_ANONYMOUS_LOGON_RID = 0x7119SECURITY_PROXY_RID = 0x8120SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9121SECURITY_SERVER_LOGON_RID = SECURITY_ENTERPRISE_CONTROLLERS_RID122SECURITY_AUTHENTICATED_USER_RID = 0xb123SECURITY_RESTRICTED_CODE_RID = 0xc124SECURITY_NT_NON_UNIQUE_RID = 0x15125)126127// Predefined domain-relative RIDs for local groups.128// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx129const (130DOMAIN_ALIAS_RID_ADMINS = 0x220131DOMAIN_ALIAS_RID_USERS = 0x221132DOMAIN_ALIAS_RID_GUESTS = 0x222133DOMAIN_ALIAS_RID_POWER_USERS = 0x223134DOMAIN_ALIAS_RID_ACCOUNT_OPS = 0x224135DOMAIN_ALIAS_RID_SYSTEM_OPS = 0x225136DOMAIN_ALIAS_RID_PRINT_OPS = 0x226137DOMAIN_ALIAS_RID_BACKUP_OPS = 0x227138DOMAIN_ALIAS_RID_REPLICATOR = 0x228139DOMAIN_ALIAS_RID_RAS_SERVERS = 0x229140DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 0x22a141DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS = 0x22b142DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS = 0x22c143DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d144DOMAIN_ALIAS_RID_MONITORING_USERS = 0x22e145DOMAIN_ALIAS_RID_LOGGING_USERS = 0x22f146DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS = 0x230147DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS = 0x231148DOMAIN_ALIAS_RID_DCOM_USERS = 0x232149DOMAIN_ALIAS_RID_IUSERS = 0x238150DOMAIN_ALIAS_RID_CRYPTO_OPERATORS = 0x239151DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP = 0x23b152DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c153DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP = 0x23d154DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP = 0x23e155)156157//sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW158//sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW159//sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW160//sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW161//sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid162//sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid163//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.AllocateAndInitializeSid164//sys createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) = advapi32.CreateWellKnownSid165//sys isWellKnownSid(sid *SID, sidType WELL_KNOWN_SID_TYPE) (isWellKnown bool) = advapi32.IsWellKnownSid166//sys FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid167//sys EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid168//sys getSidIdentifierAuthority(sid *SID) (authority *SidIdentifierAuthority) = advapi32.GetSidIdentifierAuthority169//sys getSidSubAuthorityCount(sid *SID) (count *uint8) = advapi32.GetSidSubAuthorityCount170//sys getSidSubAuthority(sid *SID, index uint32) (subAuthority *uint32) = advapi32.GetSidSubAuthority171//sys isValidSid(sid *SID) (isValid bool) = advapi32.IsValidSid172173// The security identifier (SID) structure is a variable-length174// structure used to uniquely identify users or groups.175type SID struct{}176177// StringToSid converts a string-format security identifier178// SID into a valid, functional SID.179func StringToSid(s string) (*SID, error) {180var sid *SID181p, e := UTF16PtrFromString(s)182if e != nil {183return nil, e184}185e = ConvertStringSidToSid(p, &sid)186if e != nil {187return nil, e188}189defer LocalFree((Handle)(unsafe.Pointer(sid)))190return sid.Copy()191}192193// LookupSID retrieves a security identifier SID for the account194// and the name of the domain on which the account was found.195// System specify target computer to search.196func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {197if len(account) == 0 {198return nil, "", 0, syscall.EINVAL199}200acc, e := UTF16PtrFromString(account)201if e != nil {202return nil, "", 0, e203}204var sys *uint16205if len(system) > 0 {206sys, e = UTF16PtrFromString(system)207if e != nil {208return nil, "", 0, e209}210}211n := uint32(50)212dn := uint32(50)213for {214b := make([]byte, n)215db := make([]uint16, dn)216sid = (*SID)(unsafe.Pointer(&b[0]))217e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)218if e == nil {219return sid, UTF16ToString(db), accType, nil220}221if e != ERROR_INSUFFICIENT_BUFFER {222return nil, "", 0, e223}224if n <= uint32(len(b)) {225return nil, "", 0, e226}227}228}229230// String converts SID to a string format suitable for display, storage, or transmission.231func (sid *SID) String() string {232var s *uint16233e := ConvertSidToStringSid(sid, &s)234if e != nil {235return ""236}237defer LocalFree((Handle)(unsafe.Pointer(s)))238return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:])239}240241// Len returns the length, in bytes, of a valid security identifier SID.242func (sid *SID) Len() int {243return int(GetLengthSid(sid))244}245246// Copy creates a duplicate of security identifier SID.247func (sid *SID) Copy() (*SID, error) {248b := make([]byte, sid.Len())249sid2 := (*SID)(unsafe.Pointer(&b[0]))250e := CopySid(uint32(len(b)), sid2, sid)251if e != nil {252return nil, e253}254return sid2, nil255}256257// IdentifierAuthority returns the identifier authority of the SID.258func (sid *SID) IdentifierAuthority() SidIdentifierAuthority {259return *getSidIdentifierAuthority(sid)260}261262// SubAuthorityCount returns the number of sub-authorities in the SID.263func (sid *SID) SubAuthorityCount() uint8 {264return *getSidSubAuthorityCount(sid)265}266267// SubAuthority returns the sub-authority of the SID as specified by268// the index, which must be less than sid.SubAuthorityCount().269func (sid *SID) SubAuthority(idx uint32) uint32 {270if idx >= uint32(sid.SubAuthorityCount()) {271panic("sub-authority index out of range")272}273return *getSidSubAuthority(sid, idx)274}275276// IsValid returns whether the SID has a valid revision and length.277func (sid *SID) IsValid() bool {278return isValidSid(sid)279}280281// Equals compares two SIDs for equality.282func (sid *SID) Equals(sid2 *SID) bool {283return EqualSid(sid, sid2)284}285286// IsWellKnown determines whether the SID matches the well-known sidType.287func (sid *SID) IsWellKnown(sidType WELL_KNOWN_SID_TYPE) bool {288return isWellKnownSid(sid, sidType)289}290291// LookupAccount retrieves the name of the account for this SID292// and the name of the first domain on which this SID is found.293// System specify target computer to search for.294func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {295var sys *uint16296if len(system) > 0 {297sys, err = UTF16PtrFromString(system)298if err != nil {299return "", "", 0, err300}301}302n := uint32(50)303dn := uint32(50)304for {305b := make([]uint16, n)306db := make([]uint16, dn)307e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)308if e == nil {309return UTF16ToString(b), UTF16ToString(db), accType, nil310}311if e != ERROR_INSUFFICIENT_BUFFER {312return "", "", 0, e313}314if n <= uint32(len(b)) {315return "", "", 0, e316}317}318}319320// Various types of pre-specified SIDs that can be synthesized and compared at runtime.321type WELL_KNOWN_SID_TYPE uint32322323const (324WinNullSid = 0325WinWorldSid = 1326WinLocalSid = 2327WinCreatorOwnerSid = 3328WinCreatorGroupSid = 4329WinCreatorOwnerServerSid = 5330WinCreatorGroupServerSid = 6331WinNtAuthoritySid = 7332WinDialupSid = 8333WinNetworkSid = 9334WinBatchSid = 10335WinInteractiveSid = 11336WinServiceSid = 12337WinAnonymousSid = 13338WinProxySid = 14339WinEnterpriseControllersSid = 15340WinSelfSid = 16341WinAuthenticatedUserSid = 17342WinRestrictedCodeSid = 18343WinTerminalServerSid = 19344WinRemoteLogonIdSid = 20345WinLogonIdsSid = 21346WinLocalSystemSid = 22347WinLocalServiceSid = 23348WinNetworkServiceSid = 24349WinBuiltinDomainSid = 25350WinBuiltinAdministratorsSid = 26351WinBuiltinUsersSid = 27352WinBuiltinGuestsSid = 28353WinBuiltinPowerUsersSid = 29354WinBuiltinAccountOperatorsSid = 30355WinBuiltinSystemOperatorsSid = 31356WinBuiltinPrintOperatorsSid = 32357WinBuiltinBackupOperatorsSid = 33358WinBuiltinReplicatorSid = 34359WinBuiltinPreWindows2000CompatibleAccessSid = 35360WinBuiltinRemoteDesktopUsersSid = 36361WinBuiltinNetworkConfigurationOperatorsSid = 37362WinAccountAdministratorSid = 38363WinAccountGuestSid = 39364WinAccountKrbtgtSid = 40365WinAccountDomainAdminsSid = 41366WinAccountDomainUsersSid = 42367WinAccountDomainGuestsSid = 43368WinAccountComputersSid = 44369WinAccountControllersSid = 45370WinAccountCertAdminsSid = 46371WinAccountSchemaAdminsSid = 47372WinAccountEnterpriseAdminsSid = 48373WinAccountPolicyAdminsSid = 49374WinAccountRasAndIasServersSid = 50375WinNTLMAuthenticationSid = 51376WinDigestAuthenticationSid = 52377WinSChannelAuthenticationSid = 53378WinThisOrganizationSid = 54379WinOtherOrganizationSid = 55380WinBuiltinIncomingForestTrustBuildersSid = 56381WinBuiltinPerfMonitoringUsersSid = 57382WinBuiltinPerfLoggingUsersSid = 58383WinBuiltinAuthorizationAccessSid = 59384WinBuiltinTerminalServerLicenseServersSid = 60385WinBuiltinDCOMUsersSid = 61386WinBuiltinIUsersSid = 62387WinIUserSid = 63388WinBuiltinCryptoOperatorsSid = 64389WinUntrustedLabelSid = 65390WinLowLabelSid = 66391WinMediumLabelSid = 67392WinHighLabelSid = 68393WinSystemLabelSid = 69394WinWriteRestrictedCodeSid = 70395WinCreatorOwnerRightsSid = 71396WinCacheablePrincipalsGroupSid = 72397WinNonCacheablePrincipalsGroupSid = 73398WinEnterpriseReadonlyControllersSid = 74399WinAccountReadonlyControllersSid = 75400WinBuiltinEventLogReadersGroup = 76401WinNewEnterpriseReadonlyControllersSid = 77402WinBuiltinCertSvcDComAccessGroup = 78403WinMediumPlusLabelSid = 79404WinLocalLogonSid = 80405WinConsoleLogonSid = 81406WinThisOrganizationCertificateSid = 82407WinApplicationPackageAuthoritySid = 83408WinBuiltinAnyPackageSid = 84409WinCapabilityInternetClientSid = 85410WinCapabilityInternetClientServerSid = 86411WinCapabilityPrivateNetworkClientServerSid = 87412WinCapabilityPicturesLibrarySid = 88413WinCapabilityVideosLibrarySid = 89414WinCapabilityMusicLibrarySid = 90415WinCapabilityDocumentsLibrarySid = 91416WinCapabilitySharedUserCertificatesSid = 92417WinCapabilityEnterpriseAuthenticationSid = 93418WinCapabilityRemovableStorageSid = 94419WinBuiltinRDSRemoteAccessServersSid = 95420WinBuiltinRDSEndpointServersSid = 96421WinBuiltinRDSManagementServersSid = 97422WinUserModeDriversSid = 98423WinBuiltinHyperVAdminsSid = 99424WinAccountCloneableControllersSid = 100425WinBuiltinAccessControlAssistanceOperatorsSid = 101426WinBuiltinRemoteManagementUsersSid = 102427WinAuthenticationAuthorityAssertedSid = 103428WinAuthenticationServiceAssertedSid = 104429WinLocalAccountSid = 105430WinLocalAccountAndAdministratorSid = 106431WinAccountProtectedUsersSid = 107432WinCapabilityAppointmentsSid = 108433WinCapabilityContactsSid = 109434WinAccountDefaultSystemManagedSid = 110435WinBuiltinDefaultSystemManagedGroupSid = 111436WinBuiltinStorageReplicaAdminsSid = 112437WinAccountKeyAdminsSid = 113438WinAccountEnterpriseKeyAdminsSid = 114439WinAuthenticationKeyTrustSid = 115440WinAuthenticationKeyPropertyMFASid = 116441WinAuthenticationKeyPropertyAttestationSid = 117442WinAuthenticationFreshKeyAuthSid = 118443WinBuiltinDeviceOwnersSid = 119444)445446// Creates a SID for a well-known predefined alias, generally using the constants of the form447// Win*Sid, for the local machine.448func CreateWellKnownSid(sidType WELL_KNOWN_SID_TYPE) (*SID, error) {449return CreateWellKnownDomainSid(sidType, nil)450}451452// Creates a SID for a well-known predefined alias, generally using the constants of the form453// Win*Sid, for the domain specified by the domainSid parameter.454func CreateWellKnownDomainSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID) (*SID, error) {455n := uint32(50)456for {457b := make([]byte, n)458sid := (*SID)(unsafe.Pointer(&b[0]))459err := createWellKnownSid(sidType, domainSid, sid, &n)460if err == nil {461return sid, nil462}463if err != ERROR_INSUFFICIENT_BUFFER {464return nil, err465}466if n <= uint32(len(b)) {467return nil, err468}469}470}471472const (473// do not reorder474TOKEN_ASSIGN_PRIMARY = 1 << iota475TOKEN_DUPLICATE476TOKEN_IMPERSONATE477TOKEN_QUERY478TOKEN_QUERY_SOURCE479TOKEN_ADJUST_PRIVILEGES480TOKEN_ADJUST_GROUPS481TOKEN_ADJUST_DEFAULT482TOKEN_ADJUST_SESSIONID483484TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |485TOKEN_ASSIGN_PRIMARY |486TOKEN_DUPLICATE |487TOKEN_IMPERSONATE |488TOKEN_QUERY |489TOKEN_QUERY_SOURCE |490TOKEN_ADJUST_PRIVILEGES |491TOKEN_ADJUST_GROUPS |492TOKEN_ADJUST_DEFAULT |493TOKEN_ADJUST_SESSIONID494TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY495TOKEN_WRITE = STANDARD_RIGHTS_WRITE |496TOKEN_ADJUST_PRIVILEGES |497TOKEN_ADJUST_GROUPS |498TOKEN_ADJUST_DEFAULT499TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE500)501502const (503// do not reorder504TokenUser = 1 + iota505TokenGroups506TokenPrivileges507TokenOwner508TokenPrimaryGroup509TokenDefaultDacl510TokenSource511TokenType512TokenImpersonationLevel513TokenStatistics514TokenRestrictedSids515TokenSessionId516TokenGroupsAndPrivileges517TokenSessionReference518TokenSandBoxInert519TokenAuditPolicy520TokenOrigin521TokenElevationType522TokenLinkedToken523TokenElevation524TokenHasRestrictions525TokenAccessInformation526TokenVirtualizationAllowed527TokenVirtualizationEnabled528TokenIntegrityLevel529TokenUIAccess530TokenMandatoryPolicy531TokenLogonSid532MaxTokenInfoClass533)534535// Group attributes inside of Tokengroups.Groups[i].Attributes536const (537SE_GROUP_MANDATORY = 0x00000001538SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002539SE_GROUP_ENABLED = 0x00000004540SE_GROUP_OWNER = 0x00000008541SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010542SE_GROUP_INTEGRITY = 0x00000020543SE_GROUP_INTEGRITY_ENABLED = 0x00000040544SE_GROUP_LOGON_ID = 0xC0000000545SE_GROUP_RESOURCE = 0x20000000546SE_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_ENABLED547)548549// Privilege attributes550const (551SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001552SE_PRIVILEGE_ENABLED = 0x00000002553SE_PRIVILEGE_REMOVED = 0x00000004554SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000555SE_PRIVILEGE_VALID_ATTRIBUTES = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED | SE_PRIVILEGE_USED_FOR_ACCESS556)557558// Token types559const (560TokenPrimary = 1561TokenImpersonation = 2562)563564// Impersonation levels565const (566SecurityAnonymous = 0567SecurityIdentification = 1568SecurityImpersonation = 2569SecurityDelegation = 3570)571572type LUID struct {573LowPart uint32574HighPart int32575}576577type LUIDAndAttributes struct {578Luid LUID579Attributes uint32580}581582type SIDAndAttributes struct {583Sid *SID584Attributes uint32585}586587type Tokenuser struct {588User SIDAndAttributes589}590591type Tokenprimarygroup struct {592PrimaryGroup *SID593}594595type Tokengroups struct {596GroupCount uint32597Groups [1]SIDAndAttributes // Use AllGroups() for iterating.598}599600// AllGroups returns a slice that can be used to iterate over the groups in g.601func (g *Tokengroups) AllGroups() []SIDAndAttributes {602return (*[(1 << 28) - 1]SIDAndAttributes)(unsafe.Pointer(&g.Groups[0]))[:g.GroupCount:g.GroupCount]603}604605type Tokenprivileges struct {606PrivilegeCount uint32607Privileges [1]LUIDAndAttributes // Use AllPrivileges() for iterating.608}609610// AllPrivileges returns a slice that can be used to iterate over the privileges in p.611func (p *Tokenprivileges) AllPrivileges() []LUIDAndAttributes {612return (*[(1 << 27) - 1]LUIDAndAttributes)(unsafe.Pointer(&p.Privileges[0]))[:p.PrivilegeCount:p.PrivilegeCount]613}614615type Tokenmandatorylabel struct {616Label SIDAndAttributes617}618619func (tml *Tokenmandatorylabel) Size() uint32 {620return uint32(unsafe.Sizeof(Tokenmandatorylabel{})) + GetLengthSid(tml.Label.Sid)621}622623// Authorization Functions624//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership625//sys isTokenRestricted(tokenHandle Token) (ret bool, err error) [!failretval] = advapi32.IsTokenRestricted626//sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken627//sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken628//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf629//sys RevertToSelf() (err error) = advapi32.RevertToSelf630//sys SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken631//sys LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW632//sys AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) = advapi32.AdjustTokenPrivileges633//sys AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) = advapi32.AdjustTokenGroups634//sys GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation635//sys SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) = advapi32.SetTokenInformation636//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx637//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW638//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW639//sys getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetWindowsDirectoryW640//sys getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemWindowsDirectoryW641642// An access token contains the security information for a logon session.643// The system creates an access token when a user logs on, and every644// process executed on behalf of the user has a copy of the token.645// The token identifies the user, the user's groups, and the user's646// privileges. The system uses the token to control access to securable647// objects and to control the ability of the user to perform various648// system-related operations on the local computer.649type Token Handle650651// OpenCurrentProcessToken opens an access token associated with current652// process with TOKEN_QUERY access. It is a real token that needs to be closed.653//654// Deprecated: Explicitly call OpenProcessToken(CurrentProcess(), ...)655// with the desired access instead, or use GetCurrentProcessToken for a656// TOKEN_QUERY token.657func OpenCurrentProcessToken() (Token, error) {658var token Token659err := OpenProcessToken(CurrentProcess(), TOKEN_QUERY, &token)660return token, err661}662663// GetCurrentProcessToken returns the access token associated with664// the current process. It is a pseudo token that does not need665// to be closed.666func GetCurrentProcessToken() Token {667return Token(^uintptr(4 - 1))668}669670// GetCurrentThreadToken return the access token associated with671// the current thread. It is a pseudo token that does not need672// to be closed.673func GetCurrentThreadToken() Token {674return Token(^uintptr(5 - 1))675}676677// GetCurrentThreadEffectiveToken returns the effective access token678// associated with the current thread. It is a pseudo token that does679// not need to be closed.680func GetCurrentThreadEffectiveToken() Token {681return Token(^uintptr(6 - 1))682}683684// Close releases access to access token.685func (t Token) Close() error {686return CloseHandle(Handle(t))687}688689// getInfo retrieves a specified type of information about an access token.690func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {691n := uint32(initSize)692for {693b := make([]byte, n)694e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)695if e == nil {696return unsafe.Pointer(&b[0]), nil697}698if e != ERROR_INSUFFICIENT_BUFFER {699return nil, e700}701if n <= uint32(len(b)) {702return nil, e703}704}705}706707// GetTokenUser retrieves access token t user account information.708func (t Token) GetTokenUser() (*Tokenuser, error) {709i, e := t.getInfo(TokenUser, 50)710if e != nil {711return nil, e712}713return (*Tokenuser)(i), nil714}715716// GetTokenGroups retrieves group accounts associated with access token t.717func (t Token) GetTokenGroups() (*Tokengroups, error) {718i, e := t.getInfo(TokenGroups, 50)719if e != nil {720return nil, e721}722return (*Tokengroups)(i), nil723}724725// GetTokenPrimaryGroup retrieves access token t primary group information.726// A pointer to a SID structure representing a group that will become727// the primary group of any objects created by a process using this access token.728func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {729i, e := t.getInfo(TokenPrimaryGroup, 50)730if e != nil {731return nil, e732}733return (*Tokenprimarygroup)(i), nil734}735736// GetUserProfileDirectory retrieves path to the737// root directory of the access token t user's profile.738func (t Token) GetUserProfileDirectory() (string, error) {739n := uint32(100)740for {741b := make([]uint16, n)742e := GetUserProfileDirectory(t, &b[0], &n)743if e == nil {744return UTF16ToString(b), nil745}746if e != ERROR_INSUFFICIENT_BUFFER {747return "", e748}749if n <= uint32(len(b)) {750return "", e751}752}753}754755// IsElevated returns whether the current token is elevated from a UAC perspective.756func (token Token) IsElevated() bool {757var isElevated uint32758var outLen uint32759err := GetTokenInformation(token, TokenElevation, (*byte)(unsafe.Pointer(&isElevated)), uint32(unsafe.Sizeof(isElevated)), &outLen)760if err != nil {761return false762}763return outLen == uint32(unsafe.Sizeof(isElevated)) && isElevated != 0764}765766// GetLinkedToken returns the linked token, which may be an elevated UAC token.767func (token Token) GetLinkedToken() (Token, error) {768var linkedToken Token769var outLen uint32770err := GetTokenInformation(token, TokenLinkedToken, (*byte)(unsafe.Pointer(&linkedToken)), uint32(unsafe.Sizeof(linkedToken)), &outLen)771if err != nil {772return Token(0), err773}774return linkedToken, nil775}776777// GetSystemDirectory retrieves the path to current location of the system778// directory, which is typically, though not always, `C:\Windows\System32`.779func GetSystemDirectory() (string, error) {780n := uint32(MAX_PATH)781for {782b := make([]uint16, n)783l, e := getSystemDirectory(&b[0], n)784if e != nil {785return "", e786}787if l <= n {788return UTF16ToString(b[:l]), nil789}790n = l791}792}793794// GetWindowsDirectory retrieves the path to current location of the Windows795// directory, which is typically, though not always, `C:\Windows`. This may796// be a private user directory in the case that the application is running797// under a terminal server.798func GetWindowsDirectory() (string, error) {799n := uint32(MAX_PATH)800for {801b := make([]uint16, n)802l, e := getWindowsDirectory(&b[0], n)803if e != nil {804return "", e805}806if l <= n {807return UTF16ToString(b[:l]), nil808}809n = l810}811}812813// GetSystemWindowsDirectory retrieves the path to current location of the814// Windows directory, which is typically, though not always, `C:\Windows`.815func GetSystemWindowsDirectory() (string, error) {816n := uint32(MAX_PATH)817for {818b := make([]uint16, n)819l, e := getSystemWindowsDirectory(&b[0], n)820if e != nil {821return "", e822}823if l <= n {824return UTF16ToString(b[:l]), nil825}826n = l827}828}829830// IsMember reports whether the access token t is a member of the provided SID.831func (t Token) IsMember(sid *SID) (bool, error) {832var b int32833if e := checkTokenMembership(t, sid, &b); e != nil {834return false, e835}836return b != 0, nil837}838839// IsRestricted reports whether the access token t is a restricted token.840func (t Token) IsRestricted() (isRestricted bool, err error) {841isRestricted, err = isTokenRestricted(t)842if !isRestricted && err == syscall.EINVAL {843// If err is EINVAL, this returned ERROR_SUCCESS indicating a non-restricted token.844err = nil845}846return847}848849const (850WTS_CONSOLE_CONNECT = 0x1851WTS_CONSOLE_DISCONNECT = 0x2852WTS_REMOTE_CONNECT = 0x3853WTS_REMOTE_DISCONNECT = 0x4854WTS_SESSION_LOGON = 0x5855WTS_SESSION_LOGOFF = 0x6856WTS_SESSION_LOCK = 0x7857WTS_SESSION_UNLOCK = 0x8858WTS_SESSION_REMOTE_CONTROL = 0x9859WTS_SESSION_CREATE = 0xa860WTS_SESSION_TERMINATE = 0xb861)862863const (864WTSActive = 0865WTSConnected = 1866WTSConnectQuery = 2867WTSShadow = 3868WTSDisconnected = 4869WTSIdle = 5870WTSListen = 6871WTSReset = 7872WTSDown = 8873WTSInit = 9874)875876type WTSSESSION_NOTIFICATION struct {877Size uint32878SessionID uint32879}880881type WTS_SESSION_INFO struct {882SessionID uint32883WindowStationName *uint16884State uint32885}886887//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken888//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW889//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory890//sys WTSGetActiveConsoleSessionId() (sessionID uint32)891892type ACL struct {893aclRevision byte894sbz1 byte895aclSize uint16896AceCount uint16897sbz2 uint16898}899900type SECURITY_DESCRIPTOR struct {901revision byte902sbz1 byte903control SECURITY_DESCRIPTOR_CONTROL904owner *SID905group *SID906sacl *ACL907dacl *ACL908}909910type SECURITY_QUALITY_OF_SERVICE struct {911Length uint32912ImpersonationLevel uint32913ContextTrackingMode byte914EffectiveOnly byte915}916917// Constants for the ContextTrackingMode field of SECURITY_QUALITY_OF_SERVICE.918const (919SECURITY_STATIC_TRACKING = 0920SECURITY_DYNAMIC_TRACKING = 1921)922923type SecurityAttributes struct {924Length uint32925SecurityDescriptor *SECURITY_DESCRIPTOR926InheritHandle uint32927}928929type SE_OBJECT_TYPE uint32930931// Constants for type SE_OBJECT_TYPE932const (933SE_UNKNOWN_OBJECT_TYPE = 0934SE_FILE_OBJECT = 1935SE_SERVICE = 2936SE_PRINTER = 3937SE_REGISTRY_KEY = 4938SE_LMSHARE = 5939SE_KERNEL_OBJECT = 6940SE_WINDOW_OBJECT = 7941SE_DS_OBJECT = 8942SE_DS_OBJECT_ALL = 9943SE_PROVIDER_DEFINED_OBJECT = 10944SE_WMIGUID_OBJECT = 11945SE_REGISTRY_WOW64_32KEY = 12946SE_REGISTRY_WOW64_64KEY = 13947)948949type SECURITY_INFORMATION uint32950951// Constants for type SECURITY_INFORMATION952const (953OWNER_SECURITY_INFORMATION = 0x00000001954GROUP_SECURITY_INFORMATION = 0x00000002955DACL_SECURITY_INFORMATION = 0x00000004956SACL_SECURITY_INFORMATION = 0x00000008957LABEL_SECURITY_INFORMATION = 0x00000010958ATTRIBUTE_SECURITY_INFORMATION = 0x00000020959SCOPE_SECURITY_INFORMATION = 0x00000040960BACKUP_SECURITY_INFORMATION = 0x00010000961PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000962PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000963UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000964UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000965)966967type SECURITY_DESCRIPTOR_CONTROL uint16968969// Constants for type SECURITY_DESCRIPTOR_CONTROL970const (971SE_OWNER_DEFAULTED = 0x0001972SE_GROUP_DEFAULTED = 0x0002973SE_DACL_PRESENT = 0x0004974SE_DACL_DEFAULTED = 0x0008975SE_SACL_PRESENT = 0x0010976SE_SACL_DEFAULTED = 0x0020977SE_DACL_AUTO_INHERIT_REQ = 0x0100978SE_SACL_AUTO_INHERIT_REQ = 0x0200979SE_DACL_AUTO_INHERITED = 0x0400980SE_SACL_AUTO_INHERITED = 0x0800981SE_DACL_PROTECTED = 0x1000982SE_SACL_PROTECTED = 0x2000983SE_RM_CONTROL_VALID = 0x4000984SE_SELF_RELATIVE = 0x8000985)986987type ACCESS_MASK uint32988989// Constants for type ACCESS_MASK990const (991DELETE = 0x00010000992READ_CONTROL = 0x00020000993WRITE_DAC = 0x00040000994WRITE_OWNER = 0x00080000995SYNCHRONIZE = 0x00100000996STANDARD_RIGHTS_REQUIRED = 0x000F0000997STANDARD_RIGHTS_READ = READ_CONTROL998STANDARD_RIGHTS_WRITE = READ_CONTROL999STANDARD_RIGHTS_EXECUTE = READ_CONTROL1000STANDARD_RIGHTS_ALL = 0x001F00001001SPECIFIC_RIGHTS_ALL = 0x0000FFFF1002ACCESS_SYSTEM_SECURITY = 0x010000001003MAXIMUM_ALLOWED = 0x020000001004GENERIC_READ = 0x800000001005GENERIC_WRITE = 0x400000001006GENERIC_EXECUTE = 0x200000001007GENERIC_ALL = 0x100000001008)10091010type ACCESS_MODE uint3210111012// Constants for type ACCESS_MODE1013const (1014NOT_USED_ACCESS = 01015GRANT_ACCESS = 11016SET_ACCESS = 21017DENY_ACCESS = 31018REVOKE_ACCESS = 41019SET_AUDIT_SUCCESS = 51020SET_AUDIT_FAILURE = 61021)10221023// Constants for AceFlags and Inheritance fields1024const (1025NO_INHERITANCE = 0x01026SUB_OBJECTS_ONLY_INHERIT = 0x11027SUB_CONTAINERS_ONLY_INHERIT = 0x21028SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x31029INHERIT_NO_PROPAGATE = 0x41030INHERIT_ONLY = 0x81031INHERITED_ACCESS_ENTRY = 0x101032INHERITED_PARENT = 0x100000001033INHERITED_GRANDPARENT = 0x200000001034OBJECT_INHERIT_ACE = 0x11035CONTAINER_INHERIT_ACE = 0x21036NO_PROPAGATE_INHERIT_ACE = 0x41037INHERIT_ONLY_ACE = 0x81038INHERITED_ACE = 0x101039VALID_INHERIT_FLAGS = 0x1F1040)10411042type MULTIPLE_TRUSTEE_OPERATION uint3210431044// Constants for MULTIPLE_TRUSTEE_OPERATION1045const (1046NO_MULTIPLE_TRUSTEE = 01047TRUSTEE_IS_IMPERSONATE = 11048)10491050type TRUSTEE_FORM uint3210511052// Constants for TRUSTEE_FORM1053const (1054TRUSTEE_IS_SID = 01055TRUSTEE_IS_NAME = 11056TRUSTEE_BAD_FORM = 21057TRUSTEE_IS_OBJECTS_AND_SID = 31058TRUSTEE_IS_OBJECTS_AND_NAME = 41059)10601061type TRUSTEE_TYPE uint3210621063// Constants for TRUSTEE_TYPE1064const (1065TRUSTEE_IS_UNKNOWN = 01066TRUSTEE_IS_USER = 11067TRUSTEE_IS_GROUP = 21068TRUSTEE_IS_DOMAIN = 31069TRUSTEE_IS_ALIAS = 41070TRUSTEE_IS_WELL_KNOWN_GROUP = 51071TRUSTEE_IS_DELETED = 61072TRUSTEE_IS_INVALID = 71073TRUSTEE_IS_COMPUTER = 81074)10751076// Constants for ObjectsPresent field1077const (1078ACE_OBJECT_TYPE_PRESENT = 0x11079ACE_INHERITED_OBJECT_TYPE_PRESENT = 0x21080)10811082type EXPLICIT_ACCESS struct {1083AccessPermissions ACCESS_MASK1084AccessMode ACCESS_MODE1085Inheritance uint321086Trustee TRUSTEE1087}10881089// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header1090type ACE_HEADER struct {1091AceType uint81092AceFlags uint81093AceSize uint161094}10951096// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-access_allowed_ace1097type ACCESS_ALLOWED_ACE struct {1098Header ACE_HEADER1099Mask ACCESS_MASK1100SidStart uint321101}11021103const (1104// Constants for AceType1105// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header1106ACCESS_ALLOWED_ACE_TYPE = 01107ACCESS_DENIED_ACE_TYPE = 11108)11091110// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions.1111type TrusteeValue uintptr11121113func TrusteeValueFromString(str string) TrusteeValue {1114return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str)))1115}1116func TrusteeValueFromSID(sid *SID) TrusteeValue {1117return TrusteeValue(unsafe.Pointer(sid))1118}1119func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue {1120return TrusteeValue(unsafe.Pointer(objectsAndSid))1121}1122func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue {1123return TrusteeValue(unsafe.Pointer(objectsAndName))1124}11251126type TRUSTEE struct {1127MultipleTrustee *TRUSTEE1128MultipleTrusteeOperation MULTIPLE_TRUSTEE_OPERATION1129TrusteeForm TRUSTEE_FORM1130TrusteeType TRUSTEE_TYPE1131TrusteeValue TrusteeValue1132}11331134type OBJECTS_AND_SID struct {1135ObjectsPresent uint321136ObjectTypeGuid GUID1137InheritedObjectTypeGuid GUID1138Sid *SID1139}11401141type OBJECTS_AND_NAME struct {1142ObjectsPresent uint321143ObjectType SE_OBJECT_TYPE1144ObjectTypeName *uint161145InheritedObjectTypeName *uint161146Name *uint161147}11481149//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.GetSecurityInfo1150//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetSecurityInfo1151//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.GetNamedSecurityInfoW1152//sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW1153//sys SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) = advapi32.SetKernelObjectSecurity11541155//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.BuildSecurityDescriptorW1156//sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor11571158//sys getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) = advapi32.GetSecurityDescriptorControl1159//sys getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorDacl1160//sys getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorSacl1161//sys getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner1162//sys getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorGroup1163//sys getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) = advapi32.GetSecurityDescriptorLength1164//sys getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) [failretval!=0] = advapi32.GetSecurityDescriptorRMControl1165//sys isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) = advapi32.IsValidSecurityDescriptor11661167//sys setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) = advapi32.SetSecurityDescriptorControl1168//sys setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl1169//sys setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl1170//sys setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) = advapi32.SetSecurityDescriptorOwner1171//sys setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) = advapi32.SetSecurityDescriptorGroup1172//sys setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) = advapi32.SetSecurityDescriptorRMControl11731174//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW1175//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW11761177//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.MakeAbsoluteSD1178//sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD11791180//sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW1181//sys GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (err error) = advapi32.GetAce11821183// Control returns the security descriptor control bits.1184func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) {1185err = getSecurityDescriptorControl(sd, &control, &revision)1186return1187}11881189// SetControl sets the security descriptor control bits.1190func (sd *SECURITY_DESCRIPTOR) SetControl(controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) error {1191return setSecurityDescriptorControl(sd, controlBitsOfInterest, controlBitsToSet)1192}11931194// RMControl returns the security descriptor resource manager control bits.1195func (sd *SECURITY_DESCRIPTOR) RMControl() (control uint8, err error) {1196err = getSecurityDescriptorRMControl(sd, &control)1197return1198}11991200// SetRMControl sets the security descriptor resource manager control bits.1201func (sd *SECURITY_DESCRIPTOR) SetRMControl(rmControl uint8) {1202setSecurityDescriptorRMControl(sd, &rmControl)1203}12041205// DACL returns the security descriptor DACL and whether it was defaulted. The dacl return value may be nil1206// if a DACL exists but is an "empty DACL", meaning fully permissive. If the DACL does not exist, err returns1207// ERROR_OBJECT_NOT_FOUND.1208func (sd *SECURITY_DESCRIPTOR) DACL() (dacl *ACL, defaulted bool, err error) {1209var present bool1210err = getSecurityDescriptorDacl(sd, &present, &dacl, &defaulted)1211if !present {1212err = ERROR_OBJECT_NOT_FOUND1213}1214return1215}12161217// SetDACL sets the absolute security descriptor DACL.1218func (absoluteSD *SECURITY_DESCRIPTOR) SetDACL(dacl *ACL, present, defaulted bool) error {1219return setSecurityDescriptorDacl(absoluteSD, present, dacl, defaulted)1220}12211222// SACL returns the security descriptor SACL and whether it was defaulted. The sacl return value may be nil1223// if a SACL exists but is an "empty SACL", meaning fully permissive. If the SACL does not exist, err returns1224// ERROR_OBJECT_NOT_FOUND.1225func (sd *SECURITY_DESCRIPTOR) SACL() (sacl *ACL, defaulted bool, err error) {1226var present bool1227err = getSecurityDescriptorSacl(sd, &present, &sacl, &defaulted)1228if !present {1229err = ERROR_OBJECT_NOT_FOUND1230}1231return1232}12331234// SetSACL sets the absolute security descriptor SACL.1235func (absoluteSD *SECURITY_DESCRIPTOR) SetSACL(sacl *ACL, present, defaulted bool) error {1236return setSecurityDescriptorSacl(absoluteSD, present, sacl, defaulted)1237}12381239// Owner returns the security descriptor owner and whether it was defaulted.1240func (sd *SECURITY_DESCRIPTOR) Owner() (owner *SID, defaulted bool, err error) {1241err = getSecurityDescriptorOwner(sd, &owner, &defaulted)1242return1243}12441245// SetOwner sets the absolute security descriptor owner.1246func (absoluteSD *SECURITY_DESCRIPTOR) SetOwner(owner *SID, defaulted bool) error {1247return setSecurityDescriptorOwner(absoluteSD, owner, defaulted)1248}12491250// Group returns the security descriptor group and whether it was defaulted.1251func (sd *SECURITY_DESCRIPTOR) Group() (group *SID, defaulted bool, err error) {1252err = getSecurityDescriptorGroup(sd, &group, &defaulted)1253return1254}12551256// SetGroup sets the absolute security descriptor owner.1257func (absoluteSD *SECURITY_DESCRIPTOR) SetGroup(group *SID, defaulted bool) error {1258return setSecurityDescriptorGroup(absoluteSD, group, defaulted)1259}12601261// Length returns the length of the security descriptor.1262func (sd *SECURITY_DESCRIPTOR) Length() uint32 {1263return getSecurityDescriptorLength(sd)1264}12651266// IsValid returns whether the security descriptor is valid.1267func (sd *SECURITY_DESCRIPTOR) IsValid() bool {1268return isValidSecurityDescriptor(sd)1269}12701271// String returns the SDDL form of the security descriptor, with a function signature that can be1272// used with %v formatting directives.1273func (sd *SECURITY_DESCRIPTOR) String() string {1274var sddl *uint161275err := convertSecurityDescriptorToStringSecurityDescriptor(sd, 1, 0xff, &sddl, nil)1276if err != nil {1277return ""1278}1279defer LocalFree(Handle(unsafe.Pointer(sddl)))1280return UTF16PtrToString(sddl)1281}12821283// ToAbsolute converts a self-relative security descriptor into an absolute one.1284func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DESCRIPTOR, err error) {1285control, _, err := selfRelativeSD.Control()1286if err != nil {1287return1288}1289if control&SE_SELF_RELATIVE == 0 {1290err = ERROR_INVALID_PARAMETER1291return1292}1293var absoluteSDSize, daclSize, saclSize, ownerSize, groupSize uint321294err = makeAbsoluteSD(selfRelativeSD, nil, &absoluteSDSize,1295nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &groupSize)1296switch err {1297case ERROR_INSUFFICIENT_BUFFER:1298case nil:1299// makeAbsoluteSD is expected to fail, but it succeeds.1300return nil, ERROR_INTERNAL_ERROR1301default:1302return nil, err1303}1304if absoluteSDSize > 0 {1305absoluteSD = new(SECURITY_DESCRIPTOR)1306if unsafe.Sizeof(*absoluteSD) < uintptr(absoluteSDSize) {1307panic("sizeof(SECURITY_DESCRIPTOR) too small")1308}1309}1310var (1311dacl *ACL1312sacl *ACL1313owner *SID1314group *SID1315)1316if daclSize > 0 {1317dacl = (*ACL)(unsafe.Pointer(unsafe.SliceData(make([]byte, daclSize))))1318}1319if saclSize > 0 {1320sacl = (*ACL)(unsafe.Pointer(unsafe.SliceData(make([]byte, saclSize))))1321}1322if ownerSize > 0 {1323owner = (*SID)(unsafe.Pointer(unsafe.SliceData(make([]byte, ownerSize))))1324}1325if groupSize > 0 {1326group = (*SID)(unsafe.Pointer(unsafe.SliceData(make([]byte, groupSize))))1327}1328// We call into Windows via makeAbsoluteSD, which sets up1329// pointers within absoluteSD that point to other chunks of memory1330// we pass into makeAbsoluteSD, and that happens outside the view of the GC.1331// We therefore take some care here to then verify the pointers are as we expect1332// and set them explicitly in view of the GC. See https://go.dev/issue/73199.1333// TODO: consider weak pointers once Go 1.24 is appropriate. See suggestion in https://go.dev/cl/663575.1334err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize,1335dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize)1336if err != nil {1337// Don't return absoluteSD, which might be partially initialized.1338return nil, err1339}1340// Before using any fields, verify absoluteSD is in the format we expect according to Windows.1341// See https://learn.microsoft.com/en-us/windows/win32/secauthz/absolute-and-self-relative-security-descriptors1342absControl, _, err := absoluteSD.Control()1343if err != nil {1344panic("absoluteSD: " + err.Error())1345}1346if absControl&SE_SELF_RELATIVE != 0 {1347panic("absoluteSD not in absolute format")1348}1349if absoluteSD.dacl != dacl {1350panic("dacl pointer mismatch")1351}1352if absoluteSD.sacl != sacl {1353panic("sacl pointer mismatch")1354}1355if absoluteSD.owner != owner {1356panic("owner pointer mismatch")1357}1358if absoluteSD.group != group {1359panic("group pointer mismatch")1360}1361absoluteSD.dacl = dacl1362absoluteSD.sacl = sacl1363absoluteSD.owner = owner1364absoluteSD.group = group13651366return1367}13681369// ToSelfRelative converts an absolute security descriptor into a self-relative one.1370func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURITY_DESCRIPTOR, err error) {1371control, _, err := absoluteSD.Control()1372if err != nil {1373return1374}1375if control&SE_SELF_RELATIVE != 0 {1376err = ERROR_INVALID_PARAMETER1377return1378}1379var selfRelativeSDSize uint321380err = makeSelfRelativeSD(absoluteSD, nil, &selfRelativeSDSize)1381switch err {1382case ERROR_INSUFFICIENT_BUFFER:1383case nil:1384// makeSelfRelativeSD is expected to fail, but it succeeds.1385return nil, ERROR_INTERNAL_ERROR1386default:1387return nil, err1388}1389if selfRelativeSDSize > 0 {1390selfRelativeSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, selfRelativeSDSize)[0]))1391}1392err = makeSelfRelativeSD(absoluteSD, selfRelativeSD, &selfRelativeSDSize)1393return1394}13951396func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR {1397sdLen := int(selfRelativeSD.Length())1398const min = int(unsafe.Sizeof(SECURITY_DESCRIPTOR{}))1399if sdLen < min {1400sdLen = min1401}14021403src := unsafe.Slice((*byte)(unsafe.Pointer(selfRelativeSD)), sdLen)1404// SECURITY_DESCRIPTOR has pointers in it, which means checkptr expects for it to1405// be aligned properly. When we're copying a Windows-allocated struct to a1406// Go-allocated one, make sure that the Go allocation is aligned to the1407// pointer size.1408const psize = int(unsafe.Sizeof(uintptr(0)))1409alloc := make([]uintptr, (sdLen+psize-1)/psize)1410dst := unsafe.Slice((*byte)(unsafe.Pointer(&alloc[0])), sdLen)1411copy(dst, src)1412return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&dst[0]))1413}14141415// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a1416// self-relative security descriptor object allocated on the Go heap.1417func SecurityDescriptorFromString(sddl string) (sd *SECURITY_DESCRIPTOR, err error) {1418var winHeapSD *SECURITY_DESCRIPTOR1419err = convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &winHeapSD, nil)1420if err != nil {1421return1422}1423defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))1424return winHeapSD.copySelfRelativeSecurityDescriptor(), nil1425}14261427// GetSecurityInfo queries the security information for a given handle and returns the self-relative security1428// descriptor result on the Go heap.1429func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {1430var winHeapSD *SECURITY_DESCRIPTOR1431err = getSecurityInfo(handle, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)1432if err != nil {1433return1434}1435defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))1436return winHeapSD.copySelfRelativeSecurityDescriptor(), nil1437}14381439// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security1440// descriptor result on the Go heap.1441func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {1442var winHeapSD *SECURITY_DESCRIPTOR1443err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)1444if err != nil {1445return1446}1447defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))1448return winHeapSD.copySelfRelativeSecurityDescriptor(), nil1449}14501451// BuildSecurityDescriptor makes a new security descriptor using the input trustees, explicit access lists, and1452// prior security descriptor to be merged, any of which can be nil, returning the self-relative security descriptor1453// result on the Go heap.1454func BuildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, accessEntries []EXPLICIT_ACCESS, auditEntries []EXPLICIT_ACCESS, mergedSecurityDescriptor *SECURITY_DESCRIPTOR) (sd *SECURITY_DESCRIPTOR, err error) {1455var winHeapSD *SECURITY_DESCRIPTOR1456var winHeapSDSize uint321457var firstAccessEntry *EXPLICIT_ACCESS1458if len(accessEntries) > 0 {1459firstAccessEntry = &accessEntries[0]1460}1461var firstAuditEntry *EXPLICIT_ACCESS1462if len(auditEntries) > 0 {1463firstAuditEntry = &auditEntries[0]1464}1465err = buildSecurityDescriptor(owner, group, uint32(len(accessEntries)), firstAccessEntry, uint32(len(auditEntries)), firstAuditEntry, mergedSecurityDescriptor, &winHeapSDSize, &winHeapSD)1466if err != nil {1467return1468}1469defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))1470return winHeapSD.copySelfRelativeSecurityDescriptor(), nil1471}14721473// NewSecurityDescriptor creates and initializes a new absolute security descriptor.1474func NewSecurityDescriptor() (absoluteSD *SECURITY_DESCRIPTOR, err error) {1475absoluteSD = &SECURITY_DESCRIPTOR{}1476err = initializeSecurityDescriptor(absoluteSD, 1)1477return1478}14791480// ACLFromEntries returns a new ACL on the Go heap containing a list of explicit entries as well as those of another ACL.1481// Both explicitEntries and mergedACL are optional and can be nil.1482func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL, err error) {1483var firstExplicitEntry *EXPLICIT_ACCESS1484if len(explicitEntries) > 0 {1485firstExplicitEntry = &explicitEntries[0]1486}1487var winHeapACL *ACL1488err = setEntriesInAcl(uint32(len(explicitEntries)), firstExplicitEntry, mergedACL, &winHeapACL)1489if err != nil {1490return1491}1492defer LocalFree(Handle(unsafe.Pointer(winHeapACL)))1493aclBytes := make([]byte, winHeapACL.aclSize)1494copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes):len(aclBytes)])1495return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil1496}149714981499