1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/url_security_manager.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <urlmon.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#pragma comment(lib, "urlmon.lib")
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/win/scoped_comptr.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_auth_filter.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The Windows implementation of URLSecurityManager uses WinINet/IE's
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// URL security zone manager.  See the MSDN page "URL Security Zones" at
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// http://msdn.microsoft.com/en-us/library/ms537021(VS.85).aspx for more
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// info on the Internet Security Manager and Internet Zone Manager objects.
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// On Windows, we honor the WinINet/IE settings and group policy related to
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// URL Security Zones.  See the Microsoft Knowledge Base article 182569
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// "Internet Explorer security zones registry entries for advanced users"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// (http://support.microsoft.com/kb/182569) for more info on these registry
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// keys.
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass URLSecurityManagerWin : public URLSecurityManager {
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  explicit URLSecurityManagerWin(const HttpAuthFilter* whitelist_delegate);
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // URLSecurityManager methods:
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual bool CanUseDefaultCredentials(const GURL& auth_origin) const;
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual bool CanDelegate(const GURL& auth_origin) const;
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool EnsureSystemSecurityManager();
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::win::ScopedComPtr<IInternetSecurityManager> security_manager_;
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<const HttpAuthFilter> whitelist_delegate_;
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(URLSecurityManagerWin);
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickURLSecurityManagerWin::URLSecurityManagerWin(
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const HttpAuthFilter* whitelist_delegate)
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : whitelist_delegate_(whitelist_delegate) {
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool URLSecurityManagerWin::CanUseDefaultCredentials(
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const GURL& auth_origin) const {
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!const_cast<URLSecurityManagerWin*>(this)->EnsureSystemSecurityManager())
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring url_w = ASCIIToWide(auth_origin.spec());
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DWORD policy = 0;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HRESULT hr;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hr = security_manager_->ProcessUrlAction(url_w.c_str(),
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           URLACTION_CREDENTIALS_USE,
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           reinterpret_cast<BYTE*>(&policy),
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           sizeof(policy), NULL, 0,
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           PUAF_NOUI, 0);
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (FAILED(hr)) {
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "IInternetSecurityManager::ProcessUrlAction failed: " << hr;
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Four possible policies for URLACTION_CREDENTIALS_USE.  See the MSDN page
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // "About URL Security Zones" at
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // http://msdn.microsoft.com/en-us/library/ms537183(VS.85).aspx
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (policy) {
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case URLPOLICY_CREDENTIALS_SILENT_LOGON_OK:
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT: {
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // This policy means "prompt the user for permission if the resource is
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // not located in the Intranet zone".  TODO(wtc): Note that it's
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // prompting for permission (to use the default credentials), as opposed
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // to prompting the user to enter a user name and password.
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // URLZONE_LOCAL_MACHINE 0
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // URLZONE_INTRANET      1
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // URLZONE_TRUSTED       2
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // URLZONE_INTERNET      3
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // URLZONE_UNTRUSTED     4
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DWORD zone = 0;
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      hr = security_manager_->MapUrlToZone(url_w.c_str(), &zone, 0);
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (FAILED(hr)) {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LOG(ERROR) << "IInternetSecurityManager::MapUrlToZone failed: " << hr;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return false;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return zone <= URLZONE_INTRANET;
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case URLPOLICY_CREDENTIALS_MUST_PROMPT_USER:
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY:
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // TODO(wtc): we should fail the authentication.
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool URLSecurityManagerWin::CanDelegate(const GURL& auth_origin) const {
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(cbentzel): Could this just use the security zone as well? Apparently
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  //                 this is what IE does as well.
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (whitelist_delegate_.get())
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return whitelist_delegate_->IsValid(auth_origin, HttpAuth::AUTH_SERVER);
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return false;
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool URLSecurityManagerWin::EnsureSystemSecurityManager() {
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!security_manager_) {
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HRESULT hr = CoInternetCreateSecurityManager(NULL,
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                 security_manager_.Receive(),
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                 NULL);
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (FAILED(hr) || !security_manager_) {
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      LOG(ERROR) << "Unable to create the Windows Security Manager instance";
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return false;
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochURLSecurityManager* URLSecurityManager::Create(
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const HttpAuthFilter* whitelist_default,
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const HttpAuthFilter* whitelist_delegate) {
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we have a whitelist, just use that.
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (whitelist_default)
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return new URLSecurityManagerWhitelist(whitelist_default,
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           whitelist_delegate);
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return new URLSecurityManagerWin(whitelist_delegate);
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  //  namespace net
138