blob: 4f17a3331fd04ab731533f1ee0b5bba6e4b323e8 [file] [log] [blame]
khenaidooac637102019-01-14 15:44:34 -05001// 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 FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
173//sys EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
174
175// The security identifier (SID) structure is a variable-length
176// structure used to uniquely identify users or groups.
177type SID struct{}
178
179// StringToSid converts a string-format security identifier
180// sid into a valid, functional sid.
181func StringToSid(s string) (*SID, error) {
182 var sid *SID
183 p, e := UTF16PtrFromString(s)
184 if e != nil {
185 return nil, e
186 }
187 e = ConvertStringSidToSid(p, &sid)
188 if e != nil {
189 return nil, e
190 }
191 defer LocalFree((Handle)(unsafe.Pointer(sid)))
192 return sid.Copy()
193}
194
195// LookupSID retrieves a security identifier sid for the account
196// and the name of the domain on which the account was found.
197// System specify target computer to search.
198func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
199 if len(account) == 0 {
200 return nil, "", 0, syscall.EINVAL
201 }
202 acc, e := UTF16PtrFromString(account)
203 if e != nil {
204 return nil, "", 0, e
205 }
206 var sys *uint16
207 if len(system) > 0 {
208 sys, e = UTF16PtrFromString(system)
209 if e != nil {
210 return nil, "", 0, e
211 }
212 }
213 n := uint32(50)
214 dn := uint32(50)
215 for {
216 b := make([]byte, n)
217 db := make([]uint16, dn)
218 sid = (*SID)(unsafe.Pointer(&b[0]))
219 e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
220 if e == nil {
221 return sid, UTF16ToString(db), accType, nil
222 }
223 if e != ERROR_INSUFFICIENT_BUFFER {
224 return nil, "", 0, e
225 }
226 if n <= uint32(len(b)) {
227 return nil, "", 0, e
228 }
229 }
230}
231
232// String converts sid to a string format
233// suitable for display, storage, or transmission.
234func (sid *SID) String() (string, error) {
235 var s *uint16
236 e := ConvertSidToStringSid(sid, &s)
237 if e != nil {
238 return "", e
239 }
240 defer LocalFree((Handle)(unsafe.Pointer(s)))
241 return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
242}
243
244// Len returns the length, in bytes, of a valid security identifier sid.
245func (sid *SID) Len() int {
246 return int(GetLengthSid(sid))
247}
248
249// Copy creates a duplicate of security identifier sid.
250func (sid *SID) Copy() (*SID, error) {
251 b := make([]byte, sid.Len())
252 sid2 := (*SID)(unsafe.Pointer(&b[0]))
253 e := CopySid(uint32(len(b)), sid2, sid)
254 if e != nil {
255 return nil, e
256 }
257 return sid2, nil
258}
259
260// LookupAccount retrieves the name of the account for this sid
261// and the name of the first domain on which this sid is found.
262// System specify target computer to search for.
263func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
264 var sys *uint16
265 if len(system) > 0 {
266 sys, err = UTF16PtrFromString(system)
267 if err != nil {
268 return "", "", 0, err
269 }
270 }
271 n := uint32(50)
272 dn := uint32(50)
273 for {
274 b := make([]uint16, n)
275 db := make([]uint16, dn)
276 e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
277 if e == nil {
278 return UTF16ToString(b), UTF16ToString(db), accType, nil
279 }
280 if e != ERROR_INSUFFICIENT_BUFFER {
281 return "", "", 0, e
282 }
283 if n <= uint32(len(b)) {
284 return "", "", 0, e
285 }
286 }
287}
288
289const (
290 // do not reorder
291 TOKEN_ASSIGN_PRIMARY = 1 << iota
292 TOKEN_DUPLICATE
293 TOKEN_IMPERSONATE
294 TOKEN_QUERY
295 TOKEN_QUERY_SOURCE
296 TOKEN_ADJUST_PRIVILEGES
297 TOKEN_ADJUST_GROUPS
298 TOKEN_ADJUST_DEFAULT
299 TOKEN_ADJUST_SESSIONID
300
301 TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
302 TOKEN_ASSIGN_PRIMARY |
303 TOKEN_DUPLICATE |
304 TOKEN_IMPERSONATE |
305 TOKEN_QUERY |
306 TOKEN_QUERY_SOURCE |
307 TOKEN_ADJUST_PRIVILEGES |
308 TOKEN_ADJUST_GROUPS |
309 TOKEN_ADJUST_DEFAULT |
310 TOKEN_ADJUST_SESSIONID
311 TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
312 TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
313 TOKEN_ADJUST_PRIVILEGES |
314 TOKEN_ADJUST_GROUPS |
315 TOKEN_ADJUST_DEFAULT
316 TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
317)
318
319const (
320 // do not reorder
321 TokenUser = 1 + iota
322 TokenGroups
323 TokenPrivileges
324 TokenOwner
325 TokenPrimaryGroup
326 TokenDefaultDacl
327 TokenSource
328 TokenType
329 TokenImpersonationLevel
330 TokenStatistics
331 TokenRestrictedSids
332 TokenSessionId
333 TokenGroupsAndPrivileges
334 TokenSessionReference
335 TokenSandBoxInert
336 TokenAuditPolicy
337 TokenOrigin
338 TokenElevationType
339 TokenLinkedToken
340 TokenElevation
341 TokenHasRestrictions
342 TokenAccessInformation
343 TokenVirtualizationAllowed
344 TokenVirtualizationEnabled
345 TokenIntegrityLevel
346 TokenUIAccess
347 TokenMandatoryPolicy
348 TokenLogonSid
349 MaxTokenInfoClass
350)
351
352type SIDAndAttributes struct {
353 Sid *SID
354 Attributes uint32
355}
356
357type Tokenuser struct {
358 User SIDAndAttributes
359}
360
361type Tokenprimarygroup struct {
362 PrimaryGroup *SID
363}
364
365type Tokengroups struct {
366 GroupCount uint32
367 Groups [1]SIDAndAttributes
368}
369
370// Authorization Functions
371//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
372//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
373//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
374//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
375
376// An access token contains the security information for a logon session.
377// The system creates an access token when a user logs on, and every
378// process executed on behalf of the user has a copy of the token.
379// The token identifies the user, the user's groups, and the user's
380// privileges. The system uses the token to control access to securable
381// objects and to control the ability of the user to perform various
382// system-related operations on the local computer.
383type Token Handle
384
385// OpenCurrentProcessToken opens the access token
386// associated with current process.
387func OpenCurrentProcessToken() (Token, error) {
388 p, e := GetCurrentProcess()
389 if e != nil {
390 return 0, e
391 }
392 var t Token
393 e = OpenProcessToken(p, TOKEN_QUERY, &t)
394 if e != nil {
395 return 0, e
396 }
397 return t, nil
398}
399
400// Close releases access to access token.
401func (t Token) Close() error {
402 return CloseHandle(Handle(t))
403}
404
405// getInfo retrieves a specified type of information about an access token.
406func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
407 n := uint32(initSize)
408 for {
409 b := make([]byte, n)
410 e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
411 if e == nil {
412 return unsafe.Pointer(&b[0]), nil
413 }
414 if e != ERROR_INSUFFICIENT_BUFFER {
415 return nil, e
416 }
417 if n <= uint32(len(b)) {
418 return nil, e
419 }
420 }
421}
422
423// GetTokenUser retrieves access token t user account information.
424func (t Token) GetTokenUser() (*Tokenuser, error) {
425 i, e := t.getInfo(TokenUser, 50)
426 if e != nil {
427 return nil, e
428 }
429 return (*Tokenuser)(i), nil
430}
431
432// GetTokenGroups retrieves group accounts associated with access token t.
433func (t Token) GetTokenGroups() (*Tokengroups, error) {
434 i, e := t.getInfo(TokenGroups, 50)
435 if e != nil {
436 return nil, e
437 }
438 return (*Tokengroups)(i), nil
439}
440
441// GetTokenPrimaryGroup retrieves access token t primary group information.
442// A pointer to a SID structure representing a group that will become
443// the primary group of any objects created by a process using this access token.
444func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
445 i, e := t.getInfo(TokenPrimaryGroup, 50)
446 if e != nil {
447 return nil, e
448 }
449 return (*Tokenprimarygroup)(i), nil
450}
451
452// GetUserProfileDirectory retrieves path to the
453// root directory of the access token t user's profile.
454func (t Token) GetUserProfileDirectory() (string, error) {
455 n := uint32(100)
456 for {
457 b := make([]uint16, n)
458 e := GetUserProfileDirectory(t, &b[0], &n)
459 if e == nil {
460 return UTF16ToString(b), nil
461 }
462 if e != ERROR_INSUFFICIENT_BUFFER {
463 return "", e
464 }
465 if n <= uint32(len(b)) {
466 return "", e
467 }
468 }
469}
470
471// IsMember reports whether the access token t is a member of the provided SID.
472func (t Token) IsMember(sid *SID) (bool, error) {
473 var b int32
474 if e := checkTokenMembership(t, sid, &b); e != nil {
475 return false, e
476 }
477 return b != 0, nil
478}