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.

548 lines
11 KiB

  1. #include "precomp.h"
  2. GENERIC_MAPPING GenericMapping[SPD_OBJECT_COUNT] = {
  3. {
  4. SERVER_READ,
  5. SERVER_WRITE,
  6. SERVER_EXECUTE,
  7. SERVER_ALL_ACCESS
  8. }
  9. };
  10. DWORD
  11. InitializeSPDSecurity(
  12. PSECURITY_DESCRIPTOR * ppSPDSD
  13. )
  14. {
  15. DWORD dwError = 0;
  16. BOOL bOK = FALSE;
  17. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  18. PSID pAdminAliasSid = NULL;
  19. DWORD dwAceCount = 0;
  20. UCHAR AceType[MAX_ACE];
  21. PSID AceSid[MAX_ACE];
  22. ACCESS_MASK AceMask[MAX_ACE];
  23. BYTE InheritFlags[MAX_ACE];
  24. DWORD dwObjectType = SPD_OBJECT_SERVER;
  25. PSECURITY_DESCRIPTOR pSPDSD = NULL;
  26. //
  27. // Administrator Alias SID.
  28. //
  29. bOK = AllocateAndInitializeSid(
  30. &NtAuthority,
  31. 2,
  32. SECURITY_BUILTIN_DOMAIN_RID,
  33. DOMAIN_ALIAS_RID_ADMINS,
  34. 0, 0, 0, 0, 0, 0,
  35. &pAdminAliasSid
  36. );
  37. if (!bOK) {
  38. dwError = GetLastError();
  39. BAIL_ON_WIN32_ERROR(dwError);
  40. }
  41. AceType[dwAceCount] = ACCESS_ALLOWED_ACE_TYPE;
  42. AceSid[dwAceCount] = pAdminAliasSid;
  43. AceMask[dwAceCount] = SERVER_ALL_ACCESS;
  44. InheritFlags[dwAceCount] = 0;
  45. dwAceCount++;
  46. AceType[dwAceCount] = ACCESS_ALLOWED_ACE_TYPE;
  47. AceSid[dwAceCount] = pAdminAliasSid;
  48. AceMask[dwAceCount] = GENERIC_ALL;
  49. InheritFlags[dwAceCount] = INHERIT_ONLY_ACE |
  50. CONTAINER_INHERIT_ACE |
  51. OBJECT_INHERIT_ACE;
  52. dwAceCount++;
  53. if (dwAceCount > MAX_ACE) {
  54. dwError = ERROR_INVALID_PARAMETER;
  55. BAIL_ON_WIN32_ERROR(dwError);
  56. }
  57. dwError = BuildSPDObjectProtection(
  58. dwAceCount,
  59. AceType,
  60. AceSid,
  61. AceMask,
  62. InheritFlags,
  63. pAdminAliasSid,
  64. pAdminAliasSid,
  65. &GenericMapping[dwObjectType],
  66. &pSPDSD
  67. );
  68. BAIL_ON_WIN32_ERROR(dwError);
  69. *ppSPDSD = pSPDSD;
  70. cleanup:
  71. if (pAdminAliasSid) {
  72. FreeSid(pAdminAliasSid);
  73. }
  74. return (dwError);
  75. error:
  76. *ppSPDSD = NULL;
  77. goto cleanup;
  78. }
  79. DWORD
  80. BuildSPDObjectProtection(
  81. DWORD dwAceCount,
  82. PUCHAR pAceType,
  83. PSID * ppAceSid,
  84. PACCESS_MASK pAceMask,
  85. PBYTE pInheritFlags,
  86. PSID pOwnerSid,
  87. PSID pGroupSid,
  88. PGENERIC_MAPPING pGenericMap,
  89. PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  90. )
  91. {
  92. DWORD dwError = 0;
  93. BOOL bOK = FALSE;
  94. SECURITY_DESCRIPTOR Absolute;
  95. DWORD dwDaclLength = 0;
  96. DWORD i = 0;
  97. PACL pTmpAcl= NULL;
  98. PACCESS_ALLOWED_ACE pTmpAce = NULL;
  99. DWORD dwSDLength = 0;
  100. PSECURITY_DESCRIPTOR pRelative = NULL;
  101. bOK = InitializeSecurityDescriptor(
  102. &Absolute,
  103. SECURITY_DESCRIPTOR_REVISION1
  104. );
  105. if (!bOK) {
  106. dwError = GetLastError();
  107. BAIL_ON_WIN32_ERROR(dwError);
  108. }
  109. bOK = SetSecurityDescriptorOwner(
  110. &Absolute,
  111. pOwnerSid,
  112. FALSE
  113. );
  114. if (!bOK) {
  115. dwError = GetLastError();
  116. BAIL_ON_WIN32_ERROR(dwError);
  117. }
  118. bOK = SetSecurityDescriptorGroup(
  119. &Absolute,
  120. pGroupSid,
  121. FALSE
  122. );
  123. if (!bOK) {
  124. dwError = GetLastError();
  125. BAIL_ON_WIN32_ERROR(dwError);
  126. }
  127. //
  128. // Build the Discretionary ACL:
  129. // Calculate its length.
  130. // Allocate it.
  131. // Initialize it.
  132. // Add each ACE.
  133. // Set ACE as InheritOnly if necessary.
  134. // Add it to the security descriptor.
  135. //
  136. dwDaclLength = (DWORD) sizeof(ACL);
  137. for (i = 0; i < dwAceCount; i++) {
  138. dwDaclLength += GetLengthSid(ppAceSid[i]) +
  139. (DWORD) sizeof(ACCESS_ALLOWED_ACE) -
  140. (DWORD) sizeof(DWORD);
  141. //
  142. // Subtract out SidStart field length.
  143. //
  144. }
  145. pTmpAcl = (PACL) AllocSPDMem(dwDaclLength);
  146. if (!pTmpAcl) {
  147. dwError = ERROR_OUTOFMEMORY;
  148. BAIL_ON_WIN32_ERROR(dwError);
  149. }
  150. bOK = InitializeAcl(
  151. pTmpAcl,
  152. dwDaclLength,
  153. ACL_REVISION2
  154. );
  155. if (!bOK) {
  156. dwError = GetLastError();
  157. BAIL_ON_WIN32_ERROR(dwError);
  158. }
  159. for (i = 0; i < dwAceCount; i++) {
  160. if (pAceType[i] == ACCESS_ALLOWED_ACE_TYPE) {
  161. bOK = AddAccessAllowedAce(
  162. pTmpAcl,
  163. ACL_REVISION2,
  164. pAceMask[i],
  165. ppAceSid[i]
  166. );
  167. }
  168. else {
  169. bOK = AddAccessDeniedAce(
  170. pTmpAcl,
  171. ACL_REVISION2,
  172. pAceMask[i],
  173. ppAceSid[i]
  174. );
  175. }
  176. if (!bOK) {
  177. dwError = GetLastError();
  178. BAIL_ON_WIN32_ERROR(dwError);
  179. }
  180. if (pInheritFlags[i] != 0) {
  181. bOK = GetAce(pTmpAcl, i, (LPVOID *) &pTmpAce);
  182. if (!bOK) {
  183. dwError = GetLastError();
  184. BAIL_ON_WIN32_ERROR(dwError);
  185. }
  186. pTmpAce->Header.AceFlags = pInheritFlags[i];
  187. }
  188. }
  189. bOK = SetSecurityDescriptorDacl(
  190. &Absolute,
  191. TRUE,
  192. pTmpAcl,
  193. FALSE
  194. );
  195. if (!bOK) {
  196. dwError = GetLastError();
  197. BAIL_ON_WIN32_ERROR(dwError);
  198. }
  199. //
  200. // Convert the security descriptor from absolute to self-relative:
  201. // Get the length needed.
  202. // Allocate that much memory.
  203. // Copy it.
  204. // Free the generated absolute ACLs.
  205. //
  206. dwSDLength = GetSecurityDescriptorLength(&Absolute);
  207. //
  208. // Must allocate the relative SD from heap.
  209. //
  210. pRelative = LocalAlloc(0, dwSDLength);
  211. if (!pRelative) {
  212. dwError = ERROR_OUTOFMEMORY;
  213. BAIL_ON_WIN32_ERROR(dwError);
  214. }
  215. bOK = MakeSelfRelativeSD(&Absolute, pRelative, &dwSDLength);
  216. if (!bOK) {
  217. dwError = GetLastError();
  218. BAIL_ON_WIN32_ERROR(dwError);
  219. }
  220. *ppSecurityDescriptor = pRelative;
  221. cleanup:
  222. if (pTmpAcl){
  223. FreeSPDMem(pTmpAcl);
  224. }
  225. return (dwError);
  226. error:
  227. *ppSecurityDescriptor = NULL;
  228. if (pRelative) {
  229. LocalFree(pRelative);
  230. }
  231. goto cleanup;
  232. }
  233. DWORD
  234. ValidateSecurity(
  235. DWORD dwObjectType,
  236. ACCESS_MASK DesiredAccess,
  237. LPVOID pObjectHandle,
  238. PACCESS_MASK pGrantedAccess
  239. )
  240. {
  241. DWORD dwError = 0;
  242. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  243. ACCESS_MASK MappedDesiredAccess = 0;
  244. BOOL bOK = FALSE;
  245. HANDLE hClientToken = NULL;
  246. BYTE PrivilegeSetBuffer[256];
  247. DWORD dwPrivilegeSetBufferLen = 256;
  248. PPRIVILEGE_SET pPrivilegeSet = NULL;
  249. BOOL bAccessCheckOK = FALSE;
  250. ACCESS_MASK GrantedAccess = 0;
  251. BOOL bAccessStatus = FALSE;
  252. memset(PrivilegeSetBuffer, 0, dwPrivilegeSetBufferLen);
  253. switch (dwObjectType) {
  254. case SPD_OBJECT_SERVER:
  255. pSecurityDescriptor = gpSPDSD;
  256. break;
  257. default:
  258. dwError = ERROR_ACCESS_DENIED;
  259. BAIL_ON_WIN32_ERROR(dwError);
  260. break;
  261. }
  262. MapGenericToSpecificAccess(
  263. dwObjectType,
  264. DesiredAccess,
  265. &MappedDesiredAccess
  266. );
  267. bOK = GetTokenHandle(&hClientToken);
  268. if (!bOK) {
  269. dwError = GetLastError();
  270. BAIL_ON_WIN32_ERROR(dwError);
  271. }
  272. pPrivilegeSet = (PPRIVILEGE_SET) PrivilegeSetBuffer;
  273. bAccessCheckOK = AccessCheck(
  274. pSecurityDescriptor,
  275. hClientToken,
  276. MappedDesiredAccess,
  277. &GenericMapping[dwObjectType],
  278. pPrivilegeSet,
  279. &dwPrivilegeSetBufferLen,
  280. &GrantedAccess,
  281. &bAccessStatus
  282. );
  283. if (!bAccessCheckOK) {
  284. if (GetLastError() == ERROR_NO_IMPERSONATION_TOKEN) {
  285. dwError = ERROR_SUCCESS;
  286. GrantedAccess = MappedDesiredAccess;
  287. }
  288. else {
  289. dwError = GetLastError();
  290. BAIL_ON_WIN32_ERROR(dwError);
  291. }
  292. }
  293. else {
  294. if (!bAccessStatus) {
  295. dwError = GetLastError();
  296. BAIL_ON_WIN32_ERROR(dwError);
  297. }
  298. }
  299. if (pGrantedAccess) {
  300. *pGrantedAccess = GrantedAccess;
  301. }
  302. cleanup:
  303. if (hClientToken) {
  304. CloseHandle(hClientToken);
  305. }
  306. return (dwError);
  307. error:
  308. if (pGrantedAccess) {
  309. *pGrantedAccess = 0;
  310. }
  311. goto cleanup;
  312. }
  313. VOID
  314. MapGenericToSpecificAccess(
  315. DWORD dwObjectType,
  316. ACCESS_MASK GenericAccess,
  317. PACCESS_MASK pSpecificAccess
  318. )
  319. {
  320. *pSpecificAccess = GenericAccess;
  321. MapGenericMask(
  322. pSpecificAccess,
  323. &GenericMapping[dwObjectType]
  324. );
  325. }
  326. BOOL
  327. GetTokenHandle(
  328. PHANDLE phToken
  329. )
  330. {
  331. if (!OpenThreadToken(
  332. GetCurrentThread(),
  333. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  334. TRUE,
  335. phToken)) {
  336. if (GetLastError() == ERROR_NO_TOKEN) {
  337. //
  338. // This means that there's no impersonation.
  339. // Get the token out of the process.
  340. //
  341. if (!OpenProcessToken(
  342. GetCurrentProcess(),
  343. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  344. phToken)) {
  345. return (FALSE);
  346. }
  347. }
  348. else {
  349. return (FALSE);
  350. }
  351. }
  352. return (TRUE);
  353. }
  354. DWORD
  355. ValidateMMSecurity(
  356. DWORD dwObjectType,
  357. ACCESS_MASK DesiredAccess,
  358. LPVOID pObjectHandle,
  359. PACCESS_MASK pGrantedAccess
  360. )
  361. {
  362. DWORD dwError = 0;
  363. ACCESS_MASK GrantedAccess = 0;
  364. dwError = ValidateSecurity(
  365. dwObjectType,
  366. DesiredAccess,
  367. pObjectHandle,
  368. &GrantedAccess
  369. );
  370. BAIL_ON_WIN32_ERROR(dwError);
  371. if (pGrantedAccess) {
  372. *pGrantedAccess = GrantedAccess;
  373. }
  374. return (dwError);
  375. error:
  376. if (pGrantedAccess) {
  377. *pGrantedAccess = 0;
  378. }
  379. return (dwError);
  380. }
  381. DWORD
  382. ValidateTxSecurity(
  383. DWORD dwObjectType,
  384. ACCESS_MASK DesiredAccess,
  385. LPVOID pObjectHandle,
  386. PACCESS_MASK pGrantedAccess
  387. )
  388. {
  389. DWORD dwError = 0;
  390. ACCESS_MASK GrantedAccess = 0;
  391. dwError = ValidateSecurity(
  392. dwObjectType,
  393. DesiredAccess,
  394. pObjectHandle,
  395. &GrantedAccess
  396. );
  397. BAIL_ON_WIN32_ERROR(dwError);
  398. if (pGrantedAccess) {
  399. *pGrantedAccess = GrantedAccess;
  400. }
  401. return (dwError);
  402. error:
  403. if (pGrantedAccess) {
  404. *pGrantedAccess = 0;
  405. }
  406. return (dwError);
  407. }
  408. DWORD
  409. ValidateTnSecurity(
  410. DWORD dwObjectType,
  411. ACCESS_MASK DesiredAccess,
  412. LPVOID pObjectHandle,
  413. PACCESS_MASK pGrantedAccess
  414. )
  415. {
  416. DWORD dwError = 0;
  417. ACCESS_MASK GrantedAccess = 0;
  418. dwError = ValidateSecurity(
  419. dwObjectType,
  420. DesiredAccess,
  421. pObjectHandle,
  422. &GrantedAccess
  423. );
  424. BAIL_ON_WIN32_ERROR(dwError);
  425. if (pGrantedAccess) {
  426. *pGrantedAccess = GrantedAccess;
  427. }
  428. return (dwError);
  429. error:
  430. if (pGrantedAccess) {
  431. *pGrantedAccess = 0;
  432. }
  433. return (dwError);
  434. }