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); }
private static NTCreateAndXResponse CreateResponseForNamedPipe(ushort fileID, FileStatus fileStatus) { NTCreateAndXResponse response = new NTCreateAndXResponse(); response.FID = fileID; response.CreateDisposition = ToCreateDisposition(fileStatus); response.ExtFileAttributes = ExtendedFileAttributes.Normal; response.ResourceType = ResourceType.FileTypeMessageModePipe; response.NMPipeStatus.ICount = 255; response.NMPipeStatus.ReadMode = ReadMode.MessageMode; response.NMPipeStatus.NamedPipeType = NamedPipeType.MessageNodePipe; return(response); }
private static NTCreateAndXResponse CreateResponseFromFileInformation(FileNetworkOpenInformation fileInfo, ushort fileID, FileStatus fileStatus) { NTCreateAndXResponse response = new NTCreateAndXResponse(); response.FID = fileID; response.CreateDisposition = ToCreateDisposition(fileStatus); response.CreateTime = fileInfo.CreationTime; response.LastAccessTime = fileInfo.LastAccessTime; response.LastWriteTime = fileInfo.LastWriteTime; response.LastChangeTime = fileInfo.LastWriteTime; response.AllocationSize = fileInfo.AllocationSize; response.EndOfFile = fileInfo.EndOfFile; response.ExtFileAttributes = (ExtendedFileAttributes)fileInfo.FileAttributes; response.ResourceType = ResourceType.FileTypeDisk; response.Directory = fileInfo.IsDirectory; return(response); }
private static NTCreateAndXResponse CreateResponseFromFileSystemEntry(FileSystemEntry entry, ushort fileID) { NTCreateAndXResponse response = new NTCreateAndXResponse(); if (entry.IsDirectory) { response.ExtFileAttributes = ExtendedFileAttributes.Directory; response.Directory = true; } else { response.ExtFileAttributes = ExtendedFileAttributes.Normal; } response.FID = fileID; response.CreateDisposition = CreateDisposition.FILE_OPEN; response.AllocationSize = InfoHelper.GetAllocationSize(entry.Size); response.EndOfFile = entry.Size; response.CreateTime = entry.CreationTime; response.LastAccessTime = entry.LastAccessTime; response.LastWriteTime = entry.LastWriteTime; response.LastChangeTime = entry.LastWriteTime; response.ResourceType = ResourceType.FileTypeDisk; return(response); }
internal static SMB1Command GetNTCreateResponse(SMB1Header header, NTCreateAndXRequest request, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); bool isExtended = (request.Flags & NTCreateFlags.NT_CREATE_REQUEST_EXTENDED_RESPONSE) > 0; string path = request.FileName; FileAccess createAccess = NTFileStoreHelper.ToCreateFileAccess(request.DesiredAccess, request.CreateDisposition); if (share is FileSystemShare) { if (!((FileSystemShare)share).HasAccess(session.SecurityContext, path, createAccess)) { state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. User '{2}' was denied access.", share.Name, request.FileName, session.UserName); header.Status = NTStatus.STATUS_ACCESS_DENIED; return(new ErrorResponse(request.CommandName)); } } object handle; FileStatus fileStatus; NTStatus createStatus = share.FileStore.CreateFile(out handle, out fileStatus, path, request.DesiredAccess, request.ShareAccess, request.CreateDisposition, request.CreateOptions, session.SecurityContext); if (createStatus != NTStatus.STATUS_SUCCESS) { state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. NTStatus: '{2}'.", share.Name, path, createStatus); header.Status = createStatus; return(new ErrorResponse(request.CommandName)); } state.LogToServer(Severity.Verbose, "Create: Opened '{0}{1}'.", share.Name, path); ushort?fileID = session.AddOpenFile(header.TID, path, handle); if (!fileID.HasValue) { share.FileStore.CloseFile(handle); header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES; return(new ErrorResponse(request.CommandName)); } if (share is NamedPipeShare) { if (isExtended) { return(CreateResponseExtendedForNamedPipe(fileID.Value, FileStatus.FILE_OPENED)); } else { return(CreateResponseForNamedPipe(fileID.Value, FileStatus.FILE_OPENED)); } } else // FileSystemShare { FileNetworkOpenInformation fileInfo = NTFileStoreHelper.GetNetworkOpenInformation(share.FileStore, handle); if (isExtended) { NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileInformation(fileInfo, fileID.Value, fileStatus); if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0) { response.OpLockLevel = OpLockLevel.BatchOpLockGranted; } return(response); } else { NTCreateAndXResponse response = CreateResponseFromFileInformation(fileInfo, fileID.Value, fileStatus); if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0) { response.OpLockLevel = OpLockLevel.BatchOpLockGranted; } return(response); } } }
internal static SMB1Command GetNTCreateResponse(SMB1Header header, NTCreateAndXRequest request, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); bool isExtended = (request.Flags & NTCreateFlags.NT_CREATE_REQUEST_EXTENDED_RESPONSE) > 0; string path = request.FileName; if (!path.StartsWith(@"\")) { path = @"\" + path; } FileAccess createAccess = NTFileStoreHelper.ToCreateFileAccess(request.DesiredAccess, request.CreateDisposition); if (share is FileSystemShare) { if (!((FileSystemShare)share).HasAccess(session.SecurityContext, path, createAccess)) { state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. User '{2}' was denied access.", share.Name, request.FileName, session.UserName); header.Status = NTStatus.STATUS_ACCESS_DENIED; return(new ErrorResponse(request.CommandName)); } } object handle; FileStatus fileStatus; FileAttributes fileAttributes = ToFileAttributes(request.ExtFileAttributes); // GetFileInformation/FileNetworkOpenInformation requires FILE_READ_ATTRIBUTES AccessMask desiredAccess = request.DesiredAccess | (AccessMask)FileAccessMask.FILE_READ_ATTRIBUTES; NTStatus createStatus = share.FileStore.CreateFile(out handle, out fileStatus, path, desiredAccess, fileAttributes, request.ShareAccess, request.CreateDisposition, request.CreateOptions, session.SecurityContext); if (createStatus != NTStatus.STATUS_SUCCESS) { state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. NTStatus: {2}.", share.Name, path, createStatus); header.Status = createStatus; return(new ErrorResponse(request.CommandName)); } FileAccess fileAccess = NTFileStoreHelper.ToFileAccess(desiredAccess); ushort? fileID = session.AddOpenFile(header.TID, share.Name, path, handle, fileAccess); if (!fileID.HasValue) { share.FileStore.CloseFile(handle); state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. Too many open files.", share.Name, path); header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES; return(new ErrorResponse(request.CommandName)); } string fileAccessString = fileAccess.ToString().Replace(", ", "|"); string shareAccessString = request.ShareAccess.ToString().Replace(", ", "|"); state.LogToServer(Severity.Verbose, "Create: Opened '{0}{1}', FileAccess: {2}, ShareAccess: {3}. (UID: {4}, TID: {5}, FID: {6})", share.Name, path, fileAccessString, shareAccessString, header.UID, header.TID, fileID.Value); if (share is NamedPipeShare) { if (isExtended) { return(CreateResponseExtendedForNamedPipe(fileID.Value, FileStatus.FILE_OPENED)); } else { return(CreateResponseForNamedPipe(fileID.Value, FileStatus.FILE_OPENED)); } } else // FileSystemShare { FileNetworkOpenInformation fileInfo = NTFileStoreHelper.GetNetworkOpenInformation(share.FileStore, handle); if (isExtended) { NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileInformation(fileInfo, fileID.Value, fileStatus); return(response); } else { NTCreateAndXResponse response = CreateResponseFromFileInformation(fileInfo, fileID.Value, fileStatus); return(response); } } }
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); } } }
public override IEnumerable <AbstractPacket> GetSubPackets(bool includeSelfReference) { if (includeSelfReference) { yield return(this); } AbstractPacket packet = null; try { CommandTypes commandType = (CommandTypes)command; if (commandType == CommandTypes.SMB_COM_NT_CREATE_ANDX) { if (!this.FlagsResponse) { packet = new NTCreateAndXRequest(this); } else { packet = new NTCreateAndXResponse(this); } } else if (commandType == CommandTypes.SMB_COM_READ_ANDX) { if (this.FlagsResponse) { packet = new ReadAndXResponse(this); } else { packet = new ReadAndXRequest(this); } } else if (commandType == CommandTypes.SMB_COM_CLOSE) { if (!this.FlagsResponse) { packet = new CloseRequest(this); } } else if (commandType == CommandTypes.SMB_COM_NEGOTIATE) { if (!this.FlagsResponse) { packet = new NegotiateProtocolRequest(this); } else { packet = new NegotiateProtocolResponse(this); } } else if (commandType == CommandTypes.SMB_COM_SESSION_SETUP_ANDX) { if (!this.FlagsResponse) { packet = new SetupAndXRequest(this); } else { packet = new SetupAndXResponse(this); } } } catch (Exception e) { yield break;//no sub packets } if (packet != null) { yield return(packet); foreach (AbstractPacket subPacket in packet.GetSubPackets(false)) { yield return(subPacket); } } else { yield break; } }