QueryDirectoryHelper.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* Copyright (C) 2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using SMBLibrary.Authentication;
  10. using SMBLibrary.SMB2;
  11. using Utilities;
  12. namespace SMBLibrary.Server.SMB2
  13. {
  14. public class QueryDirectoryHelper
  15. {
  16. internal static SMB2Command GetQueryDirectoryResponse(QueryDirectoryRequest request, ISMBShare share, SMB2ConnectionState state)
  17. {
  18. SMB2Session session = state.GetSession(request.Header.SessionID);
  19. OpenFileObject openFile = session.GetOpenFileObject(request.FileId.Persistent);
  20. if (openFile == null)
  21. {
  22. return new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED);
  23. }
  24. if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path))
  25. {
  26. return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED);
  27. }
  28. FileSystemShare fileSystemShare = (FileSystemShare)share;
  29. ulong fileID = request.FileId.Persistent;
  30. OpenSearch openSearch = session.GetOpenSearch(fileID);
  31. if (openSearch == null || request.Reopen)
  32. {
  33. if (request.Reopen)
  34. {
  35. session.RemoveOpenSearch(fileID);
  36. }
  37. List<QueryDirectoryFileInformation> entries;
  38. NTStatus searchStatus = share.FileStore.QueryDirectory(out entries, openFile.Handle, request.FileName, request.FileInformationClass);
  39. if (searchStatus != NTStatus.STATUS_SUCCESS)
  40. {
  41. state.LogToServer(Severity.Verbose, "Query Directory: Path: '{0}', Searched for '{1}', NTStatus: {2}", openFile.Path, request.FileName, searchStatus.ToString());
  42. return new ErrorResponse(request.CommandName, searchStatus);
  43. }
  44. state.LogToServer(Severity.Verbose, "Query Directory: Path: '{0}', Searched for '{1}', found {2} matching entries", openFile.Path, request.FileName, entries.Count);
  45. openSearch = session.AddOpenSearch(fileID, entries, 0);
  46. }
  47. if (request.Restart || request.Reopen)
  48. {
  49. openSearch.EnumerationLocation = 0;
  50. }
  51. if (openSearch.Entries.Count == 0)
  52. {
  53. // [MS-SMB2] If there are no entries to return [..] the server MUST fail the request with STATUS_NO_SUCH_FILE.
  54. session.RemoveOpenSearch(fileID);
  55. return new ErrorResponse(request.CommandName, NTStatus.STATUS_NO_SUCH_FILE);
  56. }
  57. if (openSearch.EnumerationLocation == openSearch.Entries.Count)
  58. {
  59. return new ErrorResponse(request.CommandName, NTStatus.STATUS_NO_MORE_FILES);
  60. }
  61. List<QueryDirectoryFileInformation> page = new List<QueryDirectoryFileInformation>();
  62. int pageLength = 0;
  63. for (int index = openSearch.EnumerationLocation; index < openSearch.Entries.Count; index++)
  64. {
  65. QueryDirectoryFileInformation fileInformation = openSearch.Entries[index];
  66. if (fileInformation.FileInformationClass != request.FileInformationClass)
  67. {
  68. // We do not support changing FileInformationClass during a search (unless SMB2_REOPEN is set).
  69. return new ErrorResponse(request.CommandName, NTStatus.STATUS_INVALID_PARAMETER);
  70. }
  71. if (pageLength + fileInformation.Length <= request.OutputBufferLength)
  72. {
  73. page.Add(fileInformation);
  74. pageLength += fileInformation.Length;
  75. openSearch.EnumerationLocation = index + 1;
  76. }
  77. else
  78. {
  79. break;
  80. }
  81. if (request.ReturnSingleEntry)
  82. {
  83. break;
  84. }
  85. }
  86. QueryDirectoryResponse response = new QueryDirectoryResponse();
  87. response.SetFileInformationList(page);
  88. return response;
  89. }
  90. }
  91. }