Home | History | Annotate | Download | only in policy_hack
      1 // Copyright (c) 2012 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 // Most of this code is copied from:
      6 //   src/chrome/browser/policy/asynchronous_policy_loader.{h,cc}
      7 
      8 #include "remoting/host/policy_hack/policy_watcher.h"
      9 
     10 #include "base/bind.h"
     11 #include "base/compiler_specific.h"
     12 #include "base/location.h"
     13 #include "base/memory/weak_ptr.h"
     14 #include "base/single_thread_task_runner.h"
     15 #include "base/synchronization/waitable_event.h"
     16 #include "base/time/time.h"
     17 #include "base/values.h"
     18 #include "remoting/host/dns_blackhole_checker.h"
     19 
     20 #if !defined(NDEBUG)
     21 #include "base/json/json_reader.h"
     22 #endif
     23 
     24 namespace remoting {
     25 namespace policy_hack {
     26 
     27 namespace {
     28 
     29 // The time interval for rechecking policy. This is our fallback in case the
     30 // delegate never reports a change to the ReloadObserver.
     31 const int kFallbackReloadDelayMinutes = 15;
     32 
     33 // Copies all policy values from one dictionary to another, using values from
     34 // |default| if they are not set in |from|, or values from |bad_type_values| if
     35 // the value in |from| has the wrong type.
     36 scoped_ptr<base::DictionaryValue> CopyGoodValuesAndAddDefaults(
     37     const base::DictionaryValue* from,
     38     const base::DictionaryValue* default_values,
     39     const base::DictionaryValue* bad_type_values) {
     40   scoped_ptr<base::DictionaryValue> to(default_values->DeepCopy());
     41   for (base::DictionaryValue::Iterator i(*default_values);
     42        !i.IsAtEnd(); i.Advance()) {
     43 
     44     const base::Value* value = NULL;
     45 
     46     // If the policy isn't in |from|, use the default.
     47     if (!from->Get(i.key(), &value)) {
     48       continue;
     49     }
     50 
     51     // If the policy is the wrong type, use the value from |bad_type_values|.
     52     if (!value->IsType(i.value().GetType())) {
     53       CHECK(bad_type_values->Get(i.key(), &value));
     54     }
     55 
     56     to->Set(i.key(), value->DeepCopy());
     57   }
     58 
     59 #if !defined(NDEBUG)
     60   // Replace values with those specified in DebugOverridePolicies, if present.
     61   std::string policy_overrides;
     62   if (from->GetString(PolicyWatcher::kHostDebugOverridePoliciesName,
     63                       &policy_overrides)) {
     64     scoped_ptr<base::Value> value(base::JSONReader::Read(policy_overrides));
     65     const base::DictionaryValue* override_values;
     66     if (value && value->GetAsDictionary(&override_values)) {
     67       to->MergeDictionary(override_values);
     68     }
     69   }
     70 #endif  // defined(NDEBUG)
     71 
     72   return to.Pass();
     73 }
     74 
     75 }  // namespace
     76 
     77 const char PolicyWatcher::kNatPolicyName[] =
     78     "RemoteAccessHostFirewallTraversal";
     79 
     80 const char PolicyWatcher::kHostRequireTwoFactorPolicyName[] =
     81     "RemoteAccessHostRequireTwoFactor";
     82 
     83 const char PolicyWatcher::kHostDomainPolicyName[] =
     84     "RemoteAccessHostDomain";
     85 
     86 const char PolicyWatcher::kHostMatchUsernamePolicyName[] =
     87     "RemoteAccessHostMatchUsername";
     88 
     89 const char PolicyWatcher::kHostTalkGadgetPrefixPolicyName[] =
     90     "RemoteAccessHostTalkGadgetPrefix";
     91 
     92 const char PolicyWatcher::kHostRequireCurtainPolicyName[] =
     93     "RemoteAccessHostRequireCurtain";
     94 
     95 const char PolicyWatcher::kHostTokenUrlPolicyName[] =
     96     "RemoteAccessHostTokenUrl";
     97 
     98 const char PolicyWatcher::kHostTokenValidationUrlPolicyName[] =
     99     "RemoteAccessHostTokenValidationUrl";
    100 
    101 const char PolicyWatcher::kHostTokenValidationCertIssuerPolicyName[] =
    102     "RemoteAccessHostTokenValidationCertificateIssuer";
    103 
    104 const char PolicyWatcher::kHostAllowClientPairing[] =
    105     "RemoteAccessHostAllowClientPairing";
    106 
    107 const char PolicyWatcher::kHostAllowGnubbyAuthPolicyName[] =
    108     "RemoteAccessHostAllowGnubbyAuth";
    109 
    110 const char PolicyWatcher::kRelayPolicyName[] =
    111     "RemoteAccessHostAllowRelayedConnection";
    112 
    113 const char PolicyWatcher::kUdpPortRangePolicyName[] =
    114     "RemoteAccessHostUdpPortRange";
    115 
    116 const char PolicyWatcher::kHostDebugOverridePoliciesName[] =
    117     "RemoteAccessHostDebugOverridePolicies";
    118 
    119 PolicyWatcher::PolicyWatcher(
    120     scoped_refptr<base::SingleThreadTaskRunner> task_runner)
    121     : task_runner_(task_runner),
    122       old_policies_(new base::DictionaryValue()),
    123       default_values_(new base::DictionaryValue()),
    124       weak_factory_(this) {
    125   // Initialize the default values for each policy.
    126   default_values_->SetBoolean(kNatPolicyName, true);
    127   default_values_->SetBoolean(kHostRequireTwoFactorPolicyName, false);
    128   default_values_->SetBoolean(kHostRequireCurtainPolicyName, false);
    129   default_values_->SetBoolean(kHostMatchUsernamePolicyName, false);
    130   default_values_->SetString(kHostDomainPolicyName, std::string());
    131   default_values_->SetString(kHostTalkGadgetPrefixPolicyName,
    132                                kDefaultHostTalkGadgetPrefix);
    133   default_values_->SetString(kHostTokenUrlPolicyName, std::string());
    134   default_values_->SetString(kHostTokenValidationUrlPolicyName, std::string());
    135   default_values_->SetString(kHostTokenValidationCertIssuerPolicyName,
    136                              std::string());
    137   default_values_->SetBoolean(kHostAllowClientPairing, true);
    138   default_values_->SetBoolean(kHostAllowGnubbyAuthPolicyName, true);
    139   default_values_->SetBoolean(kRelayPolicyName, true);
    140   default_values_->SetString(kUdpPortRangePolicyName, "");
    141 #if !defined(NDEBUG)
    142   default_values_->SetString(kHostDebugOverridePoliciesName, std::string());
    143 #endif
    144 
    145   // Initialize the fall-back values to use for unreadable policies.
    146   // For most policies these match the defaults.
    147   bad_type_values_.reset(default_values_->DeepCopy());
    148   bad_type_values_->SetBoolean(kNatPolicyName, false);
    149   bad_type_values_->SetBoolean(kRelayPolicyName, false);
    150 }
    151 
    152 PolicyWatcher::~PolicyWatcher() {
    153 }
    154 
    155 void PolicyWatcher::StartWatching(const PolicyCallback& policy_callback) {
    156   if (!OnPolicyWatcherThread()) {
    157     task_runner_->PostTask(FROM_HERE,
    158                            base::Bind(&PolicyWatcher::StartWatching,
    159                                       base::Unretained(this),
    160                                       policy_callback));
    161     return;
    162   }
    163 
    164   policy_callback_ = policy_callback;
    165   StartWatchingInternal();
    166 }
    167 
    168 void PolicyWatcher::StopWatching(base::WaitableEvent* done) {
    169   if (!OnPolicyWatcherThread()) {
    170     task_runner_->PostTask(FROM_HERE,
    171                            base::Bind(&PolicyWatcher::StopWatching,
    172                                       base::Unretained(this), done));
    173     return;
    174   }
    175 
    176   StopWatchingInternal();
    177   weak_factory_.InvalidateWeakPtrs();
    178   policy_callback_.Reset();
    179 
    180   done->Signal();
    181 }
    182 
    183 void PolicyWatcher::ScheduleFallbackReloadTask() {
    184   DCHECK(OnPolicyWatcherThread());
    185   ScheduleReloadTask(
    186       base::TimeDelta::FromMinutes(kFallbackReloadDelayMinutes));
    187 }
    188 
    189 void PolicyWatcher::ScheduleReloadTask(const base::TimeDelta& delay) {
    190   DCHECK(OnPolicyWatcherThread());
    191   task_runner_->PostDelayedTask(
    192       FROM_HERE,
    193       base::Bind(&PolicyWatcher::Reload, weak_factory_.GetWeakPtr()),
    194       delay);
    195 }
    196 
    197 const base::DictionaryValue& PolicyWatcher::Defaults() const {
    198   return *default_values_;
    199 }
    200 
    201 bool PolicyWatcher::OnPolicyWatcherThread() const {
    202   return task_runner_->BelongsToCurrentThread();
    203 }
    204 
    205 void PolicyWatcher::UpdatePolicies(
    206     const base::DictionaryValue* new_policies_raw) {
    207   DCHECK(OnPolicyWatcherThread());
    208 
    209   // Use default values for any missing policies.
    210   scoped_ptr<base::DictionaryValue> new_policies =
    211       CopyGoodValuesAndAddDefaults(
    212           new_policies_raw, default_values_.get(), bad_type_values_.get());
    213 
    214   // Find the changed policies.
    215   scoped_ptr<base::DictionaryValue> changed_policies(
    216       new base::DictionaryValue());
    217   base::DictionaryValue::Iterator iter(*new_policies);
    218   while (!iter.IsAtEnd()) {
    219     base::Value* old_policy;
    220     if (!(old_policies_->Get(iter.key(), &old_policy) &&
    221           old_policy->Equals(&iter.value()))) {
    222       changed_policies->Set(iter.key(), iter.value().DeepCopy());
    223     }
    224     iter.Advance();
    225   }
    226 
    227   // Save the new policies.
    228   old_policies_.swap(new_policies);
    229 
    230   // Notify our client of the changed policies.
    231   if (!changed_policies->empty()) {
    232     policy_callback_.Run(changed_policies.Pass());
    233   }
    234 }
    235 
    236 }  // namespace policy_hack
    237 }  // namespace remoting
    238