OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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 "components/safe_browsing_db/safe_browsing_api_handler_util.h" | 5 #include "components/safe_browsing_db/safe_browsing_api_handler_util.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 27 matching lines...) Expand all Loading... |
38 if (threat_type == SB_THREAT_TYPE_URL_MALWARE) { | 38 if (threat_type == SB_THREAT_TYPE_URL_MALWARE) { |
39 UMA_HISTOGRAM_ENUMERATION( | 39 UMA_HISTOGRAM_ENUMERATION( |
40 "SB2.RemoteCall.ThreatSubType.PotentiallyHarmfulApp", sub_type, | 40 "SB2.RemoteCall.ThreatSubType.PotentiallyHarmfulApp", sub_type, |
41 UMA_THREAT_SUB_TYPE_MAX_VALUE); | 41 UMA_THREAT_SUB_TYPE_MAX_VALUE); |
42 } else { | 42 } else { |
43 UMA_HISTOGRAM_ENUMERATION("SB2.RemoteCall.ThreatSubType.SocialEngineering", | 43 UMA_HISTOGRAM_ENUMERATION("SB2.RemoteCall.ThreatSubType.SocialEngineering", |
44 sub_type, UMA_THREAT_SUB_TYPE_MAX_VALUE); | 44 sub_type, UMA_THREAT_SUB_TYPE_MAX_VALUE); |
45 } | 45 } |
46 } | 46 } |
47 | 47 |
48 // Parse the extra key/value pair(s) added by Safe Browsing backend. To make | 48 // Parse the appropriate "*_pattern_type" key from the metadata. |
49 // it binary compatible with the Pver3 metadata that UIManager expects to | 49 // Returns NONE if no pattern type was found. |
50 // deserialize, we convert it to a MalwarePatternType. | 50 ThreatPatternType ParseThreatSubType( |
51 // | 51 const base::DictionaryValue* match, |
52 // TODO(nparker): When chrome desktop is converted to use Pver4, convert this | 52 SBThreatType threat_type) { |
53 // to the new proto instead. | |
54 const std::string ParseExtraMetadataToPB(const base::DictionaryValue* match, | |
55 SBThreatType threat_type) { | |
56 std::string pattern_key; | 53 std::string pattern_key; |
57 if (threat_type == SB_THREAT_TYPE_URL_MALWARE) { | 54 if (threat_type == SB_THREAT_TYPE_URL_MALWARE) { |
58 pattern_key = "pha_pattern_type"; | 55 pattern_key = "pha_pattern_type"; |
59 } else { | 56 } else { |
60 DCHECK(threat_type == SB_THREAT_TYPE_URL_PHISHING); | 57 DCHECK(threat_type == SB_THREAT_TYPE_URL_PHISHING); |
61 pattern_key = "se_pattern_type"; | 58 pattern_key = "se_pattern_type"; |
62 } | 59 } |
63 | 60 |
64 std::string pattern_type; | 61 std::string pattern_type; |
65 if (!match->GetString(pattern_key, &pattern_type)) { | 62 if (!match->GetString(pattern_key, &pattern_type)) { |
66 ReportUmaThreatSubType(threat_type, UMA_THREAT_SUB_TYPE_NOT_SET); | 63 ReportUmaThreatSubType(threat_type, UMA_THREAT_SUB_TYPE_NOT_SET); |
67 return std::string(); | 64 return ThreatPatternType::NONE; |
68 } | 65 } |
69 | 66 |
70 MalwarePatternType pb; | |
71 if (pattern_type == "LANDING") { | 67 if (pattern_type == "LANDING") { |
72 pb.set_pattern_type(MalwarePatternType::LANDING); | |
73 ReportUmaThreatSubType(threat_type, UMA_THREAT_SUB_TYPE_LANDING); | 68 ReportUmaThreatSubType(threat_type, UMA_THREAT_SUB_TYPE_LANDING); |
| 69 return ThreatPatternType::LANDING; |
74 } else if (pattern_type == "DISTRIBUTION") { | 70 } else if (pattern_type == "DISTRIBUTION") { |
75 pb.set_pattern_type(MalwarePatternType::DISTRIBUTION); | |
76 ReportUmaThreatSubType(threat_type, UMA_THREAT_SUB_TYPE_DISTRIBUTION); | 71 ReportUmaThreatSubType(threat_type, UMA_THREAT_SUB_TYPE_DISTRIBUTION); |
| 72 return ThreatPatternType::DISTRIBUTION; |
77 } else { | 73 } else { |
78 ReportUmaThreatSubType(threat_type, UMA_THREAT_SUB_TYPE_UNKNOWN); | 74 ReportUmaThreatSubType(threat_type, UMA_THREAT_SUB_TYPE_UNKNOWN); |
79 return std::string(); | 75 return ThreatPatternType::NONE; |
| 76 } |
| 77 } |
| 78 |
| 79 // DEPRECATED |
| 80 // TODO(nparker): Remove this as part of crbug/589610 |
| 81 // Convert back to PB for compatibility with clank, until we land |
| 82 // a CL there to use ParseJson(). |
| 83 const std::string ParseExtraMetadataToPB(const base::DictionaryValue* match, |
| 84 SBThreatType threat_type) { |
| 85 ThreatPatternType pattern_type = ParseThreatSubType(match, threat_type); |
| 86 |
| 87 MalwarePatternType pb; |
| 88 switch (pattern_type) { |
| 89 case ThreatPatternType::LANDING: |
| 90 pb.set_pattern_type(MalwarePatternType::LANDING); |
| 91 break; |
| 92 case ThreatPatternType::DISTRIBUTION: |
| 93 pb.set_pattern_type(MalwarePatternType::DISTRIBUTION); |
| 94 break; |
| 95 default: |
| 96 return std::string(); |
80 } | 97 } |
81 | 98 |
82 return pb.SerializeAsString(); | 99 return pb.SerializeAsString(); |
83 } | 100 } |
84 | 101 |
| 102 // Parse the optional "UserPopulation" key from the metadata. |
| 103 // Returns empty string if none was found. |
| 104 std::string ParseUserPopulation(const base::DictionaryValue* match) { |
| 105 std::string population_id; |
| 106 if (!match->GetString("UserPopulation", &population_id)) |
| 107 return std::string(); |
| 108 else |
| 109 return population_id; |
| 110 } |
| 111 |
85 int GetThreatSeverity(int java_threat_num) { | 112 int GetThreatSeverity(int java_threat_num) { |
86 // Assign higher numbers to more severe threats. | 113 // Assign higher numbers to more severe threats. |
87 switch (java_threat_num) { | 114 switch (java_threat_num) { |
88 case JAVA_THREAT_TYPE_POTENTIALLY_HARMFUL_APPLICATION: | 115 case JAVA_THREAT_TYPE_POTENTIALLY_HARMFUL_APPLICATION: |
89 return 2; | 116 return 2; |
90 case JAVA_THREAT_TYPE_SOCIAL_ENGINEERING: | 117 case JAVA_THREAT_TYPE_SOCIAL_ENGINEERING: |
91 return 1; | 118 return 1; |
92 default: | 119 default: |
93 // Unknown threat type | 120 // Unknown threat type |
94 return -1; | 121 return -1; |
(...skipping 12 matching lines...) Expand all Loading... |
107 } | 134 } |
108 } | 135 } |
109 | 136 |
110 } // namespace | 137 } // namespace |
111 | 138 |
112 // Valid examples: | 139 // Valid examples: |
113 // {"matches":[{"threat_type":"5"}]} | 140 // {"matches":[{"threat_type":"5"}]} |
114 // or | 141 // or |
115 // {"matches":[{"threat_type":"4"}, | 142 // {"matches":[{"threat_type":"4"}, |
116 // {"threat_type":"5", "se_pattern_type":"LANDING"}]} | 143 // {"threat_type":"5", "se_pattern_type":"LANDING"}]} |
| 144 // or |
| 145 // {"matches":[{"threat_type":"4", "UserPopulation":"YXNvZWZpbmFqO..."}] |
| 146 UmaRemoteCallResult ParseJson(const std::string& metadata_str, |
| 147 SBThreatType* worst_threat, |
| 148 ThreatMetadata* metadata) { |
| 149 *worst_threat = SB_THREAT_TYPE_SAFE; // Default to safe. |
| 150 *metadata = ThreatMetadata(); // Default values. |
| 151 |
| 152 if (metadata_str.empty()) |
| 153 return UMA_STATUS_JSON_EMPTY; |
| 154 |
| 155 // Pick out the "matches" list. |
| 156 scoped_ptr<base::Value> value = base::JSONReader::Read(metadata_str); |
| 157 const base::ListValue* matches = nullptr; |
| 158 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY) || |
| 159 !(static_cast<base::DictionaryValue*>(value.get())) |
| 160 ->GetList(kJsonKeyMatches, &matches) || |
| 161 !matches) { |
| 162 return UMA_STATUS_JSON_FAILED_TO_PARSE; |
| 163 } |
| 164 |
| 165 // Go through each matched threat type and pick the most severe. |
| 166 int worst_threat_num = -1; |
| 167 const base::DictionaryValue* worst_match = nullptr; |
| 168 for (size_t i = 0; i < matches->GetSize(); i++) { |
| 169 // Get the threat number |
| 170 const base::DictionaryValue* match; |
| 171 std::string threat_num_str; |
| 172 int java_threat_num = -1; |
| 173 if (!matches->GetDictionary(i, &match) || |
| 174 !match->GetString(kJsonKeyThreatType, &threat_num_str) || |
| 175 !base::StringToInt(threat_num_str, &java_threat_num)) { |
| 176 continue; // Skip malformed list entries |
| 177 } |
| 178 |
| 179 if (GetThreatSeverity(java_threat_num) > |
| 180 GetThreatSeverity(worst_threat_num)) { |
| 181 worst_threat_num = java_threat_num; |
| 182 worst_match = match; |
| 183 } |
| 184 } |
| 185 |
| 186 *worst_threat = JavaToSBThreatType(worst_threat_num); |
| 187 if (*worst_threat == SB_THREAT_TYPE_SAFE || !worst_match) |
| 188 return UMA_STATUS_JSON_UNKNOWN_THREAT; |
| 189 |
| 190 // Fill in the metadata |
| 191 metadata->threat_pattern_type = |
| 192 ParseThreatSubType(worst_match, *worst_threat); |
| 193 metadata->population_id = ParseUserPopulation(worst_match); |
| 194 |
| 195 return UMA_STATUS_UNSAFE; // success |
| 196 } |
| 197 |
| 198 // DEPRECATED |
| 199 // TODO(nparker): Remove this as part of crbug/589610 |
117 UmaRemoteCallResult ParseJsonToThreatAndPB(const std::string& metadata_str, | 200 UmaRemoteCallResult ParseJsonToThreatAndPB(const std::string& metadata_str, |
118 SBThreatType* worst_threat, | 201 SBThreatType* worst_threat, |
119 std::string* metadata_pb_str) { | 202 std::string* metadata_pb_str) { |
120 *worst_threat = SB_THREAT_TYPE_SAFE; // Default to safe. | 203 *worst_threat = SB_THREAT_TYPE_SAFE; // Default to safe. |
121 *metadata_pb_str = std::string(); | 204 *metadata_pb_str = std::string(); |
122 | 205 |
123 if (metadata_str.empty()) | 206 if (metadata_str.empty()) |
124 return UMA_STATUS_JSON_EMPTY; | 207 return UMA_STATUS_JSON_EMPTY; |
125 | 208 |
126 // Pick out the "matches" list. | 209 // Pick out the "matches" list. |
(...skipping 29 matching lines...) Expand all Loading... |
156 | 239 |
157 *worst_threat = JavaToSBThreatType(worst_threat_num); | 240 *worst_threat = JavaToSBThreatType(worst_threat_num); |
158 if (*worst_threat == SB_THREAT_TYPE_SAFE || !worst_match) | 241 if (*worst_threat == SB_THREAT_TYPE_SAFE || !worst_match) |
159 return UMA_STATUS_JSON_UNKNOWN_THREAT; | 242 return UMA_STATUS_JSON_UNKNOWN_THREAT; |
160 *metadata_pb_str = ParseExtraMetadataToPB(worst_match, *worst_threat); | 243 *metadata_pb_str = ParseExtraMetadataToPB(worst_match, *worst_threat); |
161 | 244 |
162 return UMA_STATUS_UNSAFE; // success | 245 return UMA_STATUS_UNSAFE; // success |
163 } | 246 } |
164 | 247 |
165 } // namespace safe_browsing | 248 } // namespace safe_browsing |
OLD | NEW |