Home | History | Annotate | Download | only in http
      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 
      5 #include "net/http/url_security_manager.h"
      6 
      7 #include <urlmon.h>
      8 #pragma comment(lib, "urlmon.lib")
      9 
     10 #include "base/strings/string_util.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "base/win/scoped_comptr.h"
     13 #include "net/http/http_auth_filter.h"
     14 #include "url/gurl.h"
     15 
     16 // The Windows implementation of URLSecurityManager uses WinINet/IE's
     17 // URL security zone manager.  See the MSDN page "URL Security Zones" at
     18 // http://msdn.microsoft.com/en-us/library/ms537021(VS.85).aspx for more
     19 // info on the Internet Security Manager and Internet Zone Manager objects.
     20 //
     21 // On Windows, we honor the WinINet/IE settings and group policy related to
     22 // URL Security Zones.  See the Microsoft Knowledge Base article 182569
     23 // "Internet Explorer security zones registry entries for advanced users"
     24 // (http://support.microsoft.com/kb/182569) for more info on these registry
     25 // keys.
     26 
     27 namespace net {
     28 
     29 class URLSecurityManagerWin : public URLSecurityManager {
     30  public:
     31   explicit URLSecurityManagerWin(const HttpAuthFilter* whitelist_delegate);
     32 
     33   // URLSecurityManager methods:
     34   virtual bool CanUseDefaultCredentials(const GURL& auth_origin) const;
     35   virtual bool CanDelegate(const GURL& auth_origin) const;
     36 
     37  private:
     38   bool EnsureSystemSecurityManager();
     39 
     40   base::win::ScopedComPtr<IInternetSecurityManager> security_manager_;
     41   scoped_ptr<const HttpAuthFilter> whitelist_delegate_;
     42 
     43   DISALLOW_COPY_AND_ASSIGN(URLSecurityManagerWin);
     44 };
     45 
     46 URLSecurityManagerWin::URLSecurityManagerWin(
     47     const HttpAuthFilter* whitelist_delegate)
     48     : whitelist_delegate_(whitelist_delegate) {
     49 }
     50 
     51 bool URLSecurityManagerWin::CanUseDefaultCredentials(
     52     const GURL& auth_origin) const {
     53   if (!const_cast<URLSecurityManagerWin*>(this)->EnsureSystemSecurityManager())
     54     return false;
     55 
     56   std::wstring url_w = ASCIIToWide(auth_origin.spec());
     57   DWORD policy = 0;
     58   HRESULT hr;
     59   hr = security_manager_->ProcessUrlAction(url_w.c_str(),
     60                                            URLACTION_CREDENTIALS_USE,
     61                                            reinterpret_cast<BYTE*>(&policy),
     62                                            sizeof(policy), NULL, 0,
     63                                            PUAF_NOUI, 0);
     64   if (FAILED(hr)) {
     65     LOG(ERROR) << "IInternetSecurityManager::ProcessUrlAction failed: " << hr;
     66     return false;
     67   }
     68 
     69   // Four possible policies for URLACTION_CREDENTIALS_USE.  See the MSDN page
     70   // "About URL Security Zones" at
     71   // http://msdn.microsoft.com/en-us/library/ms537183(VS.85).aspx
     72   switch (policy) {
     73     case URLPOLICY_CREDENTIALS_SILENT_LOGON_OK:
     74       return true;
     75     case URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT: {
     76       // This policy means "prompt the user for permission if the resource is
     77       // not located in the Intranet zone".  TODO(wtc): Note that it's
     78       // prompting for permission (to use the default credentials), as opposed
     79       // to prompting the user to enter a user name and password.
     80 
     81       // URLZONE_LOCAL_MACHINE 0
     82       // URLZONE_INTRANET      1
     83       // URLZONE_TRUSTED       2
     84       // URLZONE_INTERNET      3
     85       // URLZONE_UNTRUSTED     4
     86       DWORD zone = 0;
     87       hr = security_manager_->MapUrlToZone(url_w.c_str(), &zone, 0);
     88       if (FAILED(hr)) {
     89         LOG(ERROR) << "IInternetSecurityManager::MapUrlToZone failed: " << hr;
     90         return false;
     91       }
     92       return zone <= URLZONE_INTRANET;
     93     }
     94     case URLPOLICY_CREDENTIALS_MUST_PROMPT_USER:
     95       return false;
     96     case URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY:
     97       // TODO(wtc): we should fail the authentication.
     98       return false;
     99     default:
    100       NOTREACHED();
    101       return false;
    102   }
    103 }
    104 
    105 bool URLSecurityManagerWin::CanDelegate(const GURL& auth_origin) const {
    106   // TODO(cbentzel): Could this just use the security zone as well? Apparently
    107   //                 this is what IE does as well.
    108   if (whitelist_delegate_.get())
    109     return whitelist_delegate_->IsValid(auth_origin, HttpAuth::AUTH_SERVER);
    110   return false;
    111 }
    112 
    113 bool URLSecurityManagerWin::EnsureSystemSecurityManager() {
    114   if (!security_manager_) {
    115     HRESULT hr = CoInternetCreateSecurityManager(NULL,
    116                                                  security_manager_.Receive(),
    117                                                  NULL);
    118     if (FAILED(hr) || !security_manager_) {
    119       LOG(ERROR) << "Unable to create the Windows Security Manager instance";
    120       return false;
    121     }
    122   }
    123   return true;
    124 }
    125 
    126 // static
    127 URLSecurityManager* URLSecurityManager::Create(
    128     const HttpAuthFilter* whitelist_default,
    129     const HttpAuthFilter* whitelist_delegate) {
    130   // If we have a whitelist, just use that.
    131   if (whitelist_default)
    132     return new URLSecurityManagerWhitelist(whitelist_default,
    133                                            whitelist_delegate);
    134   return new URLSecurityManagerWin(whitelist_delegate);
    135 }
    136 
    137 }  //  namespace net
    138