1 /*
2
3 Firewall Builder
4
5 Copyright (C) 2003-2011 NetCitadel, LLC
6
7 Author: Vadim Kurland vadim@fwbuilder.org
8
9 This program is free software which we release under the GNU General Public
10 License. You may redistribute and/or modify this program under the terms
11 of that license as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 To get a copy of the GNU General Public License, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 */
23
24 #include "config.h"
25 #include "global.h"
26 #include "utils.h"
27 #include "utils_no_qt.h"
28 #include "platforms.h"
29
30 #include "newFirewallDialog.h"
31 #include "ObjConflictResolutionDialog.h"
32 #include "upgradePredicate.h"
33 #include "FWBSettings.h"
34 #include "FWBTree.h"
35 #include "events.h"
36 #include "FWBApplication.h"
37 #include "QDesktopWidget"
38 #include "networkZoneManager.h"
39 #include "ObjConflictResolutionDialog.h"
40
41 #include "interfaceProperties.h"
42 #include "interfacePropertiesObjectFactory.h"
43
44 #include "fwbuilder/Library.h"
45 #include "fwbuilder/Firewall.h"
46 #include "fwbuilder/Resources.h"
47 #include "fwbuilder/Policy.h"
48 #include "fwbuilder/BackgroundOp.h"
49 #include "fwbuilder/IPv4.h"
50 #include "fwbuilder/IPv6.h"
51 #include "fwbuilder/Constants.h"
52
53 #include <QLineEdit>
54 #include <QTextEdit>
55 #include <QSpinBox>
56 #include <QComboBox>
57 #include <QPushButton>
58 #include <QToolButton>
59 #include <QRadioButton>
60 #include <QCheckBox>
61 #include <QTreeWidget>
62 #include <QTableWidget>
63 #include <QTextBrowser>
64 #include <QMessageBox>
65 #include <QTimer>
66 #include <QListWidget>
67 #include <QApplication>
68 #include <QCursor>
69 #include <QPixmapCache>
70 #include <QFileDialog>
71 #include <QDir>
72 #include <QtDebug>
73
74 #include <algorithm>
75 #include <iostream>
76
77 // must be the last for win
78 #include "fwbuilder/snmp.h"
79
80 using namespace libfwbuilder;
81 using namespace std;
82
83
84 #define NAME_AND_PLATFORM_PAGE 0
85 #define INTERFACES_MANUAL_OR_SNMP 1
86 #define CONFIGURE_INTERFACES_MANUALLY 2
87 #define CONFIGURE_SECURITY_LEVELS 3
88 #define CONFIGURE_NETWORK_ZONES 4
89 #define CHOOSE_FW_TEMPLATE 5
90 #define CONFIGURE_TEMPLATE_INTERFACES_MANUALLY 6
91
92
newFirewallDialog(QWidget * parentw,FWObject * _p)93 newFirewallDialog::newFirewallDialog(QWidget *parentw, FWObject *_p) :
94 QDialog(parentw)
95 {
96
97 db_orig = _p->getRoot();
98 db_copy = new FWObjectDatabase();
99 db_copy->duplicate(db_orig, false);
100
101 parent = db_copy->getById(_p->getId(), true);
102
103 m_dialog = new Ui::newFirewallDialog_q;
104 m_dialog->setupUi(this);
105
106 possible_inside_interface_labels.push_back("inside");
107 possible_inside_interface_labels.push_back("GREEN");
108 possible_inside_interface_labels.push_back("green");
109
110 possible_outside_interface_labels.push_back("outside");
111 possible_outside_interface_labels.push_back("RED");
112 possible_outside_interface_labels.push_back("red");
113
114 possible_dmz_interface_labels.push_back("dmz");
115 possible_dmz_interface_labels.push_back("ORANGE");
116 possible_dmz_interface_labels.push_back("orange");
117
118
119 setControlWidgets(this, m_dialog->stackedWidget,
120 m_dialog->nextButton,
121 m_dialog->finishButton,
122 m_dialog->backButton,
123 m_dialog->cancelButton,
124 m_dialog->titleLabel);
125
126 nfw = NULL;
127 tmpldb = NULL;
128 snmpPollCompleted = false;
129 q = NULL;
130 unloadTemplatesLib = false;
131 getInterfacesBusy = false;
132
133 timer = new QTimer(this);
134 connect( timer, SIGNAL(timeout()), this, SLOT(monitor()));
135 connect( m_dialog->selectCustomTemplateLib, SIGNAL(pressed()),
136 this, SLOT(browseTemplate()));
137 connect( m_dialog->useStandard, SIGNAL(toggled(bool)),
138 this, SLOT(updateTemplatePanel()));
139 connect( m_dialog->useTemplate, SIGNAL(released()),
140 this, SLOT(updateTemplatePanel()));
141
142 m_dialog->useStandard->setChecked(true);
143 m_dialog->templateFilePath->setText(
144 Constants::getTemplatesObjectsFilePath().c_str());
145 updateTemplatePanel();
146
147 /* fill in platform. Since iptables is the most popular, start with
148 * it.
149 */
150 QString new_fw_platform = st->getNewFirewallPlatform();
151
152 /* if new_fw_platform is empty, the drop-down list will have empty
153 * item which will be current. This is so only on the first run of
154 * the program because it remembers chosen platform and uses it on
155 * subsequent runs.
156 */
157 setPlatform(m_dialog->platform, new_fw_platform);
158
159 /* fill in host OS */
160 setHostOS(m_dialog->hostOS, readPlatform(m_dialog->platform), "");
161
162 setNextEnabled( NAME_AND_PLATFORM_PAGE, false );
163
164 //m_dialog->iface_sl_list->setAllColumnsShowFocus( true );
165 QTimer::singleShot(0, m_dialog->obj_name, SLOT(setFocus()));
166
167 currentTemplate = NULL;
168 this->m_dialog->interfaceEditor1->clear();
169 this->m_dialog->interfaceEditor2->clear();
170 this->m_dialog->interfaceEditor1->closeTab();
171 this->m_dialog->interfaceEditor2->closeTab();//->removeTab(0);
172
173 this->m_dialog->interfaceEditor1->setExplanation(
174 tr("Interfaces with the type set to 'Dynamic IP address' get "
175 "IP address by means of DHCP or PPP protocol and do not "
176 "require an address here. Interfaces with the type set to "
177 "'Static IP address' have statically configured IP address "
178 "which should be entered on this page. Interface can have "
179 "several IPv4 and IPv6 addresses.")
180 );
181
182 this->m_dialog->interfaceEditor2->setExplanation(
183 tr("Here you can change IP address of the template interface "
184 "to match addresses used on your network. "
185 "Interface can have several IPv4 and "
186 "IPv6 addresses.")
187 );
188
189 this->resize(this->width(), this->minimumHeight());
190 int maxheight = (int)(app->desktop()->height()*0.9);
191 if (this->height() > maxheight)
192 this->resize(this->width(), maxheight);
193
194 showPage(NAME_AND_PLATFORM_PAGE);
195 }
196
browseTemplate()197 void newFirewallDialog::browseTemplate()
198 {
199 QString fileName = QFileDialog::getOpenFileName(
200 this, tr("FWBuilder template files"), st->getOpenFileDir(),
201 tr("FWBuilder template files (*.xml *.fwb *.fwl)"));
202
203 if (fileName.isEmpty()) return;
204 st->setOpenFileDir(fileName);
205
206 m_dialog->templateFilePath->setText(fileName);
207 updateTemplatePanel();
208 }
209
useStandardTemplate()210 void newFirewallDialog::useStandardTemplate()
211 {
212 m_dialog->templateFilePath->setText(
213 Constants::getTemplatesObjectsFilePath().c_str());
214 updateTemplatePanel();
215 }
216
updateTemplatePanel()217 void newFirewallDialog::updateTemplatePanel()
218 {
219 if (st->customTemplatesEnabled() &&
220 m_dialog->useTemplate->checkState()==Qt::Checked)
221 {
222 QString fileName = m_dialog->templateFilePath->text();
223 bool using_std = m_dialog->useStandard->isChecked();
224
225 m_dialog->templateGroupBox->setVisible(true);
226 m_dialog->templateFilePathLabel->setVisible(true);
227 m_dialog->templateFilePath->setVisible(true);
228 m_dialog->templateLibExplanation->setVisible(true);
229
230 m_dialog->templateFilePath->setEnabled(!using_std);
231 m_dialog->selectCustomTemplateLib->setEnabled(!using_std);
232
233 if (using_std)
234 {
235 m_dialog->templateFilePath->setText(
236 Constants::getTemplatesObjectsFilePath().c_str());
237 }
238 }
239 else
240 {
241 m_dialog->templateGroupBox->setVisible(false);
242 }
243 }
244
~newFirewallDialog()245 newFirewallDialog::~newFirewallDialog()
246 {
247 delete m_dialog;
248 if (timer!=NULL) delete timer;
249 #ifdef HAVE_LIBSNMP
250 if (q!=NULL) delete q;
251 #endif
252 delete db_copy;
253 }
254
changed()255 void newFirewallDialog::changed()
256 {
257 int p = currentPage();
258
259 if (fwbdebug)
260 qDebug() << "newFirewallDialog::changed() page=" << p
261 << "use_manual=" << m_dialog->use_manual->isChecked()
262 << "use_snmp=" << m_dialog->use_snmp->isChecked();
263
264 if (p==NAME_AND_PLATFORM_PAGE)
265 {
266 setNextEnabled(p,
267 !m_dialog->obj_name->text().isEmpty() &&
268 !readPlatform(m_dialog->platform).isEmpty()
269 );
270 setHostOS(m_dialog->hostOS, readPlatform(m_dialog->platform), "");
271 QString host_os = readHostOS(m_dialog->hostOS);
272 m_dialog->interfaceEditor1->setHostOS(host_os);
273 m_dialog->interfaceEditor2->setHostOS(host_os);
274 }
275
276 if (p==INTERFACES_MANUAL_OR_SNMP)
277 {
278
279 bool use_snmp = false;
280
281 #ifdef HAVE_LIBSNMP
282 use_snmp = m_dialog->use_snmp->isChecked();
283 #else
284 use_snmp = false;
285 m_dialog->use_snmp->setEnabled( use_snmp );
286 #endif
287 m_dialog->snmpIP->setEnabled( use_snmp );
288 m_dialog->snmp_community->setEnabled( use_snmp );
289 m_dialog->snmpQuery->setEnabled( use_snmp );
290 m_dialog->snmpProgress->setEnabled( use_snmp );
291 if ( use_snmp ) m_dialog->snmp_community->setFocus();
292
293 if (use_snmp)
294 {
295 getIPAddressOfFirewallByName();
296 }
297
298 use_snmp = m_dialog->use_manual->isChecked() || snmpPollCompleted;
299 setNextEnabled( 1, use_snmp );
300 }
301
302 if (fwbdebug)
303 qDebug() << "newFirewallDialog::changed() done";
304 }
305
getIPAddressOfFirewallByName()306 void newFirewallDialog::getIPAddressOfFirewallByName()
307 {
308 getInterfacesBusy = true;
309
310 m_dialog->snmpIP->setText("");
311
312 QString name = m_dialog->obj_name->text().toLatin1().constData();
313 QApplication::setOverrideCursor( QCursor( Qt::WaitCursor) );
314 QString addr = getAddrByName(name, AF_INET);
315 QApplication::restoreOverrideCursor();
316
317 if (!addr.isEmpty())
318 m_dialog->snmpIP->setText(addr);
319 else
320 {
321 QMessageBox::warning(
322 this,"Firewall Builder",
323 tr("Address of %1 could not be obtained via DNS")
324 .arg(m_dialog->obj_name->text()),
325 "&Continue", QString::null, QString::null, 0, 1 );
326 }
327
328 getInterfacesBusy = false;
329 }
330
monitor()331 void newFirewallDialog::monitor()
332 {
333 if (logger==NULL || q==NULL) return;
334
335 #ifdef HAVE_LIBSNMP
336
337 if( logger->ready() )
338 {
339 QString str = logger->getLine().c_str();
340 m_dialog->snmpProgress->moveCursor( QTextCursor::End );
341 m_dialog->snmpProgress->insertPlainText( str );
342 return;
343 }
344
345 if (q->isRunning()) return;
346
347 timer->stop();
348
349 QString platform = readPlatform(m_dialog->platform);
350
351 guessOSAndPlatformFromSysDescr(q->getDescr().c_str(),
352 discovered_platform,
353 discovered_host_os,
354 discovered_version);
355
356 if (fwbdebug)
357 qDebug() << "Guessed version as " << discovered_version;
358
359
360 map<int, InterfaceData>* intf = q->getInterfaces();
361 map<int, InterfaceData>::iterator i;
362 this->m_dialog->interfaceEditor1->clear();
363 this->m_dialog->interfaceEditor1->removeTab(0);
364 for (i=intf->begin(); i!=intf->end(); ++i)
365 {
366 InterfaceData* idata = &(i->second);
367
368 if (fwbdebug)
369 {
370 qDebug() << "------------------------------------------------";
371 qDebug() << "id=" << idata->id.c_str();
372 qDebug() << "name=" << idata->name.c_str();
373 qDebug() << "snmp_type=" << idata->snmp_type;
374 qDebug() << "ostatus=" << idata->ostatus;
375 qDebug() << "mac_addr=" << idata->mac_addr.c_str();
376 qDebug() << "interface_type=" << idata->interface_type.c_str();
377 qDebug() << "";
378 }
379
380 /*
381 * some special treatment of discovered interfaces for Cisco ASA devices:
382 * if mac address is reported as 00:00:00:00:00:00 or
383 * 00:00:00:anything, this is usually some kind of internal special
384 * interface and we can skip it. Examples: "_internal_loopback",
385 * "Internal-Data0/1"
386 *
387 * This is different from how Linux reports mac address of a
388 * loopback because Linux snmpd returns empty string for the
389 * loopback mac address.
390 *
391 * The name of the interface reported by ASA is like this:
392 * "Adaptive Security Appliance 'Ethernet0/0' interface"
393 *
394 * Need to strip all thie verbose description
395 */
396
397 if (idata->ostatus)
398 {
399 guessInterfaceLabel(idata);
400
401 if (platform == "pix" || platform == "fwsm")
402 {
403 if ( ! idata->mac_addr.empty() && idata->snmp_type == 1 &&
404 idata->mac_addr.find("00:00:00")==0) continue;
405
406 QString name = idata->name.c_str();
407 name.replace("Adaptive Security Appliance '", "");
408 name.replace("Cisco PIX Security Appliance '", "");
409 name.replace("PIX Firewall '", "");
410 name.replace("' interface", "");
411 idata->name = name.toStdString();
412 }
413
414 this->m_dialog->interfaceEditor1->addInterfaceFromData(idata);
415 }
416 }
417 if ( this->m_dialog->interfaceEditor1->count() == 0 )
418 this->m_dialog->interfaceEditor1->addNewInterface();
419
420 delete q;
421 q=NULL;
422
423 #endif
424
425 snmpPollCompleted=true;
426 setNextEnabled( INTERFACES_MANUAL_OR_SNMP, true );
427 }
428
getInterfacesViaSNMP()429 void newFirewallDialog::getInterfacesViaSNMP()
430 {
431 #ifdef HAVE_LIBSNMP
432
433 // need to protect from reentry because getAddrByName processes events
434 if (q!=NULL || getInterfacesBusy) return;
435
436 snmpPollCompleted=false;
437 m_dialog->interfaceEditor1->clear();
438
439 string rcomm=m_dialog->snmp_community->text().toLatin1().constData();
440
441 if ( rcomm.empty() )
442 {
443 QMessageBox::warning(
444 this,"Firewall Builder",
445 tr("Missing SNMP community string."),
446 "&Continue", QString::null, QString::null, 0, 1 );
447 return ;
448 }
449
450 getInterfacesBusy = true;
451
452 InetAddr addr;
453 try
454 {
455 addr = InetAddr(m_dialog->snmpIP->text().toStdString());
456 }
457 catch (FWException &ex)
458 {
459 try
460 {
461 QApplication::setOverrideCursor( QCursor( Qt::WaitCursor) );
462 QString a = getAddrByName(m_dialog->snmpIP->text(), AF_INET);
463 QApplication::restoreOverrideCursor();
464 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
465 addr = InetAddr(a.toAscii().constData());
466 #else
467 addr = InetAddr(a.toLatin1().constData());
468 #endif
469 getInterfacesBusy = false;
470 }
471 catch (FWException &ex)
472 {
473 QMessageBox::warning(
474 this,"Firewall Builder",
475 tr("Address of %1 could not be obtained via DNS")
476 .arg(m_dialog->snmpIP->text()),
477 "&Continue", QString::null, QString::null, 0, 1 );
478 getInterfacesBusy = false;
479 return ;
480 }
481 }
482
483 logger = NULL;
484 m_dialog->snmpProgress->clear();
485
486 if (q!=NULL) delete q;
487
488 q = new SNMP_interface_query();
489 q->init(addr.toString(), rcomm, SNMP_DEFAULT_RETRIES, SNMP_DEFAULT_TIMEOUT);
490
491 timer->setSingleShot(false);
492 timer->start(0);
493
494 try
495 {
496 logger = q->start_operation();
497
498 } catch(const FWException &ex)
499 {
500 //do nothing
501 }
502
503 getInterfacesBusy = false;
504
505 #endif
506 }
507
interfaceCompare(libfwbuilder::Interface * first,libfwbuilder::Interface * second)508 bool interfaceCompare(libfwbuilder::Interface *first,
509 libfwbuilder::Interface *second)
510 {
511 return first->getName() < second->getName();
512 }
513
appropriate(const int page) const514 bool newFirewallDialog::appropriate(const int page) const
515 {
516 switch (page)
517 {
518 case NAME_AND_PLATFORM_PAGE:
519 case CHOOSE_FW_TEMPLATE:
520 return true;
521
522 case INTERFACES_MANUAL_OR_SNMP:
523 case CONFIGURE_INTERFACES_MANUALLY:
524 case CONFIGURE_SECURITY_LEVELS:
525 case CONFIGURE_NETWORK_ZONES:
526 return (!m_dialog->useTemplate->isChecked());
527 }
528 return true;
529 }
530
nextClicked()531 void newFirewallDialog::nextClicked()
532 {
533 if ( currentPage() == CHOOSE_FW_TEMPLATE )
534 {
535 if (m_dialog->templateList->currentItem() == NULL)
536 {
537 QMessageBox::warning(
538 this,"Firewall Builder",
539 tr("Please select template"),
540 tr("&Continue"), QString::null,QString::null,
541 0, 1 );
542 showPage(CHOOSE_FW_TEMPLATE);
543 return;
544 }
545 }
546
547 if ( currentPage() == CONFIGURE_INTERFACES_MANUALLY )
548 if ( !this->m_dialog->interfaceEditor1->isValid() )
549 return;
550
551 // FakeWizard::nextRelevant() finds next (in the numerical order)
552 // page that is permitted by function appropriate() and returns
553 // its number
554 if (nextRelevant( currentPage() ) > -1)
555 showPage(nextRelevant( currentPage() ));
556 }
557
backClicked()558 void newFirewallDialog::backClicked()
559 {
560 if (previousRelevant( currentPage() ) > -1)
561 showPage(previousRelevant( currentPage() ));
562 }
563
showPage(const int page)564 void newFirewallDialog::showPage(const int page)
565 {
566 FakeWizard::showPage(page);
567
568 int p = page;
569
570 if (fwbdebug)
571 qDebug() << "newFirewallDialog::showPage page=" << page;
572
573 // p is a page number _after_ it changed
574 switch (p)
575 {
576 case NAME_AND_PLATFORM_PAGE:
577 // we get here if user hits "Back" on page 4 (where they
578 // choose template object)
579 if (tmpldb!=NULL)
580 {
581 m_dialog->templateList->clear();
582 delete tmpldb;
583 tmpldb = NULL;
584 }
585 m_dialog->nextButton->setDefault(true);
586 m_dialog->obj_name->setFocus();
587 break;
588
589 case INTERFACES_MANUAL_OR_SNMP:
590 {
591 // page 1 is where we choose to configure interfaces manually or via snmp
592 m_dialog->snmpIP->setText("");
593 changed(); // to properly enable/disable widgets
594 m_dialog->nextButton->setDefault(true);
595 break;
596 }
597
598 case CONFIGURE_INTERFACES_MANUALLY:
599 {
600 if (!Resources::getTargetCapabilityBool(
601 readPlatform(m_dialog->platform).toLatin1().constData(),
602 "security_levels") )
603 {
604
605 /* if chosen fw platform does not support security levels,
606 * this is the last page
607 */
608 setNextEnabled( CONFIGURE_INTERFACES_MANUALLY, false );
609 setFinishEnabled( CONFIGURE_INTERFACES_MANUALLY, true );
610 m_dialog->finishButton->setDefault(true);
611 }
612 break;
613 }
614
615 case CONFIGURE_SECURITY_LEVELS:
616 {
617 if (m_dialog->useTemplate->isChecked())
618 {
619 showPage( NAME_AND_PLATFORM_PAGE );
620 return;
621 }
622
623 // Edit security levels
624 fillInterfaceSLList();
625
626 setNextEnabled( CONFIGURE_SECURITY_LEVELS, true );
627 setFinishEnabled( CONFIGURE_SECURITY_LEVELS, false );
628 m_dialog->nextButton->setDefault(true);
629 break;
630 }
631
632 case CONFIGURE_NETWORK_ZONES:
633 {
634 if (m_dialog->useTemplate->isChecked())
635 {
636 showPage( NAME_AND_PLATFORM_PAGE );
637 return;
638 }
639
640 // Edit network zones
641 fillInterfaceNZList();
642
643 setNextEnabled(CONFIGURE_NETWORK_ZONES, false );
644 setFinishEnabled(CONFIGURE_NETWORK_ZONES, true );
645 m_dialog->finishButton->setDefault(true);
646 break;
647 }
648
649 case CHOOSE_FW_TEMPLATE:
650 {
651 // Show firewall templates
652 setFinishEnabled( CHOOSE_FW_TEMPLATE, false );
653 setNextEnabled( CHOOSE_FW_TEMPLATE, true );
654
655 // load templates if not loaded
656 if (tmpldb==NULL)
657 {
658
659 MessageBoxUpgradePredicate upgrade_predicate(this);
660 tmpldb = new FWObjectDatabase();
661 tmpldb->setReadOnly( false );
662 try
663 {
664 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
665 tmpldb->load(
666 m_dialog->templateFilePath->text().toAscii().data(),
667 &upgrade_predicate, Constants::getDTDDirectory());
668 #else
669 tmpldb->load(
670 m_dialog->templateFilePath->text().toLatin1().data(),
671 &upgrade_predicate, Constants::getDTDDirectory());
672 #endif
673 }
674 catch (FWException &ex)
675 {
676 QMessageBox::critical(
677 this,"Firewall Builder",
678 tr("Error loading template library:\n%1")
679 .arg(ex.toString().c_str()),
680 tr("&Continue"), QString::null,QString::null,
681 0, 1 );
682 }
683 }
684
685 // nfw != NULL if user clicked Back on one of the subsequent
686 // pages because we create firewall object when they click
687 // Next on the page where they choose template ( see case
688 // CONFIGURE_TEMPLATE_INTERFACES_MANUALLY below)
689 if (nfw)
690 {
691 parent->remove(nfw, false);
692 delete nfw;
693 nfw = NULL;
694 }
695
696 list<FWObject*> fl;
697
698 FWObjectTypedChildIterator libiter = tmpldb->findByType(Library::TYPENAME);
699 for ( ; libiter!=libiter.end(); ++libiter)
700 findFirewalls(*libiter, fl, false);
701
702 QString icn = ":/Icons/Firewall/icon-tree";
703
704 m_dialog->templateList->clear();
705
706 int n = 0;
707 QListWidgetItem *first_template = NULL;
708 for (list<FWObject*>::iterator m=fl.begin(); m!=fl.end(); m++,n++)
709 {
710 FWObject *o = *m;
711
712 /*
713 Ticket #1492 requested the change to only show the user templates
714 that match platform and host OS they choose on the first page of the
715 wizard.
716
717 Unfortunately this does not really work because most templates have
718 platform and host OS set to "unknown". Either we have to maintain
719 many almost identical templates to provide enough choices for all
720 possible platforms, or we should not filter by platform.
721
722 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
723 string platform = readPlatform(m_dialog->platform).toAscii().constData();
724 string host_os = readHostOS(m_dialog->hostOS).toAscii().constData();
725 #else
726 string platform = readPlatform(m_dialog->platform).toLatin1().constData();
727 string host_os = readHostOS(m_dialog->hostOS).toLatin1().constData();
728 #endif
729 if (o->getStr("platform") != platform || o->getStr("host_OS") != host_os)
730 continue;
731 */
732
733 QPixmap pm;
734 if ( ! QPixmapCache::find( icn, pm) )
735 {
736 pm.load( icn );
737 QPixmapCache::insert( icn, pm);
738 }
739
740 QListWidgetItem *twi = new QListWidgetItem;
741 twi->setIcon( QIcon(pm) );
742 twi->setText( QString(o->getName().c_str()) );
743
744 m_dialog->templateList->addItem( twi );
745 templates[ m_dialog->templateList->item(
746 m_dialog->templateList->count()-1 ) ] = o;
747
748 if (first_template == NULL) first_template = twi;
749 }
750
751 m_dialog->templateList->setFocus();
752 m_dialog->templateList->setCurrentItem(first_template,
753 QItemSelectionModel::SelectCurrent);
754 m_dialog->finishButton->setDefault(false);
755 m_dialog->nextButton->setDefault(true);
756 break;
757 }
758
759 case CONFIGURE_TEMPLATE_INTERFACES_MANUALLY:
760 {
761 // Edit interfaces of the template object
762 createFirewallFromTemplate();
763 setFinishEnabled( CONFIGURE_TEMPLATE_INTERFACES_MANUALLY, true );
764
765 this->m_dialog->interfaceEditor2->clear();
766 this->m_dialog->interfaceEditor2->closeTab();//->removeTab(0);
767 this->m_dialog->interfaceEditor2->setCornerWidgetsVisible(false);
768 QList<Interface*> interfaces;
769 FWObjectTypedChildIterator intiter = nfw->findByType(Interface::TYPENAME);
770 for ( ; intiter != intiter.end(); ++intiter )
771 interfaces.append(Interface::cast(*intiter));
772 sort(interfaces.begin(), interfaces.end(), interfaceCompare);
773 foreach(Interface* intr, interfaces)
774 m_dialog->interfaceEditor2->addInterface(intr);
775 m_dialog->finishButton->setDefault(true);
776 }
777 }
778 }
779
getInterfaceDataFromInterfaceEditor(EditedInterfaceData & edata,InterfaceData & idata)780 void newFirewallDialog::getInterfaceDataFromInterfaceEditor(
781 EditedInterfaceData &edata, InterfaceData &idata)
782 {
783 idata.name = edata.name.toStdString();
784 idata.label = edata.label.toStdString();
785 AddressInfo address;
786 bool gotIPv4 = false;
787 foreach(AddressInfo addr, edata.addresses.values())
788 {
789 if (addr.ipv4)
790 {
791 address = addr;
792 gotIPv4 = true;
793 break;
794 }
795 }
796
797 InetAddrMask *iam;// = new InetAddrMask();
798 if (edata.type == 0 && edata.addresses.size() != 0)
799 {
800 if (!gotIPv4) address = edata.addresses.values().first();
801 if ( address.ipv4 )
802 iam = new InetAddrMask(
803 InetAddr(address.address.toStdString()),
804 InetAddr(address.netmask.toStdString()));
805 else
806 {
807 iam = new InetAddrMask(
808 InetAddr(AF_INET6, address.address.toStdString()),
809 InetAddr(AF_INET6, address.netmask.toStdString()));
810 }
811 idata.addr_mask.push_back(iam);
812 }
813
814 if (gotIPv4)
815 {
816 try
817 {
818 guessSecurityLevel(
819 readPlatform(m_dialog->platform).toStdString(), &idata);
820 }
821 catch (FWException &ex)
822 {
823 QMessageBox::warning(
824 this,"Firewall Builder", ex.toString().c_str(),
825 "&Continue", QString::null, QString::null, 0, 1 );
826 showPage( CONFIGURE_INTERFACES_MANUALLY );
827 return;
828 }
829 }
830 else idata.securityLevel = 0;
831 }
832
fillInterfaceSLList()833 void newFirewallDialog::fillInterfaceSLList()
834 {
835 m_dialog->iface_sl_list->clear();
836
837 QStringList labels;
838 labels << QObject::tr("Name") << QObject::tr("Label")
839 << QObject::tr("Address") << QObject::tr("Security Level");
840 m_dialog->iface_sl_list->setHorizontalHeaderLabels(labels);
841
842 int row = 0;
843 foreach(EditedInterfaceData iface,
844 this->m_dialog->interfaceEditor1->getData().values() +
845 this->m_dialog->interfaceEditor1->getNewData())
846 {
847 InterfaceData idata;
848
849 getInterfaceDataFromInterfaceEditor(iface, idata);
850
851 m_dialog->iface_sl_list->insertRow(row);
852
853 QTableWidgetItem* itm;
854
855 itm = new QTableWidgetItem(iface.name);
856 itm->setFlags(itm->flags() & ~Qt::ItemIsEditable);
857 m_dialog->iface_sl_list->setItem(row, 0, itm);
858
859 itm = new QTableWidgetItem(iface.label);
860 itm->setFlags(itm->flags() & ~Qt::ItemIsEditable);
861 m_dialog->iface_sl_list->setItem(row, 1, itm);
862
863 QString addr_str;
864 if (iface.addresses.size() > 0)
865 {
866 AddressInfo addr = *(iface.addresses.begin());
867 addr_str = addr.address;
868 }
869
870 itm = new QTableWidgetItem(addr_str);
871 itm->setFlags(itm->flags() & ~Qt::ItemIsEditable);
872 m_dialog->iface_sl_list->setItem(row, 2, itm);
873
874 //itm = new QTableWidgetItem(QString::number(idata.securityLevel));
875 QSpinBox *widget = new QSpinBox();
876 widget->setMaximum(100);
877 widget->setMinimum(0);
878 widget->setValue(idata.securityLevel);
879 m_dialog->iface_sl_list->setCellWidget(row, 3, widget);
880
881 row++;
882 }
883 }
884
fillInterfaceNZList()885 void newFirewallDialog::fillInterfaceNZList()
886 {
887 m_dialog->iface_nz_list->clear();
888
889 QStringList labels;
890 labels << QObject::tr("Name") << QObject::tr("Label")
891 << QObject::tr("Address") << QObject::tr("Network Zone");
892 m_dialog->iface_nz_list->setHorizontalHeaderLabels(labels);
893
894 NetworkZoneManager netzone_manager;
895 netzone_manager.load(db_copy);
896
897 int row = 0;
898 foreach(EditedInterfaceData iface,
899 this->m_dialog->interfaceEditor1->getData().values() +
900 this->m_dialog->interfaceEditor1->getNewData())
901 {
902 InterfaceData idata;
903
904 getInterfaceDataFromInterfaceEditor(iface, idata);
905
906 m_dialog->iface_nz_list->insertRow(row);
907
908 QTableWidgetItem* itm;
909
910 itm = new QTableWidgetItem(iface.name);
911 itm->setFlags(itm->flags() & ~Qt::ItemIsEditable);
912 m_dialog->iface_nz_list->setItem(row, 0, itm);
913
914 itm = new QTableWidgetItem(iface.label);
915 itm->setFlags(itm->flags() & ~Qt::ItemIsEditable);
916 m_dialog->iface_nz_list->setItem(row, 1, itm);
917
918 QString addr_str;
919 if (iface.addresses.size() > 0)
920 {
921 AddressInfo addr = *(iface.addresses.begin());
922 addr_str = addr.address;
923 }
924
925 itm = new QTableWidgetItem(addr_str);
926 itm->setFlags(itm->flags() & ~Qt::ItemIsEditable);
927 m_dialog->iface_nz_list->setItem(row, 2, itm);
928
929 QComboBox *widget = new QComboBox();
930 netzone_manager.packComboBox(widget, -1);
931 m_dialog->iface_nz_list->setCellWidget(row, 3, widget);
932
933 row++;
934 }
935
936 m_dialog->iface_nz_list->resizeColumnToContents(3);
937 }
938
939 /*
940 * this slot is connected to currentItemChanged signal of templateList
941 * As a side effect, this slot is called when we clear templateList.
942 */
templateSelected(QListWidgetItem * itm)943 void newFirewallDialog::templateSelected(QListWidgetItem *itm)
944 {
945 if (templates.size()==0) return;
946 FWObject *o = templates[itm];
947 if (o==NULL) return;
948 this->m_dialog->interfaceEditor2->setTemplate(o);
949 currentTemplate = o;
950
951 Firewall *fw = Firewall::cast(o);
952
953 m_dialog->templateComment->clear();
954 QString s = QString("<a name=\"top\">\n") + fw->getComment().c_str();
955 m_dialog->templateComment->append( s );
956 m_dialog->templateComment->scrollToAnchor("top");
957
958 bool haveOutside = false;
959 bool haveInside = false;
960 bool haveDMZ = false;
961 list<FWObject*> ll = fw->getByType(Interface::TYPENAME);
962 for (FWObject::iterator i=ll.begin(); i!=ll.end(); i++)
963 {
964 Interface *intf = Interface::cast( *i );
965 if (std::find(possible_outside_interface_labels.begin(),
966 possible_outside_interface_labels.end(),
967 intf->getLabel()) != possible_outside_interface_labels.end())
968 {
969 haveOutside=true;
970 m_dialog->intfOutsideLine->show();
971 m_dialog->intfOutsideText->show();
972 fillInterfaceData(intf,m_dialog->intfOutsideText);
973 }
974
975 if (std::find(possible_inside_interface_labels.begin(),
976 possible_inside_interface_labels.end(),
977 intf->getLabel()) != possible_inside_interface_labels.end())
978 {
979 haveInside=true;
980 m_dialog->intfInsideLine->show();
981 m_dialog->intfInsideText->show();
982 fillInterfaceData(intf,m_dialog->intfInsideText);
983 }
984
985 if (std::find(possible_dmz_interface_labels.begin(),
986 possible_dmz_interface_labels.end(),
987 intf->getLabel()) != possible_dmz_interface_labels.end())
988 {
989 haveDMZ=true;
990 m_dialog->intfDMZLine->show();
991 m_dialog->intfDMZText->show();
992 fillInterfaceData(intf,m_dialog->intfDMZText);
993 }
994 }
995
996 if (!haveOutside) { m_dialog->intfOutsideLine->hide(); m_dialog->intfOutsideText->hide(); }
997 if (!haveInside) { m_dialog->intfInsideLine->hide(); m_dialog->intfInsideText->hide(); }
998 if (!haveDMZ) { m_dialog->intfDMZLine->hide(); m_dialog->intfDMZText->hide(); }
999 }
1000
fillInterfaceData(Interface * intf,QTextBrowser * qte)1001 void newFirewallDialog::fillInterfaceData(Interface *intf, QTextBrowser *qte)
1002 {
1003 qte->clear();
1004 QString s;
1005
1006 s += "<table border='0' cellspacing='0' cellpadding='0'>";
1007
1008 s += "<tr>";
1009 s += "<td>";
1010 s += tr("Interface: %1 (%2)")
1011 .arg(intf->getName().c_str())
1012 .arg(intf->getLabel().c_str());
1013 s += "</td>";
1014 s += "</tr>";
1015
1016 s += "<tr>";
1017 s += "<td>";
1018 if (intf->isDyn()) s += tr("Dynamic address");
1019 else
1020 if (intf->isUnnumbered()) s += tr("Unnumbered interface");
1021 else
1022 {
1023 const InetAddr *addr = intf->getAddressPtr();
1024 QString addr_str = (addr) ? addr->toString().c_str() : "";
1025 const InetAddr *netm = intf->getNetmaskPtr();
1026 QString netm_str = (netm) ? netm->toString().c_str() : "";
1027 s += QString("%1/%2").arg(addr_str).arg(netm_str);
1028 }
1029 s += "</td>";
1030 s += "</tr>";
1031 s += "</table>";
1032 qte->setText(s);
1033 }
1034
validateAddressAndMask(const QString & addr,const QString & netm)1035 bool newFirewallDialog::validateAddressAndMask(const QString &addr,
1036 const QString &netm)
1037 {
1038 try
1039 {
1040 InetAddr(addr.toLatin1().constData());
1041 }
1042 catch (FWException &ex)
1043 {
1044 QMessageBox::warning(
1045 this,"Firewall Builder",
1046 tr("Invalid address '%1/%2'").arg(addr).arg(netm),
1047 "&Continue", QString::null, QString::null, 0, 1 );
1048 return false;
1049 }
1050 try
1051 {
1052 bool ok = false ;
1053 int ilen = netm.toInt (&ok);
1054 if (ok)
1055 {
1056 if (ilen < 0 || ilen > 32)
1057 {
1058 QMessageBox::warning(
1059 this,"Firewall Builder",
1060 tr("Invalid address '%1/%2'").arg(addr).arg(netm),
1061 "&Continue", QString::null, QString::null, 0, 1 );
1062 return false;
1063 }
1064 }
1065 else
1066 {
1067 InetAddr(netm.toLatin1().constData());
1068 }
1069
1070 }
1071 catch (FWException &ex)
1072 {
1073 QMessageBox::warning(
1074 this,"Firewall Builder",
1075 tr("Invalid address '%1/%2'").arg(addr).arg(netm),
1076 "&Continue", QString::null, QString::null, 0, 1 );
1077 return false;
1078 }
1079 return true;
1080 }
1081
cleanup()1082 void newFirewallDialog::cleanup()
1083 {
1084 if (nfw)
1085 {
1086 parent->remove(nfw, false);
1087 delete nfw;
1088 nfw = NULL;
1089 }
1090
1091 if (tmpldb)
1092 {
1093 delete tmpldb;
1094 tmpldb = NULL;
1095 }
1096 }
1097
cancelClicked()1098 void newFirewallDialog::cancelClicked()
1099 {
1100 cleanup();
1101 reject();
1102 }
1103
finishClicked()1104 void newFirewallDialog::finishClicked()
1105 {
1106 // getting focus to close table cell editor
1107 // see #1594
1108 m_dialog->finishButton->setFocus(Qt::OtherFocusReason);
1109
1110 if (fwbdebug)
1111 qDebug() << "newFirewallDialog::finishClicked()"
1112 << "currentPage()=" << currentPage();
1113
1114 if ((!this->m_dialog->useTemplate->isChecked()) &&
1115 currentPage() == CONFIGURE_INTERFACES_MANUALLY)
1116 {
1117 if ( !this->m_dialog->interfaceEditor1->isValid() )
1118 return;
1119 }
1120
1121 if ( currentPage() == CONFIGURE_TEMPLATE_INTERFACES_MANUALLY )
1122 if ( !this->m_dialog->interfaceEditor2->isValid() )
1123 return;
1124
1125 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
1126 string platform = readPlatform(m_dialog->platform).toAscii().constData();
1127 string host_os = readHostOS(m_dialog->hostOS).toAscii().constData();
1128 #else
1129 string platform = readPlatform(m_dialog->platform).toLatin1().constData();
1130 string host_os = readHostOS(m_dialog->hostOS).toLatin1().constData();
1131 #endif
1132
1133 st->setNewFirewallPlatform(platform.c_str());
1134
1135 if (currentPage()==CONFIGURE_INTERFACES_MANUALLY) fillInterfaceSLList();
1136
1137 if (currentPage()==CHOOSE_FW_TEMPLATE ||
1138 currentPage()==CONFIGURE_TEMPLATE_INTERFACES_MANUALLY)
1139 {
1140 // Creating from a template
1141 if (nfw==NULL) createFirewallFromTemplate();
1142 else
1143 changedAddressesInNewFirewall();
1144
1145 } else
1146 {
1147 // Create from interface list (obtained either manually or via snmp)
1148 if ( !this->m_dialog->interfaceEditor1->isValid() )
1149 return;
1150
1151 FWObject *o;
1152 o = db_copy->create(Firewall::TYPENAME);
1153
1154 if (o==NULL)
1155 {
1156 QDialog::accept();
1157 return;
1158 }
1159
1160 o->setName( string( m_dialog->obj_name->text().toUtf8().constData() ) );//.toStdString());
1161 parent->add(o);
1162
1163 nfw = Firewall::cast(o);
1164
1165 o->setStr("platform", platform);
1166 Resources::setDefaultTargetOptions(platform , nfw);
1167
1168 o->setStr("host_OS", host_os);
1169 Resources::setDefaultTargetOptions(host_os , nfw);
1170
1171 if ( ! discovered_version.isEmpty())
1172 o->setStr("version", discovered_version.toStdString());
1173
1174 /* create interfaces */
1175
1176 foreach(EditedInterfaceData iface,
1177 this->m_dialog->interfaceEditor1->getNewData())
1178 {
1179 QString name = iface.name;
1180 QString label = iface.label;
1181 bool dyn = iface.type == 1;
1182 bool unnum = iface.type == 2;
1183 QString physaddr = iface.mac;
1184 int sec_level = 0;
1185 string network_zone_str_id = "";
1186
1187 QList<QTableWidgetItem*> ltwi =
1188 m_dialog->iface_sl_list->findItems( name , Qt::MatchExactly );
1189
1190 if ( ! ltwi.empty())
1191 {
1192 QTableWidgetItem *itm2 = ltwi[0];
1193 assert(itm2!=NULL);
1194 int row = itm2->row();
1195 QSpinBox *sb = dynamic_cast<QSpinBox*>(
1196 m_dialog->iface_sl_list->cellWidget(row, 3));
1197 assert(sb!=NULL);
1198 sec_level = sb->value();
1199 }
1200
1201 ltwi = m_dialog->iface_nz_list->findItems( name , Qt::MatchExactly );
1202 if ( ! ltwi.empty())
1203 {
1204 QTableWidgetItem *itm2 = ltwi[0];
1205 assert(itm2!=NULL);
1206 int row = itm2->row();
1207 QComboBox *cb = dynamic_cast<QComboBox*>(
1208 m_dialog->iface_nz_list->cellWidget(row, 3));
1209 assert(cb!=NULL);
1210 int network_zone_int_id =
1211 cb->itemData(cb->currentIndex(), Qt::UserRole).toInt();
1212 if (network_zone_int_id != 0)
1213 network_zone_str_id = FWObjectDatabase::getStringId(
1214 network_zone_int_id);
1215 else
1216 network_zone_str_id = "";
1217 }
1218
1219 Interface *oi = Interface::cast(db_copy->create(Interface::TYPENAME));
1220 assert(oi!=NULL);
1221
1222 nfw->add(oi);
1223
1224 oi->setName( string(name.toUtf8().constData()) );
1225 oi->setLabel( string(label.toUtf8().constData()) );
1226 oi->setComment( string(iface.comment.toUtf8().constData()) );
1227
1228 oi->setDyn(dyn);
1229 oi->setUnnumbered(unnum);
1230 oi->setSecurityLevel(sec_level);
1231
1232 // only set network zone if it is supported and is not empty. See #2014
1233 if (!network_zone_str_id.empty())
1234 oi->setStr("network_zone", network_zone_str_id);
1235
1236 std::auto_ptr<interfaceProperties> int_prop(
1237 interfacePropertiesObjectFactory::getInterfacePropertiesObject(nfw));
1238 if (int_prop->looksLikeVlanInterface(name))
1239 {
1240 QString base_name;
1241 int vlan_id;
1242 int_prop->parseVlan(name, &base_name, &vlan_id);
1243
1244 oi->getOptionsObject()->setStr("type", "8021q");
1245 oi->getOptionsObject()->setInt("vlan_id", vlan_id);
1246 }
1247
1248
1249 if (iface.type == 0)
1250 {
1251 foreach(AddressInfo address, iface.addresses)
1252 {
1253 if (address.address == "0.0.0.0") continue;
1254 if (address.ipv4)
1255 {
1256 string addrname = string( QString("%1:%2:ip").arg(QString(m_dialog->obj_name->text())).arg(name).toUtf8().constData() );
1257 IPv4 *oa = IPv4::cast(db_copy->create(IPv4::TYPENAME));
1258 oi->add(oa);
1259 oa->setName(addrname);
1260 oa->setAddress( InetAddr(address.address.toLatin1().constData()) );
1261 bool ok = false ;
1262 int inetmask = address.netmask.toInt(&ok);
1263 if (ok)
1264 {
1265 oa->setNetmask( InetAddr(inetmask) );
1266 }
1267 else
1268 {
1269 oa->setNetmask( InetAddr(address.netmask.toLatin1().constData()) );
1270 }
1271 }
1272 else
1273 {
1274 string addrname = string ( QString("%1:%2:ip6").arg(QString(m_dialog->obj_name->text())).arg(name).toUtf8().constData() );
1275 IPv6 *oa = IPv6::cast(db_copy->create(IPv6::TYPENAME));
1276 oi->add(oa);
1277 oa->setName(addrname);
1278 oa->setAddress(InetAddr(AF_INET6, address.address.toLatin1().constData()) );
1279 bool ok = false ;
1280 int inetmask = address.netmask.toInt(&ok);
1281 if (ok)
1282 {
1283 oa->setNetmask( InetAddr(AF_INET6, inetmask) );
1284 }
1285 else
1286 {
1287 oa->setNetmask(InetAddr(AF_INET6, address.netmask.toLatin1().constData()));
1288 }
1289 }
1290 }
1291 }
1292 }
1293 }
1294
1295 // merge dbcopy into db
1296
1297 CompareObjectsDialog cod(this);
1298 db_orig->merge(db_copy, &cod);
1299 db_orig->fixTree();
1300
1301 nfw = Firewall::cast(db_orig->findInIndex(nfw->getId()));
1302
1303 if (tmpldb!=NULL)
1304 {
1305 delete tmpldb;
1306 tmpldb = NULL;
1307 }
1308
1309 QDialog::accept();
1310 }
1311
1312
1313