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