1 /*
2
3 Firewall Builder
4
5 Copyright (C) 2011 NetCitadel, LLC
6
7 Author: Vadim Kurland vadim@fwbuilder.org
8
9 This program is free software which we release under the GNU General Public
10 License. You may redistribute and/or modify this program under the terms
11 of that license as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
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 for more details.
18
19 To get a copy of the GNU General Public License, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 */
23
24 #include "config.h"
25
26 #include "NamedObject.h"
27
28 #include "fwbuilder/AddressRange.h"
29 #include "fwbuilder/ICMPService.h"
30 #include "fwbuilder/TCPService.h"
31 #include "fwbuilder/UDPService.h"
32 #include "fwbuilder/CustomService.h"
33 #include "fwbuilder/Interface.h"
34 #include "fwbuilder/IPv4.h"
35 #include "fwbuilder/Network.h"
36 #include "fwbuilder/Interface.h"
37
38 #include <assert.h>
39 #include <sstream>
40
41 #include <QStringList>
42 #include <QSet>
43
44
45 using namespace libfwbuilder;
46 using namespace fwcompiler;
47 using namespace std;
48
49 /*
50 * Reserved words for all versions of IOS and ASA that support named
51 * objects. It does not make sense to maintain sets of reserved words
52 * separately for each version because it would take a lot of effort
53 * for very little gain. We will maintain super-set of words that
54 * corresponds to the version that has most extensive set.
55 */
56 const char* rw[] = {
57 "ah",
58 "eigrp",
59 "esp",
60 "gre",
61 "icmp",
62 "icmp6",
63 "igmp",
64 "igrp",
65 "ip",
66 "ipinip",
67 "ipsec",
68 "nos",
69 "ospf",
70 "pcp",
71 "pim",
72 "pptp",
73 "snp",
74 "tcp",
75 "udp",
76 "tcp-aol",
77 "tcp-bgp",
78 "tcp-chargen",
79 "tcp-cifs",
80 "tcp-citrix-ica",
81 "tcp-ctiqbe",
82 "tcp-daytime",
83 "tcp-discard",
84 "tcp-domain",
85 "tcp-echo",
86 "tcp-exec",
87 "tcp-finger",
88 "tcp-ftp",
89 "tcp-ftp-data",
90 "tcp-gopher",
91 "tcp-ident",
92 "tcp-imap4",
93 "tcp-irc",
94 "tcp-hostname",
95 "tcp-kerberos",
96 "tcp-klogin",
97 "tcp-kshell",
98 "tcp-ldap",
99 "tcp-ldaps",
100 "tcp-login",
101 "tcp-lotusnotes",
102 "tcp-nfs",
103 "tcp-netbios-ssn",
104 "tcp-whois",
105 "tcp-nntp",
106 "tcp-pcanywhere-data",
107 "tcp-pim-auto-rp",
108 "tcp-pop2",
109 "tcp-pop3",
110 "tcp-pptp",
111 "tcp-lpd",
112 "tcp-rsh",
113 "tcp-rtsp",
114 "tcp-sip",
115 "tcp-smtp",
116 "tcp-ssh",
117 "tcp-sunrpc",
118 "tcp-tacacs",
119 "tcp-talk",
120 "tcp-telnet",
121 "tcp-uucp",
122 "tcp-www",
123 "tcp-http",
124 "tcp-https",
125 "tcp-cmd",
126 "tcp-sqlnet",
127 "tcp-h323",
128 "tcp-udp-cifs",
129 "tcp-udp-discard",
130 "tcp-udp-domain",
131 "tcp-udp-echo",
132 "tcp-udp-kerberos",
133 "tcp-udp-nfs",
134 "tcp-udp-pim-auto-rp",
135 "tcp-udp-sip",
136 "tcp-udp-sunrpc",
137 "tcp-udp-tacacs",
138 "tcp-udp-www",
139 "tcp-udp-http",
140 "tcp-udp-talk",
141 "udp-biff",
142 "udp-bootpc",
143 "udp-bootps",
144 "udp-cifs",
145 "udp-discard",
146 "udp-domain",
147 "udp-dnsix",
148 "udp-echo",
149 "udp-www",
150 "udp-http",
151 "udp-nameserver",
152 "udp-kerberos",
153 "udp-mobile-ip",
154 "udp-nfs",
155 "udp-netbios-ns",
156 "udp-netbios-dgm",
157 "udp-ntp",
158 "udp-pcanywhere-status",
159 "udp-pim-auto-rp",
160 "udp-radius",
161 "udp-radius-acct",
162 "udp-rip",
163 "udp-secureid-udp",
164 "udp-sip",
165 "udp-snmp",
166 "udp-snmptrap",
167 "udp-sunrpc",
168 "udp-syslog",
169 "udp-tacacs",
170 "udp-talk",
171 "udp-tftp",
172 "udp-time",
173 "udp-who",
174 "udp-xdmcp",
175 "udp-isakmp",
176 "icmp6-unreachable",
177 "icmp6-packet-too-big",
178 "icmp6-time-exceeded",
179 "icmp6-parameter-problem",
180 "icmp6-echo",
181 "icmp6-echo-reply",
182 "icmp6-membership-query",
183 "icmp6-membership-report",
184 "icmp6-membership-reduction",
185 "icmp6-router-renumbering",
186 "icmp6-router-solicitation",
187 "icmp6-router-advertisement",
188 "icmp6-neighbor-solicitation",
189 "icmp6-neighbor-advertisement",
190 "icmp6-neighbor-redirect",
191 "icmp-echo",
192 "icmp-echo-reply",
193 "icmp-unreachable",
194 "icmp-source-quench",
195 "icmp-redirect",
196 "icmp-alternate-address",
197 "icmp-router-advertisement",
198 "icmp-router-solicitation",
199 "icmp-time-exceeded",
200 "icmp-parameter-problem",
201 "icmp-timestamp-request",
202 "icmp-timestamp-reply",
203 "icmp-information-request",
204 "icmp-information-reply",
205 "icmp-mask-request",
206 "icmp-mask-reply",
207 "icmp-traceroute",
208 "icmp-conversion-error",
209 "icmp-mobile-redirect",
210 NULL
211 };
212
213 QSet<QString> NamedObject::reserved_words;
214 map<QString,int> NamedObject::name_disambiguation;
215
216
NamedObject(const FWObject * _obj,const QString & _platform)217 NamedObject::NamedObject(const FWObject *_obj, const QString &_platform)
218 {
219 obj = _obj;
220 platform = _platform;
221 if (reserved_words.empty())
222 {
223 const char** cptr = rw;
224 while (*cptr!=NULL)
225 {
226 reserved_words.insert(QString(*cptr));
227 cptr++;
228 }
229 }
230 name = sanitizeObjectName(QString::fromUtf8(obj->getName().c_str()));
231 }
232
getCommandWord()233 QString NamedObject::getCommandWord()
234 {
235 if (Address::constcast(obj)!=NULL && Address::constcast(obj)->isAny())
236 return "any";
237
238 if (Service::constcast(obj)!=NULL && Service::constcast(obj)->isAny())
239 return "any";
240
241 if (Interface::constcast(obj))
242 return "interface";
243
244 return name;
245 }
246
sanitizeObjectName(const QString & name)247 QString NamedObject::sanitizeObjectName(const QString &name)
248 {
249 QString qs = name;
250 qs = qs.replace(" ", "_").replace("/", "_").left(64);
251
252 if (reserved_words.contains(qs))
253 {
254 qs = qs + "_obj";
255 }
256
257 int n = name_disambiguation[qs];
258 name_disambiguation[qs] = n + 1;
259 qs = QString("%1.%2").arg(qs).arg(n);
260
261 return qs;
262 }
263
createNetworkObjectCommand(const Address * addr_obj)264 QString NamedObject::createNetworkObjectCommand(const Address *addr_obj)
265 {
266 if (addr_obj == NULL) return "";
267 if (addr_obj->isAny()) return "";
268 if (Interface::constcast(obj)) return "";
269
270 QStringList res;
271
272 res << QString("object network %1") .arg(name);
273
274 if (AddressRange::isA(addr_obj))
275 {
276 const AddressRange *ar = AddressRange::constcast(addr_obj);
277 res << QString(" range %1 %2")
278 .arg(ar->getRangeStart().toString().c_str())
279 .arg(ar->getRangeEnd().toString().c_str());
280 } else
281 {
282 string addr = addr_obj->getAddressPtr()->toString();
283
284 if (IPv4::isA(addr_obj))
285 {
286 res << QString(" host %1").arg(addr.c_str());
287 }
288
289 if (Network::isA(addr_obj))
290 {
291 string netm = addr_obj->getNetmaskPtr()->toString();
292 res << QString(" subnet %1 %2")
293 .arg(addr.c_str())
294 .arg(netm.c_str());
295 }
296 }
297
298
299 res << "exit";
300 res << "";
301 return res.join("\n");
302 }
303
printPorts(int rs,int re)304 QString NamedObject::printPorts(int rs, int re)
305 {
306 QStringList res;
307
308 if (rs<0) rs = 0;
309 if (re<0) re = 0;
310
311 if (rs>0 || re>0)
312 {
313 if (rs==re) res << "eq" << QString::number(rs);
314 else
315 if (rs==0 && re!=0) res << "lt" << QString::number(re);
316 else
317 if (rs!=0 && re==65535) res << "gt" << QString::number(rs);
318 else
319 res << "range " << QString::number(rs)
320 << "" << QString::number(re);
321 }
322 return res.join(" ");
323 }
324
createServiceObjectCommand(const Service * serv_obj)325 QString NamedObject::createServiceObjectCommand(const Service *serv_obj)
326 {
327 if (serv_obj == NULL) return "";
328 if (serv_obj->isAny()) return "";
329
330 QStringList res;
331
332 QString proto_name = serv_obj->getProtocolName().c_str();
333
334 res << QString("object service %1").arg(name);
335
336 QStringList service_line;
337
338 service_line << " service";
339
340 if (TCPService::isA(serv_obj) || UDPService::isA(serv_obj))
341 {
342 service_line << proto_name;
343
344 int rs = TCPUDPService::constcast(serv_obj)->getSrcRangeStart();
345 int re = TCPUDPService::constcast(serv_obj)->getSrcRangeEnd();
346 if (rs != 0 || re != 0)
347 {
348 service_line << "source" << printPorts(rs, re);
349 }
350
351 rs = TCPUDPService::constcast(serv_obj)->getDstRangeStart();
352 re = TCPUDPService::constcast(serv_obj)->getDstRangeEnd();
353 if (rs != 0 || re != 0)
354 {
355 service_line << "destination" << printPorts(rs, re);
356 }
357 }
358
359 if (ICMPService::isA(serv_obj))
360 {
361 service_line << proto_name;
362 if (serv_obj->getInt("type")!=-1)
363 service_line << QString::number(serv_obj->getInt("type"));
364 }
365
366 if (CustomService::isA(serv_obj))
367 {
368 service_line << CustomService::constcast(serv_obj)->getCodeForPlatform(
369 platform.toStdString()).c_str();
370 }
371
372 res << service_line.join(" ");
373 res << "exit";
374 res << "";
375 return res.join("\n");
376 }
377
378
getCommand()379 QString NamedObject::getCommand()
380 {
381 if (Address::constcast(obj)!=NULL)
382 return createNetworkObjectCommand(Address::constcast(obj));
383
384 if (Service::constcast(obj)!=NULL)
385 return createServiceObjectCommand(Service::constcast(obj));
386
387 return "";
388 }
389
getCommandWhenObjectGroupMember()390 QString NamedObject::getCommandWhenObjectGroupMember()
391 {
392 if (Address::constcast(obj)!=NULL) return "network-object object " + name;
393 if (Service::constcast(obj)!=NULL) return "service-object object " + name;
394 return "";
395 }
396
397
398