ReactOS  0.4.11-dev-721-g95bc44e
acchksup.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  AcChkSup.c
8 
9 Abstract:
10 
11  This module implements the FAT access checking routine
12 
13 
14 --*/
15 
16 #include "fatprocs.h"
17 
18 //
19 // Our debug trace level
20 //
21 
22 #define Dbg (DEBUG_TRACE_ACCHKSUP)
23 
27  OUT PACCESS_TOKEN *RestrictedToken
28  );
29 
30 #ifdef ALLOC_PRAGMA
31 #pragma alloc_text(PAGE, FatCheckFileAccess)
32 #pragma alloc_text(PAGE, FatCheckManageVolumeAccess)
33 #pragma alloc_text(PAGE, FatCreateRestrictEveryoneToken)
34 #pragma alloc_text(PAGE, FatExplicitDeviceAccessGranted)
35 #endif
36 
37 
38 BOOLEAN
40  PIRP_CONTEXT IrpContext,
41  IN UCHAR DirentAttributes,
43  )
44 
45 /*++
46 
47 Routine Description:
48 
49  This routine checks if a desired access is allowed to a file represented
50  by the specified DirentAttriubutes.
51 
52 Arguments:
53 
54  DirentAttributes - Supplies the Dirent attributes to check access for
55 
56  DesiredAccess - Supplies the desired access mask that we are checking for
57 
58 Return Value:
59 
60  BOOLEAN - TRUE if access is allowed and FALSE otherwise
61 
62 --*/
63 
64 {
66 
67  DebugTrace(+1, Dbg, "FatCheckFileAccess\n", 0);
68  DebugTrace( 0, Dbg, "DirentAttributes = %8lx\n", DirentAttributes);
69  DebugTrace( 0, Dbg, "DesiredAccess = %8lx\n", *DesiredAccess);
70 
71  PAGED_CODE();
72 
73  //
74  // This procedures is programmed like a string of filters each
75  // filter checks to see if some access is allowed, if it is not allowed
76  // the filter return FALSE to the user without further checks otherwise
77  // it moves on to the next filter. The filter check is to check for
78  // desired access flags that are not allowed for a particular dirent
79  //
80 
81  Result = TRUE;
82 
83  _SEH2_TRY {
84 
85  //
86  // Check for Volume ID or Device Dirents, these are not allowed user
87  // access at all
88  //
89 
90  if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_VOLUME_ID) ||
91  FlagOn(DirentAttributes, FAT_DIRENT_ATTR_DEVICE)) {
92 
93  DebugTrace(0, Dbg, "Cannot access volume id or device\n", 0);
94 
95  try_return( Result = FALSE );
96  }
97 
98  //
99  // Check the desired access for the object - we only blackball that
100  // we do not understand. The model of filesystems using ACLs is that
101  // they do not type the ACL to the object the ACL is on. Permissions
102  // are not checked for consistency vs. the object type - dir/file.
103  //
104 
105  if (FlagOn(*DesiredAccess, ~(DELETE |
106  READ_CONTROL |
107  WRITE_OWNER |
108  WRITE_DAC |
109  SYNCHRONIZE |
112  FILE_READ_EA |
113  FILE_WRITE_EA |
117  FILE_TRAVERSE |
120  MAXIMUM_ALLOWED))) {
121 
122  DebugTrace(0, Dbg, "Cannot open object\n", 0);
123 
124  try_return( Result = FALSE );
125  }
126 
127  //
128  // Check for a read-only Dirent
129  //
130 
131  if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_READ_ONLY)) {
132 
133  //
134  // Check the desired access for a read-only dirent. AccessMask will contain
135  // the flags we're going to allow.
136  //
137 
143 
144  //
145  // If this is a subdirectory also allow add file/directory and delete.
146  //
147 
148  if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_DIRECTORY)) {
149 
151  }
152 
153  if (FlagOn(*DesiredAccess, ~AccessMask)) {
154 
155  DebugTrace(0, Dbg, "Cannot open readonly\n", 0);
156 
157  try_return( Result = FALSE );
158  }
159  }
160 
161  try_exit: NOTHING;
162  } _SEH2_FINALLY {
163 
165 
166  DebugTrace(-1, Dbg, "FatCheckFileAccess -> %08lx\n", Result);
167  } _SEH2_END;
168 
169  UNREFERENCED_PARAMETER( IrpContext );
170 
171  return Result;
172 }
173 
174 
175 BOOLEAN
177  _In_ PIRP_CONTEXT IrpContext,
179  _In_ KPROCESSOR_MODE ProcessorMode
180  )
181 
182 /*++
183 
184 Routine Description:
185 
186  This function checks whether the SID described in the input access state has
187  manage volume privilege.
188 
189 Arguments:
190 
191  AccessState - the access state describing the security context to be checked
192 
193  ProcessorMode - the mode this check should occur against
194 
195 Return Value:
196 
197  BOOLEAN - TRUE if privilege is held and FALSE otherwise
198 
199 --*/
200 
201 {
202  PRIVILEGE_SET PrivilegeSet;
203 
204  PAGED_CODE();
205 
206  PrivilegeSet.PrivilegeCount = 1;
207  PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY;
208  PrivilegeSet.Privilege[0].Luid = RtlConvertLongToLuid( SE_MANAGE_VOLUME_PRIVILEGE );
209  PrivilegeSet.Privilege[0].Attributes = 0;
210 
211  if (SePrivilegeCheck( &PrivilegeSet,
212  &AccessState->SubjectSecurityContext,
213  ProcessorMode )) {
214 
215  return TRUE;
216  }
217 
218  UNREFERENCED_PARAMETER( IrpContext );
219 
220  return FALSE;
221 }
222 
223 
224 NTSTATUS
226  IN PIRP_CONTEXT IrpContext,
229  IN KPROCESSOR_MODE ProcessorMode
230  )
231 
232 /*++
233 
234 Routine Description:
235 
236  This function asks whether the SID described in the input access state has
237  been granted any explicit access to the given device object. It does this
238  by acquiring a token stripped of its ability to acquire access via the
239  Everyone SID and re-doing the access check.
240 
241 Arguments:
242 
243  DeviceObject - the device whose ACL will be checked
244 
245  AccessState - the access state describing the security context to be checked
246 
247  ProcessorMode - the mode this check should occur against
248 
249 Return Value:
250 
251  NTSTATUS - Indicating whether explicit access was granted.
252 
253 --*/
254 
255 {
257 
258  PACCESS_TOKEN OriginalAccessToken;
259  PACCESS_TOKEN RestrictedAccessToken;
260 
261  PACCESS_TOKEN *EffectiveToken;
262 
264 
265  PAGED_CODE();
266 
267  UNREFERENCED_PARAMETER( IrpContext );
268 
269  //
270  // If the access state indicates that specific access other
271  // than traverse was acquired, either Everyone does have such
272  // access or explicit access was granted. In both cases, we're
273  // happy to let this proceed.
274  //
275 
276  if (AccessState->PreviouslyGrantedAccess & (SPECIFIC_RIGHTS_ALL ^
277  FILE_TRAVERSE)) {
278 
279  return STATUS_SUCCESS;
280  }
281 
282  //
283  // If the manage volume privilege is held, this also permits access.
284  //
285 
286  if (FatCheckManageVolumeAccess( IrpContext,
287  AccessState,
288  ProcessorMode )) {
289 
290  return STATUS_SUCCESS;
291  }
292 
293  //
294  // Capture the subject context as a prelude to everything below.
295  //
296 
297  SeLockSubjectContext( &AccessState->SubjectSecurityContext );
298 
299  //
300  // Convert the token in the subject context into one which does not
301  // acquire access through the Everyone SID.
302  //
303  // The logic for deciding which token is effective comes from
304  // SeQuerySubjectContextToken; since there is no natural way
305  // of getting a pointer to it, do it by hand.
306  //
307 
308  if (ARGUMENT_PRESENT( AccessState->SubjectSecurityContext.ClientToken )) {
309  EffectiveToken = &AccessState->SubjectSecurityContext.ClientToken;
310  } else {
311  EffectiveToken = &AccessState->SubjectSecurityContext.PrimaryToken;
312  }
313 
314  OriginalAccessToken = *EffectiveToken;
315  Status = FatCreateRestrictEveryoneToken( OriginalAccessToken, &RestrictedAccessToken );
316 
317  if (!NT_SUCCESS(Status)) {
318 
319  SeReleaseSubjectContext( &AccessState->SubjectSecurityContext );
320  return Status;
321  }
322 
323  //
324  // Now see if the resulting context has access to the device through
325  // its explicitly granted access. We swap in our restricted token
326  // for this check as the effective client token.
327  //
328 
329  *EffectiveToken = RestrictedAccessToken;
330 
331 #ifdef _MSC_VER
332 #pragma prefast( suppress: 28175, "we're a file system, this is ok to touch" )
333 #endif
334  SeAccessCheck( DeviceObject->SecurityDescriptor,
335  &AccessState->SubjectSecurityContext,
336  FALSE,
337  AccessState->OriginalDesiredAccess,
338  0,
339  NULL,
341  ProcessorMode,
342  &GrantedAccess,
343  &Status );
344 
345  *EffectiveToken = OriginalAccessToken;
346 
347  //
348  // Cleanup and return.
349  //
350 
351  SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
352  ObDereferenceObject( RestrictedAccessToken );
353 
354  return Status;
355 }
356 
357 
358 NTSTATUS
361  OUT PACCESS_TOKEN *RestrictedToken
362  )
363 
364 /*++
365 
366 Routine Description:
367 
368  This function takes a token as the input and returns a new restricted token
369  from which Everyone sid has been disabled. The resulting token may be used
370  to find out if access is available to a user-sid by explicit means.
371 
372 Arguments:
373 
374  Token - Input token from which Everyone sid needs to be deactivated.
375 
376  RestrictedToken - Receives the the new restricted token.
377  This must be released using ObDereferenceObject(*RestrictedToken);
378 
379 Return Value:
380 
381  NTSTATUS - Returned by SeFilterToken.
382 
383 --*/
384 
385 {
386  //
387  // Array of sids to disable.
388  //
389 
390  TOKEN_GROUPS SidsToDisable;
391 
393 
394  PAGED_CODE();
395 
396  //
397  // Restricted token will contain the original sids with one change:
398  // If Everyone sid is present in the token, it will be marked for DenyOnly.
399  //
400 
401  *RestrictedToken = NULL;
402 
403  //
404  // Put Everyone sid in the array of sids to disable. This will mark it
405  // for SE_GROUP_USE_FOR_DENY_ONLY and it'll only be applicable for Deny aces.
406  //
407 
408  SidsToDisable.GroupCount = 1;
409  SidsToDisable.Groups[0].Attributes = 0;
410  SidsToDisable.Groups[0].Sid = SeExports->SeWorldSid;
411 
412  Status = SeFilterToken(
413  Token, // Token that needs to be restricted.
414  0, // No flags
415  &SidsToDisable, // Disable everyone sid
416  NULL, // Do not create any restricted sids
417  NULL, // Do not delete any privileges
418  RestrictedToken // Restricted token
419  );
420 
421  return Status;
422 }
423 
PGENERIC_MAPPING NTAPI IoGetFileObjectGenericMapping(VOID)
Definition: file.c:3267
#define FAT_DIRENT_ATTR_DEVICE
Definition: fat.h:374
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
BOOLEAN NTAPI SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, IN BOOLEAN SubjectContextLocked, IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK PreviouslyGrantedAccess, OUT PPRIVILEGE_SET *Privileges, IN PGENERIC_MAPPING GenericMapping, IN KPROCESSOR_MODE AccessMode, OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus)
Definition: accesschk.c:340
#define FILE_WRITE_EA
Definition: nt_native.h:640
#define IN
Definition: typedefs.h:38
VOID NTAPI SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:360
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI SeFilterToken(IN PACCESS_TOKEN ExistingToken, IN ULONG Flags, IN PTOKEN_GROUPS SidsToDisable OPTIONAL, IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL, IN PTOKEN_GROUPS RestrictedSids OPTIONAL, OUT PACCESS_TOKEN *FilteredToken)
Definition: token.c:1290
VOID NTAPI SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:336
#define ACCESS_SYSTEM_SECURITY
Definition: nt_native.h:77
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
VOID NTAPI SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:314
PVOID PACCESS_TOKEN
Definition: setypes.h:11
#define FAT_DIRENT_ATTR_READ_ONLY
Definition: fat.h:368
#define FAT_DIRENT_ATTR_DIRECTORY
Definition: fat.h:372
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
$ULONG Control
Definition: setypes.h:87
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define WRITE_OWNER
Definition: nt_native.h:60
#define FILE_APPEND_DATA
Definition: nt_native.h:634
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
#define FILE_TRAVERSE
Definition: nt_native.h:643
#define FILE_DELETE_CHILD
Definition: nt_native.h:645
#define FILE_ADD_FILE
Definition: nt_native.h:632
#define FALSE
Definition: types.h:117
PSE_EXPORTS SeExports
Definition: semgr.c:18
#define PRIVILEGE_SET_ALL_NECESSARY
Definition: setypes.h:83
#define FILE_READ_DATA
Definition: nt_native.h:628
smooth NULL
Definition: ftsmooth.c:416
#define FILE_WRITE_DATA
Definition: nt_native.h:631
$ULONG PrivilegeCount
Definition: setypes.h:86
BOOLEAN FatCheckManageVolumeAccess(_In_ PIRP_CONTEXT IrpContext, _In_ PACCESS_STATE AccessState, _In_ KPROCESSOR_MODE ProcessorMode)
Definition: acchksup.c:176
unsigned char BOOLEAN
#define DebugUnwind(X)
Definition: fatdata.h:315
NTSTATUS FatCreateRestrictEveryoneToken(IN PACCESS_TOKEN Token, OUT PACCESS_TOKEN *RestrictedToken)
Definition: acchksup.c:359
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define try_return(S)
Definition: cdprocs.h:2186
#define ARGUMENT_PRESENT(ArgumentPointer)
_In_ ACCESS_MASK AccessMask
Definition: exfuncs.h:186
#define WRITE_DAC
Definition: nt_native.h:59
#define SPECIFIC_RIGHTS_ALL
Definition: nt_native.h:71
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define READ_CONTROL
Definition: nt_native.h:58
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
_In_opt_ PVOID _In_opt_ PUNICODE_STRING _In_ PSECURITY_DESCRIPTOR _In_ PACCESS_STATE AccessState
Definition: sefuncs.h:414
unsigned char UCHAR
Definition: xmlstorage.h:181
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
#define FILE_EXECUTE
Definition: nt_native.h:642
#define NOTHING
Definition: env_spec_w32.h:461
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define SYNCHRONIZE
Definition: nt_native.h:61
BOOLEAN NTAPI SePrivilegeCheck(PPRIVILEGE_SET Privileges, PSECURITY_SUBJECT_CONTEXT SubjectContext, KPROCESSOR_MODE PreviousMode)
Definition: priv.c:491
Status
Definition: gdiplustypes.h:24
NTSTATUS FatExplicitDeviceAccessGranted(IN PIRP_CONTEXT IrpContext, IN PDEVICE_OBJECT DeviceObject, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE ProcessorMode)
Definition: acchksup.c:225
#define _In_
Definition: no_sal2.h:204
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
_SEH2_END
Definition: create.c:4424
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
BOOLEAN FatCheckFileAccess(PIRP_CONTEXT IrpContext, IN UCHAR DirentAttributes, IN PACCESS_MASK DesiredAccess)
Definition: acchksup.c:39
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK DesiredAccess
Definition: create.c:4157
SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]
Definition: setypes.h:964
_SEH2_FINALLY
Definition: create.c:4395
#define FILE_READ_EA
Definition: nt_native.h:638
#define Dbg
Definition: acchksup.c:22
$ULONG GroupCount
Definition: setypes.h:960
LUID_AND_ATTRIBUTES Privilege[ANYSIZE_ARRAY]
Definition: setypes.h:88
#define FAT_DIRENT_ATTR_VOLUME_ID
Definition: fat.h:371
#define OUT
Definition: typedefs.h:39
ACCESS_MASK * PACCESS_MASK
Definition: nt_native.h:41
PSID SeWorldSid
Definition: setypes.h:1165
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:13
return STATUS_SUCCESS
Definition: btrfs.c:2710
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define DELETE
Definition: nt_native.h:57