1 /* Copyright (c) 2016, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #ifndef GCS_XCOM_NETWORKING_H
24 #define	GCS_XCOM_NETWORKING_H
25 
26 #include <vector>
27 #include <map>
28 #include <set>
29 #include <string>
30 
31 #include "site_struct.h"
32 
33 /**
34   This function gets all network addresses on this host and their
35   subnet masks as a string. IPv4 only. (SOCK_STREAM only)
36  @param[out] out maps IP addresses to subnetmasks
37  @param filter_out_inactive If set to true, only active interfaces will be added
38                             to out
39  @return false on sucess, true otherwise.
40  */
41 bool
42 get_ipv4_local_addresses(std::map<std::string, int>& out,
43                          bool filter_out_inactive= false);
44 
45 /**
46   This function gets all private network addresses and their
47   subnet masks as a string. IPv4 only. (SOCK_STREAM only)
48  @param[out] out maps IP addresses to subnetmasks
49  @param filter_out_inactive If set to true, only active interfaces will be added
50                             to out
51  @return false on sucess, true otherwise.
52  */
53 bool
54 get_ipv4_local_private_addresses(std::map<std::string, int>& out,
55                                  bool filter_out_inactive= false);
56 
57 /**
58  This function translates hostnames to IP addresses.
59 
60  @param[in] name The hostname to translate.
61  @param[out] ip  The IP address after translation.
62 
63  @return false on success, true otherwise.
64  */
65 bool
66 resolve_ip_addr_from_hostname(std::string name, std::string& ip);
67 
68 /**
69  Converts an address in string format (X.X.X.X/XX) into network octet format
70 
71  @param[in]  addr     IP address in X.X.X.X format
72  @param[in]  mask     Network mask associated with the address
73  @param[out] out_pair
74 
75  @return false on success, true otherwise.
76  */
77 bool
78 get_address_for_whitelist(std::string addr, std::string mask,
79                           std::pair<std::vector<unsigned char>,
80                                     std::vector<unsigned char> > &out_pair);
81 
82 /**
83  @class Gcs_ip_whitelist_entry
84  @brief Base abstract class for the whitelist entries.
85 
86  This is the base class for the Whitelist entries. Any derived class must
87  implement its two abstract methods:
88  - init_value();
89  - get_value();
90  */
91 class Gcs_ip_whitelist_entry
92 {
93 public:
94   /**
95    Constructor
96 
97    @param[in] addr IP address or hostname of this entry
98    @param[in] mask Network mask of this entry.
99    */
100   Gcs_ip_whitelist_entry(std::string addr, std::string mask);
101 
~Gcs_ip_whitelist_entry()102   virtual ~Gcs_ip_whitelist_entry() {}
103 
104   /**
105    Entry initialization.
106 
107    If one needs to initialize internal values, it should be done in this
108    method.
109 
110    @return false on success, true otherwise
111    */
112   virtual bool init_value() = 0;
113 
114   /**
115    Virtual member function that implements value retrieval for this entry.
116 
117    The returned value must be an std::pair that contains both the address and the
118    mask in network octet value.
119 
120    @return an std::pair with ip and mask in network octet form
121    */
122   virtual std::pair< std::vector<unsigned char>,
123                      std::vector<unsigned char> > *get_value() = 0;
124 
125   /** Getters */
get_addr()126   std::string get_addr() const {return m_addr;};
get_mask()127   std::string get_mask() const {return m_mask;};
128 
129 private:
130   std::string m_addr;
131   std::string m_mask;
132 };
133 
134 struct Gcs_ip_whitelist_entry_pointer_comparator {
operatorGcs_ip_whitelist_entry_pointer_comparator135     bool operator() (const Gcs_ip_whitelist_entry* lhs,
136                      const Gcs_ip_whitelist_entry* rhs) const {
137       //Check if addresses are different in content
138       if(lhs->get_addr() != rhs->get_addr())
139       { //Then compare only the addresses
140         return lhs->get_addr() < rhs->get_addr();
141       }
142       else
143       { //If addresses are equal, then compare the masks to untie.
144         return lhs->get_mask() < rhs->get_mask();
145       }
146     }
147 };
148 
149 /**
150  @class Gcs_ip_whitelist_entry_ip
151  @brief Implementation of Gcs_ip_whitelist_entry to use with
152         raw IP addresses in format X.X.X.X/XX
153  */
154 class Gcs_ip_whitelist_entry_ip: public Gcs_ip_whitelist_entry
155 {
156 public:
157   Gcs_ip_whitelist_entry_ip(std::string addr, std::string mask);
158 
159 public:
160   bool init_value();
161   std::pair<std::vector<unsigned char>, std::vector<unsigned char> > *get_value();
162 
163 private:
164   std::pair<std::vector<unsigned char>, std::vector<unsigned char> > m_value;
165 };
166 
167 /**
168  @class Gcs_ip_whitelist_entry_hostname
169  @brief Implementation of Gcs_ip_whitelist_entry to use with
170         hostnames
171  */
172 class Gcs_ip_whitelist_entry_hostname: public Gcs_ip_whitelist_entry
173 {
174 public:
175   Gcs_ip_whitelist_entry_hostname(std::string addr, std::string mask);
176 
177 public:
178   bool init_value();
179   std::pair<std::vector<unsigned char>, std::vector<unsigned char> > *get_value();
180 };
181 
182 class Gcs_ip_whitelist
183 {
184 public:
185   static const std::string DEFAULT_WHITELIST;
186 
187 private:
188   /*
189    The IP whitelist. It is a list of tuples Hexadecimal IP number
190    and subnet mask also in Hexadecimal. E.g.: 192.168.1.2/24 or 127.0.0.1/32.
191 
192    This is for optimization purposes, so that we don't calculate the
193    values each time we want to check.
194    */
195   std::set< Gcs_ip_whitelist_entry*,
196             Gcs_ip_whitelist_entry_pointer_comparator> m_ip_whitelist;
197 
198   /**
199    This is the list that originally submitted to be parsed and to configure
200    the whitelist.
201    */
202   std::string m_original_list;
203 
204 public:
Gcs_ip_whitelist()205   Gcs_ip_whitelist() :
206     m_ip_whitelist(),
207     m_original_list() {}
208   virtual ~Gcs_ip_whitelist();
209 
210   /**
211    This member function shall be used to configure the whitelist.
212 
213    @param the_list The list with IP addresses. This list is a comma separated
214                    list formatted only with IP addresses and/or in the form of
215                    a subnet range, e.g., IP/netbits.
216    @return true if the configuration failed, false otherwise.
217    */
218   bool configure(const std::string& the_list);
219 
220   /**
221    This member function shall be used to validate the list that is used as input
222    to the configure member function.
223 
224    @param the_list The list with IP addresses. This list is a comma separated
225                    list formatted only with IP addresses and/or in the form of
226                    a subnet range, e.g., IP/netbits.
227 
228    @return true if the configuration failed, false otherwise.
229    */
230   bool is_valid(const std::string& the_list) const;
231 
232   /**
233    This member function SHALL return true if the given IP is to be blocked,
234    false otherwise.
235 
236    @param ip_addr a string representation of an IPv4 address.
237    @param xcom_config the latest XCom configuration.
238 
239    @return true if the ip should be blocked, false otherwise.
240    */
241   bool shall_block(const std::string& ip_addr,
242                    site_def const *xcom_config= NULL) const;
243 
244   /**
245    This member function SHALL return true if the IP of the given file descriptor
246    is to be blocked, false otherwise.
247 
248    @param fd the file descriptor of the accepted socket to check.
249    @param xcom_config the latest XCom configuration.
250 
251    @return true if the ip should be blocked, false otherwise.
252    */
253   bool shall_block(int fd, site_def const *xcom_config= NULL) const;
254 
255   /**
256    This member function gets the textual representation of the list as
257    provided to the configure member function.
258    */
get_configured_ip_whitelist()259   const std::string& get_configured_ip_whitelist() const { return m_original_list; }
260 
261   /**
262    A string representation of the internal list of IP addresses. Can have
263    more addresses than those submitted through the configure member
264    function, since there are addresses that are implicitly added when
265    configuring the list.
266    */
267   std::string to_string() const;
268 
269 private:
270   bool do_check_block(struct sockaddr_storage *sa,
271                       site_def const *xcom_config) const;
272   bool do_check_block_whitelist(
273     std::vector<unsigned char> const& incoming_octets) const;
274   bool do_check_block_xcom(std::vector<unsigned char> const& incoming_octets,
275                            site_def const *xcom_config) const;
276   bool add_address(std::string addr, std::string mask);
277 
278 private:
279   Gcs_ip_whitelist(Gcs_ip_whitelist const&);
280   Gcs_ip_whitelist& operator=(Gcs_ip_whitelist const&);
281 };
282 
283 
284 #endif	/* GCS_XCOM_NETWORKING_H */
285 
286