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

Side by Side Diff: chromeos/network/onc/onc_utils.cc

Issue 1228543002: Translate ONC ProxySettings <-> Shill ProxyConfig (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add Proxy PAC tests Created 5 years, 5 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "chromeos/network/onc/onc_utils.h" 5 #include "chromeos/network/onc/onc_utils.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chromeos/network/network_event_log.h" 14 #include "chromeos/network/network_event_log.h"
15 #include "chromeos/network/onc/onc_mapper.h" 15 #include "chromeos/network/onc/onc_mapper.h"
16 #include "chromeos/network/onc/onc_signature.h" 16 #include "chromeos/network/onc/onc_signature.h"
17 #include "chromeos/network/onc/onc_utils.h" 17 #include "chromeos/network/onc/onc_utils.h"
18 #include "chromeos/network/onc/onc_validator.h" 18 #include "chromeos/network/onc/onc_validator.h"
19 #include "components/device_event_log/device_event_log.h" 19 #include "components/device_event_log/device_event_log.h"
20 #include "components/proxy_config/proxy_config_dictionary.h"
20 #include "crypto/encryptor.h" 21 #include "crypto/encryptor.h"
21 #include "crypto/hmac.h" 22 #include "crypto/hmac.h"
22 #include "crypto/symmetric_key.h" 23 #include "crypto/symmetric_key.h"
24 #include "net/base/host_port_pair.h"
23 #include "net/cert/pem_tokenizer.h" 25 #include "net/cert/pem_tokenizer.h"
24 #include "net/cert/x509_certificate.h" 26 #include "net/cert/x509_certificate.h"
27 #include "net/proxy/proxy_bypass_rules.h"
28 #include "net/proxy/proxy_config.h"
29 #include "net/proxy/proxy_server.h"
30 #include "url/url_constants.h"
25 31
26 using namespace ::onc; 32 using namespace ::onc;
27 33
28 namespace chromeos { 34 namespace chromeos {
29 namespace onc { 35 namespace onc {
30 36
31 namespace { 37 namespace {
32 38
33 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC"; 39 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC";
34 const char kUnableToDecode[] = "Unable to decode encrypted ONC"; 40 const char kUnableToDecode[] = "Unable to decode encrypted ONC";
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 property_basename = property_key; 737 property_basename = property_key;
732 recommended_property_key = ::onc::kRecommended; 738 recommended_property_key = ::onc::kRecommended;
733 } 739 }
734 740
735 const base::ListValue* recommended_keys = nullptr; 741 const base::ListValue* recommended_keys = nullptr;
736 return (onc->GetList(recommended_property_key, &recommended_keys) && 742 return (onc->GetList(recommended_property_key, &recommended_keys) &&
737 recommended_keys->Find(base::StringValue(property_basename)) != 743 recommended_keys->Find(base::StringValue(property_basename)) !=
738 recommended_keys->end()); 744 recommended_keys->end());
739 } 745 }
740 746
747 namespace {
748
749 const char kSocksScheme[] = "socks";
750
751 net::ProxyServer ConvertOncProxyLocationToHostPort(
752 net::ProxyServer::Scheme default_proxy_scheme,
753 const base::DictionaryValue& onc_proxy_location) {
754 std::string host;
755 onc_proxy_location.GetStringWithoutPathExpansion(::onc::proxy::kHost, &host);
756 // Parse |host| according to the format [<scheme>"://"]<server>[":"<port>].
757 net::ProxyServer proxy_server =
758 net::ProxyServer::FromURI(host, default_proxy_scheme);
eroman 2015/07/08 21:26:38 Parsing might fail, in which case proxy_server wil
stevenjb 2015/07/08 22:13:08 Theoretically, ONC validation should ensure that t
759 int port = 0;
760 onc_proxy_location.GetIntegerWithoutPathExpansion(::onc::proxy::kPort, &port);
761
762 // Replace the port parsed from |host| by the provided |port|.
763 return net::ProxyServer(
764 proxy_server.scheme(),
765 net::HostPortPair(proxy_server.host_port_pair().host(),
eroman 2015/07/08 21:26:38 proxy_server may be invalid, in which case calling
stevenjb 2015/07/08 22:13:08 Since the scheme is invalid, the host_port_pair va
eroman 2015/07/13 20:08:38 It will hit a DCHECK in ProxyServer::host_port_pai
766 static_cast<uint16>(port)));
eroman 2015/07/08 21:26:38 possibility of underflow. Is the input considered
stevenjb 2015/07/08 22:13:08 The ONC input should be validated already. Otherwi
pneubeck (no reviews) 2015/07/09 07:20:32 The port of the proxy location isn't validated cur
stevenjb 2015/07/09 18:24:28 Probably. Currently we seem to at least be clampin
767 }
768
769 void AppendProxyServerForScheme(const base::DictionaryValue& onc_manual,
770 const std::string& onc_scheme,
771 std::string* spec) {
772 const base::DictionaryValue* onc_proxy_location = nullptr;
773 if (!onc_manual.GetDictionaryWithoutPathExpansion(onc_scheme,
774 &onc_proxy_location)) {
775 return;
776 }
777
778 net::ProxyServer::Scheme default_proxy_scheme = net::ProxyServer::SCHEME_HTTP;
779 std::string url_scheme;
780 if (onc_scheme == ::onc::proxy::kFtp) {
781 url_scheme = url::kFtpScheme;
782 } else if (onc_scheme == ::onc::proxy::kHttp) {
783 url_scheme = url::kHttpScheme;
784 } else if (onc_scheme == ::onc::proxy::kHttps) {
785 url_scheme = url::kHttpsScheme;
786 } else if (onc_scheme == ::onc::proxy::kSocks) {
787 default_proxy_scheme = net::ProxyServer::SCHEME_SOCKS4;
788 url_scheme = kSocksScheme;
789 } else {
790 NOTREACHED();
791 }
792
793 net::ProxyServer proxy_server = ConvertOncProxyLocationToHostPort(
794 default_proxy_scheme, *onc_proxy_location);
795
796 ProxyConfigDictionary::EncodeAndAppendProxyServer(url_scheme, proxy_server,
797 spec);
798 }
799
800 net::ProxyBypassRules ConvertOncExcludeDomainsToBypassRules(
801 const base::ListValue& onc_exclude_domains) {
802 net::ProxyBypassRules rules;
803 for (base::ListValue::const_iterator it = onc_exclude_domains.begin();
804 it != onc_exclude_domains.end(); ++it) {
805 std::string rule;
806 (*it)->GetAsString(&rule);
807 rules.AddRuleFromString(rule);
808 }
809 return rules;
810 }
811
812 void SetProxyForScheme(const net::ProxyConfig::ProxyRules& proxy_rules,
813 const std::string& scheme,
814 const std::string& onc_scheme,
815 base::DictionaryValue* dict) {
816 const net::ProxyList* proxy_list = nullptr;
817 if (proxy_rules.type == net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY) {
818 proxy_list = &proxy_rules.single_proxies;
819 } else if (proxy_rules.type ==
820 net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) {
821 proxy_list = proxy_rules.MapUrlSchemeToProxyList(scheme);
822 }
823 if (!proxy_list || proxy_list->IsEmpty())
824 return;
825 const net::ProxyServer& server = proxy_list->Get();
826 scoped_ptr<base::DictionaryValue> url_dict(new base::DictionaryValue);
827 std::string host = server.host_port_pair().host();
828 // Special case: Include the scheme for socks5 only. For all proxy types
829 // except SOCKS, the default scheme of the proxy host is HTTP and we do not
830 // prefix the host.
831 if (server.scheme() == net::ProxyServer::SCHEME_SOCKS5)
832 host = "socks5://" + host;
833 url_dict->SetStringWithoutPathExpansion(::onc::proxy::kHost, host);
834 url_dict->SetIntegerWithoutPathExpansion(::onc::proxy::kPort,
835 server.host_port_pair().port());
836 dict->SetWithoutPathExpansion(onc_scheme, url_dict.release());
837 }
838
839 } // namespace
840
841 scoped_ptr<base::DictionaryValue> ConvertOncProxySettingsToProxyConfig(
842 const base::DictionaryValue& onc_proxy_settings) {
843 std::string type;
844 onc_proxy_settings.GetStringWithoutPathExpansion(::onc::proxy::kType, &type);
845 scoped_ptr<base::DictionaryValue> proxy_dict;
846
847 if (type == ::onc::proxy::kDirect) {
848 proxy_dict.reset(ProxyConfigDictionary::CreateDirect());
849 } else if (type == ::onc::proxy::kWPAD) {
850 proxy_dict.reset(ProxyConfigDictionary::CreateAutoDetect());
851 } else if (type == ::onc::proxy::kPAC) {
852 std::string pac_url;
853 onc_proxy_settings.GetStringWithoutPathExpansion(::onc::proxy::kPAC,
854 &pac_url);
855 GURL url(pac_url);
856 DCHECK(url.is_valid()) << "Invalid URL in ProxySettings.PAC";
857 proxy_dict.reset(ProxyConfigDictionary::CreatePacScript(url.spec(), false));
858 } else if (type == ::onc::proxy::kManual) {
859 const base::DictionaryValue* manual_dict = nullptr;
860 onc_proxy_settings.GetDictionaryWithoutPathExpansion(::onc::proxy::kManual,
eroman 2015/07/08 21:26:38 The error checking throughout is pretty weak. For
stevenjb 2015/07/08 22:13:08 Here ONC validation will definitely ensure that if
861 &manual_dict);
862 std::string manual_spec;
863 AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kFtp, &manual_spec);
864 AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kHttp, &manual_spec);
865 AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kSocks,
866 &manual_spec);
867 AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kHttps,
868 &manual_spec);
869
870 const base::ListValue* exclude_domains = nullptr;
871 net::ProxyBypassRules bypass_rules;
872 if (onc_proxy_settings.GetListWithoutPathExpansion(
873 ::onc::proxy::kExcludeDomains, &exclude_domains)) {
874 bypass_rules.AssignFrom(
875 ConvertOncExcludeDomainsToBypassRules(*exclude_domains));
876 }
877 proxy_dict.reset(ProxyConfigDictionary::CreateFixedServers(
878 manual_spec, bypass_rules.ToString()));
879 } else {
880 NOTREACHED();
881 }
882 return proxy_dict.Pass();
883 }
884
885 scoped_ptr<base::DictionaryValue> ConvertProxyConfigToOncProxySettings(
886 const base::DictionaryValue& proxy_config_value) {
887 // Create a ProxyConfigDictionary from the DictionaryValue.
888 scoped_ptr<ProxyConfigDictionary> proxy_config(
889 new ProxyConfigDictionary(&proxy_config_value));
890
891 // Create the result DictionaryValue and populate it.
892 scoped_ptr<base::DictionaryValue> proxy_settings(new base::DictionaryValue);
893 ProxyPrefs::ProxyMode mode;
894 if (!proxy_config->GetMode(&mode))
895 return nullptr;
896 switch (mode) {
897 case ProxyPrefs::MODE_DIRECT: {
898 proxy_settings->SetStringWithoutPathExpansion(::onc::proxy::kType,
899 ::onc::proxy::kDirect);
900 break;
901 }
902 case ProxyPrefs::MODE_AUTO_DETECT: {
903 proxy_settings->SetStringWithoutPathExpansion(::onc::proxy::kType,
904 ::onc::proxy::kWPAD);
905 break;
906 }
907 case ProxyPrefs::MODE_PAC_SCRIPT: {
908 proxy_settings->SetStringWithoutPathExpansion(::onc::proxy::kType,
909 ::onc::proxy::kPAC);
910 std::string pac_url;
911 proxy_config->GetPacUrl(&pac_url);
912 proxy_settings->SetStringWithoutPathExpansion(::onc::proxy::kPAC,
913 pac_url);
914 break;
915 }
916 case ProxyPrefs::MODE_FIXED_SERVERS: {
917 proxy_settings->SetString(::onc::proxy::kType, ::onc::proxy::kManual);
918 scoped_ptr<base::DictionaryValue> manual(new base::DictionaryValue);
919 std::string proxy_rules_string;
920 if (proxy_config->GetProxyServer(&proxy_rules_string)) {
921 net::ProxyConfig::ProxyRules proxy_rules;
922 proxy_rules.ParseFromString(proxy_rules_string);
923 SetProxyForScheme(proxy_rules, url::kFtpScheme, ::onc::proxy::kFtp,
924 manual.get());
925 SetProxyForScheme(proxy_rules, url::kHttpScheme, ::onc::proxy::kHttp,
926 manual.get());
927 SetProxyForScheme(proxy_rules, url::kHttpsScheme, ::onc::proxy::kHttps,
928 manual.get());
929 SetProxyForScheme(proxy_rules, kSocksScheme, ::onc::proxy::kSocks,
930 manual.get());
931 }
932 proxy_settings->SetWithoutPathExpansion(::onc::proxy::kManual,
933 manual.release());
934
935 // Convert the 'bypass_list' string into dictionary entries.
936 std::string bypass_rules_string;
937 if (proxy_config->GetBypassList(&bypass_rules_string)) {
938 net::ProxyBypassRules bypass_rules;
939 bypass_rules.ParseFromString(bypass_rules_string);
940 scoped_ptr<base::ListValue> exclude_domains(new base::ListValue);
941 for (const net::ProxyBypassRules::Rule* rule : bypass_rules.rules())
942 exclude_domains->AppendString(rule->ToString());
943 if (!exclude_domains->empty()) {
944 proxy_settings->SetWithoutPathExpansion(::onc::proxy::kExcludeDomains,
945 exclude_domains.release());
946 }
947 }
948 break;
949 }
950 default: {
951 LOG(ERROR) << "Unexpected proxy mode in Shill config: " << mode;
952 return nullptr;
953 }
954 }
955 return proxy_settings.Pass();
956 }
957
741 } // namespace onc 958 } // namespace onc
742 } // namespace chromeos 959 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698