url_security_manager_win.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // Copyright (c) 2011 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 "net/http/url_security_manager.h"
  5. #include <urlmon.h>
  6. #include <wrl/client.h>
  7. #include "base/logging.h"
  8. #include "base/notreached.h"
  9. #include "base/strings/string_util.h"
  10. #include "base/strings/utf_string_conversions.h"
  11. #include "net/http/http_auth_filter.h"
  12. #include "url/scheme_host_port.h"
  13. // The Windows implementation of URLSecurityManager uses WinINet/IE's
  14. // URL security zone manager. See the MSDN page "URL Security Zones" at
  15. // http://msdn.microsoft.com/en-us/library/ms537021(VS.85).aspx for more
  16. // info on the Internet Security Manager and Internet Zone Manager objects.
  17. //
  18. // On Windows, we honor the WinINet/IE settings and group policy related to
  19. // URL Security Zones. See the Microsoft Knowledge Base article 182569
  20. // "Internet Explorer security zones registry entries for advanced users"
  21. // (http://support.microsoft.com/kb/182569) for more info on these registry
  22. // keys.
  23. namespace net {
  24. class URLSecurityManagerWin : public URLSecurityManagerAllowlist {
  25. public:
  26. URLSecurityManagerWin();
  27. URLSecurityManagerWin(const URLSecurityManagerWin&) = delete;
  28. URLSecurityManagerWin& operator=(const URLSecurityManagerWin&) = delete;
  29. ~URLSecurityManagerWin() override;
  30. // URLSecurityManager methods:
  31. bool CanUseDefaultCredentials(
  32. const url::SchemeHostPort& auth_scheme_host_port) const override;
  33. private:
  34. bool EnsureSystemSecurityManager();
  35. Microsoft::WRL::ComPtr<IInternetSecurityManager> security_manager_;
  36. };
  37. URLSecurityManagerWin::URLSecurityManagerWin() = default;
  38. URLSecurityManagerWin::~URLSecurityManagerWin() = default;
  39. bool URLSecurityManagerWin::CanUseDefaultCredentials(
  40. const url::SchemeHostPort& auth_scheme_host_port) const {
  41. if (HasDefaultAllowlist())
  42. return URLSecurityManagerAllowlist::CanUseDefaultCredentials(
  43. auth_scheme_host_port);
  44. if (!const_cast<URLSecurityManagerWin*>(this)->EnsureSystemSecurityManager())
  45. return false;
  46. std::u16string url16 = base::ASCIIToUTF16(auth_scheme_host_port.Serialize());
  47. DWORD policy = 0;
  48. HRESULT hr;
  49. hr = security_manager_->ProcessUrlAction(
  50. base::as_wcstr(url16), URLACTION_CREDENTIALS_USE,
  51. reinterpret_cast<BYTE*>(&policy), sizeof(policy), nullptr, 0, PUAF_NOUI,
  52. 0);
  53. if (FAILED(hr)) {
  54. LOG(ERROR) << "IInternetSecurityManager::ProcessUrlAction failed: " << hr;
  55. return false;
  56. }
  57. // Four possible policies for URLACTION_CREDENTIALS_USE. See the MSDN page
  58. // "About URL Security Zones" at
  59. // http://msdn.microsoft.com/en-us/library/ms537183(VS.85).aspx
  60. switch (policy) {
  61. case URLPOLICY_CREDENTIALS_SILENT_LOGON_OK:
  62. return true;
  63. case URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT: {
  64. // This policy means "prompt the user for permission if the resource is
  65. // not located in the Intranet zone". TODO(wtc): Note that it's
  66. // prompting for permission (to use the default credentials), as opposed
  67. // to prompting the user to enter a user name and password.
  68. // URLZONE_LOCAL_MACHINE 0
  69. // URLZONE_INTRANET 1
  70. // URLZONE_TRUSTED 2
  71. // URLZONE_INTERNET 3
  72. // URLZONE_UNTRUSTED 4
  73. DWORD zone = 0;
  74. hr = security_manager_->MapUrlToZone(base::as_wcstr(url16), &zone, 0);
  75. if (FAILED(hr)) {
  76. LOG(ERROR) << "IInternetSecurityManager::MapUrlToZone failed: " << hr;
  77. return false;
  78. }
  79. return zone <= URLZONE_INTRANET;
  80. }
  81. case URLPOLICY_CREDENTIALS_MUST_PROMPT_USER:
  82. return false;
  83. case URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY:
  84. // TODO(wtc): we should fail the authentication.
  85. return false;
  86. default:
  87. NOTREACHED();
  88. return false;
  89. }
  90. }
  91. // TODO(cbentzel): Could CanDelegate use the security zone as well?
  92. bool URLSecurityManagerWin::EnsureSystemSecurityManager() {
  93. if (!security_manager_.Get()) {
  94. HRESULT hr =
  95. CoInternetCreateSecurityManager(nullptr, &security_manager_, 0);
  96. if (FAILED(hr) || !security_manager_.Get()) {
  97. LOG(ERROR) << "Unable to create the Windows Security Manager instance";
  98. return false;
  99. }
  100. }
  101. return true;
  102. }
  103. // static
  104. std::unique_ptr<URLSecurityManager> URLSecurityManager::Create() {
  105. return std::make_unique<URLSecurityManagerWin>();
  106. }
  107. } // namespace net