コード例 #1
0
        internal static SMBCommand GetNTCreateResponse(SMBHeader header, NTCreateAndXRequest request, object share, StateObject state)
        {
            bool   isExtended = (request.Flags & NTCreateFlags.NT_CREATE_REQUEST_EXTENDED_RESPONSE) > 0;
            string path       = request.FileName;

            if (share is NamedPipeShare)
            {
                RemoteService service = ((NamedPipeShare)share).GetService(path);
                if (service != null)
                {
                    ushort fileID = state.AddOpenedFile(path);
                    if (isExtended)
                    {
                        return(CreateResponseExtendedForNamedPipe(fileID));
                    }
                    else
                    {
                        return(CreateResponseForNamedPipe(fileID));
                    }
                }

                header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
            }
            else // FileSystemShare
            {
                FileSystemShare fileSystemShare = (FileSystemShare)share;
                IFileSystem     fileSystem      = fileSystemShare.FileSystem;
                bool            forceDirectory  = (request.CreateOptions & CreateOptions.FILE_DIRECTORY_FILE) > 0;
                bool            forceFile       = (request.CreateOptions & CreateOptions.FILE_NON_DIRECTORY_FILE) > 0;

                if (forceDirectory & (request.CreateDisposition != CreateDisposition.FILE_CREATE &&
                                      request.CreateDisposition != CreateDisposition.FILE_OPEN &&
                                      request.CreateDisposition != CreateDisposition.FILE_OPEN_IF))
                {
                    header.Status = NTStatus.STATUS_INVALID_PARAMETER;
                    return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                }

                // 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
                    header.Status = NTStatus.STATUS_NO_SUCH_FILE;
                    return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                }

                FileSystemEntry entry = fileSystem.GetEntry(path);
                if (request.CreateDisposition == CreateDisposition.FILE_OPEN)
                {
                    if (entry == null)
                    {
                        header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }

                    if (entry.IsDirectory && forceFile)
                    {
                        header.Status = NTStatus.STATUS_FILE_IS_A_DIRECTORY;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }

                    if (!entry.IsDirectory && forceDirectory)
                    {
                        // Not sure if that's the correct response
                        header.Status = NTStatus.STATUS_OBJECT_NAME_COLLISION;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }
                }
                else if (request.CreateDisposition == CreateDisposition.FILE_CREATE)
                {
                    if (entry != null)
                    {
                        // File already exists, fail the request
                        header.Status = NTStatus.STATUS_OBJECT_NAME_COLLISION;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }

                    string userName = state.GetConnectedUserName(header.UID);
                    if (!fileSystemShare.HasWriteAccess(userName))
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }

                    try
                    {
                        if (forceDirectory)
                        {
                            entry = fileSystem.CreateDirectory(path);
                        }
                        else
                        {
                            entry = fileSystem.CreateFile(path);
                        }
                    }
                    catch (IOException ex)
                    {
                        ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                        if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                        {
                            header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }
                        else
                        {
                            header.Status = NTStatus.STATUS_DATA_ERROR;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }
                }
                else if (request.CreateDisposition == CreateDisposition.FILE_OPEN_IF ||
                         request.CreateDisposition == CreateDisposition.FILE_OVERWRITE ||
                         request.CreateDisposition == CreateDisposition.FILE_OVERWRITE_IF ||
                         request.CreateDisposition == CreateDisposition.FILE_SUPERSEDE)
                {
                    entry = fileSystem.GetEntry(path);
                    if (entry == null)
                    {
                        if (request.CreateDisposition == CreateDisposition.FILE_OVERWRITE)
                        {
                            header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }

                        string userName = state.GetConnectedUserName(header.UID);
                        if (!fileSystemShare.HasWriteAccess(userName))
                        {
                            header.Status = NTStatus.STATUS_ACCESS_DENIED;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }

                        try
                        {
                            if (forceDirectory)
                            {
                                entry = fileSystem.CreateDirectory(path);
                            }
                            else
                            {
                                entry = fileSystem.CreateFile(path);
                            }
                        }
                        catch (IOException ex)
                        {
                            ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                            if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                            {
                                header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                            }
                            else
                            {
                                header.Status = NTStatus.STATUS_DATA_ERROR;
                                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                            }
                        }
                        catch (UnauthorizedAccessException)
                        {
                            header.Status = NTStatus.STATUS_ACCESS_DENIED;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }
                    }
                    else
                    {
                        if (request.CreateDisposition == CreateDisposition.FILE_OVERWRITE ||
                            request.CreateDisposition == CreateDisposition.FILE_OVERWRITE_IF ||
                            request.CreateDisposition == CreateDisposition.FILE_SUPERSEDE)
                        {
                            string userName = state.GetConnectedUserName(header.UID);
                            if (!fileSystemShare.HasWriteAccess(userName))
                            {
                                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                            }

                            // Truncate the file
                            try
                            {
                                Stream stream = fileSystem.OpenFile(path, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite);
                                stream.Close();
                            }
                            catch (IOException ex)
                            {
                                ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                                if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                                {
                                    header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                                    return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                                }
                                else
                                {
                                    header.Status = NTStatus.STATUS_DATA_ERROR;
                                    return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                                }
                            }
                            catch (UnauthorizedAccessException)
                            {
                                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                            }
                        }
                    }
                }
                else
                {
                    throw new InvalidRequestException();
                }
                bool   isSequentialAccess = (request.CreateOptions & CreateOptions.FILE_SEQUENTIAL_ONLY) > 0;
                ushort fileID             = state.AddOpenedFile(path, isSequentialAccess);
                if (isExtended)
                {
                    NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileSystemEntry(entry, fileID);
                    if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
                    {
                        response.OpLockLevel = OpLockLevel.BatchOpLockGranted;
                    }
                    return(response);
                }
                else
                {
                    NTCreateAndXResponse response = CreateResponseFromFileSystemEntry(entry, fileID);
                    if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
                    {
                        response.OpLockLevel = OpLockLevel.BatchOpLockGranted;
                    }
                    return(response);
                }
            }
        }
コード例 #2
0
        internal static SMBCommand GetOpenAndXResponse(SMBHeader header, OpenAndXRequest request, object share, StateObject state)
        {
            bool   isExtended = (request.Flags & OpenFlags.SMB_OPEN_EXTENDED_RESPONSE) > 0;
            string path       = request.FileName;

            if (share is NamedPipeShare)
            {
                RemoteService service = ((NamedPipeShare)share).GetService(path);
                if (service != null)
                {
                    ushort fileID = state.AddOpenedFile(path);
                    if (isExtended)
                    {
                        return(CreateResponseExtendedForNamedPipe(fileID));
                    }
                    else
                    {
                        CreateResponseForNamedPipe(fileID);
                    }
                }

                header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
                return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
            }
            else // FileSystemShare
            {
                FileSystemShare fileSystemShare = (FileSystemShare)share;
                string          userName        = state.GetConnectedUserName(header.UID);
                bool            hasWriteAccess  = fileSystemShare.HasWriteAccess(userName);
                IFileSystem     fileSystem      = fileSystemShare.FileSystem;

                OpenResult      openResult;
                FileSystemEntry entry = fileSystem.GetEntry(path);
                if (entry != null)
                {
                    if (!hasWriteAccess && request.AccessMode.AccessMode == AccessMode.Write || request.AccessMode.AccessMode == AccessMode.ReadWrite)
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                    }

                    if (request.OpenMode.FileExistsOpts == FileExistsOpts.ReturnError)
                    {
                        header.Status = NTStatus.STATUS_OBJECT_NAME_COLLISION;
                        return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                    }
                    else if (request.OpenMode.FileExistsOpts == FileExistsOpts.TruncateToZero)
                    {
                        try
                        {
                            Stream stream = fileSystem.OpenFile(path, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite);
                            stream.Close();
                        }
                        catch (IOException ex)
                        {
                            ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                            if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                            {
                                header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                                return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                            }
                            else
                            {
                                header.Status = NTStatus.STATUS_DATA_ERROR;
                                return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                            }
                        }
                        catch (UnauthorizedAccessException)
                        {
                            header.Status = NTStatus.STATUS_ACCESS_DENIED;
                            return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                        }
                        openResult = OpenResult.FileExistedAndWasTruncated;
                    }
                    else // FileExistsOpts.Append
                    {
                        openResult = OpenResult.FileExistedAndWasOpened;
                    }
                }
                else
                {
                    if (request.OpenMode.CreateFile == CreateFile.ReturnErrorIfNotExist)
                    {
                        header.Status = NTStatus.STATUS_NO_SUCH_FILE;
                        return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                    }

                    entry      = fileSystem.CreateFile(path);
                    openResult = OpenResult.NotExistedAndWasCreated;
                }

                ushort fileID = state.AddOpenedFile(path, true);
                if (isExtended)
                {
                    return(CreateResponseFromFileSystemEntry(entry, fileID, openResult));
                }
                else
                {
                    return(CreateResponseExtendedFromFileSystemEntry(entry, fileID, openResult));
                }
            }
        }