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.

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