Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / renderer_host / pepper / pepper_socket_utils.cc
blob4b70dedd2c8496c1ab8d3376ee7484d294de962f
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.
5 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
7 #include <string>
8 #include <vector>
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/strings/string_util.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/content_browser_client.h"
15 #include "content/public/browser/render_frame_host.h"
16 #include "content/public/browser/site_instance.h"
17 #include "content/public/common/content_client.h"
18 #include "net/base/ip_endpoint.h"
19 #include "net/cert/x509_certificate.h"
20 #include "ppapi/c/private/ppb_net_address_private.h"
21 #include "ppapi/shared_impl/private/net_address_private_impl.h"
22 #include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
24 #if defined(OS_CHROMEOS)
25 #include "chromeos/network/firewall_hole.h"
26 #endif // defined(OS_CHROMEOS)
28 namespace content {
29 namespace pepper_socket_utils {
31 SocketPermissionRequest CreateSocketPermissionRequest(
32 SocketPermissionRequest::OperationType type,
33 const PP_NetAddress_Private& net_addr) {
34 std::string host =
35 ppapi::NetAddressPrivateImpl::DescribeNetAddress(net_addr, false);
36 uint16 port = 0;
37 std::vector<unsigned char> address;
38 ppapi::NetAddressPrivateImpl::NetAddressToIPEndPoint(
39 net_addr, &address, &port);
40 return SocketPermissionRequest(type, host, port);
43 bool CanUseSocketAPIs(bool external_plugin,
44 bool private_api,
45 const SocketPermissionRequest* params,
46 int render_process_id,
47 int render_frame_id) {
48 DCHECK_CURRENTLY_ON(BrowserThread::UI);
49 if (!external_plugin) {
50 // Always allow socket APIs for out-process plugins (other than external
51 // plugins instantiated by the embedder through
52 // BrowserPpapiHost::CreateExternalPluginProcess).
53 return true;
56 RenderFrameHost* render_frame_host =
57 RenderFrameHost::FromID(render_process_id, render_frame_id);
58 if (!render_frame_host)
59 return false;
60 SiteInstance* site_instance = render_frame_host->GetSiteInstance();
61 if (!site_instance)
62 return false;
63 if (!GetContentClient()->browser()->AllowPepperSocketAPI(
64 site_instance->GetBrowserContext(),
65 site_instance->GetSiteURL(),
66 private_api,
67 params)) {
68 LOG(ERROR) << "Host " << site_instance->GetSiteURL().host()
69 << " cannot use socket API or destination is not allowed";
70 return false;
73 return true;
76 bool GetCertificateFields(const net::X509Certificate& cert,
77 ppapi::PPB_X509Certificate_Fields* fields) {
78 const net::CertPrincipal& issuer = cert.issuer();
79 fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COMMON_NAME,
80 new base::StringValue(issuer.common_name));
81 fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_LOCALITY_NAME,
82 new base::StringValue(issuer.locality_name));
83 fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_STATE_OR_PROVINCE_NAME,
84 new base::StringValue(issuer.state_or_province_name));
85 fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COUNTRY_NAME,
86 new base::StringValue(issuer.country_name));
87 fields->SetField(
88 PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_NAME,
89 new base::StringValue(base::JoinString(issuer.organization_names, "\n")));
90 fields->SetField(
91 PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_UNIT_NAME,
92 new base::StringValue(
93 base::JoinString(issuer.organization_unit_names, "\n")));
95 const net::CertPrincipal& subject = cert.subject();
96 fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COMMON_NAME,
97 new base::StringValue(subject.common_name));
98 fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_LOCALITY_NAME,
99 new base::StringValue(subject.locality_name));
100 fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_STATE_OR_PROVINCE_NAME,
101 new base::StringValue(subject.state_or_province_name));
102 fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COUNTRY_NAME,
103 new base::StringValue(subject.country_name));
104 fields->SetField(
105 PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_NAME,
106 new base::StringValue(
107 base::JoinString(subject.organization_names, "\n")));
108 fields->SetField(
109 PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_UNIT_NAME,
110 new base::StringValue(
111 base::JoinString(subject.organization_unit_names, "\n")));
113 const std::string& serial_number = cert.serial_number();
114 fields->SetField(PP_X509CERTIFICATE_PRIVATE_SERIAL_NUMBER,
115 base::BinaryValue::CreateWithCopiedBuffer(
116 serial_number.data(), serial_number.length()));
117 fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_BEFORE,
118 new base::FundamentalValue(cert.valid_start().ToDoubleT()));
119 fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_AFTER,
120 new base::FundamentalValue(cert.valid_expiry().ToDoubleT()));
121 std::string der;
122 net::X509Certificate::GetDEREncoded(cert.os_cert_handle(), &der);
123 fields->SetField(
124 PP_X509CERTIFICATE_PRIVATE_RAW,
125 base::BinaryValue::CreateWithCopiedBuffer(der.data(), der.length()));
126 return true;
129 bool GetCertificateFields(const char* der,
130 uint32_t length,
131 ppapi::PPB_X509Certificate_Fields* fields) {
132 scoped_refptr<net::X509Certificate> cert =
133 net::X509Certificate::CreateFromBytes(der, length);
134 if (!cert.get())
135 return false;
136 return GetCertificateFields(*cert.get(), fields);
139 #if defined(OS_CHROMEOS)
140 namespace {
142 const unsigned char kIPv4Empty[] = {0, 0, 0, 0};
143 const unsigned char kIPv6Empty[] =
144 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
145 const unsigned char kIPv6Loopback[] =
146 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
148 bool isLoopbackAddress(const net::IPAddressNumber& address) {
149 if (address.size() == net::kIPv4AddressSize) {
150 // The entire IPv4 subnet 127.0.0.0/8 is for loopback. See RFC3330.
151 return address[0] == 0x7f;
152 } else if (address.size() == net::kIPv6AddressSize) {
153 // ::1 is the only loopback address in ipv6.
154 return std::equal(&kIPv6Loopback[0], &kIPv6Loopback[net::kIPv6AddressSize],
155 address.begin());
157 return false;
160 std::string addressToFirewallString(const net::IPAddressNumber& address) {
161 if (address.empty()) {
162 return std::string();
164 if (address.size() == net::kIPv4AddressSize &&
165 std::equal(&kIPv4Empty[0], &kIPv4Empty[net::kIPv4AddressSize],
166 address.begin())) {
167 return std::string();
169 if (address.size() == net::kIPv6AddressSize &&
170 std::equal(&kIPv6Empty[0], &kIPv6Empty[net::kIPv6AddressSize],
171 address.begin())) {
172 return std::string();
175 return net::IPAddressToString(address);
178 } // namespace
180 void OpenFirewallHole(const net::IPEndPoint& address,
181 chromeos::FirewallHole::PortType type,
182 FirewallHoleOpenCallback callback) {
183 if (isLoopbackAddress(address.address())) {
184 callback.Run(nullptr);
185 return;
187 std::string address_string = addressToFirewallString(address.address());
189 chromeos::FirewallHole::Open(type, address.port(), address_string, callback);
192 void OpenTCPFirewallHole(const net::IPEndPoint& address,
193 FirewallHoleOpenCallback callback) {
194 OpenFirewallHole(address, chromeos::FirewallHole::PortType::TCP, callback);
197 void OpenUDPFirewallHole(const net::IPEndPoint& address,
198 FirewallHoleOpenCallback callback) {
199 OpenFirewallHole(address, chromeos::FirewallHole::PortType::UDP, callback);
201 #endif // defined(OS_CHROMEOS)
203 } // namespace pepper_socket_utils
204 } // namespace content