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.

446 lines
14 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. shadowse.c
  5. Abstract:
  6. This module implements all security related functions for disconnected
  7. operation of Client Side Caching
  8. Revision History:
  9. Balan Sethu Raman [SethuR] 6-October-1997
  10. Notes:
  11. In NT ACL(Access Control lists) provide the necessary mechanism for
  12. denying/granting permissions to users. Each user is associated with a SID.
  13. The ACLs are specified in terms of SIDs associated with groups of users as
  14. well as individual users. Each user is associated with a token at runtime
  15. which details the various groups a user is a member of and this token is
  16. used to evaluate the ACLs. This is complicated by the fact that there are
  17. local groups associated with various machines. Therefore the token/context
  18. associated with an user varies from machine.
  19. In connected mode the credentials associated with a given user are shipped
  20. to the server where they are validated and the appropriate token created.
  21. This token is used subsequently in the evaluation of ACLs.
  22. This presents us with two options in implementing security for disconnected
  23. operation -- lazy evaluation and eager evaluation. In lazy evaluation the
  24. evaluation of ACLs is done on demand but the preparatory work for this
  25. evaluation is done in connected mode. On the other hand in eager evaluation
  26. the ACLs are evaluated and the maximal rights are stored as part of the CSC
  27. database. These rights are used to determine the appropriate access.
  28. The advantage of lazy evaluation is that the database is no longer constrained
  29. by previous access requirements while in eager evaluation we require that the
  30. user have accessed the file in connected mode in order to correctly determine
  31. the rights in disconnected mode. The flip side is that Lazy Evaluation is
  32. tougher to implement ( requires modifications in security/DS ) while the
  33. eager evaluation implementation is very easy.
  34. The current implementation corresponds to a simplified form of eager evaluation
  35. strategy. Appropriate encapsulation has been provided to allow us to
  36. swicth over to a lazy evaluation mode easily.
  37. There are three facets of the implementation
  38. 1) Storing/Retreiving Access information
  39. 2) Denying/Granting access based upon the stored access information.
  40. 3) Persisting the SID/index mapping
  41. Currently associated with each file/directory in the CSC database there is a
  42. security blob. This blob is an in
  43. --*/
  44. #include "precomp.h"
  45. #pragma hdrstop
  46. #pragma code_seg("PAGE")
  47. DWORD
  48. CscUpdateCachedSecurityInformation(
  49. PCACHED_SECURITY_INFORMATION pCachedSecurityInformation,
  50. ULONG CachedSecurityInformationLength,
  51. ULONG NumberOfSids,
  52. PCSC_SID_ACCESS_RIGHTS pSidAccessRights)
  53. /*++
  54. Routine Description:
  55. This routine updates the access rights for a given number of sids in the
  56. given cached security information structure. This routine centralizes the
  57. update process required for share level security as well as the object level
  58. security into a single routine since the on disk format for both these
  59. cases are the same. However, different APIs are required to update the
  60. in memory data structures.
  61. Arguments:
  62. pCachedSecurityInformation - the cached security information instance
  63. CachedSecurityInformationLength - the length of the cached information
  64. NumberOfSids - the number of sids for which the access rights needs to be
  65. updated
  66. pSidAccessRights - an array of the sids and the corresponding access rights.
  67. Return Value:
  68. ERROR_SUCCESS if successful, otherwise appropriate error
  69. Notes:
  70. The current implementation of this routine is based upon the assumption that
  71. the number of Sid mappings stored on a per file basis is very small ( 8 at most).
  72. If this assumption is changed this routine needs to be reworked.
  73. --*/
  74. {
  75. DWORD Status = ERROR_SUCCESS;
  76. ULONG i,j,cntNewRights=0;
  77. CACHED_SECURITY_INFORMATION NewSecurityInformation;
  78. ASSERT(CachedSecurityInformationLength == sizeof(CACHED_SECURITY_INFORMATION));
  79. if (NumberOfSids > CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES) {
  80. return ERROR_BUFFER_OVERFLOW;
  81. } else if (NumberOfSids == 0) {
  82. return ERROR_SUCCESS;
  83. }
  84. // NB assumption, CSC_INVALID_INDEX is 0
  85. memset(&NewSecurityInformation, 0, sizeof(NewSecurityInformation));
  86. // from the array of new rights
  87. for (i = 0; i < NumberOfSids; i++) {
  88. CSC_SID_INDEX SidIndex;
  89. // map the sid to a sid index
  90. SidIndex = CscMapSidToIndex(
  91. pSidAccessRights[i].pSid,
  92. pSidAccessRights[i].SidLength);
  93. if (SidIndex == CSC_INVALID_SID_INDEX) {
  94. // Map the new sid
  95. Status = CscAddSidToDatabase(
  96. pSidAccessRights[i].pSid,
  97. pSidAccessRights[i].SidLength,
  98. &SidIndex);
  99. if (Status != STATUS_SUCCESS)
  100. {
  101. return Status;
  102. }
  103. }
  104. NewSecurityInformation.AccessRights[i].SidIndex = SidIndex;
  105. NewSecurityInformation.AccessRights[i].MaximalRights =
  106. (USHORT)pSidAccessRights[i].MaximalAccessRights;
  107. cntNewRights++;
  108. }
  109. // now copy the cached rights from old array for those sids which are not already
  110. // there in the new array, till all slots in the new array are full
  111. // this ensures a round robin scheme
  112. ASSERT(cntNewRights && (cntNewRights <= CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES));
  113. for (i=0; i<CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES; ++i)
  114. {
  115. // if all slots in the new array are filled up, break
  116. if (cntNewRights==CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES)
  117. {
  118. break;
  119. }
  120. // if this is a valid sid index
  121. if (pCachedSecurityInformation->AccessRights[i].SidIndex != CSC_INVALID_SID_INDEX)
  122. {
  123. BOOLEAN fFound;
  124. fFound = FALSE;
  125. // check if it is already there in the new array.
  126. for (j=0; j< cntNewRights; ++j)
  127. {
  128. if (NewSecurityInformation.AccessRights[j].SidIndex ==
  129. pCachedSecurityInformation->AccessRights[i].SidIndex)
  130. {
  131. fFound = TRUE;
  132. break;
  133. }
  134. }
  135. // if it isn't in the new array, then we need to copy it
  136. if (!fFound)
  137. {
  138. NewSecurityInformation.AccessRights[cntNewRights] =
  139. pCachedSecurityInformation->AccessRights[i];
  140. ++cntNewRights; // the new array has
  141. }
  142. }
  143. }
  144. // update the cached security info and pass it back
  145. *pCachedSecurityInformation = NewSecurityInformation;
  146. return Status;
  147. }
  148. DWORD
  149. CscAddMaximalAccessRightsForSids(
  150. HSHADOW hParent,
  151. HSHADOW hFile,
  152. ULONG NumberOfSids,
  153. PCSC_SID_ACCESS_RIGHTS pSidAccessRights)
  154. /*++
  155. Routine Description:
  156. This routine updates the access rights for a given number of sids on the
  157. given file
  158. Arguments:
  159. hParent - the parent directory shadow handle
  160. hFile - the shadow handle
  161. NumberOfSids - the number of sids for which the access rights needs to be
  162. updated
  163. pSidAccessRights - an array of the sids and the corresponding access rights.
  164. Return Value:
  165. ERROR_SUCCESS if successful, otherwise appropriate error
  166. Notes:
  167. The current implementation of this routine is based upon the assumption that
  168. the number of Sid mappings stored on a per file basis is very small ( 8 at most).
  169. If this assumption is changed this routine needs to be reworked.
  170. --*/
  171. {
  172. DWORD Status = ERROR_SUCCESS;
  173. CACHED_SECURITY_INFORMATION CachedSecurityInformation;
  174. ULONG BytesReturned, BytesWritten;
  175. BytesReturned = sizeof(CachedSecurityInformation);
  176. Status = GetShadowInfoEx(
  177. hParent,
  178. hFile,
  179. NULL,
  180. NULL,
  181. NULL,
  182. &CachedSecurityInformation,
  183. &BytesReturned);
  184. if ((Status == ERROR_SUCCESS) &&
  185. ((BytesReturned == 0) ||
  186. (BytesReturned == sizeof(CachedSecurityInformation)))) {
  187. Status = CscUpdateCachedSecurityInformation(
  188. &CachedSecurityInformation,
  189. BytesReturned,
  190. NumberOfSids,
  191. pSidAccessRights);
  192. if (Status == ERROR_SUCCESS) {
  193. BytesWritten = sizeof(CachedSecurityInformation);
  194. Status = SetShadowInfoEx(
  195. hParent,
  196. hFile,
  197. NULL,
  198. 0,
  199. SHADOW_FLAGS_OR,
  200. NULL,
  201. &CachedSecurityInformation,
  202. &BytesWritten);
  203. }
  204. }
  205. return Status;
  206. }
  207. DWORD
  208. CscAddMaximalAccessRightsForShare(
  209. HSERVER hShare,
  210. ULONG NumberOfSids,
  211. PCSC_SID_ACCESS_RIGHTS pSidAccessRights)
  212. /*++
  213. Routine Description:
  214. This routine updates the access rights for a given number of sids on the
  215. given share
  216. Arguments:
  217. hShare - the parent directory shadow handle
  218. NumberOfSids - the number of sids for which the access rights needs to be
  219. updated
  220. pSidAccessRights - an array of the sids and the corresponding access rights.
  221. Return Value:
  222. ERROR_SUCCESS if successful, otherwise appropriate error
  223. Notes:
  224. The current implementation of this routine is based upon the assumption that
  225. the number of Sid mappings stored on a per file basis is very small ( 8 at most).
  226. If this assumption is changed this routine needs to be reworked.
  227. --*/
  228. {
  229. DWORD Status = ERROR_SUCCESS;
  230. CACHED_SECURITY_INFORMATION CachedSecurityInformation;
  231. ULONG BytesReturned, BytesWritten;
  232. BytesReturned = sizeof(CachedSecurityInformation);
  233. Status = GetShareInfoEx(
  234. hShare,
  235. NULL,
  236. NULL,
  237. &CachedSecurityInformation,
  238. &BytesReturned);
  239. if ((Status == ERROR_SUCCESS) &&
  240. ((BytesReturned == 0) ||
  241. (BytesReturned == sizeof(CachedSecurityInformation)))) {
  242. Status = CscUpdateCachedSecurityInformation(
  243. &CachedSecurityInformation,
  244. BytesReturned,
  245. NumberOfSids,
  246. pSidAccessRights);
  247. if (Status == ERROR_SUCCESS) {
  248. BytesWritten = sizeof(CachedSecurityInformation);
  249. if (SetShareStatusEx(
  250. hShare,
  251. 0,
  252. SHADOW_FLAGS_OR,
  253. &CachedSecurityInformation,
  254. &BytesWritten) >= 0)
  255. {
  256. Status = STATUS_SUCCESS;
  257. }
  258. {
  259. Status = STATUS_UNSUCCESSFUL;
  260. }
  261. }
  262. }
  263. return Status;
  264. }
  265. DWORD
  266. CscRemoveMaximalAccessRightsForSid(
  267. HSHADOW hParent,
  268. HSHADOW hFile,
  269. PVOID pSid,
  270. ULONG SidLength)
  271. /*++
  272. Routine Description:
  273. This routine removes the cached access rights for a given number of sids on
  274. the given file
  275. Arguments:
  276. hParent - the parent directory shadow handle
  277. hFile - the shadow handle
  278. pSid - the sid for which the cached access rights are revoked.
  279. SidLength - the length of the sid.
  280. Return Value:
  281. ERROR_SUCCESS if successful, otherwise appropriate error
  282. --*/
  283. {
  284. DWORD Status = ERROR_SUCCESS;
  285. USHORT SidIndex;
  286. ULONG BytesRead,BytesWritten,i;
  287. CACHED_SECURITY_INFORMATION CachedSecurityInformation;
  288. SidIndex = CscMapSidToIndex(
  289. pSid,
  290. SidLength);
  291. if (SidIndex != CSC_INVALID_SID_INDEX) {
  292. BytesRead = sizeof(CachedSecurityInformation);
  293. Status = GetShadowInfoEx(
  294. hParent,
  295. hFile,
  296. NULL,
  297. NULL,
  298. NULL,
  299. &CachedSecurityInformation,
  300. &BytesRead);
  301. if ((Status == ERROR_SUCCESS) &&
  302. (BytesRead == sizeof(CachedSecurityInformation))) {
  303. for (i = 0; i < CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES; i++) {
  304. if (CachedSecurityInformation.AccessRights[i].SidIndex == SidIndex) {
  305. CachedSecurityInformation.AccessRights[i].SidIndex =
  306. CSC_INVALID_SID_INDEX;
  307. BytesWritten = sizeof(CachedSecurityInformation);
  308. Status = SetShadowInfoEx(
  309. hParent,
  310. hFile,
  311. NULL,
  312. 0,
  313. SHADOW_FLAGS_OR,
  314. NULL,
  315. &CachedSecurityInformation,
  316. &BytesWritten);
  317. break;
  318. }
  319. }
  320. }
  321. }
  322. return Status;
  323. }
  324.