10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 20529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 30529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// found in the LICENSE file. 40529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/installer/util/advanced_firewall_manager_win.h" 60529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/guid.h" 80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/logging.h" 90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/strings/stringprintf.h" 100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/strings/utf_string_conversions.h" 110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/win/scoped_bstr.h" 120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/win/scoped_variant.h" 130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace installer { 150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 160529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochAdvancedFirewallManager::AdvancedFirewallManager() {} 170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 180529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochAdvancedFirewallManager::~AdvancedFirewallManager() {} 190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool AdvancedFirewallManager::Init(const base::string16& app_name, 210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const base::FilePath& app_path) { 220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch firewall_rules_ = NULL; 230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch HRESULT hr = firewall_policy_.CreateInstance(CLSID_NetFwPolicy2); 240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (FAILED(hr)) { 250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG(ERROR) << logging::SystemErrorCodeToString(hr); 260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch firewall_policy_ = NULL; 270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch hr = firewall_policy_->get_Rules(firewall_rules_.Receive()); 300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (FAILED(hr)) { 310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG(ERROR) << logging::SystemErrorCodeToString(hr); 320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch firewall_rules_ = NULL; 330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch app_name_ = app_name; 360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch app_path_ = app_path; 370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return true; 380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool AdvancedFirewallManager::IsFirewallEnabled() { 410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch long profile_types = 0; 420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch HRESULT hr = firewall_policy_->get_CurrentProfileTypes(&profile_types); 430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (FAILED(hr)) 440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The most-restrictive active profile takes precedence. 460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const NET_FW_PROFILE_TYPE2 kProfileTypes[] = { 470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NET_FW_PROFILE2_PUBLIC, 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NET_FW_PROFILE2_PRIVATE, 490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NET_FW_PROFILE2_DOMAIN 500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch }; 510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (size_t i = 0; i < arraysize(kProfileTypes); ++i) { 520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if ((profile_types & kProfileTypes[i]) != 0) { 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch VARIANT_BOOL enabled = VARIANT_TRUE; 540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch hr = firewall_policy_->get_FirewallEnabled(kProfileTypes[i], &enabled); 550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Assume the firewall is enabled if we can't determine. 560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (FAILED(hr) || enabled != VARIANT_FALSE) 570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return true; 580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool AdvancedFirewallManager::HasAnyRule() { 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<base::win::ScopedComPtr<INetFwRule> > rules; 650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch GetAllRules(&rules); 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return !rules.empty(); 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool AdvancedFirewallManager::AddUDPRule(const base::string16& rule_name, 700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const base::string16& description, 710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch uint16_t port) { 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Delete the rule. According MDSN |INetFwRules::Add| should replace rule with 730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // same "rule identifier". It's not clear what is "rule identifier", but it 740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // can successfully create many rule with same name. 750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DeleteRuleByName(rule_name); 760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create the rule and add it to the rule set (only succeeds if elevated). 780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedComPtr<INetFwRule> udp_rule = 790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CreateUDPRule(rule_name, description, port); 800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!udp_rule.get()) 810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch HRESULT hr = firewall_rules_->Add(udp_rule); 840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG_IF(ERROR, FAILED(hr)) << logging::SystemErrorCodeToString(hr); 850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return SUCCEEDED(hr); 860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid AdvancedFirewallManager::DeleteRuleByName( 890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const base::string16& rule_name) { 900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<base::win::ScopedComPtr<INetFwRule> > rules; 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch GetAllRules(&rules); 920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (size_t i = 0; i < rules.size(); ++i) { 930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedBstr name; 940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch HRESULT hr = rules[i]->get_Name(name.Receive()); 950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (SUCCEEDED(hr) && name && base::string16(name) == rule_name) { 960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DeleteRule(rules[i]); 970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid AdvancedFirewallManager::DeleteRule( 1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedComPtr<INetFwRule> rule) { 1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Rename rule to unique name and delete by unique name. We can't just delete 1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // rule by name. Multiple rules with the same name and different app are 1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // possible. 1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedBstr unique_name( 1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::UTF8ToUTF16(base::GenerateGUID()).c_str()); 1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch rule->put_Name(unique_name); 1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch firewall_rules_->Remove(unique_name); 1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid AdvancedFirewallManager::DeleteAllRules() { 1130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<base::win::ScopedComPtr<INetFwRule> > rules; 1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch GetAllRules(&rules); 1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (size_t i = 0; i < rules.size(); ++i) { 1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DeleteRule(rules[i]); 1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbase::win::ScopedComPtr<INetFwRule> AdvancedFirewallManager::CreateUDPRule( 1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const base::string16& rule_name, 1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const base::string16& description, 1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch uint16_t port) { 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedComPtr<INetFwRule> udp_rule; 1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch HRESULT hr = udp_rule.CreateInstance(CLSID_NetFwRule); 1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (FAILED(hr)) { 1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG(ERROR) << logging::SystemErrorCodeToString(hr); 1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return base::win::ScopedComPtr<INetFwRule>(); 1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_Name(base::win::ScopedBstr(rule_name.c_str())); 1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_Description(base::win::ScopedBstr(description.c_str())); 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_ApplicationName( 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedBstr(app_path_.value().c_str())); 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_Protocol(NET_FW_IP_PROTOCOL_UDP); 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_Direction(NET_FW_RULE_DIR_IN); 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_Enabled(VARIANT_TRUE); 1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_LocalPorts( 1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedBstr(base::StringPrintf(L"%u", port).c_str())); 1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_Grouping(base::win::ScopedBstr(app_name_.c_str())); 1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_Profiles(NET_FW_PROFILE2_ALL); 1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch udp_rule->put_Action(NET_FW_ACTION_ALLOW); 1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return udp_rule; 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid AdvancedFirewallManager::GetAllRules( 1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<base::win::ScopedComPtr<INetFwRule> >* rules) { 1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedComPtr<IUnknown> rules_enum_unknown; 1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch HRESULT hr = firewall_rules_->get__NewEnum(rules_enum_unknown.Receive()); 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (FAILED(hr)) { 1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG(ERROR) << logging::SystemErrorCodeToString(hr); 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedComPtr<IEnumVARIANT> rules_enum; 1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch hr = rules_enum.QueryFrom(rules_enum_unknown); 1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (FAILED(hr)) { 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG(ERROR) << logging::SystemErrorCodeToString(hr); 1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (;;) { 1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedVariant rule_var; 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch hr = rules_enum->Next(1, rule_var.Receive(), NULL); 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG_IF(ERROR, FAILED(hr)) << logging::SystemErrorCodeToString(hr); 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (hr != S_OK) 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_EQ(VT_DISPATCH, rule_var.type()); 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (VT_DISPATCH != rule_var.type()) { 1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG(ERROR) << "Unexpected type"; 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch continue; 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedComPtr<INetFwRule> rule; 1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch hr = rule.QueryFrom(V_DISPATCH(&rule_var)); 1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (FAILED(hr)) { 1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG(ERROR) << logging::SystemErrorCodeToString(hr); 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch continue; 1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::win::ScopedBstr path; 1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch hr = rule->get_ApplicationName(path.Receive()); 1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (FAILED(hr)) { 1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DLOG(ERROR) << logging::SystemErrorCodeToString(hr); 1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch continue; 1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!path || 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch !base::FilePath::CompareEqualIgnoreCase(static_cast<BSTR>(path), 1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch app_path_.value())) { 1920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch continue; 1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch rules->push_back(rule); 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} // namespace installer 200