15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/cloud/policy_header_service.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/base64.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/json/json_writer.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/values.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_store.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/cloud/policy_header_io_helper.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kUserDMTokenKey[] = "user_dmtoken";
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kUserPolicyTokenKey[] = "user_policy_token";
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kVerificationKeyHashKey[] = "verification_key_id";
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace policy {
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PolicyHeaderService::PolicyHeaderService(
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& server_url,
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& verification_key_hash,
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloudPolicyStore* user_policy_store,
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloudPolicyStore* device_policy_store)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : server_url_(server_url),
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      verification_key_hash_(verification_key_hash),
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      user_policy_store_(user_policy_store),
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_policy_store_(device_policy_store) {
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_policy_store_->AddObserver(this);
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (device_policy_store_)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    device_policy_store_->AddObserver(this);
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PolicyHeaderService::~PolicyHeaderService() {
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_policy_store_->RemoveObserver(this);
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (device_policy_store_)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    device_policy_store_->RemoveObserver(this);
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<PolicyHeaderIOHelper>
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PolicyHeaderService::CreatePolicyHeaderIOHelper(
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> task_runner) {
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string initial_header_value = CreateHeaderValue();
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<PolicyHeaderIOHelper> helper = make_scoped_ptr(
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new PolicyHeaderIOHelper(server_url_, initial_header_value, task_runner));
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helpers_.push_back(helper.get());
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return helper.Pass();
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string PolicyHeaderService::CreateHeaderValue() {
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If we have no user policy or no token, return an empty header.
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!user_policy_store_->has_policy() ||
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !user_policy_store_->policy()->has_request_token()) {
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return "";
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Generate a Base64-encoded header of the form:
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // {
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   user_dmtoken: <dm_token>
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   user_policy_token: <policy_token>
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   verification_key_hash: <key_hash>
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // }
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string user_dm_token = user_policy_store_->policy()->request_token();
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue value;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  value.SetString(kUserDMTokenKey, user_dm_token);
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (user_policy_store_->policy()->has_policy_token()) {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    value.SetString(kUserPolicyTokenKey,
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    user_policy_store_->policy()->policy_token());
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!verification_key_hash_.empty())
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    value.SetString(kVerificationKeyHashKey, verification_key_hash_);
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(atwilson): add user_policy_token once the server starts sending it
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // down (http://crbug.com/326799).
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string json;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::JSONWriter::Write(&value, &json);
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!json.empty());
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Base64-encode the result so we can include it in a header.
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string encoded;
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::Base64Encode(json, &encoded);
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return encoded;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PolicyHeaderService::OnStoreLoaded(CloudPolicyStore* store) {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If we have a PolicyHeaderIOHelper, notify it of the new header value.
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!helpers_.empty()) {
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string new_header = CreateHeaderValue();
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (std::vector<PolicyHeaderIOHelper*>::const_iterator it =
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             helpers_.begin(); it != helpers_.end(); ++it) {
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (*it)->UpdateHeader(new_header);
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PolicyHeaderService::OnStoreError(CloudPolicyStore* store) {
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Do nothing on errors.
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)std::vector<PolicyHeaderIOHelper*> PolicyHeaderService::GetHelpersForTest() {
10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return helpers_;
10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace policy
106