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.

476 lines
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_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
  277. TOKEN_ASSIGN_PRIMARY |
  278. TOKEN_DUPLICATE |
  279. TOKEN_IMPERSONATE |
  280. TOKEN_QUERY |
  281. TOKEN_QUERY_SOURCE |
  282. TOKEN_ADJUST_PRIVILEGES |
  283. TOKEN_ADJUST_GROUPS |
  284. TOKEN_ADJUST_DEFAULT
  285. TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
  286. TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
  287. TOKEN_ADJUST_PRIVILEGES |
  288. TOKEN_ADJUST_GROUPS |
  289. TOKEN_ADJUST_DEFAULT
  290. TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
  291. )
  292. const (
  293. // do not reorder
  294. TokenUser = 1 + iota
  295. TokenGroups
  296. TokenPrivileges
  297. TokenOwner
  298. TokenPrimaryGroup
  299. TokenDefaultDacl
  300. TokenSource
  301. TokenType
  302. TokenImpersonationLevel
  303. TokenStatistics
  304. TokenRestrictedSids
  305. TokenSessionId
  306. TokenGroupsAndPrivileges
  307. TokenSessionReference
  308. TokenSandBoxInert
  309. TokenAuditPolicy
  310. TokenOrigin
  311. TokenElevationType
  312. TokenLinkedToken
  313. TokenElevation
  314. TokenHasRestrictions
  315. TokenAccessInformation
  316. TokenVirtualizationAllowed
  317. TokenVirtualizationEnabled
  318. TokenIntegrityLevel
  319. TokenUIAccess
  320. TokenMandatoryPolicy
  321. TokenLogonSid
  322. MaxTokenInfoClass
  323. )
  324. type SIDAndAttributes struct {
  325. Sid *SID
  326. Attributes uint32
  327. }
  328. type Tokenuser struct {
  329. User SIDAndAttributes
  330. }
  331. type Tokenprimarygroup struct {
  332. PrimaryGroup *SID
  333. }
  334. type Tokengroups struct {
  335. GroupCount uint32
  336. Groups [1]SIDAndAttributes
  337. }
  338. // Authorization Functions
  339. //sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
  340. //sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
  341. //sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
  342. //sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
  343. // An access token contains the security information for a logon session.
  344. // The system creates an access token when a user logs on, and every
  345. // process executed on behalf of the user has a copy of the token.
  346. // The token identifies the user, the user's groups, and the user's
  347. // privileges. The system uses the token to control access to securable
  348. // objects and to control the ability of the user to perform various
  349. // system-related operations on the local computer.
  350. type Token Handle
  351. // OpenCurrentProcessToken opens the access token
  352. // associated with current process.
  353. func 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. // Close releases access to access token.
  366. func (t Token) Close() error {
  367. return CloseHandle(Handle(t))
  368. }
  369. // getInfo retrieves a specified type of information about an access token.
  370. func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
  371. n := uint32(initSize)
  372. for {
  373. b := make([]byte, n)
  374. e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
  375. if e == nil {
  376. return unsafe.Pointer(&b[0]), nil
  377. }
  378. if e != ERROR_INSUFFICIENT_BUFFER {
  379. return nil, e
  380. }
  381. if n <= uint32(len(b)) {
  382. return nil, e
  383. }
  384. }
  385. }
  386. // GetTokenUser retrieves access token t user account information.
  387. func (t Token) GetTokenUser() (*Tokenuser, error) {
  388. i, e := t.getInfo(TokenUser, 50)
  389. if e != nil {
  390. return nil, e
  391. }
  392. return (*Tokenuser)(i), nil
  393. }
  394. // GetTokenGroups retrieves group accounts associated with access token t.
  395. func (t Token) GetTokenGroups() (*Tokengroups, error) {
  396. i, e := t.getInfo(TokenGroups, 50)
  397. if e != nil {
  398. return nil, e
  399. }
  400. return (*Tokengroups)(i), nil
  401. }
  402. // GetTokenPrimaryGroup retrieves access token t primary group information.
  403. // A pointer to a SID structure representing a group that will become
  404. // the primary group of any objects created by a process using this access token.
  405. func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
  406. i, e := t.getInfo(TokenPrimaryGroup, 50)
  407. if e != nil {
  408. return nil, e
  409. }
  410. return (*Tokenprimarygroup)(i), nil
  411. }
  412. // GetUserProfileDirectory retrieves path to the
  413. // root directory of the access token t user's profile.
  414. func (t Token) GetUserProfileDirectory() (string, error) {
  415. n := uint32(100)
  416. for {
  417. b := make([]uint16, n)
  418. e := GetUserProfileDirectory(t, &b[0], &n)
  419. if e == nil {
  420. return UTF16ToString(b), nil
  421. }
  422. if e != ERROR_INSUFFICIENT_BUFFER {
  423. return "", e
  424. }
  425. if n <= uint32(len(b)) {
  426. return "", e
  427. }
  428. }
  429. }
  430. // IsMember reports whether the access token t is a member of the provided SID.
  431. func (t Token) IsMember(sid *SID) (bool, error) {
  432. var b int32
  433. if e := checkTokenMembership(t, sid, &b); e != nil {
  434. return false, e
  435. }
  436. return b != 0, nil
  437. }