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. 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} 436