Esempio n. 1
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)
            {
                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);
                }
            }

            SetInformation information;

            try
            {
                information = SetInformation.GetSetInformation(subcommand.InformationBytes, subcommand.InformationLevel);
            }
            catch (UnsupportedInformationLevelException)
            {
                state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL", share.Name, openFile.Path, subcommand.InformationLevel);
                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.InformationLevel);
                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}", share.Name, openFile.Path, subcommand.InformationLevel, status);
                header.Status = status;
                return(null);
            }
            state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information level: {2}", share.Name, openFile.Path, subcommand.InformationLevel);
            Transaction2SetFileInformationResponse response = new Transaction2SetFileInformationResponse();

            return(response);
        }
        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();
            }
            }
        }