Source code of Windows XP (NT5)
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.

267 lines
7.3 KiB

  1. // Security.cpp: implementation of the CSecurity class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "amisafe.h"
  6. #include "Security.h"
  7. #ifdef _DEBUG
  8. #undef THIS_FILE
  9. static char THIS_FILE[]=__FILE__;
  10. #define new DEBUG_NEW
  11. #endif
  12. #define TESTPERM_READ 1
  13. #define TESTPERM_WRITE 2
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. CSecurity::CSecurity()
  18. {
  19. }
  20. CSecurity::~CSecurity()
  21. {
  22. }
  23. BOOL CSecurity::IsAdministrator()
  24. {
  25. BOOL fAdmin = FALSE;
  26. HANDLE hToken = NULL;
  27. DWORD dwStatus;
  28. DWORD dwACLSize;
  29. DWORD cbps = sizeof(PRIVILEGE_SET);
  30. PACL pACL = NULL;
  31. PSID psidAdmin = NULL;
  32. PSECURITY_DESCRIPTOR psdAdmin = NULL;
  33. PRIVILEGE_SET ps;
  34. GENERIC_MAPPING gm;
  35. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  36. // Prepare some memory
  37. ZeroMemory(&ps, sizeof(ps));
  38. ZeroMemory(&gm, sizeof(gm));
  39. // Get the Administrators SID
  40. if (AllocateAndInitializeSid(&sia, 2,
  41. SECURITY_BUILTIN_DOMAIN_RID,
  42. DOMAIN_ALIAS_RID_ADMINS,
  43. 0, 0, 0, 0, 0, 0, &psidAdmin) )
  44. {
  45. // Get the Asministrators Security Descriptor (SD)
  46. psdAdmin = LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
  47. if(InitializeSecurityDescriptor(psdAdmin,SECURITY_DESCRIPTOR_REVISION))
  48. {
  49. // Compute size needed for the ACL then allocate the
  50. // memory for it
  51. dwACLSize = sizeof(ACCESS_ALLOWED_ACE) + 8 +
  52. GetLengthSid(psidAdmin) - sizeof(DWORD);
  53. pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
  54. // Initialize the new ACL
  55. if(InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
  56. {
  57. // Add the access-allowed ACE to the DACL
  58. if(AddAccessAllowedAce(pACL,ACL_REVISION2,
  59. (TESTPERM_READ | TESTPERM_WRITE),psidAdmin))
  60. {
  61. // Set our DACL to the Administrator's SD
  62. if (SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))
  63. {
  64. // AccessCheck is downright picky about what is in the SD,
  65. // so set the group and owner
  66. SetSecurityDescriptorGroup(psdAdmin,psidAdmin,FALSE);
  67. SetSecurityDescriptorOwner(psdAdmin,psidAdmin,FALSE);
  68. // Initialize GenericMapping structure even though we
  69. // won't be using generic rights
  70. gm.GenericRead = TESTPERM_READ;
  71. gm.GenericWrite = TESTPERM_WRITE;
  72. gm.GenericExecute = 0;
  73. gm.GenericAll = TESTPERM_READ | TESTPERM_WRITE;
  74. // AccessCheck requires an impersonation token, so lets
  75. // indulge it
  76. ImpersonateSelf(SecurityImpersonation);
  77. if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken))
  78. {
  79. if (!AccessCheck(psdAdmin, hToken, TESTPERM_READ, &gm,
  80. &ps,&cbps,&dwStatus,&fAdmin))
  81. fAdmin = FALSE;
  82. CloseHandle(hToken);
  83. }
  84. }
  85. }
  86. }
  87. LocalFree(pACL);
  88. }
  89. LocalFree(psdAdmin);
  90. FreeSid(psidAdmin);
  91. }
  92. RevertToSelf();
  93. return(fAdmin);
  94. }
  95. BOOL CSecurity::IsUntrusted(void)
  96. {
  97. BOOL fResult = FALSE;
  98. HANDLE hToken;
  99. if (OpenProcessToken(GetCurrentProcess(),
  100. TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) {
  101. fResult = IsTokenUntrusted(hToken);
  102. CloseHandle(hToken);
  103. }
  104. return fResult;
  105. }
  106. // Return TRUE if the token does is not able to access a DACL against the
  107. // Token User SID. This is typically the case in these situations:
  108. // - the User SID is disabled (for deny-use only)
  109. // - there are Restricting SIDs and the User SID is not one of them.
  110. //
  111. // If an error occurs during the evaluation of this check, the result
  112. // returned will be TRUE (assumed untrusted).
  113. //
  114. // The passed token handle must have been opened for TOKEN_QUERY and
  115. // TOKEN_DUPLICATE access or else the evaluation will fail.
  116. BOOL CSecurity::IsTokenUntrusted(HANDLE hToken)
  117. {
  118. BOOL fTrusted = FALSE;
  119. DWORD dwStatus;
  120. DWORD dwACLSize;
  121. DWORD cbps = sizeof(PRIVILEGE_SET);
  122. PACL pACL = NULL;
  123. DWORD dwUserSidSize;
  124. PTOKEN_USER psidUser = NULL;
  125. PSECURITY_DESCRIPTOR psdUser = NULL;
  126. PRIVILEGE_SET ps;
  127. GENERIC_MAPPING gm;
  128. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  129. HANDLE hImpToken;
  130. // Prepare some memory
  131. ZeroMemory(&ps, sizeof(ps));
  132. ZeroMemory(&gm, sizeof(gm));
  133. // Get the User's SID.
  134. if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwUserSidSize))
  135. {
  136. psidUser = (PTOKEN_USER) LocalAlloc(LPTR, dwUserSidSize);
  137. if (psidUser != NULL)
  138. {
  139. if (GetTokenInformation(hToken, TokenUser, psidUser, dwUserSidSize, &dwUserSidSize))
  140. {
  141. // Create the Security Descriptor (SD)
  142. psdUser = LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
  143. if(InitializeSecurityDescriptor(psdUser,SECURITY_DESCRIPTOR_REVISION))
  144. {
  145. // Compute size needed for the ACL then allocate the
  146. // memory for it
  147. dwACLSize = sizeof(ACCESS_ALLOWED_ACE) + 8 +
  148. GetLengthSid(psidUser->User.Sid) - sizeof(DWORD);
  149. pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
  150. // Initialize the new ACL
  151. if(InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
  152. {
  153. // Add the access-allowed ACE to the DACL
  154. if(AddAccessAllowedAce(pACL,ACL_REVISION2,
  155. (TESTPERM_READ | TESTPERM_WRITE),psidUser->User.Sid))
  156. {
  157. // Set our DACL to the Administrator's SD
  158. if (SetSecurityDescriptorDacl(psdUser, TRUE, pACL, FALSE))
  159. {
  160. // AccessCheck is downright picky about what is in the SD,
  161. // so set the group and owner
  162. SetSecurityDescriptorGroup(psdUser,psidUser->User.Sid,FALSE);
  163. SetSecurityDescriptorOwner(psdUser,psidUser->User.Sid,FALSE);
  164. // Initialize GenericMapping structure even though we
  165. // won't be using generic rights
  166. gm.GenericRead = TESTPERM_READ;
  167. gm.GenericWrite = TESTPERM_WRITE;
  168. gm.GenericExecute = 0;
  169. gm.GenericAll = TESTPERM_READ | TESTPERM_WRITE;
  170. if (ImpersonateLoggedOnUser(hToken) &&
  171. OpenThreadToken(GetCurrentThread(),
  172. TOKEN_QUERY, FALSE, &hImpToken))
  173. {
  174. if (!AccessCheck(psdUser, hImpToken, TESTPERM_READ, &gm,
  175. &ps,&cbps,&dwStatus,&fTrusted))
  176. fTrusted = FALSE;
  177. CloseHandle(hImpToken);
  178. }
  179. }
  180. }
  181. }
  182. LocalFree(pACL);
  183. }
  184. LocalFree(psdUser);
  185. }
  186. LocalFree(psidUser);
  187. }
  188. }
  189. RevertToSelf();
  190. return(!fTrusted);
  191. }
  192. BOOL CSecurity::GetLoggedInUsername(LPTSTR szInBuffer, DWORD dwInBufferSize)
  193. {
  194. DWORD dwUserSidSize;
  195. PTOKEN_USER psidUser = NULL;
  196. HANDLE hToken;
  197. // Get the current process token.
  198. if (OpenProcessToken(GetCurrentProcess(),
  199. TOKEN_QUERY | TOKEN_DUPLICATE, &hToken))
  200. {
  201. // Get the User's SID.
  202. if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwUserSidSize))
  203. {
  204. psidUser = (PTOKEN_USER) LocalAlloc(LPTR, dwUserSidSize);
  205. if (psidUser != NULL)
  206. {
  207. if (GetTokenInformation(hToken, TokenUser, psidUser, dwUserSidSize, &dwUserSidSize))
  208. {
  209. TCHAR szDomain[200];
  210. DWORD dwDomainSize = sizeof(szDomain) / sizeof(TCHAR);
  211. SID_NAME_USE eSidUse;
  212. if (LookupAccountSid(
  213. NULL, psidUser->User.Sid,
  214. szInBuffer, &dwInBufferSize,
  215. szDomain, &dwDomainSize, &eSidUse))
  216. {
  217. LocalFree((HLOCAL) psidUser);
  218. CloseHandle(hToken);
  219. return TRUE;
  220. }
  221. }
  222. LocalFree((HLOCAL) psidUser);
  223. }
  224. }
  225. CloseHandle(hToken);
  226. }
  227. return NULL;
  228. }