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