Home | History | Annotate | Download | only in permissions
      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