rippled
Port.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/safe_cast.h>
21 #include <ripple/beast/core/LexicalCast.h>
22 #include <ripple/beast/rfc2616.h>
23 #include <ripple/server/Port.h>
24 #include <boost/algorithm/string/predicate.hpp>
25 #include <boost/algorithm/string/trim.hpp>
26 #include <sstream>
27 
28 namespace ripple {
29 
30 bool
31 Port::secure() const
32 {
33  return protocol.count("peer") > 0 || protocol.count("https") > 0 ||
34  protocol.count("wss") > 0 || protocol.count("wss2") > 0;
35 }
36 
39 {
40  std::string s;
41  for (auto iter = protocol.cbegin(); iter != protocol.cend(); ++iter)
42  s += (iter != protocol.cbegin() ? "," : "") + *iter;
43  return s;
44 }
45 
48 {
49  os << "'" << p.name << "' (ip=" << p.ip << ":" << p.port << ", ";
50 
51  if (p.admin_nets_v4.size() || p.admin_nets_v6.size())
52  {
53  os << "admin nets:";
54  for (auto const& net : p.admin_nets_v4)
55  {
56  os << net.to_string();
57  os << ", ";
58  }
59  for (auto const& net : p.admin_nets_v6)
60  {
61  os << net.to_string();
62  os << ", ";
63  }
64  }
65 
67  {
68  os << "secure_gateway nets:";
69  for (auto const& net : p.secure_gateway_nets_v4)
70  {
71  os << net.to_string();
72  os << ", ";
73  }
74  for (auto const& net : p.secure_gateway_nets_v6)
75  {
76  os << net.to_string();
77  os << ", ";
78  }
79  }
80 
81  os << p.protocols() << ")";
82  return os;
83 }
84 
85 //------------------------------------------------------------------------------
86 
87 static void
89  Section const& section,
90  std::string const& field,
91  std::ostream& log,
94 {
95  auto const optResult = section.get(field);
96  if (!optResult)
97  return;
98 
99  std::stringstream ss(*optResult);
100  std::string ip;
101 
102  while (std::getline(ss, ip, ','))
103  {
104  boost::algorithm::trim(ip);
105  bool v4;
106  boost::asio::ip::network_v4 v4Net;
107  boost::asio::ip::network_v6 v6Net;
108 
109  try
110  {
111  // First, check to see if 0.0.0.0 or ipv6 equivalent was configured,
112  // which means all IP addresses.
113  auto const addr = beast::IP::Endpoint::from_string_checked(ip);
114  if (addr)
115  {
116  if (is_unspecified(*addr))
117  {
118  nets4.push_back(
119  boost::asio::ip::make_network_v4("0.0.0.0/0"));
120  nets6.push_back(boost::asio::ip::make_network_v6("::/0"));
121  // No reason to allow more IPs--it would be redundant.
122  break;
123  }
124 
125  // The configured address is a single IP (or else addr would
126  // be unset). We need this to be a subnet, so append
127  // the number of network bits to make a subnet of 1,
128  // depending on type.
129  v4 = addr->is_v4();
130  std::string addressString = addr->to_string();
131  if (v4)
132  {
133  addressString += "/32";
134  v4Net = boost::asio::ip::make_network_v4(addressString);
135  }
136  else
137  {
138  addressString += "/128";
139  v6Net = boost::asio::ip::make_network_v6(addressString);
140  }
141  }
142  else
143  {
144  // Since addr is empty, assume that the entry is
145  // for a subnet which includes trailing /0-32 or /0-128
146  // depending on ip type.
147  // First, see if it's an ipv4 subnet. If not, try ipv6.
148  // If that throws, then there's nothing we can do with
149  // the entry.
150  try
151  {
152  v4Net = boost::asio::ip::make_network_v4(ip);
153  v4 = true;
154  }
155  catch (boost::system::system_error const&)
156  {
157  v6Net = boost::asio::ip::make_network_v6(ip);
158  v4 = false;
159  }
160  }
161 
162  // Confirm that the address entry is the same as the subnet's
163  // underlying network address.
164  // 10.1.2.3/24 makes no sense. The underlying network address
165  // is 10.1.2.0/24.
166  if (v4)
167  {
168  if (v4Net != v4Net.canonical())
169  {
170  log << "The configured subnet " << v4Net.to_string()
171  << " is not the same as the network address, which is "
172  << v4Net.canonical().to_string();
173  Throw<std::exception>();
174  }
175  nets4.push_back(v4Net);
176  }
177  else
178  {
179  if (v6Net != v6Net.canonical())
180  {
181  log << "The configured subnet " << v6Net.to_string()
182  << " is not the same as the network address, which is "
183  << v6Net.canonical().to_string();
184  Throw<std::exception>();
185  }
186  nets6.push_back(v6Net);
187  }
188  }
189  catch (boost::system::system_error const& e)
190  {
191  log << "Invalid value '" << ip << "' for key '" << field << "' in ["
192  << section.name() << "]: " << e.what();
193  Throw<std::exception>();
194  }
195  }
196 }
197 
198 void
199 parse_Port(ParsedPort& port, Section const& section, std::ostream& log)
200 {
201  {
202  auto const optResult = section.get("ip");
203  if (optResult)
204  {
205  try
206  {
207  port.ip = boost::asio::ip::address::from_string(*optResult);
208  }
209  catch (std::exception const&)
210  {
211  log << "Invalid value '" << *optResult << "' for key 'ip' in ["
212  << section.name() << "]";
213  Rethrow();
214  }
215  }
216  }
217 
218  {
219  auto const optResult = section.get("port");
220  if (optResult)
221  {
222  try
223  {
224  port.port = beast::lexicalCastThrow<std::uint16_t>(*optResult);
225 
226  // Port 0 is not supported
227  if (*port.port == 0)
228  Throw<std::exception>();
229  }
230  catch (std::exception const&)
231  {
232  log << "Invalid value '" << *optResult << "' for key "
233  << "'port' in [" << section.name() << "]";
234  Rethrow();
235  }
236  }
237  }
238 
239  {
240  auto const optResult = section.get("protocol");
241  if (optResult)
242  {
243  for (auto const& s : beast::rfc2616::split_commas(
244  optResult->begin(), optResult->end()))
245  port.protocol.insert(s);
246  }
247  }
248 
249  {
250  auto const lim = get(section, "limit", "unlimited");
251 
252  if (!boost::iequals(lim, "unlimited"))
253  {
254  try
255  {
256  port.limit =
257  safe_cast<int>(beast::lexicalCastThrow<std::uint16_t>(lim));
258  }
259  catch (std::exception const&)
260  {
261  log << "Invalid value '" << lim << "' for key "
262  << "'limit' in [" << section.name() << "]";
263  Rethrow();
264  }
265  }
266  }
267 
268  {
269  auto const optResult = section.get("send_queue_limit");
270  if (optResult)
271  {
272  try
273  {
274  port.ws_queue_limit =
275  beast::lexicalCastThrow<std::uint16_t>(*optResult);
276 
277  // Queue must be greater than 0
278  if (port.ws_queue_limit == 0)
279  Throw<std::exception>();
280  }
281  catch (std::exception const&)
282  {
283  log << "Invalid value '" << *optResult << "' for key "
284  << "'send_queue_limit' in [" << section.name() << "]";
285  Rethrow();
286  }
287  }
288  else
289  {
290  // Default Websocket send queue size limit
291  port.ws_queue_limit = 100;
292  }
293  }
294 
295  populate(section, "admin", log, port.admin_nets_v4, port.admin_nets_v6);
296  populate(
297  section,
298  "secure_gateway",
299  log,
302 
303  set(port.user, "user", section);
304  set(port.password, "password", section);
305  set(port.admin_user, "admin_user", section);
306  set(port.admin_password, "admin_password", section);
307  set(port.ssl_key, "ssl_key", section);
308  set(port.ssl_cert, "ssl_cert", section);
309  set(port.ssl_chain, "ssl_chain", section);
310  set(port.ssl_ciphers, "ssl_ciphers", section);
311 
312  port.pmd_options.server_enable =
313  section.value_or("permessage_deflate", true);
314  port.pmd_options.client_max_window_bits =
315  section.value_or("client_max_window_bits", 15);
316  port.pmd_options.server_max_window_bits =
317  section.value_or("server_max_window_bits", 15);
318  port.pmd_options.client_no_context_takeover =
319  section.value_or("client_no_context_takeover", false);
320  port.pmd_options.server_no_context_takeover =
321  section.value_or("server_no_context_takeover", false);
322  port.pmd_options.compLevel = section.value_or("compress_level", 8);
323  port.pmd_options.memLevel = section.value_or("memory_level", 4);
324 }
325 
326 } // namespace ripple
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:42
sstream
std::string
STL class.
std::exception
STL class.
ripple::Port::protocols
std::string protocols() const
Definition: Port.cpp:38
ripple::populate
static void populate(Section const &section, std::string const &field, std::ostream &log, std::vector< boost::asio::ip::network_v4 > &nets4, std::vector< boost::asio::ip::network_v6 > &nets6)
Definition: Port.cpp:88
ripple::ParsedPort::admin_nets_v6
std::vector< boost::asio::ip::network_v6 > admin_nets_v6
Definition: Port.h:117
ripple::ParsedPort::ssl_ciphers
std::string ssl_ciphers
Definition: Port.h:109
std::vector< boost::asio::ip::network_v4 >
std::vector::size
T size(T... args)
ripple::Port::secure_gateway_nets_v6
std::vector< boost::asio::ip::network_v6 > secure_gateway_nets_v6
Definition: Port.h:59
ripple::Port::ip
boost::asio::ip::address ip
Definition: Port.h:53
ripple::Port::secure
bool secure() const
Definition: Port.cpp:31
ripple::ParsedPort::limit
int limit
Definition: Port.h:111
std::stringstream
STL class.
ripple::Section::value_or
T value_or(std::string const &name, T const &other) const
Returns a value if present, else another value.
Definition: BasicConfig.h:149
ripple::parse_Port
void parse_Port(ParsedPort &port, Section const &section, std::ostream &log)
Definition: Port.cpp:199
ripple::Port::name
std::string name
Definition: Port.h:52
ripple::Port::port
std::uint16_t port
Definition: Port.h:54
ripple::ParsedPort
Definition: Port.h:96
ripple::operator<<
std::ostream & operator<<(std::ostream &os, TOffer< TIn, TOut > const &offer)
Definition: Offer.h:242
std::vector::push_back
T push_back(T... args)
ripple::Section::name
std::string const & name() const
Returns the name of this section.
Definition: BasicConfig.h:59
ripple::ParsedPort::secure_gateway_nets_v6
std::vector< boost::asio::ip::network_v6 > secure_gateway_nets_v6
Definition: Port.h:119
ripple::Port::admin_nets_v6
std::vector< boost::asio::ip::network_v6 > admin_nets_v6
Definition: Port.h:57
ripple::ParsedPort::password
std::string password
Definition: Port.h:103
std::ostream
STL class.
ripple::Rethrow
void Rethrow()
Rethrow the exception currently being handled.
Definition: contract.h:48
ripple::Port::secure_gateway_nets_v4
std::vector< boost::asio::ip::network_v4 > secure_gateway_nets_v4
Definition: Port.h:58
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:313
ripple::Port::admin_nets_v4
std::vector< boost::asio::ip::network_v4 > admin_nets_v4
Definition: Port.h:56
ripple::ParsedPort::admin_user
std::string admin_user
Definition: Port.h:104
ripple::Port
Configuration information for a Server listening port.
Definition: Port.h:48
beast::rfc2616::split_commas
Result split_commas(FwdIt first, FwdIt last)
Definition: rfc2616.h:199
ripple::ParsedPort::ssl_chain
std::string ssl_chain
Definition: Port.h:108
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::ParsedPort::ip
std::optional< boost::asio::ip::address > ip
Definition: Port.h:114
protocol
Definition: ValidatorList.h:38
ripple::ParsedPort::pmd_options
boost::beast::websocket::permessage_deflate pmd_options
Definition: Port.h:110
std::getline
T getline(T... args)
ripple::ParsedPort::ssl_key
std::string ssl_key
Definition: Port.h:106
ripple::ParsedPort::port
std::optional< std::uint16_t > port
Definition: Port.h:115
std::set::insert
T insert(T... args)
ripple::ParsedPort::user
std::string user
Definition: Port.h:102
ripple::ParsedPort::ws_queue_limit
std::uint16_t ws_queue_limit
Definition: Port.h:112
ripple::Section::get
std::optional< T > get(std::string const &name) const
Definition: BasicConfig.h:138
ripple::ParsedPort::protocol
std::set< std::string, boost::beast::iless > protocol
Definition: Port.h:101
ripple::ParsedPort::admin_password
std::string admin_password
Definition: Port.h:105
beast::IP::Endpoint::from_string_checked
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Definition: IPEndpoint.cpp:35
ripple::ParsedPort::ssl_cert
std::string ssl_cert
Definition: Port.h:107
ripple::ParsedPort::secure_gateway_nets_v4
std::vector< boost::asio::ip::network_v4 > secure_gateway_nets_v4
Definition: Port.h:118
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:118
ripple::ParsedPort::admin_nets_v4
std::vector< boost::asio::ip::network_v4 > admin_nets_v4
Definition: Port.h:116