1 /*
2 
3                           Firewall Builder
4 
5                  Copyright (C) 2000 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 #include "global.h"
28 
29 #include "platforms.h"
30 #include "FWBSettings.h"
31 #include "interfaceProperties.h"
32 #include "interfacePropertiesObjectFactory.h"
33 
34 #include <QObject>
35 #include <QStringList>
36 #include <QComboBox>
37 #include <QtDebug>
38 
39 #include "fwbuilder/Cluster.h"
40 #include "fwbuilder/Firewall.h"
41 #include "fwbuilder/Interface.h"
42 #include "fwbuilder/FWOptions.h"
43 #include "fwbuilder/Management.h"
44 #include "fwbuilder/Resources.h"
45 #include "fwbuilder/Rule.h"
46 #include "fwbuilder/Policy.h"
47 #include <fwbuilder/FailoverClusterGroup.h>
48 #include <fwbuilder/StateSyncClusterGroup.h>
49 
50 #include <algorithm>
51 #include <iostream>
52 #include <memory>
53 
54 
55 using namespace std;
56 using namespace libfwbuilder;
57 
58 
59 QStringList emptyList;
60 QStringList logLevels;
61 QStringList logFacilities;
62 QStringList actionsOnReject;
63 QStringList routeOptions_pf_ipf;
64 QStringList routeLoadOptions_pf;
65 QStringList limitSuffixes;
66 QStringList classifyOptions_ipfw;
67 
init_platforms()68 void init_platforms()
69 {
70     logLevels.push_back("");
71     logLevels.push_back("");
72     logLevels.push_back(QObject::tr( "alert"  ));
73     logLevels.push_back(             "alert"  );
74     logLevels.push_back(QObject::tr( "crit"   ));
75     logLevels.push_back(             "crit"   );
76     logLevels.push_back(QObject::tr( "error"  ));
77     logLevels.push_back(             "error"  );
78     logLevels.push_back(QObject::tr( "warning"));
79     logLevels.push_back(             "warning");
80     logLevels.push_back(QObject::tr( "notice" ));
81     logLevels.push_back(             "notice" );
82     logLevels.push_back(QObject::tr( "info"   ));
83     logLevels.push_back(             "info"   );
84     logLevels.push_back(QObject::tr( "debug"  ));
85     logLevels.push_back(             "debug"  );
86 
87 
88     logFacilities.push_back("");
89     logFacilities.push_back("");
90     logFacilities.push_back(QObject::tr( "kern"   ));
91     logFacilities.push_back(             "kern"   );
92     logFacilities.push_back(QObject::tr( "user"   ));
93     logFacilities.push_back(             "user"   );
94     logFacilities.push_back(QObject::tr( "mail"   ));
95     logFacilities.push_back(             "mail"   );
96     logFacilities.push_back(QObject::tr( "daemon" ));
97     logFacilities.push_back(             "daemon" );
98     logFacilities.push_back(QObject::tr( "auth"   ));
99     logFacilities.push_back(             "auth"   );
100     logFacilities.push_back(QObject::tr( "syslog" ));
101     logFacilities.push_back(             "syslog" );
102     logFacilities.push_back(QObject::tr( "lpr"    ));
103     logFacilities.push_back(             "lpr"    );
104     logFacilities.push_back(QObject::tr( "news"   ));
105     logFacilities.push_back(             "news"   );
106     logFacilities.push_back(QObject::tr( "uucp"   ));
107     logFacilities.push_back(             "uucp"   );
108     logFacilities.push_back(QObject::tr( "cron"   ));
109     logFacilities.push_back(             "cron"   );
110     logFacilities.push_back(QObject::tr( "authpriv" ));
111     logFacilities.push_back(             "authpriv");
112     logFacilities.push_back(QObject::tr( "ftp"    ));
113     logFacilities.push_back(             "ftp"    );
114     logFacilities.push_back(QObject::tr( "local0" ));
115     logFacilities.push_back(             "local0" );
116     logFacilities.push_back(QObject::tr( "local1" ));
117     logFacilities.push_back(             "local1" );
118     logFacilities.push_back(QObject::tr( "local2" ));
119     logFacilities.push_back(             "local2" );
120     logFacilities.push_back(QObject::tr( "local3" ));
121     logFacilities.push_back(             "local3" );
122     logFacilities.push_back(QObject::tr( "local4" ));
123     logFacilities.push_back(             "local4" );
124     logFacilities.push_back(QObject::tr( "local5" ));
125     logFacilities.push_back(             "local5" );
126     logFacilities.push_back(QObject::tr( "local6" ));
127     logFacilities.push_back(             "local6" );
128     logFacilities.push_back(QObject::tr( "local7" ));
129     logFacilities.push_back(             "local7" );
130 
131     actionsOnReject.push_back("");
132     actionsOnReject.push_back("");
133     actionsOnReject.push_back(QObject::tr("ICMP admin prohibited"));
134     actionsOnReject.push_back("ICMP admin prohibited");
135     actionsOnReject.push_back(QObject::tr("ICMP host prohibited"));
136     actionsOnReject.push_back("ICMP host prohibited");
137     actionsOnReject.push_back(QObject::tr("ICMP host unreachable"));
138     actionsOnReject.push_back("ICMP host unreachable");
139     actionsOnReject.push_back(QObject::tr("ICMP net prohibited"));
140     actionsOnReject.push_back("ICMP net prohibited");
141     actionsOnReject.push_back(QObject::tr("ICMP net unreachable"));
142     actionsOnReject.push_back("ICMP net unreachable");
143     actionsOnReject.push_back(QObject::tr("ICMP port unreachable"));
144     actionsOnReject.push_back("ICMP port unreachable");
145     actionsOnReject.push_back(QObject::tr("ICMP protocol unreachable"));
146     actionsOnReject.push_back("ICMP protocol unreachable");
147     actionsOnReject.push_back(QObject::tr("TCP RST"));
148     actionsOnReject.push_back("TCP RST");
149 
150     routeOptions_pf_ipf.push_back(QObject::tr("None"));
151     routeOptions_pf_ipf.push_back("none");
152     routeOptions_pf_ipf.push_back(QObject::tr("Route through"));
153     routeOptions_pf_ipf.push_back("route_through");
154     routeOptions_pf_ipf.push_back(QObject::tr("Route reply through"));
155     routeOptions_pf_ipf.push_back("route_reply_through");
156     routeOptions_pf_ipf.push_back(QObject::tr("Route a copy through"));
157     routeOptions_pf_ipf.push_back("route_copy_through");
158 
159     routeLoadOptions_pf.push_back(QObject::tr("None"));
160     routeLoadOptions_pf.push_back("none");
161     routeLoadOptions_pf.push_back(QObject::tr("Bitmask"));
162     routeLoadOptions_pf.push_back("bitmask");
163     routeLoadOptions_pf.push_back(QObject::tr("Random"));
164     routeLoadOptions_pf.push_back("random");
165     routeLoadOptions_pf.push_back(QObject::tr("Source Hash"));
166     routeLoadOptions_pf.push_back("source_hash");
167     routeLoadOptions_pf.push_back(QObject::tr("Round Robin"));
168     routeLoadOptions_pf.push_back("round_robin");
169 
170     classifyOptions_ipfw.push_back(QObject::tr("None"));
171     classifyOptions_ipfw.push_back("-1");
172     classifyOptions_ipfw.push_back(QObject::tr("dummynet(4) 'pipe'"));
173     classifyOptions_ipfw.push_back("1");
174     classifyOptions_ipfw.push_back(QObject::tr("dummynet(4) 'queue'"));
175     classifyOptions_ipfw.push_back("2");
176 
177     limitSuffixes.push_back("");
178     limitSuffixes.push_back("");
179     limitSuffixes.push_back(QObject::tr("/day"));
180     limitSuffixes.push_back("/day");
181     limitSuffixes.push_back(QObject::tr("/hour"));
182     limitSuffixes.push_back("/hour");
183     limitSuffixes.push_back(QObject::tr("/minute"));
184     limitSuffixes.push_back("/minute");
185     limitSuffixes.push_back(QObject::tr("/second"));
186     limitSuffixes.push_back("/second");
187 }
188 
189 
isUsingNetZone(Firewall * fw)190 bool isUsingNetZone(Firewall *fw)
191 {
192     string platform=fw->getStr("platform");
193     return (platform=="pix" || platform=="fwsm");
194 }
195 
isDefaultPolicyRuleOptions(FWOptions * opt)196 bool isDefaultPolicyRuleOptions(FWOptions *opt)
197 {
198     bool res = true;
199     FWObject *p;
200     PolicyRule *rule = NULL;
201 
202     p = opt;
203     do {
204         p = p->getParent();
205         if (PolicyRule::cast(p)!=NULL) rule = PolicyRule::cast(p);
206     } while ( p!=NULL && Firewall::cast(p)==NULL );
207 
208     if (p==NULL)
209     {
210         qDebug() << "isDefaultPolicyRuleOptions()"
211                  << "Can not locate parent Firewall object for the options object";
212         opt->dump(false, true);
213         return true;
214     }
215 
216     QString platform = p->getStr("platform").c_str();
217 
218 //    if (fwbdebug)
219 //        qDebug(QString("Options object type: %1").arg(opt->getTypeName()));
220 
221     if (PolicyRuleOptions::isA(opt))
222     {
223 
224 	if (platform=="iptables")
225         {
226 	    res= ( opt->getStr("log_prefix").empty() &&
227                    opt->getStr("log_level").empty()      &&
228 		   opt->getInt("limit_value")<=0         &&
229 		   ! opt->getBool("limit_value_not")     &&
230 		   opt->getInt("limit_burst")<=0         &&
231 		   opt->getInt("connlimit_value")<=0     &&
232 		   ! opt->getBool("connlimit_above_not") &&
233 		   opt->getInt("connlimit_masklen")<=0   &&
234 
235 		   opt->getStr("hashlimit_name").empty() &&
236 		   opt->getInt("hashlimit_value")<=0     &&
237 		   opt->getInt("hashlimit_burst")<=0     &&
238 		   opt->getInt("hashlimit_size")<=0      &&
239 		   opt->getInt("hashlimit_max")<=0       &&
240 		   opt->getInt("hashlimit_expire")<=0    &&
241 		   opt->getInt("hashlimit_gcinterval")<=0  &&
242 
243                    opt->getInt("ulog_nlgroup")<=1        &&
244                    opt->getStr("limit_suffix").empty()   &&
245                    opt->getStr("firewall_is_part_of_any_and_networks") == "");
246 	}
247 
248 	if (platform=="pix" || platform=="fwsm")
249         {
250             string vers="version_"+p->getStr("version");
251 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
252             if ( Resources::platform_res[platform.toAscii().constData()]->getResourceBool(
253                   "/FWBuilderResources/Target/options/"+vers+"/pix_rule_syslog_settings"))
254 #else
255             if ( Resources::platform_res[platform.toLatin1().constData()]->getResourceBool(
256                   "/FWBuilderResources/Target/options/"+vers+"/pix_rule_syslog_settings"))
257 #endif
258             {
259                 res= ( opt->getStr("log_level").empty()        &&
260                    opt->getInt("log_interval")<=0          &&
261                    ! opt->getBool("disable_logging_for_this_rule") );
262             }
263             else
264             {
265                 res=true;
266             }
267 	}
268 
269 	if (platform=="pf")
270         {
271             string version = p->getStr("version");
272             bool ge_4_0 = XMLTools::version_compare(version, "4.0")>=0;
273             bool ge_4_5 = XMLTools::version_compare(version, "4.5")>=0;
274             if (ge_4_5)
275             {
276                 res = (!opt->getBool("pf_no_sync") && !opt->getBool("pf_pflow"));
277             }
278 
279             if (ge_4_0)
280             {
281                 res = res &&
282                     ( opt->getStr("log_prefix").empty()       &&
283                       opt->getInt("pf_rule_max_state")<=0     &&
284                       ! opt->getBool("pf_source_tracking")    &&
285                       opt->getInt("pf_max_src_conn")<=0       &&
286                       opt->getInt("pf_max_src_conn_rate_num")<=0       &&
287                       opt->getInt("pf_max_src_conn_rate_seconds")<=0 &&
288                       ! opt->getBool("pf_keep_state") &&
289                       ! opt->getBool("pf_sloppy_tracker") &&
290                       ! opt->getBool("pf_synproxy")    &&
291                       ! opt->getBool("pf_modulate_state")
292                 );
293             }else
294             {
295                 res = res &&
296                     ( opt->getStr("log_prefix").empty()       &&
297                       opt->getInt("pf_rule_max_state")<=0     &&
298                       ! opt->getBool("pf_source_tracking")    &&
299                       opt->getInt("pf_max_src_conn")<=0       &&
300                       opt->getInt("pf_max_src_conn_rate_num")<=0       &&
301                         opt->getInt("pf_max_src_conn_rate_seconds")<=0 &&
302                       ! opt->getBool("pf_keep_state") &&
303                       ! opt->getBool("pf_sloppy_tracker") &&
304                       ! opt->getBool("pf_synproxy")    &&
305                       ! opt->getBool("pf_modulate_state")
306                 );
307             }
308 	}
309 
310 	if (platform=="ipf")
311         {
312 	    res= ( opt->getStr("ipf_log_facility").empty()       &&
313                    opt->getStr("log_level").empty()      &&
314 		   ! opt->getBool("ipf_keep_frags") &&
315                    ! opt->getBool("ipf_return_icmp_as_dest") );
316 	}
317 
318 	if (platform=="ipfw")
319         {
320 	    //res= ( ! opt->getBool("stateless") );
321             res = true;
322 	}
323 
324         if (rule!=NULL)
325         {
326             PolicyRule::Action act = rule->getAction();
327 
328             if (act==PolicyRule::Accept)
329             {
330                 // by default, these actions are not stateless
331                 res = res && (!opt->getBool("stateless"));
332             } else
333             {
334                 // other actions are stateless by default
335                 res = res && opt->getBool("stateless");
336             }
337 
338         }
339 
340         // all rules are stateless for IOS ACL
341 	if (platform=="iosacl" || platform=="procurve_acl")
342         {
343             res = !opt->getBool("iosacl_add_mirror_rule");
344         }
345 
346     }
347     return res;
348 }
349 
isDefaultNATRuleOptions(FWOptions * opt)350 bool isDefaultNATRuleOptions(FWOptions *opt)
351 {
352     bool res=true;
353     FWObject *p;
354 
355     p=opt;
356     do {  p=p->getParent();
357     } while ( p!=NULL && Firewall::cast(p)==NULL );
358 
359     assert(p!=NULL);
360 
361     QString platform = p->getStr("platform").c_str();
362 
363     if (NATRuleOptions::isA(opt))
364     {
365 	if (platform=="iptables")
366         {
367             res = !opt->getBool("ipt_use_snat_instead_of_masq") &&
368                 !opt->getBool("ipt_nat_random") &&
369                 !opt->getBool("ipt_nat_persistent");
370         }
371 
372 	if (platform=="pf")
373         {
374             // if "pf_pool_type_none" is undefined, then all others
375             // should not be defined too because they all are set by
376             // the same dialog
377             // In this case consider options default.
378             res = (opt->getStr("pf_pool_type_none") == "" ||
379                    ( opt->getBool("pf_pool_type_none") &&
380                      ! opt->getBool("pf_bitmask")      &&
381                      ! opt->getBool("pf_random")       &&
382                      ! opt->getBool("pf_source_hash")  &&
383                      ! opt->getBool("pf_round_robin")  &&
384                      ! opt->getBool("pf_static_port") ) );
385 	}
386 
387 	if (platform=="pix" || platform=="fwsm")
388         {
389             res = (! opt->getBool("asa8_nat_dns") &&
390                    ! opt->getBool("asa8_nat_static") &&
391                    ! opt->getBool("asa8_nat_dynamic"));
392 
393         }
394     }
395     return res;
396 }
397 
isDefaultRoutingRuleOptions(FWOptions * opt)398 bool isDefaultRoutingRuleOptions(FWOptions *opt)
399 {
400     bool res=true;
401 
402 //    if (fwbdebug)
403 //        qDebug(QString("Options object type: %1").arg(opt->getTypeName()));
404 
405     if (RoutingRuleOptions::isA(opt))
406     {
407         res= ( ! opt->getBool("no_fail") );
408     }
409     return res;
410 }
411 
getVersionString(const QString & platform,const QString & version)412 QString getVersionString(const QString &platform, const QString &version)
413 {
414     list<QStringPair> vl;
415     getVersionsForPlatform(platform, vl);
416     list<QStringPair>::iterator li =
417         std::find_if(vl.begin(),vl.end(),findFirstInQStringPair(version));
418     QString readableVersion = (li!=vl.end())?li->second:"";
419     return readableVersion;
420 }
421 
getVersionsForPlatform(const QString & platform,std::list<QStringPair> & res)422 void getVersionsForPlatform(const QString &platform, std::list<QStringPair> &res)
423 {
424 /* versions are defined here instead of the resource files so that
425  * strings could be localized. We use strings that can be localized
426  * only for iptables but define versions for all platforms here for
427  * uniformity
428  */
429 
430     if (platform=="iptables")
431     {
432         res.push_back(QStringPair("", QObject::tr("- any -")));
433         res.push_back(QStringPair("lt_1.2.6", QObject::tr("1.2.5 or earlier")));
434         res.push_back(QStringPair("ge_1.2.6", QObject::tr("1.2.6 to 1.2.8")));
435         res.push_back(QStringPair("1.2.9", QObject::tr("1.2.9 to 1.2.11")));
436         res.push_back(QStringPair("1.3.0", QObject::tr("1.3.x")));
437         res.push_back(QStringPair("1.4.0", QObject::tr("1.4.0 or later")));
438         res.push_back(QStringPair("1.4.1.1", QObject::tr("1.4.1.1 or later")));
439         res.push_back(QStringPair("1.4.3", QObject::tr("1.4.3")));
440         res.push_back(QStringPair("1.4.4", QObject::tr("1.4.4 or later")));
441         res.push_back(QStringPair("1.4.11", QObject::tr("1.4.11 or later")));
442         res.push_back(QStringPair("1.4.20", QObject::tr("1.4.20 or later")));
443     } else
444     {
445         // we list supported versions for the following platforms in
446         // corresponding resource .xml file
447         if (platform=="pix" ||
448             platform=="fwsm" ||
449             platform=="nxosacl" ||
450             platform=="iosacl" ||
451             platform=="procurve_acl")
452         {
453 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
454             QString lst = Resources::platform_res[
455                 platform.toAscii().constData()]->getResourceStr(
456                     "/FWBuilderResources/Target/versions").c_str();
457 #else
458             QString lst = Resources::platform_res[
459                 platform.toLatin1().constData()]->getResourceStr(
460                     "/FWBuilderResources/Target/versions").c_str();
461 #endif
462 
463             QStringList ll=lst.split(',');
464 
465             for (QStringList::iterator i=ll.begin(); i!=ll.end(); ++i)
466                 res.push_back(QStringPair(*i,*i));
467         } else
468         {
469             if (platform=="pf")
470             {
471                 res.push_back(QStringPair("","- any -"));
472                 res.push_back(QStringPair("3.x", QObject::tr("3.x")));
473 		res.push_back(QStringPair("ge_3.7", QObject::tr("3.7 to 3.9")));
474                 res.push_back(QStringPair("4.0", QObject::tr("4.0 to 4.2")));
475                 res.push_back(QStringPair("4.3", QObject::tr("4.3")));
476                 res.push_back(QStringPair("4.5", QObject::tr("4.5")));
477                 res.push_back(QStringPair("4.6", QObject::tr("4.6")));
478                 res.push_back(QStringPair("4.7", QObject::tr("4.7 and later")));
479 /* add pf versions here */
480             } else
481             {
482                 if (platform=="ipf")
483                 {
484                     res.push_back(QStringPair("","- any -"));
485 /* add ipf versions here */
486                 } else
487                 {
488                     if (platform=="ipfw")
489                     {
490                         res.push_back(QStringPair("","- any -"));
491 /* add ipfw versions here */
492                     } else
493                         res.push_back(QStringPair("","- any -"));
494                 }
495             }
496         }
497     }
498 }
499 
500 /*
501  * ticket #58: move state sync types and failover types to resource files.
502  *
503  * Note: this function fills in list of QString pairs, each pair is
504  * <protocol_name>,<user_readable_protocol_name>
505  * The second element in the pair is for QComboBox and is visible to the user.
506  */
getStateSyncTypesForOS(const QString & host_os,std::list<QStringPair> & res)507 void getStateSyncTypesForOS(const QString &host_os, std::list<QStringPair> &res)
508 {
509     Resources* os_res = Resources::os_res[host_os.toStdString()];
510     if (os_res==NULL) return;
511     list<string> protocols;
512     os_res->getResourceStrList("/FWBuilderResources/Target/protocols/state_sync",
513                                protocols);
514     _repackStringList(protocols, res);
515 }
516 
getFailoverTypesForOS(const QString & host_os,std::list<QStringPair> & res)517 void getFailoverTypesForOS(const QString &host_os, std::list<QStringPair> &res)
518 {
519     Resources* os_res = Resources::os_res[host_os.toStdString()];
520     if (os_res==NULL) return;
521     list<string> protocols;
522     os_res->getResourceStrList("/FWBuilderResources/Target/protocols/failover",
523                                protocols);
524     _repackStringList(protocols, res);
525 }
526 
getInterfaceTypes(Interface * iface,list<QStringPair> & res)527 void getInterfaceTypes(Interface *iface, list<QStringPair> &res)
528 {
529     FWObject *fw = iface->getParent();
530     string host_os = fw->getStr("host_OS");
531     Resources* os_res = Resources::os_res[host_os];
532     if (os_res==NULL) return;
533     list<string> interface_types;
534 
535     if (Cluster::isA(fw))
536     {
537         os_res->getResourceStrList("/FWBuilderResources/Target/interfaces/cluster",
538                                    interface_types);
539     } else
540     {
541         os_res->getResourceStrList("/FWBuilderResources/Target/interfaces/firewall",
542                                    interface_types);
543     }
544     _repackStringList(interface_types, res);
545 }
546 
547 /*
548  * Return list of types of subinterfaces that given interface can have
549  *
550  * @iface an Interface object. This is not a subinterface, this is a
551  * regular interface. This function returns list of subinterface types
552  * this interface can have.
553  *
554  * @res a list of pairs of QString, each pair is <type>,<description>
555  */
getSubInterfaceTypes(Interface * iface,list<QStringPair> & res)556 void getSubInterfaceTypes(Interface *iface, list<QStringPair> &res)
557 {
558     FWObject *p = Host::getParentHost(iface);
559     //FWObject *p = iface->getParentHost();
560     assert(p!=NULL);
561 
562     QString host_os = p->getStr("host_OS").c_str();
563     Resources* os_res = Resources::os_res[host_os.toStdString()];
564     if (os_res==NULL) return;
565 
566     FWOptions *ifopt;
567     ifopt = Interface::cast(iface)->getOptionsObject();
568     string parent_type = ifopt->getStr("type");
569 
570     // empty parent type is equivalent to "ethernet" for backwards
571     // compatibility
572     if (parent_type.empty()) parent_type = "ethernet";
573 
574     QString obj_name = iface->getName().c_str();
575 
576     list<string> interface_types;
577     os_res->getResourceStrList(
578         "/FWBuilderResources/Target/subinterfaces/" + parent_type,
579         interface_types);
580     _repackStringList(interface_types, res);
581 }
582 
setInterfaceTypes(QComboBox * iface_type,Interface * iface,const QString & current_type)583 void setInterfaceTypes(QComboBox *iface_type,
584                        Interface *iface,
585                        const QString &current_type)
586 {
587     bool this_is_subinterface = Interface::isA(iface->getParent());
588     list<QStringPair> mapping;
589     if (this_is_subinterface)
590         getSubInterfaceTypes(Interface::cast(iface->getParent()), mapping);
591     else getInterfaceTypes(iface, mapping);
592 
593     if (st->getBool("Objects/Interface/autoconfigureInterfaces"))
594     {
595         // #335 : if interface name matches naming convention for vlan
596         // interfaces and vlan type is in the list that came from the
597         // resource file, then leave only vlan in the list we return.
598         // Note that if resource file says this subint can not be vlan, we
599         // dan't return vlan type on the list even if its name looks like
600         // it could be one.
601         FWObject *p = Host::getParentHost(iface);
602         //FWObject *p = iface->getParentHost();
603         assert(p!=NULL);
604         QString host_os = p->getStr("host_OS").c_str();
605         QString obj_name = iface->getName().c_str();
606 
607         Resources* os_res = Resources::os_res[p->getStr("host_OS")];
608         string os_family = p->getStr("host_OS");
609         if (os_res!=NULL)
610             os_family = os_res->getResourceStr("/FWBuilderResources/Target/family");
611 
612         std::auto_ptr<interfaceProperties> int_prop(
613             interfacePropertiesObjectFactory::getInterfacePropertiesObject(
614                 os_family));
615         if (int_prop->looksLikeVlanInterface(obj_name))
616         {
617             QString parent_name = iface->getParent()->getName().c_str();
618             QString err;
619             if (int_prop->isValidVlanInterfaceName(obj_name, parent_name, err))
620             {
621                 // iface can be valid vlan interface. Leave only vlan type
622                 // in the list if it was there to begin with.
623                 for (list<QStringPair>::iterator it=mapping.begin();
624                      it!=mapping.end(); ++it)
625                 {
626                     QString itype = it->first;
627                     QString rtype = it->second;
628                     if (itype == "8021q")
629                     {
630                         mapping.clear();
631                         mapping.push_back(QStringPair(itype, rtype));
632                         mapping.push_back(QStringPair("unknown", "Unknown"));
633                         break;
634                     }
635                 }
636             }
637         }
638     }
639 
640     list<QStringPair>::iterator it;
641     int idx = 0;
642     int unknown_idx = 0;
643     int current_idx = -1;
644     for (it = mapping.begin(); it != mapping.end(); it++)
645     {
646         if (it->first == "unknown") unknown_idx = idx;
647         iface_type->addItem(it->second);
648         iface_type->setItemData(idx,  QVariant(it->first));
649         if (current_type == it->first)
650             current_idx = idx;
651         idx++;
652     }
653     if (current_idx >= 0)
654         iface_type->setCurrentIndex(current_idx);
655     else
656         iface_type->setCurrentIndex(unknown_idx);
657 }
658 
659 /* currently we return the same list for all platforms */
getLogLevels(const QString &)660 const QStringList& getLogLevels(const QString&)
661 {
662     return logLevels;
663 }
664 
getLogFacilities(const QString &)665 const QStringList& getLogFacilities(const QString&)
666 {
667     return logFacilities;
668 }
669 
getActionsOnReject(const QString &)670 const QStringList& getActionsOnReject(const QString&)
671 {
672     return actionsOnReject;
673 }
674 
675 /*
676  *  need to return mapping list for the parameter 'route_option' of
677  *  action 'Routing' regardless of the firewall platform even though
678  *  it only makes sense and is needed for pf and ipf. This is because
679  *  ActionsDialog is designed with widget stack and therefore must
680  *  always initialize widgets for all platforms. Worse, it always
681  *  saves all parameters into rule options object, regardless of the
682  *  platform. So, if we return an empty mapping list from this method
683  *  because platform is not pf or ipf while user is editing action
684  *  parameters for iptables, parameters for pf and ipf get saved
685  *  uninitizalized and unmapped. QComboBox::currentText() returns the
686  *  first item which goes straight into rule options object. This is
687  *  ok in English locale, but breaks XML if the item has been
688  *  translated and the program runs under national locale. Sigh.
689  */
getRouteOptions_pf_ipf(const QString &)690 const QStringList& getRouteOptions_pf_ipf(const QString&)
691 {
692     return routeOptions_pf_ipf;
693 }
694 
getRouteLoadOptions_pf(const QString &)695 const QStringList& getRouteLoadOptions_pf(const QString&)
696 {
697     return routeLoadOptions_pf;
698 }
699 
getClassifyOptions_ipfw(const QString &)700 const QStringList& getClassifyOptions_ipfw(const QString&)
701 {
702     return classifyOptions_ipfw;
703 }
704 
getLimitSuffixes(const QString &)705 const QStringList& getLimitSuffixes(const QString&)
706 {
707     return limitSuffixes;
708 }
709 
710 
getScreenNames(const QStringList & sl)711 QStringList getScreenNames(const QStringList &sl)
712 {
713     QStringList res;
714 
715     for( QStringList::const_iterator it = sl.begin();
716          it!=sl.end();
717          ++it,++it)
718     {
719         res.push_back(*it);
720     }
721     return res;
722 }
723 
getScreenName(QString s,const QStringList & sl)724 QString getScreenName(QString s, const QStringList &sl)
725 {
726     QString res;
727     for( QStringList::const_iterator it = sl.begin();
728          it!=sl.end();
729          ++it)
730     {
731         res=(*it);
732         ++it;
733         if ((*it)==s) break;
734     }
735     return res;
736 }
737 
getRuleAction(Rule * rule)738 QString getRuleAction(Rule *rule)
739 {
740     PolicyRule *policy_rule = PolicyRule::cast(rule);
741     NATRule *nat_rule = NATRule::cast(rule);
742     string act;
743     if (policy_rule) act = policy_rule->getActionAsString();
744     if (nat_rule) act = nat_rule->getActionAsString();
745     return act.c_str();
746 }
747 
748 /*
749  * will remap names of some actions to make it clear what commands or
750  * configuration language keywords they will be translated to for the
751  * target firewall platform. This should help users who are familiar
752  * with the platform. There are very few places where such mapping is
753  * necessary, plus we need to provide for localization of the mapped
754  * names. That is why action names are not stored in platform resource
755  * files and are not pulled using Rule::getActionAsString.
756  */
757 
getActionNameForPlatform(Firewall * fw,Rule * rule)758 QString getActionNameForPlatform(Firewall *fw, Rule *rule)
759 {
760     if (fw==NULL) return "";
761     PolicyRule *policy_rule = PolicyRule::cast(rule);
762     NATRule *nat_rule = NATRule::cast(rule);
763     string act;
764     if (policy_rule) act = policy_rule->getActionAsString();
765     if (nat_rule) act = nat_rule->getActionAsString();
766     return getActionNameForPlatform(fw, act);
767 }
768 
getActionNameForPlatform(Firewall * fw,const std::string & action)769 QString getActionNameForPlatform(Firewall *fw, const std::string &action)
770 {
771     if (fw==NULL) return "";
772     string platform = fw->getStr("platform");
773     string name;
774     try
775     {
776         name = Resources::getTargetCapabilityStr(
777             platform, "actions/" + action + "/description");
778     } catch (FWException &ex) { }
779     return name.c_str();
780 }
781 
782 /*
783  * this function provides logic for the decision whether the rule
784  * should be stateless by default. Currently it only depends on the
785  * action, but may depend on the platform as well.
786  *
787  * actions Accept, Tag and Route by default assume the rule is
788  * stateful.  Other actions by default assume it is stateless
789  * and set rule option accordingly
790  *
791  * See bugs #1676635 and 1671910
792  */
getStatelessFlagForAction(PolicyRule * rule)793 bool getStatelessFlagForAction(PolicyRule *rule)
794 {
795     PolicyRule::Action act = rule->getAction();
796     if (act==PolicyRule::Accept) return false;
797     else
798         return true;
799 }
800 
801 /**
802  * Returns translatable string - name of the corresponding rule element.
803  */
getReadableRuleElementName(const string & platform,const string & re_type_name)804 QString getReadableRuleElementName(const string &platform,
805                                    const string &re_type_name)
806 {
807     bool nat_intf_in = Resources::getTargetCapabilityBool(
808             platform, "inbound_interface_in_nat");
809     bool nat_intf_out = Resources::getTargetCapabilityBool(
810             platform, "outbound_interface_in_nat");
811 
812     // The following map TYPENAME of RuleElement classes to readable
813     // translatable names.
814     if (re_type_name == "Src") return QObject::tr("Source");
815     if (re_type_name == "Dst") return QObject::tr("Destination");
816     if (re_type_name == "Srv") return QObject::tr("Service");
817     if (re_type_name == "Itf") return QObject::tr("Interface");
818     if (re_type_name == "When") return QObject::tr("Time");
819 
820     if (re_type_name == "OSrc") return QObject::tr("Original Src");
821     if (re_type_name == "ODst") return QObject::tr("Original Dst");
822     if (re_type_name == "OSrv") return QObject::tr("Original Srv");
823 
824     if (re_type_name == "TSrc") return QObject::tr("Translated Src");
825     if (re_type_name == "TDst") return QObject::tr("Translated Dst");
826     if (re_type_name == "TSrv") return QObject::tr("Translated Srv");
827 
828     if (nat_intf_in != nat_intf_out)
829     {
830         // For some platforms I only show one interface column in nat
831         // rules, in this case nat_intf_in and nat_intf_out have
832         // different values.  For example, for PF I hide inbound
833         // interface and show outbound interface column. Columns title
834         // should then be just "Interface"
835         if (re_type_name == "ItfInb") return QObject::tr("Interface");
836         if (re_type_name == "ItfOutb") return QObject::tr("Interface");
837     } else
838     {
839         if (re_type_name == "ItfInb") return QObject::tr("Interface In");
840         if (re_type_name == "ItfOutb") return QObject::tr("Interface Out");
841     }
842 
843     if (re_type_name == "RDst") return QObject::tr("Destination");
844     if (re_type_name == "RGtw") return QObject::tr("Gateway");
845     if (re_type_name == "RItf") return QObject::tr("Interface");
846 
847     // as of v3.0.x the following are not real rule elements (not separate
848     // classes with names) but just attributes of corresponding Rule class.
849     if (re_type_name == "Direction") return QObject::tr("Direction");
850     if (re_type_name == "Action") return QObject::tr("Action");
851     if (re_type_name == "Options") return QObject::tr("Options");
852     if (re_type_name == "Metric") return QObject::tr("Metric");
853     if (re_type_name == "Comment") return QObject::tr("Comment");
854 
855     return QString();
856 }
857 
getAllPlatforms(bool filter)858 QMap<QString,QString> getAllPlatforms(bool filter)
859 {
860     QMap<QString,QString> res;
861     map<string,string> platforms = Resources::getPlatforms();
862     map<string,string>::iterator i;
863     for (i=platforms.begin(); i!=platforms.end(); i++)
864     {
865         QString name = i->first.c_str();
866         QString res_status = Resources::platform_res[name.toStdString()]->getResourceStr(
867             "/FWBuilderResources/Target/status/").c_str();
868         QString status = st->getTargetStatus(name, res_status);
869         if (filter && status == "disabled") continue;
870         res[name] = i->second.c_str();
871     }
872     return res;
873 }
874 
getAllOS(bool filter)875 QMap<QString,QString> getAllOS(bool filter)
876 {
877     QMap<QString,QString> res;
878     map<string,string> OSs = Resources::getOS();
879     map<string,string>::iterator i;
880     for (i=OSs.begin(); i!=OSs.end(); i++)
881     {
882         QString name = i->first.c_str();
883         QString res_status = Resources::os_res[name.toStdString()]->getResourceStr(
884             "/FWBuilderResources/Target/status/").c_str();
885         QString status = st->getTargetStatus(name, res_status);
886         if (filter && status == "disabled") continue;
887         res[name] = i->second.c_str();
888     }
889     return res;
890 }
891 
readPlatform(QComboBox * platform)892 QString readPlatform(QComboBox *platform)
893 {
894     return platform->itemData(platform->currentIndex()).toString();
895 }
896 
readHostOS(QComboBox * hostOS)897 QString readHostOS(QComboBox *hostOS)
898 {
899     return hostOS->itemData(hostOS->currentIndex()).toString();
900 }
901 
902 /*
903  * Fill combobox widget <platform> with items that exist in resources.
904  * If second argument is not an empty string, make corresponding item current.
905  * If it is an empty string, add an empty item on top to the combo box and make
906  * it current.
907  */
setPlatform(QComboBox * platform,const QString & pl)908 void setPlatform(QComboBox *platform, const QString &pl)
909 {
910     platform->clear();
911     // platforms maps platform name (pix) to readable name (Cisco PIX)
912     QMap<QString,QString> platforms = getAllPlatforms();
913 
914     QMap<QString,QString>::iterator i;
915 
916     // platform_mapping maps key (<group>.<platform name>) to pair
917     // <group>, <platform name>
918     QMap<QString, QPair<QString, QString> > platform_mapping;
919     QStringList platform_keys;
920 
921     for (i=platforms.begin(); i!=platforms.end(); i++)
922     {
923         QString group =
924             Resources::platform_res[i.key().toLatin1().constData()]->
925                 getResourceStr("/FWBuilderResources/Target/group").c_str();
926         QString key = group + "." + i.key();
927         platform_mapping[key] = QPair<QString,QString>(group, i.key());
928         platform_keys.push_back(key);
929     }
930 
931     qSort(platform_keys);
932 
933     QStringList::iterator iter;
934     int ind = 0;
935     int cp = 0;
936 
937     if (pl.isEmpty())
938     {
939         platform->addItem("", "");
940         cp++;
941     }
942 
943     QString current_group = "";
944     for (iter=platform_keys.begin(); iter!=platform_keys.end(); iter++)
945     {
946         if (fwbdebug) qDebug() << *iter;
947 
948         QString group = platform_mapping[*iter].first;
949         QString platform_name = platform_mapping[*iter].second;
950 
951         if (platforms.count(platform_name) == 0) continue;
952 
953         if (group != current_group)
954         {
955             current_group = group;
956 #if (QT_VERSION > 0x040500)
957             platform->insertSeparator(cp);  // QT before 4.4.? does not support separator in QComboBox
958 #else
959             platform->addItem("");
960 #endif
961             cp++;
962         }
963 
964         platform->addItem(platforms[platform_name], platform_name);
965         // note that if pl is "", then no real platform name will
966         // match it and ind will remain 0, which makes the top item in
967         // the combobox current.
968         if ( pl == platform_name ) ind = cp;
969         cp++;
970     }
971     platform->setCurrentIndex( ind );
972 }
973 
974 /*
975  * Fill in "host os" combo box with list of os supported for the given
976  * platform and make current host os item current.
977  *
978  * If platform == "", then use all known host OS but also add
979  *  empty item on top of the combobox and make that item current.
980  * If os == "", make the first OS in the list current.
981  */
setHostOS(QComboBox * hostOS,const QString & platform,const QString & os)982 void setHostOS(QComboBox *hostOS, const QString &platform, const QString &os)
983 {
984     hostOS->clear();
985 
986     QStringList supported_os_list;
987 
988     if (!platform.isEmpty())
989     {
990         Resources *platform_res = Resources::platform_res[platform.toLatin1().constData()];
991         if (!platform_res)
992             platform_res = Resources::platform_res["unknown"];
993 
994         QString supported_os = platform_res->
995             getResourceStr("/FWBuilderResources/Target/supported_os").c_str();
996 
997         if (fwbdebug)
998             qDebug("supported_os %s", supported_os.toLatin1().constData());
999 
1000         if (supported_os.isEmpty())
1001         {
1002             // something is broken, we have no supported host OS for
1003             // this platform.  Just add os to the combo box and return
1004             if (fwbdebug)
1005                 qDebug("No supported host OS for platform %s",
1006                        platform.toLatin1().constData());
1007 
1008             hostOS->addItem(os, os);
1009             hostOS->setCurrentIndex(0);
1010             return;
1011         }
1012         supported_os_list = supported_os.split(",");
1013 
1014         int cp = 0;
1015         int ind = 0;
1016         QMap<QString,QString> OSs = getAllOS();
1017         QStringList::iterator os_iter;
1018         for (os_iter=supported_os_list.begin();
1019              os_iter!=supported_os_list.end(); ++os_iter)
1020         {
1021             QString os_code = *os_iter;
1022             if (OSs.count(os_code) > 0)
1023             {
1024                 hostOS->addItem( OSs[os_code], os_code);
1025                 if ( os == os_code ) ind = cp;
1026                 cp++;
1027             }
1028         }
1029         hostOS->setCurrentIndex( ind );
1030         return;
1031     }
1032 
1033     // platform is empty
1034 
1035     int cp = 0;
1036     int ind = 0;
1037 
1038     hostOS->addItem("", "");
1039     cp++;
1040 
1041     QMap<QString,QString> OSs = getAllOS();
1042     QMap<QString,QString>::iterator i;
1043     for (i=OSs.begin(); i!=OSs.end(); i++)
1044     {
1045         hostOS->addItem( i.value(), i.key() );
1046         if ( os == i.key() ) ind = cp;
1047         cp++;
1048     }
1049 
1050     hostOS->setCurrentIndex( ind );
1051 }
1052 
_repackStringList(list<string> & list1,list<QStringPair> & list2)1053 void _repackStringList(list<string> &list1, list<QStringPair> &list2)
1054 {
1055     list2.clear();
1056     foreach(string p, list1)
1057     {
1058         QString str = QString(p.c_str());
1059         QStringList pl = str.split(",");
1060         if (pl.size() == 1)
1061             list2.push_back(QStringPair(str, str));
1062         else
1063             list2.push_back(QStringPair(pl[0], pl[1]));
1064     }
1065 }
1066 
setDefaultStateSyncGroupAttributes(StateSyncClusterGroup * grp)1067 void setDefaultStateSyncGroupAttributes(StateSyncClusterGroup *grp)
1068 {
1069     FWObject *p = grp;
1070     while (p && Cluster::cast(p)==NULL) p = p->getParent();
1071     assert(p != NULL);
1072     Cluster *cluster = Cluster::cast(p);
1073     Resources *os_res = Resources::os_res[cluster->getStr("host_OS")];
1074     assert(os_res != NULL);
1075 
1076     list<string> protocols;
1077     os_res->getResourceStrList("/FWBuilderResources/Target/protocols/state_sync",
1078                                protocols);
1079 
1080     QStringList protocol_names = QString(protocols.front().c_str()).split(",");
1081 
1082     grp->setName(protocol_names[1].toStdString());
1083     grp->setStr("type", protocol_names[0].toStdString());
1084 }
1085 
setDefaultFailoverGroupAttributes(FailoverClusterGroup * grp)1086 void setDefaultFailoverGroupAttributes(FailoverClusterGroup *grp)
1087 {
1088     FWObject *p = grp;
1089     while (p && Cluster::cast(p)==NULL) p = p->getParent();
1090     assert(p != NULL);
1091     Cluster *cluster = Cluster::cast(p);
1092     Resources *os_res = Resources::os_res[cluster->getStr("host_OS")];
1093     assert(os_res != NULL);
1094 
1095     FWOptions *gropt = grp-> getOptionsObject();
1096     assert(gropt != NULL);
1097 
1098     string failover_protocol = grp->getStr("type");
1099 
1100     if (failover_protocol == "carp")
1101     {
1102         gropt->setStr("carp_password", "");
1103         gropt->setInt("carp_vhid", 1);
1104         gropt->setInt("carp_advbase", 1);
1105         gropt->setInt("carp_master_advskew", 10);
1106         gropt->setInt("carp_default_advskew", 20);
1107     }
1108 
1109     if (failover_protocol == "vrrp")
1110     {
1111         gropt->setStr("vrrp_secret", "");
1112         gropt->setInt("vrrp_vrid", 1);
1113         gropt->setBool("vrrp_over_ipsec_ah", false);
1114     }
1115 
1116     if (failover_protocol == "heartbeat")
1117     {
1118         string default_address =
1119             os_res->getResourceStr(
1120                 "/FWBuilderResources/Target/protocols/heartbeat/default_address");
1121         string default_port =
1122             os_res->getResourceStr(
1123                 "/FWBuilderResources/Target/protocols/heartbeat/default_port");
1124 
1125         gropt->setStr("heartbeat_address", default_address);
1126         gropt->setStr("heartbeat_port", default_port);
1127         gropt->setBool("heartbeat_unicast", false);
1128     }
1129 
1130     if (failover_protocol == "openais")
1131     {
1132         string default_address =
1133             os_res->getResourceStr(
1134                 "/FWBuilderResources/Target/protocols/openais/default_address");
1135         string default_port =
1136             os_res->getResourceStr(
1137                 "/FWBuilderResources/Target/protocols/openais/default_port");
1138         gropt->setStr("openais_address", default_address);
1139         gropt->setStr("openais_port", default_port);
1140     }
1141 
1142     if (failover_protocol == "pix_failover")
1143     {
1144         gropt->setStr("pix_failover_key", "");
1145     }
1146 }
1147 
guessInterfaceLabel(InterfaceData * idata)1148 void guessInterfaceLabel(InterfaceData *idata)
1149 {
1150 /*
1151  *  some firewalls report fairly regular names for interfaces through
1152  *  their built-in SNMP agent. We can use this to assign labels
1153  *  automatically.
1154  *
1155  *  in PIX interfaces have names like "PIX Firewall 'inside' interface"
1156  *
1157  */
1158     QString qs_name = idata->name.c_str();
1159     QString qs_label;
1160 
1161     QRegExp pat1("Adaptive Security Appliance '(.*)' interface");
1162     QRegExp pat2("Cisco PIX Security Appliance '(.*)' interface");
1163     QRegExp pat3("PIX Firewall '(.*)' interface");
1164 
1165     if (pat1.indexIn(qs_name) > -1) qs_label = pat1.cap(1);
1166     if (pat2.indexIn(qs_name) > -1) qs_label = pat2.cap(1);
1167     if (pat3.indexIn(qs_name) > -1) qs_label = pat3.cap(1);
1168 
1169     idata->label = qs_label.toStdString();
1170 
1171     if ( ! idata->isDyn &&
1172          ! idata->isUnnumbered &&
1173          ! idata->isBridgePort &&
1174          idata->addr_mask.size()!=0 &&
1175          idata->addr_mask.front()->getAddressPtr()->toString() == InetAddr::getLoopbackAddr().toString())
1176         idata->label = "loopback";
1177 }
1178 
guessSecurityLevel(const string &,InterfaceData * idata)1179 void guessSecurityLevel(const string&, InterfaceData *idata)
1180 {
1181     InetAddrMask n10(InetAddr("10.0.0.0"), InetAddr("255.0.0.0"));
1182     InetAddrMask n172(InetAddr("172.16.0.0"), InetAddr("255.240.0.0"));
1183     InetAddrMask n192(InetAddr("192.168.0.0"), InetAddr("255.255.0.0"));
1184 
1185     idata->securityLevel = -1;
1186 
1187     string llbl = idata->label;
1188 
1189     for (string::size_type i=0; i<llbl.length(); i++)
1190         llbl[i] = tolower( llbl[i] );
1191 
1192     if ( llbl=="out" ||
1193          llbl=="ext" ||
1194          llbl=="internet" ||
1195          llbl=="wan" ||
1196          llbl=="dsl" ||
1197          llbl=="cable" ||
1198          llbl.find("outside")!=string::npos ||
1199          llbl.find("external")!=string::npos) idata->securityLevel = 0;
1200 
1201     if ( llbl=="lan" ||
1202          llbl=="in" ||
1203          llbl.find("inside")!=string::npos ||
1204          llbl.find("internal")!=string::npos ) idata->securityLevel = 100;
1205 
1206     if ( llbl.find("dmz")!=string::npos ) idata->securityLevel = 50;
1207 
1208     if ((*(idata->addr_mask.front()->getAddressPtr()))==InetAddr::getLoopbackAddr())
1209         idata->securityLevel = 100;
1210 
1211     if (idata->name=="Null0") idata->securityLevel = 100;
1212 
1213     if (idata->securityLevel==-1 &&
1214         ! idata->isDyn && ! idata->isUnnumbered && ! idata->isBridgePort)
1215     {
1216         if (n10.belongs(InetAddr(*(idata->addr_mask.front()->getAddressPtr()))))
1217             idata->securityLevel = 100;
1218 
1219         if (n172.belongs(InetAddr(*(idata->addr_mask.front()->getAddressPtr()))))
1220             idata->securityLevel = 100;
1221 
1222         if (n192.belongs(InetAddr(*(idata->addr_mask.front()->getAddressPtr()))))
1223             idata->securityLevel = 100;
1224     }
1225 
1226     if (idata->isDyn || idata->isUnnumbered || idata->isBridgePort)
1227         idata->securityLevel = 0;
1228 
1229     if (idata->securityLevel==-1) idata->securityLevel = 0;
1230 }
1231 
guessOSAndPlatformFromSysDescr(const QString & sysDescr,QString & platform,QString & hostOS,QString & version)1232 void guessOSAndPlatformFromSysDescr(
1233     const QString &sysDescr, QString &platform, QString &hostOS, QString &version)
1234 {
1235     QList<QRegExp> pix_re;
1236     pix_re << QRegExp("Cisco PIX Firewall Version ([0-9\\.]+)")
1237            << QRegExp("Cisco PIX Security Appliance Version ([0-9\\.]+)")
1238            << QRegExp("Cisco Adaptive Security Appliance Version ([0-9\\.]+)");
1239 
1240     QList<QRegExp> ios_re;
1241     ios_re << QRegExp("Cisco Internetwork Operating System Software .* Version ([0-9\\.]+)");
1242 
1243     platform = "";
1244     hostOS = "";
1245     version = "";
1246 
1247     if (fwbdebug)
1248         qDebug() << "guessOSAndPlatformFromSysDescr:"
1249                  << "sysdescr=" << sysDescr;
1250 
1251     list<QStringPair> allowed_versions;
1252     QString version_from_sysdescr;
1253 
1254     foreach (QRegExp re, pix_re)
1255     {
1256         if (re.indexIn(sysDescr) > -1)
1257         {
1258             platform = "pix";
1259             hostOS = "pix_os";
1260             version_from_sysdescr = re.cap(1);
1261         }
1262     }
1263 
1264 
1265     foreach (QRegExp re, ios_re)
1266     {
1267         if (re.indexIn(sysDescr) > -1)
1268         {
1269             platform = "iosacl";
1270             hostOS = "ios";
1271             version_from_sysdescr = re.cap(1);
1272         }
1273     }
1274 
1275     if (fwbdebug)
1276         qDebug() << "guessOSAndPlatformFromSysDescr:"
1277                  << "platform=" << platform
1278                  << "hostOS=" << hostOS
1279                  << "version=" << version_from_sysdescr;
1280 
1281     if ( ! platform.isEmpty())
1282         version = findBestVersionMatch(platform, version_from_sysdescr);
1283 
1284 }
1285 
findBestVersionMatch(const QString & platform,const QString & discovered_version)1286 QString findBestVersionMatch(const QString &platform,
1287                              const QString &discovered_version)
1288 {
1289     list<QStringPair> allowed_versions;
1290 
1291     getVersionsForPlatform(platform, allowed_versions);
1292 
1293     if ( ! discovered_version.isEmpty())
1294     {
1295         QString version_fit;
1296         list<QStringPair>::iterator it;
1297         foreach (QStringPair p, allowed_versions)
1298         {
1299             QString vers = p.first;
1300             if (XMLTools::version_compare(vers.toStdString(),
1301                                           discovered_version.toStdString())>0)
1302                 break;
1303             version_fit = vers;
1304         }
1305         return version_fit;
1306     }
1307     return "";
1308 }
1309 
1310 
1311 
1312