コード例 #1
0
        public void QueryDirectory(out List <QueryDirectoryFileInformation> result, NtHandle handle, string fileName, FileInformationClass informationClass)
        {
            result = new List <QueryDirectoryFileInformation>();

            QueryDirectoryRequest request = new QueryDirectoryRequest
            {
                Header = { CreditCharge = (ushort)Math.Ceiling((double)m_client.MaxTransactSize / BytesPerCredit) },
                FileInformationClass = informationClass,
                Reopen             = true,
                FileId             = (FileID)handle,
                OutputBufferLength = m_client.MaxTransactSize,
                FileName           = fileName
            };

            SendCommand(request);
            SMB2Command?response = WaitForCommand(request.MessageID);

            response.IsSuccessElseThrow();

            while (response is QueryDirectoryResponse queryDirectoryResponse)
            {
                List <QueryDirectoryFileInformation> page = queryDirectoryResponse.GetFileInformationList(informationClass);
                result.AddRange(page);
                request.Reopen = false;
                SendCommand(request);
                response = WaitForCommand(request.MessageID);
                if (response.Header.Status == NTStatus.STATUS_NO_MORE_FILES)
                {
                    break;
                }

                response.IsSuccessElseThrow();
            }
        }
コード例 #2
0
        public async Task <(NTStatus status, IEnumerable <QueryDirectoryFileInformation> result)> QueryDirectory(object handle, string fileName, FileInformationClass informationClass, CancellationToken cancellationToken)
        {
            QueryDirectoryRequest request = new QueryDirectoryRequest();

            request.Header.CreditCharge  = (ushort)Math.Ceiling((double)m_client.MaxTransactSize / BytesPerCredit);
            request.FileInformationClass = informationClass;
            request.Reopen             = true;
            request.FileId             = (FileID)handle;
            request.OutputBufferLength = m_client.MaxTransactSize;
            request.FileName           = fileName;

            await TrySendCommandAsync(request, cancellationToken);

            SMB2Command response = m_client.WaitForCommand(SMB2CommandName.QueryDirectory);

            if (response != null)
            {
                var result = new List <QueryDirectoryFileInformation>();
                while (response.Header.Status == NTStatus.STATUS_SUCCESS && response is QueryDirectoryResponse)
                {
                    var page = ((QueryDirectoryResponse)response).GetFileInformationList(informationClass);
                    result.AddRange(page);
                    request.Reopen = false;
                    await TrySendCommandAsync(request, cancellationToken);

                    response = m_client.WaitForCommand(SMB2CommandName.QueryDirectory);
                }
                return(response.Header.Status, result);
            }

            return(NTStatus.STATUS_INVALID_SMB, Enumerable.Empty <QueryDirectoryFileInformation>());
        }
コード例 #3
0
        public NTStatus QueryDirectory(out List <QueryDirectoryFileInformation> result, object handle, string fileName, FileInformationClass informationClass)
        {
            result = new List <QueryDirectoryFileInformation>();
            QueryDirectoryRequest request = new QueryDirectoryRequest();

            request.FileInformationClass = informationClass;
            request.Reopen             = true;
            request.FileId             = (FileID)handle;
            request.OutputBufferLength = m_client.MaxTransactSize;
            request.FileName           = fileName;

            ulong       messageId = TrySendCommand(request);
            SMB2Command response  = m_client.WaitForCommand(SMB2CommandName.QueryDirectory, messageId);

            if (response != null)
            {
                while (response.Header.Status == NTStatus.STATUS_SUCCESS && response is QueryDirectoryResponse)
                {
                    List <QueryDirectoryFileInformation> page = ((QueryDirectoryResponse)response).GetFileInformationList(informationClass);
                    result.AddRange(page);
                    request.Reopen = false;
                    messageId      = TrySendCommand(request);
                    response       = m_client.WaitForCommand(SMB2CommandName.QueryDirectory, messageId);
                }
                return(response.Header.Status);
            }

            return(NTStatus.STATUS_INVALID_SMB);
        }
コード例 #4
0
        internal static SMB2Command GetQueryDirectoryResponse(QueryDirectoryRequest request, ISMBShare share, SMB2ConnectionState state)
        {
            SMB2Session    session  = state.GetSession(request.Header.SessionID);
            OpenFileObject openFile = session.GetOpenFileObject(request.FileId);

            if (openFile == null)
            {
                state.LogToServer(Severity.Verbose, "Query Directory failed. Invalid FileId. (SessionID: {0}, TreeID: {1}, FileId: {2})", request.Header.SessionID, request.Header.TreeID, request.FileId.Volatile);
                return(new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED));
            }

            if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path))
            {
                state.LogToServer(Severity.Verbose, "Query Directory on '{0}{1}' failed. User '{2}' was denied access.", share.Name, openFile.Path, session.UserName);
                return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED));
            }

            FileSystemShare fileSystemShare = (FileSystemShare)share;

            FileID     fileID     = request.FileId;
            OpenSearch openSearch = session.GetOpenSearch(fileID);

            if (openSearch == null || request.Reopen)
            {
                if (request.Reopen)
                {
                    session.RemoveOpenSearch(fileID);
                }
                List <QueryDirectoryFileInformation> entries;
                NTStatus searchStatus = share.FileStore.QueryDirectory(out entries, openFile.Handle, request.FileName, request.FileInformationClass);
                if (searchStatus != NTStatus.STATUS_SUCCESS)
                {
                    state.LogToServer(Severity.Verbose, "Query Directory on '{0}{1}', Searched for '{2}', NTStatus: {3}", share.Name, openFile.Path, request.FileName, searchStatus.ToString());
                    return(new ErrorResponse(request.CommandName, searchStatus));
                }
                state.LogToServer(Severity.Information, "Query Directory on '{0}{1}', Searched for '{2}', found {3} matching entries", share.Name, openFile.Path, request.FileName, entries.Count);
                openSearch = session.AddOpenSearch(fileID, entries, 0);
            }

            if (request.Restart || request.Reopen)
            {
                openSearch.EnumerationLocation = 0;
            }

            if (openSearch.Entries.Count == 0)
            {
                // [MS-SMB2] If there are no entries to return [..] the server MUST fail the request with STATUS_NO_SUCH_FILE.
                session.RemoveOpenSearch(fileID);
                return(new ErrorResponse(request.CommandName, NTStatus.STATUS_NO_SUCH_FILE));
            }

            if (openSearch.EnumerationLocation == openSearch.Entries.Count)
            {
                return(new ErrorResponse(request.CommandName, NTStatus.STATUS_NO_MORE_FILES));
            }

            List <QueryDirectoryFileInformation> page = new List <QueryDirectoryFileInformation>();
            int pageLength = 0;

            for (int index = openSearch.EnumerationLocation; index < openSearch.Entries.Count; index++)
            {
                QueryDirectoryFileInformation fileInformation = openSearch.Entries[index];
                if (fileInformation.FileInformationClass != request.FileInformationClass)
                {
                    // We do not support changing FileInformationClass during a search (unless SMB2_REOPEN is set).
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_INVALID_PARAMETER));
                }

                int entryLength = fileInformation.Length;
                if (pageLength + entryLength <= request.OutputBufferLength)
                {
                    page.Add(fileInformation);
                    int paddedLength = (int)Math.Ceiling((double)entryLength / 8) * 8;
                    pageLength += paddedLength;
                    openSearch.EnumerationLocation = index + 1;
                }
                else
                {
                    break;
                }

                if (request.ReturnSingleEntry)
                {
                    break;
                }
            }

            QueryDirectoryResponse response = new QueryDirectoryResponse();

            response.SetFileInformationList(page);
            return(response);
        }