onc_validator.cc 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  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. #include "chromeos/components/onc/onc_validator.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <algorithm>
  8. #include <utility>
  9. #include "base/containers/contains.h"
  10. #include "base/json/json_writer.h"
  11. #include "base/logging.h"
  12. #include "base/memory/ptr_util.h"
  13. #include "base/notreached.h"
  14. #include "base/strings/string_number_conversions.h"
  15. #include "base/strings/string_piece.h"
  16. #include "base/strings/string_util.h"
  17. #include "base/values.h"
  18. #include "chromeos/components/onc/onc_signature.h"
  19. #include "components/crx_file/id_util.h"
  20. #include "components/device_event_log/device_event_log.h"
  21. #include "components/onc/onc_constants.h"
  22. #include "third_party/abseil-cpp/absl/types/optional.h"
  23. namespace chromeos {
  24. namespace onc {
  25. namespace {
  26. // According to the IEEE 802.11 standard the SSID is a series of 0 to 32 octets.
  27. const int kMaximumSSIDLengthInBytes = 32;
  28. void AddKeyToList(const char* key, base::Value* list) {
  29. base::Value key_value(key);
  30. if (!base::Contains(list->GetListDeprecated(), key_value))
  31. list->Append(std::move(key_value));
  32. }
  33. std::string GetStringFromDict(const base::Value& dict, const char* key) {
  34. const base::Value* value = dict.FindKeyOfType(key, base::Value::Type::STRING);
  35. return value ? value->GetString() : std::string();
  36. }
  37. bool FieldIsRecommended(const base::Value& object,
  38. const std::string& field_name) {
  39. const base::Value* recommended =
  40. object.FindKeyOfType(::onc::kRecommended, base::Value::Type::LIST);
  41. return recommended && base::Contains(recommended->GetListDeprecated(),
  42. base::Value(field_name));
  43. }
  44. bool FieldIsSetToValueOrRecommended(const base::Value& object,
  45. const std::string& field_name,
  46. const base::Value& expected_value) {
  47. const base::Value* actual_value = object.FindKey(field_name);
  48. if (actual_value && expected_value == *actual_value)
  49. return true;
  50. return FieldIsRecommended(object, field_name);
  51. }
  52. } // namespace
  53. Validator::Validator(bool error_on_unknown_field,
  54. bool error_on_wrong_recommended,
  55. bool error_on_missing_field,
  56. bool managed_onc,
  57. bool log_warnings)
  58. : error_on_unknown_field_(error_on_unknown_field),
  59. error_on_wrong_recommended_(error_on_wrong_recommended),
  60. error_on_missing_field_(error_on_missing_field),
  61. managed_onc_(managed_onc),
  62. log_warnings_(log_warnings),
  63. onc_source_(::onc::ONC_SOURCE_NONE) {}
  64. Validator::~Validator() = default;
  65. base::Value Validator::ValidateAndRepairObject(
  66. const OncValueSignature* object_signature,
  67. const base::Value& onc_object,
  68. Result* result) {
  69. CHECK(object_signature);
  70. *result = VALID;
  71. bool error = false;
  72. base::Value result_value = MapValue(*object_signature, onc_object, &error);
  73. if (error) {
  74. *result = INVALID;
  75. return {};
  76. }
  77. if (!validation_issues_.empty())
  78. *result = VALID_WITH_WARNINGS;
  79. return result_value;
  80. }
  81. base::Value Validator::MapValue(const OncValueSignature& signature,
  82. const base::Value& onc_value,
  83. bool* error) {
  84. if (onc_value.type() != signature.onc_type) {
  85. *error = true;
  86. std::ostringstream msg;
  87. msg << "Found value of type '" << base::Value::GetTypeName(onc_value.type())
  88. << "', but type '" << base::Value::GetTypeName(signature.onc_type)
  89. << "' is required.";
  90. AddValidationIssue(true /* is_error */, msg.str());
  91. return {};
  92. }
  93. base::Value repaired = Mapper::MapValue(signature, onc_value, error);
  94. CHECK(repaired.is_none() || repaired.type() == signature.onc_type);
  95. return repaired;
  96. }
  97. base::Value Validator::MapObject(const OncValueSignature& signature,
  98. const base::Value& onc_object,
  99. bool* error) {
  100. base::Value repaired(base::Value::Type::DICTIONARY);
  101. bool valid = ValidateObjectDefault(signature, onc_object, &repaired);
  102. if (valid) {
  103. if (&signature == &kToplevelConfigurationSignature) {
  104. valid = ValidateToplevelConfiguration(&repaired);
  105. } else if (&signature == &kNetworkConfigurationSignature) {
  106. valid = ValidateNetworkConfiguration(&repaired);
  107. } else if (&signature == &kEthernetSignature) {
  108. valid = ValidateEthernet(&repaired);
  109. } else if (&signature == &kIPConfigSignature ||
  110. &signature == &kSavedIPConfigSignature) {
  111. valid = ValidateIPConfig(&repaired);
  112. } else if (&signature == &kWiFiSignature) {
  113. valid = ValidateWiFi(&repaired);
  114. } else if (&signature == &kVPNSignature) {
  115. valid = ValidateVPN(&repaired);
  116. } else if (&signature == &kIPsecSignature) {
  117. valid = ValidateIPsec(&repaired);
  118. } else if (&signature == &kOpenVPNSignature) {
  119. valid = ValidateOpenVPN(&repaired);
  120. } else if (&signature == &kWireGuardSignature) {
  121. valid = ValidateWireGuard(&repaired);
  122. } else if (&signature == &kThirdPartyVPNSignature) {
  123. valid = ValidateThirdPartyVPN(&repaired);
  124. } else if (&signature == &kARCVPNSignature) {
  125. valid = ValidateARCVPN(&repaired);
  126. } else if (&signature == &kVerifyX509Signature) {
  127. valid = ValidateVerifyX509(&repaired);
  128. } else if (&signature == &kCertificatePatternSignature) {
  129. valid = ValidateCertificatePattern(&repaired);
  130. } else if (&signature == &kGlobalNetworkConfigurationSignature) {
  131. valid = ValidateGlobalNetworkConfiguration(&repaired);
  132. } else if (&signature == &kProxySettingsSignature) {
  133. valid = ValidateProxySettings(&repaired);
  134. } else if (&signature == &kProxyLocationSignature) {
  135. valid = ValidateProxyLocation(&repaired);
  136. } else if (&signature == &kEAPSignature) {
  137. valid = ValidateEAP(&repaired);
  138. } else if (&signature == &kEAPSubjectAlternativeNameMatchSignature) {
  139. valid = ValidateSubjectAlternativeNameMatch(&repaired);
  140. } else if (&signature == &kCertificateSignature) {
  141. valid = ValidateCertificate(&repaired);
  142. } else if (&signature == &kScopeSignature) {
  143. valid = ValidateScope(&repaired);
  144. } else if (&signature == &kTetherWithStateSignature) {
  145. valid = ValidateTether(&repaired);
  146. }
  147. // StaticIPConfig is not validated here, because its correctness depends
  148. // on NetworkConfiguration's 'IPAddressConfigType', 'NameServersConfigType'
  149. // and 'Recommended' fields. It's validated in
  150. // ValidateNetworkConfiguration() instead.
  151. }
  152. if (valid)
  153. return repaired;
  154. DCHECK(!validation_issues_.empty());
  155. *error = true;
  156. return {};
  157. }
  158. base::Value Validator::MapField(const std::string& field_name,
  159. const OncValueSignature& object_signature,
  160. const base::Value& onc_value,
  161. bool* found_unknown_field,
  162. bool* error) {
  163. path_.push_back(field_name);
  164. bool current_field_unknown = false;
  165. base::Value result = Mapper::MapField(field_name, object_signature, onc_value,
  166. &current_field_unknown, error);
  167. DCHECK_EQ(field_name, path_.back());
  168. path_.pop_back();
  169. if (current_field_unknown) {
  170. *found_unknown_field = true;
  171. std::ostringstream msg;
  172. msg << "Field name '" << field_name << "' is unknown.";
  173. AddValidationIssue(error_on_unknown_field_, msg.str());
  174. }
  175. return result;
  176. }
  177. base::Value Validator::MapArray(const OncValueSignature& array_signature,
  178. const base::Value& onc_array,
  179. bool* nested_error) {
  180. bool nested_error_in_current_array = false;
  181. base::Value result = Mapper::MapArray(array_signature, onc_array,
  182. &nested_error_in_current_array);
  183. // Drop individual networks and certificates instead of rejecting all of
  184. // the configuration.
  185. if (nested_error_in_current_array &&
  186. &array_signature != &kNetworkConfigurationListSignature &&
  187. &array_signature != &kCertificateListSignature) {
  188. *nested_error = nested_error_in_current_array;
  189. }
  190. return result;
  191. }
  192. base::Value Validator::MapEntry(int index,
  193. const OncValueSignature& signature,
  194. const base::Value& onc_value,
  195. bool* error) {
  196. std::string index_as_string = base::NumberToString(index);
  197. path_.push_back(index_as_string);
  198. base::Value result = Mapper::MapEntry(index, signature, onc_value, error);
  199. DCHECK_EQ(index_as_string, path_.back());
  200. path_.pop_back();
  201. if (result.is_none() && (&signature == &kNetworkConfigurationSignature ||
  202. &signature == &kCertificateSignature)) {
  203. std::ostringstream msg;
  204. msg << "Entry at index '" << index_as_string
  205. << "' has been removed because it contained errors.";
  206. AddValidationIssue(false /* is_error */, msg.str());
  207. }
  208. return result;
  209. }
  210. bool Validator::ValidateObjectDefault(const OncValueSignature& signature,
  211. const base::Value& onc_object,
  212. base::Value* result) {
  213. bool found_unknown_field = false;
  214. bool nested_error_occured = false;
  215. MapFields(signature, onc_object, &found_unknown_field, &nested_error_occured,
  216. result);
  217. if (found_unknown_field && error_on_unknown_field_) {
  218. DVLOG(1) << "Unknown field names are errors: Aborting.";
  219. return false;
  220. }
  221. if (nested_error_occured)
  222. return false;
  223. return ValidateRecommendedField(signature, result);
  224. }
  225. bool Validator::ValidateRecommendedField(
  226. const OncValueSignature& object_signature,
  227. base::Value* result) {
  228. CHECK(result);
  229. absl::optional<base::Value> recommended_value =
  230. result->ExtractKey(::onc::kRecommended);
  231. // This remove passes ownership to |recommended_value|.
  232. if (!recommended_value) {
  233. return true;
  234. }
  235. // The types of field values are already verified.
  236. DCHECK(recommended_value->is_list());
  237. if (!managed_onc_) {
  238. std::ostringstream msg;
  239. msg << "Found the field '" << ::onc::kRecommended
  240. << "' in an unmanaged ONC";
  241. AddValidationIssue(false /* is_error */, msg.str());
  242. return true;
  243. }
  244. base::Value repaired_recommended(base::Value::Type::LIST);
  245. for (const auto& entry : recommended_value->GetListDeprecated()) {
  246. const std::string* field_name = entry.GetIfString();
  247. if (!field_name) {
  248. NOTREACHED(); // The types of field values are already verified.
  249. continue;
  250. }
  251. const OncFieldSignature* field_signature =
  252. GetFieldSignature(object_signature, *field_name);
  253. bool found_error = false;
  254. std::string error_cause;
  255. if (!field_signature) {
  256. found_error = true;
  257. error_cause = "unknown";
  258. } else if (field_signature->value_signature->onc_type ==
  259. base::Value::Type::DICTIONARY) {
  260. found_error = true;
  261. error_cause = "dictionary-typed";
  262. }
  263. if (found_error) {
  264. path_.push_back(::onc::kRecommended);
  265. std::ostringstream msg;
  266. msg << "The " << error_cause << " field '" << *field_name
  267. << "' cannot be recommended.";
  268. AddValidationIssue(error_on_wrong_recommended_, msg.str());
  269. path_.pop_back();
  270. if (error_on_wrong_recommended_)
  271. return false;
  272. continue;
  273. }
  274. repaired_recommended.Append(*field_name);
  275. }
  276. result->SetKey(::onc::kRecommended, std::move(repaired_recommended));
  277. return true;
  278. }
  279. bool Validator::ValidateClientCertFields(bool allow_cert_type_none,
  280. base::Value* result) {
  281. std::vector<const char*> valid_cert_types = {
  282. ::onc::client_cert::kRef, ::onc::client_cert::kPattern,
  283. ::onc::client_cert::kProvisioningProfileId,
  284. ::onc::client_cert::kPKCS11Id};
  285. if (allow_cert_type_none)
  286. valid_cert_types.push_back(::onc::client_cert::kClientCertTypeNone);
  287. std::string cert_type =
  288. GetStringFromDict(*result, ::onc::client_cert::kClientCertType);
  289. // TODO(https://crbug.com/1049955): Remove the client certificate type empty
  290. // check. Ignored fields should be removed by normalizer before validating.
  291. if (cert_type.empty())
  292. return true;
  293. if (!IsValidValue(cert_type, valid_cert_types))
  294. return false;
  295. bool all_required_exist = true;
  296. if (cert_type == ::onc::client_cert::kProvisioningProfileId)
  297. all_required_exist &= RequireField(
  298. *result, ::onc::client_cert::kClientCertProvisioningProfileId);
  299. else if (cert_type == ::onc::client_cert::kPattern)
  300. all_required_exist &=
  301. RequireField(*result, ::onc::client_cert::kClientCertPattern);
  302. else if (cert_type == ::onc::client_cert::kRef)
  303. all_required_exist &=
  304. RequireField(*result, ::onc::client_cert::kClientCertRef);
  305. else if (cert_type == ::onc::client_cert::kPKCS11Id)
  306. all_required_exist &=
  307. RequireField(*result, ::onc::client_cert::kClientCertPKCS11Id);
  308. return !error_on_missing_field_ || all_required_exist;
  309. }
  310. namespace {
  311. std::string JoinStringRange(const std::vector<const char*>& strings,
  312. const std::string& separator) {
  313. std::vector<base::StringPiece> string_vector(strings.begin(), strings.end());
  314. return base::JoinString(string_vector, separator);
  315. }
  316. } // namespace
  317. bool Validator::IsInDevicePolicy(base::Value* result,
  318. const std::string& field_name) {
  319. if (result->FindKey(field_name)) {
  320. if (onc_source_ != ::onc::ONC_SOURCE_DEVICE_POLICY) {
  321. std::ostringstream msg;
  322. msg << "Field '" << field_name << "' is only allowed in a device policy.";
  323. AddValidationIssue(true /* is_error */, msg.str());
  324. return false;
  325. }
  326. }
  327. return true;
  328. }
  329. bool Validator::IsValidValue(const std::string& field_value,
  330. const std::vector<const char*>& valid_values) {
  331. for (const char* it : valid_values) {
  332. if (field_value == it)
  333. return true;
  334. }
  335. std::ostringstream msg;
  336. msg << "Found value '" << field_value << "', but expected one of the values ["
  337. << JoinStringRange(valid_values, ", ") << "]";
  338. AddValidationIssue(true /* is_error */, msg.str());
  339. return false;
  340. }
  341. bool Validator::FieldExistsAndHasNoValidValue(
  342. const base::Value& object,
  343. const std::string& field_name,
  344. const std::vector<const char*>& valid_values) {
  345. const std::string* actual_value = object.FindStringKey(field_name);
  346. if (!actual_value)
  347. return false;
  348. path_.push_back(field_name);
  349. const bool valid = IsValidValue(*actual_value, valid_values);
  350. path_.pop_back();
  351. return !valid;
  352. }
  353. bool Validator::FieldExistsAndIsNotInRange(const base::Value& object,
  354. const std::string& field_name,
  355. int lower_bound,
  356. int upper_bound) {
  357. absl::optional<int> actual_value = object.FindIntKey(field_name);
  358. if (!actual_value || (lower_bound <= actual_value.value() &&
  359. actual_value.value() <= upper_bound)) {
  360. return false;
  361. }
  362. path_.push_back(field_name);
  363. std::ostringstream msg;
  364. msg << "Found value '" << actual_value.value()
  365. << "', but expected a value in the range [" << lower_bound << ", "
  366. << upper_bound << "] (boundaries inclusive)";
  367. AddValidationIssue(true /* is_error */, msg.str());
  368. path_.pop_back();
  369. return true;
  370. }
  371. bool Validator::FieldExistsAndIsEmpty(const base::Value& object,
  372. const std::string& field_name) {
  373. const base::Value* value = object.FindKey(field_name);
  374. if (!value)
  375. return false;
  376. const std::string* str = value->GetIfString();
  377. if (str) {
  378. if (!(*str).empty())
  379. return false;
  380. } else if (value->is_list()) {
  381. if (!value->GetListDeprecated().empty())
  382. return false;
  383. } else {
  384. NOTREACHED();
  385. return false;
  386. }
  387. path_.push_back(field_name);
  388. std::ostringstream msg;
  389. msg << "Found an empty string, but expected a non-empty string.";
  390. AddValidationIssue(true /* is_error */, msg.str());
  391. path_.pop_back();
  392. return true;
  393. }
  394. bool Validator::FieldShouldExistOrBeRecommended(const base::Value& object,
  395. const std::string& field_name) {
  396. if (object.FindKey(field_name) || FieldIsRecommended(object, field_name))
  397. return true;
  398. std::ostringstream msg;
  399. msg << "Field " << field_name << " is not found, but expected either to be "
  400. << "set or to be recommended.";
  401. AddValidationIssue(error_on_missing_field_, msg.str());
  402. return !error_on_missing_field_;
  403. }
  404. bool Validator::OnlyOneFieldSet(const base::Value& object,
  405. const std::string& field_name1,
  406. const std::string& field_name2) {
  407. if (object.FindKey(field_name1) && object.FindKey(field_name2)) {
  408. std::ostringstream msg;
  409. msg << "At most one of '" << field_name1 << "' and '" << field_name2
  410. << "' can be set.";
  411. AddValidationIssue(true /* is_error */, msg.str());
  412. return false;
  413. }
  414. return true;
  415. }
  416. bool Validator::ListFieldContainsValidValues(
  417. const base::Value& object,
  418. const std::string& field_name,
  419. const std::vector<const char*>& valid_values) {
  420. const base::Value* list = object.FindListKey(field_name);
  421. if (!list)
  422. return true;
  423. path_.push_back(field_name);
  424. for (const auto& entry : list->GetListDeprecated()) {
  425. const std::string* value = entry.GetIfString();
  426. if (!value) {
  427. NOTREACHED(); // The types of field values are already verified.
  428. continue;
  429. }
  430. if (!IsValidValue(*value, valid_values)) {
  431. path_.pop_back();
  432. return false;
  433. }
  434. }
  435. path_.pop_back();
  436. return true;
  437. }
  438. bool Validator::ValidateSSIDAndHexSSID(base::Value* object) {
  439. const std::string kInvalidLength = "Invalid length";
  440. // Check SSID validity.
  441. std::string* ssid_string = object->FindStringKey(::onc::wifi::kSSID);
  442. if (ssid_string && (ssid_string->size() <= 0 ||
  443. ssid_string->size() > kMaximumSSIDLengthInBytes)) {
  444. path_.push_back(::onc::wifi::kSSID);
  445. std::ostringstream msg;
  446. msg << kInvalidLength;
  447. // If the HexSSID field is present, ignore errors in SSID because these
  448. // might be caused by the usage of a non-UTF-8 encoding when the SSID
  449. // field was automatically added (see FillInHexSSIDField).
  450. if (!object->FindKey(::onc::wifi::kHexSSID)) {
  451. AddValidationIssue(true /* is_error */, msg.str());
  452. path_.pop_back();
  453. return false;
  454. }
  455. AddValidationIssue(false /* is_error */, msg.str());
  456. path_.pop_back();
  457. }
  458. // Check HexSSID validity.
  459. std::string* hex_ssid_string = object->FindStringKey(::onc::wifi::kHexSSID);
  460. if (!hex_ssid_string)
  461. return true;
  462. std::string decoded_ssid;
  463. if (!base::HexStringToString(*hex_ssid_string, &decoded_ssid)) {
  464. path_.push_back(::onc::wifi::kHexSSID);
  465. std::ostringstream msg;
  466. msg << "Not a valid hex representation: '" << *hex_ssid_string << "'";
  467. AddValidationIssue(true /* is_error */, msg.str());
  468. path_.pop_back();
  469. return false;
  470. }
  471. if (decoded_ssid.size() <= 0 ||
  472. decoded_ssid.size() > kMaximumSSIDLengthInBytes) {
  473. path_.push_back(::onc::wifi::kHexSSID);
  474. std::ostringstream msg;
  475. msg << kInvalidLength;
  476. AddValidationIssue(true /* is_error */, msg.str());
  477. path_.pop_back();
  478. return false;
  479. }
  480. // If both SSID and HexSSID are set, check whether they are consistent, i.e.
  481. // HexSSID contains the UTF-8 encoding of SSID. If not, remove the SSID
  482. // field.
  483. if (ssid_string && ssid_string->length() > 0) {
  484. if (*ssid_string != decoded_ssid) {
  485. path_.push_back(::onc::wifi::kSSID);
  486. std::ostringstream msg;
  487. msg << "Fields '" << ::onc::wifi::kSSID << "' and '"
  488. << ::onc::wifi::kHexSSID << "' contain inconsistent values.";
  489. AddValidationIssue(false /* is_error */, msg.str());
  490. path_.pop_back();
  491. object->RemoveKey(::onc::wifi::kSSID);
  492. }
  493. }
  494. return true;
  495. }
  496. bool Validator::RequireField(const base::Value& dict,
  497. const std::string& field_name) {
  498. if (dict.FindKey(field_name))
  499. return true;
  500. std::ostringstream msg;
  501. msg << "The required field '" << field_name << "' is missing.";
  502. AddValidationIssue(error_on_missing_field_, msg.str());
  503. return false;
  504. }
  505. bool Validator::CheckGuidIsUniqueAndAddToSet(const base::Value& dict,
  506. const std::string& key_guid,
  507. std::set<std::string>* guids) {
  508. const std::string* guid = dict.FindStringKey(key_guid);
  509. if (!guid)
  510. return true;
  511. if (guids->count(*guid) != 0) {
  512. path_.push_back(key_guid);
  513. std::ostringstream msg;
  514. msg << "Found a duplicate GUID '" << *guid << "'.";
  515. AddValidationIssue(true /* is_error */, msg.str());
  516. path_.pop_back();
  517. return false;
  518. }
  519. guids->insert(*guid);
  520. return true;
  521. }
  522. bool Validator::IsGlobalNetworkConfigInUserImport(
  523. const base::Value& onc_object) {
  524. if (onc_source_ == ::onc::ONC_SOURCE_USER_IMPORT &&
  525. onc_object.FindKey(::onc::toplevel_config::kGlobalNetworkConfiguration)) {
  526. std::ostringstream msg;
  527. msg << "Field '" << ::onc::toplevel_config::kGlobalNetworkConfiguration
  528. << "' is prohibited in ONC user imports";
  529. AddValidationIssue(true /* is_error */, msg.str());
  530. return true;
  531. }
  532. return false;
  533. }
  534. bool Validator::ValidateToplevelConfiguration(base::Value* result) {
  535. const std::vector<const char*> valid_types = {
  536. ::onc::toplevel_config::kUnencryptedConfiguration,
  537. ::onc::toplevel_config::kEncryptedConfiguration};
  538. if (FieldExistsAndHasNoValidValue(*result, ::onc::toplevel_config::kType,
  539. valid_types))
  540. return false;
  541. if (IsGlobalNetworkConfigInUserImport(*result))
  542. return false;
  543. return true;
  544. }
  545. bool Validator::ValidateNetworkConfiguration(base::Value* result) {
  546. const std::string* onc_type =
  547. result->FindStringKey(::onc::network_config::kType);
  548. if (onc_type && *onc_type == ::onc::network_type::kWimaxDeprecated) {
  549. AddValidationIssue(/*is_error=*/false, "WiMax is deprecated");
  550. return true;
  551. }
  552. const std::vector<const char*> valid_types = {
  553. ::onc::network_type::kEthernet, ::onc::network_type::kVPN,
  554. ::onc::network_type::kWiFi, ::onc::network_type::kCellular,
  555. ::onc::network_type::kTether,
  556. };
  557. const std::vector<const char*> valid_ipconfig_types = {
  558. ::onc::network_config::kIPConfigTypeDHCP,
  559. ::onc::network_config::kIPConfigTypeStatic};
  560. if (FieldExistsAndHasNoValidValue(*result, ::onc::network_config::kType,
  561. valid_types) ||
  562. FieldExistsAndHasNoValidValue(*result,
  563. ::onc::network_config::kIPAddressConfigType,
  564. valid_ipconfig_types) ||
  565. FieldExistsAndHasNoValidValue(
  566. *result, ::onc::network_config::kNameServersConfigType,
  567. valid_ipconfig_types) ||
  568. FieldExistsAndIsEmpty(*result, ::onc::network_config::kGUID)) {
  569. return false;
  570. }
  571. if (!CheckGuidIsUniqueAndAddToSet(*result, ::onc::network_config::kGUID,
  572. &network_guids_))
  573. return false;
  574. bool all_required_exist = RequireField(*result, ::onc::network_config::kGUID);
  575. bool remove = result->FindBoolKey(::onc::kRemove).value_or(false);
  576. if (!remove) {
  577. all_required_exist &= RequireField(*result, ::onc::network_config::kName) &&
  578. RequireField(*result, ::onc::network_config::kType);
  579. if (!NetworkHasCorrectStaticIPConfig(result))
  580. return false;
  581. std::string type = GetStringFromDict(*result, ::onc::network_config::kType);
  582. // Prohibit anything but WiFi, Ethernet, VPN and Cellular for device-level
  583. // policy (which corresponds to shared networks). See also
  584. // http://crosbug.com/28741.
  585. if (onc_source_ == ::onc::ONC_SOURCE_DEVICE_POLICY && !type.empty() &&
  586. type != ::onc::network_type::kVPN &&
  587. type != ::onc::network_type::kWiFi &&
  588. type != ::onc::network_type::kEthernet &&
  589. type != ::onc::network_type::kCellular) {
  590. std::ostringstream msg;
  591. msg << "Networks of type '" << type
  592. << "' are prohibited in ONC device policies.";
  593. AddValidationIssue(true /* is_error */, msg.str());
  594. return false;
  595. }
  596. if (type == ::onc::network_type::kWiFi) {
  597. all_required_exist &= RequireField(*result, ::onc::network_config::kWiFi);
  598. } else if (type == ::onc::network_type::kEthernet) {
  599. all_required_exist &=
  600. RequireField(*result, ::onc::network_config::kEthernet);
  601. } else if (type == ::onc::network_type::kCellular) {
  602. all_required_exist &=
  603. RequireField(*result, ::onc::network_config::kCellular);
  604. } else if (type == ::onc::network_type::kWimaxDeprecated) {
  605. all_required_exist &=
  606. RequireField(*result, ::onc::network_config::kWimaxDeprecated);
  607. } else if (type == ::onc::network_type::kVPN) {
  608. all_required_exist &= RequireField(*result, ::onc::network_config::kVPN);
  609. } else if (type == ::onc::network_type::kTether) {
  610. all_required_exist &=
  611. RequireField(*result, ::onc::network_config::kTether);
  612. } else if (type == ::onc::network_type::kCellular) {
  613. all_required_exist &=
  614. RequireField(*result, ::onc::network_config::kCellular);
  615. }
  616. }
  617. return !error_on_missing_field_ || all_required_exist;
  618. }
  619. bool Validator::ValidateEthernet(base::Value* result) {
  620. const std::vector<const char*> valid_authentications = {
  621. ::onc::ethernet::kAuthenticationNone, ::onc::ethernet::k8021X};
  622. if (FieldExistsAndHasNoValidValue(*result, ::onc::ethernet::kAuthentication,
  623. valid_authentications)) {
  624. return false;
  625. }
  626. bool all_required_exist = true;
  627. std::string auth =
  628. GetStringFromDict(*result, ::onc::ethernet::kAuthentication);
  629. if (auth == ::onc::ethernet::k8021X)
  630. all_required_exist &= RequireField(*result, ::onc::ethernet::kEAP);
  631. return !error_on_missing_field_ || all_required_exist;
  632. }
  633. bool Validator::ValidateIPConfig(base::Value* result, bool require_fields) {
  634. const std::vector<const char*> valid_types = {::onc::ipconfig::kIPv4,
  635. ::onc::ipconfig::kIPv6};
  636. if (FieldExistsAndHasNoValidValue(*result, ::onc::ipconfig::kType,
  637. valid_types))
  638. return false;
  639. std::string type = GetStringFromDict(*result, ::onc::ipconfig::kType);
  640. int lower_bound = 1;
  641. // In case of missing type, choose higher upper_bound.
  642. int upper_bound = (type == ::onc::ipconfig::kIPv4) ? 32 : 128;
  643. if (FieldExistsAndIsNotInRange(*result, ::onc::ipconfig::kRoutingPrefix,
  644. lower_bound, upper_bound)) {
  645. return false;
  646. }
  647. bool all_required_exist = true;
  648. if (require_fields) {
  649. all_required_exist &= RequireField(*result, ::onc::ipconfig::kIPAddress);
  650. all_required_exist &=
  651. RequireField(*result, ::onc::ipconfig::kRoutingPrefix);
  652. all_required_exist &= RequireField(*result, ::onc::ipconfig::kGateway);
  653. } else {
  654. all_required_exist &=
  655. FieldShouldExistOrBeRecommended(*result, ::onc::ipconfig::kIPAddress);
  656. all_required_exist &= FieldShouldExistOrBeRecommended(
  657. *result, ::onc::ipconfig::kRoutingPrefix);
  658. all_required_exist &=
  659. FieldShouldExistOrBeRecommended(*result, ::onc::ipconfig::kGateway);
  660. }
  661. return !error_on_missing_field_ || all_required_exist;
  662. }
  663. bool Validator::NetworkHasCorrectStaticIPConfig(base::Value* network) {
  664. bool must_have_ip_config = FieldIsSetToValueOrRecommended(
  665. *network, ::onc::network_config::kIPAddressConfigType,
  666. base::Value(::onc::network_config::kIPConfigTypeStatic));
  667. bool must_have_nameservers = FieldIsSetToValueOrRecommended(
  668. *network, ::onc::network_config::kNameServersConfigType,
  669. base::Value(::onc::network_config::kIPConfigTypeStatic));
  670. if (!must_have_ip_config && !must_have_nameservers)
  671. return true;
  672. if (!RequireField(*network, ::onc::network_config::kStaticIPConfig))
  673. return false;
  674. base::Value* static_ip_config =
  675. network->FindDictKey(::onc::network_config::kStaticIPConfig);
  676. bool valid = true;
  677. // StaticIPConfig should have all fields required by the corresponding
  678. // IPAddressConfigType and NameServersConfigType values.
  679. if (must_have_ip_config)
  680. valid &= ValidateIPConfig(static_ip_config, false /* require_fields */);
  681. if (must_have_nameservers)
  682. valid &= FieldShouldExistOrBeRecommended(*static_ip_config,
  683. ::onc::ipconfig::kNameServers);
  684. return valid;
  685. }
  686. bool Validator::ValidateWiFi(base::Value* result) {
  687. const std::vector<const char*> valid_securities = {
  688. ::onc::wifi::kSecurityNone, ::onc::wifi::kWEP_PSK,
  689. ::onc::wifi::kWEP_8021X, ::onc::wifi::kWPA_PSK, ::onc::wifi::kWPA_EAP};
  690. if (FieldExistsAndHasNoValidValue(*result, ::onc::wifi::kSecurity,
  691. valid_securities))
  692. return false;
  693. if (!ValidateSSIDAndHexSSID(result))
  694. return false;
  695. bool all_required_exist = RequireField(*result, ::onc::wifi::kSecurity);
  696. // One of {kSSID, kHexSSID} must be present.
  697. if (!result->FindKey(::onc::wifi::kSSID))
  698. all_required_exist &= RequireField(*result, ::onc::wifi::kHexSSID);
  699. if (!result->FindKey(::onc::wifi::kHexSSID))
  700. all_required_exist &= RequireField(*result, ::onc::wifi::kSSID);
  701. std::string security = GetStringFromDict(*result, ::onc::wifi::kSecurity);
  702. if (security == ::onc::wifi::kWEP_8021X || security == ::onc::wifi::kWPA_EAP)
  703. all_required_exist &= RequireField(*result, ::onc::wifi::kEAP);
  704. else if (security == ::onc::wifi::kWEP_PSK ||
  705. security == ::onc::wifi::kWPA_PSK)
  706. all_required_exist &= RequireField(*result, ::onc::wifi::kPassphrase);
  707. return !error_on_missing_field_ || all_required_exist;
  708. }
  709. bool Validator::ValidateVPN(base::Value* result) {
  710. std::vector<const char*> valid_types = {
  711. ::onc::vpn::kIPsec,
  712. ::onc::vpn::kTypeL2TP_IPsec,
  713. ::onc::vpn::kOpenVPN,
  714. ::onc::vpn::kWireGuard,
  715. };
  716. if (!managed_onc_) {
  717. valid_types.push_back(::onc::vpn::kThirdPartyVpn);
  718. valid_types.push_back(::onc::vpn::kArcVpn);
  719. }
  720. if (FieldExistsAndHasNoValidValue(*result, ::onc::vpn::kType, valid_types))
  721. return false;
  722. bool all_required_exist = RequireField(*result, ::onc::vpn::kType);
  723. std::string type = GetStringFromDict(*result, ::onc::vpn::kType);
  724. if (type == ::onc::vpn::kOpenVPN) {
  725. all_required_exist &= RequireField(*result, ::onc::vpn::kOpenVPN);
  726. } else if (type == ::onc::vpn::kIPsec) {
  727. all_required_exist &= RequireField(*result, ::onc::vpn::kIPsec);
  728. } else if (type == ::onc::vpn::kTypeL2TP_IPsec) {
  729. all_required_exist &= RequireField(*result, ::onc::vpn::kIPsec) &&
  730. RequireField(*result, ::onc::vpn::kL2TP);
  731. } else if (type == ::onc::vpn::kWireGuard) {
  732. all_required_exist &= RequireField(*result, ::onc::vpn::kWireGuard);
  733. } else if (type == ::onc::vpn::kThirdPartyVpn) {
  734. all_required_exist &= RequireField(*result, ::onc::vpn::kThirdPartyVpn);
  735. } else if (type == ::onc::vpn::kArcVpn) {
  736. all_required_exist &= RequireField(*result, ::onc::vpn::kArcVpn);
  737. }
  738. return !error_on_missing_field_ || all_required_exist;
  739. }
  740. bool Validator::ValidateIPsec(base::Value* result) {
  741. const std::vector<const char*> valid_authentications = {
  742. ::onc::ipsec::kPSK, ::onc::ipsec::kCert, ::onc::ipsec::kEAP};
  743. if (FieldExistsAndHasNoValidValue(*result, ::onc::ipsec::kAuthenticationType,
  744. valid_authentications) ||
  745. FieldExistsAndIsEmpty(*result, ::onc::ipsec::kServerCARefs)) {
  746. return false;
  747. }
  748. if (!OnlyOneFieldSet(*result, ::onc::ipsec::kServerCARefs,
  749. ::onc::ipsec::kServerCARef))
  750. return false;
  751. if (!ValidateClientCertFields(/*allow_cert_type_none=*/false, result))
  752. return false;
  753. bool all_required_exist =
  754. RequireField(*result, ::onc::ipsec::kAuthenticationType) &&
  755. RequireField(*result, ::onc::ipsec::kIKEVersion);
  756. std::string auth =
  757. GetStringFromDict(*result, ::onc::ipsec::kAuthenticationType);
  758. if (auth == ::onc::ipsec::kCert) {
  759. all_required_exist &=
  760. RequireField(*result, ::onc::client_cert::kClientCertType);
  761. }
  762. // For cert-based or EAP-based authentication, server CA must exist.
  763. // For PSK-based authentication, server CA must not exist.
  764. bool has_server_ca_cert = result->FindKey(::onc::ipsec::kServerCARefs) ||
  765. result->FindKey(::onc::ipsec::kServerCARef) ||
  766. result->FindKey(::onc::ipsec::kServerCAPEMs);
  767. if ((auth == ::onc::ipsec::kCert || auth == ::onc::ipsec::kEAP) &&
  768. !has_server_ca_cert) {
  769. all_required_exist = false;
  770. std::ostringstream msg;
  771. msg << "Server CA config is missing (one of the fields "
  772. << ::onc::ipsec::kServerCARefs << " or " << ::onc::ipsec::kServerCAPEMs
  773. << ").";
  774. AddValidationIssue(error_on_missing_field_, msg.str());
  775. }
  776. if (auth == ::onc::ipsec::kPSK && has_server_ca_cert) {
  777. std::ostringstream msg;
  778. msg << "Field '" << ::onc::ipsec::kServerCARefs << "' (or '"
  779. << ::onc::ipsec::kServerCARef << "') can only be set if '"
  780. << ::onc::ipsec::kAuthenticationType << "' is set to '"
  781. << ::onc::ipsec::kCert << "'.";
  782. AddValidationIssue(true /* is_error */, msg.str());
  783. return false;
  784. }
  785. return !error_on_missing_field_ || all_required_exist;
  786. }
  787. bool Validator::ValidateOpenVPN(base::Value* result) {
  788. const std::vector<const char*> valid_auth_retry_values = {
  789. ::onc::openvpn::kNone, ::onc::openvpn::kInteract,
  790. ::onc::openvpn::kNoInteract};
  791. const std::vector<const char*> valid_cert_tls_values = {
  792. ::onc::openvpn::kNone, ::onc::openvpn::kServer};
  793. const std::vector<const char*> valid_compression_algorithm_values = {
  794. ::onc::openvpn_compression_algorithm::kFramingOnly,
  795. ::onc::openvpn_compression_algorithm::kLz4,
  796. ::onc::openvpn_compression_algorithm::kLz4V2,
  797. ::onc::openvpn_compression_algorithm::kLzo,
  798. ::onc::openvpn_compression_algorithm::kNone};
  799. const std::vector<const char*> valid_user_auth_types = {
  800. ::onc::openvpn_user_auth_type::kNone, ::onc::openvpn_user_auth_type::kOTP,
  801. ::onc::openvpn_user_auth_type::kPassword,
  802. ::onc::openvpn_user_auth_type::kPasswordAndOTP};
  803. if (FieldExistsAndHasNoValidValue(*result, ::onc::openvpn::kAuthRetry,
  804. valid_auth_retry_values) ||
  805. FieldExistsAndHasNoValidValue(*result, ::onc::openvpn::kRemoteCertTLS,
  806. valid_cert_tls_values) ||
  807. FieldExistsAndHasNoValidValue(*result,
  808. ::onc::openvpn::kCompressionAlgorithm,
  809. valid_compression_algorithm_values) ||
  810. FieldExistsAndHasNoValidValue(*result,
  811. ::onc::openvpn::kUserAuthenticationType,
  812. valid_user_auth_types) ||
  813. FieldExistsAndIsEmpty(*result, ::onc::openvpn::kServerCARefs)) {
  814. return false;
  815. }
  816. // ONC policy prevents the UI from setting properties that are not explicitly
  817. // listed as 'recommended' (i.e. the default is 'enforced'). Historically
  818. // the configuration UI ignored this restriction. In order to support legacy
  819. // ONC configurations, add recommended entries for user authentication
  820. // properties where appropriate.
  821. if ((onc_source_ == ::onc::ONC_SOURCE_DEVICE_POLICY ||
  822. onc_source_ == ::onc::ONC_SOURCE_USER_POLICY)) {
  823. base::Value* recommended =
  824. result->FindKeyOfType(::onc::kRecommended, base::Value::Type::LIST);
  825. if (!recommended)
  826. recommended = result->SetKey(::onc::kRecommended,
  827. base::Value(base::Value::Type::LIST));
  828. // If kUserAuthenticationType is unspecified, allow Password and OTP.
  829. if (!result->FindStringKey(::onc::openvpn::kUserAuthenticationType)) {
  830. AddKeyToList(::onc::openvpn::kPassword, recommended);
  831. AddKeyToList(::onc::openvpn::kOTP, recommended);
  832. }
  833. // If client cert type is not provided, empty, or 'None', allow client cert
  834. // properties.
  835. std::string client_cert_type =
  836. GetStringFromDict(*result, ::onc::client_cert::kClientCertType);
  837. if (client_cert_type.empty() ||
  838. client_cert_type == ::onc::client_cert::kClientCertTypeNone) {
  839. AddKeyToList(::onc::client_cert::kClientCertType, recommended);
  840. AddKeyToList(::onc::client_cert::kClientCertPKCS11Id, recommended);
  841. }
  842. }
  843. if (!OnlyOneFieldSet(*result, ::onc::openvpn::kServerCARefs,
  844. ::onc::openvpn::kServerCARef))
  845. return false;
  846. if (!ValidateClientCertFields(true /* allow ClientCertType None */, result))
  847. return false;
  848. bool all_required_exist =
  849. RequireField(*result, ::onc::client_cert::kClientCertType);
  850. return !error_on_missing_field_ || all_required_exist;
  851. }
  852. bool Validator::ValidateWireGuard(base::Value* result) {
  853. const base::Value* peers = result->FindKey(::onc::wireguard::kPeers);
  854. std::ostringstream msg;
  855. if (!peers->is_list()) {
  856. msg << "A " << ::onc::wireguard::kPeers
  857. << " list is required but not present.";
  858. AddValidationIssue(true /* is_error */, msg.str());
  859. return false;
  860. }
  861. for (const base::Value& p : peers->GetListDeprecated()) {
  862. if (!p.FindKey(::onc::wireguard::kPublicKey)) {
  863. msg << ::onc::wireguard::kPublicKey
  864. << " field is required for each peer.";
  865. AddValidationIssue(true /* is_error */, msg.str());
  866. return false;
  867. }
  868. }
  869. const bool all_required_exist =
  870. RequireField(*result, ::onc::wireguard::kEndpoint);
  871. return !error_on_missing_field_ || all_required_exist;
  872. }
  873. bool Validator::ValidateThirdPartyVPN(base::Value* result) {
  874. const bool all_required_exist =
  875. RequireField(*result, ::onc::third_party_vpn::kExtensionID);
  876. return !error_on_missing_field_ || all_required_exist;
  877. }
  878. bool Validator::ValidateARCVPN(base::Value* result) {
  879. const bool all_required_exist =
  880. RequireField(*result, ::onc::arc_vpn::kTunnelChrome);
  881. return !error_on_missing_field_ || all_required_exist;
  882. }
  883. bool Validator::ValidateVerifyX509(base::Value* result) {
  884. const std::vector<const char*> valid_types = {
  885. ::onc::verify_x509::types::kName, ::onc::verify_x509::types::kNamePrefix,
  886. ::onc::verify_x509::types::kSubject};
  887. if (FieldExistsAndHasNoValidValue(*result, ::onc::verify_x509::kType,
  888. valid_types))
  889. return false;
  890. bool all_required_exist = RequireField(*result, ::onc::verify_x509::kName);
  891. return !error_on_missing_field_ || all_required_exist;
  892. }
  893. bool Validator::ValidateCertificatePattern(base::Value* result) {
  894. bool all_required_exist = true;
  895. if (!result->FindKey(::onc::client_cert::kSubject) &&
  896. !result->FindKey(::onc::client_cert::kIssuer) &&
  897. !result->FindKey(::onc::client_cert::kIssuerCARef)) {
  898. all_required_exist = false;
  899. std::ostringstream msg;
  900. msg << "None of the fields '" << ::onc::client_cert::kSubject << "', '"
  901. << ::onc::client_cert::kIssuer << "', and '"
  902. << ::onc::client_cert::kIssuerCARef
  903. << "' is present, but at least one is required.";
  904. AddValidationIssue(error_on_missing_field_, msg.str());
  905. }
  906. return !error_on_missing_field_ || all_required_exist;
  907. }
  908. bool Validator::ValidateGlobalNetworkConfiguration(base::Value* result) {
  909. // Replace the deprecated kBlacklistedHexSSIDs with kBlockedHexSSIDs.
  910. if (!result->FindKey(::onc::global_network_config::kBlockedHexSSIDs)) {
  911. absl::optional<base::Value> blocked =
  912. result->ExtractKey(::onc::global_network_config::kBlacklistedHexSSIDs);
  913. if (blocked) {
  914. result->SetKey(::onc::global_network_config::kBlockedHexSSIDs,
  915. std::move(*blocked));
  916. }
  917. }
  918. // Validate that kAllowCellularSimLock, kDisableNetworkTypes,
  919. // kAllowOnlyPolicyWiFiToConnect, kAllowOnlyPolicyCellularNetworks and
  920. // kBlockedHexSSIDs are only allowed in device policy.
  921. if (!IsInDevicePolicy(result,
  922. ::onc ::global_network_config::kAllowCellularSimLock) ||
  923. !IsInDevicePolicy(result,
  924. ::onc::global_network_config::kDisableNetworkTypes) ||
  925. !IsInDevicePolicy(
  926. result,
  927. ::onc::global_network_config::kAllowOnlyPolicyCellularNetworks) ||
  928. !IsInDevicePolicy(
  929. result,
  930. ::onc::global_network_config::kAllowOnlyPolicyWiFiToConnect) ||
  931. !IsInDevicePolicy(result, ::onc::global_network_config::
  932. kAllowOnlyPolicyWiFiToConnectIfAvailable) ||
  933. !IsInDevicePolicy(result,
  934. ::onc::global_network_config::kBlockedHexSSIDs)) {
  935. return false;
  936. }
  937. // Ensure the list contains only legitimate network type identifiers.
  938. const std::vector<const char*> valid_network_type_values = {
  939. ::onc::network_config::kCellular, ::onc::network_config::kEthernet,
  940. ::onc::network_config::kTether, ::onc::network_config::kWiFi,
  941. ::onc::network_config::kVPN, ::onc::network_config::kWimaxDeprecated,
  942. };
  943. if (!ListFieldContainsValidValues(
  944. *result, ::onc::global_network_config::kDisableNetworkTypes,
  945. valid_network_type_values)) {
  946. return false;
  947. }
  948. return true;
  949. }
  950. bool Validator::ValidateProxySettings(base::Value* result) {
  951. const std::vector<const char*> valid_types = {
  952. ::onc::proxy::kDirect, ::onc::proxy::kManual, ::onc::proxy::kPAC,
  953. ::onc::proxy::kWPAD};
  954. if (FieldExistsAndHasNoValidValue(*result, ::onc::proxy::kType, valid_types))
  955. return false;
  956. bool all_required_exist = RequireField(*result, ::onc::proxy::kType);
  957. std::string type = GetStringFromDict(*result, ::onc::proxy::kType);
  958. if (type == ::onc::proxy::kManual)
  959. all_required_exist &= RequireField(*result, ::onc::proxy::kManual);
  960. else if (type == ::onc::proxy::kPAC)
  961. all_required_exist &= RequireField(*result, ::onc::proxy::kPAC);
  962. return !error_on_missing_field_ || all_required_exist;
  963. }
  964. bool Validator::ValidateProxyLocation(base::Value* result) {
  965. bool all_required_exist = RequireField(*result, ::onc::proxy::kHost) &&
  966. RequireField(*result, ::onc::proxy::kPort);
  967. return !error_on_missing_field_ || all_required_exist;
  968. }
  969. bool Validator::ValidateEAP(base::Value* result) {
  970. const std::vector<const char*> valid_inner_values = {
  971. ::onc::eap::kAutomatic, ::onc::eap::kGTC, ::onc::eap::kMD5,
  972. ::onc::eap::kMSCHAPv2, ::onc::eap::kPAP};
  973. std::vector<const char*> valid_outer_values = {
  974. ::onc::eap::kPEAP, ::onc::eap::kEAP_TLS, ::onc::eap::kEAP_TTLS,
  975. ::onc::eap::kLEAP, ::onc::eap::kEAP_SIM, ::onc::eap::kEAP_FAST,
  976. ::onc::eap::kEAP_AKA};
  977. // If this EAP dict is in a IPsec dict (i.e., IPsec is the second-to-last
  978. // element in its path), the only valid method is MSCHAPv2.
  979. if (path_.size() >= 2) {
  980. auto it = std::next(path_.rbegin());
  981. if (*it == ::onc::vpn::kIPsec)
  982. valid_outer_values = {::onc::eap::kMSCHAPv2};
  983. }
  984. if (FieldExistsAndHasNoValidValue(*result, ::onc::eap::kInner,
  985. valid_inner_values) ||
  986. FieldExistsAndHasNoValidValue(*result, ::onc::eap::kOuter,
  987. valid_outer_values) ||
  988. FieldExistsAndIsEmpty(*result, ::onc::eap::kServerCARefs)) {
  989. return false;
  990. }
  991. if (!OnlyOneFieldSet(*result, ::onc::eap::kServerCARefs,
  992. ::onc::eap::kServerCARef))
  993. return false;
  994. if (!ValidateClientCertFields(true /* allow ClientCertType None */, result))
  995. return false;
  996. bool all_required_exist = RequireField(*result, ::onc::eap::kOuter);
  997. return !error_on_missing_field_ || all_required_exist;
  998. }
  999. bool Validator::ValidateSubjectAlternativeNameMatch(base::Value* result) {
  1000. const std::vector<const char*> valid_types = {
  1001. ::onc::eap_subject_alternative_name_match::kEMAIL,
  1002. ::onc::eap_subject_alternative_name_match::kDNS,
  1003. ::onc::eap_subject_alternative_name_match::kURI};
  1004. if (FieldExistsAndHasNoValidValue(
  1005. *result, ::onc::eap_subject_alternative_name_match::kType,
  1006. valid_types)) {
  1007. return false;
  1008. }
  1009. bool all_required_exist =
  1010. RequireField(*result, ::onc::eap_subject_alternative_name_match::kType) &&
  1011. RequireField(*result, ::onc::eap_subject_alternative_name_match::kValue);
  1012. return !error_on_missing_field_ || all_required_exist;
  1013. }
  1014. bool Validator::ValidateCertificate(base::Value* result) {
  1015. const std::vector<const char*> valid_types = {::onc::certificate::kClient,
  1016. ::onc::certificate::kServer,
  1017. ::onc::certificate::kAuthority};
  1018. if (FieldExistsAndHasNoValidValue(*result, ::onc::certificate::kType,
  1019. valid_types) ||
  1020. FieldExistsAndIsEmpty(*result, ::onc::certificate::kGUID)) {
  1021. return false;
  1022. }
  1023. std::string type = GetStringFromDict(*result, ::onc::certificate::kType);
  1024. if (!CheckGuidIsUniqueAndAddToSet(*result, ::onc::certificate::kGUID,
  1025. &certificate_guids_))
  1026. return false;
  1027. bool all_required_exist = RequireField(*result, ::onc::certificate::kGUID);
  1028. bool remove = result->FindBoolKey(::onc::kRemove).value_or(false);
  1029. if (remove) {
  1030. path_.push_back(::onc::kRemove);
  1031. std::ostringstream msg;
  1032. msg << "Removal of certificates is not supported.";
  1033. AddValidationIssue(true /* is_error */, msg.str());
  1034. path_.pop_back();
  1035. return false;
  1036. }
  1037. all_required_exist &= RequireField(*result, ::onc::certificate::kType);
  1038. if (type == ::onc::certificate::kClient)
  1039. all_required_exist &= RequireField(*result, ::onc::certificate::kPKCS12);
  1040. else if (type == ::onc::certificate::kServer ||
  1041. type == ::onc::certificate::kAuthority)
  1042. all_required_exist &= RequireField(*result, ::onc::certificate::kX509);
  1043. return !error_on_missing_field_ || all_required_exist;
  1044. }
  1045. bool Validator::ValidateScope(base::Value* result) {
  1046. const std::vector<const char*> valid_types = {::onc::scope::kDefault,
  1047. ::onc::scope::kExtension};
  1048. if (FieldExistsAndHasNoValidValue(*result, ::onc::scope::kType,
  1049. valid_types) ||
  1050. FieldExistsAndIsEmpty(*result, ::onc::scope::kId)) {
  1051. return false;
  1052. }
  1053. bool all_required_exist = RequireField(*result, ::onc::scope::kType);
  1054. const std::string* type_string = result->FindStringKey(::onc::scope::kType);
  1055. if (type_string && *type_string == ::onc::scope::kExtension) {
  1056. all_required_exist &= RequireField(*result, ::onc::scope::kId);
  1057. // Check Id validity for type 'Extension'.
  1058. const std::string* id_string = result->FindStringKey(::onc::scope::kId);
  1059. if (id_string && !crx_file::id_util::IdIsValid(*id_string)) {
  1060. std::ostringstream msg;
  1061. msg << "Field '" << ::onc::scope::kId << "' is not a valid extension id.";
  1062. AddValidationIssue(false /* is_error */, msg.str());
  1063. return false;
  1064. }
  1065. }
  1066. return !error_on_missing_field_ || all_required_exist;
  1067. }
  1068. bool Validator::ValidateTether(base::Value* result) {
  1069. if (FieldExistsAndIsNotInRange(*result, ::onc::tether::kBatteryPercentage, 0,
  1070. 100) ||
  1071. FieldExistsAndIsNotInRange(*result, ::onc::tether::kSignalStrength, 0,
  1072. 100) ||
  1073. FieldExistsAndIsEmpty(*result, ::onc::tether::kCarrier)) {
  1074. return false;
  1075. }
  1076. bool all_required_exist =
  1077. RequireField(*result, ::onc::tether::kHasConnectedToHost);
  1078. all_required_exist &=
  1079. RequireField(*result, ::onc::tether::kBatteryPercentage);
  1080. all_required_exist &= RequireField(*result, ::onc::tether::kSignalStrength);
  1081. all_required_exist &= RequireField(*result, ::onc::tether::kCarrier);
  1082. return !error_on_missing_field_ || all_required_exist;
  1083. }
  1084. void Validator::AddValidationIssue(bool is_error,
  1085. const std::string& debug_info) {
  1086. std::ostringstream msg;
  1087. msg << (is_error ? "ERROR: " : "WARNING: ") << debug_info << " (at "
  1088. << (path_.empty() ? "toplevel" : base::JoinString(path_, ".")) << ")";
  1089. std::string message = msg.str();
  1090. if (is_error)
  1091. NET_LOG(ERROR) << message;
  1092. else if (log_warnings_)
  1093. NET_LOG(DEBUG) << message;
  1094. validation_issues_.push_back({is_error, message});
  1095. }
  1096. } // namespace onc
  1097. } // namespace chromeos