예제 #1
0
        public NTCreateAndXRequest(byte[] buffer, int offset, bool isUnicode) : base(buffer, offset, isUnicode)
        {
            Reserved           = ByteReader.ReadByte(this.SMBParameters, 4);
            NameLength         = LittleEndianConverter.ToUInt16(this.SMBParameters, 5);
            Flags              = (NTCreateFlags)LittleEndianConverter.ToUInt32(this.SMBParameters, 7);
            RootDirectoryFID   = LittleEndianConverter.ToUInt32(this.SMBParameters, 11);
            DesiredAccess      = (FileAccessMask)LittleEndianConverter.ToUInt32(this.SMBParameters, 15);
            AllocationSize     = LittleEndianConverter.ToInt64(this.SMBParameters, 19);
            ExtFileAttributes  = (ExtendedFileAttributes)LittleEndianConverter.ToUInt32(this.SMBParameters, 27);
            ShareAccess        = (ShareAccess)LittleEndianConverter.ToUInt32(this.SMBParameters, 31);
            CreateDisposition  = (CreateDisposition)LittleEndianConverter.ToUInt32(this.SMBParameters, 35);
            CreateOptions      = (CreateOptions)LittleEndianConverter.ToUInt32(this.SMBParameters, 39);
            ImpersonationLevel = (ImpersonationLevel)LittleEndianConverter.ToUInt32(this.SMBParameters, 43);
            SecurityFlags      = (SecurityFlags)ByteReader.ReadByte(this.SMBParameters, 47);

            int dataOffset = 0;

            if (isUnicode)
            {
                // A Unicode string MUST be aligned to a 16-bit boundary with respect to the beginning of the SMB Header.
                // Note: SMBData starts at an odd offset.
                dataOffset = 1;
            }
            FileName = SMB1Helper.ReadSMBString(this.SMBData, dataOffset, isUnicode);
        }
예제 #2
0
        public static NTStatus Rename(INTFileStore fileStore, string oldName, string newName, SMBFileAttributes searchAttributes, SecurityContext securityContext)
        {
            object        handle;
            FileStatus    fileStatus;
            CreateOptions createOptions = 0;

            // Windows 2000 SP4 clients will use this command to rename directories.
            // Hidden, System and Directory attributes are inclusive.
            if ((searchAttributes & SMBFileAttributes.Directory) == 0)
            {
                createOptions = CreateOptions.FILE_NON_DIRECTORY_FILE;
            }
            ShareAccess shareAccess = ShareAccess.Read | ShareAccess.Write | ShareAccess.Delete;
            NTStatus    status      = fileStore.CreateFile(out handle, out fileStatus, oldName, AccessMask.DELETE, 0, shareAccess, CreateDisposition.FILE_OPEN, createOptions, securityContext);

            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(status);
            }
            FileRenameInformationType2 renameInfo = new FileRenameInformationType2();

            renameInfo.ReplaceIfExists = false;
            renameInfo.FileName        = newName;
            status = fileStore.SetFileInformation(handle, renameInfo);
            fileStore.CloseFile(handle);
            return(status);
        }
예제 #3
0
        public NTTransactCreateRequest(byte[] parameters, byte[] data, bool isUnicode)
        {
            int parametersOffset = 0;

            Flags             = (NTCreateFlags)LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);
            RootDirectoryFID  = LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);
            DesiredAccess     = (AccessMask)LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);
            AllocationSize    = LittleEndianReader.ReadInt64(parameters, ref parametersOffset);
            ExtFileAttributes = (ExtendedFileAttributes)LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);
            ShareAccess       = (ShareAccess)LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);
            CreateDisposition = (CreateDisposition)LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);
            CreateOptions     = (CreateOptions)LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);
            uint securityDescriptiorLength = LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);

            _ = LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);
            uint nameLength = LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);

            ImpersonationLevel = (ImpersonationLevel)LittleEndianReader.ReadUInt32(parameters, ref parametersOffset);
            SecurityFlags      = (SecurityFlags)ByteReader.ReadByte(parameters, ref parametersOffset);

            if (isUnicode)
            {
                parametersOffset++;
            }
            Name = SMB1Helper.ReadFixedLengthString(parameters, ref parametersOffset, isUnicode, (int)nameLength);
            if (securityDescriptiorLength > 0)
            {
                SecurityDescriptor = new SecurityDescriptor(data, 0);
            }
            ExtendedAttributes = FileFullEAInformation.ReadList(data, (int)securityDescriptiorLength);
        }
 internal static MessageStatus WorkaroundOpenExistingFile(ShareAccess shareAccess, FileAccess desiredAccess,
                                                          bool streamFound, bool isSymbolicLink, FileType openFileType, FileNameStatus fileNameStatus,
                                                          CreateOptions existingOpenModeCreateOption, ShareAccess existOpenShareModeShareAccess,
                                                          FileAccess existOpenDesiredAccess, CreateOptions createOption, CreateDisposition createDisposition,
                                                          StreamTypeNameToOpen streamTypeNameToOPen, FileAttribute fileAttribute,
                                                          FileAttribute desiredFileAttribute, MessageStatus returnedStatus, ITestSite site)
 {
     if (shareAccess == ShareAccess.FILE_SHARE_READ && desiredAccess == FileAccess.FILE_ADD_SUBDIRECTORY &&
         !streamFound && !isSymbolicLink && openFileType == FileType.DataFile && fileNameStatus == FileNameStatus.Normal &&
         existingOpenModeCreateOption == CreateOptions.NON_DIRECTORY_FILE && existOpenShareModeShareAccess == ShareAccess.FILE_SHARE_READ &&
         existOpenDesiredAccess == FileAccess.FILE_LIST_DIRECTORY && createOption == CreateOptions.NO_INTERMEDIATE_BUFFERING &&
         createDisposition == CreateDisposition.OPEN_IF && streamTypeNameToOPen == StreamTypeNameToOpen.NULL &&
         fileAttribute == FileAttribute.NORMAL && desiredFileAttribute == FileAttribute.NORMAL)
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(376, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == (CreateOptions.SYNCHRONOUS_IO_NONALERT | CreateOptions.SYNCHRONOUS_IO_ALERT))
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(373, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == CreateOptions.SYNCHRONOUS_IO_ALERT &&
              desiredAccess == FileAccess.FILE_READ_DATA)
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(369, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == CreateOptions.SYNCHRONOUS_IO_NONALERT &&
              desiredAccess == FileAccess.FILE_READ_DATA)
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(2373, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == CreateOptions.DELETE_ON_CLOSE &&
              (desiredAccess == FileAccess.ACCESS_SYSTEM_SECURITY))
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(371, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == (CreateOptions.COMPLETE_IF_OPLOCKED | CreateOptions.RESERVE_OPFILTER))
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(375, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (streamFound && !isSymbolicLink && openFileType == FileType.DataFile &&
              existingOpenModeCreateOption == CreateOptions.DIRECTORY_FILE &&
              existOpenDesiredAccess == FileAccess.FILE_LIST_DIRECTORY &&
              createOption == CreateOptions.DIRECTORY_FILE)
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(375, MessageStatus.ACCESS_VIOLATION, returnedStatus, site);
     }
     else if (!streamFound && !isSymbolicLink && openFileType == FileType.DataFile &&
              existingOpenModeCreateOption == CreateOptions.NON_DIRECTORY_FILE &&
              existOpenDesiredAccess == FileAccess.FILE_LIST_DIRECTORY &&
              createOption == CreateOptions.NON_DIRECTORY_FILE &&
              fileAttribute == FileAttribute.READONLY)
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(375, MessageStatus.ACCESS_DENIED, returnedStatus, site);
     }
     return(returnedStatus);
 }
예제 #5
0
        protected virtual AccessRights GetMask(IWorkflowActivityContext context)
        {
            var mask = AccessRights.None;

            if (Read.Get(context.GetExecutionContext()))
            {
                mask = mask | AccessRights.ReadAccess;
            }

            if (Append.Get(context.GetExecutionContext()))
            {
                mask = mask | AccessRights.AppendAccess;
            }

            if (AppendTo.Get(context.GetExecutionContext()))
            {
                mask = mask | AccessRights.AppendToAccess;
            }

            if (Read.Get(context.GetExecutionContext()))
            {
                mask = mask | AccessRights.ReadAccess;
            }

            if (Write.Get(context.GetExecutionContext()))
            {
                mask = mask | AccessRights.WriteAccess;
            }

            if (Delete.Get(context.GetExecutionContext()))
            {
                mask = mask | AccessRights.DeleteAccess;
            }

            if (AssignAccess.Get(context.GetExecutionContext()))
            {
                mask = mask | AccessRights.AssignAccess;
            }

            if (ShareAccess.Get(context.GetExecutionContext()))
            {
                mask = mask | AccessRights.ShareAccess;
            }

            return(mask);
        }
예제 #6
0
        public static NTStatus Delete(INTFileStore fileStore, string path, CreateOptions createOptions, SecurityContext securityContext)
        {
            object      handle;
            FileStatus  fileStatus;
            ShareAccess shareAccess = ShareAccess.Read | ShareAccess.Write | ShareAccess.Delete;
            NTStatus    status      = fileStore.CreateFile(out handle, out fileStatus, path, AccessMask.DELETE, 0, shareAccess, CreateDisposition.FILE_OPEN, createOptions, securityContext);

            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(status);
            }
            FileDispositionInformation fileDispositionInfo = new FileDispositionInformation();

            fileDispositionInfo.DeletePending = true;
            status = fileStore.SetFileInformation(handle, fileDispositionInfo);
            fileStore.CloseFile(handle);
            return(status);
        }
예제 #7
0
        public static FileShare ToFileShare(ShareAccess shareAccess)
        {
            FileShare result = FileShare.None;

            if ((shareAccess & ShareAccess.FILE_SHARE_READ) > 0)
            {
                result |= FileShare.Read;
            }

            if ((shareAccess & ShareAccess.FILE_SHARE_WRITE) > 0)
            {
                result |= FileShare.Write;
            }

            if ((shareAccess & ShareAccess.FILE_SHARE_DELETE) > 0)
            {
                result |= FileShare.Delete;
            }

            return(result);
        }
예제 #8
0
        public static FileShare ToFileShare(ShareAccess shareAccess)
        {
            FileShare result = FileShare.None;

            if ((shareAccess & ShareAccess.Read) > 0)
            {
                result |= FileShare.Read;
            }

            if ((shareAccess & ShareAccess.Write) > 0)
            {
                result |= FileShare.Write;
            }

            if ((shareAccess & ShareAccess.Delete) > 0)
            {
                result |= FileShare.Delete;
            }

            return(result);
        }
 internal static MessageStatus WorkaroundOpenExistingFile(ShareAccess shareAccess, FileAccess desiredAccess,
                                                          bool streamFound, bool isSymbolicLink, FileType openFileType, FileNameStatus fileNameStatus,
                                                          CreateOptions existingOpenModeCreateOption, ShareAccess existOpenShareModeShareAccess,
                                                          FileAccess existOpenDesiredAccess, CreateOptions createOption, CreateDisposition createDisposition,
                                                          StreamTypeNameToOPen streamTypeNameToOPen, FileAttribute fileAttribute,
                                                          FileAttribute desiredFileAttribute, MessageStatus returnedStatus, ITestSite site)
 {
     // SMB1 server return ACCESS_DENIED instead of INVALID_PARAMETER when "CreateOptions.DELETE_ON_CLOS && !DesiredAccess.DELETE"
     if (createOption == CreateOptions.DELETE_ON_CLOSE &&
         desiredAccess != FileAccess.DELETE)
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(371, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (desiredAccess == FileAccess.None || desiredAccess == FileAccess.INVALID_ACCESS_MASK)
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(377, MessageStatus.ACCESS_DENIED, returnedStatus, site);
     }
     else if (createOption == CreateOptions.NO_INTERMEDIATE_BUFFERING &&
              (desiredAccess == FileAccess.FILE_APPEND_DATA || desiredAccess == FileAccess.FILE_ADD_SUBDIRECTORY))
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(376, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (streamFound && !isSymbolicLink && openFileType == FileType.DataFile &&
              existingOpenModeCreateOption == CreateOptions.DIRECTORY_FILE &&
              existOpenDesiredAccess == FileAccess.FILE_LIST_DIRECTORY &&
              createOption == CreateOptions.DIRECTORY_FILE)
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(375, MessageStatus.ACCESS_VIOLATION, returnedStatus, site);
     }
     else if (!streamFound && !isSymbolicLink && openFileType == FileType.DataFile &&
              existingOpenModeCreateOption == CreateOptions.NON_DIRECTORY_FILE &&
              existOpenDesiredAccess == FileAccess.FILE_LIST_DIRECTORY &&
              createOption == CreateOptions.NON_DIRECTORY_FILE &&
              fileAttribute == FileAttribute.READONLY)
     {
         returnedStatus = FsaUtility.TransferExpectedResult <MessageStatus>(375, MessageStatus.ACCESS_DENIED, returnedStatus, site);
     }
     return(returnedStatus);
 }
예제 #10
0
 public CreateRequest(byte[] buffer, int offset) : base(buffer, offset)
 {
     StructureSize         = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
     SecurityFlags         = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
     RequestedOplockLevel  = (OplockLevel)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
     ImpersonationLevel    = (ImpersonationLevel)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
     SmbCreateFlags        = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 8);
     Reserved              = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 16);
     DesiredAccess         = new AccessMask(buffer, offset + SMB2Header.Length + 24);
     FileAttributes        = (FileAttributes)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
     ShareAccess           = (ShareAccess)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 32);
     CreateDisposition     = (CreateDisposition)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 36);
     CreateOptions         = (CreateOptions)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 40);
     NameOffset            = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 44);
     NameLength            = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 46);
     CreateContextsOffsets = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 48);
     CreateContextsLength  = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 52);
     Name = ByteReader.ReadUTF16String(buffer, offset + NameOffset, NameLength / 2);
     if (CreateContextsLength > 0)
     {
         CreateContexts = CreateContext.ReadCreateContextList(buffer, (int)CreateContextsOffsets);
     }
 }
예제 #11
0
        public NTCreateAndXRequest(byte[] buffer, int offset, bool isUnicode) : base(buffer, offset, isUnicode)
        {
            Reserved = ByteReader.ReadByte(this.SMBParameters, 4);
            ushort nameLength = LittleEndianConverter.ToUInt16(this.SMBParameters, 5);

            Flags              = (NTCreateFlags)LittleEndianConverter.ToUInt32(this.SMBParameters, 7);
            RootDirectoryFID   = LittleEndianConverter.ToUInt32(this.SMBParameters, 11);
            DesiredAccess      = (DesiredAccess)LittleEndianConverter.ToUInt32(this.SMBParameters, 15);
            AllocationSize     = LittleEndianConverter.ToUInt64(this.SMBParameters, 19);
            ExtFileAttributes  = (ExtendedFileAttributes)LittleEndianConverter.ToUInt32(this.SMBParameters, 27);
            ShareAccess        = (ShareAccess)LittleEndianConverter.ToUInt32(this.SMBParameters, 31);
            CreateDisposition  = (CreateDisposition)LittleEndianConverter.ToUInt32(this.SMBParameters, 35);
            CreateOptions      = (CreateOptions)LittleEndianConverter.ToUInt32(this.SMBParameters, 39);
            ImpersonationLevel = (ImpersonationLevel)LittleEndianConverter.ToUInt32(this.SMBParameters, 43);
            SecurityFlags      = (SecurityFlags)ByteReader.ReadByte(this.SMBParameters, 47);

            int dataOffset = 0;

            if (isUnicode)
            {
                dataOffset = 1; // 1 byte padding for 2 byte alignment
            }
            FileName = SMBHelper.ReadSMBString(this.SMBData, dataOffset, isUnicode);
        }
        public static MessageStatus CreateFile(
            FileAttribute desiredFileAttribute,
            CreateOptions createOption,
            StreamTypeNameToOpen streamTypeNameToOPen,
            FileAccess desiredAccess,
            ShareAccess shareAccess,
            CreateDisposition createDisposition,
            StreamFoundType streamFoundType,
            SymbolicLinkType symbolicLinkType,
            FileType openFileType,
            FileNameStatus fileNameStatus
            )
        {
            MessageStatus status = OpenFileinitial(
                desiredAccess,
                shareAccess,
                createOption,
                createDisposition,
                desiredFileAttribute,
                streamFoundType,
                symbolicLinkType,
                streamTypeNameToOPen,
                openFileType,
                fileNameStatus);

            if (status != MessageStatus.SUCCESS)
            {
                return(status);
            }

            #region Pseudocode for the operation

            //If FileTypeToOpen is DirectoryFile and DesiredFileAttributes.FILE_ATTRIBUTE_TEMPORARY is set
            if (gfileTypeToOpen == FileType.DirectoryFile &&
                desiredFileAttribute == FileAttribute.TEMPORARY)
            {
                Helper.CaptureRequirement(418, @"[In Creation of a New File,Pseudocode for the operation is as follows:]If FileTypeToOpen is DirectoryFile and DesiredFileAttributes.FILE_ATTRIBUTE_TEMPORARY is set, the operation MUST be failed with STATUS_INVALID_PARAMETER.");
                return(MessageStatus.INVALID_PARAMETER);
            }

            //If DesiredFileAttributes.FILE_ATTRIBUTE_READONLY and CreateOptions.FILE_DELETE_ON_CLOSE
            //are both set
            if (desiredFileAttribute == FileAttribute.READONLY &&
                createOption == CreateOptions.DELETE_ON_CLOSE)
            {
                Helper.CaptureRequirement(419, @"[In Creation of a New File,Pseudocode for the operation is as follows:]If DesiredFileAttributes.FILE_ATTRIBUTE_READONLY and CreateOptions.FILE_DELETE_ON_CLOSE are both set, the operation MUST be failed with STATUS_CANNOT_DELETE.");
                return(MessageStatus.CANNOT_DELETE);
            }

            //If StreamTypeNameToOpen is non-empty and has a value other than "$DATA" or
            //"$INDEX_ALLOCATION", the operation MUST be failed with STATUS_ACCESS_DENIED.
            if (streamTypeNameToOPen == StreamTypeNameToOpen.Other)
            {
                Helper.CaptureRequirement(420, @"[In Creation of a New File,Pseudocode for the operation is as follows:]If StreamTypeNameToOpen is non-empty and has a value other than \""$DATA"",the operation MUST be failed with STATUS_ACCESS_DENIED.");
                return(MessageStatus.OBJECT_NAME_INVALID);
            }

            //If Open.RemainingDesiredAccess.ACCESS_SYSTEM_SECURITY is set and
            //Open.GrantedAccess.ACCESS_SYSTEM_SECURITY is not set and
            //SecurityContext.PrivilegeSet does not contain "SeSecurityPrivilege"
            //3 indicate SeBackupPrivilege and SeRestorePrivilege
            if (gOpenRemainingDesiredAccess == FileAccess.ACCESS_SYSTEM_SECURITY &&
                gOpenGrantedAccess == FileAccess.FILE_APPEND_DATA &&
                gSecurityContext.privilegeSet == (PrivilegeSet.SeBackupPrivilege | PrivilegeSet.SeRestorePrivilege))
            {
                Helper.CaptureRequirement(422, @"[In Creation of a New File,Pseudocode for the operation is as follows:]If Open.RemainingDesiredAccess.ACCESS_SYSTEM_SECURITY is set and Open.GrantedAccess.ACCESS_SYSTEM_SECURITY is not set and SecurityContext.PrivilegeSet does not contain \""SeSecurityPrivilege"", the operation MUST be failed with STATUS_ACCESS_DENIED.");
                return(MessageStatus.ACCESS_DENIED);
            }

            //If FileTypeToOpen is DataFile and Open.GrantedAccess.FILE_ADD_FILE is not set
            //and AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor,
            //FILE_ADD_FILE ) returns FALSE and Open.HasRestoreAccess is FALSE

            if (gfileTypeToOpen == FileType.DataFile &&
                gOpenGrantedAccess == FileAccess.FILE_ADD_SUBDIRECTORY &&
                !isOpenHasRestoreAccess)
            {
                Helper.CaptureRequirement(423, @"[In Creation of a New File,Pseudocode for the operation is as follows:]
                    If FileTypeToOpen is DataFile and Open.GrantedAccess.FILE_ADD_FILE is not set and 
                    AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor, FILE_ADD_FILE ) 
                    returns FALSE and Open.HasRestoreAccess is FALSE, the operation MUST be failed with STATUS_ACCESS_DENIED.");
                return(MessageStatus.ACCESS_DENIED);
            }

            //If FileTypeToOpen is DirectoryFile and Open.GrantedAccess.FILE_ADD_SUBDIRECTORY
            //is not set and AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor,
            //FILE_ADD_SUBDIRECTORY ) returns FALSE and Open.HasRestoreAccess is FALSE

            if (gfileTypeToOpen == FileType.DirectoryFile &&
                gOpenGrantedAccess == FileAccess.FILE_ADD_FILE &&
                !isOpenHasRestoreAccess)
            {
                Helper.CaptureRequirement(424, @"[In Creation of a New File,Pseudocode for the operation is as follows:]
                   If FileTypeToOpen is DirectoryFile and Open.GrantedAccess.FILE_ADD_SUBDIRECTORY is not set and 
                   AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor, FILE_ADD_SUBDIRECTORY ) 
                   returns FALSE and Open.HasRestoreAccess is FALSE, the operation MUST be failed with STATUS_ACCESS_DENIED.");
                return(MessageStatus.ACCESS_DENIED);
            }

            if (streamTypeNameToOPen == StreamTypeNameToOpen.DATA ||
                streamTypeNameToOPen == StreamTypeNameToOpen.NULL)
            {
                gStreamType = StreamType.DataStream;
            }
            else
            {
                gStreamType = StreamType.DirectoryStream;
            }

            gFileAttribute = desiredFileAttribute;
            Helper.CaptureRequirement(475, @"[In Creation of a New File,Pseudocode for the operation is as follows:]
                The object store MUST return:CreateAction set to FILE_CREATED.");
            gCreateAction = CreateAction.CREATED;

            #endregion

            Helper.CaptureRequirement(474, @"[In Creation of a New File,Pseudocode for the operation is as follows:]
                The object store MUST return :Status set to STATUS_SUCCESS.");
            return(MessageStatus.SUCCESS);
        }
예제 #13
0
        public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext)
        {
            handle     = null;
            fileStatus = FileStatus.FILE_DOES_NOT_EXIST;
            CreateRequest request = new CreateRequest();

            request.Name               = path;
            request.DesiredAccess      = desiredAccess;
            request.FileAttributes     = fileAttributes;
            request.ShareAccess        = shareAccess;
            request.CreateDisposition  = createDisposition;
            request.CreateOptions      = createOptions;
            request.ImpersonationLevel = ImpersonationLevel.Impersonation;
            ulong messageId = TrySendCommand(request);

            SMB2Command response = m_client.WaitForCommand(SMB2CommandName.Create, messageId);

            if (response != null)
            {
                if (response.Header.Status == NTStatus.STATUS_SUCCESS && response is CreateResponse)
                {
                    CreateResponse createResponse = ((CreateResponse)response);
                    handle     = createResponse.FileId;
                    fileStatus = ToFileStatus(createResponse.CreateAction);
                }
                return(response.Header.Status);
            }

            return(NTStatus.STATUS_INVALID_SMB);
        }
        public static MessageStatus CheckShareAccess(
            StreamFoundType streamFoundType,
            ShareAccess existOpenShareModeShareAccess,
            FileAccess openDesiredAccess,
            FileAccess existOpenDesiredAccess,
            ShareAccess shareAccess)
        {
            //If AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor, FILE_WRITE_DATA )
            //returns FALSE, the object store MUST set Open.SharingMode.FILE_SHARE_READ to true.

            //If ExistingOpen.Stream equals Open.Stream
            if (streamFoundType == StreamFoundType.StreamIsFound)
            {
                //If ExistingOpen.SharingMode.FILE_SHARE_READ is FALSE and Open.DesiredAccess contains
                //FILE_READ_DATA
                if ((existOpenShareModeShareAccess & ShareAccess.FILE_SHARE_READ) == 0 &&
                    (openDesiredAccess & FileAccess.FILE_READ_DATA) != 0)
                {
                    return MessageStatus.ACCESS_VIOLATION;
                }

                //If ExistingOpen.SharingMode.FILE_SHARE_READ is FALSE and Open.DesiredAccess contains
                //FILE_EXECUTE
                if ((existOpenShareModeShareAccess & ShareAccess.FILE_SHARE_READ) == 0 &&
                    (openDesiredAccess & FileAccess.FILE_EXECUTE) != 0)
                {
                    Helper.CaptureRequirement(650, @"[In Algorithm to Check Sharing Access to an Existing Stream or Directory,
                        Pseudocode for these checks is as follows,For each ExistingOpen in Open.File.OpenList:If ExistingOpen.Stream equals Open.Stream,
                        then return STATUS_ACCESS_VIOLATION under any of the following conditions:]
                        If ExistingOpen.SharingMode.FILE_SHARE_WRITE is FALSE and Open.DesiredAccess contains  FILE_EXECUTE.");
                    return MessageStatus.ACCESS_VIOLATION;
                }

                //If ExistingOpen.SharingMode.FILE_SHARE_WRITE is FALSE and Open.DesiredAccess contains
                //FILE_WRITE_DATA
                if ((existOpenShareModeShareAccess & ShareAccess.FILE_SHARE_WRITE) == 0 &&
                    (openDesiredAccess & FileAccess.FILE_WRITE_DATA) != 0)
                {
                    return MessageStatus.ACCESS_VIOLATION;
                }

                //If ExistingOpen.SharingMode.FILE_SHARE_WRITE is FALSE and Open.DesiredAccess contains
                //FILE_APPEND_DATA.
                if ((existOpenShareModeShareAccess & ShareAccess.FILE_SHARE_WRITE) == 0 &&
                    (openDesiredAccess & FileAccess.FILE_APPEND_DATA) != 0)
                {
                    return MessageStatus.ACCESS_VIOLATION;
                }

                //If ExistingOpen.SharingMode.FILE_SHARE_DELETE is FALSE and Open.DesiredAccess contains DELETE.
                if ((existOpenShareModeShareAccess & ShareAccess.FILE_SHARE_DELETE) == 0 &&
                    (openDesiredAccess & FileAccess.DELETE) != 0)
                {
                    return MessageStatus.ACCESS_VIOLATION;
                }

                //If Open.SharingMode.FILE_SHARE_READ is FALSE and ExistingOpen.DesiredAccess contains
                //FILE_READ_DATA
                if ((gOpenSharingMode & ShareAccess.FILE_SHARE_READ) == 0 &&
                    (existOpenDesiredAccess & FileAccess.FILE_READ_DATA) != 0)
                {
                    return MessageStatus.ACCESS_VIOLATION;
                }

                //If Open.SharingMode.FILE_SHARE_READ is FALSE and ExistingOpen.DesiredAccess contains
                //FILE_EXECUTE.
                if ((gOpenSharingMode & ShareAccess.FILE_SHARE_READ) == 0 &&
                    (existOpenDesiredAccess & FileAccess.FILE_EXECUTE) != 0)
                {
                    return MessageStatus.ACCESS_VIOLATION;
                }

                //If Open.SharingMode.FILE_SHARE_WRITE is FALSE and ExistingOpen.DesiredAccess
                //contains FILE_WRITE_DATA
                if ((gOpenSharingMode & ShareAccess.FILE_SHARE_WRITE) == 0 &&
                    (existOpenDesiredAccess & FileAccess.FILE_WRITE_DATA) != 0)
                {
                    Helper.CaptureRequirement(653, @"[In Algorithm to Check Sharing Access to an Existing Stream or Directory,
                        Pseudocode for these checks is as follows,For each ExistingOpen in Open.File.OpenList:If ExistingOpen.Stream equals Open.Stream,
                        then return STATUS_ACCESS_VIOLATION under any of the following conditions:]
                        If Open.SharingMode.FILE_SHARE_WRITE is FALSE and ExistingOpen.DesiredAccess contains  FILE_WRITE_DATA .");
                    return MessageStatus.ACCESS_VIOLATION;
                }

                //If Open.SharingMode.FILE_SHARE_WRITE is FALSE and ExistingOpen.DesiredAccess
                //contains FILE_APPEND_DATA.
                if ((gOpenSharingMode & ShareAccess.FILE_SHARE_WRITE) == 0 &&
                    (existOpenDesiredAccess & FileAccess.FILE_APPEND_DATA) != 0)
                {
                    return MessageStatus.ACCESS_VIOLATION;
                }

                //If Open.SharingMode.FILE_SHARE_READ is FALSE and ExistingOpen.DesiredAccess contains DELETE.
                if ((gOpenSharingMode & ShareAccess.FILE_SHARE_READ) != 0 &&
                    (existOpenDesiredAccess & FileAccess.DELETE) == 0)
                {
                    return MessageStatus.ACCESS_VIOLATION;
                }
            }

            Helper.CaptureRequirement(656, @"[In Algorithm to Check Sharing Access to an Existing Stream or Directory]
                Pseudocode for these checks is as follows,if the sharing checks has no violation]Return STATUS_SUCCESS.");
            return MessageStatus.SUCCESS;
        }
예제 #15
0
        public void CreateFile(out NtHandle handle, out FileStatus fileStatus, string path,
                               AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess,
                               CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext?securityContext)
        {
            handle     = null;
            fileStatus = FileStatus.FILE_DOES_NOT_EXIST;
            NTCreateAndXRequest request = new NTCreateAndXRequest
            {
                FileName           = path,
                DesiredAccess      = desiredAccess,
                ExtFileAttributes  = ToExtendedFileAttributes(fileAttributes),
                ShareAccess        = shareAccess,
                CreateDisposition  = createDisposition,
                CreateOptions      = createOptions,
                ImpersonationLevel = ImpersonationLevel.Impersonation
            };

            TrySendMessage(request);
            SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_NT_CREATE_ANDX);

            switch (reply.Commands[0])
            {
            case NTCreateAndXResponse response:
            {
                handle     = new Smb1Handle(response.FID);
                fileStatus = ToFileStatus(response.CreateDisposition);
                reply.IsSuccessElseThrow();
                break;
            }

            case ErrorResponse _:
                reply.IsSuccessElseThrow();
                break;

            default:
                throw new NtStatusException(NTStatus.STATUS_INVALID_SMB);
            }
        }
예제 #16
0
 private static extern NTStatus NtCreateFile(out IntPtr handle, uint desiredAccess, ref OBJECT_ATTRIBUTES objectAttributes, out IO_STATUS_BLOCK ioStatusBlock, ref long allocationSize, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, IntPtr eaBuffer, uint eaLength);
예제 #17
0
        public override bool Exists(string path)
        {
            if (!path.IsSharePath())
            {
                return(base.Exists(path));
            }

            ISMBFileStore fileStore = null;
            object        handle    = null;

            try
            {
                if (!path.TryResolveHostnameFromPath(out var ipAddress))
                {
                    throw new SMBException($"Failed to determine if {path} exists", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
                }

                NTStatus status = NTStatus.STATUS_SUCCESS;

                var credential = _credentialProvider.GetSMBCredential(path);

                using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize))
                {
                    var shareName     = path.ShareName();
                    var directoryPath = _fileSystem.Path.GetDirectoryName(path).Replace(path.SharePath(), "").RemoveLeadingAndTrailingSeperators();
                    var fileName      = _fileSystem.Path.GetFileName(path);

                    _logger?.LogTrace($"Trying to determine if {{DirectoryPath: {directoryPath}}} {{FileName: {fileName}}} Exists for {{ShareName: {shareName}}}");

                    fileStore = connection.SMBClient.TreeConnect(shareName, out status);

                    status.HandleStatus();

                    AccessMask        accessMask    = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ;
                    ShareAccess       shareAccess   = ShareAccess.Read;
                    CreateDisposition disposition   = CreateDisposition.FILE_OPEN;
                    CreateOptions     createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_DIRECTORY_FILE;

                    status = fileStore.CreateFile(out handle, out FileStatus fileStatus, directoryPath, accessMask, 0, shareAccess,
                                                  disposition, createOptions, null);

                    status.HandleStatus();

                    fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, string.IsNullOrEmpty(fileName) ? "*" : fileName, FileInformationClass.FileDirectoryInformation);

                    foreach (var file in queryDirectoryFileInformation)
                    {
                        if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation)
                        {
                            FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file;
                            if (fileDirectoryInformation.FileName == fileName)
                            {
                                FileStoreUtilities.CloseFile(fileStore, ref handle);
                                return(true);
                            }
                        }
                    }

                    FileStoreUtilities.CloseFile(fileStore, ref handle);
                }

                return(false);
            }
            catch (Exception ex)
            {
                _logger?.LogTrace(ex, $"Failed to determine if {path} exists.");
                return(false);
            }
            finally
            {
                FileStoreUtilities.CloseFile(fileStore, ref handle);
            }
        }
예제 #18
0
        internal IFileInfo FromFileName(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(null);
            }

            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new SMBException($"Failed FromFileName for {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
            }

            NTStatus status = NTStatus.STATUS_SUCCESS;

            if (credential == null)
            {
                credential = _credentialProvider.GetSMBCredential(path);
            }

            if (credential == null)
            {
                throw new SMBException($"Failed FromFileName for {path}", new InvalidCredentialException($"Unable to find credential for path: {path}"));
            }

            ISMBFileStore fileStore = null;
            object        handle    = null;

            try
            {
                var shareName    = path.ShareName();
                var relativePath = path.RelativeSharePath();

                _logger?.LogTrace($"Trying FromFileName {{RelativePath: {relativePath}}} for {{ShareName: {shareName}}}");

                using var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize);

                fileStore = connection.SMBClient.TreeConnect(shareName, out status);

                status.HandleStatus();

                AccessMask        accessMask    = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ;
                ShareAccess       shareAccess   = ShareAccess.Read;
                CreateDisposition disposition   = CreateDisposition.FILE_OPEN;
                CreateOptions     createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_NON_DIRECTORY_FILE;

                status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, accessMask, 0, shareAccess,
                                              disposition, createOptions, null);

                status.HandleStatus();

                status = fileStore.GetFileInformation(out FileInformation fileBasicInfo, handle, FileInformationClass.FileBasicInformation);
                status.HandleStatus();
                status = fileStore.GetFileInformation(out FileInformation fileStandardInfo, handle, FileInformationClass.FileStandardInformation);
                status.HandleStatus();

                FileStoreUtilities.CloseFile(fileStore, ref handle);

                return(new SMBFileInfo(path, _fileSystem, (FileBasicInformation)fileBasicInfo, (FileStandardInformation)fileStandardInfo, credential));
            }
            catch (Exception ex)
            {
                throw new SMBException($"Failed FromFileName for {path}", ex);
            }
            finally
            {
                FileStoreUtilities.CloseFile(fileStore, ref handle);
            }
        }
예제 #19
0
        private NTStatus CreateFile(out IntPtr handle, out FileStatus fileStatus, string nativePath, AccessMask desiredAccess, long allocationSize, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions)
        {
            UNICODE_STRING    objectName       = new UNICODE_STRING(nativePath);
            OBJECT_ATTRIBUTES objectAttributes = InitializeObjectAttributes(objectName);
            IO_STATUS_BLOCK   ioStatusBlock;
            NTStatus          status = NtCreateFile(out handle, (uint)desiredAccess, ref objectAttributes, out ioStatusBlock, ref allocationSize, fileAttributes, shareAccess, createDisposition, createOptions, IntPtr.Zero, 0);

            fileStatus = (FileStatus)ioStatusBlock.Information;
            return(status);
        }
예제 #20
0
        public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext)
        {
            handle     = null;
            fileStatus = FileStatus.FILE_DOES_NOT_EXIST;
            FileAccess createAccess         = NTFileStoreHelper.ToCreateFileAccess(desiredAccess, createDisposition);
            bool       requestedWriteAccess = (createAccess & FileAccess.Write) > 0;

            bool forceDirectory = (createOptions & CreateOptions.FILE_DIRECTORY_FILE) > 0;
            bool forceFile      = (createOptions & CreateOptions.FILE_NON_DIRECTORY_FILE) > 0;

            if (forceDirectory & (createDisposition != CreateDisposition.FILE_CREATE &&
                                  createDisposition != CreateDisposition.FILE_OPEN &&
                                  createDisposition != CreateDisposition.FILE_OPEN_IF &&
                                  createDisposition != CreateDisposition.FILE_SUPERSEDE))
            {
                return(NTStatus.STATUS_INVALID_PARAMETER);
            }

            // Windows will try to access named streams (alternate data streams) regardless of the FILE_NAMED_STREAMS flag, we need to prevent this behaviour.
            if (!m_fileSystem.SupportsNamedStreams && path.Contains(":"))
            {
                // Windows Server 2003 will return STATUS_OBJECT_NAME_NOT_FOUND
                return(NTStatus.STATUS_NO_SUCH_FILE);
            }

            FileSystemEntry entry = null;

            try
            {
                entry = m_fileSystem.GetEntry(path);
            }
            catch (FileNotFoundException)
            {
            }
            catch (DirectoryNotFoundException)
            {
            }
            catch (Exception ex)
            {
                if (ex is IOException || ex is UnauthorizedAccessException)
                {
                    NTStatus status = ToNTStatus(ex);
                    Log(Severity.Verbose, "CreateFile: Error retrieving '{0}'. {1}.", path, status);
                    return(status);
                }
                else
                {
                    throw;
                }
            }

            if (createDisposition == CreateDisposition.FILE_OPEN)
            {
                if (entry == null)
                {
                    return(NTStatus.STATUS_NO_SUCH_FILE);
                }

                fileStatus = FileStatus.FILE_EXISTS;
                if (entry.IsDirectory && forceFile)
                {
                    return(NTStatus.STATUS_FILE_IS_A_DIRECTORY);
                }

                if (!entry.IsDirectory && forceDirectory)
                {
                    return(NTStatus.STATUS_OBJECT_PATH_INVALID);
                }
            }
            else if (createDisposition == CreateDisposition.FILE_CREATE)
            {
                if (entry != null)
                {
                    // File already exists, fail the request
                    Log(Severity.Verbose, "CreateFile: File '{0}' already exists.", path);
                    fileStatus = FileStatus.FILE_EXISTS;
                    return(NTStatus.STATUS_OBJECT_NAME_COLLISION);
                }

                if (!requestedWriteAccess)
                {
                    return(NTStatus.STATUS_ACCESS_DENIED);
                }

                try
                {
                    if (forceDirectory)
                    {
                        Log(Severity.Information, "CreateFile: Creating directory '{0}'", path);
                        entry = m_fileSystem.CreateDirectory(path);
                    }
                    else
                    {
                        Log(Severity.Information, "CreateFile: Creating file '{0}'", path);
                        entry = m_fileSystem.CreateFile(path);
                    }
                }
                catch (Exception ex)
                {
                    if (ex is IOException || ex is UnauthorizedAccessException)
                    {
                        NTStatus status = ToNTStatus(ex);
                        Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status);
                        return(status);
                    }
                    else
                    {
                        throw;
                    }
                }
                fileStatus = FileStatus.FILE_CREATED;
            }
            else if (createDisposition == CreateDisposition.FILE_OPEN_IF ||
                     createDisposition == CreateDisposition.FILE_OVERWRITE ||
                     createDisposition == CreateDisposition.FILE_OVERWRITE_IF ||
                     createDisposition == CreateDisposition.FILE_SUPERSEDE)
            {
                if (entry == null)
                {
                    if (createDisposition == CreateDisposition.FILE_OVERWRITE)
                    {
                        return(NTStatus.STATUS_OBJECT_PATH_NOT_FOUND);
                    }

                    if (!requestedWriteAccess)
                    {
                        return(NTStatus.STATUS_ACCESS_DENIED);
                    }

                    try
                    {
                        if (forceDirectory)
                        {
                            Log(Severity.Information, "CreateFile: Creating directory '{0}'", path);
                            entry = m_fileSystem.CreateDirectory(path);
                        }
                        else
                        {
                            Log(Severity.Information, "CreateFile: Creating file '{0}'", path);
                            entry = m_fileSystem.CreateFile(path);
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ex is IOException || ex is UnauthorizedAccessException)
                        {
                            NTStatus status = ToNTStatus(ex);
                            Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status);
                            return(status);
                        }
                        else
                        {
                            throw;
                        }
                    }
                    fileStatus = FileStatus.FILE_CREATED;
                }
                else
                {
                    fileStatus = FileStatus.FILE_EXISTS;
                    if (createDisposition == CreateDisposition.FILE_OPEN_IF)
                    {
                        if (entry.IsDirectory && forceFile)
                        {
                            return(NTStatus.STATUS_FILE_IS_A_DIRECTORY);
                        }

                        if (!entry.IsDirectory && forceDirectory)
                        {
                            return(NTStatus.STATUS_OBJECT_PATH_INVALID);
                        }
                    }
                    else
                    {
                        if (!requestedWriteAccess)
                        {
                            return(NTStatus.STATUS_ACCESS_DENIED);
                        }

                        if (createDisposition == CreateDisposition.FILE_OVERWRITE ||
                            createDisposition == CreateDisposition.FILE_OVERWRITE_IF)
                        {
                            // Truncate the file
                            try
                            {
                                Stream temp = m_fileSystem.OpenFile(path, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite, FileOptions.None);
                                temp.Close();
                            }
                            catch (Exception ex)
                            {
                                if (ex is IOException || ex is UnauthorizedAccessException)
                                {
                                    NTStatus status = ToNTStatus(ex);
                                    Log(Severity.Verbose, "CreateFile: Error truncating '{0}'. {1}.", path, status);
                                    return(status);
                                }
                                else
                                {
                                    throw;
                                }
                            }
                            fileStatus = FileStatus.FILE_OVERWRITTEN;
                        }
                        else if (createDisposition == CreateDisposition.FILE_SUPERSEDE)
                        {
                            // Delete the old file
                            try
                            {
                                m_fileSystem.Delete(path);
                            }
                            catch (Exception ex)
                            {
                                if (ex is IOException || ex is UnauthorizedAccessException)
                                {
                                    NTStatus status = ToNTStatus(ex);
                                    Log(Severity.Verbose, "CreateFile: Error deleting '{0}'. {1}.", path, status);
                                    return(status);
                                }
                                else
                                {
                                    throw;
                                }
                            }

                            try
                            {
                                if (forceDirectory)
                                {
                                    Log(Severity.Information, "CreateFile: Creating directory '{0}'", path);
                                    entry = m_fileSystem.CreateDirectory(path);
                                }
                                else
                                {
                                    Log(Severity.Information, "CreateFile: Creating file '{0}'", path);
                                    entry = m_fileSystem.CreateFile(path);
                                }
                            }
                            catch (Exception ex)
                            {
                                if (ex is IOException || ex is UnauthorizedAccessException)
                                {
                                    NTStatus status = ToNTStatus(ex);
                                    Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status);
                                    return(status);
                                }
                                else
                                {
                                    throw;
                                }
                            }
                            fileStatus = FileStatus.FILE_SUPERSEDED;
                        }
                    }
                }
            }
            else
            {
                return(NTStatus.STATUS_INVALID_PARAMETER);
            }

            FileAccess fileAccess = NTFileStoreHelper.ToFileAccess(desiredAccess);
            Stream     stream;

            if (fileAccess == (FileAccess)0 || entry.IsDirectory)
            {
                stream = null;
            }
            else
            {
                // Note that SetFileInformationByHandle/FILE_DISPOSITION_INFO has no effect if the handle was opened with FILE_DELETE_ON_CLOSE.
                NTStatus openStatus = OpenFileStream(out stream, path, fileAccess, shareAccess, createOptions);
                if (openStatus != NTStatus.STATUS_SUCCESS)
                {
                    return(openStatus);
                }
            }

            bool deleteOnClose = (createOptions & CreateOptions.FILE_DELETE_ON_CLOSE) > 0;

            handle = new FileHandle(path, entry.IsDirectory, stream, deleteOnClose);
            if (fileStatus != FileStatus.FILE_CREATED &&
                fileStatus != FileStatus.FILE_OVERWRITTEN &&
                fileStatus != FileStatus.FILE_SUPERSEDED)
            {
                fileStatus = FileStatus.FILE_OPENED;
            }
            return(NTStatus.STATUS_SUCCESS);
        }
예제 #21
0
        private NTStatus OpenFileStream(out Stream stream, string path, FileAccess fileAccess, ShareAccess shareAccess, CreateOptions openOptions)
        {
            stream = null;
            FileShare   fileShare         = NTFileStoreHelper.ToFileShare(shareAccess);
            FileOptions fileOptions       = ToFileOptions(openOptions);
            string      fileShareString   = fileShare.ToString().Replace(", ", "|");
            string      fileOptionsString = ToFileOptionsString(fileOptions);

            try
            {
                stream = m_fileSystem.OpenFile(path, FileMode.Open, fileAccess, fileShare, fileOptions);
            }
            catch (Exception ex)
            {
                if (ex is IOException || ex is UnauthorizedAccessException)
                {
                    NTStatus status = ToNTStatus(ex);
                    Log(Severity.Verbose, "OpenFile: Cannot open '{0}', Access={1}, Share={2}. NTStatus: {3}.", path, fileAccess, fileShareString, status);
                    return(status);
                }
                else
                {
                    throw;
                }
            }

            Log(Severity.Information, "OpenFileStream: Opened '{0}', Access={1}, Share={2}, FileOptions={3}", path, fileAccess, fileShareString, fileOptionsString);
            return(NTStatus.STATUS_SUCCESS);
        }
예제 #22
0
        public object OpenFile(
            string filename,
            bool isDirectory,
            FileMode fileMode     = FileMode.Open,
            FileAccess fileAccess = FileAccess.Read,
            FileShare fileShare   = FileShare.None,
            bool forDeletion      = false)
        {
            AccessMask accessMask = 0;

            if (fileAccess == FileAccess.Read)
            {
                accessMask |= AccessMask.GENERIC_READ;
            }
            if (fileAccess == FileAccess.Write)
            {
                accessMask |= AccessMask.GENERIC_WRITE;
            }
            if (fileAccess == FileAccess.ReadWrite)
            {
                accessMask |= AccessMask.GENERIC_WRITE | AccessMask.GENERIC_READ;
            }

            if (forDeletion)
            {
                accessMask |= AccessMask.DELETE;
            }

            ShareAccess shareAccess = ShareAccess.None;

            if (fileShare == FileShare.Read)
            {
                shareAccess |= ShareAccess.Read;
            }
            if (fileShare == FileShare.Delete)
            {
                shareAccess |= ShareAccess.Delete;
            }
            if (fileShare == FileShare.Write)
            {
                shareAccess |= ShareAccess.Write;
            }
            if (fileShare == FileShare.ReadWrite)
            {
                shareAccess |= ShareAccess.Write | ShareAccess.Read;
            }

            CreateDisposition createDisposition = CreateDisposition.FILE_SUPERSEDE;

            if (fileMode == FileMode.CreateNew)
            {
                createDisposition = CreateDisposition.FILE_CREATE;
            }
            if (fileMode == FileMode.Create)
            {
                createDisposition = CreateDisposition.FILE_SUPERSEDE;
            }
            if (fileMode == FileMode.Open)
            {
                createDisposition = CreateDisposition.FILE_OPEN;
            }
            if (fileMode == FileMode.OpenOrCreate)
            {
                createDisposition = CreateDisposition.FILE_OPEN_IF;
            }
            if (fileMode == FileMode.Truncate)
            {
                createDisposition = CreateDisposition.FILE_OVERWRITE_IF;
            }
            if (fileMode == FileMode.Append)
            {
                createDisposition = CreateDisposition.FILE_OPEN;
            }

            CreateOptions createOptions = 0;

            if (isDirectory)
            {
                createOptions |= CreateOptions.FILE_DIRECTORY_FILE;
            }
            else
            {
                createOptions |= CreateOptions.FILE_NON_DIRECTORY_FILE;
            }


            object     fileHandle;
            FileStatus fileStatus;

            ThrowOnError(FileStore.CreateFile(
                             out fileHandle,
                             out fileStatus,
                             filename,
                             accessMask,
                             SMBLibrary.FileAttributes.Normal,
                             shareAccess,
                             createDisposition,
                             createOptions,
                             null));

            return(fileHandle);
        }
        public static MessageStatus OpenFileinitial(
            FileAccess desiredAccess,
            ShareAccess shareAccess,
            CreateOptions createOption,
            CreateDisposition createDisposition,
            FileAttribute fileAttribute,
            StreamFoundType streamFoundType,
            SymbolicLinkType symbolicLinkType,
            StreamTypeNameToOPen streamTypeNameToOPen,
            FileType openFileType,
            FileNameStatus fileNameStatus)
        {
            #region phase 1  Parameter Validation

            //If DesiredAccess is not a valid value as specified in MS-SMB2 section 2.2.13.1
            if (desiredAccess == FileAccess.None)
            {
                Helper.CaptureRequirement(366, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]If any of the bits in the mask 0x0CE0FE00 are set,
                    the operation MUST be failed with STATUS_ACCESS_DENIED.");
                //If DesiredAccess is zero
                Helper.CaptureRequirement(377, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]If DesiredAccess is zero, the operation MUST be failed with STATUS_ACCESS_DENIED.");
                return MessageStatus.ACCESS_DENIED;
            }

            //If ShareAccess is not valid values for a file object as specified in MS-SMB2 section 2.2.13
            if (shareAccess == ShareAccess.NOT_VALID_VALUE)
            {
                Helper.CaptureRequirement(2370, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If ShareAccess are not valid values for a file object as specified in [MS-SMB2] section 2.2.13.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateOptions is not valid values for a file object as specified in MS-SMB2 section 2.2.13
            if (createOption == CreateOptions.NOT_VALID_VALUE)
            {
                Helper.CaptureRequirement(2371, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions are not valid values for a file object as specified in [MS-SMB2] section 2.2.13.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateDisposition is not valid values for a file object as specified in MS-SMB2 section 2.2.13
            if (createDisposition == CreateDisposition.NOT_VALID_VALUE)
            {
                Helper.CaptureRequirement(2372, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateDisposition are not valid values for a file object as specified in [MS-SMB2] section 2.2.13.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If FileAttributes is not valid values for a file object as specified in MS-SMB2 section 2.2.13
            if (fileAttribute == FileAttribute.NOT_VALID_VALUE)
            {
                Helper.CaptureRequirement(404, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If FileAttributes are not valid values for a file object as specified in [MS-SMB2] section 2.2.13.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateOptions.FILE_DIRECTORY_FILE && CreateOptions.FILE_NON_DIRECTORY_FILE.
            //65 indicates CreateOptions.FILE_DIRECTORY_FILE && CreateOptions.FILE_NON_DIRECTORY_FILE
            if (createOption == (CreateOptions.DIRECTORY_FILE | CreateOptions.NON_DIRECTORY_FILE))
            {
                Helper.CaptureRequirement(368, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions.FILE_DIRECTORY_FILE && CreateOptions.FILE_NON_DIRECTORY_FILE.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateOptions.FILE_SYNCHRONOUS_IO_ALERT && !DesiredAccess.SYNCHRONIZE.
            //updated by meying:desiredAccess == FileAccess.FILE_READ_DATA
            if (createOption == CreateOptions.SYNCHRONOUS_IO_ALERT
               && desiredAccess == FileAccess.FILE_READ_DATA)
            {
                Helper.CaptureRequirement(369, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions.FILE_SYNCHRONOUS_IO_ALERT && !DesiredAccess.SYNCHRONIZE.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If Create.FILE_SYNCHRONOUS_IO_NONALERT && !DesiredAccess.SYNCHRONIZE.
            //updated by meying:desiredAccess == FileAccess.FILE_READ_DATA
            if (createOption == CreateOptions.SYNCHRONOUS_IO_NONALERT
               && desiredAccess == FileAccess.FILE_READ_DATA)
            {
                Helper.CaptureRequirement(2373, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If Create.FILE_SYNCHRONOUS_IO_NONALERT&& !DesiredAccess.SYNCHRONIZE.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateOptions.FILE_DELETE_ON_CLOSE && !DesiredAccess.DELETE.
            if (createOption == CreateOptions.DELETE_ON_CLOSE &&
                (desiredAccess == FileAccess.FILE_READ_DATA))
            {
                Helper.CaptureRequirement(371, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions.FILE_DELETE_ON_CLOSE && !DesiredAccess.DELETE.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //CreateOptions.FILE_SYNCHRONOUS_IO_ALERT && Create.FILE_SYNCHRONOUS_IO_NONALERT
            //48 indicates CreateOptions.FILE_SYNCHRONOUS_IO_ALERT && Create.FILE_SYNCHRONOUS_IO_NONALERT
            if (createOption == (CreateOptions.SYNCHRONOUS_IO_NONALERT | CreateOptions.SYNCHRONOUS_IO_ALERT))
            {
                Helper.CaptureRequirement(373, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions.FILE_SYNCHRONOUS_IO_ALERT && Create.FILE_SYNCHRONOUS_IO_NONALERT.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateOptions.FILE_DIRECTORY_FILE && CreateDisposition == OVERWRITE.
            if (createOption == CreateOptions.DIRECTORY_FILE &&
                createDisposition == CreateDisposition.OVERWRITE)
            {
                Helper.CaptureRequirement(2375, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions.FILE_DIRECTORY_FILE && CreateDisposition == OVERWRITE.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateOptions.FILE_DIRECTORY_FILE && CreateDisposition == NONE .
            if (createOption == CreateOptions.DIRECTORY_FILE &&
                createDisposition == CreateDisposition.SUPERSEDE)
            {
                Helper.CaptureRequirement(2374, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions.FILE_DIRECTORY_FILE && CreateDisposition == SUPERSEDE .");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateOptions.FILE_DIRECTORY_FILE && CreateDisposition == OVERWRITE_IF.
            if (createOption == CreateOptions.DIRECTORY_FILE &&
                createDisposition == CreateDisposition.OVERWRITE_IF)
            {
                Helper.CaptureRequirement(2376, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions.FILE_DIRECTORY_FILE && CreateDisposition == OVERWRITE_IF).");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateOptions.COMPLETE_IF_OPLOCKED && CreateOptions.FILE_RESERVE_OPFILTER
            //if ((createOption & (CreateOptions.COMPLETE_IF_OPLOCKED | CreateOptions.RESERVE_OPFILTER)) != 0)
            //1048832 indicates CreateOptions.COMPLETE_IF_OPLOCKED && CreateOptions.FILE_RESERVE_OPFILTER
            if (createOption == (CreateOptions.COMPLETE_IF_OPLOCKED | CreateOptions.RESERVE_OPFILTER))
            {
                Helper.CaptureRequirement(375, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions.COMPLETE_IF_OPLOCKED && CreateOptions.FILE_RESERVE_OPFILTER.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If CreateOptions.FILE_NO_INTERMEDIATE_BUFFERING && DesiredAccess.FILE_APPEND_DATA.
            if (createOption == CreateOptions.NO_INTERMEDIATE_BUFFERING &&
                desiredAccess == FileAccess.FILE_APPEND_DATA)
            {
                Helper.CaptureRequirement(376, @"[In Application Requests an Open of a File ,Phase 1 - Parameter Validation:]
                    The operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:
                    If CreateOptions.FILE_NO_INTERMEDIATE_BUFFERING && DesiredAccess.FILE_APPEND_DATA.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If PathName is not valid as specified in [MS-FSCC] section 2.1.5.
            if (fileNameStatus == FileNameStatus.NotPathNameValid)
            {
                Helper.CaptureRequirement(379, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_OBJECT_NAME_INVALID under any of the following conditions:
                    If PathName is not valid as specified in [MS-FSCC] section 2.1.5.");
                return MessageStatus.OBJECT_NAME_INVALID;
            }

            //If PathName contains a trailing backslash and CreateOptions.FILE_NON_DIRECTORY_FILE is true
            if (fileNameStatus == FileNameStatus.BlacklashName &&
                createOption == CreateOptions.NON_DIRECTORY_FILE &&
                desiredAccess == FileAccess.FILE_READ_DATA)
            {
                Helper.CaptureRequirement(380, @"[In Application Requests an Open of a File ,Pseudocode for the operation is as follows:
                    Phase 1 - Parameter Validation:]The operation MUST be failed with STATUS_OBJECT_NAME_INVALID under any of the following conditions:
                    If PathName contains a trailing backslash and CreateOptions.FILE_NON_DIRECTORY_FILE is TRUE.");
                return MessageStatus.OBJECT_NAME_INVALID;
            }

            #endregion

            #region phase 2  Volume State

            //If RootOpen.Volume.IsReadOnly && (CreateDisposition == FILE_CREATE)
            //then the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED
            if (isFileVolumeReadOnly && (createDisposition == CreateDisposition.CREATE))
            {
                Helper.CaptureRequirement(2377, @"[In Application Requests an Open of a File,Pseudocode for the operation is as follows: ]
                    If RootOpen.Volume.IsReadOnly && CreateDisposition == FILE_CREATE,then the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.");
                return MessageStatus.MEDIA_WRITE_PROTECTED;
            }

            //If RootOpen.Volume.IsReadOnly && (CreateDisposition == FILE_SUPERSEDE)
            //then the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED
            if (isFileVolumeReadOnly && (createDisposition == CreateDisposition.SUPERSEDE))
            {
                Helper.CaptureRequirement(2378, @"[In Application Requests an Open of a File,Pseudocode for the operation is as follows: ]
                    If RootOpen.Volume.IsReadOnly &&CreateDisposition == FILE_SUPERSEDE, then the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.");
                return MessageStatus.MEDIA_WRITE_PROTECTED;
            }

            //If RootOpen.Volume.IsReadOnly && (CreateDisposition == OVERWRITE)
            //then the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED
            if (isFileVolumeReadOnly && (createDisposition == CreateDisposition.OVERWRITE))
            {
                Helper.CaptureRequirement(2379, @"[In Application Requests an Open of a File,Pseudocode for the operation is as follows: ]
                    If RootOpen.Volume.IsReadOnly &&CreateDisposition == OVERWRITE, then the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.");
                return MessageStatus.MEDIA_WRITE_PROTECTED;
            }

            //If RootOpen.Volume.IsReadOnly && (CreateDisposition == OVERWRITE_IF)
            //then the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED
            if (isFileVolumeReadOnly && (createDisposition == CreateDisposition.OVERWRITE_IF))
            {
                Helper.CaptureRequirement(2380, @"[In Application Requests an Open of a File,Pseudocode for the operation is as follows: ]
                    If RootOpen.Volume.IsReadOnly &&CreateDisposition == OVERWRITE_IF, then the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.");
                return MessageStatus.MEDIA_WRITE_PROTECTED;
            }

            #endregion

            #region Phase 3  Initialization of Open Object

            gOpenRemainingDesiredAccess = desiredAccess;
            gOpenSharingMode = shareAccess;
            //4158 indicates (createOption & (CreateOptions.WRITE_THROUGH |
            //CreateOptions.SEQUENTIAL_ONLY | CreateOptions.NO_INTERMEDIATE_BUFFERING |
            //CreateOptions.SYNCHRONOUS_IO_ALERT | CreateOptions.SYNCHRONOUS_IO_NONALERT |
            //CreateOptions.DELETE_ON_CLOSE));

            gOpenMode = (CreateOptions.WRITE_THROUGH |
            CreateOptions.SEQUENTIAL_ONLY | CreateOptions.NO_INTERMEDIATE_BUFFERING |
            CreateOptions.SYNCHRONOUS_IO_ALERT | CreateOptions.SYNCHRONOUS_IO_NONALERT |
            CreateOptions.DELETE_ON_CLOSE);
            if (gSecurityContext.privilegeSet == PrivilegeSet.SeBackupPrivilege)
            {
                isOpenHasBackupAccess = true;
            }

            if (gSecurityContext.privilegeSet == PrivilegeSet.SeRestorePrivilege)
            {
                isOpenHasRestoreAccess = true;
            }

            if (gSecurityContext.privilegeSet == PrivilegeSet.SeCreateSymbolicLinkPrivilege)
            {
                isOpenHasCreateSymbolicLinkAccess = true;
            }

            if (gSecurityContext.privilegeSet == PrivilegeSet.SeManageVolumePrivilege)
            {
                isOpenHasManageVolumeAccess = true;
            }

            if (gSecurityContext.isSecurityContextSIDsContainWellKnown)
            {
                isOpenIsAdministrator = true;
            }

            #endregion

            #region phase 4  Check for backup/restore intent

            //If CreateOptions.FILE_OPEN_FOR_BACKUP_INTENT is set and (CreateDisposition ==
            //FILE_OPEN || CreateDisposition == FILE_OPEN_IF || CreateDisposition ==
            //FILE_OVERWRITE_IF) and Open.HasBackupAccess is true, then the object store
            //SHOULD grant backup access as shown in the following pseudocode:
            if (createOption == CreateOptions.OPEN_FOR_BACKUP_INTENT &&
                (createDisposition == CreateDisposition.OPEN ||
                createDisposition == CreateDisposition.OPEN_IF ||
                createDisposition == CreateDisposition.OVERWRITE_IF) && isOpenHasBackupAccess)
            {
                //2164391968 indicates FileAccess.READ_CONTROL |
                //FileAccess.ACCESS_SYSTEM_SECURITY | FileAccess.GENERIC_READ |
                //FileAccess.FILE_TRAVERSE;
                FileAccess BackupAccess = FileAccess.READ_CONTROL |
                FileAccess.ACCESS_SYSTEM_SECURITY | FileAccess.GENERIC_READ |
                FileAccess.FILE_TRAVERSE;

                if (gOpenRemainingDesiredAccess == FileAccess.MAXIMUM_ALLOWED)
                {
                    gOpenGrantedAccess = gOpenGrantedAccess | BackupAccess;
                }
                else
                {
                    gOpenGrantedAccess = gOpenGrantedAccess | (gOpenRemainingDesiredAccess & BackupAccess);
                }

                gOpenRemainingDesiredAccess = gOpenRemainingDesiredAccess & (~gOpenGrantedAccess);
            }

            //If CreateOptions.FILE_OPEN_FOR_BACKUP_INTENT is set and Open.HasRestoreAccess is true,
            //then the object store SHOULD grant restore access as shown in the following pseudocode:
            if (createOption == CreateOptions.OPEN_FOR_BACKUP_INTENT && isHasRestoreAccess)
            {
                //1091309574 indicates FileAccess.WRITE_DAC | FileAccess.WRITE_OWNER |
                //FileAccess.ACCESS_SYSTEM_SECURITY | FileAccess.GENERIC_WRITE |
                //FileAccess.FILE_ADD_FILE | FileAccess.FILE_ADD_SUBDIRECTORY |
                //FileAccess.DELETE
                FileAccess RestoreAccess = FileAccess.WRITE_DAC | FileAccess.WRITE_OWNER |
                FileAccess.ACCESS_SYSTEM_SECURITY | FileAccess.GENERIC_WRITE |
                FileAccess.FILE_ADD_FILE | FileAccess.FILE_ADD_SUBDIRECTORY |
                FileAccess.DELETE;

                if (gOpenRemainingDesiredAccess == FileAccess.MAXIMUM_ALLOWED)
                {
                    gOpenGrantedAccess = gOpenGrantedAccess | RestoreAccess;
                }
                else
                {
                    gOpenGrantedAccess = gOpenGrantedAccess | (gOpenRemainingDesiredAccess & RestoreAccess);
                }

                gOpenRemainingDesiredAccess = gOpenRemainingDesiredAccess & (~gOpenGrantedAccess);
            }

            #endregion

            #region phase 5  Parse path name

            //If any StreamTypeNamei is "$INDEX_ALLOCATION" and the corresponding
            //StreamNamei has a value other than an empty string or "$I30"
            if (fileNameStatus == FileNameStatus.StreamTypeNameIsINDEX_ALLOCATION)
            {
                if (sutPlatForm != PlatformType.NoneWindows)
                {
                    Helper.CaptureRequirement(507, @"[In Application Requests an Open of a File ,Phase 5 -- Parse path name:]
                        If any StreamTypeNamei is \""$INDEX_ALLOCATION"" and the corresponding StreamNamei has a value other than an empty string
                        or \""$I30"", the operation is failed with STATUS_INVALID_PARAMETER in Windows.");
                    return MessageStatus.INVALID_PARAMETER;
                }
                else if (isR507Implemented)
                {
                    Helper.CaptureRequirement(392, @"[In Application Requests an Open of a File ,Phase 5 -- Parse path name:]
                        If any StreamTypeNamei is \""$INDEX_ALLOCATION"" and the corresponding StreamNamei has a value other than an empty string
                        or \""$I30\"", the operation SHOULD be failed with STATUS_INVALID_PARAMETER.");
                    return MessageStatus.INVALID_PARAMETER;
                }
            }

            #endregion

            #region phase 6  Location of file

            if (streamFoundType == StreamFoundType.StreamIsNotFound)
            {
                //If (CreateDisposition == FILE_OPEN )
                if (createDisposition == CreateDisposition.OPEN)
                {
                    Helper.CaptureRequirement(513, @"[In Application Requests an Open of a File , Pseudocode for the operation is as follows:
                        Phase 6 -- Location of file:] Else:[If such a link is not found:]
                        If CreateDisposition == FILE_OPEN, the operation MUST be failed with STATUS_OBJECT_NAME_NOT_FOUND.");
                    return MessageStatus.OBJECT_NAME_NOT_FOUND;
                }

                //If (CreateDisposition == FILE_OVERWRITE)
                if (createDisposition == CreateDisposition.OVERWRITE)
                {
                    Helper.CaptureRequirement(2395, @"[In Application Requests an Open of a File , Pseudocode for the operation is as follows:
                        Phase 6 -- Location of file:] Else:[If such a link is not found:]If CreateDisposition == FILE_OVERWRITE),
                        the operation MUST be failed with STATUS_OBJECT_NAME_NOT_FOUND.");
                    return MessageStatus.OBJECT_NAME_NOT_FOUND;
                }

                //If RootOpen.Volume.IsReadOnly
                if (isFileVolumeReadOnly)
                {
                    Helper.CaptureRequirement(514, @"[In Application Requests an Open of a File , Pseudocode for the operation is as follows:
                        Phase 6 -- Location of file:] Else:[If such a link is not found:]If RootOpen.Volume.IsReadOnly
                        then the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.");
                    return MessageStatus.MEDIA_WRITE_PROTECTED;
                }

                //Helper.CaptureRequirement(547, @"[In Application Requests an Open of a File , Pseudocode for the operation is as follows:Phase 6 -- Location of file:] for this search is as follows:For i = 1 to n-1:Search ParentFile.DirectoryList for a Link where Link.Name or Link.ShortName matches FileNamei,If no such link is found, the operation MUST be failed with STATUS_OBJECT_PATH_NOT_FOUND.");
                //return MessageStatus.OBJECT_PATH_NOT_FOUND;
            }

            //If Open.GrantedAccess.FILE_TRAVERSE is not set and
            //AccessCheck( SecurityContext, Link.File.SecurityDescriptor, FILE_TRAVERSE )
            //returns FALSE,
            if ((gOpenGrantedAccess & FileAccess.FILE_TRAVERSE) == 0)
            {
                if (sutPlatForm != PlatformType.NoneWindows)
                {
                    Helper.CaptureRequirement(405, @"[In Application Requests an Open of a File , Pseudocode for the operation is as follows:
                        Phase 6 -- Location of file:] Pseudocode for this search:For i = 1 to n-1:
                        If Open.GrantedAccess.FILE_TRAVERSE is not set and AccessCheck( SecurityContext, Link.File.SecurityDescriptor, FILE_TRAVERSE )
                        returns FALSE, the operation is not  failed with STATUS_ACCESS_DENIED in Windows.");
                }
                if (isR405Implemented)
                {
                    Helper.CaptureRequirement(397, @"[In Application Requests an Open of a File ,
                        Pseudocode for the operation is as follows:Phase 6 -- Location of file:]
                        Pseudocode for this search:For i = 1 to n-1:If Open.GrantedAccess.FILE_TRAVERSE is not set
                        and AccessCheck( SecurityContext, Link.File.SecurityDescriptor, FILE_TRAVERSE ) returns FALSE, the operation MAY be failed with STATUS_ACCESS_DENIED.");
                    return MessageStatus.ACCESS_DENIED;
                }
            }
            //If Link.File.IsSymbolicLink is true
            if (symbolicLinkType == SymbolicLinkType.IsSymbolicLink)
            {
                Helper.CaptureRequirement(399, @"[In Application Requests an Open of a File ,
                     Pseudocode for the operation is as follows:Phase 6 - Location of file:]
                     Pseudocode for this search:For i = 1 to n-1:If Link.File.IsSymbolicLink is TRUE,
                     the operation MUST be failed with Status set to STATUS_STOPPED_ON_SYMLINK .");
                return MessageStatus.STOPPED_ON_SYMLINK;
            }

            #endregion

            #region phase 7  Type of file to open

            //If CreateOptions.FILE_DIRECTORY_FILE is true
            if (createOption == CreateOptions.DIRECTORY_FILE)
            {
                gfileTypeToOpen = FileType.DirectoryFile;
            }
            //Else if CreateOptions.FILE_NON_DIRECTORY_FILE is true
            else if (createOption == CreateOptions.NON_DIRECTORY_FILE)
            {
                gfileTypeToOpen = FileType.DataFile;
            }
            //Else if StreamTypeNameToOpen is "$INDEX_ALLOCATION"
            else if (streamTypeNameToOPen == StreamTypeNameToOPen.INDEX_ALLOCATION)
            {
                gfileTypeToOpen = FileType.DirectoryFile;
            }
            //Else if StreamTypeNameToOpen is "$DATA"
            else if (streamTypeNameToOPen == StreamTypeNameToOPen.DATA)
            {
                gfileTypeToOpen = FileType.DataFile;
            }
            //Else if Open.File is not NULL and Open.File.FileType is DirectoryFile
            else if (fileNameStatus == FileNameStatus.OpenFileNotNull &&
                openFileType == FileType.DirectoryFile)
            {
                gfileTypeToOpen = FileType.DirectoryFile;
            }
            //Else if PathName contains a trailing backslash
            else if (fileNameStatus == FileNameStatus.PathNameTraiblack)
            {
                gfileTypeToOpen = FileType.DirectoryFile;
            }
            //else
            else
            {
                gfileTypeToOpen = FileType.DataFile;
            }

            //If FileTypeToOpen is DirectoryFile and Open.File is not NULL and
            //Open.File.FileType is not DirectoryFile:
            if (gfileTypeToOpen == FileType.DirectoryFile &&
                fileNameStatus == FileNameStatus.OpenFileNotNull &&
                openFileType == FileType.DataFile)
            {
                //If CreateDisposition == FILE_CREATE
                if (createDisposition == CreateDisposition.CREATE)
                {
                    Helper.CaptureRequirement(414, @"[In Application Requests an Open of a File , Pseudocode for the operation is as follows:
                        Phase 7 -- Type of file to open:]If FileTypeToOpen is DirectoryFile and Open.File is not NULL
                        and Open.File.FileType is not DirectoryFile:If CreateDisposition == FILE_CREATE then the operation MUST be failed with STATUS_OBJECT_NAME_COLLISION.");
                    return MessageStatus.OBJECT_NAME_COLLISION;
                }
                //else
                else
                {
                    Helper.CaptureRequirement(2396, @"[In Application Requests an Open of a File , Phase 7 -- Type of file to open:]
                        If FileTypeToOpen is DirectoryFile and Open.File is not NULL and Open.File.FileType is not DirectoryFile:
                        else[If CreateDisposition != FILE_CREATE] the operation MUST be failed with STATUS_NOT_A_DIRECTORY.");
                    return MessageStatus.NOT_A_DIRECTORY;
                }
            }

            //If FileTypeToOpen is DataFile and StreamNameToOpen is empty and Open.File
            //is not NULL and Open.File.FileType is DirectoryFile
            if (gfileTypeToOpen == FileType.DataFile &&
                streamTypeNameToOPen == StreamTypeNameToOPen.NULL &&
                fileNameStatus == FileNameStatus.OpenFileNotNull &&
                openFileType == FileType.DirectoryFile)
            {
                Helper.CaptureRequirement(415, @"[In Application Requests an Open of a File , Pseudocode for the operation is as follows:
                    Phase 7 -- Type of file to open:]If FileTypeToOpen is DataFile and StreamNameToOpen is empty and Open.File is not NULL
                    and Open.File.FileType is DirectoryFile, the operation MUST be failed with STATUS_FILE_IS_A_DIRECTORY.");
                return MessageStatus.FILE_IS_A_DIRECTORY;
            }

            #endregion

            return MessageStatus.SUCCESS;
        }
 internal static MessageStatus WorkaroundOpenExistingFile(ShareAccess shareAccess, FileAccess desiredAccess,
     bool streamFound, bool isSymbolicLink, FileType openFileType, FileNameStatus fileNameStatus,
     CreateOptions existingOpenModeCreateOption, ShareAccess existOpenShareModeShareAccess,
     FileAccess existOpenDesiredAccess, CreateOptions createOption, CreateDisposition createDisposition,
     StreamTypeNameToOPen streamTypeNameToOPen, FileAttribute fileAttribute,
     FileAttribute desiredFileAttribute, MessageStatus returnedStatus, ITestSite site)
 {
     if (shareAccess == ShareAccess.FILE_SHARE_READ && desiredAccess == FileAccess.FILE_ADD_SUBDIRECTORY
         && !streamFound && !isSymbolicLink && openFileType == FileType.DataFile && fileNameStatus == FileNameStatus.Normal
         && existingOpenModeCreateOption == CreateOptions.NON_DIRECTORY_FILE && existOpenShareModeShareAccess == ShareAccess.FILE_SHARE_READ
         && existOpenDesiredAccess == FileAccess.FILE_LIST_DIRECTORY && createOption == CreateOptions.NO_INTERMEDIATE_BUFFERING
         && createDisposition == CreateDisposition.OPEN_IF && streamTypeNameToOPen == StreamTypeNameToOPen.NULL
         && fileAttribute == FileAttribute.NORMAL && desiredFileAttribute == FileAttribute.NORMAL)
     {
         returnedStatus = FsaUtility.TransferExpectedResult<MessageStatus>(376, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == (CreateOptions.SYNCHRONOUS_IO_NONALERT | CreateOptions.SYNCHRONOUS_IO_ALERT))
     {
         returnedStatus = FsaUtility.TransferExpectedResult<MessageStatus>(373, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == CreateOptions.SYNCHRONOUS_IO_ALERT
        && desiredAccess == FileAccess.FILE_READ_DATA)
     {
         returnedStatus = FsaUtility.TransferExpectedResult<MessageStatus>(369, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == CreateOptions.SYNCHRONOUS_IO_NONALERT
         && desiredAccess == FileAccess.FILE_READ_DATA)
     {
         returnedStatus = FsaUtility.TransferExpectedResult<MessageStatus>(2373, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == CreateOptions.DELETE_ON_CLOSE &&
         (desiredAccess == FileAccess.ACCESS_SYSTEM_SECURITY))
     {
         returnedStatus = FsaUtility.TransferExpectedResult<MessageStatus>(371, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (createOption == (CreateOptions.COMPLETE_IF_OPLOCKED | CreateOptions.RESERVE_OPFILTER))
     {
         returnedStatus = FsaUtility.TransferExpectedResult<MessageStatus>(375, MessageStatus.INVALID_PARAMETER, returnedStatus, site);
     }
     else if (streamFound && !isSymbolicLink && openFileType == FileType.DataFile &&
         existingOpenModeCreateOption == CreateOptions.DIRECTORY_FILE &&
         existOpenDesiredAccess == FileAccess.FILE_LIST_DIRECTORY &&
         createOption == CreateOptions.DIRECTORY_FILE)
     {
         returnedStatus = FsaUtility.TransferExpectedResult<MessageStatus>(375, MessageStatus.ACCESS_VIOLATION, returnedStatus, site);
     }
     else if (!streamFound && !isSymbolicLink && openFileType == FileType.DataFile &&
         existingOpenModeCreateOption == CreateOptions.NON_DIRECTORY_FILE &&
         existOpenDesiredAccess == FileAccess.FILE_LIST_DIRECTORY &&
         createOption == CreateOptions.NON_DIRECTORY_FILE &&
         fileAttribute == FileAttribute.READONLY)
     {
         returnedStatus = FsaUtility.TransferExpectedResult<MessageStatus>(375, MessageStatus.ACCESS_DENIED, returnedStatus, site);
     }
     return returnedStatus;
 }
예제 #25
0
        public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext)
        {
            fileStatus = FileStatus.FILE_DOES_NOT_EXIST;
            // It is possible to have a named pipe that does not use RPC (e.g. MS-WSP),
            // However this is not currently needed by our implementation.
            RemoteService service = GetService(path);

            if (service != null)
            {
                // All instances of a named pipe share the same pipe name, but each instance has its own buffers and handles,
                // and provides a separate conduit for client/server communication.
                RPCPipeStream stream = new RPCPipeStream(service);
                handle     = new FileHandle(path, false, stream, false);
                fileStatus = FileStatus.FILE_OPENED;
                return(NTStatus.STATUS_SUCCESS);
            }
            handle = null;
            return(NTStatus.STATUS_OBJECT_PATH_NOT_FOUND);
        }
        public static MessageStatus CheckExistingFileAccess(
            FileType openFileType,
            FileAttribute fileAttribute,
            FileAccess desiredAccess,
            CreateOptions createOption,
            CreateOptions existingOpenModeCreateOption,
            StreamTypeNameToOPen streamTypeNameToOPen,
            ShareAccess shareAccess,
            ShareAccess existOpenShareModeShareAccess)
        {
            //If Open.File.FileType is DataFile and (File.FileAttributes.FILE_ATTRIBUTE_READONLY &&
            //(DesiredAccess.FILE_WRITE_DATA))
            if (openFileType == FileType.DataFile &&
                existingOpenModeCreateOption == CreateOptions.NON_DIRECTORY_FILE &&
                (fileAttribute == FileAttribute.READONLY &&
                desiredAccess == FileAccess.FILE_WRITE_DATA))
            {
                Helper.CaptureRequirement(2422, @"[In Algorithm to Check Access to an Existing File]Pseudocode for these checks is as follows:
                    If Open.File.FileType is DataFile and (File.FileAttributes.FILE_ATTRIBUTE_READONLY && (DesiredAccess.FILE_APPEND_DATA)),
                    then return STATUS_ACCESS_DENIED.");
                return MessageStatus.ACCESS_DENIED;
            }

            //If Open.File.FileType is DataFile and (File.FileAttributes.FILE_ATTRIBUTE_READONLY &&
            //(DesiredAccess.FILE_APPEND_DATA))
            if (openFileType == FileType.DataFile &&
                existingOpenModeCreateOption == CreateOptions.NON_DIRECTORY_FILE &&
                (fileAttribute == FileAttribute.READONLY &&
                desiredAccess == FileAccess.FILE_APPEND_DATA))
            {
                Helper.CaptureRequirement(53, @"[In Algorithm to Check Access to an Existing File,Pseudocode for these checks is as follows:]
                    If Open.File.FileType is DataFile and (File.FileAttributes.FILE_ATTRIBUTE_READONLY && (DesiredAccess.FILE_WRITE_DATA )), then return STATUS_ACCESS_DENIED.");
                return MessageStatus.ACCESS_DENIED;
            }

            //If ((File.FileAttributes.FILE_ATTRIBUTE_READONLY ) &&
            //CreateOptions.FILE_DELETE_ON_CLOSE)
            if (fileAttribute == FileAttribute.READONLY &&
                (createOption == CreateOptions.DELETE_ON_CLOSE))
            {
                Helper.CaptureRequirement(54, @"[In Algorithm to Check Access to an Existing File,Pseudocode for these checks is as follows:]
                    If ((File.FileAttributes.FILE_ATTRIBUTE_READONLY) && CreateOptions.FILE_DELETE_ON_CLOSE), then return STATUS_CANNOT_DELETE.");
                return MessageStatus.CANNOT_DELETE;
            }

            //If ((File.Volume.IsReadOnly) &&
            //CreateOptions.FILE_DELETE_ON_CLOSE)
            if (isFileVolumeReadOnly &&
                (createOption == CreateOptions.DELETE_ON_CLOSE))
            {
                Helper.CaptureRequirement(2423, @"[In Algorithm to Check Access to an Existing File,Pseudocode for these checks is as follows:]
                    If (( File.Volume.IsReadOnly) && CreateOptions.FILE_DELETE_ON_CLOSE), then return STATUS_CANNOT_DELETE.");

                return MessageStatus.CANNOT_DELETE;
            }

            //If Open.RemainingDesiredAccess is nonzero
            if (gOpenRemainingDesiredAccess != FileAccess.None)
            {
                //If Open.RemainingDesiredAccess.MAXIMUM_ALLOWED
                if ((gOpenRemainingDesiredAccess & FileAccess.MAXIMUM_ALLOWED) != 0)
                {
                    //For each Access Flag in FILE_ALL_ACCESS, the object store MUST set Open.GrantedAccess.
                    //Access if SecurityContext has Access based on File.SecurityDescriptor
                    //gOpenGrantedAccess = FileAccess.FILE_ALL_ACCESS;
                    //If File.FileAttributes.FILE_ATTRIBUTE_READONLY or File.Volume.IsReadOnly
                    if ((fileAttribute == FileAttribute.READONLY) || isFileVolumeReadOnly)
                    {
                        //then the object store MUST clear (FILE_WRITE_DATA | FILE_APPEND_DATA |
                        //FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD) from Open.GrantedAccess.
                        gOpenGrantedAccess = gOpenGrantedAccess & (~(FileAccess.FILE_WRITE_DATA |
                            FileAccess.FILE_APPEND_DATA | FileAccess.FILE_ADD_SUBDIRECTORY |
                            FileAccess.FILE_DELETE_CHILD));
                    }
                }
                else
                {
                    //For each Access Flag in Open.RemainingDesired.Access, the object store MUST set
                    //Open.GrantedAccess.Access if SecurityContext has Access based on File.SecurityDescriptor
                    gOpenGrantedAccess = gOpenRemainingDesiredAccess;
                }

                //If (Open.RemainingDesiredAccess.MAXIMUM_ALLOWED || Open.RemainingDesiredAccess.DELETE),
                //the object store MUST set Open.GrantedAccess.DELETE if AccessCheck( SecurityContext,
                //Open.Link.ParentFile.SecurityDescriptor, FILE_DELETE_CHILD ) returns true

                if (gOpenRemainingDesiredAccess == FileAccess.MAXIMUM_ALLOWED ||
                    gOpenRemainingDesiredAccess == FileAccess.DELETE)
                {
                    //the object store MUST set Open.GrantedAccess.FILE_READ_ATTRIBUTES
                    gOpenGrantedAccess = FileAccess.DELETE;
                }
                //If (Open.RemainingDesiredAccess.MAXIMUM_ALLOWED || Open.RemainingDesiredAccess.
                //FILE_READ_ATTRIBUTES), the object store MUST set Open.GrantedAccess.FILE_READ_ATTRIBUTES
                //if AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor, FILE_LIST_DIRECTORY )
                //returns true

                if (gOpenRemainingDesiredAccess == FileAccess.MAXIMUM_ALLOWED ||
                    gOpenRemainingDesiredAccess == FileAccess.FILE_READ_ATTRIBUTES)
                {
                    //the object store MUST set Open.GrantedAccess.FILE_READ_ATTRIBUTES
                    gOpenGrantedAccess = FileAccess.FILE_READ_ATTRIBUTES;
                }
                //Open.RemainingDesiredAccess &= ~(Open.GrantedAccess | MAXIMUM_ALLOWED)
                gOpenRemainingDesiredAccess = gOpenRemainingDesiredAccess &
                    (~(gOpenGrantedAccess | FileAccess.MAXIMUM_ALLOWED));
                //If Open.RemainingDesiredAccess is nonzero, then return STATUS_ACCESS_DENIED.
                if (gOpenRemainingDesiredAccess != FileAccess.None)
                {
                    Helper.CaptureRequirement(61, @"[In Algorithm to Check Access to an Existing File,Pseudocode for these checks is as follows:,
                        If Open.RemainingDesiredAccess is nonzero:]If Open.RemainingDesiredAccess is nonzero, then return STATUS_ACCESS_DENIED.");
                    return MessageStatus.ACCESS_DENIED;
                }
            }
            //If Open.SharingMode.FILE_SHARE_DELETE is FALSE and Open.GrantedAccess contains any
            //one or more of (FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA):
            if ((gOpenSharingMode & ShareAccess.FILE_SHARE_DELETE) != 0 &&
                (gOpenGrantedAccess & (FileAccess.FILE_EXECUTE |
                FileAccess.FILE_READ_DATA | FileAccess.FILE_WRITE_DATA |
                FileAccess.FILE_APPEND_DATA)) != 0)
            {
                //For each ExistingOpen is Open.File.OpenList:
                //If ExistingOpen.Mode.FILE_DELETE_ON_CLOSE is true and ExistingOpen.Stream.StreamType is
                //DirectoryStream
                if ((existingOpenModeCreateOption & CreateOptions.DELETE_ON_CLOSE) != 0 &&
                    openFileType == FileType.DirectoryFile)
                {
                    Helper.CaptureRequirement(68, @"[In Algorithm to Check Access to an Existing File,Pseudocode for these checks is as follows:]
                        Pseudocode for these checks is as follows:If Open.SharingMode.FILE_SHARE_DELETE is FALSE and Open.
                        GrantedAccess contains any one or more of (FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA):
                        For each ExistingOpen is Open.File.OpenList:
                        If ExistingOpen.Mode.FILE_DELETE_ON_CLOSE is TRUE and ExistingOpen.Stream.StreamType is DirectoryStream, then return STATUS_SHARING_VIOLATION.");
                    return MessageStatus.SHARING_VIOLATION;
                }
            }

            //If Open.GrantedAccess.DELETE is true and Open.Stream.StreamType is DirectoryStream
            if ((gOpenGrantedAccess & FileAccess.DELETE) != 0 &&
                (streamTypeNameToOPen == StreamTypeNameToOPen.INDEX_ALLOCATION))
            {
                //For each ExistingOpen in Open.File.OpenList:
                //If ExistingOpen.SharingMode.FILE_SHARE_DELETE is FALSE
                if (existOpenShareModeShareAccess != ShareAccess.FILE_SHARE_DELETE)
                {
                    Helper.CaptureRequirement(66, @"[In Algorithm to Check Access to an Existing File,Pseudocode for these checks is as follows:]
                        If Open.GrantedAccess.DELETE is TRUE and Open.Stream.StreamType is DirectoryStream:For each ExistingOpen in Open.File.OpenList:
                        If ExistingOpen.SharingMode.FILE_SHARE_DELETE is FALSE, then return STATUS_SHARING_VIOLATION.");
                    return MessageStatus.SHARING_VIOLATION;
                }
            }

            Helper.CaptureRequirement(65, @"[In Algorithm to Check Access to an Existing File,Pseudocode for these checks is as follows:,
                if the sharing conflicts check has no violation]Return STATUS_SUCCESS.");
            return MessageStatus.SUCCESS;
        }
예제 #27
0
        public void CreateFile(out NtHandle handle, out FileStatus fileStatus, string path,
                               AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess,
                               CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext?securityContext)
        {
            fileStatus = FileStatus.FILE_DOES_NOT_EXIST;
            CreateRequest request = new CreateRequest
            {
                Name               = path,
                DesiredAccess      = desiredAccess,
                FileAttributes     = fileAttributes,
                ShareAccess        = shareAccess,
                CreateDisposition  = createDisposition,
                CreateOptions      = createOptions,
                ImpersonationLevel = ImpersonationLevel.Impersonation
            };

            SendCommand(request);

            CreateResponse createResponse = (CreateResponse)WaitForCommand(request.MessageID);

            createResponse.IsSuccessElseThrow();

            handle     = createResponse.FileId;
            fileStatus = ToFileStatus(createResponse.CreateAction);
        }
예제 #28
0
        public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext)
        {
            handle     = null;
            fileStatus = FileStatus.FILE_DOES_NOT_EXIST;
            NTCreateAndXRequest request = new NTCreateAndXRequest();

            request.FileName           = path;
            request.DesiredAccess      = desiredAccess;
            request.ExtFileAttributes  = ToExtendedFileAttributes(fileAttributes);
            request.ShareAccess        = shareAccess;
            request.CreateDisposition  = createDisposition;
            request.CreateOptions      = createOptions;
            request.ImpersonationLevel = ImpersonationLevel.Impersonation;

            TrySendMessage(request);
            SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_NT_CREATE_ANDX);

            if (reply != null)
            {
                if (reply.Commands[0] is NTCreateAndXResponse)
                {
                    NTCreateAndXResponse response = reply.Commands[0] as NTCreateAndXResponse;
                    handle     = response.FID;
                    fileStatus = ToFileStatus(response.CreateDisposition);
                    return(reply.Header.Status);
                }
                else if (reply.Commands[0] is ErrorResponse)
                {
                    return(reply.Header.Status);
                }
            }
            return(NTStatus.STATUS_INVALID_SMB);
        }
예제 #29
0
        public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext)
        {
            IntPtr fileHandle;
            string nativePath = ToNativePath(path);

            // NtQueryDirectoryFile will return STATUS_PENDING if the directory handle was not opened with SYNCHRONIZE and FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT.
            // Our usage of NtNotifyChangeDirectoryFile assumes the directory handle is opened with SYNCHRONIZE and FILE_SYNCHRONOUS_IO_ALERT (or FILE_SYNCHRONOUS_IO_NONALERT starting from Windows Vista).
            // Note: Sometimes a directory will be opened without specifying FILE_DIRECTORY_FILE.
            desiredAccess |= AccessMask.SYNCHRONIZE;
            createOptions &= ~CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT;
            createOptions |= CreateOptions.FILE_SYNCHRONOUS_IO_ALERT;

            if ((createOptions & CreateOptions.FILE_NO_INTERMEDIATE_BUFFERING) > 0 &&
                ((FileAccessMask)desiredAccess & FileAccessMask.FILE_APPEND_DATA) > 0)
            {
                // FILE_NO_INTERMEDIATE_BUFFERING is incompatible with FILE_APPEND_DATA
                // [MS-SMB2] 3.3.5.9 suggests setting FILE_APPEND_DATA to zero in this case.
                desiredAccess = (AccessMask)((uint)desiredAccess & (uint)~FileAccessMask.FILE_APPEND_DATA);
            }

            NTStatus status = CreateFile(out fileHandle, out fileStatus, nativePath, desiredAccess, 0, fileAttributes, shareAccess, createDisposition, createOptions);

            handle = fileHandle;
            return(status);
        }
        public static MessageStatus CreateFile(
            FileAttribute desiredFileAttribute,
            CreateOptions createOption,
            StreamTypeNameToOPen streamTypeNameToOPen,
            FileAccess desiredAccess,
            ShareAccess shareAccess,
            CreateDisposition createDisposition,
            StreamFoundType streamFoundType,
            SymbolicLinkType symbolicLinkType,
            FileType openFileType,
            FileNameStatus fileNameStatus
            )
        {
            MessageStatus status = OpenFileinitial(
            desiredAccess,
            shareAccess,
            createOption,
            createDisposition,
            desiredFileAttribute,
            streamFoundType,
            symbolicLinkType,
            streamTypeNameToOPen,
            openFileType,
            fileNameStatus);

            if (status != MessageStatus.SUCCESS)
            {
                return status;
            }

            #region Pseudocode for the operation

            //If FileTypeToOpen is DirectoryFile and DesiredFileAttributes.FILE_ATTRIBUTE_TEMPORARY is set
            if (gfileTypeToOpen == FileType.DirectoryFile &&
                desiredFileAttribute == FileAttribute.TEMPORARY)
            {
                Helper.CaptureRequirement(418, @"[In Creation of a New File,Pseudocode for the operation is as follows:]If FileTypeToOpen is DirectoryFile and DesiredFileAttributes.FILE_ATTRIBUTE_TEMPORARY is set, the operation MUST be failed with STATUS_INVALID_PARAMETER.");
                return MessageStatus.INVALID_PARAMETER;
            }

            //If DesiredFileAttributes.FILE_ATTRIBUTE_READONLY and CreateOptions.FILE_DELETE_ON_CLOSE
            //are both set
            if (desiredFileAttribute == FileAttribute.READONLY &&
                createOption == CreateOptions.DELETE_ON_CLOSE)
            {
                Helper.CaptureRequirement(419, @"[In Creation of a New File,Pseudocode for the operation is as follows:]If DesiredFileAttributes.FILE_ATTRIBUTE_READONLY and CreateOptions.FILE_DELETE_ON_CLOSE are both set, the operation MUST be failed with STATUS_CANNOT_DELETE.");
                return MessageStatus.CANNOT_DELETE;
            }

            //If StreamTypeNameToOpen is non-empty and has a value other than "$DATA" or
            //"$INDEX_ALLOCATION", the operation MUST be failed with STATUS_ACCESS_DENIED.
            if (streamTypeNameToOPen == StreamTypeNameToOPen.Other)
            {
                Helper.CaptureRequirement(420, @"[In Creation of a New File,Pseudocode for the operation is as follows:]If StreamTypeNameToOpen is non-empty and has a value other than \""$DATA"",the operation MUST be failed with STATUS_ACCESS_DENIED.");
                return MessageStatus.OBJECT_NAME_INVALID;
            }

            //If Open.RemainingDesiredAccess.ACCESS_SYSTEM_SECURITY is set and
            //Open.GrantedAccess.ACCESS_SYSTEM_SECURITY is not set and
            //SecurityContext.PrivilegeSet does not contain "SeSecurityPrivilege"
            //3 indicate SeBackupPrivilege and SeRestorePrivilege
            if (gOpenRemainingDesiredAccess == FileAccess.ACCESS_SYSTEM_SECURITY &&
                gOpenGrantedAccess == FileAccess.FILE_APPEND_DATA &&
                gSecurityContext.privilegeSet == (PrivilegeSet.SeBackupPrivilege | PrivilegeSet.SeRestorePrivilege))
            {
                Helper.CaptureRequirement(422, @"[In Creation of a New File,Pseudocode for the operation is as follows:]If Open.RemainingDesiredAccess.ACCESS_SYSTEM_SECURITY is set and Open.GrantedAccess.ACCESS_SYSTEM_SECURITY is not set and SecurityContext.PrivilegeSet does not contain \""SeSecurityPrivilege"", the operation MUST be failed with STATUS_ACCESS_DENIED.");
                return MessageStatus.ACCESS_DENIED;
            }

            //If FileTypeToOpen is DataFile and Open.GrantedAccess.FILE_ADD_FILE is not set
            //and AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor,
            //FILE_ADD_FILE ) returns FALSE and Open.HasRestoreAccess is FALSE

            if (gfileTypeToOpen == FileType.DataFile &&
                gOpenGrantedAccess == FileAccess.FILE_ADD_SUBDIRECTORY &&
                !isOpenHasRestoreAccess)
            {
                Helper.CaptureRequirement(423, @"[In Creation of a New File,Pseudocode for the operation is as follows:]
                    If FileTypeToOpen is DataFile and Open.GrantedAccess.FILE_ADD_FILE is not set and
                    AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor, FILE_ADD_FILE )
                    returns FALSE and Open.HasRestoreAccess is FALSE, the operation MUST be failed with STATUS_ACCESS_DENIED.");
                return MessageStatus.ACCESS_DENIED;
            }

            //If FileTypeToOpen is DirectoryFile and Open.GrantedAccess.FILE_ADD_SUBDIRECTORY
            //is not set and AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor,
            //FILE_ADD_SUBDIRECTORY ) returns FALSE and Open.HasRestoreAccess is FALSE

            if (gfileTypeToOpen == FileType.DirectoryFile &&
                gOpenGrantedAccess == FileAccess.FILE_ADD_FILE &&
                !isOpenHasRestoreAccess)
            {
                Helper.CaptureRequirement(424, @"[In Creation of a New File,Pseudocode for the operation is as follows:]
                   If FileTypeToOpen is DirectoryFile and Open.GrantedAccess.FILE_ADD_SUBDIRECTORY is not set and
                   AccessCheck( SecurityContext, Open.Link.ParentFile.SecurityDescriptor, FILE_ADD_SUBDIRECTORY )
                   returns FALSE and Open.HasRestoreAccess is FALSE, the operation MUST be failed with STATUS_ACCESS_DENIED.");
                return MessageStatus.ACCESS_DENIED;
            }

            if (streamTypeNameToOPen == StreamTypeNameToOPen.DATA ||
                streamTypeNameToOPen == StreamTypeNameToOPen.NULL)
            {
                gStreamType = StreamType.DataStream;
            }
            else
            {
                gStreamType = StreamType.DirectoryStream;
            }

            gFileAttribute = desiredFileAttribute;
            Helper.CaptureRequirement(475, @"[In Creation of a New File,Pseudocode for the operation is as follows:]
                The object store MUST return:CreateAction set to FILE_CREATED.");
            gCreateAction = CreateAction.CREATED;

            #endregion

            Helper.CaptureRequirement(474, @"[In Creation of a New File,Pseudocode for the operation is as follows:]
                The object store MUST return :Status set to STATUS_SUCCESS.");
            return MessageStatus.SUCCESS;
        }
예제 #31
0
        public override void Delete(string path)
        {
            if (!path.IsSharePath())
            {
                base.Delete(path);
                return;
            }

            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new SMBException($"Failed to Delete {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
            }

            var credential = _credentialProvider.GetSMBCredential(path);

            if (credential == null)
            {
                throw new SMBException($"Failed to Delete {path}", new InvalidCredentialException($"Unable to find credential in SMBCredentialProvider for path: {path}"));
            }

            ISMBFileStore fileStore = null;
            object        handle    = null;

            try
            {
                var shareName    = path.ShareName();
                var relativePath = path.RelativeSharePath();

                _logger?.LogTrace($"Trying to Delete {{RelativePath: {relativePath}}} for {{ShareName: {shareName}}}");

                using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize))
                {
                    fileStore = connection.SMBClient.TreeConnect(shareName, out var status);

                    status.HandleStatus();

                    AccessMask        accessMask    = AccessMask.SYNCHRONIZE | AccessMask.DELETE;
                    ShareAccess       shareAccess   = ShareAccess.Read | ShareAccess.Delete;
                    CreateDisposition disposition   = CreateDisposition.FILE_OPEN;
                    CreateOptions     createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_DELETE_ON_CLOSE;

                    var stopwatch = new Stopwatch();
                    stopwatch.Start();

                    do
                    {
                        if (status == NTStatus.STATUS_PENDING)
                        {
                            _logger.LogTrace($"STATUS_PENDING while trying to delete file {path}. {stopwatch.Elapsed.TotalSeconds}/{_smbFileSystemSettings.ClientSessionTimeout} seconds elapsed.");
                        }

                        status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, accessMask, 0, shareAccess,
                                                      disposition, createOptions, null);
                    }while (status == NTStatus.STATUS_PENDING && stopwatch.Elapsed.TotalSeconds <= _smbFileSystemSettings.ClientSessionTimeout);

                    stopwatch.Stop();
                    status.HandleStatus();

                    // There should be a seperate option to delete, but it doesn't seem to exsist in the library we are using, so this should work for now. Really hacky though.
                    FileStoreUtilities.CloseFile(fileStore, ref handle);
                }
            }
            catch (Exception ex)
            {
                throw new SMBException($"Failed to Delete {path}", ex);
            }
            finally
            {
                FileStoreUtilities.CloseFile(fileStore, ref handle);
            }
        }
예제 #32
0
        private IDirectoryInfo CreateDirectory(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.CreateDirectory(path));
            }

            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new ArgumentException($"Unable to resolve \"{path.Hostname()}\"");
            }

            NTStatus status = NTStatus.STATUS_SUCCESS;

            AccessMask        accessMask    = AccessMask.MAXIMUM_ALLOWED;
            ShareAccess       shareAccess   = ShareAccess.Read;
            CreateDisposition disposition   = CreateDisposition.FILE_OPEN_IF;
            CreateOptions     createOptions = CreateOptions.FILE_DIRECTORY_FILE;

            if (credential == null)
            {
                credential = _credentialProvider.GetSMBCredential(path);
            }

            if (credential == null)
            {
                throw new Exception($"Unable to find credential for path: {path}");
            }

            using var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize);

            var shareName    = path.ShareName();
            var relativePath = path.RelativeSharePath();

            ISMBFileStore fileStore = connection.SMBClient.TreeConnect(shareName, out status);

            status.HandleStatus();

            int    attempts      = 0;
            int    allowedRetrys = 3;
            object handle;

            do
            {
                attempts++;

                status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, accessMask, 0, shareAccess,
                                              disposition, createOptions, null);

                if (status == NTStatus.STATUS_OBJECT_PATH_NOT_FOUND)
                {
                    CreateDirectory(path.GetParentPath(), credential);
                    status = fileStore.CreateFile(out handle, out fileStatus, relativePath, accessMask, 0, shareAccess,
                                                  disposition, createOptions, null);
                }
            }while (status == NTStatus.STATUS_PENDING && attempts < allowedRetrys);

            status.HandleStatus();

            fileStore.CloseFile(handle);

            return(_directoryInfoFactory.FromDirectoryName(path, credential));
        }
예제 #33
0
        internal Stream Open(string path, FileMode mode, FileAccess access, FileShare share, FileOptions fileOptions, ISMBCredential credential)
        {
            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new SMBException($"Failed to Open {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
            }

            NTStatus status = NTStatus.STATUS_SUCCESS;

            AccessMask        accessMask  = AccessMask.MAXIMUM_ALLOWED;
            ShareAccess       shareAccess = ShareAccess.None;
            CreateDisposition disposition = CreateDisposition.FILE_OPEN;
            CreateOptions     createOptions;

            switch (fileOptions)
            {
            case FileOptions.DeleteOnClose:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_DELETE_ON_CLOSE;
                break;

            case FileOptions.RandomAccess:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_RANDOM_ACCESS;
                break;

            case FileOptions.SequentialScan:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_SEQUENTIAL_ONLY;
                break;

            case FileOptions.WriteThrough:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_WRITE_THROUGH;
                break;

            case FileOptions.None:
            case FileOptions.Encrypted:         // These two are not suported unless I am missing something
            case FileOptions.Asynchronous:      //
            default:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_NON_DIRECTORY_FILE;
                break;
            }

            switch (access)
            {
            case FileAccess.Read:
                accessMask  = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ;
                shareAccess = ShareAccess.Read;
                break;

            case FileAccess.Write:
                accessMask  = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_WRITE;
                shareAccess = ShareAccess.Write;
                break;

            case FileAccess.ReadWrite:
                accessMask  = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE;
                shareAccess = ShareAccess.Read | ShareAccess.Write;
                break;
            }

            if (credential == null)
            {
                credential = _credentialProvider.GetSMBCredential(path);
            }

            if (credential == null)
            {
                throw new SMBException($"Failed to Open {path}", new InvalidCredentialException($"Unable to find credential in SMBCredentialProvider for path: {path}"));
            }

            SMBConnection connection = null;

            try
            {
                connection = SMBConnection.CreateSMBConnectionForStream(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize);

                var shareName    = path.ShareName();
                var relativePath = path.RelativeSharePath();

                ISMBFileStore fileStore = connection.SMBClient.TreeConnect(shareName, out status);

                status.HandleStatus();

                switch (mode)
                {
                case FileMode.Create:
                    disposition = CreateDisposition.FILE_OVERWRITE_IF;
                    break;

                case FileMode.CreateNew:
                    disposition = CreateDisposition.FILE_CREATE;
                    break;

                case FileMode.Open:
                    disposition = CreateDisposition.FILE_OPEN;
                    break;

                case FileMode.OpenOrCreate:
                    disposition = CreateDisposition.FILE_OPEN_IF;
                    break;
                }

                object handle;
                var    stopwatch = new Stopwatch();

                stopwatch.Start();
                do
                {
                    if (status == NTStatus.STATUS_PENDING)
                    {
                        _logger.LogTrace($"STATUS_PENDING while trying to open file {path}. {stopwatch.Elapsed.TotalSeconds}/{_smbFileSystemSettings.ClientSessionTimeout} seconds elapsed.");
                    }

                    status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, accessMask, 0, shareAccess,
                                                  disposition, createOptions, null);
                }while (status == NTStatus.STATUS_PENDING && stopwatch.Elapsed.TotalSeconds <= _smbFileSystemSettings.ClientSessionTimeout);
                stopwatch.Stop();

                status.HandleStatus();

                FileInformation fileInfo;

                stopwatch.Reset();
                stopwatch.Start();
                do
                {
                    status = fileStore.GetFileInformation(out fileInfo, handle, FileInformationClass.FileStandardInformation);
                }while (status == NTStatus.STATUS_NETWORK_NAME_DELETED && stopwatch.Elapsed.TotalSeconds <= _smbFileSystemSettings.ClientSessionTimeout);
                stopwatch.Stop();

                status.HandleStatus();

                var fileStandardInfo = (FileStandardInformation)fileInfo;

                Stream s = new SMBStream(fileStore, handle, connection, fileStandardInfo.EndOfFile, _smbFileSystemSettings);

                if (mode == FileMode.Append)
                {
                    s.Seek(0, SeekOrigin.End);
                }

                return(s);
            }
            catch (Exception ex)
            {
                // Dispose connection if fail to open stream
                connection?.Dispose();
                throw new SMBException($"Failed to Open {path}", ex);
            }
        }
        public static MessageStatus OpenExistingFile(
            ShareAccess shareAccess,
            FileAccess desiredAccess,
            StreamFoundType streamFoundType,
            SymbolicLinkType symbolicLinkType,
            FileType openFileType,
            FileNameStatus fileNameStatus,
            CreateOptions existingOpenModeCreateOption,
            ShareAccess existOpenShareModeShareAccess,
            FileAccess existOpenDesiredAccess,
            CreateOptions createOption,
            CreateDisposition createDisposition,
            StreamTypeNameToOPen streamTypeNameToOPen,
            FileAttribute fileAttribute,
            FileAttribute desiredFileAttribute
            )
        {
            MessageStatus statusShareAccess = MessageStatus.SUCCESS;
            MessageStatus statusExistAccess = MessageStatus.SUCCESS;

            //call 3.1.5.1 openInitial
            MessageStatus statusInitial = OpenFileinitial(
            desiredAccess,
            shareAccess,
            createOption,
            createDisposition,
            desiredFileAttribute,
            streamFoundType,
            symbolicLinkType,
            streamTypeNameToOPen,
            openFileType,
            fileNameStatus);

            if (statusInitial != MessageStatus.SUCCESS)
            {
                return statusInitial;
            }

            #region FileTypeToOpen

            //If FileTypeToOpen is DirectoryFile
            if (gfileTypeToOpen == FileType.DirectoryFile)
            {
                //If CreateDisposition is FILE_OPEN
                if (createDisposition == CreateDisposition.OPEN)
                {
                    //call 3.1.5.1.2.1
                    statusExistAccess = CheckExistingFileAccess(
                    openFileType,
                    fileAttribute,
                    desiredAccess,
                    createOption,
                    existingOpenModeCreateOption,
                    streamTypeNameToOPen,
                    shareAccess,
                    existOpenShareModeShareAccess);

                    if (statusExistAccess != MessageStatus.SUCCESS)
                    {
                        Helper.CaptureRequirement(635, @"[In Open of an Existing File,Pseudocode for the operation is as follows:
                            If FileTypeToOpen is DirectoryFile:If CreateDisposition is FILE_OPEN then:]
                            If this[Perform access checks as described in section 3.1.5.1.2.1.] fails, the request MUST be failed with the same status.");
                        return statusExistAccess;
                    }

                    //call 3.1.5.1.2.2
                    statusShareAccess = CheckShareAccess(
                    streamFoundType,
                    existOpenShareModeShareAccess,
                    desiredAccess,
                    existOpenDesiredAccess,
                    shareAccess);

                    if (statusShareAccess != MessageStatus.SUCCESS)
                    {
                        Helper.CaptureRequirement(636, @"[In Open of an Existing File,Pseudocode for the operation is as follows:
                            If OpenFileType is DirectoryFile:If CreateDisposition is FILE_OPEN_IF then:]
                            If this[Perform access checks as described in section 3.1.5.1.2.1.] fails, the request MUST be failed with the same status.");
                        return statusShareAccess;
                    }

                    gCreateAction = CreateAction.OPENED;
                }
                //If CreateDisposition is FILE_OPEN_IF then
                else if (createDisposition == CreateDisposition.OPEN_IF)
                {
                    //call 3.1.5.1.2.1
                    statusExistAccess = CheckExistingFileAccess(
                    openFileType,
                    fileAttribute,
                    desiredAccess,
                    createOption,
                    existingOpenModeCreateOption,
                    streamTypeNameToOPen,
                    shareAccess,
                    existOpenShareModeShareAccess);

                    if (statusExistAccess != MessageStatus.SUCCESS)
                    {
                        Helper.CaptureRequirement(640, @"[In Open of an Existing File,Pseudocode for the operation is as follows:
                            If FileTypeToOpen is DirectoryFile:If CreateDisposition is FILE_OPEN_IF then:]
                            If this[Perform sharing access checks as described in section 3.1.5.1.2.2.] fails, the request MUST be failed with the same status.");
                        return statusExistAccess;
                    }

                    //call 3.1.5.1.2.2
                    statusShareAccess = CheckShareAccess(
                    streamFoundType,
                    existOpenShareModeShareAccess,
                    desiredAccess,
                    existOpenDesiredAccess,
                    shareAccess);

                    if (statusShareAccess != MessageStatus.SUCCESS)
                    {
                        Helper.CaptureRequirement(639, @"[In Open of an Existing File,Pseudocode for the operation is as follows:
                            If FileTypeToOpen is DirectoryFile:If CreateDisposition is FILE_OPEN then:]
                            If this [Perform sharing access checks as described in section 3.1.5.1.2.2.]fails, the request MUST be failed with the same status.");
                        return statusShareAccess;
                    }

                    gCreateAction = CreateAction.OPENED;
                }
                else
                {
                    //Existing directories cannot be overwritten/superseded
                    //If File == File.Volume.RootDirectory
                    if (isFileEqualRootDirectory)
                    {
                        Helper.CaptureRequirement(578, @"[In Open of an Existing File,Pseudocode for the operation is as follows:
                            If FileTypeToOpen is DirectoryFile:]
                            Else If File == File.Volume.RootDirectory then the operation MUST be failed with STATUS_ACCESS_DENIED.");
                        return MessageStatus.ACCESS_DENIED;
                    }
                    else
                    {
                        Helper.CaptureRequirement(579, @"[In Open of an Existing File,Pseudocode for the operation is as follows:
                            If FileTypeToOpen is DirectoryFile:]
                            else[If File != File.Volume.RootDirectory ] the operation MUST be failed with STATUS_OBJECT_NAME_COLLISION.");
                        return MessageStatus.OBJECT_NAME_COLLISION;
                    }
                }
            }
            //Else if FileTypeToOpen is DataFile
            else if (gfileTypeToOpen == FileType.DataFile)
            {
                #region If Stream was found

                if (streamFoundType == StreamFoundType.StreamIsFound)
                {
                    //If CreateDisposition is FILE_CREATE
                    if (createDisposition == CreateDisposition.CREATE)
                    {
                        Helper.CaptureRequirement(584, @"[In Open of an Existing File,Pseudocode for the operation is as follows:
                            Else if FileTypeToOpen is DataFile,If Stream was found,]If CreateDisposition is FILE_CREATE,
                            then the operation MUST be failed with STATUS_OBJECT_NAME_COLLISION.");
                        return MessageStatus.OBJECT_NAME_COLLISION;
                    }

                    //If CreateDisposition is FILE_OPEN_IF
                    if (createDisposition == CreateDisposition.OPEN_IF)
                    {
                        //call 3.1.5.1.2.1
                        statusExistAccess = CheckExistingFileAccess(
                        openFileType,
                        fileAttribute,
                        desiredAccess,
                        createOption,
                        existingOpenModeCreateOption,
                        streamTypeNameToOPen,
                        shareAccess,
                        existOpenShareModeShareAccess);

                        if (statusExistAccess != MessageStatus.SUCCESS)
                        {
                            return statusExistAccess;
                        }

                        //call 3.1.5.1.2.2
                        statusShareAccess = CheckShareAccess(
                        streamFoundType,
                        existOpenShareModeShareAccess,
                        desiredAccess,
                        existOpenDesiredAccess,
                        shareAccess);

                        if (statusShareAccess != MessageStatus.SUCCESS)
                        {
                            return statusShareAccess;
                        }

                        gCreateAction = CreateAction.OPENED;
                    }
                    //If CreateDisposition is FILE_OPEN
                    else if (createDisposition == CreateDisposition.OPEN)
                    {

                        //call 3.1.5.1.2.1
                        statusExistAccess = CheckExistingFileAccess(
                        openFileType,
                        fileAttribute,
                        desiredAccess,
                        createOption,
                        existingOpenModeCreateOption,
                        streamTypeNameToOPen,
                        shareAccess,
                        existOpenShareModeShareAccess);

                        if (statusExistAccess != MessageStatus.SUCCESS)
                        {
                            return statusExistAccess;
                        }

                        //call 3.1.5.1.2.2
                        statusShareAccess = CheckShareAccess(
                        streamFoundType,
                        existOpenShareModeShareAccess,
                        desiredAccess,
                        existOpenDesiredAccess,
                        shareAccess);

                        if (statusShareAccess != MessageStatus.SUCCESS)
                        {
                            return statusShareAccess;
                        }
                        gCreateAction = CreateAction.OPENED;
                    }
                    else
                    {
                        //If File.Volume.IsReadOnly is true
                        if (isFileVolumeReadOnly)
                        {
                            Helper.CaptureRequirement(596, @"[In Open of an Existing File,Pseudocode for the operation is as follows:
                                Else if FileTypeToOpen is DataFile:If Stream was found]Else (CreateDisposition is not FILE_OPEN and is not FILE_OPEN_IF)
                                If File.Volume.IsReadOnly is true, the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.");
                            return MessageStatus.MEDIA_WRITE_PROTECTED;
                        }

                        //If Stream.Name is empty
                        if (fileNameStatus == FileNameStatus.StreamNameNull)
                        {
                            //If File.FileAttributes.FILE_ATTRIBUTE_HIDDEN is true and
                            //DesiredFileAttributes.FILE_ATTRIBUTE_HIDDEN is FALSE
                            if (fileAttribute == FileAttribute.HIDDEN &&
                                desiredFileAttribute != FileAttribute.HIDDEN)
                            {
                                Helper.CaptureRequirement(487, @"[In Open of an Existing File,Pseudocode for these checks is as follows:
                                    Else if FileTypeToOpen is DataFile,If Stream was found,Else (CreateDisposition is not FILE_OPEN and is not FILE_OPEN_IF),
                                    If Stream.Name is empty:]If File.FileAttributes.FILE_ATTRIBUTE_HIDDEN is TRUE
                                    and DesiredFileAttributes.FILE_ATTRIBUTE_HIDDEN is FALSE, then the operation MUST be failed with STATUS_ACCESS_DENIED.");
                                return MessageStatus.ACCESS_DENIED;
                            }
                            //If File.FileAttributes.FILE_ATTRIBUTE_SYSTEM is true and
                            //DesiredFileAttributes.FILE_ATTRIBUTE_SYSTEM is FALSE
                            if (fileAttribute == FileAttribute.SYSTEM &&
                                desiredFileAttribute != FileAttribute.SYSTEM)
                            {
                                Helper.CaptureRequirement(488, @"[In Open of an Existing File,Pseudocode for these checks is as follows:
                                    Else if FileTypeToOpen is DataFile,If Stream was found,Else (CreateDisposition is not FILE_OPEN and is not FILE_OPEN_IF),
                                    If Stream.Name is empty:]If File.FileAttributes.FILE_ATTRIBUTE_SYSTEM is TRUE
                                    and DesiredFileAttributes.FILE_ATTRIBUTE_SYSTEM is FALSE, then the operation MUST be failed with STATUS_ACCESS_DENIED.");
                                return MessageStatus.ACCESS_DENIED;
                            }

                            //Set DesiredFileAttributes.FILE_ATTRIBUTE_ARCHIVE to true.
                            desiredFileAttribute = desiredFileAttribute | FileAttribute.ARCHIVE;

                            //Set DesiredFileAttributes.FILE_ATTRIBUTE_NORMAL to FALSE.
                            desiredFileAttribute = desiredFileAttribute & (~FileAttribute.NORMAL);

                            //Set DesiredFileAttributes.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED to FALSE
                            desiredFileAttribute = desiredFileAttribute &
                                (~FileAttribute.NOT_CONTENT_INDEXED);

                            //If File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is true, then
                            //set DesiredFileAttributes.FILE_ATTRIBUTE_ENCRYPTED to true.
                            if ((fileAttribute & FileAttribute.ENCRYPTED) != 0)
                            {
                                desiredFileAttribute = desiredFileAttribute | FileAttribute.ENCRYPTED;
                            }

                            //If Open.HasRestoreAccess is true
                            if (isOpenHasRestoreAccess)
                            {
                                //set Open.GrantedAccess.FILE_WRITE_EA to true
                                gOpenGrantedAccess = gOpenGrantedAccess | FileAccess.FILE_WRITE_EA;

                                //set Open.GrantedAccess.FILE_WRITE_ATTRIBUTES to true
                                gOpenGrantedAccess = gOpenGrantedAccess | FileAccess.FILE_WRITE_ATTRIBUTES;
                            }
                            else
                            {
                                //set Open.RemainingDesiredAccess
                                gOpenRemainingDesiredAccess = gOpenRemainingDesiredAccess |
                                    FileAccess.FILE_WRITE_EA;

                                //store must set Open.RemainingDesiredAccess.FILE_WRITE_ATTRIBUTES to
                                //true
                                gOpenRemainingDesiredAccess = gOpenRemainingDesiredAccess |
                                    FileAccess.FILE_WRITE_ATTRIBUTES;
                            }
                        }

                        //If CreateDisposition is FILE_SUPERSEDE
                        if (createDisposition == CreateDisposition.SUPERSEDE)
                        {
                            //If Open.HasRestoreAccess is true
                            if (isOpenHasRestoreAccess)
                            {
                                //set Open.GrantedAccess.DELETE to true
                                gOpenGrantedAccess = gOpenGrantedAccess | FileAccess.DELETE;
                            }
                            else
                            {
                                //Otherwise, the object store must set Open.RemainingDesiredAccess.
                                //FILE_WRITE_DATA to true
                                gOpenRemainingDesiredAccess = gOpenRemainingDesiredAccess | FileAccess.DELETE;
                            }
                        }
                        else
                        {
                            //If Open.HasRestoreAccess is true
                            if (isOpenHasRestoreAccess)
                            {
                                //set Open.GrantedAccess.DELETE to true
                                gOpenGrantedAccess = gOpenGrantedAccess | FileAccess.FILE_WRITE_DATA;
                            }
                            else
                            {
                                //Otherwise, the object store must set Open.RemainingDesiredAccess.
                                //FILE_WRITE_DATA to true
                                gOpenRemainingDesiredAccess = gOpenRemainingDesiredAccess |
                                    FileAccess.FILE_WRITE_DATA;
                            }
                        }

                        gOpenRemainingDesiredAccess = gOpenRemainingDesiredAccess & (~gOpenGrantedAccess);

                        if (createDisposition == CreateDisposition.SUPERSEDE)
                        {
                            gCreateAction = CreateAction.SUPERSEDED;
                        }
                        else
                        {
                            gCreateAction = CreateAction.OVERWRITTEN;
                        }
                    }
                }

                #endregion

                #region Stream not found

                else
                {
                    //If CreateDisposition is FILE_OPEN or FILE_OVERWRITE
                    if (createDisposition == CreateDisposition.OPEN)
                    {
                        Helper.CaptureRequirement(610, @"[In Open of an Existing File,Pseudocode for these checks is as follows:
                            Else if FileTypeToOpen is DataFile,Else (Steam not found)]If CreateDisposition is FILE_OPEN ,
                            the operation MUST be failed with STATUS_OBJECT_NAME_NOT_FOUND.");
                        return MessageStatus.OBJECT_NAME_NOT_FOUND;
                    }

                    //If CreateDisposition is FILE_OPEN or FILE_OVERWRITE
                    if (createDisposition == CreateDisposition.OVERWRITE)
                    {
                        Helper.CaptureRequirement(2416, @"[In Open of an Existing File,Pseudocode for these checks is as follows:
                            Else if FileTypeToOpen is DataFile,Else (Steam not found)]If CreateDisposition is FILE_OVERWRITE, the operation
                            MUST be failed with STATUS_OBJECT_NAME_NOT_FOUND.");
                        return MessageStatus.OBJECT_NAME_NOT_FOUND;
                    }

                    //If Open.GrantedAccess.FILE_WRITE_DATA is not set and Open.RemainingDesiredAccess.
                    //FILE_WRITE_DATA is not set:
                    if ((gOpenGrantedAccess & FileAccess.FILE_WRITE_DATA) == 0 &&
                        (gOpenRemainingDesiredAccess & FileAccess.FILE_WRITE_DATA) == 0)
                    {
                        //If Open.HasRestoreAccess is true
                        if (isOpenHasRestoreAccess)
                        {
                            //then the object store MUST set Open.GrantedAccess.FILE_WRITE_DATA to true.
                            gOpenGrantedAccess = gOpenGrantedAccess | FileAccess.FILE_WRITE_DATA;
                        }
                        else
                        {
                            //Otherwise, the object store MUST set Open.RemainingDesiredAccess.
                            //FILE_WRITE_DATA to true.
                            gOpenRemainingDesiredAccess = gOpenRemainingDesiredAccess | FileAccess.FILE_WRITE_DATA;
                        }
                    }

                    //call 3.1.5.1.2.1
                    statusExistAccess = CheckExistingFileAccess(
                    openFileType,
                    fileAttribute,
                    desiredAccess,
                    createOption,
                    existingOpenModeCreateOption,
                    streamTypeNameToOPen,
                    shareAccess,
                    existOpenShareModeShareAccess);

                    if (statusExistAccess != MessageStatus.SUCCESS)
                    {
                        Helper.CaptureRequirement(9840, @"[In Open of an Existing File,Pseudocode for these checks is as follows:
                            Else if FileTypeToOpen is DataFile,Else (Steam not found)] If this[Perform access checks as described in section 3.1.5.1.2.1] fails,
                            the request MUST be failed with the same status.");

                        return statusExistAccess;
                    }

                    //If File.Volume.IsReadOnly is true
                    if (isFileVolumeReadOnly)
                    {
                        Helper.CaptureRequirement(614, @"[In Open of an Existing File,Pseudocode for these checks is as follows:
                            Else if FileTypeToOpen is DataFile,Else (Steam not found)]If File.Volume.IsReadOnly is TRUE,
                            the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.");
                        return MessageStatus.MEDIA_WRITE_PROTECTED;
                    }

                    //Set CreateAction to FILE_CREATED.
                    gCreateAction = CreateAction.CREATED;
                }

                #endregion

            }

            #endregion

            // If the object store implements encryption:
            if (gSecurityContext.isImplementsEncryption)
            {
                //If (CreateAction is FILE_OVERWRITTEN) and
                //(Stream.Name is empty) and (DesiredAttributes.FILE_ATTRIBUTE_ENCRYPTED is true)
                //and (File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is FALSE) then:
                if ((gCreateAction == CreateAction.OVERWRITTEN)
                    && (fileNameStatus == FileNameStatus.StreamNameNull) &&
                    ((desiredFileAttribute & FileAttribute.ENCRYPTED) != 0)
                    && ((fileAttribute & FileAttribute.ENCRYPTED) == 0))
                {
                    //If File.OpenList is non-empty
                    //the openList must not empty
                    Helper.CaptureRequirement(623, @"[In Open of an Existing File,Pseudocode for these checks is as follows:]
                        If the object store implements encryption:If (CreateAction is FILE_OVERWRITTEN) and (Stream.Name is empty) and (DesiredAttributes.FILE_ATTRIBUTE_ENCRYPTED is TRUE) and (File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is FALSE), then:If File.OpenList is non-empty, then the operation MUST be failed with STATUS_SHARING_VIOLATION.");
                    return MessageStatus.SHARING_VIOLATION;
                }

                //If (CreateAction is FILE_SUPERSEDED) and
                //(Stream.Name is empty) and (DesiredAttributes.FILE_ATTRIBUTE_ENCRYPTED is true)
                //and (File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is FALSE) then:
                if ((gCreateAction == CreateAction.SUPERSEDED)
                    && (fileNameStatus == FileNameStatus.FileNameNull) &&
                    ((desiredFileAttribute & FileAttribute.ENCRYPTED) != 0)
                    && ((fileAttribute & FileAttribute.ENCRYPTED) == 0))
                {
                    //If File.OpenList is non-empty
                    //the openList must not empty
                    Helper.CaptureRequirement(2417, @"[In Open of an Existing File,Pseudocode for these checks is as follows:]
                        If the object store implements encryption:If (CreateAction is FILE_SUPERSEDED) and (Stream.Name is empty) and (DesiredAttributes.FILE_ATTRIBUTE_ENCRYPTED is TRUE) and (File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is FALSE), then:If File.OpenList is non-empty, then the operation MUST be failed with STATUS_SHARING_VIOLATION.");
                    return MessageStatus.SHARING_VIOLATION;
                }
            }

            // If CreateAction is FILE_OVERWRITTEN
            if (gCreateAction == CreateAction.OVERWRITTEN)
            {
                if (fileNameStatus == FileNameStatus.FileNameNull)
                {
                    //Set File.FileAttributes to DesiredFileAttributes
                    fileAttribute = desiredFileAttribute;
                }
            }

            // If CreateAction is FILE_SUPERSEDED
            if (gCreateAction == CreateAction.SUPERSEDED)
            {
                if (fileNameStatus == FileNameStatus.FileNameNull)
                {
                    //Set File.FileAttributes to DesiredFileAttributes
                    fileAttribute = desiredFileAttribute;
                }
            }

            Helper.CaptureRequirement(631, @"[In Open of an Existing File,Pseudocode for these checks is as follows:]
                The object store MUST return :CreateAction set to FILE_OPENED.");
            gCreateAction = CreateAction.OPENED;

            Helper.CaptureRequirement(630, @"[In Open of an Existing File,Pseudocode for these checks is as follows:]
                The object store MUST return:Status set to STATUS_SUCCESS.");
            return MessageStatus.SUCCESS;
        }
예제 #35
0
        public async Task <(NTStatus status, object handle, FileStatus fileStatus)> CreateFile(string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext, CancellationToken cancellationToken)
        {
            CreateRequest request = new CreateRequest();

            request.Name               = path;
            request.DesiredAccess      = desiredAccess;
            request.FileAttributes     = fileAttributes;
            request.ShareAccess        = shareAccess;
            request.CreateDisposition  = createDisposition;
            request.CreateOptions      = createOptions;
            request.ImpersonationLevel = ImpersonationLevel.Impersonation;
            await TrySendCommandAsync(request, cancellationToken);

            SMB2Command response = m_client.WaitForCommand(SMB2CommandName.Create);

            var fileStatus = FileStatus.FILE_DOES_NOT_EXIST;

            if (response != null)
            {
                object handle = null;

                if (response.Header.Status == NTStatus.STATUS_SUCCESS && response is CreateResponse)
                {
                    CreateResponse createResponse = ((CreateResponse)response);
                    handle     = createResponse.FileId;
                    fileStatus = ToFileStatus(createResponse.CreateAction);
                }
                return(response.Header.Status, handle, fileStatus);
            }

            return(NTStatus.STATUS_INVALID_SMB, null, fileStatus);
        }
예제 #36
0
        private NTStatus OpenFileStream(out Stream stream, string path, FileAccess fileAccess, ShareAccess shareAccess, CreateOptions openOptions)
        {
            stream = null;
            // When FILE_OPEN_REPARSE_POINT is specified, the operation should continue normally if the file is not a reparse point.
            // FILE_OPEN_REPARSE_POINT is a hint that the caller does not intend to actually read the file, with the exception
            // of a file copy operation (where the caller will attempt to simply copy the reparse point).
            bool      openReparsePoint = (openOptions & CreateOptions.FILE_OPEN_REPARSE_POINT) > 0;
            bool      disableBuffering = (openOptions & CreateOptions.FILE_NO_INTERMEDIATE_BUFFERING) > 0;
            bool      buffered         = (openOptions & CreateOptions.FILE_SEQUENTIAL_ONLY) > 0 && !disableBuffering && !openReparsePoint;
            FileShare fileShare        = NTFileStoreHelper.ToFileShare(shareAccess);
            string    fileShareString  = fileShare.ToString().Replace(", ", "|");

            try
            {
                stream = m_fileSystem.OpenFile(path, FileMode.Open, fileAccess, fileShare);
            }
            catch (Exception ex)
            {
                NTStatus status = ToNTStatus(ex);
                Log(Severity.Verbose, "OpenFile: Cannot open '{0}', Access={1}, Share={2}. NTStatus: {3}.", path, fileAccess, fileShareString, status);
                return(status);
            }

            Log(Severity.Information, "OpenFileStream: Opened '{0}', Access={1}, Share={2}, Buffered={3}", path, fileAccess, fileShareString, buffered);
            if (buffered)
            {
                stream = new PrefetchedStream(stream);
            }

            return(NTStatus.STATUS_SUCCESS);
        }