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