caller_validation.cc 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "chrome/elevation_service/caller_validation.h"
  5. #include <windows.h> // Must be in front of other Windows header files.
  6. #include <psapi.h>
  7. #include <string>
  8. #include <vector>
  9. #include "base/logging.h"
  10. #include "base/process/process.h"
  11. #include "base/strings/string_util.h"
  12. #include "chrome/elevation_service/elevation_service_idl.h"
  13. namespace elevation_service {
  14. namespace {
  15. constexpr char kPathValidationPrefix[] = "PATH";
  16. constexpr char kNoneValidationPrefix[] = "NONE";
  17. std::string GetProcessExecutablePath(const base::Process& process) {
  18. std::string image_path(MAX_PATH, L'\0');
  19. DWORD path_length = image_path.size();
  20. BOOL success = ::QueryFullProcessImageNameA(
  21. process.Handle(), PROCESS_NAME_NATIVE, image_path.data(), &path_length);
  22. if (!success && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  23. // Process name is potentially greater than MAX_PATH, try larger max size.
  24. // https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
  25. image_path.resize(UNICODE_STRING_MAX_CHARS);
  26. path_length = image_path.size();
  27. success = ::QueryFullProcessImageNameA(
  28. process.Handle(), PROCESS_NAME_NATIVE, image_path.data(), &path_length);
  29. }
  30. if (!success) {
  31. PLOG_IF(ERROR, ::GetLastError() != ERROR_GEN_FAILURE)
  32. << "Failed to get process image path";
  33. return std::string();
  34. }
  35. image_path.resize(path_length);
  36. return image_path;
  37. }
  38. // Generate path based validation data, or return empty string if this was not
  39. // possible.
  40. std::string GeneratePathValidationData(const base::Process& process) {
  41. return GetProcessExecutablePath(process);
  42. }
  43. bool ValidatePath(const base::Process& process, const std::string& data) {
  44. return data == GetProcessExecutablePath(process);
  45. }
  46. } // namespace
  47. std::string GenerateValidationData(ProtectionLevel level,
  48. const base::Process& process) {
  49. std::string validation_data;
  50. switch (level) {
  51. case ProtectionLevel::NONE:
  52. validation_data.insert(0, kNoneValidationPrefix);
  53. break;
  54. case ProtectionLevel::PATH_VALIDATION:
  55. validation_data = GeneratePathValidationData(process);
  56. if (validation_data.empty())
  57. return std::string();
  58. validation_data.insert(0, kPathValidationPrefix);
  59. break;
  60. }
  61. return validation_data;
  62. }
  63. bool ValidateData(const base::Process& process,
  64. const std::string& validation_data) {
  65. // Determine which kind of validation was requested.
  66. if (base::StartsWith(validation_data, kNoneValidationPrefix,
  67. base::CompareCase::SENSITIVE)) {
  68. // No validation always returns true.
  69. return true;
  70. } else if (base::StartsWith(validation_data, kPathValidationPrefix,
  71. base::CompareCase::SENSITIVE)) {
  72. // Strip off the path validation header.
  73. const std::string path_validation_data =
  74. validation_data.substr(sizeof(kPathValidationPrefix) - 1);
  75. // Defer to the path validation.
  76. return ValidatePath(process, path_validation_data);
  77. }
  78. return false;
  79. }
  80. } // namespace elevation_service