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

Side by Side Diff: chrome/browser/safe_browsing/signature_evaluator_mac.mm

Issue 1363613004: Implement anonymous, opt-in, collection of OS X binary integrity incidents. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test checkperms changs Created 5 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
(Empty)
1 // Copyright (c) 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/safe_browsing/signature_evaluator_mac.h"
6
7 #include <CoreFoundation/CoreFoundation.h>
8 #include <Foundation/Foundation.h>
9 #include <Security/Security.h>
10 #include <sys/xattr.h>
11
12 #include "base/mac/foundation_util.h"
13 #include "base/mac/mac_util.h"
14 #include "base/mac/scoped_cftyperef.h"
15 #include "base/mac/scoped_nsobject.h"
16 #include "base/strings/sys_string_conversions.h"
17 #include "chrome/common/safe_browsing/binary_feature_extractor.h"
18 #include "chrome/common/safe_browsing/csd.pb.h"
19 #include "chrome/common/safe_browsing/mach_o_image_reader_mac.h"
20
21 namespace safe_browsing {
22
23 namespace {
24
25 // OS X code signing data can be stored in extended attributes as well. This is
26 // a list of the extended attributes slots currently used in Security.framework,
27 // from codesign.h (see the kSecCS_* constants).
28 const char* const xattrs[] = {
29 "com.apple.cs.CodeDirectory",
30 "com.apple.cs.CodeSignature",
31 "com.apple.cs.CodeRequirements",
32 "com.apple.cs.CodeResources",
33 "com.apple.cs.CodeApplication",
34 "com.apple.cs.CodeEntitlements",
35 };
36
37 // Convenience function to get the appropriate path from a variety of NSObject
38 // types.
39 bool GetPathFromNSObject(id obj, std::string* output) {
40 if (NSString* str = base::mac::ObjCCast<NSString>(obj)) {
41 output->assign([str UTF8String]);
42 return true;
43 } else if (NSURL* url = base::mac::ObjCCast<NSURL>(obj)) {
44 output->assign([[url path] UTF8String]);
45 return true;
46 } else if (NSBundle* bundle = base::mac::ObjCCast<NSBundle>(obj)) {
47 output->assign([[bundle bundlePath] UTF8String]);
48 return true;
49 }
50 return false;
51 }
52
53 } // namespace
54
55 MacSignatureEvaluator::MacSignatureEvaluator(
56 const base::FilePath& signed_object_path)
57 : path_(signed_object_path),
58 has_requirement_(false),
59 code_(nullptr),
60 requirement_(nullptr) {}
61
62 MacSignatureEvaluator::MacSignatureEvaluator(
63 const base::FilePath& signed_object_path,
64 const std::string& requirement)
65 : path_(signed_object_path),
66 requirement_str_(requirement),
67 has_requirement_(true),
68 code_(nullptr),
69 requirement_(nullptr) {}
70
71 MacSignatureEvaluator::~MacSignatureEvaluator() {}
72
73 void MacSignatureEvaluator::ReportAlteredFiles(
74 id detail,
75 int32_t err_code,
76 std::vector<ClientIncidentReport_IncidentData_BinaryIntegrityIncident>&
77 results) {
78 if (NSArray* arr = base::mac::ObjCCast<NSArray>(detail)) {
79 for (id obj in arr)
80 ReportAlteredFiles(obj, err_code, results);
81 } else {
82 std::string path_str;
83 if (!GetPathFromNSObject(detail, &path_str))
84 return;
85
86 base::FilePath path(path_str);
87 ClientIncidentReport_IncidentData_BinaryIntegrityIncident incident;
88 incident.set_file_basename(path.BaseName().AsUTF8Unsafe());
89 incident.set_sec_error(err_code);
90 scoped_refptr<BinaryFeatureExtractor> bfe = new BinaryFeatureExtractor();
91 // TODO(kerrnel): if Chrome ever opts into the OS X "kill" semantics, this
92 // call has to change. `ExtractImageFeatures` maps the file, which will
93 // cause Chrome to be killed before it can report on the invalid file.
94 // This call will need to read(2) the binary into a buffer.
95 if (!bfe->ExtractImageFeatures(
96 path, BinaryFeatureExtractor::kDefaultOptions,
97 incident.mutable_image_headers(),
98 incident.mutable_signature()->mutable_signed_data())) {
99 // If this is not a mach-o file, search inside the extended attributes.
100 for (const char* attr : xattrs) {
101 ssize_t rc = getxattr(path.value().c_str(), attr, nullptr, 0, 0, 0);
102 if (rc >= 0) {
103 std::vector<uint8_t> xattr_data(rc);
104 if (getxattr(path.value().c_str(), attr, &xattr_data[0],
105 xattr_data.size(), 0, 0) >= 0) {
106 ClientDownloadRequest_ExtendedAttr* xattr_msg =
107 incident.mutable_signature()->add_xattr();
108 xattr_msg->set_key(attr);
109 xattr_msg->set_value(xattr_data.data(), xattr_data.size());
110 }
111 }
112 }
113 }
114 results.push_back(incident);
115 }
116 }
117
118 bool MacSignatureEvaluator::Initialize() {
119 base::scoped_nsobject<NSURL> code_url([[NSURL alloc]
120 initFileURLWithPath:base::SysUTF8ToNSString(path_.value())]);
121 if (!code_url)
122 return false;
123
124 if (SecStaticCodeCreateWithPath(base::mac::NSToCFCast(code_url.get()),
125 kSecCSDefaultFlags,
126 code_.InitializeInto()) != errSecSuccess)
Robert Sesek 2015/10/08 19:20:06 nit: needs braces since multi-line
Greg K 2015/10/09 17:12:01 Done.
127 return false;
128
129 if (has_requirement_) {
130 if (SecRequirementCreateWithString(
131 base::mac::NSToCFCast(base::SysUTF8ToNSString(requirement_str_)),
132 kSecCSDefaultFlags, requirement_.InitializeInto()) != errSecSuccess)
Robert Sesek 2015/10/08 19:20:06 nit: same, braces required
Greg K 2015/10/09 17:12:01 Done.
133 return false;
134 }
135
136 return true;
137 }
138
139 bool MacSignatureEvaluator::PerformEvaluation(
140 std::vector<ClientIncidentReport_IncidentData_BinaryIntegrityIncident>&
141 results) {
142 base::ScopedCFTypeRef<CFErrorRef> errors(nullptr);
143 OSStatus err = SecStaticCodeCheckValidityWithErrors(
144 code_, kSecCSCheckAllArchitectures, requirement_,
145 errors.InitializeInto());
146 if (err == errSecSuccess)
147 return true;
148 // This adds the signature of the main binary to the incident reports.
149 ReportAlteredFiles(base::SysUTF8ToNSString(path_.value()), err, results);
150 if (errors) {
151 NSDictionary* info = [base::mac::CFToNSCast(errors.get()) userInfo];
152 CFStringRef keys[] = {
153 kSecCFErrorResourceAltered, kSecCFErrorResourceMissing,
154 };
155 for (CFStringRef key : keys) {
156 if (id detail = [info objectForKey:base::mac::CFToNSCast(key)])
157 ReportAlteredFiles(detail, err, results);
158 }
159 }
160 return false;
161 }
162
163 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698