Firewall rules editor improvements. #113
- wildcard hostname "*" matching all hosts (0.0.0.0/0) - wildcard port "*" matching the whole host - port ranges (11-222) support in UI
This commit is contained in:
parent
c8781da11e
commit
2cc61172f3
@ -48,16 +48,6 @@
|
|||||||
<string>Address</string>
|
<string>Address</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QLineEdit" name="addressEdit">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>70</x>
|
|
||||||
<y>10</y>
|
|
||||||
<width>301</width>
|
|
||||||
<height>27</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
@ -84,9 +74,22 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QComboBox" name="addressComboBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>70</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>301</width>
|
||||||
|
<height>27</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="editable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>addressEdit</tabstop>
|
<tabstop>addressComboBox</tabstop>
|
||||||
<tabstop>serviceComboBox</tabstop>
|
<tabstop>serviceComboBox</tabstop>
|
||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>buttonBox</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
|
@ -75,31 +75,56 @@ class EditFwRulesDlg (QDialog, ui_editfwrulesdlg.Ui_EditFwRulesDlg):
|
|||||||
def edit_rule_button_pressed(self):
|
def edit_rule_button_pressed(self):
|
||||||
dialog = NewFwRuleDlg()
|
dialog = NewFwRuleDlg()
|
||||||
dialog.set_ok_enabled(True)
|
dialog.set_ok_enabled(True)
|
||||||
row = self.rulesTreeView.selectedIndexes().pop().row()
|
selected = self.rulesTreeView.selectedIndexes()
|
||||||
item = self.__model.children[row]
|
if len(selected) > 0:
|
||||||
dialog.addressEdit.setText(item.address)
|
row = self.rulesTreeView.selectedIndexes().pop().row()
|
||||||
service = self.__model.get_service_name(item.portBegin)
|
address = self.__model.get_column_string(0, row).replace(' ', '')
|
||||||
dialog.serviceComboBox.insertItem(0, service)
|
dialog.addressComboBox.setItemText(0, address)
|
||||||
dialog.serviceComboBox.setCurrentIndex(0)
|
dialog.addressComboBox.setCurrentIndex(0)
|
||||||
self.run_rule_dialog(dialog, row)
|
service = self.__model.get_column_string(1, row)
|
||||||
|
dialog.serviceComboBox.setItemText(0, service)
|
||||||
|
dialog.serviceComboBox.setCurrentIndex(0)
|
||||||
|
self.run_rule_dialog(dialog, row)
|
||||||
|
|
||||||
def run_rule_dialog(self, dialog, row = None):
|
def run_rule_dialog(self, dialog, row = None):
|
||||||
if dialog.exec_():
|
if dialog.exec_():
|
||||||
address = dialog.addressEdit.text()
|
address = str(dialog.addressComboBox.currentText())
|
||||||
service = dialog.serviceComboBox.currentText()
|
service = str(dialog.serviceComboBox.currentText())
|
||||||
port = None
|
port = None
|
||||||
|
port2 = None
|
||||||
|
|
||||||
|
unmask = address.split("/", 1)
|
||||||
|
if len(unmask) == 2:
|
||||||
|
address = unmask[0]
|
||||||
|
netmask = int(unmask[1])
|
||||||
|
else:
|
||||||
|
netmask = 32
|
||||||
|
|
||||||
|
if address == "*":
|
||||||
|
address = "0.0.0.0"
|
||||||
|
netmask = 0
|
||||||
|
|
||||||
|
if service == "*":
|
||||||
|
service = "0"
|
||||||
try:
|
try:
|
||||||
port = int(service)
|
range = service.split("-", 1)
|
||||||
|
if len(range) == 2:
|
||||||
|
port = int(range[0])
|
||||||
|
port2 = int(range[1])
|
||||||
|
else:
|
||||||
|
port = int(service)
|
||||||
except (TypeError, ValueError) as ex:
|
except (TypeError, ValueError) as ex:
|
||||||
port = self.__model.get_service_port(service)
|
port = self.__model.get_service_port(service)
|
||||||
|
|
||||||
if port is not None:
|
if port is not None:
|
||||||
item = QubesFirewallRuleItem(address, 32, port, None)
|
if port2 is not None and port2 <= port:
|
||||||
if row is not None:
|
QMessageBox.warning(None, "Invalid service ports range", "Port {0} is lower than port {1}.".format(port2, port))
|
||||||
self.__model.setChild(row, item)
|
|
||||||
else:
|
else:
|
||||||
self.__model.appendChild(item)
|
item = QubesFirewallRuleItem(address, netmask, port, port2)
|
||||||
|
if row is not None:
|
||||||
|
self.__model.setChild(row, item)
|
||||||
|
else:
|
||||||
|
self.__model.appendChild(item)
|
||||||
else:
|
else:
|
||||||
QMessageBox.warning(None, "Invalid service name", "Service '{0} is unknown.".format(service))
|
QMessageBox.warning(None, "Invalid service name", "Service '{0} is unknown.".format(service))
|
||||||
|
|
||||||
@ -112,11 +137,28 @@ class QIPAddressValidator(QValidator):
|
|||||||
super (QIPAddressValidator, self).__init__(parent)
|
super (QIPAddressValidator, self).__init__(parent)
|
||||||
|
|
||||||
def validate(self, input, pos):
|
def validate(self, input, pos):
|
||||||
hostname = input
|
hostname = str(input)
|
||||||
|
|
||||||
if len(hostname) > 255 or len(hostname) == 0:
|
if len(hostname) > 255 or len(hostname) == 0:
|
||||||
return (QValidator.Intermediate, pos)
|
return (QValidator.Intermediate, pos)
|
||||||
|
|
||||||
|
if hostname == "*":
|
||||||
|
return (QValidator.Acceptable, pos)
|
||||||
|
|
||||||
|
unmask = hostname.split("/", 1)
|
||||||
|
if len(unmask) == 2:
|
||||||
|
hostname = unmask[0]
|
||||||
|
mask = unmask[1]
|
||||||
|
if mask.isdigit() or mask == "":
|
||||||
|
if re.match("^([0-9]{1,3}\.){3}[0-9]{1,3}$", hostname) is None:
|
||||||
|
return (QValidator.Invalid, pos)
|
||||||
|
if mask != "":
|
||||||
|
mask = int(unmask[1])
|
||||||
|
if mask < 0 or mask > 32:
|
||||||
|
return (QValidator.Invalid, pos)
|
||||||
|
else:
|
||||||
|
return (QValidator.Invalid, pos)
|
||||||
|
|
||||||
if hostname[-1:] == ".":
|
if hostname[-1:] == ".":
|
||||||
hostname = hostname[:-1]
|
hostname = hostname[:-1]
|
||||||
|
|
||||||
@ -135,22 +177,31 @@ class NewFwRuleDlg (QDialog, ui_newfwruledlg.Ui_NewFwRuleDlg):
|
|||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.set_ok_enabled(False)
|
self.set_ok_enabled(False)
|
||||||
self.addressEdit.setValidator(QIPAddressValidator())
|
self.addressComboBox.setValidator(QIPAddressValidator())
|
||||||
self.addressEdit.editingFinished.connect(self.address_editing_finished)
|
self.addressComboBox.editTextChanged.connect(self.address_editing_finished)
|
||||||
self.serviceComboBox.setValidator(QRegExpValidator(QRegExp("[a-z][a-z0-9-]+|[0-9]+", Qt.CaseInsensitive), None))
|
self.serviceComboBox.setValidator(QRegExpValidator(QRegExp("[a-z][a-z0-9-]+|[0-9]+(-[0-9]+)?", Qt.CaseInsensitive), None))
|
||||||
|
|
||||||
self.serviceComboBox.setInsertPolicy(QComboBox.InsertAtBottom)
|
self.serviceComboBox.setInsertPolicy(QComboBox.InsertAtBottom)
|
||||||
self.populate_services_combo()
|
self.populate_combos()
|
||||||
self.serviceComboBox.setInsertPolicy(QComboBox.InsertAtTop)
|
self.serviceComboBox.setInsertPolicy(QComboBox.InsertAtTop)
|
||||||
|
|
||||||
def populate_services_combo(self):
|
def populate_combos(self):
|
||||||
|
example_addresses = [
|
||||||
|
"", "www.example.com",
|
||||||
|
"192.168.1.100", "192.168.0.0/16",
|
||||||
|
"*"
|
||||||
|
]
|
||||||
displayed_services = [
|
displayed_services = [
|
||||||
|
'',
|
||||||
'http', 'https', 'ftp', 'ftps',
|
'http', 'https', 'ftp', 'ftps',
|
||||||
'smtp', 'pop3', 'pop3s', 'imap', 'imaps', 'nntp', 'nntps',
|
'smtp', 'pop3', 'pop3s', 'imap', 'imaps', 'nntp', 'nntps',
|
||||||
'ssh', 'telnet', 'telnets', 'ntp', 'snmp',
|
'ssh', 'telnet', 'telnets', 'ntp', 'snmp',
|
||||||
'ldap', 'ldaps', 'irc', 'ircs', 'xmpp-client',
|
'ldap', 'ldaps', 'irc', 'ircs', 'xmpp-client',
|
||||||
'syslog', 'printer', 'nfs', 'x11',
|
'syslog', 'printer', 'nfs', 'x11',
|
||||||
|
'*', '1024-1234'
|
||||||
]
|
]
|
||||||
|
for address in example_addresses:
|
||||||
|
self.addressComboBox.addItem(address)
|
||||||
for service in displayed_services:
|
for service in displayed_services:
|
||||||
self.serviceComboBox.addItem(service)
|
self.serviceComboBox.addItem(service)
|
||||||
|
|
||||||
@ -193,8 +244,11 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
|||||||
QAbstractItemModel.__init__(self, parent)
|
QAbstractItemModel.__init__(self, parent)
|
||||||
|
|
||||||
self.__columnValues = {
|
self.__columnValues = {
|
||||||
0: lambda x: self.children[x].address,
|
0: lambda x: "*" if self.children[x].address == "0.0.0.0" and self.children[x].netmask == 0 \
|
||||||
1: lambda x: "{0}-{1}".format(self.children[x].portBegin, self.children[x].portEnd) if self.children[x].portEnd is not None \
|
else self.children[x].address + ("" if self.children[x].netmask == 32 \
|
||||||
|
else " /{0}".format(self.children[x].netmask)),
|
||||||
|
1: lambda x: "*" if self.children[x].portBegin == 0 \
|
||||||
|
else "{0}-{1}".format(self.children[x].portBegin, self.children[x].portEnd) if self.children[x].portEnd is not None \
|
||||||
else self.get_service_name(self.children[x].portBegin),
|
else self.get_service_name(self.children[x].portBegin),
|
||||||
}
|
}
|
||||||
self.__columnNames = {
|
self.__columnNames = {
|
||||||
@ -224,6 +278,9 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
|||||||
return service[1]
|
return service[1]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_column_string(self, col, row):
|
||||||
|
return self.__columnValues[col](row)
|
||||||
|
|
||||||
def set_vm(self, vm):
|
def set_vm(self, vm):
|
||||||
self.__vm = vm
|
self.__vm = vm
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user