File: url_security_manager_win.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (130 lines) | stat: -rw-r--r-- 4,622 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/url_security_manager.h"

#include <urlmon.h>
#include <wrl/client.h>

#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "net/http/http_auth_filter.h"
#include "url/scheme_host_port.h"

// The Windows implementation of URLSecurityManager uses WinINet/IE's
// URL security zone manager.  See the MSDN page "URL Security Zones" at
// http://msdn.microsoft.com/en-us/library/ms537021(VS.85).aspx for more
// info on the Internet Security Manager and Internet Zone Manager objects.
//
// On Windows, we honor the WinINet/IE settings and group policy related to
// URL Security Zones.  See the Microsoft Knowledge Base article 182569
// "Internet Explorer security zones registry entries for advanced users"
// (http://support.microsoft.com/kb/182569) for more info on these registry
// keys.

namespace net {

class URLSecurityManagerWin : public URLSecurityManagerAllowlist {
 public:
  URLSecurityManagerWin();

  URLSecurityManagerWin(const URLSecurityManagerWin&) = delete;
  URLSecurityManagerWin& operator=(const URLSecurityManagerWin&) = delete;

  ~URLSecurityManagerWin() override;

  // URLSecurityManager methods:
  bool CanUseDefaultCredentials(
      const url::SchemeHostPort& auth_scheme_host_port) const override;

 private:
  bool EnsureSystemSecurityManager();

  Microsoft::WRL::ComPtr<IInternetSecurityManager> security_manager_;
};

URLSecurityManagerWin::URLSecurityManagerWin() = default;
URLSecurityManagerWin::~URLSecurityManagerWin() = default;

bool URLSecurityManagerWin::CanUseDefaultCredentials(
    const url::SchemeHostPort& auth_scheme_host_port) const {
  if (HasDefaultAllowlist())
    return URLSecurityManagerAllowlist::CanUseDefaultCredentials(
        auth_scheme_host_port);
  if (!const_cast<URLSecurityManagerWin*>(this)->EnsureSystemSecurityManager())
    return false;

  std::u16string url16 = base::ASCIIToUTF16(auth_scheme_host_port.Serialize());
  DWORD policy = 0;
  HRESULT hr;
  hr = security_manager_->ProcessUrlAction(
      base::as_wcstr(url16), URLACTION_CREDENTIALS_USE,
      reinterpret_cast<BYTE*>(&policy), sizeof(policy), nullptr, 0, PUAF_NOUI,
      0);
  if (FAILED(hr)) {
    LOG(ERROR) << "IInternetSecurityManager::ProcessUrlAction failed: " << hr;
    return false;
  }

  // Four possible policies for URLACTION_CREDENTIALS_USE.  See the MSDN page
  // "About URL Security Zones" at
  // http://msdn.microsoft.com/en-us/library/ms537183(VS.85).aspx
  switch (policy) {
    case URLPOLICY_CREDENTIALS_SILENT_LOGON_OK:
      return true;
    case URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT: {
      // This policy means "prompt the user for permission if the resource is
      // not located in the Intranet zone".  TODO(wtc): Note that it's
      // prompting for permission (to use the default credentials), as opposed
      // to prompting the user to enter a user name and password.

      // URLZONE_LOCAL_MACHINE 0
      // URLZONE_INTRANET      1
      // URLZONE_TRUSTED       2
      // URLZONE_INTERNET      3
      // URLZONE_UNTRUSTED     4
      DWORD zone = 0;
      hr = security_manager_->MapUrlToZone(base::as_wcstr(url16), &zone, 0);
      if (FAILED(hr)) {
        LOG(ERROR) << "IInternetSecurityManager::MapUrlToZone failed: " << hr;
        return false;
      }
      return zone <= URLZONE_INTRANET;
    }
    case URLPOLICY_CREDENTIALS_MUST_PROMPT_USER:
      return false;
    case URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY:
      // TODO(wtc): we should fail the authentication.
      return false;
    default:
      LOG(ERROR) << "Unexpected policy: " << policy;
      SCOPED_CRASH_KEY_NUMBER("CanUseDefaultCredentials", "policy", policy);
      base::debug::DumpWithoutCrashing();
      return false;
  }
}
// TODO(cbentzel): Could CanDelegate use the security zone as well?

bool URLSecurityManagerWin::EnsureSystemSecurityManager() {
  if (!security_manager_.Get()) {
    HRESULT hr =
        CoInternetCreateSecurityManager(nullptr, &security_manager_, 0);
    if (FAILED(hr) || !security_manager_.Get()) {
      LOG(ERROR) << "Unable to create the Windows Security Manager instance";
      return false;
    }
  }
  return true;
}

// static
std::unique_ptr<URLSecurityManager> URLSecurityManager::Create() {
  return std::make_unique<URLSecurityManagerWin>();
}

}  //  namespace net