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

Side by Side Diff: chrome/browser/extensions/api/cast_channel/cast_channel_api.cc

Issue 255443002: Implement argument validation for chrome.cast.channel.{open,send} (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix issues with prior patch. More test cases for Send. Created 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "chrome/browser/extensions/api/cast_channel/cast_channel_api.h" 5 #include "chrome/browser/extensions/api/cast_channel/cast_channel_api.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <string>
8 9
9 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
10 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
12 #include "base/values.h" 13 #include "base/values.h"
13 #include "chrome/browser/browser_process.h" 14 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h" 15 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h"
15 #include "chrome/browser/net/chrome_net_log.h" 16 #include "chrome/browser/net/chrome_net_log.h"
16 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
17 #include "extensions/browser/event_router.h" 18 #include "extensions/browser/event_router.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 channel_info->channel_id = socket.id(); 54 channel_info->channel_id = socket.id();
54 channel_info->url = socket.CastUrl(); 55 channel_info->url = socket.CastUrl();
55 const net::IPEndPoint& ip_endpoint = socket.ip_endpoint(); 56 const net::IPEndPoint& ip_endpoint = socket.ip_endpoint();
56 channel_info->connect_info.ip_address = ip_endpoint.ToStringWithoutPort(); 57 channel_info->connect_info.ip_address = ip_endpoint.ToStringWithoutPort();
57 channel_info->connect_info.port = ip_endpoint.port(); 58 channel_info->connect_info.port = ip_endpoint.port();
58 channel_info->connect_info.auth = socket.channel_auth(); 59 channel_info->connect_info.auth = socket.channel_auth();
59 channel_info->ready_state = socket.ready_state(); 60 channel_info->ready_state = socket.ready_state();
60 channel_info->error_state = socket.error_state(); 61 channel_info->error_state = socket.error_state();
61 } 62 }
62 63
64 bool IsValidConnectInfoPort(const ConnectInfo& connect_info) {
65 return connect_info.port > 0 && connect_info.port <
66 std::numeric_limits<unsigned short>::max();
67 }
68
69 bool IsValidConnectInfoAuth(const ConnectInfo& connect_info) {
70 return connect_info.auth == cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED ||
71 connect_info.auth == cast_channel::CHANNEL_AUTH_TYPE_SSL;
72 }
73
74 bool IsValidConnectInfoIpAddress(const ConnectInfo& connect_info) {
75 net::IPAddressNumber ip_address;
76 return net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address);
77 }
78
63 } // namespace 79 } // namespace
64 80
65 CastChannelAPI::CastChannelAPI(content::BrowserContext* context) 81 CastChannelAPI::CastChannelAPI(content::BrowserContext* context)
66 : browser_context_(context) { 82 : browser_context_(context) {
67 DCHECK(browser_context_); 83 DCHECK(browser_context_);
68 } 84 }
69 85
70 // static 86 // static
71 CastChannelAPI* CastChannelAPI::Get(content::BrowserContext* context) { 87 CastChannelAPI* CastChannelAPI::Get(content::BrowserContext* context) {
72 return BrowserContextKeyedAPIFactory<CastChannelAPI>::Get(context); 88 return BrowserContextKeyedAPIFactory<CastChannelAPI>::Get(context);
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 VLOG(2) << "IP: " << ip_address_str << " Port: " << port_str; 253 VLOG(2) << "IP: " << ip_address_str << " Port: " << port_str;
238 int port; 254 int port;
239 if (!base::StringToInt(port_str, &port)) 255 if (!base::StringToInt(port_str, &port))
240 return false; 256 return false;
241 connect_info->ip_address = ip_address_str; 257 connect_info->ip_address = ip_address_str;
242 connect_info->port = port; 258 connect_info->port = port;
243 connect_info->auth = auth_required ? 259 connect_info->auth = auth_required ?
244 cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED : 260 cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED :
245 cast_channel::CHANNEL_AUTH_TYPE_SSL; 261 cast_channel::CHANNEL_AUTH_TYPE_SSL;
246 return true; 262 return true;
247 }; 263 }
248 264
249 net::IPEndPoint* CastChannelOpenFunction::ParseConnectInfo( 265 net::IPEndPoint* CastChannelOpenFunction::ParseConnectInfo(
250 const ConnectInfo& connect_info) { 266 const ConnectInfo& connect_info) {
251 net::IPAddressNumber ip_address; 267 net::IPAddressNumber ip_address;
252 if (!net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address)) { 268 CHECK(net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address));
253 return NULL;
254 }
255 if (connect_info.port < 0 || connect_info.port >
256 std::numeric_limits<unsigned short>::max()) {
257 return NULL;
258 }
259 if (connect_info.auth != cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED &&
260 connect_info.auth != cast_channel::CHANNEL_AUTH_TYPE_SSL) {
261 return NULL;
262 }
263 return new net::IPEndPoint(ip_address, connect_info.port); 269 return new net::IPEndPoint(ip_address, connect_info.port);
264 } 270 }
265 271
266 bool CastChannelOpenFunction::PrePrepare() { 272 bool CastChannelOpenFunction::PrePrepare() {
267 api_ = CastChannelAPI::Get(browser_context()); 273 api_ = CastChannelAPI::Get(browser_context());
268 return CastChannelAsyncApiFunction::PrePrepare(); 274 return CastChannelAsyncApiFunction::PrePrepare();
269 } 275 }
270 276
271 bool CastChannelOpenFunction::Prepare() { 277 bool CastChannelOpenFunction::Prepare() {
272 params_ = Open::Params::Create(*args_); 278 params_ = Open::Params::Create(*args_);
273 EXTENSION_FUNCTION_VALIDATE(params_.get()); 279 EXTENSION_FUNCTION_VALIDATE(params_.get());
274 // The connect_info parameter may be a string URL like cast:// or casts:// or 280 // The connect_info parameter may be a string URL like cast:// or casts:// or
275 // a ConnectInfo object. 281 // a ConnectInfo object.
276 std::string cast_url; 282 std::string cast_url;
283 bool is_connect_info_url = false;
284 bool is_connect_info_dict = false;
277 switch (params_->connect_info->GetType()) { 285 switch (params_->connect_info->GetType()) {
278 case base::Value::TYPE_STRING: 286 case base::Value::TYPE_STRING:
287 is_connect_info_url = true;
279 CHECK(params_->connect_info->GetAsString(&cast_url)); 288 CHECK(params_->connect_info->GetAsString(&cast_url));
280 connect_info_.reset(new ConnectInfo); 289 connect_info_.reset(new ConnectInfo);
281 if (!ParseChannelUrl(GURL(cast_url), connect_info_.get())) { 290 if (!ParseChannelUrl(GURL(cast_url), connect_info_.get())) {
282 connect_info_.reset(); 291 connect_info_.reset();
283 } 292 }
284 break; 293 break;
285 case base::Value::TYPE_DICTIONARY: 294 case base::Value::TYPE_DICTIONARY:
295 is_connect_info_dict = true;
286 connect_info_ = ConnectInfo::FromValue(*(params_->connect_info)); 296 connect_info_ = ConnectInfo::FromValue(*(params_->connect_info));
287 break; 297 break;
288 default: 298 default:
289 break; 299 break;
290 } 300 }
291 if (connect_info_.get()) { 301
292 channel_auth_ = connect_info_->auth; 302 DCHECK(!is_connect_info_dict || !is_connect_info_url);
293 ip_endpoint_.reset(ParseConnectInfo(*connect_info_)); 303 if (!connect_info_.get()) {
294 return ip_endpoint_.get() != NULL; 304 if (!is_connect_info_dict && !is_connect_info_url) {
305 SetError("Invalid connect_info (unknown type)");
Wez 2014/07/17 21:16:47 This can just go in the default: case, surely?
mark a. foltz 2014/07/17 22:23:40 Done.
306 } else if (is_connect_info_dict) {
307 SetError("connect_info.auth is required");
Wez 2014/07/17 21:16:47 I was actually thinking we could just get rid of t
mark a. foltz 2014/07/17 22:23:40 FromValue() is generated code that can't be change
308 } else {
309 SetError("Invalid connect_info (invalid Cast URL " + cast_url + ")");
Wez 2014/07/17 21:16:47 This could go in the TYPE_STRING failure block, if
mark a. foltz 2014/07/17 22:23:40 Done.
310 }
311 return false;
295 } 312 }
296 return false; 313
314 if (!IsValidConnectInfoPort(*connect_info_)) {
315 SetError("Invalid connect_info (invalid port)");
316 } else if (!IsValidConnectInfoAuth(*connect_info_)) {
317 SetError("Invalid connect_info (invalid auth)");
318 } else if (!IsValidConnectInfoIpAddress(*connect_info_)) {
319 SetError("Invalid connect_info (invalid IP address)");
320 }
321 if (!GetError().empty()) {
322 return false;
323 }
324 channel_auth_ = connect_info_->auth;
325 ip_endpoint_.reset(ParseConnectInfo(*connect_info_));
326 return true;
297 } 327 }
298 328
299 void CastChannelOpenFunction::AsyncWorkStart() { 329 void CastChannelOpenFunction::AsyncWorkStart() {
300 DCHECK(api_); 330 DCHECK(api_);
301 DCHECK(ip_endpoint_.get()); 331 DCHECK(ip_endpoint_.get());
302 scoped_ptr<CastSocket> socket = api_->CreateCastSocket( 332 scoped_ptr<CastSocket> socket = api_->CreateCastSocket(
303 extension_->id(), *ip_endpoint_, channel_auth_); 333 extension_->id(), *ip_endpoint_, channel_auth_);
304 new_channel_id_ = AddSocket(socket.release()); 334 new_channel_id_ = AddSocket(socket.release());
305 GetSocket(new_channel_id_)->Connect( 335 GetSocket(new_channel_id_)->Connect(
306 base::Bind(&CastChannelOpenFunction::OnOpen, this)); 336 base::Bind(&CastChannelOpenFunction::OnOpen, this));
307 } 337 }
308 338
309 void CastChannelOpenFunction::OnOpen(int result) { 339 void CastChannelOpenFunction::OnOpen(int result) {
310 DCHECK_CURRENTLY_ON(BrowserThread::IO); 340 DCHECK_CURRENTLY_ON(BrowserThread::IO);
311 SetResultFromSocket(new_channel_id_); 341 SetResultFromSocket(new_channel_id_);
312 AsyncWorkCompleted(); 342 AsyncWorkCompleted();
313 } 343 }
314 344
315 CastChannelSendFunction::CastChannelSendFunction() { } 345 CastChannelSendFunction::CastChannelSendFunction() { }
316 346
317 CastChannelSendFunction::~CastChannelSendFunction() { } 347 CastChannelSendFunction::~CastChannelSendFunction() { }
318 348
319 bool CastChannelSendFunction::Prepare() { 349 bool CastChannelSendFunction::Prepare() {
320 params_ = Send::Params::Create(*args_); 350 params_ = Send::Params::Create(*args_);
321 EXTENSION_FUNCTION_VALIDATE(params_.get()); 351 EXTENSION_FUNCTION_VALIDATE(params_.get());
352 if (params_->message.namespace_.empty()) {
353 SetError("message_info.namespace_ is required");
354 return false;
355 }
356 if (params_->message.source_id.empty()) {
357 SetError("message_info.source_id is required");
358 return false;
359 }
360 if (params_->message.destination_id.empty()) {
361 SetError("message_info.destination_id is required");
362 return false;
363 }
364 switch (params_->message.data->GetType()) {
365 case base::Value::TYPE_STRING:
366 case base::Value::TYPE_BINARY:
367 break;
368 default:
369 SetError("Invalid type of message_info.data");
370 return false;
371 }
322 return true; 372 return true;
323 } 373 }
324 374
325 void CastChannelSendFunction::AsyncWorkStart() { 375 void CastChannelSendFunction::AsyncWorkStart() {
326 CastSocket* socket = GetSocketOrCompleteWithError( 376 CastSocket* socket = GetSocketOrCompleteWithError(
327 params_->channel.channel_id); 377 params_->channel.channel_id);
328 if (socket) 378 if (socket)
329 socket->SendMessage(params_->message, 379 socket->SendMessage(params_->message,
330 base::Bind(&CastChannelSendFunction::OnSend, this)); 380 base::Bind(&CastChannelSendFunction::OnSend, this));
331 } 381 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR); 414 SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR);
365 } else { 415 } else {
366 int channel_id = params_->channel.channel_id; 416 int channel_id = params_->channel.channel_id;
367 SetResultFromSocket(channel_id); 417 SetResultFromSocket(channel_id);
368 RemoveSocket(channel_id); 418 RemoveSocket(channel_id);
369 } 419 }
370 AsyncWorkCompleted(); 420 AsyncWorkCompleted();
371 } 421 }
372 422
373 } // namespace extensions 423 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698