1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation. You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 //--------------------------------------------------------------------------
18 // config_ignore_ports.cc author Josh Rosenbaum <jrosenba@cisco.com>
19
20 #include <sstream>
21 #include <vector>
22 #include <string>
23 #include <stdexcept>
24
25 #include "conversion_state.h"
26 #include "helpers/converter.h"
27 #include "helpers/s2l_util.h"
28 #include "helpers/util_binder.h"
29
30 namespace config
31 {
32 namespace
33 {
34 constexpr uint16_t MAX_PORTS = 0xFFFF; // == 65535
35
36 class IgnorePorts : public ConversionState
37 {
38 public:
IgnorePorts(Converter & c)39 IgnorePorts(Converter& c) : ConversionState(c) { }
40 bool convert(std::istringstream& data_stream) override;
41 };
42 } // namespace
43
convert(std::istringstream & data_stream)44 bool IgnorePorts::convert(std::istringstream& data_stream)
45 {
46 bool retval = true;
47 std::string keyword;
48 std::string port;
49
50 std::streamoff pos = data_stream.tellg();
51 std::string port_string = data_stream.str();
52 port_string = port_string.substr(pos);
53 port_string = data_api.expand_vars(port_string);
54
55 // if the keyword is not 'tcp' or 'udp', return false;
56 if (!(data_stream >> keyword) ||
57 (keyword != "udp" && keyword != "tcp") )
58 {
59 data_api.failed_conversion(data_stream, keyword);
60 return false;
61 }
62
63 // Only add to the binder once we have validated the configuration.
64 auto& bind = cv.make_binder();
65 bind.set_when_proto(keyword);
66
67 while (data_stream >> port)
68 {
69 try
70 {
71 const std::size_t colon_pos = port.find(':');
72
73 if (port == "any")
74 {
75 // Possible Snort bug, but only port zero is ignored
76 bind.add_when_port("0");
77 }
78 else if (colon_pos == std::string::npos)
79 {
80 bind.add_when_port(port);
81 }
82 else if (colon_pos == 0)
83 {
84 int high = std::stoi(port.substr(1));
85
86 if (high > MAX_PORTS)
87 throw std::out_of_range("");
88
89 for (int i = 0; i <= high; i++)
90 bind.add_when_port(std::to_string(i));
91 }
92 else if ((colon_pos+1) == port.size())
93 {
94 int low = std::stoi(port.substr(0, colon_pos));
95
96 if (low > MAX_PORTS)
97 throw std::out_of_range("");
98
99 for (int i = low; i <= MAX_PORTS; i++)
100 bind.add_when_port(std::to_string(i));
101 }
102 else
103 {
104 int low = std::stoi(port.substr(0, colon_pos));
105 int high = std::stoi(port.substr(colon_pos + 1));
106
107 if (low > MAX_PORTS || high > MAX_PORTS || low > high)
108 throw std::out_of_range("");
109
110 for (int i = low; i <= high; i++)
111 bind.add_when_port(std::to_string(i));
112 }
113 }
114 catch (std::invalid_argument&)
115 {
116 data_api.failed_conversion(data_stream, "can't convert " + port);
117 retval = false;
118 bind.print_binding(false); // don't print the binding if an error occurred
119 }
120 catch (std::out_of_range&)
121 {
122 data_api.failed_conversion(data_stream, "Port" + port + " must be <= 65535");
123 retval = false;
124 bind.print_binding(false); // don't print the binding if an error occurred
125 }
126 }
127
128 bind.set_use_action("allow");
129 return retval;
130 }
131
132 /**************************
133 ******* A P I ***********
134 **************************/
135
ctor(Converter & c)136 static ConversionState* ctor(Converter& c)
137 { return new IgnorePorts(c); }
138
139 static const ConvertMap config_ignore_ports =
140 {
141 "ignore_ports",
142 ctor,
143 };
144
145 const ConvertMap* ignore_ports_map = &config_ignore_ports;
146 } // namespace config
147
148