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 syscall 6 7import ( 8 "unsafe" 9) 10 11const ( 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 17) 18 19const ( 20 NameUnknown = 0 21 NameFullyQualifiedDN = 1 22 NameSamCompatible = 2 23 NameDisplay = 3 24 NameUniqueId = 6 25 NameCanonical = 7 26 NameUserPrincipal = 8 27 NameCanonicalEx = 9 28 NameServicePrincipal = 10 29 NameDnsDomain = 12 30) 31 32// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL. 33// https://learn.microsoft.com/en-gb/archive/blogs/drnick/windows-and-upn-format-credentials 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 36 37// TranslateAccountName converts a directory service 38// object name from one format to another. 39func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) { 40 u, e := UTF16PtrFromString(username) 41 if e != nil { 42 return "", e 43 } 44 n := uint32(50) 45 for { 46 b := make([]uint16, n) 47 e = TranslateName(u, from, to, &b[0], &n) 48 if e == nil { 49 return UTF16ToString(b[:n]), nil 50 } 51 if e != ERROR_INSUFFICIENT_BUFFER { 52 return "", e 53 } 54 if n <= uint32(len(b)) { 55 return "", e 56 } 57 } 58} 59 60const ( 61 // do not reorder 62 NetSetupUnknownStatus = iota 63 NetSetupUnjoined 64 NetSetupWorkgroupName 65 NetSetupDomainName 66) 67 68type UserInfo10 struct { 69 Name *uint16 70 Comment *uint16 71 UsrComment *uint16 72 FullName *uint16 73} 74 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 78 79const ( 80 // do not reorder 81 SidTypeUser = 1 + iota 82 SidTypeGroup 83 SidTypeDomain 84 SidTypeAlias 85 SidTypeWellKnownGroup 86 SidTypeDeletedAccount 87 SidTypeInvalid 88 SidTypeUnknown 89 SidTypeComputer 90 SidTypeLabel 91) 92 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 99 100// The security identifier (SID) structure is a variable-length 101// structure used to uniquely identify users or groups. 102type SID struct{} 103 104// StringToSid converts a string-format security identifier 105// sid into a valid, functional sid. 106func StringToSid(s string) (*SID, error) { 107 var sid *SID 108 p, e := UTF16PtrFromString(s) 109 if e != nil { 110 return nil, e 111 } 112 e = ConvertStringSidToSid(p, &sid) 113 if e != nil { 114 return nil, e 115 } 116 defer LocalFree((Handle)(unsafe.Pointer(sid))) 117 return sid.Copy() 118} 119 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. 123func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) { 124 if len(account) == 0 { 125 return nil, "", 0, EINVAL 126 } 127 acc, e := UTF16PtrFromString(account) 128 if e != nil { 129 return nil, "", 0, e 130 } 131 var sys *uint16 132 if len(system) > 0 { 133 sys, e = UTF16PtrFromString(system) 134 if e != nil { 135 return nil, "", 0, e 136 } 137 } 138 n := uint32(50) 139 dn := uint32(50) 140 for { 141 b := make([]byte, n) 142 db := make([]uint16, dn) 143 sid = (*SID)(unsafe.Pointer(&b[0])) 144 e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType) 145 if e == nil { 146 return sid, UTF16ToString(db), accType, nil 147 } 148 if e != ERROR_INSUFFICIENT_BUFFER { 149 return nil, "", 0, e 150 } 151 if n <= uint32(len(b)) { 152 return nil, "", 0, e 153 } 154 } 155} 156 157// String converts sid to a string format 158// suitable for display, storage, or transmission. 159func (sid *SID) String() (string, error) { 160 var s *uint16 161 e := ConvertSidToStringSid(sid, &s) 162 if e != nil { 163 return "", e 164 } 165 defer LocalFree((Handle)(unsafe.Pointer(s))) 166 return utf16PtrToString(s), nil 167} 168 169// Len returns the length, in bytes, of a valid security identifier sid. 170func (sid *SID) Len() int { 171 return int(GetLengthSid(sid)) 172} 173 174// Copy creates a duplicate of security identifier sid. 175func (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) 179 if e != nil { 180 return nil, e 181 } 182 return sid2, nil 183} 184 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. 188func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) { 189 var sys *uint16 190 if len(system) > 0 { 191 sys, err = UTF16PtrFromString(system) 192 if err != nil { 193 return "", "", 0, err 194 } 195 } 196 n := uint32(50) 197 dn := uint32(50) 198 for { 199 b := make([]uint16, n) 200 db := make([]uint16, dn) 201 e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType) 202 if e == nil { 203 return UTF16ToString(b), UTF16ToString(db), accType, nil 204 } 205 if e != ERROR_INSUFFICIENT_BUFFER { 206 return "", "", 0, e 207 } 208 if n <= uint32(len(b)) { 209 return "", "", 0, e 210 } 211 } 212} 213 214const ( 215 // do not reorder 216 TOKEN_ASSIGN_PRIMARY = 1 << iota 217 TOKEN_DUPLICATE 218 TOKEN_IMPERSONATE 219 TOKEN_QUERY 220 TOKEN_QUERY_SOURCE 221 TOKEN_ADJUST_PRIVILEGES 222 TOKEN_ADJUST_GROUPS 223 TOKEN_ADJUST_DEFAULT 224 TOKEN_ADJUST_SESSIONID 225 226 TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | 227 TOKEN_ASSIGN_PRIMARY | 228 TOKEN_DUPLICATE | 229 TOKEN_IMPERSONATE | 230 TOKEN_QUERY | 231 TOKEN_QUERY_SOURCE | 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 | 240 TOKEN_ADJUST_DEFAULT 241 TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE 242) 243 244const ( 245 // do not reorder 246 TokenUser = 1 + iota 247 TokenGroups 248 TokenPrivileges 249 TokenOwner 250 TokenPrimaryGroup 251 TokenDefaultDacl 252 TokenSource 253 TokenType 254 TokenImpersonationLevel 255 TokenStatistics 256 TokenRestrictedSids 257 TokenSessionId 258 TokenGroupsAndPrivileges 259 TokenSessionReference 260 TokenSandBoxInert 261 TokenAuditPolicy 262 TokenOrigin 263 TokenElevationType 264 TokenLinkedToken 265 TokenElevation 266 TokenHasRestrictions 267 TokenAccessInformation 268 TokenVirtualizationAllowed 269 TokenVirtualizationEnabled 270 TokenIntegrityLevel 271 TokenUIAccess 272 TokenMandatoryPolicy 273 TokenLogonSid 274 MaxTokenInfoClass 275) 276 277type SIDAndAttributes struct { 278 Sid *SID 279 Attributes uint32 280} 281 282type Tokenuser struct { 283 User SIDAndAttributes 284} 285 286type Tokenprimarygroup struct { 287 PrimaryGroup *SID 288} 289 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 294// An access token contains the security information for a logon session. 295// The system creates an access token when a user logs on, and every 296// process executed on behalf of the user has a copy of the token. 297// The token identifies the user, the user's groups, and the user's 298// privileges. The system uses the token to control access to securable 299// objects and to control the ability of the user to perform various 300// system-related operations on the local computer. 301type Token Handle 302 303// OpenCurrentProcessToken opens the access token 304// associated with current process. 305func OpenCurrentProcessToken() (Token, error) { 306 p, e := GetCurrentProcess() 307 if e != nil { 308 return 0, e 309 } 310 var t Token 311 e = OpenProcessToken(p, TOKEN_QUERY, &t) 312 if e != nil { 313 return 0, e 314 } 315 return t, nil 316} 317 318// Close releases access to access token. 319func (t Token) Close() error { 320 return CloseHandle(Handle(t)) 321} 322 323// getInfo retrieves a specified type of information about an access token. 324func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) { 325 n := uint32(initSize) 326 for { 327 b := make([]byte, n) 328 e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n) 329 if e == nil { 330 return unsafe.Pointer(&b[0]), nil 331 } 332 if e != ERROR_INSUFFICIENT_BUFFER { 333 return nil, e 334 } 335 if n <= uint32(len(b)) { 336 return nil, e 337 } 338 } 339} 340 341// GetTokenUser retrieves access token t user account information. 342func (t Token) GetTokenUser() (*Tokenuser, error) { 343 i, e := t.getInfo(TokenUser, 50) 344 if e != nil { 345 return nil, e 346 } 347 return (*Tokenuser)(i), nil 348} 349 350// GetTokenPrimaryGroup retrieves access token t primary group information. 351// A pointer to a SID structure representing a group that will become 352// the primary group of any objects created by a process using this access token. 353func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) { 354 i, e := t.getInfo(TokenPrimaryGroup, 50) 355 if e != nil { 356 return nil, e 357 } 358 return (*Tokenprimarygroup)(i), nil 359} 360 361// GetUserProfileDirectory retrieves path to the 362// root directory of the access token t user's profile. 363func (t Token) GetUserProfileDirectory() (string, error) { 364 n := uint32(100) 365 for { 366 b := make([]uint16, n) 367 e := GetUserProfileDirectory(t, &b[0], &n) 368 if e == nil { 369 return UTF16ToString(b), nil 370 } 371 if e != ERROR_INSUFFICIENT_BUFFER { 372 return "", e 373 } 374 if n <= uint32(len(b)) { 375 return "", e 376 } 377 } 378} 379