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 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 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 83 SocketPermissionData::SocketPermissionData() {} 84 85 SocketPermissionData::~SocketPermissionData() {} 86 87 bool SocketPermissionData::operator<(const SocketPermissionData& rhs) const { 88 return entry_ < rhs.entry_; 89 } 90 91 bool SocketPermissionData::operator==(const SocketPermissionData& rhs) const { 92 return entry_ == rhs.entry_; 93 } 94 95 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 105 scoped_ptr<base::Value> SocketPermissionData::ToValue() const { 106 return scoped_ptr<base::Value>(new base::StringValue(GetAsString())); 107 } 108 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 117 SocketPermissionEntry& SocketPermissionData::entry() { 118 // Clear the spec because the caller could mutate |this|. 119 spec_.clear(); 120 return entry_; 121 } 122 123 // TODO(reillyg): Rewrite this method to support IPv6. 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 140 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 153 void SocketPermissionData::Reset() { 154 entry_ = SocketPermissionEntry(); 155 spec_.clear(); 156 } 157 158 } // namespace extensions 159