OLD | NEW |
| (Empty) |
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 #include "chrome/browser/policy/enterprise_install_attributes.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "base/file_util.h" | |
10 #include "base/logging.h" | |
11 #include "chrome/browser/chromeos/cros/cryptohome_library.h" | |
12 #include "chrome/browser/policy/proto/install_attributes.pb.h" | |
13 #include "google_apis/gaia/gaia_auth_util.h" | |
14 | |
15 namespace policy { | |
16 | |
17 namespace { | |
18 | |
19 // Translates DeviceMode constants to strings used in the lockbox. | |
20 std::string GetDeviceModeString(DeviceMode mode) { | |
21 switch (mode) { | |
22 case DEVICE_MODE_CONSUMER: | |
23 return EnterpriseInstallAttributes::kConsumerDeviceMode; | |
24 case DEVICE_MODE_ENTERPRISE: | |
25 return EnterpriseInstallAttributes::kEnterpiseDeviceMode; | |
26 case DEVICE_MODE_KIOSK: | |
27 return EnterpriseInstallAttributes::kKioskDeviceMode; | |
28 case DEVICE_MODE_PENDING: | |
29 case DEVICE_MODE_NOT_SET: | |
30 break; | |
31 } | |
32 NOTREACHED() << "Invalid device mode: " << mode; | |
33 return EnterpriseInstallAttributes::kUnknownDeviceMode; | |
34 } | |
35 | |
36 // Translates strings used in the lockbox to DeviceMode values. | |
37 DeviceMode GetDeviceModeFromString( | |
38 const std::string& mode) { | |
39 if (mode == EnterpriseInstallAttributes::kConsumerDeviceMode) | |
40 return DEVICE_MODE_CONSUMER; | |
41 else if (mode == EnterpriseInstallAttributes::kEnterpiseDeviceMode) | |
42 return DEVICE_MODE_ENTERPRISE; | |
43 else if (mode == EnterpriseInstallAttributes::kKioskDeviceMode) | |
44 return DEVICE_MODE_KIOSK; | |
45 NOTREACHED() << "Unknown device mode string: " << mode; | |
46 return DEVICE_MODE_NOT_SET; | |
47 } | |
48 | |
49 bool ReadMapKey(const std::map<std::string, std::string>& map, | |
50 const std::string& key, | |
51 std::string* value) { | |
52 std::map<std::string, std::string>::const_iterator entry = map.find(key); | |
53 if (entry == map.end()) | |
54 return false; | |
55 | |
56 *value = entry->second; | |
57 return true; | |
58 } | |
59 | |
60 } // namespace | |
61 | |
62 const char EnterpriseInstallAttributes::kConsumerDeviceMode[] = "consumer"; | |
63 const char EnterpriseInstallAttributes::kEnterpiseDeviceMode[] = "enterprise"; | |
64 const char EnterpriseInstallAttributes::kKioskDeviceMode[] = "kiosk"; | |
65 const char EnterpriseInstallAttributes::kUnknownDeviceMode[] = "unknown"; | |
66 | |
67 const char EnterpriseInstallAttributes::kAttrEnterpriseDeviceId[] = | |
68 "enterprise.device_id"; | |
69 const char EnterpriseInstallAttributes::kAttrEnterpriseDomain[] = | |
70 "enterprise.domain"; | |
71 const char EnterpriseInstallAttributes::kAttrEnterpriseMode[] = | |
72 "enterprise.mode"; | |
73 const char EnterpriseInstallAttributes::kAttrEnterpriseOwned[] = | |
74 "enterprise.owned"; | |
75 const char EnterpriseInstallAttributes::kAttrEnterpriseUser[] = | |
76 "enterprise.user"; | |
77 | |
78 EnterpriseInstallAttributes::EnterpriseInstallAttributes( | |
79 chromeos::CryptohomeLibrary* cryptohome) | |
80 : cryptohome_(cryptohome), | |
81 device_locked_(false), | |
82 registration_mode_(DEVICE_MODE_PENDING) {} | |
83 | |
84 void EnterpriseInstallAttributes::ReadCacheFile( | |
85 const base::FilePath& cache_file) { | |
86 if (device_locked_ || !file_util::PathExists(cache_file)) | |
87 return; | |
88 | |
89 device_locked_ = true; | |
90 | |
91 char buf[16384]; | |
92 int len = file_util::ReadFile(cache_file, buf, sizeof(buf)); | |
93 if (len == -1 || len >= static_cast<int>(sizeof(buf))) { | |
94 PLOG(ERROR) << "Failed to read " << cache_file.value(); | |
95 return; | |
96 } | |
97 | |
98 cryptohome::SerializedInstallAttributes install_attrs_proto; | |
99 if (!install_attrs_proto.ParseFromArray(buf, len)) { | |
100 LOG(ERROR) << "Failed to parse install attributes cache"; | |
101 return; | |
102 } | |
103 | |
104 google::protobuf::RepeatedPtrField< | |
105 const cryptohome::SerializedInstallAttributes::Attribute>::iterator entry; | |
106 std::map<std::string, std::string> attr_map; | |
107 for (entry = install_attrs_proto.attributes().begin(); | |
108 entry != install_attrs_proto.attributes().end(); | |
109 ++entry) { | |
110 // The protobuf values unfortunately contain terminating null characters, so | |
111 // we have to sanitize the value here. | |
112 attr_map.insert(std::make_pair(entry->name(), | |
113 std::string(entry->value().c_str()))); | |
114 } | |
115 | |
116 DecodeInstallAttributes(attr_map); | |
117 } | |
118 | |
119 void EnterpriseInstallAttributes::ReadImmutableAttributes() { | |
120 if (device_locked_) | |
121 return; | |
122 | |
123 if (cryptohome_ && cryptohome_->InstallAttributesIsReady()) { | |
124 registration_mode_ = DEVICE_MODE_NOT_SET; | |
125 if (!cryptohome_->InstallAttributesIsInvalid() && | |
126 !cryptohome_->InstallAttributesIsFirstInstall()) { | |
127 device_locked_ = true; | |
128 | |
129 static const char* kEnterpriseAttributes[] = { | |
130 kAttrEnterpriseDeviceId, | |
131 kAttrEnterpriseDomain, | |
132 kAttrEnterpriseMode, | |
133 kAttrEnterpriseOwned, | |
134 kAttrEnterpriseUser, | |
135 }; | |
136 std::map<std::string, std::string> attr_map; | |
137 for (size_t i = 0; i < arraysize(kEnterpriseAttributes); ++i) { | |
138 std::string value; | |
139 if (cryptohome_->InstallAttributesGet(kEnterpriseAttributes[i], &value)) | |
140 attr_map[kEnterpriseAttributes[i]] = value; | |
141 } | |
142 | |
143 DecodeInstallAttributes(attr_map); | |
144 } | |
145 } | |
146 } | |
147 | |
148 EnterpriseInstallAttributes::LockResult EnterpriseInstallAttributes::LockDevice( | |
149 const std::string& user, | |
150 DeviceMode device_mode, | |
151 const std::string& device_id) { | |
152 CHECK_NE(device_mode, DEVICE_MODE_PENDING); | |
153 CHECK_NE(device_mode, DEVICE_MODE_NOT_SET); | |
154 | |
155 std::string domain = gaia::ExtractDomainName(user); | |
156 | |
157 // Check for existing lock first. | |
158 if (device_locked_) { | |
159 return !registration_domain_.empty() && domain == registration_domain_ ? | |
160 LOCK_SUCCESS : LOCK_WRONG_USER; | |
161 } | |
162 | |
163 if (!cryptohome_ || !cryptohome_->InstallAttributesIsReady()) | |
164 return LOCK_NOT_READY; | |
165 | |
166 // Clearing the TPM password seems to be always a good deal. | |
167 if (cryptohome_->TpmIsEnabled() && | |
168 !cryptohome_->TpmIsBeingOwned() && | |
169 cryptohome_->TpmIsOwned()) { | |
170 cryptohome_->TpmClearStoredPassword(); | |
171 } | |
172 | |
173 // Make sure we really have a working InstallAttrs. | |
174 if (cryptohome_->InstallAttributesIsInvalid()) { | |
175 LOG(ERROR) << "Install attributes invalid."; | |
176 return LOCK_BACKEND_ERROR; | |
177 } | |
178 | |
179 if (!cryptohome_->InstallAttributesIsFirstInstall()) | |
180 return LOCK_WRONG_USER; | |
181 | |
182 std::string mode = GetDeviceModeString(device_mode); | |
183 | |
184 // Set values in the InstallAttrs and lock it. | |
185 if (!cryptohome_->InstallAttributesSet(kAttrEnterpriseOwned, "true") || | |
186 !cryptohome_->InstallAttributesSet(kAttrEnterpriseUser, user) || | |
187 !cryptohome_->InstallAttributesSet(kAttrEnterpriseDomain, domain) || | |
188 !cryptohome_->InstallAttributesSet(kAttrEnterpriseMode, mode) || | |
189 !cryptohome_->InstallAttributesSet(kAttrEnterpriseDeviceId, device_id)) { | |
190 LOG(ERROR) << "Failed writing attributes"; | |
191 return LOCK_BACKEND_ERROR; | |
192 } | |
193 | |
194 if (!cryptohome_->InstallAttributesFinalize() || | |
195 cryptohome_->InstallAttributesIsFirstInstall()) { | |
196 LOG(ERROR) << "Failed locking."; | |
197 return LOCK_BACKEND_ERROR; | |
198 } | |
199 | |
200 ReadImmutableAttributes(); | |
201 if (GetRegistrationUser() != user) { | |
202 LOG(ERROR) << "Locked data doesn't match"; | |
203 return LOCK_BACKEND_ERROR; | |
204 } | |
205 | |
206 return LOCK_SUCCESS; | |
207 } | |
208 | |
209 bool EnterpriseInstallAttributes::IsEnterpriseDevice() { | |
210 return device_locked_ && !registration_user_.empty(); | |
211 } | |
212 | |
213 std::string EnterpriseInstallAttributes::GetRegistrationUser() { | |
214 if (!device_locked_) | |
215 return std::string(); | |
216 | |
217 return registration_user_; | |
218 } | |
219 | |
220 std::string EnterpriseInstallAttributes::GetDomain() { | |
221 if (!IsEnterpriseDevice()) | |
222 return std::string(); | |
223 | |
224 return registration_domain_; | |
225 } | |
226 | |
227 std::string EnterpriseInstallAttributes::GetDeviceId() { | |
228 if (!IsEnterpriseDevice()) | |
229 return std::string(); | |
230 | |
231 return registration_device_id_; | |
232 } | |
233 | |
234 DeviceMode EnterpriseInstallAttributes::GetMode() { | |
235 return registration_mode_; | |
236 } | |
237 | |
238 void EnterpriseInstallAttributes::DecodeInstallAttributes( | |
239 const std::map<std::string, std::string>& attr_map) { | |
240 std::string enterprise_owned; | |
241 std::string enterprise_user; | |
242 if (ReadMapKey(attr_map, kAttrEnterpriseOwned, &enterprise_owned) && | |
243 ReadMapKey(attr_map, kAttrEnterpriseUser, &enterprise_user) && | |
244 enterprise_owned == "true" && | |
245 !enterprise_user.empty()) { | |
246 registration_user_ = gaia::CanonicalizeEmail(enterprise_user); | |
247 | |
248 // Initialize the mode to the legacy enterprise mode here and update | |
249 // below if more information is present. | |
250 registration_mode_ = DEVICE_MODE_ENTERPRISE; | |
251 | |
252 // If we could extract basic setting we should try to extract the | |
253 // extended ones too. We try to set these to defaults as good as | |
254 // as possible if present, which could happen for device enrolled in | |
255 // pre 19 revisions of the code, before these new attributes were added. | |
256 if (ReadMapKey(attr_map, kAttrEnterpriseDomain, ®istration_domain_)) | |
257 registration_domain_ = gaia::CanonicalizeDomain(registration_domain_); | |
258 else | |
259 registration_domain_ = gaia::ExtractDomainName(registration_user_); | |
260 | |
261 ReadMapKey(attr_map, kAttrEnterpriseDeviceId, ®istration_device_id_); | |
262 | |
263 std::string mode; | |
264 if (ReadMapKey(attr_map, kAttrEnterpriseMode, &mode)) | |
265 registration_mode_ = GetDeviceModeFromString(mode); | |
266 } else if (enterprise_user.empty() && enterprise_owned != "true") { | |
267 // |registration_user_| is empty on consumer devices. | |
268 registration_mode_ = DEVICE_MODE_CONSUMER; | |
269 } | |
270 } | |
271 | |
272 } // namespace policy | |
OLD | NEW |