You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

479 regels
14 KiB

  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. package windows
  5. import (
  6. "syscall"
  7. "unsafe"
  8. )
  9. const (
  10. STANDARD_RIGHTS_REQUIRED = 0xf0000
  11. STANDARD_RIGHTS_READ = 0x20000
  12. STANDARD_RIGHTS_WRITE = 0x20000
  13. STANDARD_RIGHTS_EXECUTE = 0x20000
  14. STANDARD_RIGHTS_ALL = 0x1F0000
  15. )
  16. const (
  17. NameUnknown = 0
  18. NameFullyQualifiedDN = 1
  19. NameSamCompatible = 2
  20. NameDisplay = 3
  21. NameUniqueId = 6
  22. NameCanonical = 7
  23. NameUserPrincipal = 8
  24. NameCanonicalEx = 9
  25. NameServicePrincipal = 10
  26. NameDnsDomain = 12
  27. )
  28. // This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
  29. // http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
  30. //sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
  31. //sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
  32. // TranslateAccountName converts a directory service
  33. // object name from one format to another.
  34. func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
  35. u, e := UTF16PtrFromString(username)
  36. if e != nil {
  37. return "", e
  38. }
  39. n := uint32(50)
  40. for {
  41. b := make([]uint16, n)
  42. e = TranslateName(u, from, to, &b[0], &n)
  43. if e == nil {
  44. return UTF16ToString(b[:n]), nil
  45. }
  46. if e != ERROR_INSUFFICIENT_BUFFER {
  47. return "", e
  48. }
  49. if n <= uint32(len(b)) {
  50. return "", e
  51. }
  52. }
  53. }
  54. const (
  55. // do not reorder
  56. NetSetupUnknownStatus = iota
  57. NetSetupUnjoined
  58. NetSetupWorkgroupName
  59. NetSetupDomainName
  60. )
  61. type UserInfo10 struct {
  62. Name *uint16
  63. Comment *uint16
  64. UsrComment *uint16
  65. FullName *uint16
  66. }
  67. //sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
  68. //sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
  69. //sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
  70. const (
  71. // do not reorder
  72. SidTypeUser = 1 + iota
  73. SidTypeGroup
  74. SidTypeDomain
  75. SidTypeAlias
  76. SidTypeWellKnownGroup
  77. SidTypeDeletedAccount
  78. SidTypeInvalid
  79. SidTypeUnknown
  80. SidTypeComputer
  81. SidTypeLabel
  82. )
  83. type SidIdentifierAuthority struct {
  84. Value [6]byte
  85. }
  86. var (
  87. SECURITY_NULL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
  88. SECURITY_WORLD_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
  89. SECURITY_LOCAL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
  90. SECURITY_CREATOR_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
  91. SECURITY_NON_UNIQUE_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
  92. SECURITY_NT_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
  93. SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
  94. )
  95. const (
  96. SECURITY_NULL_RID = 0
  97. SECURITY_WORLD_RID = 0
  98. SECURITY_LOCAL_RID = 0
  99. SECURITY_CREATOR_OWNER_RID = 0
  100. SECURITY_CREATOR_GROUP_RID = 1
  101. SECURITY_DIALUP_RID = 1
  102. SECURITY_NETWORK_RID = 2
  103. SECURITY_BATCH_RID = 3
  104. SECURITY_INTERACTIVE_RID = 4
  105. SECURITY_LOGON_IDS_RID = 5
  106. SECURITY_SERVICE_RID = 6
  107. SECURITY_LOCAL_SYSTEM_RID = 18
  108. SECURITY_BUILTIN_DOMAIN_RID = 32
  109. SECURITY_PRINCIPAL_SELF_RID = 10
  110. SECURITY_CREATOR_OWNER_SERVER_RID = 0x2
  111. SECURITY_CREATOR_GROUP_SERVER_RID = 0x3
  112. SECURITY_LOGON_IDS_RID_COUNT = 0x3
  113. SECURITY_ANONYMOUS_LOGON_RID = 0x7
  114. SECURITY_PROXY_RID = 0x8
  115. SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
  116. SECURITY_SERVER_LOGON_RID = SECURITY_ENTERPRISE_CONTROLLERS_RID
  117. SECURITY_AUTHENTICATED_USER_RID = 0xb
  118. SECURITY_RESTRICTED_CODE_RID = 0xc
  119. SECURITY_NT_NON_UNIQUE_RID = 0x15
  120. )
  121. // Predefined domain-relative RIDs for local groups.
  122. // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
  123. const (
  124. DOMAIN_ALIAS_RID_ADMINS = 0x220
  125. DOMAIN_ALIAS_RID_USERS = 0x221
  126. DOMAIN_ALIAS_RID_GUESTS = 0x222
  127. DOMAIN_ALIAS_RID_POWER_USERS = 0x223
  128. DOMAIN_ALIAS_RID_ACCOUNT_OPS = 0x224
  129. DOMAIN_ALIAS_RID_SYSTEM_OPS = 0x225
  130. DOMAIN_ALIAS_RID_PRINT_OPS = 0x226
  131. DOMAIN_ALIAS_RID_BACKUP_OPS = 0x227
  132. DOMAIN_ALIAS_RID_REPLICATOR = 0x228
  133. DOMAIN_ALIAS_RID_RAS_SERVERS = 0x229
  134. DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 0x22a
  135. DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS = 0x22b
  136. DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS = 0x22c
  137. DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
  138. DOMAIN_ALIAS_RID_MONITORING_USERS = 0X22e
  139. DOMAIN_ALIAS_RID_LOGGING_USERS = 0x22f
  140. DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS = 0x230
  141. DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS = 0x231
  142. DOMAIN_ALIAS_RID_DCOM_USERS = 0x232
  143. DOMAIN_ALIAS_RID_IUSERS = 0x238
  144. DOMAIN_ALIAS_RID_CRYPTO_OPERATORS = 0x239
  145. DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP = 0x23b
  146. DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c
  147. DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP = 0x23d
  148. DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP = 0x23e
  149. )
  150. //sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
  151. //sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
  152. //sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
  153. //sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
  154. //sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
  155. //sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
  156. //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
  157. //sys FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
  158. //sys EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
  159. // The security identifier (SID) structure is a variable-length
  160. // structure used to uniquely identify users or groups.
  161. type SID struct{}
  162. // StringToSid converts a string-format security identifier
  163. // sid into a valid, functional sid.
  164. func StringToSid(s string) (*SID, error) {
  165. var sid *SID
  166. p, e := UTF16PtrFromString(s)
  167. if e != nil {
  168. return nil, e
  169. }
  170. e = ConvertStringSidToSid(p, &sid)
  171. if e != nil {
  172. return nil, e
  173. }
  174. defer LocalFree((Handle)(unsafe.Pointer(sid)))
  175. return sid.Copy()
  176. }
  177. // LookupSID retrieves a security identifier sid for the account
  178. // and the name of the domain on which the account was found.
  179. // System specify target computer to search.
  180. func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
  181. if len(account) == 0 {
  182. return nil, "", 0, syscall.EINVAL
  183. }
  184. acc, e := UTF16PtrFromString(account)
  185. if e != nil {
  186. return nil, "", 0, e
  187. }
  188. var sys *uint16
  189. if len(system) > 0 {
  190. sys, e = UTF16PtrFromString(system)
  191. if e != nil {
  192. return nil, "", 0, e
  193. }
  194. }
  195. n := uint32(50)
  196. dn := uint32(50)
  197. for {
  198. b := make([]byte, n)
  199. db := make([]uint16, dn)
  200. sid = (*SID)(unsafe.Pointer(&b[0]))
  201. e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
  202. if e == nil {
  203. return sid, UTF16ToString(db), accType, nil
  204. }
  205. if e != ERROR_INSUFFICIENT_BUFFER {
  206. return nil, "", 0, e
  207. }
  208. if n <= uint32(len(b)) {
  209. return nil, "", 0, e
  210. }
  211. }
  212. }
  213. // String converts sid to a string format
  214. // suitable for display, storage, or transmission.
  215. func (sid *SID) String() (string, error) {
  216. var s *uint16
  217. e := ConvertSidToStringSid(sid, &s)
  218. if e != nil {
  219. return "", e
  220. }
  221. defer LocalFree((Handle)(unsafe.Pointer(s)))
  222. return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
  223. }
  224. // Len returns the length, in bytes, of a valid security identifier sid.
  225. func (sid *SID) Len() int {
  226. return int(GetLengthSid(sid))
  227. }
  228. // Copy creates a duplicate of security identifier sid.
  229. func (sid *SID) Copy() (*SID, error) {
  230. b := make([]byte, sid.Len())
  231. sid2 := (*SID)(unsafe.Pointer(&b[0]))
  232. e := CopySid(uint32(len(b)), sid2, sid)
  233. if e != nil {
  234. return nil, e
  235. }
  236. return sid2, nil
  237. }
  238. // LookupAccount retrieves the name of the account for this sid
  239. // and the name of the first domain on which this sid is found.
  240. // System specify target computer to search for.
  241. func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
  242. var sys *uint16
  243. if len(system) > 0 {
  244. sys, err = UTF16PtrFromString(system)
  245. if err != nil {
  246. return "", "", 0, err
  247. }
  248. }
  249. n := uint32(50)
  250. dn := uint32(50)
  251. for {
  252. b := make([]uint16, n)
  253. db := make([]uint16, dn)
  254. e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
  255. if e == nil {
  256. return UTF16ToString(b), UTF16ToString(db), accType, nil
  257. }
  258. if e != ERROR_INSUFFICIENT_BUFFER {
  259. return "", "", 0, e
  260. }
  261. if n <= uint32(len(b)) {
  262. return "", "", 0, e
  263. }
  264. }
  265. }
  266. const (
  267. // do not reorder
  268. TOKEN_ASSIGN_PRIMARY = 1 << iota
  269. TOKEN_DUPLICATE
  270. TOKEN_IMPERSONATE
  271. TOKEN_QUERY
  272. TOKEN_QUERY_SOURCE
  273. TOKEN_ADJUST_PRIVILEGES
  274. TOKEN_ADJUST_GROUPS
  275. TOKEN_ADJUST_DEFAULT
  276. TOKEN_ADJUST_SESSIONID
  277. TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
  278. TOKEN_ASSIGN_PRIMARY |
  279. TOKEN_DUPLICATE |
  280. TOKEN_IMPERSONATE |
  281. TOKEN_QUERY |
  282. TOKEN_QUERY_SOURCE |
  283. TOKEN_ADJUST_PRIVILEGES |
  284. TOKEN_ADJUST_GROUPS |
  285. TOKEN_ADJUST_DEFAULT |
  286. TOKEN_ADJUST_SESSIONID
  287. TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
  288. TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
  289. TOKEN_ADJUST_PRIVILEGES |
  290. TOKEN_ADJUST_GROUPS |
  291. TOKEN_ADJUST_DEFAULT
  292. TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
  293. )
  294. const (
  295. // do not reorder
  296. TokenUser = 1 + iota
  297. TokenGroups
  298. TokenPrivileges
  299. TokenOwner
  300. TokenPrimaryGroup
  301. TokenDefaultDacl
  302. TokenSource
  303. TokenType
  304. TokenImpersonationLevel
  305. TokenStatistics
  306. TokenRestrictedSids
  307. TokenSessionId
  308. TokenGroupsAndPrivileges
  309. TokenSessionReference
  310. TokenSandBoxInert
  311. TokenAuditPolicy
  312. TokenOrigin
  313. TokenElevationType
  314. TokenLinkedToken
  315. TokenElevation
  316. TokenHasRestrictions
  317. TokenAccessInformation
  318. TokenVirtualizationAllowed
  319. TokenVirtualizationEnabled
  320. TokenIntegrityLevel
  321. TokenUIAccess
  322. TokenMandatoryPolicy
  323. TokenLogonSid
  324. MaxTokenInfoClass
  325. )
  326. type SIDAndAttributes struct {
  327. Sid *SID
  328. Attributes uint32
  329. }
  330. type Tokenuser struct {
  331. User SIDAndAttributes
  332. }
  333. type Tokenprimarygroup struct {
  334. PrimaryGroup *SID
  335. }
  336. type Tokengroups struct {
  337. GroupCount uint32
  338. Groups [1]SIDAndAttributes
  339. }
  340. // Authorization Functions
  341. //sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
  342. //sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
  343. //sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
  344. //sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
  345. // An access token contains the security information for a logon session.
  346. // The system creates an access token when a user logs on, and every
  347. // process executed on behalf of the user has a copy of the token.
  348. // The token identifies the user, the user's groups, and the user's
  349. // privileges. The system uses the token to control access to securable
  350. // objects and to control the ability of the user to perform various
  351. // system-related operations on the local computer.
  352. type Token Handle
  353. // OpenCurrentProcessToken opens the access token
  354. // associated with current process.
  355. func OpenCurrentProcessToken() (Token, error) {
  356. p, e := GetCurrentProcess()
  357. if e != nil {
  358. return 0, e
  359. }
  360. var t Token
  361. e = OpenProcessToken(p, TOKEN_QUERY, &t)
  362. if e != nil {
  363. return 0, e
  364. }
  365. return t, nil
  366. }
  367. // Close releases access to access token.
  368. func (t Token) Close() error {
  369. return CloseHandle(Handle(t))
  370. }
  371. // getInfo retrieves a specified type of information about an access token.
  372. func (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. // GetTokenUser retrieves access token t user account information.
  389. func (t Token) GetTokenUser() (*Tokenuser, error) {
  390. i, e := t.getInfo(TokenUser, 50)
  391. if e != nil {
  392. return nil, e
  393. }
  394. return (*Tokenuser)(i), nil
  395. }
  396. // GetTokenGroups retrieves group accounts associated with access token t.
  397. func (t Token) GetTokenGroups() (*Tokengroups, error) {
  398. i, e := t.getInfo(TokenGroups, 50)
  399. if e != nil {
  400. return nil, e
  401. }
  402. return (*Tokengroups)(i), nil
  403. }
  404. // GetTokenPrimaryGroup retrieves access token t primary group information.
  405. // A pointer to a SID structure representing a group that will become
  406. // the primary group of any objects created by a process using this access token.
  407. func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
  408. i, e := t.getInfo(TokenPrimaryGroup, 50)
  409. if e != nil {
  410. return nil, e
  411. }
  412. return (*Tokenprimarygroup)(i), nil
  413. }
  414. // GetUserProfileDirectory retrieves path to the
  415. // root directory of the access token t user's profile.
  416. func (t Token) GetUserProfileDirectory() (string, error) {
  417. n := uint32(100)
  418. for {
  419. b := make([]uint16, n)
  420. e := GetUserProfileDirectory(t, &b[0], &n)
  421. if e == nil {
  422. return UTF16ToString(b), nil
  423. }
  424. if e != ERROR_INSUFFICIENT_BUFFER {
  425. return "", e
  426. }
  427. if n <= uint32(len(b)) {
  428. return "", e
  429. }
  430. }
  431. }
  432. // IsMember reports whether the access token t is a member of the provided SID.
  433. func (t Token) IsMember(sid *SID) (bool, error) {
  434. var b int32
  435. if e := checkTokenMembership(t, sid, &b); e != nil {
  436. return false, e
  437. }
  438. return b != 0, nil
  439. }