1 /*
2
3 Firewall Builder
4
5 Copyright (C) 2002 NetCitadel, LLC
6
7 Author: Vadim Kurland vadim@vk.crocodile.org
8
9 $Id$
10
11 This program is free software which we release under the GNU General Public
12 License. You may redistribute and/or modify this program under the terms
13 of that license as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 To get a copy of the GNU General Public License, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
24 */
25
26 #include "config.h"
27
28 #include "NATCompiler_ipf.h"
29
30 #include "fwbuilder/AddressRange.h"
31 #include "fwbuilder/AddressTable.h"
32 #include "fwbuilder/FWObjectDatabase.h"
33 #include "fwbuilder/Firewall.h"
34 #include "fwbuilder/Host.h"
35 #include "fwbuilder/ICMPService.h"
36 #include "fwbuilder/IPService.h"
37 #include "fwbuilder/Interface.h"
38 #include "fwbuilder/Library.h"
39 #include "fwbuilder/NAT.h"
40 #include "fwbuilder/Network.h"
41 #include "fwbuilder/RuleElement.h"
42 #include "fwbuilder/TCPService.h"
43 #include "fwbuilder/UDPService.h"
44
45 #include <QString>
46
47 #include <iostream>
48
49 #include <assert.h>
50
51 using namespace libfwbuilder;
52 using namespace fwcompiler;
53 using namespace std;
54
myPlatformName()55 string NATCompiler_ipf::myPlatformName() { return "ipf"; }
56
57
prolog()58 int NATCompiler_ipf::prolog()
59 {
60
61 int n=NATCompiler_pf::prolog();
62
63 return n;
64 }
65
processNext()66 bool NATCompiler_ipf::VerifyRules::processNext()
67 {
68 NATRule *rule=getNext(); if (rule==NULL) return false;
69 tmp_queue.push_back(rule);
70
71 RuleElementOSrc *osrc=rule->getOSrc(); assert(osrc);
72 RuleElementODst *odst=rule->getODst(); assert(odst);
73 RuleElementOSrv *osrv=rule->getOSrv(); assert(osrv);
74
75 RuleElementTSrc *tsrc=rule->getTSrc(); assert(tsrc);
76 RuleElementTDst *tdst=rule->getTDst(); assert(tdst);
77 RuleElementTSrv *tsrv=rule->getTSrv(); assert(tsrv);
78
79 if (rule->getRuleType()==NATRule::DNAT && odst->size()!=1)
80 compiler->abort(rule,
81 "There should be no more than one object in "
82 "original destination");
83
84 // if (rule->getRuleType()==NATRule::SNAT && tsrc->size()!=1)
85 // compiler->abort(rule, "There should be no more than one object in translated source in the rule "+rule->getLabel());
86
87 if (rule->getRuleType()==NATRule::DNAT && osrv->isAny())
88 compiler->abort(rule,
89 "Service must be specified for destination translation rule");
90
91 if (tsrv->size()!=1)
92 compiler->abort(rule,
93 "Translated service should be 'Original' or should "
94 "contain single object");
95
96 FWObject *o=tsrv->front();
97 if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
98
99 if ( Group::cast(o)!=NULL)
100 compiler->abort(rule,
101 "Can not use group in translated service");
102
103 if (rule->getRuleType()==NATRule::SNetnat && !tsrc->isAny() )
104 {
105 Network *a1=Network::cast(compiler->getFirstOSrc(rule));
106 Network *a2=Network::cast(compiler->getFirstTSrc(rule));
107 if ( a1==NULL || a2==NULL ||
108 a1->getNetmaskPtr()->getLength()!=a2->getNetmaskPtr()->getLength() )
109 compiler->abort(rule,
110 "Original and translated source should both "
111 "be networks of the same size");
112 }
113
114 if (rule->getRuleType()==NATRule::DNetnat && !tsrc->isAny() )
115 {
116 Network *a1=Network::cast(compiler->getFirstODst(rule));
117 Network *a2=Network::cast(compiler->getFirstTDst(rule));
118 if ( a1==NULL || a2==NULL ||
119 a1->getNetmaskPtr()->getLength()!=a2->getNetmaskPtr()->getLength() )
120 compiler->abort(rule,
121 "Original and translated destination should "
122 "both be networks of the same size");
123 }
124
125 if (osrc->getNeg() || odst->getNeg() || osrv->getNeg())
126 compiler->abort(rule, "Negation in NAT rules is not supported");
127
128 return true;
129 }
130
processNext()131 bool NATCompiler_ipf::ExpandPortRange::processNext()
132 {
133 NATRule *rule=getNext(); if (rule==NULL) return false;
134
135 Service *osrv=compiler->getFirstOSrv(rule);
136
137 if (UDPService::isA(osrv) || TCPService::isA(osrv))
138 {
139 int rs = TCPUDPService::cast(osrv)->getDstRangeStart();
140 int re = TCPUDPService::cast(osrv)->getDstRangeEnd();
141
142 int numPorts = re-rs+1;
143 if (numPorts==1)
144 {
145 tmp_queue.push_back(rule);
146 return true;
147 }
148
149 if (numPorts > 20)
150 {
151 ostringstream ostr;
152 ostr << string("Expanding port range ") << osrv->getName()
153 << " creates " << numPorts << " rules";
154 compiler->warning(rule, ostr.str());
155 }
156
157 string newSrvType = TCPService::TYPENAME;
158 if (UDPService::isA(osrv)) newSrvType = UDPService::TYPENAME;
159
160 for (int p=rs; p<=re; ++p)
161 {
162 NATRule *r = compiler->dbcopy->createNATRule();
163 r->duplicate(rule);
164
165 FWObject *newSrv = compiler->dbcopy->create(newSrvType);
166 newSrv->duplicate(osrv,true);
167 TCPUDPService::cast(newSrv)->setDstRangeStart(p);
168 TCPUDPService::cast(newSrv)->setDstRangeEnd(p);
169 compiler->persistent_objects->add(newSrv,false);
170 compiler->dbcopy->addToIndex(newSrv);
171
172 RuleElementOSrv *nosrv = r->getOSrv();
173 nosrv->clearChildren();
174 nosrv->addRef(newSrv);
175
176 compiler->temp_ruleset->add(r);
177 tmp_queue.push_back(r);
178 }
179 } else
180 {
181 tmp_queue.push_back(rule);
182 }
183 return true;
184 }
185
processNext()186 bool NATCompiler_ipf::AssignInterface::processNext()
187 {
188 NATRule *rule = getNext(); if (rule==NULL) return false;
189 RuleElementItfOutb *itf_re = rule->getItfOutb();
190
191 Address *a = NULL;
192
193 switch (rule->getRuleType() )
194 {
195
196 case NATRule::Continue:
197 case NATRule::NONAT:
198 {
199 /* use heuristic to assign nonat rule to interfaces */
200 Interface *iface;
201
202 a=compiler->getFirstODst(rule);
203 iface=compiler->findInterfaceFor( compiler->getFirstODst(rule) ,
204 compiler->fw);
205 if (iface!=NULL && !iface->isLoopback())
206 {
207 if ( ! itf_re->hasRef(iface)) itf_re->addRef(iface);
208 // rule->setInterfaceId( iface->getId() );
209 tmp_queue.push_back( rule );
210 return true;
211 }
212 /* slip into Redirect case to assign rule to all interfaces */
213 }
214
215 case NATRule::Redirect:
216 case NATRule::DNAT:
217 case NATRule::DNetnat:
218 case NATRule::LB:
219 {
220 /*
221 * we do not have network zones here, so our ability to pick right
222 * interfaces is rather limited. First, we try to find interface that
223 * is connected to the subnet OSrc belongs to. If that does not work,
224 * we assign rule to all interfaces, except loopback
225 */
226 a = NULL;
227 if ( ! rule->getOSrc()->isAny() ) a = compiler->getFirstOSrc(rule);
228 if ( a==NULL && ! rule->getODst()->isAny() )
229 a = compiler->getFirstODst(rule);
230
231 if (a!=NULL)
232 {
233 Interface *iface;
234 iface = compiler->findInterfaceFor(a,compiler->fw);
235
236 if (iface!=NULL && !iface->isLoopback())
237 {
238 if ( ! itf_re->hasRef(iface)) itf_re->addRef(iface);
239 // rule->setInterfaceId( iface->getId() );
240 tmp_queue.push_back(rule);
241 return true;
242 }
243 }
244
245 FWObjectTypedChildIterator j=compiler->fw->findByType(Interface::TYPENAME);
246 for ( ; j!=j.end(); ++j )
247 {
248 Interface *iface = Interface::cast(*j);
249 assert(iface);
250 if ( iface->isUnnumbered() ||
251 iface->isBridgePort() ||
252 iface->isLoopback()) continue;
253
254 NATRule *r = compiler->dbcopy->createNATRule();
255 compiler->temp_ruleset->add(r);
256 r->duplicate(rule);
257 RuleElementItfOutb *itf_re = r->getItfOutb();
258 if ( ! itf_re->hasRef(iface)) itf_re->addRef(iface);
259 //r->setInterfaceId( iface->getId() );
260 tmp_queue.push_back( r );
261 }
262 return true;
263 }
264
265 case NATRule::SNAT:
266 case NATRule::SNetnat:
267 {
268 a=compiler->getFirstTSrc(rule);
269
270 if ( (Interface::isA(a) || IPv4::isA(a)) && a->isChildOf(compiler->fw))
271 {
272 FWObject *p = a;
273 while ( ! Interface::isA(p) ) p = p->getParent();
274 if ( ! itf_re->hasRef(p)) itf_re->addRef(p);
275 // rule->setInterfaceId( p->getId() );
276 tmp_queue.push_back(rule);
277 return true;
278 }
279
280 /* if we appear here, then TSrc is not an interface or address of an
281 * interface.
282 */
283 int n=0;
284 list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
285 for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
286 {
287 Interface *iface=Interface::cast(*i);
288 assert(iface);
289
290 if (iface->isLoopback() ||
291 iface->isUnnumbered() ||
292 iface->isBridgePort()) continue;
293
294 NATRule *r = compiler->dbcopy->createNATRule();
295 r->duplicate(rule);
296 compiler->temp_ruleset->add(r);
297
298 RuleElementItfOutb *itf_re = r->getItfOutb();
299 if ( ! itf_re->hasRef(iface)) itf_re->addRef(iface);
300 // r->setInterfaceId( iface->getId() );
301
302 tmp_queue.push_back(r);
303 n++;
304 }
305 if (n==0) tmp_queue.push_back(rule);
306
307 return true;
308 }
309 default: ;
310 }
311
312 compiler->abort(rule,
313 "Could not assign NAT rule to the interface. "
314 "Perhaps one of the objects has address which does not "
315 "belong to any subnet the firewall has interface on");
316
317 return true;
318 }
319
320
processNext()321 bool NATCompiler_ipf::prepareForLB::processNext()
322 {
323 NATRule *rule=getNext(); if (rule==NULL) return false;
324
325 if (rule->getRuleType()==NATRule::LB )
326 {
327 RuleElementTDst *tdst=rule->getTDst(); assert(tdst);
328 if (tdst->size()>2)
329 {
330 std::vector<FWObject*> cl;
331 for(list<FWObject*>::iterator i=tdst->begin(); i!=tdst->end(); ++i)
332 {
333 FWObject *o= *i;
334 if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
335
336 cl.push_back(o);
337 if (cl.size()==2)
338 {
339 NATRule *r= compiler->dbcopy->createNATRule();
340 compiler->temp_ruleset->add(r);
341 r->duplicate(rule);
342 RuleElementTDst *notdst=r->getTDst();
343 notdst->clearChildren();
344 notdst->addRef( cl[0] );
345 notdst->addRef( cl[1] );
346 cl.clear();
347 tmp_queue.push_back( r );
348 }
349 }
350
351 if (cl.size()!=0)
352 {
353 NATRule *r= compiler->dbcopy->createNATRule();
354 compiler->temp_ruleset->add(r);
355 r->duplicate(rule);
356 RuleElementTDst *notdst=r->getTDst();
357 notdst->clearChildren();
358 notdst->addRef( cl[0] );
359 // notdst->addRef( cl[1] );
360 cl.clear();
361 tmp_queue.push_back( r );
362 }
363
364 } else tmp_queue.push_back(rule);
365 } else tmp_queue.push_back(rule);
366
367 return true;
368 }
369
370 /*
371 * by now the rule should have already been assigned to interface.
372 *
373 * TODO: We should also take into account a situation when interface has
374 * multiple addresses...
375 */
processNext()376 bool NATCompiler_ipf::RedirectRules::processNext()
377 {
378 NATRule *rule = getNext(); if (rule==NULL) return false;
379 RuleElementItfOutb *itf_re = rule->getItfOutb();
380 Interface *rule_iface =
381 Interface::cast(FWObjectReference::getObject(itf_re->front()));
382 // Interface::cast( rule->getRoot()->getById(rule->getInterfaceId() ,true) );
383
384 tmp_queue.push_back(rule);
385
386 RuleElementTDst *rel=rule->getTDst(); assert(rel);
387 Address *otdst=compiler->getFirstTDst(rule);
388
389 if (rule->getRuleType()==NATRule::Redirect && rule_iface!=NULL &&
390 otdst->getId()==compiler->fw->getId())
391 {
392 rel->clearChildren();
393 rel->addRef( rule_iface );
394 }
395
396 return true;
397 }
398
399
processNext()400 bool NATCompiler_ipf::appProxy::processNext()
401 {
402 NATRule *rule=getNext(); if (rule==NULL) return false;
403
404 bool ftp_proxy = compiler->getCachedFwOpt()->getBool("ipf_nat_ftp_proxy");
405 bool rcmd_proxy = compiler->getCachedFwOpt()->getBool("ipf_nat_rcmd_proxy");
406 bool krcmd_proxy = compiler->getCachedFwOpt()->getBool("ipf_nat_krcmd_proxy");
407 bool ekshell_proxy = compiler->getCachedFwOpt()->getBool("ipf_nat_ekshell_proxy");
408 bool raudio_proxy = compiler->getCachedFwOpt()->getBool("ipf_nat_raudio_proxy");
409 bool h323_proxy = compiler->getCachedFwOpt()->getBool("ipf_nat_h323_proxy");
410 bool ipsec_proxy = compiler->getCachedFwOpt()->getBool("ipf_nat_ipsec_proxy");
411 bool pptp_proxy = compiler->getCachedFwOpt()->getBool("ipf_nat_pptp_proxy");
412 bool irc_proxy = compiler->getCachedFwOpt()->getBool("ipf_nat_irc_proxy");
413
414 QString ipsec_proxy_str = QString("proxy port %1 ipsec/udp ").arg(ISAKMP_PORT);
415 QString ftp_proxy_str = QString("proxy port %1 ftp/tcp ").arg(FTP_PORT);
416 QString rcmd_proxy_str = QString("proxy port %1 rcmd/tcp ").arg(RCMD_PORT);
417 QString krcmd_proxy_str = QString("proxy port %1 rcmd/tcp ").arg(KRCMD_PORT);
418 QString ekshell_proxy_str = QString("proxy port %1 rcmd/tcp ").arg(EKSHELL_PORT);
419 QString raudio_proxy_str = QString("proxy port %1 raudio/tcp ").arg(RAUDIO_PORT);
420 QString h323_proxy_str = QString("proxy port %1 h323/tcp ").arg(H323_PORT);
421 QString pptp_proxy_str = QString("proxy port %1 pptp/tcp ").arg(PPTP_PORT);
422 QString irc_proxy_str = QString("proxy port %1 irc/tcp ").arg(IRC_PORT);
423
424
425 if (rule->getRuleType()==NATRule::SNAT ||
426 rule->getRuleType()==NATRule::NONAT)
427 {
428 Service *osrv = compiler->getFirstOSrv(rule);
429
430 if (UDPService::isA(osrv))
431 {
432 UDPService *s=UDPService::cast(osrv);
433 if (ipsec_proxy &&
434 s->getDstRangeStart()==ISAKMP_PORT && s->getDstRangeEnd()==ISAKMP_PORT)
435 rule->setStr("nat_rule_proxy", ipsec_proxy_str.toStdString());
436 }
437
438 if (TCPService::isA(osrv))
439 {
440 TCPService *s = TCPService::cast(osrv);
441 int range_start = s->getDstRangeStart();
442 int range_end = s->getDstRangeEnd();
443 if (ftp_proxy && range_start==FTP_PORT && range_end==FTP_PORT)
444 rule->setStr("nat_rule_proxy", ftp_proxy_str.toStdString());
445
446 if (rcmd_proxy && range_start==RCMD_PORT && range_end==RCMD_PORT)
447 rule->setStr("nat_rule_proxy", rcmd_proxy_str.toStdString());
448
449 if (krcmd_proxy && range_start==KRCMD_PORT && range_end==KRCMD_PORT )
450 rule->setStr("nat_rule_proxy", krcmd_proxy_str.toStdString());
451
452 if (ekshell_proxy && range_start==EKSHELL_PORT && range_end==EKSHELL_PORT )
453 rule->setStr("nat_rule_proxy", ekshell_proxy_str.toStdString());
454
455 if (raudio_proxy && range_start==RAUDIO_PORT && range_end==RAUDIO_PORT )
456 rule->setStr("nat_rule_proxy", raudio_proxy_str.toStdString());
457
458 if (h323_proxy && range_start==H323_PORT && range_end==H323_PORT )
459 rule->setStr("nat_rule_proxy", h323_proxy_str.toStdString());
460
461 if (pptp_proxy && range_start==PPTP_PORT && range_end==PPTP_PORT )
462 rule->setStr("nat_rule_proxy", pptp_proxy_str.toStdString());
463
464 if (irc_proxy && range_start==IRC_PORT && range_end==IRC_PORT )
465 rule->setStr("nat_rule_proxy", irc_proxy_str.toStdString());
466 }
467 }
468 tmp_queue.push_back(rule);
469
470 return true;
471 }
472
processNext()473 bool NATCompiler_ipf::expandAnyService::processNext()
474 {
475 NATRule *rule=getNext(); if (rule==NULL) return false;
476 RuleElementOSrv *srv=rule->getOSrv();
477
478 if (rule->getRuleType()==NATRule::SNAT && srv->isAny())
479 {
480 NATRule *r= compiler->dbcopy->createNATRule();
481 compiler->temp_ruleset->add(r);
482 r->duplicate(rule);
483 r->setBool("needs_portmap",true);
484 tmp_queue.push_back(r);
485 }
486 tmp_queue.push_back(rule);
487
488 return true;
489 }
490
processNext()491 bool NATCompiler_ipf::processMultiAddressObjectsInRE::processNext()
492 {
493 NATRule *rule=getNext(); if (rule==NULL) return false;
494 RuleElement *re=RuleElement::cast( rule->getFirstByType(re_type) );
495
496 for (FWObject::iterator i=re->begin(); i!=re->end(); i++)
497 {
498 FWObject *o= *i;
499 if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
500 MultiAddressRunTime *atrt = MultiAddressRunTime::cast(o);
501 if (atrt!=NULL && atrt->getSubstitutionTypeName()==AddressTable::TYPENAME)
502 compiler->abort(
503 rule,
504 "Run-time AddressTable objects are not supported.");
505 }
506
507 tmp_queue.push_back(rule);
508 return true;
509 }
510
511
compile()512 void NATCompiler_ipf::compile()
513 {
514 bool manage_virtual_addr=getCachedFwOpt()->getBool("manage_virtual_addr");
515
516 info(" Compiling NAT rules for " + fw->getName());
517
518 Compiler::compile();
519
520 add( new Begin());
521 add( new printTotalNumberOfRules() );
522
523 add( new singleRuleFilter());
524
525 add( new recursiveGroupsInOSrc( "check for recursive groups in OSRC" ) );
526 add( new recursiveGroupsInODst( "check for recursive groups in ODST" ) );
527 add( new recursiveGroupsInOSrv( "check for recursive groups in OSRV" ) );
528
529 add( new recursiveGroupsInTSrc( "check for recursive groups in TSRC" ) );
530 add( new recursiveGroupsInTDst( "check for recursive groups in TDST" ) );
531 add( new recursiveGroupsInTSrv( "check for recursive groups in TSRV" ) );
532
533 add( new emptyGroupsInOSrc( "check for empty groups in OSRC" ) );
534 add( new emptyGroupsInODst( "check for empty groups in ODST" ) );
535 add( new emptyGroupsInOSrv( "check for empty groups in OSRV" ) );
536
537 add( new emptyGroupsInTSrc( "check for empty groups in TSRC" ) );
538 add( new emptyGroupsInTDst( "check for empty groups in TDST" ) );
539 add( new emptyGroupsInTSrv( "check for empty groups in TSRV" ) );
540
541 add( new ExpandGroups( "expand groups" ) );
542 add( new eliminateDuplicatesInOSRC( "eliminate duplicates in OSRC" ) );
543 add( new eliminateDuplicatesInODST( "eliminate duplicates in ODST" ) );
544 add( new eliminateDuplicatesInOSRV( "eliminate duplicates in OSRV" ) );
545
546 add( new swapMultiAddressObjectsInOSrc(" swap MultiAddress -> MultiAddressRunTime in OSrc") );
547 add( new swapMultiAddressObjectsInODst(" swap MultiAddress -> MultiAddressRunTime in ODst") );
548
549 add( new processMultiAddressObjectsInOSrc("process MultiAddress objects in OSrc") );
550 add( new processMultiAddressObjectsInODst("process MultiAddress objects in ODst") );
551
552 add( new splitOnOSrv( "split rule on original service" ) );
553 add( new ExpandPortRange("expand port ranges") );
554 add( new fillTranslatedSrv( "fill translated service" ) );
555 add( new NATRuleType( "determine NAT rule types" ) );
556 add( new VerifyRules( "verify NAT rules" ) );
557 add( new splitODstForSNAT("split rule if objects in ODst belong to different subnets" ) );
558 add( new ReplaceFirewallObjectsODst( "replace references to the firewall in ODst" ) );
559 add( new ReplaceFirewallObjectsTSrc( "replace references to the firewall in TSrc" ) );
560
561 if ( manage_virtual_addr ) {
562 add( new addVirtualAddress( "add virtual addresses for NAT rules" ) );
563 }
564
565 add( new ExpandMultipleAddresses( "expand multiple addresses" ) );
566 add( new checkForUnnumbered( "check for unnumbered interfaces" ) );
567 add( new checkForDynamicInterfacesOfOtherObjects( "check for dynamic interfaces of other hosts and firewalls" ) );
568 add( new ExpandAddressRanges( "expand address range objects" ) );
569 add( new ConvertToAtomicForOriginal( "convert to atomic rules in OSrc and ODst" ) );
570 add( new ConvertToAtomicForTSrc( "convert to atomic rules in TSrc" ) );
571 add( new prepareForLB( "prepare for load balancing rules" ) );
572 add( new appProxy( "add application proxy code to map rules" ) );
573 add( new expandAnyService("split NAT rules with ANY service" ) );
574 add( new AssignInterface( "assign rules to interfaces" ) );
575 add( new RedirectRules( "replace objects in TDst for 'Redirect' rules" ) );
576
577 add( new checkForObjectsWithErrors(
578 "check if we have objects with errors in rule elements"));
579
580 add( new PrintRule("generate ipfilter code") );
581 add( new simplePrintProgress() );
582
583 runRuleProcessors();
584
585
586 }
587
588
epilog()589 void NATCompiler_ipf::epilog()
590 {
591 }
592