Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc

Issue 2367363002: Update Public Session permissions (manifest features part) (Closed)
Patch Set: Fixed failing tests Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/extensions/device_local_account_management_pol icy_provider.h" 5 #include "chrome/browser/chromeos/extensions/device_local_account_management_pol icy_provider.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <cstddef> 9 #include <cstddef>
10 #include <string> 10 #include <string>
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 // Testing extensions: 117 // Testing extensions:
118 "ongnjlefhnoajpbodoldndkbkdgfomlp", // Show Managed Storage 118 "ongnjlefhnoajpbodoldndkbkdgfomlp", // Show Managed Storage
119 "ilnpadgckeacioehlommkaafedibdeob", // Enterprise DeviceAttributes 119 "ilnpadgckeacioehlommkaafedibdeob", // Enterprise DeviceAttributes
120 "oflckobdemeldmjddmlbaiaookhhcngo", // Citrix Receiver QA version 120 "oflckobdemeldmjddmlbaiaookhhcngo", // Citrix Receiver QA version
121 "ljacajndfccfgnfohlgkdphmbnpkjflk", // Chrome Remote Desktop (Dev Build) 121 "ljacajndfccfgnfohlgkdphmbnpkjflk", // Chrome Remote Desktop (Dev Build)
122 }; 122 };
123 123
124 // List of manifest entries from https://developer.chrome.com/apps/manifest. 124 // List of manifest entries from https://developer.chrome.com/apps/manifest.
125 // Unsafe entries are commented out and special cases too. 125 // Unsafe entries are commented out and special cases too.
126 const char* const kSafeManifestEntries[] = { 126 const char* const kSafeManifestEntries[] = {
127 // Special-cased in IsPlatformAppSafeForPublicSession(). 127 emk::kAboutPage,
128
129 // Special-cased in IsSafeForPublicSession().
128 // emk::kApp, 130 // emk::kApp,
129 131
130 // Documented in https://developer.chrome.com/extensions/manifest but not 132 // Documented in https://developer.chrome.com/extensions/manifest but not
131 // implemented anywhere. Still, a lot of apps use it. 133 // implemented anywhere. Still, a lot of apps use it.
132 "author", 134 "author",
133 135
134 // TBD 136 // Allows inspection of page contents, not enabled on stable anyways except
135 // emk::kBluetooth, 137 // for whitelist.
138 // emk::kAutomation,
136 139
137 // TBD 140 // TODO(isandrk): Ask Mattias for comments on entries without a comment.
Andrew T Wilson (Slow) 2016/09/27 15:15:07 Please file a bug for this and put the bug number
Ivan Šandrk 2016/09/27 15:28:19 Done.
138 // emk::kCommands, 141 "background",
142
143 emk::kBackgroundPageLegacy,
144
145 emk::kBackgroundPersistent,
146
147 emk::kBluetooth,
148
149 emk::kBrowserAction,
150
151 // Allows to replace the search provider which is somewhat risky - need to
152 // double check how the search provider policy behaves in PS.
153 // emk::kSettingsOverride,
154
155 // Custom bookmark managers - I think this is fair game, bookmarks should be
156 // URLs only, and it's restricted to whitelist on stable.
157 emk::kUIOverride,
158
159 // Bookmark manager, history, new tab - should be safe.
160 emk::kChromeURLOverrides,
161
162 // General risk of capturing user input, but key combos must include Ctrl or
163 // Alt, so I think this is safe.
164 emk::kCommands,
165
166 // General risk of capturing user input, but key combos must include Ctrl or
167 // Alt, so I think this is safe.
168 emk::kContentCapabilities,
169
170 // Access to web content.
171 // emk::kContentScripts,
172
173 emk::kContentSecurityPolicy,
174
175 // Access to web content.
176 // emk::kConvertedFromUserScript,
139 177
140 // An implementation detail (actually written by Chrome, not the app 178 // An implementation detail (actually written by Chrome, not the app
141 // author). 179 // author).
142 emk::kCurrentLocale, 180 emk::kCurrentLocale,
143 181
144 // Name of directory containg default strings. 182 // Name of directory containg default strings.
145 emk::kDefaultLocale, 183 emk::kDefaultLocale,
146 184
147 // Just a display string. 185 // Just a display string.
148 emk::kDescription, 186 emk::kDescription,
149 187
150 // TBD, looks unsafe 188 // Access to web content.
189 // emk::kDevToolsPage,
190
191 // Restricted to whitelist already.
192 emk::kDisplayInLauncher,
193
194 emk::kDisplayInNewTabPage,
195
196 // This allows to declaratively filter web requests and content, matching on
197 // content data. Doesn't allow direct access to request/content data. Can be
198 // used to brute-force e.g. cookies (reload with filter rules adjusted to
199 // match all possible cookie values) - but that's equivalent to an
200 // off-device brute-force attack.
201 // Looks safe in general with one exception: There's an action that allows
202 // to insert content scripts on matching content. We can't allow this, need
203 // to check whether there's also a host permission required for this case.
151 // emk::kEventRules, 204 // emk::kEventRules,
152 205
153 // Shared Modules configuration: Allow other extensions to access resources. 206 // Shared Modules configuration: Allow other extensions to access resources.
154 emk::kExport, 207 emk::kExport,
155 208
156 // TBD 209 emk::kExternallyConnectable,
157 // emk::kExternallyConnectable,
158 210
159 // TBD 211 emk::kFileBrowserHandlers,
160 // emk::kFileHandlers,
161 212
162 // TBD 213 // Extension file handlers are restricted to whitelist which only contains
163 // emk::kFileSystemProviderCapabilities, 214 // quickoffice.
215 emk::kFileHandlers,
216
217 emk::kFileSystemProviderCapabilities,
218
219 emk::kHomepageURL,
164 220
165 // Just UX. 221 // Just UX.
166 emk::kIcons, 222 emk::kIcons,
167 223
168 // Shared Modules configuration: Import resources from another extension. 224 // Shared Modules configuration: Import resources from another extension.
169 emk::kImport, 225 emk::kImport,
170 226
227 emk::kIncognito,
228
229 // Keylogging.
230 // emk::kInputComponents,
231
171 // Shared Modules configuration: Specify extension id for development. 232 // Shared Modules configuration: Specify extension id for development.
172 emk::kKey, 233 emk::kKey,
173 234
174 // Descriptive statement about the app. 235 emk::kKiosk,
236
175 emk::kKioskEnabled, 237 emk::kKioskEnabled,
176 238
177 // Contradicts the purpose of running inside a Public Session. 239 // Not useful since it will prevent app from running, but we don't care.
178 // emk::kKioskOnly, 240 emk::kKioskOnly,
179 241
180 // Special-cased in IsPlatformAppSafeForPublicSession(). 242 emk::kKioskRequiredPlatformVersion,
243
244 // Not useful since it will prevent app from running, but we don't care.
245 emk::kKioskSecondaryApps,
246
247 // Whitelisted to only allow Google Now.
248 emk::kLauncherPage,
249
250 // Special-cased in IsSafeForPublicSession().
181 // emk::kManifestVersion, 251 // emk::kManifestVersion,
182 252
183 // Descriptive statement about the app. 253 emk::kMIMETypes,
254
255 // Whitelisted to only allow browser tests and PDF viewer.
256 emk::kMimeTypesHandler,
257
184 emk::kMinimumChromeVersion, 258 emk::kMinimumChromeVersion,
185 259
186 // NaCl modules are bound to app permissions just like the rest of the app 260 // NaCl modules are bound to app permissions just like the rest of the app
187 // and thus should not pose a risk. 261 // and thus should not pose a risk.
188 emk::kNaClModules, 262 emk::kNaClModules,
189 263
190 // Just a display string. 264 // Just a display string.
191 emk::kName, 265 emk::kName,
192 266
193 // TBD, doc missing 267 // Used in conjunction with the identity API - not really used when there's
194 // emk::kOAuth2, 268 // no GAIA user signed in.
269 emk::kOAuth2,
195 270
196 // Descriptive statement about the app. 271 // Generally safe (i.e. only whitelist apps), except for the policy to
272 // whitelist apps for auto-approved token minting (we should just ignore
273 // this in public sessions). Risk is that admin mints OAuth tokens to access
274 // services on behalf of the user silently.
275 // emk::kOAuth2AutoApprove,
276
197 emk::kOfflineEnabled, 277 emk::kOfflineEnabled,
198 278
199 // Special-cased in IsPlatformAppSafeForPublicSession(). 279 // A bit risky as the extensions sees all keystrokes entered into the
280 // omnibox after the search key matches, but generally we deem URLs fair
281 // game.
282 emk::kOmnibox,
283
284 // Special-cased in IsSafeForPublicSession(). Subject to permission
285 // restrictions.
200 // emk::kOptionalPermissions, 286 // emk::kOptionalPermissions,
201 287
202 // Special-cased in IsPlatformAppSafeForPublicSession(). 288 emk::kOptionsPage,
289
290 emk::kOptionsUI,
291
292 emk::kPageAction,
293
294 // Special-cased in IsSafeForPublicSession(). Subject to permission
295 // restrictions.
203 // emk::kPermissions, 296 // emk::kPermissions,
204 297
205 // No constant in manifest_constants.cc. 298 // No constant in manifest_constants.cc. Declared as a feature, but unused.
206 // "platforms", 299 // "platforms",
207 300
208 // Descriptive statement about the app. 301 // N/A on Chrome OS, so we don't care.
302 emk::kPlugins,
303
304 // Stated 3D/WebGL/plugin requirements of an app.
209 emk::kRequirements, 305 emk::kRequirements,
210 306
211 // Execute some pages in a separate sandbox. (Note: Using string literal 307 // Execute some pages in a separate sandbox. (Note: Using string literal
212 // since extensions::manifest_keys only has constants for sub-keys.) 308 // since extensions::manifest_keys only has constants for sub-keys.)
213 "sandbox", 309 "sandbox",
214 310
215 // Just a display string. 311 // Just a display string.
216 emk::kShortName, 312 emk::kShortName,
217 313
218 // TBD, doc missing 314 // Doc missing. Declared as a feature, but unused.
219 // emk::kSignature, 315 // emk::kSignature,
220 316
221 // Network access. 317 // Network access.
222 emk::kSockets, 318 emk::kSockets,
223 319
224 // TBD. (Note: Using string literal since extensions::manifest_keys only 320 // Just provides dictionaries, no access to content.
225 // has constants for sub-keys.) 321 emk::kSpellcheck,
226 // "storage",
227 322
228 // TBD, doc missing 323 // (Note: Using string literal since extensions::manifest_keys only has
229 // emk::kSystemIndicator, 324 // constants for sub-keys.)
325 "storage",
326
327 // Only Hangouts is whitelisted.
328 emk::kSystemIndicator,
329
330 emk::kTheme,
331
332 // Might need this for accessibilty, but has content access. Manual
333 // whitelisting might be reasonable here?
334 // emk::kTtsEngine,
230 335
231 // TODO(tnagel): Ensure that extension updates query UserMayLoad(). 336 // TODO(tnagel): Ensure that extension updates query UserMayLoad().
232 // https://crbug.com/549720 337 // https://crbug.com/549720
233 emk::kUpdateURL, 338 emk::kUpdateURL,
234 339
235 // Apps may intercept navigations to URL patterns for domains for which the 340 // Apps may intercept navigations to URL patterns for domains for which the
236 // app author has proven ownership of to the Web Store. (Chrome starts the 341 // app author has proven ownership of to the Web Store. (Chrome starts the
237 // app instead of fulfilling the navigation.) This is only safe for apps 342 // app instead of fulfilling the navigation.) This is only safe for apps
238 // that have been loaded from the Web Store and thus is special-cased in 343 // that have been loaded from the Web Store and thus is special-cased in
239 // IsPlatformAppSafeForPublicSession(). 344 // IsSafeForPublicSession().
240 // emk::kUrlHandlers, 345 // emk::kUrlHandlers,
241 346
242 // TBD 347 emk::kUsbPrinters,
243 // emk::kUsbPrinters,
244 348
245 // Version string (for app updates). 349 // Version string (for app updates).
246 emk::kVersion, 350 emk::kVersion,
247 351
248 // Just a display string. 352 // Just a display string.
249 emk::kVersionName, 353 emk::kVersionName,
250 354
355 emk::kWebAccessibleResources,
356
251 // Webview has no special privileges or capabilities. 357 // Webview has no special privileges or capabilities.
252 emk::kWebview, 358 emk::kWebview,
253 }; 359 };
254 360
255 // List of permission strings based on [1] and [2]. See |kSafePermissionDicts| 361 // List of permission strings based on [1] and [2]. See |kSafePermissionDicts|
256 // for permission dicts. Since Public Session users may be fully unaware of any 362 // for permission dicts. Since Public Session users may be fully unaware of any
257 // apps being installed, their consent to access any kind of sensitive 363 // apps being installed, their consent to access any kind of sensitive
258 // information cannot be assumed. Therefore only APIs are whitelisted which 364 // information cannot be assumed. Therefore only APIs are whitelisted which
259 // should not leak sensitive data to the caller. Since the privacy boundary is 365 // should not leak sensitive data to the caller. Since the privacy boundary is
260 // drawn at the API level, no safeguards are required to prevent exfiltration 366 // drawn at the API level, no safeguards are required to prevent exfiltration
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 // Some permissions take the form of a dictionary. See |kSafePermissionStrings| 504 // Some permissions take the form of a dictionary. See |kSafePermissionStrings|
399 // for permission strings (and for more documentation). 505 // for permission strings (and for more documentation).
400 const char* const kSafePermissionDicts[] = { 506 const char* const kSafePermissionDicts[] = {
401 // TBD 507 // TBD
402 // "fileSystem", 508 // "fileSystem",
403 509
404 // Just another type of connectivity. 510 // Just another type of connectivity.
405 "socket", 511 "socket",
406 }; 512 };
407 513
514 // List of safe entries for the "app" dict in manifest.
515 const char* const kSafeAppStrings[] = {
516 "background",
517 "content_security_policy",
518 "icon_color",
519 "isolation",
520 "launch",
521 "linked_icons",
522 };
523
408 // Return true iff |entry| is contained in |char_array|. 524 // Return true iff |entry| is contained in |char_array|.
409 bool ArrayContainsImpl(const char* const char_array[], 525 bool ArrayContainsImpl(const char* const char_array[],
410 size_t entry_count, 526 size_t entry_count,
411 const std::string& entry) { 527 const std::string& entry) {
412 for (size_t i = 0; i < entry_count; ++i) { 528 for (size_t i = 0; i < entry_count; ++i) {
413 if (entry == char_array[i]) { 529 if (entry == char_array[i]) {
414 return true; 530 return true;
415 } 531 }
416 } 532 }
417 return false; 533 return false;
418 } 534 }
419 535
420 // See http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx for an 536 // See http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx for an
421 // explanation of array size determination. 537 // explanation of array size determination.
422 template <size_t N> 538 template <size_t N>
423 bool ArrayContains(const char* const (&char_array)[N], 539 bool ArrayContains(const char* const (&char_array)[N],
424 const std::string& entry) { 540 const std::string& entry) {
425 return ArrayContainsImpl(char_array, N, entry); 541 return ArrayContainsImpl(char_array, N, entry);
426 } 542 }
427 543
428 // Returns true for platform apps that are considered safe for Public Sessions, 544 // Returns true for extensions that are considered safe for Public Sessions,
429 // which among other things requires the manifest top-level entries to be 545 // which among other things requires the manifest top-level entries to be
430 // contained in the |kSafeManifestEntries| whitelist and all permissions to be 546 // contained in the |kSafeManifestEntries| whitelist and all permissions to be
431 // contained in |kSafePermissionStrings| or |kSafePermissionDicts|. Otherwise 547 // contained in |kSafePermissionStrings| or |kSafePermissionDicts|. Otherwise
432 // returns false and logs all reasons for failure. 548 // returns false and logs all reasons for failure.
433 bool IsPlatformAppSafeForPublicSession(const extensions::Extension* extension) { 549 bool IsSafeForPublicSession(const extensions::Extension* extension) {
434 bool safe = true; 550 bool safe = true;
435 if (extension->GetType() != extensions::Manifest::TYPE_PLATFORM_APP) { 551 if (!extension->is_extension() &&
436 LOG(ERROR) << extension->id() << " is not a platform app."; 552 !extension->is_hosted_app() &&
553 !extension->is_platform_app() &&
554 !extension->is_shared_module() &&
555 !extension->is_theme()) {
556 LOG(ERROR) << extension->id()
557 << " is not of a supported type. Extension type: "
558 << extension->GetType();
437 safe = false; 559 safe = false;
438 } 560 }
439 561
440 for (base::DictionaryValue::Iterator it(*extension->manifest()->value()); 562 for (base::DictionaryValue::Iterator it(*extension->manifest()->value());
441 !it.IsAtEnd(); it.Advance()) { 563 !it.IsAtEnd(); it.Advance()) {
442 if (ArrayContains(kSafeManifestEntries, it.key())) { 564 if (ArrayContains(kSafeManifestEntries, it.key())) {
443 continue; 565 continue;
444 } 566 }
445 567
446 // Permissions must be whitelisted in |kSafePermissionStrings| or 568 // Permissions must be whitelisted in |kSafePermissionStrings| or
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 base::CompareCase::SENSITIVE) || 618 base::CompareCase::SENSITIVE) ||
497 base::StartsWith(permission_string, "ftp://", 619 base::StartsWith(permission_string, "ftp://",
498 base::CompareCase::SENSITIVE)) { 620 base::CompareCase::SENSITIVE)) {
499 continue; 621 continue;
500 } 622 }
501 LOG(ERROR) << extension->id() 623 LOG(ERROR) << extension->id()
502 << " requested non-whitelisted permission: " 624 << " requested non-whitelisted permission: "
503 << permission_string; 625 << permission_string;
504 safe = false; 626 safe = false;
505 } 627 }
506 // "app" may only contain "background".
507 } else if (it.key() == emk::kApp) { 628 } else if (it.key() == emk::kApp) {
629 if (!extension->is_hosted_app() &&
630 !extension->is_platform_app()) {
631 LOG(ERROR) << extension->id()
632 << ": app manifest entry is allowed only for hosted_app or "
633 "platform_app extension type. Current extension type: "
634 << extension->GetType();
635 safe = false;
636 }
508 const base::DictionaryValue *dict_value; 637 const base::DictionaryValue *dict_value;
509 if (!it.value().GetAsDictionary(&dict_value)) { 638 if (!it.value().GetAsDictionary(&dict_value)) {
510 LOG(ERROR) << extension->id() << ": app is not a dictionary."; 639 LOG(ERROR) << extension->id() << ": app is not a dictionary.";
511 safe = false; 640 safe = false;
512 continue; 641 continue;
513 } 642 }
514 for (base::DictionaryValue::Iterator it2(*dict_value); 643 for (base::DictionaryValue::Iterator it2(*dict_value);
515 !it2.IsAtEnd(); it2.Advance()) { 644 !it2.IsAtEnd(); it2.Advance()) {
516 if (it2.key() != "background") { 645 if (!ArrayContains(kSafeAppStrings, it2.key())) {
517 LOG(ERROR) << extension->id() 646 LOG(ERROR) << extension->id()
518 << " has non-whitelisted manifest entry: " 647 << " has non-whitelisted manifest entry: "
519 << it.key() << "." << it2.key(); 648 << it.key() << "." << it2.key();
520 safe = false; 649 safe = false;
521 continue; 650 continue;
522 } 651 }
523 } 652 }
524 // Require v2 because that's the only version we understand. 653 // Require v2 because that's the only version we understand.
525 } else if (it.key() == emk::kManifestVersion) { 654 } else if (it.key() == emk::kManifestVersion) {
526 int version; 655 int version;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 if (extension->GetType() == extensions::Manifest::TYPE_HOSTED_APP) { 719 if (extension->GetType() == extensions::Manifest::TYPE_HOSTED_APP) {
591 return true; 720 return true;
592 } 721 }
593 722
594 // Allow extension if its specific ID is whitelisted for use in public 723 // Allow extension if its specific ID is whitelisted for use in public
595 // sessions. 724 // sessions.
596 if (ArrayContains(kPublicSessionWhitelist, extension->id())) { 725 if (ArrayContains(kPublicSessionWhitelist, extension->id())) {
597 return true; 726 return true;
598 } 727 }
599 728
600 // Allow force-installed platform app if all manifest contents are 729 // Allow force-installed extension if all manifest contents are whitelisted.
601 // whitelisted.
602 if ((extension->location() == extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD 730 if ((extension->location() == extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD
603 || extension->location() == extensions::Manifest::EXTERNAL_POLICY) 731 || extension->location() == extensions::Manifest::EXTERNAL_POLICY)
604 && IsPlatformAppSafeForPublicSession(extension)) { 732 && IsSafeForPublicSession(extension)) {
605 return true; 733 return true;
606 } 734 }
607 } else if (account_type_ == policy::DeviceLocalAccount::TYPE_KIOSK_APP) { 735 } else if (account_type_ == policy::DeviceLocalAccount::TYPE_KIOSK_APP) {
608 // For single-app kiosk sessions, allow platform apps, extesions and shared 736 // For single-app kiosk sessions, allow platform apps, extesions and shared
609 // modules. 737 // modules.
610 if (extension->GetType() == extensions::Manifest::TYPE_PLATFORM_APP || 738 if (extension->GetType() == extensions::Manifest::TYPE_PLATFORM_APP ||
611 extension->GetType() == extensions::Manifest::TYPE_SHARED_MODULE || 739 extension->GetType() == extensions::Manifest::TYPE_SHARED_MODULE ||
612 extension->GetType() == extensions::Manifest::TYPE_EXTENSION) { 740 extension->GetType() == extensions::Manifest::TYPE_EXTENSION) {
613 return true; 741 return true;
614 } 742 }
615 } 743 }
616 744
617 // Disallow all other extensions. 745 // Disallow all other extensions.
618 if (error) { 746 if (error) {
619 *error = l10n_util::GetStringFUTF16( 747 *error = l10n_util::GetStringFUTF16(
620 IDS_EXTENSION_CANT_INSTALL_IN_DEVICE_LOCAL_ACCOUNT, 748 IDS_EXTENSION_CANT_INSTALL_IN_DEVICE_LOCAL_ACCOUNT,
621 base::UTF8ToUTF16(extension->name()), 749 base::UTF8ToUTF16(extension->name()),
622 base::UTF8ToUTF16(extension->id())); 750 base::UTF8ToUTF16(extension->id()));
623 } 751 }
624 return false; 752 return false;
625 } 753 }
626 754
627 } // namespace chromeos 755 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698