Пример #1
0
        public NTStatus SetFileInformation(object handle, SetInformation information)
        {
            int maxOutputLength = 4096;
            Transaction2SetFileInformationRequest subcommand = new Transaction2SetFileInformationRequest();

            subcommand.FID = (ushort)handle;
            subcommand.SetInformation(information);

            Transaction2Request request = new Transaction2Request();

            request.Setup               = subcommand.GetSetup();
            request.TransParameters     = subcommand.GetParameters(m_client.Unicode);
            request.TransData           = subcommand.GetData(m_client.Unicode);
            request.TotalDataCount      = (ushort)request.TransData.Length;
            request.TotalParameterCount = (ushort)request.TransParameters.Length;
            request.MaxParameterCount   = Transaction2SetFileInformationResponse.ParametersLength;
            request.MaxDataCount        = (ushort)maxOutputLength;

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

            if (reply != null)
            {
                return(reply.Header.Status);
            }
            return(NTStatus.STATUS_INVALID_SMB);
        }
Пример #2
0
        public void SetFileInformation(NtHandle handle, SetInformation information)
        {
            int maxOutputLength = 4096;
            Transaction2SetFileInformationRequest subcommand = new Transaction2SetFileInformationRequest
            {
                FID = ((Smb1Handle)handle).FID,
            };

            subcommand.SetInformation(information);

            Transaction2Request request = new Transaction2Request
            {
                Setup           = subcommand.GetSetup(),
                TransParameters = subcommand.GetParameters(m_client.Unicode),
                TransData       = subcommand.GetData(m_client.Unicode)
            };

            request.TotalDataCount      = (ushort)request.TransData.Length;
            request.TotalParameterCount = (ushort)request.TransParameters.Length;
            request.MaxParameterCount   = Transaction2SetFileInformationResponse.ParametersLength;
            request.MaxDataCount        = (ushort)maxOutputLength;

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

            reply.IsSuccessElseThrow();
        }
Пример #3
0
        public void SetFileInformation(NtHandle handle, FileInformation information)
        {
            if (!m_client.InfoLevelPassthrough)
            {
                throw new NotSupportedException("Server does not support InfoLevelPassthrough");
            }

            if (information is FileRenameInformationType2 fileRenameInformationType2)
            {
                FileRenameInformationType1 informationType1 = new FileRenameInformationType1
                {
                    FileName        = fileRenameInformationType2.FileName,
                    ReplaceIfExists = fileRenameInformationType2.ReplaceIfExists,
                    RootDirectory   = (uint)fileRenameInformationType2.RootDirectory
                };
                information = informationType1;
            }

            int maxOutputLength = 4096;
            Transaction2SetFileInformationRequest subcommand = new Transaction2SetFileInformationRequest
            {
                FID = ((Smb1Handle)handle).FID,
            };

            subcommand.SetInformation(information);

            Transaction2Request request = new Transaction2Request
            {
                Setup           = subcommand.GetSetup(),
                TransParameters = subcommand.GetParameters(m_client.Unicode),
                TransData       = subcommand.GetData(m_client.Unicode)
            };

            request.TotalDataCount      = (ushort)request.TransData.Length;
            request.TotalParameterCount = (ushort)request.TransParameters.Length;
            request.MaxParameterCount   = Transaction2SetFileInformationResponse.ParametersLength;
            request.MaxDataCount        = (ushort)maxOutputLength;

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

            reply.IsSuccessElseThrow();
        }
Пример #4
0
        public NTStatus SetFileInformation(object handle, FileInformation information)
        {
            if (m_client.InfoLevelPassthrough)
            {
                if (information is FileRenameInformationType2)
                {
                    FileRenameInformationType1 informationType1 = new FileRenameInformationType1();
                    informationType1.FileName        = ((FileRenameInformationType2)information).FileName;
                    informationType1.ReplaceIfExists = ((FileRenameInformationType2)information).ReplaceIfExists;
                    informationType1.RootDirectory   = (uint)((FileRenameInformationType2)information).RootDirectory;
                    information = informationType1;
                }

                int maxOutputLength = 4096;
                Transaction2SetFileInformationRequest subcommand = new Transaction2SetFileInformationRequest();
                subcommand.FID = (ushort)handle;
                subcommand.SetInformation(information);

                Transaction2Request request = new Transaction2Request();
                request.Setup               = subcommand.GetSetup();
                request.TransParameters     = subcommand.GetParameters(m_client.Unicode);
                request.TransData           = subcommand.GetData(m_client.Unicode);
                request.TotalDataCount      = (ushort)request.TransData.Length;
                request.TotalParameterCount = (ushort)request.TransParameters.Length;
                request.MaxParameterCount   = Transaction2SetFileInformationResponse.ParametersLength;
                request.MaxDataCount        = (ushort)maxOutputLength;

                TrySendMessage(request);
                SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_TRANSACTION2);
                if (reply != null)
                {
                    return(reply.Header.Status);
                }
                return(NTStatus.STATUS_INVALID_SMB);
            }
            else
            {
                throw new NotSupportedException("Server does not support InfoLevelPassthrough");
            }
        }
        internal static Transaction2SetFileInformationResponse GetSubcommandResponse(SMBHeader header, Transaction2SetFileInformationRequest subcommand, FileSystemShare share, StateObject state)
        {
            string openedFilePath = state.GetOpenedFilePath(subcommand.FID);

            if (openedFilePath == null)
            {
                header.Status = NTStatus.STATUS_INVALID_HANDLE;
                return(null);
            }

            Transaction2SetFileInformationResponse response = new Transaction2SetFileInformationResponse();

            switch (subcommand.InformationLevel)
            {
            case SetInformationLevel.SMB_INFO_STANDARD:
            {
                return(response);
            }

            case SetInformationLevel.SMB_INFO_SET_EAS:
            {
                throw new NotImplementedException();
            }

            case SetInformationLevel.SMB_SET_FILE_BASIC_INFO:
            {
                string userName = state.GetConnectedUserName(header.UID);
                if (!share.HasWriteAccess(userName))
                {
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }

                SetFileBasicInfo info       = (SetFileBasicInfo)subcommand.SetInfo;
                bool             isHidden   = (info.ExtFileAttributes & ExtendedFileAttributes.Hidden) > 0;
                bool             isReadonly = (info.ExtFileAttributes & ExtendedFileAttributes.Readonly) > 0;
                bool             isArchived = (info.ExtFileAttributes & ExtendedFileAttributes.Archive) > 0;
                try
                {
                    share.FileSystem.SetAttributes(openedFilePath, isHidden, isReadonly, isArchived);
                }
                catch (UnauthorizedAccessException)
                {
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }

                DateTime?creationTime   = null;
                DateTime?lastWriteDT    = null;
                DateTime?lastAccessTime = null;
                if (info.CreationTime != SMBHelper.FileTimeNotSpecified)
                {
                    creationTime = info.CreationTime;
                }
                if (info.LastWriteTime != SMBHelper.FileTimeNotSpecified)
                {
                    lastWriteDT = info.LastWriteTime;
                }
                if (info.LastAccessTime != SMBHelper.FileTimeNotSpecified)
                {
                    lastAccessTime = info.LastAccessTime;
                }

                try
                {
                    share.FileSystem.SetDates(openedFilePath, creationTime, lastWriteDT, lastAccessTime);
                }
                catch (IOException ex)
                {
                    ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                    if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                    {
                        // Returning STATUS_SHARING_VIOLATION is undocumented but apparently valid
                        header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                        return(null);
                    }
                    else
                    {
                        header.Status = NTStatus.STATUS_DATA_ERROR;
                        return(null);
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }
                return(response);
            }

            case SetInformationLevel.SMB_SET_FILE_DISPOSITION_INFO:
            {
                if (((SetFileDispositionInfo)subcommand.SetInfo).DeletePending)
                {
                    // We're supposed to delete the file on close, but it's too late to report errors at this late stage
                    string userName = state.GetConnectedUserName(header.UID);
                    if (!share.HasWriteAccess(userName))
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(null);
                    }

                    try
                    {
                        share.FileSystem.Delete(openedFilePath);
                    }
                    catch (IOException)
                    {
                        header.Status = NTStatus.STATUS_FILE_LOCK_CONFLICT;
                        return(null);
                    }
                    catch (UnauthorizedAccessException)
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(null);
                    }
                }
                return(response);
            }

            case SetInformationLevel.SMB_SET_FILE_ALLOCATION_INFO:
            {
                // This subcommand is used to set the file length in bytes.
                // Note: the input will NOT be a multiple of the cluster size / bytes per sector.
                ulong allocationSize = ((SetFileAllocationInfo)subcommand.SetInfo).AllocationSize;
                try
                {
                    Stream stream = share.FileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                    stream.SetLength((long)allocationSize);
                    stream.Close();
                }
                catch
                {
                }
                return(response);
            }

            case SetInformationLevel.SMB_SET_FILE_END_OF_FILE_INFO:
            {
                ulong endOfFile = ((SetFileEndOfFileInfo)subcommand.SetInfo).EndOfFile;
                try
                {
                    Stream stream = share.FileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                    stream.SetLength((long)endOfFile);
                    stream.Close();
                }
                catch
                {
                }
                return(response);
            }

            default:
            {
                throw new InvalidRequestException();
            }
            }
        }
Пример #6
0
        internal static Transaction2SetFileInformationResponse GetSubcommandResponse(SMB1Header header, Transaction2SetFileInformationRequest subcommand, ISMBShare share, SMB1ConnectionState state)
        {
            SMB1Session    session  = state.GetSession(header.UID);
            OpenFileObject openFile = session.GetOpenFileObject(subcommand.FID);

            if (openFile == null)
            {
                state.LogToServer(Severity.Verbose, "SetFileInformation failed. Invalid FID. (UID: {0}, TID: {1}, FID: {2})", header.UID, header.TID, subcommand.FID);
                header.Status = NTStatus.STATUS_INVALID_HANDLE;
                return(null);
            }

            if (share is FileSystemShare)
            {
                if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, openFile.Path))
                {
                    state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. User '{2}' was denied access.", share.Name, openFile.Path, session.UserName);
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }
            }

            if (subcommand.IsPassthroughInformationLevel)
            {
                FileInformation fileInfo;
                try
                {
                    fileInfo = FileInformation.GetFileInformation(subcommand.InformationBytes, 0, subcommand.FileInformationClass);
                }
                catch (UnsupportedInformationLevelException)
                {
                    state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL.", share.Name, openFile.Path, subcommand.FileInformationClass);
                    header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL;
                    return(null);
                }
                catch (Exception)
                {
                    state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: STATUS_INVALID_PARAMETER.", share.Name, openFile.Path, subcommand.FileInformationClass);
                    header.Status = NTStatus.STATUS_INVALID_PARAMETER;
                    return(null);
                }

                NTStatus status = share.FileStore.SetFileInformation(openFile.Handle, fileInfo);
                if (status != NTStatus.STATUS_SUCCESS)
                {
                    state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.FileInformationClass, status, subcommand.FID);
                    header.Status = status;
                    return(null);
                }
                state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information class: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.FileInformationClass, subcommand.FID);
            }
            else
            {
                SetInformation information;
                try
                {
                    information = SetInformation.GetSetInformation(subcommand.InformationBytes, subcommand.SetInformationLevel);
                }
                catch (UnsupportedInformationLevelException)
                {
                    state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL.", share.Name, openFile.Path, subcommand.SetInformationLevel);
                    header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL;
                    return(null);
                }
                catch (Exception)
                {
                    state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_INVALID_PARAMETER.", share.Name, openFile.Path, subcommand.SetInformationLevel);
                    header.Status = NTStatus.STATUS_INVALID_PARAMETER;
                    return(null);
                }

                NTStatus status = SMB1FileStoreHelper.SetFileInformation(share.FileStore, openFile.Handle, information);
                if (status != NTStatus.STATUS_SUCCESS)
                {
                    state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.SetInformationLevel, status, subcommand.FID);
                    header.Status = status;
                    return(null);
                }
                state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.SetInformationLevel, subcommand.FID);
            }
            Transaction2SetFileInformationResponse response = new Transaction2SetFileInformationResponse();

            return(response);
        }