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::kHostAllowClientPairing[] =
    102     "RemoteAccessHostAllowClientPairing";
    103 
    104 const char PolicyWatcher::kHostDebugOverridePoliciesName[] =
    105     "RemoteAccessHostDebugOverridePolicies";
    106 
    107 PolicyWatcher::PolicyWatcher(
    108     scoped_refptr<base::SingleThreadTaskRunner> task_runner)
    109     : task_runner_(task_runner),
    110       old_policies_(new base::DictionaryValue()),
    111       default_values_(new base::DictionaryValue()),
    112       weak_factory_(this) {
    113   // Initialize the default values for each policy.
    114   default_values_->SetBoolean(kNatPolicyName, true);
    115   default_values_->SetBoolean(kHostRequireTwoFactorPolicyName, false);
    116   default_values_->SetBoolean(kHostRequireCurtainPolicyName, false);
    117   default_values_->SetBoolean(kHostMatchUsernamePolicyName, false);
    118   default_values_->SetString(kHostDomainPolicyName, std::string());
    119   default_values_->SetString(kHostTalkGadgetPrefixPolicyName,
    120                                kDefaultHostTalkGadgetPrefix);
    121   default_values_->SetString(kHostTokenUrlPolicyName, std::string());
    122   default_values_->SetString(kHostTokenValidationUrlPolicyName, std::string());
    123   default_values_->SetBoolean(kHostAllowClientPairing, true);
    124 #if !defined(NDEBUG)
    125   default_values_->SetString(kHostDebugOverridePoliciesName, std::string());
    126 #endif
    127 
    128   // Initialize the fall-back values to use for unreadable policies.
    129   // For most policies these match the defaults.
    130   bad_type_values_.reset(default_values_->DeepCopy());
    131   bad_type_values_->SetBoolean(kNatPolicyName, false);
    132 }
    133 
    134 PolicyWatcher::~PolicyWatcher() {
    135 }
    136 
    137 void PolicyWatcher::StartWatching(const PolicyCallback& policy_callback) {
    138   if (!OnPolicyWatcherThread()) {
    139     task_runner_->PostTask(FROM_HERE,
    140                            base::Bind(&PolicyWatcher::StartWatching,
    141                                       base::Unretained(this),
    142                                       policy_callback));
    143     return;
    144   }
    145 
    146   policy_callback_ = policy_callback;
    147   StartWatchingInternal();
    148 }
    149 
    150 void PolicyWatcher::StopWatching(base::WaitableEvent* done) {
    151   if (!OnPolicyWatcherThread()) {
    152     task_runner_->PostTask(FROM_HERE,
    153                            base::Bind(&PolicyWatcher::StopWatching,
    154                                       base::Unretained(this), done));
    155     return;
    156   }
    157 
    158   StopWatchingInternal();
    159   weak_factory_.InvalidateWeakPtrs();
    160   policy_callback_.Reset();
    161 
    162   done->Signal();
    163 }
    164 
    165 void PolicyWatcher::ScheduleFallbackReloadTask() {
    166   DCHECK(OnPolicyWatcherThread());
    167   ScheduleReloadTask(
    168       base::TimeDelta::FromMinutes(kFallbackReloadDelayMinutes));
    169 }
    170 
    171 void PolicyWatcher::ScheduleReloadTask(const base::TimeDelta& delay) {
    172   DCHECK(OnPolicyWatcherThread());
    173   task_runner_->PostDelayedTask(
    174       FROM_HERE,
    175       base::Bind(&PolicyWatcher::Reload, weak_factory_.GetWeakPtr()),
    176       delay);
    177 }
    178 
    179 const base::DictionaryValue& PolicyWatcher::Defaults() const {
    180   return *default_values_;
    181 }
    182 
    183 bool PolicyWatcher::OnPolicyWatcherThread() const {
    184   return task_runner_->BelongsToCurrentThread();
    185 }
    186 
    187 void PolicyWatcher::UpdatePolicies(
    188     const base::DictionaryValue* new_policies_raw) {
    189   DCHECK(OnPolicyWatcherThread());
    190 
    191   // Use default values for any missing policies.
    192   scoped_ptr<base::DictionaryValue> new_policies =
    193       CopyGoodValuesAndAddDefaults(
    194           new_policies_raw, default_values_.get(), bad_type_values_.get());
    195 
    196   // Find the changed policies.
    197   scoped_ptr<base::DictionaryValue> changed_policies(
    198       new base::DictionaryValue());
    199   base::DictionaryValue::Iterator iter(*new_policies);
    200   while (!iter.IsAtEnd()) {
    201     base::Value* old_policy;
    202     if (!(old_policies_->Get(iter.key(), &old_policy) &&
    203           old_policy->Equals(&iter.value()))) {
    204       changed_policies->Set(iter.key(), iter.value().DeepCopy());
    205     }
    206     iter.Advance();
    207   }
    208 
    209   // Save the new policies.
    210   old_policies_.swap(new_policies);
    211 
    212   // Notify our client of the changed policies.
    213   if (!changed_policies->empty()) {
    214     policy_callback_.Run(changed_policies.Pass());
    215   }
    216 }
    217 
    218 }  // namespace policy_hack
    219 }  // namespace remoting
    220