• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 "extensions/common/permissions/socket_permission_data.h"
6 
7 #include <cstdlib>
8 #include <sstream>
9 #include <vector>
10 
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "extensions/common/permissions/api_permission.h"
17 #include "extensions/common/permissions/socket_permission.h"
18 #include "url/url_canon.h"
19 
20 namespace {
21 
22 using content::SocketPermissionRequest;
23 using extensions::SocketPermissionData;
24 
25 const char kColon = ':';
26 const char kInvalid[] = "invalid";
27 const char kTCPConnect[] = "tcp-connect";
28 const char kTCPListen[] = "tcp-listen";
29 const char kUDPBind[] = "udp-bind";
30 const char kUDPSendTo[] = "udp-send-to";
31 const char kUDPMulticastMembership[] = "udp-multicast-membership";
32 const char kResolveHost[] = "resolve-host";
33 const char kResolveProxy[] = "resolve-proxy";
34 const char kNetworkState[] = "network-state";
35 
StringToType(const std::string & s)36 SocketPermissionRequest::OperationType StringToType(const std::string& s) {
37   if (s == kTCPConnect)
38     return SocketPermissionRequest::TCP_CONNECT;
39   if (s == kTCPListen)
40     return SocketPermissionRequest::TCP_LISTEN;
41   if (s == kUDPBind)
42     return SocketPermissionRequest::UDP_BIND;
43   if (s == kUDPSendTo)
44     return SocketPermissionRequest::UDP_SEND_TO;
45   if (s == kUDPMulticastMembership)
46     return SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP;
47   if (s == kResolveHost)
48     return SocketPermissionRequest::RESOLVE_HOST;
49   if (s == kResolveProxy)
50     return SocketPermissionRequest::RESOLVE_PROXY;
51   if (s == kNetworkState)
52     return SocketPermissionRequest::NETWORK_STATE;
53   return SocketPermissionRequest::NONE;
54 }
55 
TypeToString(SocketPermissionRequest::OperationType type)56 const char* TypeToString(SocketPermissionRequest::OperationType type) {
57   switch (type) {
58     case SocketPermissionRequest::TCP_CONNECT:
59       return kTCPConnect;
60     case SocketPermissionRequest::TCP_LISTEN:
61       return kTCPListen;
62     case SocketPermissionRequest::UDP_BIND:
63       return kUDPBind;
64     case SocketPermissionRequest::UDP_SEND_TO:
65       return kUDPSendTo;
66     case SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP:
67       return kUDPMulticastMembership;
68     case SocketPermissionRequest::RESOLVE_HOST:
69       return kResolveHost;
70     case SocketPermissionRequest::RESOLVE_PROXY:
71       return kResolveProxy;
72     case SocketPermissionRequest::NETWORK_STATE:
73       return kNetworkState;
74     default:
75       return kInvalid;
76   }
77 }
78 
79 }  // namespace
80 
81 namespace extensions {
82 
SocketPermissionData()83 SocketPermissionData::SocketPermissionData() {}
84 
~SocketPermissionData()85 SocketPermissionData::~SocketPermissionData() {}
86 
operator <(const SocketPermissionData & rhs) const87 bool SocketPermissionData::operator<(const SocketPermissionData& rhs) const {
88   return entry_ < rhs.entry_;
89 }
90 
operator ==(const SocketPermissionData & rhs) const91 bool SocketPermissionData::operator==(const SocketPermissionData& rhs) const {
92   return entry_ == rhs.entry_;
93 }
94 
Check(const APIPermission::CheckParam * param) const95 bool SocketPermissionData::Check(const APIPermission::CheckParam* param) const {
96   if (!param)
97     return false;
98   const SocketPermission::CheckParam& specific_param =
99       *static_cast<const SocketPermission::CheckParam*>(param);
100   const SocketPermissionRequest& request = specific_param.request;
101 
102   return entry_.Check(request);
103 }
104 
ToValue() const105 scoped_ptr<base::Value> SocketPermissionData::ToValue() const {
106   return scoped_ptr<base::Value>(new base::StringValue(GetAsString()));
107 }
108 
FromValue(const base::Value * value)109 bool SocketPermissionData::FromValue(const base::Value* value) {
110   std::string spec;
111   if (!value->GetAsString(&spec))
112     return false;
113 
114   return Parse(spec);
115 }
116 
entry()117 SocketPermissionEntry& SocketPermissionData::entry() {
118   // Clear the spec because the caller could mutate |this|.
119   spec_.clear();
120   return entry_;
121 }
122 
123 // TODO(ikarienator): Rewrite this method to support IPv6.
Parse(const std::string & permission)124 bool SocketPermissionData::Parse(const std::string& permission) {
125   Reset();
126 
127   std::vector<std::string> tokens;
128   base::SplitStringDontTrim(permission, kColon, &tokens);
129   if (tokens.empty())
130     return false;
131 
132   SocketPermissionRequest::OperationType type = StringToType(tokens[0]);
133   if (type == SocketPermissionRequest::NONE)
134     return false;
135 
136   tokens.erase(tokens.begin());
137   return SocketPermissionEntry::ParseHostPattern(type, tokens, &entry_);
138 }
139 
GetAsString() const140 const std::string& SocketPermissionData::GetAsString() const {
141   if (!spec_.empty())
142     return spec_;
143 
144   spec_.reserve(64);
145   spec_.append(TypeToString(entry_.pattern().type));
146   std::string pattern = entry_.GetHostPatternAsString();
147   if (!pattern.empty()) {
148     spec_.append(1, kColon).append(pattern);
149   }
150   return spec_;
151 }
152 
Reset()153 void SocketPermissionData::Reset() {
154   entry_ = SocketPermissionEntry();
155   spec_.clear();
156 }
157 
158 }  // namespace extensions
159