1 // Copyright 2015 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 "chrome/browser/chromeos/login/users/affiliation.h"
6 
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/command_line.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/browser_process_platform_part.h"
12 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
13 #include "chrome/browser/chromeos/policy/device_local_account.h"
14 #include "chrome/browser/chromeos/settings/device_settings_service.h"
15 #include "components/account_id/account_id.h"
16 #include "components/policy/core/common/policy_switches.h"
17 #include "components/policy/proto/device_management_backend.pb.h"
18 #include "google_apis/gaia/gaia_auth_util.h"
19 
20 namespace chromeos {
21 
22 namespace {
23 
GetDeviceDMTokenIfAffiliated(const AccountId & account_id,const std::vector<std::string> & user_affiliation_ids)24 std::string GetDeviceDMTokenIfAffiliated(
25     const AccountId& account_id,
26     const std::vector<std::string>& user_affiliation_ids) {
27   const AffiliationIDSet set_of_user_affiliation_ids(
28       user_affiliation_ids.begin(), user_affiliation_ids.end());
29   const policy::BrowserPolicyConnectorChromeOS* connector =
30       g_browser_process->platform_part()->browser_policy_connector_chromeos();
31   DCHECK(connector);
32   const bool is_affiliated = IsUserAffiliated(
33       set_of_user_affiliation_ids, connector->GetDeviceAffiliationIDs(),
34       account_id.GetUserEmail());
35   if (is_affiliated) {
36     const enterprise_management::PolicyData* policy_data =
37         DeviceSettingsService::Get()->policy_data();
38     CHECK(policy_data);
39     return policy_data->request_token();
40   }
41   return std::string();
42 }
43 
44 }  // namespace
45 
HaveCommonElement(const std::set<std::string> & set1,const std::set<std::string> & set2)46 bool HaveCommonElement(const std::set<std::string>& set1,
47                        const std::set<std::string>& set2) {
48   std::set<std::string>::const_iterator it1 = set1.begin();
49   std::set<std::string>::const_iterator it2 = set2.begin();
50 
51   while (it1 != set1.end() && it2 != set2.end()) {
52     if (*it1 == *it2)
53       return true;
54     if (*it1 < *it2) {
55       ++it1;
56     } else {
57       ++it2;
58     }
59   }
60   return false;
61 }
62 
IsUserAffiliated(const AffiliationIDSet & user_affiliation_ids,const AffiliationIDSet & device_affiliation_ids,const std::string & email)63 bool IsUserAffiliated(const AffiliationIDSet& user_affiliation_ids,
64                       const AffiliationIDSet& device_affiliation_ids,
65                       const std::string& email) {
66   // An empty username means incognito user in case of Chrome OS and no
67   // logged-in user in case of Chrome (SigninService). Many tests use nonsense
68   // email addresses (e.g. 'test') so treat those as non-enterprise users.
69   if (email.empty() || email.find('@') == std::string::npos) {
70     return false;
71   }
72 
73   if (policy::IsDeviceLocalAccountUser(email, NULL)) {
74     return true;
75   }
76 
77   // Not all test servers correctly support affiliation ids so far, so
78   // this is a work-around.
79   // TODO(antrim): remove this once all test servers support affiliation ids.
80   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
81   if (command_line->HasSwitch(policy::switches::kUserAlwaysAffiliated)) {
82     return true;
83   }
84 
85   if (!device_affiliation_ids.empty() && !user_affiliation_ids.empty()) {
86     return HaveCommonElement(user_affiliation_ids, device_affiliation_ids);
87   }
88 
89   return false;
90 }
91 
92 base::RepeatingCallback<std::string(const std::vector<std::string>&)>
GetDeviceDMTokenForUserPolicyGetter(const AccountId & account_id)93 GetDeviceDMTokenForUserPolicyGetter(const AccountId& account_id) {
94   return base::BindRepeating(&GetDeviceDMTokenIfAffiliated, account_id);
95 }
96 
97 }  // namespace chromeos
98