Leaked source code of windows server 2003
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.

438 lines
12 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: security.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes: None.
  11. //
  12. // Functions: None.
  13. //
  14. // History: 26-Jun-96 MarkBl Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "..\pch\headers.hxx"
  18. #pragma hdrstop
  19. #include <common.hxx> // MAX_SID_SIZE
  20. #include "..\inc\debug.hxx"
  21. #include "..\inc\security.hxx"
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Function: CreateSecurityDescriptor
  25. //
  26. // Synopsis: Create a security descriptor with the ACE information
  27. // specified.
  28. //
  29. // Arguments: [AceCount] -- ACE count (no. of rgMyAce and rgAce elements).
  30. // [rgMyAce] -- ACE specification array.
  31. // [rgAce] -- Caller allocated array of ptrs to ACEs so
  32. // this function doesn't have to allocate it.
  33. //
  34. // Returns: TRUE -- Function succeeded,
  35. // FALSE -- Otherwise.
  36. //
  37. // Notes: None.
  38. //
  39. //----------------------------------------------------------------------------
  40. PSECURITY_DESCRIPTOR
  41. CreateSecurityDescriptor(
  42. DWORD AceCount,
  43. MYACE rgMyAce[],
  44. PACCESS_ALLOWED_ACE rgAce[],
  45. DWORD * pStatus)
  46. {
  47. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  48. PACL pAcl = NULL;
  49. DWORD LengthAces = 0;
  50. DWORD LengthAcl;
  51. DWORD i;
  52. DWORD Status;
  53. for (i = 0; i < AceCount; i++)
  54. {
  55. rgAce[i] = CreateAccessAllowedAce(rgMyAce[i].pSid,
  56. rgMyAce[i].AccessMask,
  57. 0,
  58. rgMyAce[i].InheritFlags,
  59. &Status);
  60. if (rgAce[i] == NULL)
  61. {
  62. goto ErrorExit;
  63. }
  64. LengthAces += rgAce[i]->Header.AceSize;
  65. }
  66. //
  67. // Calculate ACL and SD sizes
  68. //
  69. LengthAcl = sizeof(ACL) + LengthAces;
  70. //
  71. // Create the ACL.
  72. //
  73. pAcl = (PACL)LocalAlloc(LMEM_FIXED, LengthAcl);
  74. if (pAcl == NULL)
  75. {
  76. Status = ERROR_NOT_ENOUGH_MEMORY;
  77. schDebugOut((DEB_ERROR,
  78. "CreateSecurityDescriptor, ACL allocation failed\n"));
  79. goto ErrorExit;
  80. }
  81. if (!InitializeAcl(pAcl, LengthAcl, ACL_REVISION))
  82. {
  83. Status = GetLastError();
  84. schDebugOut((DEB_ERROR,
  85. "CreateSecurityDescriptor, InitializeAcl failed, " \
  86. "status = 0x%lx\n",
  87. Status));
  88. goto ErrorExit;
  89. }
  90. for (i = 0; i < AceCount; i++)
  91. {
  92. if (!AddAce(pAcl,
  93. ACL_REVISION,
  94. 0,
  95. rgAce[i],
  96. rgAce[i]->Header.AceSize))
  97. {
  98. Status = GetLastError();
  99. schDebugOut((DEB_ERROR,
  100. "CreateSecurityDescriptor, AddAce[%l] failed, " \
  101. "status = 0x%lx\n", i, Status));
  102. goto ErrorExit;
  103. }
  104. LocalFree(rgAce[i]);
  105. rgAce[i] = NULL;
  106. }
  107. //
  108. // Create the security descriptor.
  109. //
  110. pSecurityDescriptor = LocalAlloc(LMEM_FIXED,
  111. SECURITY_DESCRIPTOR_MIN_LENGTH);
  112. if (pSecurityDescriptor == NULL)
  113. {
  114. Status = ERROR_NOT_ENOUGH_MEMORY;
  115. schDebugOut((DEB_ERROR,
  116. "CreateSecurityDescriptor, SECURITY_DESCRIPTOR allocation " \
  117. "failed\n"));
  118. goto ErrorExit;
  119. }
  120. if (!InitializeSecurityDescriptor(pSecurityDescriptor,
  121. SECURITY_DESCRIPTOR_REVISION))
  122. {
  123. Status = GetLastError();
  124. schDebugOut((DEB_ERROR,
  125. "CreateSecurityDescriptor, InitializeSecurityDescriptor " \
  126. "failed, status = 0x%lx\n",
  127. Status));
  128. goto ErrorExit;
  129. }
  130. if (!SetSecurityDescriptorDacl(pSecurityDescriptor,
  131. TRUE,
  132. pAcl,
  133. FALSE))
  134. {
  135. Status = GetLastError();
  136. schDebugOut((DEB_ERROR,
  137. "CreateSecurityDescriptor, SetSecurityDescriptorDacl " \
  138. "failed, status = 0x%lx\n",
  139. Status));
  140. goto ErrorExit;
  141. }
  142. if (pStatus != NULL) *pStatus = ERROR_SUCCESS;
  143. return(pSecurityDescriptor);
  144. ErrorExit:
  145. for (i = 0; i < AceCount; i++)
  146. {
  147. if (rgAce[i] != NULL)
  148. {
  149. LocalFree(rgAce[i]);
  150. rgAce[i] = NULL;
  151. }
  152. }
  153. if (pAcl != NULL) LocalFree(pAcl);
  154. if (pSecurityDescriptor != NULL) LocalFree(pSecurityDescriptor);
  155. if (pStatus != NULL) *pStatus = Status;
  156. return(NULL);
  157. }
  158. //+---------------------------------------------------------------------------
  159. //
  160. // Function: DeleteSecurityDescriptor
  161. //
  162. // Synopsis: Deallocate the security descriptor allocated in
  163. // CreateSecurityDescriptor.
  164. //
  165. // Arguments: [pSecurityDescriptor] -- SD returned from
  166. // CreateSecurityDescriptor.
  167. //
  168. // Returns: None.
  169. //
  170. // Notes: None.
  171. //
  172. //----------------------------------------------------------------------------
  173. void
  174. DeleteSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor)
  175. {
  176. BOOL fPresent;
  177. BOOL fDefaulted;
  178. PACL pAcl;
  179. schAssert(pSecurityDescriptor != NULL);
  180. if (GetSecurityDescriptorDacl(pSecurityDescriptor,
  181. &fPresent,
  182. &pAcl,
  183. &fDefaulted))
  184. {
  185. if (fPresent && pAcl != NULL)
  186. {
  187. LocalFree(pAcl);
  188. }
  189. }
  190. else
  191. {
  192. schDebugOut((DEB_ERROR,
  193. "DeleteSecurityDescriptor, GetSecurityDescriptorDacl failed, " \
  194. "status = 0x%lx\n",
  195. GetLastError()));
  196. }
  197. LocalFree(pSecurityDescriptor);
  198. }
  199. //+---------------------------------------------------------------------------
  200. //
  201. // Function: CreateAccessAllowedAce
  202. //
  203. // Synopsis: Scavenged code from winlogon to create an access allowed ACE.
  204. // Modified a bit to use Win32 vs. Rtl.
  205. //
  206. // Arguments: [pSid] -- Sid to which this ACE is applied.
  207. // [AccessMask] -- ACE access mask value.
  208. // [AceFlags] -- ACE flags value.
  209. // [InheritFlags] -- ACE inherit flags value.
  210. //
  211. // Returns: Created ACE if successful.
  212. // NULL on error.
  213. //
  214. // Notes: None.
  215. //
  216. //----------------------------------------------------------------------------
  217. PACCESS_ALLOWED_ACE
  218. CreateAccessAllowedAce(
  219. PSID pSid,
  220. ACCESS_MASK AccessMask,
  221. UCHAR AceFlags,
  222. UCHAR InheritFlags,
  223. DWORD * pStatus)
  224. {
  225. ULONG LengthSid = GetLengthSid(pSid);
  226. ULONG LengthACE = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + LengthSid;
  227. PACCESS_ALLOWED_ACE Ace;
  228. Ace = (PACCESS_ALLOWED_ACE)LocalAlloc(LMEM_FIXED, LengthACE);
  229. if (Ace == NULL)
  230. {
  231. if (pStatus != NULL) *pStatus = ERROR_NOT_ENOUGH_MEMORY;
  232. schDebugOut((DEB_ERROR,
  233. "CreateAccessAllowedAce, ACE allocation failed\n"));
  234. return(NULL);
  235. }
  236. Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  237. Ace->Header.AceSize = (UCHAR)LengthACE;
  238. Ace->Header.AceFlags = AceFlags | InheritFlags;
  239. Ace->Mask = AccessMask;
  240. CopySid(LengthSid, (PSID)(&(Ace->SidStart)), pSid);
  241. if (pStatus != NULL) *pStatus = ERROR_SUCCESS;
  242. return(Ace);
  243. }
  244. //+---------------------------------------------------------------------------
  245. //
  246. // Function: IsThreadCallerAnAdmin
  247. //
  248. // Synopsis: Determine if the user represented by the specified token is a
  249. // member of the administrators group.
  250. //
  251. // Arguments: [hThreadToken] -- Token to check. If NULL, the current
  252. // thread's token is used if there is one, or else the
  253. // current process' token.
  254. //
  255. // Returns: TRUE -- Match
  256. // FALSE -- Thread caller not an admin or an error occurred.
  257. //
  258. //----------------------------------------------------------------------------
  259. BOOL
  260. IsThreadCallerAnAdmin(HANDLE hThreadToken)
  261. {
  262. //
  263. // Create an admin SID to compare against.
  264. //
  265. #if 1
  266. //
  267. // Efficient way - relies on the format of the SID structure (which is
  268. // published in winnt.h) - valid for at least NT 4 and NT 5
  269. //
  270. schAssert(sizeof SID == 12);
  271. const struct
  272. {
  273. SID Sid;
  274. DWORD SubAuthority1;
  275. } AdminSid =
  276. {
  277. { SID_REVISION, // Revision
  278. 2, // SubAuthorityCount
  279. SECURITY_NT_AUTHORITY, // IdentifierAuthority
  280. SECURITY_BUILTIN_DOMAIN_RID }, // SubAuthority[0]
  281. DOMAIN_ALIAS_RID_ADMINS // SubAuthority[1]
  282. };
  283. #else
  284. /*
  285. #error SID structure has changed!
  286. //
  287. // Inefficient way, initialize at run time
  288. //
  289. BYTE AdminSid[MAX_SID_SIZE];
  290. SID_IDENTIFIER_AUTHORITY IdentifierAuthority = SECURITY_NT_AUTHORITY;
  291. if (! InitializeSid(rgbAdminSid, &IdentifierAuthority, 2))
  292. {
  293. schAssert(0);
  294. CHECK_HRESULT(HRESULT_FROM_WIN32(GetLastError()));
  295. return FALSE;
  296. }
  297. *GetSidSubAuthority(rgbAdminSid, 0) = SECURITY_BUILTIN_DOMAIN_RID;
  298. *GetSidSubAuthority(rgbAdminSid, 1) = DOMAIN_ALIAS_RID_ADMINS;
  299. */
  300. #endif
  301. //
  302. // See if the token is a member.
  303. //
  304. BOOL fIsCallerAdmin;
  305. if (!CheckTokenMembership(hThreadToken,
  306. (PSID) &AdminSid,
  307. &fIsCallerAdmin))
  308. {
  309. CHECK_HRESULT(HRESULT_FROM_WIN32(GetLastError()));
  310. return FALSE;
  311. }
  312. return fIsCallerAdmin;
  313. }
  314. //+---------------------------------------------------------------------------
  315. //
  316. // Function: EnablePrivilege
  317. //
  318. // Synopsis: Tries to enable / disable a privilege for the current process.
  319. //
  320. // Arguments: [pszPrivName] - name of privilege to enable / disable.
  321. // [bEnable] - enable / disable switch.
  322. // [pbWasEnabled] - optional pointer to receive the previous
  323. // state of the privilege.
  324. //
  325. // Returns: win32 error code.
  326. //
  327. //----------------------------------------------------------------------------
  328. DWORD
  329. EnablePrivilege(
  330. IN PCWSTR pszPrivName,
  331. IN BOOL bEnable,
  332. OUT PBOOL pbWasEnabled OPTIONAL
  333. )
  334. {
  335. DWORD dwError = ERROR_SUCCESS;
  336. BOOL bSuccess;
  337. HANDLE hToken = 0;
  338. DWORD dwSize;
  339. TOKEN_PRIVILEGES privNew;
  340. TOKEN_PRIVILEGES privOld;
  341. bSuccess = OpenProcessToken(
  342. GetCurrentProcess(),
  343. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  344. &hToken);
  345. if (!bSuccess)
  346. {
  347. dwError = GetLastError();
  348. goto Cleanup;
  349. }
  350. bSuccess = LookupPrivilegeValue(
  351. 0,
  352. pszPrivName,
  353. &privNew.Privileges[0].Luid);
  354. if (!bSuccess)
  355. {
  356. dwError = GetLastError();
  357. goto Cleanup;
  358. }
  359. privNew.PrivilegeCount = 1;
  360. privNew.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
  361. bSuccess = AdjustTokenPrivileges(
  362. hToken,
  363. FALSE,
  364. &privNew,
  365. sizeof(privOld),
  366. &privOld,
  367. &dwSize);
  368. if (!bSuccess)
  369. {
  370. dwError = GetLastError();
  371. goto Cleanup;
  372. }
  373. if (pbWasEnabled)
  374. {
  375. *pbWasEnabled = (privOld.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED)
  376. ? TRUE : FALSE;
  377. }
  378. Cleanup:
  379. if (hToken)
  380. {
  381. CloseHandle(hToken);
  382. }
  383. return dwError;
  384. }