예제 #1
0
        public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, 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 (path.Contains(":"))
            {
                // Windows Server 2003 will return STATUS_OBJECT_NAME_NOT_FOUND
                return(NTStatus.STATUS_NO_SUCH_FILE);
            }

            FileSystemEntry entry;

            try
            {
                entry = m_fileSystem.GetEntry(path);
            }
            catch (Exception ex)
            {
                NTStatus status = ToNTStatus(ex);
                Log(Severity.Verbose, "CreateFile: Error retrieving '{0}'. {1}.", path, status);
                return(status);
            }

            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 exist", 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)
                {
                    NTStatus status = ToNTStatus(ex);
                    Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status);
                    return(status);
                }
                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)
                    {
                        NTStatus status = ToNTStatus(ex);
                        Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status);
                        return(status);
                    }
                    fileStatus = FileStatus.FILE_CREATED;
                }
                else
                {
                    fileStatus = FileStatus.FILE_EXISTS;
                    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);
                            temp.Close();
                        }
                        catch (Exception ex)
                        {
                            NTStatus status = ToNTStatus(ex);
                            Log(Severity.Verbose, "CreateFile: Error truncating '{0}'. {1}.", path, status);
                            return(status);
                        }
                        fileStatus = FileStatus.FILE_OVERWRITTEN;
                    }
                    else if (createDisposition == CreateDisposition.FILE_SUPERSEDE)
                    {
                        // Delete the old file
                        try
                        {
                            m_fileSystem.Delete(path);
                        }
                        catch (Exception ex)
                        {
                            NTStatus status = ToNTStatus(ex);
                            Log(Severity.Verbose, "CreateFile: Error deleting '{0}'. {1}.", path, status);
                            return(status);
                        }

                        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)
                        {
                            NTStatus status = ToNTStatus(ex);
                            Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status);
                            return(status);
                        }
                        fileStatus = FileStatus.FILE_SUPERSEDED;
                    }
                }
            }
            else
            {
                return(NTStatus.STATUS_INVALID_PARAMETER);
            }

            FileAccess fileAccess = NTFileStoreHelper.ToFileAccess(desiredAccess.File);
            Stream     stream;
            bool       deleteOnClose = false;

            if (fileAccess == (FileAccess)0 || entry.IsDirectory)
            {
                stream = null;
            }
            else
            {
                NTStatus openStatus = OpenFileStream(out stream, path, fileAccess, shareAccess, createOptions);
                if (openStatus != NTStatus.STATUS_SUCCESS)
                {
                    return(openStatus);
                }
            }

            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);
        }
예제 #2
0
 public FileAccessInformation(byte[] buffer, int offset)
 {
     AccessFlags = (AccessMask)LittleEndianConverter.ToUInt32(buffer, offset + 0);
 }
예제 #3
0
 /// <summary>
 /// Will return desired FileAccess rights to the file data.
 /// </summary>
 public static FileAccess ToFileAccess(AccessMask desiredAccess)
 {
     return(ToFileAccess((FileAccessMask)desiredAccess));
 }
예제 #4
0
        public Task <(NTStatus status, object handle, FileStatus fileStatus)> CreateFile(string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext, CancellationToken cancellationToken)
        {
            var 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);
                var           handle = new FileHandle(path, false, stream, false);
                fileStatus = FileStatus.FILE_OPENED;
                return(Task.FromResult <(NTStatus, object, FileStatus)>((NTStatus.STATUS_SUCCESS, handle, fileStatus)));
            }

            return(Task.FromResult <(NTStatus, object, FileStatus)>((NTStatus.STATUS_OBJECT_PATH_NOT_FOUND, null, fileStatus)));
        }
예제 #5
0
 public AccessAllowedACE(byte[] buffer, int offset)
 {
     Header = new AceHeader(buffer, offset + 0);
     Mask   = (AccessMask)LittleEndianConverter.ToUInt32(buffer, offset + 4);
     Sid    = new SID(buffer, offset + 8);
 }