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

Side by Side Diff: chrome/browser/chromeos/network_settings/onc_validator.cc

Issue 11299236: This moves the ONC parsing code into chromeos/network/onc (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix unit tests Created 8 years 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
OLDNEW
(Empty)
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
5 #include "chrome/browser/chromeos/network_settings/onc_validator.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "base/logging.h"
11 #include "base/string_util.h"
12 #include "base/values.h"
13 #include "chrome/browser/chromeos/cros/onc_constants.h"
14 #include "chrome/browser/chromeos/network_settings/onc_signature.h"
15
16 namespace chromeos {
17 namespace onc {
18
19 Validator::Validator(
20 bool error_on_unknown_field,
21 bool error_on_wrong_recommended,
22 bool error_on_missing_field,
23 bool managed_onc)
24 : error_on_unknown_field_(error_on_unknown_field),
25 error_on_wrong_recommended_(error_on_wrong_recommended),
26 error_on_missing_field_(error_on_missing_field),
27 managed_onc_(managed_onc) {
28 }
29
30 Validator::~Validator() {
31 }
32
33 scoped_ptr<base::DictionaryValue> Validator::ValidateAndRepairObject(
34 const OncValueSignature* object_signature,
35 const base::DictionaryValue& onc_object) {
36 CHECK(object_signature != NULL);
37 scoped_ptr<base::Value> result_value =
38 MapValue(*object_signature, onc_object);
39 base::DictionaryValue* result_dict = NULL;
40 if (result_value.get() != NULL) {
41 result_value.release()->GetAsDictionary(&result_dict);
42 CHECK(result_dict != NULL);
43 }
44
45 return make_scoped_ptr(result_dict);
46 }
47
48 scoped_ptr<base::Value> Validator::MapValue(
49 const OncValueSignature& signature,
50 const base::Value& onc_value) {
51 if (onc_value.GetType() != signature.onc_type) {
52 DVLOG(1) << "Wrong type. Expected " << signature.onc_type
53 << ", but found " << onc_value.GetType();
54 return scoped_ptr<base::Value>();
55 }
56
57 scoped_ptr<base::Value> repaired = Mapper::MapValue(signature, onc_value);
58 if (repaired.get() != NULL)
59 CHECK_EQ(repaired->GetType(), signature.onc_type);
60 return repaired.Pass();
61 }
62
63 scoped_ptr<base::DictionaryValue> Validator::MapObject(
64 const OncValueSignature& signature,
65 const base::DictionaryValue& onc_object) {
66 scoped_ptr<base::DictionaryValue> repaired(new base::DictionaryValue);
67
68 bool valid;
69 if (&signature == &kNetworkConfigurationSignature)
70 valid = ValidateNetworkConfiguration(onc_object, repaired.get());
71 else if (&signature == &kEthernetSignature)
72 valid = ValidateEthernet(onc_object, repaired.get());
73 else if (&signature == &kIPConfigSignature)
74 valid = ValidateIPConfig(onc_object, repaired.get());
75 else if (&signature == &kWiFiSignature)
76 valid = ValidateWiFi(onc_object, repaired.get());
77 else if (&signature == &kVPNSignature)
78 valid = ValidateVPN(onc_object, repaired.get());
79 else if (&signature == &kIPsecSignature)
80 valid = ValidateIPsec(onc_object, repaired.get());
81 else if (&signature == &kOpenVPNSignature)
82 valid = ValidateOpenVPN(onc_object, repaired.get());
83 else if (&signature == &kCertificatePatternSignature)
84 valid = ValidateCertificatePattern(onc_object, repaired.get());
85 else if (&signature == &kProxySettingsSignature)
86 valid = ValidateProxySettings(onc_object, repaired.get());
87 else if (&signature == &kProxyLocationSignature)
88 valid = ValidateProxyLocation(onc_object, repaired.get());
89 else if (&signature == &kEAPSignature)
90 valid = ValidateEAP(onc_object, repaired.get());
91 else if (&signature == &kCertificateSignature)
92 valid = ValidateCertificate(onc_object, repaired.get());
93 else
94 valid = ValidateObjectDefault(signature, onc_object, repaired.get());
95
96 if (valid)
97 return repaired.Pass();
98 else
99 return scoped_ptr<base::DictionaryValue>();
100 }
101
102 bool Validator::ValidateObjectDefault(
103 const OncValueSignature& signature,
104 const base::DictionaryValue& onc_object,
105 base::DictionaryValue* result) {
106 bool found_unknown_field = false;
107 bool nested_error_occured = false;
108 MapFields(signature, onc_object, &found_unknown_field, &nested_error_occured,
109 result);
110 if (nested_error_occured)
111 return false;
112
113 if (found_unknown_field) {
114 if (error_on_unknown_field_) {
115 DVLOG(1) << "Unknown field name. Aborting.";
116 return false;
117 }
118 DVLOG(1) << "Unknown field name. Ignoring.";
119 }
120
121 return ValidateRecommendedField(signature, result);
122 }
123
124 bool Validator::ValidateRecommendedField(
125 const OncValueSignature& object_signature,
126 base::DictionaryValue* result) {
127 CHECK(result != NULL);
128
129 scoped_ptr<base::ListValue> recommended;
130 base::Value* recommended_value;
131 // This remove passes ownership to |recommended_value|.
132 if (!result->RemoveWithoutPathExpansion(onc::kRecommended,
133 &recommended_value)) {
134 return true;
135 }
136 base::ListValue* recommended_list;
137 recommended_value->GetAsList(&recommended_list);
138 CHECK(recommended_list != NULL);
139
140 recommended.reset(recommended_list);
141
142 if (!managed_onc_) {
143 DVLOG(1) << "Found a " << onc::kRecommended
144 << " field in unmanaged ONC. Removing it.";
145 return true;
146 }
147
148 scoped_ptr<base::ListValue> repaired_recommended(new base::ListValue);
149 for (base::ListValue::iterator it = recommended->begin();
150 it != recommended->end(); ++it) {
151 std::string field_name;
152 if (!(*it)->GetAsString(&field_name)) {
153 NOTREACHED();
154 continue;
155 }
156
157 const OncFieldSignature* field_signature =
158 GetFieldSignature(object_signature, field_name);
159
160 bool found_error = false;
161 std::string error_cause;
162 if (field_signature == NULL) {
163 found_error = true;
164 error_cause = "unknown";
165 } else if (field_signature->value_signature->onc_type ==
166 base::Value::TYPE_DICTIONARY) {
167 found_error = true;
168 error_cause = "dictionary-typed";
169 }
170
171 if (found_error) {
172 DVLOG(1) << "Found " << error_cause << " field name '" << field_name
173 << "' in kRecommended array. "
174 << (error_on_wrong_recommended_ ? "Aborting." : "Ignoring.");
175 if (error_on_wrong_recommended_)
176 return false;
177 else
178 continue;
179 }
180
181 repaired_recommended->Append((*it)->DeepCopy());
182 }
183
184 result->Set(onc::kRecommended, repaired_recommended.release());
185 return true;
186 }
187
188 namespace {
189
190 std::string JoinStringRange(const char** range_begin,
191 const char** range_end,
192 const std::string& separator) {
193 std::vector<std::string> string_vector;
194 std::copy(range_begin, range_end, std::back_inserter(string_vector));
195 return JoinString(string_vector, separator);
196 }
197
198 bool RequireAnyOf(const std::string &actual, const char** valid_values) {
199 const char** it = valid_values;
200 for (; *it != NULL; ++it) {
201 if (actual == *it)
202 return true;
203 }
204 DVLOG(1) << "Found " << actual << ", but expected one of "
205 << JoinStringRange(valid_values, it, ", ");
206 return false;
207 }
208
209 bool IsInRange(int actual, int lower_bound, int upper_bound) {
210 if (lower_bound <= actual && actual <= upper_bound)
211 return true;
212 DVLOG(1) << "Found " << actual << ", which is out of range [" << lower_bound
213 << ", " << upper_bound << "]";
214 return false;
215 }
216
217 bool RequireField(const base::DictionaryValue& dict, std::string key) {
218 if (dict.HasKey(key))
219 return true;
220 DVLOG(1) << "Required field " << key << " missing.";
221 return false;
222 }
223
224 } // namespace
225
226 bool Validator::ValidateNetworkConfiguration(
227 const base::DictionaryValue& onc_object,
228 base::DictionaryValue* result) {
229 if (!ValidateObjectDefault(kNetworkConfigurationSignature,
230 onc_object, result)) {
231 return false;
232 }
233
234 std::string type;
235 static const char* kValidTypes[] = { kEthernet, kVPN, kWiFi, NULL };
236 if (result->GetStringWithoutPathExpansion(kType, &type) &&
237 !RequireAnyOf(type, kValidTypes)) {
238 return false;
239 }
240
241 bool allRequiredExist = RequireField(*result, kGUID);
242
243 bool remove = false;
244 result->GetBooleanWithoutPathExpansion(kRemove, &remove);
245 if (!remove) {
246 allRequiredExist &= RequireField(*result, kName);
247 allRequiredExist &= RequireField(*result, kType);
248 allRequiredExist &= type.empty() || RequireField(*result, type);
249 }
250
251 return !error_on_missing_field_ || allRequiredExist;
252 }
253
254 bool Validator::ValidateEthernet(
255 const base::DictionaryValue& onc_object,
256 base::DictionaryValue* result) {
257 using namespace onc::ethernet;
258 if (!ValidateObjectDefault(kEthernetSignature, onc_object, result))
259 return false;
260
261 std::string auth;
262 static const char* kValidAuthentications[] = { kNone, k8021X, NULL };
263 if (result->GetStringWithoutPathExpansion(kAuthentication, &auth) &&
264 !RequireAnyOf(auth, kValidAuthentications)) {
265 return false;
266 }
267
268 bool allRequiredExist = true;
269 if (auth == k8021X)
270 allRequiredExist &= RequireField(*result, kEAP);
271
272 return !error_on_missing_field_ || allRequiredExist;
273 }
274
275 bool Validator::ValidateIPConfig(
276 const base::DictionaryValue& onc_object,
277 base::DictionaryValue* result) {
278 using namespace onc::ipconfig;
279 if (!ValidateObjectDefault(kIPConfigSignature, onc_object, result))
280 return false;
281
282 std::string type;
283 static const char* kValidTypes[] = { kIPv4, kIPv6, NULL };
284 if (result->GetStringWithoutPathExpansion(ipconfig::kType, &type) &&
285 !RequireAnyOf(type, kValidTypes)) {
286 return false;
287 }
288
289 int routing_prefix;
290 int lower_bound = 1;
291 // In case of missing type, choose higher upper_bound.
292 int upper_bound = (type == kIPv4) ? 32 : 128;
293 if (result->GetIntegerWithoutPathExpansion(kRoutingPrefix, &routing_prefix) &&
294 !IsInRange(routing_prefix, lower_bound, upper_bound)) {
295 return false;
296 }
297
298 bool allRequiredExist = RequireField(*result, kIPAddress) &
299 RequireField(*result, kRoutingPrefix) &
300 RequireField(*result, ipconfig::kType);
301
302 return !error_on_missing_field_ || allRequiredExist;
303 }
304
305 bool Validator::ValidateWiFi(
306 const base::DictionaryValue& onc_object,
307 base::DictionaryValue* result) {
308 using namespace onc::wifi;
309 if (!ValidateObjectDefault(kWiFiSignature, onc_object, result))
310 return false;
311
312 std::string security;
313 static const char* kValidSecurities[] =
314 { kNone, kWEP_PSK, kWEP_8021X, kWPA_PSK, kWPA_EAP, NULL };
315 if (result->GetStringWithoutPathExpansion(kSecurity, &security) &&
316 !RequireAnyOf(security, kValidSecurities)) {
317 return false;
318 }
319
320 bool allRequiredExist = RequireField(*result, kSecurity) &
321 RequireField(*result, kSSID);
322 if (security == kWEP_8021X || security == kWPA_EAP)
323 allRequiredExist &= RequireField(*result, kEAP);
324 else if (security == kWEP_PSK || security == kWPA_PSK)
325 allRequiredExist &= RequireField(*result, kPassphrase);
326
327 return !error_on_missing_field_ || allRequiredExist;
328 }
329
330 bool Validator::ValidateVPN(
331 const base::DictionaryValue& onc_object,
332 base::DictionaryValue* result) {
333 using namespace vpn;
334 if (!ValidateObjectDefault(kVPNSignature, onc_object, result))
335 return false;
336
337 std::string type;
338 static const char* kValidTypes[] =
339 { kIPsec, kTypeL2TP_IPsec, kOpenVPN, NULL };
340 if (result->GetStringWithoutPathExpansion(vpn::kType, &type) &&
341 !RequireAnyOf(type, kValidTypes)) {
342 return false;
343 }
344
345 bool allRequiredExist = RequireField(*result, vpn::kType);
346
347 if (type == kOpenVPN) {
348 allRequiredExist &= RequireField(*result, kOpenVPN);
349 } else if (type == kIPsec) {
350 allRequiredExist &= RequireField(*result, kIPsec);
351 } else if (type == kTypeL2TP_IPsec) {
352 allRequiredExist &= RequireField(*result, kIPsec) &
353 RequireField(*result, kL2TP);
354 }
355
356 return !error_on_missing_field_ || allRequiredExist;
357 }
358
359 bool Validator::ValidateIPsec(
360 const base::DictionaryValue& onc_object,
361 base::DictionaryValue* result) {
362 using namespace onc::vpn;
363 using namespace onc::certificate;
364 if (!ValidateObjectDefault(kIPsecSignature, onc_object, result))
365 return false;
366
367 std::string auth;
368 static const char* kValidAuthentications[] = { kPSK, kCert, NULL };
369 if (result->GetStringWithoutPathExpansion(kAuthenticationType, &auth) &&
370 !RequireAnyOf(auth, kValidAuthentications)) {
371 return false;
372 }
373
374 std::string cert_type;
375 static const char* kValidCertTypes[] = { kRef, kPattern, NULL };
376 if (result->GetStringWithoutPathExpansion(kClientCertType, &cert_type) &&
377 !RequireAnyOf(cert_type, kValidCertTypes)) {
378 return false;
379 }
380
381 bool allRequiredExist = RequireField(*result, kAuthenticationType) &
382 RequireField(*result, kIKEVersion);
383 if (auth == kCert) {
384 allRequiredExist &= RequireField(*result, kClientCertType) &
385 RequireField(*result, kServerCARef);
386 }
387 if (cert_type == kPattern)
388 allRequiredExist &= RequireField(*result, kClientCertPattern);
389 else if (cert_type == kRef)
390 allRequiredExist &= RequireField(*result, kClientCertRef);
391
392 return !error_on_missing_field_ || allRequiredExist;
393 }
394
395 bool Validator::ValidateOpenVPN(
396 const base::DictionaryValue& onc_object,
397 base::DictionaryValue* result) {
398 using namespace onc::vpn;
399 using namespace onc::openvpn;
400 using namespace onc::certificate;
401 if (!ValidateObjectDefault(kOpenVPNSignature, onc_object, result))
402 return false;
403
404 std::string auth_retry;
405 static const char* kValidAuthRetryValues[] =
406 { openvpn::kNone, kInteract, kNoInteract, NULL };
407 if (result->GetStringWithoutPathExpansion(kAuthRetry, &auth_retry) &&
408 !RequireAnyOf(auth_retry, kValidAuthRetryValues)) {
409 return false;
410 }
411
412 std::string cert_type;
413 static const char* kValidCertTypes[] =
414 { certificate::kNone, kRef, kPattern, NULL };
415 if (result->GetStringWithoutPathExpansion(kClientCertType, &cert_type) &&
416 !RequireAnyOf(cert_type, kValidCertTypes)) {
417 return false;
418 }
419
420 std::string cert_tls;
421 static const char* kValidCertTlsValues[] =
422 { openvpn::kNone, openvpn::kServer, NULL };
423 if (result->GetStringWithoutPathExpansion(kRemoteCertTLS, &cert_tls) &&
424 !RequireAnyOf(cert_tls, kValidCertTlsValues)) {
425 return false;
426 }
427
428 bool allRequiredExist = RequireField(*result, kClientCertType);
429 if (cert_type == kPattern)
430 allRequiredExist &= RequireField(*result, kClientCertPattern);
431 else if (cert_type == kRef)
432 allRequiredExist &= RequireField(*result, kClientCertRef);
433
434 return !error_on_missing_field_ || allRequiredExist;
435 }
436
437 bool Validator::ValidateCertificatePattern(
438 const base::DictionaryValue& onc_object,
439 base::DictionaryValue* result) {
440 using namespace onc::certificate;
441 if (!ValidateObjectDefault(kCertificatePatternSignature, onc_object, result))
442 return false;
443
444 bool allRequiredExist = true;
445 if (!result->HasKey(kSubject) && !result->HasKey(kIssuer) &&
446 !result->HasKey(kIssuerCARef)) {
447 allRequiredExist = false;
448 DVLOG(1) << "None of the fields " << kSubject << ", " << kIssuer << ", and "
449 << kIssuerCARef << " exists, but at least one is required.";
450 }
451
452 return !error_on_missing_field_ || allRequiredExist;
453 }
454
455 bool Validator::ValidateProxySettings(const base::DictionaryValue& onc_object,
456 base::DictionaryValue* result) {
457 using namespace onc::proxy;
458 if (!ValidateObjectDefault(kProxySettingsSignature, onc_object, result))
459 return false;
460
461 std::string type;
462 static const char* kValidTypes[] = { kDirect, kManual, kPAC, kWPAD, NULL };
463 if (result->GetStringWithoutPathExpansion(proxy::kType, &type) &&
464 !RequireAnyOf(type, kValidTypes)) {
465 return false;
466 }
467
468 bool allRequiredExist = RequireField(*result, proxy::kType);
469
470 if (type == kManual)
471 allRequiredExist &= RequireField(*result, kManual);
472 else if (type == kPAC)
473 allRequiredExist &= RequireField(*result, kPAC);
474
475 return !error_on_missing_field_ || allRequiredExist;
476 }
477
478 bool Validator::ValidateProxyLocation(const base::DictionaryValue& onc_object,
479 base::DictionaryValue* result) {
480 using namespace onc::proxy;
481 if (!ValidateObjectDefault(kProxyLocationSignature, onc_object, result))
482 return false;
483
484 bool allRequiredExist = RequireField(*result, kHost) &
485 RequireField(*result, kPort);
486
487 return !error_on_missing_field_ || allRequiredExist;
488 }
489
490 bool Validator::ValidateEAP(const base::DictionaryValue& onc_object,
491 base::DictionaryValue* result) {
492 using namespace onc::eap;
493 using namespace onc::certificate;
494 if (!ValidateObjectDefault(kEAPSignature, onc_object, result))
495 return false;
496
497 std::string inner;
498 static const char* kValidInnerValues[] =
499 { kAutomatic, kMD5, kMSCHAPv2, kPAP, NULL };
500 if (result->GetStringWithoutPathExpansion(kInner, &inner) &&
501 !RequireAnyOf(inner, kValidInnerValues)) {
502 return false;
503 }
504
505 std::string outer;
506 static const char* kValidOuterValues[] =
507 { kPEAP, kEAP_TLS, kEAP_TTLS, kLEAP, kEAP_SIM, kEAP_FAST, kEAP_AKA,
508 NULL };
509 if (result->GetStringWithoutPathExpansion(kOuter, &outer) &&
510 !RequireAnyOf(outer, kValidOuterValues)) {
511 return false;
512 }
513
514 std::string cert_type;
515 static const char* kValidCertTypes[] = { kRef, kPattern, NULL };
516 if (result->GetStringWithoutPathExpansion(kClientCertType, &cert_type) &&
517 !RequireAnyOf(cert_type, kValidCertTypes )) {
518 return false;
519 }
520
521 bool allRequiredExist = RequireField(*result, kOuter);
522
523 if (cert_type == kPattern)
524 allRequiredExist &= RequireField(*result, kClientCertPattern);
525 else if (cert_type == kRef)
526 allRequiredExist &= RequireField(*result, kClientCertRef);
527
528 return !error_on_missing_field_ || allRequiredExist;
529 }
530
531 bool Validator::ValidateCertificate(
532 const base::DictionaryValue& onc_object,
533 base::DictionaryValue* result) {
534 using namespace onc::certificate;
535 if (!ValidateObjectDefault(kCertificateSignature, onc_object, result))
536 return false;
537
538 std::string type;
539 static const char* kValidTypes[] = { kClient, kServer, kAuthority, NULL };
540 if (result->GetStringWithoutPathExpansion(certificate::kType, &type) &&
541 !RequireAnyOf(type, kValidTypes)) {
542 return false;
543 }
544
545 bool allRequiredExist = RequireField(*result, kGUID);
546
547 bool remove = false;
548 result->GetBooleanWithoutPathExpansion(kRemove, &remove);
549 if (!remove) {
550 allRequiredExist &= RequireField(*result, certificate::kType);
551
552 if (type == kClient)
553 allRequiredExist &= RequireField(*result, kPKCS12);
554 else if (type == kServer || type == kAuthority)
555 allRequiredExist &= RequireField(*result, kX509);
556 }
557
558 return !error_on_missing_field_ || allRequiredExist;
559 }
560
561 } // namespace onc
562 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698