1 /*
2 
3                           Firewall Builder
4 
5                  Copyright (C) 2000 NetCitadel, LLC
6 
7   Author:  Vadim Kurland     vadim@fwbuilder.org
8 
9   $Id$
10 
11 
12   This program is free software which we release under the GNU General Public
13   License. You may redistribute and/or modify this program under the terms
14   of that license as published by the Free Software Foundation; either
15   version 2 of the License, or (at your option) any later version.
16 
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21 
22   To get a copy of the GNU General Public License, write to the Free Software
23   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 
25 */
26 
27 #include "config.h"
28 #include "fwbuilder/libfwbuilder-config.h"
29 
30 
31 #include <sys/types.h>
32 
33 #include <sys/stat.h>
34 #ifndef _WIN32
35 #  include <pwd.h>
36 #  include <unistd.h>
37 #endif
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <assert.h>
41 
42 #include <iostream>
43 #include <fstream>
44 #include <cstdlib>
45 #include <cstring>
46 
47 #include "fwbuilder/Resources.h"
48 #include "fwbuilder/Constants.h"
49 #include "fwbuilder/FWObject.h"
50 #include "fwbuilder/FWObjectDatabase.h"
51 #include "fwbuilder/RuleElement.h"
52 #include "fwbuilder/FWOptions.h"
53 #include "fwbuilder/Firewall.h"
54 #include "fwbuilder/Interface.h"
55 #include "fwbuilder/Host.h"
56 #include "fwbuilder/Tools.h"
57 
58 using namespace libfwbuilder;
59 using namespace std;
60 
61 const string Resources::PLATFORM_RES_DIR_NAME = "platform";
62 const string Resources::OS_RES_DIR_NAME = "os";
63 
64 Resources*  Resources::global_res = NULL;
65 map<string,Resources*>  Resources::platform_res;
66 map<string,Resources*>  Resources::os_res;
67 
68 
Resources()69 Resources::Resources() throw(FWException)
70 {
71     doc=NULL;
72 }
73 
Resources(const string & _resF)74 Resources::Resources(const string &_resF) throw(FWException)
75 {
76     doc = NULL;
77     resfile = _resF;
78 
79     if (global_res==NULL)
80     {
81         global_res = this;
82         loadRes(_resF);
83         loadSystemResources();
84     } else
85         loadRes(_resF);
86 }
87 
~Resources()88 Resources::~Resources()
89 {
90     if (doc) xmlFreeDoc(doc);
91 }
92 
clear()93 void Resources::clear()
94 {
95     for (map<string,Resources*>::iterator it=platform_res.begin();
96          it!=platform_res.end(); ++it)
97     {
98         delete it->second;
99     }
100     platform_res.clear();
101 
102     for (map<string,Resources*>::iterator it=os_res.begin();
103          it!=os_res.end(); ++it)
104     {
105         delete it->second;
106     }
107     os_res.clear();
108 }
109 
getXmlNodeContent(xmlNodePtr node)110 string Resources::getXmlNodeContent(xmlNodePtr node)
111 {
112     string res;
113     char* cptr= (char*)( xmlNodeGetContent(node) );
114     if (cptr!=NULL)
115     {
116         res=cptr;
117         FREEXMLBUFF(cptr);
118     }
119     return res;
120 }
121 
getXmlNodeProp(xmlNodePtr node,string prop)122 string Resources::getXmlNodeProp(xmlNodePtr node,string prop)
123 {
124     string res;
125     char* cptr=(char*)( xmlGetProp(node,TOXMLCAST(prop.c_str())));
126     if (cptr!=NULL)
127     {
128         res=cptr;
129         FREEXMLBUFF(cptr);
130     }
131     return res;
132 }
133 
loadRes(const std::string & rfile)134 void Resources::loadRes(const std::string &rfile ) throw(FWException)
135 {
136 
137     string buffer = XMLTools::readFile(rfile);
138     doc = xmlParseMemory(buffer.c_str(), buffer.length());
139 
140 //    doc = xmlParseFile(rfile.c_str());
141 //    doc = XMLTools::loadAndParseFile(rfile);
142 
143     if (!doc) throw FWException("Error parsing "+rfile);
144 
145     root = xmlDocGetRootElement(doc);
146 
147     if(!root || !root->name || strcmp(FROMXMLCAST(root->name), "FWBuilderResources")!=0)
148     {
149         xmlFreeDoc(doc);
150         throw FWException("Invalid resources file "+rfile);
151     }
152 }
153 
loadSystemResources()154 void Resources::loadSystemResources() throw(FWException)
155 {
156 /*
157  * Find and open resources for individual firewall platforms and OS.
158  * If corresponding directory does not exist or is empty, then no
159  * target platform support package is installed. So be it, not my
160  * problem
161  */
162 //    string resDir=Constants::getTemplateDirectory();
163 
164     string::size_type n=resfile.find_last_of("/\\");
165     string resDir = resfile.substr(0,n);
166 
167     list<string> pllist = getDirList( resDir + FS_SEPARATOR +PLATFORM_RES_DIR_NAME,
168                                       "xml" );
169 
170     for (list<string>::iterator lsi1=pllist.begin(); lsi1!=pllist.end(); lsi1++)
171     {
172         string::size_type n=lsi1->find_last_of("/\\")+1;
173         string platform=lsi1->substr(n, lsi1->rfind(".xml")-n);
174         Resources *tr=new Resources(*lsi1);
175         platform_res[platform]=tr;
176     }
177 
178 
179     list<string> oslist = getDirList( resDir + FS_SEPARATOR +OS_RES_DIR_NAME,
180                                       "xml" );
181     for (list<string>::iterator lsi2=oslist.begin(); lsi2!=oslist.end(); lsi2++)
182     {
183         string::size_type n=lsi2->find_last_of("/\\")+1;
184         string os=lsi2->substr(n, lsi2->rfind(".xml")-n);
185         Resources *tr=new Resources(*lsi2);
186         os_res[os]=tr;
187     }
188 
189 #if 0
190     cerr << "Loaded resources for the following modules :\n";
191 
192     map<string,string> p=getPlatforms();
193     map<string,string>::iterator i1;
194     for (i1=p.begin(); i1!=p.end(); ++i1)
195     {
196         cerr << (*i1).first << "  " << (*i1).second << endl;
197     }
198 
199     p=getOS();
200     for (i1=p.begin(); i1!=p.end(); ++i1)
201     {
202         cerr << (*i1).first << "  " << (*i1).second << endl;
203     }
204 #endif
205 }
206 
getXmlNode(const string & path)207 xmlNodePtr Resources::getXmlNode(const string& path)
208 {
209     return XMLTools::getXmlNodeByPath(root,path);
210 }
211 
212 
getIconPath(const char * icon)213 string  Resources::getIconPath(const char* icon)
214 {
215     string icn;
216 
217     icn= getResourceStr("/FWBuilderResources/Paths/Icndir");
218     icn += "/";
219     icn += getResourceStr(string("/FWBuilderResources/UI/Icons/")+icon);
220 
221     return icn;
222 }
223 
getIconPath(const string & icon)224 string  Resources::getIconPath(const string& icon)
225 {
226     return getIconPath(icon.c_str());
227 }
228 
getResourceStr(const string & resource_path)229 string  Resources::getResourceStr(const string& resource_path)
230 {
231     xmlNodePtr node=XMLTools::getXmlNodeByPath(root,resource_path.c_str());
232     if (node)  return getXmlNodeContent(node);
233     return "";
234 }
235 
getResourceInt(const string & resource_path)236 int     Resources::getResourceInt(const string& resource_path)
237 {
238     return atoi(getResourceStr(resource_path).c_str());
239 }
240 
getResourceBool(const string & resource_path)241 bool    Resources::getResourceBool(const string& resource_path)
242 {
243     string res=getResourceStr(resource_path);
244     return (res=="true" || res=="True");
245 }
246 
247 /*
248  * Adds bodies of xml elements found directly under resource_path to
249  * the list<string> res
250  *
251  * <element1>
252  *   <element2>
253  *      <string>value1</string>
254  *      <string>value2</string>
255  *      <string>value3</string>
256  *      <string>value4</string>
257  *   </element2>
258  * </element1>
259  *
260  * here resorce_path="/element1/element2", returned list consists of
261  * strings value1,value2,value3,value4
262  */
getResourceStrList(const string & resource_path,list<string> & res)263 void Resources::getResourceStrList(const string& resource_path, list<string> &res)
264 {
265     xmlNodePtr node = XMLTools::getXmlNodeByPath(root, resource_path.c_str());
266     if (node)
267     {
268         xmlNodePtr c;
269         for(c=node->xmlChildrenNode; c; c=c->next)
270         {
271             if ( xmlIsBlankNode(c) ) continue;
272             res.push_back(getXmlNodeContent(c));
273         }
274     }
275 }
276 
getObjResourceStr(const FWObject * obj,const string & resource_name)277 string  Resources::getObjResourceStr(const FWObject *obj,
278                                      const string& resource_name)
279 {
280     string objid   = FWObjectDatabase::getStringId(obj->getId());
281     string objtype = obj->getTypeName();
282     string res;
283     string resource="/FWBuilderResources/Object/"+objid+"/"+resource_name;
284     res= getResourceStr(resource);
285     if (res.empty())
286     {
287         string resource="/FWBuilderResources/Type/"+objtype+"/"+resource_name;
288         res= getResourceStr(resource);
289         if (res.empty())
290         {
291             resource="/FWBuilderResources/Type/DEFAULT/"+resource_name;
292             res= getResourceStr(resource);
293         }
294     }
295 
296     if (res.empty())
297         cerr << "Failed to locate resource for object " << obj->getName()
298              << " (type=" << objtype << "), "
299              << " (id=" << obj->getId() << "), resource name: "
300              << resource_name << endl;
301 
302     return res;
303 }
304 
getObjResourceBool(const FWObject * obj,const string & resource_name)305 bool  Resources::getObjResourceBool(const FWObject *obj,
306 				    const string&  resource_name)
307 {
308     string res=getObjResourceStr(obj,resource_name);
309     return (res=="true" || res=="True");
310 }
311 
312 /*
313  *  call this using appropriate Resources object, like this:
314  *
315  *  platform_res["iptables"]->getVersion()
316  */
getVersion()317 string  Resources::getVersion()
318 {
319     xmlNodePtr pn=getXmlNode("/FWBuilderResources/");
320     return getXmlNodeProp(pn,"version");
321 }
322 
323 /*
324  *  call this using appropriate Resources object, like this:
325  *
326  *  platform_res["iptables"]->getCompiler()
327  */
getCompiler()328 string  Resources::getCompiler()
329 {
330     return getResourceStr("/FWBuilderResources/Target/compiler");
331 }
332 
getInstaller()333 string  Resources::getInstaller()
334 {
335     return getResourceStr("/FWBuilderResources/Target/installer");
336 }
337 
getTransferAgent()338 string  Resources::getTransferAgent()
339 {
340     return getResourceStr("/FWBuilderResources/Target/transfer_agent");
341 }
342 
getListOfPlatforms()343 vector<string> Resources::getListOfPlatforms()
344 {
345     vector<string> vs;
346     for (map<string,Resources*>::iterator i1=platform_res.begin();
347          i1!=platform_res.end(); ++i1)
348     {
349         vs.push_back( (*i1).first );
350     }
351     return vs;
352 }
353 
354 
355 
getPlatforms()356 map<string,string> Resources::getPlatforms()
357 {
358     map<string,string> vs;
359     for (map<string,Resources*>::iterator i1=platform_res.begin();
360          i1!=platform_res.end(); ++i1)
361     {
362         Resources *res = (*i1).second;
363         if (res)
364         {
365             string desc = res->getResourceStr(
366                 "/FWBuilderResources/Target/description");
367             vs[ (*i1).first ]=desc;
368         }
369     }
370     return vs;
371 }
372 
373 
getOS()374 map<string,string> Resources::getOS()
375 {
376     map<string,string> vs;
377     for (map<string,Resources*>::iterator i1=os_res.begin(); i1!=os_res.end(); ++i1)
378     {
379         Resources *res = (*i1).second;
380         if (res)
381         {
382             string desc = res->getResourceStr(
383                 "/FWBuilderResources/Target/description");
384             vs[ (*i1).first ]=desc;
385         }
386     }
387     return vs;
388 }
389 
390 
getRuleElementResourceStr(const string & rel,const string & resource_name)391 string Resources::getRuleElementResourceStr(const string &rel,
392                                             const string &resource_name)
393 
394 {
395     xmlNodePtr  c,d;
396 
397     xmlNodePtr  dptr=Resources::global_res->getXmlNode("FWBuilderResources/RuleElements");
398 
399     assert (dptr!=NULL);
400 
401     for(c=dptr->xmlChildrenNode; c; c=c->next)
402     {
403 	if ( xmlIsBlankNode(c) ) continue;
404         if (rel==getXmlNodeProp(c,"RuleElement"))
405         {
406             d=XMLTools::getXmlChildNode(c,resource_name.c_str());
407             if (d)
408             {
409                 return getXmlNodeContent(d);
410             }
411 	}
412     }
413     return string("");
414 }
415 
isSystem(const FWObject * o)416 bool Resources::isSystem(const FWObject *o)
417 {
418     return global_res->getObjResourceBool(o, "system");
419 }
420 
getIconFileName(const FWObject * o)421 string  Resources::getIconFileName(const FWObject *o)
422 {
423     string res;
424 
425     res=global_res->getResourceStr("/FWBuilderResources/Paths/Icndir");
426     res += "/";
427     res += global_res->getObjResourceStr(o, "icon");
428 
429     return res;
430 }
431 
getNegIconFileName(const FWObject * o)432 string  Resources::getNegIconFileName(const FWObject *o)
433 {
434     string res;
435 
436     res=global_res->getResourceStr("/FWBuilderResources/Paths/Icndir");
437     res += "/";
438     res += global_res->getObjResourceStr(o, "icon-neg");
439 
440     return res;
441 }
442 
getRefIconFileName(const FWObject * o)443 string  Resources::getRefIconFileName(const FWObject *o)
444 {
445     string res;
446 
447     res=global_res->getResourceStr("/FWBuilderResources/Paths/Icndir");
448     res += "/";
449     res += global_res->getObjResourceStr(o, "icon-ref");
450 
451     return res;
452 }
453 
getTreeIconFileName(const FWObject * o)454 string  Resources::getTreeIconFileName(const FWObject *o)
455 {
456     string res;
457 
458     res=global_res->getResourceStr("/FWBuilderResources/Paths/Icndir");
459     res += "/";
460     res += global_res->getObjResourceStr(o, "icon-tree");
461 
462     return res;
463 }
464 
setDefaultOption(FWObject * o,const string & xml_node)465 void    Resources::setDefaultOption(FWObject *o,const string &xml_node)
466 {
467     xmlNodePtr pn = XMLTools::getXmlNodeByPath(root,xml_node.c_str());
468     if (pn==NULL) return;
469 
470     string optname=FROMXMLCAST(pn->name);
471     string optval =getXmlNodeContent(pn);
472     o->setStr(optname , optval);
473 }
474 
setDefaultOptionsAll(FWObject * o,const string & xml_node)475 void    Resources::setDefaultOptionsAll(FWObject *o,const string &xml_node)
476 {
477     xmlNodePtr pn = XMLTools::getXmlNodeByPath(root , xml_node.c_str() );
478     if (pn==NULL) return;
479 
480     xmlNodePtr opt;
481 
482     for(opt=pn->xmlChildrenNode; opt; opt=opt->next)
483     {
484         if ( xmlIsBlankNode(opt) ) continue;
485         setDefaultOption(o,xml_node+"/"+FROMXMLCAST(opt->name));
486     }
487 }
488 
489 
setDefaultTargetOptions(const string & target,Firewall * fw)490 void    Resources::setDefaultTargetOptions(const string &target,Firewall *fw)  throw (FWException)
491 {
492     FWOptions *opt=fw->getOptionsObject();
493     Resources *r=NULL;
494 
495     if (platform_res.count(target)!=0)      r=platform_res[target];
496     if (r==NULL && os_res.count(target)!=0) r=os_res[target];
497     if (r==NULL)
498         throw FWException("Support module for target '"+target+"' is not available");
499 
500     r->setDefaultOptionsAll(opt,"/FWBuilderResources/Target/options/default");
501 }
502 
setDefaultIfaceOptions(const string & target,Interface * iface)503 void    Resources::setDefaultIfaceOptions(const string &target,Interface *iface)
504         throw (FWException)
505 {
506     FWOptions *opt=iface->getOptionsObject();
507     /* if InterfaceOptions object does not yet exist -> create one */
508     if (opt == NULL) {
509         iface->add(iface->getRoot()->create(InterfaceOptions::TYPENAME));
510         opt = iface->getOptionsObject();
511     }
512 
513     Resources *r=NULL;
514 
515     if (platform_res.count(target)!=0)      r=platform_res[target];
516     if (r==NULL && os_res.count(target)!=0) r=os_res[target];
517     if (r==NULL)
518         throw FWException("Support module for target '"+target+"' is not available");
519 
520     r->setDefaultOptionsAll(opt,"/FWBuilderResources/Target/options/interface");
521 }
522 
setDefaultOptions(Host * h)523 void    Resources::setDefaultOptions(Host *h)
524 {
525     FWOptions *opt=h->getOptionsObject();
526 
527     global_res->setDefaultOptionsAll(opt,
528       "/FWBuilderResources/Type/"+h->getTypeName()+"/options");
529 }
530 
setDefaultProperties(FWObject * obj)531 void    Resources::setDefaultProperties(FWObject *obj)
532 {
533     global_res->setDefaultOptionsAll(obj,
534       "/FWBuilderResources/Type/"+obj->getTypeName()+"/properties");
535 }
536 
getTargetCapabilityStr(const string & target,const string & cap_name)537 string Resources::getTargetCapabilityStr(const string &target,
538                                          const string &cap_name)  throw (FWException)
539 {
540     Resources *r=NULL;
541 
542     if (platform_res.count(target)!=0)      r=platform_res[target];
543     if (r==NULL && os_res.count(target)!=0) r=os_res[target];
544     if (r==NULL)
545         throw FWException("Support module for target '"+target+"' is not available");
546 
547     return r->getResourceStr("/FWBuilderResources/Target/capabilities/"+cap_name);
548 }
549 
getTargetCapabilityBool(const string & target,const string & cap_name)550 bool Resources::getTargetCapabilityBool(const string &target,
551                                         const string &cap_name)  throw (FWException)
552 {
553     string s=getTargetCapabilityStr(target,cap_name);
554     return (s=="true" || s=="True");
555 }
556 
isTargetActionSupported(const string & target,const string & action)557 bool Resources::isTargetActionSupported(const string &target, const string &action)
558 {
559     bool res=false;
560     try
561     {
562          res = getTargetCapabilityBool(target, "actions/" + action + "/supported");
563     } catch (FWException &ex) { }
564     return res;
565 }
566 
getActionEditor(const string & target,const string & action)567 string Resources::getActionEditor(const string &target, const string &action)
568 {
569     string res="None";
570     try
571     {
572          res = getTargetCapabilityStr(target, "actions/" + action + "/parameter");
573     } catch (FWException &ex) { }
574     return res;
575 }
576 
getTargetOptionStr(const string & target,const string & opt_name)577 string Resources::getTargetOptionStr(const string &target,
578                                      const string &opt_name)  throw (FWException)
579 {
580     Resources *r=NULL;
581 
582     if (platform_res.count(target)!=0)      r=platform_res[target];
583     if (r==NULL && os_res.count(target)!=0) r=os_res[target];
584     if (r==NULL)
585         throw FWException("Support module for target '"+target+"' is not available");
586 
587     return r->getResourceStr("/FWBuilderResources/Target/options/"+opt_name);
588 }
589 
getTargetOptionBool(const string & target,const string & opt_name)590 bool  Resources::getTargetOptionBool(const string &target,
591                                      const string &opt_name)  throw (FWException)
592 {
593     string s=getTargetOptionStr(target,opt_name);
594     return (s=="true" || s=="True");
595 }
596 
597 
598