1 /*
2
3 Firewall Builder
4
5 Copyright (C) 2003 NetCitadel, LLC
6
7 Author: Vadim Kurland vadim@fwbuilder.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 #include "utils.h"
29
30 #include "FWBTree.h"
31 #include "NetworkDialog.h"
32 #include "ProjectPanel.h"
33 #include "FWBSettings.h"
34 #include "FWCmdChange.h"
35
36 #include "fwbuilder/Library.h"
37 #include "fwbuilder/Network.h"
38 #include "fwbuilder/Interface.h"
39 #include "fwbuilder/FWException.h"
40 #include "fwbuilder/Inet6AddrMask.h"
41
42 #include <memory>
43
44 #include <qlineedit.h>
45 #include <qspinbox.h>
46 #include <qcheckbox.h>
47 #include <qtextedit.h>
48 #include <qcombobox.h>
49 #include <qmessagebox.h>
50 #include <qpushbutton.h>
51 #include <QUndoStack>
52 #include <QtDebug>
53 #include <QApplication>
54
55
56 using namespace std;
57 using namespace libfwbuilder;
58
NetworkDialog(QWidget * parent)59 NetworkDialog::NetworkDialog(QWidget *parent) : BaseObjectDialog(parent)
60 {
61 m_dialog = new Ui::NetworkDialog_q;
62 m_dialog->setupUi(this);
63 obj=NULL;
64
65 connectSignalsOfAllWidgetsToSlotChange();
66 }
67
~NetworkDialog()68 NetworkDialog::~NetworkDialog() { delete m_dialog; }
69
loadFWObject(FWObject * o)70 void NetworkDialog::loadFWObject(FWObject *o)
71 {
72 obj = o;
73 Network *s = dynamic_cast<Network*>(obj);
74 assert(s!=NULL);
75
76 init = true;
77
78 // See #893 No need to show address and mask 0.0.0.0 to the user
79 // if the object is "Any", especially because the same object is
80 // used as "any" for both ipv4 and ipv6 rules. It can be confusing
81 // if they see address "0.0.0.0" while they want to find object
82 // "any" for ipv6.
83
84 // see also #2454, trying to do even more handholding for users
85 // who do not understand what "any" means in a rule.
86
87 if (obj->getId() == FWObjectDatabase::ANY_ADDRESS_ID)
88 {
89 m_dialog->object_attributes->hide();
90 m_dialog->commentKeywords->setReadOnlyComment(
91 QObject::tr(
92 "When used in the Source or Destination field of a rule, "
93 "the Any object will match all "
94 "IP addresses. To update your rule to match only specific "
95 "IP addresses, drag-and-drop an object from "
96 "the Object tree into the field in the rule."));
97 } else
98 {
99 m_dialog->obj_name->setText( QString::fromUtf8(s->getName().c_str()) );
100 m_dialog->address->setText( s->getAddressPtr()->toString().c_str() );
101 m_dialog->netmask->setText( s->getNetmaskPtr()->toString().c_str() );
102 m_dialog->commentKeywords->loadFWObject(o);
103
104 m_dialog->object_attributes->show();
105
106 m_dialog->obj_name->setEnabled(!o->isReadOnly());
107 setDisabledPalette(m_dialog->obj_name);
108
109 m_dialog->address->setEnabled(!o->isReadOnly());
110 setDisabledPalette(m_dialog->address);
111
112 m_dialog->netmask->setEnabled(!o->isReadOnly());
113 setDisabledPalette(m_dialog->netmask);
114 }
115
116 init = false;
117 }
118
validate(bool * result)119 void NetworkDialog::validate(bool *result)
120 {
121 if (fwbdebug) qDebug() << "NetworkDialog::validate";
122
123 *result = true;
124
125 if (!validateName(this,obj,m_dialog->obj_name->text()))
126 {
127 *result = false;
128 return;
129 }
130
131 Network *s = dynamic_cast<Network*>(obj);
132 assert(s!=NULL);
133 try
134 {
135 InetAddr( m_dialog->address->text().toStdString() );
136 } catch (FWException &ex)
137 {
138 *result = false;
139 if (QApplication::focusWidget() != NULL)
140 {
141 blockSignals(true);
142 QMessageBox::critical(
143 this, "Firewall Builder",
144 tr("Illegal IP address '%1'").arg(m_dialog->address->text()),
145 tr("&Continue"), 0, 0,
146 0 );
147 blockSignals(false);
148 }
149 return;
150 }
151
152 InetAddr addr(m_dialog->address->text().toStdString());
153
154 try
155 {
156 QString len = m_dialog->netmask->text() ;
157 bool ok = false ;
158 int ilen = len.toInt(&ok);
159 if (ok)
160 {
161 // permit netmask 0.0.0.0 if the address is also 0.0.0.0
162 if (addr.isAny() && ilen == 0) return;
163
164 if (ilen>0 && ilen < 32)
165 {
166 return ;
167 }
168 else
169 {
170 *result = false;
171 QMessageBox::critical(
172 this, "Firewall Builder",
173 tr("Illegal netmask '%1'").arg( m_dialog->netmask->text() ),
174 tr("&Continue"), 0, 0,
175 0 );
176 return;
177 }
178 }
179
180 InetAddr nm( m_dialog->netmask->text().toStdString() );
181
182 if (nm.isAny())
183 {
184 // permit netmask 0.0.0.0 if the address is also 0.0.0.0
185 if (addr.isAny()) return;
186 else
187 {
188 *result = false;
189 if (QApplication::focusWidget() != NULL)
190 {
191 blockSignals(true);
192 // Do not allow netmask of 0 bits See #251
193 QMessageBox::critical(
194 this, "Firewall Builder",
195 tr("Network object should not have netmask '0.0.0.0'"),
196 tr("&Continue"), 0, 0,
197 0 );
198 blockSignals(false);
199 }
200 return;
201 }
202 }
203
204 if (!nm.isValidV4Netmask())
205 {
206 *result = false;
207 if (QApplication::focusWidget() != NULL)
208 {
209 blockSignals(true);
210 // Do not allow netmask with zeroes inside.
211 QMessageBox::critical(
212 this, "Firewall Builder",
213 tr("Netmasks with zeroes in the middle are not supported"),
214 tr("&Continue"), 0, 0,
215 0 );
216 blockSignals(false);
217 }
218 return;
219 }
220
221 } catch (FWException &ex)
222 {
223
224 *result = false;
225 if (QApplication::focusWidget() != NULL)
226 {
227 blockSignals(true);
228 QMessageBox::critical(
229 this, "Firewall Builder",
230 tr("Illegal netmask '%1'").arg( m_dialog->netmask->text() ),
231 tr("&Continue"), 0, 0,
232 0 );
233 blockSignals(false);
234 }
235 }
236 }
237
238
239
applyChanges()240 void NetworkDialog::applyChanges()
241 {
242 std::auto_ptr<FWCmdChange> cmd( new FWCmdChange(m_project, obj));
243 FWObject* new_state = cmd->getNewState();
244
245 Network *s = dynamic_cast<Network*>(new_state);
246 assert(s!=NULL);
247
248 string oldname = obj->getName();
249 new_state->setName(string(m_dialog->obj_name->text().toUtf8().constData()));
250 m_dialog->commentKeywords->applyChanges(new_state);
251
252 try
253 {
254 s->setAddress(InetAddr(m_dialog->address->text().toStdString()));
255 } catch (FWException &ex)
256 {
257 // exception thrown if user types illegal m_dialog->address or
258 // m_dialog->netmask
259 }
260
261 try
262 {
263 QString len = m_dialog->netmask->text() ;
264 bool ok = false ;
265 int ilen = len.toInt (&ok);
266 if (ok)
267 {
268 s->setNetmask(InetAddr(ilen));
269 }
270 else
271 {
272 s->setNetmask(InetAddr(m_dialog->netmask->text().toStdString()));
273 }
274 } catch (FWException &ex)
275 {
276 // exception thrown if user types illegal m_dialog->address or
277 // m_dialog->netmask
278 // bool ok = false ;
279 }
280
281 if (!cmd->getOldState()->cmp(new_state, true))
282 {
283 if (fwbdebug)
284 qDebug() << "Pushing FWCmdChange to undo stack";
285
286 if (obj->isReadOnly()) return;
287 m_project->undoStack->push(cmd.release());
288 }
289
290 }
291
addressEntered()292 void NetworkDialog::addressEntered()
293 {
294 try
295 {
296 QString addr = m_dialog->address->text();
297 InetAddrMask address_and_mask(string(addr.toStdString()));
298 if (addr.contains('/'))
299 {
300 m_dialog->address->setText(
301 address_and_mask.getAddressPtr()->toString().c_str());
302 m_dialog->netmask->setText(
303 address_and_mask.getNetmaskPtr()->toString().c_str());
304 }
305 } catch (FWException &ex)
306 {
307 // exception thrown if user types illegal m_dialog->address do
308 // not show error dialog. This method is called by
309 // editingFinished signal and therefore is invoked when user
310 // switches focus from the address input widget to some other
311 // widget or even when user switches to another application to
312 // look up the address. Error dialog interrupts the workflow
313 // in the latter case which is annoying.
314 }
315
316 }
317
318