Skip to content

Commit 292e99b

Browse files
author
Keith Newton
committed
Improvements to management of file security dokan-dev#210
1 parent a0d9eed commit 292e99b

File tree

13 files changed

+631
-355
lines changed

13 files changed

+631
-355
lines changed

dokan/access.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,32 +22,40 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
2222
#include "dokani.h"
2323
#include "fileinfo.h"
2424

25-
HANDLE DOKANAPI DokanOpenRequestorToken(PDOKAN_CREATE_FILE_EVENT FileInfo) {
25+
HANDLE DOKANAPI DokanOpenRequestorToken(PDOKAN_FILE_INFO FileInfo) {
2626

27-
PDOKAN_IO_EVENT ioEvent = (PDOKAN_IO_EVENT)FileInfo;
27+
PDOKAN_IO_EVENT ioEvent = (PDOKAN_IO_EVENT)FileInfo->DokanContext;
2828
BOOL status;
2929
ULONG returnedLength;
3030
PEVENT_INFORMATION eventInfo;
3131
HANDLE handle = INVALID_HANDLE_VALUE;
3232
ULONG eventInfoSize;
3333
WCHAR rawDeviceName[MAX_PATH];
3434

35-
if (ioEvent->DokanOpenInfo == NULL) {
36-
return INVALID_HANDLE_VALUE;
37-
}
35+
if (ioEvent->DokanOpenInfo == NULL
36+
|| ioEvent->DokanInstance == NULL
37+
|| ioEvent->DokanFileInfo.DokanContext != (PVOID)ioEvent) {
38+
39+
SetLastError(ERROR_INVALID_PARAMETER);
3840

39-
if (ioEvent->DokanInstance == NULL) {
4041
return INVALID_HANDLE_VALUE;
4142
}
4243

43-
if (ioEvent->KernelInfo.EventContext.MajorFunction != IRP_MJ_CREATE) {
44+
if (ioEvent->KernelInfo.EventContext.MajorFunction != IRP_MJ_CREATE
45+
&& ioEvent->KernelInfo.EventContext.MajorFunction != IRP_MJ_SET_SECURITY) {
46+
47+
SetLastError(ERROR_INVALID_PARAMETER);
48+
4449
return INVALID_HANDLE_VALUE;
4550
}
4651

4752
eventInfoSize = sizeof(EVENT_INFORMATION);
4853
eventInfo = (PEVENT_INFORMATION)DokanMalloc(eventInfoSize);
4954

5055
if (eventInfo == NULL) {
56+
57+
SetLastError(ERROR_OUTOFMEMORY);
58+
5159
return INVALID_HANDLE_VALUE;
5260
}
5361

@@ -61,8 +69,11 @@ HANDLE DOKANAPI DokanOpenRequestorToken(PDOKAN_CREATE_FILE_EVENT FileInfo) {
6169
eventInfoSize, &returnedLength);
6270

6371
if (status) {
72+
6473
handle = eventInfo->Operation.AccessToken.Handle;
65-
} else {
74+
}
75+
else {
76+
6677
DbgPrintW(L"IOCTL_GET_ACCESS_TOKEN failed\n");
6778
}
6879

dokan/create.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ void BeginDispatchCreate(DOKAN_IO_EVENT *EventInfo) {
113113
createFileEvent->CreateDisposition = (EventInfo->KernelInfo.EventContext.Operation.Create.CreateOptions >> 24) & 0x000000ff;
114114
createFileEvent->FileAttributes = EventInfo->KernelInfo.EventContext.Operation.Create.FileAttributes;
115115
createFileEvent->ShareAccess = EventInfo->KernelInfo.EventContext.Operation.Create.ShareAccess;
116-
createFileEvent->AccessToken = EventInfo->KernelInfo.EventContext.Operation.Create.AccessToken;
117116

118117
if((createFileEvent->CreateOptions & FILE_NON_DIRECTORY_FILE) && (createFileEvent->CreateOptions & FILE_DIRECTORY_FILE)) {
119118

dokan/dokan.c

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,37 +1681,86 @@ BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, LPVOID Reserved) {
16811681
return TRUE;
16821682
}
16831683

1684+
// https://msdn.microsoft.com/en-us/library/windows/hardware/bb530716(v=vs.85).aspx
1685+
BOOL DokanIsBackupName(DOKAN_CREATE_FILE_EVENT *EventInfo) {
1686+
1687+
// mask for SE_BACKUP_NAME privilege
1688+
DWORD mask =
1689+
READ_CONTROL
1690+
| FILE_READ_ATTRIBUTES
1691+
| STANDARD_RIGHTS_READ;
1692+
1693+
if((EventInfo->DesiredAccess & mask) == mask
1694+
&& (EventInfo->SecurityContext.AccessState.Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE)
1695+
&& (EventInfo->SecurityContext.AccessState.Flags & (TOKEN_HAS_BACKUP_PRIVILEGE | SE_BACKUP_PRIVILEGES_CHECKED))) {
1696+
1697+
return TRUE;
1698+
}
1699+
1700+
return FALSE;
1701+
}
1702+
1703+
// https://msdn.microsoft.com/en-us/library/windows/hardware/bb530716(v=vs.85).aspx
1704+
BOOL DokanIsRestoreName(DOKAN_CREATE_FILE_EVENT *EventInfo) {
1705+
1706+
// mask for SE_RESTORE_NAME privilege
1707+
DWORD mask =
1708+
WRITE_DAC
1709+
| WRITE_OWNER
1710+
//| ACCESS_SYSTEM_SECURITY
1711+
| STANDARD_RIGHTS_WRITE;
1712+
//| FILE_ADD_FILE
1713+
//| FILE_ADD_SUBDIRECTORY
1714+
//| DELETE;
1715+
1716+
if((EventInfo->DesiredAccess & mask) == mask
1717+
&& (EventInfo->SecurityContext.AccessState.Flags & (TOKEN_HAS_RESTORE_PRIVILEGE | SE_BACKUP_PRIVILEGES_CHECKED))) {
1718+
1719+
return TRUE;
1720+
}
1721+
1722+
return FALSE;
1723+
}
1724+
16841725
VOID DOKANAPI DokanMapKernelToUserCreateFileFlags(
1685-
ULONG FileAttributes, ULONG CreateOptions, ULONG CreateDisposition,
1686-
DWORD *outFileAttributesAndFlags, DWORD *outCreationDisposition) {
1726+
DOKAN_CREATE_FILE_EVENT *EventInfo,
1727+
DWORD *outFileAttributesAndFlags,
1728+
DWORD *outCreationDisposition) {
1729+
16871730
if (outFileAttributesAndFlags) {
16881731

1689-
*outFileAttributesAndFlags = FileAttributes;
1732+
*outFileAttributesAndFlags = EventInfo->FileAttributes;
16901733

1691-
DokanMapKernelBit(*outFileAttributesAndFlags, CreateOptions,
1734+
DokanMapKernelBit(*outFileAttributesAndFlags, EventInfo->CreateOptions,
16921735
FILE_FLAG_WRITE_THROUGH, FILE_WRITE_THROUGH);
1693-
DokanMapKernelBit(*outFileAttributesAndFlags, CreateOptions,
1736+
DokanMapKernelBit(*outFileAttributesAndFlags, EventInfo->CreateOptions,
16941737
FILE_FLAG_SEQUENTIAL_SCAN, FILE_SEQUENTIAL_ONLY);
1695-
DokanMapKernelBit(*outFileAttributesAndFlags, CreateOptions,
1738+
DokanMapKernelBit(*outFileAttributesAndFlags, EventInfo->CreateOptions,
16961739
FILE_FLAG_RANDOM_ACCESS, FILE_RANDOM_ACCESS);
1697-
DokanMapKernelBit(*outFileAttributesAndFlags, CreateOptions,
1740+
DokanMapKernelBit(*outFileAttributesAndFlags, EventInfo->CreateOptions,
16981741
FILE_FLAG_NO_BUFFERING, FILE_NO_INTERMEDIATE_BUFFERING);
1699-
DokanMapKernelBit(*outFileAttributesAndFlags, CreateOptions,
1742+
DokanMapKernelBit(*outFileAttributesAndFlags, EventInfo->CreateOptions,
17001743
FILE_FLAG_OPEN_REPARSE_POINT, FILE_OPEN_REPARSE_POINT);
1701-
DokanMapKernelBit(*outFileAttributesAndFlags, CreateOptions,
1744+
DokanMapKernelBit(*outFileAttributesAndFlags, EventInfo->CreateOptions,
17021745
FILE_FLAG_DELETE_ON_CLOSE, FILE_DELETE_ON_CLOSE);
1703-
DokanMapKernelBit(*outFileAttributesAndFlags, CreateOptions,
1746+
DokanMapKernelBit(*outFileAttributesAndFlags, EventInfo->CreateOptions,
17041747
FILE_FLAG_BACKUP_SEMANTICS, FILE_OPEN_FOR_BACKUP_INTENT);
17051748

17061749
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
1707-
DokanMapKernelBit(*outFileAttributesAndFlags, CreateOptions,
1750+
DokanMapKernelBit(*outFileAttributesAndFlags, EventInfo->CreateOptions,
17081751
FILE_FLAG_SESSION_AWARE, FILE_SESSION_AWARE);
17091752
#endif
1753+
1754+
if(DokanIsBackupName(EventInfo)
1755+
|| DokanIsRestoreName(EventInfo)) {
1756+
1757+
*outFileAttributesAndFlags |= FILE_FLAG_BACKUP_SEMANTICS;
1758+
}
17101759
}
17111760

17121761
if (outCreationDisposition) {
17131762

1714-
switch (CreateDisposition) {
1763+
switch (EventInfo->CreateDisposition) {
17151764
case FILE_CREATE:
17161765
*outCreationDisposition = CREATE_NEW;
17171766
break;

dokan/dokan.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ typedef struct _DOKAN_CREATE_FILE_EVENT {
162162
PDOKAN_FILE_INFO DokanFileInfo;
163163
LPCWSTR FileName;
164164
LPCWSTR OriginalFileName;
165-
HANDLE AccessToken;
166165
DOKAN_IO_SECURITY_CONTEXT SecurityContext; // https://msdn.microsoft.com/en-us/library/windows/hardware/ff550613(v=vs.85).aspx
167166

168167
ACCESS_MASK DesiredAccess;
@@ -273,18 +272,17 @@ typedef struct _DOKAN_GET_VOLUME_ATTRIBUTES_EVENT {
273272
typedef struct _DOKAN_GET_FILE_SECURITY_EVENT {
274273
PDOKAN_FILE_INFO DokanFileInfo;
275274
LPWSTR FileName;
276-
PSECURITY_INFORMATION SecurityInformation; // A pointer to SECURITY_INFORMATION value being requested
277275
PSECURITY_DESCRIPTOR SecurityDescriptor; // A pointer to SECURITY_DESCRIPTOR buffer to be filled
276+
SECURITY_INFORMATION SecurityInformation; // The types of security information being requested
278277
ULONG SecurityDescriptorSize; // length of Security descriptor buffer
279278
ULONG LengthNeeded;
280279
} DOKAN_GET_FILE_SECURITY_EVENT, *PDOKAN_GET_FILE_SECURITY_EVENT;
281280

282281
typedef struct _DOKAN_SET_FILE_SECURITY_EVENT {
283282
PDOKAN_FILE_INFO DokanFileInfo;
284283
LPWSTR FileName;
285-
HANDLE AccessToken;
286-
PSECURITY_INFORMATION SecurityInformation;
287284
PSECURITY_DESCRIPTOR SecurityDescriptor; // A pointer to SECURITY_DESCRIPTOR buffer to be filled
285+
SECURITY_INFORMATION SecurityInformation;
288286
ULONG SecurityDescriptorSize; // length of Security descriptor buffer
289287
} DOKAN_SET_FILE_SECURITY_EVENT, *PDOKAN_SET_FILE_SECURITY_EVENT;
290288

@@ -458,14 +456,15 @@ BOOL DOKANAPI DokanResetTimeout(ULONG Timeout, // timeout in millisecond
458456
// Get the handle to Access Token
459457
// This method needs be called in CreateFile callback.
460458
// The caller must call CloseHandle for the returned handle.
461-
HANDLE DOKANAPI DokanOpenRequestorToken(PDOKAN_CREATE_FILE_EVENT DokanFileInfo);
459+
HANDLE DOKANAPI DokanOpenRequestorToken(PDOKAN_FILE_INFO DokanFileInfo);
462460

463461
BOOL DOKANAPI DokanGetMountPointList(PDOKAN_CONTROL list, ULONG length,
464462
BOOL uncOnly, PULONG nbRead);
465463

466464
VOID DOKANAPI DokanMapKernelToUserCreateFileFlags(
467-
ULONG FileAttributes, ULONG CreateOptions, ULONG CreateDisposition,
468-
DWORD *outFileAttributesAndFlags, DWORD *outCreationDisposition);
465+
DOKAN_CREATE_FILE_EVENT *EventInfo,
466+
DWORD *outFileAttributesAndFlags,
467+
DWORD *outCreationDisposition);
469468

470469
// Translate Win32 Error code to the NtStatus code's corresponding
471470
NTSTATUS DOKANAPI DokanNtStatusFromWin32(DWORD Error);

dokan/fileinfo.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,4 +510,33 @@ typedef struct _UNICODE_STRING {
510510
PWSTR Buffer;
511511
} UNICODE_STRING, *PUNICODE_STRING;
512512

513+
//
514+
// Token Flags
515+
//
516+
// Flags that may be defined in the TokenFlags field of the token object,
517+
// or in an ACCESS_STATE structure
518+
//
519+
520+
#define TOKEN_HAS_TRAVERSE_PRIVILEGE 0x0001
521+
#define TOKEN_HAS_BACKUP_PRIVILEGE 0x0002
522+
#define TOKEN_HAS_RESTORE_PRIVILEGE 0x0004
523+
#define TOKEN_WRITE_RESTRICTED 0x0008
524+
#define TOKEN_IS_RESTRICTED 0x0010
525+
#define TOKEN_SESSION_NOT_REFERENCED 0x0020
526+
#define TOKEN_SANDBOX_INERT 0x0040
527+
#define TOKEN_HAS_IMPERSONATE_PRIVILEGE 0x0080
528+
#define SE_BACKUP_PRIVILEGES_CHECKED 0x0100
529+
#define TOKEN_VIRTUALIZE_ALLOWED 0x0200
530+
#define TOKEN_VIRTUALIZE_ENABLED 0x0400
531+
#define TOKEN_IS_FILTERED 0x0800
532+
#define TOKEN_UIACCESS 0x1000
533+
#define TOKEN_NOT_LOW 0x2000
534+
#define TOKEN_LOWBOX 0x4000
535+
#define TOKEN_HAS_OWN_CLAIM_ATTRIBUTES 0x8000
536+
537+
#define TOKEN_PRIVATE_NAMESPACE 0x00010000
538+
#define TOKEN_DO_NOT_USE_GLOBAL_ATTRIBS_FOR_QUERY 0x00020000
539+
#define SPECIAL_ENCRYPTED_OPEN 0x00040000
540+
#define TOKEN_NO_CHILD_PROCESS 0x00080000
541+
513542
#endif // FILEINFO_H_

dokan/security.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ void BeginDispatchQuerySecurity(DOKAN_IO_EVENT *EventInfo) {
4444

4545
getFileSecurity->DokanFileInfo = &EventInfo->DokanFileInfo;
4646
getFileSecurity->FileName = EventInfo->KernelInfo.EventContext.Operation.Security.FileName;
47-
getFileSecurity->SecurityInformation = &EventInfo->KernelInfo.EventContext.Operation.Security.SecurityInformation;
4847
getFileSecurity->SecurityDescriptor = (PSECURITY_DESCRIPTOR)&EventInfo->EventResult->Buffer[0];
48+
getFileSecurity->SecurityInformation = EventInfo->KernelInfo.EventContext.Operation.Security.SecurityInformation;
4949
getFileSecurity->SecurityDescriptorSize = IoEventResultBufferSize(EventInfo);
5050

5151
assert(getFileSecurity->LengthNeeded == 0);
@@ -112,9 +112,8 @@ void BeginDispatchSetSecurity(DOKAN_IO_EVENT *EventInfo) {
112112

113113
setFileSecurity->DokanFileInfo = &EventInfo->DokanFileInfo;
114114
setFileSecurity->FileName = EventInfo->KernelInfo.EventContext.Operation.SetSecurity.FileName;
115-
setFileSecurity->AccessToken = EventInfo->KernelInfo.EventContext.Operation.SetSecurity.AccessToken;
116-
setFileSecurity->SecurityInformation = &EventInfo->KernelInfo.EventContext.Operation.SetSecurity.SecurityInformation;
117115
setFileSecurity->SecurityDescriptor = (PCHAR)&EventInfo->KernelInfo.EventContext + EventInfo->KernelInfo.EventContext.Operation.SetSecurity.BufferOffset;
116+
setFileSecurity->SecurityInformation = EventInfo->KernelInfo.EventContext.Operation.SetSecurity.SecurityInformation;
118117
setFileSecurity->SecurityDescriptorSize = EventInfo->KernelInfo.EventContext.Operation.SetSecurity.BufferLength;
119118

120119
status = EventInfo->DokanInstance->DokanOperations->SetFileSecurityW(setFileSecurity);

dokan_fuse/src/dokanfuse.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ FuseGetFileSecurity(DOKAN_GET_FILE_SECURITY_EVENT *EventInfo) {
522522
impl_fuse_context *impl = the_impl;
523523

524524
if (impl->debug())
525-
FPRINTF(stderr, "GetFileSecurity: %x\n", *EventInfo->SecurityInformation);
525+
FPRINTF(stderr, "GetFileSecurity: %x\n", EventInfo->SecurityInformation);
526526

527527
BY_HANDLE_FILE_INFORMATION byHandleFileInfo;
528528
ZeroMemory(&byHandleFileInfo, sizeof(BY_HANDLE_FILE_INFORMATION));
@@ -551,7 +551,7 @@ FuseGetFileSecurity(DOKAN_GET_FILE_SECURITY_EVENT *EventInfo) {
551551

552552
LPTSTR pStringBuffer = NULL;
553553
if (!ConvertSecurityDescriptorToStringSecurityDescriptor(
554-
EventInfo->SecurityDescriptor, SDDL_REVISION_1, *EventInfo->SecurityInformation,
554+
EventInfo->SecurityDescriptor, SDDL_REVISION_1, EventInfo->SecurityInformation,
555555
&pStringBuffer, NULL)) {
556556
return STATUS_NOT_IMPLEMENTED;
557557
}

0 commit comments

Comments
 (0)