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

Side by Side Diff: chrome/common/mac/cfbundle_blocker.mm

Issue 8226026: Allow whitelisted bundles to load in Chrome (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/common/mac/cfbundle_blocker.h" 5 #include "chrome/common/mac/cfbundle_blocker.h"
6 6
7 #include <CoreFoundation/CoreFoundation.h> 7 #include <CoreFoundation/CoreFoundation.h>
8 #import <Foundation/Foundation.h> 8 #import <Foundation/Foundation.h>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 NSArray* blocked_prefixes = 53 NSArray* blocked_prefixes =
54 NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, 54 NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
55 NSUserDomainMask | 55 NSUserDomainMask |
56 NSLocalDomainMask | 56 NSLocalDomainMask |
57 NSNetworkDomainMask, 57 NSNetworkDomainMask,
58 YES); 58 YES);
59 59
60 // Everything in the suffix list has a trailing slash so as to only block 60 // Everything in the suffix list has a trailing slash so as to only block
61 // loading things contained in these directories. 61 // loading things contained in these directories.
62 NSString* const blocked_suffixes[] = { 62 NSString* const blocked_suffixes[] = {
63 // SIMBL - http://code.google.com/p/simbl/source/browse/src/SIMBL.{h,m}.
64 // It attempts to inject itself via an AppleScript event.
65 // http://code.google.com/p/simbl/source/browse/SIMBL%20Agent/SIMBLAgent.m
66 // Blocking input managers and scripting additions may already be enough
67 // to prevent SIMBL plugins from loading.
68 @"Application Support/SIMBL/Plugins/",
69
70 #if !defined(__LP64__) 63 #if !defined(__LP64__)
71 // Contextual menu manager plug-ins are unavailable to 64-bit processes. 64 // Contextual menu manager plug-ins are unavailable to 64-bit processes.
72 // http://developer.apple.com/library/mac/releasenotes/Cocoa/AppKitOlderNo tes.html#NSMenu 65 // http://developer.apple.com/library/mac/releasenotes/Cocoa/AppKitOlderNo tes.html#NSMenu
73 // Contextual menu plug-ins are loaded when a contextual menu is opened, 66 // Contextual menu plug-ins are loaded when a contextual menu is opened,
74 // for example, from within 67 // for example, from within
75 // +[NSMenu popUpContextMenu:withEvent:forView:]. 68 // +[NSMenu popUpContextMenu:withEvent:forView:].
76 @"Contextual Menu Items/", 69 @"Contextual Menu Items/",
77 70
78 // Input managers are deprecated, would only be loaded under specific 71 // Input managers are deprecated, would only be loaded under specific
79 // circumstances, and are entirely unavailable to 64-bit processes. 72 // circumstances, and are entirely unavailable to 64-bit processes.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 // If bundle_path is inside blocked_path (it has blocked_path as a 132 // If bundle_path is inside blocked_path (it has blocked_path as a
140 // prefix), refuse to load it. 133 // prefix), refuse to load it.
141 return true; 134 return true;
142 } 135 }
143 } 136 }
144 137
145 // bundle_path is not inside any blocked_path from blocked_paths. 138 // bundle_path is not inside any blocked_path from blocked_paths.
146 return false; 139 return false;
147 } 140 }
148 141
149 // Returns true if bundle_id identifies a bundle that is allowed to be loaded 142 struct AllowedBundle {
143 // The bundle identifier to permit. These are matched with a case-sensitive
144 // literal comparison. "Children" of the declared bundle ID are permitted:
145 // if bundle_id here is @"org.chromium", it would match both @"org.chromium"
146 // and @"org.chromium.Chromium".
147 NSString* bundle_id;
148
149 // If bundle_id should only be permitted as of a certain minimum version,
150 // this string defines that version, which will be compared to the bundle's
151 // version with a numeric comparison. If bundle_id may be permitted at any
152 // version, set minimum_version to nil.
153 NSString* minimum_version;
154 };
155
156 // Returns true if |bundle| identifies a bundle that is allowed to be loaded
150 // even when found in a blocked directory. 157 // even when found in a blocked directory.
151 bool IsBundleIDAllowed(NSString* bundle_id) { 158 bool IsBundleAllowed(CFBundleRef bundle) {
152 return [bundle_id isEqualToString:@"com.google.osax.Google_Authenticator_BT"]; 159 const AllowedBundle kAllowedBundles[] = {
Nico 2011/10/12 17:25:59 Add a comment saying "// If you want your plugin t
160 // Google Authenticator BT
161 // dmaclach
162 { @"com.google.osax.Google_Authenticator_BT", nil },
163
164 // Default Folder X, http://www.stclairsoft.com/DefaultFolderX/
165 // Jon Gotow <gotow@stclairsoft.com>
166 { @"com.stclairsoft.DefaultFolderX", @"4.4.3" },
167
168 // MySpeed, http://www.enounce.com/myspeed
169 // Edward Bianchi <ejbianchi@enounce.com>
170 { @"com.enounce.MySpeed.osax", @"1201" },
171
172 // SIMBL (fork), https://github.com/albertz/simbl
173 // Albert Zeyer <albzey@googlemail.com>
174 { @"net.culater.SIMBL", nil },
175
176 // Smart Scroll, http://marcmoini.com/sx_en.html
177 // Marc Moini <marc@a9ff.com>
178 { @"com.marcmoini.SmartScroll", @"3.9" },
179 };
180
181 CFStringRef identifier_cf = CFBundleGetIdentifier(bundle);
182 NSString* identifier_ns = base::mac::CFToNSCast(identifier_cf);
183
184 for (size_t index = 0; index < arraysize(kAllowedBundles); ++index) {
185 const AllowedBundle& allowed_bundle = kAllowedBundles[index];
186 NSString* allowed_bundle_id = allowed_bundle.bundle_id;
187
188 // Try a direct equality test.
189 bool bundle_id_match = [identifier_ns isEqualToString:allowed_bundle_id];
190
191 if (!bundle_id_match) {
192 // Permit bundle identifiers that are "children" of the allowed
193 // identifier.
194 NSUInteger bundle_id_length = [identifier_ns length];
195 NSUInteger allowed_bundle_id_length = [allowed_bundle_id length];
196 if (bundle_id_length > allowed_bundle_id_length &&
197 [identifier_ns characterAtIndex:allowed_bundle_id_length] == '.') {
198 NSComparisonResult result =
199 [identifier_ns compare:allowed_bundle_id
200 options:NSLiteralSearch
201 range:NSMakeRange(0, allowed_bundle_id_length)];
202 bundle_id_match = result == NSOrderedSame;
203 }
204 }
205
206 if (bundle_id_match) {
207 NSString* minimum_version = allowed_bundle.minimum_version;
208 if (!minimum_version) {
209 // If the rule didn't declare any version requirement, the bundle is
210 // allowed to load.
211 return true;
212 }
213
214 NSDictionary* bundle_dictionary =
215 base::mac::CFToNSCast(CFBundleGetInfoDictionary(bundle));
216 NSString* version = [bundle_dictionary objectForKey:
217 base::mac::CFToNSCast(kCFBundleVersionKey)];
218 if (![version isKindOfClass:[NSString class]]) {
219 // If there wasn't any version but one was required, the bundle isn't
220 // allowed to load.
221 return false;
222 }
223
224 // A numeric search is appropriate for comparing version numbers.
225 NSComparisonResult result = [version compare:minimum_version
226 options:NSNumericSearch];
227 return result != NSOrderedAscending;
228 }
229 }
230
231 // Nothing matched.
232 return false;
153 } 233 }
154 234
155 typedef Boolean (*_CFBundleLoadExecutableAndReturnError_Type)(CFBundleRef, 235 typedef Boolean (*_CFBundleLoadExecutableAndReturnError_Type)(CFBundleRef,
156 Boolean, 236 Boolean,
157 CFErrorRef*); 237 CFErrorRef*);
158 238
159 // Call this to execute the original implementation of 239 // Call this to execute the original implementation of
160 // _CFBundleLoadExecutableAndReturnError. 240 // _CFBundleLoadExecutableAndReturnError.
161 _CFBundleLoadExecutableAndReturnError_Type 241 _CFBundleLoadExecutableAndReturnError_Type
162 g_original_underscore_cfbundle_load_executable_and_return_error; 242 g_original_underscore_cfbundle_load_executable_and_return_error;
163 243
164 Boolean ChromeCFBundleLoadExecutableAndReturnError(CFBundleRef bundle, 244 Boolean ChromeCFBundleLoadExecutableAndReturnError(CFBundleRef bundle,
165 Boolean force_global, 245 Boolean force_global,
166 CFErrorRef* error) { 246 CFErrorRef* error) {
167 base::mac::ScopedNSAutoreleasePool autorelease_pool; 247 base::mac::ScopedNSAutoreleasePool autorelease_pool;
168 248
169 DCHECK(g_original_underscore_cfbundle_load_executable_and_return_error); 249 DCHECK(g_original_underscore_cfbundle_load_executable_and_return_error);
170 250
171 base::mac::ScopedCFTypeRef<CFURLRef> url_cf(CFBundleCopyBundleURL(bundle)); 251 base::mac::ScopedCFTypeRef<CFURLRef> url_cf(CFBundleCopyBundleURL(bundle));
172 base::mac::ScopedCFTypeRef<CFStringRef> path_cf( 252 base::mac::ScopedCFTypeRef<CFStringRef> path_cf(
173 CFURLCopyFileSystemPath(url_cf, kCFURLPOSIXPathStyle)); 253 CFURLCopyFileSystemPath(url_cf, kCFURLPOSIXPathStyle));
174 NSString* path_ns = base::mac::CFToNSCast(path_cf); 254 NSString* path_ns = base::mac::CFToNSCast(path_cf);
175 255
176 CFStringRef identifier_cf = CFBundleGetIdentifier(bundle); 256 CFStringRef identifier_cf = CFBundleGetIdentifier(bundle);
177 NSString* identifier_ns = base::mac::CFToNSCast(identifier_cf); 257 NSString* identifier_ns = base::mac::CFToNSCast(identifier_cf);
178 258
179 if (IsBundlePathBlocked(path_ns) && !IsBundleIDAllowed(identifier_ns)) { 259 if (IsBundlePathBlocked(path_ns) && !IsBundleAllowed(bundle)) {
180 NSString* identifier_ns_print = identifier_ns ? identifier_ns : @"(nil)"; 260 NSString* identifier_ns_print = identifier_ns ? identifier_ns : @"(nil)";
181 261
182 LOG(INFO) << "Blocking attempt to load bundle " 262 LOG(INFO) << "Blocking attempt to load bundle "
183 << [identifier_ns_print UTF8String] 263 << [identifier_ns_print UTF8String]
184 << " at " 264 << " at "
185 << [path_ns fileSystemRepresentation]; 265 << [path_ns fileSystemRepresentation];
186 266
187 if (error) { 267 if (error) {
188 base::mac::ScopedCFTypeRef<CFStringRef> bundle_id( 268 base::mac::ScopedCFTypeRef<CFStringRef> bundle_id(
189 base::SysUTF8ToCFStringRef(base::mac::BaseBundleID())); 269 base::SysUTF8ToCFStringRef(base::mac::BaseBundleID()));
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 &g_original_underscore_cfbundle_load_executable_and_return_error)); 309 &g_original_underscore_cfbundle_load_executable_and_return_error));
230 if (err != err_none) { 310 if (err != err_none) {
231 LOG(WARNING) << "mach_override _CFBundleLoadExecutableAndReturnError: " 311 LOG(WARNING) << "mach_override _CFBundleLoadExecutableAndReturnError: "
232 << err; 312 << err;
233 } 313 }
234 } 314 }
235 315
236 } // namespace mac 316 } // namespace mac
237 } // namespace common 317 } // namespace common
238 } // namespace chrome 318 } // namespace chrome
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698