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