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.
12 STANDARD_RIGHTS_REQUIRED
= 0xf0000
13 STANDARD_RIGHTS_READ
= 0x20000
14 STANDARD_RIGHTS_WRITE
= 0x20000
15 STANDARD_RIGHTS_EXECUTE
= 0x20000
16 STANDARD_RIGHTS_ALL
= 0x1F0000
21 NameFullyQualifiedDN
= 1
28 NameServicePrincipal
= 10
32 // This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
33 // https://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
34 //sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
35 //sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
37 // TranslateAccountName converts a directory service
38 // object name from one format to another.
39 func TranslateAccountName(username
string, from
, to
uint32, initSize
int) (string, error
) {
40 u
, e
:= UTF16PtrFromString(username
)
46 b
:= make([]uint16, n
)
47 e
= TranslateName(u
, from
, to
, &b
[0], &n
)
49 return UTF16ToString(b
[:n
]), nil
51 if e
!= ERROR_INSUFFICIENT_BUFFER
{
54 if n
<= uint32(len(b
)) {
62 NetSetupUnknownStatus
= iota
68 type UserInfo10
struct {
75 //sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
76 //sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
77 //sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
81 SidTypeUser
= 1 + iota
93 //sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
94 //sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
95 //sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
96 //sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
97 //sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
98 //sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
100 // The security identifier (SID) structure is a variable-length
101 // structure used to uniquely identify users or groups.
104 // StringToSid converts a string-format security identifier
105 // sid into a valid, functional sid.
106 func StringToSid(s
string) (*SID
, error
) {
108 p
, e
:= UTF16PtrFromString(s
)
112 e
= ConvertStringSidToSid(p
, &sid
)
116 defer LocalFree((Handle
)(unsafe
.Pointer(sid
)))
120 // LookupSID retrieves a security identifier sid for the account
121 // and the name of the domain on which the account was found.
122 // System specify target computer to search.
123 func LookupSID(system
, account
string) (sid
*SID
, domain
string, accType
uint32, err error
) {
124 if len(account
) == 0 {
125 return nil, "", 0, EINVAL
127 acc
, e
:= UTF16PtrFromString(account
)
133 sys
, e
= UTF16PtrFromString(system
)
142 db
:= make([]uint16, dn
)
143 sid
= (*SID
)(unsafe
.Pointer(&b
[0]))
144 e
= LookupAccountName(sys
, acc
, sid
, &n
, &db
[0], &dn
, &accType
)
146 return sid
, UTF16ToString(db
), accType
, nil
148 if e
!= ERROR_INSUFFICIENT_BUFFER
{
151 if n
<= uint32(len(b
)) {
157 // String converts sid to a string format
158 // suitable for display, storage, or transmission.
159 func (sid
*SID
) String() (string, error
) {
161 e
:= ConvertSidToStringSid(sid
, &s
)
165 defer LocalFree((Handle
)(unsafe
.Pointer(s
)))
166 return utf16PtrToString(s
, 256), nil
169 // Len returns the length, in bytes, of a valid security identifier sid.
170 func (sid
*SID
) Len() int {
171 return int(GetLengthSid(sid
))
174 // Copy creates a duplicate of security identifier sid.
175 func (sid
*SID
) Copy() (*SID
, error
) {
176 b
:= make([]byte, sid
.Len())
177 sid2
:= (*SID
)(unsafe
.Pointer(&b
[0]))
178 e
:= CopySid(uint32(len(b
)), sid2
, sid
)
185 // LookupAccount retrieves the name of the account for this sid
186 // and the name of the first domain on which this sid is found.
187 // System specify target computer to search for.
188 func (sid
*SID
) LookupAccount(system
string) (account
, domain
string, accType
uint32, err error
) {
191 sys
, err
= UTF16PtrFromString(system
)
193 return "", "", 0, err
199 b
:= make([]uint16, n
)
200 db
:= make([]uint16, dn
)
201 e
:= LookupAccountSid(sys
, sid
, &b
[0], &n
, &db
[0], &dn
, &accType
)
203 return UTF16ToString(b
), UTF16ToString(db
), accType
, nil
205 if e
!= ERROR_INSUFFICIENT_BUFFER
{
208 if n
<= uint32(len(b
)) {
216 TOKEN_ASSIGN_PRIMARY
= 1 << iota
221 TOKEN_ADJUST_PRIVILEGES
224 TOKEN_ADJUST_SESSIONID
226 TOKEN_ALL_ACCESS
= STANDARD_RIGHTS_REQUIRED |
227 TOKEN_ASSIGN_PRIMARY |
232 TOKEN_ADJUST_PRIVILEGES |
233 TOKEN_ADJUST_GROUPS |
234 TOKEN_ADJUST_DEFAULT |
235 TOKEN_ADJUST_SESSIONID
236 TOKEN_READ
= STANDARD_RIGHTS_READ | TOKEN_QUERY
237 TOKEN_WRITE
= STANDARD_RIGHTS_WRITE |
238 TOKEN_ADJUST_PRIVILEGES |
239 TOKEN_ADJUST_GROUPS |
241 TOKEN_EXECUTE
= STANDARD_RIGHTS_EXECUTE
254 TokenImpersonationLevel
258 TokenGroupsAndPrivileges
259 TokenSessionReference
267 TokenAccessInformation
268 TokenVirtualizationAllowed
269 TokenVirtualizationEnabled
277 type SIDAndAttributes
struct {
282 type Tokenuser
struct {
283 User SIDAndAttributes
286 type Tokenprimarygroup
struct {
290 //sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
291 //sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
292 //sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
293 //sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
295 // An access token contains the security information for a logon session.
296 // The system creates an access token when a user logs on, and every
297 // process executed on behalf of the user has a copy of the token.
298 // The token identifies the user, the user's groups, and the user's
299 // privileges. The system uses the token to control access to securable
300 // objects and to control the ability of the user to perform various
301 // system-related operations on the local computer.
304 // OpenCurrentProcessToken opens the access token
305 // associated with current process.
306 func OpenCurrentProcessToken() (Token
, error
) {
307 p
, e
:= GetCurrentProcess()
312 e
= OpenProcessToken(p
, TOKEN_QUERY
, &t
)
319 // Close releases access to access token.
320 func (t Token
) Close() error
{
321 return CloseHandle(Handle(t
))
324 // getInfo retrieves a specified type of information about an access token.
325 func (t Token
) getInfo(class
uint32, initSize
int) (unsafe
.Pointer
, error
) {
326 n
:= uint32(initSize
)
329 e
:= GetTokenInformation(t
, class
, &b
[0], uint32(len(b
)), &n
)
331 return unsafe
.Pointer(&b
[0]), nil
333 if e
!= ERROR_INSUFFICIENT_BUFFER
{
336 if n
<= uint32(len(b
)) {
342 // GetTokenUser retrieves access token t user account information.
343 func (t Token
) GetTokenUser() (*Tokenuser
, error
) {
344 i
, e
:= t
.getInfo(TokenUser
, 50)
348 return (*Tokenuser
)(i
), nil
351 // GetTokenPrimaryGroup retrieves access token t primary group information.
352 // A pointer to a SID structure representing a group that will become
353 // the primary group of any objects created by a process using this access token.
354 func (t Token
) GetTokenPrimaryGroup() (*Tokenprimarygroup
, error
) {
355 i
, e
:= t
.getInfo(TokenPrimaryGroup
, 50)
359 return (*Tokenprimarygroup
)(i
), nil
362 // GetUserProfileDirectory retrieves path to the
363 // root directory of the access token t user's profile.
364 func (t Token
) GetUserProfileDirectory() (string, error
) {
367 b
:= make([]uint16, n
)
368 e
:= GetUserProfileDirectory(t
, &b
[0], &n
)
370 return UTF16ToString(b
), nil
372 if e
!= ERROR_INSUFFICIENT_BUFFER
{
375 if n
<= uint32(len(b
)) {